summaryrefslogtreecommitdiff
authorzecke <zecke>2004-12-20 21:58:55 (UTC)
committer zecke <zecke>2004-12-20 21:58:55 (UTC)
commit5f35158ba0e7c2813768aaab6d6ad478dc0271a1 (patch) (unidiff)
treea4d6e8000e14ecd4e48ffee18fba733f78fbd0a7
parent7479e7ac142eb830329fb08f16179bb3aca642e5 (diff)
downloadopie-5f35158ba0e7c2813768aaab6d6ad478dc0271a1.zip
opie-5f35158ba0e7c2813768aaab6d6ad478dc0271a1.tar.gz
opie-5f35158ba0e7c2813768aaab6d6ad478dc0271a1.tar.bz2
Restore lost change
-Kill Config instance in different scope for the same file -Work when a ftp client sends -la in a listdir request
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/transferserver.cpp10
1 files changed, 7 insertions, 3 deletions
diff --git a/core/launcher/transferserver.cpp b/core/launcher/transferserver.cpp
index 1d4ca40..2b2e435 100644
--- a/core/launcher/transferserver.cpp
+++ b/core/launcher/transferserver.cpp
@@ -107,406 +107,407 @@ QString SyncAuthentication::ownerName()
107 Contact c; 107 Contact c;
108 c = Contact::readVCard( vfilename )[0]; 108 c = Contact::readVCard( vfilename )[0];
109 return c.fullName(); 109 return c.fullName();
110 } 110 }
111 111
112 return QString::null; 112 return QString::null;
113} 113}
114 114
115QString SyncAuthentication::loginName() 115QString SyncAuthentication::loginName()
116{ 116{
117 struct passwd *pw = 0L; 117 struct passwd *pw = 0L;
118#ifndef Q_OS_WIN32 118#ifndef Q_OS_WIN32
119 pw = getpwuid( geteuid() ); 119 pw = getpwuid( geteuid() );
120 return QString::fromLocal8Bit( pw->pw_name ); 120 return QString::fromLocal8Bit( pw->pw_name );
121#else 121#else
122 //### revise 122 //### revise
123 return QString(); 123 return QString();
124#endif 124#endif
125} 125}
126 126
127int SyncAuthentication::isAuthorized(QHostAddress peeraddress) 127int SyncAuthentication::isAuthorized(QHostAddress peeraddress)
128{ 128{
129 Config cfg("Security"); 129 Config cfg("Security");
130 cfg.setGroup("Sync"); 130 cfg.setGroup("Sync");
131 // QString allowedstr = cfg.readEntry("auth_peer","192.168.1.0"); 131 // QString allowedstr = cfg.readEntry("auth_peer","192.168.1.0");
132 uint auth_peer = cfg.readNumEntry("auth_peer", 0xc0a80100); 132 uint auth_peer = cfg.readNumEntry("auth_peer", 0xc0a80100);
133 133
134 // QHostAddress allowed; 134 // QHostAddress allowed;
135 // allowed.setAddress(allowedstr); 135 // allowed.setAddress(allowedstr);
136 // uint auth_peer = allowed.ip4Addr(); 136 // uint auth_peer = allowed.ip4Addr();
137 uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits", 24); 137 uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits", 24);
138 uint mask = auth_peer_bits >= 32 // shifting by 32 is not defined 138 uint mask = auth_peer_bits >= 32 // shifting by 32 is not defined
139 ? 0xffffffff : (((1 << auth_peer_bits) - 1) << (32 - auth_peer_bits)); 139 ? 0xffffffff : (((1 << auth_peer_bits) - 1) << (32 - auth_peer_bits));
140 140
141 return (peeraddress.ip4Addr() & mask) == auth_peer; 141 return (peeraddress.ip4Addr() & mask) == auth_peer;
142} 142}
143 143
144bool SyncAuthentication::checkUser( const QString& user ) 144bool SyncAuthentication::checkUser( const QString& user )
145{ 145{
146 if ( user.isEmpty() ) return FALSE; 146 if ( user.isEmpty() ) return FALSE;
147 QString euser = loginName(); 147 QString euser = loginName();
148 return user == euser; 148 return user == euser;
149} 149}
150 150
151bool SyncAuthentication::checkPassword( const QString& password ) 151bool SyncAuthentication::checkPassword( const QString& password )
152{ 152{
153#ifdef ALLOW_UNIX_USER_FTP 153#ifdef ALLOW_UNIX_USER_FTP
154 // First, check system password... 154 // First, check system password...
155 155
156 struct passwd *pw = 0; 156 struct passwd *pw = 0;
157 struct spwd *spw = 0; 157 struct spwd *spw = 0;
158 158
159 pw = getpwuid( geteuid() ); 159 pw = getpwuid( geteuid() );
160 spw = getspnam( pw->pw_name ); 160 spw = getspnam( pw->pw_name );
161 161
162 QString cpwd = QString::fromLocal8Bit( pw->pw_passwd ); 162 QString cpwd = QString::fromLocal8Bit( pw->pw_passwd );
163 if ( cpwd == "x" && spw ) 163 if ( cpwd == "x" && spw )
164 cpwd = QString::fromLocal8Bit( spw->sp_pwdp ); 164 cpwd = QString::fromLocal8Bit( spw->sp_pwdp );
165 165
166 // Note: some systems use more than crypt for passwords. 166 // Note: some systems use more than crypt for passwords.
167 QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) ); 167 QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) );
168 if ( cpwd == cpassword ) 168 if ( cpwd == cpassword )
169 return TRUE; 169 return TRUE;
170#endif 170#endif
171 171
172 static int lastdenial=0; 172 static int lastdenial=0;
173 static int denials=0; 173 static int denials=0;
174 int now = time(0); 174 int now = time(0);
175 175
176 Config cfg("Security"); 176 Config cfg("Security");
177 cfg.setGroup("SyncMode"); 177 cfg.setGroup("SyncMode");
178 int mode = cfg.readNumEntry("Mode", 0x02 ); 178 int mode = cfg.readNumEntry("Mode", 0x02 );
179 179
180 //No pass word needed if the user really needs it 180 //No pass word needed if the user really needs it
181 if (mode & 0x04) { 181 if (mode & 0x04) {
182 QMessageBox unauth( 182 QMessageBox unauth(
183 tr("Sync Connection"), 183 tr("Sync Connection"),
184 tr("<qt><p>An unauthorized system is requesting access to this device." 184 tr("<qt><p>An unauthorized system is requesting access to this device."
185 "<p>You chose IntelliSync so you may I allow or deny this connection.</qt>" ), 185 "<p>You chose IntelliSync so you may I allow or deny this connection.</qt>" ),
186 QMessageBox::Warning, 186 QMessageBox::Warning,
187 QMessageBox::Ok, QMessageBox::Cancel|QMessageBox::Default, QMessageBox::NoButton, 187 QMessageBox::Ok, QMessageBox::Cancel|QMessageBox::Default, QMessageBox::NoButton,
188 0, QString::null, TRUE, WStyle_StaysOnTop); 188 0, QString::null, TRUE, WStyle_StaysOnTop);
189 unauth.setButtonText(QMessageBox::Ok, tr("Allow" ) ); 189 unauth.setButtonText(QMessageBox::Ok, tr("Allow" ) );
190 unauth.setButtonText(QMessageBox::Cancel, tr("Deny")); 190 unauth.setButtonText(QMessageBox::Cancel, tr("Deny"));
191 switch( unauth.exec() ) { 191 switch( unauth.exec() ) {
192 case QMessageBox::Ok: 192 case QMessageBox::Ok:
193 return TRUE; 193 return TRUE;
194 break; 194 break;
195 case QMessageBox::Cancel: 195 case QMessageBox::Cancel:
196 default: 196 default:
197 denials++; 197 denials++;
198 lastdenial=now; 198 lastdenial=now;
199 return FALSE; 199 return FALSE;
200 } 200 }
201 } 201 }
202 202
203 // Detect old Qtopia Desktop (no password) and fail 203 // Detect old Qtopia Desktop (no password) and fail
204 if ( password.isEmpty() ) { 204 if ( password.isEmpty() ) {
205 if ( denials < 3 || now > lastdenial+600 ) { 205 if ( denials < 3 || now > lastdenial+600 ) {
206 QMessageBox unauth( 206 QMessageBox unauth(
207 tr("Sync Connection"), 207 tr("Sync Connection"),
208 tr("<p>An unauthorized system is requesting access to this device." 208 tr("<p>An unauthorized system is requesting access to this device."
209 "<p>If you are using a version of Qtopia Desktop older than 1.5.1, " 209 "<p>If you are using a version of Qtopia Desktop older than 1.5.1, "
210 "please upgrade or change the security setting to use IntelliSync." ), 210 "please upgrade or change the security setting to use IntelliSync." ),
211 QMessageBox::Warning, 211 QMessageBox::Warning,
212 QMessageBox::Cancel, QMessageBox::NoButton, QMessageBox::NoButton, 212 QMessageBox::Cancel, QMessageBox::NoButton, QMessageBox::NoButton,
213 0, QString::null, TRUE, WStyle_StaysOnTop); 213 0, QString::null, TRUE, WStyle_StaysOnTop);
214 unauth.setButtonText(QMessageBox::Cancel, tr("Deny")); 214 unauth.setButtonText(QMessageBox::Cancel, tr("Deny"));
215 unauth.exec(); 215 unauth.exec();
216 216
217 denials++; 217 denials++;
218 lastdenial=now; 218 lastdenial=now;
219 } 219 }
220 return FALSE; 220 return FALSE;
221 221
222 } 222 }
223 223
224 // Second, check sync password... 224 // Second, check sync password...
225 225
226 static int lock=0; 226 static int lock=0;
227 if ( lock ) return FALSE; 227 if ( lock ) return FALSE;
228 228
229 ++lock; 229 ++lock;
230 230
231 /* 231 /*
232 * we need to support old Sync software and QtopiaDesktop 232 * we need to support old Sync software and QtopiaDesktop
233 */ 233 */
234 if ( password.left(6) == "Qtopia" || password.left(6) == "rootme" ) { 234 if ( password.left(6) == "Qtopia" || password.left(6) == "rootme" ) {
235 Config cfg( "Security" );
236 cfg.setGroup("Sync"); 235 cfg.setGroup("Sync");
237 QStringList pwds = cfg.readListEntry("Passwords",' '); 236 QStringList pwds = cfg.readListEntry("Passwords",' ');
238 for (QStringList::ConstIterator it=pwds.begin(); it!=pwds.end(); ++it) { 237 for (QStringList::ConstIterator it=pwds.begin(); it!=pwds.end(); ++it) {
239#ifndef Q_OS_WIN32 238#ifndef Q_OS_WIN32
240 QString cpassword = QString::fromLocal8Bit( 239 QString cpassword = QString::fromLocal8Bit(
241 crypt( password.mid(8).local8Bit(), (*it).left(2).latin1() ) ); 240 crypt( password.mid(8).local8Bit(), (*it).left(2).latin1() ) );
242#else 241#else
243 // ### revise 242 // ### revise
244 QString cpassword(""); 243 QString cpassword("");
245#endif 244#endif
246 if ( *it == cpassword ) { 245 if ( *it == cpassword ) {
247 lock--; 246 lock--;
248 return TRUE; 247 return TRUE;
249 } 248 }
250 } 249 }
251 250
252 // Unrecognized system. Be careful... 251 // Unrecognized system. Be careful...
253 QMessageBox unrecbox( 252 QMessageBox unrecbox(
254 tr("Sync Connection"), 253 tr("Sync Connection"),
255 tr( "<p>An unrecognized system is requesting access to this device." 254 tr( "<p>An unrecognized system is requesting access to this device."
256 "<p>If you have just initiated a Sync for the first time, this is normal."), 255 "<p>If you have just initiated a Sync for the first time, this is normal."),
257 QMessageBox::Warning, 256 QMessageBox::Warning,
258 QMessageBox::Cancel, QMessageBox::Yes, QMessageBox::NoButton, 257 QMessageBox::Cancel, QMessageBox::Yes, QMessageBox::NoButton,
259 0, QString::null, TRUE, WStyle_StaysOnTop); 258 0, QString::null, TRUE, WStyle_StaysOnTop);
260 unrecbox.setButtonText(QMessageBox::Cancel, tr("Deny")); 259 unrecbox.setButtonText(QMessageBox::Cancel, tr("Deny"));
261 unrecbox.setButtonText(QMessageBox::Yes, tr("Allow")); 260 unrecbox.setButtonText(QMessageBox::Yes, tr("Allow"));
262 261
263 if ( (denials > 2 && now < lastdenial+600) 262 if ( (denials > 2 && now < lastdenial+600)
264 || unrecbox.exec() != QMessageBox::Yes) 263 || unrecbox.exec() != QMessageBox::Yes)
265 { 264 {
266 denials++; 265 denials++;
267 lastdenial=now; 266 lastdenial=now;
268 lock--; 267 lock--;
269 return FALSE; 268 return FALSE;
270 } else { 269 } else {
271 const char salty[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/."; 270 const char salty[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/.";
272 char salt[2]; 271 char salt[2];
273 salt[0]= salty[rand() % (sizeof(salty)-1)]; 272 salt[0]= salty[rand() % (sizeof(salty)-1)];
274 salt[1]= salty[rand() % (sizeof(salty)-1)]; 273 salt[1]= salty[rand() % (sizeof(salty)-1)];
275#ifndef Q_OS_WIN32 274#ifndef Q_OS_WIN32
276 QString cpassword = QString::fromLocal8Bit( 275 QString cpassword = QString::fromLocal8Bit(
277 crypt( password.mid(8).local8Bit(), salt ) ); 276 crypt( password.mid(8).local8Bit(), salt ) );
278#else 277#else
279 //### revise 278 //### revise
280 QString cpassword(""); 279 QString cpassword("");
281#endif 280#endif
282 denials=0; 281 denials=0;
283 pwds.prepend(cpassword); 282 pwds.prepend(cpassword);
284 cfg.writeEntry("Passwords",pwds,' '); 283 cfg.writeEntry("Passwords",pwds,' ');
285 lock--; 284 lock--;
286 return TRUE; 285 return TRUE;
287 } 286 }
288 } 287 }
289 lock--; 288 lock--;
290 289
291 return FALSE; 290 return FALSE;
292} 291}
293 292
294 293
295ServerPI::ServerPI( int socket, QObject *parent, const char* name ) 294ServerPI::ServerPI( int socket, QObject *parent, const char* name )
296 : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 ), 295 : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 ),
297 storFileSize(-1) 296 storFileSize(-1)
298{ 297{
299 state = Connected; 298 state = Connected;
300 299
301 setSocket( socket ); 300 setSocket( socket );
302 301
303 peerport = peerPort(); 302 peerport = peerPort();
304 peeraddress = peerAddress(); 303 peeraddress = peerAddress();
305 304
306#ifndef INSECURE 305#ifndef INSECURE
307 if ( !SyncAuthentication::isAuthorized(peeraddress) ) { 306 if ( !SyncAuthentication::isAuthorized(peeraddress) ) {
308 state = Forbidden; 307 state = Forbidden;
309 startTimer( 0 ); 308 startTimer( 0 );
310 } else 309 } else
311#endif 310#endif
312 { 311 {
313 connect( this, SIGNAL( readyRead() ), SLOT( read() ) ); 312 connect( this, SIGNAL( readyRead() ), SLOT( read() ) );
314 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) ); 313 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) );
315 314
316 passiv = FALSE; 315 passiv = FALSE;
317 for( int i = 0; i < 4; i++ ) 316 for( int i = 0; i < 4; i++ )
318 wait[i] = FALSE; 317 wait[i] = FALSE;
319 318
320 send( "220 Qtopia " QPE_VERSION " FTP Server" ); // No tr 319 send( "220 Qtopia " QPE_VERSION " FTP Server" ); // No tr
321 state = Wait_USER; 320 state = Wait_USER;
322 321
323 dtp = new ServerDTP( this ); 322 dtp = new ServerDTP( this );
324 connect( dtp, SIGNAL( completed() ), SLOT( dtpCompleted() ) ); 323 connect( dtp, SIGNAL( completed() ), SLOT( dtpCompleted() ) );
325 connect( dtp, SIGNAL( failed() ), SLOT( dtpFailed() ) ); 324 connect( dtp, SIGNAL( failed() ), SLOT( dtpFailed() ) );
326 connect( dtp, SIGNAL( error(int) ), SLOT( dtpError(int) ) ); 325 connect( dtp, SIGNAL( error(int) ), SLOT( dtpError(int) ) );
327 326
328 327
329 directory = QDir::currentDirPath(); 328 directory = QDir::currentDirPath();
330 329
331 static int p = 1024; 330 static int p = 1024;
332 331
333 while ( !serversocket || !serversocket->ok() ) { 332 while ( !serversocket || !serversocket->ok() ) {
334 delete serversocket; 333 delete serversocket;
335 serversocket = new ServerSocket( ++p, this ); 334 serversocket = new ServerSocket( ++p, this );
336 } 335 }
337 connect( serversocket, SIGNAL( newIncomming(int) ), 336 connect( serversocket, SIGNAL( newIncomming(int) ),
338 SLOT( newConnection(int) ) ); 337 SLOT( newConnection(int) ) );
339 } 338 }
340} 339}
341 340
342ServerPI::~ServerPI() 341ServerPI::~ServerPI()
343{ 342{
344 close(); 343 close();
345 344
346 if ( dtp ) 345 if ( dtp )
347 dtp->close(); 346 dtp->close();
348 delete dtp; 347 delete dtp;
349 delete serversocket; 348 delete serversocket;
350} 349}
351 350
352bool ServerPI::verifyAuthorised() 351bool ServerPI::verifyAuthorised()
353{ 352{
354 if ( !SyncAuthentication::isAuthorized(peerAddress()) ) { 353 if ( !SyncAuthentication::isAuthorized(peerAddress()) ) {
355 state = Forbidden; 354 state = Forbidden;
356 return FALSE; 355 return FALSE;
357 } 356 }
358 return TRUE; 357 return TRUE;
359} 358}
360 359
361void ServerPI::connectionClosed() 360void ServerPI::connectionClosed()
362{ 361{
363 // odebug << "Debug: Connection closed" << oendl; 362 // odebug << "Debug: Connection closed" << oendl;
364 emit connectionClosed(this); 363 emit connectionClosed(this);
365} 364}
366 365
367void ServerPI::send( const QString& msg ) 366void ServerPI::send( const QString& msg )
368{ 367{
369 QTextStream os( this ); 368 QTextStream os( this );
370 os << msg << endl; 369 os << msg << endl;
371 //odebug << "Reply: " << msg << "" << oendl; 370 //odebug << "Reply: " << msg << "" << oendl;
372} 371}
373 372
374void ServerPI::read() 373void ServerPI::read()
375{ 374{
376 while ( canReadLine() ) 375 while ( canReadLine() )
377 process( readLine().stripWhiteSpace() ); 376 process( readLine().stripWhiteSpace() );
378} 377}
379 378
380bool ServerPI::checkReadFile( const QString& file ) 379bool ServerPI::checkReadFile( const QString& file )
381{ 380{
382 QString filename; 381 QString filename;
383 382
384 if ( file[0] != "/" ) 383 if ( file.length() == 1 && file[0] == "/" )
384 filename = file;
385 else if ( file[0] != "/" )
385 filename = directory.path() + "/" + file; 386 filename = directory.path() + "/" + file;
386 else 387 else
387 filename = file; 388 filename = file;
388 389
389 QFileInfo fi( filename ); 390 QFileInfo fi( filename );
390 return ( fi.exists() && fi.isReadable() ); 391 return ( fi.exists() && fi.isReadable() );
391} 392}
392 393
393bool ServerPI::checkWriteFile( const QString& file ) 394bool ServerPI::checkWriteFile( const QString& file )
394{ 395{
395 QString filename; 396 QString filename;
396 397
397 if ( file[0] != "/" ) 398 if ( file[0] != "/" )
398 filename = directory.path() + "/" + file; 399 filename = directory.path() + "/" + file;
399 else 400 else
400 filename = file; 401 filename = file;
401 402
402 QFileInfo fi( filename ); 403 QFileInfo fi( filename );
403 404
404 if ( fi.exists() ) 405 if ( fi.exists() )
405 if ( !QFile( filename ).remove() ) 406 if ( !QFile( filename ).remove() )
406 return FALSE; 407 return FALSE;
407 return TRUE; 408 return TRUE;
408} 409}
409 410
410void ServerPI::process( const QString& message ) 411void ServerPI::process( const QString& message )
411{ 412{
412 //odebug << "Command: " << message << "" << oendl; 413 //odebug << "Command: " << message << "" << oendl;
413 414
414 // split message using "," as separator 415 // split message using "," as separator
415 QStringList msg = QStringList::split( " ", message ); 416 QStringList msg = QStringList::split( " ", message );
416 if ( msg.isEmpty() ) return; 417 if ( msg.isEmpty() ) return;
417 418
418 // command token 419 // command token
419 QString cmd = msg[0].upper(); 420 QString cmd = msg[0].upper();
420 421
421 // argument token 422 // argument token
422 QString arg; 423 QString arg;
423 if ( msg.count() >= 2 ) 424 if ( msg.count() >= 2 )
424 arg = msg[1]; 425 arg = msg[1];
425 426
426 // full argument string 427 // full argument string
427 QString args; 428 QString args;
428 if ( msg.count() >= 2 ) { 429 if ( msg.count() >= 2 ) {
429 QStringList copy( msg ); 430 QStringList copy( msg );
430 // FIXME: for Qt3 431 // FIXME: for Qt3
431 // copy.pop_front() 432 // copy.pop_front()
432 copy.remove( copy.begin() ); 433 copy.remove( copy.begin() );
433 args = copy.join( " " ); 434 args = copy.join( " " );
434 } 435 }
435 436
436 //odebug << "args: " << args << "" << oendl; 437 //odebug << "args: " << args << "" << oendl;
437 438
438 // we always respond to QUIT, regardless of state 439 // we always respond to QUIT, regardless of state
439 if ( cmd == "QUIT" ) { 440 if ( cmd == "QUIT" ) {
440 send( "211 Good bye!" ); // No tr 441 send( "211 Good bye!" ); // No tr
441 close(); 442 close();
442 return; 443 return;
443 } 444 }
444 445
445 // connected to client 446 // connected to client
446 if ( Connected == state ) 447 if ( Connected == state )
447 return; 448 return;
448 449
449 // waiting for user name 450 // waiting for user name
450 if ( Wait_USER == state ) { 451 if ( Wait_USER == state ) {
451 452
452 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) { 453 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) {
453 send( "530 Please login with USER and PASS" ); // No tr 454 send( "530 Please login with USER and PASS" ); // No tr
454 return; 455 return;
455 } 456 }
456 send( "331 User name ok, need password" ); // No tr 457 send( "331 User name ok, need password" ); // No tr
457 state = Wait_PASS; 458 state = Wait_PASS;
458 return; 459 return;
459 } 460 }
460 461
461 // waiting for password 462 // waiting for password
462 if ( Wait_PASS == state ) { 463 if ( Wait_PASS == state ) {
463 464
464 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) { 465 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) {
465 send( "530 Please login with USER and PASS" ); // No tr 466 send( "530 Please login with USER and PASS" ); // No tr
466 return; 467 return;
467 } 468 }
468 send( "230 User logged in, proceed" ); // No tr 469 send( "230 User logged in, proceed" ); // No tr
469 state = Ready; 470 state = Ready;
470 return; 471 return;
471 } 472 }
472 473
473 // ACCESS CONTROL COMMANDS 474 // ACCESS CONTROL COMMANDS
474 475
475 // Only an ALLO sent immediately before STOR is valid. 476 // Only an ALLO sent immediately before STOR is valid.
476 if ( cmd != "STOR" ) 477 if ( cmd != "STOR" )
477 storFileSize = -1; 478 storFileSize = -1;
478 479
479 // account (ACCT) 480 // account (ACCT)
480 if ( cmd == "ACCT" ) { 481 if ( cmd == "ACCT" ) {
481 // even wu-ftp does not support it 482 // even wu-ftp does not support it
482 send( "502 Command not implemented" ); // No tr 483 send( "502 Command not implemented" ); // No tr
483 } 484 }
484 485
485 // change working directory (CWD) 486 // change working directory (CWD)
486 else if ( cmd == "CWD" ) { 487 else if ( cmd == "CWD" ) {
487 488
488 if ( !args.isEmpty() ) { 489 if ( !args.isEmpty() ) {
489 if ( directory.cd( args, TRUE ) ) 490 if ( directory.cd( args, TRUE ) )
490 send( "250 Requested file action okay, completed" ); // No tr 491 send( "250 Requested file action okay, completed" ); // No tr
491 else 492 else
492 send( "550 Requested action not taken" ); // No tr 493 send( "550 Requested action not taken" ); // No tr
493 } 494 }
494 else 495 else
495 send( "500 Syntax error, command unrecognized" ); // No tr 496 send( "500 Syntax error, command unrecognized" ); // No tr
496 } 497 }
497 498
498 // change to parent directory (CDUP) 499 // change to parent directory (CDUP)
499 else if ( cmd == "CDUP" ) { 500 else if ( cmd == "CDUP" ) {
500 if ( directory.cdUp() ) 501 if ( directory.cdUp() )
501 send( "250 Requested file action okay, completed" ); // No tr 502 send( "250 Requested file action okay, completed" ); // No tr
502 else 503 else
503 send( "550 Requested action not taken" ); // No tr 504 send( "550 Requested action not taken" ); // No tr
504 } 505 }
505 506
506 // structure mount (SMNT) 507 // structure mount (SMNT)
507 else if ( cmd == "SMNT" ) { 508 else if ( cmd == "SMNT" ) {
508 // even wu-ftp does not support it 509 // even wu-ftp does not support it
509 send( "502 Command not implemented" ); // No tr 510 send( "502 Command not implemented" ); // No tr
510 } 511 }
511 512
512 // reinitialize (REIN) 513 // reinitialize (REIN)
@@ -572,256 +573,259 @@ void ServerPI::process( const QString& message )
572 sendFile( absFilePath( args ) ); 573 sendFile( absFilePath( args ) );
573 } 574 }
574 else { 575 else {
575 odebug << "550 Requested action not taken" << oendl; 576 odebug << "550 Requested action not taken" << oendl;
576 send( "550 Requested action not taken" ); // No tr 577 send( "550 Requested action not taken" ); // No tr
577 } 578 }
578 579
579 // store (STOR) 580 // store (STOR)
580 else if ( cmd == "STOR" ) 581 else if ( cmd == "STOR" )
581 if ( !args.isEmpty() && checkWriteFile( absFilePath( args ) ) ) { 582 if ( !args.isEmpty() && checkWriteFile( absFilePath( args ) ) ) {
582 send( "150 File status okay" ); // No tr 583 send( "150 File status okay" ); // No tr
583 retrieveFile( absFilePath( args ) ); 584 retrieveFile( absFilePath( args ) );
584 } 585 }
585 else 586 else
586 send( "550 Requested action not taken" ); // No tr 587 send( "550 Requested action not taken" ); // No tr
587 588
588 // store unique (STOU) 589 // store unique (STOU)
589 else if ( cmd == "STOU" ) { 590 else if ( cmd == "STOU" ) {
590 send( "502 Command not implemented" ); // No tr 591 send( "502 Command not implemented" ); // No tr
591 } 592 }
592 593
593 // append (APPE) 594 // append (APPE)
594 else if ( cmd == "APPE" ) { 595 else if ( cmd == "APPE" ) {
595 send( "502 Command not implemented" ); // No tr 596 send( "502 Command not implemented" ); // No tr
596 } 597 }
597 598
598 // allocate (ALLO) 599 // allocate (ALLO)
599 else if ( cmd == "ALLO" ) { 600 else if ( cmd == "ALLO" ) {
600 storFileSize = args.toInt(); 601 storFileSize = args.toInt();
601 send( "200 Command okay" ); // No tr 602 send( "200 Command okay" ); // No tr
602 } 603 }
603 604
604 // restart (REST) 605 // restart (REST)
605 else if ( cmd == "REST" ) { 606 else if ( cmd == "REST" ) {
606 send( "502 Command not implemented" ); // No tr 607 send( "502 Command not implemented" ); // No tr
607 } 608 }
608 609
609 // rename from (RNFR) 610 // rename from (RNFR)
610 else if ( cmd == "RNFR" ) { 611 else if ( cmd == "RNFR" ) {
611 renameFrom = QString::null; 612 renameFrom = QString::null;
612 if ( args.isEmpty() ) 613 if ( args.isEmpty() )
613 send( "500 Syntax error, command unrecognized" ); // No tr 614 send( "500 Syntax error, command unrecognized" ); // No tr
614 else { 615 else {
615 QFile file( absFilePath( args ) ); 616 QFile file( absFilePath( args ) );
616 if ( file.exists() ) { 617 if ( file.exists() ) {
617 send( "350 File exists, ready for destination name" ); // No tr 618 send( "350 File exists, ready for destination name" ); // No tr
618 renameFrom = absFilePath( args ); 619 renameFrom = absFilePath( args );
619 } 620 }
620 else 621 else
621 send( "550 Requested action not taken" ); // No tr 622 send( "550 Requested action not taken" ); // No tr
622 } 623 }
623 } 624 }
624 625
625 // rename to (RNTO) 626 // rename to (RNTO)
626 else if ( cmd == "RNTO" ) { 627 else if ( cmd == "RNTO" ) {
627 if ( lastCommand != "RNFR" ) 628 if ( lastCommand != "RNFR" )
628 send( "503 Bad sequence of commands" ); // No tr 629 send( "503 Bad sequence of commands" ); // No tr
629 else if ( args.isEmpty() ) 630 else if ( args.isEmpty() )
630 send( "500 Syntax error, command unrecognized" ); // No tr 631 send( "500 Syntax error, command unrecognized" ); // No tr
631 else { 632 else {
632 QDir dir( absFilePath( args ) ); 633 QDir dir( absFilePath( args ) );
633 if ( dir.rename( renameFrom, absFilePath( args ), TRUE ) ) 634 if ( dir.rename( renameFrom, absFilePath( args ), TRUE ) )
634 send( "250 Requested file action okay, completed." ); // No tr 635 send( "250 Requested file action okay, completed." ); // No tr
635 else 636 else
636 send( "550 Requested action not taken" ); // No tr 637 send( "550 Requested action not taken" ); // No tr
637 } 638 }
638 } 639 }
639 640
640 // abort (ABOR) 641 // abort (ABOR)
641 else if ( cmd.contains( "ABOR" ) ) { 642 else if ( cmd.contains( "ABOR" ) ) {
642 dtp->close(); 643 dtp->close();
643 if ( dtp->dtpMode() != ServerDTP::Idle ) 644 if ( dtp->dtpMode() != ServerDTP::Idle )
644 send( "426 Connection closed; transfer aborted" ); // No tr 645 send( "426 Connection closed; transfer aborted" ); // No tr
645 else 646 else
646 send( "226 Closing data connection" ); // No tr 647 send( "226 Closing data connection" ); // No tr
647 } 648 }
648 649
649 // delete (DELE) 650 // delete (DELE)
650 else if ( cmd == "DELE" ) { 651 else if ( cmd == "DELE" ) {
651 if ( args.isEmpty() ) 652 if ( args.isEmpty() )
652 send( "500 Syntax error, command unrecognized" ); // No tr 653 send( "500 Syntax error, command unrecognized" ); // No tr
653 else { 654 else {
654 QFile file( absFilePath( args ) ) ; 655 QFile file( absFilePath( args ) ) ;
655 if ( file.remove() ) { 656 if ( file.remove() ) {
656 send( "250 Requested file action okay, completed" ); // No tr 657 send( "250 Requested file action okay, completed" ); // No tr
657 QCopEnvelope e("QPE/System", "linkChanged(QString)" ); 658 QCopEnvelope e("QPE/System", "linkChanged(QString)" );
658 e << file.name(); 659 e << file.name();
659 } else { 660 } else {
660 send( "550 Requested action not taken" ); // No tr 661 send( "550 Requested action not taken" ); // No tr
661 } 662 }
662 } 663 }
663 } 664 }
664 665
665 // remove directory (RMD) 666 // remove directory (RMD)
666 else if ( cmd == "RMD" ) { 667 else if ( cmd == "RMD" ) {
667 if ( args.isEmpty() ) 668 if ( args.isEmpty() )
668 send( "500 Syntax error, command unrecognized" ); // No tr 669 send( "500 Syntax error, command unrecognized" ); // No tr
669 else { 670 else {
670 QDir dir; 671 QDir dir;
671 if ( dir.rmdir( absFilePath( args ), TRUE ) ) 672 if ( dir.rmdir( absFilePath( args ), TRUE ) )
672 send( "250 Requested file action okay, completed" ); // No tr 673 send( "250 Requested file action okay, completed" ); // No tr
673 else 674 else
674 send( "550 Requested action not taken" ); // No tr 675 send( "550 Requested action not taken" ); // No tr
675 } 676 }
676 } 677 }
677 678
678 // make directory (MKD) 679 // make directory (MKD)
679 else if ( cmd == "MKD" ) { 680 else if ( cmd == "MKD" ) {
680 if ( args.isEmpty() ) { 681 if ( args.isEmpty() ) {
681 odebug << " Error: no arg" << oendl; 682 odebug << " Error: no arg" << oendl;
682 send( "500 Syntax error, command unrecognized" ); // No tr 683 send( "500 Syntax error, command unrecognized" ); // No tr
683 } 684 }
684 else { 685 else {
685 QDir dir; 686 QDir dir;
686 if ( dir.mkdir( absFilePath( args ), TRUE ) ) 687 if ( dir.mkdir( absFilePath( args ), TRUE ) )
687 send( "250 Requested file action okay, completed." ); // No tr 688 send( "250 Requested file action okay, completed." ); // No tr
688 else 689 else
689 send( "550 Requested action not taken" ); // No tr 690 send( "550 Requested action not taken" ); // No tr
690 } 691 }
691 } 692 }
692 693
693 // print working directory (PWD) 694 // print working directory (PWD)
694 else if ( cmd == "PWD" ) { 695 else if ( cmd == "PWD" ) {
695 send( "257 \"" + directory.path() +"\"" ); 696 send( "257 \"" + directory.path() +"\"" );
696 } 697 }
697 698
698 // list (LIST) 699 // list (LIST)
699 else if ( cmd == "LIST" ) { 700 else if ( cmd == "LIST" ) {
701 if ( args == "-la" )
702 args = QString::null;
703
700 if ( sendList( absFilePath( args ) ) ) 704 if ( sendList( absFilePath( args ) ) )
701 send( "150 File status okay" ); // No tr 705 send( "150 File status okay" ); // No tr
702 else 706 else
703 send( "500 Syntax error, command unrecognized" ); // No tr 707 send( "500 Syntax error, command unrecognized" ); // No tr
704 } 708 }
705 709
706 // size (SIZE) 710 // size (SIZE)
707 else if ( cmd == "SIZE" ) { 711 else if ( cmd == "SIZE" ) {
708 QString filePath = absFilePath( args ); 712 QString filePath = absFilePath( args );
709 QFileInfo fi( filePath ); 713 QFileInfo fi( filePath );
710 bool gzipfile = backupRestoreGzip( filePath ); 714 bool gzipfile = backupRestoreGzip( filePath );
711 if ( !fi.exists() && !gzipfile ) 715 if ( !fi.exists() && !gzipfile )
712 send( "500 Syntax error, command unrecognized" ); // No tr 716 send( "500 Syntax error, command unrecognized" ); // No tr
713 else { 717 else {
714 if ( !gzipfile ) 718 if ( !gzipfile )
715 send( "213 " + QString::number( fi.size() ) ); 719 send( "213 " + QString::number( fi.size() ) );
716 else { 720 else {
717 Process duproc( QString("du") ); 721 Process duproc( QString("du") );
718 duproc.addArgument("-s"); 722 duproc.addArgument("-s");
719 QString in, out; 723 QString in, out;
720 if ( !duproc.exec(in, out) ) { 724 if ( !duproc.exec(in, out) ) {
721 odebug << "du process failed; just sending back 1K" << oendl; 725 odebug << "du process failed; just sending back 1K" << oendl;
722 send( "213 1024"); 726 send( "213 1024");
723 } 727 }
724 else { 728 else {
725 QString size = out.left( out.find("\t") ); 729 QString size = out.left( out.find("\t") );
726 int guess = size.toInt()/5; 730 int guess = size.toInt()/5;
727 if ( filePath.contains("doc") ) // No tr 731 if ( filePath.contains("doc") ) // No tr
728 guess *= 1000; 732 guess *= 1000;
729 odebug << "sending back gzip guess of " << guess << "" << oendl; 733 odebug << "sending back gzip guess of " << guess << "" << oendl;
730 send( "213 " + QString::number(guess) ); 734 send( "213 " + QString::number(guess) );
731 } 735 }
732 } 736 }
733 } 737 }
734 } 738 }
735 // name list (NLST) 739 // name list (NLST)
736 else if ( cmd == "NLST" ) { 740 else if ( cmd == "NLST" ) {
737 send( "502 Command not implemented" ); // No tr 741 send( "502 Command not implemented" ); // No tr
738 } 742 }
739 743
740 // site parameters (SITE) 744 // site parameters (SITE)
741 else if ( cmd == "SITE" ) { 745 else if ( cmd == "SITE" ) {
742 send( "502 Command not implemented" ); // No tr 746 send( "502 Command not implemented" ); // No tr
743 } 747 }
744 748
745 // system (SYST) 749 // system (SYST)
746 else if ( cmd == "SYST" ) { 750 else if ( cmd == "SYST" ) {
747 send( "215 UNIX Type: L8" ); // No tr 751 send( "215 UNIX Type: L8" ); // No tr
748 } 752 }
749 753
750 // status (STAT) 754 // status (STAT)
751 else if ( cmd == "STAT" ) { 755 else if ( cmd == "STAT" ) {
752 send( "502 Command not implemented" ); // No tr 756 send( "502 Command not implemented" ); // No tr
753 } 757 }
754 758
755 // help (HELP ) 759 // help (HELP )
756 else if ( cmd == "HELP" ) { 760 else if ( cmd == "HELP" ) {
757 send( "502 Command not implemented" ); // No tr 761 send( "502 Command not implemented" ); // No tr
758 } 762 }
759 763
760 // noop (NOOP) 764 // noop (NOOP)
761 else if ( cmd == "NOOP" ) { 765 else if ( cmd == "NOOP" ) {
762 send( "200 Command okay" ); // No tr 766 send( "200 Command okay" ); // No tr
763 } 767 }
764 768
765 // not implemented 769 // not implemented
766 else 770 else
767 send( "502 Command not implemented" ); // No tr 771 send( "502 Command not implemented" ); // No tr
768 772
769 lastCommand = cmd; 773 lastCommand = cmd;
770} 774}
771 775
772bool ServerPI::backupRestoreGzip( const QString &file ) 776bool ServerPI::backupRestoreGzip( const QString &file )
773{ 777{
774 return (file.find( "backup" ) != -1 && // No tr 778 return (file.find( "backup" ) != -1 && // No tr
775 file.findRev( ".tgz" ) == (int)file.length()-4 ); 779 file.findRev( ".tgz" ) == (int)file.length()-4 );
776} 780}
777 781
778bool ServerPI::backupRestoreGzip( const QString &file, QStringList &targets ) 782bool ServerPI::backupRestoreGzip( const QString &file, QStringList &targets )
779{ 783{
780 if ( file.find( "backup" ) != -1 && // No tr 784 if ( file.find( "backup" ) != -1 && // No tr
781 file.findRev( ".tgz" ) == (int)file.length()-4 ) { 785 file.findRev( ".tgz" ) == (int)file.length()-4 ) {
782 QFileInfo info( file ); 786 QFileInfo info( file );
783 targets = info.dirPath( TRUE ); 787 targets = info.dirPath( TRUE );
784 odebug << "ServerPI::backupRestoreGzip for " << file.latin1() << " = " << targets.join(" ").latin1() << oendl; 788 odebug << "ServerPI::backupRestoreGzip for " << file.latin1() << " = " << targets.join(" ").latin1() << oendl;
785 return true; 789 return true;
786 } 790 }
787 return false; 791 return false;
788} 792}
789 793
790void ServerPI::sendFile( const QString& file ) 794void ServerPI::sendFile( const QString& file )
791{ 795{
792 if ( passiv ) { 796 if ( passiv ) {
793 wait[SendFile] = TRUE; 797 wait[SendFile] = TRUE;
794 waitfile = file; 798 waitfile = file;
795 if ( waitsocket ) 799 if ( waitsocket )
796 newConnection( waitsocket ); 800 newConnection( waitsocket );
797 } 801 }
798 else { 802 else {
799 QStringList targets; 803 QStringList targets;
800 if ( backupRestoreGzip( file, targets ) ) 804 if ( backupRestoreGzip( file, targets ) )
801 dtp->sendGzipFile( file, targets, peeraddress, peerport ); 805 dtp->sendGzipFile( file, targets, peeraddress, peerport );
802 else dtp->sendFile( file, peeraddress, peerport ); 806 else dtp->sendFile( file, peeraddress, peerport );
803 } 807 }
804} 808}
805 809
806void ServerPI::retrieveFile( const QString& file ) 810void ServerPI::retrieveFile( const QString& file )
807{ 811{
808 if ( passiv ) { 812 if ( passiv ) {
809 wait[RetrieveFile] = TRUE; 813 wait[RetrieveFile] = TRUE;
810 waitfile = file; 814 waitfile = file;
811 if ( waitsocket ) 815 if ( waitsocket )
812 newConnection( waitsocket ); 816 newConnection( waitsocket );
813 } 817 }
814 else { 818 else {
815 QStringList targets; 819 QStringList targets;
816 if ( backupRestoreGzip( file, targets ) ) 820 if ( backupRestoreGzip( file, targets ) )
817 dtp->retrieveGzipFile( file, peeraddress, peerport ); 821 dtp->retrieveGzipFile( file, peeraddress, peerport );
818 else 822 else
819 dtp->retrieveFile( file, peeraddress, peerport, storFileSize ); 823 dtp->retrieveFile( file, peeraddress, peerport, storFileSize );
820 } 824 }
821} 825}
822 826
823bool ServerPI::parsePort( const QString& pp ) 827bool ServerPI::parsePort( const QString& pp )
824{ 828{
825 QStringList p = QStringList::split( ",", pp ); 829 QStringList p = QStringList::split( ",", pp );
826 if ( p.count() != 6 ) return FALSE; 830 if ( p.count() != 6 ) return FALSE;
827 831