From: lvaatamoinen Date: Mon, 23 Nov 2009 12:33:07 +0000 (+0000) Subject: - SearchPlugin checks for Content-type -header, so now it is able to download X-Git-Url: http://git.maemo.org/git/?p=qtrapids;a=commitdiff_plain;h=da9f6437885ec39f194b6749d0d2fdc33e4f5f9c - SearchPlugin checks for Content-type -header, so now it is able to download through links that dont have suffix .torrent - TODO: File renaming. Some filenames are not valid to be copied (contain brackets etc.) git-svn-id: file:///svnroot/qtrapids/trunk@46 42ac0dd5-4c8c-4c71-bb3e-ecdfe252ffda --- diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp index 9a6770c..e233aee 100644 --- a/src/gui/MainWindow.cpp +++ b/src/gui/MainWindow.cpp @@ -166,12 +166,12 @@ void MainWindow::addMenuItem(QWidget* widget, PluginWidgetType type) bool MainWindow::eventRequest(QVariant param, PluginRequest req) { if (req == qtrapids::PluginHostInterface::OPEN_FILE) { - QString sourceFile = param.toString(); - + QString sourceFile = param.toString(); + // Get the source files name from the full path: QFileInfo fInfo(sourceFile); QString targetFile = fInfo.fileName(); - targetFile = settings_.value("download/directory").toString() + targetFile; + targetFile = settings_.value("download/directory").toString() + "/" + targetFile; // Copy temoporary file to Downloads directory... if (!QFile::copy(sourceFile, targetFile)) { @@ -181,9 +181,14 @@ bool MainWindow::eventRequest(QVariant param, PluginRequest req) // If copying was successful, remove the original temporary file. QFile::remove(sourceFile); } - + + /// @todo Torrent bencoding validity should be checked before starting(?) // ...and start the torrent: on_torrentFileSelected(targetFile); + + } else if (req == qtrapids::PluginHostInterface::READ_BUFFER) { + // Create torrent information from char* buffer and start. + StartTorrentFromBufferData(param.toByteArray().constData(), param.toByteArray().size()); } return true; @@ -252,6 +257,28 @@ void MainWindow::LoadPlugins() } } + + +// Opens torrent information from buffer data and adds torrent to session +void MainWindow::StartTorrentFromBufferData(char const* data, int size) +{ + // For params, see: http://www.rasterbar.com/products/libtorrent/manual.html#add-torrent + /// @todo Should typedef libtorrent::torrent_info to something + AddTorrentParams addParams; + boost::intrusive_ptr tiTmp = + new libtorrent::torrent_info(data, size); + addParams.ti = tiTmp; + // save_path is the only mandatory parameter, rest are optional. + addParams.save_path = boost::filesystem::path(settings_.value("download/directory").toString().toStdString()); + //addParams.storage_mode = libtorrent::storage_mode_allocate; + qtrapids::QTorrentHandle handle = btSession_.addTorrent(addParams); + dlView_->newItem(handle); +// torrentHandles_.push_back(handlePtr); +#ifdef QTRAPIDS_DEBUG + qDebug() << "Is valid: " << handle.isValid(); +#endif +} + // =========================== SLOTS ================================= void MainWindow::on_openAction_clicked() { @@ -339,6 +366,7 @@ void MainWindow::on_torrentFileSelected(const QString& file) // Otherwise add torrent // For params, see: http://www.rasterbar.com/products/libtorrent/manual.html#add-torrent + /// @todo Should typedef libtorrent::torrent_info to something AddTorrentParams addParams; boost::intrusive_ptr tiTmp = new libtorrent::torrent_info(boost::filesystem::path(file.toStdString())); @@ -354,7 +382,6 @@ void MainWindow::on_torrentFileSelected(const QString& file) #endif } - void MainWindow::on_alert(std::auto_ptr al) { if (al.get() != NULL) { diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h index 6f104d2..fcea41d 100644 --- a/src/gui/MainWindow.h +++ b/src/gui/MainWindow.h @@ -72,6 +72,7 @@ class MainWindow : public QMainWindow, public qtrapids::PluginHostInterface { private: void LoadPlugins(); + void StartTorrentFromBufferData(char const* data, int size); private: QTabWidget *tabWidget_; diff --git a/src/plugins/PluginInterface.h b/src/plugins/PluginInterface.h index a5ea554..1048efd 100644 --- a/src/plugins/PluginInterface.h +++ b/src/plugins/PluginInterface.h @@ -56,6 +56,7 @@ namespace qtrapids /// @todo Additional functionality request constants. enum PluginRequest { OPEN_FILE, + READ_BUFFER, UNKNOWN_REQUEST }; diff --git a/src/plugins/searchplugin/SearchPlugin.cpp b/src/plugins/searchplugin/SearchPlugin.cpp index add01e0..fbc406f 100644 --- a/src/plugins/searchplugin/SearchPlugin.cpp +++ b/src/plugins/searchplugin/SearchPlugin.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "SearchPlugin.h" @@ -47,13 +48,10 @@ namespace qtrapids searchButton_(NULL), result_(NULL), dlManager_(NULL), host_(NULL) { - // TODO: Parse search engine XML(?) descriptions. - // -Add search engines to model - // -Show model in comboBox - // Add back/forward/refresh -buttons to widget to allow some browsing - + // TODO: Add back/forward/refresh -buttons to widget to allow some browsing functionality } + void SearchPlugin::initialize(PluginHostInterface* host, Info info) { host_ = host; @@ -94,11 +92,12 @@ namespace qtrapids void SearchPlugin::on_searchButton_clicked() { - int i = comboBox_->currentIndex(); QString tmp = engineTemplates_.at(i); + i = tmp.indexOf(SEARCH_TERMS_STRING); tmp.replace(i, SEARCH_TERMS_STRING.length(), searchLine_->text()); + QUrl searchUrl(tmp); qDebug() << searchUrl; result_ = new QWebView; @@ -107,9 +106,13 @@ namespace qtrapids QWebPage *resultPage = result_->page(); resultPage->setLinkDelegationPolicy(QWebPage::DelegateExternalLinks); + // Get the network access manager for examining HTTP replies. + QNetworkAccessManager *netwAccessManager_ = resultPage->networkAccessManager(); + connect(resultPage, SIGNAL(linkClicked(const QUrl&)), this, SLOT(on_linkClicked(const QUrl&))); connect(result_, SIGNAL(loadFinished(bool)), this, SLOT(on_loadFinished(bool))); - + connect(netwAccessManager_, SIGNAL(finished(QNetworkReply*)), this, SLOT(on_networkReplyFinished(QNetworkReply*))); + result_->load(searchUrl); on_searchResult((QWidget*)result_); @@ -126,54 +129,79 @@ namespace qtrapids } - void SearchPlugin::on_searchResult(QWidget* resultWidget) + void SearchPlugin::on_networkReplyFinished(QNetworkReply* reply) { -#ifdef QTRAPIDS_DEBUG - qDebug() << "on_searchResult()"; -#endif - if (host_) { - host_->addPluginWidget(resultWidget, qtrapids::PluginHostInterface::TAB_PAGE); - } - } - - void SearchPlugin::on_linkClicked(const QUrl& url) - { - // Get the path part of URL (the part after the host part) - QString path = url.path(); - QFileInfo fInfo(path); - // Check path suffix. If it is .torrent, we should download: - /// @todo We should actually check for MIME-type application/x-bittorrent in HTTP response, - /// instead of relying on file suffix. - /// e.g. link - ///http://www.bitenova.org/download.php?id=c84375141231eef49fc6c55e6347ba4f4a623a05&name=Nero_Linux_3.5.1.0__(Debian)_deutsch - /// will not work. - /// @todo Also, after downloading, the torrent bencoding validity should be checked at plugin host.. - if (fInfo.suffix() == "torrent") { -#ifdef QTRAPIDS_DEBUG - qDebug() << "IS TORRENT"; -#endif - QString filename = fInfo.fileName(); + qDebug() << "on_networkReplyFinished()"; + QString contentType = reply->header(QNetworkRequest::ContentTypeHeader).toString(); + QString filename; + QByteArray replyData; + QUrl url = reply->url(); + + qDebug() << "on_networkReplyFinished():" << url; + + // If content type is torrent data, read reply data: + if (contentType == "application/x-bittorrent") { + + // If HTTP-response has Content-Disposition: -header, then we must use that as filename. + if (reply->hasRawHeader("Content-Disposition")) { // NOTE this code block taken from kwebpage.cpp + const QString value = QLatin1String(reply->rawHeader("Content-Disposition")); + const int pos = value.indexOf(QLatin1String("filename=")); + if (pos != -1) { + QString name = value.mid(pos + 9); + if (name.startsWith(QLatin1Char('"')) && name.endsWith(QLatin1Char('"'))) + name = name.mid(1, name.size() - 2); + filename = name; + } + // No content-disposition header, use last part (the filename) of URL as filename: + } else { + QString path = url.path(); + QFileInfo fInfo(path); + filename = fInfo.fileName(); + } // Destroy ongoing download, if any. if (dlManager_) { delete dlManager_; dlManager_ = NULL; } - + + /// @todo Is this a bit of a hack now; we get the reply and check Content-Type, + /// The download is then started afterwards, so we get unecessarily one extra + /// HTTP-response here. + /// @todo Could this whole content-type checking be logically moved to DownloadManager? // Start downloading Torrent file. dlManager_ = new DownloadManager(url, "/tmp/" + filename); connect(dlManager_, SIGNAL(finished(QString)), this, SLOT(on_downloadFinished(QString))); dlManager_->start(); - } else { - // If was not .torrent -file, check URL validity and load the page as usual. - if (url.isValid()) { - result_->load(url); - } } } + + void SearchPlugin::on_searchResult(QWidget* resultWidget) + { +#ifdef QTRAPIDS_DEBUG + qDebug() << "on_searchResult()"; +#endif + if (host_) { + host_->addPluginWidget(resultWidget, qtrapids::PluginHostInterface::TAB_PAGE); + } + } + + + /// @todo It may be that we don't actually need link delegation, because we check response Content-Type header + /// on_linkClicked() in that case unnecessary function + void SearchPlugin::on_linkClicked(const QUrl& url) + { + qDebug() << "on_linkClicked():" << url; + + if (url.isValid()) { + result_->load(url); + } + } + + void SearchPlugin::on_downloadFinished(QString filepath) { #ifdef QTRAPIDS_DEBUG @@ -181,7 +209,9 @@ namespace qtrapids #endif delete dlManager_; dlManager_ = NULL; - host_->eventRequest(QVariant(filepath), qtrapids::PluginHostInterface::OPEN_FILE); + if (host_) { + host_->eventRequest(QVariant(filepath), qtrapids::PluginHostInterface::OPEN_FILE); + } } @@ -189,55 +219,41 @@ namespace qtrapids { foreach (QString dirName, dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) { - QFile file(dir.path() + "/" + dirName + "/" + DESCRIPTION_FILENAME); + QFile file(dir.path() + "/" + dirName + "/" + DESCRIPTION_FILENAME); + + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + qWarning() << "Unable to open " << DESCRIPTION_FILENAME << " for reading in " << dir.path(); + continue; + } + + // Parse the XML file to DOM document. + QDomDocument document; + + // Second parameter: nameSpaceProcessing = false + if (!document.setContent(&file, false)) { + qWarning() << "Unable to parse " << DESCRIPTION_FILENAME << " in " << dirName; + } else { + QDomNodeList urlElements = document.elementsByTagName("Url"); + QDomNodeList shortNameElements = document.elementsByTagName("ShortName"); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - qWarning() << "Unable to open " << DESCRIPTION_FILENAME << " for reading in " << dir.path(); - continue; + QDomNode n = urlElements.item(0); + QDomNode m; + QDomNamedNodeMap attribMap; + if (n.hasAttributes()) { + attribMap = n.attributes(); + m = attribMap.namedItem("template"); + engineTemplates_.push_back(m.nodeValue()); } - // Parse the XML file to DOM document. - QDomDocument document; - - // Second parameter: nameSpaceProcessing = false - if (!document.setContent(&file, false)) { - qWarning() << "Unable to parse " << DESCRIPTION_FILENAME << " in " << dirName; - } else { - QDomNodeList urlElements = document.elementsByTagName("Url"); - QDomNodeList shortNameElements = document.elementsByTagName("ShortName"); - - QDomNode n = urlElements.item(0); - QDomNode m; - QDomNamedNodeMap attribMap; - if (n.hasAttributes()) { - attribMap = n.attributes(); - m = attribMap.namedItem("template"); - engineTemplates_.push_back(m.nodeValue()); - } - - n = shortNameElements.item(0); - if (n.hasChildNodes()) { - m = n.firstChild(); - comboBox_->addItem(m.nodeValue()); - } + n = shortNameElements.item(0); + if (n.hasChildNodes()) { + m = n.firstChild(); + comboBox_->addItem(m.nodeValue()); } } - - - /// @todo save parsed xml elements and to a model which is displayed in combobox. } - - /* - QDomElement docElem = document.documentElement(); - QDomNode n = docElem.firstChild(); - while(!n.isNull()) { - QDomElement e = n.toElement(); // try to convert the node to an element. - if(!e.isNull()) { - qDebug() << qPrintable(e.tagName()); // the node really is an element. - } - n = n.nextSibling(); - } - */ + /// @todo save parsed xml elements and to a model which is displayed in combobox. + } } // namespace qtrapids diff --git a/src/plugins/searchplugin/SearchPlugin.h b/src/plugins/searchplugin/SearchPlugin.h index 1b16330..eecabd3 100644 --- a/src/plugins/searchplugin/SearchPlugin.h +++ b/src/plugins/searchplugin/SearchPlugin.h @@ -30,6 +30,7 @@ class QComboBox; class QPushButton; class QLineEdit; class QWebView; +class QNetworkReply; class DownloadManager; class QDir; @@ -56,6 +57,7 @@ class SearchPlugin : public PluginInterface void on_searchButton_clicked(); void on_searchResult(QWidget* resultWidget); void on_loadFinished(bool ok); + void on_networkReplyFinished(QNetworkReply* reply); void on_linkClicked(const QUrl& url); void on_downloadFinished(QString filepath);