~ubuntu-branches/ubuntu/jaunty/psi/jaunty

« back to all changes in this revision

Viewing changes to src/filetrans.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2002-04-19 02:28:44 UTC
  • Revision ID: james.westby@ubuntu.com-20020419022844-za7xgai5qyfd9xv6
Tags: upstream-0.8.5
ImportĀ upstreamĀ versionĀ 0.8.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
** filetrans.cpp - classes for handling file transfers
 
3
** Copyright (C) 2001, 2002  Justin Karneges
 
4
**
 
5
** This program is free software; you can redistribute it and/or
 
6
** modify it under the terms of the GNU General Public License
 
7
** as published by the Free Software Foundation; either version 2
 
8
** of the License, or (at your option) any later version.
 
9
**
 
10
** This program is distributed in the hope that it will be useful,
 
11
** but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
** GNU General Public License for more details.
 
14
**
 
15
** You should have received a copy of the GNU General Public License
 
16
** along with this program; if not, write to the Free Software
 
17
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
 
18
**
 
19
****************************************************************************/
 
20
 
 
21
#include"filetrans.h"
 
22
#include"common.h"
 
23
#include<qtimer.h>
 
24
#include<qdir.h>
 
25
#include<qstringlist.h>
 
26
 
 
27
#include<stdlib.h>
 
28
#include<time.h>
 
29
 
 
30
#ifndef Q_WS_WIN
 
31
#include<signal.h>
 
32
#endif
 
33
 
 
34
 
 
35
static QString urlEncode(const QString &in);
 
36
static QString urlDecode(const QString &in);
 
37
static QString mimeGuess(const QString &in);
 
38
static QString generateHTMLDirectory(bool base, const QString &dir, const QString &title);
 
39
 
 
40
 
 
41
/****************************************************************************
 
42
  FileTransfer
 
43
****************************************************************************/
 
44
FileTransfer::FileTransfer(FileServer *_par)
 
45
{
 
46
        par = _par;
 
47
        v_isValid = FALSE;
 
48
        finished = FALSE;
 
49
        at = 0;
 
50
        bytesSent = 0;
 
51
        type = FT_FILE;
 
52
}
 
53
 
 
54
FileTransfer::~FileTransfer()
 
55
{
 
56
}
 
57
 
 
58
void FileTransfer::discard()
 
59
{
 
60
        /*if(v_isValid) {
 
61
                sock.close();
 
62
                if(!finished) {
 
63
                        file.close();
 
64
                }
 
65
        }*/
 
66
 
 
67
        discarding();
 
68
        deleteLater();
 
69
}
 
70
 
 
71
void FileTransfer::start()
 
72
{
 
73
        connect(&sock, SIGNAL(readyRead()), SLOT(sock_readyRead()));
 
74
        connect(&sock, SIGNAL(connectionClosed()), SLOT(sock_connectionClosed()));
 
75
        connect(&sock, SIGNAL(bytesWritten(int)), SLOT(sock_bytesWritten(int)));
 
76
 
 
77
        printf("%04d: new transfer: ip=[%s]\n", id, sock.peerAddress().toString().latin1());
 
78
}
 
79
 
 
80
void FileTransfer::processChunk()
 
81
{
 
82
        if(finished)
 
83
                return;
 
84
 
 
85
        QByteArray data;
 
86
        data.resize(1024);
 
87
        int readSize;
 
88
 
 
89
        if(type == FT_FILE) {
 
90
                // read a chunk from the file
 
91
                readSize = file.readBlock(data.data(), 1024);
 
92
 
 
93
                if(file.atEnd()) {
 
94
                        file.close();
 
95
                        finished = TRUE;
 
96
                }
 
97
        }
 
98
        else {
 
99
                int left = stringData.size() - bytesSent;
 
100
                if(left > 1024)
 
101
                        readSize = 1024;
 
102
                else {
 
103
                        readSize = left;
 
104
                        finished = TRUE;
 
105
                }
 
106
 
 
107
                for(int n = 0; n < readSize; ++n)
 
108
                        data[n] = stringData[bytesSent + n];
 
109
        }
 
110
 
 
111
        bytesSent += readSize;
 
112
        printf("\r%04d: sent %d bytes                    ", id, bytesSent);
 
113
        fflush(stdout);
 
114
        sock.writeBlock(data.data(), readSize);
 
115
}
 
116
 
 
117
void FileTransfer::sock_readyRead()
 
118
{
 
119
        printf("%04d: data ready\n", id);
 
120
 
 
121
        if(!isValid()) {
 
122
                int size = sock.readBlock(recvBuf + at, 1024 - at);
 
123
                if(size == -1)
 
124
                        return;
 
125
                at += size;
 
126
 
 
127
                //if(size > 1023)
 
128
                //      size = 1023;
 
129
                //recvBuf[size] = 0;
 
130
                //printf("got: [%s]\n", recvBuf);
 
131
                //return;
 
132
 
 
133
                bool ok = FALSE;
 
134
 
 
135
                if(at > 1023) {
 
136
                        at = 1023;
 
137
                        recvBuf[at] = 0;
 
138
                        ok = TRUE;
 
139
                }
 
140
                else {
 
141
                        for(int n = 0; n < at; ++n) {
 
142
                                if(recvBuf[n] == '\n' || recvBuf[n] == '\r') {
 
143
                                        recvBuf[n] = 0;
 
144
                                        ok = TRUE;
 
145
                                        break;
 
146
                                }
 
147
                        }
 
148
                }
 
149
 
 
150
                if(ok) {
 
151
                        // see if it is a valid request
 
152
                        QString str = recvBuf;
 
153
                        printf("%04d: request: [%s]\n", id, str.latin1());
 
154
 
 
155
                        QString res, http_ver;
 
156
                        if(!getGETInfo(str, &res, &http_ver)) {
 
157
                                discard();
 
158
                                return;
 
159
                        }
 
160
 
 
161
                        printf("%04d: res: [%s], http_ver: [%s]\n", id, res.latin1(), http_ver.latin1());
 
162
 
 
163
                        char *useImage_data = 0;
 
164
                        int useImage_len = 0;
 
165
                        if(res == "/image/ft_back.png") {
 
166
                                useImage_data = pixdat_ft_back;
 
167
                                useImage_len = pixlen_ft_back;
 
168
                        }
 
169
                        else if(res == "/image/ft_file.png") {
 
170
                                useImage_data = pixdat_ft_file;
 
171
                                useImage_len = pixlen_ft_file;
 
172
                        }
 
173
                        else if(res == "/image/ft_folder.png") {
 
174
                                useImage_data = pixdat_ft_folder;
 
175
                                useImage_len = pixlen_ft_folder;
 
176
                        }
 
177
 
 
178
 
 
179
                        if(!useImage_data) {
 
180
                                QString resource, key;
 
181
                                if(!extractResourceInfo(res, &resource, &key)) {
 
182
                                        discard();
 
183
                                        return;
 
184
                                }
 
185
 
 
186
                                // does the key pass?
 
187
                                FileServerItem *fi = par->getFSI(key);
 
188
                                if(!fi) {
 
189
                                        discard();
 
190
                                        return;
 
191
                                }
 
192
 
 
193
                                printf("%04d: validated: key=[%s]\n", id, key.latin1());
 
194
 
 
195
                                // how about the resource?
 
196
                                QString fname;
 
197
                                QFileInfo info;
 
198
                                int transType = FT_FILE;
 
199
 
 
200
                                if(fi->type == 0) {
 
201
                                        if(resource != fi->file.fileName()) {
 
202
                                                discard();
 
203
                                                return;
 
204
                                        }
 
205
                                        fname = fi->file.filePath();
 
206
                                        info.setFile(fname);
 
207
                                }
 
208
                                else {
 
209
                                        QString base, rest;
 
210
                                        int n = resource.find('/');
 
211
                                        if(n == -1) {
 
212
                                                base = resource;
 
213
                                                rest = "/";
 
214
                                        }
 
215
                                        else {
 
216
                                                base = resource.mid(0, n);
 
217
                                                rest = resource.mid(n);
 
218
                                        }
 
219
 
 
220
                                        if(base != fi->file.fileName()) {
 
221
                                                discard();
 
222
                                                return;
 
223
                                        }
 
224
 
 
225
                                        fname = fi->file.filePath() + rest;
 
226
                                        info.setFile(fname);
 
227
                                        QDir d;
 
228
                                        if(info.isDir())
 
229
                                                d.setPath(fname);
 
230
                                        else
 
231
                                                d = info.dir();
 
232
 
 
233
                                        // simplify
 
234
                                        QString str = d.canonicalPath();
 
235
                                        if(str.isNull()) {
 
236
                                                discard();
 
237
                                                return;
 
238
                                        }
 
239
                                        fname = str;
 
240
                                        if(!info.isDir())
 
241
                                                fname += QString("/") + info.fileName();
 
242
 
 
243
                                        info.setFile(fname);
 
244
 
 
245
                                        QString basePath = fi->file.filePath();
 
246
                                        int len = basePath.length();
 
247
                                        for(n = 0; n < len; ++n) {
 
248
                                                if(basePath.at(n) != fname.at(n))
 
249
                                                        break;
 
250
                                        }
 
251
                                        if(n < len) {
 
252
                                                printf("%04d: illegal path.  hacking attempt?\n", id);
 
253
                                                discard();
 
254
                                                return;
 
255
                                        }
 
256
 
 
257
                                        if(info.isDir()) {
 
258
                                                transType = FT_STRING;
 
259
                                        }
 
260
                                }
 
261
 
 
262
 
 
263
                                if(transType == FT_FILE) {
 
264
                                        printf("%04d: serving: [%s]\n", id, info.filePath().latin1());
 
265
 
 
266
                                        type = FT_FILE;
 
267
 
 
268
                                        // now try to open it
 
269
                                        file.setName(fname);
 
270
                                        if(!file.open(IO_ReadOnly)) {
 
271
                                                discard();
 
272
                                                return;
 
273
                                        }
 
274
 
 
275
                                        v_isValid = TRUE;
 
276
                                        valid();
 
277
 
 
278
                                        // write header
 
279
                                        QString header;
 
280
                                        header.sprintf(
 
281
                                                "HTTP/1.0 200 OK\n"
 
282
                                                "Content-Type: %s\n"
 
283
                                                "Content-Length: %d\n"
 
284
                                                "Connection: close\n"
 
285
                                                "\n", mimeGuess(info.fileName()).latin1(), info.size());
 
286
                                        printf("Sending header:\n%s", header.latin1());
 
287
                                        sock.writeBlock(header, header.length());
 
288
                                }
 
289
                                else {
 
290
                                        printf("%04d: listing: [%s]\n", id, info.filePath().latin1());
 
291
 
 
292
                                        bool base = FALSE;
 
293
                                        if(fi->file.filePath() == info.filePath())
 
294
                                                base = TRUE;
 
295
 
 
296
                                        type = FT_STRING;
 
297
                                        stringData = generateHTMLDirectory(base, info.filePath(), QString("Index of %1").arg(resource)).utf8();
 
298
 
 
299
                                        v_isValid = TRUE;
 
300
                                        valid();
 
301
 
 
302
                                        // write header
 
303
                                        QString header = QString(
 
304
                                                "HTTP/1.0 200 OK\n"
 
305
                                                "Content-Type: text/html\n"
 
306
                                                "Content-Length: %1\n"
 
307
                                                "Connection: close\n"
 
308
                                                "\n").arg(stringData.size());
 
309
                                        printf("Sending header:\n%s", header.latin1());
 
310
                                        sock.writeBlock(header, header.length());
 
311
                                }
 
312
                        }
 
313
                        else {
 
314
                                printf("%04d: serving: [%s]\n", id, res.latin1());
 
315
 
 
316
                                type = FT_STRING;
 
317
                                stringData.resize(useImage_len);
 
318
                                memcpy(stringData.data(), useImage_data, useImage_len);
 
319
 
 
320
                                v_isValid = TRUE;
 
321
                                valid();
 
322
 
 
323
                                // write header
 
324
                                QString header = QString(
 
325
                                        "HTTP/1.0 200 OK\n"
 
326
                                        "Content-Type: image/png\n"
 
327
                                        "Content-Length: %1\n"
 
328
                                        "Connection: close\n"
 
329
                                        "\n").arg(stringData.size());
 
330
                                printf("Sending header:\n%s", header.latin1());
 
331
                                sock.writeBlock(header, header.length());
 
332
 
 
333
                        }
 
334
 
 
335
                        // write the first chunk
 
336
                        processChunk();
 
337
                }
 
338
        }
 
339
}
 
340
 
 
341
void FileTransfer::sock_connectionClosed()
 
342
{
 
343
        printf("\n%04d: connection closed\n", id);
 
344
        discard();
 
345
}
 
346
 
 
347
void FileTransfer::sock_bytesWritten(int)
 
348
{
 
349
        if(sock.bytesToWrite() <= 0) {
 
350
                if(finished) {
 
351
                        printf("\n%04d: transfer finished.\n", id);
 
352
                        sock.close();
 
353
                        discard();
 
354
                        return;
 
355
                }
 
356
 
 
357
                QTimer::singleShot(0, this, SLOT(processChunk()));
 
358
        }
 
359
}
 
360
 
 
361
bool FileTransfer::getGETInfo(const QString &getReq, QString *resource, QString *http_ver)
 
362
{
 
363
        QString req = getReq.simplifyWhiteSpace();
 
364
 
 
365
        // these must be the first 4 chars
 
366
        if(req.left(4) != "GET ")
 
367
                return FALSE;
 
368
 
 
369
        QString str = getReq.mid(4);
 
370
 
 
371
        // is there a space later?  if so, grab what is after it (assuming HTTP version)
 
372
        *http_ver = "";
 
373
        int n = str.find(' ');
 
374
        if(n != -1) {
 
375
                if((int)str.length() > n + 1)
 
376
                        *http_ver = str.mid(n + 1);
 
377
                str = str.mid(0, n);
 
378
        }
 
379
        *resource = str;
 
380
 
 
381
        return TRUE;
 
382
}
 
383
 
 
384
bool FileTransfer::extractResourceInfo(const QString &resource, QString *fname, QString *key)
 
385
{
 
386
        QString str = resource;
 
387
 
 
388
        // make sure we begin with a slash
 
389
        if(str.at(0) != '/')
 
390
                return FALSE;
 
391
 
 
392
        // remove it
 
393
        str.remove(0,1);
 
394
 
 
395
        // make sure there is a slash to separate key and filename
 
396
        int n = str.find('/');
 
397
        if(n == -1)
 
398
                return FALSE;
 
399
 
 
400
        *key = str.mid(0, n);
 
401
 
 
402
        *fname = str.mid(n);
 
403
        fname->remove(0,1); // remove the beginning slash
 
404
        *fname = urlDecode(*fname);
 
405
 
 
406
        return TRUE;
 
407
}
 
408
 
 
409
QString urlEncode(const QString &in)
 
410
{
 
411
        QString out;
 
412
 
 
413
        for(unsigned int n = 0; n < in.length(); ++n) {
 
414
                if(in.at(n) == '.') {
 
415
                        out.append('.');
 
416
                }
 
417
                else if(in.at(n) == ' ') {
 
418
                        out.append('+');
 
419
                }
 
420
                else if(!in.at(n).isLetterOrNumber()) {
 
421
                        // hex encode
 
422
                        QString hex;
 
423
                        hex.sprintf("%%%02X", in.at(n).latin1());
 
424
                        out.append(hex);
 
425
                }
 
426
                else {
 
427
                        out.append(in.at(n));
 
428
                }
 
429
        }
 
430
 
 
431
        return out;
 
432
}
 
433
 
 
434
QString urlDecode(const QString &in)
 
435
{
 
436
        QString out;
 
437
 
 
438
        for(unsigned int n = 0; n < in.length(); ++n) {
 
439
                if(in.at(n) == '%' && (in.length() - n - 1) >= 2) {
 
440
                        QString str = in.mid(n+1,2);
 
441
                        bool ok;
 
442
                        char c = str.toInt(&ok, 16);
 
443
                        if(!ok)
 
444
                                continue;
 
445
 
 
446
                        QChar a(c);
 
447
                        out.append(a);
 
448
                        n += 2;
 
449
                }
 
450
                else if(in.at(n) == '+')
 
451
                        out.append(' ');
 
452
                else
 
453
                        out.append(in.at(n));
 
454
        }
 
455
 
 
456
        return out;
 
457
}
 
458
 
 
459
QString mimeGuess(const QString &in)
 
460
{
 
461
        QString ext;
 
462
        int n;
 
463
        for(n = in.length()-1; n > 0; --n) {
 
464
                if(in.at(n) == '.')
 
465
                        break;
 
466
        }
 
467
        if(n == 0)
 
468
                ext = "";
 
469
        else
 
470
                ext = in.mid(n+1).lower();
 
471
 
 
472
        if(ext == "txt" || ext == "c" || ext == "h" || ext == "cpp")
 
473
                return "text/plain";
 
474
        else if(ext == "gif")
 
475
                return "image/gif";
 
476
        else if(ext == "jpeg" || ext == "jpg" || ext == "jpe")
 
477
                return "image/jpeg";
 
478
        else if(ext == "png")
 
479
                return "image/png";
 
480
 
 
481
        return "application/octet-stream";
 
482
}
 
483
 
 
484
QString generateHTMLDirectory(bool base, const QString &dir, const QString &title)
 
485
{
 
486
        QDir d(dir);
 
487
        QString text;
 
488
 
 
489
        // blatant sourceforge ripoff
 
490
        text = QString(
 
491
                "<html>\n"
 
492
                "<head>\n"
 
493
                "  <title>%1</title>\n"
 
494
                "  <style type=\"text/css\">\n"
 
495
                "    body {\n"
 
496
                //"      background-image: url(img/sf-stipple.png);\n"
 
497
                "      background-color: #aaa;\n"
 
498
                "      margin: 0;\n"
 
499
                "    }\n"
 
500
                "    td { font: small sans-serif; padding-left: 0.5em; padding-right: 0.5em;}\n"
 
501
                "    .footer {text-align: center;}\n"
 
502
                "    .directory {color: #595;}\n"
 
503
                "    .sort {color: #000;}\n"
 
504
                "    .label-date {font-family: monospace; color: #555; text-align: left;}\n"
 
505
                "    .label-size {font-family: monospace; color: #555; text-align: center;}\n"
 
506
                "  </style>\n"
 
507
                "</head>\n"
 
508
                "\n"
 
509
                "<body>\n"
 
510
                "\n"
 
511
                "<table align=\"center\" width=\"90%\" bgcolor=\"#FFFFFF\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\">\n"
 
512
                "  <tr><td align=\"center\">\n"
 
513
                "    <table width=\"100%\" cellpadding=\"3\" cellspacing=\"1\" bgcolor=\"#FFFFFF\">\n"
 
514
                "      <tr bgcolor=\"#FFFFFF\">\n<td>Psi Folder Share</td></tr>\n"
 
515
                //"      <tr bgcolor=\"#FFFFFF\">\n"
 
516
                //"        <td colspan=\"3\">Current Directory: <b>http://telia.dl.sourceforge.net/ mirrors/ </b></td>\n"
 
517
                //"      </tr>\n"
 
518
                "      <tr bgcolor=\"#FFFFFF\">\n"
 
519
                "        <th width=\"80%\">File Name</th>\n"
 
520
                "        <th width=\"10%\">Size</th>\n"
 
521
                "        <th width=\"10%\">Date</th>\n"
 
522
                "      </tr>\n"
 
523
                ).arg(title);
 
524
 
 
525
        QStringList entries = d.entryList();
 
526
        entries.sort();
 
527
        bool colorOn = FALSE;
 
528
        for(QStringList::Iterator it = entries.begin(); it != entries.end(); ++it) {
 
529
                QString fname = *it;
 
530
                if(fname == ".")
 
531
                        continue;
 
532
 
 
533
                if(fname == ".." && base)
 
534
                        continue;
 
535
 
 
536
                QString str = "";
 
537
                if(colorOn) {
 
538
                        str += "<tr bgcolor=\"#DDDDDD\">\n";
 
539
                        colorOn = FALSE;
 
540
                }
 
541
                else {
 
542
                        str += "<tr bgcolor=\"#EEEEEE\">\n";
 
543
                        colorOn = TRUE;
 
544
                }
 
545
 
 
546
                QFileInfo info(dir + '/' + fname);
 
547
                if(info.isDir())
 
548
                        fname += '/';
 
549
 
 
550
                if(fname == "../")
 
551
                        str += QString("<td nowrap align=\"left\"><img src=\"%1\" align=\"middle\" width=\"20\" height=\"22\">&nbsp;<a href=\"../\"><font class=\"directory\"><b>-- Parent Directory --</b></font></a></td>\n").arg("/image/ft_back.png");
 
552
                else
 
553
                        str += QString("<td nowrap align=\"left\"><img src=\"%1\" align=\"middle\" width=\"20\" height=\"22\">&nbsp;").arg(info.isDir() ? "/image/ft_folder.png" : "/image/ft_file.png") + QString("<a href=\"%1\">").arg(fname) + QString("<font class=\"directory\"><b>%1</b></font></a></td>\n").arg(fname);
 
554
 
 
555
                QString size, date;
 
556
                if(info.isDir())
 
557
                        size = "-";
 
558
                else
 
559
                        size.sprintf("%d", info.size());
 
560
 
 
561
                date = info.lastModified().toString();
 
562
 
 
563
                str += QString(
 
564
                        "  <td nowrap align=\"center\" class=\"label-size\">%1</td>\n").arg(size);
 
565
                str += QString(
 
566
                        "  <td nowrap align=\"left\" class=\"label-date\">%1</td>\n"
 
567
                        "</tr>\n").arg(date);
 
568
 
 
569
                text += str;
 
570
        }
 
571
 
 
572
        text += QString(
 
573
                "        <tr>\n"
 
574
                "          <td colspan=\"3\">\n"
 
575
                "            <pre></pre>\n"
 
576
                "          </td>\n"
 
577
                "        </tr>\n"
 
578
                "      </table>\n"
 
579
                "      <p class=\"footer\">%1</p>\n"
 
580
                "    </td>\n"
 
581
                "  </tr>\n"
 
582
                "</table>\n"
 
583
                "\n"
 
584
                "</body>\n"
 
585
                "</html>\n\n").arg(QDateTime::currentDateTime().toString());
 
586
 
 
587
        return text;
 
588
}
 
589
 
 
590
 
 
591
/****************************************************************************
 
592
  FileServer
 
593
****************************************************************************/
 
594
FileServer::FileServer()
 
595
{
 
596
#ifndef Q_WS_WIN
 
597
        // block SIGPIPE
 
598
        old_sigpipe = signal(SIGPIPE, SIG_IGN);
 
599
#endif
 
600
 
 
601
        // seed random number generator
 
602
        srand(time(NULL));
 
603
 
 
604
        current_id = 0;
 
605
        sigmap[0] = new QSignalMapper(this);
 
606
        sigmap[1] = new QSignalMapper(this);
 
607
        connect(sigmap[0], SIGNAL(mapped(int)), this, SLOT(transferDiscarded(int)));
 
608
        filelist.setAutoDelete(TRUE);
 
609
 
 
610
        host = "127.0.0.1";
 
611
        port = 12345;
 
612
        serv = 0;
 
613
}
 
614
 
 
615
FileServer::~FileServer()
 
616
{
 
617
        delete sigmap[0];
 
618
        delete sigmap[1];
 
619
 
 
620
        ftlist.setAutoDelete(TRUE);
 
621
        ftlist.clear();
 
622
 
 
623
#ifndef Q_WS_WIN
 
624
        signal(SIGPIPE, old_sigpipe);
 
625
#endif
 
626
}
 
627
 
 
628
void FileServer::setServer(const QString &_host, int _port)
 
629
{
 
630
        host = _host;
 
631
        port = _port;
 
632
 
 
633
        listen();
 
634
}
 
635
 
 
636
FileServerItem *FileServer::addFile(const QString &_fname, const QString &desc, const QString &who)
 
637
{
 
638
        QString fname = _fname;
 
639
 
 
640
        // hack off a trailing backslash
 
641
        if(fname.at(fname.length()-1) == '/')
 
642
                fname.remove(fname.length()-1, 1);
 
643
 
 
644
        // get unused key
 
645
        QString key;
 
646
        bool ok;
 
647
        do {
 
648
                key = genKey();
 
649
 
 
650
                ok = TRUE;
 
651
                QPtrListIterator<FileServerItem> it(filelist);
 
652
                FileServerItem *fi;
 
653
                for(; (fi = it.current()); ++it) {
 
654
                        if(fi->key == key) {
 
655
                                ok = FALSE;
 
656
                                break;
 
657
                        }
 
658
                }
 
659
        } while(!ok);
 
660
 
 
661
        QFileInfo info(fname);
 
662
        info.convertToAbs();
 
663
        if(!info.exists())
 
664
                return 0;
 
665
 
 
666
        FileServerItem *i;
 
667
        i = new FileServerItem;
 
668
        i->file = info;
 
669
        i->type = info.isDir() ? 1: 0;
 
670
        i->key = key;
 
671
        i->who = who;
 
672
        i->desc = desc;
 
673
        i->url = QString("http://") + host + QString(":%1").arg(port) + "/" + key + "/" + urlEncode(i->file.fileName());
 
674
        if(i->type == 1)
 
675
                i->url += '/';
 
676
        filelist.append(i);
 
677
 
 
678
        return i;
 
679
}
 
680
 
 
681
QPtrList<FileServerItem> FileServer::items() const
 
682
{
 
683
        QPtrList<FileServerItem> list;
 
684
        list.setAutoDelete(FALSE);
 
685
 
 
686
        QPtrListIterator<FileServerItem> it(filelist);
 
687
        FileServerItem *fi;
 
688
        for(; (fi = it.current()); ++it)
 
689
                list.append(fi);
 
690
 
 
691
        return list;
 
692
}
 
693
 
 
694
void FileServer::listen()
 
695
{
 
696
        if(serv) {
 
697
                delete serv;
 
698
                serv = 0;
 
699
        }
 
700
 
 
701
        serv = new ServSock(port);
 
702
        connect(serv, SIGNAL(connectionReady(int)), SLOT(connectionReady(int)));
 
703
}
 
704
 
 
705
FileTransfer *FileServer::findByID(int id)
 
706
{
 
707
        QPtrListIterator<FileTransfer> it(ftlist);
 
708
        for(FileTransfer *f; (f = it.current()); ++it) {
 
709
                if(f->id == id)
 
710
                        return f;
 
711
        }
 
712
 
 
713
        return 0;
 
714
}
 
715
 
 
716
void FileServer::connectionReady(int sock)
 
717
{
 
718
        FileTransfer *f = new FileTransfer(this);
 
719
        f->sock.setSocket(sock);
 
720
        f->id = current_id;
 
721
        ftlist.append(f);
 
722
        ++current_id;
 
723
 
 
724
        sigmap[0]->setMapping(f, f->id);
 
725
        connect(f, SIGNAL(discarding()), sigmap[0], SLOT(map()));
 
726
        f->start();
 
727
}
 
728
 
 
729
QString FileServer::genKey()
 
730
{
 
731
        QString key;
 
732
 
 
733
        for(int i = 0; i < 4; ++i) {
 
734
                int word = rand() & 0xffff;
 
735
                for(int n = 0; n < 4; ++n) {
 
736
                        QString s;
 
737
                        s.sprintf("%x", (word >> (n * 4)) & 0xf);
 
738
                        key.append(s);
 
739
                }
 
740
        }
 
741
 
 
742
        return key;
 
743
}
 
744
 
 
745
FileServerItem *FileServer::getFSI(const QString &key)
 
746
{
 
747
        QPtrListIterator<FileServerItem> it(filelist);
 
748
        FileServerItem *fi;
 
749
        for(; (fi = it.current()); ++it) {
 
750
                if(fi->key == key)
 
751
                        return fi;
 
752
        }
 
753
 
 
754
        return 0;
 
755
}
 
756
 
 
757
void FileServer::transferDiscarded(int x)
 
758
{
 
759
        FileTransfer *f = findByID(x);
 
760
        if(!f)
 
761
                return;
 
762
 
 
763
        printf("%04d: transfer object discarded.\n", f->id);
 
764
 
 
765
        ftlist.remove(f);
 
766
}
 
767
 
 
768
//                      QGuardedPtr<FileTransfer> gf = f;
 
769
//                      newDownload(gf);
 
770
 
 
771
/****************************************************************************
 
772
  ServSock
 
773
****************************************************************************/
 
774
ServSock::ServSock(int port)
 
775
:QServerSocket(port, 16)
 
776
{
 
777
}
 
778
 
 
779
void ServSock::newConnection(int x)
 
780
{
 
781
        connectionReady(x);
 
782
}