00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "qcopbridge.h"
00022 #include "transferserver.h"
00023
00024
00025 #include <qpe/qcopenvelope_qws.h>
00026 #include <qpe/qpeapplication.h>
00027 #include <qpe/version.h>
00028 #include <opie2/odebug.h>
00029
00030
00031 #include <qtextstream.h>
00032 #ifdef QWS
00033 #include <qcopchannel_qws.h>
00034 #endif
00035
00036
00037 #define _XOPEN_SOURCE
00038 #include <pwd.h>
00039 #include <sys/types.h>
00040 #include <unistd.h>
00041
00042 #if defined(_OS_LINUX_)
00043 #include <shadow.h>
00044 #endif
00045
00046
00047
00048 const int block_size = 51200;
00049
00050 QCopBridge::QCopBridge( Q_UINT16 port, QObject *parent ,
00051 const char* name )
00052 : QServerSocket( port, 1, parent, name ),
00053 desktopChannel( 0 ),
00054 cardChannel( 0 )
00055 {
00056 if ( !ok() )
00057 owarn << "Failed to bind to port " << port << "" << oendl;
00058 else {
00059 #ifndef QT_NO_COP
00060 desktopChannel = new QCopChannel( "QPE/Desktop", this );
00061 connect( desktopChannel, SIGNAL(received(const QCString&,const QByteArray&)),
00062 this, SLOT(desktopMessage(const QCString&,const QByteArray&)) );
00063 cardChannel = new QCopChannel( "QPE/Card", this );
00064 connect( cardChannel, SIGNAL(received(const QCString&,const QByteArray&)),
00065 this, SLOT(desktopMessage(const QCString&,const QByteArray&)) );
00066 #endif
00067 }
00068 sendSync = FALSE;
00069 }
00070
00071 QCopBridge::~QCopBridge()
00072 {
00073 #ifndef QT_NO_COP
00074 delete desktopChannel;
00075 #endif
00076 }
00077
00078 void QCopBridge::newConnection( int socket )
00079 {
00080 QCopBridgePI *pi = new QCopBridgePI( socket, this );
00081 openConnections.append( pi );
00082 connect ( pi, SIGNAL( connectionClosed(QCopBridgePI*) ), this, SLOT( connectionClosed(QCopBridgePI*) ) );
00083 #ifndef QT_NO_COP
00084 QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::DisableSuspend;
00085 #endif
00086
00087 if ( sendSync ) {
00088 pi ->startSync();
00089 sendSync = FALSE;
00090 }
00091 }
00092
00093 void QCopBridge::connectionClosed( QCopBridgePI *pi )
00094 {
00095 openConnections.remove( pi );
00096 if ( openConnections.count() == 0 ) {
00097 #ifndef QT_NO_COP
00098 QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable;
00099 #endif
00100 }
00101 }
00102
00103 void QCopBridge::closeOpenConnections()
00104 {
00105 QCopBridgePI *pi;
00106 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() )
00107 pi->close();
00108 }
00109
00110
00111 void QCopBridge::desktopMessage( const QCString &command, const QByteArray &args )
00112 {
00113 command.stripWhiteSpace();
00114
00115 int paren = command.find( "(" );
00116 if ( paren <= 0 ) {
00117 odebug << "DesktopMessage: bad qcop syntax" << oendl;
00118 return;
00119 }
00120
00121 QString params = command.mid( paren + 1 );
00122 if ( params[params.length()-1] != ')' ) {
00123 odebug << "DesktopMessage: bad qcop syntax" << oendl;
00124 return;
00125 }
00126
00127 params.truncate( params.length()-1 );
00128
00129 QStringList paramList = QStringList::split( ",", params );
00130 QString data;
00131 if ( paramList.count() ) {
00132 QDataStream stream( args, IO_ReadOnly );
00133 for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) {
00134 QString str;
00135 if ( *it == "QString" ) {
00136 stream >> str;
00137 } else if ( *it == "QCString" ) {
00138 QCString cstr;
00139 stream >> cstr;
00140 str = QString::fromLocal8Bit( cstr );
00141 } else if ( *it == "int" ) {
00142 int i;
00143 stream >> i;
00144 str = QString::number( i );
00145 } else if ( *it == "bool" ) {
00146 int i;
00147 stream >> i;
00148 str = QString::number( i );
00149 } else {
00150 odebug << " cannot route the argument type " << (*it) << " throught the qcop bridge" << oendl;
00151 return;
00152 }
00153 QString estr;
00154 for (int i=0; i<(int)str.length(); i++) {
00155 QChar ch = str[i];
00156 if ( ch.row() )
00157 goto quick;
00158 switch (ch.cell()) {
00159 case '&':
00160 estr.append( "&" );
00161 break;
00162 case ' ':
00163 estr.append( "&0x20;" );
00164 break;
00165 case '\n':
00166 estr.append( "&0x0d;" );
00167 break;
00168 case '\r':
00169 estr.append( "&0x0a;" );
00170 break;
00171 default: quick:
00172 estr.append(ch);
00173 }
00174 }
00175 data += " " + estr;
00176 }
00177 }
00178 QString sendCommand = QString(command.data()) + data;
00179
00180 if ( command == "startSync()" ) {
00181
00182 sendSync = TRUE;
00183 startTimer( 20000 );
00184 }
00185
00186 QCopBridgePI *pi;
00187 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() ) {
00188 pi->sendDesktopMessage( sendCommand );
00189 }
00190 }
00191
00192 void QCopBridge::timerEvent( QTimerEvent * )
00193 {
00194 sendSync = FALSE;
00195 killTimers();
00196 }
00197
00198
00199 QCopBridgePI::QCopBridgePI( int socket, QObject *parent , const char* name )
00200 : QSocket( parent, name )
00201 {
00202 setSocket( socket );
00203
00204 peerport = peerPort();
00205 peeraddress = peerAddress();
00206
00207 #ifndef INSECURE
00208 if ( !SyncAuthentication::isAuthorized(peeraddress) ) {
00209 state = Forbidden;
00210 startTimer( 0 );
00211 } else
00212 #endif
00213 {
00214 state = Connected;
00215 sendSync = FALSE;
00216 connect( this, SIGNAL( readyRead() ), SLOT( read() ) );
00217 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) );
00218
00219 QString intro="220 Qtopia ";
00220 intro += QPE_VERSION; intro += ";";
00221 intro += "challenge="; intro += SyncAuthentication::serverId(); intro += ";";
00222 intro += "loginname="; intro += SyncAuthentication::loginName(); intro += ";";
00223 intro += "displayname="; intro += SyncAuthentication::ownerName(); intro += ";";
00224 send( intro );
00225 state = Wait_USER;
00226
00227
00228 startTimer( 60000 );
00229 connected = TRUE;
00230 }
00231 }
00232
00233
00234 QCopBridgePI::~QCopBridgePI()
00235 {
00236
00237 }
00238
00239 void QCopBridgePI::connectionClosed()
00240 {
00241 emit connectionClosed( this );
00242
00243 delete this;
00244 }
00245
00246 void QCopBridgePI::sendDesktopMessage( const QString &msg )
00247 {
00248 QString str = "CALL QPE/Desktop " + msg;
00249 send ( str );
00250 }
00251
00252
00253 void QCopBridgePI::send( const QString& msg )
00254 {
00255 QTextStream os( this );
00256 os << msg << endl;
00257
00258 }
00259
00260 void QCopBridgePI::read()
00261 {
00262 while ( canReadLine() )
00263 process( readLine().stripWhiteSpace() );
00264 }
00265
00266 void QCopBridgePI::process( const QString& message )
00267 {
00268
00269
00270
00271 QStringList msg = QStringList::split( " ", message );
00272 if ( msg.isEmpty() ) return;
00273
00274
00275 QString cmd = msg[0].upper();
00276
00277
00278 QString arg;
00279 if ( msg.count() >= 2 )
00280 arg = msg[1];
00281
00282
00283 if ( cmd == "QUIT" ) {
00284 send( "211 Have a nice day!" );
00285 delete this;
00286 return;
00287 }
00288
00289
00290 if ( Connected == state )
00291 return;
00292
00293
00294 if ( Wait_USER == state ) {
00295
00296 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) {
00297 send( "530 Please login with USER and PASS" );
00298 return;
00299 }
00300 send( "331 User name ok, need password" );
00301 state = Wait_PASS;
00302 return;
00303 }
00304
00305
00306 if ( Wait_PASS == state ) {
00307
00308 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) {
00309 send( "530 Please login with USER and PASS" );
00310 return;
00311 }
00312 send( "230 User logged in, proceed" );
00313 state = Ready;
00314 if ( sendSync ) {
00315 sendDesktopMessage( "startSync()" );
00316 sendSync = FALSE;
00317 }
00318 return;
00319 }
00320
00321
00322 else if ( cmd == "NOOP" ) {
00323 connected = TRUE;
00324 send( "200 Command okay" );
00325 }
00326
00327
00328 else if ( cmd == "CALL" ) {
00329
00330
00331
00332 if ( msg.count() < 3 ) {
00333 send( "500 Syntax error, command unrecognized" );
00334 }
00335 else {
00336
00337 QString channel = msg[1];
00338 QString command = msg[2];
00339
00340 command.stripWhiteSpace();
00341
00342 int paren = command.find( "(" );
00343 if ( paren <= 0 ) {
00344 send( "500 Syntax error, command unrecognized" );
00345 return;
00346 }
00347
00348 QString params = command.mid( paren + 1 );
00349 if ( params[params.length()-1] != ')' ) {
00350 send( "500 Syntax error, command unrecognized" );
00351 return;
00352 }
00353
00354 params.truncate( params.length()-1 );
00355 QByteArray buffer;
00356 QDataStream ds( buffer, IO_WriteOnly );
00357
00358 int msgId = 3;
00359
00360 QStringList paramList = QStringList::split( ",", params );
00361 if ( paramList.count() > msg.count() - 3 ) {
00362 send( "500 Syntax error, command unrecognized" );
00363 return;
00364 }
00365
00366 for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) {
00367
00368 QString arg = msg[msgId];
00369 arg.replace( QRegExp("&0x20;"), " " );
00370 arg.replace( QRegExp("&"), "&" );
00371 arg.replace( QRegExp("&0x0d;"), "\n" );
00372 arg.replace( QRegExp("&0x0a;"), "\r" );
00373 if ( *it == "QString" )
00374 ds << arg;
00375 else if ( *it == "QCString" )
00376 ds << arg.local8Bit();
00377 else if ( *it == "int" )
00378 ds << arg.toInt();
00379 else if ( *it == "bool" )
00380 ds << arg.toInt();
00381 else {
00382 send( "500 Syntax error, command unrecognized" );
00383 return;
00384 }
00385 msgId++;
00386 }
00387
00388 #ifndef QT_NO_COP
00389 if ( !QCopChannel::isRegistered( channel.latin1() ) ) {
00390
00391 QString answer = "599 ChannelNotRegistered " + channel;
00392 send( answer );
00393 return;
00394 }
00395 #endif
00396
00397 #ifndef QT_NO_COP
00398 if ( paramList.count() )
00399 QCopChannel::send( channel.latin1(), command.latin1(), buffer );
00400 else
00401 QCopChannel::send( channel.latin1(), command.latin1() );
00402
00403 send( "200 Command okay" );
00404 #endif
00405 }
00406 }
00407
00408 else
00409 send( "502 Command not implemented" );
00410 }
00411
00412
00413
00414 void QCopBridgePI::timerEvent( QTimerEvent * )
00415 {
00416 if ( connected )
00417 connected = FALSE;
00418 else
00419 connectionClosed();
00420 }