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