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