• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • dcop
 

dcop

  • dcop
dcopclient.cpp
1/*****************************************************************
2
3Copyright (c) 1999 Preston Brown <pbrown@kde.org>
4Copyright (c) 1999 Matthias Ettrich <ettrich@kde.org>
5
6Permission is hereby granted, free of charge, to any person obtaining a copy
7of this software and associated documentation files (the "Software"), to deal
8in the Software without restriction, including without limitation the rights
9to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10copies of the Software, and to permit persons to whom the Software is
11furnished to do so, subject to the following conditions:
12
13The above copyright notice and this permission notice shall be included in
14all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23******************************************************************/
24
25// qt <-> dcop integration
26#include <tqobjectlist.h>
27#include <tqmetaobject.h>
28#include <tqvariant.h>
29#include <tqtimer.h>
30#include <tqintdict.h>
31#include <tqeventloop.h>
32// end of qt <-> dcop integration
33
34#include "config.h"
35
36#include <config.h>
37#include <dcopref.h>
38
39#include <sys/time.h>
40#include <sys/types.h>
41#include <sys/stat.h>
42#include <sys/file.h>
43#include <sys/socket.h>
44#include <sys/un.h>
45#include <fcntl.h>
46#include <unistd.h>
47
48#include <ctype.h>
49#include <unistd.h>
50#include <stdlib.h>
51#include <assert.h>
52#include <string.h>
53#ifdef HAVE_UCRED_H
54#include <ucred.h>
55#endif /* HAVE_UCRED_H */
56
57#include <tqguardedptr.h>
58#include <tqtextstream.h>
59#include <tqfile.h>
60#include <tqdir.h>
61#include <tqapplication.h>
62#include <tqsocketnotifier.h>
63#include <tqregexp.h>
64
65#include <private/tqucomextra_p.h>
66
67#include <dcopglobal.h>
68#include <dcopclient.h>
69#include <dcopobject.h>
70
71#if defined TQ_WS_X11 && ! defined K_WS_QTONLY
72#include <X11/Xmd.h>
73#endif
74extern "C" {
75#include <KDE-ICE/ICElib.h>
76#include <KDE-ICE/ICEutil.h>
77#include <KDE-ICE/ICEmsg.h>
78#include <KDE-ICE/ICEproto.h>
79}
80
81// #define DCOPCLIENT_DEBUG 1
82
83extern TQMap<TQCString, DCOPObject *> * kde_dcopObjMap; // defined in dcopobject.cpp
84
85/*********************************************
86 * Keep track of local clients
87 *********************************************/
88typedef TQAsciiDict<DCOPClient> client_map_t;
89static client_map_t *DCOPClient_CliMap = 0;
90
91static
92client_map_t *cliMap()
93{
94 if (!DCOPClient_CliMap)
95 DCOPClient_CliMap = new client_map_t;
96 return DCOPClient_CliMap;
97}
98
99DCOPClient *DCOPClient::findLocalClient( const TQCString &_appId )
100{
101 return cliMap()->find(_appId.data());
102}
103
104static
105void registerLocalClient( const TQCString &_appId, DCOPClient *client )
106{
107 cliMap()->replace(_appId.data(), client);
108}
109
110static
111void unregisterLocalClient( const TQCString &_appId )
112{
113 client_map_t *map = cliMap();
114 map->remove(_appId.data());
115}
117
118template class TQPtrList<DCOPObjectProxy>;
119template class TQPtrList<DCOPClientTransaction>;
120template class TQPtrList<_IceConn>;
121
122struct DCOPClientMessage
123{
124 int opcode;
125 CARD32 key;
126 TQByteArray data;
127};
128
129class DCOPClient::ReplyStruct
130{
131public:
132 enum ReplyStatus { Pending, Ok, Failed };
133 ReplyStruct() {
134 status = Pending;
135 replyType = 0;
136 replyData = 0;
137 replyId = -1;
138 transactionId = -1;
139 replyObject = 0;
140 }
141 ReplyStatus status;
142 TQCString* replyType;
143 TQByteArray* replyData;
144 int replyId;
145 TQ_INT32 transactionId;
146 TQCString calledApp;
147 TQGuardedPtr<TQObject> replyObject;
148 TQCString replySlot;
149};
150
151class DCOPClientPrivate
152{
153public:
154 DCOPClient *parent;
155 TQCString appId;
156 IceConn iceConn;
157 int majorOpcode; // major opcode negotiated w/server and used to tag all comms.
158
159 int majorVersion, minorVersion; // protocol versions negotiated w/server
160
161 static const char* serverAddr; // location of server in ICE-friendly format.
162 TQSocketNotifier *notifier;
163 bool non_blocking_call_lock;
164 bool registered;
165 bool foreign_server;
166 bool accept_calls;
167 bool accept_calls_override; // If true, user has specified policy.
168 bool qt_bridge_enabled;
169
170 TQCString senderId;
171 TQCString objId;
172 TQCString function;
173
174 TQCString defaultObject;
175 TQPtrList<DCOPClientTransaction> *transactionList;
176 bool transaction;
177 TQ_INT32 transactionId;
178 int opcode;
179
180 // Special key values:
181 // 0 : Not specified
182 // 1 : DCOPSend
183 // 2 : Priority
184 // >= 42: Normal
185 CARD32 key;
186 CARD32 currentKey;
187 CARD32 currentKeySaved;
188
189 TQTimer postMessageTimer;
190 TQPtrList<DCOPClientMessage> messages;
191
192 TQPtrList<DCOPClient::ReplyStruct> pendingReplies;
193 TQPtrList<DCOPClient::ReplyStruct> asyncReplyQueue;
194
195 struct LocalTransactionResult
196 {
197 TQCString replyType;
198 TQByteArray replyData;
199 };
200
201 TQIntDict<LocalTransactionResult> localTransActionList;
202
203 TQTimer eventLoopTimer;
204};
205
206class DCOPClientTransaction
207{
208public:
209 TQ_INT32 id;
210 CARD32 key;
211 TQCString senderId;
212};
213
214TQCString DCOPClient::iceauthPath()
215{
216#if defined(ICEAUTH_PATH)
217 if (
218# if defined(TQ_WS_WIN)
219 access(ICEAUTH_PATH, 0) == 0
220# else
221 access(ICEAUTH_PATH, X_OK) == 0
222# endif
223 )
224 {
225 return TQCString(ICEAUTH_PATH);
226 }
227
228#elif defined(Q_OS_WIN32)
229 char szPath[512];
230 char * pszFilePart;
231 int ret;
232 ret = SearchPathA(NULL,"iceauth.exe",NULL,sizeof(szPath)/sizeof(szPath[0]),szPath,&pszFilePart);
233 if(ret != 0)
234 return TQCString(szPath);
235
236#else
237 TQCString path = ::getenv("PATH");
238 if (path.isEmpty())
239 path = "/bin:/usr/bin";
240 path += ":/usr/bin/X11:/usr/X11/bin:/usr/X11R6/bin";
241 TQCString fPath = strtok(path.data(), ":\b");
242 while (!fPath.isNull())
243 {
244 fPath += "/iceauth";
245 if (access(fPath.data(), X_OK) == 0)
246 {
247 return fPath;
248 }
249 fPath = strtok(NULL, ":\b");
250 }
251
252#endif
253 return 0;
254}
255
256static TQCString dcopServerFile(const TQCString &hostname, bool old)
257{
258 TQCString fName = ::getenv("DCOPAUTHORITY");
259 if (!old && !fName.isEmpty())
260 return fName;
261
262 fName = TQFile::encodeName( TQDir::homeDirPath() );
263// fName = ::getenv("HOME");
264 if (fName.isEmpty())
265 {
266 fprintf(stderr, "Aborting. $HOME is not set.\n");
267 exit(1);
268 }
269#ifdef TQ_WS_X11
270 TQCString disp = getenv("DISPLAY");
271#elif defined(TQ_WS_QWS)
272 TQCString disp = getenv("QWS_DISPLAY");
273#else
274 TQCString disp;
275#endif
276 if (disp.isEmpty())
277 disp = "NODISPLAY";
278
279 int i;
280 if((i = disp.findRev('.')) > disp.findRev(KPATH_SEPARATOR) && i >= 0)
281 disp.truncate(i);
282
283 if (!old)
284 {
285 while( (i = disp.find(KPATH_SEPARATOR)) >= 0)
286 disp[i] = '_';
287 }
288
289 fName += "/.DCOPserver_";
290 if (hostname.isEmpty())
291 {
292 char hostName[256];
293 hostName[0] = '\0';
294 if (getenv("XAUTHLOCALHOSTNAME"))
295 fName += getenv("XAUTHLOCALHOSTNAME");
296 else if (gethostname(hostName, sizeof(hostName)))
297 {
298 fName += "localhost";
299 }
300 else
301 {
302 hostName[sizeof(hostName)-1] = '\0';
303 fName += hostName;
304 }
305 }
306 else
307 {
308 fName += hostname;
309 }
310 fName += "_"+disp;
311 return fName;
312}
313
314
315// static
316TQCString DCOPClient::dcopServerFile(const TQCString &hostname)
317{
318 return ::dcopServerFile(hostname, false);
319}
320
321
322// static
323TQCString DCOPClient::dcopServerFileOld(const TQCString &hostname)
324{
325 return ::dcopServerFile(hostname, true);
326}
327
328
329const char* DCOPClientPrivate::serverAddr = 0;
330
331static void DCOPProcessInternal( DCOPClientPrivate *d, int opcode, CARD32 key, const TQByteArray& dataReceived, bool canPost );
332
333void DCOPClient::handleAsyncReply(ReplyStruct *replyStruct)
334{
335 if (replyStruct->replyObject)
336 {
337 TQObject::connect(this, TQ_SIGNAL(callBack(int, const TQCString&, const TQByteArray &)),
338 replyStruct->replyObject, replyStruct->replySlot);
339 emit callBack(replyStruct->replyId, *(replyStruct->replyType), *(replyStruct->replyData));
340 TQObject::disconnect(this, TQ_SIGNAL(callBack(int, const TQCString&, const TQByteArray &)),
341 replyStruct->replyObject, replyStruct->replySlot);
342 }
343 delete replyStruct;
344}
345
349static void DCOPProcessMessage(IceConn iceConn, IcePointer clientObject,
350 int opcode, unsigned long length, Bool /*swap*/,
351 IceReplyWaitInfo *replyWait,
352 Bool *replyWaitRet)
353{
354 DCOPMsg *pMsg = 0;
355 DCOPClientPrivate *d = static_cast<DCOPClientPrivate *>(clientObject);
356 DCOPClient::ReplyStruct *replyStruct = replyWait ? static_cast<DCOPClient::ReplyStruct*>(replyWait->reply) : 0;
357
358 IceReadMessageHeader(iceConn, sizeof(DCOPMsg), DCOPMsg, pMsg);
359 CARD32 key = pMsg->key;
360 if ( d->key == 0 )
361 d->key = key; // received a key from the server
362
363 TQByteArray dataReceived( length );
364 IceReadData(iceConn, length, dataReceived.data() );
365
366 d->opcode = opcode;
367 switch (opcode ) {
368
369 case DCOPReplyFailed:
370 if ( replyStruct ) {
371 replyStruct->status = DCOPClient::ReplyStruct::Failed;
372 replyStruct->transactionId = 0;
373 *replyWaitRet = True;
374 return;
375 } else {
376 tqWarning("Very strange! got a DCOPReplyFailed opcode, but we were not waiting for a reply!");
377 return;
378 }
379 case DCOPReply:
380 if ( replyStruct ) {
381 TQByteArray* b = replyStruct->replyData;
382 TQCString* t = replyStruct->replyType;
383 replyStruct->status = DCOPClient::ReplyStruct::Ok;
384 replyStruct->transactionId = 0;
385
386 TQCString calledApp, app;
387 TQDataStream ds( dataReceived, IO_ReadOnly );
388 ds >> calledApp >> app >> *t >> *b;
389
390 *replyWaitRet = True;
391 return;
392 } else {
393 tqWarning("Very strange! got a DCOPReply opcode, but we were not waiting for a reply!");
394 return;
395 }
396 case DCOPReplyWait:
397 if ( replyStruct ) {
398 TQCString calledApp, app;
399 TQ_INT32 id;
400 TQDataStream ds( dataReceived, IO_ReadOnly );
401 ds >> calledApp >> app >> id;
402 replyStruct->transactionId = id;
403 replyStruct->calledApp = calledApp;
404 d->pendingReplies.append(replyStruct);
405 *replyWaitRet = True;
406 return;
407 } else {
408 tqWarning("Very strange! got a DCOPReplyWait opcode, but we were not waiting for a reply!");
409 return;
410 }
411 case DCOPReplyDelayed:
412 {
413 TQDataStream ds( dataReceived, IO_ReadOnly );
414 TQCString calledApp, app;
415 TQ_INT32 id;
416
417 ds >> calledApp >> app >> id;
418 if (replyStruct && (id == replyStruct->transactionId) && (calledApp == replyStruct->calledApp))
419 {
420 *replyWaitRet = True;
421 }
422
423 for(DCOPClient::ReplyStruct *rs = d->pendingReplies.first(); rs;
424 rs = d->pendingReplies.next())
425 {
426 if ((rs->transactionId == id) && (rs->calledApp == calledApp))
427 {
428 d->pendingReplies.remove();
429 TQByteArray* b = rs->replyData;
430 TQCString* t = rs->replyType;
431 ds >> *t >> *b;
432
433 rs->status = DCOPClient::ReplyStruct::Ok;
434 rs->transactionId = 0;
435 if (!rs->replySlot.isEmpty())
436 {
437 d->parent->handleAsyncReply(rs);
438 }
439 return;
440 }
441 }
442 tqWarning("Very strange! got a DCOPReplyDelayed opcode, but we were not waiting for a reply!");
443 return;
444 }
445 case DCOPCall:
446 case DCOPFind:
447 case DCOPSend:
448 DCOPProcessInternal( d, opcode, key, dataReceived, true );
449 }
450}
451
452void DCOPClient::processPostedMessagesInternal()
453{
454 if ( d->messages.isEmpty() )
455 return;
456 TQPtrListIterator<DCOPClientMessage> it (d->messages );
457 DCOPClientMessage* msg ;
458 while ( ( msg = it.current() ) ) {
459 ++it;
460 if ( d->currentKey && msg->key != d->currentKey )
461 continue;
462 d->messages.removeRef( msg );
463 d->opcode = msg->opcode;
464 DCOPProcessInternal( d, msg->opcode, msg->key, msg->data, false );
465 delete msg;
466 }
467 if ( !d->messages.isEmpty() )
468 d->postMessageTimer.start( 100, true );
469}
470
474void DCOPProcessInternal( DCOPClientPrivate *d, int opcode, CARD32 key, const TQByteArray& dataReceived, bool canPost )
475{
476 if (!d->accept_calls && (opcode == DCOPSend))
477 return;
478
479 IceConn iceConn = d->iceConn;
480 DCOPMsg *pMsg = 0;
481 DCOPClient *c = d->parent;
482 TQDataStream ds( dataReceived, IO_ReadOnly );
483
484 TQCString fromApp;
485 ds >> fromApp;
486 if (fromApp.isEmpty())
487 return; // Reserved for local calls
488
489 if (!d->accept_calls)
490 {
491 TQByteArray reply;
492 TQDataStream replyStream( reply, IO_WriteOnly );
493 // Call rejected.
494 replyStream << d->appId << fromApp;
495 IceGetHeader( iceConn, d->majorOpcode, DCOPReplyFailed,
496 sizeof(DCOPMsg), DCOPMsg, pMsg );
497 int datalen = reply.size();
498 pMsg->key = key;
499 pMsg->length += datalen;
500 IceSendData( iceConn, datalen, reply.data());
501 return;
502 }
503
504 TQCString app, objId, fun;
505 TQByteArray data;
506 ds >> app >> objId >> fun >> data;
507 d->senderId = fromApp;
508 d->objId = objId;
509 d->function = fun;
510
511// tqWarning("DCOP: %s got call: %s:%s:%s key = %d currentKey = %d", d->appId.data(), app.data(), objId.data(), fun.data(), key, d->currentKey);
512
513 if ( canPost && d->currentKey && key != d->currentKey ) {
514 DCOPClientMessage* msg = new DCOPClientMessage;
515 msg->opcode = opcode;
516 msg->key = key;
517 msg->data = dataReceived;
518 d->messages.append( msg );
519 d->postMessageTimer.start( 0, true );
520 return;
521 }
522
523 d->objId = objId;
524 d->function = fun;
525
526 TQCString replyType;
527 TQByteArray replyData;
528 bool b;
529 CARD32 oldCurrentKey = d->currentKey;
530 if ( opcode != DCOPSend ) // DCOPSend doesn't change the current key
531 d->currentKey = key;
532
533 if ( opcode == DCOPFind )
534 b = c->find(app, objId, fun, data, replyType, replyData );
535 else
536 b = c->receive( app, objId, fun, data, replyType, replyData );
537 // set notifier back to previous state
538
539 if ( opcode == DCOPSend )
540 return;
541
542 if ((d->currentKey == key) || (oldCurrentKey != 2))
543 d->currentKey = oldCurrentKey;
544
545 TQByteArray reply;
546 TQDataStream replyStream( reply, IO_WriteOnly );
547
548 TQ_INT32 id = c->transactionId();
549 if (id) {
550 // Call delayed. Send back the transaction ID.
551 replyStream << d->appId << fromApp << id;
552
553 IceGetHeader( iceConn, d->majorOpcode, DCOPReplyWait,
554 sizeof(DCOPMsg), DCOPMsg, pMsg );
555 pMsg->key = key;
556 pMsg->length += reply.size();
557 IceSendData( iceConn, reply.size(), const_cast<char *>(reply.data()));
558 return;
559 }
560
561 if ( !b ) {
562 // Call failed. No data send back.
563
564 replyStream << d->appId << fromApp;
565 IceGetHeader( iceConn, d->majorOpcode, DCOPReplyFailed,
566 sizeof(DCOPMsg), DCOPMsg, pMsg );
567 int datalen = reply.size();
568 pMsg->key = key;
569 pMsg->length += datalen;
570 IceSendData( iceConn, datalen, const_cast<char *>(reply.data()));
571 return;
572 }
573
574 // Call successful. Send back replyType and replyData.
575 replyStream << d->appId << fromApp << replyType << replyData.size();
576
577
578 // we are calling, so we need to set up reply data
579 IceGetHeader( iceConn, d->majorOpcode, DCOPReply,
580 sizeof(DCOPMsg), DCOPMsg, pMsg );
581 int datalen = reply.size() + replyData.size();
582 pMsg->key = key;
583 pMsg->length += datalen;
584 // use IceSendData not IceWriteData to avoid a copy. Output buffer
585 // shouldn't need to be flushed.
586 IceSendData( iceConn, reply.size(), const_cast<char *>(reply.data()));
587 IceSendData( iceConn, replyData.size(), const_cast<char *>(replyData.data()));
588}
589
590
591
592static IcePoVersionRec DCOPClientVersions[] = {
593 { DCOPVersionMajor, DCOPVersionMinor, DCOPProcessMessage }
594};
595
596
597static DCOPClient* dcop_main_client = 0;
598
599DCOPClient* DCOPClient::mainClient()
600{
601 return dcop_main_client;
602}
603
604void DCOPClient::setMainClient( DCOPClient* client )
605{
606 dcop_main_client = client;
607}
608
609
610DCOPClient::DCOPClient()
611{
612 d = new DCOPClientPrivate;
613 d->parent = this;
614 d->iceConn = 0L;
615 d->key = 0;
616 d->currentKey = 0;
617 d->majorOpcode = 0;
618 d->appId = 0;
619 d->notifier = 0L;
620 d->non_blocking_call_lock = false;
621 d->registered = false;
622 d->foreign_server = true;
623 d->accept_calls = true;
624 d->accept_calls_override = false;
625 d->qt_bridge_enabled = true;
626 d->transactionList = 0L;
627 d->transactionId = 0;
628 TQObject::connect( &d->postMessageTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( processPostedMessagesInternal() ) );
629 TQObject::connect( &d->eventLoopTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( eventLoopTimeout() ) );
630
631 if ( !mainClient() )
632 setMainClient( this );
633}
634
635DCOPClient::~DCOPClient()
636{
637#ifdef DCOPCLIENT_DEBUG
638 tqWarning("d->messages.count() = %d", d->messages.count());
639 TQPtrListIterator<DCOPClientMessage> it (d->messages );
640 DCOPClientMessage* msg ;
641 while ( ( msg = it.current() ) ) {
642 ++it;
643 d->messages.removeRef( msg );
644 tqWarning("DROPPING UNHANDLED DCOP MESSAGE:");
645 tqWarning(" opcode = %d key = %d", msg->opcode, msg->key);
646 TQDataStream ds( msg->data, IO_ReadOnly );
647
648 TQCString fromApp, app, objId, fun;
649 ds >> fromApp >> app >> objId >> fun;
650 tqWarning(" from = %s", fromApp.data());
651 tqWarning(" to = %s / %s / %s", app.data(), objId.data(), fun.data());
652 delete msg;
653 }
654#endif
655 if (d->iceConn)
656 if (IceConnectionStatus(d->iceConn) == IceConnectAccepted)
657 detach();
658
659 if (d->registered)
660 unregisterLocalClient( d->appId );
661
662 delete d->notifier;
663 delete d->transactionList;
664 d->messages.setAutoDelete(true);
665 delete d;
666
667 if ( mainClient() == this )
668 setMainClient( 0 );
669}
670
671void DCOPClient::setServerAddress(const TQCString &addr)
672{
673 TQCString env = "DCOPSERVER=" + addr;
674 putenv(strdup(env.data()));
675 delete [] DCOPClientPrivate::serverAddr;
676 DCOPClientPrivate::serverAddr = tqstrdup( addr.data() );
677}
678
679bool DCOPClient::attach()
680{
681 if (!attachInternal( true ))
682 if (!attachInternal( true ))
683 return false; // Try two times!
684 return true;
685}
686
687void DCOPClient::bindToApp()
688{
689 // check if we have a tqApp instantiated. If we do,
690 // we can create a TQSocketNotifier and use it for receiving data.
691 if (tqApp) {
692 if ( d->notifier )
693 delete d->notifier;
694 d->notifier = new TQSocketNotifier(socket(),
695 TQSocketNotifier::Read, 0, 0);
696 TQObject::connect(d->notifier, TQ_SIGNAL(activated(int)),
697 TQ_SLOT(processSocketData(int)));
698 }
699}
700
701void DCOPClient::suspend()
702{
703#ifdef TQ_WS_WIN //TODO: remove (win32 ports sometimes do not create notifiers)
704 if (!d->notifier)
705 return;
706#endif
707 assert(d->notifier); // Suspending makes no sense if we didn't had a tqApp yet
708 d->notifier->setEnabled(false);
709}
710
711void DCOPClient::resume()
712{
713#ifdef TQ_WS_WIN //TODO: remove
714 if (!d->notifier)
715 return;
716#endif
717 assert(d->notifier); // Should never happen
718 d->notifier->setEnabled(true);
719}
720
721bool DCOPClient::isSuspended() const
722{
723#if defined(TQ_WS_WIN) || defined(TQ_WS_MAC) //TODO: REMOVE
724 if (!d->notifier)
725 return false;
726#endif
727 return !d->notifier->isEnabled();
728}
729
730#if defined(SO_PEERCRED) || defined(LOCAL_PEEREID) || defined(HAVE_GETPEERUCRED)
731#define USE_PEER_IS_US
732// Check whether the remote end is owned by the same user.
733static bool peerIsUs(int sockfd)
734{
735#ifdef SO_PEERCRED
736#if defined(__OpenBSD__)
737 struct sockpeercred cred;
738#else
739 struct ucred cred;
740#endif
741 socklen_t siz = sizeof(cred);
742 if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cred, &siz) != 0)
743 return false;
744 return (cred.uid == getuid());
745#elif defined LOCAL_PEEREID
746 struct unpcbid cred;
747 socklen_t siz = sizeof(cred);
748 if (getsockopt(sockfd, 0, LOCAL_PEEREID, &cred, &siz) != 0 || siz != sizeof(cred))
749 return false;
750 return (cred.unp_euid == geteuid());
751#elif defined(HAVE_GETPEERUCRED)
752 ucred_t *cred = nullptr;
753 uint_t peer_uid;
754
755 if (getpeerucred(sockfd, &cred) != 0) {
756 if (cred != nullptr)
757 ucred_free(cred);
758 return false;
759 }
760 peer_uid = ucred_geteuid(cred);
761 ucred_free(cred);
762 return (peer_uid == getuid());
763#endif
764}
765#else
766// Check whether the socket is owned by the same user.
767static bool isServerSocketOwnedByUser(const char*server)
768{
769#ifdef Q_OS_WIN
770 if (strncmp(server, "tcp/", 4) != 0)
771 return false; // Not a local socket -> foreign.
772 else
773 return true;
774#else
775 if (strncmp(server, "local/", 6) != 0)
776 return false; // Not a local socket -> foreign.
777 const char *path = strchr(server, KPATH_SEPARATOR);
778 if (!path)
779 return false;
780 path++;
781
782 struct stat stat_buf;
783 if (stat(path, &stat_buf) != 0)
784 return false;
785
786 return (stat_buf.st_uid == getuid());
787#endif
788}
789#endif
790
791
792bool DCOPClient::attachInternal( bool registerAsAnonymous )
793{
794 char errBuf[1024];
795
796 if ( isAttached() )
797 detach();
798
799 if ((d->majorOpcode = IceRegisterForProtocolSetup(const_cast<char *>("DCOP"),
800 const_cast<char *>(DCOPVendorString),
801 const_cast<char *>(DCOPReleaseString),
802 1, DCOPClientVersions,
803 DCOPAuthCount,
804 const_cast<char **>(DCOPAuthNames),
805 DCOPClientAuthProcs, 0L)) < 0) {
806 emit attachFailed(TQString::fromLatin1( "Communications could not be established." ));
807 return false;
808 }
809
810 bool bClearServerAddr = false;
811 // first, check if serverAddr was ever set.
812 if (!d->serverAddr) {
813 // here, we obtain the list of possible DCOP connections,
814 // and attach to them.
815 TQCString dcopSrv;
816 dcopSrv = ::getenv("DCOPSERVER");
817 if (dcopSrv.isEmpty()) {
818 TQCString fName = dcopServerFile();
819 TQFile f(TQFile::decodeName(fName));
820 if (!f.open(IO_ReadOnly)) {
821 emit attachFailed(TQString::fromLatin1( "Could not read network connection list.\n" )+TQFile::decodeName(fName));
822 return false;
823 }
824 int size = TQMIN( (long)1024, f.size() ); // protection against a huge file
825 TQCString contents( size+1 );
826 if ( f.readBlock( contents.data(), size ) != size )
827 {
828 tqDebug("Error reading from %s, didn't read the expected %d bytes", fName.data(), size);
829 // Should we abort ?
830 }
831 contents[size] = '\0';
832 int pos = contents.find('\n');
833 if ( pos == -1 ) // Shouldn't happen
834 {
835 tqDebug("Only one line in dcopserver file !: %s", contents.data());
836 dcopSrv = contents;
837 }
838 else
839 {
840 if(contents[pos - 1] == '\r') // check for windows end of line
841 pos--;
842 dcopSrv = contents.left( pos );
843//#ifndef NDEBUG
844// tqDebug("dcopserver address: %s", dcopSrv.data());
845//#endif
846 }
847 }
848 d->serverAddr = tqstrdup( const_cast<char *>(dcopSrv.data()) );
849 bClearServerAddr = true;
850 }
851
852 if ((d->iceConn = IceOpenConnection(const_cast<char*>(d->serverAddr),
853 static_cast<IcePointer>(this), False, d->majorOpcode,
854 sizeof(errBuf), errBuf)) == 0L) {
855 tqDebug("DCOPClient::attachInternal. Attach failed %s", errBuf);
856 d->iceConn = 0;
857 if (bClearServerAddr) {
858 delete [] d->serverAddr;
859 d->serverAddr = 0;
860 }
861 emit attachFailed(TQString::fromLatin1( errBuf ));
862 return false;
863 }
864 fcntl(socket(), F_SETFL, FD_CLOEXEC);
865
866 IceSetShutdownNegotiation(d->iceConn, False);
867
868 int setupstat;
869 char* vendor = 0;
870 char* release = 0;
871 setupstat = IceProtocolSetup(d->iceConn, d->majorOpcode,
872 static_cast<IcePointer>(d),
873 False, /* must authenticate */
874 &(d->majorVersion), &(d->minorVersion),
875 &(vendor), &(release), 1024, errBuf);
876 if (vendor) free(vendor);
877 if (release) free(release);
878
879 if (setupstat == IceProtocolSetupFailure ||
880 setupstat == IceProtocolSetupIOError) {
881 IceCloseConnection(d->iceConn);
882 d->iceConn = 0;
883 if (bClearServerAddr) {
884 delete [] d->serverAddr;
885 d->serverAddr = 0;
886 }
887 emit attachFailed(TQString::fromLatin1( errBuf ));
888 return false;
889 } else if (setupstat == IceProtocolAlreadyActive) {
890 if (bClearServerAddr) {
891 delete [] d->serverAddr;
892 d->serverAddr = 0;
893 }
894 /* should not happen because 3rd arg to IceOpenConnection was 0. */
895 emit attachFailed(TQString::fromLatin1( "internal error in IceOpenConnection" ));
896 return false;
897 }
898
899
900 if (IceConnectionStatus(d->iceConn) != IceConnectAccepted) {
901 if (bClearServerAddr) {
902 delete [] d->serverAddr;
903 d->serverAddr = 0;
904 }
905 emit attachFailed(TQString::fromLatin1( "DCOP server did not accept the connection." ));
906 return false;
907 }
908
909#ifdef USE_PEER_IS_US
910 d->foreign_server = !peerIsUs(socket());
911#else
912 d->foreign_server = !isServerSocketOwnedByUser(d->serverAddr);
913#endif
914 if (!d->accept_calls_override)
915 d->accept_calls = !d->foreign_server;
916
917 bindToApp();
918
919 if ( registerAsAnonymous )
920 registerAs( "anonymous", true );
921
922 return true;
923}
924
925
926bool DCOPClient::detach()
927{
928 int status;
929
930 if (d->iceConn) {
931 IceProtocolShutdown(d->iceConn, d->majorOpcode);
932 status = IceCloseConnection(d->iceConn);
933 if (status != IceClosedNow)
934 return false;
935 else
936 d->iceConn = 0L;
937 }
938
939 if (d->registered)
940 unregisterLocalClient(d->appId);
941
942 delete d->notifier;
943 d->notifier = 0L;
944 d->registered = false;
945 d->foreign_server = true;
946 return true;
947}
948
949bool DCOPClient::isAttached() const
950{
951 if (!d->iceConn)
952 return false;
953
954 return (IceConnectionStatus(d->iceConn) == IceConnectAccepted);
955}
956
957bool DCOPClient::isAttachedToForeignServer() const
958{
959 return isAttached() && d->foreign_server;
960}
961
962bool DCOPClient::acceptCalls() const
963{
964 return isAttached() && d->accept_calls;
965}
966
967void DCOPClient::setAcceptCalls(bool b)
968{
969 d->accept_calls = b;
970 d->accept_calls_override = true;
971}
972
973bool DCOPClient::qtBridgeEnabled()
974{
975 return d->qt_bridge_enabled;
976}
977
978void DCOPClient::setQtBridgeEnabled(bool b)
979{
980 d->qt_bridge_enabled = b;
981}
982
983TQCString DCOPClient::registerAs( const TQCString &appId, bool addPID )
984{
985 TQCString result;
986
987 TQCString _appId = appId;
988
989 if (addPID) {
990 TQCString pid;
991 pid.sprintf("-%d", getpid());
992 _appId = _appId + pid;
993 }
994
995 if( d->appId == _appId )
996 return d->appId;
997
998#if 0 // no need to detach, dcopserver can handle renaming
999 // Detach before reregistering.
1000 if ( isRegistered() ) {
1001 detach();
1002 }
1003#endif
1004
1005 if ( !isAttached() ) {
1006 if (!attachInternal( false ))
1007 if (!attachInternal( false ))
1008 return result; // Try two times
1009 }
1010
1011 // register the application identifier with the server
1012 TQCString replyType;
1013 TQByteArray data, replyData;
1014 TQDataStream arg( data, IO_WriteOnly );
1015 arg << _appId;
1016 if ( call( "DCOPServer", "", "registerAs(TQCString)", data, replyType, replyData ) ) {
1017 TQDataStream reply( replyData, IO_ReadOnly );
1018 reply >> result;
1019 }
1020
1021 d->appId = result;
1022 d->registered = !result.isNull();
1023
1024 if (d->registered)
1025 registerLocalClient( d->appId, this );
1026
1027 return result;
1028}
1029
1030bool DCOPClient::isRegistered() const
1031{
1032 return d->registered;
1033}
1034
1035
1036TQCString DCOPClient::appId() const
1037{
1038 return d->appId;
1039}
1040
1041
1042int DCOPClient::socket() const
1043{
1044 if (d->iceConn)
1045 return IceConnectionNumber(d->iceConn);
1046 return 0;
1047}
1048
1049static inline bool isIdentChar( char x )
1050{ // Avoid bug in isalnum
1051 return x == '_' || (x >= '0' && x <= '9') ||
1052 (x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z');
1053}
1054
1055TQCString DCOPClient::normalizeFunctionSignature( const TQCString& fun ) {
1056 if ( fun.isEmpty() ) // nothing to do
1057 return fun.copy();
1058 TQCString result( fun.size() );
1059 char *from = const_cast<TQCString&>(fun).data();
1060 char *to = result.data();
1061 char *first = to;
1062 char last = 0;
1063 while ( true ) {
1064 while ( *from && isspace(*from) )
1065 from++;
1066 if ( last && isIdentChar( last ) && isIdentChar( *from ) )
1067 *to++ = 0x20;
1068 while ( *from && !isspace(*from) ) {
1069 last = *from++;
1070 *to++ = last;
1071 }
1072 if ( !*from )
1073 break;
1074 }
1075 if ( to > first && *(to-1) == 0x20 )
1076 to--;
1077 *to = '\0';
1078 result.resize( (int)((long)to - (long)result.data()) + 1 );
1079 return result;
1080}
1081
1082
1083TQCString DCOPClient::senderId() const
1084{
1085 return d->senderId;
1086}
1087
1088
1089bool DCOPClient::send(const TQCString &remApp, const TQCString &remObjId,
1090 const TQCString &remFun, const TQByteArray &data)
1091{
1092 if (remApp.isEmpty())
1093 return false;
1094 DCOPClient *localClient = findLocalClient( remApp );
1095
1096 if ( localClient ) {
1097 bool saveTransaction = d->transaction;
1098 TQ_INT32 saveTransactionId = d->transactionId;
1099 TQCString saveSenderId = d->senderId;
1100
1101 d->senderId = 0; // Local call
1102 TQCString replyType;
1103 TQByteArray replyData;
1104 (void) localClient->receive( remApp, remObjId, remFun, data, replyType, replyData );
1105
1106 d->transaction = saveTransaction;
1107 d->transactionId = saveTransactionId;
1108 d->senderId = saveSenderId;
1109 // send() returns true if the data could be send to the DCOPServer,
1110 // regardles of receiving the data on the other application.
1111 // So we assume the data is successfully send to the (virtual) server
1112 // and return true in any case.
1113 return true;
1114 }
1115
1116 if ( !isAttached() )
1117 return false;
1118
1119
1120 DCOPMsg *pMsg;
1121
1122 TQByteArray ba;
1123 TQDataStream ds(ba, IO_WriteOnly);
1124 ds << d->appId << remApp << remObjId << normalizeFunctionSignature(remFun) << data.size();
1125
1126 IceGetHeader(d->iceConn, d->majorOpcode, DCOPSend,
1127 sizeof(DCOPMsg), DCOPMsg, pMsg);
1128
1129 pMsg->key = 1; // DCOPSend always uses the magic key 1
1130 int datalen = ba.size() + data.size();
1131 pMsg->length += datalen;
1132
1133 IceSendData( d->iceConn, ba.size(), const_cast<char *>(ba.data()) );
1134 IceSendData( d->iceConn, data.size(), const_cast<char *>(data.data()) );
1135
1136 //IceFlush(d->iceConn);
1137
1138 if (IceConnectionStatus(d->iceConn) == IceConnectAccepted)
1139 return true;
1140 return false;
1141}
1142
1143bool DCOPClient::send(const TQCString &remApp, const TQCString &remObjId,
1144 const TQCString &remFun, const TQString &data)
1145{
1146 TQByteArray ba;
1147 TQDataStream ds(ba, IO_WriteOnly);
1148 ds << data;
1149 return send(remApp, remObjId, remFun, ba);
1150}
1151
1152bool DCOPClient::findObject(const TQCString &remApp, const TQCString &remObj,
1153 const TQCString &remFun, const TQByteArray &data,
1154 TQCString &foundApp, TQCString &foundObj,
1155 bool useEventLoop)
1156{
1157 return findObject( remApp, remObj, remFun, data, foundApp, foundObj, useEventLoop, -1 );
1158}
1159
1160bool DCOPClient::findObject(const TQCString &remApp, const TQCString &remObj,
1161 const TQCString &remFun, const TQByteArray &data,
1162 TQCString &foundApp, TQCString &foundObj,
1163 bool useEventLoop, int timeout)
1164{
1165 QCStringList appList;
1166 TQCString app = remApp;
1167 if (app.isEmpty())
1168 app = "*";
1169
1170 foundApp = 0;
1171 foundObj = 0;
1172
1173 if (app[app.length()-1] == '*')
1174 {
1175 // Find all apps that match 'app'.
1176 // NOTE: It would be more efficient to do the filtering in
1177 // the dcopserver itself.
1178 int len = app.length()-1;
1179 QCStringList apps=registeredApplications();
1180 for( QCStringList::ConstIterator it = apps.begin();
1181 it != apps.end();
1182 ++it)
1183 {
1184 if ( strncmp( (*it).data(), app.data(), len) == 0)
1185 appList.append(*it);
1186 }
1187 }
1188 else
1189 {
1190 appList.append(app);
1191 }
1192
1193 // We do all the local clients in phase1 and the rest in phase2
1194 for(int phase=1; phase <= 2; phase++)
1195 {
1196 for( QCStringList::ConstIterator it = appList.begin();
1197 it != appList.end();
1198 ++it)
1199 {
1200 TQCString remApp = *it;
1201 TQCString replyType;
1202 TQByteArray replyData;
1203 bool result = false;
1204 DCOPClient *localClient = findLocalClient( remApp );
1205
1206 if ( (phase == 1) && localClient ) {
1207 // In phase 1 we do all local clients
1208 bool saveTransaction = d->transaction;
1209 TQ_INT32 saveTransactionId = d->transactionId;
1210 TQCString saveSenderId = d->senderId;
1211
1212 d->senderId = 0; // Local call
1213 result = localClient->find( remApp, remObj, remFun, data, replyType, replyData );
1214
1215 TQ_INT32 id = localClient->transactionId();
1216 if (id) {
1217 // Call delayed. We have to wait till it has been processed.
1218 do {
1219 TQApplication::eventLoop()->processEvents( TQEventLoop::WaitForMore);
1220 } while( !localClient->isLocalTransactionFinished(id, replyType, replyData));
1221 result = true;
1222 }
1223 d->transaction = saveTransaction;
1224 d->transactionId = saveTransactionId;
1225 d->senderId = saveSenderId;
1226 }
1227 else if ((phase == 2) && !localClient)
1228 {
1229 // In phase 2 we do the other clients
1230 result = callInternal(remApp, remObj, remFun, data,
1231 replyType, replyData, useEventLoop, timeout, DCOPFind);
1232 }
1233
1234 if (result)
1235 {
1236 if (replyType == "DCOPRef")
1237 {
1238 DCOPRef ref;
1239 TQDataStream reply( replyData, IO_ReadOnly );
1240 reply >> ref;
1241
1242 if (ref.app() == remApp) // Consistency check
1243 {
1244 // replyType contains objId.
1245 foundApp = ref.app();
1246 foundObj = ref.object();
1247 return true;
1248 }
1249 }
1250 }
1251 }
1252 }
1253 return false;
1254}
1255
1256bool DCOPClient::process(const TQCString &, const TQByteArray &,
1257 TQCString&, TQByteArray &)
1258{
1259 return false;
1260}
1261
1262bool DCOPClient::isApplicationRegistered( const TQCString& remApp)
1263{
1264 TQCString replyType;
1265 TQByteArray data, replyData;
1266 TQDataStream arg( data, IO_WriteOnly );
1267 arg << remApp;
1268 int result = false;
1269 if ( call( "DCOPServer", "", "isApplicationRegistered(TQCString)", data, replyType, replyData ) ) {
1270 TQDataStream reply( replyData, IO_ReadOnly );
1271 reply >> result;
1272 }
1273 return result;
1274}
1275
1276QCStringList DCOPClient::registeredApplications()
1277{
1278 TQCString replyType;
1279 TQByteArray data, replyData;
1280 QCStringList result;
1281 if ( call( "DCOPServer", "", "registeredApplications()", data, replyType, replyData ) ) {
1282 TQDataStream reply( replyData, IO_ReadOnly );
1283 reply >> result;
1284 }
1285 return result;
1286}
1287
1288QCStringList DCOPClient::remoteObjects( const TQCString& remApp, bool *ok )
1289{
1290 TQCString replyType;
1291 TQByteArray data, replyData;
1292 QCStringList result;
1293 if ( ok )
1294 *ok = false;
1295 if ( call( remApp, "DCOPClient", "objects()", data, replyType, replyData ) ) {
1296 TQDataStream reply( replyData, IO_ReadOnly );
1297 reply >> result;
1298 if ( ok )
1299 *ok = true;
1300 }
1301 return result;
1302}
1303
1304QCStringList DCOPClient::remoteInterfaces( const TQCString& remApp, const TQCString& remObj, bool *ok )
1305{
1306 TQCString replyType;
1307 TQByteArray data, replyData;
1308 QCStringList result;
1309 if ( ok )
1310 *ok = false;
1311 if ( call( remApp, remObj, "interfaces()", data, replyType, replyData ) && replyType == "QCStringList") {
1312 TQDataStream reply( replyData, IO_ReadOnly );
1313 reply >> result;
1314 if ( ok )
1315 *ok = true;
1316 }
1317 return result;
1318}
1319
1320QCStringList DCOPClient::remoteFunctions( const TQCString& remApp, const TQCString& remObj, bool *ok )
1321{
1322 TQCString replyType;
1323 TQByteArray data, replyData;
1324 QCStringList result;
1325 if ( ok )
1326 *ok = false;
1327 if ( call( remApp, remObj, "functions()", data, replyType, replyData ) && replyType == "QCStringList") {
1328 TQDataStream reply( replyData, IO_ReadOnly );
1329 reply >> result;
1330 if ( ok )
1331 *ok = true;
1332 }
1333 return result;
1334}
1335
1336void DCOPClient::setNotifications(bool enabled)
1337{
1338 TQByteArray data;
1339 TQDataStream ds(data, IO_WriteOnly);
1340 ds << static_cast<TQ_INT8>(enabled);
1341
1342 TQCString replyType;
1343 TQByteArray reply;
1344 if (!call("DCOPServer", "", "setNotifications( bool )", data, replyType, reply))
1345 tqWarning("I couldn't enable notifications at the dcopserver!");
1346}
1347
1348void DCOPClient::setDaemonMode( bool daemonMode )
1349{
1350 TQByteArray data;
1351 TQDataStream ds(data, IO_WriteOnly);
1352 ds << static_cast<TQ_INT8>( daemonMode );
1353
1354 TQCString replyType;
1355 TQByteArray reply;
1356 if (!call("DCOPServer", "", "setDaemonMode(bool)", data, replyType, reply))
1357 tqWarning("I couldn't enable daemon mode at the dcopserver!");
1358}
1359
1360
1361
1362/*
1363 DCOP <-> Qt bridge
1364
1365 ********************************************************************************
1366 */
1367static void fillQtObjects( QCStringList& l, TQObject* o, TQCString path )
1368{
1369 if ( !path.isEmpty() )
1370 path += '/';
1371
1372 int unnamed = 0;
1373 const TQObjectList list = o ? o->childrenListObject() : TQObject::objectTreesListObject();
1374 if ( !list.isEmpty() ) {
1375 TQObjectListIt it( list );
1376 TQObject *obj;
1377 while ( (obj=it.current()) ) {
1378 ++it;
1379 TQCString n = obj->name();
1380 if ( n == "unnamed" || n.isEmpty() )
1381 {
1382 n.sprintf("%p", (void *) obj);
1383 n = TQString(TQString("unnamed%1(%2, %3)").arg(++unnamed).arg(obj->className()).arg(TQString(n))).latin1();
1384 }
1385 TQCString fn = path + n;
1386 l.append( fn );
1387 if ( !obj->childrenListObject().isEmpty() )
1388 fillQtObjects( l, obj, fn );
1389 }
1390 }
1391}
1392
1393namespace
1394{
1395struct O
1396{
1397 O(): o(0) {}
1398 O ( const TQCString& str, TQObject* obj ):s(str), o(obj){}
1399 TQCString s;
1400 TQObject* o;
1401};
1402} // namespace
1403
1404static void fillQtObjectsEx( TQValueList<O>& l, TQObject* o, TQCString path )
1405{
1406 if ( !path.isEmpty() )
1407 path += '/';
1408
1409 int unnamed = 0;
1410 const TQObjectList list = o ? o->childrenListObject() : TQObject::objectTreesListObject();
1411 if ( !list.isEmpty() ) {
1412 TQObjectListIt it( list );
1413 TQObject *obj;
1414 while ( (obj=it.current()) ) {
1415 ++it;
1416 TQCString n = obj->name();
1417 if ( n == "unnamed" || n.isEmpty() )
1418 {
1419 n.sprintf("%p", (void *) obj);
1420 n = TQString(TQString("unnamed%1(%2, %3)").arg(++unnamed).arg(obj->className()).arg(TQString(n))).latin1();
1421 }
1422 TQCString fn = path + n;
1423 l.append( O( fn, obj ) );
1424 if ( !obj->childrenListObject().isEmpty() )
1425 fillQtObjectsEx( l, obj, fn );
1426 }
1427 }
1428}
1429
1430
1431static TQObject* findQtObject( TQCString id )
1432{
1433 TQRegExp expr( id );
1434 TQValueList<O> l;
1435 fillQtObjectsEx( l, 0, "qt" );
1436 // Prefer an exact match, but fall-back on the first that contains the substring
1437 TQObject* firstContains = 0L;
1438 for ( TQValueList<O>::ConstIterator it = l.begin(); it != l.end(); ++it ) {
1439 if ( (*it).s == id ) // exact match
1440 return (*it).o;
1441 if ( !firstContains && (*it).s.contains( expr ) ) {
1442 firstContains = (*it).o;
1443 }
1444 }
1445 return firstContains;
1446}
1447
1448static QCStringList findQtObjects( TQCString id )
1449{
1450 TQRegExp expr( id );
1451 TQValueList<O> l;
1452 fillQtObjectsEx( l, 0, "qt" );
1453 QCStringList result;
1454 for ( TQValueList<O>::ConstIterator it = l.begin(); it != l.end(); ++it ) {
1455 if ( (*it).s.contains( expr ) )
1456 result << (*it).s;
1457 }
1458 return result;
1459}
1460
1461static bool receiveQtObject( const TQCString &objId, const TQCString &fun, const TQByteArray &data,
1462 TQCString& replyType, TQByteArray &replyData)
1463{
1464 if ( objId == "qt" ) {
1465 if ( fun == "interfaces()" ) {
1466 replyType = "QCStringList";
1467 TQDataStream reply( replyData, IO_WriteOnly );
1468 QCStringList l;
1469 l << "DCOPObject";
1470 l << "Qt";
1471 reply << l;
1472 return true;
1473 } else if ( fun == "functions()" ) {
1474 replyType = "QCStringList";
1475 TQDataStream reply( replyData, IO_WriteOnly );
1476 QCStringList l;
1477 l << "QCStringList functions()";
1478 l << "QCStringList interfaces()";
1479 l << "QCStringList objects()";
1480 l << "QCStringList find(TQCString)";
1481 reply << l;
1482 return true;
1483 } else if ( fun == "objects()" ) {
1484 replyType = "QCStringList";
1485 TQDataStream reply( replyData, IO_WriteOnly );
1486 QCStringList l;
1487 fillQtObjects( l, 0, "qt" );
1488 reply << l;
1489 return true;
1490 } else if ( fun == "find(TQCString)" ) {
1491 TQDataStream ds( data, IO_ReadOnly );
1492 TQCString id;
1493 ds >> id ;
1494 replyType = "QCStringList";
1495 TQDataStream reply( replyData, IO_WriteOnly );
1496 reply << findQtObjects( id ) ;
1497 return true;
1498 }
1499 } else if ( objId.left(3) == "qt/" ) {
1500 TQObject* o = findQtObject( objId );
1501 if ( !o )
1502 return false;
1503 if ( fun == "functions()" ) {
1504 replyType = "QCStringList";
1505 TQDataStream reply( replyData, IO_WriteOnly );
1506 QCStringList l;
1507 l << "QCStringList functions()";
1508 l << "QCStringList interfaces()";
1509 l << "QCStringList properties()";
1510 l << "bool setProperty(TQCString,TQVariant)";
1511 l << "TQVariant property(TQCString)";
1512 TQStrList lst = o->metaObject()->slotNames( true );
1513 int i = 0;
1514 for ( TQPtrListIterator<char> it( lst ); it.current(); ++it ) {
1515 if ( o->metaObject()->slot( i++, true )->access != TQMetaData::Public )
1516 continue;
1517 TQCString slot = it.current();
1518 if ( slot.contains( "()" ) ) {
1519 slot.prepend("void ");
1520 l << slot;
1521 }
1522 }
1523 reply << l;
1524 return true;
1525 } else if ( fun == "interfaces()" ) {
1526 replyType = "QCStringList";
1527 TQDataStream reply( replyData, IO_WriteOnly );
1528 QCStringList l;
1529 TQMetaObject *meta = o->metaObject();
1530 while ( meta ) {
1531 l.prepend( meta->className() );
1532 meta = meta->superClass();
1533 }
1534 reply << l;
1535 return true;
1536 } else if ( fun == "properties()" ) {
1537 replyType = "QCStringList";
1538 TQDataStream reply( replyData, IO_WriteOnly );
1539 QCStringList l;
1540 TQStrList lst = o->metaObject()->propertyNames( true );
1541 for ( TQPtrListIterator<char> it( lst ); it.current(); ++it ) {
1542 TQMetaObject *mo = o->metaObject();
1543 const TQMetaProperty* p = mo->property( mo->findProperty( it.current(), true ), true );
1544 if ( !p )
1545 continue;
1546 TQCString prop = p->type();
1547 prop += ' ';
1548 prop += p->name();
1549 if ( !p->writable() )
1550 prop += " readonly";
1551 l << prop;
1552 }
1553 reply << l;
1554 return true;
1555 } else if ( fun == "property(TQCString)" ) {
1556 replyType = "TQVariant";
1557 TQDataStream ds( data, IO_ReadOnly );
1558 TQCString name;
1559 ds >> name ;
1560 TQVariant result = o->property( name );
1561 TQDataStream reply( replyData, IO_WriteOnly );
1562 reply << result;
1563 return true;
1564 } else if ( fun == "setProperty(TQCString,TQVariant)" ) {
1565 TQDataStream ds( data, IO_ReadOnly );
1566 TQCString name;
1567 TQVariant value;
1568 ds >> name >> value;
1569 replyType = "bool";
1570 TQDataStream reply( replyData, IO_WriteOnly );
1571 reply << (TQ_INT8) o->setProperty( name, value );
1572 return true;
1573 } else {
1574 int slot = o->metaObject()->findSlot( fun, true );
1575 if ( slot != -1 ) {
1576 replyType = "void";
1577 TQUObject uo[ 1 ];
1578 o->tqt_invoke( slot, uo );
1579 return true;
1580 }
1581 }
1582
1583
1584 }
1585 return false;
1586}
1587
1588
1589/*
1590 ********************************************************************************
1591 End of DCOP <-> Qt bridge
1592 */
1593
1594
1595bool DCOPClient::receive(const TQCString &/*app*/, const TQCString &objId,
1596 const TQCString &fun, const TQByteArray &data,
1597 TQCString& replyType, TQByteArray &replyData)
1598{
1599 d->transaction = false; // Assume no transaction.
1600 if ( objId == "DCOPClient" ) {
1601 if ( fun == "objects()" ) {
1602 replyType = "QCStringList";
1603 TQDataStream reply( replyData, IO_WriteOnly );
1604 QCStringList l;
1605 if (d->qt_bridge_enabled)
1606 {
1607 l << "qt"; // the Qt bridge object
1608 }
1609 if ( kde_dcopObjMap ) {
1610 TQMap<TQCString, DCOPObject *>::ConstIterator it( kde_dcopObjMap->begin());
1611 for (; it != kde_dcopObjMap->end(); ++it) {
1612 if ( !it.key().isEmpty() ) {
1613 if ( it.key() == d->defaultObject )
1614 l << "default";
1615 l << it.key();
1616 }
1617 }
1618 }
1619 reply << l;
1620 return true;
1621 }
1622 }
1623
1624 if ( objId.isEmpty() || objId == "DCOPClient" ) {
1625 if ( fun == "applicationRegistered(TQCString)" ) {
1626 TQDataStream ds( data, IO_ReadOnly );
1627 TQCString r;
1628 ds >> r;
1629 emit applicationRegistered( r );
1630 return true;
1631 } else if ( fun == "applicationRemoved(TQCString)" ) {
1632 TQDataStream ds( data, IO_ReadOnly );
1633 TQCString r;
1634 ds >> r;
1635 emit applicationRemoved( r );
1636 return true;
1637 }
1638
1639 if ( process( fun, data, replyType, replyData ) )
1640 return true;
1641 // fall through and send to defaultObject if available
1642
1643 } else if (d->qt_bridge_enabled &&
1644 (objId == "qt" || objId.left(3) == "qt/") ) { // dcop <-> qt bridge
1645 return receiveQtObject( objId, fun, data, replyType, replyData );
1646 }
1647
1648 if ( objId.isEmpty() || objId == "default" ) {
1649 if ( !d->defaultObject.isEmpty() && DCOPObject::hasObject( d->defaultObject ) ) {
1650 DCOPObject *objPtr = DCOPObject::find( d->defaultObject );
1651 objPtr->setCallingDcopClient(this);
1652 if (objPtr->process(fun, data, replyType, replyData))
1653 return true;
1654 }
1655
1656 // fall through and send to object proxies
1657 }
1658
1659// if (!objId.isEmpty() && objId[objId.length()-1] == '*') {
1660 if (!objId.isEmpty() && ((objId.length()>0)?(objId[objId.length()-1] == '*'):0)) {
1661 // handle a multicast to several objects.
1662 // doesn't handle proxies currently. should it?
1663 TQPtrList<DCOPObject> matchList =
1664 DCOPObject::match(objId.left(objId.length()-1));
1665 for (DCOPObject *objPtr = matchList.first();
1666 objPtr != 0L; objPtr = matchList.next()) {
1667 objPtr->setCallingDcopClient(this);
1668 if (!objPtr->process(fun, data, replyType, replyData))
1669 return false;
1670 }
1671 return true;
1672 } else if (!DCOPObject::hasObject(objId)) {
1673 if ( DCOPObjectProxy::proxies ) {
1674 for ( TQPtrListIterator<DCOPObjectProxy> it( *DCOPObjectProxy::proxies ); it.current(); ++it ) {
1675 // TODO: it.current()->setCallingDcopClient(this);
1676 if ( it.current()->process( objId, fun, data, replyType, replyData ) )
1677 return true;
1678 }
1679 }
1680 return false;
1681
1682 } else {
1683 DCOPObject *objPtr = DCOPObject::find(objId);
1684 objPtr->setCallingDcopClient(this);
1685 if (!objPtr->process(fun, data, replyType, replyData)) {
1686 // obj doesn't understand function or some other error.
1687 return false;
1688 }
1689 }
1690
1691 return true;
1692}
1693
1694// Check if the function result is a bool with the value "true"
1695// If so set the function result to DCOPRef pointing to (app,objId) and
1696// return true. Return false otherwise.
1697static bool findResultOk(TQCString &replyType, TQByteArray &replyData)
1698{
1699 TQ_INT8 success; // Tsk.. why is there no operator>>(bool)?
1700 if (replyType != "bool") return false;
1701
1702 TQDataStream reply( replyData, IO_ReadOnly );
1703 reply >> success;
1704
1705 if (!success) return false;
1706 return true;
1707}
1708
1709// set the function result to DCOPRef pointing to (app,objId) and
1710// return true.
1711static bool findSuccess(const TQCString &app, const TQCString objId, TQCString &replyType, TQByteArray &replyData)
1712{
1713 DCOPRef ref(app, objId);
1714 replyType = "DCOPRef";
1715
1716 replyData = TQByteArray();
1717 TQDataStream final_reply( replyData, IO_WriteOnly );
1718 final_reply << ref;
1719 return true;
1720}
1721
1722
1723bool DCOPClient::find(const TQCString &app, const TQCString &objId,
1724 const TQCString &fun, const TQByteArray &data,
1725 TQCString& replyType, TQByteArray &replyData)
1726{
1727 d->transaction = false; // Transactions are not allowed.
1728 if ( !app.isEmpty() && app != d->appId && app[app.length()-1] != '*') {
1729 tqWarning("WEIRD! we somehow received a DCOP message w/a different appId");
1730 return false;
1731 }
1732
1733 if (objId.isEmpty() || objId[objId.length()-1] != '*')
1734 {
1735 if (fun.isEmpty())
1736 {
1737 if (objId.isEmpty() || DCOPObject::hasObject(objId))
1738 return findSuccess(app, objId, replyType, replyData);
1739 return false;
1740 }
1741 // Message to application or single object...
1742 if (receive(app, objId, fun, data, replyType, replyData))
1743 {
1744 if (findResultOk(replyType, replyData))
1745 return findSuccess(app, objId, replyType, replyData);
1746 }
1747 }
1748 else {
1749 // handle a multicast to several objects.
1750 // doesn't handle proxies currently. should it?
1751 TQPtrList<DCOPObject> matchList =
1752 DCOPObject::match(objId.left(objId.length()-1));
1753 for (DCOPObject *objPtr = matchList.first();
1754 objPtr != 0L; objPtr = matchList.next())
1755 {
1756 replyType = 0;
1757 replyData = TQByteArray();
1758 if (fun.isEmpty())
1759 return findSuccess(app, objPtr->objId(), replyType, replyData);
1760 objPtr->setCallingDcopClient(this);
1761 if (objPtr->process(fun, data, replyType, replyData))
1762 if (findResultOk(replyType, replyData))
1763 return findSuccess(app, objPtr->objId(), replyType, replyData);
1764 }
1765 }
1766 return false;
1767}
1768
1769
1770bool DCOPClient::call(const TQCString &remApp, const TQCString &remObjId,
1771 const TQCString &remFun, const TQByteArray &data,
1772 TQCString& replyType, TQByteArray &replyData,
1773 bool useEventLoop)
1774{
1775 return call( remApp, remObjId, remFun, data, replyType, replyData, useEventLoop, -1, false );
1776}
1777
1778bool DCOPClient::call(const TQCString &remApp, const TQCString &remObjId,
1779 const TQCString &remFun, const TQByteArray &data,
1780 TQCString& replyType, TQByteArray &replyData,
1781 bool useEventLoop, int timeout)
1782{
1783 return call( remApp, remObjId, remFun, data, replyType, replyData, useEventLoop, timeout, false );
1784}
1785
1786bool DCOPClient::call(const TQCString &remApp, const TQCString &remObjId,
1787 const TQCString &remFun, const TQByteArray &data,
1788 TQCString& replyType, TQByteArray &replyData,
1789 bool useEventLoop, int timeout, bool forceRemote)
1790{
1791 if (remApp.isEmpty())
1792 return false;
1793 DCOPClient *localClient = findLocalClient( remApp );
1794
1795 if ( localClient && !forceRemote ) {
1796 bool saveTransaction = d->transaction;
1797 TQ_INT32 saveTransactionId = d->transactionId;
1798 TQCString saveSenderId = d->senderId;
1799
1800 d->senderId = 0; // Local call
1801 bool b = localClient->receive( remApp, remObjId, remFun, data, replyType, replyData );
1802
1803 TQ_INT32 id = localClient->transactionId();
1804 if (id) {
1805 // Call delayed. We have to wait till it has been processed.
1806 do {
1807 TQApplication::eventLoop()->processEvents(TQEventLoop::WaitForMore);
1808 } while( !localClient->isLocalTransactionFinished(id, replyType, replyData));
1809 b = true;
1810 }
1811 d->transaction = saveTransaction;
1812 d->transactionId = saveTransactionId;
1813 d->senderId = saveSenderId;
1814 return b;
1815 }
1816
1817 return callInternal(remApp, remObjId, remFun, data,
1818 replyType, replyData, useEventLoop, timeout, DCOPCall);
1819}
1820
1821void DCOPClient::asyncReplyReady()
1822{
1823 while( d->asyncReplyQueue.count() )
1824 {
1825 ReplyStruct *replyStruct = d->asyncReplyQueue.take(0);
1826 handleAsyncReply(replyStruct);
1827 }
1828}
1829
1830int DCOPClient::callAsync(const TQCString &remApp, const TQCString &remObjId,
1831 const TQCString &remFun, const TQByteArray &data,
1832 TQObject *callBackObj, const char *callBackSlot)
1833{
1834 TQCString replyType;
1835 TQByteArray replyData;
1836
1837 ReplyStruct *replyStruct = new ReplyStruct;
1838 replyStruct->replyType = new TQCString;
1839 replyStruct->replyData = new TQByteArray;
1840 replyStruct->replyObject = callBackObj;
1841 replyStruct->replySlot = callBackSlot;
1842 replyStruct->replyId = ++d->transactionId;
1843 if (d->transactionId < 0) // Ensure that ids > 0
1844 d->transactionId = 0;
1845
1846 bool b = callInternal(remApp, remObjId, remFun, data,
1847 replyStruct, false, -1, DCOPCall);
1848 if (!b)
1849 {
1850 delete replyStruct->replyType;
1851 delete replyStruct->replyData;
1852 delete replyStruct;
1853 return 0;
1854 }
1855
1856 if (replyStruct->transactionId == 0)
1857 {
1858 // Call is finished already
1859 TQTimer::singleShot(0, this, TQ_SLOT(asyncReplyReady()));
1860 d->asyncReplyQueue.append(replyStruct);
1861 }
1862
1863 return replyStruct->replyId;
1864}
1865
1866bool DCOPClient::callInternal(const TQCString &remApp, const TQCString &remObjId,
1867 const TQCString &remFun, const TQByteArray &data,
1868 TQCString& replyType, TQByteArray &replyData,
1869 bool useEventLoop, int timeout, int minor_opcode)
1870{
1871 ReplyStruct replyStruct;
1872 replyStruct.replyType = &replyType;
1873 replyStruct.replyData = &replyData;
1874 return callInternal(remApp, remObjId, remFun, data, &replyStruct, useEventLoop, timeout, minor_opcode);
1875}
1876
1877bool DCOPClient::callInternal(const TQCString &remApp, const TQCString &remObjId,
1878 const TQCString &remFun, const TQByteArray &data,
1879 ReplyStruct *replyStruct,
1880 bool useEventLoop, int timeout, int minor_opcode)
1881{
1882 if ( !isAttached() )
1883 return false;
1884
1885 DCOPMsg *pMsg;
1886
1887 CARD32 oldCurrentKey = d->currentKey;
1888 if ( !d->currentKey )
1889 d->currentKey = d->key; // no key yet, initiate new call
1890
1891 TQByteArray ba;
1892 TQDataStream ds(ba, IO_WriteOnly);
1893 ds << d->appId << remApp << remObjId << normalizeFunctionSignature(remFun) << data.size();
1894
1895 IceGetHeader(d->iceConn, d->majorOpcode, minor_opcode,
1896 sizeof(DCOPMsg), DCOPMsg, pMsg);
1897
1898 pMsg->key = d->currentKey;
1899 int datalen = ba.size() + data.size();
1900 pMsg->length += datalen;
1901
1902// tqWarning("DCOP: %s made call %s:%s:%s key = %d", d->appId.data(), remApp.data(), remObjId.data(), remFun.data(), pMsg->key);
1903
1904 IceSendData(d->iceConn, ba.size(), const_cast<char *>(ba.data()));
1905 IceSendData(d->iceConn, data.size(), const_cast<char *>(data.data()));
1906
1907 if (IceConnectionStatus(d->iceConn) != IceConnectAccepted)
1908 return false;
1909
1910 IceFlush (d->iceConn);
1911
1912 IceReplyWaitInfo waitInfo;
1913 waitInfo.sequence_of_request = IceLastSentSequenceNumber(d->iceConn);
1914 waitInfo.major_opcode_of_request = d->majorOpcode;
1915 waitInfo.minor_opcode_of_request = minor_opcode;
1916
1917 replyStruct->transactionId = -1;
1918 waitInfo.reply = static_cast<IcePointer>(replyStruct);
1919
1920 Bool readyRet = False;
1921 IceProcessMessagesStatus s;
1922
1923 timeval time_start;
1924 int time_left = -1;
1925 if( timeout >= 0 )
1926 {
1927 gettimeofday( &time_start, NULL );
1928 time_left = timeout;
1929 }
1930 for(;;) {
1931 bool checkMessages = true;
1932 if ( useEventLoop
1933 ? d->notifier != NULL // useEventLoop needs a socket notifier and a tqApp
1934 : timeout >= 0 ) { // !useEventLoop doesn't block only for timeout >= 0
1935 const int guiTimeout = 100;
1936 checkMessages = false;
1937
1938 int msecs = useEventLoop
1939 ? guiTimeout // timeout for the GUI refresh
1940 : time_left; // time remaining for the whole call
1941 fd_set fds;
1942 struct timeval tv;
1943 FD_ZERO( &fds );
1944 FD_SET( socket(), &fds );
1945 tv.tv_sec = msecs / 1000;
1946 tv.tv_usec = (msecs % 1000) * 1000;
1947 if ( select( socket() + 1, &fds, 0, 0, &tv ) <= 0 ) {
1948 if( useEventLoop && (timeout < 0 || time_left > guiTimeout)) {
1949 // nothing was available, we got a timeout. Reactivate
1950 // the GUI in blocked state.
1951 bool old_lock = d->non_blocking_call_lock;
1952 if ( !old_lock ) {
1953 d->non_blocking_call_lock = true;
1954 emit blockUserInput( true );
1955 }
1956 if( timeout >= 0 )
1957 d->eventLoopTimer.start(time_left - guiTimeout, true);
1958 tqApp->enter_loop();
1959 d->eventLoopTimer.stop();
1960 if ( !old_lock ) {
1961 d->non_blocking_call_lock = false;
1962 emit blockUserInput( false );
1963 }
1964 }
1965 }
1966 else
1967 {
1968 checkMessages = true;
1969 }
1970 }
1971 if (!d->iceConn)
1972 return false;
1973
1974 if( replyStruct->transactionId != -1 )
1975 {
1976 if (replyStruct->transactionId == 0)
1977 break; // Call complete
1978 if (!replyStruct->replySlot.isEmpty())
1979 break; // Async call
1980 }
1981
1982 if( checkMessages ) { // something is available
1983 s = IceProcessMessages(d->iceConn, &waitInfo,
1984 &readyRet);
1985 if (s == IceProcessMessagesIOError) {
1986 detach();
1987 d->currentKey = oldCurrentKey;
1988 return false;
1989 }
1990 }
1991
1992 if( replyStruct->transactionId != -1 )
1993 {
1994 if (replyStruct->transactionId == 0)
1995 break; // Call complete
1996 if (!replyStruct->replySlot.isEmpty())
1997 break; // Async call
1998 }
1999
2000 if( timeout < 0 )
2001 continue;
2002 timeval time_now;
2003 gettimeofday( &time_now, NULL );
2004 time_left = timeout -
2005 ((time_now.tv_sec - time_start.tv_sec) * 1000) -
2006 ((time_now.tv_usec - time_start.tv_usec) / 1000);
2007 if( time_left <= 0)
2008 {
2009 if (useEventLoop)
2010 {
2011 // Before we fail, check one more time if something is available
2012 time_left = 0;
2013 useEventLoop = false;
2014 continue;
2015 }
2016 *(replyStruct->replyType) = TQCString();
2017 *(replyStruct->replyData) = TQByteArray();
2018 replyStruct->status = ReplyStruct::Failed;
2019 break;
2020 }
2021 }
2022
2023 // Wake up parent call, maybe it's reply is available already.
2024 if ( d->non_blocking_call_lock ) {
2025 tqApp->exit_loop();
2026 }
2027
2028 d->currentKey = oldCurrentKey;
2029 return replyStruct->status != ReplyStruct::Failed;
2030}
2031
2032void DCOPClient::eventLoopTimeout()
2033{
2034 tqApp->exit_loop();
2035}
2036
2037void DCOPClient::processSocketData(int fd)
2038{
2039 // Make sure there is data to read!
2040 fd_set fds;
2041 timeval timeout;
2042 timeout.tv_sec = 0;
2043 timeout.tv_usec = 0;
2044 FD_ZERO(&fds);
2045 FD_SET(fd, &fds);
2046 int result = select(fd+1, &fds, 0, 0, &timeout);
2047 if (result == 0)
2048 return;
2049
2050 if ( d->non_blocking_call_lock ) {
2051 if( tqApp )
2052 tqApp->exit_loop();
2053 return;
2054 }
2055
2056 if (!d->iceConn) {
2057 if( d->notifier )
2058 d->notifier->deleteLater();
2059 d->notifier = 0;
2060 tqWarning("received an error processing data from the DCOP server!");
2061 return;
2062 }
2063
2064 IceProcessMessagesStatus s = IceProcessMessages(d->iceConn, 0, 0);
2065
2066 if (s == IceProcessMessagesIOError) {
2067 detach();
2068 tqWarning("received an error processing data from the DCOP server!");
2069 return;
2070 }
2071}
2072
2073void DCOPClient::setDefaultObject( const TQCString& objId )
2074{
2075 d->defaultObject = objId;
2076}
2077
2078
2079TQCString DCOPClient::defaultObject() const
2080{
2081 return d->defaultObject;
2082}
2083
2084bool
2085DCOPClient::isLocalTransactionFinished(TQ_INT32 id, TQCString &replyType, TQByteArray &replyData)
2086{
2087 DCOPClientPrivate::LocalTransactionResult *result = d->localTransActionList.take(id);
2088 if (!result)
2089 return false;
2090
2091 replyType = result->replyType;
2092 replyData = result->replyData;
2093 delete result;
2094
2095 return true;
2096}
2097
2098DCOPClientTransaction *
2099DCOPClient::beginTransaction()
2100{
2101 if (d->opcode == DCOPSend)
2102 return 0;
2103 if (!d->transactionList)
2104 d->transactionList = new TQPtrList<DCOPClientTransaction>;
2105
2106 d->transaction = true;
2107 DCOPClientTransaction *trans = new DCOPClientTransaction();
2108 trans->senderId = d->senderId;
2109 trans->id = ++d->transactionId;
2110 if (d->transactionId < 0) // Ensure that ids > 0
2111 d->transactionId = 0;
2112 trans->key = d->currentKey;
2113
2114 d->transactionList->append( trans );
2115
2116 return trans;
2117}
2118
2119TQ_INT32
2120DCOPClient::transactionId() const
2121{
2122 if (d->transaction)
2123 return d->transactionId;
2124 else
2125 return 0;
2126}
2127
2128void
2129DCOPClient::endTransaction( DCOPClientTransaction *trans, TQCString& replyType,
2130 TQByteArray &replyData)
2131{
2132 if ( !trans )
2133 return;
2134
2135 if ( !isAttached() )
2136 return;
2137
2138 if ( !d->transactionList) {
2139 tqWarning("Transaction unknown: No pending transactions!");
2140 return; // No pending transactions!
2141 }
2142
2143 if ( !d->transactionList->removeRef( trans ) ) {
2144 tqWarning("Transaction unknown: Not on list of pending transactions!");
2145 return; // Transaction
2146 }
2147
2148 if (trans->senderId.isEmpty())
2149 {
2150 // Local transaction
2151 DCOPClientPrivate::LocalTransactionResult *result = new DCOPClientPrivate::LocalTransactionResult();
2152 result->replyType = replyType;
2153 result->replyData = replyData;
2154
2155 d->localTransActionList.insert(trans->id, result);
2156
2157 delete trans;
2158
2159 return;
2160 }
2161
2162 DCOPMsg *pMsg;
2163
2164 TQByteArray ba;
2165 TQDataStream ds(ba, IO_WriteOnly);
2166 ds << d->appId << trans->senderId << trans->id << replyType << replyData;
2167
2168 IceGetHeader(d->iceConn, d->majorOpcode, DCOPReplyDelayed,
2169 sizeof(DCOPMsg), DCOPMsg, pMsg);
2170 pMsg->key = trans->key;
2171 pMsg->length += ba.size();
2172
2173 IceSendData( d->iceConn, ba.size(), const_cast<char *>(ba.data()) );
2174
2175 delete trans;
2176}
2177
2178void
2179DCOPClient::emitDCOPSignal( const TQCString &object, const TQCString &signal, const TQByteArray &data)
2180{
2181 // We hack the sending object name into the signal name
2182 send("DCOPServer", "emit", object+"#"+normalizeFunctionSignature(signal), data);
2183}
2184
2185void
2186DCOPClient::emitDCOPSignal( const TQCString &signal, const TQByteArray &data)
2187{
2188 emitDCOPSignal(0, signal, data);
2189}
2190
2191bool
2192DCOPClient::connectDCOPSignal( const TQCString &sender, const TQCString &senderObj,
2193 const TQCString &signal,
2194 const TQCString &receiverObj, const TQCString &slot, bool Volatile)
2195{
2196 TQCString replyType;
2197 TQByteArray data, replyData;
2198 TQ_INT8 iVolatile = Volatile ? 1 : 0;
2199
2200 TQDataStream args(data, IO_WriteOnly );
2201 args << sender << senderObj << normalizeFunctionSignature(signal) << receiverObj << normalizeFunctionSignature(slot) << iVolatile;
2202
2203 if (!call("DCOPServer", 0,
2204 "connectSignal(TQCString,TQCString,TQCString,TQCString,TQCString,bool)",
2205 data, replyType, replyData))
2206 {
2207 return false;
2208 }
2209
2210 if (replyType != "bool")
2211 return false;
2212
2213 TQDataStream reply(replyData, IO_ReadOnly );
2214 TQ_INT8 result;
2215 reply >> result;
2216 return (result != 0);
2217}
2218
2219bool
2220DCOPClient::connectDCOPSignal( const TQCString &sender, const TQCString &signal,
2221 const TQCString &receiverObj, const TQCString &slot, bool Volatile)
2222{
2223 return connectDCOPSignal( sender, 0, signal, receiverObj, slot, Volatile);
2224}
2225
2226bool
2227DCOPClient::disconnectDCOPSignal( const TQCString &sender, const TQCString &senderObj,
2228 const TQCString &signal,
2229 const TQCString &receiverObj, const TQCString &slot)
2230{
2231 TQCString replyType;
2232 TQByteArray data, replyData;
2233
2234 TQDataStream args(data, IO_WriteOnly );
2235 args << sender << senderObj << normalizeFunctionSignature(signal) << receiverObj << normalizeFunctionSignature(slot);
2236
2237 if (!call("DCOPServer", 0,
2238 "disconnectSignal(TQCString,TQCString,TQCString,TQCString,TQCString)",
2239 data, replyType, replyData))
2240 {
2241 return false;
2242 }
2243
2244 if (replyType != "bool")
2245 return false;
2246
2247 TQDataStream reply(replyData, IO_ReadOnly );
2248 TQ_INT8 result;
2249 reply >> result;
2250 return (result != 0);
2251}
2252
2253bool
2254DCOPClient::disconnectDCOPSignal( const TQCString &sender, const TQCString &signal,
2255 const TQCString &receiverObj, const TQCString &slot)
2256{
2257 return disconnectDCOPSignal( sender, 0, signal, receiverObj, slot);
2258}
2259
2260void
2261DCOPClient::setPriorityCall(bool b)
2262{
2263 if (b)
2264 {
2265 if (d->currentKey == 2)
2266 return;
2267 d->currentKeySaved = d->currentKey;
2268 d->currentKey = 2;
2269 }
2270 else
2271 {
2272 if (d->currentKey != 2)
2273 return;
2274 d->currentKey = d->currentKeySaved;
2275 if ( !d->messages.isEmpty() )
2276 d->postMessageTimer.start( 0, true ); // Process queued messages
2277 }
2278}
2279
2280
2281
2282void
2283DCOPClient::emergencyClose()
2284{
2285 TQPtrList<DCOPClient> list;
2286 client_map_t *map = DCOPClient_CliMap;
2287 if (!map) return;
2288 TQAsciiDictIterator<DCOPClient> it(*map);
2289 while(it.current()) {
2290 list.removeRef(it.current());
2291 list.append(it.current());
2292 ++it;
2293 }
2294 for(DCOPClient *cl = list.first(); cl; cl = list.next())
2295 {
2296 if (cl->d->iceConn) {
2297 IceProtocolShutdown(cl->d->iceConn, cl->d->majorOpcode);
2298 IceCloseConnection(cl->d->iceConn);
2299 cl->d->iceConn = 0L;
2300 }
2301 }
2302}
2303
2304const char *
2305DCOPClient::postMortemSender()
2306{
2307 if (!dcop_main_client)
2308 return "";
2309 if (dcop_main_client->d->senderId.isEmpty())
2310 return "";
2311 return dcop_main_client->d->senderId.data();
2312}
2313
2314const char *
2315DCOPClient::postMortemObject()
2316{
2317 if (!dcop_main_client)
2318 return "";
2319 return dcop_main_client->d->objId.data();
2320}
2321const char *
2322DCOPClient::postMortemFunction()
2323{
2324 if (!dcop_main_client)
2325 return "";
2326 return dcop_main_client->d->function.data();
2327}
2328
2329void DCOPClient::virtual_hook( int, void* )
2330{ /*BASE::virtual_hook( id, data );*/ }
2331
2332#include <dcopclient.moc>
2333
DCOPClient
Inter-process communication and remote procedure calls for KDE applications.
Definition: dcopclient.h:69
DCOPClient::setDaemonMode
void setDaemonMode(bool daemonMode)
Tells the dcopserver to treat the client as daemon client, not as regular client.
Definition: dcopclient.cpp:1348
DCOPClient::remoteFunctions
QCStringList remoteFunctions(const TQCString &remApp, const TQCString &remObj, bool *ok=0)
Retrieves the list of functions of the remote object remObj of application remApp.
Definition: dcopclient.cpp:1320
DCOPClient::endTransaction
void endTransaction(DCOPClientTransaction *t, TQCString &replyType, TQByteArray &replyData)
Sends the delayed reply of a function call.
Definition: dcopclient.cpp:2129
DCOPClient::appId
TQCString appId() const
Returns the current app id or a null string if the application hasn't yet been registered.
Definition: dcopclient.cpp:1036
DCOPClient::detach
bool detach()
Detaches from the DCOP server.
Definition: dcopclient.cpp:926
DCOPClient::setQtBridgeEnabled
void setQtBridgeEnabled(bool b)
Specify whether Qt objects of the application should be accessible via DCOP.
Definition: dcopclient.cpp:978
DCOPClient::beginTransaction
DCOPClientTransaction * beginTransaction()
Delays the reply of the current function call until endTransaction() is called.
Definition: dcopclient.cpp:2099
DCOPClient::isApplicationRegistered
bool isApplicationRegistered(const TQCString &remApp)
Checks whether remApp is registered with the DCOP server.
Definition: dcopclient.cpp:1262
DCOPClient::emitDCOPSignal
void emitDCOPSignal(const TQCString &object, const TQCString &signal, const TQByteArray &data)
Emits signal as DCOP signal from object object with data as arguments.
Definition: dcopclient.cpp:2179
DCOPClient::registeredApplications
QCStringList registeredApplications()
Retrieves the list of all currently registered applications from dcopserver.
Definition: dcopclient.cpp:1276
DCOPClient::disconnectDCOPSignal
bool disconnectDCOPSignal(const TQCString &sender, const TQCString &senderObj, const TQCString &signal, const TQCString &receiverObj, const TQCString &slot)
Disconnects a DCOP signal.
Definition: dcopclient.cpp:2227
DCOPClient::remoteInterfaces
QCStringList remoteInterfaces(const TQCString &remApp, const TQCString &remObj, bool *ok=0)
Retrieves the list of interfaces of the remote object remObj of application remApp.
Definition: dcopclient.cpp:1304
DCOPClient::transactionId
TQ_INT32 transactionId() const
Test whether the current function call is delayed.
Definition: dcopclient.cpp:2120
DCOPClient::dcopServerFileOld
static TQCString dcopServerFileOld(const TQCString &hostname=0) TDE_DEPRECATED
Definition: dcopclient.cpp:323
DCOPClient::attach
bool attach()
Attaches to the DCOP server.
Definition: dcopclient.cpp:679
DCOPClient::send
bool send(const TQCString &remApp, const TQCString &remObj, const TQCString &remFun, const TQByteArray &data)
Sends a data block to the server.
Definition: dcopclient.cpp:1089
DCOPClient::isRegistered
bool isRegistered() const
Returns whether or not the client is registered at the server.
Definition: dcopclient.cpp:1030
DCOPClient::resume
void resume()
Resumes the processing of DCOP events.
Definition: dcopclient.cpp:711
DCOPClient::isAttachedToForeignServer
bool isAttachedToForeignServer() const
Returns whether the client is attached to a server owned by another user.
Definition: dcopclient.cpp:957
DCOPClient::senderId
TQCString senderId() const
Returns the appId of the last application that talked to us.
Definition: dcopclient.cpp:1083
DCOPClient::findLocalClient
static DCOPClient * findLocalClient(const TQCString &_appId)
Look for the given client only in this process.
Definition: dcopclient.cpp:99
DCOPClient::qtBridgeEnabled
bool qtBridgeEnabled()
Returns whether the DCOP - Qt bridge is enabled.
Definition: dcopclient.cpp:973
DCOPClient::callAsync
int callAsync(const TQCString &remApp, const TQCString &remObj, const TQCString &remFun, const TQByteArray &data, TQObject *callBackObj, const char *callBackSlot)
Performs a asynchronous send with receive callback.
Definition: dcopclient.cpp:1830
DCOPClient::isAttached
bool isAttached() const
Returns whether or not the client is attached to the server.
Definition: dcopclient.cpp:949
DCOPClient::acceptCalls
bool acceptCalls() const
Returns whether the client handles incoming calls.
Definition: dcopclient.cpp:962
DCOPClient::call
bool call(const TQCString &remApp, const TQCString &remObj, const TQCString &remFun, const TQByteArray &data, TQCString &replyType, TQByteArray &replyData, bool useEventLoop, int timeout, bool forceRemote)
Performs a synchronous send and receive.
Definition: dcopclient.cpp:1786
DCOPClient::socket
int socket() const
Returns the socket fd that is used for communication with the server.
Definition: dcopclient.cpp:1042
DCOPClient::setNotifications
void setNotifications(bool enabled)
Enables / disables the applicationRegistered() / applicationRemoved() signals.
Definition: dcopclient.cpp:1336
DCOPClient::setMainClient
static void setMainClient(DCOPClient *mainClient)
Sets the application's main dcop client.
Definition: dcopclient.cpp:604
DCOPClient::blockUserInput
void blockUserInput(bool block)
Indicates that user input shall be blocked or released, depending on the argument.
DCOPClient::setServerAddress
static void setServerAddress(const TQCString &addr)
Sets the address of a server to use upon attaching.
Definition: dcopclient.cpp:671
DCOPClient::applicationRegistered
void applicationRegistered(const TQCString &appId)
Indicates that the application appId has been registered with the server we are attached to.
DCOPClient::mainClient
static DCOPClient * mainClient()
Returns the application's main dcop client.
Definition: dcopclient.cpp:599
DCOPClient::applicationRemoved
void applicationRemoved(const TQCString &appId)
Indicates that the formerly registered application appId has been removed.
DCOPClient::findObject
bool findObject(const TQCString &remApp, const TQCString &remObj, const TQCString &remFun, const TQByteArray &data, TQCString &foundApp, TQCString &foundObj, bool useEventLoop, int timeout)
Searches for an object which matches a criteria.
Definition: dcopclient.cpp:1160
DCOPClient::defaultObject
TQCString defaultObject() const
Returns the current default object or an empty string if no object is installed as default object.
Definition: dcopclient.cpp:2079
DCOPClient::DCOPClient
DCOPClient()
Constructs a new DCOP client, but does not attach to any server.
Definition: dcopclient.cpp:610
DCOPClient::attachFailed
void attachFailed(const TQString &msg)
Indicates that the process of establishing DCOP communications failed in some manner.
DCOPClient::remoteObjects
QCStringList remoteObjects(const TQCString &remApp, bool *ok=0)
Retrieves the list of objects of the remote application remApp.
Definition: dcopclient.cpp:1288
DCOPClient::process
virtual bool process(const TQCString &fun, const TQByteArray &data, TQCString &replyType, TQByteArray &replyData)
Reimplement this function to handle app-wide function calls unassociated w/an object.
Definition: dcopclient.cpp:1256
DCOPClient::connectDCOPSignal
bool connectDCOPSignal(const TQCString &sender, const TQCString &senderObj, const TQCString &signal, const TQCString &receiverObj, const TQCString &slot, bool Volatile)
Connects to a DCOP signal.
Definition: dcopclient.cpp:2192
DCOPClient::suspend
void suspend()
Temporarily suspends processing of DCOP events.
Definition: dcopclient.cpp:701
DCOPClient::~DCOPClient
virtual ~DCOPClient()
Cleans up any open connections and dynamic data.
Definition: dcopclient.cpp:635
DCOPClient::registerAs
TQCString registerAs(const TQCString &appId, bool addPID=true)
Registers at the DCOP server.
Definition: dcopclient.cpp:983
DCOPClient::processSocketData
void processSocketData(int socknum)
Process data from the socket.
Definition: dcopclient.cpp:2037
DCOPClient::isSuspended
bool isSuspended() const
Returns whether DCOP events are being processed.
Definition: dcopclient.cpp:721
DCOPClient::dcopServerFile
static TQCString dcopServerFile(const TQCString &hostname=0)
File with information how to reach the dcopserver.
Definition: dcopclient.cpp:316
DCOPClient::normalizeFunctionSignature
static TQCString normalizeFunctionSignature(const TQCString &fun)
Normalizes the function signature fun.
Definition: dcopclient.cpp:1055
DCOPClient::setAcceptCalls
void setAcceptCalls(bool b)
Specify whether the client should accept incoming calls.
Definition: dcopclient.cpp:967
DCOPClient::setDefaultObject
void setDefaultObject(const TQCString &objId)
Installs object objId as application-wide default object.
Definition: dcopclient.cpp:2073
DCOPClient::iceauthPath
static TQCString iceauthPath()
Return the path of iceauth or an empty string if not found.
Definition: dcopclient.cpp:214
DCOPObject
Provides an interface for receiving DCOP messages.
Definition: dcopobject.h:68
DCOPObject::match
static TQPtrList< DCOPObject > match(const TQCString &partialId)
Tries to find an object using a partial object id.
Definition: dcopobject.cpp:135
DCOPObject::hasObject
static bool hasObject(const TQCString &objId)
Checks whether an object with the given id is known in this process.
Definition: dcopobject.cpp:117
DCOPObject::objId
TQCString objId() const
Returns the object id of the DCOPObject.
Definition: dcopobject.cpp:112
DCOPObject::find
static DCOPObject * find(const TQCString &objId)
Try to find a dcop object with the given id.
Definition: dcopobject.cpp:125
DCOPObject::process
virtual bool process(const TQCString &fun, const TQByteArray &data, TQCString &replyType, TQByteArray &replyData)
Dispatches a message.
Definition: dcopobject.cpp:166
DCOPRef
A DCOPRef(erence) encapsulates a remote DCOP object as a triple <app,obj,type> where type is optional...
Definition: dcopref.h:279
DCOPRef::object
TQCString object() const
Definition: dcopref.cpp:150
DCOPRef::app
TQCString app() const
Name of the application in which the object resides.
Definition: dcopref.cpp:140
DCOPReply
Represents the return value of a DCOPRef:call() or DCOPRef:send() invocation.
Definition: dcopref.h:45
TDEStdAccel::key
int key(StdAccel id)
TDEStdAccel::name
TQString name(StdAccel id)

dcop

Skip menu "dcop"
  • Main Page
  • Modules
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

dcop

Skip menu "dcop"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for dcop by doxygen 1.9.4
This website is maintained by Timothy Pearson.