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

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.1.2
This website is maintained by Timothy Pearson.