• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdelibs API Reference
  • KDE Home
  • Contact Us
 

KIO

  • sources
  • kde-4.14
  • kdelibs
  • kio
  • kio
dataprotocol.cpp
Go to the documentation of this file.
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 // Copyright (C) 2002, 2003 by Leo Savernik <l.savernik@aon.at>
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 <kurl.h>
23 #include "global.h"
24 #include <kglobal.h>
25 
26 #include <QtCore/QByteArray>
27 #include <QtCore/QCharRef>
28 #include <QtCore/QMutableStringListIterator>
29 #include <QtCore/QTextCodec>
30 
31 #ifdef DATAKIOSLAVE
32 # include <kinstance.h>
33 # include <stdlib.h>
34 #endif
35 
36 #if !defined(DATAKIOSLAVE)
37 # define DISPATCH(f) dispatch_##f
38 #else
39 # define DISPATCH(f) f
40 #endif
41 
42 using namespace KIO;
43 #ifdef DATAKIOSLAVE
44 extern "C" {
45 
46  int kdemain( int argc, char **argv ) {
47  KComponentData componentData( "kio_data" );
48 
49  kDebug(7101) << "*** Starting kio_data ";
50 
51  if (argc != 4) {
52  kDebug(7101) << "Usage: kio_data protocol domain-socket1 domain-socket2";
53  exit(-1);
54  }
55 
56  DataProtocol slave(argv[2], argv[3]);
57  slave.dispatchLoop();
58 
59  kDebug(7101) << "*** kio_data Done";
60  return 0;
61  }
62 }
63 #endif
64 
66 struct DataHeader {
67  QString mime_type; // mime type of content (lowercase)
68  MetaData attributes; // attribute/value pairs (attribute lowercase,
69  // value unchanged)
70  bool is_base64; // true if data is base64 encoded
71  QByteArray url; // reference to decoded url
72  int data_offset; // zero-indexed position within url
73  // where the real data begins. May point beyond
74  // the end to indicate that there is no data
75 };
76 
85 static int find(const QByteArray &buf, int begin, const char c1)
86 {
87  static const char comma = ',';
88  static const char semicolon = ';';
89  int pos = begin;
90  int size = buf.length();
91  while (pos < size) {
92  const char ch = buf[pos];
93  if (ch == comma || ch == semicolon || (c1 != '\0' && ch == c1))
94  break;
95  pos++;
96  }/*wend*/
97  return pos;
98 }
99 
108 static inline QString extract(const QByteArray &buf, int &pos,
109  const char c1 = '\0')
110 {
111  int oldpos = pos;
112  pos = find(buf, oldpos, c1);
113  return buf.mid(oldpos, pos-oldpos);
114 }
115 
122 static inline void ignoreWS(const QString &buf, int &pos)
123 {
124  int size = buf.length();
125  while (pos < size && buf[pos].isSpace())
126  ++pos;
127 }
128 
137 static QString parseQuotedString(const QString &buf, int &pos) {
138  int size = buf.length();
139  QString res;
140  res.reserve(size); // can't be larger than buf
141  pos++; // jump over leading quote
142  bool escaped = false; // if true means next character is literal
143  bool parsing = true; // true as long as end quote not found
144  while (parsing && pos < size) {
145  const QChar ch = buf[pos++];
146  if (escaped) {
147  res += ch;
148  escaped = false;
149  } else {
150  switch (ch.unicode()) {
151  case '"': parsing = false; break;
152  case '\\': escaped = true; break;
153  default: res += ch; break;
154  }/*end switch*/
155  }/*end if*/
156  }/*wend*/
157  res.squeeze();
158  return res;
159 }
160 
166 static DataHeader parseDataHeader(const KUrl &url, const bool mimeOnly)
167 {
168  static const QString& text_plain = KGlobal::staticQString("text/plain");
169  static const QString& charset = KGlobal::staticQString("charset");
170  static const QString& us_ascii = KGlobal::staticQString("us-ascii");
171  static const QString& base64 = KGlobal::staticQString("base64");
172 
173  DataHeader header_info;
174 
175  // initialize header info members
176  header_info.mime_type = text_plain;
177  header_info.attributes.insert(charset, us_ascii);
178  header_info.is_base64 = false;
179 
180  // decode url and save it
181  const QByteArray &raw_url = header_info.url = QByteArray::fromPercentEncoding( url.encodedPath() );
182  const int raw_url_len = raw_url.length();
183 
184  header_info.data_offset = 0;
185 
186  // read mime type
187  if (raw_url_len == 0)
188  return header_info;
189  const QString mime_type = extract(raw_url, header_info.data_offset).trimmed();
190  if (!mime_type.isEmpty()) header_info.mime_type = mime_type;
191  if (mimeOnly)
192  return header_info;
193 
194  if (header_info.data_offset >= raw_url_len)
195  return header_info;
196  // jump over delimiter token and return if data reached
197  if (raw_url[header_info.data_offset++] == QLatin1Char(','))
198  return header_info;
199 
200  // read all attributes and store them
201  bool data_begin_reached = false;
202  while (!data_begin_reached && header_info.data_offset < raw_url_len) {
203  // read attribute
204  const QString attribute = extract(raw_url, header_info.data_offset, '=').trimmed();
205  if (header_info.data_offset >= raw_url_len
206  || raw_url[header_info.data_offset] != QLatin1Char('=')) {
207  // no assigment, must be base64 option
208  if (attribute == base64)
209  header_info.is_base64 = true;
210  } else {
211  header_info.data_offset++; // jump over '=' token
212 
213  // read value
214  ignoreWS(raw_url,header_info.data_offset);
215  if (header_info.data_offset >= raw_url_len)
216  return header_info;
217 
218  QString value;
219  if (raw_url[header_info.data_offset] == QLatin1Char('"')) {
220  value = parseQuotedString(raw_url,header_info.data_offset);
221  ignoreWS(raw_url,header_info.data_offset);
222  } else
223  value = extract(raw_url, header_info.data_offset).trimmed();
224 
225  // add attribute to map
226  header_info.attributes[attribute.toLower()] = value;
227 
228  }/*end if*/
229  if (header_info.data_offset < raw_url_len
230  && raw_url[header_info.data_offset] == QLatin1Char(','))
231  data_begin_reached = true;
232  header_info.data_offset++; // jump over separator token
233  }/*wend*/
234 
235  return header_info;
236 }
237 
238 #ifdef DATAKIOSLAVE
239 DataProtocol::DataProtocol(const QByteArray &pool_socket, const QByteArray &app_socket)
240  : SlaveBase("kio_data", pool_socket, app_socket) {
241 #else
242 DataProtocol::DataProtocol() {
243 #endif
244  kDebug();
245 }
246 
247 /* --------------------------------------------------------------------- */
248 
249 DataProtocol::~DataProtocol() {
250  kDebug();
251 }
252 
253 /* --------------------------------------------------------------------- */
254 
255 void DataProtocol::get(const KUrl& url) {
256  ref();
257  kDebug() << "kio_data@"<<this<<"::get(const KUrl& url)";
258 
259  const DataHeader hdr = parseDataHeader(url, false);
260 
261  const int size = hdr.url.length();
262  const int data_ofs = qMin(hdr.data_offset, size);
263  // FIXME: string is copied, would be nice if we could have a reference only
264  const QByteArray url_data = hdr.url.mid(data_ofs);
265  QByteArray outData;
266 
267  if (hdr.is_base64) {
268  // base64 stuff is expected to contain the correct charset, so we just
269  // decode it and pass it to the receiver
270  outData = QByteArray::fromBase64(url_data);
271  } else {
272  QTextCodec *codec = QTextCodec::codecForName(hdr.attributes["charset"].toLatin1());
273  if (codec != 0) {
274  outData = codec->toUnicode(url_data).toUtf8();
275  } else {
276  outData = url_data;
277  }/*end if*/
278  }/*end if*/
279 
280  //kDebug() << "emit mimeType@"<<this;
281  mimeType(hdr.mime_type);
282  //kDebug() << "emit totalSize@"<<this;
283  totalSize(outData.size());
284 
285  //kDebug() << "emit setMetaData@"<<this;
286 #if defined(DATAKIOSLAVE)
287  MetaData::ConstIterator it;
288  for (it = hdr.attributes.constBegin(); it != hdr.attributes.constEnd(); ++it) {
289  setMetaData(it.key(),it.value());
290  }/*next it*/
291 #else
292  setAllMetaData(hdr.attributes);
293 #endif
294 
295  //kDebug() << "emit sendMetaData@"<<this;
296  sendMetaData();
297 // kDebug() << "(1) queue size " << dispatchQueue.size();
298  // empiric studies have shown that this shouldn't be queued & dispatched
299  data(outData);
300 // kDebug() << "(2) queue size " << dispatchQueue.size();
301  DISPATCH(data(QByteArray()));
302 // kDebug() << "(3) queue size " << dispatchQueue.size();
303  DISPATCH(finished());
304 // kDebug() << "(4) queue size " << dispatchQueue.size();
305  deref();
306 }
307 
308 /* --------------------------------------------------------------------- */
309 
310 void DataProtocol::mimetype(const KUrl &url) {
311  ref();
312  mimeType(parseDataHeader(url, true).mime_type);
313  finished();
314  deref();
315 }
316 
317 /* --------------------------------------------------------------------- */
KIO::DataSlave::sendMetaData
void sendMetaData()
Sends metadata set with setAllMetaData.
Definition: dataslave.cpp:170
KIO::DataProtocol::~DataProtocol
virtual ~DataProtocol()
Definition: dataprotocol.cpp:249
KIO::SlaveInterface::data
void data(const QByteArray &)
kdebug.h
kurl.h
QByteArray
KIO::DataProtocol::get
virtual void get(const KUrl &url)
Definition: dataprotocol.cpp:255
QChar
extract
static QString extract(const QByteArray &buf, int &pos, const char c1= '\0')
extracts the string between the current position pos and the first occurrence of either c1 or comma (...
Definition: dataprotocol.cpp:108
QByteArray::fromPercentEncoding
QByteArray fromPercentEncoding(const QByteArray &input, char percent)
ignoreWS
static void ignoreWS(const QString &buf, int &pos)
ignores all whitespaces
Definition: dataprotocol.cpp:122
parseQuotedString
static QString parseQuotedString(const QString &buf, int &pos)
parses a quoted string as per rfc 822.
Definition: dataprotocol.cpp:137
KIO::SlaveInterface::totalSize
void totalSize(KIO::filesize_t)
QByteArray::length
int length() const
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
global.h
DISPATCH
#define DISPATCH(f)
Definition: dataprotocol.cpp:37
KIO::MetaData
MetaData is a simple map of key/value strings.
Definition: global.h:396
KUrl
KIO::Slave::ref
void ref()
Definition: slave.cpp:235
KIO::DataSlave::setAllMetaData
void setAllMetaData(const MetaData &)
Sets metadata.
Definition: dataslave.cpp:166
KIO::SlaveInterface::finished
void finished()
kglobal.h
dataprotocol.h
KIO::Slave::deref
void deref()
Definition: slave.cpp:241
KIO::SlaveBase
There are two classes that specifies the protocol between application (job) and kioslave.
Definition: slavebase.h:50
QString::isEmpty
bool isEmpty() const
QString::trimmed
QString trimmed() const
QString
QChar::unicode
ushort unicode() const
QTextCodec
QByteArray::mid
QByteArray mid(int pos, int len) const
KIO::DataProtocol::DataProtocol
DataProtocol()
Definition: dataprotocol.cpp:242
QString::toLower
QString toLower() const
find
static int find(const QByteArray &buf, int begin, const char c1)
returns the position of the first occurrence of any of the given characters c1 or comma ('...
Definition: dataprotocol.cpp:85
QUrl::encodedPath
QByteArray encodedPath() const
QLatin1Char
KIO::SlaveInterface::mimeType
void mimeType(const QString &)
parseDataHeader
static DataHeader parseDataHeader(const KUrl &url, const bool mimeOnly)
parses the header of a data url
Definition: dataprotocol.cpp:166
KIO::DataProtocol::mimetype
virtual void mimetype(const KUrl &url)
Definition: dataprotocol.cpp:310
QByteArray::fromBase64
QByteArray fromBase64(const QByteArray &base64)
QTextCodec::codecForName
QTextCodec * codecForName(const QByteArray &name)
QString::length
int length() const
QString::reserve
void reserve(int size)
KGlobal::staticQString
const QString & staticQString(const char *str)
QMap< QString, QString >::ConstIterator
typedef ConstIterator
QByteArray::size
int size() const
QString::squeeze
void squeeze()
KComponentData
KIO::DataProtocol
This kioslave provides support of data urls as specified by rfc 2397.
Definition: dataprotocol.h:63
QTextCodec::toUnicode
QString toUnicode(const QByteArray &a) const
QString::toUtf8
QByteArray toUtf8() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:24:52 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs API Reference

Skip menu "kdelibs API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal