• 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 
54 #ifndef QT_CLEAN_NAMESPACE
55 #define QT_CLEAN_NAMESPACE
56 #endif
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 <tqucomextra_p.h>
66 
67 #include <dcopglobal.h>
68 #include <dcopclient.h>
69 #include <dcopobject.h>
70 
71 #if defined Q_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(Q_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 Q_WS_X11
270  TQCString disp = getenv("DISPLAY");
271 #elif defined(Q_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, TQT_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, TQT_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, TQT_SIGNAL( timeout() ), this, TQT_SLOT( processPostedMessagesInternal() ) );
629  TQObject::connect( &d->eventLoopTimer, TQT_SIGNAL( timeout() ), this, TQT_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, TQT_SIGNAL(activated(int)),
697  TQT_SLOT(processSocketData(int)));
698  }
699 }
700 
701 void DCOPClient::suspend()
702 {
703 #ifdef Q_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 Q_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(Q_WS_WIN) || defined(Q_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)
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 #endif
752 }
753 #else
754 // Check whether the socket is owned by the same user.
755 static bool isServerSocketOwnedByUser(const char*server)
756 {
757 #ifdef Q_OS_WIN
758  if (strncmp(server, "tcp/", 4) != 0)
759  return false; // Not a local socket -> foreign.
760  else
761  return true;
762 #else
763  if (strncmp(server, "local/", 6) != 0)
764  return false; // Not a local socket -> foreign.
765  const char *path = strchr(server, KPATH_SEPARATOR);
766  if (!path)
767  return false;
768  path++;
769 
770  struct stat stat_buf;
771  if (stat(path, &stat_buf) != 0)
772  return false;
773 
774  return (stat_buf.st_uid == getuid());
775 #endif
776 }
777 #endif
778 
779 
780 bool DCOPClient::attachInternal( bool registerAsAnonymous )
781 {
782  char errBuf[1024];
783 
784  if ( isAttached() )
785  detach();
786 
787  if ((d->majorOpcode = IceRegisterForProtocolSetup(const_cast<char *>("DCOP"),
788  const_cast<char *>(DCOPVendorString),
789  const_cast<char *>(DCOPReleaseString),
790  1, DCOPClientVersions,
791  DCOPAuthCount,
792  const_cast<char **>(DCOPAuthNames),
793  DCOPClientAuthProcs, 0L)) < 0) {
794  emit attachFailed(TQString::fromLatin1( "Communications could not be established." ));
795  return false;
796  }
797 
798  bool bClearServerAddr = false;
799  // first, check if serverAddr was ever set.
800  if (!d->serverAddr) {
801  // here, we obtain the list of possible DCOP connections,
802  // and attach to them.
803  TQCString dcopSrv;
804  dcopSrv = ::getenv("DCOPSERVER");
805  if (dcopSrv.isEmpty()) {
806  TQCString fName = dcopServerFile();
807  TQFile f(TQFile::decodeName(fName));
808  if (!f.open(IO_ReadOnly)) {
809  emit attachFailed(TQString::fromLatin1( "Could not read network connection list.\n" )+TQFile::decodeName(fName));
810  return false;
811  }
812  int size = TQMIN( (qint64)1024, f.size() ); // protection against a huge file
813  TQCString contents( size+1 );
814  if ( f.readBlock( contents.data(), size ) != size )
815  {
816  tqDebug("Error reading from %s, didn't read the expected %d bytes", fName.data(), size);
817  // Should we abort ?
818  }
819  contents[size] = '\0';
820  int pos = contents.find('\n');
821  if ( pos == -1 ) // Shouldn't happen
822  {
823  tqDebug("Only one line in dcopserver file !: %s", contents.data());
824  dcopSrv = contents;
825  }
826  else
827  {
828  if(contents[pos - 1] == '\r') // check for windows end of line
829  pos--;
830  dcopSrv = contents.left( pos );
831 //#ifndef NDEBUG
832 // tqDebug("dcopserver address: %s", dcopSrv.data());
833 //#endif
834  }
835  }
836  d->serverAddr = tqstrdup( const_cast<char *>(dcopSrv.data()) );
837  bClearServerAddr = true;
838  }
839 
840  if ((d->iceConn = IceOpenConnection(const_cast<char*>(d->serverAddr),
841  static_cast<IcePointer>(this), False, d->majorOpcode,
842  sizeof(errBuf), errBuf)) == 0L) {
843  tqDebug("DCOPClient::attachInternal. Attach failed %s", errBuf);
844  d->iceConn = 0;
845  if (bClearServerAddr) {
846  delete [] d->serverAddr;
847  d->serverAddr = 0;
848  }
849  emit attachFailed(TQString::fromLatin1( errBuf ));
850  return false;
851  }
852  fcntl(socket(), F_SETFL, FD_CLOEXEC);
853 
854  IceSetShutdownNegotiation(d->iceConn, False);
855 
856  int setupstat;
857  char* vendor = 0;
858  char* release = 0;
859  setupstat = IceProtocolSetup(d->iceConn, d->majorOpcode,
860  static_cast<IcePointer>(d),
861  False, /* must authenticate */
862  &(d->majorVersion), &(d->minorVersion),
863  &(vendor), &(release), 1024, errBuf);
864  if (vendor) free(vendor);
865  if (release) free(release);
866 
867  if (setupstat == IceProtocolSetupFailure ||
868  setupstat == IceProtocolSetupIOError) {
869  IceCloseConnection(d->iceConn);
870  d->iceConn = 0;
871  if (bClearServerAddr) {
872  delete [] d->serverAddr;
873  d->serverAddr = 0;
874  }
875  emit attachFailed(TQString::fromLatin1( errBuf ));
876  return false;
877  } else if (setupstat == IceProtocolAlreadyActive) {
878  if (bClearServerAddr) {
879  delete [] d->serverAddr;
880  d->serverAddr = 0;
881  }
882  /* should not happen because 3rd arg to IceOpenConnection was 0. */
883  emit attachFailed(TQString::fromLatin1( "internal error in IceOpenConnection" ));
884  return false;
885  }
886 
887 
888  if (IceConnectionStatus(d->iceConn) != IceConnectAccepted) {
889  if (bClearServerAddr) {
890  delete [] d->serverAddr;
891  d->serverAddr = 0;
892  }
893  emit attachFailed(TQString::fromLatin1( "DCOP server did not accept the connection." ));
894  return false;
895  }
896 
897 #ifdef USE_PEER_IS_US
898  d->foreign_server = !peerIsUs(socket());
899 #else
900  d->foreign_server = !isServerSocketOwnedByUser(d->serverAddr);
901 #endif
902  if (!d->accept_calls_override)
903  d->accept_calls = !d->foreign_server;
904 
905  bindToApp();
906 
907  if ( registerAsAnonymous )
908  registerAs( "anonymous", true );
909 
910  return true;
911 }
912 
913 
914 bool DCOPClient::detach()
915 {
916  int status;
917 
918  if (d->iceConn) {
919  IceProtocolShutdown(d->iceConn, d->majorOpcode);
920  status = IceCloseConnection(d->iceConn);
921  if (status != IceClosedNow)
922  return false;
923  else
924  d->iceConn = 0L;
925  }
926 
927  if (d->registered)
928  unregisterLocalClient(d->appId);
929 
930  delete d->notifier;
931  d->notifier = 0L;
932  d->registered = false;
933  d->foreign_server = true;
934  return true;
935 }
936 
937 bool DCOPClient::isAttached() const
938 {
939  if (!d->iceConn)
940  return false;
941 
942  return (IceConnectionStatus(d->iceConn) == IceConnectAccepted);
943 }
944 
945 bool DCOPClient::isAttachedToForeignServer() const
946 {
947  return isAttached() && d->foreign_server;
948 }
949 
950 bool DCOPClient::acceptCalls() const
951 {
952  return isAttached() && d->accept_calls;
953 }
954 
955 void DCOPClient::setAcceptCalls(bool b)
956 {
957  d->accept_calls = b;
958  d->accept_calls_override = true;
959 }
960 
961 bool DCOPClient::qtBridgeEnabled()
962 {
963  return d->qt_bridge_enabled;
964 }
965 
966 void DCOPClient::setQtBridgeEnabled(bool b)
967 {
968  d->qt_bridge_enabled = b;
969 }
970 
971 TQCString DCOPClient::registerAs( const TQCString &appId, bool addPID )
972 {
973  TQCString result;
974 
975  TQCString _appId = appId;
976 
977  if (addPID) {
978  TQCString pid;
979  pid.sprintf("-%d", getpid());
980  _appId = _appId + pid;
981  }
982 
983  if( d->appId == _appId )
984  return d->appId;
985 
986 #if 0 // no need to detach, dcopserver can handle renaming
987  // Detach before reregistering.
988  if ( isRegistered() ) {
989  detach();
990  }
991 #endif
992 
993  if ( !isAttached() ) {
994  if (!attachInternal( false ))
995  if (!attachInternal( false ))
996  return result; // Try two times
997  }
998 
999  // register the application identifier with the server
1000  TQCString replyType;
1001  TQByteArray data, replyData;
1002  TQDataStream arg( data, IO_WriteOnly );
1003  arg << _appId;
1004  if ( call( "DCOPServer", "", "registerAs(TQCString)", data, replyType, replyData ) ) {
1005  TQDataStream reply( replyData, IO_ReadOnly );
1006  reply >> result;
1007  }
1008 
1009  d->appId = result;
1010  d->registered = !result.isNull();
1011 
1012  if (d->registered)
1013  registerLocalClient( d->appId, this );
1014 
1015  return result;
1016 }
1017 
1018 bool DCOPClient::isRegistered() const
1019 {
1020  return d->registered;
1021 }
1022 
1023 
1024 TQCString DCOPClient::appId() const
1025 {
1026  return d->appId;
1027 }
1028 
1029 
1030 int DCOPClient::socket() const
1031 {
1032  if (d->iceConn)
1033  return IceConnectionNumber(d->iceConn);
1034  return 0;
1035 }
1036 
1037 static inline bool isIdentChar( char x )
1038 { // Avoid bug in isalnum
1039  return x == '_' || (x >= '0' && x <= '9') ||
1040  (x >= 'a' && x <= 'z') || (x >= 'A' && x <= 'Z');
1041 }
1042 
1043 TQCString DCOPClient::normalizeFunctionSignature( const TQCString& fun ) {
1044  if ( fun.isEmpty() ) // nothing to do
1045  return fun.copy();
1046  TQCString result( fun.size() );
1047  char *from = const_cast<TQCString&>(fun).data();
1048  char *to = result.data();
1049  char *first = to;
1050  char last = 0;
1051  while ( true ) {
1052  while ( *from && isspace(*from) )
1053  from++;
1054  if ( last && isIdentChar( last ) && isIdentChar( *from ) )
1055  *to++ = 0x20;
1056  while ( *from && !isspace(*from) ) {
1057  last = *from++;
1058  *to++ = last;
1059  }
1060  if ( !*from )
1061  break;
1062  }
1063  if ( to > first && *(to-1) == 0x20 )
1064  to--;
1065  *to = '\0';
1066  result.resize( (int)((long)to - (long)result.data()) + 1 );
1067  return result;
1068 }
1069 
1070 
1071 TQCString DCOPClient::senderId() const
1072 {
1073  return d->senderId;
1074 }
1075 
1076 
1077 bool DCOPClient::send(const TQCString &remApp, const TQCString &remObjId,
1078  const TQCString &remFun, const TQByteArray &data)
1079 {
1080  if (remApp.isEmpty())
1081  return false;
1082  DCOPClient *localClient = findLocalClient( remApp );
1083 
1084  if ( localClient ) {
1085  bool saveTransaction = d->transaction;
1086  TQ_INT32 saveTransactionId = d->transactionId;
1087  TQCString saveSenderId = d->senderId;
1088 
1089  d->senderId = 0; // Local call
1090  TQCString replyType;
1091  TQByteArray replyData;
1092  (void) localClient->receive( remApp, remObjId, remFun, data, replyType, replyData );
1093 
1094  d->transaction = saveTransaction;
1095  d->transactionId = saveTransactionId;
1096  d->senderId = saveSenderId;
1097  // send() returns true if the data could be send to the DCOPServer,
1098  // regardles of receiving the data on the other application.
1099  // So we assume the data is successfully send to the (virtual) server
1100  // and return true in any case.
1101  return true;
1102  }
1103 
1104  if ( !isAttached() )
1105  return false;
1106 
1107 
1108  DCOPMsg *pMsg;
1109 
1110  TQByteArray ba;
1111  TQDataStream ds(ba, IO_WriteOnly);
1112  ds << d->appId << remApp << remObjId << normalizeFunctionSignature(remFun) << data.size();
1113 
1114  IceGetHeader(d->iceConn, d->majorOpcode, DCOPSend,
1115  sizeof(DCOPMsg), DCOPMsg, pMsg);
1116 
1117  pMsg->key = 1; // DCOPSend always uses the magic key 1
1118  int datalen = ba.size() + data.size();
1119  pMsg->length += datalen;
1120 
1121  IceSendData( d->iceConn, ba.size(), const_cast<char *>(ba.data()) );
1122  IceSendData( d->iceConn, data.size(), const_cast<char *>(data.data()) );
1123 
1124  //IceFlush(d->iceConn);
1125 
1126  if (IceConnectionStatus(d->iceConn) == IceConnectAccepted)
1127  return true;
1128  return false;
1129 }
1130 
1131 bool DCOPClient::send(const TQCString &remApp, const TQCString &remObjId,
1132  const TQCString &remFun, const TQString &data)
1133 {
1134  TQByteArray ba;
1135  TQDataStream ds(ba, IO_WriteOnly);
1136  ds << data;
1137  return send(remApp, remObjId, remFun, ba);
1138 }
1139 
1140 bool DCOPClient::findObject(const TQCString &remApp, const TQCString &remObj,
1141  const TQCString &remFun, const TQByteArray &data,
1142  TQCString &foundApp, TQCString &foundObj,
1143  bool useEventLoop)
1144 {
1145  return findObject( remApp, remObj, remFun, data, foundApp, foundObj, useEventLoop, -1 );
1146 }
1147 
1148 bool DCOPClient::findObject(const TQCString &remApp, const TQCString &remObj,
1149  const TQCString &remFun, const TQByteArray &data,
1150  TQCString &foundApp, TQCString &foundObj,
1151  bool useEventLoop, int timeout)
1152 {
1153  QCStringList appList;
1154  TQCString app = remApp;
1155  if (app.isEmpty())
1156  app = "*";
1157 
1158  foundApp = 0;
1159  foundObj = 0;
1160 
1161  if (app[app.length()-1] == '*')
1162  {
1163  // Find all apps that match 'app'.
1164  // NOTE: It would be more efficient to do the filtering in
1165  // the dcopserver itself.
1166  int len = app.length()-1;
1167  QCStringList apps=registeredApplications();
1168  for( QCStringList::ConstIterator it = apps.begin();
1169  it != apps.end();
1170  ++it)
1171  {
1172  if ( strncmp( (*it).data(), app.data(), len) == 0)
1173  appList.append(*it);
1174  }
1175  }
1176  else
1177  {
1178  appList.append(app);
1179  }
1180 
1181  // We do all the local clients in phase1 and the rest in phase2
1182  for(int phase=1; phase <= 2; phase++)
1183  {
1184  for( QCStringList::ConstIterator it = appList.begin();
1185  it != appList.end();
1186  ++it)
1187  {
1188  TQCString remApp = *it;
1189  TQCString replyType;
1190  TQByteArray replyData;
1191  bool result = false;
1192  DCOPClient *localClient = findLocalClient( remApp );
1193 
1194  if ( (phase == 1) && localClient ) {
1195  // In phase 1 we do all local clients
1196  bool saveTransaction = d->transaction;
1197  TQ_INT32 saveTransactionId = d->transactionId;
1198  TQCString saveSenderId = d->senderId;
1199 
1200  d->senderId = 0; // Local call
1201  result = localClient->find( remApp, remObj, remFun, data, replyType, replyData );
1202 
1203  TQ_INT32 id = localClient->transactionId();
1204  if (id) {
1205  // Call delayed. We have to wait till it has been processed.
1206  do {
1207  TQApplication::eventLoop()->processEvents( TQEventLoop::WaitForMore);
1208  } while( !localClient->isLocalTransactionFinished(id, replyType, replyData));
1209  result = true;
1210  }
1211  d->transaction = saveTransaction;
1212  d->transactionId = saveTransactionId;
1213  d->senderId = saveSenderId;
1214  }
1215  else if ((phase == 2) && !localClient)
1216  {
1217  // In phase 2 we do the other clients
1218  result = callInternal(remApp, remObj, remFun, data,
1219  replyType, replyData, useEventLoop, timeout, DCOPFind);
1220  }
1221 
1222  if (result)
1223  {
1224  if (replyType == "DCOPRef")
1225  {
1226  DCOPRef ref;
1227  TQDataStream reply( replyData, IO_ReadOnly );
1228  reply >> ref;
1229 
1230  if (ref.app() == remApp) // Consistency check
1231  {
1232  // replyType contains objId.
1233  foundApp = ref.app();
1234  foundObj = ref.object();
1235  return true;
1236  }
1237  }
1238  }
1239  }
1240  }
1241  return false;
1242 }
1243 
1244 bool DCOPClient::process(const TQCString &, const TQByteArray &,
1245  TQCString&, TQByteArray &)
1246 {
1247  return false;
1248 }
1249 
1250 bool DCOPClient::isApplicationRegistered( const TQCString& remApp)
1251 {
1252  TQCString replyType;
1253  TQByteArray data, replyData;
1254  TQDataStream arg( data, IO_WriteOnly );
1255  arg << remApp;
1256  int result = false;
1257  if ( call( "DCOPServer", "", "isApplicationRegistered(TQCString)", data, replyType, replyData ) ) {
1258  TQDataStream reply( replyData, IO_ReadOnly );
1259  reply >> result;
1260  }
1261  return result;
1262 }
1263 
1264 QCStringList DCOPClient::registeredApplications()
1265 {
1266  TQCString replyType;
1267  TQByteArray data, replyData;
1268  QCStringList result;
1269  if ( call( "DCOPServer", "", "registeredApplications()", data, replyType, replyData ) ) {
1270  TQDataStream reply( replyData, IO_ReadOnly );
1271  reply >> result;
1272  }
1273  return result;
1274 }
1275 
1276 QCStringList DCOPClient::remoteObjects( const TQCString& remApp, bool *ok )
1277 {
1278  TQCString replyType;
1279  TQByteArray data, replyData;
1280  QCStringList result;
1281  if ( ok )
1282  *ok = false;
1283  if ( call( remApp, "DCOPClient", "objects()", data, replyType, replyData ) ) {
1284  TQDataStream reply( replyData, IO_ReadOnly );
1285  reply >> result;
1286  if ( ok )
1287  *ok = true;
1288  }
1289  return result;
1290 }
1291 
1292 QCStringList DCOPClient::remoteInterfaces( const TQCString& remApp, const TQCString& remObj, bool *ok )
1293 {
1294  TQCString replyType;
1295  TQByteArray data, replyData;
1296  QCStringList result;
1297  if ( ok )
1298  *ok = false;
1299  if ( call( remApp, remObj, "interfaces()", data, replyType, replyData ) && replyType == "QCStringList") {
1300  TQDataStream reply( replyData, IO_ReadOnly );
1301  reply >> result;
1302  if ( ok )
1303  *ok = true;
1304  }
1305  return result;
1306 }
1307 
1308 QCStringList DCOPClient::remoteFunctions( const TQCString& remApp, const TQCString& remObj, bool *ok )
1309 {
1310  TQCString replyType;
1311  TQByteArray data, replyData;
1312  QCStringList result;
1313  if ( ok )
1314  *ok = false;
1315  if ( call( remApp, remObj, "functions()", data, replyType, replyData ) && replyType == "QCStringList") {
1316  TQDataStream reply( replyData, IO_ReadOnly );
1317  reply >> result;
1318  if ( ok )
1319  *ok = true;
1320  }
1321  return result;
1322 }
1323 
1324 void DCOPClient::setNotifications(bool enabled)
1325 {
1326  TQByteArray data;
1327  TQDataStream ds(data, IO_WriteOnly);
1328  ds << static_cast<TQ_INT8>(enabled);
1329 
1330  TQCString replyType;
1331  TQByteArray reply;
1332  if (!call("DCOPServer", "", "setNotifications( bool )", data, replyType, reply))
1333  tqWarning("I couldn't enable notifications at the dcopserver!");
1334 }
1335 
1336 void DCOPClient::setDaemonMode( bool daemonMode )
1337 {
1338  TQByteArray data;
1339  TQDataStream ds(data, IO_WriteOnly);
1340  ds << static_cast<TQ_INT8>( daemonMode );
1341 
1342  TQCString replyType;
1343  TQByteArray reply;
1344  if (!call("DCOPServer", "", "setDaemonMode(bool)", data, replyType, reply))
1345  tqWarning("I couldn't enable daemon mode at the dcopserver!");
1346 }
1347 
1348 
1349 
1350 /*
1351  DCOP <-> Qt bridge
1352 
1353  ********************************************************************************
1354  */
1355 static void fillQtObjects( QCStringList& l, TQObject* o, TQCString path )
1356 {
1357  if ( !path.isEmpty() )
1358  path += '/';
1359 
1360  int unnamed = 0;
1361  const TQObjectList list = o ? o->childrenListObject() : TQObject::objectTreesListObject();
1362  if ( !list.isEmpty() ) {
1363  TQObjectListIt it( list );
1364  TQObject *obj;
1365  while ( (obj=it.current()) ) {
1366  ++it;
1367  TQCString n = obj->name();
1368  if ( n == "unnamed" || n.isEmpty() )
1369  {
1370  n.sprintf("%p", (void *) obj);
1371  n = TQString(TQString("unnamed%1(%2, %3)").arg(++unnamed).arg(obj->className()).arg(TQString(n))).latin1();
1372  }
1373  TQCString fn = path + n;
1374  l.append( fn );
1375  if ( !obj->childrenListObject().isEmpty() )
1376  fillQtObjects( l, obj, fn );
1377  }
1378  }
1379 }
1380 
1381 namespace
1382 {
1383 struct O
1384 {
1385  O(): o(0) {}
1386  O ( const TQCString& str, TQObject* obj ):s(str), o(obj){}
1387  TQCString s;
1388  TQObject* o;
1389 };
1390 } // namespace
1391 
1392 static void fillQtObjectsEx( TQValueList<O>& l, TQObject* o, TQCString path )
1393 {
1394  if ( !path.isEmpty() )
1395  path += '/';
1396 
1397  int unnamed = 0;
1398  const TQObjectList list = o ? o->childrenListObject() : TQObject::objectTreesListObject();
1399  if ( !list.isEmpty() ) {
1400  TQObjectListIt it( list );
1401  TQObject *obj;
1402  while ( (obj=it.current()) ) {
1403  ++it;
1404  TQCString n = obj->name();
1405  if ( n == "unnamed" || n.isEmpty() )
1406  {
1407  n.sprintf("%p", (void *) obj);
1408  n = TQString(TQString("unnamed%1(%2, %3)").arg(++unnamed).arg(obj->className()).arg(TQString(n))).latin1();
1409  }
1410  TQCString fn = path + n;
1411  l.append( O( fn, obj ) );
1412  if ( !obj->childrenListObject().isEmpty() )
1413  fillQtObjectsEx( l, obj, fn );
1414  }
1415  }
1416 }
1417 
1418 
1419 static TQObject* findQtObject( TQCString id )
1420 {
1421  TQRegExp expr( id );
1422  TQValueList<O> l;
1423  fillQtObjectsEx( l, 0, "qt" );
1424  // Prefer an exact match, but fall-back on the first that contains the substring
1425  TQObject* firstContains = 0L;
1426  for ( TQValueList<O>::ConstIterator it = l.begin(); it != l.end(); ++it ) {
1427  if ( (*it).s == id ) // exact match
1428  return (*it).o;
1429  if ( !firstContains && (*it).s.contains( expr ) ) {
1430  firstContains = (*it).o;
1431  }
1432  }
1433  return firstContains;
1434 }
1435 
1436 static QCStringList findQtObjects( TQCString id )
1437 {
1438  TQRegExp expr( id );
1439  TQValueList<O> l;
1440  fillQtObjectsEx( l, 0, "qt" );
1441  QCStringList result;
1442  for ( TQValueList<O>::ConstIterator it = l.begin(); it != l.end(); ++it ) {
1443  if ( (*it).s.contains( expr ) )
1444  result << (*it).s;
1445  }
1446  return result;
1447 }
1448 
1449 static bool receiveQtObject( const TQCString &objId, const TQCString &fun, const TQByteArray &data,
1450  TQCString& replyType, TQByteArray &replyData)
1451 {
1452  if ( objId == "qt" ) {
1453  if ( fun == "interfaces()" ) {
1454  replyType = "QCStringList";
1455  TQDataStream reply( replyData, IO_WriteOnly );
1456  QCStringList l;
1457  l << "DCOPObject";
1458  l << "Qt";
1459  reply << l;
1460  return true;
1461  } else if ( fun == "functions()" ) {
1462  replyType = "QCStringList";
1463  TQDataStream reply( replyData, IO_WriteOnly );
1464  QCStringList l;
1465  l << "QCStringList functions()";
1466  l << "QCStringList interfaces()";
1467  l << "QCStringList objects()";
1468  l << "QCStringList find(TQCString)";
1469  reply << l;
1470  return true;
1471  } else if ( fun == "objects()" ) {
1472  replyType = "QCStringList";
1473  TQDataStream reply( replyData, IO_WriteOnly );
1474  QCStringList l;
1475  fillQtObjects( l, 0, "qt" );
1476  reply << l;
1477  return true;
1478  } else if ( fun == "find(TQCString)" ) {
1479  TQDataStream ds( data, IO_ReadOnly );
1480  TQCString id;
1481  ds >> id ;
1482  replyType = "QCStringList";
1483  TQDataStream reply( replyData, IO_WriteOnly );
1484  reply << findQtObjects( id ) ;
1485  return true;
1486  }
1487  } else if ( objId.left(3) == "qt/" ) {
1488  TQObject* o = findQtObject( objId );
1489  if ( !o )
1490  return false;
1491  if ( fun == "functions()" ) {
1492  replyType = "QCStringList";
1493  TQDataStream reply( replyData, IO_WriteOnly );
1494  QCStringList l;
1495  l << "QCStringList functions()";
1496  l << "QCStringList interfaces()";
1497  l << "QCStringList properties()";
1498  l << "bool setProperty(TQCString,TQVariant)";
1499  l << "TQVariant property(TQCString)";
1500  TQStrList lst = o->metaObject()->slotNames( true );
1501  int i = 0;
1502  for ( TQPtrListIterator<char> it( lst ); it.current(); ++it ) {
1503  if ( o->metaObject()->slot( i++, true )->tqt_mo_access != TQMetaData::Public )
1504  continue;
1505  TQCString slot = it.current();
1506  if ( slot.contains( "()" ) ) {
1507  slot.prepend("void ");
1508  l << slot;
1509  }
1510  }
1511  reply << l;
1512  return true;
1513  } else if ( fun == "interfaces()" ) {
1514  replyType = "QCStringList";
1515  TQDataStream reply( replyData, IO_WriteOnly );
1516  QCStringList l;
1517  TQMetaObject *meta = o->metaObject();
1518  while ( meta ) {
1519  l.prepend( meta->className() );
1520  meta = meta->superClass();
1521  }
1522  reply << l;
1523  return true;
1524  } else if ( fun == "properties()" ) {
1525  replyType = "QCStringList";
1526  TQDataStream reply( replyData, IO_WriteOnly );
1527  QCStringList l;
1528  TQStrList lst = o->metaObject()->propertyNames( true );
1529  for ( TQPtrListIterator<char> it( lst ); it.current(); ++it ) {
1530  TQMetaObject *mo = o->metaObject();
1531  const TQMetaProperty* p = mo->property( mo->findProperty( it.current(), true ), true );
1532  if ( !p )
1533  continue;
1534  TQCString prop = p->type();
1535  prop += ' ';
1536  prop += p->name();
1537  if ( !p->writable() )
1538  prop += " readonly";
1539  l << prop;
1540  }
1541  reply << l;
1542  return true;
1543  } else if ( fun == "property(TQCString)" ) {
1544  replyType = "TQVariant";
1545  TQDataStream ds( data, IO_ReadOnly );
1546  TQCString name;
1547  ds >> name ;
1548  TQVariant result = o->property( name );
1549  TQDataStream reply( replyData, IO_WriteOnly );
1550  reply << result;
1551  return true;
1552  } else if ( fun == "setProperty(TQCString,TQVariant)" ) {
1553  TQDataStream ds( data, IO_ReadOnly );
1554  TQCString name;
1555  TQVariant value;
1556  ds >> name >> value;
1557  replyType = "bool";
1558  TQDataStream reply( replyData, IO_WriteOnly );
1559  reply << (TQ_INT8) o->setProperty( name, value );
1560  return true;
1561  } else {
1562  int slot = o->metaObject()->findSlot( fun, true );
1563  if ( slot != -1 ) {
1564  replyType = "void";
1565  TQUObject uo[ 1 ];
1566  o->tqt_invoke( slot, uo );
1567  return true;
1568  }
1569  }
1570 
1571 
1572  }
1573  return false;
1574 }
1575 
1576 
1577 /*
1578  ********************************************************************************
1579  End of DCOP <-> Qt bridge
1580  */
1581 
1582 
1583 bool DCOPClient::receive(const TQCString &/*app*/, const TQCString &objId,
1584  const TQCString &fun, const TQByteArray &data,
1585  TQCString& replyType, TQByteArray &replyData)
1586 {
1587  d->transaction = false; // Assume no transaction.
1588  if ( objId == "DCOPClient" ) {
1589  if ( fun == "objects()" ) {
1590  replyType = "QCStringList";
1591  TQDataStream reply( replyData, IO_WriteOnly );
1592  QCStringList l;
1593  if (d->qt_bridge_enabled)
1594  {
1595  l << "qt"; // the Qt bridge object
1596  }
1597  if ( kde_dcopObjMap ) {
1598  TQMap<TQCString, DCOPObject *>::ConstIterator it( kde_dcopObjMap->begin());
1599  for (; it != kde_dcopObjMap->end(); ++it) {
1600  if ( !it.key().isEmpty() ) {
1601  if ( it.key() == d->defaultObject )
1602  l << "default";
1603  l << it.key();
1604  }
1605  }
1606  }
1607  reply << l;
1608  return true;
1609  }
1610  }
1611 
1612  if ( objId.isEmpty() || objId == "DCOPClient" ) {
1613  if ( fun == "applicationRegistered(TQCString)" ) {
1614  TQDataStream ds( data, IO_ReadOnly );
1615  TQCString r;
1616  ds >> r;
1617  emit applicationRegistered( r );
1618  return true;
1619  } else if ( fun == "applicationRemoved(TQCString)" ) {
1620  TQDataStream ds( data, IO_ReadOnly );
1621  TQCString r;
1622  ds >> r;
1623  emit applicationRemoved( r );
1624  return true;
1625  }
1626 
1627  if ( process( fun, data, replyType, replyData ) )
1628  return true;
1629  // fall through and send to defaultObject if available
1630 
1631  } else if (d->qt_bridge_enabled &&
1632  (objId == "qt" || objId.left(3) == "qt/") ) { // dcop <-> qt bridge
1633  return receiveQtObject( objId, fun, data, replyType, replyData );
1634  }
1635 
1636  if ( objId.isEmpty() || objId == "default" ) {
1637  if ( !d->defaultObject.isEmpty() && DCOPObject::hasObject( d->defaultObject ) ) {
1638  DCOPObject *objPtr = DCOPObject::find( d->defaultObject );
1639  objPtr->setCallingDcopClient(this);
1640  if (objPtr->process(fun, data, replyType, replyData))
1641  return true;
1642  }
1643 
1644  // fall through and send to object proxies
1645  }
1646 
1647 // if (!objId.isEmpty() && objId[objId.length()-1] == '*') {
1648  if (!objId.isEmpty() && ((objId.length()>0)?(objId[objId.length()-1] == '*'):0)) {
1649  // handle a multicast to several objects.
1650  // doesn't handle proxies currently. should it?
1651  TQPtrList<DCOPObject> matchList =
1652  DCOPObject::match(objId.left(objId.length()-1));
1653  for (DCOPObject *objPtr = matchList.first();
1654  objPtr != 0L; objPtr = matchList.next()) {
1655  objPtr->setCallingDcopClient(this);
1656  if (!objPtr->process(fun, data, replyType, replyData))
1657  return false;
1658  }
1659  return true;
1660  } else if (!DCOPObject::hasObject(objId)) {
1661  if ( DCOPObjectProxy::proxies ) {
1662  for ( TQPtrListIterator<DCOPObjectProxy> it( *DCOPObjectProxy::proxies ); it.current(); ++it ) {
1663  // TODO: it.current()->setCallingDcopClient(this);
1664  if ( it.current()->process( objId, fun, data, replyType, replyData ) )
1665  return true;
1666  }
1667  }
1668  return false;
1669 
1670  } else {
1671  DCOPObject *objPtr = DCOPObject::find(objId);
1672  objPtr->setCallingDcopClient(this);
1673  if (!objPtr->process(fun, data, replyType, replyData)) {
1674  // obj doesn't understand function or some other error.
1675  return false;
1676  }
1677  }
1678 
1679  return true;
1680 }
1681 
1682 // Check if the function result is a bool with the value "true"
1683 // If so set the function result to DCOPRef pointing to (app,objId) and
1684 // return true. Return false otherwise.
1685 static bool findResultOk(TQCString &replyType, TQByteArray &replyData)
1686 {
1687  TQ_INT8 success; // Tsk.. why is there no operator>>(bool)?
1688  if (replyType != "bool") return false;
1689 
1690  TQDataStream reply( replyData, IO_ReadOnly );
1691  reply >> success;
1692 
1693  if (!success) return false;
1694  return true;
1695 }
1696 
1697 // set the function result to DCOPRef pointing to (app,objId) and
1698 // return true.
1699 static bool findSuccess(const TQCString &app, const TQCString objId, TQCString &replyType, TQByteArray &replyData)
1700 {
1701  DCOPRef ref(app, objId);
1702  replyType = "DCOPRef";
1703 
1704  replyData = TQByteArray();
1705  TQDataStream final_reply( replyData, IO_WriteOnly );
1706  final_reply << ref;
1707  return true;
1708 }
1709 
1710 
1711 bool DCOPClient::find(const TQCString &app, const TQCString &objId,
1712  const TQCString &fun, const TQByteArray &data,
1713  TQCString& replyType, TQByteArray &replyData)
1714 {
1715  d->transaction = false; // Transactions are not allowed.
1716  if ( !app.isEmpty() && app != d->appId && app[app.length()-1] != '*') {
1717  tqWarning("WEIRD! we somehow received a DCOP message w/a different appId");
1718  return false;
1719  }
1720 
1721  if (objId.isEmpty() || objId[objId.length()-1] != '*')
1722  {
1723  if (fun.isEmpty())
1724  {
1725  if (objId.isEmpty() || DCOPObject::hasObject(objId))
1726  return findSuccess(app, objId, replyType, replyData);
1727  return false;
1728  }
1729  // Message to application or single object...
1730  if (receive(app, objId, fun, data, replyType, replyData))
1731  {
1732  if (findResultOk(replyType, replyData))
1733  return findSuccess(app, objId, replyType, replyData);
1734  }
1735  }
1736  else {
1737  // handle a multicast to several objects.
1738  // doesn't handle proxies currently. should it?
1739  TQPtrList<DCOPObject> matchList =
1740  DCOPObject::match(objId.left(objId.length()-1));
1741  for (DCOPObject *objPtr = matchList.first();
1742  objPtr != 0L; objPtr = matchList.next())
1743  {
1744  replyType = 0;
1745  replyData = TQByteArray();
1746  if (fun.isEmpty())
1747  return findSuccess(app, objPtr->objId(), replyType, replyData);
1748  objPtr->setCallingDcopClient(this);
1749  if (objPtr->process(fun, data, replyType, replyData))
1750  if (findResultOk(replyType, replyData))
1751  return findSuccess(app, objPtr->objId(), replyType, replyData);
1752  }
1753  }
1754  return false;
1755 }
1756 
1757 
1758 bool DCOPClient::call(const TQCString &remApp, const TQCString &remObjId,
1759  const TQCString &remFun, const TQByteArray &data,
1760  TQCString& replyType, TQByteArray &replyData,
1761  bool useEventLoop)
1762 {
1763  return call( remApp, remObjId, remFun, data, replyType, replyData, useEventLoop, -1, false );
1764 }
1765 
1766 bool DCOPClient::call(const TQCString &remApp, const TQCString &remObjId,
1767  const TQCString &remFun, const TQByteArray &data,
1768  TQCString& replyType, TQByteArray &replyData,
1769  bool useEventLoop, int timeout)
1770 {
1771  return call( remApp, remObjId, remFun, data, replyType, replyData, useEventLoop, timeout, false );
1772 }
1773 
1774 bool DCOPClient::call(const TQCString &remApp, const TQCString &remObjId,
1775  const TQCString &remFun, const TQByteArray &data,
1776  TQCString& replyType, TQByteArray &replyData,
1777  bool useEventLoop, int timeout, bool forceRemote)
1778 {
1779  if (remApp.isEmpty())
1780  return false;
1781  DCOPClient *localClient = findLocalClient( remApp );
1782 
1783  if ( localClient && !forceRemote ) {
1784  bool saveTransaction = d->transaction;
1785  TQ_INT32 saveTransactionId = d->transactionId;
1786  TQCString saveSenderId = d->senderId;
1787 
1788  d->senderId = 0; // Local call
1789  bool b = localClient->receive( remApp, remObjId, remFun, data, replyType, replyData );
1790 
1791  TQ_INT32 id = localClient->transactionId();
1792  if (id) {
1793  // Call delayed. We have to wait till it has been processed.
1794  do {
1795  TQApplication::eventLoop()->processEvents(TQEventLoop::WaitForMore);
1796  } while( !localClient->isLocalTransactionFinished(id, replyType, replyData));
1797  b = true;
1798  }
1799  d->transaction = saveTransaction;
1800  d->transactionId = saveTransactionId;
1801  d->senderId = saveSenderId;
1802  return b;
1803  }
1804 
1805  return callInternal(remApp, remObjId, remFun, data,
1806  replyType, replyData, useEventLoop, timeout, DCOPCall);
1807 }
1808 
1809 void DCOPClient::asyncReplyReady()
1810 {
1811  while( d->asyncReplyQueue.count() )
1812  {
1813  ReplyStruct *replyStruct = d->asyncReplyQueue.take(0);
1814  handleAsyncReply(replyStruct);
1815  }
1816 }
1817 
1818 int DCOPClient::callAsync(const TQCString &remApp, const TQCString &remObjId,
1819  const TQCString &remFun, const TQByteArray &data,
1820  TQObject *callBackObj, const char *callBackSlot)
1821 {
1822  TQCString replyType;
1823  TQByteArray replyData;
1824 
1825  ReplyStruct *replyStruct = new ReplyStruct;
1826  replyStruct->replyType = new TQCString;
1827  replyStruct->replyData = new TQByteArray;
1828  replyStruct->replyObject = callBackObj;
1829  replyStruct->replySlot = callBackSlot;
1830  replyStruct->replyId = ++d->transactionId;
1831  if (d->transactionId < 0) // Ensure that ids > 0
1832  d->transactionId = 0;
1833 
1834  bool b = callInternal(remApp, remObjId, remFun, data,
1835  replyStruct, false, -1, DCOPCall);
1836  if (!b)
1837  {
1838  delete replyStruct->replyType;
1839  delete replyStruct->replyData;
1840  delete replyStruct;
1841  return 0;
1842  }
1843 
1844  if (replyStruct->transactionId == 0)
1845  {
1846  // Call is finished already
1847  TQTimer::singleShot(0, this, TQT_SLOT(asyncReplyReady()));
1848  d->asyncReplyQueue.append(replyStruct);
1849  }
1850 
1851  return replyStruct->replyId;
1852 }
1853 
1854 bool DCOPClient::callInternal(const TQCString &remApp, const TQCString &remObjId,
1855  const TQCString &remFun, const TQByteArray &data,
1856  TQCString& replyType, TQByteArray &replyData,
1857  bool useEventLoop, int timeout, int minor_opcode)
1858 {
1859  ReplyStruct replyStruct;
1860  replyStruct.replyType = &replyType;
1861  replyStruct.replyData = &replyData;
1862  return callInternal(remApp, remObjId, remFun, data, &replyStruct, useEventLoop, timeout, minor_opcode);
1863 }
1864 
1865 bool DCOPClient::callInternal(const TQCString &remApp, const TQCString &remObjId,
1866  const TQCString &remFun, const TQByteArray &data,
1867  ReplyStruct *replyStruct,
1868  bool useEventLoop, int timeout, int minor_opcode)
1869 {
1870  if ( !isAttached() )
1871  return false;
1872 
1873  DCOPMsg *pMsg;
1874 
1875  CARD32 oldCurrentKey = d->currentKey;
1876  if ( !d->currentKey )
1877  d->currentKey = d->key; // no key yet, initiate new call
1878 
1879  TQByteArray ba;
1880  TQDataStream ds(ba, IO_WriteOnly);
1881  ds << d->appId << remApp << remObjId << normalizeFunctionSignature(remFun) << data.size();
1882 
1883  IceGetHeader(d->iceConn, d->majorOpcode, minor_opcode,
1884  sizeof(DCOPMsg), DCOPMsg, pMsg);
1885 
1886  pMsg->key = d->currentKey;
1887  int datalen = ba.size() + data.size();
1888  pMsg->length += datalen;
1889 
1890 // tqWarning("DCOP: %s made call %s:%s:%s key = %d", d->appId.data(), remApp.data(), remObjId.data(), remFun.data(), pMsg->key);
1891 
1892  IceSendData(d->iceConn, ba.size(), const_cast<char *>(ba.data()));
1893  IceSendData(d->iceConn, data.size(), const_cast<char *>(data.data()));
1894 
1895  if (IceConnectionStatus(d->iceConn) != IceConnectAccepted)
1896  return false;
1897 
1898  IceFlush (d->iceConn);
1899 
1900  IceReplyWaitInfo waitInfo;
1901  waitInfo.sequence_of_request = IceLastSentSequenceNumber(d->iceConn);
1902  waitInfo.major_opcode_of_request = d->majorOpcode;
1903  waitInfo.minor_opcode_of_request = minor_opcode;
1904 
1905  replyStruct->transactionId = -1;
1906  waitInfo.reply = static_cast<IcePointer>(replyStruct);
1907 
1908  Bool readyRet = False;
1909  IceProcessMessagesStatus s;
1910 
1911  timeval time_start;
1912  int time_left = -1;
1913  if( timeout >= 0 )
1914  {
1915  gettimeofday( &time_start, NULL );
1916  time_left = timeout;
1917  }
1918  for(;;) {
1919  bool checkMessages = true;
1920  if ( useEventLoop
1921  ? d->notifier != NULL // useEventLoop needs a socket notifier and a tqApp
1922  : timeout >= 0 ) { // !useEventLoop doesn't block only for timeout >= 0
1923  const int guiTimeout = 100;
1924  checkMessages = false;
1925 
1926  int msecs = useEventLoop
1927  ? guiTimeout // timeout for the GUI refresh
1928  : time_left; // time remaining for the whole call
1929  fd_set fds;
1930  struct timeval tv;
1931  FD_ZERO( &fds );
1932  FD_SET( socket(), &fds );
1933  tv.tv_sec = msecs / 1000;
1934  tv.tv_usec = (msecs % 1000) * 1000;
1935  if ( select( socket() + 1, &fds, 0, 0, &tv ) <= 0 ) {
1936  if( useEventLoop && (timeout < 0 || time_left > guiTimeout)) {
1937  // nothing was available, we got a timeout. Reactivate
1938  // the GUI in blocked state.
1939  bool old_lock = d->non_blocking_call_lock;
1940  if ( !old_lock ) {
1941  d->non_blocking_call_lock = true;
1942  emit blockUserInput( true );
1943  }
1944  if( timeout >= 0 )
1945  d->eventLoopTimer.start(time_left - guiTimeout, true);
1946  tqApp->enter_loop();
1947  d->eventLoopTimer.stop();
1948  if ( !old_lock ) {
1949  d->non_blocking_call_lock = false;
1950  emit blockUserInput( false );
1951  }
1952  }
1953  }
1954  else
1955  {
1956  checkMessages = true;
1957  }
1958  }
1959  if (!d->iceConn)
1960  return false;
1961 
1962  if( replyStruct->transactionId != -1 )
1963  {
1964  if (replyStruct->transactionId == 0)
1965  break; // Call complete
1966  if (!replyStruct->replySlot.isEmpty())
1967  break; // Async call
1968  }
1969 
1970  if( checkMessages ) { // something is available
1971  s = IceProcessMessages(d->iceConn, &waitInfo,
1972  &readyRet);
1973  if (s == IceProcessMessagesIOError) {
1974  detach();
1975  d->currentKey = oldCurrentKey;
1976  return false;
1977  }
1978  }
1979 
1980  if( replyStruct->transactionId != -1 )
1981  {
1982  if (replyStruct->transactionId == 0)
1983  break; // Call complete
1984  if (!replyStruct->replySlot.isEmpty())
1985  break; // Async call
1986  }
1987 
1988  if( timeout < 0 )
1989  continue;
1990  timeval time_now;
1991  gettimeofday( &time_now, NULL );
1992  time_left = timeout -
1993  ((time_now.tv_sec - time_start.tv_sec) * 1000) -
1994  ((time_now.tv_usec - time_start.tv_usec) / 1000);
1995  if( time_left <= 0)
1996  {
1997  if (useEventLoop)
1998  {
1999  // Before we fail, check one more time if something is available
2000  time_left = 0;
2001  useEventLoop = false;
2002  continue;
2003  }
2004  *(replyStruct->replyType) = TQCString();
2005  *(replyStruct->replyData) = TQByteArray();
2006  replyStruct->status = ReplyStruct::Failed;
2007  break;
2008  }
2009  }
2010 
2011  // Wake up parent call, maybe it's reply is available already.
2012  if ( d->non_blocking_call_lock ) {
2013  tqApp->exit_loop();
2014  }
2015 
2016  d->currentKey = oldCurrentKey;
2017  return replyStruct->status != ReplyStruct::Failed;
2018 }
2019 
2020 void DCOPClient::eventLoopTimeout()
2021 {
2022  tqApp->exit_loop();
2023 }
2024 
2025 void DCOPClient::processSocketData(int fd)
2026 {
2027  // Make sure there is data to read!
2028  fd_set fds;
2029  timeval timeout;
2030  timeout.tv_sec = 0;
2031  timeout.tv_usec = 0;
2032  FD_ZERO(&fds);
2033  FD_SET(fd, &fds);
2034  int result = select(fd+1, &fds, 0, 0, &timeout);
2035  if (result == 0)
2036  return;
2037 
2038  if ( d->non_blocking_call_lock ) {
2039  if( tqApp )
2040  tqApp->exit_loop();
2041  return;
2042  }
2043 
2044  if (!d->iceConn) {
2045  if( d->notifier )
2046  d->notifier->deleteLater();
2047  d->notifier = 0;
2048  tqWarning("received an error processing data from the DCOP server!");
2049  return;
2050  }
2051 
2052  IceProcessMessagesStatus s = IceProcessMessages(d->iceConn, 0, 0);
2053 
2054  if (s == IceProcessMessagesIOError) {
2055  detach();
2056  tqWarning("received an error processing data from the DCOP server!");
2057  return;
2058  }
2059 }
2060 
2061 void DCOPClient::setDefaultObject( const TQCString& objId )
2062 {
2063  d->defaultObject = objId;
2064 }
2065 
2066 
2067 TQCString DCOPClient::defaultObject() const
2068 {
2069  return d->defaultObject;
2070 }
2071 
2072 bool
2073 DCOPClient::isLocalTransactionFinished(TQ_INT32 id, TQCString &replyType, TQByteArray &replyData)
2074 {
2075  DCOPClientPrivate::LocalTransactionResult *result = d->localTransActionList.take(id);
2076  if (!result)
2077  return false;
2078 
2079  replyType = result->replyType;
2080  replyData = result->replyData;
2081  delete result;
2082 
2083  return true;
2084 }
2085 
2086 DCOPClientTransaction *
2087 DCOPClient::beginTransaction()
2088 {
2089  if (d->opcode == DCOPSend)
2090  return 0;
2091  if (!d->transactionList)
2092  d->transactionList = new TQPtrList<DCOPClientTransaction>;
2093 
2094  d->transaction = true;
2095  DCOPClientTransaction *trans = new DCOPClientTransaction();
2096  trans->senderId = d->senderId;
2097  trans->id = ++d->transactionId;
2098  if (d->transactionId < 0) // Ensure that ids > 0
2099  d->transactionId = 0;
2100  trans->key = d->currentKey;
2101 
2102  d->transactionList->append( trans );
2103 
2104  return trans;
2105 }
2106 
2107 TQ_INT32
2108 DCOPClient::transactionId() const
2109 {
2110  if (d->transaction)
2111  return d->transactionId;
2112  else
2113  return 0;
2114 }
2115 
2116 void
2117 DCOPClient::endTransaction( DCOPClientTransaction *trans, TQCString& replyType,
2118  TQByteArray &replyData)
2119 {
2120  if ( !trans )
2121  return;
2122 
2123  if ( !isAttached() )
2124  return;
2125 
2126  if ( !d->transactionList) {
2127  tqWarning("Transaction unknown: No pending transactions!");
2128  return; // No pending transactions!
2129  }
2130 
2131  if ( !d->transactionList->removeRef( trans ) ) {
2132  tqWarning("Transaction unknown: Not on list of pending transactions!");
2133  return; // Transaction
2134  }
2135 
2136  if (trans->senderId.isEmpty())
2137  {
2138  // Local transaction
2139  DCOPClientPrivate::LocalTransactionResult *result = new DCOPClientPrivate::LocalTransactionResult();
2140  result->replyType = replyType;
2141  result->replyData = replyData;
2142 
2143  d->localTransActionList.insert(trans->id, result);
2144 
2145  delete trans;
2146 
2147  return;
2148  }
2149 
2150  DCOPMsg *pMsg;
2151 
2152  TQByteArray ba;
2153  TQDataStream ds(ba, IO_WriteOnly);
2154  ds << d->appId << trans->senderId << trans->id << replyType << replyData;
2155 
2156  IceGetHeader(d->iceConn, d->majorOpcode, DCOPReplyDelayed,
2157  sizeof(DCOPMsg), DCOPMsg, pMsg);
2158  pMsg->key = trans->key;
2159  pMsg->length += ba.size();
2160 
2161  IceSendData( d->iceConn, ba.size(), const_cast<char *>(ba.data()) );
2162 
2163  delete trans;
2164 }
2165 
2166 void
2167 DCOPClient::emitDCOPSignal( const TQCString &object, const TQCString &signal, const TQByteArray &data)
2168 {
2169  // We hack the sending object name into the signal name
2170  send("DCOPServer", "emit", object+"#"+normalizeFunctionSignature(signal), data);
2171 }
2172 
2173 void
2174 DCOPClient::emitDCOPSignal( const TQCString &signal, const TQByteArray &data)
2175 {
2176  emitDCOPSignal(0, signal, data);
2177 }
2178 
2179 bool
2180 DCOPClient::connectDCOPSignal( const TQCString &sender, const TQCString &senderObj,
2181  const TQCString &signal,
2182  const TQCString &receiverObj, const TQCString &slot, bool Volatile)
2183 {
2184  TQCString replyType;
2185  TQByteArray data, replyData;
2186  TQ_INT8 iVolatile = Volatile ? 1 : 0;
2187 
2188  TQDataStream args(data, IO_WriteOnly );
2189  args << sender << senderObj << normalizeFunctionSignature(signal) << receiverObj << normalizeFunctionSignature(slot) << iVolatile;
2190 
2191  if (!call("DCOPServer", 0,
2192  "connectSignal(TQCString,TQCString,TQCString,TQCString,TQCString,bool)",
2193  data, replyType, replyData))
2194  {
2195  return false;
2196  }
2197 
2198  if (replyType != "bool")
2199  return false;
2200 
2201  TQDataStream reply(replyData, IO_ReadOnly );
2202  TQ_INT8 result;
2203  reply >> result;
2204  return (result != 0);
2205 }
2206 
2207 bool
2208 DCOPClient::connectDCOPSignal( const TQCString &sender, const TQCString &signal,
2209  const TQCString &receiverObj, const TQCString &slot, bool Volatile)
2210 {
2211  return connectDCOPSignal( sender, 0, signal, receiverObj, slot, Volatile);
2212 }
2213 
2214 bool
2215 DCOPClient::disconnectDCOPSignal( const TQCString &sender, const TQCString &senderObj,
2216  const TQCString &signal,
2217  const TQCString &receiverObj, const TQCString &slot)
2218 {
2219  TQCString replyType;
2220  TQByteArray data, replyData;
2221 
2222  TQDataStream args(data, IO_WriteOnly );
2223  args << sender << senderObj << normalizeFunctionSignature(signal) << receiverObj << normalizeFunctionSignature(slot);
2224 
2225  if (!call("DCOPServer", 0,
2226  "disconnectSignal(TQCString,TQCString,TQCString,TQCString,TQCString)",
2227  data, replyType, replyData))
2228  {
2229  return false;
2230  }
2231 
2232  if (replyType != "bool")
2233  return false;
2234 
2235  TQDataStream reply(replyData, IO_ReadOnly );
2236  TQ_INT8 result;
2237  reply >> result;
2238  return (result != 0);
2239 }
2240 
2241 bool
2242 DCOPClient::disconnectDCOPSignal( const TQCString &sender, const TQCString &signal,
2243  const TQCString &receiverObj, const TQCString &slot)
2244 {
2245  return disconnectDCOPSignal( sender, 0, signal, receiverObj, slot);
2246 }
2247 
2248 void
2249 DCOPClient::setPriorityCall(bool b)
2250 {
2251  if (b)
2252  {
2253  if (d->currentKey == 2)
2254  return;
2255  d->currentKeySaved = d->currentKey;
2256  d->currentKey = 2;
2257  }
2258  else
2259  {
2260  if (d->currentKey != 2)
2261  return;
2262  d->currentKey = d->currentKeySaved;
2263  if ( !d->messages.isEmpty() )
2264  d->postMessageTimer.start( 0, true ); // Process queued messages
2265  }
2266 }
2267 
2268 
2269 
2270 void
2271 DCOPClient::emergencyClose()
2272 {
2273  TQPtrList<DCOPClient> list;
2274  client_map_t *map = DCOPClient_CliMap;
2275  if (!map) return;
2276  TQAsciiDictIterator<DCOPClient> it(*map);
2277  while(it.current()) {
2278  list.removeRef(it.current());
2279  list.append(it.current());
2280  ++it;
2281  }
2282  for(DCOPClient *cl = list.first(); cl; cl = list.next())
2283  {
2284  if (cl->d->iceConn) {
2285  IceProtocolShutdown(cl->d->iceConn, cl->d->majorOpcode);
2286  IceCloseConnection(cl->d->iceConn);
2287  cl->d->iceConn = 0L;
2288  }
2289  }
2290 }
2291 
2292 const char *
2293 DCOPClient::postMortemSender()
2294 {
2295  if (!dcop_main_client)
2296  return "";
2297  if (dcop_main_client->d->senderId.isEmpty())
2298  return "";
2299  return dcop_main_client->d->senderId.data();
2300 }
2301 
2302 const char *
2303 DCOPClient::postMortemObject()
2304 {
2305  if (!dcop_main_client)
2306  return "";
2307  return dcop_main_client->d->objId.data();
2308 }
2309 const char *
2310 DCOPClient::postMortemFunction()
2311 {
2312  if (!dcop_main_client)
2313  return "";
2314  return dcop_main_client->d->function.data();
2315 }
2316 
2317 void DCOPClient::virtual_hook( int, void* )
2318 { /*BASE::virtual_hook( id, data );*/ }
2319 
2320 #include <dcopclient.moc>
2321 
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:214
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::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:2180
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:1250
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:950
DCOPClient::mainClient
static DCOPClient * mainClient()
Returns the application's main dcop client.
Definition: dcopclient.cpp:599
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:2061
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:1818
DCOPClient::attach
bool attach()
Attaches to the DCOP server.
Definition: dcopclient.cpp:679
DCOPClient::setAcceptCalls
void setAcceptCalls(bool b)
Specify whether the client should accept incoming calls.
Definition: dcopclient.cpp:955
DCOPClient::DCOPClient
DCOPClient()
Constructs a new DCOP client, but does not attach to any server.
Definition: dcopclient.cpp:610
DCOPClient::endTransaction
void endTransaction(DCOPClientTransaction *t, TQCString &replyType, TQByteArray &replyData)
Sends the delayed reply of a function call.
Definition: dcopclient.cpp:2117
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:1077
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:966
DCOPClient::~DCOPClient
virtual ~DCOPClient()
Cleans up any open connections and dynamic data.
Definition: dcopclient.cpp:635
DCOPClient::qtBridgeEnabled
bool qtBridgeEnabled()
Returns whether the DCOP - Qt bridge is enabled.
Definition: dcopclient.cpp:961
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:2215
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:2087
DCOPClient::isRegistered
bool isRegistered() const
Returns whether or not the client is registered at the server.
Definition: dcopclient.cpp:1018
DCOPClient::processSocketData
void processSocketData(int socknum)
Process data from the socket.
Definition: dcopclient.cpp:2025
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:1244
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:99
DCOPClient::registerAs
TQCString registerAs(const TQCString &appId, bool addPID=true)
Registers at the DCOP server.
Definition: dcopclient.cpp:971
DCOPClient::registeredApplications
QCStringList registeredApplications()
Retrieves the list of all currently registered applications from dcopserver.
Definition: dcopclient.cpp:1264
DCOPClient::setMainClient
static void setMainClient(DCOPClient *mainClient)
Sets the application's main dcop client.
Definition: dcopclient.cpp:604
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:1024
DCOPClient::transactionId
TQ_INT32 transactionId() const
Test whether the current function call is delayed.
Definition: dcopclient.cpp:2108
DCOPClient::suspend
void suspend()
Temporarily suspends processing of DCOP events.
Definition: dcopclient.cpp:701
DCOPClient::detach
bool detach()
Detaches from the DCOP server.
Definition: dcopclient.cpp:914
DCOPClient::senderId
TQCString senderId() const
Returns the appId of the last application that talked to us.
Definition: dcopclient.cpp:1071
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:1292
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:1336
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:2067
DCOPClient::setNotifications
void setNotifications(bool enabled)
Enables / disables the applicationRegistered() / applicationRemoved() signals.
Definition: dcopclient.cpp:1324
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:1148
DCOPClient::isAttachedToForeignServer
bool isAttachedToForeignServer() const
Returns whether the client is attached to a server owned by another user.
Definition: dcopclient.cpp:945
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:1308
DCOPClient::remoteObjects
QCStringList remoteObjects(const TQCString &remApp, bool *ok=0)
Retrieves the list of objects of the remote application remApp.
Definition: dcopclient.cpp:1276
DCOPClient::resume
void resume()
Resumes the processing of DCOP events.
Definition: dcopclient.cpp:711
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:316
DCOPClient::isAttached
bool isAttached() const
Returns whether or not the client is attached to the server.
Definition: dcopclient.cpp:937
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:2167
DCOPClient::isSuspended
bool isSuspended() const
Returns whether DCOP events are being processed.
Definition: dcopclient.cpp:721
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:1030
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:1774
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:323
DCOPClient::normalizeFunctionSignature
static TQCString normalizeFunctionSignature(const TQCString &fun)
Normalizes the function signature fun.
Definition: dcopclient.cpp:1043

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.