summaryrefslogtreecommitdiff
path: root/core/qws/qcopbridge.cpp
Unidiff
Diffstat (limited to 'core/qws/qcopbridge.cpp') (more/less context) (show whitespace changes)
-rw-r--r--core/qws/qcopbridge.cpp422
1 files changed, 422 insertions, 0 deletions
diff --git a/core/qws/qcopbridge.cpp b/core/qws/qcopbridge.cpp
new file mode 100644
index 0000000..6177a7c
--- a/dev/null
+++ b/core/qws/qcopbridge.cpp
@@ -0,0 +1,422 @@
1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3**
4** This file is part of the Qtopia Environment.
5**
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
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
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.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include "qcopbridge.h"
22#include "transferserver.h"
23
24#include <qpe/qcopenvelope_qws.h>
25#include <qpe/qpeapplication.h>
26#include <qpe/version.h>
27
28#include <qdir.h>
29#include <qfile.h>
30#include <qtextstream.h>
31#include <qdatastream.h>
32#include <qstringlist.h>
33#include <qfileinfo.h>
34#include <qregexp.h>
35#ifdef QWS
36#include <qcopchannel_qws.h>
37#endif
38
39#define _XOPEN_SOURCE
40#include <pwd.h>
41#include <sys/types.h>
42#include <unistd.h>
43
44#if defined(_OS_LINUX_)
45#include <shadow.h>
46#endif
47
48//#define INSECURE
49
50const int block_size = 51200;
51
52QCopBridge::QCopBridge( Q_UINT16 port, QObject *parent ,
53 const char* name )
54 : QServerSocket( port, 1, parent, name ),
55 desktopChannel( 0 ),
56 cardChannel( 0 )
57{
58 if ( !ok() )
59 qWarning( "Failed to bind to port %d", port );
60 else {
61#ifndef QT_NO_COP
62 desktopChannel = new QCopChannel( "QPE/Desktop", this );
63 connect( desktopChannel, SIGNAL(received(const QCString &, const QByteArray &)),
64 this, SLOT(desktopMessage( const QCString &, const QByteArray &)) );
65 cardChannel = new QCopChannel( "QPE/Card", this );
66 connect( cardChannel, SIGNAL(received(const QCString &, const QByteArray &)),
67 this, SLOT(desktopMessage( const QCString &, const QByteArray &)) );
68#endif
69 }
70 sendSync = FALSE;
71}
72
73QCopBridge::~QCopBridge()
74{
75#ifndef QT_NO_COP
76 delete desktopChannel;
77#endif
78}
79
80void QCopBridge::newConnection( int socket )
81{
82 QCopBridgePI *pi = new QCopBridgePI( socket, this );
83 openConnections.append( pi );
84 connect ( pi, SIGNAL( connectionClosed( QCopBridgePI *) ), this, SLOT( connectionClosed( QCopBridgePI *) ) );
85#ifndef QT_NO_COP
86 QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::DisableSuspend;
87#endif
88
89 if ( sendSync ) {
90 pi ->startSync();
91 sendSync = FALSE;
92 }
93}
94
95void QCopBridge::connectionClosed( QCopBridgePI *pi )
96{
97 openConnections.remove( pi );
98 if ( openConnections.count() == 0 ) {
99#ifndef QT_NO_COP
100 QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable;
101#endif
102 }
103}
104
105void QCopBridge::closeOpenConnections()
106{
107 QCopBridgePI *pi;
108 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() )
109 pi->close();
110}
111
112
113void QCopBridge::desktopMessage( const QCString &command, const QByteArray &args )
114{
115 command.stripWhiteSpace();
116
117 int paren = command.find( "(" );
118 if ( paren <= 0 ) {
119 qDebug("DesktopMessage: bad qcop syntax");
120 return;
121 }
122
123 QString params = command.mid( paren + 1 );
124 if ( params[params.length()-1] != ')' ) {
125 qDebug("DesktopMessage: bad qcop syntax");
126 return;
127 }
128
129 params.truncate( params.length()-1 );
130
131 QStringList paramList = QStringList::split( ",", params );
132 QString data;
133 if ( paramList.count() ) {
134 QDataStream stream( args, IO_ReadOnly );
135 for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) {
136 QString str;
137 if ( *it == "QString" ) {
138 stream >> str;
139 } else if ( *it == "QCString" ) {
140 QCString cstr;
141 stream >> cstr;
142 str = QString::fromLocal8Bit( cstr );
143 } else if ( *it == "int" ) {
144 int i;
145 stream >> i;
146 str = QString::number( i );
147 } else if ( *it == "bool" ) {
148 int i;
149 stream >> i;
150 str = QString::number( i );
151 } else {
152 qDebug(" cannot route the argument type %s throught the qcop bridge", (*it).latin1() );
153 return;
154 }
155 QString estr;
156 for (int i=0; i<(int)str.length(); i++) {
157 QChar ch = str[i];
158 if ( ch.row() )
159 goto quick;
160 switch (ch.cell()) {
161 case '&':
162 estr.append( "&amp;" );
163 break;
164 case ' ':
165 estr.append( "&0x20;" );
166 break;
167 case '\n':
168 estr.append( "&0x0d;" );
169 break;
170 case '\r':
171 estr.append( "&0x0a;" );
172 break;
173 default: quick:
174 estr.append(ch);
175 }
176 }
177 data += " " + estr;
178 }
179 }
180 QString sendCommand = QString(command.data()) + data;
181 // send the command to all open connections
182 if ( command == "startSync()" ) {
183 // we need to buffer it a bit
184 sendSync = TRUE;
185 startTimer( 20000 );
186 }
187
188 QCopBridgePI *pi;
189 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() ) {
190 pi->sendDesktopMessage( sendCommand );
191 }
192}
193
194void QCopBridge::timerEvent( QTimerEvent * )
195{
196 sendSync = FALSE;
197 killTimers();
198}
199
200
201QCopBridgePI::QCopBridgePI( int socket, QObject *parent , const char* name )
202 : QSocket( parent, name )
203{
204 setSocket( socket );
205
206 peerport = peerPort();
207 peeraddress = peerAddress();
208
209#ifndef INSECURE
210 if ( !SyncAuthentication::isAuthorized(peeraddress) ) {
211 state = Forbidden;
212 startTimer( 0 );
213 } else
214 #endif
215 {
216 state = Connected;
217 sendSync = FALSE;
218 connect( this, SIGNAL( readyRead() ), SLOT( read() ) );
219 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) );
220
221 QString intro="220 Qtopia ";
222 intro += QPE_VERSION; intro += ";";
223 intro += "challenge="; intro += SyncAuthentication::serverId(); intro += ";";
224 intro += "loginname="; intro += SyncAuthentication::loginName(); intro += ";";
225 intro += "displayname="; intro += SyncAuthentication::ownerName(); intro += ";";
226 send( intro );
227 state = Wait_USER;
228
229 // idle timer to close connections when not used anymore
230 startTimer( 60000 );
231 connected = TRUE;
232 }
233}
234
235
236QCopBridgePI::~QCopBridgePI()
237{
238
239}
240
241void QCopBridgePI::connectionClosed()
242{
243 emit connectionClosed( this );
244 // qDebug( "Debug: Connection closed" );
245 delete this;
246}
247
248void QCopBridgePI::sendDesktopMessage( const QString &msg )
249{
250 QString str = "CALL QPE/Desktop " + msg;
251 send ( str );
252}
253
254
255void QCopBridgePI::send( const QString& msg )
256{
257 QTextStream os( this );
258 os << msg << endl;
259 //qDebug( "sending qcop message: %s", msg.latin1() );
260}
261
262void QCopBridgePI::read()
263{
264 while ( canReadLine() )
265 process( readLine().stripWhiteSpace() );
266}
267
268void QCopBridgePI::process( const QString& message )
269{
270 //qDebug( "Command: %s", message.latin1() );
271
272 // split message using "," as separator
273 QStringList msg = QStringList::split( " ", message );
274 if ( msg.isEmpty() ) return;
275
276 // command token
277 QString cmd = msg[0].upper();
278
279 // argument token
280 QString arg;
281 if ( msg.count() >= 2 )
282 arg = msg[1];
283
284 // we always respond to QUIT, regardless of state
285 if ( cmd == "QUIT" ) {
286 send( "211 Have a nice day!" );
287 delete this;
288 return;
289 }
290
291 // connected to client
292 if ( Connected == state )
293 return;
294
295 // waiting for user name
296 if ( Wait_USER == state ) {
297
298 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) {
299 send( "530 Please login with USER and PASS" );
300 return;
301 }
302 send( "331 User name ok, need password" );
303 state = Wait_PASS;
304 return;
305 }
306
307 // waiting for password
308 if ( Wait_PASS == state ) {
309
310 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) {
311 send( "530 Please login with USER and PASS" );
312 return;
313 }
314 send( "230 User logged in, proceed" );
315 state = Ready;
316 if ( sendSync ) {
317 sendDesktopMessage( "startSync()" );
318 sendSync = FALSE;
319 }
320 return;
321 }
322
323 // noop (NOOP)
324 else if ( cmd == "NOOP" ) {
325 connected = TRUE;
326 send( "200 Command okay" );
327 }
328
329 // call (CALL)
330 else if ( cmd == "CALL" ) {
331
332 // example: call QPE/System execute(QString) addressbook
333
334 if ( msg.count() < 3 ) {
335 send( "500 Syntax error, command unrecognized" );
336 }
337 else {
338
339 QString channel = msg[1];
340 QString command = msg[2];
341
342 command.stripWhiteSpace();
343
344 int paren = command.find( "(" );
345 if ( paren <= 0 ) {
346 send( "500 Syntax error, command unrecognized" );
347 return;
348 }
349
350 QString params = command.mid( paren + 1 );
351 if ( params[params.length()-1] != ')' ) {
352 send( "500 Syntax error, command unrecognized" );
353 return;
354 }
355
356 params.truncate( params.length()-1 );
357 QByteArray buffer;
358 QDataStream ds( buffer, IO_WriteOnly );
359
360 int msgId = 3;
361
362 QStringList paramList = QStringList::split( ",", params );
363 if ( paramList.count() > msg.count() - 3 ) {
364 send( "500 Syntax error, command unrecognized" );
365 return;
366 }
367
368 for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) {
369
370 QString arg = msg[msgId];
371 arg.replace( QRegExp("&0x20;"), " " );
372 arg.replace( QRegExp("&amp;"), "&" );
373 arg.replace( QRegExp("&0x0d;"), "\n" );
374 arg.replace( QRegExp("&0x0a;"), "\r" );
375 if ( *it == "QString" )
376 ds << arg;
377 else if ( *it == "QCString" )
378 ds << arg.local8Bit();
379 else if ( *it == "int" )
380 ds << arg.toInt();
381 else if ( *it == "bool" )
382 ds << arg.toInt();
383 else {
384 send( "500 Syntax error, command unrecognized" );
385 return;
386 }
387 msgId++;
388 }
389
390#ifndef QT_NO_COP
391 if ( !QCopChannel::isRegistered( channel.latin1() ) ) {
392 // send message back about it
393 QString answer = "599 ChannelNotRegistered " + channel;
394 send( answer );
395 return;
396 }
397#endif
398
399#ifndef QT_NO_COP
400 if ( paramList.count() )
401 QCopChannel::send( channel.latin1(), command.latin1(), buffer );
402 else
403 QCopChannel::send( channel.latin1(), command.latin1() );
404
405 send( "200 Command okay" );
406#endif
407 }
408 }
409 // not implemented
410 else
411 send( "502 Command not implemented" );
412}
413
414
415
416void QCopBridgePI::timerEvent( QTimerEvent * )
417{
418 if ( connected )
419 connected = FALSE;
420 else
421 connectionClosed();
422}