• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeio/tdeio
 

tdeio/tdeio

  • tdeio
  • tdeio
dataprotocol.cpp
1 // dataprotocol.cpp
2 // ==================
3 //
4 // Implementation of the data protocol (rfc 2397)
5 //
6 // Author: Leo Savernik
7 // Email: l.savernik@aon.at
8 // (C) 2002, 2003 by Leo Savernik
9 // Created: Sam Dez 28 14:11:18 CET 2002
10 
11 /***************************************************************************
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU Lesser General Public License as *
15  * published by the Free Software Foundation; version 2. *
16  * *
17  ***************************************************************************/
18 
19 #include "dataprotocol.h"
20 
21 #include <kdebug.h>
22 #include <kmdcodec.h>
23 #include <kurl.h>
24 #include <tdeio/global.h>
25 
26 #include <tqcstring.h>
27 #include <tqstring.h>
28 #include <tqstringlist.h>
29 #include <tqtextcodec.h>
30 
31 #ifdef DATAKIOSLAVE
32 # include <kinstance.h>
33 # include <stdlib.h>
34 #endif
35 #ifdef TESTKIO
36 # include <iostream>
37 #endif
38 
39 #if !defined(DATAKIOSLAVE) && !defined(TESTKIO)
40 # define DISPATCH(f) dispatch_##f
41 #else
42 # define DISPATCH(f) f
43 #endif
44 
45 using namespace TDEIO;
46 #ifdef DATAKIOSLAVE
47 extern "C" {
48 
49  int kdemain( int argc, char **argv ) {
50  TDEInstance instance( "tdeio_data" );
51 
52  kdDebug(7101) << "*** Starting tdeio_data " << endl;
53 
54  if (argc != 4) {
55  kdDebug(7101) << "Usage: tdeio_data protocol domain-socket1 domain-socket2" << endl;
56  exit(-1);
57  }
58 
59  DataProtocol slave(argv[2], argv[3]);
60  slave.dispatchLoop();
61 
62  kdDebug(7101) << "*** tdeio_data Done" << endl;
63  return 0;
64  }
65 }
66 #endif
67 
69 struct DataHeader {
70  TQString mime_type; // mime type of content (lowercase)
71  MetaData attributes; // attribute/value pairs (attribute lowercase,
72  // value unchanged)
73  bool is_base64; // true if data is base64 encoded
74  TQString url; // reference to decoded url
75  int data_offset; // zero-indexed position within url
76  // where the real data begins. May point beyond
77  // the end to indicate that there is no data
78  TQString *charset; // shortcut to charset (it always exists)
79 };
80 
81 // constant string data
82 const TQChar text_plain_str[] = { 't','e','x','t','/','p','l','a','i','n' };
83 const TQChar charset_str[] = { 'c','h','a','r','s','e','t' };
84 const TQChar us_ascii_str[] = { 'u','s','-','a','s','c','i','i' };
85 const TQChar base64_str[] = { 'b','a','s','e','6','4' };
86 
95 static int find(const TQString &buf, int begin, TQChar c1, TQChar c2 = '\0',
96  TQChar c3 = '\0') {
97  int pos = begin;
98  int size = (int)buf.length();
99  while (pos < size) {
100  TQChar ch = buf[pos];
101  if (ch == c1
102  || (c2 != '\0' && ch == c2)
103  || (c3 != '\0' && ch == c3))
104  break;
105  pos++;
106  }/*wend*/
107  return pos;
108 }
109 
120 inline TQString extract(const TQString &buf, int &pos, TQChar c1,
121  TQChar c2 = '\0', TQChar c3 = '\0') {
122  int oldpos = pos;
123  pos = find(buf,oldpos,c1,c2,c3);
124  return TQString(buf.unicode() + oldpos, pos - oldpos);
125 }
126 
133 inline void ignoreWS(const TQString &buf, int &pos) {
134  int size = (int)buf.length();
135  TQChar ch = buf[pos];
136  while (pos < size && (ch == ' ' || ch == '\t' || ch == '\n'
137  || ch == '\r'))
138  ch = buf[++pos];
139 }
140 
149 static TQString parseQuotedString(const TQString &buf, int &pos) {
150  int size = (int)buf.length();
151  TQString res;
152  pos++; // jump over leading quote
153  bool escaped = false; // if true means next character is literal
154  bool parsing = true; // true as long as end quote not found
155  while (parsing && pos < size) {
156  TQChar ch = buf[pos++];
157  if (escaped) {
158  res += ch;
159  escaped = false;
160  } else {
161  switch (ch) {
162  case '"': parsing = false; break;
163  case '\\': escaped = true; break;
164  default: res += ch; break;
165  }/*end switch*/
166  }/*end if*/
167  }/*wend*/
168  return res;
169 }
170 
176 static void parseDataHeader(const KURL &url, DataHeader &header_info) {
177  TQConstString text_plain(text_plain_str,sizeof text_plain_str/sizeof text_plain_str[0]);
178  TQConstString charset(charset_str,sizeof charset_str/sizeof charset_str[0]);
179  TQConstString us_ascii(us_ascii_str,sizeof us_ascii_str/sizeof us_ascii_str[0]);
180  TQConstString base64(base64_str,sizeof base64_str/sizeof base64_str[0]);
181  // initialize header info members
182  header_info.mime_type = text_plain.string();
183  header_info.charset = &header_info.attributes.insert(
184  charset.string(),us_ascii.string())
185  .data();
186  header_info.is_base64 = false;
187 
188  // decode url and save it
189  TQString &raw_url = header_info.url = TQString::fromLatin1("data:") + url.path();
190  int raw_url_len = (int)raw_url.length();
191 
192  // jump over scheme part (must be "data:", we don't even check that)
193  header_info.data_offset = raw_url.find(':');
194  header_info.data_offset++; // jump over colon or to begin if scheme was missing
195 
196  // read mime type
197  if (header_info.data_offset >= raw_url_len) return;
198  TQString mime_type = extract(raw_url,header_info.data_offset,';',',')
199  .stripWhiteSpace();
200  if (!mime_type.isEmpty()) header_info.mime_type = mime_type;
201 
202  if (header_info.data_offset >= raw_url_len) return;
203  // jump over delimiter token and return if data reached
204  if (raw_url[header_info.data_offset++] == ',') return;
205 
206  // read all attributes and store them
207  bool data_begin_reached = false;
208  while (!data_begin_reached && header_info.data_offset < raw_url_len) {
209  // read attribute
210  TQString attribute = extract(raw_url,header_info.data_offset,'=',';',',')
211  .stripWhiteSpace();
212  if (header_info.data_offset >= raw_url_len
213  || raw_url[header_info.data_offset] != '=') {
214  // no assigment, must be base64 option
215  if (attribute == base64.string())
216  header_info.is_base64 = true;
217  } else {
218  header_info.data_offset++; // jump over '=' token
219 
220  // read value
221  ignoreWS(raw_url,header_info.data_offset);
222  if (header_info.data_offset >= raw_url_len) return;
223 
224  TQString value;
225  if (raw_url[header_info.data_offset] == '"') {
226  value = parseQuotedString(raw_url,header_info.data_offset);
227  ignoreWS(raw_url,header_info.data_offset);
228  } else
229  value = extract(raw_url,header_info.data_offset,';',',')
230  .stripWhiteSpace();
231 
232  // add attribute to map
233  header_info.attributes[attribute.lower()] = value;
234 
235  }/*end if*/
236  if (header_info.data_offset < raw_url_len
237  && raw_url[header_info.data_offset] == ',')
238  data_begin_reached = true;
239  header_info.data_offset++; // jump over separator token
240  }/*wend*/
241 }
242 
243 #ifdef DATAKIOSLAVE
244 DataProtocol::DataProtocol(const TQCString &pool_socket, const TQCString &app_socket)
245  : SlaveBase("tdeio_data", pool_socket, app_socket) {
246 #else
247 DataProtocol::DataProtocol() {
248 #endif
249  kdDebug() << "DataProtocol::DataProtocol()" << endl;
250 }
251 
252 /* --------------------------------------------------------------------- */
253 
254 DataProtocol::~DataProtocol() {
255  kdDebug() << "DataProtocol::~DataProtocol()" << endl;
256 }
257 
258 /* --------------------------------------------------------------------- */
259 
260 void DataProtocol::get(const KURL& url) {
261  ref();
262  //kdDebug() << "===============================================================================================================================================================================" << endl;
263  kdDebug() << "tdeio_data@"<<this<<"::get(const KURL& url)" << endl ;
264 
265  DataHeader hdr;
266  parseDataHeader(url,hdr);
267 
268  int size = (int)hdr.url.length();
269  int data_ofs = TQMIN(hdr.data_offset,size);
270  // FIXME: string is copied, would be nice if we could have a reference only
271  TQString url_data = hdr.url.mid(data_ofs);
272  TQCString outData;
273 
274 #ifdef TESTKIO
275 // cout << "current charset: \"" << *hdr.charset << "\"" << endl;
276 #endif
277  if (hdr.is_base64) {
278  // base64 stuff is expected to contain the correct charset, so we just
279  // decode it and pass it to the receiver
280  KCodecs::base64Decode(url_data.local8Bit(),outData);
281  } else {
282  // FIXME: This is all flawed, must be reworked thoroughly
283  // non encoded data must be converted to the given charset
284  TQTextCodec *codec = TQTextCodec::codecForName(hdr.charset->latin1());
285  if (codec != 0) {
286  outData = codec->fromUnicode(url_data);
287  } else {
288  // if there is no approprate codec, just use local encoding. This
289  // should work for >90% of all cases.
290  outData = url_data.local8Bit();
291  }/*end if*/
292  }/*end if*/
293 
294  //kdDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
295  //kdDebug() << "emit mimeType@"<<this << endl ;
296  mimeType(hdr.mime_type);
297  //kdDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
298  //kdDebug() << "emit totalSize@"<<this << endl ;
299  totalSize(outData.size());
300 
301  //kdDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
302  //kdDebug() << "emit setMetaData@"<<this << endl ;
303 #if defined(TESTKIO) || defined(DATAKIOSLAVE)
304  MetaData::ConstIterator it;
305  for (it = hdr.attributes.begin(); it != hdr.attributes.end(); ++it) {
306  setMetaData(it.key(),it.data());
307  }/*next it*/
308 #else
309  setAllMetaData(hdr.attributes);
310 #endif
311 
312  //kdDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
313  //kdDebug() << "emit sendMetaData@"<<this << endl ;
314  sendMetaData();
315  //kdDebug() << "^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C" << endl;
316 // kdDebug() << "(1) queue size " << dispatchQueue.size() << endl;
317  // empiric studies have shown that this shouldn't be queued & dispatched
318  /*DISPATCH*/(data(outData));
319 // kdDebug() << "(2) queue size " << dispatchQueue.size() << endl;
320  DISPATCH(data(TQByteArray()));
321 // kdDebug() << "(3) queue size " << dispatchQueue.size() << endl;
322  DISPATCH(finished());
323 // kdDebug() << "(4) queue size " << dispatchQueue.size() << endl;
324  deref();
325 }
326 
327 /* --------------------------------------------------------------------- */
328 
329 void DataProtocol::mimetype(const KURL &url) {
330  ref();
331  DataHeader hdr;
332  parseDataHeader(url,hdr);
333  mimeType(hdr.mime_type);
334  finished();
335  deref();
336 }
337 
338 /* --------------------------------------------------------------------- */
339 
TDEIO::DataProtocol
This tdeioslave provides support of data urls as specified by rfc 2397.
Definition: dataprotocol.h:51
TDEIO::DataSlave::setAllMetaData
void setAllMetaData(const MetaData &)
Sets metadata.
Definition: dataslave.cpp:163
TDEIO::DataSlave::sendMetaData
void sendMetaData()
Sends metadata set with setAllMetaData.
Definition: dataslave.cpp:167
TDEIO::MetaData
MetaData is a simple map of key/value strings.
Definition: global.h:516
TDEIO::SlaveBase
There are two classes that specifies the protocol between application (job) and tdeioslave.
Definition: slavebase.h:46
TDEIO
A namespace for TDEIO globals.
Definition: authinfo.h:29

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdeio/tdeio

Skip menu "tdeio/tdeio"
  • 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 tdeio/tdeio by doxygen 1.9.1
This website is maintained by Timothy Pearson.