diff options
author | Michele Calgaro <[email protected]> | 2018-08-26 00:18:56 +0900 |
---|---|---|
committer | Michele Calgaro <[email protected]> | 2018-08-26 00:18:56 +0900 |
commit | a18f9fcc94b6982fecb8b75ccb5c21b213e78706 (patch) | |
tree | db1e3d87eaba2952829717f25a51e9b7a5c18d8c /src/tdeio_gopher.cpp | |
parent | 3eaf665507fb178a718ef9f57f2bb9ec908d5ac8 (diff) | |
download | tdeio-gopher-a18f9fcc94b6982fecb8b75ccb5c21b213e78706.tar.gz tdeio-gopher-a18f9fcc94b6982fecb8b75ccb5c21b213e78706.zip |
Adapted to TDE and TQt3. Build and work fine. No helpbook or
translation are built yet.
Signed-off-by: Michele Calgaro <[email protected]>
Diffstat (limited to 'src/tdeio_gopher.cpp')
-rw-r--r-- | src/tdeio_gopher.cpp | 345 |
1 files changed, 345 insertions, 0 deletions
diff --git a/src/tdeio_gopher.cpp b/src/tdeio_gopher.cpp new file mode 100644 index 0000000..cbfdd33 --- /dev/null +++ b/src/tdeio_gopher.cpp @@ -0,0 +1,345 @@ +/**************************************************************************** + * Copyright (C) 2003-2008 by Albert Astals Cid * + * [email protected] * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ****************************************************************************/ + +#include "tdeio_gopher.h" + +#include <stdlib.h> +#include <kurl.h> +#include <kdebug.h> +#include <kmdcodec.h> +#include <kinstance.h> +#include <kdebug.h> +#include <tdelocale.h> +#include <kmimetype.h> + +#include <ntqbuffer.h> +#include <ntqfile.h> + +using namespace TDEIO; + +extern "C" +{ + int KDE_EXPORT kdemain( int argc, char **argv ) + { + TDEInstance instance( "tdeio_gopher" ); + + if (argc != 4) + { + fprintf(stderr, "Usage: tdeio_gopher protocol domain-socket1 domain-socket2\n"); + exit(-1); + } + + GopherProtocol slave(argv[2], argv[3]); + slave.dispatchLoop(); + return 0; + } +} + + +/* gopher */ + +GopherProtocol::GopherProtocol(const TQCString &pool_socket, const TQCString &app_socket) + : TCPSlaveBase(70, "gopher", pool_socket, app_socket) +{ +} + +void GopherProtocol::get(const KURL& url ) +{ + // gopher urls are + // gopher://<host>:<port>/<gopher-path> + // + // where <gopher-path> is one of + // + // <gophertype><selector> + // <gophertype><selector>%09<search> + // <gophertype><selector>%09<search>%09<gopher+_string> + int port; + TQChar type; + TQString path(url.path()); + TQString query(url.query()); + + // determine the type + if (path != "/" && path != "") type = path[1]; + else type = '1'; + + // determine the port + if (url.port() > 0) port = url.port(); + else port = 70; + + setBlockConnection(true); + + // connect to the host + if (!connectToHost(url.host(), port)) return; + + if (type == '7' && query.isNull()) + { + closeDescriptor(); + handleSearch(url.host(), path, port); + } + else + { + int i, bytes; + char aux[10240]; + TQBuffer received; + received.open(IO_WriteOnly); + + infoMessage(i18n("Connecting to %1...").arg(url.host())); + infoMessage(i18n("%1 contacted. Retrieving data...").arg(url.host())); + bytes = 0; + + // send the selector + path.remove(0, 2); + write(path.latin1(), path.length()); + write(query.latin1(), query.length()); + write("\r\n", 2); + + // read the data + while((i = read(aux, 10240)) > 0) + { + bytes += i; + received.writeBlock(aux, i); + processedSize(bytes); + infoMessage(i18n("Retrieved %1 bytes from %2...").arg(bytes).arg(url.host())); + } + + if (type == '1' || type =='7') + { + processDirectory(received.buffer().data(), url.host(), url.path()); + } + else + { + KMimeType::Ptr result = KMimeType::findByContent(received.buffer()); + mimeType(result->name()); + data(received.buffer()); + } + closeDescriptor(); + } + finished(); +} + +void GopherProtocol::processDirectory(const TQString &received_str, const TQString &host, const TQString &path) +{ + TQString received(received_str); + TQString pathToShow; + if (path == "/" || path == "/1") + { + pathToShow = ""; + } + else + { + pathToShow = path; + } + mimeType("text/html"); + TQString info; + TQString show("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n" + "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\t<head>\n\t\t<title>"); + show += host.utf8(); + show += pathToShow.utf8(); + show += TQString("</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n" + "\t\t<style type=\"text/css\">\n\t\t\t.info{ font-size : small; display : block; font-family : monospace; " + "white-space : pre; margin-left : 18px; }\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<h1>"); + show += host.utf8(); + show += pathToShow.utf8(); + show += "</h1>\n"; + int i, remove; + findLine(received, &i, &remove); + while(i != -1) + { + processDirectoryLine(received.left(i), show, info); + received.remove(0, i + remove); + findLine(received, &i, &remove); + } + show += "\t</body>\n</html>\n"; + TQByteArray showdata; + showdata.duplicate(show.utf8(), show.length()); + data(showdata); +} + +void GopherProtocol::processDirectoryLine(const TQString &d, TQString &show, TQString &info) +{ + // gopher <type><display><tab><selector><tab><server><tab><port><\r><\n> + // gopher+ <type><display><tab><selector><tab><server><tab><port><tab><things><\r><\n> + int i; + TQString data(d); + + TQString type = data.left(1); + data.remove(0, 1); + + i = data.find("\t"); + TQString name = data.left(i); + data.remove(0, i + 1); + + i = data.find("\t"); + TQString url = data.left(i); + data.remove(0, i + 1); + + i = data.find("\t"); + TQString server = data.left(i); + data.remove(0, i + 1); + + TQString port = parsePort(data); + + if (type == "i") + { + if (!info.isEmpty()) + info.append("\n"); + info.append(name); + } + else + { + if (!info.isEmpty()) + { + show.append("\t\t<div class=\"info\">"); + show.append(info); + show.append("</div>\n"); + info = ""; + } + // it's the final line, ignore it + if (type == ".") return; + // those are the standard gopher types defined in the rfc + // 0 Item is a file + // 1 Item is a directory + // 2 Item is a CSO phone-book server + // 3 Error + // 4 Item is a BinHexed Macintosh file. + // 5 Item is DOS binary archive of some sort. Client must read until the TCP connection closes. Beware. + // 6 Item is a UNIX uuencoded file. + // 7 Item is an Index-Search server. + // 8 Item points to a text-based telnet session. + // 9 Item is a binary file! Client must read until the TCP connection closes. Beware. + // + Item is a redundant server + // T Item points to a text-based tn3270 session. + // g Item is a GIF format graphics file. + // I Item is some kind of image file. Client decides how to display. + show.append("\t\t\t<div>"); + // support the non-standard extension for URL to external sites + // in this case, url begins with 'URL:' + TQString finalUrl; + TQString iconUrl; + if (url.startsWith("URL:")) + { + finalUrl = url.mid(4); + iconUrl = finalUrl; + } + else + { + finalUrl = "gopher://" + server; + if (port != "70") + { + finalUrl.append(":"); + finalUrl.append(port); + } + finalUrl.append('/' + type + url); + iconUrl = url; + } + show.append("\t\t\t\t<a href=\""); + show.append(finalUrl); + show.append("\">"); + addIcon(type, iconUrl, show); + show.append(name); + show.append("</a><br />\n"); + show.append("\t\t\t</div>"); + } +} + +TQString GopherProtocol::parsePort(TQString &received) +{ + uint i = 0; + TQString port; + bool found = false; + TQChar c; + while (!found && i < received.length()) + { + c = received[i]; + if (c.isDigit()) + i++; + else + found = true; + } + port = received.left(i); + received.remove(0, i); + return port; +} + +void GopherProtocol::findLine(const TQString &received, int *i, int *remove) +{ + // it's not in the rfc but most servers don't follow the spec + // find lines ending only in \n and in \r\n + int aux, aux2; + aux = received.find("\r\n"); + aux2 = received.find("\n"); + + if (aux == -1) + { + *i = aux2; + *remove = 1; + } + else + { + if (aux2 < aux) + { + *remove = 1; + *i = aux2; + } + else + { + *remove = 2; + *i = aux; + } + } +} + +void GopherProtocol::handleSearch(const TQString &host, const TQString &path, int port) +{ + TQString sPort; + if (port != 70) sPort = ':' + TQString::number(port); + mimeType("text/html"); + TQString show("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n" + "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n\t<head>\n\t\t<title>"); + show += host.utf8(); + show += path.utf8(); + show += "</title>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n" + "\t\t<script type=\"text/javascript\">\n\t\t\tfunction search()\n\t\t\t{\n\t\t\t\tdocument.location = 'gopher://"; + show += host.utf8(); + show += sPort.utf8(); + show += path.utf8(); + show += "?' + document.getElementById('what').value;\n\t\t\t}\n\t\t</script>\n\t</head>\n\t<body>\n\t\t<h1>"; + show.append(host.utf8()); + show.append(path.utf8()); + show += "</h1>\n\t\t"; + show += i18n("Enter a search term:").utf8(); + show += "<br />\n\t\t<input id=\"what\" type=\"text\">\n\t\t<input type=\"button\" value=\""; + show += i18n("Text on a search button, like at a search engine", "Search").utf8(); + show += "\" onClick=\"search()\">\n\t</body>\n</html>\n"; + TQByteArray showdata; + showdata.duplicate(show.utf8(), show.length()); + data(showdata); +} + +void GopherProtocol::addIcon(const TQString &type, const TQString &url, TQString &show) +{ + TQString icon; + if (type == "1") icon = "inode-directory.png"; + else if (type == "3") icon = "dialog-error.png"; + else if (type == "7") icon = "system-search.png"; + else if (type == "g") icon = "image-gif.png"; + else if (type == "I") icon = "image-x-generic.png"; + else + { + KMimeType::Ptr mime = KMimeType::findByURL(KURL(url), 0, false, true); + icon = mime->icon(TQString::null, false); + } + TQFile file(m_iconLoader.iconPath(icon, -16)); + file.open(IO_ReadOnly); + TQByteArray ba = file.readAll(); + show.append("<img width=\"16\" height=\"16\" src=\"data:image/png;base64,"); + show.append(KCodecs::base64Encode(ba)); + show.append("\" /> "); +} |