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