00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
#include "dataprotocol.h"
00020
00021
#include <kdebug.h>
00022
#include <kmdcodec.h>
00023
#include <kurl.h>
00024
#include <kio/global.h>
00025
00026
#include <qcstring.h>
00027
#include <qstring.h>
00028
#include <qtextcodec.h>
00029
00030
#ifdef DATAKIOSLAVE
00031
# include <kinstance.h>
00032
# include <stdlib.h>
00033
#endif
00034
#ifdef TESTKIO
00035
# include <iostream.h>
00036
#endif
00037
00038
#if !defined(DATAKIOSLAVE) && !defined(TESTKIO)
00039
# define DISPATCH(f) dispatch_##f
00040
#else
00041
# define DISPATCH(f) f
00042
#endif
00043
00044
using namespace KIO;
00045
#ifdef DATAKIOSLAVE
00046
extern "C" {
00047
00048
int kdemain(
int argc,
char **argv ) {
00049
KInstance instance(
"kio_data" );
00050
00051
kdDebug(7101) <<
"*** Starting kio_data " <<
endl;
00052
00053
if (argc != 4) {
00054
kdDebug(7101) <<
"Usage: kio_data protocol domain-socket1 domain-socket2" <<
endl;
00055 exit(-1);
00056 }
00057
00058
DataProtocol slave(argv[2], argv[3]);
00059 slave.dispatchLoop();
00060
00061
kdDebug(7101) <<
"*** kio_data Done" <<
endl;
00062
return 0;
00063 }
00064 }
00065
#endif
00066
00068
struct DataHeader {
00069
QString mime_type;
00070
MetaData attributes;
00071
00072
bool is_base64;
00073
QString url;
00074
int data_offset;
00075
00076
00077
QString *charset;
00078 };
00079
00080
00081
const QChar text_plain_str[] = {
't',
'e',
'x',
't',
'/',
'p',
'l',
'a',
'i',
'n' };
00082
const QChar charset_str[] = {
'c',
'h',
'a',
'r',
's',
'e',
't' };
00083
const QChar us_ascii_str[] = {
'u',
's',
'-',
'a',
's',
'c',
'i',
'i' };
00084
const QChar base64_str[] = {
'b',
'a',
's',
'e',
'6',
'4' };
00085
00094
static int find(
const QString &buf,
int begin,
QChar c1,
QChar c2 =
'\0',
00095
QChar c3 =
'\0') {
00096
int pos = begin;
00097
int size = (
int)buf.
length();
00098
while (pos < size) {
00099
QChar ch = buf[pos];
00100
if (ch == c1
00101 || (c2 !=
'\0' && ch == c2)
00102 || (c3 !=
'\0' && ch == c3))
00103
break;
00104 pos++;
00105 }
00106
return pos;
00107 }
00108
00119
inline QString extract(
const QString &buf,
int &pos,
QChar c1,
00120
QChar c2 =
'\0',
QChar c3 =
'\0') {
00121
int oldpos = pos;
00122 pos =
find(buf,oldpos,c1,c2,c3);
00123
return QString(buf.
unicode() + oldpos, pos - oldpos);
00124 }
00125
00132
inline void ignoreWS(
const QString &buf,
int &pos) {
00133
int size = (
int)buf.
length();
00134
QChar ch = buf[pos];
00135
while (pos < size && (ch ==
' ' || ch ==
'\t' || ch ==
'\n'
00136 || ch ==
'\r'))
00137 ch = buf[++pos];
00138 }
00139
00148
static QString parseQuotedString(
const QString &buf,
int &pos) {
00149
int size = (
int)buf.
length();
00150
QString res;
00151 pos++;
00152
bool escaped =
false;
00153
bool parsing =
true;
00154
while (parsing && pos < size) {
00155
QChar ch = buf[pos++];
00156
if (escaped) {
00157 res += ch;
00158 escaped =
false;
00159 }
else {
00160
switch (ch) {
00161
case '"': parsing =
false;
break;
00162
case '\\': escaped =
true;
break;
00163
default: res += ch;
break;
00164 }
00165 }
00166 }
00167
return res;
00168 }
00169
00175
static void parseDataHeader(
const KURL &url, DataHeader &header_info) {
00176
QConstString text_plain(text_plain_str,
sizeof text_plain_str/
sizeof text_plain_str[0]);
00177
QConstString charset(charset_str,
sizeof charset_str/
sizeof charset_str[0]);
00178
QConstString us_ascii(us_ascii_str,
sizeof us_ascii_str/
sizeof us_ascii_str[0]);
00179
QConstString base64(base64_str,
sizeof base64_str/
sizeof base64_str[0]);
00180
00181 header_info.mime_type = text_plain.
string();
00182 header_info.charset = &header_info.attributes.insert(
00183 charset.
string(),us_ascii.
string())
00184 .data();
00185 header_info.is_base64 =
false;
00186
00187
00188
QString &raw_url = header_info.url =
KURL::decode_string(url.
url());
00189
int raw_url_len = (
int)raw_url.
length();
00190
00191
00192 header_info.data_offset = raw_url.
find(
':');
00193 header_info.data_offset++;
00194
00195
00196
if (header_info.data_offset >= raw_url_len)
return;
00197
QString mime_type = extract(raw_url,header_info.data_offset,
';',
',')
00198 .
stripWhiteSpace();
00199
if (!mime_type.
isEmpty()) header_info.mime_type = mime_type;
00200
00201
if (header_info.data_offset >= raw_url_len)
return;
00202
00203
if (raw_url[header_info.data_offset++] ==
',')
return;
00204
00205
00206
bool data_begin_reached =
false;
00207
while (!data_begin_reached && header_info.data_offset < raw_url_len) {
00208
00209
QString attribute = extract(raw_url,header_info.data_offset,
'=',
';',
',')
00210 .
stripWhiteSpace();
00211
if (header_info.data_offset >= raw_url_len
00212 || raw_url[header_info.data_offset] !=
'=') {
00213
00214
if (attribute == base64.
string())
00215 header_info.is_base64 =
true;
00216 }
else {
00217 header_info.data_offset++;
00218
00219
00220 ignoreWS(raw_url,header_info.data_offset);
00221
if (header_info.data_offset >= raw_url_len)
return;
00222
00223
QString value;
00224
if (raw_url[header_info.data_offset] ==
'"') {
00225 value = parseQuotedString(raw_url,header_info.data_offset);
00226 ignoreWS(raw_url,header_info.data_offset);
00227 }
else
00228 value = extract(raw_url,header_info.data_offset,
';',
',')
00229 .
stripWhiteSpace();
00230
00231
00232 header_info.attributes[attribute.
lower()] = value;
00233
00234 }
00235
if (header_info.data_offset < raw_url_len
00236 && raw_url[header_info.data_offset] ==
',')
00237 data_begin_reached =
true;
00238 header_info.data_offset++;
00239 }
00240 }
00241
00242
#ifdef DATAKIOSLAVE
00243
DataProtocol::DataProtocol(
const QCString &pool_socket,
const QCString &app_socket)
00244 :
SlaveBase("kio_data", pool_socket, app_socket) {
00245
#else
00246
DataProtocol::DataProtocol() {
00247
#endif
00248
kdDebug() <<
"DataProtocol::DataProtocol()" <<
endl;
00249 }
00250
00251
00252
00253 DataProtocol::~DataProtocol() {
00254
kdDebug() <<
"DataProtocol::~DataProtocol()" <<
endl;
00255 }
00256
00257
00258
00259
void DataProtocol::get(
const KURL& url) {
00260
00261
kdDebug() <<
"kio_data@"<<
this<<
"::get(const KURL& url)" <<
endl ;
00262
00263 DataHeader hdr;
00264 parseDataHeader(url,hdr);
00265
00266
int size = (
int)hdr.url.length();
00267
int data_ofs = QMIN(hdr.data_offset,size);
00268
00269
QString url_data = hdr.url.mid(data_ofs);
00270
QCString outData;
00271
00272
#ifdef TESTKIO
00273
00274
#endif
00275
if (hdr.is_base64) {
00276
00277
00278
KCodecs::base64Decode(url_data.
local8Bit(),outData);
00279 }
else {
00280
00281
00282
QTextCodec *codec =
QTextCodec::codecForName(hdr.charset->latin1());
00283
if (codec != 0) {
00284 outData = codec->
fromUnicode(url_data);
00285 }
else {
00286
00287
00288 outData = url_data.
local8Bit();
00289 }
00290 }
00291
00292
00293
00294 mimeType(hdr.mime_type);
00295
00296
00297 totalSize(outData.size());
00298
00299
00300
00301
#if defined(TESTKIO) || defined(DATAKIOSLAVE)
00302
MetaData::ConstIterator it;
00303
for (it = hdr.attributes.begin(); it != hdr.attributes.end(); ++it) {
00304 setMetaData(it.key(),it.data());
00305 }
00306
#else
00307
setAllMetaData(hdr.attributes);
00308
#endif
00309
00310
00311
00312
sendMetaData();
00313
00314
00315
00316 (data(outData));
00317
00318 DISPATCH(data(
QByteArray()));
00319
00320 DISPATCH(finished());
00321
00322 }
00323
00324
00325
00326
void DataProtocol::mimetype(
const KURL &url) {
00327 DataHeader hdr;
00328 parseDataHeader(url,hdr);
00329 mimeType(hdr.mime_type);
00330 finished();
00331 }
00332
00333
00334