• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kio

dataprotocol.cpp

Go to the documentation of this file.
00001 //  dataprotocol.cpp
00002 // ==================
00003 //
00004 // Implementation of the data protocol (rfc 2397)
00005 //
00006 // Author: Leo Savernik
00007 // Email: l.savernik@aon.at
00008 // (C) 2002, 2003 by Leo Savernik
00009 // Created: Sam Dez 28 14:11:18 CET 2002
00010 
00011 /***************************************************************************
00012  *                                                                         *
00013  *   This program is free software; you can redistribute it and/or modify  *
00014  *   it under the terms of the GNU Lesser General Public License as        *
00015  *   published by the Free Software Foundation; version 2.                 *
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;        // mime type of content (lowercase)
00071   MetaData attributes;      // attribute/value pairs (attribute lowercase,
00072                 //  value unchanged)
00073   bool is_base64;       // true if data is base64 encoded
00074   QString url;          // reference to decoded url
00075   int data_offset;      // zero-indexed position within url
00076                 // where the real data begins. May point beyond
00077                     // the end to indicate that there is no data
00078   QString *charset;     // shortcut to charset (it always exists)
00079 };
00080 
00081 // constant string data
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   }/*wend*/
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++;        // jump over leading quote
00153   bool escaped = false; // if true means next character is literal
00154   bool parsing = true;  // true as long as end quote not found
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       }/*end switch*/
00166     }/*end if*/
00167   }/*wend*/
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   // initialize header info members
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   // decode url and save it
00189   QString &raw_url = header_info.url = QString::fromLatin1("data:") + url.path();
00190   int raw_url_len = (int)raw_url.length();
00191 
00192   // jump over scheme part (must be "data:", we don't even check that)
00193   header_info.data_offset = raw_url.find(':');
00194   header_info.data_offset++;    // jump over colon or to begin if scheme was missing
00195 
00196   // read mime type
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   // jump over delimiter token and return if data reached
00204   if (raw_url[header_info.data_offset++] == ',') return;
00205 
00206   // read all attributes and store them
00207   bool data_begin_reached = false;
00208   while (!data_begin_reached && header_info.data_offset < raw_url_len) {
00209     // read attribute
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       // no assigment, must be base64 option
00215       if (attribute == base64.string())
00216         header_info.is_base64 = true;
00217     } else {
00218       header_info.data_offset++; // jump over '=' token
00219 
00220       // read value
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       // add attribute to map
00233       header_info.attributes[attribute.lower()] = value;
00234 
00235     }/*end if*/
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++; // jump over separator token
00240   }/*wend*/
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   //kdDebug() << "===============================================================================================================================================================================" << endl;
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   // FIXME: string is copied, would be nice if we could have a reference only
00271   QString url_data = hdr.url.mid(data_ofs);
00272   QCString outData;
00273 
00274 #ifdef TESTKIO
00275 //  cout << "current charset: \"" << *hdr.charset << "\"" << endl;
00276 #endif
00277   if (hdr.is_base64) {
00278     // base64 stuff is expected to contain the correct charset, so we just
00279     // decode it and pass it to the receiver
00280     KCodecs::base64Decode(url_data.local8Bit(),outData);
00281   } else {
00282     // FIXME: This is all flawed, must be reworked thoroughly
00283     // non encoded data must be converted to the given charset
00284     QTextCodec *codec = QTextCodec::codecForName(hdr.charset->latin1());
00285     if (codec != 0) {
00286       outData = codec->fromUnicode(url_data);
00287     } else {
00288       // if there is no approprate codec, just use local encoding. This
00289       // should work for >90% of all cases.
00290       outData = url_data.local8Bit();
00291     }/*end if*/
00292   }/*end if*/
00293 
00294   //kdDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
00295   //kdDebug() << "emit mimeType@"<<this << endl ;
00296   mimeType(hdr.mime_type);
00297   //kdDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
00298   //kdDebug() << "emit totalSize@"<<this << endl ;
00299   totalSize(outData.size());
00300 
00301   //kdDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
00302   //kdDebug() << "emit setMetaData@"<<this << endl ;
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   }/*next it*/
00308 #else
00309   setAllMetaData(hdr.attributes);
00310 #endif
00311 
00312   //kdDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
00313   //kdDebug() << "emit sendMetaData@"<<this << endl ;
00314   sendMetaData();
00315   //kdDebug() << "^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C^[[C" << endl;
00316 //   kdDebug() << "(1) queue size " << dispatchQueue.size() << endl;
00317   // empiric studies have shown that this shouldn't be queued & dispatched
00318   /*DISPATCH*/(data(outData));
00319 //   kdDebug() << "(2) queue size " << dispatchQueue.size() << endl;
00320   DISPATCH(data(QByteArray()));
00321 //   kdDebug() << "(3) queue size " << dispatchQueue.size() << endl;
00322   DISPATCH(finished());
00323 //   kdDebug() << "(4) queue size " << dispatchQueue.size() << endl;
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 

kio

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

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal