00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <tqobjectlist.h>
00027 #include <tqmetaobject.h>
00028 #include <tqvariant.h>
00029 #include <tqtimer.h>
00030 #include <tqintdict.h>
00031 #include <tqeventloop.h>
00032
00033
00034 #include "config.h"
00035
00036 #include <config.h>
00037 #include <dcopref.h>
00038
00039 #include <sys/time.h>
00040 #include <sys/types.h>
00041 #include <sys/stat.h>
00042 #include <sys/file.h>
00043 #include <sys/socket.h>
00044 #include <fcntl.h>
00045 #include <unistd.h>
00046
00047 #include <ctype.h>
00048 #include <unistd.h>
00049 #include <stdlib.h>
00050 #include <assert.h>
00051 #include <string.h>
00052
00053 #ifndef QT_CLEAN_NAMESPACE
00054 #define QT_CLEAN_NAMESPACE
00055 #endif
00056 #include <tqguardedptr.h>
00057 #include <tqtextstream.h>
00058 #include <tqfile.h>
00059 #include <tqdir.h>
00060 #include <tqapplication.h>
00061 #include <tqsocketnotifier.h>
00062 #include <tqregexp.h>
00063
00064 #include <tqucomextra_p.h>
00065
00066 #include <dcopglobal.h>
00067 #include <dcopclient.h>
00068 #include <dcopobject.h>
00069
00070 #if defined Q_WS_X11 && ! defined K_WS_QTONLY
00071 #include <X11/Xmd.h>
00072 #endif
00073 extern "C" {
00074 #include <KDE-ICE/ICElib.h>
00075 #include <KDE-ICE/ICEutil.h>
00076 #include <KDE-ICE/ICEmsg.h>
00077 #include <KDE-ICE/ICEproto.h>
00078 }
00079
00080
00081
00082 extern TQMap<TQCString, DCOPObject *> * kde_dcopObjMap;
00083
00084
00085
00086
00087 typedef TQAsciiDict<DCOPClient> client_map_t;
00088 static client_map_t *DCOPClient_CliMap = 0;
00089
00090 static
00091 client_map_t *cliMap()
00092 {
00093 if (!DCOPClient_CliMap)
00094 DCOPClient_CliMap = new client_map_t;
00095 return DCOPClient_CliMap;
00096 }
00097
00098 DCOPClient *DCOPClient::findLocalClient( const TQCString &_appId )
00099 {
00100 return cliMap()->find(_appId.data());
00101 }
00102
00103 static
00104 void registerLocalClient( const TQCString &_appId, DCOPClient *client )
00105 {
00106 cliMap()->replace(_appId.data(), client);
00107 }
00108
00109 static
00110 void unregisterLocalClient( const TQCString &_appId )
00111 {
00112 client_map_t *map = cliMap();
00113 map->remove(_appId.data());
00114 }
00116
00117 template class TQPtrList<DCOPObjectProxy>;
00118 template class TQPtrList<DCOPClientTransaction>;
00119 template class TQPtrList<_IceConn>;
00120
00121 struct DCOPClientMessage
00122 {
00123 int opcode;
00124 CARD32 key;
00125 TQByteArray data;
00126 };
00127
00128 class DCOPClient::ReplyStruct
00129 {
00130 public:
00131 enum ReplyStatus { Pending, Ok, Failed };
00132 ReplyStruct() {
00133 status = Pending;
00134 replyType = 0;
00135 replyData = 0;
00136 replyId = -1;
00137 transactionId = -1;
00138 replyObject = 0;
00139 }
00140 ReplyStatus status;
00141 TQCString* replyType;
00142 TQByteArray* replyData;
00143 int replyId;
00144 TQ_INT32 transactionId;
00145 TQCString calledApp;
00146 TQGuardedPtr<TQObject> replyObject;
00147 TQCString replySlot;
00148 };
00149
00150 class DCOPClientPrivate
00151 {
00152 public:
00153 DCOPClient *parent;
00154 TQCString appId;
00155 IceConn iceConn;
00156 int majorOpcode;
00157
00158 int majorVersion, minorVersion;
00159
00160 static const char* serverAddr;
00161 TQSocketNotifier *notifier;
00162 bool non_blocking_call_lock;
00163 bool registered;
00164 bool foreign_server;
00165 bool accept_calls;
00166 bool accept_calls_override;
00167 bool qt_bridge_enabled;
00168
00169 TQCString senderId;
00170 TQCString objId;
00171 TQCString function;
00172
00173 TQCString defaultObject;
00174 TQPtrList<DCOPClientTransaction> *transactionList;
00175 bool transaction;
00176 TQ_INT32 transactionId;
00177 int opcode;
00178
00179
00180
00181
00182
00183
00184 CARD32 key;
00185 CARD32 currentKey;
00186 CARD32 currentKeySaved;
00187
00188 TQTimer postMessageTimer;
00189 TQPtrList<DCOPClientMessage> messages;
00190
00191 TQPtrList<DCOPClient::ReplyStruct> pendingReplies;
00192 TQPtrList<DCOPClient::ReplyStruct> asyncReplyQueue;
00193
00194 struct LocalTransactionResult
00195 {
00196 TQCString replyType;
00197 TQByteArray replyData;
00198 };
00199
00200 TQIntDict<LocalTransactionResult> localTransActionList;
00201
00202 TQTimer eventLoopTimer;
00203 };
00204
00205 class DCOPClientTransaction
00206 {
00207 public:
00208 TQ_INT32 id;
00209 CARD32 key;
00210 TQCString senderId;
00211 };
00212
00213 TQCString DCOPClient::iceauthPath()
00214 {
00215 #ifdef Q_OS_WIN32
00216 char szPath[512];
00217 char * pszFilePart;
00218 int ret;
00219 ret = SearchPathA(NULL,"iceauth.exe",NULL,sizeof(szPath)/sizeof(szPath[0]),szPath,&pszFilePart);
00220 if(ret != 0)
00221 return TQCString(szPath);
00222 #else
00223 TQCString path = ::getenv("PATH");
00224 if (path.isEmpty())
00225 path = "/bin:/usr/bin";
00226 path += ":/usr/bin/X11:/usr/X11/bin:/usr/X11R6/bin";
00227 TQCString fPath = strtok(path.data(), ":\b");
00228 while (!fPath.isNull())
00229 {
00230 fPath += "/iceauth";
00231 if (access(fPath.data(), X_OK) == 0)
00232 {
00233 return fPath;
00234 }
00235
00236 fPath = strtok(NULL, ":\b");
00237 }
00238 #endif
00239 return 0;
00240 }
00241
00242 static TQCString dcopServerFile(const TQCString &hostname, bool old)
00243 {
00244 TQCString fName = ::getenv("DCOPAUTHORITY");
00245 if (!old && !fName.isEmpty())
00246 return fName;
00247
00248 fName = TQFile::encodeName( TQDir::homeDirPath() );
00249
00250 if (fName.isEmpty())
00251 {
00252 fprintf(stderr, "Aborting. $HOME is not set.\n");
00253 exit(1);
00254 }
00255 #ifdef Q_WS_X11
00256 TQCString disp = getenv("DISPLAY");
00257 #elif defined(Q_WS_QWS)
00258 TQCString disp = getenv("QWS_DISPLAY");
00259 #else
00260 TQCString disp;
00261 #endif
00262 if (disp.isEmpty())
00263 disp = "NODISPLAY";
00264
00265 int i;
00266 if((i = disp.findRev('.')) > disp.findRev(KPATH_SEPARATOR) && i >= 0)
00267 disp.truncate(i);
00268
00269 if (!old)
00270 {
00271 while( (i = disp.find(KPATH_SEPARATOR)) >= 0)
00272 disp[i] = '_';
00273 }
00274
00275 fName += "/.DCOPserver_";
00276 if (hostname.isEmpty())
00277 {
00278 char hostName[256];
00279 hostName[0] = '\0';
00280 if (getenv("XAUTHLOCALHOSTNAME"))
00281 fName += getenv("XAUTHLOCALHOSTNAME");
00282 else if (gethostname(hostName, sizeof(hostName)))
00283 {
00284 fName += "localhost";
00285 }
00286 else
00287 {
00288 hostName[sizeof(hostName)-1] = '\0';
00289 fName += hostName;
00290 }
00291 }
00292 else
00293 {
00294 fName += hostname;
00295 }
00296 fName += "_"+disp;
00297 return fName;
00298 }
00299
00300
00301
00302 TQCString DCOPClient::dcopServerFile(const TQCString &hostname)
00303 {
00304 return ::dcopServerFile(hostname, false);
00305 }
00306
00307
00308
00309 TQCString DCOPClient::dcopServerFileOld(const TQCString &hostname)
00310 {
00311 return ::dcopServerFile(hostname, true);
00312 }
00313
00314
00315 const char* DCOPClientPrivate::serverAddr = 0;
00316
00317 static void DCOPProcessInternal( DCOPClientPrivate *d, int opcode, CARD32 key, const TQByteArray& dataReceived, bool canPost );
00318
00319 void DCOPClient::handleAsyncReply(ReplyStruct *replyStruct)
00320 {
00321 if (replyStruct->replyObject)
00322 {
00323 TQObject::connect(this, TQT_SIGNAL(callBack(int, const TQCString&, const TQByteArray &)),
00324 replyStruct->replyObject, replyStruct->replySlot);
00325 emit callBack(replyStruct->replyId, *(replyStruct->replyType), *(replyStruct->replyData));
00326 TQObject::disconnect(this, TQT_SIGNAL(callBack(int, const TQCString&, const TQByteArray &)),
00327 replyStruct->replyObject, replyStruct->replySlot);
00328 }
00329 delete replyStruct;
00330 }
00331
00335 static void DCOPProcessMessage(IceConn iceConn, IcePointer clientObject,
00336 int opcode, unsigned long length, Bool ,
00337 IceReplyWaitInfo *replyWait,
00338 Bool *replyWaitRet)
00339 {
00340 DCOPMsg *pMsg = 0;
00341 DCOPClientPrivate *d = static_cast<DCOPClientPrivate *>(clientObject);
00342 DCOPClient::ReplyStruct *replyStruct = replyWait ? static_cast<DCOPClient::ReplyStruct*>(replyWait->reply) : 0;
00343
00344 IceReadMessageHeader(iceConn, sizeof(DCOPMsg), DCOPMsg, pMsg);
00345 CARD32 key = pMsg->key;
00346 if ( d->key == 0 )
00347 d->key = key;
00348
00349 TQByteArray dataReceived( length );
00350 IceReadData(iceConn, length, dataReceived.data() );
00351
00352 d->opcode = opcode;
00353 switch (opcode ) {
00354
00355 case DCOPReplyFailed:
00356 if ( replyStruct ) {
00357 replyStruct->status = DCOPClient::ReplyStruct::Failed;
00358 replyStruct->transactionId = 0;
00359 *replyWaitRet = True;
00360 return;
00361 } else {
00362 tqWarning("Very strange! got a DCOPReplyFailed opcode, but we were not waiting for a reply!");
00363 return;
00364 }
00365 case DCOPReply:
00366 if ( replyStruct ) {
00367 TQByteArray* b = replyStruct->replyData;
00368 TQCString* t = replyStruct->replyType;
00369 replyStruct->status = DCOPClient::ReplyStruct::Ok;
00370 replyStruct->transactionId = 0;
00371
00372 TQCString calledApp, app;
00373 TQDataStream ds( dataReceived, IO_ReadOnly );
00374 ds >> calledApp >> app >> *t >> *b;
00375
00376 *replyWaitRet = True;
00377 return;
00378 } else {
00379 tqWarning("Very strange! got a DCOPReply opcode, but we were not waiting for a reply!");
00380 return;
00381 }
00382 case DCOPReplyWait:
00383 if ( replyStruct ) {
00384 TQCString calledApp, app;
00385 TQ_INT32 id;
00386 TQDataStream ds( dataReceived, IO_ReadOnly );
00387 ds >> calledApp >> app >> id;
00388 replyStruct->transactionId = id;
00389 replyStruct->calledApp = calledApp;
00390 d->pendingReplies.append(replyStruct);
00391 *replyWaitRet = True;
00392 return;
00393 } else {
00394 tqWarning("Very strange! got a DCOPReplyWait opcode, but we were not waiting for a reply!");
00395 return;
00396 }
00397 case DCOPReplyDelayed:
00398 {
00399 TQDataStream ds( dataReceived, IO_ReadOnly );
00400 TQCString calledApp, app;
00401 TQ_INT32 id;
00402
00403 ds >> calledApp >> app >> id;
00404 if (replyStruct && (id == replyStruct->transactionId) && (calledApp == replyStruct->calledApp))
00405 {
00406 *replyWaitRet = True;
00407 }
00408
00409 for(DCOPClient::ReplyStruct *rs = d->pendingReplies.first(); rs;
00410 rs = d->pendingReplies.next())
00411 {
00412 if ((rs->transactionId == id) && (rs->calledApp == calledApp))
00413 {
00414 d->pendingReplies.remove();
00415 TQByteArray* b = rs->replyData;
00416 TQCString* t = rs->replyType;
00417 ds >> *t >> *b;
00418
00419 rs->status = DCOPClient::ReplyStruct::Ok;
00420 rs->transactionId = 0;
00421 if (!rs->replySlot.isEmpty())
00422 {
00423 d->parent->handleAsyncReply(rs);
00424 }
00425 return;
00426 }
00427 }
00428 }
00429 tqWarning("Very strange! got a DCOPReplyDelayed opcode, but we were not waiting for a reply!");
00430 return;
00431 case DCOPCall:
00432 case DCOPFind:
00433 case DCOPSend:
00434 DCOPProcessInternal( d, opcode, key, dataReceived, true );
00435 }
00436 }
00437
00438 void DCOPClient::processPostedMessagesInternal()
00439 {
00440 if ( d->messages.isEmpty() )
00441 return;
00442 TQPtrListIterator<DCOPClientMessage> it (d->messages );
00443 DCOPClientMessage* msg ;
00444 while ( ( msg = it.current() ) ) {
00445 ++it;
00446 if ( d->currentKey && msg->key != d->currentKey )
00447 continue;
00448 d->messages.removeRef( msg );
00449 d->opcode = msg->opcode;
00450 DCOPProcessInternal( d, msg->opcode, msg->key, msg->data, false );
00451 delete msg;
00452 }
00453 if ( !d->messages.isEmpty() )
00454 d->postMessageTimer.start( 100, true );
00455 }
00456
00460 void DCOPProcessInternal( DCOPClientPrivate *d, int opcode, CARD32 key, const TQByteArray& dataReceived, bool canPost )
00461 {
00462 if (!d->accept_calls && (opcode == DCOPSend))
00463 return;
00464
00465 IceConn iceConn = d->iceConn;
00466 DCOPMsg *pMsg = 0;
00467 DCOPClient *c = d->parent;
00468 TQDataStream ds( dataReceived, IO_ReadOnly );
00469
00470 TQCString fromApp;
00471 ds >> fromApp;
00472 if (fromApp.isEmpty())
00473 return;
00474
00475 if (!d->accept_calls)
00476 {
00477 TQByteArray reply;
00478 TQDataStream replyStream( reply, IO_WriteOnly );
00479
00480 replyStream << d->appId << fromApp;
00481 IceGetHeader( iceConn, d->majorOpcode, DCOPReplyFailed,
00482 sizeof(DCOPMsg), DCOPMsg, pMsg );
00483 int datalen = reply.size();
00484 pMsg->key = key;
00485 pMsg->length += datalen;
00486 IceSendData( iceConn, datalen, reply.data());
00487 return;
00488 }
00489
00490 TQCString app, objId, fun;
00491 TQByteArray data;
00492 ds >> app >> objId >> fun >> data;
00493 d->senderId = fromApp;
00494 d->objId = objId;
00495 d->function = fun;
00496
00497
00498
00499 if ( canPost && d->currentKey && key != d->currentKey ) {
00500 DCOPClientMessage* msg = new DCOPClientMessage;
00501 msg->opcode = opcode;
00502 msg->key = key;
00503 msg->data = dataReceived;
00504 d->messages.append( msg );
00505 d->postMessageTimer.start( 0, true );
00506 return;
00507 }
00508
00509 d->objId = objId;
00510 d->function = fun;
00511
00512 TQCString replyType;
00513 TQByteArray replyData;
00514 bool b;
00515 CARD32 oldCurrentKey = d->currentKey;
00516 if ( opcode != DCOPSend )
00517 d->currentKey = key;
00518
00519 if ( opcode == DCOPFind )
00520 b = c->find(app, objId, fun, data, replyType, replyData );
00521 else
00522 b = c->receive( app, objId, fun, data, replyType, replyData );
00523
00524
00525 if ( opcode == DCOPSend )
00526 return;
00527
00528 if ((d->currentKey == key) || (oldCurrentKey != 2))
00529 d->currentKey = oldCurrentKey;
00530
00531 TQByteArray reply;
00532 TQDataStream replyStream( reply, IO_WriteOnly );
00533
00534 TQ_INT32 id = c->transactionId();
00535 if (id) {
00536
00537 replyStream << d->appId << fromApp << id;
00538
00539 IceGetHeader( iceConn, d->majorOpcode, DCOPReplyWait,
00540 sizeof(DCOPMsg), DCOPMsg, pMsg );
00541 pMsg->key = key;
00542 pMsg->length += reply.size();
00543 IceSendData( iceConn, reply.size(), const_cast<char *>(reply.data()));
00544 return;
00545 }
00546
00547 if ( !b ) {
00548
00549
00550 replyStream << d->appId << fromApp;
00551 IceGetHeader( iceConn, d->majorOpcode, DCOPReplyFailed,
00552 sizeof(DCOPMsg), DCOPMsg, pMsg );
00553 int datalen = reply.size();
00554 pMsg->key = key;
00555 pMsg->length += datalen;
00556 IceSendData( iceConn, datalen, const_cast<char *>(reply.data()));
00557 return;
00558 }
00559
00560
00561 replyStream << d->appId << fromApp << replyType << replyData.size();
00562
00563
00564
00565 IceGetHeader( iceConn, d->majorOpcode, DCOPReply,
00566 sizeof(DCOPMsg), DCOPMsg, pMsg );
00567 int datalen = reply.size() + replyData.size();
00568 pMsg->key = key;
00569 pMsg->length += datalen;
00570
00571
00572 IceSendData( iceConn, reply.size(), const_cast<char *>(reply.data()));
00573 IceSendData( iceConn, replyData.size(), const_cast<char *>(replyData.data()));
00574 }
00575
00576
00577
00578 static IcePoVersionRec DCOPClientVersions[] = {
00579 { DCOPVersionMajor, DCOPVersionMinor, DCOPProcessMessage }
00580 };
00581
00582
00583 static DCOPClient* dcop_main_client = 0;
00584
00585 DCOPClient* DCOPClient::mainClient()
00586 {
00587 return dcop_main_client;
00588 }
00589
00590 void DCOPClient::setMainClient( DCOPClient* client )
00591 {
00592 dcop_main_client = client;
00593 }
00594
00595
00596 DCOPClient::DCOPClient()
00597 {
00598 d = new DCOPClientPrivate;
00599 d->parent = this;
00600 d->iceConn = 0L;
00601 d->key = 0;
00602 d->currentKey = 0;
00603 d->majorOpcode = 0;
00604 d->appId = 0;
00605 d->notifier = 0L;
00606 d->non_blocking_call_lock = false;
00607 d->registered = false;
00608 d->foreign_server = true;
00609 d->accept_calls = true;
00610 d->accept_calls_override = false;
00611 d->qt_bridge_enabled = true;
00612 d->transactionList = 0L;
00613 d->transactionId = 0;
00614 TQObject::connect( &d->postMessageTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( processPostedMessagesInternal() ) );
00615 TQObject::connect( &d->eventLoopTimer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( eventLoopTimeout() ) );
00616
00617 if ( !mainClient() )
00618 setMainClient( this );
00619 }
00620
00621 DCOPClient::~DCOPClient()
00622 {
00623 #ifdef DCOPCLIENT_DEBUG
00624 tqWarning("d->messages.count() = %d", d->messages.count());
00625 TQPtrListIterator<DCOPClientMessage> it (d->messages );
00626 DCOPClientMessage* msg ;
00627 while ( ( msg = it.current() ) ) {
00628 ++it;
00629 d->messages.removeRef( msg );
00630 tqWarning("DROPPING UNHANDLED DCOP MESSAGE:");
00631 tqWarning(" opcode = %d key = %d", msg->opcode, msg->key);
00632 TQDataStream ds( msg->data, IO_ReadOnly );
00633
00634 TQCString fromApp, app, objId, fun;
00635 ds >> fromApp >> app >> objId >> fun;
00636 tqWarning(" from = %s", fromApp.data());
00637 tqWarning(" to = %s / %s / %s", app.data(), objId.data(), fun.data());
00638 delete msg;
00639 }
00640 #endif
00641 if (d->iceConn)
00642 if (IceConnectionStatus(d->iceConn) == IceConnectAccepted)
00643 detach();
00644
00645 if (d->registered)
00646 unregisterLocalClient( d->appId );
00647
00648 delete d->notifier;
00649 delete d->transactionList;
00650 d->messages.setAutoDelete(true);
00651 delete d;
00652
00653 if ( mainClient() == this )
00654 setMainClient( 0 );
00655 }
00656
00657 void DCOPClient::setServerAddress(const TQCString &addr)
00658 {
00659 TQCString env = "DCOPSERVER=" + addr;
00660 putenv(strdup(env.data()));
00661 delete [] DCOPClientPrivate::serverAddr;
00662 DCOPClientPrivate::serverAddr = tqstrdup( addr.data() );
00663 }
00664
00665 bool DCOPClient::attach()
00666 {
00667 if (!attachInternal( true ))
00668 if (!attachInternal( true ))
00669 return false;
00670 return true;
00671 }
00672
00673 void DCOPClient::bindToApp()
00674 {
00675
00676
00677 if (tqApp) {
00678 if ( d->notifier )
00679 delete d->notifier;
00680 d->notifier = new TQSocketNotifier(socket(),
00681 TQSocketNotifier::Read, 0, 0);
00682 TQObject::connect(d->notifier, TQT_SIGNAL(activated(int)),
00683 TQT_SLOT(processSocketData(int)));
00684 }
00685 }
00686
00687 void DCOPClient::suspend()
00688 {
00689 #ifdef Q_WS_WIN //TODO: remove (win32 ports sometimes do not create notifiers)
00690 if (!d->notifier)
00691 return;
00692 #endif
00693 assert(d->notifier);
00694 d->notifier->setEnabled(false);
00695 }
00696
00697 void DCOPClient::resume()
00698 {
00699 #ifdef Q_WS_WIN //TODO: remove
00700 if (!d->notifier)
00701 return;
00702 #endif
00703 assert(d->notifier);
00704 d->notifier->setEnabled(true);
00705 }
00706
00707 bool DCOPClient::isSuspended() const
00708 {
00709 #if defined(Q_WS_WIN) || defined(Q_WS_MAC) //TODO: REMOVE
00710 if (!d->notifier)
00711 return false;
00712 #endif
00713 return !d->notifier->isEnabled();
00714 }
00715
00716 #ifdef SO_PEERCRED
00717
00718 static bool peerIsUs(int sockfd)
00719 {
00720 #if defined(__OpenBSD__)
00721 struct sockpeercred cred;
00722 #else
00723 struct ucred cred;
00724 #endif
00725 socklen_t siz = sizeof(cred);
00726 if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cred, &siz) != 0)
00727 return false;
00728 return (cred.uid == getuid());
00729 }
00730 #else
00731
00732 static bool isServerSocketOwnedByUser(const char*server)
00733 {
00734 #ifdef Q_OS_WIN
00735 if (strncmp(server, "tcp/", 4) != 0)
00736 return false;
00737 else
00738 return true;
00739 #else
00740 if (strncmp(server, "local/", 6) != 0)
00741 return false;
00742 const char *path = strchr(server, KPATH_SEPARATOR);
00743 if (!path)
00744 return false;
00745 path++;
00746
00747 struct stat stat_buf;
00748 if (stat(path, &stat_buf) != 0)
00749 return false;
00750
00751 return (stat_buf.st_uid == getuid());
00752 #endif
00753 }
00754 #endif
00755
00756
00757 bool DCOPClient::attachInternal( bool registerAsAnonymous )
00758 {
00759 char errBuf[1024];
00760
00761 if ( isAttached() )
00762 detach();
00763
00764 if ((d->majorOpcode = IceRegisterForProtocolSetup(const_cast<char *>("DCOP"),
00765 const_cast<char *>(DCOPVendorString),
00766 const_cast<char *>(DCOPReleaseString),
00767 1, DCOPClientVersions,
00768 DCOPAuthCount,
00769 const_cast<char **>(DCOPAuthNames),
00770 DCOPClientAuthProcs, 0L)) < 0) {
00771 emit attachFailed(TQString::fromLatin1( "Communications could not be established." ));
00772 return false;
00773 }
00774
00775 bool bClearServerAddr = false;
00776
00777 if (!d->serverAddr) {
00778
00779
00780 TQCString dcopSrv;
00781 dcopSrv = ::getenv("DCOPSERVER");
00782 if (dcopSrv.isEmpty()) {
00783 TQCString fName = dcopServerFile();
00784 TQFile f(TQFile::decodeName(fName));
00785 if (!f.open(IO_ReadOnly)) {
00786 emit attachFailed(TQString::fromLatin1( "Could not read network connection list.\n" )+TQFile::decodeName(fName));
00787 return false;
00788 }
00789 int size = TQMIN( (qint64)1024, f.size() );
00790 TQCString contents( size+1 );
00791 if ( f.readBlock( contents.data(), size ) != size )
00792 {
00793 tqDebug("Error reading from %s, didn't read the expected %d bytes", fName.data(), size);
00794
00795 }
00796 contents[size] = '\0';
00797 int pos = contents.find('\n');
00798 if ( pos == -1 )
00799 {
00800 tqDebug("Only one line in dcopserver file !: %s", contents.data());
00801 dcopSrv = contents;
00802 }
00803 else
00804 {
00805 if(contents[pos - 1] == '\r')
00806 pos--;
00807 dcopSrv = contents.left( pos );
00808
00809
00810
00811 }
00812 }
00813 d->serverAddr = tqstrdup( const_cast<char *>(dcopSrv.data()) );
00814 bClearServerAddr = true;
00815 }
00816
00817 if ((d->iceConn = IceOpenConnection(const_cast<char*>(d->serverAddr),
00818 static_cast<IcePointer>(this), False, d->majorOpcode,
00819 sizeof(errBuf), errBuf)) == 0L) {
00820 tqDebug("DCOPClient::attachInternal. Attach failed %s", errBuf);
00821 d->iceConn = 0;
00822 if (bClearServerAddr) {
00823 delete [] d->serverAddr;
00824 d->serverAddr = 0;
00825 }
00826 emit attachFailed(TQString::fromLatin1( errBuf ));
00827 return false;
00828 }
00829 fcntl(socket(), F_SETFL, FD_CLOEXEC);
00830
00831 IceSetShutdownNegotiation(d->iceConn, False);
00832
00833 int setupstat;
00834 char* vendor = 0;
00835 char* release = 0;
00836 setupstat = IceProtocolSetup(d->iceConn, d->majorOpcode,
00837 static_cast<IcePointer>(d),
00838 False,
00839 &(d->majorVersion), &(d->minorVersion),
00840 &(vendor), &(release), 1024, errBuf);
00841 if (vendor) free(vendor);
00842 if (release) free(release);
00843
00844 if (setupstat == IceProtocolSetupFailure ||
00845 setupstat == IceProtocolSetupIOError) {
00846 IceCloseConnection(d->iceConn);
00847 d->iceConn = 0;
00848 if (bClearServerAddr) {
00849 delete [] d->serverAddr;
00850 d->serverAddr = 0;
00851 }
00852 emit attachFailed(TQString::fromLatin1( errBuf ));
00853 return false;
00854 } else if (setupstat == IceProtocolAlreadyActive) {
00855 if (bClearServerAddr) {
00856 delete [] d->serverAddr;
00857 d->serverAddr = 0;
00858 }
00859
00860 emit attachFailed(TQString::fromLatin1( "internal error in IceOpenConnection" ));
00861 return false;
00862 }
00863
00864
00865 if (IceConnectionStatus(d->iceConn) != IceConnectAccepted) {
00866 if (bClearServerAddr) {
00867 delete [] d->serverAddr;
00868 d->serverAddr = 0;
00869 }
00870 emit attachFailed(TQString::fromLatin1( "DCOP server did not accept the connection." ));
00871 return false;
00872 }
00873
00874 #ifdef SO_PEERCRED
00875 d->foreign_server = !peerIsUs(socket());
00876 #else
00877 d->foreign_server = !isServerSocketOwnedByUser(d->serverAddr);
00878 #endif
00879 if (!d->accept_calls_override)
00880 d->accept_calls = !d->foreign_server;
00881
00882 bindToApp();
00883
00884 if ( registerAsAnonymous )
00885 registerAs( "anonymous", true );
00886
00887 return true;
00888 }
00889
00890
00891 bool DCOPClient::detach()
00892 {
00893 int status;
00894
00895 if (d->iceConn) {
00896 IceProtocolShutdown(d->iceConn, d->majorOpcode);
00897 status = IceCloseConnection(d->iceConn);
00898 if (status != IceClosedNow)
00899 return false;
00900 else
00901 d->iceConn = 0L;
00902 }
00903
00904 if (d->registered)
00905 unregisterLocalClient(d->appId);
00906
00907 delete d->notifier;
00908 d->notifier = 0L;
00909 d->registered = false;
00910 d->foreign_server = true;
00911 return true;
00912 }
00913
00914 bool DCOPClient::isAttached() const
00915 {
00916 if (!d->iceConn)
00917 return false;
00918
00919 return (IceConnectionStatus(d->iceConn) == IceConnectAccepted);
00920 }
00921
00922 bool DCOPClient::isAttachedToForeignServer() const
00923 {
00924 return isAttached() && d->foreign_server;
00925 }
00926
00927 bool DCOPClient::acceptCalls() const
00928 {
00929 return isAttached() && d->accept_calls;
00930 }
00931
00932 void DCOPClient::setAcceptCalls(bool b)
00933 {
00934 d->accept_calls = b;
00935 d->accept_calls_override = true;
00936 }
00937
00938 bool DCOPClient::qtBridgeEnabled()
00939 {
00940 return d->qt_bridge_enabled;
00941 }
00942
00943 void DCOPClient::setQtBridgeEnabled(bool b)
00944 {
00945 d->qt_bridge_enabled = b;
00946 }
00947
00948 TQCString DCOPClient::registerAs( const TQCString &appId, bool addPID )
00949 {
00950 TQCString result;
00951
00952 TQCString _appId = appId;
00953
00954 if (addPID) {
00955 TQCString pid;
00956 pid.sprintf("-%d", getpid());
00957 _appId = _appId + pid;
00958 }
00959
00960 if( d->appId == _appId )
00961 return d->appId;
00962
00963 #if 0 // no need to detach, dcopserver can handle renaming
00964
00965 if ( isRegistered() ) {
00966 detach();
00967 }
00968 #endif
00969
00970 if ( !isAttached() ) {
00971 if (!attachInternal( false ))
00972 if (!attachInternal( false ))
00973 return result;
00974 }
00975
00976
00977 TQCString replyType;
00978 TQByteArray data, replyData;
00979 TQDataStream arg( data, IO_WriteOnly );
00980 arg << _appId;
00981 if ( call( "DCOPServer", "", "registerAs(TQCString)", data, replyType, replyData ) ) {
00982 TQDataStream reply( replyData, IO_ReadOnly );
00983 reply >> result;
00984 }
00985
00986 d->appId = result;
00987 d->registered = !result.isNull();
00988
00989 if (d->registered)
00990 registerLocalClient( d->appId, this );
00991
00992 return result;
00993 }
00994
00995 bool DCOPClient::isRegistered() const
00996 {
00997 return d->registered;
00998 }
00999
01000
01001 TQCString DCOPClient::appId() const
01002 {
01003 return d->appId;
01004 }
01005
01006
01007 int DCOPClient::socket() const
01008 {
01009 if (d->iceConn)
01010 return IceConnectionNumber(d->iceConn);
01011 return 0;
01012 }
01013
01014 static inline bool isIdentChar( char x )
01015 {
01016 return x == '_' || (x >= '0' && x <= '9') ||
01017 (x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z');
01018 }
01019
01020 TQCString DCOPClient::normalizeFunctionSignature( const TQCString& fun ) {
01021 if ( fun.isEmpty() )
01022 return fun.copy();
01023 TQCString result( fun.size() );
01024 char *from = const_cast<TQCString&>(fun).data();
01025 char *to = result.data();
01026 char *first = to;
01027 char last = 0;
01028 while ( true ) {
01029 while ( *from && isspace(*from) )
01030 from++;
01031 if ( last && isIdentChar( last ) && isIdentChar( *from ) )
01032 *to++ = 0x20;
01033 while ( *from && !isspace(*from) ) {
01034 last = *from++;
01035 *to++ = last;
01036 }
01037 if ( !*from )
01038 break;
01039 }
01040 if ( to > first && *(to-1) == 0x20 )
01041 to--;
01042 *to = '\0';
01043 result.resize( (int)((long)to - (long)result.data()) + 1 );
01044 return result;
01045 }
01046
01047
01048 TQCString DCOPClient::senderId() const
01049 {
01050 return d->senderId;
01051 }
01052
01053
01054 bool DCOPClient::send(const TQCString &remApp, const TQCString &remObjId,
01055 const TQCString &remFun, const TQByteArray &data)
01056 {
01057 if (remApp.isEmpty())
01058 return false;
01059 DCOPClient *localClient = findLocalClient( remApp );
01060
01061 if ( localClient ) {
01062 bool saveTransaction = d->transaction;
01063 TQ_INT32 saveTransactionId = d->transactionId;
01064 TQCString saveSenderId = d->senderId;
01065
01066 d->senderId = 0;
01067 TQCString replyType;
01068 TQByteArray replyData;
01069 (void) localClient->receive( remApp, remObjId, remFun, data, replyType, replyData );
01070
01071 d->transaction = saveTransaction;
01072 d->transactionId = saveTransactionId;
01073 d->senderId = saveSenderId;
01074
01075
01076
01077
01078 return true;
01079 }
01080
01081 if ( !isAttached() )
01082 return false;
01083
01084
01085 DCOPMsg *pMsg;
01086
01087 TQByteArray ba;
01088 TQDataStream ds(ba, IO_WriteOnly);
01089 ds << d->appId << remApp << remObjId << normalizeFunctionSignature(remFun) << data.size();
01090
01091 IceGetHeader(d->iceConn, d->majorOpcode, DCOPSend,
01092 sizeof(DCOPMsg), DCOPMsg, pMsg);
01093
01094 pMsg->key = 1;
01095 int datalen = ba.size() + data.size();
01096 pMsg->length += datalen;
01097
01098 IceSendData( d->iceConn, ba.size(), const_cast<char *>(ba.data()) );
01099 IceSendData( d->iceConn, data.size(), const_cast<char *>(data.data()) );
01100
01101
01102
01103 if (IceConnectionStatus(d->iceConn) == IceConnectAccepted)
01104 return true;
01105 return false;
01106 }
01107
01108 bool DCOPClient::send(const TQCString &remApp, const TQCString &remObjId,
01109 const TQCString &remFun, const TQString &data)
01110 {
01111 TQByteArray ba;
01112 TQDataStream ds(ba, IO_WriteOnly);
01113 ds << data;
01114 return send(remApp, remObjId, remFun, ba);
01115 }
01116
01117 bool DCOPClient::findObject(const TQCString &remApp, const TQCString &remObj,
01118 const TQCString &remFun, const TQByteArray &data,
01119 TQCString &foundApp, TQCString &foundObj,
01120 bool useEventLoop)
01121 {
01122 return findObject( remApp, remObj, remFun, data, foundApp, foundObj, useEventLoop, -1 );
01123 }
01124
01125 bool DCOPClient::findObject(const TQCString &remApp, const TQCString &remObj,
01126 const TQCString &remFun, const TQByteArray &data,
01127 TQCString &foundApp, TQCString &foundObj,
01128 bool useEventLoop, int timeout)
01129 {
01130 QCStringList appList;
01131 TQCString app = remApp;
01132 if (app.isEmpty())
01133 app = "*";
01134
01135 foundApp = 0;
01136 foundObj = 0;
01137
01138 if (app[app.length()-1] == '*')
01139 {
01140
01141
01142
01143 int len = app.length()-1;
01144 QCStringList apps=registeredApplications();
01145 for( QCStringList::ConstIterator it = apps.begin();
01146 it != apps.end();
01147 ++it)
01148 {
01149 if ( strncmp( (*it).data(), app.data(), len) == 0)
01150 appList.append(*it);
01151 }
01152 }
01153 else
01154 {
01155 appList.append(app);
01156 }
01157
01158
01159 for(int phase=1; phase <= 2; phase++)
01160 {
01161 for( QCStringList::ConstIterator it = appList.begin();
01162 it != appList.end();
01163 ++it)
01164 {
01165 TQCString remApp = *it;
01166 TQCString replyType;
01167 TQByteArray replyData;
01168 bool result = false;
01169 DCOPClient *localClient = findLocalClient( remApp );
01170
01171 if ( (phase == 1) && localClient ) {
01172
01173 bool saveTransaction = d->transaction;
01174 TQ_INT32 saveTransactionId = d->transactionId;
01175 TQCString saveSenderId = d->senderId;
01176
01177 d->senderId = 0;
01178 result = localClient->find( remApp, remObj, remFun, data, replyType, replyData );
01179
01180 TQ_INT32 id = localClient->transactionId();
01181 if (id) {
01182
01183 do {
01184 TQApplication::eventLoop()->processEvents( TQEventLoop::WaitForMore);
01185 } while( !localClient->isLocalTransactionFinished(id, replyType, replyData));
01186 result = true;
01187 }
01188 d->transaction = saveTransaction;
01189 d->transactionId = saveTransactionId;
01190 d->senderId = saveSenderId;
01191 }
01192 else if ((phase == 2) && !localClient)
01193 {
01194
01195 result = callInternal(remApp, remObj, remFun, data,
01196 replyType, replyData, useEventLoop, timeout, DCOPFind);
01197 }
01198
01199 if (result)
01200 {
01201 if (replyType == "DCOPRef")
01202 {
01203 DCOPRef ref;
01204 TQDataStream reply( replyData, IO_ReadOnly );
01205 reply >> ref;
01206
01207 if (ref.app() == remApp)
01208 {
01209
01210 foundApp = ref.app();
01211 foundObj = ref.object();
01212 return true;
01213 }
01214 }
01215 }
01216 }
01217 }
01218 return false;
01219 }
01220
01221 bool DCOPClient::process(const TQCString &, const TQByteArray &,
01222 TQCString&, TQByteArray &)
01223 {
01224 return false;
01225 }
01226
01227 bool DCOPClient::isApplicationRegistered( const TQCString& remApp)
01228 {
01229 TQCString replyType;
01230 TQByteArray data, replyData;
01231 TQDataStream arg( data, IO_WriteOnly );
01232 arg << remApp;
01233 int result = false;
01234 if ( call( "DCOPServer", "", "isApplicationRegistered(TQCString)", data, replyType, replyData ) ) {
01235 TQDataStream reply( replyData, IO_ReadOnly );
01236 reply >> result;
01237 }
01238 return result;
01239 }
01240
01241 QCStringList DCOPClient::registeredApplications()
01242 {
01243 TQCString replyType;
01244 TQByteArray data, replyData;
01245 QCStringList result;
01246 if ( call( "DCOPServer", "", "registeredApplications()", data, replyType, replyData ) ) {
01247 TQDataStream reply( replyData, IO_ReadOnly );
01248 reply >> result;
01249 }
01250 return result;
01251 }
01252
01253 QCStringList DCOPClient::remoteObjects( const TQCString& remApp, bool *ok )
01254 {
01255 TQCString replyType;
01256 TQByteArray data, replyData;
01257 QCStringList result;
01258 if ( ok )
01259 *ok = false;
01260 if ( call( remApp, "DCOPClient", "objects()", data, replyType, replyData ) ) {
01261 TQDataStream reply( replyData, IO_ReadOnly );
01262 reply >> result;
01263 if ( ok )
01264 *ok = true;
01265 }
01266 return result;
01267 }
01268
01269 QCStringList DCOPClient::remoteInterfaces( const TQCString& remApp, const TQCString& remObj, bool *ok )
01270 {
01271 TQCString replyType;
01272 TQByteArray data, replyData;
01273 QCStringList result;
01274 if ( ok )
01275 *ok = false;
01276 if ( call( remApp, remObj, "interfaces()", data, replyType, replyData ) && replyType == "QCStringList") {
01277 TQDataStream reply( replyData, IO_ReadOnly );
01278 reply >> result;
01279 if ( ok )
01280 *ok = true;
01281 }
01282 return result;
01283 }
01284
01285 QCStringList DCOPClient::remoteFunctions( const TQCString& remApp, const TQCString& remObj, bool *ok )
01286 {
01287 TQCString replyType;
01288 TQByteArray data, replyData;
01289 QCStringList result;
01290 if ( ok )
01291 *ok = false;
01292 if ( call( remApp, remObj, "functions()", data, replyType, replyData ) && replyType == "QCStringList") {
01293 TQDataStream reply( replyData, IO_ReadOnly );
01294 reply >> result;
01295 if ( ok )
01296 *ok = true;
01297 }
01298 return result;
01299 }
01300
01301 void DCOPClient::setNotifications(bool enabled)
01302 {
01303 TQByteArray data;
01304 TQDataStream ds(data, IO_WriteOnly);
01305 ds << static_cast<TQ_INT8>(enabled);
01306
01307 TQCString replyType;
01308 TQByteArray reply;
01309 if (!call("DCOPServer", "", "setNotifications( bool )", data, replyType, reply))
01310 tqWarning("I couldn't enable notifications at the dcopserver!");
01311 }
01312
01313 void DCOPClient::setDaemonMode( bool daemonMode )
01314 {
01315 TQByteArray data;
01316 TQDataStream ds(data, IO_WriteOnly);
01317 ds << static_cast<TQ_INT8>( daemonMode );
01318
01319 TQCString replyType;
01320 TQByteArray reply;
01321 if (!call("DCOPServer", "", "setDaemonMode(bool)", data, replyType, reply))
01322 tqWarning("I couldn't enable daemon mode at the dcopserver!");
01323 }
01324
01325
01326
01327
01328
01329
01330
01331
01332 static void fillQtObjects( QCStringList& l, TQObject* o, TQCString path )
01333 {
01334 if ( !path.isEmpty() )
01335 path += '/';
01336
01337 int unnamed = 0;
01338 const TQObjectList list = o ? o->childrenListObject() : TQObject::objectTreesListObject();
01339 if ( !list.isEmpty() ) {
01340 TQObjectListIt it( list );
01341 TQObject *obj;
01342 while ( (obj=it.current()) ) {
01343 ++it;
01344 TQCString n = obj->name();
01345 if ( n == "unnamed" || n.isEmpty() )
01346 {
01347 n.sprintf("%p", (void *) obj);
01348 n = TQString(TQString("unnamed%1(%2, %3)").arg(++unnamed).arg(obj->className()).arg(TQString(n))).latin1();
01349 }
01350 TQCString fn = path + n;
01351 l.append( fn );
01352 if ( !obj->childrenListObject().isEmpty() )
01353 fillQtObjects( l, obj, fn );
01354 }
01355 }
01356 }
01357
01358 namespace
01359 {
01360 struct O
01361 {
01362 O(): o(0) {}
01363 O ( const TQCString& str, TQObject* obj ):s(str), o(obj){}
01364 TQCString s;
01365 TQObject* o;
01366 };
01367 }
01368
01369 static void fillQtObjectsEx( TQValueList<O>& l, TQObject* o, TQCString path )
01370 {
01371 if ( !path.isEmpty() )
01372 path += '/';
01373
01374 int unnamed = 0;
01375 const TQObjectList list = o ? o->childrenListObject() : TQObject::objectTreesListObject();
01376 if ( !list.isEmpty() ) {
01377 TQObjectListIt it( list );
01378 TQObject *obj;
01379 while ( (obj=it.current()) ) {
01380 ++it;
01381 TQCString n = obj->name();
01382 if ( n == "unnamed" || n.isEmpty() )
01383 {
01384 n.sprintf("%p", (void *) obj);
01385 n = TQString(TQString("unnamed%1(%2, %3)").arg(++unnamed).arg(obj->className()).arg(TQString(n))).latin1();
01386 }
01387 TQCString fn = path + n;
01388 l.append( O( fn, obj ) );
01389 if ( !obj->childrenListObject().isEmpty() )
01390 fillQtObjectsEx( l, obj, fn );
01391 }
01392 }
01393 }
01394
01395
01396 static TQObject* findQtObject( TQCString id )
01397 {
01398 TQRegExp expr( id );
01399 TQValueList<O> l;
01400 fillQtObjectsEx( l, 0, "qt" );
01401
01402 TQObject* firstContains = 0L;
01403 for ( TQValueList<O>::ConstIterator it = l.begin(); it != l.end(); ++it ) {
01404 if ( (*it).s == id )
01405 return (*it).o;
01406 if ( !firstContains && (*it).s.contains( expr ) ) {
01407 firstContains = (*it).o;
01408 }
01409 }
01410 return firstContains;
01411 }
01412
01413 static QCStringList findQtObjects( TQCString id )
01414 {
01415 TQRegExp expr( id );
01416 TQValueList<O> l;
01417 fillQtObjectsEx( l, 0, "qt" );
01418 QCStringList result;
01419 for ( TQValueList<O>::ConstIterator it = l.begin(); it != l.end(); ++it ) {
01420 if ( (*it).s.contains( expr ) )
01421 result << (*it).s;
01422 }
01423 return result;
01424 }
01425
01426 static bool receiveQtObject( const TQCString &objId, const TQCString &fun, const TQByteArray &data,
01427 TQCString& replyType, TQByteArray &replyData)
01428 {
01429 if ( objId == "qt" ) {
01430 if ( fun == "interfaces()" ) {
01431 replyType = "QCStringList";
01432 TQDataStream reply( replyData, IO_WriteOnly );
01433 QCStringList l;
01434 l << "DCOPObject";
01435 l << "Qt";
01436 reply << l;
01437 return true;
01438 } else if ( fun == "functions()" ) {
01439 replyType = "QCStringList";
01440 TQDataStream reply( replyData, IO_WriteOnly );
01441 QCStringList l;
01442 l << "QCStringList functions()";
01443 l << "QCStringList interfaces()";
01444 l << "QCStringList objects()";
01445 l << "QCStringList find(TQCString)";
01446 reply << l;
01447 return true;
01448 } else if ( fun == "objects()" ) {
01449 replyType = "QCStringList";
01450 TQDataStream reply( replyData, IO_WriteOnly );
01451 QCStringList l;
01452 fillQtObjects( l, 0, "qt" );
01453 reply << l;
01454 return true;
01455 } else if ( fun == "find(TQCString)" ) {
01456 TQDataStream ds( data, IO_ReadOnly );
01457 TQCString id;
01458 ds >> id ;
01459 replyType = "QCStringList";
01460 TQDataStream reply( replyData, IO_WriteOnly );
01461 reply << findQtObjects( id ) ;
01462 return true;
01463 }
01464 } else if ( objId.left(3) == "qt/" ) {
01465 TQObject* o = findQtObject( objId );
01466 if ( !o )
01467 return false;
01468 if ( fun == "functions()" ) {
01469 replyType = "QCStringList";
01470 TQDataStream reply( replyData, IO_WriteOnly );
01471 QCStringList l;
01472 l << "QCStringList functions()";
01473 l << "QCStringList interfaces()";
01474 l << "QCStringList properties()";
01475 l << "bool setProperty(TQCString,TQVariant)";
01476 l << "TQVariant property(TQCString)";
01477 TQStrList lst = o->metaObject()->slotNames( true );
01478 int i = 0;
01479 for ( TQPtrListIterator<char> it( lst ); it.current(); ++it ) {
01480 if ( o->metaObject()->slot( i++, true )->tqt_mo_access != TQMetaData::Public )
01481 continue;
01482 TQCString slot = it.current();
01483 if ( slot.contains( "()" ) ) {
01484 slot.prepend("void ");
01485 l << slot;
01486 }
01487 }
01488 reply << l;
01489 return true;
01490 } else if ( fun == "interfaces()" ) {
01491 replyType = "QCStringList";
01492 TQDataStream reply( replyData, IO_WriteOnly );
01493 QCStringList l;
01494 TQMetaObject *meta = o->metaObject();
01495 while ( meta ) {
01496 l.prepend( meta->className() );
01497 meta = meta->superClass();
01498 }
01499 reply << l;
01500 return true;
01501 } else if ( fun == "properties()" ) {
01502 replyType = "QCStringList";
01503 TQDataStream reply( replyData, IO_WriteOnly );
01504 QCStringList l;
01505 TQStrList lst = o->metaObject()->propertyNames( true );
01506 for ( TQPtrListIterator<char> it( lst ); it.current(); ++it ) {
01507 TQMetaObject *mo = o->metaObject();
01508 const TQMetaProperty* p = mo->property( mo->findProperty( it.current(), true ), true );
01509 if ( !p )
01510 continue;
01511 TQCString prop = p->type();
01512 prop += ' ';
01513 prop += p->name();
01514 if ( !p->writable() )
01515 prop += " readonly";
01516 l << prop;
01517 }
01518 reply << l;
01519 return true;
01520 } else if ( fun == "property(TQCString)" ) {
01521 replyType = "TQVariant";
01522 TQDataStream ds( data, IO_ReadOnly );
01523 TQCString name;
01524 ds >> name ;
01525 TQVariant result = o->property( name );
01526 TQDataStream reply( replyData, IO_WriteOnly );
01527 reply << result;
01528 return true;
01529 } else if ( fun == "setProperty(TQCString,TQVariant)" ) {
01530 TQDataStream ds( data, IO_ReadOnly );
01531 TQCString name;
01532 TQVariant value;
01533 ds >> name >> value;
01534 replyType = "bool";
01535 TQDataStream reply( replyData, IO_WriteOnly );
01536 reply << (TQ_INT8) o->setProperty( name, value );
01537 return true;
01538 } else {
01539 int slot = o->metaObject()->findSlot( fun, true );
01540 if ( slot != -1 ) {
01541 replyType = "void";
01542 TQUObject uo[ 1 ];
01543 o->tqt_invoke( slot, uo );
01544 return true;
01545 }
01546 }
01547
01548
01549 }
01550 return false;
01551 }
01552
01553
01554
01555
01556
01557
01558
01559
01560 bool DCOPClient::receive(const TQCString &, const TQCString &objId,
01561 const TQCString &fun, const TQByteArray &data,
01562 TQCString& replyType, TQByteArray &replyData)
01563 {
01564 d->transaction = false;
01565 if ( objId == "DCOPClient" ) {
01566 if ( fun == "objects()" ) {
01567 replyType = "QCStringList";
01568 TQDataStream reply( replyData, IO_WriteOnly );
01569 QCStringList l;
01570 if (d->qt_bridge_enabled)
01571 {
01572 l << "qt";
01573 }
01574 if ( kde_dcopObjMap ) {
01575 TQMap<TQCString, DCOPObject *>::ConstIterator it( kde_dcopObjMap->begin());
01576 for (; it != kde_dcopObjMap->end(); ++it) {
01577 if ( !it.key().isEmpty() ) {
01578 if ( it.key() == d->defaultObject )
01579 l << "default";
01580 l << it.key();
01581 }
01582 }
01583 }
01584 reply << l;
01585 return true;
01586 }
01587 }
01588
01589 if ( objId.isEmpty() || objId == "DCOPClient" ) {
01590 if ( fun == "applicationRegistered(TQCString)" ) {
01591 TQDataStream ds( data, IO_ReadOnly );
01592 TQCString r;
01593 ds >> r;
01594 emit applicationRegistered( r );
01595 return true;
01596 } else if ( fun == "applicationRemoved(TQCString)" ) {
01597 TQDataStream ds( data, IO_ReadOnly );
01598 TQCString r;
01599 ds >> r;
01600 emit applicationRemoved( r );
01601 return true;
01602 }
01603
01604 if ( process( fun, data, replyType, replyData ) )
01605 return true;
01606
01607
01608 } else if (d->qt_bridge_enabled &&
01609 (objId == "qt" || objId.left(3) == "qt/") ) {
01610 return receiveQtObject( objId, fun, data, replyType, replyData );
01611 }
01612
01613 if ( objId.isEmpty() || objId == "default" ) {
01614 if ( !d->defaultObject.isEmpty() && DCOPObject::hasObject( d->defaultObject ) ) {
01615 DCOPObject *objPtr = DCOPObject::find( d->defaultObject );
01616 objPtr->setCallingDcopClient(this);
01617 if (objPtr->process(fun, data, replyType, replyData))
01618 return true;
01619 }
01620
01621
01622 }
01623
01624
01625 if (!objId.isEmpty() && ((objId.length()>0)?(objId[objId.length()-1] == '*'):0)) {
01626
01627
01628 TQPtrList<DCOPObject> matchList =
01629 DCOPObject::match(objId.left(objId.length()-1));
01630 for (DCOPObject *objPtr = matchList.first();
01631 objPtr != 0L; objPtr = matchList.next()) {
01632 objPtr->setCallingDcopClient(this);
01633 if (!objPtr->process(fun, data, replyType, replyData))
01634 return false;
01635 }
01636 return true;
01637 } else if (!DCOPObject::hasObject(objId)) {
01638 if ( DCOPObjectProxy::proxies ) {
01639 for ( TQPtrListIterator<DCOPObjectProxy> it( *DCOPObjectProxy::proxies ); it.current(); ++it ) {
01640
01641 if ( it.current()->process( objId, fun, data, replyType, replyData ) )
01642 return true;
01643 }
01644 }
01645 return false;
01646
01647 } else {
01648 DCOPObject *objPtr = DCOPObject::find(objId);
01649 objPtr->setCallingDcopClient(this);
01650 if (!objPtr->process(fun, data, replyType, replyData)) {
01651
01652 return false;
01653 }
01654 }
01655
01656 return true;
01657 }
01658
01659
01660
01661
01662 static bool findResultOk(TQCString &replyType, TQByteArray &replyData)
01663 {
01664 TQ_INT8 success;
01665 if (replyType != "bool") return false;
01666
01667 TQDataStream reply( replyData, IO_ReadOnly );
01668 reply >> success;
01669
01670 if (!success) return false;
01671 return true;
01672 }
01673
01674
01675
01676 static bool findSuccess(const TQCString &app, const TQCString objId, TQCString &replyType, TQByteArray &replyData)
01677 {
01678 DCOPRef ref(app, objId);
01679 replyType = "DCOPRef";
01680
01681 replyData = TQByteArray();
01682 TQDataStream final_reply( replyData, IO_WriteOnly );
01683 final_reply << ref;
01684 return true;
01685 }
01686
01687
01688 bool DCOPClient::find(const TQCString &app, const TQCString &objId,
01689 const TQCString &fun, const TQByteArray &data,
01690 TQCString& replyType, TQByteArray &replyData)
01691 {
01692 d->transaction = false;
01693 if ( !app.isEmpty() && app != d->appId && app[app.length()-1] != '*') {
01694 tqWarning("WEIRD! we somehow received a DCOP message w/a different appId");
01695 return false;
01696 }
01697
01698 if (objId.isEmpty() || objId[objId.length()-1] != '*')
01699 {
01700 if (fun.isEmpty())
01701 {
01702 if (objId.isEmpty() || DCOPObject::hasObject(objId))
01703 return findSuccess(app, objId, replyType, replyData);
01704 return false;
01705 }
01706
01707 if (receive(app, objId, fun, data, replyType, replyData))
01708 {
01709 if (findResultOk(replyType, replyData))
01710 return findSuccess(app, objId, replyType, replyData);
01711 }
01712 }
01713 else {
01714
01715
01716 TQPtrList<DCOPObject> matchList =
01717 DCOPObject::match(objId.left(objId.length()-1));
01718 for (DCOPObject *objPtr = matchList.first();
01719 objPtr != 0L; objPtr = matchList.next())
01720 {
01721 replyType = 0;
01722 replyData = TQByteArray();
01723 if (fun.isEmpty())
01724 return findSuccess(app, objPtr->objId(), replyType, replyData);
01725 objPtr->setCallingDcopClient(this);
01726 if (objPtr->process(fun, data, replyType, replyData))
01727 if (findResultOk(replyType, replyData))
01728 return findSuccess(app, objPtr->objId(), replyType, replyData);
01729 }
01730 }
01731 return false;
01732 }
01733
01734
01735 bool DCOPClient::call(const TQCString &remApp, const TQCString &remObjId,
01736 const TQCString &remFun, const TQByteArray &data,
01737 TQCString& replyType, TQByteArray &replyData,
01738 bool useEventLoop)
01739 {
01740 return call( remApp, remObjId, remFun, data, replyType, replyData, useEventLoop, -1, false );
01741 }
01742
01743 bool DCOPClient::call(const TQCString &remApp, const TQCString &remObjId,
01744 const TQCString &remFun, const TQByteArray &data,
01745 TQCString& replyType, TQByteArray &replyData,
01746 bool useEventLoop, int timeout)
01747 {
01748 return call( remApp, remObjId, remFun, data, replyType, replyData, useEventLoop, timeout, false );
01749 }
01750
01751 bool DCOPClient::call(const TQCString &remApp, const TQCString &remObjId,
01752 const TQCString &remFun, const TQByteArray &data,
01753 TQCString& replyType, TQByteArray &replyData,
01754 bool useEventLoop, int timeout, bool forceRemote)
01755 {
01756 if (remApp.isEmpty())
01757 return false;
01758 DCOPClient *localClient = findLocalClient( remApp );
01759
01760 if ( localClient && !forceRemote ) {
01761 bool saveTransaction = d->transaction;
01762 TQ_INT32 saveTransactionId = d->transactionId;
01763 TQCString saveSenderId = d->senderId;
01764
01765 d->senderId = 0;
01766 bool b = localClient->receive( remApp, remObjId, remFun, data, replyType, replyData );
01767
01768 TQ_INT32 id = localClient->transactionId();
01769 if (id) {
01770
01771 do {
01772 TQApplication::eventLoop()->processEvents(TQEventLoop::WaitForMore);
01773 } while( !localClient->isLocalTransactionFinished(id, replyType, replyData));
01774 b = true;
01775 }
01776 d->transaction = saveTransaction;
01777 d->transactionId = saveTransactionId;
01778 d->senderId = saveSenderId;
01779 return b;
01780 }
01781
01782 return callInternal(remApp, remObjId, remFun, data,
01783 replyType, replyData, useEventLoop, timeout, DCOPCall);
01784 }
01785
01786 void DCOPClient::asyncReplyReady()
01787 {
01788 while( d->asyncReplyQueue.count() )
01789 {
01790 ReplyStruct *replyStruct = d->asyncReplyQueue.take(0);
01791 handleAsyncReply(replyStruct);
01792 }
01793 }
01794
01795 int DCOPClient::callAsync(const TQCString &remApp, const TQCString &remObjId,
01796 const TQCString &remFun, const TQByteArray &data,
01797 TQObject *callBackObj, const char *callBackSlot)
01798 {
01799 TQCString replyType;
01800 TQByteArray replyData;
01801
01802 ReplyStruct *replyStruct = new ReplyStruct;
01803 replyStruct->replyType = new TQCString;
01804 replyStruct->replyData = new TQByteArray;
01805 replyStruct->replyObject = callBackObj;
01806 replyStruct->replySlot = callBackSlot;
01807 replyStruct->replyId = ++d->transactionId;
01808 if (d->transactionId < 0)
01809 d->transactionId = 0;
01810
01811 bool b = callInternal(remApp, remObjId, remFun, data,
01812 replyStruct, false, -1, DCOPCall);
01813 if (!b)
01814 {
01815 delete replyStruct->replyType;
01816 delete replyStruct->replyData;
01817 delete replyStruct;
01818 return 0;
01819 }
01820
01821 if (replyStruct->transactionId == 0)
01822 {
01823
01824 TQTimer::singleShot(0, this, TQT_SLOT(asyncReplyReady()));
01825 d->asyncReplyQueue.append(replyStruct);
01826 }
01827
01828 return replyStruct->replyId;
01829 }
01830
01831 bool DCOPClient::callInternal(const TQCString &remApp, const TQCString &remObjId,
01832 const TQCString &remFun, const TQByteArray &data,
01833 TQCString& replyType, TQByteArray &replyData,
01834 bool useEventLoop, int timeout, int minor_opcode)
01835 {
01836 ReplyStruct replyStruct;
01837 replyStruct.replyType = &replyType;
01838 replyStruct.replyData = &replyData;
01839 return callInternal(remApp, remObjId, remFun, data, &replyStruct, useEventLoop, timeout, minor_opcode);
01840 }
01841
01842 bool DCOPClient::callInternal(const TQCString &remApp, const TQCString &remObjId,
01843 const TQCString &remFun, const TQByteArray &data,
01844 ReplyStruct *replyStruct,
01845 bool useEventLoop, int timeout, int minor_opcode)
01846 {
01847 if ( !isAttached() )
01848 return false;
01849
01850 DCOPMsg *pMsg;
01851
01852 CARD32 oldCurrentKey = d->currentKey;
01853 if ( !d->currentKey )
01854 d->currentKey = d->key;
01855
01856 TQByteArray ba;
01857 TQDataStream ds(ba, IO_WriteOnly);
01858 ds << d->appId << remApp << remObjId << normalizeFunctionSignature(remFun) << data.size();
01859
01860 IceGetHeader(d->iceConn, d->majorOpcode, minor_opcode,
01861 sizeof(DCOPMsg), DCOPMsg, pMsg);
01862
01863 pMsg->key = d->currentKey;
01864 int datalen = ba.size() + data.size();
01865 pMsg->length += datalen;
01866
01867
01868
01869 IceSendData(d->iceConn, ba.size(), const_cast<char *>(ba.data()));
01870 IceSendData(d->iceConn, data.size(), const_cast<char *>(data.data()));
01871
01872 if (IceConnectionStatus(d->iceConn) != IceConnectAccepted)
01873 return false;
01874
01875 IceFlush (d->iceConn);
01876
01877 IceReplyWaitInfo waitInfo;
01878 waitInfo.sequence_of_request = IceLastSentSequenceNumber(d->iceConn);
01879 waitInfo.major_opcode_of_request = d->majorOpcode;
01880 waitInfo.minor_opcode_of_request = minor_opcode;
01881
01882 replyStruct->transactionId = -1;
01883 waitInfo.reply = static_cast<IcePointer>(replyStruct);
01884
01885 Bool readyRet = False;
01886 IceProcessMessagesStatus s;
01887
01888 timeval time_start;
01889 int time_left = -1;
01890 if( timeout >= 0 )
01891 {
01892 gettimeofday( &time_start, NULL );
01893 time_left = timeout;
01894 }
01895 for(;;) {
01896 bool checkMessages = true;
01897 if ( useEventLoop
01898 ? d->notifier != NULL
01899 : timeout >= 0 ) {
01900 const int guiTimeout = 100;
01901 checkMessages = false;
01902
01903 int msecs = useEventLoop
01904 ? guiTimeout
01905 : time_left;
01906 fd_set fds;
01907 struct timeval tv;
01908 FD_ZERO( &fds );
01909 FD_SET( socket(), &fds );
01910 tv.tv_sec = msecs / 1000;
01911 tv.tv_usec = (msecs % 1000) * 1000;
01912 if ( select( socket() + 1, &fds, 0, 0, &tv ) <= 0 ) {
01913 if( useEventLoop && (timeout < 0 || time_left > guiTimeout)) {
01914
01915
01916 bool old_lock = d->non_blocking_call_lock;
01917 if ( !old_lock ) {
01918 d->non_blocking_call_lock = true;
01919 emit blockUserInput( true );
01920 }
01921 if( timeout >= 0 )
01922 d->eventLoopTimer.start(time_left - guiTimeout, true);
01923 tqApp->enter_loop();
01924 d->eventLoopTimer.stop();
01925 if ( !old_lock ) {
01926 d->non_blocking_call_lock = false;
01927 emit blockUserInput( false );
01928 }
01929 }
01930 }
01931 else
01932 {
01933 checkMessages = true;
01934 }
01935 }
01936 if (!d->iceConn)
01937 return false;
01938
01939 if( replyStruct->transactionId != -1 )
01940 {
01941 if (replyStruct->transactionId == 0)
01942 break;
01943 if (!replyStruct->replySlot.isEmpty())
01944 break;
01945 }
01946
01947 if( checkMessages ) {
01948 s = IceProcessMessages(d->iceConn, &waitInfo,
01949 &readyRet);
01950 if (s == IceProcessMessagesIOError) {
01951 detach();
01952 d->currentKey = oldCurrentKey;
01953 return false;
01954 }
01955 }
01956
01957 if( replyStruct->transactionId != -1 )
01958 {
01959 if (replyStruct->transactionId == 0)
01960 break;
01961 if (!replyStruct->replySlot.isEmpty())
01962 break;
01963 }
01964
01965 if( timeout < 0 )
01966 continue;
01967 timeval time_now;
01968 gettimeofday( &time_now, NULL );
01969 time_left = timeout -
01970 ((time_now.tv_sec - time_start.tv_sec) * 1000) -
01971 ((time_now.tv_usec - time_start.tv_usec) / 1000);
01972 if( time_left <= 0)
01973 {
01974 if (useEventLoop)
01975 {
01976
01977 time_left = 0;
01978 useEventLoop = false;
01979 continue;
01980 }
01981 *(replyStruct->replyType) = TQCString();
01982 *(replyStruct->replyData) = TQByteArray();
01983 replyStruct->status = ReplyStruct::Failed;
01984 break;
01985 }
01986 }
01987
01988
01989 if ( d->non_blocking_call_lock ) {
01990 tqApp->exit_loop();
01991 }
01992
01993 d->currentKey = oldCurrentKey;
01994 return replyStruct->status != ReplyStruct::Failed;
01995 }
01996
01997 void DCOPClient::eventLoopTimeout()
01998 {
01999 tqApp->exit_loop();
02000 }
02001
02002 void DCOPClient::processSocketData(int fd)
02003 {
02004
02005 fd_set fds;
02006 timeval timeout;
02007 timeout.tv_sec = 0;
02008 timeout.tv_usec = 0;
02009 FD_ZERO(&fds);
02010 FD_SET(fd, &fds);
02011 int result = select(fd+1, &fds, 0, 0, &timeout);
02012 if (result == 0)
02013 return;
02014
02015 if ( d->non_blocking_call_lock ) {
02016 if( tqApp )
02017 tqApp->exit_loop();
02018 return;
02019 }
02020
02021 if (!d->iceConn) {
02022 if( d->notifier )
02023 d->notifier->deleteLater();
02024 d->notifier = 0;
02025 tqWarning("received an error processing data from the DCOP server!");
02026 return;
02027 }
02028
02029 IceProcessMessagesStatus s = IceProcessMessages(d->iceConn, 0, 0);
02030
02031 if (s == IceProcessMessagesIOError) {
02032 detach();
02033 tqWarning("received an error processing data from the DCOP server!");
02034 return;
02035 }
02036 }
02037
02038 void DCOPClient::setDefaultObject( const TQCString& objId )
02039 {
02040 d->defaultObject = objId;
02041 }
02042
02043
02044 TQCString DCOPClient::defaultObject() const
02045 {
02046 return d->defaultObject;
02047 }
02048
02049 bool
02050 DCOPClient::isLocalTransactionFinished(TQ_INT32 id, TQCString &replyType, TQByteArray &replyData)
02051 {
02052 DCOPClientPrivate::LocalTransactionResult *result = d->localTransActionList.take(id);
02053 if (!result)
02054 return false;
02055
02056 replyType = result->replyType;
02057 replyData = result->replyData;
02058 delete result;
02059
02060 return true;
02061 }
02062
02063 DCOPClientTransaction *
02064 DCOPClient::beginTransaction()
02065 {
02066 if (d->opcode == DCOPSend)
02067 return 0;
02068 if (!d->transactionList)
02069 d->transactionList = new TQPtrList<DCOPClientTransaction>;
02070
02071 d->transaction = true;
02072 DCOPClientTransaction *trans = new DCOPClientTransaction();
02073 trans->senderId = d->senderId;
02074 trans->id = ++d->transactionId;
02075 if (d->transactionId < 0)
02076 d->transactionId = 0;
02077 trans->key = d->currentKey;
02078
02079 d->transactionList->append( trans );
02080
02081 return trans;
02082 }
02083
02084 TQ_INT32
02085 DCOPClient::transactionId() const
02086 {
02087 if (d->transaction)
02088 return d->transactionId;
02089 else
02090 return 0;
02091 }
02092
02093 void
02094 DCOPClient::endTransaction( DCOPClientTransaction *trans, TQCString& replyType,
02095 TQByteArray &replyData)
02096 {
02097 if ( !trans )
02098 return;
02099
02100 if ( !isAttached() )
02101 return;
02102
02103 if ( !d->transactionList) {
02104 tqWarning("Transaction unknown: No pending transactions!");
02105 return;
02106 }
02107
02108 if ( !d->transactionList->removeRef( trans ) ) {
02109 tqWarning("Transaction unknown: Not on list of pending transactions!");
02110 return;
02111 }
02112
02113 if (trans->senderId.isEmpty())
02114 {
02115
02116 DCOPClientPrivate::LocalTransactionResult *result = new DCOPClientPrivate::LocalTransactionResult();
02117 result->replyType = replyType;
02118 result->replyData = replyData;
02119
02120 d->localTransActionList.insert(trans->id, result);
02121
02122 delete trans;
02123
02124 return;
02125 }
02126
02127 DCOPMsg *pMsg;
02128
02129 TQByteArray ba;
02130 TQDataStream ds(ba, IO_WriteOnly);
02131 ds << d->appId << trans->senderId << trans->id << replyType << replyData;
02132
02133 IceGetHeader(d->iceConn, d->majorOpcode, DCOPReplyDelayed,
02134 sizeof(DCOPMsg), DCOPMsg, pMsg);
02135 pMsg->key = trans->key;
02136 pMsg->length += ba.size();
02137
02138 IceSendData( d->iceConn, ba.size(), const_cast<char *>(ba.data()) );
02139
02140 delete trans;
02141 }
02142
02143 void
02144 DCOPClient::emitDCOPSignal( const TQCString &object, const TQCString &signal, const TQByteArray &data)
02145 {
02146
02147 send("DCOPServer", "emit", object+"#"+normalizeFunctionSignature(signal), data);
02148 }
02149
02150 void
02151 DCOPClient::emitDCOPSignal( const TQCString &signal, const TQByteArray &data)
02152 {
02153 emitDCOPSignal(0, signal, data);
02154 }
02155
02156 bool
02157 DCOPClient::connectDCOPSignal( const TQCString &sender, const TQCString &senderObj,
02158 const TQCString &signal,
02159 const TQCString &receiverObj, const TQCString &slot, bool Volatile)
02160 {
02161 TQCString replyType;
02162 TQByteArray data, replyData;
02163 TQ_INT8 iVolatile = Volatile ? 1 : 0;
02164
02165 TQDataStream args(data, IO_WriteOnly );
02166 args << sender << senderObj << normalizeFunctionSignature(signal) << receiverObj << normalizeFunctionSignature(slot) << iVolatile;
02167
02168 if (!call("DCOPServer", 0,
02169 "connectSignal(TQCString,TQCString,TQCString,TQCString,TQCString,bool)",
02170 data, replyType, replyData))
02171 {
02172 return false;
02173 }
02174
02175 if (replyType != "bool")
02176 return false;
02177
02178 TQDataStream reply(replyData, IO_ReadOnly );
02179 TQ_INT8 result;
02180 reply >> result;
02181 return (result != 0);
02182 }
02183
02184 bool
02185 DCOPClient::connectDCOPSignal( const TQCString &sender, const TQCString &signal,
02186 const TQCString &receiverObj, const TQCString &slot, bool Volatile)
02187 {
02188 return connectDCOPSignal( sender, 0, signal, receiverObj, slot, Volatile);
02189 }
02190
02191 bool
02192 DCOPClient::disconnectDCOPSignal( const TQCString &sender, const TQCString &senderObj,
02193 const TQCString &signal,
02194 const TQCString &receiverObj, const TQCString &slot)
02195 {
02196 TQCString replyType;
02197 TQByteArray data, replyData;
02198
02199 TQDataStream args(data, IO_WriteOnly );
02200 args << sender << senderObj << normalizeFunctionSignature(signal) << receiverObj << normalizeFunctionSignature(slot);
02201
02202 if (!call("DCOPServer", 0,
02203 "disconnectSignal(TQCString,TQCString,TQCString,TQCString,TQCString)",
02204 data, replyType, replyData))
02205 {
02206 return false;
02207 }
02208
02209 if (replyType != "bool")
02210 return false;
02211
02212 TQDataStream reply(replyData, IO_ReadOnly );
02213 TQ_INT8 result;
02214 reply >> result;
02215 return (result != 0);
02216 }
02217
02218 bool
02219 DCOPClient::disconnectDCOPSignal( const TQCString &sender, const TQCString &signal,
02220 const TQCString &receiverObj, const TQCString &slot)
02221 {
02222 return disconnectDCOPSignal( sender, 0, signal, receiverObj, slot);
02223 }
02224
02225 void
02226 DCOPClient::setPriorityCall(bool b)
02227 {
02228 if (b)
02229 {
02230 if (d->currentKey == 2)
02231 return;
02232 d->currentKeySaved = d->currentKey;
02233 d->currentKey = 2;
02234 }
02235 else
02236 {
02237 if (d->currentKey != 2)
02238 return;
02239 d->currentKey = d->currentKeySaved;
02240 if ( !d->messages.isEmpty() )
02241 d->postMessageTimer.start( 0, true );
02242 }
02243 }
02244
02245
02246
02247 void
02248 DCOPClient::emergencyClose()
02249 {
02250 TQPtrList<DCOPClient> list;
02251 client_map_t *map = DCOPClient_CliMap;
02252 if (!map) return;
02253 TQAsciiDictIterator<DCOPClient> it(*map);
02254 while(it.current()) {
02255 list.removeRef(it.current());
02256 list.append(it.current());
02257 ++it;
02258 }
02259 for(DCOPClient *cl = list.first(); cl; cl = list.next())
02260 {
02261 if (cl->d->iceConn) {
02262 IceProtocolShutdown(cl->d->iceConn, cl->d->majorOpcode);
02263 IceCloseConnection(cl->d->iceConn);
02264 cl->d->iceConn = 0L;
02265 }
02266 }
02267 }
02268
02269 const char *
02270 DCOPClient::postMortemSender()
02271 {
02272 if (!dcop_main_client)
02273 return "";
02274 if (dcop_main_client->d->senderId.isEmpty())
02275 return "";
02276 return dcop_main_client->d->senderId.data();
02277 }
02278
02279 const char *
02280 DCOPClient::postMortemObject()
02281 {
02282 if (!dcop_main_client)
02283 return "";
02284 return dcop_main_client->d->objId.data();
02285 }
02286 const char *
02287 DCOPClient::postMortemFunction()
02288 {
02289 if (!dcop_main_client)
02290 return "";
02291 return dcop_main_client->d->function.data();
02292 }
02293
02294 void DCOPClient::virtual_hook( int, void* )
02295 { }
02296
02297 #include <dcopclient.moc>
02298