mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2024-11-22 09:16:05 +03:00
- Improved a lot downloading from url using libcommoncpp2 instead of libcurl
- TODO soon: - Updated configure file - Add url download error handling
This commit is contained in:
parent
347b03d699
commit
7c8677d787
7 changed files with 61 additions and 93 deletions
|
@ -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
|
||||
|
|
3
TODO
3
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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -28,11 +28,15 @@
|
|||
#include <QMutex>
|
||||
#include <QMutexLocker>
|
||||
#include <QWaitCondition>
|
||||
#include <curl/curl.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <cc++/common.h>
|
||||
#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);
|
||||
|
|
25
src/rss.h
25
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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue