Browse Source

- Allow to download torrents from a local file (Web UI)

adaptive-webui-19844
Christophe Dumez 17 years ago
parent
commit
b9c4a434c9
  1. 31
      src/httpconnection.cpp
  2. 1
      src/httpconnection.h
  3. 19
      src/httprequestparser.cpp
  4. 8
      src/httprequestparser.h
  5. 1
      src/httpserver.cpp
  6. 1
      src/webui.qrc
  7. 2
      src/webui/index.html
  8. 17
      src/webui/scripts/mocha-events.js
  9. 21
      src/webui/upload.html

31
src/httpconnection.cpp

@ -30,6 +30,7 @@
#include <QHttpResponseHeader> #include <QHttpResponseHeader>
#include <QFile> #include <QFile>
#include <QDebug> #include <QDebug>
#include <QTemporaryFile>
HttpConnection::HttpConnection(QTcpSocket *socket, HttpServer *parent) HttpConnection::HttpConnection(QTcpSocket *socket, HttpServer *parent)
: QObject(parent), socket(socket), parent(parent) : QObject(parent), socket(socket), parent(parent)
@ -45,11 +46,17 @@ HttpConnection::~HttpConnection()
void HttpConnection::read() void HttpConnection::read()
{ {
QString input = socket->readAll(); QByteArray input = socket->readAll();
qDebug(" -------"); qDebug(" -------");
qDebug("|REQUEST|"); qDebug("|REQUEST|");
qDebug(" -------"); qDebug(" -------");
qDebug("%s", input.toAscii().constData()); //qDebug("%s", input.toAscii().constData());
if(input.size() > 100000) {
qDebug("Request too big");
generator.setStatusLine(400, "Bad Request");
write();
return;
}
parser.write(input); parser.write(input);
if(parser.isError()) if(parser.isError())
{ {
@ -74,6 +81,7 @@ void HttpConnection::write()
void HttpConnection::respond() void HttpConnection::respond()
{ {
qDebug("Respond called");
QStringList auth = parser.value("Authorization").split(" ", QString::SkipEmptyParts); QStringList auth = parser.value("Authorization").split(" ", QString::SkipEmptyParts);
if (auth.size() != 2 || QString::compare(auth[0], "Basic", Qt::CaseInsensitive) != 0 || !parent->isAuthorized(auth[1].toUtf8())) if (auth.size() != 2 || QString::compare(auth[0], "Basic", Qt::CaseInsensitive) != 0 || !parent->isAuthorized(auth[1].toUtf8()))
{ {
@ -176,6 +184,25 @@ void HttpConnection::respondCommand(QString command)
emit urlsReadyToBeDownloaded(url_list_cleaned); emit urlsReadyToBeDownloaded(url_list_cleaned);
return; return;
} }
if(command == "upload")
{
QByteArray torrentfile = parser.torrent();
// XXX: Trick to get a unique filename
QString filePath;
QTemporaryFile *tmpfile = new QTemporaryFile();
if (tmpfile->open()) {
filePath = tmpfile->fileName();
}
delete tmpfile;
// write it to HD
QFile torrent(filePath);
if(torrent.open(QIODevice::WriteOnly)) {
torrent.write(torrentfile);
torrent.close();
}
emit torrentReadyToBeDownloaded(filePath, false, QString(), false);
return;
}
if(command == "resumeall") if(command == "resumeall")
{ {
emit resumeAllTorrents(); emit resumeAllTorrents();

1
src/httpconnection.h

@ -57,6 +57,7 @@ class HttpConnection : public QObject
signals: signals:
void urlsReadyToBeDownloaded(const QStringList&); void urlsReadyToBeDownloaded(const QStringList&);
void torrentReadyToBeDownloaded(QString, bool, QString, bool);
void deleteTorrent(QString hash); void deleteTorrent(QString hash);
void resumeTorrent(QString hash); void resumeTorrent(QString hash);
void pauseTorrent(QString hash); void pauseTorrent(QString hash);

19
src/httprequestparser.cpp

@ -49,11 +49,11 @@ QString HttpRequestParser::url() const
return path; return path;
} }
QString HttpRequestParser::message() const QByteArray HttpRequestParser::message() const
{ {
if(isParsable()) if(isParsable())
return data; return data;
return QString(); return QByteArray();
} }
QString HttpRequestParser::get(const QString key) const QString HttpRequestParser::get(const QString key) const
@ -66,7 +66,12 @@ QString HttpRequestParser::post(const QString key) const
return postMap[key]; return postMap[key];
} }
void HttpRequestParser::write(QString str) QByteArray HttpRequestParser::torrent() const
{
return torrent_content;
}
void HttpRequestParser::write(QByteArray str)
{ {
while (!headerDone && str.size()>0) while (!headerDone && str.size()>0)
{ {
@ -111,7 +116,7 @@ void HttpRequestParser::write(QString str)
if(contentType() == "application/x-www-form-urlencoded") if(contentType() == "application/x-www-form-urlencoded")
{ {
QUrl url; QUrl url;
url.setEncodedQuery(data.toAscii()); url.setEncodedQuery(data);
QListIterator<QPair<QString, QString> > i(url.queryItems()); QListIterator<QPair<QString, QString> > i(url.queryItems());
while (i.hasNext()) while (i.hasNext())
{ {
@ -120,9 +125,15 @@ void HttpRequestParser::write(QString str)
qDebug() << pair.first << "=" << post(pair.first); qDebug() << pair.first << "=" << post(pair.first);
} }
} }
if(contentType() == "multipart/form-data")
{
//qDebug() << data.right(data.size()-data.indexOf("\r\n\r\n")-QByteArray("\r\n\r\n").size());
torrent_content = data.right(data.size()-data.indexOf("\r\n\r\n")-QByteArray("\r\n\r\n").size());
}
} }
} }
else else
error = true; error = true;
} }
qDebug() << "isError: " << isError();
} }

8
src/httprequestparser.h

@ -30,10 +30,11 @@ class HttpRequestParser : public QHttpRequestHeader
bool headerDone; bool headerDone;
bool messageDone; bool messageDone;
bool error; bool error;
QString data; QByteArray data;
QString path; QString path;
QMap<QString, QString> postMap; QMap<QString, QString> postMap;
QMap<QString, QString> getMap; QMap<QString, QString> getMap;
QByteArray torrent_content;
public: public:
HttpRequestParser(); HttpRequestParser();
@ -41,10 +42,11 @@ class HttpRequestParser : public QHttpRequestHeader
bool isParsable() const; bool isParsable() const;
bool isError() const; bool isError() const;
QString url() const; QString url() const;
QString message() const; QByteArray message() const;
QString get(const QString key) const; QString get(const QString key) const;
QString post(const QString key) const; QString post(const QString key) const;
void write(QString str); QByteArray torrent() const;
void write(QByteArray str);
}; };
#endif #endif

1
src/httpserver.cpp

@ -62,6 +62,7 @@ void HttpServer::newHttpConnection()
HttpConnection *connection = new HttpConnection(socket, this); HttpConnection *connection = new HttpConnection(socket, this);
//connect connection to BTSession //connect connection to BTSession
connect(connection, SIGNAL(urlsReadyToBeDownloaded(const QStringList&)), BTSession, SLOT(downloadFromURLList(const QStringList&))); connect(connection, SIGNAL(urlsReadyToBeDownloaded(const QStringList&)), BTSession, SLOT(downloadFromURLList(const QStringList&)));
connect(connection, SIGNAL(torrentReadyToBeDownloaded(QString, bool, QString, bool)), BTSession, SLOT(addTorrent(QString, bool, QString, bool)));
connect(connection, SIGNAL(deleteTorrent(QString)), BTSession, SLOT(deleteTorrent(QString))); connect(connection, SIGNAL(deleteTorrent(QString)), BTSession, SLOT(deleteTorrent(QString)));
connect(connection, SIGNAL(pauseTorrent(QString)), BTSession, SLOT(pauseTorrent(QString))); connect(connection, SIGNAL(pauseTorrent(QString)), BTSession, SLOT(pauseTorrent(QString)));
connect(connection, SIGNAL(resumeTorrent(QString)), BTSession, SLOT(resumeTorrent(QString))); connect(connection, SIGNAL(resumeTorrent(QString)), BTSession, SLOT(resumeTorrent(QString)));

1
src/webui.qrc

@ -2,6 +2,7 @@
<qresource> <qresource>
<file>webui/index.html</file> <file>webui/index.html</file>
<file>webui/download.html</file> <file>webui/download.html</file>
<file>webui/upload.html</file>
<file>webui/about.html</file> <file>webui/about.html</file>
<file>webui/css/mocha.css</file> <file>webui/css/mocha.css</file>
<file>webui/css/dynamicTable.css</file> <file>webui/css/dynamicTable.css</file>

2
src/webui/index.html

@ -27,6 +27,7 @@
<a class="returnFalse">File</a> <a class="returnFalse">File</a>
<ul> <ul>
<li><a id="downloadLink">Download from URL</a></li> <li><a id="downloadLink">Download from URL</a></li>
<li><a id="uploadLink">Download local torrent</a></li>
</ul> </ul>
</li> </li>
<li> <li>
@ -52,6 +53,7 @@
</div> </div>
<div id="mochaToolbar"> <div id="mochaToolbar">
<a id="downloadButton"><img class="mochaToolButton" title="Download from URL" src="images/skin/url.png"/></a> <a id="downloadButton"><img class="mochaToolButton" title="Download from URL" src="images/skin/url.png"/></a>
<a id="uploadButton"><img class="mochaToolButton" title="Download local torrent" src="images/skin/open.png"/></a>
<a id="deleteButton"><img class="mochaToolButton" title="Delete" src="images/skin/delete.png"/></a> <a id="deleteButton"><img class="mochaToolButton" title="Delete" src="images/skin/delete.png"/></a>
<a id="resumeButton"><img class="mochaToolButton" title="Resume" src="images/skin/play.png"/></a> <a id="resumeButton"><img class="mochaToolButton" title="Resume" src="images/skin/play.png"/></a>
<a id="pauseButton"><img class="mochaToolButton" title="Pause" src="images/skin/pause.png"/></a> <a id="pauseButton"><img class="mochaToolButton" title="Pause" src="images/skin/pause.png"/></a>

17
src/webui/scripts/mocha-events.js

@ -36,6 +36,23 @@ function attachMochaLinkEvents(){
}); });
}); });
addClickEvent('upload', function(e){
new Event(e).stop();
document.mochaUI.newWindow({
id: 'uploadPage',
title: 'Upload torrent file',
loadMethod: 'iframe',
contentURL:'upload.html',
scrollbars: false,
resizable: false,
maximizable: false,
paddingVertical: 0,
paddingHorizontal: 0,
width: 500,
height: 120
});
});
addClickEvent('delete', function(e){ addClickEvent('delete', function(e){
new Event(e).stop(); new Event(e).stop();
var h = myTable.selectedId(); var h = myTable.selectedId();

21
src/webui/upload.html

@ -0,0 +1,21 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Upload local torrent file</title>
<link rel="stylesheet" href="css/style.css" type="text/css" />
<link rel="stylesheet" href="css/mocha.css" type="text/css" />
<script type="text/javascript" src="scripts/mootools-trunk-1475.js" charset="utf-8"></script>
<!-- <script type="text/javascript" src="scripts/upload.js" charset="utf-8"></script> -->
</head>
<body>
<center>
<h1 class="vcenter"><img class="vcenter" title="Download local torrent" src="images/skin/open.png"/>Download local torrent</h1>
<form action="/command/upload" enctype="multipart/form-data" method="post" name="uploadForm">
<input type="file" name="torrentfile" id="torrentfile" size="40"/><p>Point to torrent file</p><!--<input type="submit" value="Download"/> -->
<a id="upButton" onclick="document.uploadForm.submit();window.parent.document.getElementById('uploadPage').parentNode.removeChild(window.parent.document.getElementById('uploadPage'));">Download</a>
</form>
</center>
</body>
</html>
Loading…
Cancel
Save