~ubuntu-branches/ubuntu/hoary/kvirc/hoary

« back to all changes in this revision

Viewing changes to src/plugins/fserve/libkvifserve.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Robin Verduijn
  • Date: 2004-12-14 15:32:19 UTC
  • mfrom: (0.2.1 upstream) (1.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20041214153219-fdink3gyp2s20b6g
Tags: 2:2.1.3.1-2
* Change Recommends on xmms to a Suggests.
* Rebuild against KDE 3.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//
2
 
//   File : libkvfserve.cpp (/usr/build/KVIrc/kvirc/src/kvilib/libkvifserve.cpp)
3
 
//   Last major modification : Wed Jul 21 1999 16:41:14 by Szymon Stefanek
4
 
//
5
 
//   This file is part of the KVirc irc client distribution
6
 
//   Copyright (C) 1999-2000 Szymon Stefanek (stefanek@tin.it)
7
 
//
8
 
//   This program is FREE software. You can redistribute it and/or
9
 
//   modify it under the terms of the GNU General Public License
10
 
//   as published by the Free Software Foundation; either version 2
11
 
//   of the License, or (at your opinion) any later version.
12
 
//
13
 
//   This program is distributed in the HOPE that it will be USEFUL,
14
 
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
 
//   See the GNU General Public License for more details.
17
 
//
18
 
//   You should have received a copy of the GNU General Public License
19
 
//   along with this program. If not, write to the Free Software Foundation,
20
 
//   Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
 
//
22
 
#define __KVIRC_PLUGIN__
23
 
#include "kvirc_plugin.h"
24
 
 
25
 
#include "libkvifserve.h"
26
 
 
27
 
#include "kvi_dcc_chat.h"
28
 
#include "kvi_dcc_manager.h"
29
 
 
30
 
#include "kvi_locale.h"
31
 
 
32
 
#include <qdir.h>
33
 
#include <qfileinfo.h>
34
 
#include <qpushbutton.h>
35
 
 
36
 
// Maximum number of saved user sessions
37
 
#define KVIFSERVE_MAX_SAVED_SESSIONS 32
38
 
#define KVIFSERVE_MAX_PENDING_SESSIONS 32
39
 
 
40
 
// A running fserve session structure
41
 
typedef struct _KviFServeSession
42
 
{
43
 
        KviStr      nick;                       // nickname of the user
44
 
        KviStr      address;                    // ip address (it is the ip address of the remote end of the dcc chat)
45
 
        KviStr      credit;                     // current credit in bytes or the string "unlimited"
46
 
        KviStr      currentDir;                 // current directory , relative to the fserve root
47
 
        KviWindow * pWnd;                       // dcc chat window pointer
48
 
} KviFServeSession;
49
 
 
50
 
// A pending dcc fservice
51
 
typedef struct _KviPendingSession
52
 
{
53
 
        KviWindow * pWnd;                       // an opened dcc chat window waiting for the connection
54
 
        KviStr      password;                   // a password (if it has been specified in PRIVMSG)
55
 
} KviPendingSession;
56
 
 
57
 
// A saved fserve session
58
 
// Used to save the credit
59
 
typedef struct _KviSavedSession
60
 
{
61
 
        KviStr nick;                            // nickname
62
 
        KviStr address;                         // ip address
63
 
        KviStr credit;                          // last credit (never "unlimited")
64
 
} KviSavedSession;
65
 
 
66
 
 
67
 
// Global variables
68
 
static KviStr g_szFServeRoot("/");          // root directory of the fileserver (must be an absolute path)
69
 
static KviStr g_szMotd("No MOTD yet");      // message of the day (multiline text)
70
 
static KviStr g_szFServePass("");           // password for the public access
71
 
static KviStr g_szInitialCredit("0");       // initial credit for the public access
72
 
static int g_iRatioTake = 1;                // ratio : give g_iRatioGive bytes of credit for each
73
 
static int g_iRatioGive = 1;                //         packet of g_iRatioTake bytes
74
 
static bool g_bServerActive = false;        // global activation flag (if this is false the fserver is dead)
75
 
static bool g_bShowMotdAtLogin = true;      // show message of the day at user login ?
76
 
static QList<KviStr> * g_pBannedIpList = 0; // banned ip addresses
77
 
static bool g_bListenToPrivmsg = false;     // can be run by /msg <nick> !fserve <pass> ?
78
 
static unsigned int g_uMaxRunningSessions = 10;      // maximum number of running sessions
79
 
 
80
 
static QList<KviFServeSession> * g_pSessions = 0;         // list of active sessions
81
 
static QList<KviSavedSession> * g_pSavedSessions = 0;     // list of saved sessions
82
 
static KviFServeConfigDialog * g_pConfigDialog = 0;       // global plugin configuration dialog
83
 
static QList<KviPendingSession> * g_pPendingSessions = 0; // list of pending sessions
84
 
 
85
 
void * g_handle = 0;                        // global plugin handle (set by the init routine)
86
 
 
87
 
static bool fserve_checkRoot()
88
 
{
89
 
        //
90
 
        // Check the existence and validity of the fserver root directory
91
 
        //
92
 
 
93
 
        g_szFServeRoot.stripWhiteSpace();
94
 
        if(g_szFServeRoot.lastCharIs('/')){
95
 
                // We need no slash at the end (unless the root is '/')
96
 
                if(g_szFServeRoot.len() > 1)g_szFServeRoot.cutRight(1);
97
 
        }
98
 
        // The root must be an absolute path!
99
 
        if(*(g_szFServeRoot.ptr()) != '/'){
100
 
                debug("FSERVE: File server root path is relative");
101
 
                return false;
102
 
        } else {
103
 
                // Check if we can list the contents of the dir
104
 
                QDir d(g_szFServeRoot.ptr());
105
 
                if(!d.entryInfoList()){
106
 
                        debug("FSERVE: Could not read root directory contents");
107
 
                        return false;
108
 
                }
109
 
        }
110
 
        return true;
111
 
}
112
 
 
113
 
 
114
 
static void fserve_pluginSaveState()
115
 
{
116
 
        KviStr fName;
117
 
        kvirc_plugin_get_config_file_path(fName,"fserve");
118
 
 
119
 
        KviConfig cfg(fName.ptr());
120
 
 
121
 
        KviStr tmp = g_szMotd;
122
 
        tmp.replaceAll('\n',"{NewLine}");
123
 
        cfg.writeEntry("Motd",tmp.ptr());
124
 
        cfg.writeEntry("ShowMotdAtLogin",g_bShowMotdAtLogin);
125
 
        cfg.writeEntry("ServerActive",g_bServerActive);
126
 
        cfg.writeEntry("RatioGive",g_iRatioGive);
127
 
        cfg.writeEntry("RatioTake",g_iRatioTake);
128
 
        cfg.writeEntry("InitialCredit",g_szInitialCredit.ptr());
129
 
        cfg.writeEntry("FServePass",g_szFServePass.ptr());
130
 
        cfg.writeEntry("FServeRoot",g_szFServeRoot.ptr());
131
 
        cfg.writeEntry("ListenToPrivmsg",g_bListenToPrivmsg);
132
 
        cfg.writeEntry("MaxRunningSessions",g_uMaxRunningSessions);
133
 
 
134
 
        tmp = "";
135
 
        for(KviStr * s = g_pBannedIpList->first();s;s=g_pBannedIpList->next()){
136
 
                if(tmp.hasData())tmp.append(',');
137
 
                tmp.append(s->ptr());
138
 
        }
139
 
        cfg.writeEntry("BannedIpList",tmp.ptr());
140
 
}
141
 
 
142
 
 
143
 
 
144
 
 
145
 
static void fserve_pluginLoadState()
146
 
{
147
 
        //
148
 
        // Load the options of the plugin
149
 
        // called from the init_routine
150
 
        //
151
 
 
152
 
        // Find the config file path...
153
 
        // We just have to supply the plugin name
154
 
        // KVIrc will tell us how the file is named and
155
 
        // where it is.
156
 
        KviStr fName;
157
 
        kvirc_plugin_get_config_file_path(fName,"fserve");
158
 
        // Create a KviConfig object
159
 
        // KviConfig is a class specifically designed
160
 
        // for dealing with config files
161
 
        // Its declaration is in kvilib/kvi_config.h
162
 
        KviConfig cfg(fName.ptr());
163
 
        // Finally load the options
164
 
        g_szFServeRoot     = cfg.readEntry("FServeRoot","/usr/local");
165
 
        g_szFServePass     = cfg.readEntry("FServePass","");
166
 
        g_szInitialCredit  = cfg.readEntry("InitialCredit","0");
167
 
        g_iRatioTake       = cfg.readIntEntry("RatioTake",1);
168
 
        if(g_iRatioTake < 1)g_iRatioTake = 1;
169
 
        g_iRatioGive       = cfg.readIntEntry("RatioGive",1);
170
 
        if(g_iRatioGive < 0)g_iRatioGive = 1;
171
 
        g_bServerActive    = cfg.readBoolEntry("ServerActive",false);
172
 
        g_bListenToPrivmsg = cfg.readBoolEntry("ListenToPrivmsg",false);
173
 
        g_uMaxRunningSessions = cfg.readUIntEntry("MaxRunningSessions",10);
174
 
        // The message of the day
175
 
        g_bShowMotdAtLogin = cfg.readBoolEntry("ShowMotdAtLogin",true);
176
 
        g_szMotd           = cfg.readEntry("Motd","No MOTD yet...");
177
 
        // the KviConfig class can not save multiline text options
178
 
        // here is the workaround
179
 
        g_szMotd.replaceAll("{NewLine}","\n");
180
 
        // Banned Ip addresses
181
 
        KviStr tmp         = cfg.readEntry("BannedIpList","");
182
 
        KviStr ip;
183
 
        while(tmp.hasData()){
184
 
                tmp.getToken(ip,',');
185
 
                ip.stripWhiteSpace();
186
 
                if(ip.hasData()){
187
 
                        // TODO : check if it is a valid IP address mask ??
188
 
                        g_pBannedIpList->append(new KviStr(ip.ptr()));
189
 
                }
190
 
        }
191
 
        // Check the server root directory
192
 
        g_bServerActive = (fserve_checkRoot() && g_bServerActive);
193
 
}
194
 
 
195
 
static KviFServeSession * fserve_findRunningSession(KviWindow * wnd)
196
 
{
197
 
        //
198
 
        // Find a running fserve session
199
 
        //
200
 
 
201
 
        for(KviFServeSession *s=g_pSessions->first();s;s=g_pSessions->next()){
202
 
                if(wnd == s->pWnd)return s;
203
 
        }
204
 
        return 0;
205
 
}
206
 
 
207
 
static KviFServeSession * fserve_findRunningSessionByNickAndIp(const char *nick,const char *ip)
208
 
{
209
 
        //
210
 
        // Find a running fserve session
211
 
        //
212
 
 
213
 
        for(KviFServeSession *s=g_pSessions->first();s;s=g_pSessions->next()){
214
 
                if(kvi_strEqualCI(nick,s->nick.ptr())){
215
 
                        if(kvi_strEqualCI(s->address.ptr(),ip))return s;
216
 
                }
217
 
        }
218
 
        return 0;
219
 
}
220
 
 
221
 
static KviPendingSession * fserve_findPendingSession(KviWindow * wnd)
222
 
{
223
 
        //
224
 
        // Find a pending fserve session
225
 
        //
226
 
 
227
 
        for(KviPendingSession *s=g_pPendingSessions->first();s;s=g_pPendingSessions->next()){
228
 
                if(wnd == s->pWnd)return s;
229
 
        }
230
 
        return 0;
231
 
}
232
 
 
233
 
static KviSavedSession * fserve_findSavedSession(const char *nick,const char *ip)
234
 
{
235
 
        //
236
 
        // Find a saved fserve session
237
 
        //
238
 
 
239
 
        for(KviSavedSession *s=g_pSavedSessions->first();s;s=g_pSavedSessions->next()){
240
 
                if(kvi_strEqualCI(s->nick.ptr(),nick)){
241
 
                        if(kvi_strEqualCI(s->address.ptr(),ip))return s;
242
 
                }
243
 
        }
244
 
        return 0;
245
 
}
246
 
 
247
 
static void fserve_cleanupPendingSessions(KviFrame * frm)
248
 
{
249
 
        QList<KviPendingSession> l;
250
 
        l.setAutoDelete(false);
251
 
        for(KviPendingSession *s=g_pPendingSessions->first();s;s=g_pPendingSessions->next()){
252
 
                if(!frm->windowExists(s->pWnd))l.append(s);
253
 
        }
254
 
        for(KviPendingSession *ps=l.first();ps;ps=l.next())g_pPendingSessions->removeRef(ps);
255
 
}
256
 
 
257
 
static void fserve_chatOutputAndSend(KviPluginCommandStruct *cmd,const char *nick,const KviStr& data)
258
 
{
259
 
        cmd->window->output(KVI_OUT_OWN,"[fserve >> %s] %s",nick,data.ptr());
260
 
        KviStr tmp="[fserve] ";
261
 
        tmp.append(data);
262
 
        if(!((KviDccChat *)(cmd->window))->sendData(tmp.ptr()))debug("oops! dcc chat not connected?");
263
 
}
264
 
 
265
 
static void fserve_parseCmdStats(KviPluginCommandStruct *cmd,KviFServeSession *s)
266
 
{
267
 
        KviStr tmp(KviStr::Format,"Stats for user %s@%s",s->nick.ptr(),s->address.ptr());
268
 
        fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
269
 
        tmp.sprintf("Directory : %s",s->currentDir.ptr());
270
 
        fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
271
 
        tmp.sprintf("Credit : %s bytes",s->credit.ptr());
272
 
        fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
273
 
        if(s->credit.isUnsignedNum()){
274
 
                tmp.sprintf("Ratio : %d:%d",g_iRatioTake,g_iRatioGive);
275
 
                fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
276
 
        }
277
 
}
278
 
 
279
 
static void fserve_parseCmdUnknown(KviPluginCommandStruct *cmd,KviFServeSession *s)
280
 
{
281
 
        cmd->window->output(KVI_OUT_OWN,"[fserve >> %s] %s",s->nick.ptr(),"Unknown command");
282
 
        ((KviDccChat *)(cmd->window))->sendData("[fserve] Unknown command");
283
 
}
284
 
 
285
 
static void fserve_parseCmdLs(KviPluginCommandStruct *cmd,KviFServeSession *s)
286
 
{
287
 
        KviStr tmp = g_szFServeRoot;
288
 
        tmp.append('/');
289
 
        tmp.append(s->currentDir);
290
 
 
291
 
        QString nameFilter = ((cmd->params->count() > 6) ? QString(kvirc_plugin_param(cmd,6)) : QString::null);
292
 
 
293
 
//      if(cmd->params->count() > 6)nameFilter = kvirc_plugin_param(cmd,6);
294
 
 
295
 
        QDir d(QString(tmp.ptr()),nameFilter,QDir::Name|QDir::IgnoreCase|QDir::DirsFirst,QDir::All|QDir::Readable|QDir::Hidden);
296
 
 
297
 
        const QFileInfoList * l = d.entryInfoList();
298
 
        if(!l){
299
 
                fserve_chatOutputAndSend(cmd,s->nick.ptr(),KviStr("Unable to list directory contents."));
300
 
                fserve_chatOutputAndSend(cmd,s->nick.ptr(),KviStr("Probably the file server root directory was reconfigured"));
301
 
                fserve_chatOutputAndSend(cmd,s->nick.ptr(),KviStr("Warping you to /"));
302
 
                s->currentDir = "/";
303
 
                return;
304
 
        }
305
 
 
306
 
        QFileInfoListIterator it(*l);
307
 
        QFileInfo *fi;
308
 
 
309
 
        int total = 0;
310
 
        bool bUnlimitedCredit = kvi_strEqualCI(s->credit.ptr(),"unlimited");
311
 
        unsigned long credit = 0;
312
 
 
313
 
        if(!bUnlimitedCredit){
314
 
                bool bOk = false;
315
 
                credit = s->credit.toUInt(&bOk);
316
 
                if(!bOk)s->credit = "0";
317
 
                credit = 0;
318
 
        }
319
 
 
320
 
        KviStr num;
321
 
 
322
 
        while((fi = it.current())){
323
 
                if(fi->isDir()){
324
 
                        tmp = "D           ";
325
 
                        tmp.append(KVI_TEXT_BOLD);
326
 
                        tmp.append(fi->fileName());
327
 
                        tmp.append(KVI_TEXT_BOLD);
328
 
                } else if(fi->isSymLink()){
329
 
                        tmp = "L ";
330
 
                        num.setNum(fi->size());
331
 
                        if((fi->size() > credit) && (!bUnlimitedCredit)){
332
 
                                tmp.append(KVI_TEXT_COLOR);
333
 
                                tmp.append("4 ");
334
 
                                tmp.append(num);
335
 
                                tmp.append(KVI_TEXT_RESET);
336
 
                                tmp.append(' ');
337
 
                                while(tmp.len() < 15)tmp.append(' ');
338
 
                        } else {
339
 
                                tmp.append(' ');
340
 
                                tmp.append(num);
341
 
                                tmp.append(' ');
342
 
                                while(tmp.len() < 12)tmp.append(' ');
343
 
                        }
344
 
                        tmp.append(fi->fileName());
345
 
                } else {
346
 
                        tmp = "F ";
347
 
                        num.setNum(fi->size());
348
 
                        if((fi->size() > credit) && (!bUnlimitedCredit)){
349
 
                                tmp.append(KVI_TEXT_COLOR);
350
 
                                tmp.append("4 ");
351
 
                                tmp.append(num);
352
 
                                tmp.append(KVI_TEXT_RESET);
353
 
                                tmp.append(' ');
354
 
                                while(tmp.len() < 15)tmp.append(' ');
355
 
                        } else {
356
 
                                tmp.append(' ');
357
 
                                tmp.append(num);
358
 
                                tmp.append(' ');
359
 
                                while(tmp.len() < 12)tmp.append(' ');
360
 
                        }
361
 
                        tmp.append(fi->fileName());
362
 
                }
363
 
 
364
 
                fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
365
 
                
366
 
                ++it;
367
 
                ++total;
368
 
        }
369
 
        tmp.setNum(total);
370
 
        tmp.prepend("total ");
371
 
        fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
372
 
}
373
 
 
374
 
static void fserve_parseCmdCd(KviPluginCommandStruct *cmd,KviFServeSession *s)
375
 
{
376
 
        // get the directory , other parameters are ignored
377
 
        if(cmd->params->count() < 7)return;
378
 
 
379
 
        KviStr dir = kvirc_plugin_param(cmd,6);
380
 
        if(dir.isEmpty())return;
381
 
 
382
 
        KviStr token;
383
 
        const char *aux = dir.ptr();
384
 
        // save the last directory
385
 
        KviStr saveDir = s->currentDir;
386
 
        // if it is absolute path , start from the root
387
 
        while(*aux == '/'){
388
 
                s->currentDir = "/";
389
 
                aux++;
390
 
        }
391
 
 
392
 
        // ensure that our s->currentDir is valid at all
393
 
        if(*(s->currentDir.ptr()) != '/')s->currentDir = '/';
394
 
 
395
 
        bool bError = false;
396
 
 
397
 
        // cd one dir at a time
398
 
        while((*aux) && (!bError)){
399
 
                // get the next path component
400
 
                aux = kvi_extractToken(token,aux,'/');
401
 
 
402
 
                if(token.hasData()){
403
 
                        if(kvi_strEqualCI(token.ptr() , "..")){
404
 
                                // cdup
405
 
                                if(s->currentDir.len() > 1){
406
 
                                        // can cdup
407
 
                                        if(s->currentDir.lastCharIs('/'))s->currentDir.cutRight(1);
408
 
                                        int idx = s->currentDir.findLastIdx('/');
409
 
                                        if(idx > 0)s->currentDir = s->currentDir.left(idx);
410
 
                                        else {
411
 
                                                if(idx == 0)s->currentDir = '/';
412
 
                                        }
413
 
                                        // double check
414
 
                                        if(*(s->currentDir.ptr()) != '/')s->currentDir = "/";
415
 
                                }
416
 
                        } else if(!kvi_strEqualCI(token.ptr(), ".")){
417
 
                                // cd directory
418
 
                                KviStr tmp = g_szFServeRoot;
419
 
                                tmp.append(s->currentDir);
420
 
                                if(!s->currentDir.lastCharIs('/'))tmp.append('/');
421
 
                                tmp.append(token);
422
 
                                if(kvi_directoryExists(tmp.ptr())){
423
 
                                        if(!s->currentDir.lastCharIs('/'))s->currentDir.append('/');
424
 
                                        s->currentDir.append(token);
425
 
                                } else bError = true;
426
 
                        }
427
 
                }
428
 
        }
429
 
 
430
 
        if(bError){
431
 
                s->currentDir = saveDir;
432
 
                token.sprintf("Can not cd to %s : no such directory",dir.ptr());
433
 
        } else token.sprintf("Directory changed to %s",s->currentDir.ptr());
434
 
 
435
 
        fserve_chatOutputAndSend(cmd,s->nick.ptr(),token);
436
 
}
437
 
 
438
 
static void fserve_parseCmdGet(KviPluginCommandStruct *cmd,KviFServeSession *s)
439
 
{
440
 
        if(cmd->params->count() < 7)return;
441
 
        KviStr filename = kvirc_plugin_param(cmd,6);
442
 
        if(filename.isEmpty())return;
443
 
 
444
 
        if(filename.findFirstIdx('/') == -1){
445
 
 
446
 
                KviStr fName = g_szFServeRoot;
447
 
                if(!fName.lastCharIs('/'))fName.append('/');
448
 
                fName.append(s->currentDir);
449
 
                if(!fName.lastCharIs('/'))fName.append('/');
450
 
                fName.append(filename);
451
 
 
452
 
                QFileInfo fi(fName.ptr());
453
 
                if(fi.exists()){
454
 
                        if(fi.isReadable()){
455
 
                                bool bOk = false;
456
 
                                unsigned int credit = s->credit.toUInt(&bOk);
457
 
                                if(bOk){
458
 
                                        if(credit < fi.size()){
459
 
                                                KviStr tmp(KviStr::Format,"%s: Credit too low , please upload first",filename.ptr());
460
 
                                                fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
461
 
                                                return;
462
 
                                        } else {
463
 
                                                credit -= fi.size();
464
 
                                                s->credit.setNum(credit);
465
 
                                        }
466
 
                                }
467
 
                                // start the DCC
468
 
                                cmd->frame->m_pDccManager->requestDccSend(s->nick.ptr(),fName.ptr());
469
 
                                filename.prepend('/');
470
 
                                filename.prepend(s->currentDir);
471
 
                                KviStr tmp(KviStr::Format,"Sending file %s",filename.ptr());
472
 
                                fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
473
 
                                if(bOk){
474
 
                                        tmp.sprintf("Your credit is now %s bytes",s->credit.ptr());
475
 
                                        fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
476
 
                                }
477
 
                        } else {
478
 
                                KviStr tmp(KviStr::Format,"%s: Access forbidden",filename.ptr());
479
 
                                fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
480
 
                        }
481
 
                } else {
482
 
                        KviStr tmp(KviStr::Format,"%s: No such file",filename.ptr());
483
 
                        fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
484
 
                }
485
 
        } else {
486
 
                KviStr tmp(KviStr::Format,"Invalid file name %s (no path elements allowed)",filename.ptr());
487
 
                fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
488
 
        }
489
 
}
490
 
 
491
 
static void fserve_parseCmdHelp(KviPluginCommandStruct *cmd,KviFServeSession *s)
492
 
{
493
 
        fserve_chatOutputAndSend(cmd,s->nick.ptr(),KviStr("Available commands:"));
494
 
        fserve_chatOutputAndSend(cmd,s->nick.ptr(),KviStr(".cd <directory> : changes the current working directory"));
495
 
        fserve_chatOutputAndSend(cmd,s->nick.ptr(),KviStr(".ls : lists the contents of the current directory"));
496
 
        fserve_chatOutputAndSend(cmd,s->nick.ptr(),KviStr(".get <filename> : starts a dcc get session"));
497
 
        fserve_chatOutputAndSend(cmd,s->nick.ptr(),KviStr(".stats : shows your current credit"));
498
 
        fserve_chatOutputAndSend(cmd,s->nick.ptr(),KviStr(".motd : shows the message of the day"));
499
 
        fserve_chatOutputAndSend(cmd,s->nick.ptr(),KviStr(".pwd : shows the current working directory"));
500
 
        fserve_chatOutputAndSend(cmd,s->nick.ptr(),KviStr(".quit: exits fserve mode"));
501
 
}
502
 
 
503
 
static void fserve_parseCmdMotd(KviPluginCommandStruct *cmd,KviFServeSession *s)
504
 
{
505
 
        KviStr tmp = g_szMotd;
506
 
        KviStr line;
507
 
        while(tmp.getLine(line))fserve_chatOutputAndSend(cmd,s->nick.ptr(),line);
508
 
}
509
 
 
510
 
static void fserve_parseCmdPwd(KviPluginCommandStruct *cmd,KviFServeSession *s)
511
 
{
512
 
        KviStr tmp(KviStr::Format,"Current directory is %s",s->currentDir.ptr());
513
 
        fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);        
514
 
}
515
 
 
516
 
static void fserve_closeSession(KviFServeSession *s)
517
 
{
518
 
        if(!kvi_strEqualCI(s->credit.ptr(),"unlimited")){
519
 
                // limited credit....need to save the session
520
 
                KviSavedSession * ss = new KviSavedSession;
521
 
                ss->nick = s->nick;
522
 
                ss->address = s->address;
523
 
                ss->credit = s->credit;
524
 
                g_pSavedSessions->append(ss);
525
 
                if(g_pSavedSessions->count() > KVIFSERVE_MAX_SAVED_SESSIONS)g_pSavedSessions->removeFirst();
526
 
        }
527
 
        // close the session
528
 
        g_pSessions->removeRef(s);
529
 
}
530
 
 
531
 
static void fserve_parseCmdQuit(KviPluginCommandStruct *cmd,KviFServeSession *s)
532
 
{
533
 
        fserve_chatOutputAndSend(cmd,s->nick.ptr(),KviStr("File server session closed."));      
534
 
        fserve_closeSession(s);
535
 
}
536
 
 
537
 
static bool fserve_isBannedIp(const char *ip)
538
 
{
539
 
        for(KviStr * s=g_pBannedIpList->first();s;s=g_pBannedIpList->next()){
540
 
                if(kvi_matchWildExpr(ip,s->ptr()))return true;
541
 
        }
542
 
        return false;
543
 
}
544
 
 
545
 
static void fserve_startSession(KviPluginCommandStruct *cmd,const char *nick,
546
 
        const char *ip,const char *credit)
547
 
{
548
 
        KviFServeSession *s = new KviFServeSession;
549
 
        s->nick = nick;
550
 
        s->address = ip;
551
 
        s->currentDir = "/";
552
 
        s->credit = credit;
553
 
        s->pWnd = cmd->window;
554
 
        g_pSessions->append(s);
555
 
        cmd->window->output(KVI_OUT_INTERNAL,"[fserve] Opening fserve session for user %s@%s",s->nick.ptr(),s->address.ptr());
556
 
        if(g_bShowMotdAtLogin)fserve_parseCmdMotd(cmd,s);
557
 
        fserve_parseCmdStats(cmd,s);
558
 
//      fserve_parseCmdPwd(cmd,s);
559
 
}
560
 
 
561
 
static void fserve_startNormalSession(KviPluginCommandStruct *cmd,const char *nick,const char *ip)
562
 
{
563
 
        KviSavedSession * ss= fserve_findSavedSession(nick,ip);
564
 
        if(ss){
565
 
                // normal session
566
 
                fserve_startSession(cmd,nick,ip,ss->credit.ptr());
567
 
                g_pSavedSessions->removeRef(ss);
568
 
        } else {
569
 
                // new session
570
 
                fserve_startSession(cmd,nick,ip,g_szInitialCredit.ptr());
571
 
        }
572
 
}
573
 
 
574
 
static void fserve_doLogin(KviPluginCommandStruct * cmd,KviStr &nick,KviStr &user,KviStr &host,KviStr &ip,KviStr &pass)
575
 
{
576
 
        // user & host is known
577
 
        if(g_pSessions->count() >= g_uMaxRunningSessions){
578
 
                fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Sorry , the server is full: try again later"));
579
 
                return;
580
 
        }
581
 
 
582
 
        KviStr mask(KviStr::Format,"%s!%s@%s",nick.ptr(),user.ptr(),host.ptr());
583
 
        KviRegisteredUser * u = kvirc_plugin_find_registered_user_with_flag(mask.ptr(),'f');
584
 
        if(u){
585
 
                // user is registered with the fserve flag
586
 
                // check if has a password set
587
 
                u->passwd.stripWhiteSpace(); // no spaces allowed
588
 
                if(u->passwd.hasData()){
589
 
                        // check if the user specified a password
590
 
                        if(pass.isEmpty()){
591
 
                                // failed...no pass specified
592
 
                                // if the fserve has no global pass , allow a normal login
593
 
                                if(g_szFServePass.isEmpty()){
594
 
                                        // the fserve doesn't need a global pass...ok
595
 
                                        fserve_startNormalSession(cmd,nick.ptr(),ip.ptr());
596
 
                                } else {
597
 
                                        // the fserve needs also a global pass...failed
598
 
                                        fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Use '.fserve <password>' to login"));
599
 
                                }
600
 
                        } else {
601
 
                                if(kvi_strEqualCI(pass.ptr(),u->passwd.ptr())){
602
 
                                        // matched his password...ok..leech account
603
 
                                        fserve_startSession(cmd,nick.ptr(),ip.ptr(),"unlimited");
604
 
                                } else if(kvi_strEqualCI(pass.ptr(),g_szFServePass.ptr())){
605
 
                                        // seems that he wants a normal session
606
 
                                        fserve_startNormalSession(cmd,nick.ptr(),ip.ptr());
607
 
                                } else {
608
 
                                        // failed at all...
609
 
                                        fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Access denied: invalid password"));
610
 
                                }       
611
 
                        }
612
 
                } else {
613
 
                        // no password needed: start the session
614
 
                        fserve_startSession(cmd,nick.ptr(),ip.ptr(),"unlimited");
615
 
                }
616
 
        } else {
617
 
                // user is not registered
618
 
                if(g_szFServePass.hasData()){
619
 
                        // a password is needed
620
 
                        if(pass.isEmpty()){
621
 
                                // failed...no pass specified
622
 
                                fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Use '.fserve <password>' to login"));
623
 
                                return;
624
 
                        } else {
625
 
                                if(!kvi_strEqualCI(pass.ptr(),g_szFServePass.ptr())){
626
 
                                        fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Access denied: invalid password"));
627
 
                                        return;
628
 
                                }       
629
 
                        }
630
 
                }       
631
 
                // no password needed or password ok
632
 
                fserve_startNormalSession(cmd,nick.ptr(),ip.ptr());
633
 
        }
634
 
}
635
 
 
636
 
static void fserve_parseCmdFServe(KviPluginCommandStruct *cmd)
637
 
{
638
 
        // first of all , build a mask
639
 
        // .fserve [<user> <host>] [password]
640
 
        KviStr nick = kvirc_plugin_param(cmd,1);
641
 
        KviStr user = kvirc_plugin_param(cmd,2);
642
 
        KviStr host = kvirc_plugin_param(cmd,3);
643
 
        KviStr ip   = kvirc_plugin_param(cmd,4);
644
 
        KviStr pass;
645
 
        g_szFServePass.stripWhiteSpace();
646
 
 
647
 
        if(g_pSessions->count() >= g_uMaxRunningSessions){
648
 
                fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Sorry , the server is full: try again later"));
649
 
                return;
650
 
        }
651
 
 
652
 
        if(fserve_isBannedIp(ip.ptr())){
653
 
                fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Sorry , you're banned from this file server"));
654
 
                return;
655
 
        }
656
 
 
657
 
        switch(cmd->params->count()){
658
 
                case 6:
659
 
                        // Ok... :)
660
 
                break;
661
 
                case 7:
662
 
                        pass = kvirc_plugin_param(cmd,6);
663
 
                break;
664
 
                case 8:
665
 
                        user = kvirc_plugin_param(cmd,6);
666
 
                        host = kvirc_plugin_param(cmd,7);
667
 
                break;
668
 
                case 9:
669
 
                        user = kvirc_plugin_param(cmd,6);
670
 
                        host = kvirc_plugin_param(cmd,7);
671
 
                        pass = kvirc_plugin_param(cmd,8);
672
 
                break;
673
 
                default:
674
 
                        fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Invalid number of parameters."));
675
 
                        fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Syntax: .fserve [<user> <host>] [password]"));
676
 
                        return; 
677
 
                break;
678
 
        }
679
 
 
680
 
        if(kvi_strEqualCS("*",host.ptr()) || kvi_strEqualCS("*",user.ptr())){
681
 
                // user & host unknown
682
 
                fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Sorry , your user@hostname is unknown."));
683
 
                fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Please login with '.fserve <user> <host> [password]'"));
684
 
                return;
685
 
        }
686
 
        fserve_doLogin(cmd,nick,user,host,ip,pass);
687
 
}
688
 
 
689
 
bool fserve_plugin_hook_onMePrivateMessage(KviPluginCommandStruct *cmd)
690
 
{
691
 
        if(!g_bServerActive || !g_bListenToPrivmsg)debug("WARNING : Unexpected hook on private message");
692
 
 
693
 
        if(kvi_strEqualCIN(kvirc_plugin_param(cmd,3),"!fserve",7)){
694
 
 
695
 
                if(g_pSessions->count() >= g_uMaxRunningSessions)return false; //server full
696
 
                if(g_szFServePass.hasData()){
697
 
                        KviStr mask(KviStr::Format,"%s!%s",kvirc_plugin_param(cmd,1),kvirc_plugin_param(cmd,2));
698
 
                        KviRegisteredUser * u = kvirc_plugin_find_registered_user_with_flag(mask.ptr(),'f');
699
 
                
700
 
                        if(cmd->params->count() == 4){
701
 
                                // must be registered with f flag and have no password set
702
 
                                if(!u)return false;
703
 
                                if(u->passwd.hasData())return false;
704
 
                        } else {
705
 
                                // specified a password
706
 
                                if(!kvi_strEqualCI(g_szFServePass.ptr(),kvirc_plugin_param(cmd,4))){
707
 
                                        // invalid fserve global pass
708
 
                                        if(!u)return false;
709
 
                                        if(u->passwd.isEmpty())return false;
710
 
                                        if(!kvi_strEqualCI(u->passwd.ptr(),kvirc_plugin_param(cmd,4)))return false;
711
 
                                }
712
 
                        }
713
 
                }
714
 
 
715
 
                cmd->window->output(KVI_OUT_INTERNAL,"[fserve] Received a valid file service request from %s!%s: %s %s",
716
 
                        kvirc_plugin_param(cmd,1),kvirc_plugin_param(cmd,2),kvirc_plugin_param(cmd,3),
717
 
                        (cmd->params->count() > 4 ? kvirc_plugin_param(cmd,4) : ""));
718
 
 
719
 
                KviPendingSession * s = new KviPendingSession;
720
 
                s->pWnd = cmd->frame->m_pDccManager->requestDccChat(kvirc_plugin_param(cmd,1),kvirc_plugin_param(cmd,2));
721
 
                if(cmd->params->count() > 4)s->password = kvirc_plugin_param(cmd,4);
722
 
 
723
 
                fserve_cleanupPendingSessions(cmd->frame);
724
 
                g_pPendingSessions->append(s);
725
 
                return true; // do not output , do not create the query if it is not there
726
 
        }
727
 
        return false;
728
 
}
729
 
 
730
 
bool fserve_plugin_hook_onDccChatConnected(KviPluginCommandStruct *cmd)
731
 
{
732
 
        if(!g_bServerActive)return false;
733
 
        KviPendingSession * s = fserve_findPendingSession(cmd->window);
734
 
        if(!s)return false;
735
 
        KviStr nick = kvirc_plugin_param(cmd,1);
736
 
        KviStr user = kvirc_plugin_param(cmd,2);
737
 
        KviStr host = kvirc_plugin_param(cmd,3);
738
 
        KviStr ip   = kvirc_plugin_param(cmd,4);
739
 
        KviStr pass = s->password;
740
 
        fserve_doLogin(cmd,nick,user,host,ip,pass);
741
 
        g_pPendingSessions->removeRef(s);
742
 
        fserve_cleanupPendingSessions(cmd->frame);
743
 
        return false; // do not block any output
744
 
}
745
 
 
746
 
bool fserve_plugin_hook_onDccChatMessage(KviPluginCommandStruct *cmd)
747
 
{
748
 
        if(!g_bServerActive)return false;
749
 
 
750
 
        KviStr * firstWord = cmd->params->at(5);
751
 
 
752
 
        if(!firstWord)return false; // not a fserve command at all
753
 
        if(*(firstWord->ptr()) != '.')return false; // same as above
754
 
 
755
 
 
756
 
        KviFServeSession * s = fserve_findRunningSession(cmd->window);
757
 
        if(s){
758
 
                // A running service
759
 
                KviStr out = firstWord->ptr();
760
 
                for(unsigned int i=6;i < cmd->params->count();i++){
761
 
                        out.append(' ');
762
 
                        out.append(kvirc_plugin_param(cmd,i));
763
 
                }
764
 
                cmd->window->output(KVI_OUT_NONE,"[%s >> fserve] %s",s->nick.ptr(),out.ptr());
765
 
 
766
 
                if(kvi_strEqualCI(firstWord->ptr(),".stats"))fserve_parseCmdStats(cmd,s);
767
 
                else if(kvi_strEqualCI(firstWord->ptr(),".ls") || kvi_strEqualCI(firstWord->ptr(),".dir"))fserve_parseCmdLs(cmd,s);
768
 
                else if(kvi_strEqualCI(firstWord->ptr(),".cd") && (cmd->params->count() > 6))fserve_parseCmdCd(cmd,s);
769
 
                else if(kvi_strEqualCI(firstWord->ptr(),".get") && (cmd->params->count() > 6))fserve_parseCmdGet(cmd,s);
770
 
                else if(kvi_strEqualCI(firstWord->ptr(),".help"))fserve_parseCmdHelp(cmd,s);
771
 
                else if(kvi_strEqualCI(firstWord->ptr(),".motd"))fserve_parseCmdMotd(cmd,s);
772
 
                else if(kvi_strEqualCI(firstWord->ptr(),".quit"))fserve_parseCmdQuit(cmd,s);
773
 
                else if(kvi_strEqualCI(firstWord->ptr(),".pwd"))fserve_parseCmdPwd(cmd,s);
774
 
                else fserve_parseCmdUnknown(cmd,s);
775
 
        } else {
776
 
                // Not a running service
777
 
                if(kvi_strEqualCI(firstWord->ptr(),".fserve")){
778
 
                        // A login attempt
779
 
                        KviStr out = firstWord->ptr();
780
 
                        for(unsigned int i=6;i < cmd->params->count();i++){
781
 
                                out.append(' ');
782
 
                                out.append(cmd->params->at(i)->ptr());
783
 
                        }
784
 
                        cmd->window->output(KVI_OUT_NONE,"[%s >> fserve] %s",kvirc_plugin_param(cmd,1),out.ptr());
785
 
                        fserve_parseCmdFServe(cmd);
786
 
                } else return false;
787
 
        }
788
 
 
789
 
        return true;
790
 
}
791
 
 
792
 
bool fserve_plugin_hook_onDccChatTerminated(KviPluginCommandStruct *cmd)
793
 
{
794
 
        KviFServeSession * s = fserve_findRunningSession(cmd->window);
795
 
        if(s)fserve_closeSession(s);
796
 
        fserve_cleanupPendingSessions(cmd->frame); //not needed...but do it...just in case
797
 
        return false; // do not block any output
798
 
}
799
 
 
800
 
bool fserve_plugin_hook_onDccGetTransferComplete(KviPluginCommandStruct *cmd)
801
 
{
802
 
        bool bOk = false;
803
 
        unsigned int crAdd = cmd->params->at(6)->toUInt(&bOk);
804
 
        if(!bOk){
805
 
                debug("oops...can't calculate the credit to give to %s , giving (100.000 bytes * ratio)",cmd->params->at(1)->ptr());
806
 
                crAdd = 100000;
807
 
        }
808
 
 
809
 
        KviFServeSession * s = fserve_findRunningSessionByNickAndIp(kvirc_plugin_param(cmd,1),kvirc_plugin_param(cmd,4));
810
 
        if(s){
811
 
                if(s->credit.isUnsignedNum()){
812
 
                        unsigned int crOld = s->credit.toUInt();
813
 
                        crOld += ((crAdd / g_iRatioTake) * g_iRatioGive);
814
 
                        s->credit.setNum(crOld);
815
 
                        KviStr fName = kvirc_plugin_param(cmd,5);
816
 
                        int idx = fName.findLastIdx('/');
817
 
                        if(idx >= 0)fName.cutLeft(idx + 1);
818
 
                        KviStr tmp(KviStr::Format,"I have received succesfully the file '%s' , %s bytes long",cmd->params->at(5)->ptr(),cmd->params->at(6)->ptr());
819
 
                        s->pWnd->output(KVI_OUT_OWN,"[fserve >> %s] %s",s->nick.ptr(),tmp.ptr());
820
 
                        tmp.prepend("[fserve] ");
821
 
                        ((KviDccChat *)(s->pWnd))->sendData(tmp.ptr());
822
 
                        tmp.sprintf("Your credit is now %s bytes",s->credit.ptr());
823
 
                        s->pWnd->output(KVI_OUT_OWN,"[fserve >> %s] %s",s->nick.ptr(),tmp.ptr());
824
 
                        tmp.prepend("[fserve] ");
825
 
                        ((KviDccChat *)(s->pWnd))->sendData(tmp.ptr());
826
 
                }
827
 
        } else {
828
 
                KviSavedSession * ss = fserve_findSavedSession(kvirc_plugin_param(cmd,1),kvirc_plugin_param(cmd,4));
829
 
                if(ss){
830
 
                        unsigned int crOld = ss->credit.toUInt(&bOk);
831
 
                        if(!bOk)crOld = 0;
832
 
                        crOld += ((crAdd / g_iRatioTake) * g_iRatioGive);
833
 
                        ss->credit.setNum(crOld);
834
 
                }
835
 
                // We could also ack the dcc send completion to that user...
836
 
        }
837
 
        return false;
838
 
}
839
 
 
840
 
void fserve_plugin_config()
841
 
{
842
 
        if(!g_pConfigDialog){
843
 
                g_pConfigDialog = new KviFServeConfigDialog();
844
 
                g_pConfigDialog->show();
845
 
        }
846
 
}
847
 
 
848
 
bool fserve_plugin_command_fserve(KviPluginCommandStruct *cmd)
849
 
{
850
 
        if(!g_bServerActive){
851
 
                cmd->window->output(KVI_OUT_INTERNAL,__tr("[fserve] The file server is not active"));
852
 
                return true;
853
 
        }
854
 
        if(cmd->params->count() < 2){
855
 
                cmd->error = KVI_ERROR_MissingParameter;
856
 
                return false;
857
 
        }
858
 
        if(kvi_strEqualCI(kvirc_plugin_param(cmd,1),"list")){
859
 
                int total = 0;
860
 
                for(KviFServeSession * s = g_pSessions->first();s;s=g_pSessions->next()){
861
 
                        cmd->window->output(KVI_OUT_INTERNAL,__tr("%cSession: %s@%s"),KVI_TEXT_BOLD,s->nick.ptr(),s->address.ptr());
862
 
                        cmd->window->output(KVI_OUT_INTERNAL,__tr("Current credit: %s"),s->credit.ptr());
863
 
                        cmd->window->output(KVI_OUT_INTERNAL,__tr("Current directory: %s"),s->currentDir.ptr());
864
 
                        total++;
865
 
                }
866
 
                cmd->window->output(KVI_OUT_INTERNAL,__tr("[fserve] Total : %d running sessions"),total);
867
 
        } else if(kvi_strEqualCI(kvirc_plugin_param(cmd,1),"boot")){
868
 
                if(cmd->params->count() < 3){
869
 
                        cmd->error = KVI_ERROR_MissingParameter;
870
 
                        cmd->errorstr = __tr("The 'boot' operation requires a target (<nick>@<address>)");
871
 
                        return false;
872
 
                }
873
 
                KviStr address = kvirc_plugin_param(cmd,2);
874
 
                KviStr nick = address.getToken('@');
875
 
                KviFServeSession * s = fserve_findRunningSessionByNickAndIp(nick.ptr(),address.ptr());
876
 
                if(!s){
877
 
                        cmd->error = KVI_ERROR_InvalidParameter;
878
 
                        cmd->errorstr = __tr("Session not found");
879
 
                        return false;
880
 
                }
881
 
                s->pWnd->output(KVI_OUT_OWN,"[fserve >> %s] Your session has been closed by the system administrator.",s->nick.ptr());
882
 
                ((KviDccChat *)(s->pWnd))->sendData("[fserve] Your session has been closed by the system administrator.");
883
 
                fserve_closeSession(s);
884
 
                cmd->window->output(KVI_OUT_INTERNAL,__tr("[fserve] Session closed (%s@%s)"),nick.ptr(),address.ptr());
885
 
        } else if(kvi_strEqualCI(kvirc_plugin_param(cmd,1),"credit")){
886
 
                if(cmd->params->count() < 4){
887
 
                        cmd->error = KVI_ERROR_MissingParameter;
888
 
                        cmd->errorstr = __tr("The 'credit' operation requires a target (<nick>@<address>) and a credit value");
889
 
                        return false;
890
 
                }
891
 
                KviStr address = kvirc_plugin_param(cmd,2);
892
 
                KviStr nick = address.getToken('@');
893
 
                KviFServeSession * s = fserve_findRunningSessionByNickAndIp(nick.ptr(),address.ptr());
894
 
                if(!s){
895
 
                        cmd->error = KVI_ERROR_InvalidParameter;
896
 
                        cmd->errorstr = __tr("Session not found");
897
 
                        return false;
898
 
                }
899
 
                KviStr credit = kvirc_plugin_param(cmd,3);
900
 
                if(!credit.isUnsignedNum()){
901
 
                        if(!kvi_strEqualCI(credit.ptr(),"unlimited")){
902
 
                                cmd->error = KVI_ERROR_InvalidParameter;
903
 
                                cmd->errorstr = __tr("The credit must be an unsigned integer or the word 'unlimited'");
904
 
                                return false;
905
 
                        }
906
 
                }
907
 
                s->credit = credit;
908
 
                KviStr tmp(KviStr::Format,"Your credit was reset by the system administrator to %s bytes",credit.ptr());
909
 
                s->pWnd->output(KVI_OUT_OWN,"[fserve >> %s] %s",s->nick.ptr(),tmp.ptr());
910
 
                tmp.prepend("[fserve] ");
911
 
                ((KviDccChat *)(s->pWnd))->sendData(tmp.ptr());
912
 
                cmd->window->output(KVI_OUT_INTERNAL,__tr("[fserve] Credit for session %s@%s succesfully set to %s"),nick.ptr(),address.ptr(),credit.ptr());
913
 
        } else if(kvi_strEqualCI(kvirc_plugin_param(cmd,1),"config")){
914
 
                fserve_plugin_config();
915
 
                return true;
916
 
        } else {
917
 
                cmd->error = KVI_ERROR_InvalidOperation;
918
 
                cmd->errorstr = __tr("Available operations are : 'list' , 'boot' and 'credit'");
919
 
                return false;
920
 
        }
921
 
        return true;
922
 
}
923
 
 
924
 
// init routine
925
 
bool fserve_plugin_init(KviPluginCommandStruct * cmd)
926
 
{
927
 
        // Initialize globals
928
 
        g_pSessions = new QList<KviFServeSession>;
929
 
        g_pSessions->setAutoDelete(true);
930
 
        g_pBannedIpList = new QList<KviStr>;
931
 
        g_pBannedIpList->setAutoDelete(true);
932
 
        g_pSavedSessions = new QList<KviSavedSession>;
933
 
        g_pSavedSessions->setAutoDelete(true);
934
 
        g_pPendingSessions = new QList<KviPendingSession>;
935
 
        g_pPendingSessions->setAutoDelete(true);
936
 
        g_handle = cmd->handle;
937
 
        // Load configuration
938
 
        fserve_pluginLoadState();
939
 
 
940
 
        kvirc_plugin_register_command(cmd->handle,"FSERVE",fserve_plugin_command_fserve);
941
 
 
942
 
        if(g_bServerActive){
943
 
                kvirc_plugin_add_hook(g_handle,KviEvent_OnDccChatConnected,fserve_plugin_hook_onDccChatConnected);
944
 
                kvirc_plugin_add_hook(g_handle,KviEvent_OnDccChatTerminated,fserve_plugin_hook_onDccChatTerminated);
945
 
                kvirc_plugin_add_hook(g_handle,KviEvent_OnDccChatMessage,fserve_plugin_hook_onDccChatMessage);
946
 
                kvirc_plugin_add_hook(g_handle,KviEvent_OnDccGetTransferComplete,fserve_plugin_hook_onDccGetTransferComplete);
947
 
                if(g_bListenToPrivmsg){
948
 
                        kvirc_plugin_add_hook(g_handle,KviEvent_OnMePrivateMessage,fserve_plugin_hook_onMePrivateMessage);
949
 
                }
950
 
        }
951
 
 
952
 
        return true;
953
 
}
954
 
 
955
 
void fserve_plugin_cleanup()
956
 
{
957
 
        fserve_pluginSaveState();
958
 
 
959
 
        if(g_pConfigDialog)delete g_pConfigDialog; //we're unloaded!
960
 
        delete g_pSessions;
961
 
        delete g_pBannedIpList;
962
 
        delete g_pSavedSessions;
963
 
        delete g_pPendingSessions;
964
 
 
965
 
        kvirc_plugin_unregister_meta_object("KviFServeConfigDialog");
966
 
}
967
 
 
968
 
void fserve_configFinished(bool bCommit)
969
 
{
970
 
        if(bCommit){
971
 
                // Ensure that the pass is correctly assigned
972
 
                g_szFServePass.stripWhiteSpace();
973
 
                // check the root directory , and if some check fails , disable the server
974
 
                g_bServerActive = fserve_checkRoot() && g_bServerActive;
975
 
 
976
 
                g_szInitialCredit.stripWhiteSpace();
977
 
                if(!g_szInitialCredit.isUnsignedNum()){
978
 
                        if(!kvi_strEqualCI(g_szInitialCredit.ptr(),"unlimited")){
979
 
                                debug("Initial credit has a syntax error inside...setting to 0");
980
 
                                g_szInitialCredit = "0";
981
 
                        }
982
 
                }
983
 
 
984
 
                if(!g_bServerActive){
985
 
                        // The server has been disactivated...kill all the sessions
986
 
                        for(KviFServeSession *s=g_pSessions->first();s;s=g_pSessions->next()){
987
 
                                s->pWnd->output(KVI_OUT_OWN,"[fserve >> %s] The file service has been disactivated: closing your session.",s->nick.ptr());
988
 
                                ((KviDccChat *)(s->pWnd))->sendData("[fserve] The file service has been disactivated: closing your session.");
989
 
                        }
990
 
                        while(g_pSessions->first())fserve_closeSession(g_pSessions->first());
991
 
                        while(g_pPendingSessions->first())g_pPendingSessions->removeFirst();
992
 
                        // remove the hooks (avoid unnecessary lag to KVIrc)
993
 
                        kvirc_plugin_remove_all_hooks(g_handle);
994
 
                } else {
995
 
                        // The root may be changed...warp all sessions to '/'
996
 
                        for(KviFServeSession *s=g_pSessions->first();s;s=g_pSessions->next()){
997
 
                                s->pWnd->output(KVI_OUT_OWN,"[fserve >> %s] The file service has been reconfigured: warping you to '/'.",s->nick.ptr());
998
 
                                ((KviDccChat *)(s->pWnd))->sendData("[fserve] The file service has been reconfigured: warping you to '/'.");
999
 
                                s->currentDir = "/";
1000
 
                        }
1001
 
                        // If the server was previously disabled , reinstall the hooks
1002
 
                        if(!kvirc_plugin_is_hook_registered(g_handle,KviEvent_OnDccChatConnected)){
1003
 
                                // no previous hooks (the server was disabled)
1004
 
                                kvirc_plugin_add_hook(g_handle,KviEvent_OnDccChatConnected,fserve_plugin_hook_onDccChatConnected);
1005
 
                                kvirc_plugin_add_hook(g_handle,KviEvent_OnDccChatTerminated,fserve_plugin_hook_onDccChatTerminated);
1006
 
                                kvirc_plugin_add_hook(g_handle,KviEvent_OnDccChatMessage,fserve_plugin_hook_onDccChatMessage);
1007
 
                                kvirc_plugin_add_hook(g_handle,KviEvent_OnDccGetTransferComplete,fserve_plugin_hook_onDccGetTransferComplete);
1008
 
                                if(g_bListenToPrivmsg){
1009
 
                                        kvirc_plugin_add_hook(g_handle,KviEvent_OnMePrivateMessage,fserve_plugin_hook_onMePrivateMessage);
1010
 
                                }
1011
 
                        } else {
1012
 
                                // the main hooks are already installed
1013
 
                                if(g_bListenToPrivmsg){
1014
 
                                        // Check if we have to install the hook or it is already done
1015
 
                                        if(!kvirc_plugin_is_hook_registered(g_handle,KviEvent_OnMePrivateMessage)){
1016
 
                                                // This hook was not previously registered
1017
 
                                                kvirc_plugin_add_hook(g_handle,KviEvent_OnMePrivateMessage,fserve_plugin_hook_onMePrivateMessage);
1018
 
                                        }
1019
 
                                } else {
1020
 
                                        // Check if we have to remove the hook
1021
 
                                        if(kvirc_plugin_is_hook_registered(g_handle,KviEvent_OnMePrivateMessage)){
1022
 
                                                // This hook was not previously registered
1023
 
                                                kvirc_plugin_remove_hook(g_handle,KviEvent_OnMePrivateMessage);
1024
 
                                        }
1025
 
                                }
1026
 
                        }
1027
 
                }
1028
 
        }
1029
 
        delete g_pConfigDialog;
1030
 
        g_pConfigDialog = 0;
1031
 
}
1032
 
 
1033
 
/*
1034
 
        @document: doc_plugin_fserve.kvihelp
1035
 
        @title: The KVIrc FServe plugin
1036
 
                The KVIrc FServe plugin is a simple implementation of a file transfer
1037
 
                service over a DCC connnection.<br>
1038
 
                <docsubtitle>Directory tree</docsubtitle>
1039
 
                The file server works in its own directory tree , which root
1040
 
                directory path can be specified in the settings dialog.<br>
1041
 
                Any user that access the server will see the root directory as '/'
1042
 
                and will be able to discend the entire underlying tree by using the '.cd' command.<br>
1043
 
                He will be also able to list the directory contents with the '.ls' command.<br>
1044
 
                Obviously all this assuming that the user that is running the fserve
1045
 
                has access to that directory tree.<br>
1046
 
                <docsubtitle>Access</docsubtitle>
1047
 
                There are two kind of accesses:<br>
1048
 
                <b>- Public access</b><br>
1049
 
                It is optionally protected by a global fserve password.<br>
1050
 
                Any remote user can access the file service by typing '.fserve [password]'
1051
 
                in a running DCC CHAT connection.<br>
1052
 
                If no global password has been set , the service will be accessible by simply
1053
 
                typing '.fserve'.<br>
1054
 
                The user will obtain the global initial credit (specified in the settings dialog)
1055
 
                that can be optionally 'unlimited'.<br>
1056
 
                The user will be able to download files from the fserve directory tree
1057
 
                by typing '.get &lt;filename&gt;' , where &lt;filename&gt; is a file contained in
1058
 
                its current working directory (i.e. the file name can NOT contain a path prefix).<br>
1059
 
                The download will be allowed only if the user's credit is greater or equal
1060
 
                than the requested file size.<br>
1061
 
                At the transfer start moment , the size of the file (in bytes) will be subtracted
1062
 
                from the user's credit (unless the credit is 'unlimited').<br>
1063
 
                Users can also upload files by simply sending it by DCC.<br>
1064
 
                At the end of the upload , the transfered file size multiplied for the fserve ratio
1065
 
                (configurable in the settings dialog) will be added to the user's credit;<br>
1066
 
                either if the user is still using the fserver or not.<br>
1067
 
                The last 32 'Limited credit' sessions will be saved in memory
1068
 
                until the file service is stopped (i.e. the plugin is unloaded, the file service
1069
 
                disactivated or kvirc application is terminated).<br>
1070
 
                <b>- Registered access</b><br>
1071
 
                Users registered in the "KVIrc users database" with the 'f' flag can access
1072
 
                the file service and obtain 'unlimited' credit access by typing '.fserve [user_password]'.<br>
1073
 
                If the user has no password set , he will be able to access the file server by simply
1074
 
                typing '.fserve'.<br>
1075
 
                <docsubtitle>Restricting access</docsubtitle>
1076
 
                - The file server supports 'bans' on ip addresses.<br>
1077
 
                You can add a list of ip address masks (like 127.0.*.*) that will be rejected
1078
 
                - There is a configurable limit on the number of running sessions.<br>
1079
 
                When the server is 'full' any login will be rejected.<br>
1080
 
                <docsubtitle>Other features</docsubtitle>
1081
 
                - Optionally the file server can react to requests through private messages.<br>
1082
 
                In that case any previously described access can be obtained by typing
1083
 
                '/msg &lt;your_nickname&gt; !fserve [password]'.<br>
1084
 
                The fserve will open a DCC CHAT connection and enter the file server mode automatically.<br>
1085
 
                To enable this feature you must check the appropriate option in the plugin configuration dialog.<br>
1086
 
                - A configurable 'message of the day' can be displayed to the user at login time
1087
 
                and can be later accessed by using the '.motd' command.<br>
1088
 
                - The user is able to list available commands by using the '.help' command.<br>
1089
 
                <docsubtitle>Local commands</docsubtitle>
1090
 
                <br><b>/fserve list</b><br><br>
1091
 
                Lists active user sessions.<br>
1092
 
                <br><b>/fserve boot &lt;nickname@ipaddress&gt;</b><br><br>
1093
 
                Terminates a running file service.<br>
1094
 
                A similar result can be achieved by simply closing the DCC chat connection.<br>
1095
 
                NOTE : /fserve boot will NOT close the DCC connection , it will just close the fserve session.<br>
1096
 
                <br><b>/fserve credit &lt;nickname@ipaddress&gt; &lt;creditvalue&gt;</b><br><br>
1097
 
                Sets the credit of a specified session to &lt;creditvalue&gt; that can be a positive
1098
 
                numeric value or the string 'unlimited'.<br>
1099
 
                <br><b>/fserve config</b><br>
1100
 
                Opens the plugin configuration dialog.<br>
1101
 
*/
1102
 
 
1103
 
void fserve_plugin_help()
1104
 
{
1105
 
        kvirc_plugin_show_help_page("doc_plugin_fserve.kvihelp");
1106
 
}
1107
 
 
1108
 
// plugin definition structure
1109
 
// MUST be named 'kvirc_plugin'
1110
 
KviPlugin kvirc_plugin =
1111
 
{
1112
 
        "fserve" ,                                    // plugin name
1113
 
        "KVIrc DCC file server" ,                     // description
1114
 
        "1.0" ,                                       // version
1115
 
        "Szymon Stefanek <stefanek@tin.it>" ,         // author info
1116
 
        "Allows remote users to browse a local " \
1117
 
        "file archive in an ftp-like manner.\n" \
1118
 
        "The users can download files and a " \
1119
 
        "downloaded/uploaded bytes ratio can be set." ,
1120
 
        fserve_plugin_init ,                          // init routine
1121
 
        fserve_plugin_cleanup ,                       // cleanup routine
1122
 
        fserve_plugin_config ,                        // configuration routine
1123
 
        fserve_plugin_help
1124
 
};
1125
 
 
1126
 
 
1127
 
// =======================================
1128
 
// Config dialog
1129
 
// =======================================
1130
 
 
1131
 
#include <qlayout.h>
1132
 
#include <qframe.h>
1133
 
 
1134
 
#include "kvi_selectors.h"
1135
 
 
1136
 
KviFServeConfigDialog::KviFServeConfigDialog()
1137
 
:QTabDialog()
1138
 
{
1139
 
        setCaption(__tr("File server configuration"));
1140
 
 
1141
 
        QWidget *tab = new QWidget(this);
1142
 
        QGridLayout *g = new QGridLayout(tab,5,1,10,4);
1143
 
 
1144
 
        KviNewBoolSelector *b=new KviNewBoolSelector(tab,__tr("Activate file server"),&(g_bServerActive),true);
1145
 
        g->addWidget(b,0,0);
1146
 
 
1147
 
        QFrame *r = new QFrame(tab);
1148
 
        r->setFrameStyle(QFrame::Sunken | QFrame::HLine);
1149
 
        g->addWidget(r,1,0);
1150
 
 
1151
 
        QLabel *l = new QLabel(
1152
 
                __tr("A misconfigured file server may allow remote users to download " \
1153
 
                "unwanted files from your filesystem.\n" \
1154
 
                "Please check the settings twice before enabling the service.\n" \
1155
 
                "It is also not reccomended to leave the service " \
1156
 
                "running \"alone\" while you are away.\nHave fun! :)"),tab);
1157
 
        l->setAlignment(AlignCenter|WordBreak);
1158
 
        l->setEnabled(false);
1159
 
        g->addWidget(l,2,0);
1160
 
 
1161
 
        r = new QFrame(tab);
1162
 
        r->setFrameStyle(QFrame::Sunken | QFrame::HLine);
1163
 
        g->addWidget(r,3,0);
1164
 
 
1165
 
        KviNewStringSelector *s=new KviNewStringSelector(tab,__tr("File server root "),&(g_szFServeRoot),g_bServerActive);
1166
 
        connect(b,SIGNAL(toggled(bool)),s,SLOT(setEnabled(bool)));
1167
 
        g->addWidget(s,4,0);
1168
 
 
1169
 
        g->setRowStretch(2,2);
1170
 
 
1171
 
        addTab(tab,__tr("Main"));
1172
 
 
1173
 
        tab = new QWidget(this);
1174
 
        g = new QGridLayout(tab,7,1,10,4);
1175
 
 
1176
 
        s=new KviNewStringSelector(tab,__tr("Password"),&(g_szFServePass),g_bServerActive);
1177
 
        connect(b,SIGNAL(toggled(bool)),s,SLOT(setEnabled(bool)));
1178
 
        g->addMultiCellWidget(s,0,0,0,4);
1179
 
 
1180
 
        s=new KviNewStringSelector(tab,__tr("Initial credit"),&(g_szInitialCredit),g_bServerActive);
1181
 
        connect(b,SIGNAL(toggled(bool)),s,SLOT(setEnabled(bool)));
1182
 
        g->addMultiCellWidget(s,1,1,0,4);
1183
 
 
1184
 
        r = new QFrame(tab);
1185
 
        r->setFrameStyle(QFrame::Sunken | QFrame::HLine);
1186
 
        g->addMultiCellWidget(r,2,2,0,4);
1187
 
 
1188
 
        l = new QLabel(__tr("Give "),tab);
1189
 
        l->setEnabled(g_bServerActive);
1190
 
        connect(b,SIGNAL(toggled(bool)),l,SLOT(setEnabled(bool)));
1191
 
        g->addWidget(l,3,0);
1192
 
 
1193
 
        m_pRatioGiveEdit = new QLineEdit(tab);
1194
 
        m_pRatioGiveEdit->setEnabled(g_bServerActive);
1195
 
        KviStr tmp;
1196
 
        tmp.setNum(g_iRatioGive);
1197
 
        m_pRatioGiveEdit->setText(tmp.ptr());
1198
 
        connect(b,SIGNAL(toggled(bool)),m_pRatioGiveEdit,SLOT(setEnabled(bool)));
1199
 
        g->addWidget(m_pRatioGiveEdit,3,1);
1200
 
 
1201
 
        l = new QLabel(__tr(" byte(s) for each block of "),tab);
1202
 
        l->setEnabled(g_bServerActive);
1203
 
        connect(b,SIGNAL(toggled(bool)),l,SLOT(setEnabled(bool)));
1204
 
        l->setMinimumSize(l->sizeHint());
1205
 
        g->addWidget(l,3,2);
1206
 
 
1207
 
        m_pRatioTakeEdit = new QLineEdit(tab);
1208
 
        m_pRatioTakeEdit->setEnabled(g_bServerActive);
1209
 
        tmp.setNum(g_iRatioTake);
1210
 
        m_pRatioTakeEdit->setText(tmp.ptr());
1211
 
        connect(b,SIGNAL(toggled(bool)),m_pRatioTakeEdit,SLOT(setEnabled(bool)));
1212
 
        g->addWidget(m_pRatioTakeEdit,3,3);
1213
 
 
1214
 
        l = new QLabel(__tr(" byte(s) received"),tab);
1215
 
        l->setEnabled(g_bServerActive);
1216
 
        connect(b,SIGNAL(toggled(bool)),l,SLOT(setEnabled(bool)));
1217
 
        l->setMinimumSize(l->sizeHint());
1218
 
        g->addWidget(l,3,4);
1219
 
 
1220
 
        r = new QFrame(tab);
1221
 
        r->setFrameStyle(QFrame::Sunken | QFrame::HLine);
1222
 
        r->setMinimumHeight(r->frameWidth() * 2);
1223
 
        g->addMultiCellWidget(r,4,4,0,4);
1224
 
 
1225
 
        KviNewBoolSelector * b1=new KviNewBoolSelector(tab,__tr("Listen to PRIVMGS <mynick> !fserve [password]"),&(g_bListenToPrivmsg),g_bServerActive);
1226
 
        connect(b,SIGNAL(toggled(bool)),b1,SLOT(setEnabled(bool)));
1227
 
        g->addMultiCellWidget(b1,5,5,0,4);
1228
 
 
1229
 
        KviNewIntegerSelector * i1 = new KviNewIntegerSelector(tab,__tr("Max running sessions "),&(g_uMaxRunningSessions),KviNewIntegerSelector::UInt,
1230
 
                0,65535,1,g_bServerActive);
1231
 
        connect(b,SIGNAL(toggled(bool)),i1,SLOT(setEnabled(bool)));
1232
 
        g->addMultiCellWidget(i1,6,6,0,4);
1233
 
 
1234
 
        addTab(tab,__tr("Public access"));
1235
 
 
1236
 
        tab = new QWidget(this);
1237
 
        g = new QGridLayout(tab,2,1,10,4);
1238
 
 
1239
 
        b1=new KviNewBoolSelector(tab,__tr("Show motd after login"),&(g_bShowMotdAtLogin),g_bServerActive);
1240
 
        connect(b,SIGNAL(toggled(bool)),b1,SLOT(setEnabled(bool)));
1241
 
        g->addWidget(b1,0,0);
1242
 
 
1243
 
        m_pMotdEdit = new QMultiLineEdit(tab);
1244
 
        m_pMotdEdit->setEnabled(g_bServerActive);
1245
 
        m_pMotdEdit->setText(g_szMotd.ptr());
1246
 
        connect(b,SIGNAL(toggled(bool)),m_pMotdEdit,SLOT(setEnabled(bool)));
1247
 
        g->addWidget(m_pMotdEdit,1,0);
1248
 
        g->setRowStretch(1,2);
1249
 
 
1250
 
        addTab(tab,__tr("Motd"));
1251
 
 
1252
 
        tab = new QWidget(this);
1253
 
        g = new QGridLayout(tab,1,3,10,4);
1254
 
 
1255
 
        m_pBannedIpEdit = new QLineEdit(tab);
1256
 
        m_pBannedIpEdit->setEnabled(g_bServerActive);
1257
 
        connect(b,SIGNAL(toggled(bool)),m_pBannedIpEdit,SLOT(setEnabled(bool)));
1258
 
        g->addWidget(m_pBannedIpEdit,0,0);
1259
 
 
1260
 
        QPushButton * btn = new QPushButton(__tr("<-- Add"),tab);
1261
 
        btn->setEnabled(g_bServerActive);
1262
 
        connect(b,SIGNAL(toggled(bool)),btn,SLOT(setEnabled(bool)));
1263
 
        connect(btn,SIGNAL(clicked()),this,SLOT(addBannedIp()));
1264
 
        g->addWidget(btn,0,1);
1265
 
 
1266
 
        btn = new QPushButton(__tr("Remove selected"),tab);
1267
 
        btn->setEnabled(g_bServerActive);
1268
 
        connect(b,SIGNAL(toggled(bool)),btn,SLOT(setEnabled(bool)));
1269
 
        connect(btn,SIGNAL(clicked()),this,SLOT(removeBannedIp()));
1270
 
        g->addWidget(btn,0,2);
1271
 
 
1272
 
        m_pBannedIpList = new QListBox(tab);
1273
 
        m_pBannedIpList->setEnabled(g_bServerActive);
1274
 
        connect(b,SIGNAL(toggled(bool)),m_pBannedIpList,SLOT(setEnabled(bool)));
1275
 
        g->addMultiCellWidget(m_pBannedIpList,1,1,0,2);
1276
 
 
1277
 
        for(KviStr * s=g_pBannedIpList->first();s;s=g_pBannedIpList->next()){
1278
 
                m_pBannedIpList->insertItem(s->ptr());
1279
 
        }
1280
 
 
1281
 
        g->setRowStretch(1,2);
1282
 
 
1283
 
        addTab(tab,__tr("Banned IP addresses"));
1284
 
 
1285
 
        setCancelButton(__tr("Cancel"));
1286
 
 
1287
 
}
1288
 
 
1289
 
KviFServeConfigDialog::~KviFServeConfigDialog()
1290
 
{
1291
 
}
1292
 
 
1293
 
void KviFServeConfigDialog::done(int r)
1294
 
{
1295
 
        QTabDialog::done(r);
1296
 
        if(r == Accepted){
1297
 
                KviNewBoolSelector::commitAll(this);
1298
 
                KviNewStringSelector::commitAll(this);
1299
 
                KviNewIntegerSelector::commitAll(this);
1300
 
                KviStr tmp = m_pRatioTakeEdit->text();
1301
 
                tmp.stripWhiteSpace();
1302
 
                bool bOk = false;
1303
 
                g_iRatioTake = tmp.toInt(&bOk);
1304
 
                if((!bOk) || (g_iRatioTake < 1))g_iRatioTake = 1;
1305
 
                tmp = m_pRatioGiveEdit->text();
1306
 
                tmp.stripWhiteSpace();
1307
 
                bOk = false;
1308
 
                g_iRatioGive = tmp.toInt(&bOk);
1309
 
                if((!bOk) || (g_iRatioGive < 0))g_iRatioGive = 1;
1310
 
                g_szMotd = m_pMotdEdit->text();
1311
 
 
1312
 
                while(g_pBannedIpList->first())g_pBannedIpList->removeFirst();
1313
 
                unsigned int count = m_pBannedIpList->count();
1314
 
                for(unsigned int i=0;i<count;i++){
1315
 
                        tmp = m_pBannedIpList->text(i);
1316
 
                        tmp.stripWhiteSpace();
1317
 
                        if(tmp.hasData())g_pBannedIpList->append(new KviStr(tmp.ptr()));
1318
 
                }
1319
 
        }
1320
 
        fserve_configFinished((r == Accepted));
1321
 
}
1322
 
 
1323
 
void KviFServeConfigDialog::closeEvent(QCloseEvent *)
1324
 
{
1325
 
        // Finished without committing
1326
 
        fserve_configFinished(false);
1327
 
}
1328
 
 
1329
 
void KviFServeConfigDialog::addBannedIp()
1330
 
{
1331
 
        KviStr tmp = m_pBannedIpEdit->text();
1332
 
        tmp.stripWhiteSpace();
1333
 
        if(tmp.hasData())m_pBannedIpList->insertItem(tmp.ptr());
1334
 
}
1335
 
 
1336
 
void KviFServeConfigDialog::removeBannedIp()
1337
 
{
1338
 
        int idx = m_pBannedIpList->currentItem();
1339
 
        if(idx != -1)m_pBannedIpList->removeItem(idx);
1340
 
}
1341
 
 
1342
 
#include "m_libkvifserve.moc"