summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/launcher/qcopbridge.cpp222
-rw-r--r--core/launcher/qcopbridge.h25
-rw-r--r--core/launcher/runningappbar.cpp356
3 files changed, 228 insertions, 375 deletions
diff --git a/core/launcher/qcopbridge.cpp b/core/launcher/qcopbridge.cpp
index 6177a7c..f780235 100644
--- a/core/launcher/qcopbridge.cpp
+++ b/core/launcher/qcopbridge.cpp
@@ -1,422 +1,404 @@
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#include <qpe/qcopenvelope_qws.h> 24#ifdef Q_WS_QWS
25#include <qpe/qpeapplication.h> 25#include <qtopia/qcopenvelope_qws.h>
26#include <qpe/version.h> 26#endif
27#include <qtopia/qpeapplication.h>
28#include <qtopia/global.h>
29#include <qtopia/version.h>
27 30
28#include <qdir.h> 31#include <qdir.h>
29#include <qfile.h> 32#include <qfile.h>
30#include <qtextstream.h> 33#include <qtextstream.h>
31#include <qdatastream.h> 34#include <qdatastream.h>
35#include <qcstring.h>
32#include <qstringlist.h> 36#include <qstringlist.h>
33#include <qfileinfo.h> 37#include <qfileinfo.h>
34#include <qregexp.h> 38#include <qregexp.h>
35#ifdef QWS 39#include <qtimer.h>
40#ifdef Q_WS_QWS
36#include <qcopchannel_qws.h> 41#include <qcopchannel_qws.h>
37#endif 42#endif
38 43
44#ifndef _XOPEN_SOURCE
39#define _XOPEN_SOURCE 45#define _XOPEN_SOURCE
46#endif
47#ifndef Q_OS_WIN32
40#include <pwd.h> 48#include <pwd.h>
41#include <sys/types.h>
42#include <unistd.h> 49#include <unistd.h>
50#include <sys/types.h>
51#endif
43 52
44#if defined(_OS_LINUX_) 53#if defined(_OS_LINUX_)
45#include <shadow.h> 54#include <shadow.h>
46#endif 55#endif
47 56
57#include "launcherglobal.h"
58
48//#define INSECURE 59//#define INSECURE
49 60
50const int block_size = 51200; 61const int block_size = 51200;
51 62
52QCopBridge::QCopBridge( Q_UINT16 port, QObject *parent , 63QCopBridge::QCopBridge( Q_UINT16 port, QObject *parent,
53 const char* name ) 64 const char* name )
54 : QServerSocket( port, 1, parent, name ), 65 : QServerSocket( port, 1, parent, name ),
55 desktopChannel( 0 ), 66 desktopChannel( 0 ),
56 cardChannel( 0 ) 67 cardChannel( 0 )
57{ 68{
58 if ( !ok() ) 69 if ( !ok() )
59 qWarning( "Failed to bind to port %d", port ); 70 qWarning( "Failed to bind to port %d", port );
60 else { 71 else {
61#ifndef QT_NO_COP 72#ifndef QT_NO_COP
62 desktopChannel = new QCopChannel( "QPE/Desktop", this ); 73 desktopChannel = new QCopChannel( "QPE/Desktop", this );
63 connect( desktopChannel, SIGNAL(received(const QCString &, const QByteArray &)), 74 connect( desktopChannel, SIGNAL(received(const QCString &, const QByteArray &)),
64 this, SLOT(desktopMessage( const QCString &, const QByteArray &)) ); 75 this, SLOT(desktopMessage( const QCString &, const QByteArray &)) );
65 cardChannel = new QCopChannel( "QPE/Card", this ); 76 cardChannel = new QCopChannel( "QPE/Card", this );
66 connect( cardChannel, SIGNAL(received(const QCString &, const QByteArray &)), 77 connect( cardChannel, SIGNAL(received(const QCString &, const QByteArray &)),
67 this, SLOT(desktopMessage( const QCString &, const QByteArray &)) ); 78 this, SLOT(desktopMessage( const QCString &, const QByteArray &)) );
68#endif 79#endif
69 } 80 }
70 sendSync = FALSE; 81 sendSync = FALSE;
82 openConnections.setAutoDelete( TRUE );
71} 83}
72 84
73QCopBridge::~QCopBridge() 85QCopBridge::~QCopBridge()
74{ 86{
75#ifndef QT_NO_COP 87#ifndef QT_NO_COP
76 delete desktopChannel; 88 delete desktopChannel;
77#endif 89#endif
78} 90}
79 91
92void QCopBridge::authorizeConnections()
93{
94 QListIterator<QCopBridgePI> it(openConnections);
95 while ( it.current() ) {
96 if ( !it.current()->verifyAuthorised() ) {
97 disconnect ( it.current(), SIGNAL( connectionClosed( QCopBridgePI *) ), this, SLOT( closed( QCopBridgePI *) ) );
98 openConnections.removeRef( it.current() );
99 } else
100 ++it;
101 }
102}
103
80void QCopBridge::newConnection( int socket ) 104void QCopBridge::newConnection( int socket )
81{ 105{
82 QCopBridgePI *pi = new QCopBridgePI( socket, this ); 106 QCopBridgePI *pi = new QCopBridgePI( socket, this );
83 openConnections.append( pi ); 107 openConnections.append( pi );
84 connect ( pi, SIGNAL( connectionClosed( QCopBridgePI *) ), this, SLOT( connectionClosed( QCopBridgePI *) ) ); 108 connect ( pi, SIGNAL( connectionClosed( QCopBridgePI *) ), this, SLOT( closed( QCopBridgePI *) ) );
109
110 /* ### libqtopia merge FIXME */
111#if 0
112 QPEApplication::setTempScreenSaverMode( QPEApplication::DisableSuspend );
113#endif
85#ifndef QT_NO_COP 114#ifndef QT_NO_COP
86 QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::DisableSuspend; 115 QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::DisableSuspend;
87#endif 116#endif
88 117
89 if ( sendSync ) { 118 if ( sendSync ) {
90 pi ->startSync(); 119 pi ->startSync();
91 sendSync = FALSE; 120 sendSync = FALSE;
92 } 121 }
93} 122}
94 123
95void QCopBridge::connectionClosed( QCopBridgePI *pi ) 124void QCopBridge::closed( QCopBridgePI *pi )
96{ 125{
97 openConnections.remove( pi ); 126 emit connectionClosed( pi->peerAddress() );
127 openConnections.removeRef( pi );
98 if ( openConnections.count() == 0 ) { 128 if ( openConnections.count() == 0 ) {
129 /* ### FIXME libqtopia merge */
130#if 0
131 QPEApplication::setTempScreenSaverMode( QPEApplication::Enable );
132#endif
99#ifndef QT_NO_COP 133#ifndef QT_NO_COP
100 QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable; 134 QCopEnvelope( "QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable;
101#endif 135#endif
102 } 136 }
103} 137}
104 138
105void QCopBridge::closeOpenConnections() 139void QCopBridge::closeOpenConnections()
106{ 140{
107 QCopBridgePI *pi; 141 QCopBridgePI *pi;
108 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() ) 142 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() )
109 pi->close(); 143 pi->close();
110} 144}
111 145
112 146
113void QCopBridge::desktopMessage( const QCString &command, const QByteArray &args ) 147void QCopBridge::desktopMessage( const QCString &command, const QByteArray &data )
114{ 148{
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()" ) { 149 if ( command == "startSync()" ) {
183 // we need to buffer it a bit 150 // we need to buffer it a bit
184 sendSync = TRUE; 151 sendSync = TRUE;
185 startTimer( 20000 ); 152 startTimer( 20000 );
186 } 153 }
187 154
155 // send the command to all open connections
188 QCopBridgePI *pi; 156 QCopBridgePI *pi;
189 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() ) { 157 for ( pi = openConnections.first(); pi != 0; pi = openConnections.next() ) {
190 pi->sendDesktopMessage( sendCommand ); 158 pi->sendDesktopMessage( command, data );
191 } 159 }
192} 160}
193 161
194void QCopBridge::timerEvent( QTimerEvent * ) 162void QCopBridge::timerEvent( QTimerEvent * )
195{ 163{
196 sendSync = FALSE; 164 sendSync = FALSE;
197 killTimers(); 165 killTimers();
198} 166}
199 167
200 168
201QCopBridgePI::QCopBridgePI( int socket, QObject *parent , const char* name ) 169QCopBridgePI::QCopBridgePI( int socket, QObject *parent, const char* name )
202 : QSocket( parent, name ) 170 : QSocket( parent, name )
203{ 171{
204 setSocket( socket ); 172 setSocket( socket );
205 173
206 peerport = peerPort(); 174 peerport = peerPort();
207 peeraddress = peerAddress(); 175 peeraddress = peerAddress();
208 176
209#ifndef INSECURE 177#ifndef INSECURE
210 if ( !SyncAuthentication::isAuthorized(peeraddress) ) { 178 if ( !SyncAuthentication::isAuthorized(peeraddress) ) {
211 state = Forbidden; 179 state = Forbidden;
212 startTimer( 0 ); 180 close();
213 } else 181 } else
214 #endif 182#endif
215 { 183 {
216 state = Connected; 184 state = Connected;
217 sendSync = FALSE;
218 connect( this, SIGNAL( readyRead() ), SLOT( read() ) ); 185 connect( this, SIGNAL( readyRead() ), SLOT( read() ) );
219 connect( this, SIGNAL( connectionClosed() ), SLOT( connectionClosed() ) );
220
221 QString intro="220 Qtopia "; 186 QString intro="220 Qtopia ";
222 intro += QPE_VERSION; intro += ";"; 187 intro += QPE_VERSION; intro += ";";
223 intro += "challenge="; intro += SyncAuthentication::serverId(); intro += ";"; 188 intro += "challenge="; intro += SyncAuthentication::serverId(); intro += ";"; // No tr
224 intro += "loginname="; intro += SyncAuthentication::loginName(); intro += ";"; 189 intro += "loginname="; intro += SyncAuthentication::loginName(); intro += ";";
225 intro += "displayname="; intro += SyncAuthentication::ownerName(); intro += ";"; 190 intro += "displayname="; intro += SyncAuthentication::ownerName(); intro += ";";
226 send( intro ); 191 send( intro );
227 state = Wait_USER; 192 state = Wait_USER;
228
229 // idle timer to close connections when not used anymore
230 startTimer( 60000 );
231 connected = TRUE;
232 } 193 }
194 sendSync = FALSE;
195 connect( this, SIGNAL( connectionClosed() ), SLOT( myConnectionClosed() ) );
196
197 // idle timer to close connections when not used anymore
198 timer = new QTimer(this);
199 connect( timer, SIGNAL(timeout()), this, SLOT(myConnectionClosed()) );
200 timer->start( 300000, TRUE );
233} 201}
234 202
235 203
236QCopBridgePI::~QCopBridgePI() 204QCopBridgePI::~QCopBridgePI()
237{ 205{
206}
238 207
208bool QCopBridgePI::verifyAuthorised()
209{
210 if ( !SyncAuthentication::isAuthorized(peerAddress()) ) {
211 state = Forbidden;
212 return FALSE;
213 }
214 return TRUE;
239} 215}
240 216
241void QCopBridgePI::connectionClosed() 217void QCopBridgePI::myConnectionClosed()
242{ 218{
243 emit connectionClosed( this ); 219 emit connectionClosed( this );
244 // qDebug( "Debug: Connection closed" );
245 delete this;
246} 220}
247 221
248void QCopBridgePI::sendDesktopMessage( const QString &msg ) 222void QCopBridgePI::sendDesktopMessage( const QString &msg )
249{ 223{
250 QString str = "CALL QPE/Desktop " + msg; 224 QString str = "CALL QPE/Desktop " + msg; // No tr
251 send ( str ); 225 send ( str );
252} 226}
253 227
228void QCopBridgePI::sendDesktopMessage( const QCString &msg, const QByteArray& data )
229{
230 if ( !isOpen() ) // eg. Forbidden
231 return;
232 const char hdr[]="CALLB QPE/Desktop ";
233 writeBlock(hdr,sizeof(hdr)-1);
234 writeBlock(msg,msg.length());
235 writeBlock(" ",1);
236 QByteArray b64 = Opie::Global::encodeBase64(data);
237 writeBlock(b64.data(),b64.size());
238 writeBlock("\r\n",2);
239}
240
254 241
255void QCopBridgePI::send( const QString& msg ) 242void QCopBridgePI::send( const QString& msg )
256{ 243{
244 if ( !isOpen() ) // eg. Forbidden
245 return;
257 QTextStream os( this ); 246 QTextStream os( this );
258 os << msg << endl; 247 os << msg << endl;
259 //qDebug( "sending qcop message: %s", msg.latin1() ); 248 //qDebug( "sending qcop message: %s", msg.latin1() );
260} 249}
261 250
262void QCopBridgePI::read() 251void QCopBridgePI::read()
263{ 252{
264 while ( canReadLine() ) 253 while ( canReadLine() ) {
254 timer->start( 300000, TRUE );
265 process( readLine().stripWhiteSpace() ); 255 process( readLine().stripWhiteSpace() );
256 }
266} 257}
267 258
268void QCopBridgePI::process( const QString& message ) 259void QCopBridgePI::process( const QString& message )
269{ 260{
270 //qDebug( "Command: %s", message.latin1() ); 261 //qDebug( "Command: %s", message.latin1() );
271 262
272 // split message using "," as separator 263 // split message using "," as separator
273 QStringList msg = QStringList::split( " ", message ); 264 QStringList msg = QStringList::split( " ", message );
274 if ( msg.isEmpty() ) return; 265 if ( msg.isEmpty() ) return;
275 266
276 // command token 267 // command token
277 QString cmd = msg[0].upper(); 268 QString cmd = msg[0].upper();
278 269
279 // argument token 270 // argument token
280 QString arg; 271 QString arg;
281 if ( msg.count() >= 2 ) 272 if ( msg.count() >= 2 )
282 arg = msg[1]; 273 arg = msg[1];
283 274
284 // we always respond to QUIT, regardless of state 275 // we always respond to QUIT, regardless of state
285 if ( cmd == "QUIT" ) { 276 if ( cmd == "QUIT" ) {
286 send( "211 Have a nice day!" ); 277 send( "211 Have a nice day!" ); // No tr
287 delete this; 278 close();
288 return; 279 return;
289 } 280 }
290 281
291 // connected to client 282 // connected to client
292 if ( Connected == state ) 283 if ( Connected == state )
293 return; 284 return;
294 285
295 // waiting for user name 286 // waiting for user name
296 if ( Wait_USER == state ) { 287 if ( Wait_USER == state ) {
297 288
298 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) { 289 if ( cmd != "USER" || msg.count() < 2 || !SyncAuthentication::checkUser( arg ) ) {
299 send( "530 Please login with USER and PASS" ); 290 send( "530 Please login with USER and PASS" ); // No tr
300 return; 291 return;
301 } 292 }
302 send( "331 User name ok, need password" ); 293 send( "331 User name ok, need password" ); // No tr
303 state = Wait_PASS; 294 state = Wait_PASS;
304 return; 295 return;
305 } 296 }
306 297
307 // waiting for password 298 // waiting for password
308 if ( Wait_PASS == state ) { 299 if ( Wait_PASS == state ) {
309 300
310 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) { 301 if ( cmd != "PASS" || !SyncAuthentication::checkPassword( arg ) ) {
311 send( "530 Please login with USER and PASS" ); 302 send( "530 Please login with USER and PASS" ); // No tr
312 return; 303 return;
313 } 304 }
314 send( "230 User logged in, proceed" ); 305 send( "230 User logged in, proceed" ); // No tr
315 state = Ready; 306 state = Ready;
316 if ( sendSync ) { 307 if ( sendSync ) {
317 sendDesktopMessage( "startSync()" ); 308 sendDesktopMessage( "startSync()" );
318 sendSync = FALSE; 309 sendSync = FALSE;
319 } 310 }
320 return; 311 return;
321 } 312 }
322 313
323 // noop (NOOP) 314 // noop (NOOP)
324 else if ( cmd == "NOOP" ) { 315 else if ( cmd == "NOOP" ) {
325 connected = TRUE; 316 send( "200 Command okay" ); // No tr
326 send( "200 Command okay" );
327 } 317 }
328 318
329 // call (CALL) 319 // call (CALL)
330 else if ( cmd == "CALL" ) { 320 else if ( cmd == "CALL" ) {
331 321
332 // example: call QPE/System execute(QString) addressbook 322 // example: call QPE/System execute(QString) addressbook
333 323
334 if ( msg.count() < 3 ) { 324 if ( msg.count() < 3 ) {
335 send( "500 Syntax error, command unrecognized" ); 325 send( "500 Syntax error, command unrecognized" ); // No tr
336 } 326 }
337 else { 327 else {
338 328
339 QString channel = msg[1]; 329 QString channel = msg[1];
340 QString command = msg[2]; 330 QString command = msg[2];
341 331
342 command.stripWhiteSpace(); 332 command.stripWhiteSpace();
343 333
344 int paren = command.find( "(" ); 334 int paren = command.find( "(" );
345 if ( paren <= 0 ) { 335 if ( paren <= 0 ) {
346 send( "500 Syntax error, command unrecognized" ); 336 send( "500 Syntax error, command unrecognized" ); // No tr
347 return; 337 return;
348 } 338 }
349 339
350 QString params = command.mid( paren + 1 ); 340 QString params = command.mid( paren + 1 );
351 if ( params[params.length()-1] != ')' ) { 341 if ( params[(int)params.length()-1] != ')' ) {
352 send( "500 Syntax error, command unrecognized" ); 342 send( "500 Syntax error, command unrecognized" ); // No tr
353 return; 343 return;
354 } 344 }
355 345
356 params.truncate( params.length()-1 ); 346 params.truncate( params.length()-1 );
357 QByteArray buffer; 347 QByteArray buffer;
358 QDataStream ds( buffer, IO_WriteOnly ); 348 QDataStream ds( buffer, IO_WriteOnly );
359 349
360 int msgId = 3; 350 int msgId = 3;
361 351
362 QStringList paramList = QStringList::split( ",", params ); 352 QStringList paramList = QStringList::split( ",", params );
363 if ( paramList.count() > msg.count() - 3 ) { 353 if ( paramList.count() > msg.count() - 3 ) {
364 send( "500 Syntax error, command unrecognized" ); 354 send( "500 Syntax error, command unrecognized" ); // No tr
365 return; 355 return;
366 } 356 }
367 357
368 for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) { 358 for ( QStringList::Iterator it = paramList.begin(); it != paramList.end(); ++it ) {
369 359
370 QString arg = msg[msgId]; 360 QString arg = msg[msgId];
371 arg.replace( QRegExp("&0x20;"), " " ); 361 arg.replace( QRegExp("&0x20;"), " " );
372 arg.replace( QRegExp("&amp;"), "&" ); 362 arg.replace( QRegExp("&amp;"), "&" );
373 arg.replace( QRegExp("&0x0d;"), "\n" ); 363 arg.replace( QRegExp("&0x0d;"), "\n" );
374 arg.replace( QRegExp("&0x0a;"), "\r" ); 364 arg.replace( QRegExp("&0x0a;"), "\r" );
375 if ( *it == "QString" ) 365 if ( *it == "QString" )
376 ds << arg; 366 ds << arg;
377 else if ( *it == "QCString" ) 367 else if ( *it == "QCString" )
378 ds << arg.local8Bit(); 368 ds << arg.local8Bit();
379 else if ( *it == "int" ) 369 else if ( *it == "int" )
380 ds << arg.toInt(); 370 ds << arg.toInt();
381 else if ( *it == "bool" ) 371 else if ( *it == "bool" )
382 ds << arg.toInt(); 372 ds << arg.toInt();
383 else { 373 else {
384 send( "500 Syntax error, command unrecognized" ); 374 send( "500 Syntax error, command unrecognized" ); // No tr
385 return; 375 return;
386 } 376 }
387 msgId++; 377 msgId++;
388 } 378 }
389 379
390#ifndef QT_NO_COP 380#ifndef QT_NO_COP
391 if ( !QCopChannel::isRegistered( channel.latin1() ) ) { 381 if ( !QCopChannel::isRegistered( channel.latin1() ) ) {
392 // send message back about it 382 // send message back about it
393 QString answer = "599 ChannelNotRegistered " + channel; 383 QString answer = "599 ChannelNotRegistered " + channel;
394 send( answer ); 384 send( answer );
395 return; 385 return;
396 } 386 }
397#endif 387#endif
398 388
399#ifndef QT_NO_COP 389#ifndef QT_NO_COP
400 if ( paramList.count() ) 390 if ( paramList.count() )
401 QCopChannel::send( channel.latin1(), command.latin1(), buffer ); 391 QCopChannel::send( channel.latin1(), command.latin1(), buffer );
402 else 392 else
403 QCopChannel::send( channel.latin1(), command.latin1() ); 393 QCopChannel::send( channel.latin1(), command.latin1() );
404 394
405 send( "200 Command okay" ); 395 send( "200 Command okay" ); // No tr
406#endif 396#endif
407 } 397 }
408 } 398 }
409 // not implemented 399 // not implemented
410 else 400 else
411 send( "502 Command not implemented" ); 401 send( "502 Command not implemented" ); // No tr
412} 402}
413 403
414 404
415
416void QCopBridgePI::timerEvent( QTimerEvent * )
417{
418 if ( connected )
419 connected = FALSE;
420 else
421 connectionClosed();
422}
diff --git a/core/launcher/qcopbridge.h b/core/launcher/qcopbridge.h
index 408d10d..bae3f88 100644
--- a/core/launcher/qcopbridge.h
+++ b/core/launcher/qcopbridge.h
@@ -1,92 +1,97 @@
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#ifndef __qcopbridge_h__ 20#ifndef __qcopbridge_h__
21#define __qcopbridge_h__ 21#define __qcopbridge_h__
22 22
23#include <qtopia/global.h>
23#include <qserversocket.h> 24#include <qserversocket.h>
24#include <qsocket.h> 25#include <qsocket.h>
25#include <qdir.h> 26#include <qdir.h>
26#include <qfile.h> 27#include <qfile.h>
27#include <qbuffer.h> 28#include <qbuffer.h>
28 29
29class QFileInfo; 30class QFileInfo;
30class QCopBridgePI; 31class QCopBridgePI;
31class QCopChannel; 32class QCopChannel;
33class QTimer;
32 34
33class QCopBridge : public QServerSocket 35class QCopBridge : public QServerSocket
34{ 36{
35 Q_OBJECT 37 Q_OBJECT
36 38
37public: 39public:
38 QCopBridge( Q_UINT16 port, QObject *parent = 0, const char* name = 0 ); 40 QCopBridge( Q_UINT16 port, QObject *parent = 0, const char* name = 0 );
39 virtual ~QCopBridge(); 41 virtual ~QCopBridge();
40 42
41 void newConnection( int socket ); 43 void newConnection( int socket );
42 void closeOpenConnections(); 44 void closeOpenConnections();
45 void authorizeConnections();
43 46
44public slots: 47public slots:
45 void connectionClosed( QCopBridgePI *pi ); 48 void closed( QCopBridgePI *pi );
46 void desktopMessage( const QCString &call, const QByteArray & ); 49 void desktopMessage( const QCString &call, const QByteArray & );
47 50
51signals:
52 void connectionClosed( const QHostAddress & );
53
48protected: 54protected:
49 void timerEvent( QTimerEvent * ); 55 void timerEvent( QTimerEvent * );
50 56
51private: 57private:
52 QCopChannel *desktopChannel; 58 QCopChannel *desktopChannel;
53 QCopChannel *cardChannel; 59 QCopChannel *cardChannel;
54 QList<QCopBridgePI> openConnections; 60 QList<QCopBridgePI> openConnections;
55 bool sendSync; 61 bool sendSync;
56}; 62};
57 63
58 64
59class QCopBridgePI : public QSocket 65class QCopBridgePI : public QSocket
60{ 66{
61 Q_OBJECT 67 Q_OBJECT
62 68
63 enum State { Connected, Wait_USER, Wait_PASS, Ready, Forbidden }; 69 enum State { Connected, Wait_USER, Wait_PASS, Ready, Forbidden };
64 70
65public: 71public:
66 QCopBridgePI( int socket, QObject *parent = 0, const char* name = 0 ); 72 QCopBridgePI( int socket, QObject *parent = 0, const char* name = 0 );
67 virtual ~QCopBridgePI(); 73 virtual ~QCopBridgePI();
68 74
69 void sendDesktopMessage( const QString &msg ); 75 void sendDesktopMessage( const QString &msg );
76 void sendDesktopMessage( const QCString &msg, const QByteArray& );
70 void startSync() { sendSync = TRUE; } 77 void startSync() { sendSync = TRUE; }
71 78 bool verifyAuthorised();
79
72signals: 80signals:
73 void connectionClosed( QCopBridgePI *); 81 void connectionClosed( QCopBridgePI *);
74 82
75protected slots: 83protected slots:
76 void read(); 84 void read();
77 void send( const QString& msg ); 85 void send( const QString& msg );
78 void process( const QString& command ); 86 void process( const QString& command );
79 void connectionClosed(); 87 void myConnectionClosed();
80
81protected:
82 void timerEvent( QTimerEvent *e );
83 88
84private: 89private:
85 State state; 90 State state;
86 Q_UINT16 peerport; 91 Q_UINT16 peerport;
87 QHostAddress peeraddress; 92 QHostAddress peeraddress;
88 bool connected;
89 bool sendSync; 93 bool sendSync;
94 QTimer *timer;
90}; 95};
91 96
92#endif 97#endif
diff --git a/core/launcher/runningappbar.cpp b/core/launcher/runningappbar.cpp
index 356200b..1fda5a4 100644
--- a/core/launcher/runningappbar.cpp
+++ b/core/launcher/runningappbar.cpp
@@ -1,313 +1,179 @@
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*/
21 20
22#define QTOPIA_INTERNAL_PRELOADACCESS 21#define QTOPIA_INTERNAL_PRELOADACCESS
23 22
24// For "kill" 23#include <qtopia/global.h>
25#include <sys/types.h> 24
26#include <signal.h>
27#include <stdio.h>
28#include <stdlib.h> 25#include <stdlib.h>
29 26
30#include <qdir.h>
31#include <qtimer.h> 27#include <qtimer.h>
32#include <qpopupmenu.h> 28#include <qpopupmenu.h>
33#include <qmessagebox.h>
34#include <qpainter.h> 29#include <qpainter.h>
35#include <opie/oprocess.h> 30#include <qmessagebox.h>
36#include <qpe/qpeapplication.h> 31
37#include <qpe/applnk.h> 32#include <qtopia/qpeapplication.h>
38#include <qpe/qcopenvelope_qws.h> 33#include <qtopia/applnk.h>
39#include <qpe/global.h> 34#include <qtopia/qcopenvelope_qws.h>
40#include <qwindowsystem_qws.h> 35#include <qtopia/mimetype.h>
36
41#include "runningappbar.h" 37#include "runningappbar.h"
38#include "serverinterface.h"
42 39
43RunningAppBar::RunningAppBar(QWidget* parent) 40RunningAppBar::RunningAppBar(QWidget* parent)
44 : QFrame(parent), m_AppLnkSet(0L), m_SelectedAppIndex( -1) 41 : QFrame(parent), selectedAppIndex(-1)
45{ 42{
46 setBackgroundMode( PaletteBackground ); 43 QCopChannel* channel = new QCopChannel( "QPE/System", this );
47 44 connect( channel, SIGNAL(received(const QCString&, const QByteArray&)),
48 m_AppLnkSet = new AppLnkSet( QPEApplication::qpeDir() + "apps" ); 45 this, SLOT(received(const QCString&, const QByteArray&)) );
49
50#ifdef QWS
51 46
52 connect(qwsServer, SIGNAL(newChannel(const QString&)), this, SLOT(newQcopChannel(const QString&))); 47 spacing = AppLnk::smallIconSize()+3;
53 connect(qwsServer, SIGNAL(removedChannel(const QString&)), this, SLOT(removedQcopChannel(const QString&)));
54#endif
55
56 QCopChannel* channel = new QCopChannel( "QPE/System", this );
57 connect( channel, SIGNAL(received(const QCString&, const QByteArray&)),
58 this, SLOT(received(const QCString&, const QByteArray&)) );
59
60 spacing = AppLnk::smallIconSize() + 3;
61} 48}
62 49
63RunningAppBar::~RunningAppBar() 50RunningAppBar::~RunningAppBar()
64{}
65
66void RunningAppBar::newQcopChannel(const QString& channelName)
67{
68 QString prefix("QPE/Application/");
69 if (channelName.startsWith(prefix)) {
70 QString appName = channelName.mid(prefix.length());
71 // qDebug("App %s just connected!", appName.latin1());
72 const AppLnk* newGuy = m_AppLnkSet->findExec(appName);
73 if (newGuy && !newGuy->isPreloaded()) {
74 addTask(*newGuy);
75 }
76 }
77}
78
79void RunningAppBar::removedQcopChannel(const QString& channelName)
80{ 51{
81 QString prefix("QPE/Application/");
82 if (channelName.startsWith(prefix)) {
83 QString appName = channelName.mid(prefix.length());
84 qDebug("App %s just disconnected!", appName.latin1());
85 const AppLnk* newGuy = m_AppLnkSet->findExec(appName);
86 if (newGuy) {
87 removeTask(*newGuy);
88 }
89 }
90} 52}
91 53
92void RunningAppBar::received(const QCString& msg, const QByteArray& data) 54void RunningAppBar::received(const QCString& msg, const QByteArray& data) {
93{ 55 // Since fast apps appear and disappear without disconnecting from their
94 // Since fast apps appear and disappear without disconnecting from their 56 // channel we need to watch for the showing/hiding events and update according.
95 // channel we need to watch for the showing/hiding events and update according. 57 QDataStream stream( data, IO_ReadOnly );
96 QDataStream stream( data, IO_ReadOnly ); 58 if ( msg == "fastAppShowing(QString)") {
97 if ( msg == "fastAppShowing(QString)") { 59 QString appName;
98 QString appName; 60 stream >> appName;
99 stream >> appName; 61 // qDebug("fastAppShowing %s", appName.data() );
100 addTask(*m_AppLnkSet->findExec(appName)); 62 const AppLnk* f = ServerInterface::appLnks().findExec(appName);
101 } 63 if ( f ) addTask(*f);
102 else if ( msg == "fastAppHiding(QString)") { 64 } else if ( msg == "fastAppHiding(QString)") {
103 QString appName; 65 QString appName;
104 stream >> appName; 66 stream >> appName;
105 removeTask(*m_AppLnkSet->findExec(appName)); 67 const AppLnk* f = ServerInterface::appLnks().findExec(appName);
106 } 68 if ( f ) removeTask(*f);
69 }
107} 70}
108 71
109void RunningAppBar::addTask(const AppLnk& appLnk) 72void RunningAppBar::addTask(const AppLnk& appLnk) {
110{ 73 qDebug("Added %s to app list.", appLnk.name().latin1());
111 // qDebug("Added %s to app list.", appLnk.name().latin1()); 74 AppLnk* newApp = new AppLnk(appLnk);
112 AppLnk* newApp = new AppLnk(appLnk); 75 newApp->setExec(appLnk.exec());
113 newApp->setExec(appLnk.exec()); 76 appList.prepend(newApp);
114 m_AppList.prepend(newApp); 77 update();
115 update();
116} 78}
117 79
118void RunningAppBar::removeTask(const AppLnk& appLnk) 80void RunningAppBar::removeTask(const AppLnk& appLnk) {
119{ 81 unsigned int i = 0;
120 unsigned int i = 0; 82 for (; i < appList.count() ; i++) {
121 for (; i < m_AppList.count() ; i++) { 83 AppLnk* target = appList.at(i);
122 AppLnk* target = m_AppList.at(i); 84 if (target->exec() == appLnk.exec()) {
123 if (target->exec() == appLnk.exec()) { 85 qDebug("Removing %s from app list.", appLnk.name().latin1());
124 qDebug("Removing %s from app list.", appLnk.name().latin1()); 86 appList.remove();
125 m_AppList.remove(); 87 delete target;
126 88 }
127 delete target; 89 }
128 } 90 update();
129 }
130 update();
131} 91}
132 92
133void RunningAppBar::mousePressEvent(QMouseEvent *e) 93void RunningAppBar::mousePressEvent(QMouseEvent *e)
134{ 94{
135 // Find out if the user is clicking on an app icon... 95 // Find out if the user is clicking on an app icon...
136 // If so, snag the index so when we repaint we show it 96 // If so, snag the index so when we repaint we show it
137 // as highlighed. 97 // as highlighed.
138 m_SelectedAppIndex = 0; 98 selectedAppIndex = 0;
139 int x = 0; 99 int x=0;
140 QListIterator<AppLnk> it( m_AppList ); 100 QListIterator<AppLnk> it( appList );
141 for ( ; it.current(); ++it, ++m_SelectedAppIndex, x += spacing ) { 101 for ( ; it.current(); ++it,++selectedAppIndex,x+=spacing ) {
142 if ( x + spacing <= width() ) { 102 if ( x + spacing <= width() ) {
143 if ( e->x() >= x && e->x() < x + spacing ) { 103 if ( e->x() >= x && e->x() < x+spacing ) {
144 if ( m_SelectedAppIndex < (int)m_AppList.count() ) { 104 if ( selectedAppIndex < (int)appList.count() ) {
145 repaint(FALSE); 105 repaint(FALSE);
146 return ; 106 return;
147 }
148 }
149 }
150 else {
151 break;
152 }
153 } 107 }
154 m_SelectedAppIndex = -1; 108 }
155 repaint( FALSE ); 109 } else {
110 break;
111 }
112 }
113 selectedAppIndex = -1;
114 repaint( FALSE );
156} 115}
157 116
158void RunningAppBar::mouseReleaseEvent(QMouseEvent *e) 117void RunningAppBar::mouseReleaseEvent(QMouseEvent *e)
159{ 118{
160 if (e->button() == QMouseEvent::RightButton) { 119 if (e->button() == QMouseEvent::RightButton)
161 return ; 120 return;
162 } 121 if ( selectedAppIndex >= 0 ) {
163 if ( m_SelectedAppIndex >= 0 ) { 122 QString app = appList.at(selectedAppIndex)->exec();
164 QString channel = QString("QPE/Application/") + m_AppList.at(m_SelectedAppIndex)->exec(); 123 QCopEnvelope e("QPE/System", "raise(QString)");
165 if (QCopChannel::isRegistered(channel.latin1())) { 124 e << app;
166 // qDebug("%s is running!", m_AppList.at(m_SelectedAppIndex)->exec().latin1()); 125 selectedAppIndex = -1;
167 QCopEnvelope e(channel.latin1(), "raise()"); 126 update();
168 // This class will delete itself after hearing from the app or the timer expiring 127 }
169 (void)new AppMonitor(*m_AppList.at(m_SelectedAppIndex), *this);
170 }
171 else {
172 removeTask(*m_AppList.at(m_SelectedAppIndex));
173 }
174
175 m_SelectedAppIndex = -1;
176 update();
177 }
178} 128}
179 129
180void RunningAppBar::paintEvent( QPaintEvent * ) 130void RunningAppBar::paintEvent( QPaintEvent * )
181{ 131{
182 QPainter p( this ); 132 QPainter p( this );
183 AppLnk *curApp; 133 AppLnk *curApp;
184 int x = 0; 134 int x = 0;
185 int y = (height() - AppLnk::smallIconSize()) / 2; 135 int y = (height() - AppLnk::smallIconSize()) / 2;
186 int i = 0; 136 int i = 0;
187 137
188 //p.fillRect( 0, 0, width(), height(), colorGroup().background() ); 138 p.fillRect( 0, 0, width(), height(), colorGroup().background() );
189 139
190 QListIterator<AppLnk> it(m_AppList); 140 QListIterator<AppLnk> it(appList);
191 141
192 for (; it.current(); i++, ++it ) { 142 for (; it.current(); i++, ++it ) {
193 if ( x + spacing <= width() ) { 143 if ( x + spacing <= width() ) {
194 curApp = it.current(); 144 curApp = it.current();
195 if ( (int)i == m_SelectedAppIndex ) 145 qWarning("Drawing %s", curApp->name().latin1() );
196 p.fillRect( x, y, spacing, curApp->pixmap().height() + 1, colorGroup().highlight() ); 146 if ( (int)i == selectedAppIndex )
197 else 147 p.fillRect( x, y, spacing, curApp->pixmap().height()+1, colorGroup().highlight() );
198 // p.eraseRect( x, y, spacing, curApp->pixmap().height()+1 ); 148 else
199 p.drawPixmap( x, y, curApp->pixmap() ); 149 p.eraseRect( x, y, spacing, curApp->pixmap().height()+1 );
200 x += spacing; 150 p.drawPixmap( x, y, curApp->pixmap() );
201 } 151 x += spacing;
202 } 152 }
153 }
203} 154}
204 155
205QSize RunningAppBar::sizeHint() const 156QSize RunningAppBar::sizeHint() const
206{ 157{
207 return QSize( frameWidth(), AppLnk::smallIconSize() + frameWidth()*2 + 3 ); 158 return QSize( frameWidth(), AppLnk::smallIconSize()+frameWidth()*2+3 );
208} 159}
209 160
210const int AppMonitor::RAISE_TIMEOUT_MS = 500; 161void RunningAppBar::applicationLaunched(const QString &appName)
211
212AppMonitor::AppMonitor(const AppLnk& app, RunningAppBar& owner)
213 : QObject(0L), m_Owner(owner), m_App(app), m_AppKillerBox(0L)
214{ 162{
215 QCopChannel* channel = new QCopChannel( "QPE/System", this ); 163 qDebug("desktop:: app: %s launched with pid ", appName.data() );
216 connect( channel, SIGNAL(received(const QCString&, const QByteArray&)), 164 const AppLnk* newGuy = ServerInterface::appLnks().findExec(appName);
217 this, SLOT(received(const QCString&, const QByteArray&)) ); 165 if ( newGuy && !newGuy->isPreloaded() ) {
218 connect(&m_Timer, SIGNAL(timeout()), this, SLOT(timerExpired())); 166 addTask( *newGuy );
219 m_Timer.start(RAISE_TIMEOUT_MS, TRUE); 167 }
220} 168}
221 169
222AppMonitor::~AppMonitor() 170void RunningAppBar::applicationTerminated(const QString &app)
223{ 171{
224 if (m_AppKillerBox) { 172 const AppLnk* gone = ServerInterface::appLnks().findExec(app);
225 delete m_AppKillerBox; 173 if ( gone ) {
226 m_AppKillerBox = 0L; 174 removeTask(*gone);
227 } 175 }
228}
229
230void AppMonitor::received(const QCString& msg, const QByteArray& data)
231{
232 QDataStream stream( data, IO_ReadOnly );
233
234 if (msg == "appRaised(QString)") {
235 QString appName;
236 stream >> appName;
237 if (appName == m_App.exec()) {
238 // qDebug("Got a heartbeat from %s", appName.latin1());
239 m_Timer.stop();
240 // Check to make sure we're not waiting on user input...
241 if (m_AppKillerBox) {
242 // If we are, we kill the dialog box, and the code waiting on the result
243 // will clean us up (basically the user said "no").
244 delete m_AppKillerBox;
245 m_AppKillerBox = 0L;
246 }
247 else {
248 // Ok, we're not waiting on user input, so clean us up now.
249 // WE DELETE OURSELVES HERE! Don't do anything else!!
250 delete this;
251 }
252 }
253 }
254} 176}
255 177
256void AppMonitor::timerExpired()
257{
258 // We store this incase the application responds while we're
259 // waiting for user input so we know not to delete ourselves. This
260 // will be cleaned up in the destructor.
261 m_AppKillerBox = new QMessageBox(tr("Application Problem"),
262 tr("<p>%1 is not responding.</p>").arg(m_App.name()) +
263 tr("<p>Would you like to force the application to exit?</p>"),
264 QMessageBox::Warning, QMessageBox::Yes,
265 QMessageBox::No | QMessageBox::Default,
266 QMessageBox::NoButton);
267 if ( m_AppKillerBox-> exec ( ) == QMessageBox::Yes ) {
268 QDir proc ( "/proc/", "[0-9]*", QDir::Name | QDir::Reversed, QDir::Dirs );
269 QStringList allprocs = proc. entryList ( );
270
271 pid_t mypid = ::getpid ( );
272
273 for ( QStringList::Iterator it = allprocs. begin ( ); it != allprocs. end ( ); ++it ) {
274 if (( *it ). toInt ( ) <= mypid ) // only interested in children
275 continue;
276
277 QCString s = QString ( "/proc/" + *it + "/stat" ). local8Bit ( );
278
279 FILE *fp = ::fopen ( s. data ( ), "r" );
280 if ( fp ) {
281 pid_t pid, ppid;
282 char *execptr, *exec = 0;
283
284 if ( ::fscanf ( fp, "%d %as %*c %d ", &pid, &execptr, &ppid ) == 3 ) {
285 exec = execptr [0] ? execptr + 1 : execptr;
286 if ( exec [0] )
287 exec [::strlen ( exec ) - 1] = 0;
288
289 if (( ppid == ::getpid ( )) && ( m_App. exec ( ). local8Bit ( ) == exec )) {
290 bool success = false;
291 178
292 qDebug ( "trying to kill pid=%d, exec=%s, ppid=%d", pid, exec, ppid );
293
294
295 success |= ( ::kill ( pid, SIGTERM ) == 0 );
296 ::usleep ( 1000 * 500 );
297 success |= ( ::kill ( pid, SIGKILL ) == 0 );
298
299 if ( success )
300 m_Owner. removeTask ( m_App );
301
302 ::free ( execptr );
303 break;
304 }
305 ::free ( execptr );
306 }
307 ::fclose ( fp );
308 }
309 }
310 }
311 delete this;
312}
313 179