• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • dcop
 

dcop

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

dcop

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

dcop

Skip menu "dcop"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   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.9.1
This website is maintained by Timothy Pearson.