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