diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2013-01-27 01:04:16 -0600 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2013-01-27 01:04:16 -0600 |
commit | 5159cd2beb2e87806a5b54e9991b7895285c9d3e (patch) | |
tree | 9b70e8be47a390f8f4d56ead812ab0c9dad88709 /tdeio/tdeio/dataprotocol.cpp | |
parent | c17cb900dcf52b8bd6dc300d4f103392900ec2b4 (diff) | |
download | tdelibs-5159cd2beb2e87806a5b54e9991b7895285c9d3e.tar.gz tdelibs-5159cd2beb2e87806a5b54e9991b7895285c9d3e.zip |
Rename a number of libraries and executables to avoid conflicts with KDE4
Diffstat (limited to 'tdeio/tdeio/dataprotocol.cpp')
-rw-r--r-- | tdeio/tdeio/dataprotocol.cpp | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/tdeio/tdeio/dataprotocol.cpp b/tdeio/tdeio/dataprotocol.cpp new file mode 100644 index 000000000..acc7b28e9 --- /dev/null +++ b/tdeio/tdeio/dataprotocol.cpp @@ -0,0 +1,339 @@ +// dataprotocol.cpp +// ================== +// +// Implementation of the data protocol (rfc 2397) +// +// Author: Leo Savernik +// Email: l.savernik@aon.at +// (C) 2002, 2003 by Leo Savernik +// Created: Sam Dez 28 14:11:18 CET 2002 + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License as * + * published by the Free Software Foundation; version 2. * + * * + ***************************************************************************/ + +#include "dataprotocol.h" + +#include <kdebug.h> +#include <kmdcodec.h> +#include <kurl.h> +#include <tdeio/global.h> + +#include <tqcstring.h> +#include <tqstring.h> +#include <tqstringlist.h> +#include <tqtextcodec.h> + +#ifdef DATAKIOSLAVE +# include <kinstance.h> +# include <stdlib.h> +#endif +#ifdef TESTKIO +# include <iostream.h> +#endif + +#if !defined(DATAKIOSLAVE) && !defined(TESTKIO) +# define DISPATCH(f) dispatch_##f +#else +# define DISPATCH(f) f +#endif + +using namespace TDEIO; +#ifdef DATAKIOSLAVE +extern "C" { + + int kdemain( int argc, char **argv ) { + TDEInstance instance( "kio_data" ); + + kdDebug(7101) << "*** Starting kio_data " << endl; + + if (argc != 4) { + kdDebug(7101) << "Usage: kio_data protocol domain-socket1 domain-socket2" << endl; + exit(-1); + } + + DataProtocol slave(argv[2], argv[3]); + slave.dispatchLoop(); + + kdDebug(7101) << "*** kio_data Done" << endl; + return 0; + } +} +#endif + +/** structure containing header information */ +struct DataHeader { + TQString mime_type; // mime type of content (lowercase) + MetaData attributes; // attribute/value pairs (attribute lowercase, + // value unchanged) + bool is_base64; // true if data is base64 encoded + TQString url; // reference to decoded url + int data_offset; // zero-indexed position within url + // where the real data begins. May point beyond + // the end to indicate that there is no data + TQString *charset; // shortcut to charset (it always exists) +}; + +// constant string data +const TQChar text_plain_str[] = { 't','e','x','t','/','p','l','a','i','n' }; +const TQChar charset_str[] = { 'c','h','a','r','s','e','t' }; +const TQChar us_ascii_str[] = { 'u','s','-','a','s','c','i','i' }; +const TQChar base64_str[] = { 'b','a','s','e','6','4' }; + +/** returns the position of the first occurrence of any of the given characters + * @p c1 to @p c3 or buf.length() if none is contained. + * @param buf buffer where to look for c + * @param begin zero-indexed starting position + * @param c1 character to find + * @param c2 alternative character to find or '\0' to ignore + * @param c3 alternative character to find or '\0' to ignore + */ +static int find(const TQString &buf, int begin, TQChar c1, TQChar c2 = '\0', + TQChar c3 = '\0') { + int pos = begin; + int size = (int)buf.length(); + while (pos < size) { + TQChar ch = buf[pos]; + if (ch == c1 + || (c2 != '\0' && ch == c2) + || (c3 != '\0' && ch == c3)) + break; + pos++; + }/*wend*/ + return pos; +} + +/** extracts the string between the current position @p pos and the first + * occurrence of either @p c1 to @p c3 exclusively and updates @p pos + * to point at the found delimiter or at the end of the buffer if + * neither character occurred. + * @param buf buffer where to look for + * @param pos zero-indexed position within buffer + * @param c1 character to find + * @param c2 alternative character to find or 0 to ignore + * @param c3 alternative character to find or 0 to ignore + */ +inline TQString extract(const TQString &buf, int &pos, TQChar c1, + TQChar c2 = '\0', TQChar c3 = '\0') { + int oldpos = pos; + pos = find(buf,oldpos,c1,c2,c3); + return TQString(buf.unicode() + oldpos, pos - oldpos); +} + +/** ignores all whitespaces + * @param buf buffer to operate on + * @param pos position to shift to first non-whitespace character + * Upon return @p pos will either point to the first non-whitespace + * character or to the end of the buffer. + */ +inline void ignoreWS(const TQString &buf, int &pos) { + int size = (int)buf.length(); + TQChar ch = buf[pos]; + while (pos < size && (ch == ' ' || ch == '\t' || ch == '\n' + || ch == '\r')) + ch = buf[++pos]; +} + +/** parses a quoted string as per rfc 822. + * + * If trailing quote is missing, the whole rest of the buffer is returned. + * @param buf buffer to operate on + * @param pos position pointing to the leading quote + * @return the extracted string. @p pos will be updated to point to the + * character following the trailing quote. + */ +static TQString parseQuotedString(const TQString &buf, int &pos) { + int size = (int)buf.length(); + TQString res; + pos++; // jump over leading quote + bool escaped = false; // if true means next character is literal + bool parsing = true; // true as long as end quote not found + while (parsing && pos < size) { + TQChar ch = buf[pos++]; + if (escaped) { + res += ch; + escaped = false; + } else { + switch (ch) { + case '"': parsing = false; break; + case '\\': escaped = true; break; + default: res += ch; break; + }/*end switch*/ + }/*end if*/ + }/*wend*/ + return res; +} + +/** parses the header of a data url + * @param url the data url + * @param header_info fills the given DataHeader structure with the header + * information + */ +static void parseDataHeader(const KURL &url, DataHeader &header_info) { + TQConstString text_plain(text_plain_str,sizeof text_plain_str/sizeof text_plain_str[0]); + TQConstString charset(charset_str,sizeof charset_str/sizeof charset_str[0]); + TQConstString us_ascii(us_ascii_str,sizeof us_ascii_str/sizeof us_ascii_str[0]); + TQConstString base64(base64_str,sizeof base64_str/sizeof base64_str[0]); + // initialize header info members + header_info.mime_type = text_plain.string(); + header_info.charset = &header_info.attributes.insert( + charset.string(),us_ascii.string()) + .data(); + header_info.is_base64 = false; + + // decode url and save it + TQString &raw_url = header_info.url = TQString::fromLatin1("data:") + url.path(); + int raw_url_len = (int)raw_url.length(); + + // jump over scheme part (must be "data:", we don't even check that) + header_info.data_offset = raw_url.find(':'); + header_info.data_offset++; // jump over colon or to begin if scheme was missing + + // read mime type + if (header_info.data_offset >= raw_url_len) return; + TQString mime_type = extract(raw_url,header_info.data_offset,';',',') + .stripWhiteSpace(); + if (!mime_type.isEmpty()) header_info.mime_type = mime_type; + + if (header_info.data_offset >= raw_url_len) return; + // jump over delimiter token and return if data reached + if (raw_url[header_info.data_offset++] == ',') return; + + // read all attributes and store them + bool data_begin_reached = false; + while (!data_begin_reached && header_info.data_offset < raw_url_len) { + // read attribute + TQString attribute = extract(raw_url,header_info.data_offset,'=',';',',') + .stripWhiteSpace(); + if (header_info.data_offset >= raw_url_len + || raw_url[header_info.data_offset] != '=') { + // no assigment, must be base64 option + if (attribute == base64.string()) + header_info.is_base64 = true; + } else { + header_info.data_offset++; // jump over '=' token + + // read value + ignoreWS(raw_url,header_info.data_offset); + if (header_info.data_offset >= raw_url_len) return; + + TQString value; + if (raw_url[header_info.data_offset] == '"') { + value = parseQuotedString(raw_url,header_info.data_offset); + ignoreWS(raw_url,header_info.data_offset); + } else + value = extract(raw_url,header_info.data_offset,';',',') + .stripWhiteSpace(); + + // add attribute to map + header_info.attributes[attribute.lower()] = value; + + }/*end if*/ + if (header_info.data_offset < raw_url_len + && raw_url[header_info.data_offset] == ',') + data_begin_reached = true; + header_info.data_offset++; // jump over separator token + }/*wend*/ +} + +#ifdef DATAKIOSLAVE +DataProtocol::DataProtocol(const TQCString &pool_socket, const TQCString &app_socket) + : SlaveBase("kio_data", pool_socket, app_socket) { +#else +DataProtocol::DataProtocol() { +#endif + kdDebug() << "DataProtocol::DataProtocol()" << endl; +} + +/* --------------------------------------------------------------------- */ + +DataProtocol::~DataProtocol() { + kdDebug() << "DataProtocol::~DataProtocol()" << endl; +} + +/* --------------------------------------------------------------------- */ + +void DataProtocol::get(const KURL& url) { + ref(); + //kdDebug() << "===============================================================================================================================================================================" << endl; + kdDebug() << "kio_data@"<<this<<"::get(const KURL& url)" << endl ; + + DataHeader hdr; + parseDataHeader(url,hdr); + + int size = (int)hdr.url.length(); + int data_ofs = QMIN(hdr.data_offset,size); + // FIXME: string is copied, would be nice if we could have a reference only + TQString url_data = hdr.url.mid(data_ofs); + TQCString outData; + +#ifdef TESTKIO +// cout << "current charset: \"" << *hdr.charset << "\"" << endl; +#endif + if (hdr.is_base64) { + // base64 stuff is expected to contain the correct charset, so we just + // decode it and pass it to the receiver + KCodecs::base64Decode(url_data.local8Bit(),outData); + } else { + // FIXME: This is all flawed, must be reworked thoroughly + // non encoded data must be converted to the given charset + TQTextCodec *codec = TQTextCodec::codecForName(hdr.charset->latin1()); + if (codec != 0) { + outData = codec->fromUnicode(url_data); + } else { + // if there is no approprate codec, just use local encoding. This + // should work for >90% of all cases. + outData = url_data.local8Bit(); + }/*end if*/ + }/*end if*/ + + //kdDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; + //kdDebug() << "emit mimeType@"<<this << endl ; + mimeType(hdr.mime_type); + //kdDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; + //kdDebug() << "emit totalSize@"<<this << endl ; + totalSize(outData.size()); + + //kdDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; + //kdDebug() << "emit setMetaData@"<<this << endl ; +#if defined(TESTKIO) || defined(DATAKIOSLAVE) + MetaData::ConstIterator it; + for (it = hdr.attributes.begin(); it != hdr.attributes.end(); ++it) { + setMetaData(it.key(),it.data()); + }/*next it*/ +#else + setAllMetaData(hdr.attributes); +#endif + + //kdDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl; + //kdDebug() << "emit sendMetaData@"<<this << endl ; + sendMetaData(); + //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; +// kdDebug() << "(1) queue size " << dispatchQueue.size() << endl; + // empiric studies have shown that this shouldn't be queued & dispatched + /*DISPATCH*/(data(outData)); +// kdDebug() << "(2) queue size " << dispatchQueue.size() << endl; + DISPATCH(data(TQByteArray())); +// kdDebug() << "(3) queue size " << dispatchQueue.size() << endl; + DISPATCH(finished()); +// kdDebug() << "(4) queue size " << dispatchQueue.size() << endl; + deref(); +} + +/* --------------------------------------------------------------------- */ + +void DataProtocol::mimetype(const KURL &url) { + ref(); + DataHeader hdr; + parseDataHeader(url,hdr); + mimeType(hdr.mime_type); + finished(); + deref(); +} + +/* --------------------------------------------------------------------- */ + |