summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/qws/transferserver.cpp1
1 files changed, 1 insertions, 0 deletions
diff --git a/core/qws/transferserver.cpp b/core/qws/transferserver.cpp
index 7bf6719..42ac917 100644
--- a/core/qws/transferserver.cpp
+++ b/core/qws/transferserver.cpp
@@ -1,414 +1,415 @@
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 20
21/* OPIE */ 21/* OPIE */
22#include <opie2/odebug.h> 22#include <opie2/odebug.h>
23 23
24/* STD */ 24/* STD */
25#define _XOPEN_SOURCE 25#define _XOPEN_SOURCE
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 <crypt.h>
31 32
32#ifndef Q_OS_MACX 33#ifndef Q_OS_MACX
33#include <shadow.h> 34#include <shadow.h>
34#endif /* Q_OS_MACX */ 35#endif /* Q_OS_MACX */
35 36
36/* we need the _OS_LINUX stuff first ! */ 37/* we need the _OS_LINUX stuff first ! */
37 38
38#ifndef _OS_LINUX_ 39#ifndef _OS_LINUX_
39// Is anybody able to review this ? The include "uuid/uuid.h" couldn't be found 40// Is anybody able to review this ? The include "uuid/uuid.h" couldn't be found
40// anywhere ? Therfore I removed it completely.. 41// anywhere ? Therfore I removed it completely..
41// I think it should be made permanentyl !? (eilers) 42// I think it should be made permanentyl !? (eilers)
42#warning "Where should uuid/uuid.h be found ? Removed this part .. (eilers)" 43#warning "Where should uuid/uuid.h be found ? Removed this part .. (eilers)"
43#if 0 44#if 0
44 45
45extern "C" 46extern "C"
46{ 47{
47#include <uuid/uuid.h> 48#include <uuid/uuid.h>
48#define UUID_H_INCLUDED 49#define UUID_H_INCLUDED
49} 50}
50 51
51#endif 52#endif
52 53
53#endif // not defined linux 54#endif // not defined linux
54 55
55#if defined(_OS_LINUX_) 56#if defined(_OS_LINUX_)
56#include <shadow.h> 57#include <shadow.h>
57#elif defined(Q_OS_MACX) 58#elif defined(Q_OS_MACX)
58#include <stdlib.h> 59#include <stdlib.h>
59#endif 60#endif
60 61
61#include <qtextstream.h> 62#include <qtextstream.h>
62#include <qmessagebox.h> 63#include <qmessagebox.h>
63//#include <qpe/qcopchannel_qws.h> 64//#include <qpe/qcopchannel_qws.h>
64#include <qpe/process.h> 65#include <qpe/process.h>
65#include <qpe/global.h> 66#include <qpe/global.h>
66#include <qpe/config.h> 67#include <qpe/config.h>
67#include <qpe/contact.h> 68#include <qpe/contact.h>
68#include <qpe/version.h> 69#include <qpe/version.h>
69#include <qpe/qcopenvelope_qws.h> 70#include <qpe/qcopenvelope_qws.h>
70 71
71#include "transferserver.h" 72#include "transferserver.h"
72#include <opie2/oprocess.h> 73#include <opie2/oprocess.h>
73using namespace Opie::Core; 74using namespace Opie::Core;
74 75
75const int block_size = 51200; 76const int block_size = 51200;
76 77
77TransferServer::TransferServer( Q_UINT16 port, QObject *parent , 78TransferServer::TransferServer( Q_UINT16 port, QObject *parent ,
78 const char* name ) 79 const char* name )
79 : QServerSocket( port, 1, parent, name ) 80 : QServerSocket( port, 1, parent, name )
80{ 81{
81 if ( !ok() ) 82 if ( !ok() )
82 owarn << "Failed to bind to port " << port << "" << oendl; 83 owarn << "Failed to bind to port " << port << "" << oendl;
83} 84}
84 85
85TransferServer::~TransferServer() 86TransferServer::~TransferServer()
86{ 87{
87} 88}
88 89
89void TransferServer::newConnection( int socket ) 90void TransferServer::newConnection( int socket )
90{ 91{
91 (void) new ServerPI( socket, this ); 92 (void) new ServerPI( socket, this );
92} 93}
93 94
94/* 95/*
95 * small class in anonymous namespace 96 * small class in anonymous namespace
96 * to generate a QUUid for us 97 * to generate a QUUid for us
97 */ 98 */
98namespace 99namespace
99{ 100{
100struct UidGen 101struct UidGen
101{ 102{
102 QString uuid(); 103 QString uuid();
103}; 104};
104#if defined(Q_OS_MACX) 105#if defined(Q_OS_MACX)
105QString UidGen::uuid() 106QString UidGen::uuid()
106{ 107{
107 srandom( random() ); 108 srandom( random() );
108 QString numStr = QString::number( random() ); 109 QString numStr = QString::number( random() );
109 110
110 return "{" + numStr + "}"; 111 return "{" + numStr + "}";
111} 112}
112#elif defined(_OS_LINUX_) 113#elif defined(_OS_LINUX_)
113/* 114/*
114* linux got a /proc/sys/kernel/random/uuid file 115* linux got a /proc/sys/kernel/random/uuid file
115* it'll generate the uuids for us 116* it'll generate the uuids for us
116*/ 117*/
117QString UidGen::uuid() 118QString UidGen::uuid()
118{ 119{
119 QFile file( "/proc/sys/kernel/random/uuid" ); 120 QFile file( "/proc/sys/kernel/random/uuid" );
120 if (!file.open(IO_ReadOnly ) ) 121 if (!file.open(IO_ReadOnly ) )
121 return QString::null; 122 return QString::null;
122 123
123 QTextStream stream(&file); 124 QTextStream stream(&file);
124 125
125 return "{" + stream.read().stripWhiteSpace() + "}"; 126 return "{" + stream.read().stripWhiteSpace() + "}";
126} 127}
127#else 128#else
128QString UidGen::uuid() 129QString UidGen::uuid()
129{ 130{
130 uuid_t uuid; 131 uuid_t uuid;
131 ::uuid_generate( uuid ); 132 ::uuid_generate( uuid );
132 return QUUid( uuid ).toString(); 133 return QUUid( uuid ).toString();
133} 134}
134#endif 135#endif
135} 136}
136 137
137QString SyncAuthentication::serverId() 138QString SyncAuthentication::serverId()
138{ 139{
139 Config cfg("Security"); 140 Config cfg("Security");
140 cfg.setGroup("Sync"); 141 cfg.setGroup("Sync");
141 QString r = cfg.readEntry("serverid"); 142 QString r = cfg.readEntry("serverid");
142 if ( r.isEmpty() ) { 143 if ( r.isEmpty() ) {
143 UidGen gen; 144 UidGen gen;
144 r = gen.uuid(); 145 r = gen.uuid();
145 cfg.writeEntry("serverid", r ); 146 cfg.writeEntry("serverid", r );
146 } 147 }
147 return r; 148 return r;
148} 149}
149 150
150QString SyncAuthentication::ownerName() 151QString SyncAuthentication::ownerName()
151{ 152{
152 QString vfilename = Global::applicationFileName("addressbook", 153 QString vfilename = Global::applicationFileName("addressbook",
153 "businesscard.vcf"); 154 "businesscard.vcf");
154 if (QFile::exists(vfilename)) { 155 if (QFile::exists(vfilename)) {
155 Contact c; 156 Contact c;
156 c = Contact::readVCard( vfilename )[0]; 157 c = Contact::readVCard( vfilename )[0];
157 return c.fullName(); 158 return c.fullName();
158 } 159 }
159 160
160 return ""; 161 return "";
161} 162}
162 163
163QString SyncAuthentication::loginName() 164QString SyncAuthentication::loginName()
164{ 165{
165 struct passwd *pw; 166 struct passwd *pw;
166 pw = getpwuid( geteuid() ); 167 pw = getpwuid( geteuid() );
167 return QString::fromLocal8Bit( pw->pw_name ); 168 return QString::fromLocal8Bit( pw->pw_name );
168} 169}
169 170
170int SyncAuthentication::isAuthorized(QHostAddress peeraddress) 171int SyncAuthentication::isAuthorized(QHostAddress peeraddress)
171{ 172{
172 Config cfg("Security"); 173 Config cfg("Security");
173 cfg.setGroup("Sync"); 174 cfg.setGroup("Sync");
174 // QString allowedstr = cfg.readEntry("auth_peer","192.168.1.0"); 175 // QString allowedstr = cfg.readEntry("auth_peer","192.168.1.0");
175 uint auth_peer = cfg.readNumEntry("auth_peer", 0xc0a80100); 176 uint auth_peer = cfg.readNumEntry("auth_peer", 0xc0a80100);
176 177
177 // QHostAddress allowed; 178 // QHostAddress allowed;
178 // allowed.setAddress(allowedstr); 179 // allowed.setAddress(allowedstr);
179 // uint auth_peer = allowed.ip4Addr(); 180 // uint auth_peer = allowed.ip4Addr();
180 uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits", 24); 181 uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits", 24);
181 uint mask = auth_peer_bits >= 32 // shifting by 32 is not defined 182 uint mask = auth_peer_bits >= 32 // shifting by 32 is not defined
182 ? 0xffffffff : (((1 << auth_peer_bits) - 1) << (32 - auth_peer_bits)); 183 ? 0xffffffff : (((1 << auth_peer_bits) - 1) << (32 - auth_peer_bits));
183 return (peeraddress.ip4Addr() & mask) == auth_peer; 184 return (peeraddress.ip4Addr() & mask) == auth_peer;
184} 185}
185 186
186bool SyncAuthentication::checkUser( const QString& user ) 187bool SyncAuthentication::checkUser( const QString& user )
187{ 188{
188 if ( user.isEmpty() ) 189 if ( user.isEmpty() )
189 return FALSE; 190 return FALSE;
190 QString euser = loginName(); 191 QString euser = loginName();
191 return user == euser; 192 return user == euser;
192} 193}
193 194
194bool SyncAuthentication::checkPassword( const QString& password ) 195bool SyncAuthentication::checkPassword( const QString& password )
195{ 196{
196#ifdef ALLOW_UNIX_USER_FTP 197#ifdef ALLOW_UNIX_USER_FTP
197 // First, check system password... 198 // First, check system password...
198 199
199 struct passwd *pw = 0; 200 struct passwd *pw = 0;
200 struct spwd *spw = 0; 201 struct spwd *spw = 0;
201 202
202 pw = getpwuid( geteuid() ); 203 pw = getpwuid( geteuid() );
203 spw = getspnam( pw->pw_name ); 204 spw = getspnam( pw->pw_name );
204 205
205 QString cpwd = QString::fromLocal8Bit( pw->pw_passwd ); 206 QString cpwd = QString::fromLocal8Bit( pw->pw_passwd );
206 if ( cpwd == "x" && spw ) 207 if ( cpwd == "x" && spw )
207 cpwd = QString::fromLocal8Bit( spw->sp_pwdp ); 208 cpwd = QString::fromLocal8Bit( spw->sp_pwdp );
208 209
209 // Note: some systems use more than crypt for passwords. 210 // Note: some systems use more than crypt for passwords.
210 QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) ); 211 QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) );
211 if ( cpwd == cpassword ) 212 if ( cpwd == cpassword )
212 return TRUE; 213 return TRUE;
213#endif 214#endif
214 215
215 static int lastdenial = 0; 216 static int lastdenial = 0;
216 static int denials = 0; 217 static int denials = 0;
217 int now = time(0); 218 int now = time(0);
218 219
219 // Detect old Qtopia Desktop (no password) 220 // Detect old Qtopia Desktop (no password)
220 if ( password.isEmpty() ) { 221 if ( password.isEmpty() ) {
221 if ( denials < 1 || now > lastdenial + 600 ) { 222 if ( denials < 1 || now > lastdenial + 600 ) {
222 QMessageBox::warning( 0, tr("Sync Connection"), 223 QMessageBox::warning( 0, tr("Sync Connection"),
223 tr("<p>An unauthorized system is requesting access to this device." 224 tr("<p>An unauthorized system is requesting access to this device."
224 "<p>If you are using a version of Qtopia Desktop older than 1.5.1, " 225 "<p>If you are using a version of Qtopia Desktop older than 1.5.1, "
225 "please upgrade."), 226 "please upgrade."),
226 tr("Deny") ); 227 tr("Deny") );
227 denials++; 228 denials++;
228 lastdenial = now; 229 lastdenial = now;
229 } 230 }
230 return FALSE; 231 return FALSE;
231 } 232 }
232 233
233 // Second, check sync password... 234 // Second, check sync password...
234 QString pass = password.left(6); 235 QString pass = password.left(6);
235 /* old QtopiaDesktops are sending 236 /* old QtopiaDesktops are sending
236 * rootme newer versions got a Qtopia 237 * rootme newer versions got a Qtopia
237 * prefixed. Qtopia prefix will suceed 238 * prefixed. Qtopia prefix will suceed
238 * until the sync software syncs up 239 * until the sync software syncs up
239 * FIXME 240 * FIXME
240 */ 241 */
241 if ( pass == "rootme" || pass == "Qtopia") { 242 if ( pass == "rootme" || pass == "Qtopia") {
242 243
243 QString cpassword = QString::fromLocal8Bit( crypt( password.mid(8).local8Bit(), "qp" ) ); 244 QString cpassword = QString::fromLocal8Bit( crypt( password.mid(8).local8Bit(), "qp" ) );
244 Config cfg("Security"); 245 Config cfg("Security");
245 cfg.setGroup("Sync"); 246 cfg.setGroup("Sync");
246 QString pwds = cfg.readEntry("Passwords"); 247 QString pwds = cfg.readEntry("Passwords");
247 if ( QStringList::split(QChar(' '), pwds).contains(cpassword) ) 248 if ( QStringList::split(QChar(' '), pwds).contains(cpassword) )
248 return TRUE; 249 return TRUE;
249 250
250 // Unrecognized system. Be careful... 251 // Unrecognized system. Be careful...
251 252
252 if ( (denials > 2 && now < lastdenial + 600) 253 if ( (denials > 2 && now < lastdenial + 600)
253 || QMessageBox::warning(0, tr("Sync Connection"), 254 || QMessageBox::warning(0, tr("Sync Connection"),
254 tr("<p>An unrecognized system is requesting access to this device." 255 tr("<p>An unrecognized system is requesting access to this device."
255 "<p>If you have just initiated a Sync for the first time, this is normal."), 256 "<p>If you have just initiated a Sync for the first time, this is normal."),
256 tr("Allow"), tr("Deny"), 0, 1, 1 ) == 1 ) { 257 tr("Allow"), tr("Deny"), 0, 1, 1 ) == 1 ) {
257 denials++; 258 denials++;
258 lastdenial = now; 259 lastdenial = now;
259 return FALSE; 260 return FALSE;
260 } 261 }
261 else { 262 else {
262 denials = 0; 263 denials = 0;
263 cfg.writeEntry("Passwords", pwds + " " + cpassword); 264 cfg.writeEntry("Passwords", pwds + " " + cpassword);
264 return TRUE; 265 return TRUE;
265 } 266 }
266 } 267 }
267 268
268 return FALSE; 269 return FALSE;
269} 270}
270 271
271ServerPI::ServerPI( int socket, QObject *parent , const char* name ) 272ServerPI::ServerPI( int socket, QObject *parent , const char* name )
272 : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 ) 273 : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 )
273{ 274{
274 state = Connected; 275 state = Connected;
275 276
276 setSocket( socket ); 277 setSocket( socket );
277 278
278 peerport = peerPort(); 279 peerport = peerPort();
279 peeraddress = peerAddress(); 280 peeraddress = peerAddress();
280 281
281#ifndef INSECURE 282#ifndef INSECURE
282 283
283 if ( !SyncAuthentication::isAuthorized(peeraddress) ) { 284 if ( !SyncAuthentication::isAuthorized(peeraddress) ) {
284 state = Forbidden; 285 state = Forbidden;
285 startTimer( 0 ); 286 startTimer( 0 );
286 } 287 }
287 else 288 else
288#endif 289#endif
289 { 290 {
290 connect( this, SIGNAL( readyRead() ), SLOT( read() ) ); 291 connect( this, SIGNAL( readyRead() ), SLOT( read() ) );
291 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) ); 292 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) );
292 293
293 passiv = FALSE; 294 passiv = FALSE;
294 for ( int i = 0; i < 4; i++ ) 295 for ( int i = 0; i < 4; i++ )
295 wait[i] = FALSE; 296 wait[i] = FALSE;
296 297
297 send( "220 Qtopia " QPE_VERSION " FTP Server" ); 298 send( "220 Qtopia " QPE_VERSION " FTP Server" );
298 state = Wait_USER; 299 state = Wait_USER;
299 300
300 dtp = new ServerDTP( this ); 301 dtp = new ServerDTP( this );
301 connect( dtp, SIGNAL( completed() ), SLOT( dtpCompleted() ) ); 302 connect( dtp, SIGNAL( completed() ), SLOT( dtpCompleted() ) );
302 connect( dtp, SIGNAL( failed() ), SLOT( dtpFailed() ) ); 303 connect( dtp, SIGNAL( failed() ), SLOT( dtpFailed() ) );
303 connect( dtp, SIGNAL( error(int) ), SLOT( dtpError(int) ) ); 304 connect( dtp, SIGNAL( error(int) ), SLOT( dtpError(int) ) );
304 305
305 306
306 directory = QDir::currentDirPath(); 307 directory = QDir::currentDirPath();
307 308
308 static int p = 1024; 309 static int p = 1024;
309 310
310 while ( !serversocket || !serversocket->ok() ) { 311 while ( !serversocket || !serversocket->ok() ) {
311 delete serversocket; 312 delete serversocket;
312 serversocket = new ServerSocket( ++p, this ); 313 serversocket = new ServerSocket( ++p, this );
313 } 314 }
314 connect( serversocket, SIGNAL( newIncomming(int) ), 315 connect( serversocket, SIGNAL( newIncomming(int) ),
315 SLOT( newConnection(int) ) ); 316 SLOT( newConnection(int) ) );
316 } 317 }
317} 318}
318 319
319ServerPI::~ServerPI() 320ServerPI::~ServerPI()
320{ 321{
321} 322}
322 323
323void ServerPI::connectionClosed() 324void ServerPI::connectionClosed()
324{ 325{
325 // odebug << "Debug: Connection closed" << oendl; 326 // odebug << "Debug: Connection closed" << oendl;
326 delete this; 327 delete this;
327} 328}
328 329
329void ServerPI::send( const QString& msg ) 330void ServerPI::send( const QString& msg )
330{ 331{
331 QTextStream os( this ); 332 QTextStream os( this );
332 os << msg << endl; 333 os << msg << endl;
333 //odebug << "Reply: " << msg << "" << oendl; 334 //odebug << "Reply: " << msg << "" << oendl;
334} 335}
335 336
336void ServerPI::read() 337void ServerPI::read()
337{ 338{
338 while ( canReadLine() ) 339 while ( canReadLine() )
339 process( readLine().stripWhiteSpace() ); 340 process( readLine().stripWhiteSpace() );
340} 341}
341 342
342bool ServerPI::checkReadFile( const QString& file ) 343bool ServerPI::checkReadFile( const QString& file )
343{ 344{
344 QString filename; 345 QString filename;
345 346
346 if ( file[0] != "/" ) 347 if ( file[0] != "/" )
347 filename = directory.path() + "/" + file; 348 filename = directory.path() + "/" + file;
348 else 349 else
349 filename = file; 350 filename = file;
350 351
351 QFileInfo fi( filename ); 352 QFileInfo fi( filename );
352 return ( fi.exists() && fi.isReadable() ); 353 return ( fi.exists() && fi.isReadable() );
353} 354}
354 355
355bool ServerPI::checkWriteFile( const QString& file ) 356bool ServerPI::checkWriteFile( const QString& file )
356{ 357{
357 QString filename; 358 QString filename;
358 359
359 if ( file[0] != "/" ) 360 if ( file[0] != "/" )
360 filename = directory.path() + "/" + file; 361 filename = directory.path() + "/" + file;
361 else 362 else
362 filename = file; 363 filename = file;
363 364
364 QFileInfo fi( filename ); 365 QFileInfo fi( filename );
365 366
366 if ( fi.exists() ) 367 if ( fi.exists() )
367 if ( !QFile( filename ).remove() ) 368 if ( !QFile( filename ).remove() )
368 return FALSE; 369 return FALSE;
369 return TRUE; 370 return TRUE;
370} 371}
371 372
372void ServerPI::process( const QString& message ) 373void ServerPI::process( const QString& message )
373{ 374{
374 //odebug << "Command: " << message << "" << oendl; 375 //odebug << "Command: " << message << "" << oendl;
375 376
376 // split message using "," as separator 377 // split message using "," as separator
377 QStringList msg = QStringList::split( " ", message ); 378 QStringList msg = QStringList::split( " ", message );
378 if ( msg.isEmpty() ) 379 if ( msg.isEmpty() )
379 return ; 380 return ;
380 381
381 // command token 382 // command token
382 QString cmd = msg[0].upper(); 383 QString cmd = msg[0].upper();
383 384
384 // argument token 385 // argument token
385 QString arg; 386 QString arg;
386 if ( msg.count() >= 2 ) 387 if ( msg.count() >= 2 )
387 arg = msg[1]; 388 arg = msg[1];
388 389
389 // full argument string 390 // full argument string
390 QString args; 391 QString args;
391 if ( msg.count() >= 2 ) { 392 if ( msg.count() >= 2 ) {
392 QStringList copy( msg ); 393 QStringList copy( msg );
393 // FIXME: for Qt3 394 // FIXME: for Qt3
394 // copy.pop_front() 395 // copy.pop_front()
395 copy.remove( copy.begin() ); 396 copy.remove( copy.begin() );
396 args = copy.join( " " ); 397 args = copy.join( " " );
397 } 398 }
398 399
399 //odebug << "args: " << args << "" << oendl; 400 //odebug << "args: " << args << "" << oendl;
400 401
401 // we always respond to QUIT, regardless of state 402 // we always respond to QUIT, regardless of state
402 if ( cmd == "QUIT" ) { 403 if ( cmd == "QUIT" ) {
403 send( "211 Good bye!" ); 404 send( "211 Good bye!" );
404 delete this; 405 delete this;
405 return ; 406 return ;
406 } 407 }
407 408
408 // connected to client 409 // connected to client
409 if ( Connected == state ) 410 if ( Connected == state )
410 return ; 411 return ;
411 412
412 // waiting for user name 413 // waiting for user name
413 if ( Wait_USER == state ) { 414 if ( Wait_USER == state ) {
414 415