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

dcop

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

dcop

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