summaryrefslogtreecommitdiff
authorzecke <zecke>2003-11-21 09:37:54 (UTC)
committer zecke <zecke>2003-11-21 09:37:54 (UTC)
commit10ae99b2cbbf3e24f3568367a85b3b2d6c0fa289 (patch) (unidiff)
treeac9c821ddeef8d6e05024206e19b7dc780791611
parent99ecb210f893437068060194b031cb37b94a0398 (diff)
downloadopie-10ae99b2cbbf3e24f3568367a85b3b2d6c0fa289.zip
opie-10ae99b2cbbf3e24f3568367a85b3b2d6c0fa289.tar.gz
opie-10ae99b2cbbf3e24f3568367a85b3b2d6c0fa289.tar.bz2
Fix bug 1219.
If not authorized no dtp is created so 0x000000000->close is likely to fail. lpotter something I think Qtopia suffers from as well
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/transferserver.cpp4
1 files changed, 3 insertions, 1 deletions
diff --git a/core/launcher/transferserver.cpp b/core/launcher/transferserver.cpp
index eea9f3a..9519d11 100644
--- a/core/launcher/transferserver.cpp
+++ b/core/launcher/transferserver.cpp
@@ -1,1432 +1,1434 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of the Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20//#define _XOPEN_SOURCE 20//#define _XOPEN_SOURCE
21 21
22#include <qtopia/global.h> 22#include <qtopia/global.h>
23#include <qtopia/qpeapplication.h> 23#include <qtopia/qpeapplication.h>
24 24
25#ifndef Q_OS_WIN32 25#ifndef Q_OS_WIN32
26#include <pwd.h> 26#include <pwd.h>
27#include <sys/types.h> 27#include <sys/types.h>
28#include <unistd.h> 28#include <unistd.h>
29#include <stdlib.h> 29#include <stdlib.h>
30#include <time.h> 30#include <time.h>
31 31
32#ifndef Q_OS_MACX 32#ifndef Q_OS_MACX
33#include <shadow.h> 33#include <shadow.h>
34#include <crypt.h> 34#include <crypt.h>
35#endif /* Q_OS_MACX */ 35#endif /* Q_OS_MACX */
36 36
37#else 37#else
38#include <stdlib.h> 38#include <stdlib.h>
39#include <time.h> 39#include <time.h>
40#endif 40#endif
41 41
42 42
43#if defined(_OS_LINUX_) 43#if defined(_OS_LINUX_)
44#include <shadow.h> 44#include <shadow.h>
45#endif 45#endif
46 46
47#include <qdir.h> 47#include <qdir.h>
48#include <qfile.h> 48#include <qfile.h>
49#include <qtextstream.h> 49#include <qtextstream.h>
50#include <qdatastream.h> 50#include <qdatastream.h>
51#include <qmessagebox.h> 51#include <qmessagebox.h>
52#include <qstringlist.h> 52#include <qstringlist.h>
53#include <qfileinfo.h> 53#include <qfileinfo.h>
54#include <qregexp.h> 54#include <qregexp.h>
55//#include <qtopia/qcopchannel_qws.h> 55//#include <qtopia/qcopchannel_qws.h>
56#include <qtopia/process.h> 56#include <qtopia/process.h>
57#include <qtopia/global.h> 57#include <qtopia/global.h>
58#include <qtopia/config.h> 58#include <qtopia/config.h>
59#include <qtopia/private/contact.h> 59#include <qtopia/private/contact.h>
60#include <qtopia/quuid.h> 60#include <qtopia/quuid.h>
61#include <qtopia/version.h> 61#include <qtopia/version.h>
62#ifdef Q_WS_QWS 62#ifdef Q_WS_QWS
63#include <qtopia/qcopenvelope_qws.h> 63#include <qtopia/qcopenvelope_qws.h>
64#endif 64#endif
65 65
66#include "launcherglobal.h" 66#include "launcherglobal.h"
67 67
68#include "transferserver.h" 68#include "transferserver.h"
69#include <qtopia/qprocess.h> 69#include <qtopia/qprocess.h>
70 70
71const int block_size = 51200; 71const int block_size = 51200;
72 72
73TransferServer::TransferServer( Q_UINT16 port, QObject *parent, 73TransferServer::TransferServer( Q_UINT16 port, QObject *parent,
74 const char* name) 74 const char* name)
75 : QServerSocket( port, 1, parent, name ) 75 : QServerSocket( port, 1, parent, name )
76{ 76{
77 connections.setAutoDelete( TRUE ); 77 connections.setAutoDelete( TRUE );
78 if ( !ok() ) 78 if ( !ok() )
79 qWarning( "Failed to bind to port %d", port ); 79 qWarning( "Failed to bind to port %d", port );
80} 80}
81 81
82void TransferServer::authorizeConnections() 82void TransferServer::authorizeConnections()
83{ 83{
84 QListIterator<ServerPI> it(connections); 84 QListIterator<ServerPI> it(connections);
85 while ( it.current() ) { 85 while ( it.current() ) {
86 if ( !it.current()->verifyAuthorised() ) { 86 if ( !it.current()->verifyAuthorised() ) {
87 disconnect( it.current(), SIGNAL(connectionClosed(ServerPI *)), this, SLOT( closed(ServerPI *)) ); 87 disconnect( it.current(), SIGNAL(connectionClosed(ServerPI *)), this, SLOT( closed(ServerPI *)) );
88 connections.removeRef( it.current() ); 88 connections.removeRef( it.current() );
89 } else 89 } else
90 ++it; 90 ++it;
91 } 91 }
92} 92}
93 93
94void TransferServer::closed(ServerPI *item) 94void TransferServer::closed(ServerPI *item)
95{ 95{
96 connections.removeRef(item); 96 connections.removeRef(item);
97} 97}
98 98
99TransferServer::~TransferServer() 99TransferServer::~TransferServer()
100{ 100{
101} 101}
102 102
103void TransferServer::newConnection( int socket ) 103void TransferServer::newConnection( int socket )
104{ 104{
105 ServerPI *ptr = new ServerPI( socket, this ); 105 ServerPI *ptr = new ServerPI( socket, this );
106 connect( ptr, SIGNAL(connectionClosed(ServerPI *)), this, SLOT( closed(ServerPI *)) ); 106 connect( ptr, SIGNAL(connectionClosed(ServerPI *)), this, SLOT( closed(ServerPI *)) );
107 connections.append( ptr ); 107 connections.append( ptr );
108} 108}
109 109
110QString SyncAuthentication::serverId() 110QString SyncAuthentication::serverId()
111{ 111{
112 Config cfg("Security"); 112 Config cfg("Security");
113 cfg.setGroup("Sync"); 113 cfg.setGroup("Sync");
114 QString r = cfg.readEntry("serverid"); 114 QString r = cfg.readEntry("serverid");
115 115
116 if ( r.isEmpty() ) { 116 if ( r.isEmpty() ) {
117 r = Opie::Global::uuid(); 117 r = Opie::Global::uuid();
118 cfg.writeEntry("serverid", r ); 118 cfg.writeEntry("serverid", r );
119 } 119 }
120 return r; 120 return r;
121} 121}
122 122
123QString SyncAuthentication::ownerName() 123QString SyncAuthentication::ownerName()
124{ 124{
125 QString vfilename = Global::applicationFileName("addressbook", 125 QString vfilename = Global::applicationFileName("addressbook",
126 "businesscard.vcf"); 126 "businesscard.vcf");
127 if (QFile::exists(vfilename)) { 127 if (QFile::exists(vfilename)) {
128 Contact c; 128 Contact c;
129 c = Contact::readVCard( vfilename )[0]; 129 c = Contact::readVCard( vfilename )[0];
130 return c.fullName(); 130 return c.fullName();
131 } 131 }
132 132
133 return QString::null; 133 return QString::null;
134} 134}
135 135
136QString SyncAuthentication::loginName() 136QString SyncAuthentication::loginName()
137{ 137{
138 struct passwd *pw = 0L; 138 struct passwd *pw = 0L;
139#ifndef Q_OS_WIN32 139#ifndef Q_OS_WIN32
140 pw = getpwuid( geteuid() ); 140 pw = getpwuid( geteuid() );
141 return QString::fromLocal8Bit( pw->pw_name ); 141 return QString::fromLocal8Bit( pw->pw_name );
142#else 142#else
143 //### revise 143 //### revise
144 return QString(); 144 return QString();
145#endif 145#endif
146} 146}
147 147
148int SyncAuthentication::isAuthorized(QHostAddress peeraddress) 148int SyncAuthentication::isAuthorized(QHostAddress peeraddress)
149{ 149{
150 Config cfg("Security"); 150 Config cfg("Security");
151 cfg.setGroup("Sync"); 151 cfg.setGroup("Sync");
152 // QString allowedstr = cfg.readEntry("auth_peer","192.168.1.0"); 152 // QString allowedstr = cfg.readEntry("auth_peer","192.168.1.0");
153 uint auth_peer = cfg.readNumEntry("auth_peer", 0xc0a80100); 153 uint auth_peer = cfg.readNumEntry("auth_peer", 0xc0a80100);
154 154
155 // QHostAddress allowed; 155 // QHostAddress allowed;
156 // allowed.setAddress(allowedstr); 156 // allowed.setAddress(allowedstr);
157 // uint auth_peer = allowed.ip4Addr(); 157 // uint auth_peer = allowed.ip4Addr();
158 uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits", 24); 158 uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits", 24);
159 uint mask = auth_peer_bits >= 32 // shifting by 32 is not defined 159 uint mask = auth_peer_bits >= 32 // shifting by 32 is not defined
160 ? 0xffffffff : (((1 << auth_peer_bits) - 1) << (32 - auth_peer_bits)); 160 ? 0xffffffff : (((1 << auth_peer_bits) - 1) << (32 - auth_peer_bits));
161 161
162 return (peeraddress.ip4Addr() & mask) == auth_peer; 162 return (peeraddress.ip4Addr() & mask) == auth_peer;
163} 163}
164 164
165bool SyncAuthentication::checkUser( const QString& user ) 165bool SyncAuthentication::checkUser( const QString& user )
166{ 166{
167 if ( user.isEmpty() ) return FALSE; 167 if ( user.isEmpty() ) return FALSE;
168 QString euser = loginName(); 168 QString euser = loginName();
169 return user == euser; 169 return user == euser;
170} 170}
171 171
172bool SyncAuthentication::checkPassword( const QString& password ) 172bool SyncAuthentication::checkPassword( const QString& password )
173{ 173{
174#ifdef ALLOW_UNIX_USER_FTP 174#ifdef ALLOW_UNIX_USER_FTP
175 // First, check system password... 175 // First, check system password...
176 176
177 struct passwd *pw = 0; 177 struct passwd *pw = 0;
178 struct spwd *spw = 0; 178 struct spwd *spw = 0;
179 179
180 pw = getpwuid( geteuid() ); 180 pw = getpwuid( geteuid() );
181 spw = getspnam( pw->pw_name ); 181 spw = getspnam( pw->pw_name );
182 182
183 QString cpwd = QString::fromLocal8Bit( pw->pw_passwd ); 183 QString cpwd = QString::fromLocal8Bit( pw->pw_passwd );
184 if ( cpwd == "x" && spw ) 184 if ( cpwd == "x" && spw )
185 cpwd = QString::fromLocal8Bit( spw->sp_pwdp ); 185 cpwd = QString::fromLocal8Bit( spw->sp_pwdp );
186 186
187 // Note: some systems use more than crypt for passwords. 187 // Note: some systems use more than crypt for passwords.
188 QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) ); 188 QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) );
189 if ( cpwd == cpassword ) 189 if ( cpwd == cpassword )
190 return TRUE; 190 return TRUE;
191#endif 191#endif
192 192
193 static int lastdenial=0; 193 static int lastdenial=0;
194 static int denials=0; 194 static int denials=0;
195 int now = time(0); 195 int now = time(0);
196 196
197 Config cfg("Security"); 197 Config cfg("Security");
198 cfg.setGroup("Sync"); 198 cfg.setGroup("Sync");
199 QString syncapp = cfg.readEntry("syncapp","Qtopia"); 199 QString syncapp = cfg.readEntry("syncapp","Qtopia");
200 200
201 //No password needed if the user really wants it 201 //No password needed if the user really wants it
202 if (syncapp == "IntelliSync") { 202 if (syncapp == "IntelliSync") {
203 return TRUE; 203 return TRUE;
204 } 204 }
205 205
206 // Detect old Qtopia Desktop (no password) 206 // Detect old Qtopia Desktop (no password)
207 if ( password.isEmpty() ) { 207 if ( password.isEmpty() ) {
208 if ( denials < 3 || now > lastdenial+600 ) { 208 if ( denials < 3 || now > lastdenial+600 ) {
209 QMessageBox unauth( 209 QMessageBox unauth(
210 tr("Sync Connection"), 210 tr("Sync Connection"),
211 tr("<p>An unauthorized system is requesting access to this device." 211 tr("<p>An unauthorized system is requesting access to this device."
212 "<p>If you are using a version of Qtopia Desktop older than 1.5.1, " 212 "<p>If you are using a version of Qtopia Desktop older than 1.5.1, "
213 "please upgrade or change the security setting to use IntelliSync." ), 213 "please upgrade or change the security setting to use IntelliSync." ),
214 QMessageBox::Warning, 214 QMessageBox::Warning,
215 QMessageBox::Cancel, QMessageBox::NoButton, QMessageBox::NoButton, 215 QMessageBox::Cancel, QMessageBox::NoButton, QMessageBox::NoButton,
216 0, QString::null, TRUE, WStyle_StaysOnTop); 216 0, QString::null, TRUE, WStyle_StaysOnTop);
217 unauth.setButtonText(QMessageBox::Cancel, tr("Deny")); 217 unauth.setButtonText(QMessageBox::Cancel, tr("Deny"));
218 unauth.exec(); 218 unauth.exec();
219 219
220 denials++; 220 denials++;
221 lastdenial=now; 221 lastdenial=now;
222 } 222 }
223 return FALSE; 223 return FALSE;
224 224
225 } 225 }
226 226
227 // Second, check sync password... 227 // Second, check sync password...
228 228
229 static int lock=0; 229 static int lock=0;
230 if ( lock ) return FALSE; 230 if ( lock ) return FALSE;
231 231
232 ++lock; 232 ++lock;
233 233
234 /* 234 /*
235 * we need to support old Sync software and QtopiaDesktop 235 * we need to support old Sync software and QtopiaDesktop
236 */ 236 */
237 if ( password.left(6) == "Qtopia" || password.left(6) == "rootme" ) { 237 if ( password.left(6) == "Qtopia" || password.left(6) == "rootme" ) {
238 Config cfg( "Security" ); 238 Config cfg( "Security" );
239 cfg.setGroup("Sync"); 239 cfg.setGroup("Sync");
240 QStringList pwds = cfg.readListEntry("Passwords",' '); 240 QStringList pwds = cfg.readListEntry("Passwords",' ');
241 for (QStringList::ConstIterator it=pwds.begin(); it!=pwds.end(); ++it) { 241 for (QStringList::ConstIterator it=pwds.begin(); it!=pwds.end(); ++it) {
242#ifndef Q_OS_WIN32 242#ifndef Q_OS_WIN32
243 QString cpassword = QString::fromLocal8Bit( 243 QString cpassword = QString::fromLocal8Bit(
244 crypt( password.mid(8).local8Bit(), (*it).left(2).latin1() ) ); 244 crypt( password.mid(8).local8Bit(), (*it).left(2).latin1() ) );
245#else 245#else
246 // ### revise 246 // ### revise
247 QString cpassword(""); 247 QString cpassword("");
248#endif 248#endif
249 if ( *it == cpassword ) { 249 if ( *it == cpassword ) {
250 lock--; 250 lock--;
251 return TRUE; 251 return TRUE;
252 } 252 }
253 } 253 }
254 254
255 // Unrecognized system. Be careful... 255 // Unrecognized system. Be careful...
256 QMessageBox unrecbox( 256 QMessageBox unrecbox(
257 tr("Sync Connection"), 257 tr("Sync Connection"),
258 tr("<p>An unrecognized system is requesting access to this device." 258 tr("<p>An unrecognized system is requesting access to this device."
259 "<p>If you have just initiated a Sync for the first time, this is normal."), 259 "<p>If you have just initiated a Sync for the first time, this is normal."),
260 QMessageBox::Warning, 260 QMessageBox::Warning,
261 QMessageBox::Cancel, QMessageBox::Yes, QMessageBox::NoButton, 261 QMessageBox::Cancel, QMessageBox::Yes, QMessageBox::NoButton,
262 0, QString::null, TRUE, WStyle_StaysOnTop); 262 0, QString::null, TRUE, WStyle_StaysOnTop);
263 unrecbox.setButtonText(QMessageBox::Cancel, tr("Deny")); 263 unrecbox.setButtonText(QMessageBox::Cancel, tr("Deny"));
264 unrecbox.setButtonText(QMessageBox::Yes, tr("Allow")); 264 unrecbox.setButtonText(QMessageBox::Yes, tr("Allow"));
265 265
266 if ( (denials > 2 && now < lastdenial+600) 266 if ( (denials > 2 && now < lastdenial+600)
267 || unrecbox.exec() != QMessageBox::Yes) 267 || unrecbox.exec() != QMessageBox::Yes)
268 { 268 {
269 denials++; 269 denials++;
270 lastdenial=now; 270 lastdenial=now;
271 lock--; 271 lock--;
272 return FALSE; 272 return FALSE;
273 } else { 273 } else {
274 const char salty[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/."; 274 const char salty[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/.";
275 char salt[2]; 275 char salt[2];
276 salt[0]= salty[rand() % (sizeof(salty)-1)]; 276 salt[0]= salty[rand() % (sizeof(salty)-1)];
277 salt[1]= salty[rand() % (sizeof(salty)-1)]; 277 salt[1]= salty[rand() % (sizeof(salty)-1)];
278#ifndef Q_OS_WIN32 278#ifndef Q_OS_WIN32
279 QString cpassword = QString::fromLocal8Bit( 279 QString cpassword = QString::fromLocal8Bit(
280 crypt( password.mid(8).local8Bit(), salt ) ); 280 crypt( password.mid(8).local8Bit(), salt ) );
281#else 281#else
282 //### revise 282 //### revise
283 QString cpassword(""); 283 QString cpassword("");
284#endif 284#endif
285 denials=0; 285 denials=0;
286 pwds.prepend(cpassword); 286 pwds.prepend(cpassword);
287 cfg.writeEntry("Passwords",pwds,' '); 287 cfg.writeEntry("Passwords",pwds,' ');
288 lock--; 288 lock--;
289 return TRUE; 289 return TRUE;
290 } 290 }
291 } 291 }
292 lock--; 292 lock--;
293 293
294 return FALSE; 294 return FALSE;
295} 295}
296 296
297 297
298ServerPI::ServerPI( int socket, QObject *parent, const char* name ) 298ServerPI::ServerPI( int socket, QObject *parent, const char* name )
299 : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 ), 299 : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 ),
300 storFileSize(-1) 300 storFileSize(-1)
301{ 301{
302 state = Connected; 302 state = Connected;
303 303
304 setSocket( socket ); 304 setSocket( socket );
305 305
306 peerport = peerPort(); 306 peerport = peerPort();
307 peeraddress = peerAddress(); 307 peeraddress = peerAddress();
308 308
309#ifndef INSECURE 309#ifndef INSECURE
310 if ( !SyncAuthentication::isAuthorized(peeraddress) ) { 310 if ( !SyncAuthentication::isAuthorized(peeraddress) ) {
311 state = Forbidden; 311 state = Forbidden;
312 startTimer( 0 ); 312 startTimer( 0 );
313 } else 313 } else
314#endif 314#endif
315 { 315 {
316 connect( this, SIGNAL( readyRead() ), SLOT( read() ) ); 316 connect( this, SIGNAL( readyRead() ), SLOT( read() ) );
317 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) ); 317 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) );
318 318
319 passiv = FALSE; 319 passiv = FALSE;
320 for( int i = 0; i < 4; i++ ) 320 for( int i = 0; i < 4; i++ )
321 wait[i] = FALSE; 321 wait[i] = FALSE;
322 322
323 send( "220 Qtopia " QPE_VERSION " FTP Server" ); // No tr 323 send( "220 Qtopia " QPE_VERSION " FTP Server" ); // No tr
324 state = Wait_USER; 324 state = Wait_USER;
325 325
326 dtp = new ServerDTP( this ); 326 dtp = new ServerDTP( this );
327 connect( dtp, SIGNAL( completed() ), SLOT( dtpCompleted() ) ); 327 connect( dtp, SIGNAL( completed() ), SLOT( dtpCompleted() ) );
328 connect( dtp, SIGNAL( failed() ), SLOT( dtpFailed() ) ); 328 connect( dtp, SIGNAL( failed() ), SLOT( dtpFailed() ) );
329 connect( dtp, SIGNAL( error( int ) ), SLOT( dtpError( int ) ) ); 329 connect( dtp, SIGNAL( error( int ) ), SLOT( dtpError( int ) ) );
330 330
331 331
332 directory = QDir::currentDirPath(); 332 directory = QDir::currentDirPath();
333 333
334 static int p = 1024; 334 static int p = 1024;
335 335
336 while ( !serversocket || !serversocket->ok() ) { 336 while ( !serversocket || !serversocket->ok() ) {
337 delete serversocket; 337 delete serversocket;
338 serversocket = new ServerSocket( ++p, this ); 338 serversocket = new ServerSocket( ++p, this );
339 } 339 }
340 connect( serversocket, SIGNAL( newIncomming( int ) ), 340 connect( serversocket, SIGNAL( newIncomming( int ) ),
341 SLOT( newConnection( int ) ) ); 341 SLOT( newConnection( int ) ) );
342 } 342 }
343} 343}
344 344
345ServerPI::~ServerPI() 345ServerPI::~ServerPI()
346{ 346{
347 close(); 347 close();
348 dtp->close(); 348
349 if ( dtp )
350 dtp->close();
349 delete dtp; 351 delete dtp;
350 delete serversocket; 352 delete serversocket;
351} 353}
352 354
353bool ServerPI::verifyAuthorised() 355bool ServerPI::verifyAuthorised()
354{ 356{
355 if ( !SyncAuthentication::isAuthorized(peerAddress()) ) { 357 if ( !SyncAuthentication::isAuthorized(peerAddress()) ) {
356 state = Forbidden; 358 state = Forbidden;
357 return FALSE; 359 return FALSE;
358 } 360 }
359 return TRUE; 361 return TRUE;
360} 362}
361 363
362void ServerPI::connectionClosed() 364void ServerPI::connectionClosed()
363{ 365{
364 // qDebug( "Debug: Connection closed" ); 366 // qDebug( "Debug: Connection closed" );
365 emit connectionClosed(this); 367 emit connectionClosed(this);
366} 368}
367 369
368void ServerPI::send( const QString& msg ) 370void ServerPI::send( const QString& msg )
369{ 371{
370 QTextStream os( this ); 372 QTextStream os( this );
371 os << msg << endl; 373 os << msg << endl;
372 //qDebug( "Reply: %s", msg.latin1() ); 374 //qDebug( "Reply: %s", msg.latin1() );
373} 375}
374 376
375void ServerPI::read() 377void ServerPI::read()
376{ 378{
377 while ( canReadLine() ) 379 while ( canReadLine() )
378 process( readLine().stripWhiteSpace() ); 380 process( readLine().stripWhiteSpace() );
379} 381}
380 382
381bool ServerPI::checkReadFile( const QString& file ) 383bool ServerPI::checkReadFile( const QString& file )
382{ 384{
383 QString filename; 385 QString filename;
384 386
385 if ( file[0] != "/" ) 387 if ( file[0] != "/" )
386 filename = directory.path() + "/" + file; 388 filename = directory.path() + "/" + file;
387 else 389 else
388 filename = file; 390 filename = file;
389 391
390 QFileInfo fi( filename ); 392 QFileInfo fi( filename );
391 return ( fi.exists() && fi.isReadable() ); 393 return ( fi.exists() && fi.isReadable() );
392} 394}
393 395
394bool ServerPI::checkWriteFile( const QString& file ) 396bool ServerPI::checkWriteFile( const QString& file )
395{ 397{
396 QString filename; 398 QString filename;
397 399
398 if ( file[0] != "/" ) 400 if ( file[0] != "/" )
399 filename = directory.path() + "/" + file; 401 filename = directory.path() + "/" + file;
400 else 402 else
401 filename = file; 403 filename = file;
402 404
403 QFileInfo fi( filename ); 405 QFileInfo fi( filename );
404 406
405 if ( fi.exists() ) 407 if ( fi.exists() )
406 if ( !QFile( filename ).remove() ) 408 if ( !QFile( filename ).remove() )
407 return FALSE; 409 return FALSE;
408 return TRUE; 410 return TRUE;
409} 411}
410 412
411void ServerPI::process( const QString& message ) 413void ServerPI::process( const QString& message )
412{ 414{
413 //qDebug( "Command: %s", message.latin1() ); 415 //qDebug( "Command: %s", message.latin1() );
414 416
415 // split message using "," as separator 417 // split message using "," as separator
416 QStringList msg = QStringList::split( " ", message ); 418 QStringList msg = QStringList::split( " ", message );
417 if ( msg.isEmpty() ) return; 419 if ( msg.isEmpty() ) return;
418 420
419 // command token 421 // command token
420 QString cmd = msg[0].upper(); 422 QString cmd = msg[0].upper();
421 423
422 // argument token 424 // argument token
423 QString arg; 425 QString arg;
424 if ( msg.count() >= 2 ) 426 if ( msg.count() >= 2 )
425 arg = msg[1]; 427 arg = msg[1];
426 428
427 // full argument string 429 // full argument string
428 QString args; 430 QString args;
429 if ( msg.count() >= 2 ) { 431 if ( msg.count() >= 2 ) {
430 QStringList copy( msg ); 432 QStringList copy( msg );
431 // FIXME: for Qt3 433 // FIXME: for Qt3
432 // copy.pop_front() 434 // copy.pop_front()
433 copy.remove( copy.begin() ); 435 copy.remove( copy.begin() );
434 args = copy.join( " " ); 436 args = copy.join( " " );
435 } 437 }
436 438
437 //qDebug( "args: %s", args.latin1() ); 439 //qDebug( "args: %s", args.latin1() );
438 440
439 // we always respond to QUIT, regardless of state 441 // we always respond to QUIT, regardless of state
440 if ( cmd == "QUIT" ) { 442 if ( cmd == "QUIT" ) {
441 send( "211 Good bye!" ); // No tr 443 send( "211 Good bye!" ); // No tr
442 close(); 444 close();
443 return; 445 return;
444 } 446 }
445 447
446 // connected to client 448 // connected to client
447 if ( Connected == state ) 449 if ( Connected == state )
448 return; 450 return;
449 451
450 // waiting for user name 452 // waiting for user name
451 if ( Wait_USER == state ) { 453 if ( Wait_USER == state ) {
452 454
453 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) { 455 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) {
454 send( "530 Please login with USER and PASS" ); // No tr 456 send( "530 Please login with USER and PASS" ); // No tr
455 return; 457 return;
456 } 458 }
457 send( "331 User name ok, need password" ); // No tr 459 send( "331 User name ok, need password" ); // No tr
458 state = Wait_PASS; 460 state = Wait_PASS;
459 return; 461 return;
460 } 462 }
461 463
462 // waiting for password 464 // waiting for password
463 if ( Wait_PASS == state ) { 465 if ( Wait_PASS == state ) {
464 466
465 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) { 467 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) {
466 send( "530 Please login with USER and PASS" ); // No tr 468 send( "530 Please login with USER and PASS" ); // No tr
467 return; 469 return;
468 } 470 }
469 send( "230 User logged in, proceed" ); // No tr 471 send( "230 User logged in, proceed" ); // No tr
470 state = Ready; 472 state = Ready;
471 return; 473 return;
472 } 474 }
473 475
474 // ACCESS CONTROL COMMANDS 476 // ACCESS CONTROL COMMANDS
475 477
476 // Only an ALLO sent immediately before STOR is valid. 478 // Only an ALLO sent immediately before STOR is valid.
477 if ( cmd != "STOR" ) 479 if ( cmd != "STOR" )
478 storFileSize = -1; 480 storFileSize = -1;
479 481
480 // account (ACCT) 482 // account (ACCT)
481 if ( cmd == "ACCT" ) { 483 if ( cmd == "ACCT" ) {
482 // even wu-ftp does not support it 484 // even wu-ftp does not support it
483 send( "502 Command not implemented" ); // No tr 485 send( "502 Command not implemented" ); // No tr
484 } 486 }
485 487
486 // change working directory (CWD) 488 // change working directory (CWD)
487 else if ( cmd == "CWD" ) { 489 else if ( cmd == "CWD" ) {
488 490
489 if ( !args.isEmpty() ) { 491 if ( !args.isEmpty() ) {
490 if ( directory.cd( args, TRUE ) ) 492 if ( directory.cd( args, TRUE ) )
491 send( "250 Requested file action okay, completed" ); // No tr 493 send( "250 Requested file action okay, completed" ); // No tr
492 else 494 else
493 send( "550 Requested action not taken" ); // No tr 495 send( "550 Requested action not taken" ); // No tr
494 } 496 }
495 else 497 else
496 send( "500 Syntax error, command unrecognized" ); // No tr 498 send( "500 Syntax error, command unrecognized" ); // No tr
497 } 499 }
498 500
499 // change to parent directory (CDUP) 501 // change to parent directory (CDUP)
500 else if ( cmd == "CDUP" ) { 502 else if ( cmd == "CDUP" ) {
501 if ( directory.cdUp() ) 503 if ( directory.cdUp() )
502 send( "250 Requested file action okay, completed" ); // No tr 504 send( "250 Requested file action okay, completed" ); // No tr
503 else 505 else
504 send( "550 Requested action not taken" ); // No tr 506 send( "550 Requested action not taken" ); // No tr
505 } 507 }
506 508
507 // structure mount (SMNT) 509 // structure mount (SMNT)
508 else if ( cmd == "SMNT" ) { 510 else if ( cmd == "SMNT" ) {
509 // even wu-ftp does not support it 511 // even wu-ftp does not support it
510 send( "502 Command not implemented" ); // No tr 512 send( "502 Command not implemented" ); // No tr
511 } 513 }
512 514
513 // reinitialize (REIN) 515 // reinitialize (REIN)
514 else if ( cmd == "REIN" ) { 516 else if ( cmd == "REIN" ) {
515 // even wu-ftp does not support it 517 // even wu-ftp does not support it
516 send( "502 Command not implemented" ); // No tr 518 send( "502 Command not implemented" ); // No tr
517 } 519 }
518 520
519 521
520 // TRANSFER PARAMETER COMMANDS 522 // TRANSFER PARAMETER COMMANDS
521 523
522 524
523 // data port (PORT) 525 // data port (PORT)
524 else if ( cmd == "PORT" ) { 526 else if ( cmd == "PORT" ) {
525 if ( parsePort( arg ) ) 527 if ( parsePort( arg ) )
526 send( "200 Command okay" ); // No tr 528 send( "200 Command okay" ); // No tr
527 else 529 else
528 send( "500 Syntax error, command unrecognized" ); // No tr 530 send( "500 Syntax error, command unrecognized" ); // No tr
529 } 531 }
530 532
531 // passive (PASV) 533 // passive (PASV)
532 else if ( cmd == "PASV" ) { 534 else if ( cmd == "PASV" ) {
533 passiv = TRUE; 535 passiv = TRUE;
534 send( "227 Entering Passive Mode (" // No tr 536 send( "227 Entering Passive Mode (" // No tr
535 + address().toString().replace( QRegExp( "\\." ), "," ) + "," 537 + address().toString().replace( QRegExp( "\\." ), "," ) + ","
536 + QString::number( ( serversocket->port() ) >> 8 ) + "," 538 + QString::number( ( serversocket->port() ) >> 8 ) + ","
537 + QString::number( ( serversocket->port() ) & 0xFF ) +")" ); 539 + QString::number( ( serversocket->port() ) & 0xFF ) +")" );
538 } 540 }
539 541
540 // representation type (TYPE) 542 // representation type (TYPE)
541 else if ( cmd == "TYPE" ) { 543 else if ( cmd == "TYPE" ) {
542 if ( arg.upper() == "A" || arg.upper() == "I" ) 544 if ( arg.upper() == "A" || arg.upper() == "I" )
543 send( "200 Command okay" ); // No tr 545 send( "200 Command okay" ); // No tr
544 else 546 else
545 send( "504 Command not implemented for that parameter" ); // No tr 547 send( "504 Command not implemented for that parameter" ); // No tr
546 } 548 }
547 549
548 // file structure (STRU) 550 // file structure (STRU)
549 else if ( cmd == "STRU" ) { 551 else if ( cmd == "STRU" ) {
550 if ( arg.upper() == "F" ) 552 if ( arg.upper() == "F" )
551 send( "200 Command okay" ); // No tr 553 send( "200 Command okay" ); // No tr
552 else 554 else
553 send( "504 Command not implemented for that parameter" ); // No tr 555 send( "504 Command not implemented for that parameter" ); // No tr
554 } 556 }
555 557
556 // transfer mode (MODE) 558 // transfer mode (MODE)
557 else if ( cmd == "MODE" ) { 559 else if ( cmd == "MODE" ) {
558 if ( arg.upper() == "S" ) 560 if ( arg.upper() == "S" )
559 send( "200 Command okay" ); // No tr 561 send( "200 Command okay" ); // No tr
560 else 562 else
561 send( "504 Command not implemented for that parameter" ); // No tr 563 send( "504 Command not implemented for that parameter" ); // No tr
562 } 564 }
563 565
564 566
565 // FTP SERVICE COMMANDS 567 // FTP SERVICE COMMANDS
566 568
567 569
568 // retrieve (RETR) 570 // retrieve (RETR)
569 else if ( cmd == "RETR" ) 571 else if ( cmd == "RETR" )
570 if ( !args.isEmpty() && checkReadFile( absFilePath( args ) ) 572 if ( !args.isEmpty() && checkReadFile( absFilePath( args ) )
571 || backupRestoreGzip( absFilePath( args ) ) ) { 573 || backupRestoreGzip( absFilePath( args ) ) ) {
572 send( "150 File status okay" ); // No tr 574 send( "150 File status okay" ); // No tr
573 sendFile( absFilePath( args ) ); 575 sendFile( absFilePath( args ) );
574 } 576 }
575 else { 577 else {
576 qDebug("550 Requested action not taken"); 578 qDebug("550 Requested action not taken");
577 send( "550 Requested action not taken" ); // No tr 579 send( "550 Requested action not taken" ); // No tr
578 } 580 }
579 581
580 // store (STOR) 582 // store (STOR)
581 else if ( cmd == "STOR" ) 583 else if ( cmd == "STOR" )
582 if ( !args.isEmpty() && checkWriteFile( absFilePath( args ) ) ) { 584 if ( !args.isEmpty() && checkWriteFile( absFilePath( args ) ) ) {
583 send( "150 File status okay" ); // No tr 585 send( "150 File status okay" ); // No tr
584 retrieveFile( absFilePath( args ) ); 586 retrieveFile( absFilePath( args ) );
585 } 587 }
586 else 588 else
587 send( "550 Requested action not taken" ); // No tr 589 send( "550 Requested action not taken" ); // No tr
588 590
589 // store unique (STOU) 591 // store unique (STOU)
590 else if ( cmd == "STOU" ) { 592 else if ( cmd == "STOU" ) {
591 send( "502 Command not implemented" ); // No tr 593 send( "502 Command not implemented" ); // No tr
592 } 594 }
593 595
594 // append (APPE) 596 // append (APPE)
595 else if ( cmd == "APPE" ) { 597 else if ( cmd == "APPE" ) {
596 send( "502 Command not implemented" ); // No tr 598 send( "502 Command not implemented" ); // No tr
597 } 599 }
598 600
599 // allocate (ALLO) 601 // allocate (ALLO)
600 else if ( cmd == "ALLO" ) { 602 else if ( cmd == "ALLO" ) {
601 storFileSize = args.toInt(); 603 storFileSize = args.toInt();
602 send( "200 Command okay" ); // No tr 604 send( "200 Command okay" ); // No tr
603 } 605 }
604 606
605 // restart (REST) 607 // restart (REST)
606 else if ( cmd == "REST" ) { 608 else if ( cmd == "REST" ) {
607 send( "502 Command not implemented" ); // No tr 609 send( "502 Command not implemented" ); // No tr
608 } 610 }
609 611
610 // rename from (RNFR) 612 // rename from (RNFR)
611 else if ( cmd == "RNFR" ) { 613 else if ( cmd == "RNFR" ) {
612 renameFrom = QString::null; 614 renameFrom = QString::null;
613 if ( args.isEmpty() ) 615 if ( args.isEmpty() )
614 send( "500 Syntax error, command unrecognized" ); // No tr 616 send( "500 Syntax error, command unrecognized" ); // No tr
615 else { 617 else {
616 QFile file( absFilePath( args ) ); 618 QFile file( absFilePath( args ) );
617 if ( file.exists() ) { 619 if ( file.exists() ) {
618 send( "350 File exists, ready for destination name" ); // No tr 620 send( "350 File exists, ready for destination name" ); // No tr
619 renameFrom = absFilePath( args ); 621 renameFrom = absFilePath( args );
620 } 622 }
621 else 623 else
622 send( "550 Requested action not taken" ); // No tr 624 send( "550 Requested action not taken" ); // No tr
623 } 625 }
624 } 626 }
625 627
626 // rename to (RNTO) 628 // rename to (RNTO)
627 else if ( cmd == "RNTO" ) { 629 else if ( cmd == "RNTO" ) {
628 if ( lastCommand != "RNFR" ) 630 if ( lastCommand != "RNFR" )
629 send( "503 Bad sequence of commands" ); // No tr 631 send( "503 Bad sequence of commands" ); // No tr
630 else if ( args.isEmpty() ) 632 else if ( args.isEmpty() )
631 send( "500 Syntax error, command unrecognized" ); // No tr 633 send( "500 Syntax error, command unrecognized" ); // No tr
632 else { 634 else {
633 QDir dir( absFilePath( args ) ); 635 QDir dir( absFilePath( args ) );
634 if ( dir.rename( renameFrom, absFilePath( args ), TRUE ) ) 636 if ( dir.rename( renameFrom, absFilePath( args ), TRUE ) )
635 send( "250 Requested file action okay, completed." ); // No tr 637 send( "250 Requested file action okay, completed." ); // No tr
636 else 638 else
637 send( "550 Requested action not taken" ); // No tr 639 send( "550 Requested action not taken" ); // No tr
638 } 640 }
639 } 641 }
640 642
641 // abort (ABOR) 643 // abort (ABOR)
642 else if ( cmd.contains( "ABOR" ) ) { 644 else if ( cmd.contains( "ABOR" ) ) {
643 dtp->close(); 645 dtp->close();
644 if ( dtp->dtpMode() != ServerDTP::Idle ) 646 if ( dtp->dtpMode() != ServerDTP::Idle )
645 send( "426 Connection closed; transfer aborted" ); // No tr 647 send( "426 Connection closed; transfer aborted" ); // No tr
646 else 648 else
647 send( "226 Closing data connection" ); // No tr 649 send( "226 Closing data connection" ); // No tr
648 } 650 }
649 651
650 // delete (DELE) 652 // delete (DELE)
651 else if ( cmd == "DELE" ) { 653 else if ( cmd == "DELE" ) {
652 if ( args.isEmpty() ) 654 if ( args.isEmpty() )
653 send( "500 Syntax error, command unrecognized" ); // No tr 655 send( "500 Syntax error, command unrecognized" ); // No tr
654 else { 656 else {
655 QFile file( absFilePath( args ) ) ; 657 QFile file( absFilePath( args ) ) ;
656 if ( file.remove() ) { 658 if ( file.remove() ) {
657 send( "250 Requested file action okay, completed" ); // No tr 659 send( "250 Requested file action okay, completed" ); // No tr
658 QCopEnvelope e("QPE/System", "linkChanged(QString)" ); 660 QCopEnvelope e("QPE/System", "linkChanged(QString)" );
659 e << file.name(); 661 e << file.name();
660 } else { 662 } else {
661 send( "550 Requested action not taken" ); // No tr 663 send( "550 Requested action not taken" ); // No tr
662 } 664 }
663 } 665 }
664 } 666 }
665 667
666 // remove directory (RMD) 668 // remove directory (RMD)
667 else if ( cmd == "RMD" ) { 669 else if ( cmd == "RMD" ) {
668 if ( args.isEmpty() ) 670 if ( args.isEmpty() )
669 send( "500 Syntax error, command unrecognized" ); // No tr 671 send( "500 Syntax error, command unrecognized" ); // No tr
670 else { 672 else {
671 QDir dir; 673 QDir dir;
672 if ( dir.rmdir( absFilePath( args ), TRUE ) ) 674 if ( dir.rmdir( absFilePath( args ), TRUE ) )
673 send( "250 Requested file action okay, completed" ); // No tr 675 send( "250 Requested file action okay, completed" ); // No tr
674 else 676 else
675 send( "550 Requested action not taken" ); // No tr 677 send( "550 Requested action not taken" ); // No tr
676 } 678 }
677 } 679 }
678 680
679 // make directory (MKD) 681 // make directory (MKD)
680 else if ( cmd == "MKD" ) { 682 else if ( cmd == "MKD" ) {
681 if ( args.isEmpty() ) { 683 if ( args.isEmpty() ) {
682 qDebug(" Error: no arg"); 684 qDebug(" Error: no arg");
683 send( "500 Syntax error, command unrecognized" ); // No tr 685 send( "500 Syntax error, command unrecognized" ); // No tr
684 } 686 }
685 else { 687 else {
686 QDir dir; 688 QDir dir;
687 if ( dir.mkdir( absFilePath( args ), TRUE ) ) 689 if ( dir.mkdir( absFilePath( args ), TRUE ) )
688 send( "250 Requested file action okay, completed." ); // No tr 690 send( "250 Requested file action okay, completed." ); // No tr
689 else 691 else
690 send( "550 Requested action not taken" ); // No tr 692 send( "550 Requested action not taken" ); // No tr
691 } 693 }
692 } 694 }
693 695
694 // print working directory (PWD) 696 // print working directory (PWD)
695 else if ( cmd == "PWD" ) { 697 else if ( cmd == "PWD" ) {
696 send( "257 \"" + directory.path() +"\"" ); 698 send( "257 \"" + directory.path() +"\"" );
697 } 699 }
698 700
699 // list (LIST) 701 // list (LIST)
700 else if ( cmd == "LIST" ) { 702 else if ( cmd == "LIST" ) {
701 if ( sendList( absFilePath( args ) ) ) 703 if ( sendList( absFilePath( args ) ) )
702 send( "150 File status okay" ); // No tr 704 send( "150 File status okay" ); // No tr
703 else 705 else
704 send( "500 Syntax error, command unrecognized" ); // No tr 706 send( "500 Syntax error, command unrecognized" ); // No tr
705 } 707 }
706 708
707 // size (SIZE) 709 // size (SIZE)
708 else if ( cmd == "SIZE" ) { 710 else if ( cmd == "SIZE" ) {
709 QString filePath = absFilePath( args ); 711 QString filePath = absFilePath( args );
710 QFileInfo fi( filePath ); 712 QFileInfo fi( filePath );
711 bool gzipfile = backupRestoreGzip( filePath ); 713 bool gzipfile = backupRestoreGzip( filePath );
712 if ( !fi.exists() && !gzipfile ) 714 if ( !fi.exists() && !gzipfile )
713 send( "500 Syntax error, command unrecognized" ); // No tr 715 send( "500 Syntax error, command unrecognized" ); // No tr
714 else { 716 else {
715 if ( !gzipfile ) 717 if ( !gzipfile )
716 send( "213 " + QString::number( fi.size() ) ); 718 send( "213 " + QString::number( fi.size() ) );
717 else { 719 else {
718 Process duproc( QString("du") ); 720 Process duproc( QString("du") );
719 duproc.addArgument("-s"); 721 duproc.addArgument("-s");
720 QString in, out; 722 QString in, out;
721 if ( !duproc.exec(in, out) ) { 723 if ( !duproc.exec(in, out) ) {
722 qDebug("du process failed; just sending back 1K"); 724 qDebug("du process failed; just sending back 1K");
723 send( "213 1024"); 725 send( "213 1024");
724 } 726 }
725 else { 727 else {
726 QString size = out.left( out.find("\t") ); 728 QString size = out.left( out.find("\t") );
727 int guess = size.toInt()/5; 729 int guess = size.toInt()/5;
728 if ( filePath.contains("doc") ) // No tr 730 if ( filePath.contains("doc") ) // No tr
729 guess *= 1000; 731 guess *= 1000;
730 qDebug("sending back gzip guess of %d", guess); 732 qDebug("sending back gzip guess of %d", guess);
731 send( "213 " + QString::number(guess) ); 733 send( "213 " + QString::number(guess) );
732 } 734 }
733 } 735 }
734 } 736 }
735 } 737 }
736 // name list (NLST) 738 // name list (NLST)
737 else if ( cmd == "NLST" ) { 739 else if ( cmd == "NLST" ) {
738 send( "502 Command not implemented" ); // No tr 740 send( "502 Command not implemented" ); // No tr
739 } 741 }
740 742
741 // site parameters (SITE) 743 // site parameters (SITE)
742 else if ( cmd == "SITE" ) { 744 else if ( cmd == "SITE" ) {
743 send( "502 Command not implemented" ); // No tr 745 send( "502 Command not implemented" ); // No tr
744 } 746 }
745 747
746 // system (SYST) 748 // system (SYST)
747 else if ( cmd == "SYST" ) { 749 else if ( cmd == "SYST" ) {
748 send( "215 UNIX Type: L8" ); // No tr 750 send( "215 UNIX Type: L8" ); // No tr
749 } 751 }
750 752
751 // status (STAT) 753 // status (STAT)
752 else if ( cmd == "STAT" ) { 754 else if ( cmd == "STAT" ) {
753 send( "502 Command not implemented" ); // No tr 755 send( "502 Command not implemented" ); // No tr
754 } 756 }
755 757
756 // help (HELP ) 758 // help (HELP )
757 else if ( cmd == "HELP" ) { 759 else if ( cmd == "HELP" ) {
758 send( "502 Command not implemented" ); // No tr 760 send( "502 Command not implemented" ); // No tr
759 } 761 }
760 762
761 // noop (NOOP) 763 // noop (NOOP)
762 else if ( cmd == "NOOP" ) { 764 else if ( cmd == "NOOP" ) {
763 send( "200 Command okay" ); // No tr 765 send( "200 Command okay" ); // No tr
764 } 766 }
765 767
766 // not implemented 768 // not implemented
767 else 769 else
768 send( "502 Command not implemented" ); // No tr 770 send( "502 Command not implemented" ); // No tr
769 771
770 lastCommand = cmd; 772 lastCommand = cmd;
771} 773}
772 774
773bool ServerPI::backupRestoreGzip( const QString &file ) 775bool ServerPI::backupRestoreGzip( const QString &file )
774{ 776{
775 return (file.find( "backup" ) != -1 && // No tr 777 return (file.find( "backup" ) != -1 && // No tr
776 file.findRev( ".tgz" ) == (int)file.length()-4 ); 778 file.findRev( ".tgz" ) == (int)file.length()-4 );
777} 779}
778 780
779bool ServerPI::backupRestoreGzip( const QString &file, QStringList &targets ) 781bool ServerPI::backupRestoreGzip( const QString &file, QStringList &targets )
780{ 782{
781 if ( file.find( "backup" ) != -1 && // No tr 783 if ( file.find( "backup" ) != -1 && // No tr
782 file.findRev( ".tgz" ) == (int)file.length()-4 ) { 784 file.findRev( ".tgz" ) == (int)file.length()-4 ) {
783 QFileInfo info( file ); 785 QFileInfo info( file );
784 targets = info.dirPath( TRUE ); 786 targets = info.dirPath( TRUE );
785 qDebug("ServerPI::backupRestoreGzip for %s = %s", file.latin1(), 787 qDebug("ServerPI::backupRestoreGzip for %s = %s", file.latin1(),
786 targets.join(" ").latin1() ); 788 targets.join(" ").latin1() );
787 return true; 789 return true;
788 } 790 }
789 return false; 791 return false;
790} 792}
791 793
792void ServerPI::sendFile( const QString& file ) 794void ServerPI::sendFile( const QString& file )
793{ 795{
794 if ( passiv ) { 796 if ( passiv ) {
795 wait[SendFile] = TRUE; 797 wait[SendFile] = TRUE;
796 waitfile = file; 798 waitfile = file;
797 if ( waitsocket ) 799 if ( waitsocket )
798 newConnection( waitsocket ); 800 newConnection( waitsocket );
799 } 801 }
800 else { 802 else {
801 QStringList targets; 803 QStringList targets;
802 if ( backupRestoreGzip( file, targets ) ) 804 if ( backupRestoreGzip( file, targets ) )
803 dtp->sendGzipFile( file, targets, peeraddress, peerport ); 805 dtp->sendGzipFile( file, targets, peeraddress, peerport );
804 else dtp->sendFile( file, peeraddress, peerport ); 806 else dtp->sendFile( file, peeraddress, peerport );
805 } 807 }
806} 808}
807 809
808void ServerPI::retrieveFile( const QString& file ) 810void ServerPI::retrieveFile( const QString& file )
809{ 811{
810 if ( passiv ) { 812 if ( passiv ) {
811 wait[RetrieveFile] = TRUE; 813 wait[RetrieveFile] = TRUE;
812 waitfile = file; 814 waitfile = file;
813 if ( waitsocket ) 815 if ( waitsocket )
814 newConnection( waitsocket ); 816 newConnection( waitsocket );
815 } 817 }
816 else { 818 else {
817 QStringList targets; 819 QStringList targets;
818 if ( backupRestoreGzip( file, targets ) ) 820 if ( backupRestoreGzip( file, targets ) )
819 dtp->retrieveGzipFile( file, peeraddress, peerport ); 821 dtp->retrieveGzipFile( file, peeraddress, peerport );
820 else 822 else
821 dtp->retrieveFile( file, peeraddress, peerport, storFileSize ); 823 dtp->retrieveFile( file, peeraddress, peerport, storFileSize );
822 } 824 }
823} 825}
824 826
825bool ServerPI::parsePort( const QString& pp ) 827bool ServerPI::parsePort( const QString& pp )
826{ 828{
827 QStringList p = QStringList::split( ",", pp ); 829 QStringList p = QStringList::split( ",", pp );
828 if ( p.count() != 6 ) return FALSE; 830 if ( p.count() != 6 ) return FALSE;
829 831
830 // h1,h2,h3,h4,p1,p2 832 // h1,h2,h3,h4,p1,p2
831 peeraddress = QHostAddress( ( p[0].toInt() << 24 ) + ( p[1].toInt() << 16 ) + 833 peeraddress = QHostAddress( ( p[0].toInt() << 24 ) + ( p[1].toInt() << 16 ) +
832 ( p[2].toInt() << 8 ) + p[3].toInt() ); 834 ( p[2].toInt() << 8 ) + p[3].toInt() );
833 peerport = ( p[4].toInt() << 8 ) + p[5].toInt(); 835 peerport = ( p[4].toInt() << 8 ) + p[5].toInt();
834 return TRUE; 836 return TRUE;
835} 837}
836 838
837void ServerPI::dtpCompleted() 839void ServerPI::dtpCompleted()
838{ 840{
839 send( "226 Closing data connection, file transfer successful" ); // No tr 841 send( "226 Closing data connection, file transfer successful" ); // No tr
840 if ( dtp->dtpMode() == ServerDTP::RetrieveFile ) { 842 if ( dtp->dtpMode() == ServerDTP::RetrieveFile ) {
841 QString fn = dtp->fileName(); 843 QString fn = dtp->fileName();
842 if ( fn.right(8)==".desktop" && fn.find("/Documents/")>=0 ) { 844 if ( fn.right(8)==".desktop" && fn.find("/Documents/")>=0 ) {
843 QCopEnvelope e("QPE/System", "linkChanged(QString)" ); 845 QCopEnvelope e("QPE/System", "linkChanged(QString)" );
844 e << fn; 846 e << fn;
845 } 847 }
846 } 848 }
847 waitsocket = 0; 849 waitsocket = 0;
848 dtp->close(); 850 dtp->close();
849 storFileSize = -1; 851 storFileSize = -1;
850} 852}
851 853
852void ServerPI::dtpFailed() 854void ServerPI::dtpFailed()
853{ 855{
854 dtp->close(); 856 dtp->close();
855 waitsocket = 0; 857 waitsocket = 0;
856 send( "451 Requested action aborted: local error in processing" ); // No tr 858 send( "451 Requested action aborted: local error in processing" ); // No tr
857 storFileSize = -1; 859 storFileSize = -1;
858} 860}
859 861
860void ServerPI::dtpError( int ) 862void ServerPI::dtpError( int )
861{ 863{
862 dtp->close(); 864 dtp->close();
863 waitsocket = 0; 865 waitsocket = 0;
864 send( "451 Requested action aborted: local error in processing" ); // No tr 866 send( "451 Requested action aborted: local error in processing" ); // No tr
865 storFileSize = -1; 867 storFileSize = -1;
866} 868}
867 869
868bool ServerPI::sendList( const QString& arg ) 870bool ServerPI::sendList( const QString& arg )
869{ 871{
870 QByteArray listing; 872 QByteArray listing;
871 QBuffer buffer( listing ); 873 QBuffer buffer( listing );
872 874
873 if ( !buffer.open( IO_WriteOnly ) ) 875 if ( !buffer.open( IO_WriteOnly ) )
874 return FALSE; 876 return FALSE;
875 877
876 QTextStream ts( &buffer ); 878 QTextStream ts( &buffer );
877 QString fn = arg; 879 QString fn = arg;
878 880
879 if ( fn.isEmpty() ) 881 if ( fn.isEmpty() )
880 fn = directory.path(); 882 fn = directory.path();
881 883
882 QFileInfo fi( fn ); 884 QFileInfo fi( fn );
883 if ( !fi.exists() ) return FALSE; 885 if ( !fi.exists() ) return FALSE;
884 886
885 // return file listing 887 // return file listing
886 if ( fi.isFile() ) { 888 if ( fi.isFile() ) {
887 ts << fileListing( &fi ) << endl; 889 ts << fileListing( &fi ) << endl;
888 } 890 }
889 891
890 // return directory listing 892 // return directory listing
891 else if ( fi.isDir() ) { 893 else if ( fi.isDir() ) {
892 QDir dir( fn ); 894 QDir dir( fn );
893 const QFileInfoList *list = dir.entryInfoList( QDir::All | QDir::Hidden ); 895 const QFileInfoList *list = dir.entryInfoList( QDir::All | QDir::Hidden );
894 896
895 QFileInfoListIterator it( *list ); 897 QFileInfoListIterator it( *list );
896 QFileInfo *info; 898 QFileInfo *info;
897 899
898 unsigned long total = 0; 900 unsigned long total = 0;
899 while ( ( info = it.current() ) ) { 901 while ( ( info = it.current() ) ) {
900 if ( info->fileName() != "." && info->fileName() != ".." ) 902 if ( info->fileName() != "." && info->fileName() != ".." )
901 total += info->size(); 903 total += info->size();
902 ++it; 904 ++it;
903 } 905 }
904 906
905 ts << "total " << QString::number( total / 1024 ) << endl; // No tr 907 ts << "total " << QString::number( total / 1024 ) << endl; // No tr
906 908
907 it.toFirst(); 909 it.toFirst();
908 while ( ( info = it.current() ) ) { 910 while ( ( info = it.current() ) ) {
909 if ( info->fileName() == "." || info->fileName() == ".." ) { 911 if ( info->fileName() == "." || info->fileName() == ".." ) {
910 ++it; 912 ++it;
911 continue; 913 continue;
912 } 914 }
913 ts << fileListing( info ) << endl; 915 ts << fileListing( info ) << endl;
914 ++it; 916 ++it;
915 } 917 }
916 } 918 }
917 919
918 if ( passiv ) { 920 if ( passiv ) {
919 waitarray = buffer.buffer(); 921 waitarray = buffer.buffer();
920 wait[SendByteArray] = TRUE; 922 wait[SendByteArray] = TRUE;
921 if ( waitsocket ) 923 if ( waitsocket )
922 newConnection( waitsocket ); 924 newConnection( waitsocket );
923 } 925 }
924 else 926 else
925 dtp->sendByteArray( buffer.buffer(), peeraddress, peerport ); 927 dtp->sendByteArray( buffer.buffer(), peeraddress, peerport );
926 return TRUE; 928 return TRUE;
927} 929}
928 930
929QString ServerPI::fileListing( QFileInfo *info ) 931QString ServerPI::fileListing( QFileInfo *info )
930{ 932{
931 if ( !info ) return QString::null; 933 if ( !info ) return QString::null;
932 QString s; 934 QString s;
933 935
934 // type char 936 // type char
935 if ( info->isDir() ) 937 if ( info->isDir() )
936 s += "d"; 938 s += "d";
937 else if ( info->isSymLink() ) 939 else if ( info->isSymLink() )
938 s += "l"; 940 s += "l";
939 else 941 else
940 s += "-"; 942 s += "-";
941 943
942 // permisson string 944 // permisson string
943 s += permissionString( info ) + " "; 945 s += permissionString( info ) + " ";
944 946
945 // number of hardlinks 947 // number of hardlinks
946 int subdirs = 1; 948 int subdirs = 1;
947 949
948 if ( info->isDir() ) 950 if ( info->isDir() )
949 subdirs = 2; 951 subdirs = 2;
950 // FIXME : this is to slow 952 // FIXME : this is to slow
951 //if ( info->isDir() ) 953 //if ( info->isDir() )
952 //subdirs = QDir( info->absFilePath() ).entryList( QDir::Dirs ).count(); 954 //subdirs = QDir( info->absFilePath() ).entryList( QDir::Dirs ).count();
953 955
954 s += QString::number( subdirs ).rightJustify( 3, ' ', TRUE ) + " "; 956 s += QString::number( subdirs ).rightJustify( 3, ' ', TRUE ) + " ";
955 957
956 // owner 958 // owner
957 QString o = info->owner(); 959 QString o = info->owner();
958 if ( o.isEmpty() ) 960 if ( o.isEmpty() )
959 o = QString::number(info->ownerId()); 961 o = QString::number(info->ownerId());
960 s += o.leftJustify( 8, ' ', TRUE ) + " "; 962 s += o.leftJustify( 8, ' ', TRUE ) + " ";
961 963
962 // group 964 // group
963 QString g = info->group(); 965 QString g = info->group();
964 if ( g.isEmpty() ) 966 if ( g.isEmpty() )
965 g = QString::number(info->groupId()); 967 g = QString::number(info->groupId());
966 s += g.leftJustify( 8, ' ', TRUE ) + " "; 968 s += g.leftJustify( 8, ' ', TRUE ) + " ";
967 969
968 // file size in bytes 970 // file size in bytes
969 s += QString::number( info->size() ).rightJustify( 9, ' ', TRUE ) + " "; 971 s += QString::number( info->size() ).rightJustify( 9, ' ', TRUE ) + " ";
970 972
971 // last modified date 973 // last modified date
972 QDate date = info->lastModified().date(); 974 QDate date = info->lastModified().date();
973 QTime time = info->lastModified().time(); 975 QTime time = info->lastModified().time();
974 s += date.monthName( date.month() ) + " " 976 s += date.monthName( date.month() ) + " "
975 + QString::number( date.day() ).rightJustify( 2, ' ', TRUE ) + " " 977 + QString::number( date.day() ).rightJustify( 2, ' ', TRUE ) + " "
976 + QString::number( time.hour() ).rightJustify( 2, '0', TRUE ) + ":" 978 + QString::number( time.hour() ).rightJustify( 2, '0', TRUE ) + ":"
977 + QString::number( time.minute() ).rightJustify( 2,'0', TRUE ) + " "; 979 + QString::number( time.minute() ).rightJustify( 2,'0', TRUE ) + " ";
978 980
979 // file name 981 // file name
980 s += info->fileName(); 982 s += info->fileName();
981 983
982 return s; 984 return s;
983} 985}
984 986
985QString ServerPI::permissionString( QFileInfo *info ) 987QString ServerPI::permissionString( QFileInfo *info )
986{ 988{
987 if ( !info ) return QString( "---------" ); 989 if ( !info ) return QString( "---------" );
988 QString s; 990 QString s;
989 991
990 // user 992 // user
991 if ( info->permission( QFileInfo::ReadUser ) ) s += "r"; 993 if ( info->permission( QFileInfo::ReadUser ) ) s += "r";
992 else s += "-"; 994 else s += "-";
993 if ( info->permission( QFileInfo::WriteUser ) ) s += "w"; 995 if ( info->permission( QFileInfo::WriteUser ) ) s += "w";
994 else s += "-"; 996 else s += "-";
995 if ( info->permission( QFileInfo::ExeUser ) ) s += "x"; 997 if ( info->permission( QFileInfo::ExeUser ) ) s += "x";
996 else s += "-"; 998 else s += "-";
997 999
998 // group 1000 // group
999 if ( info->permission( QFileInfo::ReadGroup ) ) s += "r"; 1001 if ( info->permission( QFileInfo::ReadGroup ) ) s += "r";
1000 else s += "-"; 1002 else s += "-";
1001 if ( info->permission( QFileInfo::WriteGroup ) )s += "w"; 1003 if ( info->permission( QFileInfo::WriteGroup ) )s += "w";
1002 else s += "-"; 1004 else s += "-";
1003 if ( info->permission( QFileInfo::ExeGroup ) ) s += "x"; 1005 if ( info->permission( QFileInfo::ExeGroup ) ) s += "x";
1004 else s += "-"; 1006 else s += "-";
1005 1007
1006 // exec 1008 // exec
1007 if ( info->permission( QFileInfo::ReadOther ) ) s += "r"; 1009 if ( info->permission( QFileInfo::ReadOther ) ) s += "r";
1008 else s += "-"; 1010 else s += "-";
1009 if ( info->permission( QFileInfo::WriteOther ) ) s += "w"; 1011 if ( info->permission( QFileInfo::WriteOther ) ) s += "w";
1010 else s += "-"; 1012 else s += "-";
1011 if ( info->permission( QFileInfo::ExeOther ) ) s += "x"; 1013 if ( info->permission( QFileInfo::ExeOther ) ) s += "x";
1012 else s += "-"; 1014 else s += "-";
1013 1015
1014 return s; 1016 return s;
1015} 1017}
1016 1018
1017void ServerPI::newConnection( int socket ) 1019void ServerPI::newConnection( int socket )
1018{ 1020{
1019 //qDebug( "New incomming connection" ); 1021 //qDebug( "New incomming connection" );
1020 1022
1021 if ( !passiv ) return; 1023 if ( !passiv ) return;
1022 1024
1023 if ( wait[SendFile] ) { 1025 if ( wait[SendFile] ) {
1024 QStringList targets; 1026 QStringList targets;
1025 if ( backupRestoreGzip( waitfile, targets ) ) 1027 if ( backupRestoreGzip( waitfile, targets ) )
1026 dtp->sendGzipFile( waitfile, targets ); 1028 dtp->sendGzipFile( waitfile, targets );
1027 else 1029 else
1028 dtp->sendFile( waitfile ); 1030 dtp->sendFile( waitfile );
1029 dtp->setSocket( socket ); 1031 dtp->setSocket( socket );
1030 } 1032 }
1031 else if ( wait[RetrieveFile] ) { 1033 else if ( wait[RetrieveFile] ) {
1032 qDebug("check retrieve file"); 1034 qDebug("check retrieve file");
1033 if ( backupRestoreGzip( waitfile ) ) 1035 if ( backupRestoreGzip( waitfile ) )
1034 dtp->retrieveGzipFile( waitfile ); 1036 dtp->retrieveGzipFile( waitfile );
1035 else 1037 else
1036 dtp->retrieveFile( waitfile, storFileSize ); 1038 dtp->retrieveFile( waitfile, storFileSize );
1037 dtp->setSocket( socket ); 1039 dtp->setSocket( socket );
1038 } 1040 }
1039 else if ( wait[SendByteArray] ) { 1041 else if ( wait[SendByteArray] ) {
1040 dtp->sendByteArray( waitarray ); 1042 dtp->sendByteArray( waitarray );
1041 dtp->setSocket( socket ); 1043 dtp->setSocket( socket );
1042 } 1044 }
1043 else if ( wait[RetrieveByteArray] ) { 1045 else if ( wait[RetrieveByteArray] ) {
1044 qDebug("retrieve byte array"); 1046 qDebug("retrieve byte array");
1045 dtp->retrieveByteArray(); 1047 dtp->retrieveByteArray();
1046 dtp->setSocket( socket ); 1048 dtp->setSocket( socket );
1047 } 1049 }
1048 else 1050 else
1049 waitsocket = socket; 1051 waitsocket = socket;
1050 1052
1051 for( int i = 0; i < 4; i++ ) 1053 for( int i = 0; i < 4; i++ )
1052 wait[i] = FALSE; 1054 wait[i] = FALSE;
1053} 1055}
1054 1056
1055QString ServerPI::absFilePath( const QString& file ) 1057QString ServerPI::absFilePath( const QString& file )
1056{ 1058{
1057 if ( file.isEmpty() ) return file; 1059 if ( file.isEmpty() ) return file;
1058 1060
1059 QString filepath( file ); 1061 QString filepath( file );
1060 if ( file[0] != "/" ) 1062 if ( file[0] != "/" )
1061 filepath = directory.path() + "/" + file; 1063 filepath = directory.path() + "/" + file;
1062 1064
1063 return filepath; 1065 return filepath;
1064} 1066}
1065 1067
1066 1068
1067void ServerPI::timerEvent( QTimerEvent * ) 1069void ServerPI::timerEvent( QTimerEvent * )
1068{ 1070{
1069 connectionClosed(); 1071 connectionClosed();
1070} 1072}
1071 1073
1072 1074
1073ServerDTP::ServerDTP( QObject *parent, const char* name) 1075ServerDTP::ServerDTP( QObject *parent, const char* name)
1074 : QSocket( parent, name ), mode( Idle ), createTargzProc( 0 ), 1076 : QSocket( parent, name ), mode( Idle ), createTargzProc( 0 ),
1075 retrieveTargzProc( 0 ) 1077 retrieveTargzProc( 0 )
1076{ 1078{
1077 1079
1078 connect( this, SIGNAL( connected() ), SLOT( connected() ) ); 1080 connect( this, SIGNAL( connected() ), SLOT( connected() ) );
1079 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) ); 1081 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) );
1080 connect( this, SIGNAL( bytesWritten( int ) ), SLOT( bytesWritten( int ) ) ); 1082 connect( this, SIGNAL( bytesWritten( int ) ), SLOT( bytesWritten( int ) ) );
1081 connect( this, SIGNAL( readyRead() ), SLOT( readyRead() ) ); 1083 connect( this, SIGNAL( readyRead() ), SLOT( readyRead() ) );
1082 1084
1083 createTargzProc = new QProcess( QString("tar"), this, "createTargzProc"); // No tr 1085 createTargzProc = new QProcess( QString("tar"), this, "createTargzProc"); // No tr
1084 createTargzProc->setCommunication( QProcess::Stdout ); 1086 createTargzProc->setCommunication( QProcess::Stdout );
1085 createTargzProc->setWorkingDirectory( QDir::rootDirPath() ); 1087 createTargzProc->setWorkingDirectory( QDir::rootDirPath() );
1086 connect( createTargzProc, SIGNAL( processExited() ), SLOT( targzDone() ) ); 1088 connect( createTargzProc, SIGNAL( processExited() ), SLOT( targzDone() ) );
1087 1089
1088 retrieveTargzProc = new QProcess( this, "retrieveTargzProc" ); 1090 retrieveTargzProc = new QProcess( this, "retrieveTargzProc" );
1089 retrieveTargzProc->setCommunication( QProcess::Stdin ); 1091 retrieveTargzProc->setCommunication( QProcess::Stdin );
1090 retrieveTargzProc->setWorkingDirectory( QDir::rootDirPath() ); 1092 retrieveTargzProc->setWorkingDirectory( QDir::rootDirPath() );
1091 connect( retrieveTargzProc, SIGNAL( processExited() ), 1093 connect( retrieveTargzProc, SIGNAL( processExited() ),
1092 SIGNAL( completed() ) ); 1094 SIGNAL( completed() ) );
1093 connect( retrieveTargzProc, SIGNAL( processExited() ), 1095 connect( retrieveTargzProc, SIGNAL( processExited() ),
1094 SLOT( extractTarDone() ) ); 1096 SLOT( extractTarDone() ) );
1095} 1097}
1096 1098
1097ServerDTP::~ServerDTP() 1099ServerDTP::~ServerDTP()
1098{ 1100{
1099 buf.close(); 1101 buf.close();
1100 if ( RetrieveFile == mode && file.isOpen() ) { 1102 if ( RetrieveFile == mode && file.isOpen() ) {
1101 // We're being shutdown before the client closed. 1103 // We're being shutdown before the client closed.
1102 file.close(); 1104 file.close();
1103 if ( recvFileSize >= 0 && (int)file.size() != recvFileSize ) { 1105 if ( recvFileSize >= 0 && (int)file.size() != recvFileSize ) {
1104 qDebug( "STOR incomplete" ); 1106 qDebug( "STOR incomplete" );
1105 file.remove(); 1107 file.remove();
1106 } 1108 }
1107 } else { 1109 } else {
1108 file.close(); 1110 file.close();
1109 } 1111 }
1110 createTargzProc->kill(); 1112 createTargzProc->kill();
1111} 1113}
1112 1114
1113void ServerDTP::extractTarDone() 1115void ServerDTP::extractTarDone()
1114{ 1116{
1115 qDebug("extract done"); 1117 qDebug("extract done");
1116#ifndef QT_NO_COP 1118#ifndef QT_NO_COP
1117 QCopEnvelope e( "QPE/System", "restoreDone(QString)" ); 1119 QCopEnvelope e( "QPE/System", "restoreDone(QString)" );
1118 e << file.name(); 1120 e << file.name();
1119#endif 1121#endif
1120} 1122}
1121 1123
1122void ServerDTP::connected() 1124void ServerDTP::connected()
1123{ 1125{
1124 // send file mode 1126 // send file mode
1125 switch ( mode ) { 1127 switch ( mode ) {
1126 case SendFile : 1128 case SendFile :
1127 if ( !file.exists() || !file.open( IO_ReadOnly) ) { 1129 if ( !file.exists() || !file.open( IO_ReadOnly) ) {
1128 emit failed(); 1130 emit failed();
1129 mode = Idle; 1131 mode = Idle;
1130 return; 1132 return;
1131 } 1133 }
1132 1134
1133 //qDebug( "Debug: Sending file '%s'", file.name().latin1() ); 1135 //qDebug( "Debug: Sending file '%s'", file.name().latin1() );
1134 1136
1135 bytes_written = 0; 1137 bytes_written = 0;
1136 if ( file.size() == 0 ) { 1138 if ( file.size() == 0 ) {
1137 //make sure it doesn't hang on empty files 1139 //make sure it doesn't hang on empty files
1138 file.close(); 1140 file.close();
1139 emit completed(); 1141 emit completed();
1140 mode = Idle; 1142 mode = Idle;
1141 } else { 1143 } else {
1142 // Don't write more if there is plenty buffered already. 1144 // Don't write more if there is plenty buffered already.
1143 if ( bytesToWrite() <= block_size && !file.atEnd() ) { 1145 if ( bytesToWrite() <= block_size && !file.atEnd() ) {
1144 QCString s; 1146 QCString s;
1145 s.resize( block_size ); 1147 s.resize( block_size );
1146 int bytes = file.readBlock( s.data(), block_size ); 1148 int bytes = file.readBlock( s.data(), block_size );
1147 writeBlock( s.data(), bytes ); 1149 writeBlock( s.data(), bytes );
1148 } 1150 }
1149 } 1151 }
1150 break; 1152 break;
1151 case SendGzipFile: 1153 case SendGzipFile:
1152 if ( createTargzProc->isRunning() ) { 1154 if ( createTargzProc->isRunning() ) {
1153 // SHOULDN'T GET HERE, BUT DOING A SAFETY CHECK ANYWAY 1155 // SHOULDN'T GET HERE, BUT DOING A SAFETY CHECK ANYWAY
1154 qWarning("Previous tar --gzip process is still running; killing it..."); 1156 qWarning("Previous tar --gzip process is still running; killing it...");
1155 createTargzProc->kill(); 1157 createTargzProc->kill();
1156 } 1158 }
1157 1159
1158 bytes_written = 0; 1160 bytes_written = 0;
1159 qDebug("==>start send tar process"); 1161 qDebug("==>start send tar process");
1160 if ( !createTargzProc->start() ) 1162 if ( !createTargzProc->start() )
1161 qWarning("Error starting %s", 1163 qWarning("Error starting %s",
1162 createTargzProc->arguments().join(" ").latin1()); 1164 createTargzProc->arguments().join(" ").latin1());
1163 break; 1165 break;
1164 case SendBuffer: 1166 case SendBuffer:
1165 if ( !buf.open( IO_ReadOnly) ) { 1167 if ( !buf.open( IO_ReadOnly) ) {
1166 emit failed(); 1168 emit failed();
1167 mode = Idle; 1169 mode = Idle;
1168 return; 1170 return;
1169 } 1171 }
1170 1172
1171 // qDebug( "Debug: Sending byte array" ); 1173 // qDebug( "Debug: Sending byte array" );
1172 bytes_written = 0; 1174 bytes_written = 0;
1173 while( !buf.atEnd() ) 1175 while( !buf.atEnd() )
1174 putch( buf.getch() ); 1176 putch( buf.getch() );
1175 buf.close(); 1177 buf.close();
1176 break; 1178 break;
1177 case RetrieveFile: 1179 case RetrieveFile:
1178 // retrieve file mode 1180 // retrieve file mode
1179 if ( file.exists() && !file.remove() ) { 1181 if ( file.exists() && !file.remove() ) {
1180 emit failed(); 1182 emit failed();
1181 mode = Idle; 1183 mode = Idle;
1182 return; 1184 return;
1183 } 1185 }
1184 1186
1185 if ( !file.open( IO_WriteOnly) ) { 1187 if ( !file.open( IO_WriteOnly) ) {
1186 emit failed(); 1188 emit failed();
1187 mode = Idle; 1189 mode = Idle;
1188 return; 1190 return;
1189 } 1191 }
1190 // qDebug( "Debug: Retrieving file %s", file.name().latin1() ); 1192 // qDebug( "Debug: Retrieving file %s", file.name().latin1() );
1191 break; 1193 break;
1192 case RetrieveGzipFile: 1194 case RetrieveGzipFile:
1193 qDebug("=-> starting tar process to receive .tgz file"); 1195 qDebug("=-> starting tar process to receive .tgz file");
1194 break; 1196 break;
1195 case RetrieveBuffer: 1197 case RetrieveBuffer:
1196 // retrieve buffer mode 1198 // retrieve buffer mode
1197 if ( !buf.open( IO_WriteOnly) ) { 1199 if ( !buf.open( IO_WriteOnly) ) {
1198 emit failed(); 1200 emit failed();
1199 mode = Idle; 1201 mode = Idle;
1200 return; 1202 return;
1201 } 1203 }
1202 // qDebug( "Debug: Retrieving byte array" ); 1204 // qDebug( "Debug: Retrieving byte array" );
1203 break; 1205 break;
1204 case Idle: 1206 case Idle:
1205 qDebug("connection established but mode set to Idle; BUG!"); 1207 qDebug("connection established but mode set to Idle; BUG!");
1206 break; 1208 break;
1207 } 1209 }
1208} 1210}
1209 1211
1210void ServerDTP::connectionClosed() 1212void ServerDTP::connectionClosed()
1211{ 1213{
1212 //qDebug( "Debug: Data connection closed %ld bytes written", bytes_written ); 1214 //qDebug( "Debug: Data connection closed %ld bytes written", bytes_written );
1213 1215
1214 // send file mode 1216 // send file mode
1215 if ( SendFile == mode ) { 1217 if ( SendFile == mode ) {
1216 if ( bytes_written == file.size() ) 1218 if ( bytes_written == file.size() )
1217 emit completed(); 1219 emit completed();
1218 else 1220 else
1219 emit failed(); 1221 emit failed();
1220 } 1222 }
1221 1223
1222 // send buffer mode 1224 // send buffer mode
1223 else if ( SendBuffer == mode ) { 1225 else if ( SendBuffer == mode ) {
1224 if ( bytes_written == buf.size() ) 1226 if ( bytes_written == buf.size() )
1225 emit completed(); 1227 emit completed();
1226 else 1228 else
1227 emit failed(); 1229 emit failed();
1228 } 1230 }
1229 1231
1230 // retrieve file mode 1232 // retrieve file mode
1231 else if ( RetrieveFile == mode ) { 1233 else if ( RetrieveFile == mode ) {
1232 file.close(); 1234 file.close();
1233 if ( recvFileSize >= 0 && (int)file.size() != recvFileSize ) { 1235 if ( recvFileSize >= 0 && (int)file.size() != recvFileSize ) {
1234 qDebug( "STOR incomplete" ); 1236 qDebug( "STOR incomplete" );
1235 file.remove(); 1237 file.remove();
1236 emit failed(); 1238 emit failed();
1237 } else { 1239 } else {
1238 emit completed(); 1240 emit completed();
1239 } 1241 }
1240 } 1242 }
1241 1243
1242 else if ( RetrieveGzipFile == mode ) { 1244 else if ( RetrieveGzipFile == mode ) {
1243 qDebug("Done writing ungzip file; closing input"); 1245 qDebug("Done writing ungzip file; closing input");
1244 retrieveTargzProc->flushStdin(); 1246 retrieveTargzProc->flushStdin();
1245 retrieveTargzProc->closeStdin(); 1247 retrieveTargzProc->closeStdin();
1246 } 1248 }
1247 1249
1248 // retrieve buffer mode 1250 // retrieve buffer mode
1249 else if ( RetrieveBuffer == mode ) { 1251 else if ( RetrieveBuffer == mode ) {
1250 buf.close(); 1252 buf.close();
1251 emit completed(); 1253 emit completed();
1252 } 1254 }
1253 1255
1254 mode = Idle; 1256 mode = Idle;
1255} 1257}
1256 1258
1257void ServerDTP::bytesWritten( int bytes ) 1259void ServerDTP::bytesWritten( int bytes )
1258{ 1260{
1259 bytes_written += bytes; 1261 bytes_written += bytes;
1260 1262
1261 // send file mode 1263 // send file mode
1262 if ( SendFile == mode ) { 1264 if ( SendFile == mode ) {
1263 1265
1264 if ( bytes_written == file.size() ) { 1266 if ( bytes_written == file.size() ) {
1265 // qDebug( "Debug: Sending complete: %d bytes", file.size() ); 1267 // qDebug( "Debug: Sending complete: %d bytes", file.size() );
1266 file.close(); 1268 file.close();
1267 emit completed(); 1269 emit completed();
1268 mode = Idle; 1270 mode = Idle;
1269 } 1271 }
1270 else if( !file.atEnd() ) { 1272 else if( !file.atEnd() ) {
1271 QCString s; 1273 QCString s;
1272 s.resize( block_size ); 1274 s.resize( block_size );
1273 int bytes = file.readBlock( s.data(), block_size ); 1275 int bytes = file.readBlock( s.data(), block_size );
1274 writeBlock( s.data(), bytes ); 1276 writeBlock( s.data(), bytes );
1275 } 1277 }
1276 } 1278 }
1277 1279
1278 // send buffer mode 1280 // send buffer mode
1279 if ( SendBuffer == mode ) { 1281 if ( SendBuffer == mode ) {
1280 1282
1281 if ( bytes_written == buf.size() ) { 1283 if ( bytes_written == buf.size() ) {
1282 // qDebug( "Debug: Sending complete: %d bytes", buf.size() ); 1284 // qDebug( "Debug: Sending complete: %d bytes", buf.size() );
1283 emit completed(); 1285 emit completed();
1284 mode = Idle; 1286 mode = Idle;
1285 } 1287 }
1286 } 1288 }
1287} 1289}
1288 1290
1289void ServerDTP::readyRead() 1291void ServerDTP::readyRead()
1290{ 1292{
1291 // retrieve file mode 1293 // retrieve file mode
1292 if ( RetrieveFile == mode ) { 1294 if ( RetrieveFile == mode ) {
1293 QCString s; 1295 QCString s;
1294 s.resize( bytesAvailable() ); 1296 s.resize( bytesAvailable() );
1295 readBlock( s.data(), bytesAvailable() ); 1297 readBlock( s.data(), bytesAvailable() );
1296 file.writeBlock( s.data(), s.size() ); 1298 file.writeBlock( s.data(), s.size() );
1297 } 1299 }
1298 else if ( RetrieveGzipFile == mode ) { 1300 else if ( RetrieveGzipFile == mode ) {
1299 if ( !retrieveTargzProc->isRunning() ) 1301 if ( !retrieveTargzProc->isRunning() )
1300 retrieveTargzProc->start(); 1302 retrieveTargzProc->start();
1301 1303
1302 QByteArray s; 1304 QByteArray s;
1303 s.resize( bytesAvailable() ); 1305 s.resize( bytesAvailable() );
1304 readBlock( s.data(), bytesAvailable() ); 1306 readBlock( s.data(), bytesAvailable() );
1305 retrieveTargzProc->writeToStdin( s ); 1307 retrieveTargzProc->writeToStdin( s );
1306 qDebug("wrote %d bytes to ungzip ", s.size() ); 1308 qDebug("wrote %d bytes to ungzip ", s.size() );
1307 } 1309 }
1308 // retrieve buffer mode 1310 // retrieve buffer mode
1309 else if ( RetrieveBuffer == mode ) { 1311 else if ( RetrieveBuffer == mode ) {
1310 QCString s; 1312 QCString s;
1311 s.resize( bytesAvailable() ); 1313 s.resize( bytesAvailable() );
1312 readBlock( s.data(), bytesAvailable() ); 1314 readBlock( s.data(), bytesAvailable() );
1313 buf.writeBlock( s.data(), s.size() ); 1315 buf.writeBlock( s.data(), s.size() );
1314 } 1316 }
1315} 1317}
1316 1318
1317void ServerDTP::writeTargzBlock() 1319void ServerDTP::writeTargzBlock()
1318{ 1320{
1319 QByteArray block = createTargzProc->readStdout(); 1321 QByteArray block = createTargzProc->readStdout();
1320 writeBlock( block.data(), block.size() ); 1322 writeBlock( block.data(), block.size() );
1321 qDebug("writeTargzBlock %d", block.size()); 1323 qDebug("writeTargzBlock %d", block.size());
1322} 1324}
1323 1325
1324void ServerDTP::targzDone() 1326void ServerDTP::targzDone()
1325{ 1327{
1326 qDebug("tar and gzip done"); 1328 qDebug("tar and gzip done");
1327 emit completed(); 1329 emit completed();
1328 mode = Idle; 1330 mode = Idle;
1329 disconnect( createTargzProc, SIGNAL( readyReadStdout() ), 1331 disconnect( createTargzProc, SIGNAL( readyReadStdout() ),
1330 this, SLOT( writeTargzBlock() ) ); 1332 this, SLOT( writeTargzBlock() ) );
1331} 1333}
1332 1334
1333void ServerDTP::sendFile( const QString fn, const QHostAddress& host, Q_UINT16 port ) 1335void ServerDTP::sendFile( const QString fn, const QHostAddress& host, Q_UINT16 port )
1334{ 1336{
1335 file.setName( fn ); 1337 file.setName( fn );
1336 mode = SendFile; 1338 mode = SendFile;
1337 connectToHost( host.toString(), port ); 1339 connectToHost( host.toString(), port );
1338} 1340}
1339 1341
1340void ServerDTP::sendFile( const QString fn ) 1342void ServerDTP::sendFile( const QString fn )
1341{ 1343{
1342 file.setName( fn ); 1344 file.setName( fn );
1343 mode = SendFile; 1345 mode = SendFile;
1344} 1346}
1345 1347
1346void ServerDTP::sendGzipFile( const QString &fn, 1348void ServerDTP::sendGzipFile( const QString &fn,
1347 const QStringList &archiveTargets, 1349 const QStringList &archiveTargets,
1348 const QHostAddress& host, Q_UINT16 port ) 1350 const QHostAddress& host, Q_UINT16 port )
1349{ 1351{
1350 sendGzipFile( fn, archiveTargets ); 1352 sendGzipFile( fn, archiveTargets );
1351 connectToHost( host.toString(), port ); 1353 connectToHost( host.toString(), port );
1352} 1354}
1353 1355
1354void ServerDTP::sendGzipFile( const QString &fn, 1356void ServerDTP::sendGzipFile( const QString &fn,
1355 const QStringList &archiveTargets ) 1357 const QStringList &archiveTargets )
1356{ 1358{
1357 mode = SendGzipFile; 1359 mode = SendGzipFile;
1358 file.setName( fn ); 1360 file.setName( fn );
1359 1361
1360 QStringList args = "targzip"; 1362 QStringList args = "targzip";
1361 //args += "-cv"; 1363 //args += "-cv";
1362 args += archiveTargets; 1364 args += archiveTargets;
1363 qDebug("sendGzipFile %s", args.join(" ").latin1() ); 1365 qDebug("sendGzipFile %s", args.join(" ").latin1() );
1364 createTargzProc->setArguments( args ); 1366 createTargzProc->setArguments( args );
1365 connect( createTargzProc, 1367 connect( createTargzProc,
1366 SIGNAL( readyReadStdout() ), SLOT( writeTargzBlock() ) ); 1368 SIGNAL( readyReadStdout() ), SLOT( writeTargzBlock() ) );
1367} 1369}
1368 1370
1369void ServerDTP::retrieveFile( const QString fn, const QHostAddress& host, Q_UINT16 port, int fileSize ) 1371void ServerDTP::retrieveFile( const QString fn, const QHostAddress& host, Q_UINT16 port, int fileSize )
1370{ 1372{
1371 recvFileSize = fileSize; 1373 recvFileSize = fileSize;
1372 file.setName( fn ); 1374 file.setName( fn );
1373 mode = RetrieveFile; 1375 mode = RetrieveFile;
1374 connectToHost( host.toString(), port ); 1376 connectToHost( host.toString(), port );
1375} 1377}
1376 1378
1377void ServerDTP::retrieveFile( const QString fn, int fileSize ) 1379void ServerDTP::retrieveFile( const QString fn, int fileSize )
1378{ 1380{
1379 recvFileSize = fileSize; 1381 recvFileSize = fileSize;
1380 file.setName( fn ); 1382 file.setName( fn );
1381 mode = RetrieveFile; 1383 mode = RetrieveFile;
1382} 1384}
1383 1385
1384void ServerDTP::retrieveGzipFile( const QString &fn ) 1386void ServerDTP::retrieveGzipFile( const QString &fn )
1385{ 1387{
1386 qDebug("retrieveGzipFile %s", fn.latin1()); 1388 qDebug("retrieveGzipFile %s", fn.latin1());
1387 file.setName( fn ); 1389 file.setName( fn );
1388 mode = RetrieveGzipFile; 1390 mode = RetrieveGzipFile;
1389 1391
1390 retrieveTargzProc->setArguments( "targunzip" ); 1392 retrieveTargzProc->setArguments( "targunzip" );
1391 connect( retrieveTargzProc, SIGNAL( processExited() ), 1393 connect( retrieveTargzProc, SIGNAL( processExited() ),
1392 SLOT( extractTarDone() ) ); 1394 SLOT( extractTarDone() ) );
1393} 1395}
1394 1396
1395void ServerDTP::retrieveGzipFile( const QString &fn, const QHostAddress& host, Q_UINT16 port ) 1397void ServerDTP::retrieveGzipFile( const QString &fn, const QHostAddress& host, Q_UINT16 port )
1396{ 1398{
1397 retrieveGzipFile( fn ); 1399 retrieveGzipFile( fn );
1398 connectToHost( host.toString(), port ); 1400 connectToHost( host.toString(), port );
1399} 1401}
1400 1402
1401void ServerDTP::sendByteArray( const QByteArray& array, const QHostAddress& host, Q_UINT16 port ) 1403void ServerDTP::sendByteArray( const QByteArray& array, const QHostAddress& host, Q_UINT16 port )
1402{ 1404{
1403 buf.setBuffer( array ); 1405 buf.setBuffer( array );
1404 mode = SendBuffer; 1406 mode = SendBuffer;
1405 connectToHost( host.toString(), port ); 1407 connectToHost( host.toString(), port );
1406} 1408}
1407 1409
1408void ServerDTP::sendByteArray( const QByteArray& array ) 1410void ServerDTP::sendByteArray( const QByteArray& array )
1409{ 1411{
1410 buf.setBuffer( array ); 1412 buf.setBuffer( array );
1411 mode = SendBuffer; 1413 mode = SendBuffer;
1412} 1414}
1413 1415
1414void ServerDTP::retrieveByteArray( const QHostAddress& host, Q_UINT16 port ) 1416void ServerDTP::retrieveByteArray( const QHostAddress& host, Q_UINT16 port )
1415{ 1417{
1416 buf.setBuffer( QByteArray() ); 1418 buf.setBuffer( QByteArray() );
1417 mode = RetrieveBuffer; 1419 mode = RetrieveBuffer;
1418 connectToHost( host.toString(), port ); 1420 connectToHost( host.toString(), port );
1419} 1421}
1420 1422
1421void ServerDTP::retrieveByteArray() 1423void ServerDTP::retrieveByteArray()
1422{ 1424{
1423 buf.setBuffer( QByteArray() ); 1425 buf.setBuffer( QByteArray() );
1424 mode = RetrieveBuffer; 1426 mode = RetrieveBuffer;
1425} 1427}
1426 1428
1427void ServerDTP::setSocket( int socket ) 1429void ServerDTP::setSocket( int socket )
1428{ 1430{
1429 QSocket::setSocket( socket ); 1431 QSocket::setSocket( socket );
1430 connected(); 1432 connected();
1431} 1433}
1432 1434