Qt 4.8
qwscommand_qws.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qwscommand_qws_p.h"
43 #include "qtransportauth_qws.h"
44 #include "qtransportauth_qws_p.h"
45 
46 #include <unistd.h>
47 
48 // #define QWSCOMMAND_DEBUG 1 // Uncomment to debug client/server communication
49 
50 #ifdef QWSCOMMAND_DEBUG
51 # include <qdebug.h>
52 # include "qfile.h"
53 # include <ctype.h>
54 #endif
55 
57 
58 #ifdef QWSCOMMAND_DEBUG
59 // QWSHexDump -[ start ]---------------------------------------------
60 # define QWSHEXDUMP_MAX 32
61 class QWSHexDump
62 {
63 public:
64 
65  QWSHexDump(const void *address, int len, int wrapAt = 16)
66  : wrap(wrapAt), dataSize(len)
67  {
68  init();
69  data = reinterpret_cast<const char*>(address);
70  if (len < 0)
71  dataSize = 0;
72  }
73 
74  QWSHexDump(const char *str, int len = -1, int wrapAt = 16)
75  : wrap(wrapAt), dataSize(len)
76  {
77  init();
78  data = str;
79  if (len == -1)
80  dataSize = str ? strlen(str) : 0;
81  }
82 
83  QWSHexDump(const QByteArray &array, int wrapAt = 16)
84  : wrap(wrapAt)
85  {
86  init();
87  data = array.data();
88  dataSize = array.size();
89  }
90 
91  // Sets a customized prefix for the hexdump
92  void setPrefix(const char *str) { prefix = str; }
93 
94  // Sets number of bytes to cluster together
95  void setClusterSize(uint num) { clustering = num; }
96 
97  // Output hexdump to a text stream
98  void intoTextStream(QTextStream &strm) {
99  outstrm = &strm;
100  hexDump();
101  }
102 
103  // Output hexdump to a QString
104  QString toString();
105 
106 protected:
107  void init();
108  void hexDump();
109  void sideviewDump(int at);
110 
111 private:
112  uint wrap;
113  uint clustering;
114  uint dataSize;
115  int dataWidth;
116  const char *data;
117  const char *prefix;
118  bool dirty;
119 
120  char sideviewLayout[QWSHEXDUMP_MAX + 1];
121  char sideview[15];
122 
123  QTextStream *outstrm;
124 };
125 
126 void QWSHexDump::init()
127 {
128  prefix = "> "; // Standard line prefix
129  clustering = 2; // Word-size clustering by default
130  if (wrap > QWSHEXDUMP_MAX) // No wider than QWSHexDump_MAX bytes
131  wrap = QWSHEXDUMP_MAX;
132 }
133 
134 void QWSHexDump::hexDump()
135 {
136  *outstrm << '(' << dataSize << " bytes):\n" << prefix;
137  sprintf(sideviewLayout, " [%%-%us]", wrap);
138  dataWidth = (2 * wrap) + (wrap / clustering);
139 
140  dirty = false;
141  uint wrapIndex = 0;
142  for (uint i = 0; i < dataSize; i++) {
143  uint c = static_cast<uchar>(data[i]);
144  sideview[wrapIndex = i%wrap] = isprint(c) ? c : '.';
145 
146  if (wrapIndex && (wrapIndex % clustering == 0))
147  *outstrm << ' ';
148 
149  outstrm->setFieldWidth(2);
150  outstrm->setPadChar('0');
151  outstrm->setNumberFlags( QTextStream::ShowBase );
152  *outstrm << hex << c;
153  dirty = true;
154 
155  if (wrapIndex == wrap-1) {
156  sideviewDump(wrapIndex);
157  wrapIndex = 0;
158  if (i+1 < dataSize)
159  *outstrm << endl << prefix;
160  }
161 
162  }
163  sideviewDump(wrapIndex);
164 }
165 
166 void QWSHexDump::sideviewDump(int at)
167 {
168  if (dirty) {
169  dirty = false;
170  ++at;
171  sideview[at] = '\0';
172  int currentWidth = (2 * at) + (at / clustering) - (at%clustering?0:1);
173  int missing = qMax(dataWidth - currentWidth, 0);
174  while (missing--)
175  *outstrm << ' ';
176 
177  *outstrm << " [";
178  outstrm->setPadChar(' ');
179  outstrm->setFieldWidth(wrap);
180  outstrm->setFieldAlignment( QTextStream::AlignLeft );
181  *outstrm << sideview;
182  *outstrm << ']';
183  }
184 }
185 
186 // Output hexdump to a QString
188  QString result;
189  QTextStream strm(&result, QFile::WriteOnly);
190  outstrm = &strm;
191  hexDump();
192  return result;
193 }
194 
195 #ifndef QT_NO_DEBUG
196 QDebug &operator<<(QDebug &dbg, QWSHexDump *hd) {
197  if (!hd)
198  return dbg << "QWSHexDump(0x0)";
199  QString result = hd->toString();
200  dbg.nospace() << result;
201  return dbg.space();
202 }
203 
204 // GCC & Intel wont handle references here
205 QDebug operator<<(QDebug dbg, QWSHexDump hd) {
206  return dbg << &hd;
207 }
208 #endif
209 // QWSHexDump -[ end ]-----------------------------------------------
210 
211 
213 {
214  dbg << qws_getCommandTypeString( tp );
215  return dbg;
216 }
217 
218 #define N_EVENTS 19
219 const char * eventNames[N_EVENTS] = {
220  "NoEvent",
221  "Connected",
222  "Mouse", "Focus", "Key",
223  "Region",
224  "Creation",
225  "PropertyNotify",
226  "PropertyReply",
227  "SelectionClear",
228  "SelectionRequest",
229  "SelectionNotify",
230  "MaxWindowRect",
231  "QCopMessage",
232  "WindowOperation",
233  "IMEvent",
234  "IMQuery",
235  "IMInit",
236  "Font"
237  };
238 
239 class QWSServer;
240 extern QWSServer *qwsServer;
241 #endif
242 
244 {
245  const char *typeStr;
246  switch(tp) {
247  case QWSCommand::Create:
248  typeStr = "Create";
249  break;
251  typeStr = "Shutdown";
252  break;
253  case QWSCommand::Region:
254  typeStr = "Region";
255  break;
257  typeStr = "RegionMove";
258  break;
260  typeStr = "RegionDestroy";
261  break;
263  typeStr = "SetProperty";
264  break;
266  typeStr = "AddProperty";
267  break;
269  typeStr = "RemoveProperty";
270  break;
272  typeStr = "GetProperty";
273  break;
275  typeStr = "SetSelectionOwner";
276  break;
278  typeStr = "ConvertSelection";
279  break;
281  typeStr = "RequestFocus";
282  break;
284  typeStr = "ChangeAltitude";
285  break;
287  typeStr = "SetOpacity";
288  break;
290  typeStr = "DefineCursor";
291  break;
293  typeStr = "SelectCursor";
294  break;
296  typeStr = "PositionCursor";
297  break;
299  typeStr = "GrabMouse";
300  break;
302  typeStr = "PlaySound";
303  break;
305  typeStr = "QCopRegisterChannel";
306  break;
308  typeStr = "QCopSend";
309  break;
311  typeStr = "RegionName";
312  break;
314  typeStr = "Identify";
315  break;
317  typeStr = "GrabKeyboard";
318  break;
320  typeStr = "RepaintRegion";
321  break;
322  case QWSCommand::IMMouse:
323  typeStr = "IMMouse";
324  break;
326  typeStr = "IMUpdate";
327  break;
329  typeStr = "IMResponse";
330  break;
331  case QWSCommand::Font:
332  typeStr = "Font";
333  break;
334  case QWSCommand::Unknown:
335  default:
336  typeStr = "Unknown";
337  break;
338  }
339  return typeStr;
340 }
341 
342 
343 /*********************************************************************
344  *
345  * Functions to read/write commands on/from a socket
346  *
347  *********************************************************************/
348 
349 #ifndef QT_NO_QWS_MULTIPROCESS
350 void qws_write_command(QIODevice *socket, int type, char *simpleData, int simpleLen,
351  char *rawData, int rawLen)
352 {
353 #ifdef QWSCOMMAND_DEBUG
354  if (simpleLen) qDebug() << "WRITE simpleData " << QWSHexDump(simpleData, simpleLen);
355  if (rawLen > 0) qDebug() << "WRITE rawData " << QWSHexDump(rawData, rawLen);
356 #endif
357 
358 #ifndef QT_NO_SXE
360  // ###### as soon as public API can be modified get rid of horrible casts
361  QIODevice *ad = a->passThroughByClient(reinterpret_cast<QWSClient*>(socket));
362  if (ad)
363  socket = ad;
364 #endif
365 
366  qws_write_uint(socket, type);
367 
368  if (rawLen > MAX_COMMAND_SIZE) {
369  qWarning("qws_write_command: Message of size %d too big. "
370  "Truncated to %d", rawLen, MAX_COMMAND_SIZE);
371  rawLen = MAX_COMMAND_SIZE;
372  }
373 
374  qws_write_uint(socket, rawLen == -1 ? 0 : rawLen);
375 
376  if (simpleData && simpleLen)
377  socket->write(simpleData, simpleLen);
378 
379  if (rawLen && rawData)
380  socket->write(rawData, rawLen);
381 }
382 
383 /*
384  command format: [type][rawLen][simpleData][rawData]
385  type is already read when entering this function
386 */
387 
388 bool qws_read_command(QIODevice *socket, char *&simpleData, int &simpleLen,
389  char *&rawData, int &rawLen, int &bytesRead)
390 {
391 
392  // read rawLen
393  if (rawLen == -1) {
394  rawLen = qws_read_uint(socket);
395  if (rawLen == -1)
396  return false;
397  }
398 
399  // read simpleData, assumes socket is capable of buffering all the data
400  if (simpleLen && !rawData) {
401  if (socket->bytesAvailable() < uint(simpleLen))
402  return false;
403  int tmp = socket->read(simpleData, simpleLen);
404  Q_ASSERT(tmp == simpleLen);
405  Q_UNUSED(tmp);
406  }
407 
408  if (rawLen > MAX_COMMAND_SIZE) {
409  socket->close();
410  qWarning("qws_read_command: Won't read command of length %d, "
411  "connection closed.", rawLen);
412  return false;
413  }
414 
415  // read rawData
416  if (rawLen && !rawData) {
417  rawData = new char[rawLen];
418  bytesRead = 0;
419  }
420  if (bytesRead < rawLen && socket->bytesAvailable())
421  bytesRead += socket->read(rawData + bytesRead, rawLen - bytesRead);
422 
423  return (bytesRead == rawLen);
424 }
425 #endif
426 
427 /*********************************************************************
428  *
429  * QWSCommand base class - only use derived classes from that
430  *
431  *********************************************************************/
433  if (deleteRaw)
434  delete []rawDataPtr;
435 }
436 
437 #ifndef QT_NO_QWS_MULTIPROCESS
439 #ifdef QWSCOMMAND_DEBUG
440  if (!qwsServer)
441  qDebug() << "QWSProtocolItem::write sending type " << static_cast<QWSCommand::Type>(type);
442  else
443  qDebug() << "QWSProtocolItem::write sending event " << (type < N_EVENTS ? eventNames[type] : "unknown");
444 #endif
445  qws_write_command(s, type, simpleDataPtr, simpleLen, rawDataPtr, rawLen);
446 }
447 
449 #ifdef QWSCOMMAND_DEBUG
450  QLatin1String reread( (rawLen == -1) ? "" : "REREAD");
451  if (qwsServer)
452  qDebug() << "QWSProtocolItem::read reading type " << static_cast<QWSCommand::Type>(type) << reread;
453  else
454  qDebug() << "QWSProtocolItem::read reading event " << (type < N_EVENTS ? eventNames[type] : "unknown") << reread;
455  //qDebug("QWSProtocolItem::read reading event %s", type < N_EVENTS ? eventNames[type] : "unknown");
456 #endif
457  bool b = qws_read_command(s, simpleDataPtr, simpleLen, rawDataPtr, rawLen, bytesRead);
458  if (b) {
459  setData(rawDataPtr, rawLen, false);
460  deleteRaw = true;
461  }
462 #ifdef QWSCOMMAND_DEBUG
463  else
464  {
465  qDebug() << "error in reading command " << static_cast<QWSCommand::Type>(type);
466  }
467 #endif
468  return b;
469 }
470 #endif // QT_NO_QWS_MULTIPROCESS
471 
473  if (this == item)
474  return;
475  simpleLen = item->simpleLen;
476  memcpy(simpleDataPtr, item->simpleDataPtr, simpleLen);
477  setData(item->rawDataPtr, item->rawLen);
478 }
479 
480 void QWSProtocolItem::setData(const char *data, int len, bool allocateMem) {
481  if (deleteRaw)
482  delete [] rawDataPtr;
483  if (!data || len <= 0) {
484  rawDataPtr = 0;
485  rawLen = 0;
486  return;
487  }
488  if (allocateMem) {
489  rawDataPtr = new char[len];
490  memcpy(rawDataPtr, data, len);
491  deleteRaw = true;
492  } else {
493  rawDataPtr = const_cast<char *>(data);
494  deleteRaw = false;
495  }
496  rawLen = len;
497 }
498 
500 {
501  QWSCommand *command = 0;
502  switch (type) {
503  case QWSCommand::Create:
504  command = new QWSCreateCommand;
505  break;
507  command = new QWSCommand(type, 0, 0);
508  break;
509  case QWSCommand::Region:
510  command = new QWSRegionCommand;
511  break;
513  command = new QWSRegionMoveCommand;
514  break;
516  command = new QWSRegionDestroyCommand;
517  break;
519  command = new QWSAddPropertyCommand;
520  break;
522  command = new QWSSetPropertyCommand;
523  break;
525  command = new QWSRemovePropertyCommand;
526  break;
528  command = new QWSGetPropertyCommand;
529  break;
531  command = new QWSSetSelectionOwnerCommand;
532  break;
534  command = new QWSRequestFocusCommand;
535  break;
537  command = new QWSChangeAltitudeCommand;
538  break;
540  command = new QWSSetOpacityCommand;
541  break;
543  command = new QWSDefineCursorCommand;
544  break;
546  command = new QWSSelectCursorCommand;
547  break;
549  command = new QWSGrabMouseCommand;
550  break;
552  command = new QWSGrabKeyboardCommand;
553  break;
554 #ifndef QT_NO_SOUND
556  command = new QWSPlaySoundCommand;
557  break;
558 #endif
559 #ifndef QT_NO_COP
561  command = new QWSQCopRegisterChannelCommand;
562  break;
564  command = new QWSQCopSendCommand;
565  break;
566 #endif
568  command = new QWSRegionNameCommand;
569  break;
571  command = new QWSIdentifyCommand;
572  break;
574  command = new QWSRepaintRegionCommand;
575  break;
576 #ifndef QT_NO_QWS_INPUTMETHODS
578  command = new QWSIMUpdateCommand;
579  break;
580 
581  case QWSCommand::IMMouse:
582  command = new QWSIMMouseCommand;
583  break;
584 
586  command = new QWSIMResponseCommand;
587  break;
588 #endif
590  command = new QWSPositionCursorCommand;
591  break;
592 #ifndef QT_NO_QWSEMBEDWIDGET
593  case QWSCommand::Embed:
594  command = new QWSEmbedCommand;
595  break;
596 #endif
597  case QWSCommand::Font:
598  command = new QWSFontCommand;
599  break;
601  command = new QWSScreenTransformCommand;
602  break;
603  default:
604  qWarning("QWSCommand::factory : Type error - got %08x!", type);
605  }
606  return command;
607 }
608 
The QDebug class provides an output stream for debugging information.
Definition: qdebug.h:62
bool qws_read_command(QIODevice *socket, char *&simpleData, int &simpleLen, char *&rawData, int &rawLen, int &bytesRead)
int type
Definition: qmetatype.cpp:239
unsigned char c[8]
Definition: qnumeric_p.h:62
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
virtual void close()
First emits aboutToClose(), then closes the device and sets its OpenMode to NotOpen.
Definition: qiodevice.cpp:590
static QWSCommand * factory(int type)
virtual void setData(const char *data, int len, bool allocateMem=true)
QDebug & nospace()
Clears the stream&#39;s internal flag that records whether the last character was a space and returns a r...
Definition: qdebug.h:92
#define at(className, varName)
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
void copyFrom(const QWSProtocolItem *item)
void write(QIODevice *s)
virtual ~QWSProtocolItem()
int qws_read_uint(QIODevice *socket)
Definition: qwsutils_qws.h:73
long ASN1_INTEGER_get ASN1_INTEGER * a
#define MAX_COMMAND_SIZE
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
Q_CORE_EXPORT QTextStream & hex(QTextStream &s)
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
Definition: qiodevice.cpp:791
Q_CORE_EXPORT void qDebug(const char *,...)
unsigned char uchar
Definition: qglobal.h:994
static QString toString(Register *reg, int type, bool *ok=0)
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
bool read(QIODevice *s)
static bool init
static bool setData(const QByteArray &data, STGMEDIUM *pmedium)
Definition: qmime_win.cpp:141
Q_CORE_EXPORT void qWarning(const char *,...)
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
void qws_write_command(QIODevice *socket, int type, char *simpleData, int simpleLen, char *rawData, int rawLen)
The QWSServer class encapsulates a server process in Qt for Embedded Linux.
The QTextStream class provides a convenient interface for reading and writing text.
Definition: qtextstream.h:73
virtual qint64 bytesAvailable() const
Returns the number of bytes that are available for reading.
Definition: qiodevice.cpp:752
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
const char * qws_getCommandTypeString(QWSCommand::Type tp)
QDataStream & operator<<(QDataStream &s, const QAxBase &c)
Definition: qaxbase.h:203
Authenticate a message transport.
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
Definition: qiodevice.cpp:1342
void qws_write_uint(QIODevice *socket, int i)
Definition: qwsutils_qws.h:84
The QIODevice class is the base interface class of all I/O devices in Qt.
Definition: qiodevice.h:66
QIODevice * passThroughByClient(QWSClient *) const
QDebug & space()
Writes a space character to the debug stream and returns a reference to the stream.
Definition: qdebug.h:91
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
QWSServer Q_GUI_EXPORT * qwsServer
static QTransportAuth * getInstance()
Return a pointer to the instance of this process&#39;s QTransportAuth object.
Q_CORE_EXPORT QTextStream & endl(QTextStream &s)