diff --git a/Changelog b/Changelog index 4822a960d..46aa56830 100644 --- a/Changelog +++ b/Changelog @@ -24,6 +24,7 @@ - FEATURE: Real torrent share ratio is now displayed in transfer list - FEATURE: Added keyboard shortcuts for main actions (see wiki) - FEATURE: Added a popup menu to set priority for multiple fies at once + - FEATURE: Improved a lot downloading from urls (using libcommoncpp2 instead of libcurl) - I18N: Added Hungarian translation - BUGFIX: Progress of paused torrents is now correct on restart - BUGFIX: Progress column gets sorted on restart it is was during last execution diff --git a/TODO b/TODO index a6e856083..e60839a1d 100644 --- a/TODO +++ b/TODO @@ -42,9 +42,8 @@ - update sorting when a new torrent is added? - Allow to hide columns (gtsoul) - Complete documentation and english translation -- Fix downloader thread (again). Try to use another lib than libcurl: - - libcommoncpp has a URLStream class. This C++ class allow you to download a file using HTTP. See demo/urlfetch.cpp in commoncpp2-1.3.19.tar.gz * beta2 + - Fix configure file for libcommoncpp - Wait for some bug fixes in libtorrent : - upload/download limit per torrent - ipfilter crash diff --git a/src/bittorrent.cpp b/src/bittorrent.cpp index c4a1c7b2b..825e2e3a7 100644 --- a/src/bittorrent.cpp +++ b/src/bittorrent.cpp @@ -50,7 +50,7 @@ bittorrent::bittorrent(){ ETARefresher.start(6000); // To download from urls downloader = new downloadThread(this); - connect(downloader, SIGNAL(downloadFinished(const QString&, const QString&, int, const QString&)), this, SLOT(processDownloadedFile(const QString&, const QString&, int, const QString&))); + connect(downloader, SIGNAL(downloadFinished(const QString&, const QString&)), this, SLOT(processDownloadedFile(const QString&, const QString&))); } // Main destructor @@ -1013,13 +1013,13 @@ void bittorrent::downloadFromUrl(const QString& url){ } // Add to bittorrent session the downloaded torrent file -void bittorrent::processDownloadedFile(const QString& url, const QString& file_path, int return_code, const QString& errorBuffer){ - if(return_code){ - // Download failed - emit downloadFromUrlFailure(url, errorBuffer); - QFile::remove(file_path); - return; - } +void bittorrent::processDownloadedFile(const QString& url, const QString& file_path){ +// if(return_code){ +// // Download failed +// emit downloadFromUrlFailure(url, errorBuffer); +// QFile::remove(file_path); +// return; +// } // Add file to torrent download list emit newDownloadedTorrent(file_path, url); } diff --git a/src/bittorrent.h b/src/bittorrent.h index c992078a9..eadbb391f 100644 --- a/src/bittorrent.h +++ b/src/bittorrent.h @@ -136,7 +136,7 @@ class bittorrent : public QObject{ void cleanDeleter(deleteThread* deleter); void scanDirectory(); void readAlerts(); - void processDownloadedFile(const QString&, const QString&, int, const QString&); + void processDownloadedFile(const QString&, const QString&); void resumeUnfinished(); bool loadTrackerFile(const QString& hash); void saveTrackerFile(const QString& hash); diff --git a/src/downloadThread.h b/src/downloadThread.h index 4b0665087..309a1fd80 100644 --- a/src/downloadThread.h +++ b/src/downloadThread.h @@ -28,11 +28,15 @@ #include #include #include -#include #include - +#include #include "misc.h" +#ifdef CCXX_NAMESPACES +using namespace std; +using namespace ost; +#endif + class downloadThread : public QThread { Q_OBJECT @@ -41,9 +45,10 @@ class downloadThread : public QThread { QMutex mutex; QWaitCondition condition; bool abort; + URLStream url_stream; signals: - void downloadFinished(const QString& url, const QString& file_path, int return_code, const QString& errorBuffer); + void downloadFinished(const QString& url, const QString& file_path); public: downloadThread(QObject* parent) : QThread(parent){ @@ -84,80 +89,41 @@ class downloadThread : public QThread { QString url = url_list.takeFirst(); mutex.unlock(); qDebug("In Download thread RUN, mutex unlocked (got url)"); - CURL *curl; - QString filePath; - int return_code, response; // XXX: Trick to get a unique filename - QTemporaryFile *tmpfile = new QTemporaryFile; + QString filePath; + QTemporaryFile *tmpfile = new QTemporaryFile(); if (tmpfile->open()) { filePath = tmpfile->fileName(); } delete tmpfile; - if(abort) - return; - FILE *file = fopen((const char*)filePath.toUtf8(), "w"); - if(!file){ - std::cerr << "Error: could not open temporary file...\n"; - return; + QFile dest_file(filePath); + if(!dest_file.open(QIODevice::WriteOnly | QIODevice::Text)){ + std::cerr << "Error: could't create temporary file: " << (const char*)filePath.toUtf8() << '\n'; + continue; } - // Initilization required by libcurl - curl = curl_easy_init(); - if(!curl){ - std::cerr << "Error: Failed to init curl...\n"; - fclose(file); - return; + URLStream::Error status = url_stream.get((const char*)url.toUtf8()); + if(status){ + // Failure + //TODO: handle this + QString error_msg = QString(misc::toString(status).c_str()); + qDebug("Download failed for %s, reason: %s", (const char*)url.toUtf8(), (const char*)error_msg.toUtf8()); + url_stream.close(); + continue; } - // Set url to download - curl_easy_setopt(curl, CURLOPT_URL, url.toLocal8Bit().constData()); - qDebug("Url: %s", url.toLocal8Bit().constData()); - // Define our callback to get called when there's data to be written - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, misc::my_fwrite); - // Set destination file - curl_easy_setopt(curl, CURLOPT_WRITEDATA, file); - // Some SSL mambo jambo - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); - // Disable progress meter - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1); - // Any kind of authentication - curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); - //curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); - // Auto referrer - curl_easy_setopt(curl, CURLOPT_AUTOREFERER, 1); - // Follow redirections - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); - // Enable cookies - curl_easy_setopt(curl, CURLOPT_COOKIEFILE, ""); - // We want error message: - char errorBuffer[CURL_ERROR_SIZE]; - errorBuffer[0]=0; /* prevent junk from being output */ - return_code = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer); - if(return_code){ - std::cerr << "Error: failed to set error buffer in curl\n"; - fclose(file); - QFile::remove(filePath); - return; + qDebug("Downloading %s...", (const char*)url.toUtf8()); + char cbuf[1024]; + int len; + while(!url_stream.eof()) { + url_stream.read(cbuf, sizeof(cbuf)); + len = url_stream.gcount(); + if(len > 0){ + dest_file.write(cbuf, len); + } } - unsigned short retries = 0; - bool to_many_users = false; - do{ - // Perform Download - return_code = curl_easy_perform(curl); - // We want HTTP response code - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response); - qDebug("HTTP response code: %d", response); - if(response/100 == 5){ - to_many_users = true; - ++retries; - SleeperThread::msleep(1000); - } - }while(to_many_users && retries < 10 && response!=0); - // Cleanup - curl_easy_cleanup(curl); - // Close tmp file - fclose(file); - emit downloadFinished(url, filePath, return_code, QString(errorBuffer)); - qDebug("In Download thread RUN, signal emitted, ErrorBuffer: %s", errorBuffer); + dest_file.close(); + url_stream.close(); + emit downloadFinished(url, filePath); + qDebug("In Download thread RUN, signal emitted"); }else{ qDebug("In Download thread RUN, mutex still locked (no urls) -> sleeping"); condition.wait(&mutex); diff --git a/src/rss.h b/src/rss.h index e2d16401b..ef4d92806 100644 --- a/src/rss.h +++ b/src/rss.h @@ -137,21 +137,21 @@ class RssStream : public QObject{ public slots : // read and store the downloaded rss' informations - void processDownloadedFile(const QString&, const QString& file_path, int return_code, const QString&) { + void processDownloadedFile(const QString&, const QString& file_path) { // delete the former file if(QFile::exists(filePath)) { QFile::remove(filePath); } filePath = file_path; - if(return_code){ - // Download failed - qDebug("(download failure) "+file_path.toUtf8()); - if(QFile::exists(filePath)) { - QFile::remove(filePath); - } - emit refreshFinished(url, NEWS); - return; - } +// if(return_code){ +// // Download failed +// qDebug("(download failure) "+file_path.toUtf8()); +// if(QFile::exists(filePath)) { +// QFile::remove(filePath); +// } +// emit refreshFinished(url, NEWS); +// return; +// } openRss(); emit refreshFinished(url, NEWS); } @@ -189,7 +189,7 @@ class RssStream : public QObject{ read = true; downloaderRss = new downloadThread(this); downloaderIcon = new downloadThread(this); - connect(downloaderRss, SIGNAL(downloadFinished(const QString&, const QString&, int, const QString&)), this, SLOT(processDownloadedFile(const QString&, const QString&, int, const QString&))); + connect(downloaderRss, SIGNAL(downloadFinished(const QString&, const QString&)), this, SLOT(processDownloadedFile(const QString&, const QString&))); downloaderRss->downloadUrl(url); // XXX: remove it when gif can be displayed iconPath = ":/Icons/rss.png"; @@ -216,7 +216,6 @@ class RssStream : public QObject{ } void refresh() { - connect(downloaderRss, SIGNAL(downloadFinished(const QString&, const QString&, int, const QString&)), this, SLOT(processDownloadedFile(const QString&, const QString&, int, const QString&))); downloaderRss->downloadUrl(url); lastRefresh.start(); } @@ -276,7 +275,7 @@ class RssStream : public QObject{ QString getLastRefresh() const{ return QString::number(lastRefresh.hour())+"h"+QString::number(lastRefresh.minute())+"m"; - } + } bool isRead() const { return read; diff --git a/src/src.pro b/src/src.pro index 6ce68e7e5..94652f6c4 100644 --- a/src/src.pro +++ b/src/src.pro @@ -2,6 +2,9 @@ LANG_PATH = lang ICONS_PATH = Icons +LIBS += -lccext2 +LIBS += -lccgnu2 + #Set the following variable to 1 to enable debug DEBUG_MODE = 1