summaryrefslogtreecommitdiff
authorzecke <zecke>2003-09-19 16:44:24 (UTC)
committer zecke <zecke>2003-09-19 16:44:24 (UTC)
commit42a5104340694255dc514514e7621ac2cee026fe (patch) (unidiff)
tree34aaeff901102918e2bec39e0f32b365901a0a55
parent6fc0216161b4ad62cd407d2a36d78d8bd88f4ed0 (diff)
downloadopie-42a5104340694255dc514514e7621ac2cee026fe.zip
opie-42a5104340694255dc514514e7621ac2cee026fe.tar.gz
opie-42a5104340694255dc514514e7621ac2cee026fe.tar.bz2
Use local config file instead of a global....
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/transferserver.cpp4
1 files changed, 2 insertions, 2 deletions
diff --git a/core/launcher/transferserver.cpp b/core/launcher/transferserver.cpp
index fde6f8b..2180577 100644
--- a/core/launcher/transferserver.cpp
+++ b/core/launcher/transferserver.cpp
@@ -1,609 +1,609 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of the Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20//#define _XOPEN_SOURCE 20//#define _XOPEN_SOURCE
21 21
22#include <qtopia/global.h> 22#include <qtopia/global.h>
23#include <qtopia/qpeapplication.h> 23#include <qtopia/qpeapplication.h>
24 24
25#ifndef Q_OS_WIN32 25#ifndef Q_OS_WIN32
26#include <pwd.h> 26#include <pwd.h>
27#include <sys/types.h> 27#include <sys/types.h>
28#include <unistd.h> 28#include <unistd.h>
29#include <stdlib.h> 29#include <stdlib.h>
30#include <time.h> 30#include <time.h>
31#include <shadow.h> 31#include <shadow.h>
32#include <crypt.h> 32#include <crypt.h>
33 33
34#else 34#else
35#include <stdlib.h> 35#include <stdlib.h>
36#include <time.h> 36#include <time.h>
37#endif 37#endif
38 38
39 39
40#if defined(_OS_LINUX_) 40#if defined(_OS_LINUX_)
41#include <shadow.h> 41#include <shadow.h>
42#endif 42#endif
43 43
44#include <qdir.h> 44#include <qdir.h>
45#include <qfile.h> 45#include <qfile.h>
46#include <qtextstream.h> 46#include <qtextstream.h>
47#include <qdatastream.h> 47#include <qdatastream.h>
48#include <qmessagebox.h> 48#include <qmessagebox.h>
49#include <qstringlist.h> 49#include <qstringlist.h>
50#include <qfileinfo.h> 50#include <qfileinfo.h>
51#include <qregexp.h> 51#include <qregexp.h>
52//#include <qtopia/qcopchannel_qws.h> 52//#include <qtopia/qcopchannel_qws.h>
53#include <qtopia/process.h> 53#include <qtopia/process.h>
54#include <qtopia/global.h> 54#include <qtopia/global.h>
55#include <qtopia/config.h> 55#include <qtopia/config.h>
56#include <qtopia/private/contact.h> 56#include <qtopia/private/contact.h>
57#include <qtopia/quuid.h> 57#include <qtopia/quuid.h>
58#include <qtopia/version.h> 58#include <qtopia/version.h>
59#ifdef Q_WS_QWS 59#ifdef Q_WS_QWS
60#include <qtopia/qcopenvelope_qws.h> 60#include <qtopia/qcopenvelope_qws.h>
61#endif 61#endif
62 62
63#include "launcherglobal.h" 63#include "launcherglobal.h"
64 64
65#include "transferserver.h" 65#include "transferserver.h"
66#include <qtopia/qprocess.h> 66#include <qtopia/qprocess.h>
67 67
68const int block_size = 51200; 68const int block_size = 51200;
69 69
70TransferServer::TransferServer( Q_UINT16 port, QObject *parent, 70TransferServer::TransferServer( Q_UINT16 port, QObject *parent,
71 const char* name) 71 const char* name)
72 : QServerSocket( port, 1, parent, name ) 72 : QServerSocket( port, 1, parent, name )
73{ 73{
74 connections.setAutoDelete( TRUE ); 74 connections.setAutoDelete( TRUE );
75 if ( !ok() ) 75 if ( !ok() )
76 qWarning( "Failed to bind to port %d", port ); 76 qWarning( "Failed to bind to port %d", port );
77} 77}
78 78
79void TransferServer::authorizeConnections() 79void TransferServer::authorizeConnections()
80{ 80{
81 QListIterator<ServerPI> it(connections); 81 QListIterator<ServerPI> it(connections);
82 while ( it.current() ) { 82 while ( it.current() ) {
83 if ( !it.current()->verifyAuthorised() ) { 83 if ( !it.current()->verifyAuthorised() ) {
84 disconnect( it.current(), SIGNAL(connectionClosed(ServerPI *)), this, SLOT( closed(ServerPI *)) ); 84 disconnect( it.current(), SIGNAL(connectionClosed(ServerPI *)), this, SLOT( closed(ServerPI *)) );
85 connections.removeRef( it.current() ); 85 connections.removeRef( it.current() );
86 } else 86 } else
87 ++it; 87 ++it;
88 } 88 }
89} 89}
90 90
91void TransferServer::closed(ServerPI *item) 91void TransferServer::closed(ServerPI *item)
92{ 92{
93 connections.removeRef(item); 93 connections.removeRef(item);
94} 94}
95 95
96TransferServer::~TransferServer() 96TransferServer::~TransferServer()
97{ 97{
98} 98}
99 99
100void TransferServer::newConnection( int socket ) 100void TransferServer::newConnection( int socket )
101{ 101{
102 ServerPI *ptr = new ServerPI( socket, this ); 102 ServerPI *ptr = new ServerPI( socket, this );
103 connect( ptr, SIGNAL(connectionClosed(ServerPI *)), this, SLOT( closed(ServerPI *)) ); 103 connect( ptr, SIGNAL(connectionClosed(ServerPI *)), this, SLOT( closed(ServerPI *)) );
104 connections.append( ptr ); 104 connections.append( ptr );
105} 105}
106 106
107QString SyncAuthentication::serverId() 107QString SyncAuthentication::serverId()
108{ 108{
109 Config cfg("Security"); 109 Config cfg("Security");
110 cfg.setGroup("Sync"); 110 cfg.setGroup("Sync");
111 QString r = cfg.readEntry("serverid"); 111 QString r = cfg.readEntry("serverid");
112 112
113 if ( r.isEmpty() ) { 113 if ( r.isEmpty() ) {
114 r = Opie::Global::uuid(); 114 r = Opie::Global::uuid();
115 cfg.writeEntry("serverid", r ); 115 cfg.writeEntry("serverid", r );
116 } 116 }
117 return r; 117 return r;
118} 118}
119 119
120QString SyncAuthentication::ownerName() 120QString SyncAuthentication::ownerName()
121{ 121{
122 QString vfilename = Global::applicationFileName("addressbook", 122 QString vfilename = Global::applicationFileName("addressbook",
123 "businesscard.vcf"); 123 "businesscard.vcf");
124 if (QFile::exists(vfilename)) { 124 if (QFile::exists(vfilename)) {
125 Contact c; 125 Contact c;
126 c = Contact::readVCard( vfilename )[0]; 126 c = Contact::readVCard( vfilename )[0];
127 return c.fullName(); 127 return c.fullName();
128 } 128 }
129 129
130 return QString::null; 130 return QString::null;
131} 131}
132 132
133QString SyncAuthentication::loginName() 133QString SyncAuthentication::loginName()
134{ 134{
135 struct passwd *pw = 0L; 135 struct passwd *pw = 0L;
136#ifndef Q_OS_WIN32 136#ifndef Q_OS_WIN32
137 pw = getpwuid( geteuid() ); 137 pw = getpwuid( geteuid() );
138 return QString::fromLocal8Bit( pw->pw_name ); 138 return QString::fromLocal8Bit( pw->pw_name );
139#else 139#else
140 //### revise 140 //### revise
141 return QString(); 141 return QString();
142#endif 142#endif
143} 143}
144 144
145int SyncAuthentication::isAuthorized(QHostAddress peeraddress) 145int SyncAuthentication::isAuthorized(QHostAddress peeraddress)
146{ 146{
147 Config cfg("Security"); 147 Config cfg("Security");
148 cfg.setGroup("Sync"); 148 cfg.setGroup("Sync");
149 // QString allowedstr = cfg.readEntry("auth_peer","192.168.1.0"); 149 // QString allowedstr = cfg.readEntry("auth_peer","192.168.1.0");
150 uint auth_peer = cfg.readNumEntry("auth_peer", 0xc0a80100); 150 uint auth_peer = cfg.readNumEntry("auth_peer", 0xc0a80100);
151 151
152 // QHostAddress allowed; 152 // QHostAddress allowed;
153 // allowed.setAddress(allowedstr); 153 // allowed.setAddress(allowedstr);
154 // uint auth_peer = allowed.ip4Addr(); 154 // uint auth_peer = allowed.ip4Addr();
155 uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits", 24); 155 uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits", 24);
156 uint mask = auth_peer_bits >= 32 // shifting by 32 is not defined 156 uint mask = auth_peer_bits >= 32 // shifting by 32 is not defined
157 ? 0xffffffff : (((1 << auth_peer_bits) - 1) << (32 - auth_peer_bits)); 157 ? 0xffffffff : (((1 << auth_peer_bits) - 1) << (32 - auth_peer_bits));
158 158
159 return (peeraddress.ip4Addr() & mask) == auth_peer; 159 return (peeraddress.ip4Addr() & mask) == auth_peer;
160} 160}
161 161
162bool SyncAuthentication::checkUser( const QString& user ) 162bool SyncAuthentication::checkUser( const QString& user )
163{ 163{
164 if ( user.isEmpty() ) return FALSE; 164 if ( user.isEmpty() ) return FALSE;
165 QString euser = loginName(); 165 QString euser = loginName();
166 return user == euser; 166 return user == euser;
167} 167}
168 168
169bool SyncAuthentication::checkPassword( const QString& password ) 169bool SyncAuthentication::checkPassword( const QString& password )
170{ 170{
171#ifdef ALLOW_UNIX_USER_FTP 171#ifdef ALLOW_UNIX_USER_FTP
172 // First, check system password... 172 // First, check system password...
173 173
174 struct passwd *pw = 0; 174 struct passwd *pw = 0;
175 struct spwd *spw = 0; 175 struct spwd *spw = 0;
176 176
177 pw = getpwuid( geteuid() ); 177 pw = getpwuid( geteuid() );
178 spw = getspnam( pw->pw_name ); 178 spw = getspnam( pw->pw_name );
179 179
180 QString cpwd = QString::fromLocal8Bit( pw->pw_passwd ); 180 QString cpwd = QString::fromLocal8Bit( pw->pw_passwd );
181 if ( cpwd == "x" && spw ) 181 if ( cpwd == "x" && spw )
182 cpwd = QString::fromLocal8Bit( spw->sp_pwdp ); 182 cpwd = QString::fromLocal8Bit( spw->sp_pwdp );
183 183
184 // Note: some systems use more than crypt for passwords. 184 // Note: some systems use more than crypt for passwords.
185 QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) ); 185 QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) );
186 if ( cpwd == cpassword ) 186 if ( cpwd == cpassword )
187 return TRUE; 187 return TRUE;
188#endif 188#endif
189 189
190 static int lastdenial=0; 190 static int lastdenial=0;
191 static int denials=0; 191 static int denials=0;
192 int now = time(0); 192 int now = time(0);
193 193
194 // Detect old Qtopia Desktop (no password) 194 // Detect old Qtopia Desktop (no password)
195 if ( password.isEmpty() ) { 195 if ( password.isEmpty() ) {
196 if ( denials < 1 || now > lastdenial+600 ) { 196 if ( denials < 1 || now > lastdenial+600 ) {
197 QMessageBox unauth( 197 QMessageBox unauth(
198 tr("Sync Connection"), 198 tr("Sync Connection"),
199 tr("<p>An unauthorized system is requesting access to this device." 199 tr("<p>An unauthorized system is requesting access to this device."
200 "<p>If you are using a version of Qtopia Desktop older than 1.5.1, " 200 "<p>If you are using a version of Qtopia Desktop older than 1.5.1, "
201 "please upgrade."), 201 "please upgrade."),
202 QMessageBox::Warning, 202 QMessageBox::Warning,
203 QMessageBox::Cancel, QMessageBox::NoButton, QMessageBox::NoButton, 203 QMessageBox::Cancel, QMessageBox::NoButton, QMessageBox::NoButton,
204 0, QString::null, TRUE, WStyle_StaysOnTop); 204 0, QString::null, TRUE, WStyle_StaysOnTop);
205 unauth.setButtonText(QMessageBox::Cancel, tr("Deny")); 205 unauth.setButtonText(QMessageBox::Cancel, tr("Deny"));
206 unauth.exec(); 206 unauth.exec();
207 207
208 denials++; 208 denials++;
209 lastdenial=now; 209 lastdenial=now;
210 } 210 }
211 return FALSE; 211 return FALSE;
212 } 212 }
213 213
214 // Second, check sync password... 214 // Second, check sync password...
215 215
216 static int lock=0; 216 static int lock=0;
217 if ( lock ) return FALSE; 217 if ( lock ) return FALSE;
218 218
219 ++lock; 219 ++lock;
220 220
221 /* 221 /*
222 * we need to support old Sync software and QtopiaDesktop 222 * we need to support old Sync software and QtopiaDesktop
223 */ 223 */
224 if ( password.left(6) == "Qtopia" || password.left(6) == "rootme" ) { 224 if ( password.left(6) == "Qtopia" || password.left(6) == "rootme" ) {
225 Config cfg( QPEApplication::qpeDir()+"/etc/Security.conf", Config::File ); 225 Config cfg( "Security.conf" );
226 cfg.setGroup("Sync"); 226 cfg.setGroup("Sync");
227 QStringList pwds = cfg.readListEntry("Passwords",' '); 227 QStringList pwds = cfg.readListEntry("Passwords",' ');
228 for (QStringList::ConstIterator it=pwds.begin(); it!=pwds.end(); ++it) { 228 for (QStringList::ConstIterator it=pwds.begin(); it!=pwds.end(); ++it) {
229#ifndef Q_OS_WIN32 229#ifndef Q_OS_WIN32
230 QString cpassword = QString::fromLocal8Bit( 230 QString cpassword = QString::fromLocal8Bit(
231 crypt( password.mid(8).local8Bit(), (*it).left(2).latin1() ) ); 231 crypt( password.mid(8).local8Bit(), (*it).left(2).latin1() ) );
232#else 232#else
233 // ### revise 233 // ### revise
234 QString cpassword(""); 234 QString cpassword("");
235#endif 235#endif
236 if ( *it == cpassword ) { 236 if ( *it == cpassword ) {
237 lock--; 237 lock--;
238 return TRUE; 238 return TRUE;
239 } 239 }
240 } 240 }
241 241
242 // Unrecognized system. Be careful... 242 // Unrecognized system. Be careful...
243 QMessageBox unrecbox( 243 QMessageBox unrecbox(
244 tr("Sync Connection"), 244 tr("Sync Connection"),
245 tr("<p>An unrecognized system is requesting access to this device." 245 tr("<p>An unrecognized system is requesting access to this device."
246 "<p>If you have just initiated a Sync for the first time, this is normal."), 246 "<p>If you have just initiated a Sync for the first time, this is normal."),
247 QMessageBox::Warning, 247 QMessageBox::Warning,
248 QMessageBox::Cancel, QMessageBox::Yes, QMessageBox::NoButton, 248 QMessageBox::Cancel, QMessageBox::Yes, QMessageBox::NoButton,
249 0, QString::null, TRUE, WStyle_StaysOnTop); 249 0, QString::null, TRUE, WStyle_StaysOnTop);
250 unrecbox.setButtonText(QMessageBox::Cancel, tr("Deny")); 250 unrecbox.setButtonText(QMessageBox::Cancel, tr("Deny"));
251 unrecbox.setButtonText(QMessageBox::Yes, tr("Allow")); 251 unrecbox.setButtonText(QMessageBox::Yes, tr("Allow"));
252 252
253 if ( (denials > 2 && now < lastdenial+600) 253 if ( (denials > 2 && now < lastdenial+600)
254 || unrecbox.exec() != QMessageBox::Yes) 254 || unrecbox.exec() != QMessageBox::Yes)
255 { 255 {
256 denials++; 256 denials++;
257 lastdenial=now; 257 lastdenial=now;
258 lock--; 258 lock--;
259 return FALSE; 259 return FALSE;
260 } else { 260 } else {
261 const char salty[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/."; 261 const char salty[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/.";
262 char salt[2]; 262 char salt[2];
263 salt[0]= salty[rand() % (sizeof(salty)-1)]; 263 salt[0]= salty[rand() % (sizeof(salty)-1)];
264 salt[1]= salty[rand() % (sizeof(salty)-1)]; 264 salt[1]= salty[rand() % (sizeof(salty)-1)];
265#ifndef Q_OS_WIN32 265#ifndef Q_OS_WIN32
266 QString cpassword = QString::fromLocal8Bit( 266 QString cpassword = QString::fromLocal8Bit(
267 crypt( password.mid(8).local8Bit(), salt ) ); 267 crypt( password.mid(8).local8Bit(), salt ) );
268#else 268#else
269 //### revise 269 //### revise
270 QString cpassword(""); 270 QString cpassword("");
271#endif 271#endif
272 denials=0; 272 denials=0;
273 pwds.prepend(cpassword); 273 pwds.prepend(cpassword);
274 cfg.writeEntry("Passwords",pwds,' '); 274 cfg.writeEntry("Passwords",pwds,' ');
275 lock--; 275 lock--;
276 return TRUE; 276 return TRUE;
277 } 277 }
278 } 278 }
279 lock--; 279 lock--;
280 280
281 return FALSE; 281 return FALSE;
282} 282}
283 283
284 284
285ServerPI::ServerPI( int socket, QObject *parent, const char* name ) 285ServerPI::ServerPI( int socket, QObject *parent, const char* name )
286 : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 ), 286 : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 ),
287 storFileSize(-1) 287 storFileSize(-1)
288{ 288{
289 state = Connected; 289 state = Connected;
290 290
291 setSocket( socket ); 291 setSocket( socket );
292 292
293 peerport = peerPort(); 293 peerport = peerPort();
294 peeraddress = peerAddress(); 294 peeraddress = peerAddress();
295 295
296#ifndef INSECURE 296#ifndef INSECURE
297 if ( !SyncAuthentication::isAuthorized(peeraddress) ) { 297 if ( !SyncAuthentication::isAuthorized(peeraddress) ) {
298 state = Forbidden; 298 state = Forbidden;
299 startTimer( 0 ); 299 startTimer( 0 );
300 } else 300 } else
301#endif 301#endif
302 { 302 {
303 connect( this, SIGNAL( readyRead() ), SLOT( read() ) ); 303 connect( this, SIGNAL( readyRead() ), SLOT( read() ) );
304 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) ); 304 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) );
305 305
306 passiv = FALSE; 306 passiv = FALSE;
307 for( int i = 0; i < 4; i++ ) 307 for( int i = 0; i < 4; i++ )
308 wait[i] = FALSE; 308 wait[i] = FALSE;
309 309
310 send( "220 Qtopia " QPE_VERSION " FTP Server" ); // No tr 310 send( "220 Qtopia " QPE_VERSION " FTP Server" ); // No tr
311 state = Wait_USER; 311 state = Wait_USER;
312 312
313 dtp = new ServerDTP( this ); 313 dtp = new ServerDTP( this );
314 connect( dtp, SIGNAL( completed() ), SLOT( dtpCompleted() ) ); 314 connect( dtp, SIGNAL( completed() ), SLOT( dtpCompleted() ) );
315 connect( dtp, SIGNAL( failed() ), SLOT( dtpFailed() ) ); 315 connect( dtp, SIGNAL( failed() ), SLOT( dtpFailed() ) );
316 connect( dtp, SIGNAL( error( int ) ), SLOT( dtpError( int ) ) ); 316 connect( dtp, SIGNAL( error( int ) ), SLOT( dtpError( int ) ) );
317 317
318 318
319 directory = QDir::currentDirPath(); 319 directory = QDir::currentDirPath();
320 320
321 static int p = 1024; 321 static int p = 1024;
322 322
323 while ( !serversocket || !serversocket->ok() ) { 323 while ( !serversocket || !serversocket->ok() ) {
324 delete serversocket; 324 delete serversocket;
325 serversocket = new ServerSocket( ++p, this ); 325 serversocket = new ServerSocket( ++p, this );
326 } 326 }
327 connect( serversocket, SIGNAL( newIncomming( int ) ), 327 connect( serversocket, SIGNAL( newIncomming( int ) ),
328 SLOT( newConnection( int ) ) ); 328 SLOT( newConnection( int ) ) );
329 } 329 }
330} 330}
331 331
332ServerPI::~ServerPI() 332ServerPI::~ServerPI()
333{ 333{
334 close(); 334 close();
335 dtp->close(); 335 dtp->close();
336 delete dtp; 336 delete dtp;
337 delete serversocket; 337 delete serversocket;
338} 338}
339 339
340bool ServerPI::verifyAuthorised() 340bool ServerPI::verifyAuthorised()
341{ 341{
342 if ( !SyncAuthentication::isAuthorized(peerAddress()) ) { 342 if ( !SyncAuthentication::isAuthorized(peerAddress()) ) {
343 state = Forbidden; 343 state = Forbidden;
344 return FALSE; 344 return FALSE;
345 } 345 }
346 return TRUE; 346 return TRUE;
347} 347}
348 348
349void ServerPI::connectionClosed() 349void ServerPI::connectionClosed()
350{ 350{
351 // qDebug( "Debug: Connection closed" ); 351 // qDebug( "Debug: Connection closed" );
352 emit connectionClosed(this); 352 emit connectionClosed(this);
353} 353}
354 354
355void ServerPI::send( const QString& msg ) 355void ServerPI::send( const QString& msg )
356{ 356{
357 QTextStream os( this ); 357 QTextStream os( this );
358 os << msg << endl; 358 os << msg << endl;
359 //qDebug( "Reply: %s", msg.latin1() ); 359 //qDebug( "Reply: %s", msg.latin1() );
360} 360}
361 361
362void ServerPI::read() 362void ServerPI::read()
363{ 363{
364 while ( canReadLine() ) 364 while ( canReadLine() )
365 process( readLine().stripWhiteSpace() ); 365 process( readLine().stripWhiteSpace() );
366} 366}
367 367
368bool ServerPI::checkReadFile( const QString& file ) 368bool ServerPI::checkReadFile( const QString& file )
369{ 369{
370 QString filename; 370 QString filename;
371 371
372 if ( file[0] != "/" ) 372 if ( file[0] != "/" )
373 filename = directory.path() + "/" + file; 373 filename = directory.path() + "/" + file;
374 else 374 else
375 filename = file; 375 filename = file;
376 376
377 QFileInfo fi( filename ); 377 QFileInfo fi( filename );
378 return ( fi.exists() && fi.isReadable() ); 378 return ( fi.exists() && fi.isReadable() );
379} 379}
380 380
381bool ServerPI::checkWriteFile( const QString& file ) 381bool ServerPI::checkWriteFile( const QString& file )
382{ 382{
383 QString filename; 383 QString filename;
384 384
385 if ( file[0] != "/" ) 385 if ( file[0] != "/" )
386 filename = directory.path() + "/" + file; 386 filename = directory.path() + "/" + file;
387 else 387 else
388 filename = file; 388 filename = file;
389 389
390 QFileInfo fi( filename ); 390 QFileInfo fi( filename );
391 391
392 if ( fi.exists() ) 392 if ( fi.exists() )
393 if ( !QFile( filename ).remove() ) 393 if ( !QFile( filename ).remove() )
394 return FALSE; 394 return FALSE;
395 return TRUE; 395 return TRUE;
396} 396}
397 397
398void ServerPI::process( const QString& message ) 398void ServerPI::process( const QString& message )
399{ 399{
400 //qDebug( "Command: %s", message.latin1() ); 400 //qDebug( "Command: %s", message.latin1() );
401 401
402 // split message using "," as separator 402 // split message using "," as separator
403 QStringList msg = QStringList::split( " ", message ); 403 QStringList msg = QStringList::split( " ", message );
404 if ( msg.isEmpty() ) return; 404 if ( msg.isEmpty() ) return;
405 405
406 // command token 406 // command token
407 QString cmd = msg[0].upper(); 407 QString cmd = msg[0].upper();
408 408
409 // argument token 409 // argument token
410 QString arg; 410 QString arg;
411 if ( msg.count() >= 2 ) 411 if ( msg.count() >= 2 )
412 arg = msg[1]; 412 arg = msg[1];
413 413
414 // full argument string 414 // full argument string
415 QString args; 415 QString args;
416 if ( msg.count() >= 2 ) { 416 if ( msg.count() >= 2 ) {
417 QStringList copy( msg ); 417 QStringList copy( msg );
418 // FIXME: for Qt3 418 // FIXME: for Qt3
419 // copy.pop_front() 419 // copy.pop_front()
420 copy.remove( copy.begin() ); 420 copy.remove( copy.begin() );
421 args = copy.join( " " ); 421 args = copy.join( " " );
422 } 422 }
423 423
424 //qDebug( "args: %s", args.latin1() ); 424 //qDebug( "args: %s", args.latin1() );
425 425
426 // we always respond to QUIT, regardless of state 426 // we always respond to QUIT, regardless of state
427 if ( cmd == "QUIT" ) { 427 if ( cmd == "QUIT" ) {
428 send( "211 Good bye!" ); // No tr 428 send( "211 Good bye!" ); // No tr
429 close(); 429 close();
430 return; 430 return;
431 } 431 }
432 432
433 // connected to client 433 // connected to client
434 if ( Connected == state ) 434 if ( Connected == state )
435 return; 435 return;
436 436
437 // waiting for user name 437 // waiting for user name
438 if ( Wait_USER == state ) { 438 if ( Wait_USER == state ) {
439 439
440 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) { 440 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) {
441 send( "530 Please login with USER and PASS" ); // No tr 441 send( "530 Please login with USER and PASS" ); // No tr
442 return; 442 return;
443 } 443 }
444 send( "331 User name ok, need password" ); // No tr 444 send( "331 User name ok, need password" ); // No tr
445 state = Wait_PASS; 445 state = Wait_PASS;
446 return; 446 return;
447 } 447 }
448 448
449 // waiting for password 449 // waiting for password
450 if ( Wait_PASS == state ) { 450 if ( Wait_PASS == state ) {
451 451
452 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) { 452 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) {
453 send( "530 Please login with USER and PASS" ); // No tr 453 send( "530 Please login with USER and PASS" ); // No tr
454 return; 454 return;
455 } 455 }
456 send( "230 User logged in, proceed" ); // No tr 456 send( "230 User logged in, proceed" ); // No tr
457 state = Ready; 457 state = Ready;
458 return; 458 return;
459 } 459 }
460 460
461 // ACCESS CONTROL COMMANDS 461 // ACCESS CONTROL COMMANDS
462 462
463 // Only an ALLO sent immediately before STOR is valid. 463 // Only an ALLO sent immediately before STOR is valid.
464 if ( cmd != "STOR" ) 464 if ( cmd != "STOR" )
465 storFileSize = -1; 465 storFileSize = -1;
466 466
467 // account (ACCT) 467 // account (ACCT)
468 if ( cmd == "ACCT" ) { 468 if ( cmd == "ACCT" ) {
469 // even wu-ftp does not support it 469 // even wu-ftp does not support it
470 send( "502 Command not implemented" ); // No tr 470 send( "502 Command not implemented" ); // No tr
471 } 471 }
472 472
473 // change working directory (CWD) 473 // change working directory (CWD)
474 else if ( cmd == "CWD" ) { 474 else if ( cmd == "CWD" ) {
475 475
476 if ( !args.isEmpty() ) { 476 if ( !args.isEmpty() ) {
477 if ( directory.cd( args, TRUE ) ) 477 if ( directory.cd( args, TRUE ) )
478 send( "250 Requested file action okay, completed" ); // No tr 478 send( "250 Requested file action okay, completed" ); // No tr
479 else 479 else
480 send( "550 Requested action not taken" ); // No tr 480 send( "550 Requested action not taken" ); // No tr
481 } 481 }
482 else 482 else
483 send( "500 Syntax error, command unrecognized" ); // No tr 483 send( "500 Syntax error, command unrecognized" ); // No tr
484 } 484 }
485 485
486 // change to parent directory (CDUP) 486 // change to parent directory (CDUP)
487 else if ( cmd == "CDUP" ) { 487 else if ( cmd == "CDUP" ) {
488 if ( directory.cdUp() ) 488 if ( directory.cdUp() )
489 send( "250 Requested file action okay, completed" ); // No tr 489 send( "250 Requested file action okay, completed" ); // No tr
490 else 490 else
491 send( "550 Requested action not taken" ); // No tr 491 send( "550 Requested action not taken" ); // No tr
492 } 492 }
493 493
494 // structure mount (SMNT) 494 // structure mount (SMNT)
495 else if ( cmd == "SMNT" ) { 495 else if ( cmd == "SMNT" ) {
496 // even wu-ftp does not support it 496 // even wu-ftp does not support it
497 send( "502 Command not implemented" ); // No tr 497 send( "502 Command not implemented" ); // No tr
498 } 498 }
499 499
500 // reinitialize (REIN) 500 // reinitialize (REIN)
501 else if ( cmd == "REIN" ) { 501 else if ( cmd == "REIN" ) {
502 // even wu-ftp does not support it 502 // even wu-ftp does not support it
503 send( "502 Command not implemented" ); // No tr 503 send( "502 Command not implemented" ); // No tr
504 } 504 }
505 505
506 506
507 // TRANSFER PARAMETER COMMANDS 507 // TRANSFER PARAMETER COMMANDS
508 508
509 509
510 // data port (PORT) 510 // data port (PORT)
511 else if ( cmd == "PORT" ) { 511 else if ( cmd == "PORT" ) {
512 if ( parsePort( arg ) ) 512 if ( parsePort( arg ) )
513 send( "200 Command okay" ); // No tr 513 send( "200 Command okay" ); // No tr
514 else 514 else
515 send( "500 Syntax error, command unrecognized" ); // No tr 515 send( "500 Syntax error, command unrecognized" ); // No tr
516 } 516 }
517 517
518 // passive (PASV) 518 // passive (PASV)
519 else if ( cmd == "PASV" ) { 519 else if ( cmd == "PASV" ) {
520 passiv = TRUE; 520 passiv = TRUE;
521 send( "227 Entering Passive Mode (" // No tr 521 send( "227 Entering Passive Mode (" // No tr
522 + address().toString().replace( QRegExp( "\\." ), "," ) + "," 522 + address().toString().replace( QRegExp( "\\." ), "," ) + ","
523 + QString::number( ( serversocket->port() ) >> 8 ) + "," 523 + QString::number( ( serversocket->port() ) >> 8 ) + ","
524 + QString::number( ( serversocket->port() ) & 0xFF ) +")" ); 524 + QString::number( ( serversocket->port() ) & 0xFF ) +")" );
525 } 525 }
526 526
527 // representation type (TYPE) 527 // representation type (TYPE)
528 else if ( cmd == "TYPE" ) { 528 else if ( cmd == "TYPE" ) {
529 if ( arg.upper() == "A" || arg.upper() == "I" ) 529 if ( arg.upper() == "A" || arg.upper() == "I" )
530 send( "200 Command okay" ); // No tr 530 send( "200 Command okay" ); // No tr
531 else 531 else
532 send( "504 Command not implemented for that parameter" ); // No tr 532 send( "504 Command not implemented for that parameter" ); // No tr
533 } 533 }
534 534
535 // file structure (STRU) 535 // file structure (STRU)
536 else if ( cmd == "STRU" ) { 536 else if ( cmd == "STRU" ) {
537 if ( arg.upper() == "F" ) 537 if ( arg.upper() == "F" )
538 send( "200 Command okay" ); // No tr 538 send( "200 Command okay" ); // No tr
539 else 539 else
540 send( "504 Command not implemented for that parameter" ); // No tr 540 send( "504 Command not implemented for that parameter" ); // No tr
541 } 541 }
542 542
543 // transfer mode (MODE) 543 // transfer mode (MODE)
544 else if ( cmd == "MODE" ) { 544 else if ( cmd == "MODE" ) {
545 if ( arg.upper() == "S" ) 545 if ( arg.upper() == "S" )
546 send( "200 Command okay" ); // No tr 546 send( "200 Command okay" ); // No tr
547 else 547 else
548 send( "504 Command not implemented for that parameter" ); // No tr 548 send( "504 Command not implemented for that parameter" ); // No tr
549 } 549 }
550 550
551 551
552 // FTP SERVICE COMMANDS 552 // FTP SERVICE COMMANDS
553 553
554 554
555 // retrieve (RETR) 555 // retrieve (RETR)
556 else if ( cmd == "RETR" ) 556 else if ( cmd == "RETR" )
557 if ( !args.isEmpty() && checkReadFile( absFilePath( args ) ) 557 if ( !args.isEmpty() && checkReadFile( absFilePath( args ) )
558 || backupRestoreGzip( absFilePath( args ) ) ) { 558 || backupRestoreGzip( absFilePath( args ) ) ) {
559 send( "150 File status okay" ); // No tr 559 send( "150 File status okay" ); // No tr
560 sendFile( absFilePath( args ) ); 560 sendFile( absFilePath( args ) );
561 } 561 }
562 else { 562 else {
563 qDebug("550 Requested action not taken"); 563 qDebug("550 Requested action not taken");
564 send( "550 Requested action not taken" ); // No tr 564 send( "550 Requested action not taken" ); // No tr
565 } 565 }
566 566
567 // store (STOR) 567 // store (STOR)
568 else if ( cmd == "STOR" ) 568 else if ( cmd == "STOR" )
569 if ( !args.isEmpty() && checkWriteFile( absFilePath( args ) ) ) { 569 if ( !args.isEmpty() && checkWriteFile( absFilePath( args ) ) ) {
570 send( "150 File status okay" ); // No tr 570 send( "150 File status okay" ); // No tr
571 retrieveFile( absFilePath( args ) ); 571 retrieveFile( absFilePath( args ) );
572 } 572 }
573 else 573 else
574 send( "550 Requested action not taken" ); // No tr 574 send( "550 Requested action not taken" ); // No tr
575 575
576 // store unique (STOU) 576 // store unique (STOU)
577 else if ( cmd == "STOU" ) { 577 else if ( cmd == "STOU" ) {
578 send( "502 Command not implemented" ); // No tr 578 send( "502 Command not implemented" ); // No tr
579 } 579 }
580 580
581 // append (APPE) 581 // append (APPE)
582 else if ( cmd == "APPE" ) { 582 else if ( cmd == "APPE" ) {
583 send( "502 Command not implemented" ); // No tr 583 send( "502 Command not implemented" ); // No tr
584 } 584 }
585 585
586 // allocate (ALLO) 586 // allocate (ALLO)
587 else if ( cmd == "ALLO" ) { 587 else if ( cmd == "ALLO" ) {
588 storFileSize = args.toInt(); 588 storFileSize = args.toInt();
589 send( "200 Command okay" ); // No tr 589 send( "200 Command okay" ); // No tr
590 } 590 }
591 591
592 // restart (REST) 592 // restart (REST)
593 else if ( cmd == "REST" ) { 593 else if ( cmd == "REST" ) {
594 send( "502 Command not implemented" ); // No tr 594 send( "502 Command not implemented" ); // No tr
595 } 595 }
596 596
597 // rename from (RNFR) 597 // rename from (RNFR)
598 else if ( cmd == "RNFR" ) { 598 else if ( cmd == "RNFR" ) {
599 renameFrom = QString::null; 599 renameFrom = QString::null;
600 if ( args.isEmpty() ) 600 if ( args.isEmpty() )
601 send( "500 Syntax error, command unrecognized" ); // No tr 601 send( "500 Syntax error, command unrecognized" ); // No tr
602 else { 602 else {
603 QFile file( absFilePath( args ) ); 603 QFile file( absFilePath( args ) );
604 if ( file.exists() ) { 604 if ( file.exists() ) {
605 send( "350 File exists, ready for destination name" ); // No tr 605 send( "350 File exists, ready for destination name" ); // No tr
606 renameFrom = absFilePath( args ); 606 renameFrom = absFilePath( args );
607 } 607 }
608 else 608 else
609 send( "550 Requested action not taken" ); // No tr 609 send( "550 Requested action not taken" ); // No tr