summaryrefslogtreecommitdiff
Unidiff
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
@@ -171,129 +171,128 @@ bool SyncAuthentication::checkPassword( const QString& password )
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;
@@ -319,130 +318,132 @@ ServerPI::ServerPI( int socket, QObject *parent, const char* name )
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
@@ -636,128 +637,131 @@ void ServerPI::process( const QString& message )
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 }