~ubuntu-branches/ubuntu/trusty/kvirc/trusty

« back to all changes in this revision

Viewing changes to src/kvilib/ext/kvi_sharedfiles.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kai Wasserbäch, Kai Wasserbäch, Raúl Sánchez Siles
  • Date: 2011-02-12 10:40:21 UTC
  • mfrom: (14.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20110212104021-5mh4f75jlku20mnt
The combined "Twisted Experiment" and "Nocturnal Raid" release.

[ Kai Wasserbäch ]
* Synced to upstream's SVN revision 5467.
* debian/rules:
  - Added .PHONY line.
  - Resurrect -DMANUAL_REVISION, got lost somewhere and we build SVN
    revisions again.
  - Replace "-DWITH_NO_EMBEDDED_CODE=YES" with "-DWANT_CRYPTOPP=YES".
  - Change the remaining -DWITH/-DWITHOUT to the new -DWANT syntax.
* debian/control:
  - Removed DMUA, I'm a DD now.
  - Changed my e-mail address.
  - Removed unneeded relationships (no upgrades over two releases are
    supported).
  - Fix Suggests for kvirc-dbg.
  - kvirc-data: Make the "Suggests: kvirc" a Recommends, doesn't make much
    sense to install the -data package without the program.
* debian/source/local-options: Added with "unapply-patches".
* debian/kvirc.lintian-overrides: Updated to work for 4.1.1.
* debian/patches/21_make_shared-mime-info_B-D_superfluous.patch: Updated.
* debian/kvirc-data.install: Added .notifyrc.

[ Raúl Sánchez Siles ]
* Stating the right version where kvirc-data break and replace should happen.
* Fixing link to license file.
* Added French and Portuguese man pages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//=============================================================================
2
 
//
3
 
//   File : kvi_filetrader.cpp
4
 
//   Creation date : Wed Aug 27 2000 10:33:11 CEST by Szymon Stefanek
5
 
//
6
 
//   This file is part of the KVirc irc client distribution
7
 
//   Copyright (C) 2000-2008 Szymon Stefanek (pragma at kvirc dot net)
8
 
//
9
 
//   This program is FREE software. You can redistribute it and/or
10
 
//   modify it under the terms of the GNU General Public License
11
 
//   as published by the Free Software Foundation; either version 2
12
 
//   of the License, or (at your opinion) any later version.
13
 
//
14
 
//   This program is distributed in the HOPE that it will be USEFUL,
15
 
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
 
//   See the GNU General Public License for more details.
18
 
//
19
 
//   You should have received a copy of the GNU General Public License
20
 
//   along with this program. If not, write to the Free Software Foundation,
21
 
//   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
 
//
23
 
//=============================================================================
24
 
 
25
 
 
26
 
 
27
 
#include "kvi_sharedfiles.h"
28
 
 
29
 
#include "kvi_config.h"
30
 
#include "kvi_fileutils.h"
31
 
 
32
 
#include <QFileInfo>
33
 
 
34
 
// TODO: Match servers that the file requests come from
35
 
// TODO: Max number of downloads ?
36
 
 
37
 
// FIXME: MD5SUM ?
38
 
 
39
 
/*
40
 
        @doc: shared_files
41
 
        @title:
42
 
                Sharing files with KVIrc
43
 
        @type:
44
 
                generic
45
 
        @short:
46
 
                Automatically sharing your files with other IRC users
47
 
        @keyterms:
48
 
                file sharing
49
 
        @body:
50
 
                [big]What is this ?[/big]
51
 
                The "file offers" are a simple way to share your files with other IRC users.[br]
52
 
                Basically , you setup an offer by selecting a local file, choosing a "visible name" for it.
53
 
                Remote users will be able to request you the file and download it automatically by
54
 
                issuing a simple DCC GET request.[br]
55
 
                [big]Details[/big]
56
 
                Each offer refers to an existing file on one of your locally mounted file systems.
57
 
                The offer is given a visible name that the remote users will effectively request.
58
 
                To share the file /usr/arch/mp3/SonataArctica_SingInSilence_Live.mp3 you will add a file offer
59
 
                with /usr/arch/mp3/SonataArctica_SingInSilence_Live.mp3 as real file path , something like
60
 
                "SonataArctica_SingInSilence.mp3". A remote user will then request you a DCC GET SonataArctica_SingInSilence.mp3
61
 
                and KVIrc will automatically send the file.[br]
62
 
                Each file offer has an "user mask" that the requesting remote users must match to
63
 
                obtain the file: *!*@* matches any user, Pragma!*@* matches any user with nickname pragma,
64
 
                *!*@*.omnikron.net matches any user coming from the omnikron.net domain.[br]
65
 
                Each offer can have an expire time: the offer will be automatically removed after
66
 
                a defined number of seconds. An expire time of '0' seconds means that the offer should never expire.[br]
67
 
                If you have two file offers with the same name and different file, the remote user can
68
 
                use an additional "size" parameter in the DCC GET request.[br]
69
 
                [big]Security issues[/big]
70
 
                This is a nice but unsecure method of sharing files.[br]
71
 
                The user mask is a good protection but you have to use it properly!.[br]
72
 
                Setting the user mask to Nick!*@* can be easily exploited (just by making an user disconnect
73
 
                in one of the well known ways and then by using his nickname).[br]
74
 
                On the other side, the remote end must know exactly the visible name of the offer to request
75
 
                and noone but you will tell him that name.[br]
76
 
                In sum:[br]
77
 
                Don't share any really important files: this *might* be like putting it on your webpage :D[br]
78
 
                Please don't send complains if someone stoles your /etc/passwd : it is because you have permitted that.[br]
79
 
*/
80
 
 
81
 
KviSharedFile::KviSharedFile(const QString &szName,const QString &szAbsPath,const QString &szUserMask,time_t expireTime,unsigned int uFileSize)
82
 
{
83
 
        m_szName = szName;
84
 
        m_szAbsFilePath = szAbsPath;
85
 
        m_szUserMask = szUserMask;
86
 
        m_expireTime = expireTime;
87
 
        m_uFileSize = uFileSize;
88
 
 
89
 
        m_uWildCount = m_szUserMask.count('*');
90
 
        m_uNonWildCount = m_szUserMask.length() - m_uWildCount;
91
 
}
92
 
 
93
 
KviSharedFile::~KviSharedFile()
94
 
{
95
 
}
96
 
 
97
 
 
98
 
KviSharedFilesManager::KviSharedFilesManager()
99
 
: QObject()
100
 
{
101
 
        m_pSharedListDict = new KviPointerHashTable<QString,KviSharedFileList>();
102
 
        m_pSharedListDict->setAutoDelete(true);
103
 
        m_pCleanupTimer = new QTimer();
104
 
        connect(m_pCleanupTimer,SIGNAL(timeout()),this,SLOT(cleanup()));
105
 
}
106
 
 
107
 
KviSharedFilesManager::~KviSharedFilesManager()
108
 
{
109
 
        if(m_pCleanupTimer->isActive())m_pCleanupTimer->stop();
110
 
        delete m_pCleanupTimer;
111
 
        delete m_pSharedListDict;
112
 
}
113
 
 
114
 
void KviSharedFilesManager::cleanup()
115
 
{
116
 
        KviPointerHashTableIterator<QString,KviSharedFileList> it(*m_pSharedListDict);
117
 
        time_t curTime = time(0);
118
 
 
119
 
        bool bOtherStuffToCleanup = false;
120
 
        //bool bChanged = false;
121
 
 
122
 
        KviPointerList<QString> lDying;
123
 
        lDying.setAutoDelete(true);
124
 
 
125
 
        while(KviSharedFileList * l = it.current())
126
 
        {
127
 
                KviPointerList<KviSharedFile> tmp;
128
 
                tmp.setAutoDelete(false);
129
 
                for(KviSharedFile * o = l->first();o;o = l->next())
130
 
                {
131
 
                        if(o->expireTime() > 0)
132
 
                        {
133
 
                                if(((int)o->expireTime()) <= ((int)curTime))
134
 
                                {
135
 
                                        tmp.append(o);
136
 
                                        //bChanged = true;
137
 
                                } else {
138
 
                                        bOtherStuffToCleanup = true;
139
 
                                }
140
 
                        }
141
 
                }
142
 
                for(KviSharedFile * fo = tmp.first();fo;fo = tmp.next())
143
 
                {
144
 
                        l->removeRef(fo);
145
 
                        emit sharedFileRemoved(fo);
146
 
                }
147
 
                if(l->count() == 0)
148
 
                        lDying.append(new QString(it.currentKey()));
149
 
 
150
 
                ++it;
151
 
        }
152
 
 
153
 
        for(QString * pDyingKey = lDying.first();pDyingKey;pDyingKey = lDying.next())
154
 
                m_pSharedListDict->remove(*pDyingKey);
155
 
 
156
 
        if(!bOtherStuffToCleanup)m_pCleanupTimer->stop();
157
 
        //if(bChanged)emit sharedFilesChanged();
158
 
}
159
 
 
160
 
void KviSharedFilesManager::clear()
161
 
{
162
 
        m_pSharedListDict->clear();
163
 
        emit sharedFilesChanged();
164
 
}
165
 
 
166
 
void KviSharedFilesManager::doInsert(KviSharedFileList * l, KviSharedFile * o)
167
 
{
168
 
        int index = 0;
169
 
        for(KviSharedFile * fo =l->first();fo;fo = l->next())
170
 
        {
171
 
                if(o->wildcardCount() > 0)
172
 
                {
173
 
                        // the new mask has wildcards... if the current one has none, skip it
174
 
                        if(fo->wildcardCount() > 0)
175
 
                        {
176
 
                                // the one in the list has wildcards too...
177
 
                                // the ones with more non-wild chars go first...
178
 
                                if(fo->nonWildcardCount() < o->nonWildcardCount())
179
 
                                {
180
 
                                        // ok...the new one has more non-wildcards , insert
181
 
                                        l->insert(index,o);
182
 
                                        return;
183
 
                                } else {
184
 
                                        if(o->nonWildcardCount() == fo->nonWildcardCount())
185
 
                                        {
186
 
                                                // the same number of non-wildcards
187
 
                                                // let the number of wildcards decide (it will be eventually equal)
188
 
                                                if(o->wildcardCount() < fo->wildcardCount())
189
 
                                                {
190
 
                                                        // the new one has less wildcards... goes first
191
 
                                                        l->insert(index,o);
192
 
                                                        return;
193
 
                                                } // else the same number of wildcards and non-wildcards...skip
194
 
                                        } // else the existing one has more non-wildcards...skip
195
 
                                }
196
 
                        } // else the current has no wildcards...skip
197
 
                } else {
198
 
                        // the new mask has no wildcards....
199
 
                        if(fo->wildcardCount() > 0)
200
 
                        {
201
 
                                // current one has wildcards...insert
202
 
                                l->insert(index,o);
203
 
                                return;
204
 
                        }
205
 
                        // the current one has no wildcards...
206
 
                        // the longer masks go first....
207
 
                        if(fo->maskLength() < o->maskLength())
208
 
                        {
209
 
                                // the current one is shorter than the new one...insert
210
 
                                l->insert(index,o);
211
 
                                return;
212
 
                        } // else current one is longer...skip
213
 
                }
214
 
                index++;
215
 
        }
216
 
        l->append(o);
217
 
}
218
 
 
219
 
void KviSharedFilesManager::addSharedFile(KviSharedFile * f)
220
 
{
221
 
        // First find the list
222
 
        KviSharedFileList * l = m_pSharedListDict->find(f->name());
223
 
        if(!l)
224
 
        {
225
 
                l = new KviSharedFileList;
226
 
                l->setAutoDelete(true);
227
 
                m_pSharedListDict->replace(f->name(),l);
228
 
        }
229
 
 
230
 
        doInsert(l,f);
231
 
 
232
 
        if(((int)f->expireTime()) > 0)
233
 
        {
234
 
                if(!m_pCleanupTimer->isActive())m_pCleanupTimer->start(60000);
235
 
        }
236
 
 
237
 
        emit sharedFileAdded(f);
238
 
}
239
 
 
240
 
KviSharedFile * KviSharedFilesManager::addSharedFile(const QString &szName,const QString &szAbsPath,const QString &szMask,int timeoutInSecs)
241
 
{
242
 
        QFileInfo inf(szAbsPath);
243
 
        if(inf.exists() && inf.isFile() && inf.isReadable() && (inf.size() > 0))
244
 
        {
245
 
                // First find the list
246
 
                KviSharedFileList * l = m_pSharedListDict->find(szName);
247
 
                if(!l)
248
 
                {
249
 
                        l = new KviSharedFileList;
250
 
                        l->setAutoDelete(true);
251
 
                        m_pSharedListDict->replace(szName,l);
252
 
                }
253
 
 
254
 
                // Now insert
255
 
                KviSharedFile * o = new KviSharedFile(szName,szAbsPath,szMask,timeoutInSecs > 0 ? (((int)(time(0))) + timeoutInSecs) : 0,inf.size());
256
 
 
257
 
                doInsert(l,o);
258
 
 
259
 
                if(((int)o->expireTime()) > 0)
260
 
                {
261
 
                        if(!m_pCleanupTimer->isActive())m_pCleanupTimer->start(60000);
262
 
                }
263
 
 
264
 
                emit sharedFileAdded(o);
265
 
 
266
 
                return o;
267
 
        } else {
268
 
                debug("File %s unreadable: can't add offer",KviQString::toUtf8(szAbsPath).data());
269
 
                return 0;
270
 
        }
271
 
}
272
 
 
273
 
KviSharedFile * KviSharedFilesManager::lookupSharedFile(const QString &szName,KviIrcMask * mask,unsigned int uFileSize)
274
 
{
275
 
        KviSharedFileList * l = m_pSharedListDict->find(szName);
276
 
        if(!l)return 0;
277
 
 
278
 
        for(KviSharedFile * o = l->first();o;o = l->next())
279
 
        {
280
 
                bool bMatch;
281
 
                if(mask)
282
 
                {
283
 
                        KviIrcMask umask(o->userMask());
284
 
                        bMatch = mask->matchedBy(umask);
285
 
                } else bMatch = KviQString::equalCS(o->userMask(),"*!*@*");
286
 
                if(bMatch)
287
 
                {
288
 
                        if(uFileSize > 0)
289
 
                        {
290
 
                                if(uFileSize == o->fileSize())return o;
291
 
                        } else return o;
292
 
                }
293
 
        }
294
 
 
295
 
        return 0;
296
 
}
297
 
bool KviSharedFilesManager::removeSharedFile(const QString &szName,const QString &szMask,unsigned int uFileSize)
298
 
{
299
 
        KviSharedFileList * l = m_pSharedListDict->find(szName);
300
 
        if(!l)return false;
301
 
        for(KviSharedFile * o = l->first();o;o = l->next())
302
 
        {
303
 
                if(KviQString::equalCI(szMask,o->userMask()))
304
 
                {
305
 
                        bool bMatch = uFileSize > 0 ? uFileSize == o->fileSize() : true;
306
 
                        if(bMatch)
307
 
                        {
308
 
                                QString save = szName; // <-- szName MAY Be a pointer to o->name()
309
 
                                l->removeRef(o);
310
 
                                if(l->count() == 0)m_pSharedListDict->remove(save);
311
 
                                emit sharedFileRemoved(o);
312
 
                                return true;
313
 
                        }
314
 
                }
315
 
        }
316
 
        return false;
317
 
}
318
 
 
319
 
bool KviSharedFilesManager::removeSharedFile(const QString &szName,KviSharedFile * off)
320
 
{
321
 
        KviSharedFileList * l = m_pSharedListDict->find(szName);
322
 
        if(!l)return false;
323
 
        for(KviSharedFile * o = l->first();o;o = l->next())
324
 
        {
325
 
                if(off == o)
326
 
                {
327
 
                        QString save = szName; // <-- szName MAY Be a pointer to o->name()
328
 
                        l->removeRef(o);
329
 
                        if(l->count() == 0)m_pSharedListDict->remove(save);
330
 
                        emit sharedFileRemoved(off);
331
 
                        return true;
332
 
                }
333
 
        }
334
 
        return false;
335
 
}
336
 
 
337
 
 
338
 
void KviSharedFilesManager::load(const QString &filename)
339
 
{
340
 
        KviConfig cfg(filename,KviConfig::Read);
341
 
        //cfg.clear();
342
 
        cfg.setGroup("PermanentFileOffers");
343
 
        int num = cfg.readIntEntry("NEntries",0);
344
 
        for(int idx=0;idx<num;idx++)
345
 
        {
346
 
                QString tmp;
347
 
                KviQString::sprintf(tmp,"%dFName",idx);
348
 
                QString szName = cfg.readQStringEntry(tmp,"");
349
 
                KviQString::sprintf(tmp,"%dFilePath",idx);
350
 
                QString szPath = cfg.readQStringEntry(tmp,"");
351
 
                KviQString::sprintf(tmp,"%dUserMask",idx);
352
 
                QString szMask = cfg.readQStringEntry(tmp,"");
353
 
                if(!szMask.isEmpty() && !szPath.isEmpty() && !szName.isEmpty())
354
 
                        addSharedFile(szName,szPath,szMask,0);
355
 
        }
356
 
}
357
 
 
358
 
void KviSharedFilesManager::save(const QString &filename)
359
 
{
360
 
        KviConfig cfg(filename,KviConfig::Write);
361
 
        cfg.clear();
362
 
        cfg.setGroup("PermanentFileOffers");
363
 
 
364
 
        KviPointerHashTableIterator<QString,KviSharedFileList> it(*m_pSharedListDict);
365
 
        int idx = 0;
366
 
        while(KviSharedFileList * l = it.current())
367
 
        {
368
 
                for(KviSharedFile * o = l->first();o;o = l->next())
369
 
                {
370
 
                        if(((int)(o->expireTime())) == 0)
371
 
                        {
372
 
                                QString tmp;
373
 
                                KviQString::sprintf(tmp,"%dFName",idx);
374
 
                                cfg.writeEntry(tmp,it.currentKey());
375
 
                                KviQString::sprintf(tmp,"%dFilePath",idx);
376
 
                                cfg.writeEntry(tmp,o->absFilePath());
377
 
                                KviQString::sprintf(tmp,"%dUserMask",idx);
378
 
                                cfg.writeEntry(tmp,o->userMask());
379
 
                                ++idx;
380
 
                        }
381
 
                }
382
 
                ++it;
383
 
        }
384
 
        cfg.writeEntry("NEntries",idx);
385
 
}