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
5
// This file is part of the KVirc irc client distribution
6
// Copyright (C) 1999-2000 Szymon Stefanek (stefanek@tin.it)
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.
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.
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.
22
#define __KVIRC_PLUGIN__
23
#include "kvirc_plugin.h"
25
#include "libkvifserve.h"
27
#include "kvi_dcc_chat.h"
28
#include "kvi_dcc_manager.h"
30
#include "kvi_locale.h"
33
#include <qfileinfo.h>
34
#include <qpushbutton.h>
36
// Maximum number of saved user sessions
37
#define KVIFSERVE_MAX_SAVED_SESSIONS 32
38
#define KVIFSERVE_MAX_PENDING_SESSIONS 32
40
// A running fserve session structure
41
typedef struct _KviFServeSession
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
50
// A pending dcc fservice
51
typedef struct _KviPendingSession
53
KviWindow * pWnd; // an opened dcc chat window waiting for the connection
54
KviStr password; // a password (if it has been specified in PRIVMSG)
57
// A saved fserve session
58
// Used to save the credit
59
typedef struct _KviSavedSession
61
KviStr nick; // nickname
62
KviStr address; // ip address
63
KviStr credit; // last credit (never "unlimited")
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
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
85
void * g_handle = 0; // global plugin handle (set by the init routine)
87
static bool fserve_checkRoot()
90
// Check the existence and validity of the fserver root directory
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);
98
// The root must be an absolute path!
99
if(*(g_szFServeRoot.ptr()) != '/'){
100
debug("FSERVE: File server root path is relative");
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");
114
static void fserve_pluginSaveState()
117
kvirc_plugin_get_config_file_path(fName,"fserve");
119
KviConfig cfg(fName.ptr());
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);
135
for(KviStr * s = g_pBannedIpList->first();s;s=g_pBannedIpList->next()){
136
if(tmp.hasData())tmp.append(',');
137
tmp.append(s->ptr());
139
cfg.writeEntry("BannedIpList",tmp.ptr());
145
static void fserve_pluginLoadState()
148
// Load the options of the plugin
149
// called from the init_routine
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
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","");
183
while(tmp.hasData()){
184
tmp.getToken(ip,',');
185
ip.stripWhiteSpace();
187
// TODO : check if it is a valid IP address mask ??
188
g_pBannedIpList->append(new KviStr(ip.ptr()));
191
// Check the server root directory
192
g_bServerActive = (fserve_checkRoot() && g_bServerActive);
195
static KviFServeSession * fserve_findRunningSession(KviWindow * wnd)
198
// Find a running fserve session
201
for(KviFServeSession *s=g_pSessions->first();s;s=g_pSessions->next()){
202
if(wnd == s->pWnd)return s;
207
static KviFServeSession * fserve_findRunningSessionByNickAndIp(const char *nick,const char *ip)
210
// Find a running fserve session
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;
221
static KviPendingSession * fserve_findPendingSession(KviWindow * wnd)
224
// Find a pending fserve session
227
for(KviPendingSession *s=g_pPendingSessions->first();s;s=g_pPendingSessions->next()){
228
if(wnd == s->pWnd)return s;
233
static KviSavedSession * fserve_findSavedSession(const char *nick,const char *ip)
236
// Find a saved fserve session
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;
247
static void fserve_cleanupPendingSessions(KviFrame * frm)
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);
254
for(KviPendingSession *ps=l.first();ps;ps=l.next())g_pPendingSessions->removeRef(ps);
257
static void fserve_chatOutputAndSend(KviPluginCommandStruct *cmd,const char *nick,const KviStr& data)
259
cmd->window->output(KVI_OUT_OWN,"[fserve >> %s] %s",nick,data.ptr());
260
KviStr tmp="[fserve] ";
262
if(!((KviDccChat *)(cmd->window))->sendData(tmp.ptr()))debug("oops! dcc chat not connected?");
265
static void fserve_parseCmdStats(KviPluginCommandStruct *cmd,KviFServeSession *s)
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);
279
static void fserve_parseCmdUnknown(KviPluginCommandStruct *cmd,KviFServeSession *s)
281
cmd->window->output(KVI_OUT_OWN,"[fserve >> %s] %s",s->nick.ptr(),"Unknown command");
282
((KviDccChat *)(cmd->window))->sendData("[fserve] Unknown command");
285
static void fserve_parseCmdLs(KviPluginCommandStruct *cmd,KviFServeSession *s)
287
KviStr tmp = g_szFServeRoot;
289
tmp.append(s->currentDir);
291
QString nameFilter = ((cmd->params->count() > 6) ? QString(kvirc_plugin_param(cmd,6)) : QString::null);
293
// if(cmd->params->count() > 6)nameFilter = kvirc_plugin_param(cmd,6);
295
QDir d(QString(tmp.ptr()),nameFilter,QDir::Name|QDir::IgnoreCase|QDir::DirsFirst,QDir::All|QDir::Readable|QDir::Hidden);
297
const QFileInfoList * l = d.entryInfoList();
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 /"));
306
QFileInfoListIterator it(*l);
310
bool bUnlimitedCredit = kvi_strEqualCI(s->credit.ptr(),"unlimited");
311
unsigned long credit = 0;
313
if(!bUnlimitedCredit){
315
credit = s->credit.toUInt(&bOk);
316
if(!bOk)s->credit = "0";
322
while((fi = it.current())){
325
tmp.append(KVI_TEXT_BOLD);
326
tmp.append(fi->fileName());
327
tmp.append(KVI_TEXT_BOLD);
328
} else if(fi->isSymLink()){
330
num.setNum(fi->size());
331
if((fi->size() > credit) && (!bUnlimitedCredit)){
332
tmp.append(KVI_TEXT_COLOR);
335
tmp.append(KVI_TEXT_RESET);
337
while(tmp.len() < 15)tmp.append(' ');
342
while(tmp.len() < 12)tmp.append(' ');
344
tmp.append(fi->fileName());
347
num.setNum(fi->size());
348
if((fi->size() > credit) && (!bUnlimitedCredit)){
349
tmp.append(KVI_TEXT_COLOR);
352
tmp.append(KVI_TEXT_RESET);
354
while(tmp.len() < 15)tmp.append(' ');
359
while(tmp.len() < 12)tmp.append(' ');
361
tmp.append(fi->fileName());
364
fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
370
tmp.prepend("total ");
371
fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
374
static void fserve_parseCmdCd(KviPluginCommandStruct *cmd,KviFServeSession *s)
376
// get the directory , other parameters are ignored
377
if(cmd->params->count() < 7)return;
379
KviStr dir = kvirc_plugin_param(cmd,6);
380
if(dir.isEmpty())return;
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
392
// ensure that our s->currentDir is valid at all
393
if(*(s->currentDir.ptr()) != '/')s->currentDir = '/';
397
// cd one dir at a time
398
while((*aux) && (!bError)){
399
// get the next path component
400
aux = kvi_extractToken(token,aux,'/');
403
if(kvi_strEqualCI(token.ptr() , "..")){
405
if(s->currentDir.len() > 1){
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);
411
if(idx == 0)s->currentDir = '/';
414
if(*(s->currentDir.ptr()) != '/')s->currentDir = "/";
416
} else if(!kvi_strEqualCI(token.ptr(), ".")){
418
KviStr tmp = g_szFServeRoot;
419
tmp.append(s->currentDir);
420
if(!s->currentDir.lastCharIs('/'))tmp.append('/');
422
if(kvi_directoryExists(tmp.ptr())){
423
if(!s->currentDir.lastCharIs('/'))s->currentDir.append('/');
424
s->currentDir.append(token);
425
} else bError = true;
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());
435
fserve_chatOutputAndSend(cmd,s->nick.ptr(),token);
438
static void fserve_parseCmdGet(KviPluginCommandStruct *cmd,KviFServeSession *s)
440
if(cmd->params->count() < 7)return;
441
KviStr filename = kvirc_plugin_param(cmd,6);
442
if(filename.isEmpty())return;
444
if(filename.findFirstIdx('/') == -1){
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);
452
QFileInfo fi(fName.ptr());
456
unsigned int credit = s->credit.toUInt(&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);
464
s->credit.setNum(credit);
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);
474
tmp.sprintf("Your credit is now %s bytes",s->credit.ptr());
475
fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
478
KviStr tmp(KviStr::Format,"%s: Access forbidden",filename.ptr());
479
fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
482
KviStr tmp(KviStr::Format,"%s: No such file",filename.ptr());
483
fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
486
KviStr tmp(KviStr::Format,"Invalid file name %s (no path elements allowed)",filename.ptr());
487
fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
491
static void fserve_parseCmdHelp(KviPluginCommandStruct *cmd,KviFServeSession *s)
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"));
503
static void fserve_parseCmdMotd(KviPluginCommandStruct *cmd,KviFServeSession *s)
505
KviStr tmp = g_szMotd;
507
while(tmp.getLine(line))fserve_chatOutputAndSend(cmd,s->nick.ptr(),line);
510
static void fserve_parseCmdPwd(KviPluginCommandStruct *cmd,KviFServeSession *s)
512
KviStr tmp(KviStr::Format,"Current directory is %s",s->currentDir.ptr());
513
fserve_chatOutputAndSend(cmd,s->nick.ptr(),tmp);
516
static void fserve_closeSession(KviFServeSession *s)
518
if(!kvi_strEqualCI(s->credit.ptr(),"unlimited")){
519
// limited credit....need to save the session
520
KviSavedSession * ss = new KviSavedSession;
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();
528
g_pSessions->removeRef(s);
531
static void fserve_parseCmdQuit(KviPluginCommandStruct *cmd,KviFServeSession *s)
533
fserve_chatOutputAndSend(cmd,s->nick.ptr(),KviStr("File server session closed."));
534
fserve_closeSession(s);
537
static bool fserve_isBannedIp(const char *ip)
539
for(KviStr * s=g_pBannedIpList->first();s;s=g_pBannedIpList->next()){
540
if(kvi_matchWildExpr(ip,s->ptr()))return true;
545
static void fserve_startSession(KviPluginCommandStruct *cmd,const char *nick,
546
const char *ip,const char *credit)
548
KviFServeSession *s = new KviFServeSession;
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);
561
static void fserve_startNormalSession(KviPluginCommandStruct *cmd,const char *nick,const char *ip)
563
KviSavedSession * ss= fserve_findSavedSession(nick,ip);
566
fserve_startSession(cmd,nick,ip,ss->credit.ptr());
567
g_pSavedSessions->removeRef(ss);
570
fserve_startSession(cmd,nick,ip,g_szInitialCredit.ptr());
574
static void fserve_doLogin(KviPluginCommandStruct * cmd,KviStr &nick,KviStr &user,KviStr &host,KviStr &ip,KviStr &pass)
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"));
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');
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
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());
597
// the fserve needs also a global pass...failed
598
fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Use '.fserve <password>' to login"));
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());
609
fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Access denied: invalid password"));
613
// no password needed: start the session
614
fserve_startSession(cmd,nick.ptr(),ip.ptr(),"unlimited");
617
// user is not registered
618
if(g_szFServePass.hasData()){
619
// a password is needed
621
// failed...no pass specified
622
fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Use '.fserve <password>' to login"));
625
if(!kvi_strEqualCI(pass.ptr(),g_szFServePass.ptr())){
626
fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Access denied: invalid password"));
631
// no password needed or password ok
632
fserve_startNormalSession(cmd,nick.ptr(),ip.ptr());
636
static void fserve_parseCmdFServe(KviPluginCommandStruct *cmd)
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);
645
g_szFServePass.stripWhiteSpace();
647
if(g_pSessions->count() >= g_uMaxRunningSessions){
648
fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Sorry , the server is full: try again later"));
652
if(fserve_isBannedIp(ip.ptr())){
653
fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Sorry , you're banned from this file server"));
657
switch(cmd->params->count()){
662
pass = kvirc_plugin_param(cmd,6);
665
user = kvirc_plugin_param(cmd,6);
666
host = kvirc_plugin_param(cmd,7);
669
user = kvirc_plugin_param(cmd,6);
670
host = kvirc_plugin_param(cmd,7);
671
pass = kvirc_plugin_param(cmd,8);
674
fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Invalid number of parameters."));
675
fserve_chatOutputAndSend(cmd,nick.ptr(),KviStr("Syntax: .fserve [<user> <host>] [password]"));
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]'"));
686
fserve_doLogin(cmd,nick,user,host,ip,pass);
689
bool fserve_plugin_hook_onMePrivateMessage(KviPluginCommandStruct *cmd)
691
if(!g_bServerActive || !g_bListenToPrivmsg)debug("WARNING : Unexpected hook on private message");
693
if(kvi_strEqualCIN(kvirc_plugin_param(cmd,3),"!fserve",7)){
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');
700
if(cmd->params->count() == 4){
701
// must be registered with f flag and have no password set
703
if(u->passwd.hasData())return false;
705
// specified a password
706
if(!kvi_strEqualCI(g_szFServePass.ptr(),kvirc_plugin_param(cmd,4))){
707
// invalid fserve global pass
709
if(u->passwd.isEmpty())return false;
710
if(!kvi_strEqualCI(u->passwd.ptr(),kvirc_plugin_param(cmd,4)))return false;
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) : ""));
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);
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
730
bool fserve_plugin_hook_onDccChatConnected(KviPluginCommandStruct *cmd)
732
if(!g_bServerActive)return false;
733
KviPendingSession * s = fserve_findPendingSession(cmd->window);
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
746
bool fserve_plugin_hook_onDccChatMessage(KviPluginCommandStruct *cmd)
748
if(!g_bServerActive)return false;
750
KviStr * firstWord = cmd->params->at(5);
752
if(!firstWord)return false; // not a fserve command at all
753
if(*(firstWord->ptr()) != '.')return false; // same as above
756
KviFServeSession * s = fserve_findRunningSession(cmd->window);
759
KviStr out = firstWord->ptr();
760
for(unsigned int i=6;i < cmd->params->count();i++){
762
out.append(kvirc_plugin_param(cmd,i));
764
cmd->window->output(KVI_OUT_NONE,"[%s >> fserve] %s",s->nick.ptr(),out.ptr());
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);
776
// Not a running service
777
if(kvi_strEqualCI(firstWord->ptr(),".fserve")){
779
KviStr out = firstWord->ptr();
780
for(unsigned int i=6;i < cmd->params->count();i++){
782
out.append(cmd->params->at(i)->ptr());
784
cmd->window->output(KVI_OUT_NONE,"[%s >> fserve] %s",kvirc_plugin_param(cmd,1),out.ptr());
785
fserve_parseCmdFServe(cmd);
792
bool fserve_plugin_hook_onDccChatTerminated(KviPluginCommandStruct *cmd)
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
800
bool fserve_plugin_hook_onDccGetTransferComplete(KviPluginCommandStruct *cmd)
803
unsigned int crAdd = cmd->params->at(6)->toUInt(&bOk);
805
debug("oops...can't calculate the credit to give to %s , giving (100.000 bytes * ratio)",cmd->params->at(1)->ptr());
809
KviFServeSession * s = fserve_findRunningSessionByNickAndIp(kvirc_plugin_param(cmd,1),kvirc_plugin_param(cmd,4));
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());
828
KviSavedSession * ss = fserve_findSavedSession(kvirc_plugin_param(cmd,1),kvirc_plugin_param(cmd,4));
830
unsigned int crOld = ss->credit.toUInt(&bOk);
832
crOld += ((crAdd / g_iRatioTake) * g_iRatioGive);
833
ss->credit.setNum(crOld);
835
// We could also ack the dcc send completion to that user...
840
void fserve_plugin_config()
842
if(!g_pConfigDialog){
843
g_pConfigDialog = new KviFServeConfigDialog();
844
g_pConfigDialog->show();
848
bool fserve_plugin_command_fserve(KviPluginCommandStruct *cmd)
850
if(!g_bServerActive){
851
cmd->window->output(KVI_OUT_INTERNAL,__tr("[fserve] The file server is not active"));
854
if(cmd->params->count() < 2){
855
cmd->error = KVI_ERROR_MissingParameter;
858
if(kvi_strEqualCI(kvirc_plugin_param(cmd,1),"list")){
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());
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>)");
873
KviStr address = kvirc_plugin_param(cmd,2);
874
KviStr nick = address.getToken('@');
875
KviFServeSession * s = fserve_findRunningSessionByNickAndIp(nick.ptr(),address.ptr());
877
cmd->error = KVI_ERROR_InvalidParameter;
878
cmd->errorstr = __tr("Session not found");
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");
891
KviStr address = kvirc_plugin_param(cmd,2);
892
KviStr nick = address.getToken('@');
893
KviFServeSession * s = fserve_findRunningSessionByNickAndIp(nick.ptr(),address.ptr());
895
cmd->error = KVI_ERROR_InvalidParameter;
896
cmd->errorstr = __tr("Session not found");
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'");
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();
917
cmd->error = KVI_ERROR_InvalidOperation;
918
cmd->errorstr = __tr("Available operations are : 'list' , 'boot' and 'credit'");
925
bool fserve_plugin_init(KviPluginCommandStruct * cmd)
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();
940
kvirc_plugin_register_command(cmd->handle,"FSERVE",fserve_plugin_command_fserve);
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);
955
void fserve_plugin_cleanup()
957
fserve_pluginSaveState();
959
if(g_pConfigDialog)delete g_pConfigDialog; //we're unloaded!
961
delete g_pBannedIpList;
962
delete g_pSavedSessions;
963
delete g_pPendingSessions;
965
kvirc_plugin_unregister_meta_object("KviFServeConfigDialog");
968
void fserve_configFinished(bool 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;
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";
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.");
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);
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 '/'.");
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);
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);
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);
1029
delete g_pConfigDialog;
1030
g_pConfigDialog = 0;
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 <filename>' , where <filename> 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 <your_nickname> !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 <nickname@ipaddress></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 <nickname@ipaddress> <creditvalue></b><br><br>
1097
Sets the credit of a specified session to <creditvalue> 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>
1103
void fserve_plugin_help()
1105
kvirc_plugin_show_help_page("doc_plugin_fserve.kvihelp");
1108
// plugin definition structure
1109
// MUST be named 'kvirc_plugin'
1110
KviPlugin kvirc_plugin =
1112
"fserve" , // plugin name
1113
"KVIrc DCC file server" , // description
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
1127
// =======================================
1129
// =======================================
1131
#include <qlayout.h>
1134
#include "kvi_selectors.h"
1136
KviFServeConfigDialog::KviFServeConfigDialog()
1139
setCaption(__tr("File server configuration"));
1141
QWidget *tab = new QWidget(this);
1142
QGridLayout *g = new QGridLayout(tab,5,1,10,4);
1144
KviNewBoolSelector *b=new KviNewBoolSelector(tab,__tr("Activate file server"),&(g_bServerActive),true);
1145
g->addWidget(b,0,0);
1147
QFrame *r = new QFrame(tab);
1148
r->setFrameStyle(QFrame::Sunken | QFrame::HLine);
1149
g->addWidget(r,1,0);
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);
1161
r = new QFrame(tab);
1162
r->setFrameStyle(QFrame::Sunken | QFrame::HLine);
1163
g->addWidget(r,3,0);
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);
1169
g->setRowStretch(2,2);
1171
addTab(tab,__tr("Main"));
1173
tab = new QWidget(this);
1174
g = new QGridLayout(tab,7,1,10,4);
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);
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);
1184
r = new QFrame(tab);
1185
r->setFrameStyle(QFrame::Sunken | QFrame::HLine);
1186
g->addMultiCellWidget(r,2,2,0,4);
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);
1193
m_pRatioGiveEdit = new QLineEdit(tab);
1194
m_pRatioGiveEdit->setEnabled(g_bServerActive);
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);
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);
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);
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);
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);
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);
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);
1234
addTab(tab,__tr("Public access"));
1236
tab = new QWidget(this);
1237
g = new QGridLayout(tab,2,1,10,4);
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);
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);
1250
addTab(tab,__tr("Motd"));
1252
tab = new QWidget(this);
1253
g = new QGridLayout(tab,1,3,10,4);
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);
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);
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);
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);
1277
for(KviStr * s=g_pBannedIpList->first();s;s=g_pBannedIpList->next()){
1278
m_pBannedIpList->insertItem(s->ptr());
1281
g->setRowStretch(1,2);
1283
addTab(tab,__tr("Banned IP addresses"));
1285
setCancelButton(__tr("Cancel"));
1289
KviFServeConfigDialog::~KviFServeConfigDialog()
1293
void KviFServeConfigDialog::done(int r)
1295
QTabDialog::done(r);
1297
KviNewBoolSelector::commitAll(this);
1298
KviNewStringSelector::commitAll(this);
1299
KviNewIntegerSelector::commitAll(this);
1300
KviStr tmp = m_pRatioTakeEdit->text();
1301
tmp.stripWhiteSpace();
1303
g_iRatioTake = tmp.toInt(&bOk);
1304
if((!bOk) || (g_iRatioTake < 1))g_iRatioTake = 1;
1305
tmp = m_pRatioGiveEdit->text();
1306
tmp.stripWhiteSpace();
1308
g_iRatioGive = tmp.toInt(&bOk);
1309
if((!bOk) || (g_iRatioGive < 0))g_iRatioGive = 1;
1310
g_szMotd = m_pMotdEdit->text();
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()));
1320
fserve_configFinished((r == Accepted));
1323
void KviFServeConfigDialog::closeEvent(QCloseEvent *)
1325
// Finished without committing
1326
fserve_configFinished(false);
1329
void KviFServeConfigDialog::addBannedIp()
1331
KviStr tmp = m_pBannedIpEdit->text();
1332
tmp.stripWhiteSpace();
1333
if(tmp.hasData())m_pBannedIpList->insertItem(tmp.ptr());
1336
void KviFServeConfigDialog::removeBannedIp()
1338
int idx = m_pBannedIpList->currentItem();
1339
if(idx != -1)m_pBannedIpList->removeItem(idx);
1342
#include "m_libkvifserve.moc"