• 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 <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
74 extern "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 
83 extern TQMap<TQCString, DCOPObject *> * kde_dcopObjMap; // defined in dcopobject.cpp
84 
85 /*********************************************
86  * Keep track of local clients
87  *********************************************/
88 typedef TQAsciiDict<DCOPClient> client_map_t;
89 static client_map_t *DCOPClient_CliMap = 0;
90 
91 static
92 client_map_t *cliMap()
93 {
94  if (!DCOPClient_CliMap)
95  DCOPClient_CliMap = new client_map_t;
96  return DCOPClient_CliMap;
97 }
98 
99 DCOPClient *DCOPClient::findLocalClient( const TQCString &_appId )
100 {
101  return cliMap()->find(_appId.data());
102 }
103 
104 static
105 void registerLocalClient( const TQCString &_appId, DCOPClient *client )
106 {
107  cliMap()->replace(_appId.data(), client);
108 }
109 
110 static
111 void unregisterLocalClient( const TQCString &_appId )
112 {
113  client_map_t *map = cliMap();
114  map->remove(_appId.data());
115 }
117 
118 template class TQPtrList<DCOPObjectProxy>;
119 template class TQPtrList<DCOPClientTransaction>;
120 template class TQPtrList<_IceConn>;
121 
122 struct DCOPClientMessage
123 {
124  int opcode;
125  CARD32 key;
126  TQByteArray data;
127 };
128 
129 class DCOPClient::ReplyStruct
130 {
131 public:
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 
151 class DCOPClientPrivate
152 {
153 public:
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 
206 class DCOPClientTransaction
207 {
208 public:
209  TQ_INT32 id;
210  CARD32 key;
211  TQCString senderId;
212 };
213 
214 TQCString 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 
256 static 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
316 TQCString DCOPClient::dcopServerFile(const TQCString &hostname)
317 {
318  return ::dcopServerFile(hostname, false);
319 }
320 
321 
322 // static
323 TQCString DCOPClient::dcopServerFileOld(const TQCString &hostname)
324 {
325  return ::dcopServerFile(hostname, true);
326 }
327 
328 
329 const char* DCOPClientPrivate::serverAddr = 0;
330 
331 static void DCOPProcessInternal( DCOPClientPrivate *d, int opcode, CARD32 key, const TQByteArray& dataReceived, bool canPost );
332 
333 void 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 
349 static 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 
452 void 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 
474 void 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 
592 static IcePoVersionRec DCOPClientVersions[] = {
593  { DCOPVersionMajor, DCOPVersionMinor, DCOPProcessMessage }
594 };
595 
596 
597 static DCOPClient* dcop_main_client = 0;
598 
599 DCOPClient* DCOPClient::mainClient()
600 {
601  return dcop_main_client;
602 }
603 
604 void DCOPClient::setMainClient( DCOPClient* client )
605 {
606  dcop_main_client = client;
607 }
608 
609 
610 DCOPClient::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 
635 DCOPClient::~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 
671 void 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 
679 bool DCOPClient::attach()
680 {
681  if (!attachInternal( true ))
682  if (!attachInternal( true ))
683  return false; // Try two times!
684  return true;
685 }
686 
687 void 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 
701 void 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 
711 void 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 
721 bool 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.
733 static 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.
767 static 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 
792 bool 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 
926 bool 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 
949 bool DCOPClient::isAttached() const
950 {
951  if (!d->iceConn)
952  return false;
953 
954  return (IceConnectionStatus(d->iceConn) == IceConnectAccepted);
955 }
956 
957 bool DCOPClient::isAttachedToForeignServer() const
958 {
959  return isAttached() && d->foreign_server;
960 }
961 
962 bool DCOPClient::acceptCalls() const
963 {
964  return isAttached() && d->accept_calls;
965 }
966 
967 void DCOPClient::setAcceptCalls(bool b)
968 {
969  d->accept_calls = b;
970  d->accept_calls_override = true;
971 }
972 
973 bool DCOPClient::qtBridgeEnabled()
974 {
975  return d->qt_bridge_enabled;
976 }
977 
978 void DCOPClient::setQtBridgeEnabled(bool b)
979 {
980  d->qt_bridge_enabled = b;
981 }
982 
983 TQCString 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 
1030 bool DCOPClient::isRegistered() const
1031 {
1032  return d->registered;
1033 }
1034 
1035 
1036 TQCString DCOPClient::appId() const
1037 {
1038  return d->appId;
1039 }
1040 
1041 
1042 int DCOPClient::socket() const
1043 {
1044  if (d->iceConn)
1045  return IceConnectionNumber(d->iceConn);
1046  return 0;
1047 }
1048 
1049 static 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 
1055 TQCString 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 
1083 TQCString DCOPClient::senderId() const
1084 {
1085  return d->senderId;
1086 }
1087 
1088 
1089 bool 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 
1143 bool 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 
1152 bool 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 
1160 bool 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 
1256 bool DCOPClient::process(const TQCString &, const TQByteArray &,
1257  TQCString&, TQByteArray &)
1258 {
1259  return false;
1260 }
1261 
1262 bool 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 
1276 QCStringList 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 
1288 QCStringList 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 
1304 QCStringList 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 
1320 QCStringList 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 
1336 void 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 
1348 void 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  */
1367 static 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 
1393 namespace
1394 {
1395 struct 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 
1404 static 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 
1431 static 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 
1448 static 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 
1461 static 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 
1595 bool 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.
1697 static 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.
1711 static 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 
1723 bool 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 
1770 bool 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 
1778 bool 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 
1786 bool 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 
1821 void DCOPClient::asyncReplyReady()
1822 {
1823  while( d->asyncReplyQueue.count() )
1824  {
1825  ReplyStruct *replyStruct = d->asyncReplyQueue.take(0);
1826  handleAsyncReply(replyStruct);
1827  }
1828 }
1829 
1830 int 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 
1866 bool 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 
1877 bool 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 
2032 void DCOPClient::eventLoopTimeout()
2033 {
2034  tqApp->exit_loop();
2035 }
2036 
2037 void 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 
2073 void DCOPClient::setDefaultObject( const TQCString& objId )
2074 {
2075  d->defaultObject = objId;
2076 }
2077 
2078 
2079 TQCString DCOPClient::defaultObject() const
2080 {
2081  return d->defaultObject;
2082 }
2083 
2084 bool
2085 DCOPClient::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 
2098 DCOPClientTransaction *
2099 DCOPClient::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 
2119 TQ_INT32
2120 DCOPClient::transactionId() const
2121 {
2122  if (d->transaction)
2123  return d->transactionId;
2124  else
2125  return 0;
2126 }
2127 
2128 void
2129 DCOPClient::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 
2178 void
2179 DCOPClient::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 
2185 void
2186 DCOPClient::emitDCOPSignal( const TQCString &signal, const TQByteArray &data)
2187 {
2188  emitDCOPSignal(0, signal, data);
2189 }
2190 
2191 bool
2192 DCOPClient::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 
2219 bool
2220 DCOPClient::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 
2226 bool
2227 DCOPClient::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 
2253 bool
2254 DCOPClient::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 
2260 void
2261 DCOPClient::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 
2282 void
2283 DCOPClient::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 
2304 const char *
2305 DCOPClient::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 
2314 const char *
2315 DCOPClient::postMortemObject()
2316 {
2317  if (!dcop_main_client)
2318  return "";
2319  return dcop_main_client->d->objId.data();
2320 }
2321 const char *
2322 DCOPClient::postMortemFunction()
2323 {
2324  if (!dcop_main_client)
2325  return "";
2326  return dcop_main_client->d->function.data();
2327 }
2328 
2329 void 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.1
This website is maintained by Timothy Pearson.