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