You've already forked qBittorrent
							
							
				mirror of
				https://github.com/qbittorrent/qBittorrent
				synced 2025-11-02 08:10:54 +01:00 
			
		
		
		
	Compare commits
	
		
			20 Commits
		
	
	
		
			release-3.
			...
			release-2.
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					42574242ef | ||
| 
						 | 
					d5c174a6f8 | ||
| 
						 | 
					173999e504 | ||
| 
						 | 
					1ed928bc39 | ||
| 
						 | 
					b85d51ba79 | ||
| 
						 | 
					779b53722b | ||
| 
						 | 
					76780c4c46 | ||
| 
						 | 
					da74f24a71 | ||
| 
						 | 
					01c56865db | ||
| 
						 | 
					b541c9fa4c | ||
| 
						 | 
					aac0fbcbe4 | ||
| 
						 | 
					b315551edd | ||
| 
						 | 
					58a885cb87 | ||
| 
						 | 
					d19282285c | ||
| 
						 | 
					e0d8ca39a5 | ||
| 
						 | 
					ec3169c9b0 | ||
| 
						 | 
					7bfd7e9cda | ||
| 
						 | 
					459bb8c51d | ||
| 
						 | 
					9159a9f25d | ||
| 
						 | 
					8ea8f8a9f7 | 
							
								
								
									
										16
									
								
								Changelog
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								Changelog
									
									
									
									
									
								
							@@ -1,3 +1,19 @@
 | 
			
		||||
* Fri Dec 18 2009 - Christophe Dumez <chris@qbittorrent.org> - v2.0.2
 | 
			
		||||
    - BUGFIX: Fix .qbittorrent folder not being created (critical bug introduced in v2.0.1 that makes qBittorrent unusuable for new users)
 | 
			
		||||
    - BUGFIX: Fix RSS Feed downloader for some feeds
 | 
			
		||||
    - BUGFIX: Do not use home folder as a fallback when the save path is not accessible
 | 
			
		||||
    - BUGFIX: Fix Mininova, ThePirateBay search engine plugins
 | 
			
		||||
    - BUGFIX: Read RSS articles are remembered on restart for feeds with no torrents attached
 | 
			
		||||
 | 
			
		||||
* Sun Dec 13 2009 - Christophe Dumez <chris@qbittorrent.org> - v2.0.1
 | 
			
		||||
    - BUGFIX: µTorrent user-agent is now spoofed correctly
 | 
			
		||||
    - BUGFIX: Fix column hiding behavior when queueing system is disabled
 | 
			
		||||
    - BUGFIX: Fix link to plugins.qbittorrent.org in plugins dialog
 | 
			
		||||
    - BUGFIX: ~/qBT_dir is created only when it is actually used
 | 
			
		||||
    - BUGFIX: Fix possible missing slot message (toggleSelectedTorrentsSuperSeeding)
 | 
			
		||||
    - BUGFIX: Fix possible crash in torrent properties (files)
 | 
			
		||||
    - BUGFIX: Added Hex Magnet Links support (Thanks Haypo)
 | 
			
		||||
 | 
			
		||||
* Thu Dec 10 2009 - Christophe Dumez <chris@qbittorrent.org> - v2.0.0
 | 
			
		||||
    - FEATURE: Added program option to disable splash screen
 | 
			
		||||
    - FEATURE: Dropped dependency on libcurl and libzzip
 | 
			
		||||
 
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 743 B  | 
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 659 B  | 
@@ -1,6 +1,6 @@
 | 
			
		||||
[Desktop Entry]
 | 
			
		||||
Categories=Qt;Network;P2P;
 | 
			
		||||
Comment=V2.0.0
 | 
			
		||||
Comment=V2.0.2
 | 
			
		||||
Exec=qbittorrent %f
 | 
			
		||||
GenericName=Bittorrent client
 | 
			
		||||
GenericName[bg]=Торент клиент
 | 
			
		||||
 
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 79 KiB  | 
@@ -1671,7 +1671,7 @@ QString Bittorrent::getSavePath(QString hash) {
 | 
			
		||||
    if(!saveDir.mkpath(saveDir.path())) {
 | 
			
		||||
      std::cerr << "Couldn't create the save directory: " << saveDir.path().toLocal8Bit().data() << "\n";
 | 
			
		||||
      // XXX: handle this better
 | 
			
		||||
      return QDir::homePath();
 | 
			
		||||
      //return QDir::homePath();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return savePath;
 | 
			
		||||
 
 | 
			
		||||
@@ -144,7 +144,6 @@
 | 
			
		||||
  <file>Icons/oxygen/encrypted.png</file>
 | 
			
		||||
  <file>Icons/oxygen/edit_clear.png</file>
 | 
			
		||||
  <file>Icons/oxygen/download.png</file>
 | 
			
		||||
  <file>Icons/oxygen/application-x-kgetlist-no.png</file>
 | 
			
		||||
  <file>Icons/oxygen/gear.png</file>
 | 
			
		||||
  <file>Icons/oxygen/remove.png</file>
 | 
			
		||||
  <file>Icons/oxygen/dialog-warning.png</file>
 | 
			
		||||
@@ -165,7 +164,6 @@
 | 
			
		||||
  <file>Icons/oxygen/help-about.png</file>
 | 
			
		||||
  <file>Icons/oxygen/list-add.png</file>
 | 
			
		||||
  <file>Icons/oxygen/network-server.png</file>
 | 
			
		||||
  <file>Icons/oxygen/application-x-kgetlist.png</file>
 | 
			
		||||
  <file>Icons/oxygen/folder.png</file>
 | 
			
		||||
  <file>Icons/oxygen/urlseed.png</file>
 | 
			
		||||
  <file>Icons/oxygen/edit-cut.png</file>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										29
									
								
								src/misc.h
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								src/misc.h
									
									
									
									
									
								
							@@ -215,6 +215,11 @@ public:
 | 
			
		||||
  // return qBittorrent config path
 | 
			
		||||
  static QString qBittorrentPath() {
 | 
			
		||||
    QString qBtPath = QDir::homePath()+QDir::separator()+QString::fromUtf8(".qbittorrent") + QDir::separator();
 | 
			
		||||
    // Create dir if it does not exist
 | 
			
		||||
    if(!QFile::exists(qBtPath)){
 | 
			
		||||
      QDir dir(qBtPath);
 | 
			
		||||
      dir.mkpath(qBtPath);
 | 
			
		||||
    }
 | 
			
		||||
    return qBtPath;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -266,14 +271,30 @@ public:
 | 
			
		||||
 | 
			
		||||
  static QString magnetUriToHash(QString magnet_uri) {
 | 
			
		||||
    QString hash = "";
 | 
			
		||||
    QRegExp reg("urn:btih:([A-Z2-7=]+)");
 | 
			
		||||
    int pos = reg.indexIn(magnet_uri);
 | 
			
		||||
    QRegExp regHex("urn:btih:([0-9A-Za-z]+)");
 | 
			
		||||
    // Hex
 | 
			
		||||
    int pos = regHex.indexIn(magnet_uri);
 | 
			
		||||
    if(pos > -1) {
 | 
			
		||||
      QString found = regHex.cap(1);
 | 
			
		||||
      if(found.length() == 40) {
 | 
			
		||||
        sha1_hash sha1;
 | 
			
		||||
      sha1.assign(base32decode(reg.cap(1).toStdString()));
 | 
			
		||||
        sha1.assign(QString(QByteArray::fromHex(regHex.cap(1).toLocal8Bit())).toStdString());
 | 
			
		||||
        qDebug("magnetUriToHash (Hex): hash: %s", misc::toString(sha1).c_str());
 | 
			
		||||
        return misc::toQString(sha1);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    // Base 32
 | 
			
		||||
    QRegExp regBase32("urn:btih:([A-Za-z2-7=]+)");
 | 
			
		||||
    pos = regBase32.indexIn(magnet_uri);
 | 
			
		||||
    if(pos > -1) {
 | 
			
		||||
      QString found = regBase32.cap(1);
 | 
			
		||||
      if(found.length() > 20 && (found.length()*5)%40 == 0) {
 | 
			
		||||
        sha1_hash sha1;
 | 
			
		||||
        sha1.assign(base32decode(regBase32.cap(1).toStdString()));
 | 
			
		||||
        hash = misc::toQString(sha1);
 | 
			
		||||
      }
 | 
			
		||||
    qDebug("magnetUriToHash: hash: %s", hash.toLocal8Bit().data());
 | 
			
		||||
    }
 | 
			
		||||
    qDebug("magnetUriToHash (base32): hash: %s", hash.toLocal8Bit().data());
 | 
			
		||||
    return hash;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -362,7 +362,12 @@ void PropertiesWidget::loadDynamicData() {
 | 
			
		||||
    }
 | 
			
		||||
    if(stackedProperties->currentIndex() == FILES_TAB) {
 | 
			
		||||
      // Files progress
 | 
			
		||||
      if(h.has_metadata()) {
 | 
			
		||||
      if(h.is_valid() && h.has_metadata()) {
 | 
			
		||||
        if(PropListModel->rowCount() == 0) {
 | 
			
		||||
          PropListModel->setupModelData(h.get_torrent_info());
 | 
			
		||||
          // Expand first item if possible
 | 
			
		||||
          filesList->expand(PropListModel->index(0, 0));
 | 
			
		||||
        }
 | 
			
		||||
        std::vector<size_type> fp;
 | 
			
		||||
        h.file_progress(fp);
 | 
			
		||||
        PropListModel->updateFilesPriorities(h.file_priorities());
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								src/rss.cpp
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								src/rss.cpp
									
									
									
									
									
								
							@@ -376,7 +376,6 @@ void RssManager::saveStreamList(){
 | 
			
		||||
/** RssStream **/
 | 
			
		||||
 | 
			
		||||
RssStream::RssStream(RssFolder* parent, RssManager *rssmanager, Bittorrent *BTSession, QString _url): parent(parent), rssmanager(rssmanager), BTSession(BTSession), alias(""), iconPath(":/Icons/rss16.png"), refreshed(false), downloadFailure(false), currently_loading(false) {
 | 
			
		||||
  has_attachments = false;
 | 
			
		||||
  qDebug("RSSStream constructed");
 | 
			
		||||
  QSettings qBTRSS("qBittorrent", "qBittorrent-rss");
 | 
			
		||||
  url = QUrl(_url).toString();
 | 
			
		||||
@@ -388,8 +387,6 @@ RssStream::RssStream(RssFolder* parent, RssManager *rssmanager, Bittorrent *BTSe
 | 
			
		||||
    RssItem *rss_item = RssItem::fromHash(this, item);
 | 
			
		||||
    if(rss_item->isValid()) {
 | 
			
		||||
      (*this)[rss_item->getTitle()] = rss_item;
 | 
			
		||||
      if(rss_item->has_attachment())
 | 
			
		||||
        has_attachments = true;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -584,8 +581,11 @@ short RssStream::readDoc(const QDomDocument& doc) {
 | 
			
		||||
              delete item;
 | 
			
		||||
              item = this->value(title);
 | 
			
		||||
            }
 | 
			
		||||
            if(item->has_attachment()) {
 | 
			
		||||
              has_attachments = true;
 | 
			
		||||
            QString torrent_url;
 | 
			
		||||
            if(item->has_attachment())
 | 
			
		||||
              torrent_url = item->getTorrentUrl();
 | 
			
		||||
            else
 | 
			
		||||
              torrent_url = item->getLink();
 | 
			
		||||
            // Check if the item should be automatically downloaded
 | 
			
		||||
            if(!already_exists || !(*this)[item->getTitle()]->isRead()) {
 | 
			
		||||
              FeedFilter * matching_filter = FeedFilters::getFeedFilters(url).matches(item->getTitle());
 | 
			
		||||
@@ -595,12 +595,12 @@ short RssStream::readDoc(const QDomDocument& doc) {
 | 
			
		||||
                if(matching_filter->isValid()) {
 | 
			
		||||
                  QString save_path = matching_filter->getSavePath();
 | 
			
		||||
                  if(save_path.isEmpty())
 | 
			
		||||
                      BTSession->downloadUrlAndSkipDialog(item->getTorrentUrl());
 | 
			
		||||
                    BTSession->downloadUrlAndSkipDialog(torrent_url);
 | 
			
		||||
                  else
 | 
			
		||||
                      BTSession->downloadUrlAndSkipDialog(item->getTorrentUrl(), save_path);
 | 
			
		||||
                    BTSession->downloadUrlAndSkipDialog(torrent_url, save_path);
 | 
			
		||||
                } else {
 | 
			
		||||
                  // All torrents are downloaded from this feed
 | 
			
		||||
                    BTSession->downloadUrlAndSkipDialog(item->getTorrentUrl());
 | 
			
		||||
                  BTSession->downloadUrlAndSkipDialog(torrent_url);
 | 
			
		||||
                }
 | 
			
		||||
                // Item was downloaded, consider it as Read
 | 
			
		||||
                (*this)[item->getTitle()]->setRead();
 | 
			
		||||
@@ -608,7 +608,6 @@ short RssStream::readDoc(const QDomDocument& doc) {
 | 
			
		||||
                delete matching_filter;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
          } else {
 | 
			
		||||
            delete item;
 | 
			
		||||
 
 | 
			
		||||
@@ -298,7 +298,7 @@ public:
 | 
			
		||||
 | 
			
		||||
  RssItem(RssStream* parent, QString _title, QString _torrent_url, QString _news_link, QString _description, QDateTime _date, QString _author, bool _read):
 | 
			
		||||
      parent(parent), title(_title), torrent_url(_torrent_url), news_link(_news_link), description(_description), date(_date), author(_author), read(_read){
 | 
			
		||||
    if(!title.isEmpty() && !torrent_url.isEmpty()) {
 | 
			
		||||
    if(!title.isEmpty()) {
 | 
			
		||||
      is_valid = true;
 | 
			
		||||
    } else {
 | 
			
		||||
      std::cerr << "ERROR: an invalid RSS item was saved" << std::endl;
 | 
			
		||||
@@ -394,7 +394,6 @@ private:
 | 
			
		||||
  bool refreshed;
 | 
			
		||||
  bool downloadFailure;
 | 
			
		||||
  bool currently_loading;
 | 
			
		||||
  bool has_attachments;
 | 
			
		||||
 | 
			
		||||
public slots:
 | 
			
		||||
  void processDownloadedFile(QString file_path);
 | 
			
		||||
@@ -430,7 +429,6 @@ public:
 | 
			
		||||
  QList<RssItem*> getNewsList() const;
 | 
			
		||||
  QList<RssItem*> getUnreadNewsList() const;
 | 
			
		||||
  QString getIconUrl();
 | 
			
		||||
  bool hasAttachments() const { return has_attachments; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  short readDoc(const QDomDocument& doc);
 | 
			
		||||
 
 | 
			
		||||
@@ -71,12 +71,10 @@ void RSSImp::displayRSSListMenu(const QPoint& pos){
 | 
			
		||||
      myRSSListMenu.addSeparator();
 | 
			
		||||
      myRSSListMenu.addAction(actionCopy_feed_URL);
 | 
			
		||||
      if(selectedItems.size() == 1) {
 | 
			
		||||
        if(((RssStream*)listStreams->getRSSItem(selectedItems.first()))->hasAttachments()) {
 | 
			
		||||
        myRSSListMenu.addSeparator();
 | 
			
		||||
        myRSSListMenu.addAction(actionRSS_feed_downloader);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
  }else{
 | 
			
		||||
    myRSSListMenu.addAction(actionNew_subscription);
 | 
			
		||||
    myRSSListMenu.addAction(actionNew_folder);
 | 
			
		||||
@@ -293,9 +291,7 @@ void RSSImp::downloadTorrent() {
 | 
			
		||||
    if(article->has_attachment()) {
 | 
			
		||||
      BTSession->downloadFromUrl(article->getTorrentUrl());
 | 
			
		||||
    } else {
 | 
			
		||||
      QString link = article->getLink();
 | 
			
		||||
      if(!link.isEmpty())
 | 
			
		||||
        QDesktopServices::openUrl(QUrl(link));
 | 
			
		||||
      BTSession->downloadFromUrl(article->getLink());
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -444,10 +440,6 @@ void RSSImp::refreshNewsList(QTreeWidgetItem* item) {
 | 
			
		||||
  foreach(RssItem* article, news){
 | 
			
		||||
    QTreeWidgetItem* it = new QTreeWidgetItem(listNews);
 | 
			
		||||
    it->setText(NEWS_TITLE_COL, article->getTitle());
 | 
			
		||||
    if(article->has_attachment())
 | 
			
		||||
      it->setData(NEWS_TITLE_COL, Qt::DecorationRole, QVariant(QIcon(":/Icons/oxygen/application-x-kgetlist.png")));
 | 
			
		||||
    else
 | 
			
		||||
      it->setData(NEWS_TITLE_COL, Qt::DecorationRole, QVariant(QIcon(":/Icons/oxygen/application-x-kgetlist-no.png")));
 | 
			
		||||
    it->setText(NEWS_URL_COL, article->getParent()->getUrl());
 | 
			
		||||
    if(article->isRead()){
 | 
			
		||||
      it->setData(NEWS_TITLE_COL, Qt::ForegroundRole, QVariant(QColor("grey")));
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
#VERSION: 1.32
 | 
			
		||||
#AUTHORS: Fabien Devaux (fab@gnux.info)
 | 
			
		||||
#VERSION: 1.40
 | 
			
		||||
#AUTHORS: Christophe Dumez (chris@qbittorrent.org)
 | 
			
		||||
 | 
			
		||||
# Redistribution and use in source and binary forms, with or without
 | 
			
		||||
# modification, are permitted provided that the following conditions are met:
 | 
			
		||||
@@ -27,7 +27,7 @@
 | 
			
		||||
 | 
			
		||||
from novaprinter import prettyPrinter
 | 
			
		||||
from helpers import retrieve_url, download_file
 | 
			
		||||
from xml.dom import minidom
 | 
			
		||||
import sgmllib
 | 
			
		||||
import re
 | 
			
		||||
 | 
			
		||||
class mininova(object):
 | 
			
		||||
@@ -36,79 +36,76 @@ class mininova(object):
 | 
			
		||||
  name = 'Mininova'
 | 
			
		||||
  supported_categories = {'all': '0', 'movies': '4', 'tv': '8', 'music': '5', 'games': '3', 'anime': '1', 'software': '7', 'pictures': '6', 'books': '2'}
 | 
			
		||||
 | 
			
		||||
  def __init__(self):
 | 
			
		||||
    self.results = []
 | 
			
		||||
    self.parser = self.SimpleSGMLParser(self.results, self.url)
 | 
			
		||||
 | 
			
		||||
  def download_torrent(self, info):
 | 
			
		||||
    print download_file(info)
 | 
			
		||||
 | 
			
		||||
  class SimpleSGMLParser(sgmllib.SGMLParser):
 | 
			
		||||
    def __init__(self, results, url, *args):
 | 
			
		||||
      sgmllib.SGMLParser.__init__(self)
 | 
			
		||||
      self.url = url
 | 
			
		||||
      self.td_counter = None
 | 
			
		||||
      self.current_item = None
 | 
			
		||||
      self.results = results
 | 
			
		||||
      
 | 
			
		||||
    def start_a(self, attr):
 | 
			
		||||
      params = dict(attr)
 | 
			
		||||
      #print params
 | 
			
		||||
      if params.has_key('href') and params['href'].startswith("/get/"):
 | 
			
		||||
        self.current_item = {}
 | 
			
		||||
        self.td_counter = 0
 | 
			
		||||
        self.current_item['link']=self.url+params['href'].strip()
 | 
			
		||||
    
 | 
			
		||||
    def handle_data(self, data):
 | 
			
		||||
      if self.td_counter == 0:
 | 
			
		||||
        if not self.current_item.has_key('name'):
 | 
			
		||||
          self.current_item['name'] = ''
 | 
			
		||||
        self.current_item['name']+= data
 | 
			
		||||
      elif self.td_counter == 1:
 | 
			
		||||
        if not self.current_item.has_key('size'):
 | 
			
		||||
          self.current_item['size'] = ''
 | 
			
		||||
        self.current_item['size']+= data.strip()
 | 
			
		||||
      elif self.td_counter == 2:
 | 
			
		||||
        if not self.current_item.has_key('seeds'):
 | 
			
		||||
          self.current_item['seeds'] = ''
 | 
			
		||||
        self.current_item['seeds']+= data.strip()
 | 
			
		||||
      elif self.td_counter == 3:
 | 
			
		||||
        if not self.current_item.has_key('leech'):
 | 
			
		||||
          self.current_item['leech'] = ''
 | 
			
		||||
        self.current_item['leech']+= data.strip()
 | 
			
		||||
      
 | 
			
		||||
    def start_td(self,attr):
 | 
			
		||||
        if isinstance(self.td_counter,int):
 | 
			
		||||
          self.td_counter += 1
 | 
			
		||||
          if self.td_counter > 4:
 | 
			
		||||
            self.td_counter = None
 | 
			
		||||
            # Display item
 | 
			
		||||
            if self.current_item:
 | 
			
		||||
              self.current_item['engine_url'] = self.url
 | 
			
		||||
              if not self.current_item['seeds'].isdigit():
 | 
			
		||||
                self.current_item['seeds'] = 0
 | 
			
		||||
              if not self.current_item['leech'].isdigit():
 | 
			
		||||
                self.current_item['leech'] = 0
 | 
			
		||||
              prettyPrinter(self.current_item)
 | 
			
		||||
              self.results.append('a')
 | 
			
		||||
 | 
			
		||||
  def search(self, what, cat='all'):
 | 
			
		||||
 | 
			
		||||
		def get_link(lnk):
 | 
			
		||||
			lnks = lnk.getElementsByTagName('a')
 | 
			
		||||
			i = 0
 | 
			
		||||
			try:
 | 
			
		||||
				while not lnks.item(i).attributes.get('href').value.startswith('/get'):
 | 
			
		||||
					i += 1
 | 
			
		||||
			except:
 | 
			
		||||
				return None
 | 
			
		||||
			return (self.url+lnks.item(i).attributes.get('href').value).strip()
 | 
			
		||||
		
 | 
			
		||||
		def get_name(lnk):
 | 
			
		||||
			lnks = lnk.getElementsByTagName('a')
 | 
			
		||||
			i = 0
 | 
			
		||||
			try:
 | 
			
		||||
				while not lnks.item(i).attributes.get('href').value.startswith('/tor'):
 | 
			
		||||
					i += 1
 | 
			
		||||
			except:
 | 
			
		||||
				return None
 | 
			
		||||
			name = ""
 | 
			
		||||
			for node in lnks[i].childNodes:
 | 
			
		||||
				if node.hasChildNodes():
 | 
			
		||||
					name += node.firstChild.toxml()
 | 
			
		||||
				else:
 | 
			
		||||
					name += node.toxml()
 | 
			
		||||
			return re.sub('<[a-zA-Z\/][^>]*>', '', name)
 | 
			
		||||
 | 
			
		||||
		def get_text(txt):
 | 
			
		||||
			if txt.nodeType == txt.TEXT_NODE:
 | 
			
		||||
				return txt.toxml()
 | 
			
		||||
			else:
 | 
			
		||||
				return ''.join([ get_text(n) for n in txt.childNodes])
 | 
			
		||||
		
 | 
			
		||||
		if cat == 'all':
 | 
			
		||||
			self.table_items = 'added cat name size seeds leech'.split()
 | 
			
		||||
		else:
 | 
			
		||||
			self.table_items = 'added name size seeds leech'.split()
 | 
			
		||||
		page = 1
 | 
			
		||||
		while True and page<11:
 | 
			
		||||
			res = 0
 | 
			
		||||
			dat = retrieve_url(self.url+'/search/%s/%s/seeds/%d'%(what, self.supported_categories[cat], page))
 | 
			
		||||
			dat = re.sub("<a href=\"http://www.boardreader.com/index.php.*\"", "<a href=\"plop\"", dat)
 | 
			
		||||
			dat = re.sub("<=", "<=", dat)
 | 
			
		||||
			dat = re.sub("&\s", "& ", dat)
 | 
			
		||||
			dat = re.sub("&(?!amp)", "&", dat)
 | 
			
		||||
			x = minidom.parseString(dat)
 | 
			
		||||
			table = x.getElementsByTagName('table').item(0)
 | 
			
		||||
			if not table: return
 | 
			
		||||
			for tr in table.getElementsByTagName('tr'):
 | 
			
		||||
				tds = tr.getElementsByTagName('td')
 | 
			
		||||
				if tds:
 | 
			
		||||
					i = 0
 | 
			
		||||
					vals = {}
 | 
			
		||||
					for td in tds:
 | 
			
		||||
						if self.table_items[i] == 'name':
 | 
			
		||||
							vals['link'] = get_link(td)
 | 
			
		||||
							vals['name'] = get_name(td)
 | 
			
		||||
						else:
 | 
			
		||||
							vals[self.table_items[i]] = get_text(td).strip()
 | 
			
		||||
						i += 1
 | 
			
		||||
					vals['engine_url'] = self.url
 | 
			
		||||
					if not vals['seeds'].isdigit():
 | 
			
		||||
						vals['seeds'] = 0
 | 
			
		||||
					if not vals['leech'].isdigit():
 | 
			
		||||
						vals['leech'] = 0
 | 
			
		||||
					if vals['link'] is None:
 | 
			
		||||
						continue
 | 
			
		||||
					prettyPrinter(vals)
 | 
			
		||||
					res = res + 1
 | 
			
		||||
			if res == 0:
 | 
			
		||||
    ret = []
 | 
			
		||||
    i = 1
 | 
			
		||||
    while True and i<11:
 | 
			
		||||
      results = []
 | 
			
		||||
      parser = self.SimpleSGMLParser(results, self.url)
 | 
			
		||||
      dat = retrieve_url(self.url+'/search/%s/%s/seeds/%d'%(what, self.supported_categories[cat], i))
 | 
			
		||||
      results_re = re.compile('(?s)<h1>Search results for.*')
 | 
			
		||||
      for match in results_re.finditer(dat):
 | 
			
		||||
        res_tab = match.group(0)
 | 
			
		||||
        parser.feed(res_tab)
 | 
			
		||||
        parser.close()
 | 
			
		||||
        break
 | 
			
		||||
			page = page +1
 | 
			
		||||
      if len(results) <= 0:
 | 
			
		||||
        break
 | 
			
		||||
      i += 1
 | 
			
		||||
      
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
#VERSION: 1.22
 | 
			
		||||
#VERSION: 1.30
 | 
			
		||||
#AUTHORS: Fabien Devaux (fab@gnux.info)
 | 
			
		||||
#CONTRIBUTORS: Christophe Dumez (chris@qbittorrent.org)
 | 
			
		||||
 | 
			
		||||
@@ -50,32 +50,35 @@ class piratebay(object):
 | 
			
		||||
			self.results = results
 | 
			
		||||
			self.url = url
 | 
			
		||||
			self.code = 0
 | 
			
		||||
			self.in_name = None
 | 
			
		||||
 | 
			
		||||
		def start_a(self, attr):
 | 
			
		||||
			params = dict(attr)
 | 
			
		||||
			if params['href'].startswith('/browse'):
 | 
			
		||||
			if params['href'].startswith('/torrent/'):
 | 
			
		||||
				self.current_item = {}
 | 
			
		||||
				self.td_counter = 0
 | 
			
		||||
			elif params['href'].startswith('/tor'):
 | 
			
		||||
				self.code = params['href'].split('/')[2]
 | 
			
		||||
				self.in_name = True
 | 
			
		||||
			elif params['href'].startswith('http://torrents.thepiratebay.org/%s'%self.code):
 | 
			
		||||
				self.current_item['link']=params['href'].strip()
 | 
			
		||||
				self.td_counter = self.td_counter+1
 | 
			
		||||
				self.in_name = False
 | 
			
		||||
 | 
			
		||||
		def handle_data(self, data):
 | 
			
		||||
			if self.td_counter == 1:
 | 
			
		||||
			if self.td_counter == 0:
 | 
			
		||||
				if self.in_name:
 | 
			
		||||
					if not self.current_item.has_key('name'):
 | 
			
		||||
						self.current_item['name'] = ''
 | 
			
		||||
					self.current_item['name']+= data.strip()
 | 
			
		||||
			if self.td_counter == 5:
 | 
			
		||||
				if not self.current_item.has_key('size'):
 | 
			
		||||
					self.current_item['size'] = ''
 | 
			
		||||
				self.current_item['size']+= data.strip()
 | 
			
		||||
			elif self.td_counter == 6:
 | 
			
		||||
				else:
 | 
			
		||||
					#Parse size
 | 
			
		||||
					if 'Size' in data:
 | 
			
		||||
						self.current_item['size'] = data[data.index("Size")+5:]
 | 
			
		||||
						self.current_item['size'] = self.current_item['size'][:self.current_item['size'].index(',')]
 | 
			
		||||
			elif self.td_counter == 1:
 | 
			
		||||
				if not self.current_item.has_key('seeds'):
 | 
			
		||||
					self.current_item['seeds'] = ''
 | 
			
		||||
				self.current_item['seeds']+= data.strip()
 | 
			
		||||
			elif self.td_counter == 7:
 | 
			
		||||
			elif self.td_counter == 2:
 | 
			
		||||
				if not self.current_item.has_key('leech'):
 | 
			
		||||
					self.current_item['leech'] = ''
 | 
			
		||||
				self.current_item['leech']+= data.strip()
 | 
			
		||||
@@ -83,7 +86,7 @@ class piratebay(object):
 | 
			
		||||
		def start_td(self,attr):
 | 
			
		||||
			if isinstance(self.td_counter,int):
 | 
			
		||||
				self.td_counter += 1
 | 
			
		||||
				if self.td_counter > 7:
 | 
			
		||||
				if self.td_counter > 3:
 | 
			
		||||
					self.td_counter = None
 | 
			
		||||
					# Display item
 | 
			
		||||
					if self.current_item:
 | 
			
		||||
@@ -101,7 +104,8 @@ class piratebay(object):
 | 
			
		||||
		while True and i<11:
 | 
			
		||||
			results = []
 | 
			
		||||
			parser = self.SimpleSGMLParser(results, self.url)
 | 
			
		||||
			dat = retrieve_url(self.url+'/search/%s/%u/99/%s' % (what, i, self.supported_categories[cat]))
 | 
			
		||||
			dat = retrieve_url(self.url+'/search/%s/%u/7/%s' % (what, i, self.supported_categories[cat]))
 | 
			
		||||
			print self.url+'/search/%s/%u/7/%s' % (what, i, self.supported_categories[cat])
 | 
			
		||||
			parser.feed(dat)
 | 
			
		||||
			parser.close()
 | 
			
		||||
			if len(results) <= 0:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
isohunt: 1.30
 | 
			
		||||
torrentreactor: 1.20
 | 
			
		||||
btjunkie: 2.21
 | 
			
		||||
mininova: 1.32
 | 
			
		||||
piratebay: 1.22
 | 
			
		||||
mininova: 1.40
 | 
			
		||||
piratebay: 1.30
 | 
			
		||||
 
 | 
			
		||||
@@ -22,16 +22,15 @@
 | 
			
		||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 | 
			
		||||
# POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
#VERSION: 1.1
 | 
			
		||||
#VERSION: 1.2
 | 
			
		||||
 | 
			
		||||
# Author:
 | 
			
		||||
#  Christophe DUMEZ (chris@qbittorrent.org)
 | 
			
		||||
 | 
			
		||||
import re, htmlentitydefs
 | 
			
		||||
import urllib2
 | 
			
		||||
import tempfile
 | 
			
		||||
import os
 | 
			
		||||
import StringIO, gzip, httplib
 | 
			
		||||
import StringIO, gzip, urllib2
 | 
			
		||||
 | 
			
		||||
def htmlentitydecode(s):
 | 
			
		||||
    # First convert alpha entities (such as é)
 | 
			
		||||
@@ -64,12 +63,14 @@ def retrieve_url(url):
 | 
			
		||||
    dat = htmlentitydecode(dat)
 | 
			
		||||
    return dat.encode('utf-8', 'replace')
 | 
			
		||||
 | 
			
		||||
def download_file(url):
 | 
			
		||||
def download_file(url, referer=None):
 | 
			
		||||
    """ Download file at url and write it to a file, return the path to the file and the url """
 | 
			
		||||
    file, path = tempfile.mkstemp()
 | 
			
		||||
    file = os.fdopen(file, "w")
 | 
			
		||||
    # Download url
 | 
			
		||||
    req = urllib2.Request(url)
 | 
			
		||||
    if referer is not None:
 | 
			
		||||
        req.add_header('referer', referer)
 | 
			
		||||
    response = urllib2.urlopen(req)
 | 
			
		||||
    dat = response.read()
 | 
			
		||||
    # Check if data is gzip encoded
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ LANG_PATH = lang
 | 
			
		||||
ICONS_PATH = Icons
 | 
			
		||||
 | 
			
		||||
# Set the following variable to 1 to enable debug
 | 
			
		||||
DEBUG_MODE = 1
 | 
			
		||||
DEBUG_MODE = 0
 | 
			
		||||
 | 
			
		||||
# Global
 | 
			
		||||
TEMPLATE = app
 | 
			
		||||
@@ -12,10 +12,10 @@ CONFIG += qt \
 | 
			
		||||
    thread
 | 
			
		||||
 | 
			
		||||
# Update this VERSION for each release
 | 
			
		||||
DEFINES += VERSION=\\\"v2.0.0\\\"
 | 
			
		||||
DEFINES += VERSION=\\\"v2.0.2\\\"
 | 
			
		||||
DEFINES += VERSION_MAJOR=2
 | 
			
		||||
DEFINES += VERSION_MINOR=0
 | 
			
		||||
DEFINES += VERSION_BUGFIX=0
 | 
			
		||||
DEFINES += VERSION_BUGFIX=2
 | 
			
		||||
 | 
			
		||||
# !mac:QMAKE_LFLAGS += -Wl,--as-needed
 | 
			
		||||
contains(DEBUG_MODE, 1) { 
 | 
			
		||||
 
 | 
			
		||||
@@ -846,8 +846,10 @@ void TransferListWidget::displayListMenu(const QPoint&) {
 | 
			
		||||
  connect(&actionForce_recheck, SIGNAL(triggered()), this, SLOT(recheckSelectedTorrents()));
 | 
			
		||||
  QAction actionCopy_magnet_link(QIcon(QString::fromUtf8(":/Icons/magnet.png")), tr("Copy magnet link"), 0);
 | 
			
		||||
  connect(&actionCopy_magnet_link, SIGNAL(triggered()), this, SLOT(copySelectedMagnetURIs()));
 | 
			
		||||
#ifdef LIBTORRENT_0_15
 | 
			
		||||
  QAction actionSuper_seeding_mode(tr("Super seeding mode"), 0);
 | 
			
		||||
  connect(&actionSuper_seeding_mode, SIGNAL(triggered()), this, SLOT(toggleSelectedTorrentsSuperSeeding()));
 | 
			
		||||
#endif
 | 
			
		||||
  QAction actionSequential_download(tr("Download in sequential order"), 0);
 | 
			
		||||
  connect(&actionSequential_download, SIGNAL(triggered()), this, SLOT(toggleSelectedTorrentsSequentialDownload()));
 | 
			
		||||
  QAction actionFirstLastPiece_prio(tr("Download first and last piece first"), 0);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user