• 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  qWarning("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  qWarning("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  qWarning("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  }
443  qWarning("Very strange! got a DCOPReplyDelayed opcode, but we were not waiting for a reply!");
444  return;
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 // qWarning("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  qWarning("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  qWarning("DROPPING UNHANDLED DCOP MESSAGE:");
645  qWarning(" 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  qWarning(" from = %s", fromApp.data());
651  qWarning(" 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 = qstrdup( 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 = QMIN( (qint64)1024, f.size() ); // protection against a huge file
813  TQCString contents( size+1 );
814  if ( f.readBlock( contents.data(), size ) != size )
815  {
816  qDebug("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  qDebug("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 // qDebug("dcopserver address: %s", dcopSrv.data());
833 //#endif
834  }
835  }
836  d->serverAddr = qstrdup( 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  qDebug("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  qWarning("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  qWarning("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->qt_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  qWarning("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 );
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  if (remApp.isEmpty())
1772  return false;
1773  DCOPClient *localClient = findLocalClient( remApp );
1774 
1775  if ( localClient ) {
1776  bool saveTransaction = d->transaction;
1777  TQ_INT32 saveTransactionId = d->transactionId;
1778  TQCString saveSenderId = d->senderId;
1779 
1780  d->senderId = 0; // Local call
1781  bool b = localClient->receive( remApp, remObjId, remFun, data, replyType, replyData );
1782 
1783  TQ_INT32 id = localClient->transactionId();
1784  if (id) {
1785  // Call delayed. We have to wait till it has been processed.
1786  do {
1787  TQApplication::eventLoop()->processEvents( TQEventLoop::WaitForMore);
1788  } while( !localClient->isLocalTransactionFinished(id, replyType, replyData));
1789  b = true;
1790  }
1791  d->transaction = saveTransaction;
1792  d->transactionId = saveTransactionId;
1793  d->senderId = saveSenderId;
1794  return b;
1795  }
1796 
1797  return callInternal(remApp, remObjId, remFun, data,
1798  replyType, replyData, useEventLoop, timeout, DCOPCall);
1799 }
1800 
1801 void DCOPClient::asyncReplyReady()
1802 {
1803  while( d->asyncReplyQueue.count() )
1804  {
1805  ReplyStruct *replyStruct = d->asyncReplyQueue.take(0);
1806  handleAsyncReply(replyStruct);
1807  }
1808 }
1809 
1810 int DCOPClient::callAsync(const TQCString &remApp, const TQCString &remObjId,
1811  const TQCString &remFun, const TQByteArray &data,
1812  TQObject *callBackObj, const char *callBackSlot)
1813 {
1814  TQCString replyType;
1815  TQByteArray replyData;
1816 
1817  ReplyStruct *replyStruct = new ReplyStruct;
1818  replyStruct->replyType = new TQCString;
1819  replyStruct->replyData = new TQByteArray;
1820  replyStruct->replyObject = callBackObj;
1821  replyStruct->replySlot = callBackSlot;
1822  replyStruct->replyId = ++d->transactionId;
1823  if (d->transactionId < 0) // Ensure that ids > 0
1824  d->transactionId = 0;
1825 
1826  bool b = callInternal(remApp, remObjId, remFun, data,
1827  replyStruct, false, -1, DCOPCall);
1828  if (!b)
1829  {
1830  delete replyStruct->replyType;
1831  delete replyStruct->replyData;
1832  delete replyStruct;
1833  return 0;
1834  }
1835 
1836  if (replyStruct->transactionId == 0)
1837  {
1838  // Call is finished already
1839  TQTimer::singleShot(0, this, TQT_SLOT(asyncReplyReady()));
1840  d->asyncReplyQueue.append(replyStruct);
1841  }
1842 
1843  return replyStruct->replyId;
1844 }
1845 
1846 bool DCOPClient::callInternal(const TQCString &remApp, const TQCString &remObjId,
1847  const TQCString &remFun, const TQByteArray &data,
1848  TQCString& replyType, TQByteArray &replyData,
1849  bool useEventLoop, int timeout, int minor_opcode)
1850 {
1851  ReplyStruct replyStruct;
1852  replyStruct.replyType = &replyType;
1853  replyStruct.replyData = &replyData;
1854  return callInternal(remApp, remObjId, remFun, data, &replyStruct, useEventLoop, timeout, minor_opcode);
1855 }
1856 
1857 bool DCOPClient::callInternal(const TQCString &remApp, const TQCString &remObjId,
1858  const TQCString &remFun, const TQByteArray &data,
1859  ReplyStruct *replyStruct,
1860  bool useEventLoop, int timeout, int minor_opcode)
1861 {
1862  if ( !isAttached() )
1863  return false;
1864 
1865  DCOPMsg *pMsg;
1866 
1867  CARD32 oldCurrentKey = d->currentKey;
1868  if ( !d->currentKey )
1869  d->currentKey = d->key; // no key yet, initiate new call
1870 
1871  TQByteArray ba;
1872  TQDataStream ds(ba, IO_WriteOnly);
1873  ds << d->appId << remApp << remObjId << normalizeFunctionSignature(remFun) << data.size();
1874 
1875  IceGetHeader(d->iceConn, d->majorOpcode, minor_opcode,
1876  sizeof(DCOPMsg), DCOPMsg, pMsg);
1877 
1878  pMsg->key = d->currentKey;
1879  int datalen = ba.size() + data.size();
1880  pMsg->length += datalen;
1881 
1882 // qWarning("DCOP: %s made call %s:%s:%s key = %d", d->appId.data(), remApp.data(), remObjId.data(), remFun.data(), pMsg->key);
1883 
1884  IceSendData(d->iceConn, ba.size(), const_cast<char *>(ba.data()));
1885  IceSendData(d->iceConn, data.size(), const_cast<char *>(data.data()));
1886 
1887  if (IceConnectionStatus(d->iceConn) != IceConnectAccepted)
1888  return false;
1889 
1890  IceFlush (d->iceConn);
1891 
1892  IceReplyWaitInfo waitInfo;
1893  waitInfo.sequence_of_request = IceLastSentSequenceNumber(d->iceConn);
1894  waitInfo.major_opcode_of_request = d->majorOpcode;
1895  waitInfo.minor_opcode_of_request = minor_opcode;
1896 
1897  replyStruct->transactionId = -1;
1898  waitInfo.reply = static_cast<IcePointer>(replyStruct);
1899 
1900  Bool readyRet = False;
1901  IceProcessMessagesStatus s;
1902 
1903  timeval time_start;
1904  int time_left = -1;
1905  if( timeout >= 0 )
1906  {
1907  gettimeofday( &time_start, NULL );
1908  time_left = timeout;
1909  }
1910  for(;;) {
1911  bool checkMessages = true;
1912  if ( useEventLoop
1913  ? d->notifier != NULL // useEventLoop needs a socket notifier and a tqApp
1914  : timeout >= 0 ) { // !useEventLoop doesn't block only for timeout >= 0
1915  const int guiTimeout = 100;
1916  checkMessages = false;
1917 
1918  int msecs = useEventLoop
1919  ? guiTimeout // timeout for the GUI refresh
1920  : time_left; // time remaining for the whole call
1921  fd_set fds;
1922  struct timeval tv;
1923  FD_ZERO( &fds );
1924  FD_SET( socket(), &fds );
1925  tv.tv_sec = msecs / 1000;
1926  tv.tv_usec = (msecs % 1000) * 1000;
1927  if ( select( socket() + 1, &fds, 0, 0, &tv ) <= 0 ) {
1928  if( useEventLoop && (timeout < 0 || time_left > guiTimeout)) {
1929  // nothing was available, we got a timeout. Reactivate
1930  // the GUI in blocked state.
1931  bool old_lock = d->non_blocking_call_lock;
1932  if ( !old_lock ) {
1933  d->non_blocking_call_lock = true;
1934  emit blockUserInput( true );
1935  }
1936  if( timeout >= 0 )
1937  d->eventLoopTimer.start(time_left - guiTimeout, true);
1938  tqApp->enter_loop();
1939  d->eventLoopTimer.stop();
1940  if ( !old_lock ) {
1941  d->non_blocking_call_lock = false;
1942  emit blockUserInput( false );
1943  }
1944  }
1945  }
1946  else
1947  {
1948  checkMessages = true;
1949  }
1950  }
1951  if (!d->iceConn)
1952  return false;
1953 
1954  if( replyStruct->transactionId != -1 )
1955  {
1956  if (replyStruct->transactionId == 0)
1957  break; // Call complete
1958  if (!replyStruct->replySlot.isEmpty())
1959  break; // Async call
1960  }
1961 
1962  if( checkMessages ) { // something is available
1963  s = IceProcessMessages(d->iceConn, &waitInfo,
1964  &readyRet);
1965  if (s == IceProcessMessagesIOError) {
1966  detach();
1967  d->currentKey = oldCurrentKey;
1968  return false;
1969  }
1970  }
1971 
1972  if( replyStruct->transactionId != -1 )
1973  {
1974  if (replyStruct->transactionId == 0)
1975  break; // Call complete
1976  if (!replyStruct->replySlot.isEmpty())
1977  break; // Async call
1978  }
1979 
1980  if( timeout < 0 )
1981  continue;
1982  timeval time_now;
1983  gettimeofday( &time_now, NULL );
1984  time_left = timeout -
1985  ((time_now.tv_sec - time_start.tv_sec) * 1000) -
1986  ((time_now.tv_usec - time_start.tv_usec) / 1000);
1987  if( time_left <= 0)
1988  {
1989  if (useEventLoop)
1990  {
1991  // Before we fail, check one more time if something is available
1992  time_left = 0;
1993  useEventLoop = false;
1994  continue;
1995  }
1996  *(replyStruct->replyType) = TQCString();
1997  *(replyStruct->replyData) = TQByteArray();
1998  replyStruct->status = ReplyStruct::Failed;
1999  break;
2000  }
2001  }
2002 
2003  // Wake up parent call, maybe it's reply is available already.
2004  if ( d->non_blocking_call_lock ) {
2005  tqApp->exit_loop();
2006  }
2007 
2008  d->currentKey = oldCurrentKey;
2009  return replyStruct->status != ReplyStruct::Failed;
2010 }
2011 
2012 void DCOPClient::eventLoopTimeout()
2013 {
2014  tqApp->exit_loop();
2015 }
2016 
2017 void DCOPClient::processSocketData(int fd)
2018 {
2019  // Make sure there is data to read!
2020  fd_set fds;
2021  timeval timeout;
2022  timeout.tv_sec = 0;
2023  timeout.tv_usec = 0;
2024  FD_ZERO(&fds);
2025  FD_SET(fd, &fds);
2026  int result = select(fd+1, &fds, 0, 0, &timeout);
2027  if (result == 0)
2028  return;
2029 
2030  if ( d->non_blocking_call_lock ) {
2031  if( tqApp )
2032  tqApp->exit_loop();
2033  return;
2034  }
2035 
2036  if (!d->iceConn) {
2037  if( d->notifier )
2038  d->notifier->deleteLater();
2039  d->notifier = 0;
2040  qWarning("received an error processing data from the DCOP server!");
2041  return;
2042  }
2043 
2044  IceProcessMessagesStatus s = IceProcessMessages(d->iceConn, 0, 0);
2045 
2046  if (s == IceProcessMessagesIOError) {
2047  detach();
2048  qWarning("received an error processing data from the DCOP server!");
2049  return;
2050  }
2051 }
2052 
2053 void DCOPClient::setDefaultObject( const TQCString& objId )
2054 {
2055  d->defaultObject = objId;
2056 }
2057 
2058 
2059 TQCString DCOPClient::defaultObject() const
2060 {
2061  return d->defaultObject;
2062 }
2063 
2064 bool
2065 DCOPClient::isLocalTransactionFinished(TQ_INT32 id, TQCString &replyType, TQByteArray &replyData)
2066 {
2067  DCOPClientPrivate::LocalTransactionResult *result = d->localTransActionList.take(id);
2068  if (!result)
2069  return false;
2070 
2071  replyType = result->replyType;
2072  replyData = result->replyData;
2073  delete result;
2074 
2075  return true;
2076 }
2077 
2078 DCOPClientTransaction *
2079 DCOPClient::beginTransaction()
2080 {
2081  if (d->opcode == DCOPSend)
2082  return 0;
2083  if (!d->transactionList)
2084  d->transactionList = new TQPtrList<DCOPClientTransaction>;
2085 
2086  d->transaction = true;
2087  DCOPClientTransaction *trans = new DCOPClientTransaction();
2088  trans->senderId = d->senderId;
2089  trans->id = ++d->transactionId;
2090  if (d->transactionId < 0) // Ensure that ids > 0
2091  d->transactionId = 0;
2092  trans->key = d->currentKey;
2093 
2094  d->transactionList->append( trans );
2095 
2096  return trans;
2097 }
2098 
2099 TQ_INT32
2100 DCOPClient::transactionId() const
2101 {
2102  if (d->transaction)
2103  return d->transactionId;
2104  else
2105  return 0;
2106 }
2107 
2108 void
2109 DCOPClient::endTransaction( DCOPClientTransaction *trans, TQCString& replyType,
2110  TQByteArray &replyData)
2111 {
2112  if ( !trans )
2113  return;
2114 
2115  if ( !isAttached() )
2116  return;
2117 
2118  if ( !d->transactionList) {
2119  qWarning("Transaction unknown: No pending transactions!");
2120  return; // No pending transactions!
2121  }
2122 
2123  if ( !d->transactionList->removeRef( trans ) ) {
2124  qWarning("Transaction unknown: Not on list of pending transactions!");
2125  return; // Transaction
2126  }
2127 
2128  if (trans->senderId.isEmpty())
2129  {
2130  // Local transaction
2131  DCOPClientPrivate::LocalTransactionResult *result = new DCOPClientPrivate::LocalTransactionResult();
2132  result->replyType = replyType;
2133  result->replyData = replyData;
2134 
2135  d->localTransActionList.insert(trans->id, result);
2136 
2137  delete trans;
2138 
2139  return;
2140  }
2141 
2142  DCOPMsg *pMsg;
2143 
2144  TQByteArray ba;
2145  TQDataStream ds(ba, IO_WriteOnly);
2146  ds << d->appId << trans->senderId << trans->id << replyType << replyData;
2147 
2148  IceGetHeader(d->iceConn, d->majorOpcode, DCOPReplyDelayed,
2149  sizeof(DCOPMsg), DCOPMsg, pMsg);
2150  pMsg->key = trans->key;
2151  pMsg->length += ba.size();
2152 
2153  IceSendData( d->iceConn, ba.size(), const_cast<char *>(ba.data()) );
2154 
2155  delete trans;
2156 }
2157 
2158 void
2159 DCOPClient::emitDCOPSignal( const TQCString &object, const TQCString &signal, const TQByteArray &data)
2160 {
2161  // We hack the sending object name into the signal name
2162  send("DCOPServer", "emit", object+"#"+normalizeFunctionSignature(signal), data);
2163 }
2164 
2165 void
2166 DCOPClient::emitDCOPSignal( const TQCString &signal, const TQByteArray &data)
2167 {
2168  emitDCOPSignal(0, signal, data);
2169 }
2170 
2171 bool
2172 DCOPClient::connectDCOPSignal( const TQCString &sender, const TQCString &senderObj,
2173  const TQCString &signal,
2174  const TQCString &receiverObj, const TQCString &slot, bool Volatile)
2175 {
2176  TQCString replyType;
2177  TQByteArray data, replyData;
2178  TQ_INT8 iVolatile = Volatile ? 1 : 0;
2179 
2180  TQDataStream args(data, IO_WriteOnly );
2181  args << sender << senderObj << normalizeFunctionSignature(signal) << receiverObj << normalizeFunctionSignature(slot) << iVolatile;
2182 
2183  if (!call("DCOPServer", 0,
2184  "connectSignal(TQCString,TQCString,TQCString,TQCString,TQCString,bool)",
2185  data, replyType, replyData))
2186  {
2187  return false;
2188  }
2189 
2190  if (replyType != "bool")
2191  return false;
2192 
2193  TQDataStream reply(replyData, IO_ReadOnly );
2194  TQ_INT8 result;
2195  reply >> result;
2196  return (result != 0);
2197 }
2198 
2199 bool
2200 DCOPClient::connectDCOPSignal( const TQCString &sender, const TQCString &signal,
2201  const TQCString &receiverObj, const TQCString &slot, bool Volatile)
2202 {
2203  return connectDCOPSignal( sender, 0, signal, receiverObj, slot, Volatile);
2204 }
2205 
2206 bool
2207 DCOPClient::disconnectDCOPSignal( const TQCString &sender, const TQCString &senderObj,
2208  const TQCString &signal,
2209  const TQCString &receiverObj, const TQCString &slot)
2210 {
2211  TQCString replyType;
2212  TQByteArray data, replyData;
2213 
2214  TQDataStream args(data, IO_WriteOnly );
2215  args << sender << senderObj << normalizeFunctionSignature(signal) << receiverObj << normalizeFunctionSignature(slot);
2216 
2217  if (!call("DCOPServer", 0,
2218  "disconnectSignal(TQCString,TQCString,TQCString,TQCString,TQCString)",
2219  data, replyType, replyData))
2220  {
2221  return false;
2222  }
2223 
2224  if (replyType != "bool")
2225  return false;
2226 
2227  TQDataStream reply(replyData, IO_ReadOnly );
2228  TQ_INT8 result;
2229  reply >> result;
2230  return (result != 0);
2231 }
2232 
2233 bool
2234 DCOPClient::disconnectDCOPSignal( const TQCString &sender, const TQCString &signal,
2235  const TQCString &receiverObj, const TQCString &slot)
2236 {
2237  return disconnectDCOPSignal( sender, 0, signal, receiverObj, slot);
2238 }
2239 
2240 void
2241 DCOPClient::setPriorityCall(bool b)
2242 {
2243  if (b)
2244  {
2245  if (d->currentKey == 2)
2246  return;
2247  d->currentKeySaved = d->currentKey;
2248  d->currentKey = 2;
2249  }
2250  else
2251  {
2252  if (d->currentKey != 2)
2253  return;
2254  d->currentKey = d->currentKeySaved;
2255  if ( !d->messages.isEmpty() )
2256  d->postMessageTimer.start( 0, true ); // Process queued messages
2257  }
2258 }
2259 
2260 
2261 
2262 void
2263 DCOPClient::emergencyClose()
2264 {
2265  TQPtrList<DCOPClient> list;
2266  client_map_t *map = DCOPClient_CliMap;
2267  if (!map) return;
2268  TQAsciiDictIterator<DCOPClient> it(*map);
2269  while(it.current()) {
2270  list.removeRef(it.current());
2271  list.append(it.current());
2272  ++it;
2273  }
2274  for(DCOPClient *cl = list.first(); cl; cl = list.next())
2275  {
2276  if (cl->d->iceConn) {
2277  IceProtocolShutdown(cl->d->iceConn, cl->d->majorOpcode);
2278  IceCloseConnection(cl->d->iceConn);
2279  cl->d->iceConn = 0L;
2280  }
2281  }
2282 }
2283 
2284 const char *
2285 DCOPClient::postMortemSender()
2286 {
2287  if (!dcop_main_client)
2288  return "";
2289  if (dcop_main_client->d->senderId.isEmpty())
2290  return "";
2291  return dcop_main_client->d->senderId.data();
2292 }
2293 
2294 const char *
2295 DCOPClient::postMortemObject()
2296 {
2297  if (!dcop_main_client)
2298  return "";
2299  return dcop_main_client->d->objId.data();
2300 }
2301 const char *
2302 DCOPClient::postMortemFunction()
2303 {
2304  if (!dcop_main_client)
2305  return "";
2306  return dcop_main_client->d->function.data();
2307 }
2308 
2309 void DCOPClient::virtual_hook( int, void* )
2310 { /*BASE::virtual_hook( id, data );*/ }
2311 
2312 #include <dcopclient.moc>
2313 
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:1336
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::endTransaction
void endTransaction(DCOPClientTransaction *t, TQCString &replyType, TQByteArray &replyData)
Sends the delayed reply of a function call.
Definition: dcopclient.cpp:2109
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::detach
bool detach()
Detaches from the DCOP server.
Definition: dcopclient.cpp:914
DCOPClient::setQtBridgeEnabled
void setQtBridgeEnabled(bool b)
Specify whether Qt objects of the application should be accessible via DCOP.
Definition: dcopclient.cpp:966
DCOPClient::beginTransaction
DCOPClientTransaction * beginTransaction()
Delays the reply of the current function call until endTransaction() is called.
Definition: dcopclient.cpp:2079
DCOPClient::isApplicationRegistered
bool isApplicationRegistered(const TQCString &remApp)
Checks whether remApp is registered with the DCOP server.
Definition: dcopclient.cpp:1250
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:2159
DCOPClient::registeredApplications
QCStringList registeredApplications()
Retrieves the list of all currently registered applications from dcopserver.
Definition: dcopclient.cpp:1264
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:2207
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
DCOPClient::transactionId
TQ_INT32 transactionId() const
Test whether the current function call is delayed.
Definition: dcopclient.cpp:2100
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:1077
DCOPClient::isRegistered
bool isRegistered() const
Returns whether or not the client is registered at the server.
Definition: dcopclient.cpp:1018
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:945
DCOPClient::senderId
TQCString senderId() const
Returns the appId of the last application that talked to us.
Definition: dcopclient.cpp:1071
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:961
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:1810
DCOPClient::isAttached
bool isAttached() const
Returns whether or not the client is attached to the server.
Definition: dcopclient.cpp:937
DCOPClient::acceptCalls
bool acceptCalls() const
Returns whether the client handles incoming calls.
Definition: dcopclient.cpp:950
DCOPClient::socket
int socket() const
Returns the socket fd that is used for communication with the server.
Definition: dcopclient.cpp:1030
DCOPClient::setNotifications
void setNotifications(bool enabled)
Enables / disables the applicationRegistered() / applicationRemoved() signals.
Definition: dcopclient.cpp:1324
DCOPClient::call
bool call(const TQCString &remApp, const TQCString &remObj, const TQCString &remFun, const TQByteArray &data, TQCString &replyType, TQByteArray &replyData, bool useEventLoop, int timeout)
Performs a synchronous send and receive.
Definition: dcopclient.cpp:1766
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:1148
DCOPClient::dcopServerFileOld
static TQCString dcopServerFileOld(const TQCString &hostname=0) KDE_DEPRECATED
Definition: dcopclient.cpp:323
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:2059
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:1276
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
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:2172
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:971
DCOPClient::processSocketData
void processSocketData(int socknum)
Process data from the socket.
Definition: dcopclient.cpp:2017
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:1043
DCOPClient::setAcceptCalls
void setAcceptCalls(bool b)
Specify whether the client should accept incoming calls.
Definition: dcopclient.cpp:955
DCOPClient::setDefaultObject
void setDefaultObject(const TQCString &objId)
Installs object objId as application-wide default object.
Definition: dcopclient.cpp:2053
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
KStdAccel::key
int key(StdAccel id)
KStdAccel::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
  •     interface
  •     library
  •   kspeech
  •   ktexteditor
  • kabc
  • kate
  • kcmshell
  • kdecore
  • kded
  • kdefx
  • kdeprint
  • kdesu
  • kdeui
  • kdoctools
  • khtml
  • kimgio
  • kinit
  • kio
  •   bookmarks
  •   httpfilter
  •   kfile
  •   kio
  •   kioexec
  •   kpasswdserver
  •   kssl
  • kioslave
  •   http
  • kjs
  • kmdi
  •   kmdi
  • knewstuff
  • kparts
  • krandr
  • kresources
  • kspell2
  • kunittest
  • kutils
  • kwallet
  • libkmid
  • libkscreensaver
Generated for dcop by doxygen 1.9.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |