|
|
|
@ -10,8 +10,11 @@
|
|
|
|
|
|
|
|
|
|
#include "tdeio_gopher.h"
|
|
|
|
|
|
|
|
|
|
#include <kcodecs.h>
|
|
|
|
|
#include <kcomponentdata.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>
|
|
|
|
@ -25,7 +28,7 @@ extern "C"
|
|
|
|
|
{
|
|
|
|
|
int KDE_EXPORT kdemain( int argc, char **argv )
|
|
|
|
|
{
|
|
|
|
|
TDEComponentData instance( "tdeio_gopher" );
|
|
|
|
|
TDEInstance instance( "tdeio_gopher" );
|
|
|
|
|
|
|
|
|
|
if (argc != 4)
|
|
|
|
|
{
|
|
|
|
@ -33,19 +36,21 @@ extern "C"
|
|
|
|
|
exit(-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gopher slave(argv[2], argv[3]);
|
|
|
|
|
GopherProtocol slave(argv[2], argv[3]);
|
|
|
|
|
slave.dispatchLoop();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* gopher */
|
|
|
|
|
|
|
|
|
|
gopher::gopher(const TQByteArray &pool_socket, const TQByteArray &app_socket) : TCPSlaveBase("gopher", pool_socket, app_socket)
|
|
|
|
|
GopherProtocol::GopherProtocol(const TQCString &pool_socket, const TQCString &app_socket)
|
|
|
|
|
: TCPSlaveBase(70, "gopher", pool_socket, app_socket)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void gopher::get(const KUrl& url )
|
|
|
|
|
void GopherProtocol::get(const KURL& url )
|
|
|
|
|
{
|
|
|
|
|
// gopher urls are
|
|
|
|
|
// gopher://<host>:<port>/<gopher-path>
|
|
|
|
@ -68,14 +73,14 @@ void gopher::get(const KUrl& url )
|
|
|
|
|
if (url.port() > 0) port = url.port();
|
|
|
|
|
else port = 70;
|
|
|
|
|
|
|
|
|
|
setBlockConnection(true);
|
|
|
|
|
|
|
|
|
|
// connect to the host
|
|
|
|
|
if (!connectToHost("gopher", url.host(), port)) return;
|
|
|
|
|
|
|
|
|
|
setBlocking(true);
|
|
|
|
|
if (!connectToHost(url.host(), port)) return;
|
|
|
|
|
|
|
|
|
|
if (type == '7' && query.isNull())
|
|
|
|
|
{
|
|
|
|
|
disconnectFromHost();
|
|
|
|
|
closeDescriptor();
|
|
|
|
|
handleSearch(url.host(), path, port);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
@ -83,102 +88,103 @@ void gopher::get(const KUrl& url )
|
|
|
|
|
int i, bytes;
|
|
|
|
|
char aux[10240];
|
|
|
|
|
TQBuffer received;
|
|
|
|
|
received.open(TQIODevice::WriteOnly);
|
|
|
|
|
received.open(IO_WriteOnly);
|
|
|
|
|
|
|
|
|
|
infoMessage(i18n("Connecting to %1...", url.host()));
|
|
|
|
|
infoMessage(i18n("%1 contacted. Retrieving data...", url.host()));
|
|
|
|
|
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.toLatin1(), path.length());
|
|
|
|
|
write(query.toLatin1(), query.length());
|
|
|
|
|
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.write(aux, i);
|
|
|
|
|
received.writeBlock(aux, i);
|
|
|
|
|
processedSize(bytes);
|
|
|
|
|
infoMessage(i18n("Retrieved %1 bytes from %2...", bytes, url.host()));
|
|
|
|
|
infoMessage(i18n("Retrieved %1 bytes from %2...").arg(bytes).arg(url.host()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (type == '1' || type =='7') processDirectory(new TQByteArray(received.buffer().data(), bytes + 1), url.host(), url.path());
|
|
|
|
|
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());
|
|
|
|
|
}
|
|
|
|
|
disconnectFromHost();
|
|
|
|
|
closeDescriptor();
|
|
|
|
|
}
|
|
|
|
|
finished();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void gopher::processDirectory(TQByteArray *received, const TQString &host, const TQString &path)
|
|
|
|
|
void GopherProtocol::processDirectory(const TQString &received_str, const TQString &host, const TQString &path)
|
|
|
|
|
{
|
|
|
|
|
int i, remove;
|
|
|
|
|
TQString received(received_str);
|
|
|
|
|
TQString pathToShow;
|
|
|
|
|
TQByteArray show;
|
|
|
|
|
TQByteArray info;
|
|
|
|
|
if (path == "/" || path == "/1") pathToShow = "";
|
|
|
|
|
else pathToShow = path;
|
|
|
|
|
if (path == "/" || path == "/1")
|
|
|
|
|
{
|
|
|
|
|
pathToShow = "";
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
pathToShow = path;
|
|
|
|
|
}
|
|
|
|
|
mimeType("text/html");
|
|
|
|
|
show.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n");
|
|
|
|
|
show.append("<html xmlns=\"http://www.w3.org/1999/xhtml\">\n");
|
|
|
|
|
show.append("\t<head>\n");
|
|
|
|
|
show.append("\t\t<title>");
|
|
|
|
|
show.append(host.toUtf8());
|
|
|
|
|
show.append(pathToShow.toUtf8());
|
|
|
|
|
show.append("</title>\n");
|
|
|
|
|
show.append("\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n");
|
|
|
|
|
show.append("\t\t<style type=\"text/css\">\n");
|
|
|
|
|
show.append("\t\t\t.info{ font-size : small; display : block; font-family : monospace; white-space : pre; margin-left : 18px; }\n");
|
|
|
|
|
show.append("\t\t</style>\n");
|
|
|
|
|
show.append("\t</head>\n");
|
|
|
|
|
show.append("\t<body>\n");
|
|
|
|
|
show.append("\t\t<h1>");
|
|
|
|
|
show.append(host.toUtf8());
|
|
|
|
|
show.append(pathToShow.toUtf8());
|
|
|
|
|
show.append("</h1>\n");
|
|
|
|
|
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);
|
|
|
|
|
processDirectoryLine(received.left(i), show, info);
|
|
|
|
|
received.remove(0, i + remove);
|
|
|
|
|
findLine(received, &i, &remove);
|
|
|
|
|
}
|
|
|
|
|
show.append("\t</body>\n");
|
|
|
|
|
show.append("</html>\n");
|
|
|
|
|
data(show);
|
|
|
|
|
delete received;
|
|
|
|
|
show += "\t</body>\n</html>\n";
|
|
|
|
|
TQByteArray showdata;
|
|
|
|
|
showdata.duplicate(show.utf8(), show.length());
|
|
|
|
|
data(showdata);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void gopher::processDirectoryLine(const TQByteArray &d, TQByteArray &show, TQByteArray &info)
|
|
|
|
|
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;
|
|
|
|
|
TQByteArray type, name, url, server, port;
|
|
|
|
|
TQByteArray data = d;
|
|
|
|
|
TQString data(d);
|
|
|
|
|
|
|
|
|
|
type = data.left(1);
|
|
|
|
|
TQString type = data.left(1);
|
|
|
|
|
data.remove(0, 1);
|
|
|
|
|
|
|
|
|
|
i = data.indexOf("\t");
|
|
|
|
|
name = data.left(i);
|
|
|
|
|
i = data.find("\t");
|
|
|
|
|
TQString name = data.left(i);
|
|
|
|
|
data.remove(0, i + 1);
|
|
|
|
|
|
|
|
|
|
i = data.indexOf("\t");
|
|
|
|
|
url = data.left(i);
|
|
|
|
|
i = data.find("\t");
|
|
|
|
|
TQString url = data.left(i);
|
|
|
|
|
data.remove(0, i + 1);
|
|
|
|
|
|
|
|
|
|
i = data.indexOf("\t");
|
|
|
|
|
server = data.left(i);
|
|
|
|
|
i = data.find("\t");
|
|
|
|
|
TQString server = data.left(i);
|
|
|
|
|
data.remove(0, i + 1);
|
|
|
|
|
|
|
|
|
|
port = parsePort(&data);
|
|
|
|
|
TQString port = parsePort(data);
|
|
|
|
|
|
|
|
|
|
if (type == "i")
|
|
|
|
|
{
|
|
|
|
@ -215,8 +221,8 @@ void gopher::processDirectoryLine(const TQByteArray &d, TQByteArray &show, TQByt
|
|
|
|
|
show.append("\t\t\t<div>");
|
|
|
|
|
// support the non-standard extension for URL to external sites
|
|
|
|
|
// in this case, url begins with 'URL:'
|
|
|
|
|
TQByteArray finalUrl;
|
|
|
|
|
TQByteArray iconUrl;
|
|
|
|
|
TQString finalUrl;
|
|
|
|
|
TQString iconUrl;
|
|
|
|
|
if (url.startsWith("URL:"))
|
|
|
|
|
{
|
|
|
|
|
finalUrl = url.mid(4);
|
|
|
|
@ -243,30 +249,32 @@ void gopher::processDirectoryLine(const TQByteArray &d, TQByteArray &show, TQByt
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TQByteArray gopher::parsePort(TQByteArray *received)
|
|
|
|
|
TQString GopherProtocol::parsePort(TQString &received)
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
|
|
|
|
TQByteArray port;
|
|
|
|
|
uint i = 0;
|
|
|
|
|
TQString port;
|
|
|
|
|
bool found = false;
|
|
|
|
|
TQChar c;
|
|
|
|
|
while (!found && i < received -> size())
|
|
|
|
|
while (!found && i < received.length())
|
|
|
|
|
{
|
|
|
|
|
c = received -> at(i);
|
|
|
|
|
if (c.isDigit()) i++;
|
|
|
|
|
else found = true;
|
|
|
|
|
c = received[i];
|
|
|
|
|
if (c.isDigit())
|
|
|
|
|
i++;
|
|
|
|
|
else
|
|
|
|
|
found = true;
|
|
|
|
|
}
|
|
|
|
|
port = received -> left(i);
|
|
|
|
|
received -> remove(0, i);
|
|
|
|
|
port = received.left(i);
|
|
|
|
|
received.remove(0, i);
|
|
|
|
|
return port;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void gopher::findLine(TQByteArray *received, int *i, int *remove)
|
|
|
|
|
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 -> indexOf("\r\n");
|
|
|
|
|
aux2 = received -> indexOf("\n");
|
|
|
|
|
aux = received.find("\r\n");
|
|
|
|
|
aux2 = received.find("\n");
|
|
|
|
|
|
|
|
|
|
if (aux == -1)
|
|
|
|
|
{
|
|
|
|
@ -288,49 +296,34 @@ void gopher::findLine(TQByteArray *received, int *i, int *remove)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void gopher::handleSearch(const TQString &host, const TQString &path, int port)
|
|
|
|
|
void GopherProtocol::handleSearch(const TQString &host, const TQString &path, int port)
|
|
|
|
|
{
|
|
|
|
|
TQByteArray show;
|
|
|
|
|
TQString sPort;
|
|
|
|
|
if (port != 70) sPort = ':' + TQString::number(port);
|
|
|
|
|
mimeType("text/html");
|
|
|
|
|
show.append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n");
|
|
|
|
|
show.append("<html xmlns=\"http://www.w3.org/1999/xhtml\">\n");
|
|
|
|
|
show.append("\t<head>\n");
|
|
|
|
|
show.append("\t\t<title>");
|
|
|
|
|
show.append(host.toUtf8());
|
|
|
|
|
show.append(path.toUtf8());
|
|
|
|
|
show.append("</title>\n");
|
|
|
|
|
show.append("\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n");
|
|
|
|
|
show.append("\t\t<script type=\"text/javascript\">\n");
|
|
|
|
|
show.append("\t\t\tfunction search()\n");
|
|
|
|
|
show.append("\t\t\t{\n");
|
|
|
|
|
show.append("\t\t\t\tdocument.location = 'gopher://");
|
|
|
|
|
show.append(host.toUtf8());
|
|
|
|
|
show.append(sPort.toUtf8());
|
|
|
|
|
show.append(path.toUtf8());
|
|
|
|
|
show.append("?' + document.getElementById('what').value;\n");
|
|
|
|
|
show.append("\t\t\t}\n");
|
|
|
|
|
show.append("\t\t</script>\n");
|
|
|
|
|
show.append("\t</head>\n");
|
|
|
|
|
show.append("\t<body>\n");
|
|
|
|
|
show.append("\t\t<h1>");
|
|
|
|
|
show.append(host.toUtf8());
|
|
|
|
|
show.append(path.toUtf8());
|
|
|
|
|
show.append("</h1>\n");
|
|
|
|
|
show.append("\t\t");
|
|
|
|
|
show.append(i18n("Enter a search term:").toUtf8());
|
|
|
|
|
show.append("<br />\n");
|
|
|
|
|
show.append("\t\t<input id=\"what\" type=\"text\">\n");
|
|
|
|
|
show.append("\t\t<input type=\"button\" value=\"");
|
|
|
|
|
show.append(i18nc("Text on a search button, like at a search engine", "Search").toUtf8());
|
|
|
|
|
show.append("\" onClick=\"search()\">\n");
|
|
|
|
|
show.append("\t</body>\n");
|
|
|
|
|
show.append("</html>\n");
|
|
|
|
|
data(show);
|
|
|
|
|
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 gopher::addIcon(const TQString &type, const TQByteArray &url, TQByteArray &show)
|
|
|
|
|
void GopherProtocol::addIcon(const TQString &type, const TQString &url, TQString &show)
|
|
|
|
|
{
|
|
|
|
|
TQString icon;
|
|
|
|
|
if (type == "1") icon = "inode-directory.png";
|
|
|
|
@ -340,11 +333,11 @@ void gopher::addIcon(const TQString &type, const TQByteArray &url, TQByteArray &
|
|
|
|
|
else if (type == "I") icon = "image-x-generic.png";
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
KMimeType::Ptr mime = KMimeType::findByUrl(KUrl(url), 0, false, true);
|
|
|
|
|
icon = mime->iconName();
|
|
|
|
|
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(TQIODevice::ReadOnly);
|
|
|
|
|
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));
|