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

dcop

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

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
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for dcop by doxygen 1.8.8
This website is maintained by Timothy Pearson.