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

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.8.3.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |