Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

qcopbridge.cpp

Go to the documentation of this file.
00001 /**********************************************************************
00002 ** Copyright (C) 2000-2002 Trolltech AS.  All rights reserved.
00003 **
00004 ** This file is part of the Qtopia Environment.
00005 **
00006 ** This file may be distributed and/or modified under the terms of the
00007 ** GNU General Public License version 2 as published by the Free Software
00008 ** Foundation and appearing in the file LICENSE.GPL included in the
00009 ** packaging of this file.
00010 **
00011 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 **
00014 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
00015 **
00016 ** Contact info@trolltech.com if any conditions of this licensing are
00017 ** not clear to you.
00018 **
00019 **********************************************************************/
00020 
00021 #include "qcopbridge.h"
00022 #include "transferserver.h"
00023 
00024 /* OPIE */
00025 #include <qpe/qcopenvelope_qws.h>
00026 #include <qpe/qpeapplication.h>
00027 #include <qpe/version.h>
00028 #include <opie2/odebug.h>
00029 
00030 /* QT */
00031 #include <qtextstream.h>
00032 #ifdef QWS
00033 #include <qcopchannel_qws.h>
00034 #endif
00035 
00036 /* STD */
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 //#define INSECURE
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( "&amp;" );
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     // send the command to all open connections
00180     if ( command == "startSync()" ) {
00181     // we need to buffer it a bit
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     // idle timer to close connections when not used anymore
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     // odebug << "Debug: Connection closed" << oendl;
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     //odebug << "sending qcop message: " << msg << "" << oendl;
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     //odebug << "Command: " << message << "" << oendl;
00269 
00270     // split message using "," as separator
00271     QStringList msg = QStringList::split( " ", message );
00272     if ( msg.isEmpty() ) return;
00273 
00274     // command token
00275     QString cmd = msg[0].upper();
00276 
00277     // argument token
00278     QString arg;
00279     if ( msg.count() >= 2 )
00280     arg = msg[1];
00281 
00282     // we always respond to QUIT, regardless of state
00283     if ( cmd == "QUIT" ) {
00284     send( "211 Have a nice day!" );
00285     delete this;
00286     return;
00287     }
00288 
00289     // connected to client
00290     if ( Connected == state )
00291     return;
00292 
00293     // waiting for user name
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     // waiting for password
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     // noop (NOOP)
00322     else if ( cmd == "NOOP" ) {
00323     connected = TRUE;
00324     send( "200 Command okay" );
00325     }
00326 
00327     // call (CALL)
00328     else if ( cmd == "CALL" ) {
00329 
00330     // example: call QPE/System execute(QString) addressbook
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("&amp;"), "&" );
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         // send message back about it
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     // not implemented
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 }

Generated on Sat Nov 5 16:15:31 2005 for OPIE by  doxygen 1.4.2