summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/qcopbridge.cpp4
-rw-r--r--core/launcher/transferserver.cpp5
2 files changed, 7 insertions, 2 deletions
diff --git a/core/launcher/qcopbridge.cpp b/core/launcher/qcopbridge.cpp
index e339dc7..64eb096 100644
--- a/core/launcher/qcopbridge.cpp
+++ b/core/launcher/qcopbridge.cpp
@@ -1,490 +1,492 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of the Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20 20
21#include "qcopbridge.h" 21#include "qcopbridge.h"
22#include "transferserver.h" 22#include "transferserver.h"
23 23
24/* OPIE */ 24/* OPIE */
25#include <opie2/odebug.h> 25#include <opie2/odebug.h>
26#include <opie2/oglobal.h> 26#include <opie2/oglobal.h>
27#ifdef Q_WS_QWS 27#ifdef Q_WS_QWS
28#include <qtopia/qcopenvelope_qws.h> 28#include <qtopia/qcopenvelope_qws.h>
29#endif 29#endif
30#include <qtopia/qpeapplication.h> 30#include <qtopia/qpeapplication.h>
31#include <qtopia/version.h> 31#include <qtopia/version.h>
32using namespace Opie::Core; 32using namespace Opie::Core;
33 33
34/* QT */ 34/* QT */
35#include <qtextstream.h> 35#include <qtextstream.h>
36#include <qtimer.h> 36#include <qtimer.h>
37#ifdef Q_WS_QWS 37#ifdef Q_WS_QWS
38#include <qcopchannel_qws.h> 38#include <qcopchannel_qws.h>
39#endif 39#endif
40 40
41/* STD */ 41/* STD */
42#ifndef _XOPEN_SOURCE 42#ifndef _XOPEN_SOURCE
43#define _XOPEN_SOURCE 43#define _XOPEN_SOURCE
44#endif 44#endif
45#ifndef Q_OS_WIN32 45#ifndef Q_OS_WIN32
46#include <pwd.h> 46#include <pwd.h>
47#include <unistd.h> 47#include <unistd.h>
48#include <fcntl.h>
48#include <sys/types.h> 49#include <sys/types.h>
49#endif 50#endif
50 51
51#if defined(_OS_LINUX_) 52#if defined(_OS_LINUX_)
52#include <shadow.h> 53#include <shadow.h>
53#endif 54#endif
54 55
55const int block_size = 51200; 56const int block_size = 51200;
56 57
57QCopBridge::QCopBridge( Q_UINT16 port, QObject *parent, 58QCopBridge::QCopBridge( Q_UINT16 port, QObject *parent,
58 const char* name ) 59 const char* name )
59 : QServerSocket( port, 1, parent, name ), 60 : QServerSocket( port, 1, parent, name ),
60 desktopChannel( 0 ), 61 desktopChannel( 0 ),
61 cardChannel( 0 ) 62 cardChannel( 0 )
62{ 63{
63 if ( !ok() ) 64 if ( !ok() )
64 owarn << "Failed to bind to port " << port << "" << oendl; 65 owarn << "Failed to bind to port " << port << "" << oendl;
65 else { 66 else {
67 ::fcntl( socket(), F_SETFD, FD_CLOEXEC );
66#ifndef QT_NO_COP 68#ifndef QT_NO_COP
67 desktopChannel = new QCopChannel( "QPE/Desktop", this ); 69 desktopChannel = new QCopChannel( "QPE/Desktop", this );
68 connect( desktopChannel, SIGNAL(received(const QCString&,const QByteArray&)), 70 connect( desktopChannel, SIGNAL(received(const QCString&,const QByteArray&)),
69 this, SLOT(desktopMessage(const QCString&,const QByteArray&)) ); 71 this, SLOT(desktopMessage(const QCString&,const QByteArray&)) );
70 cardChannel = new QCopChannel( "QPE/Card", this ); 72 cardChannel = new QCopChannel( "QPE/Card", this );
71 connect( cardChannel, SIGNAL(received(const QCString&,const QByteArray&)), 73 connect( cardChannel, SIGNAL(received(const QCString&,const QByteArray&)),
72 this, SLOT(desktopMessage(const QCString&,const QByteArray&)) ); 74 this, SLOT(desktopMessage(const QCString&,const QByteArray&)) );
73#endif 75#endif
74 } 76 }
75 sendSync = FALSE; 77 sendSync = FALSE;
76 openConnections.setAutoDelete( TRUE ); 78 openConnections.setAutoDelete( TRUE );
77 authorizeConnections(); 79 authorizeConnections();
78} 80}
79 81
80QCopBridge::~QCopBridge() 82QCopBridge::~QCopBridge()
81{ 83{
82#ifndef QT_NO_COP 84#ifndef QT_NO_COP
83 delete desktopChannel; 85 delete desktopChannel;
84#endif 86#endif
85} 87}
86 88
87void QCopBridge::authorizeConnections() 89void QCopBridge::authorizeConnections()
88{ 90{
89 Config cfg("Security"); 91 Config cfg("Security");
90 cfg.setGroup("SyncMode"); 92 cfg.setGroup("SyncMode");
91 m_mode = Mode(cfg.readNumEntry("Mode", Sharp )); 93 m_mode = Mode(cfg.readNumEntry("Mode", Sharp ));
92 QListIterator<QCopBridgePI> it(openConnections); 94 QListIterator<QCopBridgePI> it(openConnections);
93 while ( it.current() ) { 95 while ( it.current() ) {
94 if ( !it.current()->verifyAuthorised() ) { 96 if ( !it.current()->verifyAuthorised() ) {
95 disconnect ( it.current(), SIGNAL( connectionClosed(QCopBridgePI*) ), this, SLOT( closed(QCopBridgePI*) ) ); 97 disconnect ( it.current(), SIGNAL( connectionClosed(QCopBridgePI*) ), this, SLOT( closed(QCopBridgePI*) ) );
96 openConnections.removeRef( it.current() ); 98 openConnections.removeRef( it.current() );
97 } else 99 } else
98 ++it; 100 ++it;
99 } 101 }
100} 102}
101 103
102void QCopBridge::newConnection( int socket ) 104void QCopBridge::newConnection( int socket )
103{ 105{
104 QCopBridgePI *pi = new QCopBridgePI( socket, this ); 106 QCopBridgePI *pi = new QCopBridgePI( socket, this );
105 openConnections.append( pi ); 107 openConnections.append( pi );
106 connect ( pi, SIGNAL( connectionClosed(QCopBridgePI*) ), this, SLOT( closed(QCopBridgePI*) ) ); 108 connect ( pi, SIGNAL( connectionClosed(QCopBridgePI*) ), this, SLOT( closed(QCopBridgePI*) ) );
107 109
108 /* ### libqtopia merge FIXME */ 110 /* ### libqtopia merge FIXME */
109#if 0 111#if 0
110 QPEApplication::setTempScreenSaverMode( QPEApplication::DisableSuspend ); 112 QPEApplication::setTempScreenSaverMode( QPEApplication::DisableSuspend );
111#endif 113#endif
112#ifndef QT_NO_COP 114#ifndef QT_NO_COP
113 QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::DisableSuspend; 115 QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::DisableSuspend;
114#endif 116#endif
115 117
116 if ( sendSync ) { 118 if ( sendSync ) {
117 pi ->startSync(); 119 pi ->startSync();
118 sendSync = FALSE; 120 sendSync = FALSE;
119 } 121 }
120} 122}
121 123
122void QCopBridge::closed( QCopBridgePI *pi ) 124void QCopBridge::closed( QCopBridgePI *pi )
123{ 125{
124 emit connectionClosed( pi->peerAddress() ); 126 emit connectionClosed( pi->peerAddress() );
125 openConnections.removeRef( pi ); 127 openConnections.removeRef( pi );
126 if ( openConnections.count() == 0 ) { 128 if ( openConnections.count() == 0 ) {
127 /* ### FIXME libqtopia merge */ 129 /* ### FIXME libqtopia merge */
128#if 0 130#if 0
129 QPEApplication::setTempScreenSaverMode( QPEApplication::Enable ); 131 QPEApplication::setTempScreenSaverMode( QPEApplication::Enable );
130#endif 132#endif
131#ifndef QT_NO_COP 133#ifndef QT_NO_COP
132 QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable; 134 QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable;
133#endif 135#endif
134 } 136 }
135} 137}
136 138
137void QCopBridge::closeOpenConnections() 139void QCopBridge::closeOpenConnections()
138{ 140{
139 QCopBridgePI *pi; 141 QCopBridgePI *pi;
140 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() ) 142 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() )
141 pi->close(); 143 pi->close();
142} 144}
143 145
144 146
145void QCopBridge::desktopMessage( const QCString &command, const QByteArray &data ) 147void QCopBridge::desktopMessage( const QCString &command, const QByteArray &data )
146{ 148{
147 if ( command == "startSync()" ) { 149 if ( command == "startSync()" ) {
148 // we need to buffer it a bit 150 // we need to buffer it a bit
149 sendSync = TRUE; 151 sendSync = TRUE;
150 startTimer( 20000 ); 152 startTimer( 20000 );
151 } 153 }
152 154
153 if ( m_mode & Qtopia1_7 ) { 155 if ( m_mode & Qtopia1_7 ) {
154 // send the command to all open connections 156 // send the command to all open connections
155 QCopBridgePI *pi; 157 QCopBridgePI *pi;
156 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() ) { 158 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() ) {
157 pi->sendDesktopMessage( command, data ); 159 pi->sendDesktopMessage( command, data );
158 } 160 }
159 } 161 }
160 if ( ( m_mode & Sharp ) || (m_mode & IntelliSync) ) 162 if ( ( m_mode & Sharp ) || (m_mode & IntelliSync) )
161 sendDesktopMessageOld( command, data ); 163 sendDesktopMessageOld( command, data );
162} 164}
163 165
164#ifndef OPIE_NO_OLD_SYNC_CODE 166#ifndef OPIE_NO_OLD_SYNC_CODE
165/* 167/*
166 * Old compat mode 168 * Old compat mode
167 */ 169 */
168void QCopBridge::sendDesktopMessageOld( const QCString& command, const QByteArray& args) { 170void QCopBridge::sendDesktopMessageOld( const QCString& command, const QByteArray& args) {
169 command.stripWhiteSpace(); 171 command.stripWhiteSpace();
170 172
171 int paren = command.find( "(" ); 173 int paren = command.find( "(" );
172 if ( paren <= 0 ) { 174 if ( paren <= 0 ) {
173 odebug << "DesktopMessage: bad qcop syntax" << oendl; 175 odebug << "DesktopMessage: bad qcop syntax" << oendl;
174 return; 176 return;
175 } 177 }
176 178
177 QString params = command.mid( paren + 1 ); 179 QString params = command.mid( paren + 1 );
178 if ( params[params.length()-1] != ')' ) { 180 if ( params[params.length()-1] != ')' ) {
179 odebug << "DesktopMessage: bad qcop syntax" << oendl; 181 odebug << "DesktopMessage: bad qcop syntax" << oendl;
180 return; 182 return;
181 } 183 }
182 184
183 params.truncate( params.length()-1 ); 185 params.truncate( params.length()-1 );
184 186
185 QStringList paramList = QStringList::split( ",", params ); 187 QStringList paramList = QStringList::split( ",", params );
186 QString data; 188 QString data;
187 if ( paramList.count() ) { 189 if ( paramList.count() ) {
188 QDataStream stream( args, IO_ReadOnly ); 190 QDataStream stream( args, IO_ReadOnly );
189 for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) { 191 for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) {
190 QString str; 192 QString str;
191 if ( *it == "QString" ) { 193 if ( *it == "QString" ) {
192 stream >> str; 194 stream >> str;
193 } else if ( *it == "QCString" ) { 195 } else if ( *it == "QCString" ) {
194 QCString cstr; 196 QCString cstr;
195 stream >> cstr; 197 stream >> cstr;
196 str = QString::fromLocal8Bit( cstr ); 198 str = QString::fromLocal8Bit( cstr );
197 } else if ( *it == "int" ) { 199 } else if ( *it == "int" ) {
198 int i; 200 int i;
199 stream >> i; 201 stream >> i;
200 str = QString::number( i ); 202 str = QString::number( i );
201 } else if ( *it == "bool" ) { 203 } else if ( *it == "bool" ) {
202 int i; 204 int i;
203 stream >> i; 205 stream >> i;
204 str = QString::number( i ); 206 str = QString::number( i );
205 } else { 207 } else {
206 odebug << " cannot route the argument type " << (*it) << " throught the qcop bridge" << oendl; 208 odebug << " cannot route the argument type " << (*it) << " throught the qcop bridge" << oendl;
207 return; 209 return;
208 } 210 }
209 QString estr; 211 QString estr;
210 for (int i=0; i<(int)str.length(); i++) { 212 for (int i=0; i<(int)str.length(); i++) {
211 QChar ch = str[i]; 213 QChar ch = str[i];
212 if ( ch.row() ) 214 if ( ch.row() )
213 goto quick; 215 goto quick;
214 switch (ch.cell()) { 216 switch (ch.cell()) {
215 case '&': 217 case '&':
216 estr.append( "&amp;" ); 218 estr.append( "&amp;" );
217 break; 219 break;
218 case ' ': 220 case ' ':
219 estr.append( "&0x20;" ); 221 estr.append( "&0x20;" );
220 break; 222 break;
221 case '\n': 223 case '\n':
222 estr.append( "&0x0d;" ); 224 estr.append( "&0x0d;" );
223 break; 225 break;
224 case '\r': 226 case '\r':
225 estr.append( "&0x0a;" ); 227 estr.append( "&0x0a;" );
226 break; 228 break;
227 default: quick: 229 default: quick:
228 estr.append(ch); 230 estr.append(ch);
229 } 231 }
230 } 232 }
231 data += " " + estr; 233 data += " " + estr;
232 } 234 }
233 } 235 }
234 QString sendCommand = QString(command.data()) + data; 236 QString sendCommand = QString(command.data()) + data;
235 237
236 238
237 // send the command to all open connections 239 // send the command to all open connections
238 QCopBridgePI *pi; 240 QCopBridgePI *pi;
239 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() ) 241 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() )
240 pi->sendDesktopMessage( sendCommand ); 242 pi->sendDesktopMessage( sendCommand );
241 243
242} 244}
243#endif 245#endif
244 246
245 247
246void QCopBridge::timerEvent( QTimerEvent * ) 248void QCopBridge::timerEvent( QTimerEvent * )
247{ 249{
248 sendSync = FALSE; 250 sendSync = FALSE;
249 killTimers(); 251 killTimers();
250} 252}
251 253
252 254
253QCopBridgePI::QCopBridgePI( int socket, QObject *parent, const char* name ) 255QCopBridgePI::QCopBridgePI( int socket, QObject *parent, const char* name )
254 : QSocket( parent, name ) 256 : QSocket( parent, name )
255{ 257{
256 setSocket( socket ); 258 setSocket( socket );
257 259
258 peerport = peerPort(); 260 peerport = peerPort();
259 peeraddress = peerAddress(); 261 peeraddress = peerAddress();
260 262
261#ifndef INSECURE 263#ifndef INSECURE
262 if ( !SyncAuthentication::isAuthorized(peeraddress) ) { 264 if ( !SyncAuthentication::isAuthorized(peeraddress) ) {
263 state = Forbidden; 265 state = Forbidden;
264 close(); 266 close();
265 } else 267 } else
266#endif 268#endif
267 { 269 {
268 state = Connected; 270 state = Connected;
269 connect( this, SIGNAL( readyRead() ), SLOT( read() ) ); 271 connect( this, SIGNAL( readyRead() ), SLOT( read() ) );
270 QString intro="220 Qtopia "; 272 QString intro="220 Qtopia ";
271 intro += QPE_VERSION; intro += ";"; 273 intro += QPE_VERSION; intro += ";";
272 intro += "challenge="; intro += SyncAuthentication::serverId(); intro += ";"; // No tr 274 intro += "challenge="; intro += SyncAuthentication::serverId(); intro += ";"; // No tr
273 intro += "loginname="; intro += SyncAuthentication::loginName(); intro += ";"; 275 intro += "loginname="; intro += SyncAuthentication::loginName(); intro += ";";
274 intro += "displayname="; intro += SyncAuthentication::ownerName(); intro += ";"; 276 intro += "displayname="; intro += SyncAuthentication::ownerName(); intro += ";";
275 send( intro ); 277 send( intro );
276 state = Wait_USER; 278 state = Wait_USER;
277 } 279 }
278 sendSync = FALSE; 280 sendSync = FALSE;
279 connect( this, SIGNAL( connectionClosed() ), SLOT( myConnectionClosed() ) ); 281 connect( this, SIGNAL( connectionClosed() ), SLOT( myConnectionClosed() ) );
280 282
281 // idle timer to close connections when not used anymore 283 // idle timer to close connections when not used anymore
282 timer = new QTimer(this); 284 timer = new QTimer(this);
283 connect( timer, SIGNAL(timeout()), this, SLOT(myConnectionClosed()) ); 285 connect( timer, SIGNAL(timeout()), this, SLOT(myConnectionClosed()) );
284 timer->start( 300000, TRUE ); 286 timer->start( 300000, TRUE );
285} 287}
286 288
287 289
288QCopBridgePI::~QCopBridgePI() 290QCopBridgePI::~QCopBridgePI()
289{ 291{
290} 292}
291 293
292bool QCopBridgePI::verifyAuthorised() 294bool QCopBridgePI::verifyAuthorised()
293{ 295{
294 if ( !SyncAuthentication::isAuthorized(peerAddress()) ) { 296 if ( !SyncAuthentication::isAuthorized(peerAddress()) ) {
295 state = Forbidden; 297 state = Forbidden;
296 return FALSE; 298 return FALSE;
297 } 299 }
298 return TRUE; 300 return TRUE;
299} 301}
300 302
301void QCopBridgePI::myConnectionClosed() 303void QCopBridgePI::myConnectionClosed()
302{ 304{
303 emit connectionClosed( this ); 305 emit connectionClosed( this );
304} 306}
305 307
306void QCopBridgePI::sendDesktopMessage( const QString &msg ) 308void QCopBridgePI::sendDesktopMessage( const QString &msg )
307{ 309{
308 QString str = "CALL QPE/Desktop " + msg; // No tr 310 QString str = "CALL QPE/Desktop " + msg; // No tr
309 send ( str ); 311 send ( str );
310} 312}
311 313
312void QCopBridgePI::sendDesktopMessage( const QCString &msg, const QByteArray& data ) 314void QCopBridgePI::sendDesktopMessage( const QCString &msg, const QByteArray& data )
313{ 315{
314 if ( !isOpen() ) // eg. Forbidden 316 if ( !isOpen() ) // eg. Forbidden
315 return; 317 return;
316 318
317 const char hdr[]="CALLB QPE/Desktop "; 319 const char hdr[]="CALLB QPE/Desktop ";
318 writeBlock(hdr,sizeof(hdr)-1); 320 writeBlock(hdr,sizeof(hdr)-1);
319 writeBlock(msg,msg.length()); 321 writeBlock(msg,msg.length());
320 writeBlock(" ",1); 322 writeBlock(" ",1);
321 QByteArray b64 = OGlobal::encodeBase64(data); 323 QByteArray b64 = OGlobal::encodeBase64(data);
322 writeBlock(b64.data(),b64.size()); 324 writeBlock(b64.data(),b64.size());
323 writeBlock("\r\n",2); 325 writeBlock("\r\n",2);
324 326
325} 327}
326 328
327 329
328void QCopBridgePI::send( const QString& msg ) 330void QCopBridgePI::send( const QString& msg )
329{ 331{
330 if ( !isOpen() ) // eg. Forbidden 332 if ( !isOpen() ) // eg. Forbidden
331 return; 333 return;
332 QTextStream os( this ); 334 QTextStream os( this );
333 os << msg << endl; 335 os << msg << endl;
334 //odebug << "sending qcop message: " << msg << "" << oendl; 336 //odebug << "sending qcop message: " << msg << "" << oendl;
335} 337}
336 338
337void QCopBridgePI::read() 339void QCopBridgePI::read()
338{ 340{
339 while ( canReadLine() ) { 341 while ( canReadLine() ) {
340 timer->start( 300000, TRUE ); 342 timer->start( 300000, TRUE );
341 process( readLine().stripWhiteSpace() ); 343 process( readLine().stripWhiteSpace() );
342 } 344 }
343} 345}
344 346
345void QCopBridgePI::process( const QString& message ) 347void QCopBridgePI::process( const QString& message )
346{ 348{
347 //odebug << "Command: " << message << "" << oendl; 349 //odebug << "Command: " << message << "" << oendl;
348 350
349 // split message using "," as separator 351 // split message using "," as separator
350 QStringList msg = QStringList::split( " ", message ); 352 QStringList msg = QStringList::split( " ", message );
351 if ( msg.isEmpty() ) return; 353 if ( msg.isEmpty() ) return;
352 354
353 // command token 355 // command token
354 QString cmd = msg[0].upper(); 356 QString cmd = msg[0].upper();
355 357
356 // argument token 358 // argument token
357 QString arg; 359 QString arg;
358 if ( msg.count() >= 2 ) 360 if ( msg.count() >= 2 )
359 arg = msg[1]; 361 arg = msg[1];
360 362
361 // we always respond to QUIT, regardless of state 363 // we always respond to QUIT, regardless of state
362 if ( cmd == "QUIT" ) { 364 if ( cmd == "QUIT" ) {
363 send( "211 Have a nice day!" ); // No tr 365 send( "211 Have a nice day!" ); // No tr
364 close(); 366 close();
365 return; 367 return;
366 } 368 }
367 369
368 // connected to client 370 // connected to client
369 if ( Connected == state ) 371 if ( Connected == state )
370 return; 372 return;
371 373
372 // waiting for user name 374 // waiting for user name
373 if ( Wait_USER == state ) { 375 if ( Wait_USER == state ) {
374 376
375 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) { 377 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) {
376 send( "530 Please login with USER and PASS" ); // No tr 378 send( "530 Please login with USER and PASS" ); // No tr
377 return; 379 return;
378 } 380 }
379 send( "331 User name ok, need password" ); // No tr 381 send( "331 User name ok, need password" ); // No tr
380 state = Wait_PASS; 382 state = Wait_PASS;
381 return; 383 return;
382 } 384 }
383 385
384 // waiting for password 386 // waiting for password
385 if ( Wait_PASS == state ) { 387 if ( Wait_PASS == state ) {
386 388
387 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) { 389 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) {
388 send( "530 Please login with USER and PASS" ); // No tr 390 send( "530 Please login with USER and PASS" ); // No tr
389 return; 391 return;
390 } 392 }
391 send( "230 User logged in, proceed" ); // No tr 393 send( "230 User logged in, proceed" ); // No tr
392 state = Ready; 394 state = Ready;
393 if ( sendSync ) { 395 if ( sendSync ) {
394 sendDesktopMessage( "startSync()" ); 396 sendDesktopMessage( "startSync()" );
395 sendSync = FALSE; 397 sendSync = FALSE;
396 } 398 }
397 return; 399 return;
398 } 400 }
399 401
400 // noop (NOOP) 402 // noop (NOOP)
401 else if ( cmd == "NOOP" ) { 403 else if ( cmd == "NOOP" ) {
402 send( "200 Command okay" ); // No tr 404 send( "200 Command okay" ); // No tr
403 } 405 }
404 406
405 // call (CALL) 407 // call (CALL)
406 else if ( cmd == "CALL" ) { 408 else if ( cmd == "CALL" ) {
407 409
408 // example: call QPE/System execute(QString) addressbook 410 // example: call QPE/System execute(QString) addressbook
409 411
410 if ( msg.count() < 3 ) { 412 if ( msg.count() < 3 ) {
411 send( "500 Syntax error, command unrecognized" ); // No tr 413 send( "500 Syntax error, command unrecognized" ); // No tr
412 } 414 }
413 else { 415 else {
414 416
415 QString channel = msg[1]; 417 QString channel = msg[1];
416 QString command = msg[2]; 418 QString command = msg[2];
417 419
418 command.stripWhiteSpace(); 420 command.stripWhiteSpace();
419 421
420 int paren = command.find( "(" ); 422 int paren = command.find( "(" );
421 if ( paren <= 0 ) { 423 if ( paren <= 0 ) {
422 send( "500 Syntax error, command unrecognized" ); // No tr 424 send( "500 Syntax error, command unrecognized" ); // No tr
423 return; 425 return;
424 } 426 }
425 427
426 QString params = command.mid( paren + 1 ); 428 QString params = command.mid( paren + 1 );
427 if ( params[(int)params.length()-1] != ')' ) { 429 if ( params[(int)params.length()-1] != ')' ) {
428 send( "500 Syntax error, command unrecognized" ); // No tr 430 send( "500 Syntax error, command unrecognized" ); // No tr
429 return; 431 return;
430 } 432 }
431 433
432 params.truncate( params.length()-1 ); 434 params.truncate( params.length()-1 );
433 QByteArray buffer; 435 QByteArray buffer;
434 QDataStream ds( buffer, IO_WriteOnly ); 436 QDataStream ds( buffer, IO_WriteOnly );
435 437
436 int msgId = 3; 438 int msgId = 3;
437 439
438 QStringList paramList = QStringList::split( ",", params ); 440 QStringList paramList = QStringList::split( ",", params );
439 if ( paramList.count() > msg.count() - 3 ) { 441 if ( paramList.count() > msg.count() - 3 ) {
440 send( "500 Syntax error, command unrecognized" ); // No tr 442 send( "500 Syntax error, command unrecognized" ); // No tr
441 return; 443 return;
442 } 444 }
443 445
444 for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) { 446 for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) {
445 447
446 QString arg = msg[msgId]; 448 QString arg = msg[msgId];
447 arg.replace( QRegExp("&0x20;"), " " ); 449 arg.replace( QRegExp("&0x20;"), " " );
448 arg.replace( QRegExp("&amp;"), "&" ); 450 arg.replace( QRegExp("&amp;"), "&" );
449 arg.replace( QRegExp("&0x0d;"), "\n" ); 451 arg.replace( QRegExp("&0x0d;"), "\n" );
450 arg.replace( QRegExp("&0x0a;"), "\r" ); 452 arg.replace( QRegExp("&0x0a;"), "\r" );
451 if ( *it == "QString" ) 453 if ( *it == "QString" )
452 ds << arg; 454 ds << arg;
453 else if ( *it == "QCString" ) 455 else if ( *it == "QCString" )
454 ds << arg.local8Bit(); 456 ds << arg.local8Bit();
455 else if ( *it == "int" ) 457 else if ( *it == "int" )
456 ds << arg.toInt(); 458 ds << arg.toInt();
457 else if ( *it == "bool" ) 459 else if ( *it == "bool" )
458 ds << arg.toInt(); 460 ds << arg.toInt();
459 else { 461 else {
460 send( "500 Syntax error, command unrecognized" ); // No tr 462 send( "500 Syntax error, command unrecognized" ); // No tr
461 return; 463 return;
462 } 464 }
463 msgId++; 465 msgId++;
464 } 466 }
465 467
466#ifndef QT_NO_COP 468#ifndef QT_NO_COP
467 if ( !QCopChannel::isRegistered( channel.latin1() ) ) { 469 if ( !QCopChannel::isRegistered( channel.latin1() ) ) {
468 // send message back about it 470 // send message back about it
469 QString answer = "599 ChannelNotRegistered " + channel; 471 QString answer = "599 ChannelNotRegistered " + channel;
470 send( answer ); 472 send( answer );
471 return; 473 return;
472 } 474 }
473#endif 475#endif
474 476
475#ifndef QT_NO_COP 477#ifndef QT_NO_COP
476 if ( paramList.count() ) 478 if ( paramList.count() )
477 QCopChannel::send( channel.latin1(), command.latin1(), buffer ); 479 QCopChannel::send( channel.latin1(), command.latin1(), buffer );
478 else 480 else
479 QCopChannel::send( channel.latin1(), command.latin1() ); 481 QCopChannel::send( channel.latin1(), command.latin1() );
480 482
481 send( "200 Command okay" ); // No tr 483 send( "200 Command okay" ); // No tr
482#endif 484#endif
483 } 485 }
484 } 486 }
485 // not implemented 487 // not implemented
486 else 488 else
487 send( "502 Command not implemented" ); // No tr 489 send( "502 Command not implemented" ); // No tr
488} 490}
489 491
490 492
diff --git a/core/launcher/transferserver.cpp b/core/launcher/transferserver.cpp
index 2b2e435..a219c0f 100644
--- a/core/launcher/transferserver.cpp
+++ b/core/launcher/transferserver.cpp
@@ -1,826 +1,829 @@
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 <fcntl.h>
42#include <stdlib.h> 43#include <stdlib.h>
43#include <time.h> 44#include <time.h>
44 45
45#ifndef Q_OS_MACX 46#ifndef Q_OS_MACX
46#include <shadow.h> 47#include <shadow.h>
47#include <crypt.h> 48#include <crypt.h>
48#endif /* Q_OS_MACX */ 49#endif /* Q_OS_MACX */
49 50
50const int block_size = 51200; 51const int block_size = 51200;
51 52
52TransferServer::TransferServer( Q_UINT16 port, QObject *parent, 53TransferServer::TransferServer( Q_UINT16 port, QObject *parent,
53 const char* name) 54 const char* name)
54 : QServerSocket( port, 1, parent, name ) 55 : QServerSocket( port, 1, parent, name )
55{ 56{
56 connections.setAutoDelete( TRUE ); 57 connections.setAutoDelete( TRUE );
57 if ( !ok() ) 58 if ( !ok() )
58 owarn << "Failed to bind to port " << port << "" << oendl; 59 owarn << "Failed to bind to port " << port << "" << oendl;
60 else
61 ::fcntl( socket(), F_SETFD, FD_CLOEXEC );
59} 62}
60 63
61void TransferServer::authorizeConnections() 64void TransferServer::authorizeConnections()
62{ 65{
63 QListIterator<ServerPI> it(connections); 66 QListIterator<ServerPI> it(connections);
64 while ( it.current() ) { 67 while ( it.current() ) {
65 if ( !it.current()->verifyAuthorised() ) { 68 if ( !it.current()->verifyAuthorised() ) {
66 disconnect( it.current(), SIGNAL(connectionClosed(ServerPI*)), this, SLOT( closed(ServerPI*)) ); 69 disconnect( it.current(), SIGNAL(connectionClosed(ServerPI*)), this, SLOT( closed(ServerPI*)) );
67 connections.removeRef( it.current() ); 70 connections.removeRef( it.current() );
68 } else 71 } else
69 ++it; 72 ++it;
70 } 73 }
71} 74}
72 75
73void TransferServer::closed(ServerPI *item) 76void TransferServer::closed(ServerPI *item)
74{ 77{
75 connections.removeRef(item); 78 connections.removeRef(item);
76} 79}
77 80
78TransferServer::~TransferServer() 81TransferServer::~TransferServer()
79{ 82{
80} 83}
81 84
82void TransferServer::newConnection( int socket ) 85void TransferServer::newConnection( int socket )
83{ 86{
84 ServerPI *ptr = new ServerPI( socket, this ); 87 ServerPI *ptr = new ServerPI( socket, this );
85 connect( ptr, SIGNAL(connectionClosed(ServerPI*)), this, SLOT( closed(ServerPI*)) ); 88 connect( ptr, SIGNAL(connectionClosed(ServerPI*)), this, SLOT( closed(ServerPI*)) );
86 connections.append( ptr ); 89 connections.append( ptr );
87} 90}
88 91
89QString SyncAuthentication::serverId() 92QString SyncAuthentication::serverId()
90{ 93{
91 Config cfg("Security"); 94 Config cfg("Security");
92 cfg.setGroup("Sync"); 95 cfg.setGroup("Sync");
93 QString r = cfg.readEntry("serverid"); 96 QString r = cfg.readEntry("serverid");
94 97
95 if ( r.isEmpty() ) { 98 if ( r.isEmpty() ) {
96 r = OGlobal::generateUuid(); 99 r = OGlobal::generateUuid();
97 cfg.writeEntry("serverid", r ); 100 cfg.writeEntry("serverid", r );
98 } 101 }
99 return r; 102 return r;
100} 103}
101 104
102QString SyncAuthentication::ownerName() 105QString SyncAuthentication::ownerName()
103{ 106{
104 QString vfilename = Global::applicationFileName("addressbook", 107 QString vfilename = Global::applicationFileName("addressbook",
105 "businesscard.vcf"); 108 "businesscard.vcf");
106 if (QFile::exists(vfilename)) { 109 if (QFile::exists(vfilename)) {
107 Contact c; 110 Contact c;
108 c = Contact::readVCard( vfilename )[0]; 111 c = Contact::readVCard( vfilename )[0];
109 return c.fullName(); 112 return c.fullName();
110 } 113 }
111 114
112 return QString::null; 115 return QString::null;
113} 116}
114 117
115QString SyncAuthentication::loginName() 118QString SyncAuthentication::loginName()
116{ 119{
117 struct passwd *pw = 0L; 120 struct passwd *pw = 0L;
118#ifndef Q_OS_WIN32 121#ifndef Q_OS_WIN32
119 pw = getpwuid( geteuid() ); 122 pw = getpwuid( geteuid() );
120 return QString::fromLocal8Bit( pw->pw_name ); 123 return QString::fromLocal8Bit( pw->pw_name );
121#else 124#else
122 //### revise 125 //### revise
123 return QString(); 126 return QString();
124#endif 127#endif
125} 128}
126 129
127int SyncAuthentication::isAuthorized(QHostAddress peeraddress) 130int SyncAuthentication::isAuthorized(QHostAddress peeraddress)
128{ 131{
129 Config cfg("Security"); 132 Config cfg("Security");
130 cfg.setGroup("Sync"); 133 cfg.setGroup("Sync");
131 // QString allowedstr = cfg.readEntry("auth_peer","192.168.1.0"); 134 // QString allowedstr = cfg.readEntry("auth_peer","192.168.1.0");
132 uint auth_peer = cfg.readNumEntry("auth_peer", 0xc0a80100); 135 uint auth_peer = cfg.readNumEntry("auth_peer", 0xc0a80100);
133 136
134 // QHostAddress allowed; 137 // QHostAddress allowed;
135 // allowed.setAddress(allowedstr); 138 // allowed.setAddress(allowedstr);
136 // uint auth_peer = allowed.ip4Addr(); 139 // uint auth_peer = allowed.ip4Addr();
137 uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits", 24); 140 uint auth_peer_bits = cfg.readNumEntry("auth_peer_bits", 24);
138 uint mask = auth_peer_bits >= 32 // shifting by 32 is not defined 141 uint mask = auth_peer_bits >= 32 // shifting by 32 is not defined
139 ? 0xffffffff : (((1 << auth_peer_bits) - 1) << (32 - auth_peer_bits)); 142 ? 0xffffffff : (((1 << auth_peer_bits) - 1) << (32 - auth_peer_bits));
140 143
141 return (peeraddress.ip4Addr() & mask) == auth_peer; 144 return (peeraddress.ip4Addr() & mask) == auth_peer;
142} 145}
143 146
144bool SyncAuthentication::checkUser( const QString& user ) 147bool SyncAuthentication::checkUser( const QString& user )
145{ 148{
146 if ( user.isEmpty() ) return FALSE; 149 if ( user.isEmpty() ) return FALSE;
147 QString euser = loginName(); 150 QString euser = loginName();
148 return user == euser; 151 return user == euser;
149} 152}
150 153
151bool SyncAuthentication::checkPassword( const QString& password ) 154bool SyncAuthentication::checkPassword( const QString& password )
152{ 155{
153#ifdef ALLOW_UNIX_USER_FTP 156#ifdef ALLOW_UNIX_USER_FTP
154 // First, check system password... 157 // First, check system password...
155 158
156 struct passwd *pw = 0; 159 struct passwd *pw = 0;
157 struct spwd *spw = 0; 160 struct spwd *spw = 0;
158 161
159 pw = getpwuid( geteuid() ); 162 pw = getpwuid( geteuid() );
160 spw = getspnam( pw->pw_name ); 163 spw = getspnam( pw->pw_name );
161 164
162 QString cpwd = QString::fromLocal8Bit( pw->pw_passwd ); 165 QString cpwd = QString::fromLocal8Bit( pw->pw_passwd );
163 if ( cpwd == "x" && spw ) 166 if ( cpwd == "x" && spw )
164 cpwd = QString::fromLocal8Bit( spw->sp_pwdp ); 167 cpwd = QString::fromLocal8Bit( spw->sp_pwdp );
165 168
166 // Note: some systems use more than crypt for passwords. 169 // Note: some systems use more than crypt for passwords.
167 QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) ); 170 QString cpassword = QString::fromLocal8Bit( crypt( password.local8Bit(), cpwd.local8Bit() ) );
168 if ( cpwd == cpassword ) 171 if ( cpwd == cpassword )
169 return TRUE; 172 return TRUE;
170#endif 173#endif
171 174
172 static int lastdenial=0; 175 static int lastdenial=0;
173 static int denials=0; 176 static int denials=0;
174 int now = time(0); 177 int now = time(0);
175 178
176 Config cfg("Security"); 179 Config cfg("Security");
177 cfg.setGroup("SyncMode"); 180 cfg.setGroup("SyncMode");
178 int mode = cfg.readNumEntry("Mode", 0x02 ); 181 int mode = cfg.readNumEntry("Mode", 0x02 );
179 182
180 //No pass word needed if the user really needs it 183 //No pass word needed if the user really needs it
181 if (mode & 0x04) { 184 if (mode & 0x04) {
182 QMessageBox unauth( 185 QMessageBox unauth(
183 tr("Sync Connection"), 186 tr("Sync Connection"),
184 tr("<qt><p>An unauthorized system is requesting access to this device." 187 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>" ), 188 "<p>You chose IntelliSync so you may I allow or deny this connection.</qt>" ),
186 QMessageBox::Warning, 189 QMessageBox::Warning,
187 QMessageBox::Ok, QMessageBox::Cancel|QMessageBox::Default, QMessageBox::NoButton, 190 QMessageBox::Ok, QMessageBox::Cancel|QMessageBox::Default, QMessageBox::NoButton,
188 0, QString::null, TRUE, WStyle_StaysOnTop); 191 0, QString::null, TRUE, WStyle_StaysOnTop);
189 unauth.setButtonText(QMessageBox::Ok, tr("Allow" ) ); 192 unauth.setButtonText(QMessageBox::Ok, tr("Allow" ) );
190 unauth.setButtonText(QMessageBox::Cancel, tr("Deny")); 193 unauth.setButtonText(QMessageBox::Cancel, tr("Deny"));
191 switch( unauth.exec() ) { 194 switch( unauth.exec() ) {
192 case QMessageBox::Ok: 195 case QMessageBox::Ok:
193 return TRUE; 196 return TRUE;
194 break; 197 break;
195 case QMessageBox::Cancel: 198 case QMessageBox::Cancel:
196 default: 199 default:
197 denials++; 200 denials++;
198 lastdenial=now; 201 lastdenial=now;
199 return FALSE; 202 return FALSE;
200 } 203 }
201 } 204 }
202 205
203 // Detect old Qtopia Desktop (no password) and fail 206 // Detect old Qtopia Desktop (no password) and fail
204 if ( password.isEmpty() ) { 207 if ( password.isEmpty() ) {
205 if ( denials < 3 || now > lastdenial+600 ) { 208 if ( denials < 3 || now > lastdenial+600 ) {
206 QMessageBox unauth( 209 QMessageBox unauth(
207 tr("Sync Connection"), 210 tr("Sync Connection"),
208 tr("<p>An unauthorized system is requesting access to this device." 211 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, " 212 "<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." ), 213 "please upgrade or change the security setting to use IntelliSync." ),
211 QMessageBox::Warning, 214 QMessageBox::Warning,
212 QMessageBox::Cancel, QMessageBox::NoButton, QMessageBox::NoButton, 215 QMessageBox::Cancel, QMessageBox::NoButton, QMessageBox::NoButton,
213 0, QString::null, TRUE, WStyle_StaysOnTop); 216 0, QString::null, TRUE, WStyle_StaysOnTop);
214 unauth.setButtonText(QMessageBox::Cancel, tr("Deny")); 217 unauth.setButtonText(QMessageBox::Cancel, tr("Deny"));
215 unauth.exec(); 218 unauth.exec();
216 219
217 denials++; 220 denials++;
218 lastdenial=now; 221 lastdenial=now;
219 } 222 }
220 return FALSE; 223 return FALSE;
221 224
222 } 225 }
223 226
224 // Second, check sync password... 227 // Second, check sync password...
225 228
226 static int lock=0; 229 static int lock=0;
227 if ( lock ) return FALSE; 230 if ( lock ) return FALSE;
228 231
229 ++lock; 232 ++lock;
230 233
231 /* 234 /*
232 * we need to support old Sync software and QtopiaDesktop 235 * we need to support old Sync software and QtopiaDesktop
233 */ 236 */
234 if ( password.left(6) == "Qtopia" || password.left(6) == "rootme" ) { 237 if ( password.left(6) == "Qtopia" || password.left(6) == "rootme" ) {
235 cfg.setGroup("Sync"); 238 cfg.setGroup("Sync");
236 QStringList pwds = cfg.readListEntry("Passwords",' '); 239 QStringList pwds = cfg.readListEntry("Passwords",' ');
237 for (QStringList::ConstIterator it=pwds.begin(); it!=pwds.end(); ++it) { 240 for (QStringList::ConstIterator it=pwds.begin(); it!=pwds.end(); ++it) {
238#ifndef Q_OS_WIN32 241#ifndef Q_OS_WIN32
239 QString cpassword = QString::fromLocal8Bit( 242 QString cpassword = QString::fromLocal8Bit(
240 crypt( password.mid(8).local8Bit(), (*it).left(2).latin1() ) ); 243 crypt( password.mid(8).local8Bit(), (*it).left(2).latin1() ) );
241#else 244#else
242 // ### revise 245 // ### revise
243 QString cpassword(""); 246 QString cpassword("");
244#endif 247#endif
245 if ( *it == cpassword ) { 248 if ( *it == cpassword ) {
246 lock--; 249 lock--;
247 return TRUE; 250 return TRUE;
248 } 251 }
249 } 252 }
250 253
251 // Unrecognized system. Be careful... 254 // Unrecognized system. Be careful...
252 QMessageBox unrecbox( 255 QMessageBox unrecbox(
253 tr("Sync Connection"), 256 tr("Sync Connection"),
254 tr( "<p>An unrecognized system is requesting access to this device." 257 tr( "<p>An unrecognized system is requesting access to this device."
255 "<p>If you have just initiated a Sync for the first time, this is normal."), 258 "<p>If you have just initiated a Sync for the first time, this is normal."),
256 QMessageBox::Warning, 259 QMessageBox::Warning,
257 QMessageBox::Cancel, QMessageBox::Yes, QMessageBox::NoButton, 260 QMessageBox::Cancel, QMessageBox::Yes, QMessageBox::NoButton,
258 0, QString::null, TRUE, WStyle_StaysOnTop); 261 0, QString::null, TRUE, WStyle_StaysOnTop);
259 unrecbox.setButtonText(QMessageBox::Cancel, tr("Deny")); 262 unrecbox.setButtonText(QMessageBox::Cancel, tr("Deny"));
260 unrecbox.setButtonText(QMessageBox::Yes, tr("Allow")); 263 unrecbox.setButtonText(QMessageBox::Yes, tr("Allow"));
261 264
262 if ( (denials > 2 && now < lastdenial+600) 265 if ( (denials > 2 && now < lastdenial+600)
263 || unrecbox.exec() != QMessageBox::Yes) 266 || unrecbox.exec() != QMessageBox::Yes)
264 { 267 {
265 denials++; 268 denials++;
266 lastdenial=now; 269 lastdenial=now;
267 lock--; 270 lock--;
268 return FALSE; 271 return FALSE;
269 } else { 272 } else {
270 const char salty[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/."; 273 const char salty[]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789/.";
271 char salt[2]; 274 char salt[2];
272 salt[0]= salty[rand() % (sizeof(salty)-1)]; 275 salt[0]= salty[rand() % (sizeof(salty)-1)];
273 salt[1]= salty[rand() % (sizeof(salty)-1)]; 276 salt[1]= salty[rand() % (sizeof(salty)-1)];
274#ifndef Q_OS_WIN32 277#ifndef Q_OS_WIN32
275 QString cpassword = QString::fromLocal8Bit( 278 QString cpassword = QString::fromLocal8Bit(
276 crypt( password.mid(8).local8Bit(), salt ) ); 279 crypt( password.mid(8).local8Bit(), salt ) );
277#else 280#else
278 //### revise 281 //### revise
279 QString cpassword(""); 282 QString cpassword("");
280#endif 283#endif
281 denials=0; 284 denials=0;
282 pwds.prepend(cpassword); 285 pwds.prepend(cpassword);
283 cfg.writeEntry("Passwords",pwds,' '); 286 cfg.writeEntry("Passwords",pwds,' ');
284 lock--; 287 lock--;
285 return TRUE; 288 return TRUE;
286 } 289 }
287 } 290 }
288 lock--; 291 lock--;
289 292
290 return FALSE; 293 return FALSE;
291} 294}
292 295
293 296
294ServerPI::ServerPI( int socket, QObject *parent, const char* name ) 297ServerPI::ServerPI( int socket, QObject *parent, const char* name )
295 : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 ), 298 : QSocket( parent, name ) , dtp( 0 ), serversocket( 0 ), waitsocket( 0 ),
296 storFileSize(-1) 299 storFileSize(-1)
297{ 300{
298 state = Connected; 301 state = Connected;
299 302
300 setSocket( socket ); 303 setSocket( socket );
301 304
302 peerport = peerPort(); 305 peerport = peerPort();
303 peeraddress = peerAddress(); 306 peeraddress = peerAddress();
304 307
305#ifndef INSECURE 308#ifndef INSECURE
306 if ( !SyncAuthentication::isAuthorized(peeraddress) ) { 309 if ( !SyncAuthentication::isAuthorized(peeraddress) ) {
307 state = Forbidden; 310 state = Forbidden;
308 startTimer( 0 ); 311 startTimer( 0 );
309 } else 312 } else
310#endif 313#endif
311 { 314 {
312 connect( this, SIGNAL( readyRead() ), SLOT( read() ) ); 315 connect( this, SIGNAL( readyRead() ), SLOT( read() ) );
313 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) ); 316 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) );
314 317
315 passiv = FALSE; 318 passiv = FALSE;
316 for( int i = 0; i < 4; i++ ) 319 for( int i = 0; i < 4; i++ )
317 wait[i] = FALSE; 320 wait[i] = FALSE;
318 321
319 send( "220 Qtopia " QPE_VERSION " FTP Server" ); // No tr 322 send( "220 Qtopia " QPE_VERSION " FTP Server" ); // No tr
320 state = Wait_USER; 323 state = Wait_USER;
321 324
322 dtp = new ServerDTP( this ); 325 dtp = new ServerDTP( this );
323 connect( dtp, SIGNAL( completed() ), SLOT( dtpCompleted() ) ); 326 connect( dtp, SIGNAL( completed() ), SLOT( dtpCompleted() ) );
324 connect( dtp, SIGNAL( failed() ), SLOT( dtpFailed() ) ); 327 connect( dtp, SIGNAL( failed() ), SLOT( dtpFailed() ) );
325 connect( dtp, SIGNAL( error(int) ), SLOT( dtpError(int) ) ); 328 connect( dtp, SIGNAL( error(int) ), SLOT( dtpError(int) ) );
326 329
327 330
328 directory = QDir::currentDirPath(); 331 directory = QDir::currentDirPath();
329 332
330 static int p = 1024; 333 static int p = 1024;
331 334
332 while ( !serversocket || !serversocket->ok() ) { 335 while ( !serversocket || !serversocket->ok() ) {
333 delete serversocket; 336 delete serversocket;
334 serversocket = new ServerSocket( ++p, this ); 337 serversocket = new ServerSocket( ++p, this );
335 } 338 }
336 connect( serversocket, SIGNAL( newIncomming(int) ), 339 connect( serversocket, SIGNAL( newIncomming(int) ),
337 SLOT( newConnection(int) ) ); 340 SLOT( newConnection(int) ) );
338 } 341 }
339} 342}
340 343
341ServerPI::~ServerPI() 344ServerPI::~ServerPI()
342{ 345{
343 close(); 346 close();
344 347
345 if ( dtp ) 348 if ( dtp )
346 dtp->close(); 349 dtp->close();
347 delete dtp; 350 delete dtp;
348 delete serversocket; 351 delete serversocket;
349} 352}
350 353
351bool ServerPI::verifyAuthorised() 354bool ServerPI::verifyAuthorised()
352{ 355{
353 if ( !SyncAuthentication::isAuthorized(peerAddress()) ) { 356 if ( !SyncAuthentication::isAuthorized(peerAddress()) ) {
354 state = Forbidden; 357 state = Forbidden;
355 return FALSE; 358 return FALSE;
356 } 359 }
357 return TRUE; 360 return TRUE;
358} 361}
359 362
360void ServerPI::connectionClosed() 363void ServerPI::connectionClosed()
361{ 364{
362 // odebug << "Debug: Connection closed" << oendl; 365 // odebug << "Debug: Connection closed" << oendl;
363 emit connectionClosed(this); 366 emit connectionClosed(this);
364} 367}
365 368
366void ServerPI::send( const QString& msg ) 369void ServerPI::send( const QString& msg )
367{ 370{
368 QTextStream os( this ); 371 QTextStream os( this );
369 os << msg << endl; 372 os << msg << endl;
370 //odebug << "Reply: " << msg << "" << oendl; 373 //odebug << "Reply: " << msg << "" << oendl;
371} 374}
372 375
373void ServerPI::read() 376void ServerPI::read()
374{ 377{
375 while ( canReadLine() ) 378 while ( canReadLine() )
376 process( readLine().stripWhiteSpace() ); 379 process( readLine().stripWhiteSpace() );
377} 380}
378 381
379bool ServerPI::checkReadFile( const QString& file ) 382bool ServerPI::checkReadFile( const QString& file )
380{ 383{
381 QString filename; 384 QString filename;
382 385
383 if ( file.length() == 1 && file[0] == "/" ) 386 if ( file.length() == 1 && file[0] == "/" )
384 filename = file; 387 filename = file;
385 else if ( file[0] != "/" ) 388 else if ( file[0] != "/" )
386 filename = directory.path() + "/" + file; 389 filename = directory.path() + "/" + file;
387 else 390 else
388 filename = file; 391 filename = file;
389 392
390 QFileInfo fi( filename ); 393 QFileInfo fi( filename );
391 return ( fi.exists() && fi.isReadable() ); 394 return ( fi.exists() && fi.isReadable() );
392} 395}
393 396
394bool ServerPI::checkWriteFile( const QString& file ) 397bool ServerPI::checkWriteFile( const QString& file )
395{ 398{
396 QString filename; 399 QString filename;
397 400
398 if ( file[0] != "/" ) 401 if ( file[0] != "/" )
399 filename = directory.path() + "/" + file; 402 filename = directory.path() + "/" + file;
400 else 403 else
401 filename = file; 404 filename = file;
402 405
403 QFileInfo fi( filename ); 406 QFileInfo fi( filename );
404 407
405 if ( fi.exists() ) 408 if ( fi.exists() )
406 if ( !QFile( filename ).remove() ) 409 if ( !QFile( filename ).remove() )
407 return FALSE; 410 return FALSE;
408 return TRUE; 411 return TRUE;
409} 412}
410 413
411void ServerPI::process( const QString& message ) 414void ServerPI::process( const QString& message )
412{ 415{
413 //odebug << "Command: " << message << "" << oendl; 416 //odebug << "Command: " << message << "" << oendl;
414 417
415 // split message using "," as separator 418 // split message using "," as separator
416 QStringList msg = QStringList::split( " ", message ); 419 QStringList msg = QStringList::split( " ", message );
417 if ( msg.isEmpty() ) return; 420 if ( msg.isEmpty() ) return;
418 421
419 // command token 422 // command token
420 QString cmd = msg[0].upper(); 423 QString cmd = msg[0].upper();
421 424
422 // argument token 425 // argument token
423 QString arg; 426 QString arg;
424 if ( msg.count() >= 2 ) 427 if ( msg.count() >= 2 )
425 arg = msg[1]; 428 arg = msg[1];
426 429
427 // full argument string 430 // full argument string
428 QString args; 431 QString args;
429 if ( msg.count() >= 2 ) { 432 if ( msg.count() >= 2 ) {
430 QStringList copy( msg ); 433 QStringList copy( msg );
431 // FIXME: for Qt3 434 // FIXME: for Qt3
432 // copy.pop_front() 435 // copy.pop_front()
433 copy.remove( copy.begin() ); 436 copy.remove( copy.begin() );
434 args = copy.join( " " ); 437 args = copy.join( " " );
435 } 438 }
436 439
437 //odebug << "args: " << args << "" << oendl; 440 //odebug << "args: " << args << "" << oendl;
438 441
439 // we always respond to QUIT, regardless of state 442 // we always respond to QUIT, regardless of state
440 if ( cmd == "QUIT" ) { 443 if ( cmd == "QUIT" ) {
441 send( "211 Good bye!" ); // No tr 444 send( "211 Good bye!" ); // No tr
442 close(); 445 close();
443 return; 446 return;
444 } 447 }
445 448
446 // connected to client 449 // connected to client
447 if ( Connected == state ) 450 if ( Connected == state )
448 return; 451 return;
449 452
450 // waiting for user name 453 // waiting for user name
451 if ( Wait_USER == state ) { 454 if ( Wait_USER == state ) {
452 455
453 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) { 456 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) {
454 send( "530 Please login with USER and PASS" ); // No tr 457 send( "530 Please login with USER and PASS" ); // No tr
455 return; 458 return;
456 } 459 }
457 send( "331 User name ok, need password" ); // No tr 460 send( "331 User name ok, need password" ); // No tr
458 state = Wait_PASS; 461 state = Wait_PASS;
459 return; 462 return;
460 } 463 }
461 464
462 // waiting for password 465 // waiting for password
463 if ( Wait_PASS == state ) { 466 if ( Wait_PASS == state ) {
464 467
465 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) { 468 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) {
466 send( "530 Please login with USER and PASS" ); // No tr 469 send( "530 Please login with USER and PASS" ); // No tr
467 return; 470 return;
468 } 471 }
469 send( "230 User logged in, proceed" ); // No tr 472 send( "230 User logged in, proceed" ); // No tr
470 state = Ready; 473 state = Ready;
471 return; 474 return;
472 } 475 }
473 476
474 // ACCESS CONTROL COMMANDS 477 // ACCESS CONTROL COMMANDS
475 478
476 // Only an ALLO sent immediately before STOR is valid. 479 // Only an ALLO sent immediately before STOR is valid.
477 if ( cmd != "STOR" ) 480 if ( cmd != "STOR" )
478 storFileSize = -1; 481 storFileSize = -1;
479 482
480 // account (ACCT) 483 // account (ACCT)
481 if ( cmd == "ACCT" ) { 484 if ( cmd == "ACCT" ) {
482 // even wu-ftp does not support it 485 // even wu-ftp does not support it
483 send( "502 Command not implemented" ); // No tr 486 send( "502 Command not implemented" ); // No tr
484 } 487 }
485 488
486 // change working directory (CWD) 489 // change working directory (CWD)
487 else if ( cmd == "CWD" ) { 490 else if ( cmd == "CWD" ) {
488 491
489 if ( !args.isEmpty() ) { 492 if ( !args.isEmpty() ) {
490 if ( directory.cd( args, TRUE ) ) 493 if ( directory.cd( args, TRUE ) )
491 send( "250 Requested file action okay, completed" ); // No tr 494 send( "250 Requested file action okay, completed" ); // No tr
492 else 495 else
493 send( "550 Requested action not taken" ); // No tr 496 send( "550 Requested action not taken" ); // No tr
494 } 497 }
495 else 498 else
496 send( "500 Syntax error, command unrecognized" ); // No tr 499 send( "500 Syntax error, command unrecognized" ); // No tr
497 } 500 }
498 501
499 // change to parent directory (CDUP) 502 // change to parent directory (CDUP)
500 else if ( cmd == "CDUP" ) { 503 else if ( cmd == "CDUP" ) {
501 if ( directory.cdUp() ) 504 if ( directory.cdUp() )
502 send( "250 Requested file action okay, completed" ); // No tr 505 send( "250 Requested file action okay, completed" ); // No tr
503 else 506 else
504 send( "550 Requested action not taken" ); // No tr 507 send( "550 Requested action not taken" ); // No tr
505 } 508 }
506 509
507 // structure mount (SMNT) 510 // structure mount (SMNT)
508 else if ( cmd == "SMNT" ) { 511 else if ( cmd == "SMNT" ) {
509 // even wu-ftp does not support it 512 // even wu-ftp does not support it
510 send( "502 Command not implemented" ); // No tr 513 send( "502 Command not implemented" ); // No tr
511 } 514 }
512 515
513 // reinitialize (REIN) 516 // reinitialize (REIN)
514 else if ( cmd == "REIN" ) { 517 else if ( cmd == "REIN" ) {
515 // even wu-ftp does not support it 518 // even wu-ftp does not support it
516 send( "502 Command not implemented" ); // No tr 519 send( "502 Command not implemented" ); // No tr
517 } 520 }
518 521
519 522
520 // TRANSFER PARAMETER COMMANDS 523 // TRANSFER PARAMETER COMMANDS
521 524
522 525
523 // data port (PORT) 526 // data port (PORT)
524 else if ( cmd == "PORT" ) { 527 else if ( cmd == "PORT" ) {
525 if ( parsePort( arg ) ) 528 if ( parsePort( arg ) )
526 send( "200 Command okay" ); // No tr 529 send( "200 Command okay" ); // No tr
527 else 530 else
528 send( "500 Syntax error, command unrecognized" ); // No tr 531 send( "500 Syntax error, command unrecognized" ); // No tr
529 } 532 }
530 533
531 // passive (PASV) 534 // passive (PASV)
532 else if ( cmd == "PASV" ) { 535 else if ( cmd == "PASV" ) {
533 passiv = TRUE; 536 passiv = TRUE;
534 send( "227 Entering Passive Mode (" // No tr 537 send( "227 Entering Passive Mode (" // No tr
535 + address().toString().replace( QRegExp( "\\." ), "," ) + "," 538 + address().toString().replace( QRegExp( "\\." ), "," ) + ","
536 + QString::number( ( serversocket->port() ) >> 8 ) + "," 539 + QString::number( ( serversocket->port() ) >> 8 ) + ","
537 + QString::number( ( serversocket->port() ) & 0xFF ) +")" ); 540 + QString::number( ( serversocket->port() ) & 0xFF ) +")" );
538 } 541 }
539 542
540 // representation type (TYPE) 543 // representation type (TYPE)
541 else if ( cmd == "TYPE" ) { 544 else if ( cmd == "TYPE" ) {
542 if ( arg.upper() == "A" || arg.upper() == "I" ) 545 if ( arg.upper() == "A" || arg.upper() == "I" )
543 send( "200 Command okay" ); // No tr 546 send( "200 Command okay" ); // No tr
544 else 547 else
545 send( "504 Command not implemented for that parameter" ); // No tr 548 send( "504 Command not implemented for that parameter" ); // No tr
546 } 549 }
547 550
548 // file structure (STRU) 551 // file structure (STRU)
549 else if ( cmd == "STRU" ) { 552 else if ( cmd == "STRU" ) {
550 if ( arg.upper() == "F" ) 553 if ( arg.upper() == "F" )
551 send( "200 Command okay" ); // No tr 554 send( "200 Command okay" ); // No tr
552 else 555 else
553 send( "504 Command not implemented for that parameter" ); // No tr 556 send( "504 Command not implemented for that parameter" ); // No tr
554 } 557 }
555 558
556 // transfer mode (MODE) 559 // transfer mode (MODE)
557 else if ( cmd == "MODE" ) { 560 else if ( cmd == "MODE" ) {
558 if ( arg.upper() == "S" ) 561 if ( arg.upper() == "S" )
559 send( "200 Command okay" ); // No tr 562 send( "200 Command okay" ); // No tr
560 else 563 else
561 send( "504 Command not implemented for that parameter" ); // No tr 564 send( "504 Command not implemented for that parameter" ); // No tr
562 } 565 }
563 566
564 567
565 // FTP SERVICE COMMANDS 568 // FTP SERVICE COMMANDS
566 569
567 570
568 // retrieve (RETR) 571 // retrieve (RETR)
569 else if ( cmd == "RETR" ) 572 else if ( cmd == "RETR" )
570 if ( !args.isEmpty() && checkReadFile( absFilePath( args ) ) 573 if ( !args.isEmpty() && checkReadFile( absFilePath( args ) )
571 || backupRestoreGzip( absFilePath( args ) ) ) { 574 || backupRestoreGzip( absFilePath( args ) ) ) {
572 send( "150 File status okay" ); // No tr 575 send( "150 File status okay" ); // No tr
573 sendFile( absFilePath( args ) ); 576 sendFile( absFilePath( args ) );
574 } 577 }
575 else { 578 else {
576 odebug << "550 Requested action not taken" << oendl; 579 odebug << "550 Requested action not taken" << oendl;
577 send( "550 Requested action not taken" ); // No tr 580 send( "550 Requested action not taken" ); // No tr
578 } 581 }
579 582
580 // store (STOR) 583 // store (STOR)
581 else if ( cmd == "STOR" ) 584 else if ( cmd == "STOR" )
582 if ( !args.isEmpty() && checkWriteFile( absFilePath( args ) ) ) { 585 if ( !args.isEmpty() && checkWriteFile( absFilePath( args ) ) ) {
583 send( "150 File status okay" ); // No tr 586 send( "150 File status okay" ); // No tr
584 retrieveFile( absFilePath( args ) ); 587 retrieveFile( absFilePath( args ) );
585 } 588 }
586 else 589 else
587 send( "550 Requested action not taken" ); // No tr 590 send( "550 Requested action not taken" ); // No tr
588 591
589 // store unique (STOU) 592 // store unique (STOU)
590 else if ( cmd == "STOU" ) { 593 else if ( cmd == "STOU" ) {
591 send( "502 Command not implemented" ); // No tr 594 send( "502 Command not implemented" ); // No tr
592 } 595 }
593 596
594 // append (APPE) 597 // append (APPE)
595 else if ( cmd == "APPE" ) { 598 else if ( cmd == "APPE" ) {
596 send( "502 Command not implemented" ); // No tr 599 send( "502 Command not implemented" ); // No tr
597 } 600 }
598 601
599 // allocate (ALLO) 602 // allocate (ALLO)
600 else if ( cmd == "ALLO" ) { 603 else if ( cmd == "ALLO" ) {
601 storFileSize = args.toInt(); 604 storFileSize = args.toInt();
602 send( "200 Command okay" ); // No tr 605 send( "200 Command okay" ); // No tr
603 } 606 }
604 607
605 // restart (REST) 608 // restart (REST)
606 else if ( cmd == "REST" ) { 609 else if ( cmd == "REST" ) {
607 send( "502 Command not implemented" ); // No tr 610 send( "502 Command not implemented" ); // No tr
608 } 611 }
609 612
610 // rename from (RNFR) 613 // rename from (RNFR)
611 else if ( cmd == "RNFR" ) { 614 else if ( cmd == "RNFR" ) {
612 renameFrom = QString::null; 615 renameFrom = QString::null;
613 if ( args.isEmpty() ) 616 if ( args.isEmpty() )
614 send( "500 Syntax error, command unrecognized" ); // No tr 617 send( "500 Syntax error, command unrecognized" ); // No tr
615 else { 618 else {
616 QFile file( absFilePath( args ) ); 619 QFile file( absFilePath( args ) );
617 if ( file.exists() ) { 620 if ( file.exists() ) {
618 send( "350 File exists, ready for destination name" ); // No tr 621 send( "350 File exists, ready for destination name" ); // No tr
619 renameFrom = absFilePath( args ); 622 renameFrom = absFilePath( args );
620 } 623 }
621 else 624 else
622 send( "550 Requested action not taken" ); // No tr 625 send( "550 Requested action not taken" ); // No tr
623 } 626 }
624 } 627 }
625 628
626 // rename to (RNTO) 629 // rename to (RNTO)
627 else if ( cmd == "RNTO" ) { 630 else if ( cmd == "RNTO" ) {
628 if ( lastCommand != "RNFR" ) 631 if ( lastCommand != "RNFR" )
629 send( "503 Bad sequence of commands" ); // No tr 632 send( "503 Bad sequence of commands" ); // No tr
630 else if ( args.isEmpty() ) 633 else if ( args.isEmpty() )
631 send( "500 Syntax error, command unrecognized" ); // No tr 634 send( "500 Syntax error, command unrecognized" ); // No tr
632 else { 635 else {
633 QDir dir( absFilePath( args ) ); 636 QDir dir( absFilePath( args ) );
634 if ( dir.rename( renameFrom, absFilePath( args ), TRUE ) ) 637 if ( dir.rename( renameFrom, absFilePath( args ), TRUE ) )
635 send( "250 Requested file action okay, completed." ); // No tr 638 send( "250 Requested file action okay, completed." ); // No tr
636 else 639 else
637 send( "550 Requested action not taken" ); // No tr 640 send( "550 Requested action not taken" ); // No tr
638 } 641 }
639 } 642 }
640 643
641 // abort (ABOR) 644 // abort (ABOR)
642 else if ( cmd.contains( "ABOR" ) ) { 645 else if ( cmd.contains( "ABOR" ) ) {
643 dtp->close(); 646 dtp->close();
644 if ( dtp->dtpMode() != ServerDTP::Idle ) 647 if ( dtp->dtpMode() != ServerDTP::Idle )
645 send( "426 Connection closed; transfer aborted" ); // No tr 648 send( "426 Connection closed; transfer aborted" ); // No tr
646 else 649 else
647 send( "226 Closing data connection" ); // No tr 650 send( "226 Closing data connection" ); // No tr
648 } 651 }
649 652
650 // delete (DELE) 653 // delete (DELE)
651 else if ( cmd == "DELE" ) { 654 else if ( cmd == "DELE" ) {
652 if ( args.isEmpty() ) 655 if ( args.isEmpty() )
653 send( "500 Syntax error, command unrecognized" ); // No tr 656 send( "500 Syntax error, command unrecognized" ); // No tr
654 else { 657 else {
655 QFile file( absFilePath( args ) ) ; 658 QFile file( absFilePath( args ) ) ;
656 if ( file.remove() ) { 659 if ( file.remove() ) {
657 send( "250 Requested file action okay, completed" ); // No tr 660 send( "250 Requested file action okay, completed" ); // No tr
658 QCopEnvelope e("QPE/System", "linkChanged(QString)" ); 661 QCopEnvelope e("QPE/System", "linkChanged(QString)" );
659 e << file.name(); 662 e << file.name();
660 } else { 663 } else {
661 send( "550 Requested action not taken" ); // No tr 664 send( "550 Requested action not taken" ); // No tr
662 } 665 }
663 } 666 }
664 } 667 }
665 668
666 // remove directory (RMD) 669 // remove directory (RMD)
667 else if ( cmd == "RMD" ) { 670 else if ( cmd == "RMD" ) {
668 if ( args.isEmpty() ) 671 if ( args.isEmpty() )
669 send( "500 Syntax error, command unrecognized" ); // No tr 672 send( "500 Syntax error, command unrecognized" ); // No tr
670 else { 673 else {
671 QDir dir; 674 QDir dir;
672 if ( dir.rmdir( absFilePath( args ), TRUE ) ) 675 if ( dir.rmdir( absFilePath( args ), TRUE ) )
673 send( "250 Requested file action okay, completed" ); // No tr 676 send( "250 Requested file action okay, completed" ); // No tr
674 else 677 else
675 send( "550 Requested action not taken" ); // No tr 678 send( "550 Requested action not taken" ); // No tr
676 } 679 }
677 } 680 }
678 681
679 // make directory (MKD) 682 // make directory (MKD)
680 else if ( cmd == "MKD" ) { 683 else if ( cmd == "MKD" ) {
681 if ( args.isEmpty() ) { 684 if ( args.isEmpty() ) {
682 odebug << " Error: no arg" << oendl; 685 odebug << " Error: no arg" << oendl;
683 send( "500 Syntax error, command unrecognized" ); // No tr 686 send( "500 Syntax error, command unrecognized" ); // No tr
684 } 687 }
685 else { 688 else {
686 QDir dir; 689 QDir dir;
687 if ( dir.mkdir( absFilePath( args ), TRUE ) ) 690 if ( dir.mkdir( absFilePath( args ), TRUE ) )
688 send( "250 Requested file action okay, completed." ); // No tr 691 send( "250 Requested file action okay, completed." ); // No tr
689 else 692 else
690 send( "550 Requested action not taken" ); // No tr 693 send( "550 Requested action not taken" ); // No tr
691 } 694 }
692 } 695 }
693 696
694 // print working directory (PWD) 697 // print working directory (PWD)
695 else if ( cmd == "PWD" ) { 698 else if ( cmd == "PWD" ) {
696 send( "257 \"" + directory.path() +"\"" ); 699 send( "257 \"" + directory.path() +"\"" );
697 } 700 }
698 701
699 // list (LIST) 702 // list (LIST)
700 else if ( cmd == "LIST" ) { 703 else if ( cmd == "LIST" ) {
701 if ( args == "-la" ) 704 if ( args == "-la" )
702 args = QString::null; 705 args = QString::null;
703 706
704 if ( sendList( absFilePath( args ) ) ) 707 if ( sendList( absFilePath( args ) ) )
705 send( "150 File status okay" ); // No tr 708 send( "150 File status okay" ); // No tr
706 else 709 else
707 send( "500 Syntax error, command unrecognized" ); // No tr 710 send( "500 Syntax error, command unrecognized" ); // No tr
708 } 711 }
709 712
710 // size (SIZE) 713 // size (SIZE)
711 else if ( cmd == "SIZE" ) { 714 else if ( cmd == "SIZE" ) {
712 QString filePath = absFilePath( args ); 715 QString filePath = absFilePath( args );
713 QFileInfo fi( filePath ); 716 QFileInfo fi( filePath );
714 bool gzipfile = backupRestoreGzip( filePath ); 717 bool gzipfile = backupRestoreGzip( filePath );
715 if ( !fi.exists() && !gzipfile ) 718 if ( !fi.exists() && !gzipfile )
716 send( "500 Syntax error, command unrecognized" ); // No tr 719 send( "500 Syntax error, command unrecognized" ); // No tr
717 else { 720 else {
718 if ( !gzipfile ) 721 if ( !gzipfile )
719 send( "213 " + QString::number( fi.size() ) ); 722 send( "213 " + QString::number( fi.size() ) );
720 else { 723 else {
721 Process duproc( QString("du") ); 724 Process duproc( QString("du") );
722 duproc.addArgument("-s"); 725 duproc.addArgument("-s");
723 QString in, out; 726 QString in, out;
724 if ( !duproc.exec(in, out) ) { 727 if ( !duproc.exec(in, out) ) {
725 odebug << "du process failed; just sending back 1K" << oendl; 728 odebug << "du process failed; just sending back 1K" << oendl;
726 send( "213 1024"); 729 send( "213 1024");
727 } 730 }
728 else { 731 else {
729 QString size = out.left( out.find("\t") ); 732 QString size = out.left( out.find("\t") );
730 int guess = size.toInt()/5; 733 int guess = size.toInt()/5;
731 if ( filePath.contains("doc") ) // No tr 734 if ( filePath.contains("doc") ) // No tr
732 guess *= 1000; 735 guess *= 1000;
733 odebug << "sending back gzip guess of " << guess << "" << oendl; 736 odebug << "sending back gzip guess of " << guess << "" << oendl;
734 send( "213 " + QString::number(guess) ); 737 send( "213 " + QString::number(guess) );
735 } 738 }
736 } 739 }
737 } 740 }
738 } 741 }
739 // name list (NLST) 742 // name list (NLST)
740 else if ( cmd == "NLST" ) { 743 else if ( cmd == "NLST" ) {
741 send( "502 Command not implemented" ); // No tr 744 send( "502 Command not implemented" ); // No tr
742 } 745 }
743 746
744 // site parameters (SITE) 747 // site parameters (SITE)
745 else if ( cmd == "SITE" ) { 748 else if ( cmd == "SITE" ) {
746 send( "502 Command not implemented" ); // No tr 749 send( "502 Command not implemented" ); // No tr
747 } 750 }
748 751
749 // system (SYST) 752 // system (SYST)
750 else if ( cmd == "SYST" ) { 753 else if ( cmd == "SYST" ) {
751 send( "215 UNIX Type: L8" ); // No tr 754 send( "215 UNIX Type: L8" ); // No tr
752 } 755 }
753 756
754 // status (STAT) 757 // status (STAT)
755 else if ( cmd == "STAT" ) { 758 else if ( cmd == "STAT" ) {
756 send( "502 Command not implemented" ); // No tr 759 send( "502 Command not implemented" ); // No tr
757 } 760 }
758 761
759 // help (HELP ) 762 // help (HELP )
760 else if ( cmd == "HELP" ) { 763 else if ( cmd == "HELP" ) {
761 send( "502 Command not implemented" ); // No tr 764 send( "502 Command not implemented" ); // No tr
762 } 765 }
763 766
764 // noop (NOOP) 767 // noop (NOOP)
765 else if ( cmd == "NOOP" ) { 768 else if ( cmd == "NOOP" ) {
766 send( "200 Command okay" ); // No tr 769 send( "200 Command okay" ); // No tr
767 } 770 }
768 771
769 // not implemented 772 // not implemented
770 else 773 else
771 send( "502 Command not implemented" ); // No tr 774 send( "502 Command not implemented" ); // No tr
772 775
773 lastCommand = cmd; 776 lastCommand = cmd;
774} 777}
775 778
776bool ServerPI::backupRestoreGzip( const QString &file ) 779bool ServerPI::backupRestoreGzip( const QString &file )
777{ 780{
778 return (file.find( "backup" ) != -1 && // No tr 781 return (file.find( "backup" ) != -1 && // No tr
779 file.findRev( ".tgz" ) == (int)file.length()-4 ); 782 file.findRev( ".tgz" ) == (int)file.length()-4 );
780} 783}
781 784
782bool ServerPI::backupRestoreGzip( const QString &file, QStringList &targets ) 785bool ServerPI::backupRestoreGzip( const QString &file, QStringList &targets )
783{ 786{
784 if ( file.find( "backup" ) != -1 && // No tr 787 if ( file.find( "backup" ) != -1 && // No tr
785 file.findRev( ".tgz" ) == (int)file.length()-4 ) { 788 file.findRev( ".tgz" ) == (int)file.length()-4 ) {
786 QFileInfo info( file ); 789 QFileInfo info( file );
787 targets = info.dirPath( TRUE ); 790 targets = info.dirPath( TRUE );
788 odebug << "ServerPI::backupRestoreGzip for " << file.latin1() << " = " << targets.join(" ").latin1() << oendl; 791 odebug << "ServerPI::backupRestoreGzip for " << file.latin1() << " = " << targets.join(" ").latin1() << oendl;
789 return true; 792 return true;
790 } 793 }
791 return false; 794 return false;
792} 795}
793 796
794void ServerPI::sendFile( const QString& file ) 797void ServerPI::sendFile( const QString& file )
795{ 798{
796 if ( passiv ) { 799 if ( passiv ) {
797 wait[SendFile] = TRUE; 800 wait[SendFile] = TRUE;
798 waitfile = file; 801 waitfile = file;
799 if ( waitsocket ) 802 if ( waitsocket )
800 newConnection( waitsocket ); 803 newConnection( waitsocket );
801 } 804 }
802 else { 805 else {
803 QStringList targets; 806 QStringList targets;
804 if ( backupRestoreGzip( file, targets ) ) 807 if ( backupRestoreGzip( file, targets ) )
805 dtp->sendGzipFile( file, targets, peeraddress, peerport ); 808 dtp->sendGzipFile( file, targets, peeraddress, peerport );
806 else dtp->sendFile( file, peeraddress, peerport ); 809 else dtp->sendFile( file, peeraddress, peerport );
807 } 810 }
808} 811}
809 812
810void ServerPI::retrieveFile( const QString& file ) 813void ServerPI::retrieveFile( const QString& file )
811{ 814{
812 if ( passiv ) { 815 if ( passiv ) {
813 wait[RetrieveFile] = TRUE; 816 wait[RetrieveFile] = TRUE;
814 waitfile = file; 817 waitfile = file;
815 if ( waitsocket ) 818 if ( waitsocket )
816 newConnection( waitsocket ); 819 newConnection( waitsocket );
817 } 820 }
818 else { 821 else {
819 QStringList targets; 822 QStringList targets;
820 if ( backupRestoreGzip( file, targets ) ) 823 if ( backupRestoreGzip( file, targets ) )
821 dtp->retrieveGzipFile( file, peeraddress, peerport ); 824 dtp->retrieveGzipFile( file, peeraddress, peerport );
822 else 825 else
823 dtp->retrieveFile( file, peeraddress, peerport, storFileSize ); 826 dtp->retrieveFile( file, peeraddress, peerport, storFileSize );
824 } 827 }
825} 828}
826 829