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

KIO

  • 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
42using namespace KIO;
43#ifdef DATAKIOSLAVE
44extern "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
66struct 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
85static 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
108static 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
122static 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
137static 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
166static 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
239DataProtocol::DataProtocol(const QByteArray &pool_socket, const QByteArray &app_socket)
240 : SlaveBase("kio_data", pool_socket, app_socket) {
241#else
242DataProtocol::DataProtocol() {
243#endif
244 kDebug();
245}
246
247/* --------------------------------------------------------------------- */
248
249DataProtocol::~DataProtocol() {
250 kDebug();
251}
252
253/* --------------------------------------------------------------------- */
254
255void 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
310void DataProtocol::mimetype(const KUrl &url) {
311 ref();
312 mimeType(parseDataHeader(url, true).mime_type);
313 finished();
314 deref();
315}
316
317/* --------------------------------------------------------------------- */
KComponentData
KIO::DataProtocol
This kioslave provides support of data urls as specified by rfc 2397.
Definition: dataprotocol.h:63
KIO::DataProtocol::~DataProtocol
virtual ~DataProtocol()
Definition: dataprotocol.cpp:249
KIO::DataProtocol::DataProtocol
DataProtocol()
Definition: dataprotocol.cpp:242
KIO::DataProtocol::get
virtual void get(const KUrl &url)
Definition: dataprotocol.cpp:255
KIO::DataProtocol::mimetype
virtual void mimetype(const KUrl &url)
Definition: dataprotocol.cpp:310
KIO::DataSlave::setAllMetaData
void setAllMetaData(const MetaData &)
Sets metadata.
Definition: dataslave.cpp:166
KIO::DataSlave::sendMetaData
void sendMetaData()
Sends metadata set with setAllMetaData.
Definition: dataslave.cpp:170
KIO::MetaData
MetaData is a simple map of key/value strings.
Definition: global.h:397
KIO::SlaveBase
There are two classes that specifies the protocol between application (job) and kioslave.
Definition: slavebase.h:51
KIO::SlaveInterface::totalSize
void totalSize(KIO::filesize_t)
KIO::SlaveInterface::finished
void finished()
KIO::SlaveInterface::data
void data(const QByteArray &)
KIO::SlaveInterface::mimeType
void mimeType(const QString &)
KIO::Slave::ref
void ref()
Definition: slave.cpp:235
KIO::Slave::deref
void deref()
Definition: slave.cpp:241
KUrl
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
ignoreWS
static void ignoreWS(const QString &buf, int &pos)
ignores all whitespaces
Definition: dataprotocol.cpp:122
DISPATCH
#define DISPATCH(f)
Definition: dataprotocol.cpp:37
parseDataHeader
static DataHeader parseDataHeader(const KUrl &url, const bool mimeOnly)
parses the header of a data url
Definition: dataprotocol.cpp:166
parseQuotedString
static QString parseQuotedString(const QString &buf, int &pos)
parses a quoted string as per rfc 822.
Definition: dataprotocol.cpp:137
dataprotocol.h
global.h
kDebug
#define kDebug
kdebug.h
kglobal.h
kurl.h
KGlobal::staticQString
const QString & staticQString(const char *str)
KIO
A namespace for KIO globals.
Definition: kbookmarkmenu.h:55
find
KAction * find(const QObject *recvr, const char *slot, QObject *parent)
begin
const KShortcut & begin()
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 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-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 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
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