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