Compare commits

..

84 Commits

Author SHA1 Message Date
sledgehammer999
e2da3f2ebd Bump to 3.3.2 2016-01-19 01:45:05 +02:00
sledgehammer999
f235d412f8 Bump Copyright year. 2016-01-19 01:44:03 +02:00
sledgehammer999
60b103b062 Update Changelog. 2016-01-19 01:34:08 +02:00
sledgehammer999
0fdb23098b Bump WebUI API_VERSION and API_VERSION_MIN. 2016-01-19 01:32:32 +02:00
sledgehammer999
51c296ac69 Sync translations from Transifex and run lupdate. 2016-01-19 00:50:48 +02:00
Vladimir Golovnev (Glassez)
a120842ba2 Fix unchecked dynamic_cast
Replace some unnecessary (and slow) dynamic_cast with static_cast.
2016-01-18 19:45:45 +02:00
Vladimir Golovnev (Glassez)
8911de9349 Fix unitialized pointer field 2016-01-18 19:45:45 +02:00
Vladimir Golovnev (Glassez)
013a1b8403 Fix unitialized scalar field bugs 2016-01-18 19:45:45 +02:00
Vladimir Golovnev (Glassez)
1492a24391 Simplify Log::Msg and Log::Peer
Also fixes some unitialized scalar field bugs.
2016-01-18 19:45:44 +02:00
buinsky
bf1559320b WebUI: Remember last opened tab 2016-01-18 19:45:44 +02:00
Vladimir Golovnev (Glassez)
d5648a67ae Fix loading corrupted .fastresume file 2016-01-18 19:45:44 +02:00
Vladimir Golovnev (Glassez)
a6ec82682d Delete unused include 2016-01-18 19:45:43 +02:00
Vladimir Golovnev (Glassez)
bd359ad498 Allow GeoIP in NoGUI builds 2016-01-18 19:45:43 +02:00
Vladimir Golovnev (Glassez)
458f48b290 Fix unitialized scalar fields 2016-01-18 19:45:43 +02:00
Vladimir Golovnev (Glassez)
a0ae21148a Fix NetworkCookieJar::deleteCookie() behavior to match Qt5 one 2016-01-18 19:45:42 +02:00
Vladimir Golovnev (Glassez)
5dc9b5c2dd Fix reconfigure additional trackers
Replace wrong QList::empty() call with QList::clear()
2016-01-18 19:45:42 +02:00
buinsky
48175bbb85 WebUI: Repair translation 2016-01-18 19:45:42 +02:00
Gabriele
3b03bb286e WebUI: Allow to remove the label assigned to a torrent
Empty strings are not valid label names, but they are used to remove
torrent labels, so allow them.
2016-01-18 19:45:41 +02:00
Chocobo1
23fdf3a0bc Update uncrustify script link. 2016-01-18 19:45:41 +02:00
Dmitry Victorov
4cf7618c52 Set qBittorrent as default torrent app in Mac OS 2016-01-18 19:45:41 +02:00
sledgehammer999
6fd9413dae Sync translations from Transifex and run lupdate. 2016-01-18 19:45:39 +02:00
sledgehammer999
120d073a04 Various updates on the Windows configuration file. 2016-01-18 19:45:39 +02:00
filipporig8
8fa2adb6fc Update webui run program parameters 2016-01-18 19:45:38 +02:00
buinsky
70105d5834 WebUI: Fix torrent table context menu
Don't show "Limit download speed" menu item for downloaded torrents.
2016-01-18 19:45:38 +02:00
buinsky
05961faf42 WebUI: Fix deleting torrents
Fix possible showing "qBittorrent client is not reachable" message on
deleting torrents.
2016-01-18 19:45:38 +02:00
vlakoff
386706f05b Complete French translation for installer 2016-01-18 19:45:37 +02:00
vlakoff
1813e96a42 Fixes in French translation for installer 2016-01-18 19:45:37 +02:00
buinsky
eaf6e47391 Edit speed limits and upload ratio icons 2016-01-18 19:45:37 +02:00
Chocobo1
8ba82064cd Replace names with camelCase style 2016-01-18 19:45:36 +02:00
Chocobo1
5d5a0de694 Use C++11 initializer list 2016-01-18 19:45:36 +02:00
Chocobo1
145180c2a1 Follow project coding style. Issue #2192. 2016-01-18 19:45:35 +02:00
Chocobo1
50881b9972 Rename column header 2016-01-18 19:45:35 +02:00
sledgehammer999
a115932bc1 Fix newlines in wiki rendering. 2016-01-18 19:45:35 +02:00
sledgehammer999
c7fd0fbe45 Add info and files for coding style. Issue #2192. 2016-01-18 19:45:34 +02:00
Boris Nagaev
d513d002cc convert includes like <Windows.h> to lowercase
There is header file windows.h, not Windows.h.
MinGW on Linux build machine is filename case-sensitive.
2016-01-18 19:45:34 +02:00
ngosang
a570bd5e2c [search engine] Update PirateBay URL. Closes #4470 2016-01-18 19:45:34 +02:00
ngosang
bdacfd540c [search engine] Fix PirateBay plugin implementation for Python 3 2016-01-18 19:45:33 +02:00
buinsky
c89b9edf27 Move some styles into css 2016-01-18 19:45:33 +02:00
schnurlos
0fdf788624 Update german.nsi
Translated the "A previous installation was detected ..." text.
2016-01-18 19:45:33 +02:00
ngosang
f0ae30070b Update installer translations in Spanish language 2016-01-18 19:45:32 +02:00
sledgehammer999
8fb8f4b467 Don't require GUI libs for qt4 nox build. Closes #4404. 2016-01-18 19:45:32 +02:00
dzmat
c3a2e50191 Update russian.nsi
Translated new string/
2016-01-18 19:45:31 +02:00
Vladimir Golovnev (Glassez)
b045b5ebf7 Improve RSS parsing logic. 2016-01-18 19:45:31 +02:00
Vladimir Golovnev (Glassez)
6436152c75 Redesign RSS base classes. 2016-01-18 19:45:31 +02:00
Vladimir Golovnev (Glassez)
9c3ae53330 Move base RSS names to Rss namespace. 2016-01-18 19:45:30 +02:00
Vladimir Golovnev (Glassez)
acd5fcfb00 Fix coding style (Issue #2192). 2016-01-18 19:45:30 +02:00
Vladimir Golovnev (Glassez)
9a6f8ab402 Move base RSS code to Core. 2016-01-18 19:45:29 +02:00
Vladimir Golovnev (qlassez)
0f854014af Use DownloadManager by DNSUpdater 2016-01-18 19:45:29 +02:00
Vladimir Golovnev (qlassez)
a11175afba Use DownloadManager by ProgramUpdater
Closes #2023
2016-01-18 19:45:28 +02:00
Vladimir Golovnev (qlassez)
c5776c3bf1 Save RSS cookies to common cookie storage
Closes #4305
2016-01-18 19:45:28 +02:00
Vladimir Golovnev (qlassez)
19d566253f Make DownloadManager to save/load cookies 2016-01-18 19:45:27 +02:00
Naikel Aparicio
0d59d6a03e Implemented WebUI interface for the new Watched Folders feature 2016-01-18 19:45:27 +02:00
sledgehammer999
c7b2ee367f Remove watch folders permanently only if the user accepts the Preferences dialog. 2016-01-18 19:45:27 +02:00
sledgehammer999
510ec029ea Make it scroll horizontally when necessary. 2016-01-18 19:45:26 +02:00
sledgehammer999
1f2daed9d6 Fix translated string. 2016-01-18 19:45:26 +02:00
sledgehammer999
08b854ce74 Method to update the watch path parameters. 2016-01-18 19:45:25 +02:00
sledgehammer999
6b34803c59 Don't add the watch folder before the user closes the Preferences window. 2016-01-18 19:45:25 +02:00
sledgehammer999
fca224b9d0 Support loading multiple magnets/hashes/urls per .magnet file in the watched folder(one per line). Closes #217. 2016-01-18 19:45:25 +02:00
Vladimir Golovnev (qlassez)
4f5009351f Fix setting custom download location for watched folder 2016-01-18 19:45:24 +02:00
sledgehammer999
c1f77d45ab Improve the "Watch folders" UI. Closes #4300. 2016-01-18 19:45:24 +02:00
sledgehammer999
60f0447603 Indicate to the user that he's going to download the new version.
Indicate from the installer that the old version was detected and no settings will be deleted.
Closes #4320.
2016-01-18 19:45:23 +02:00
sledgehammer999
6ae208a661 Move the 'qBittorrent-resume' file even when no magnets were recovered. Also make sure to rename it with a unique name. Closes #4334. 2016-01-18 19:45:23 +02:00
Eugene Shalygin
781c8034a5 Add column with list of currently downloading files
Add a new column to peers list that shows list of files which are
downloaded right now from a peer. The column is empty if we do not
download anything from the given peer.
2016-01-18 19:45:22 +02:00
Eugene Shalygin
4cf8359257 functions for retrieving list of currently downloading files 2016-01-18 19:45:22 +02:00
Eugene Shalygin
3ed4de3043 Revert "Remove unused parameter."
This reverts commit 87347cf0e5.
2016-01-18 19:45:22 +02:00
sledgehammer999
a374b99ba2 Update native names for Chinese locales. Closes #4381. 2016-01-18 19:45:21 +02:00
Naikel Aparicio
601734a59b Fixed bug when uploading several files and only the last one was considered. 2016-01-18 19:45:21 +02:00
Chocobo1
69cc97c3dd Turn off warning on OSX builds: unused-local-typedefs
Reorder option list, sort by lt_branch then qt then gui
2016-01-18 19:45:20 +02:00
buinsky
226f74a866 Fix paused, active and inactive filters 2016-01-18 19:45:20 +02:00
buinsky
cf35392cd2 WebUI: Show filtered torrents number 2016-01-18 19:45:20 +02:00
Chocobo1
27319e9e64 Fix typo 2016-01-18 19:45:19 +02:00
Chocobo1
69b8544e26 Simplify statement 2016-01-18 19:45:19 +02:00
Chocobo1
41e5dc8911 Add check for null. Fix provided by glassez.
Closes #4280.
2016-01-18 19:45:18 +02:00
Vladimir Golovnev (qlassez)
ba1ffa4e54 Fix moving torrents to Temp after app restart
Closes #4434
2016-01-18 19:45:18 +02:00
Vladimir Golovnev (Glassez)
4edc073373 Fix coding style (Issue #2192). 2016-01-18 19:45:18 +02:00
Vladimir Golovnev (Glassez)
1f00d2e5d7 Move basic search-related code into Core.
Also use qBittorrent torrent file download routines instead of
nova2dl.py script.
2016-01-18 19:45:17 +02:00
Vladimir Golovnev (Glassez)
d87e42ba00 Move Search-related files into Gui. 2016-01-18 19:45:17 +02:00
Vladimir Golovnev (Glassez)
975b1d5257 Fix search-related file/class names. 2016-01-18 19:43:28 +02:00
Fabio Alessandro Locati
5f84363afb Fix lrelease version due to the default Qt5 build
As title
2016-01-18 19:43:28 +02:00
Chocobo1
545c526e2f Update ISO 3166 country codes. Closes #3942. 2016-01-18 19:43:27 +02:00
sledgehammer999
06fcc57619 Fix linux build. 2016-01-18 19:43:27 +02:00
sledgehammer999
06c6a444c9 Don't apply some settings again if they weren't changed. Closes #4278. 2016-01-18 19:43:26 +02:00
sledgehammer999
8474d0d199 Don't recheck twice after 'Force Recheck' with 'Recheck torrents on completion' enabled. Closes #4274. 2016-01-18 19:43:26 +02:00
sledgehammer999
0f4610c127 Fix resolution of peer host names. Closes #4307. 2016-01-18 19:43:26 +02:00
256 changed files with 74479 additions and 70422 deletions

View File

@@ -8,12 +8,13 @@ osx_image: xcode7
env:
matrix:
# Uncomment when Travis upgraded "Ubuntu 12.04 LTS" to a newer version whose repo will have a more up-to-date libtorrent package
#- lt_branch=dist gui=true
#- lt_branch=dist gui=false
- lt_branch=RC_1_0 gui=true qt=4
- lt_branch=RC_1_0 gui=true qt=5
- lt_branch=RC_1_0 gui=false qt=4
- lt_branch=RC_1_0 gui=false qt=5
#- lt_branch=dist gui=true
#- lt_branch=dist gui=false
- lt_branch=RC_1_0 qt=5 gui=true
- lt_branch=RC_1_0 qt=5 gui=false
- lt_branch=RC_1_0 qt=4 gui=true
- lt_branch=RC_1_0 qt=4 gui=false
global:
- secure: "OI9CUjj4lTb0HwwIZU5PbECU3hLlAL6KC8KsbwohG8/O3j5fLcnmDsK4Ad9us5cC39sS11Jcd1kDP2qRcCuST/glVNhLkcjKkiQerOfd5nQ/qL4JYfz/1mfP5mdpz9jHKzpLUIG+TXkbSTjP6VVmsb5KPT+3pKEdRFZB+Pu9+J8="
- coverity_branch: coverity_scan
@@ -21,9 +22,9 @@ env:
matrix:
exclude:
- os: linux
env: lt_branch=RC_1_0 gui=true qt=5
env: lt_branch=RC_1_0 qt=5 gui=true
- os: linux
env: lt_branch=RC_1_0 gui=false qt=5
env: lt_branch=RC_1_0 qt=5 gui=false
branches:
except:
@@ -89,7 +90,8 @@ before_install:
elif [ "$TRAVIS_OS_NAME" = "linux" ]; then export "DISPLAY=:99.0" && /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16 ;
fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then qbtconf="$qbtconf --disable-qt-dbus" ; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$qt" = 5 ]; then qbtconf="$qbtconf --with-qt4=no" ; fi
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$qt" = 4 ]; then brew install qt; fi
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$qt" = 5 ]; then qbtconf="$qbtconf --with-qt4=no" ; fi
# Print settings
- echo $lt_branch
@@ -101,14 +103,14 @@ before_install:
install:
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$lt_branch" != "dist" ]; then cd "$HOME" && pwd && git clone --depth 1 https://github.com/arvidn/libtorrent.git --branch $lt_branch ; fi
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$lt_branch" != "dist" ]; then cd libtorrent && ./autotool.sh && ./configure $ltconf && make install && cd "$TRAVIS_BUILD_DIR" ; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update > /dev/null && brew install colormake libtorrent-rasterbar; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$qt" = 4 ]; then brew install qt; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ] && [ "$qt" = 5 ]; then brew install qt5 && brew link --force qt5; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update > /dev/null && brew install colormake libtorrent-rasterbar ; fi
- if [ "$TRAVIS_OS_NAME" = "osx" -a "$qt" = 5 ]; then brew install qt5 && brew link --force qt5 ; fi
script:
- if [ "$TRAVIS_BRANCH" = "$coverity_branch" ]; then exit ; fi # Skip usual build when running coverity scan
- ./bootstrap.sh && ./configure $qbtconf
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then echo QMAKE_CC=$CC >> conf.pri && echo QMAKE_CXX=$CXX >> conf.pri ; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then echo "QMAKE_CC=$CC" >> conf.pri && echo "QMAKE_CXX=$CXX" >> conf.pri ; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then sed -i "" -e 's/^\(CXXFLAGS.*\)$/\1 -Wno-unused-local-typedefs/' src/Makefile ; fi
- make && make install
after_success:

View File

@@ -79,6 +79,11 @@ Images Authors:
* file: src/icons/oxygen/checked.png
copyright: Victor Buinsky <allok.victor@gmail.com>
* file: src/icons/skin/ratio.png
copyright: Fatcow Web Hosting
license: Creative Commons Attribution 3.0 License
url: http://www.fatcow.com/free-icons
Translations authors:
* files: src/lang/*.ts

View File

@@ -1,6 +1,8 @@
All new code must follow the following coding guidelines.
If you make changes in a file that still uses another coding style, make sure that you follow these guidelines for your changes instead.
**Note:** I will now take your head if you forget and use another style. However, most probably the request will be delayed until you fix your coding style.
**Note 1:** I will not take your head if you forget and use another style. However, most probably the request will be delayed until you fix your coding style.
**Note 2:** You can use the `uncrustify` program/tool to clean up any source file. Use it with the `uncrustify.cfg` configuration file found in the root folder.
**Note 3:** There is also a style for QtCreator but it doesn't cover all cases. In QtCreator `Tools->Options...->C++->Code Style->Import...` and choose the `codingStyleQtCreator.xml` file found in the root folder.
### 1. Curly braces ###
#### a. Function blocks, class/struct definitions, namespaces ####

View File

@@ -17,7 +17,7 @@ OS version:
* **Screenshots**! A screenshot is worth a thousand words. just upload it. [(How?)](https://help.github.com/articles/file-attachments-on-issues-and-pull-requests)
### Good to know
* **Patience**. The dev team is small and resource limited. Devs finding their free time, analyzing the problem and fixing the issue, it all takes time. :clock3:
* **Be patient**. The dev team is small and resource limited. Devs finding their free time, analyzing the problem and fixing the issue, it all takes time. :clock3:
* If you can code, why not become a **contributor** by fixing the issue and open a pull request? :wink:
* Harsh words or threats won't help your situation. What's worse, your complain will (very likely) to be **ignored**. :fearful:
@@ -25,7 +25,7 @@ OS version:
# Opening a pull request
### Must read
* Read our [**coding guidelines**](https://github.com/qbittorrent/qBittorrent/blob/master/CODING_GUIDELINES.md). There are some scripts to help you: [uncrustify script](https://gist.github.com/sledgehammer999/1cb1d9224d7fec8fa632), [astyle script](https://gist.github.com/Chocobo1/539cee860d1eef0acfa6), [(related thread)](https://github.com/qbittorrent/qBittorrent/issues/2192).
* Read our [**coding guidelines**](https://github.com/qbittorrent/qBittorrent/blob/master/CODING_GUIDELINES.md). There are some scripts to help you: [uncrustify script](https://raw.githubusercontent.com/qbittorrent/qBittorrent/master/uncrustify.cfg), [astyle script](https://gist.github.com/Chocobo1/539cee860d1eef0acfa6), [(related thread)](https://github.com/qbittorrent/qBittorrent/issues/2192).
* Keep the title **short** and provide a **clear** description about what your pull request does.
* Provide **screenshots** for UI related changes.
* Keep your git commit history **clean** and **precise**. Commits like `xxx fixup` should not appear.

View File

@@ -1,3 +1,46 @@
* Tue Jan 19 2016 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.3.2
- FEATURE: Add a new column to peers list that shows list of files which are downloaded right now from a peer. (evsh)
- FEATURE: Improve the "Watch folders" UI. Closes #4300. You'll need to redo your watch folders settings. (sledgehammer999, glassez)
- FEATURE: Support loading multiple magnets/hashes/urls per .magnet file in the watched folder(one per line). Closes #217. (sledgehammer999)
- BUGFIX: Fix resolution of peer host names. Closes #4307. (sledgehammer999)
- BUGFIX: Don't recheck twice after 'Force Recheck' with 'Recheck torrents on completion' enabled. Closes #4274. (sledgehammer999)
- BUGFIX: Don't apply some settings again if they weren't changed. Closes #4278. (sledgehammer999)
- BUGFIX: Update ISO 3166 country codes. Closes #3942. (Chocobo1)
- BUGFIX: Fix moving torrents to Temp after app restart. Closes #4434. (glassez)
- BUGFIX: Fix crash in favicon code due to null pointer dereference. (glassez)
- BUGFIX: Move the 'qBittorrent-resume' file even when no magnets were recovered. Also make sure to rename it with a unique name. Closes #4334. (sledgehammer999)
- BUGFIX: Don't add the watch folder before the user closes the Preferences window. (sledgehammer999)
- BUGFIX: Remove watch folders permanently only if the user accepts the Preferences dialog. (sledgehammer999)
- BUGFIX: Better handling of cookies in the download manager (glassez)
- BUGFIX: Use the download manager for RSS, the program updater and the dns updater. (glassez)
- BUGFIX: Fix reconfigure additional trackers (glassez)
- BUGFIX: Fix loading corrupted .fastresume file (glassez)
- WEBUI: Show filtered torrents number (buinsky)
- WEBUI: Fix paused, active and inactive filters (buinsky)
- WEBUI: Fixed bug when uploading several files and only the last one was considered. (naikel)
- WEBUI: Implemented WebUI interface for the new Watched Folders feature (naikel)
- WEBUI: Fix possible showing "qBittorrent client is not reachable" message on deleting torrents. (buinsky)
- WEBUI: Don't show "Limit download speed" menu item for downloaded torrents. (buinsky)
- WEBUI: Update webui run program parameters (buinsky)
- WEBUI: Allow to remove the label assigned to a torrent (pmzqla)
- WEBUI: Repair translation (buinsky)
- WEBUI: Remember last opened tab (buinsky)
- WEBUI: Bump WebUI API_VERSION and API_VERSION_MIN.
- COSMETIC: Update native names for Chinese locales. Closes #4381. (sledgehammer999)
- COSMETIC: Rename column header in Content view. (Chocobo1)
- COSMETIC: Edit speed limits and upload ratio icons (buinsky)
- SEARCH: Code refactoring. (glassez)
- SEARCH: Fix PirateBay plugin implementation for Python 3 (ngosang)
- SEARCH: Update PirateBay URL. Closes #4470 (ngosang)
- RSS: Code refactoring. (glassez)
- LINUX: Fix build. (sledgehammer999)
- OSX: Set qBittorrent as default torrent app in Mac OS (dmitry.viktorov)
- OTHER: Fix lrelease version due to the default Qt5 build (Fabio Alessandro Locati)
- OTHER: Indicate to the user that he's going to download the new version. Indicate from the installer that the old version was detected and no settings will be deleted. Closes #4320. (sledgehammer999)
- OTHER: Don't require GUI libs for qt4 nox build. Closes #4404. (sledgehammer999)
- OTHER: Fix cross-compilation (bnagaev)
- OTHER: Allow GeoIP in nox builds (glassez)
* Tue Dec 08 2015 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.3.1
- FEATURE: New "Set as default label" option in Add torrent dialog. (takiz)
- FEATURE: Support wildcards for filtering torrent list and torrent content (vlakoff)

39
codingStyleQtCreator.xml Normal file
View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorCodeStyle>
<!-- Written by QtCreator 3.2.82, 2014-11-26T02:08:28. -->
<qtcreator>
<data>
<variable>CodeStyleData</variable>
<valuemap type="QVariantMap">
<value type="bool" key="AlignAssignments">true</value>
<value type="bool" key="AutoSpacesForTabs">false</value>
<value type="bool" key="BindStarToIdentifier">false</value>
<value type="bool" key="BindStarToLeftSpecifier">true</value>
<value type="bool" key="BindStarToRightSpecifier">false</value>
<value type="bool" key="BindStarToTypeName">true</value>
<value type="bool" key="ExtraPaddingForConditionsIfConfusingAlign">false</value>
<value type="bool" key="IndentAccessSpecifiers">false</value>
<value type="bool" key="IndentBlockBody">true</value>
<value type="bool" key="IndentBlockBraces">false</value>
<value type="bool" key="IndentBlocksRelativeToSwitchLabels">false</value>
<value type="bool" key="IndentClassBraces">false</value>
<value type="bool" key="IndentControlFlowRelativeToSwitchLabels">true</value>
<value type="bool" key="IndentDeclarationsRelativeToAccessSpecifiers">true</value>
<value type="bool" key="IndentEnumBraces">false</value>
<value type="bool" key="IndentFunctionBody">true</value>
<value type="bool" key="IndentFunctionBraces">false</value>
<value type="bool" key="IndentNamespaceBody">true</value>
<value type="bool" key="IndentNamespaceBraces">false</value>
<value type="int" key="IndentSize">4</value>
<value type="bool" key="IndentStatementsRelativeToSwitchLabels">true</value>
<value type="bool" key="IndentSwitchLabels">false</value>
<value type="int" key="PaddingMode">1</value>
<value type="bool" key="SpacesForTabs">true</value>
<value type="int" key="TabSize">4</value>
</valuemap>
</data>
<data>
<variable>DisplayName</variable>
<value type="QString">qBittorrent</value>
</data>
</qtcreator>

4
dist/mac/Info.plist vendored
View File

@@ -45,7 +45,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>3.3.1</string>
<string>3.3.2</string>
<key>CFBundleSignature</key>
<string>qBit</string>
<key>CFBundleExecutable</key>
@@ -59,7 +59,7 @@
<key>NSAppleScriptEnabled</key>
<string>YES</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2006-2015 The qBittorrent project</string>
<string>Copyright © 2006-2016 The qBittorrent project</string>
<key>UTExportedTypeDeclarations</key>
<array>
<dict>

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_AFRIKAANS} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_AFRIKAANS} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_AFRIKAANS} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_AFRIKAANS} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_AFRIKAANS} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_ALBANIAN} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_ALBANIAN} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_ALBANIAN} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_ALBANIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_ALBANIAN} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_ARABIC} "اضافة قاعدة للجدار ال
LangString inst_firewallinfo ${LANG_ARABIC} "جاري اضافة القاعدة للجدار الناري"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_ARABIC} "البرنامج يعمل. يرجى اغلاقه قبل البدء في التنصيب"
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_ARABIC} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_ARABIC} "جاري ازالة النسخة السابقة من البرنامج"
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_BASQUE} "Gehitu Windows Suhesi araua"
LangString inst_firewallinfo ${LANG_BASQUE} "Windows Suhesi araua gehitzen"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_BASQUE} "qBittorrent ekinean dago. Mesedez itxi aplikazioa ezarri aurretik."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_BASQUE} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_BASQUE} "Aurreko bertsioa kentzen."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_BELARUSIAN} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_BELARUSIAN} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_BELARUSIAN} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_BELARUSIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_BELARUSIAN} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_BOSNIAN} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_BOSNIAN} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_BOSNIAN} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_BOSNIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_BOSNIAN} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_BRETON} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_BRETON} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_BRETON} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_BRETON} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_BRETON} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_BULGARIAN} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_BULGARIAN} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_BULGARIAN} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_BULGARIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_BULGARIAN} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_CATALAN} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_CATALAN} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_CATALAN} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_CATALAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_CATALAN} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_CROATIAN} "Dodaj Windows Firewall pravilo"
LangString inst_firewallinfo ${LANG_CROATIAN} "Dodavanje Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_CROATIAN} "qBittorrent je pokrenut. Zatvorite ga prije instalacije."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_CROATIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_CROATIAN} "Deinstaliraj prethodnu verziju."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_CZECH} "Vytvořit pravidlo ve Windows Firewall"
LangString inst_firewallinfo ${LANG_CZECH} "Vytváření pravidla ve Windows Firewall"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_CZECH} "qBittorrent je spuštěn. Před instalací aplikaci ukončete, prosím."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_CZECH} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_CZECH} "Odebírání předchozí verze."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_DANISH} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_DANISH} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_DANISH} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_DANISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_DANISH} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_DUTCH} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_DUTCH} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_DUTCH} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_DUTCH} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_DUTCH} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_ESPERANTO} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_ESPERANTO} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_ESPERANTO} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_ESPERANTO} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_ESPERANTO} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_ESTONIAN} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_ESTONIAN} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_ESTONIAN} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_ESTONIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_ESTONIAN} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_FARSI} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_FARSI} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_FARSI} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_FARSI} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_FARSI} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_FINNISH} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_FINNISH} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_FINNISH} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_FINNISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_FINNISH} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -11,11 +11,13 @@ LangString inst_torrent ${LANG_FRENCH} "Ouvrir fichiers .torrent avec qBittorren
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
LangString inst_magnet ${LANG_FRENCH} "Ouvrir liens magnet avec qBittorrent"
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
LangString inst_firewall ${LANG_FRENCH} "Ajouter régle Pare-Feu Windows"
LangString inst_firewall ${LANG_FRENCH} "Ajouter règle Pare-Feu Windows"
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
LangString inst_firewallinfo ${LANG_FRENCH} "Ajout régle Pare-Feu Windows"
LangString inst_firewallinfo ${LANG_FRENCH} "Ajout règle Pare-Feu Windows"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_FRENCH} "qBittorrent est en exécution. Veuillez fermer l'application avant l'installation."
LangString inst_warning ${LANG_FRENCH} "qBittorrent est en cours d'exécution. Veuillez fermer l'application avant l'installation."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_FRENCH} "Une installation précédente a été détectée. Elle sera désinstallée sans supprimer les réglages utilisateur."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_FRENCH} "Désinstallation de la version précédente."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
@@ -30,20 +32,20 @@ LangString remove_files ${LANG_FRENCH} "Supprimer fichiers"
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
LangString remove_shortcuts ${LANG_FRENCH} "Supprimer raccourcis"
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
LangString remove_associations ${LANG_FRENCH} "Supprimer fichiers associés"
LangString remove_associations ${LANG_FRENCH} "Supprimer associations de fichiers"
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
LangString remove_registry ${LANG_FRENCH} "supprimer clés de registre"
LangString remove_registry ${LANG_FRENCH} "Supprimer clés de registre"
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
LangString remove_conf ${LANG_FRENCH} "Supprimer fichiers de configuration"
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
LangString remove_firewall ${LANG_FRENCH} "Supprimer régle Pare-Feu Windows"
LangString remove_firewall ${LANG_FRENCH} "Supprimer règle Pare-Feu Windows"
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
LangString remove_firewallinfo ${LANG_FRENCH} "Suppression régle Pare-Feu Windows"
LangString remove_firewallinfo ${LANG_FRENCH} "Suppression règle Pare-Feu Windows"
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
LangString remove_cache ${LANG_FRENCH} "Supprimer torrents et données cachées"
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
LangString uninst_warning ${LANG_FRENCH} "qBittorrent est en exécution. Veuillez fermer l'application avant la désinstallation."
LangString uninst_warning ${LANG_FRENCH} "qBittorrent est en cours d'exécution. Veuillez fermer l'application avant la désinstallation."
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
LangString uninst_tor_warn ${LANG_FRENCH} "Ne peut pas supprimer l'association du .torrent. Elle est associée avec:"
LangString uninst_tor_warn ${LANG_FRENCH} "Ne peut pas supprimer l'association du .torrent. Elle est associée avec :"
;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:"
LangString uninst_mag_warn ${LANG_FRENCH} "Ne peut pas supprimer l'association du magnet. Elle est associée avec:"
LangString uninst_mag_warn ${LANG_FRENCH} "Ne peut pas supprimer l'association du magnet. Elle est associée avec :"

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_GALICIAN} "Engadir unha regra á devasa (firewal
LangString inst_firewallinfo ${LANG_GALICIAN} "Engadindo unha regra á devasa de Windows"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_GALICIAN} "qBittorrent está en execución. Peche o aplicativo antes da instalación."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_GALICIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_GALICIAN} "Desinstalando a versión anterior."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_GERMAN} "Regel in der Windows Firewall hinzufüg
LangString inst_firewallinfo ${LANG_GERMAN} "Füge Regel in der Windows Firewall hinzu"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_GERMAN} "qBittorrent läuft gerade. Bitte das Programm vor der Installation beenden."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_GERMAN} "Eine ältere Installation wurde festgestellt. Diese wird deinstalliert ohne die Benutzereinstellungen zu löschen."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_GERMAN} "Vorherige Version wird deinstalliert."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_GREEK} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_GREEK} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_GREEK} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_GREEK} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_GREEK} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_HEBREW} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_HEBREW} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_HEBREW} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_HEBREW} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_HEBREW} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_HUNGARIAN} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_HUNGARIAN} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_HUNGARIAN} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_HUNGARIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_HUNGARIAN} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_ICELANDIC} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_ICELANDIC} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_ICELANDIC} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_ICELANDIC} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_ICELANDIC} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_INDONESIAN} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_INDONESIAN} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_INDONESIAN} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_INDONESIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_INDONESIAN} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_IRISH} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_IRISH} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_IRISH} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_IRISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_IRISH} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_ITALIAN} "Aggiungi regola al firewall di Windows
LangString inst_firewallinfo ${LANG_ITALIAN} "Aggiunta regola al firewall di Windows"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_ITALIAN} "qBittorrent è in esecuzione. Chiudi l'applicazione prima dell'installazione."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_ITALIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_ITALIAN} "Disinstallazione versione precedente."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_JAPANESE} "Windows ファイアウォールの
LangString inst_firewallinfo ${LANG_JAPANESE} "Windows ファイアウォールのルールを追加しています"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_JAPANESE} "qBittorrent が起動されています。インストールの前にアプリケーションを終了してください。"
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_JAPANESE} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_JAPANESE} "以前のバージョンをアンインストールしています。"
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_KOREAN} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_KOREAN} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_KOREAN} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_KOREAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_KOREAN} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_KURDISH} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_KURDISH} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_KURDISH} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_KURDISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_KURDISH} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_LATVIAN} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_LATVIAN} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_LATVIAN} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_LATVIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_LATVIAN} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_LITHUANIAN} "Sukurti Windows užkardos leidimą"
LangString inst_firewallinfo ${LANG_LITHUANIAN} "Pridedu Windows užkardos leidimą"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_LITHUANIAN} "qBittorrent yra paleistas. Prašau uždaryti programą prieš įdiegiant."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_LITHUANIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_LITHUANIAN} "Šalinu ankstesnę versiją."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_LUXEMBOURGISH} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_LUXEMBOURGISH} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_LUXEMBOURGISH} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_LUXEMBOURGISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_LUXEMBOURGISH} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_MACEDONIAN} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_MACEDONIAN} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_MACEDONIAN} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_MACEDONIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_MACEDONIAN} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_MALAY} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_MALAY} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_MALAY} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_MALAY} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_MALAY} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_MONGOLIAN} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_MONGOLIAN} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_MONGOLIAN} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_MONGOLIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_MONGOLIAN} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_NORWEGIAN} "Legg til Windows-brannmursregel"
LangString inst_firewallinfo ${LANG_NORWEGIAN} "Legger til Windows-brannmursregel"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_NORWEGIAN} "qBittorrent kjører. Vennligst steng applikasjonen før installering."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_NORWEGIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_NORWEGIAN} "Avinstallerer forrige versjon."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_NORWEGIANNYNORSK} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_NORWEGIANNYNORSK} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_NORWEGIANNYNORSK} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_NORWEGIANNYNORSK} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_NORWEGIANNYNORSK} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_POLISH} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_POLISH} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_POLISH} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_POLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_POLISH} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_PORTUGUESE} "Adicionar regra à firewall do Wind
LangString inst_firewallinfo ${LANG_PORTUGUESE} "Adicionando regra à firewall do Windows"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_PORTUGUESE} "O qBittorrent está a ser executado. Feche a aplicação antes de instalar esta versão."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_PORTUGUESE} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_PORTUGUESE} "A desinstalar versão anterior."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_PORTUGUESEBR} "Adicionar regra no firewall do Wi
LangString inst_firewallinfo ${LANG_PORTUGUESEBR} "Adicionando regra no firewall do Windows"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_PORTUGUESEBR} "qBittorrent está rodando. Por favor feche a aplicação antes de instalar."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_PORTUGUESEBR} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_PORTUGUESEBR} "Desinstalando versão anterior."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_ROMANIAN} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_ROMANIAN} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_ROMANIAN} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_ROMANIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_ROMANIAN} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_RUSSIAN} "Добавить в список ис
LangString inst_firewallinfo ${LANG_RUSSIAN} "Добавление в список исключений брандмауера"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_RUSSIAN} "qBittorrent запущен. Пожалуйста, закройте qBittorrent и перезапустите программу установки."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_RUSSIAN} "Обнаружена предыдущая установка. Она будет деинсталлирована без удаления пользовательских настроек."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_RUSSIAN} "Деинсталлируем старую версию."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_SERBIAN} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_SERBIAN} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_SERBIAN} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_SERBIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_SERBIAN} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_SERBIANLATIN} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_SERBIANLATIN} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_SERBIANLATIN} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_SERBIANLATIN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_SERBIANLATIN} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_SIMPCHINESE} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_SIMPCHINESE} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_SIMPCHINESE} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_SIMPCHINESE} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_SIMPCHINESE} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_SLOVAK} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_SLOVAK} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_SLOVAK} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_SLOVAK} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_SLOVAK} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_SLOVENIAN} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_SLOVENIAN} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_SLOVENIAN} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_SLOVENIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_SLOVENIAN} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_SPANISH} "Añadir regla al Firewall de Windows"
LangString inst_firewallinfo ${LANG_SPANISH} "Añadiendo regla al Firewall de Windows"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_SPANISH} "qBittorrent se está ejecutando. Ciérrelo antes de continuar."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_SPANISH} "Se detectó una instalación anterior. Será desinstalada sin eliminar la configuración del usuario."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_SPANISH} "Desinstalando la versión anterior."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_SPANISHINTERNATIONAL} "Añadir regla al Firewall
LangString inst_firewallinfo ${LANG_SPANISHINTERNATIONAL} "Añadiendo regla al Firewall de Windows"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_SPANISHINTERNATIONAL} "qBittorrent se está ejecutando. Ciérrelo antes de continuar."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_SPANISHINTERNATIONAL} "Se detectó una instalación anterior. Será desinstalada sin eliminar la configuración del usuario."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_SPANISHINTERNATIONAL} "Desinstalando la versión anterior."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_SWEDISH} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_SWEDISH} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_SWEDISH} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_SWEDISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_SWEDISH} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_THAI} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_THAI} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_THAI} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_THAI} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_THAI} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_TRADCHINESE} "建立 Windows 防火牆規則"
LangString inst_firewallinfo ${LANG_TRADCHINESE} "正在建立 Windows 防火牆規則"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_TRADCHINESE} "qBittorrent 正在執行中,請先關閉後再進行安裝。"
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_TRADCHINESE} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_TRADCHINESE} "正在移除先前版本"
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_TURKISH} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_TURKISH} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_TURKISH} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_TURKISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_TURKISH} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_UKRAINIAN} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_UKRAINIAN} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_UKRAINIAN} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_UKRAINIAN} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_UKRAINIAN} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_UZBEK} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_UZBEK} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_UZBEK} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_UZBEK} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_UZBEK} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -16,6 +16,8 @@ LangString inst_firewall ${LANG_WELSH} "Add Windows Firewall rule"
LangString inst_firewallinfo ${LANG_WELSH} "Adding Windows Firewall rule"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
LangString inst_warning ${LANG_WELSH} "qBittorrent is running. Please close the application before installing."
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
LangString inst_uninstall_question ${LANG_WELSH} "A previous installation was detected. It will be uninstalled without deleting user settings."
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_WELSH} "Uninstalling previous version."
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."

View File

@@ -4,13 +4,12 @@
FindFirst $0 $1 "$INSTDIR\uninst.exe"
FindClose $0
StrCmp $1 "" done
;Run the uninstaller of the previous install.
DetailPrint $(inst_unist)
DetailPrint $(inst_unist)
ExecWait '"$INSTDIR\uninst.exe" /S _?=$INSTDIR'
Delete "$INSTDIR\uninst.exe"
done:
SectionEnd
@@ -177,7 +176,18 @@ Function .onInit
!insertmacro Init "installer"
!insertmacro MUI_LANGDLL_DISPLAY
;Search if qBittorrent is already installed.
FindFirst $0 $1 "$INSTDIR\uninst.exe"
FindClose $0
StrCmp $1 "" done
;Inform the user
MessageBox MB_OKCANCEL|MB_ICONINFORMATION $(inst_uninstall_question) /SD IDOK IDOK done
Quit
done:
FunctionEnd
Function check_instance

View File

@@ -19,7 +19,7 @@ XPStyle on
!define CSIDL_APPDATA '0x1A' ;Application Data path
!define CSIDL_LOCALAPPDATA '0x1C' ;Local Application Data path
!define PROG_VERSION "3.3.1"
!define PROG_VERSION "3.3.2"
!define MUI_FINISHPAGE_RUN
!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun
!define MUI_FINISHPAGE_RUN_TEXT $(launch_qbt)
@@ -33,7 +33,7 @@ OutFile "qbittorrent_${PROG_VERSION}_setup.exe"
;Installer Version Information
VIAddVersionKey "ProductName" "qBittorrent"
VIAddVersionKey "CompanyName" "The qBittorrent project"
VIAddVersionKey "LegalCopyright" "Copyright ©2006-2015 The qBittorrent project"
VIAddVersionKey "LegalCopyright" "Copyright ©2006-2016 The qBittorrent project"
VIAddVersionKey "FileDescription" "qBittorrent - A Bittorrent Client"
VIAddVersionKey "FileVersion" "${PROG_VERSION}"

View File

@@ -5,7 +5,12 @@ isEmpty(QMAKE_LRELEASE) {
win32|os2:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\\lrelease.exe
else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease
unix {
equals(QT_MAJOR_VERSION, 4) {
!exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease-qt4 }
}
equals(QT_MAJOR_VERSION, 5) {
!exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease-qt5 }
}
} else {
!exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease }
}

View File

@@ -37,7 +37,7 @@
#ifndef DISABLE_GUI
#include "gui/guiiconprovider.h"
#ifdef Q_OS_WIN
#include <Windows.h>
#include <windows.h>
#include <QSharedMemory>
#include <QSessionManager>
#endif // Q_OS_WIN
@@ -462,10 +462,10 @@ void Application::cleanup()
#ifndef DISABLE_COUNTRIES_RESOLUTION
Net::GeoIPManager::freeInstance();
#endif
Net::DownloadManager::freeInstance();
Preferences::freeInstance();
Logger::freeInstance();
IconProvider::freeInstance();
Net::DownloadManager::freeInstance();
#ifndef DISABLE_GUI
#ifdef Q_OS_WIN
typedef BOOL (WINAPI *PSHUTDOWNBRDESTROY)(HWND);

View File

@@ -45,6 +45,7 @@
#include "base/utils/misc.h"
#include "base/utils/string.h"
#include "base/qinisettings.h"
#include "base/preferences.h"
bool userAcceptsUpgrade()
{
@@ -114,18 +115,22 @@ bool upgradeResumeFile(const QString &filepath, const QVariantHash &oldTorrent,
bool upgrade(bool ask = true)
{
// Move RSS cookies to common storage
Preferences::instance()->moveRSSCookies();
QIniSettings *oldResumeSettings = new QIniSettings("qBittorrent", "qBittorrent-resume");
QString oldResumeFilename = oldResumeSettings->fileName();
QVariantHash oldResumeData = oldResumeSettings->value("torrents").toHash();
delete oldResumeSettings;
if (oldResumeData.isEmpty())
bool oldResumeWasEmpty = oldResumeData.isEmpty();
if (oldResumeWasEmpty)
Utils::Fs::forceRemove(oldResumeFilename);
QString backupFolderPath = Utils::Fs::expandPathAbs(Utils::Fs::QDesktopServicesDataLocation() + "BT_backup");
QDir backupFolderDir(backupFolderPath);
QStringList backupFiles = backupFolderDir.entryList(QStringList() << QLatin1String("*.fastresume"), QDir::Files, QDir::Unsorted);
if (backupFiles.isEmpty() && oldResumeData.isEmpty()) return true;
if (backupFiles.isEmpty() && oldResumeWasEmpty) return true;
if (ask && !userAcceptsUpgrade()) return false;
int maxPrio = 0;
@@ -168,8 +173,17 @@ bool upgrade(bool ask = true)
}
}
if (!oldResumeData.isEmpty())
QFile(oldResumeFilename).rename(oldResumeFilename + ".bak");
if (!oldResumeWasEmpty) {
int counter = 0;
QString backupResumeFilename = oldResumeFilename + ".bak";
while (QFile::exists(backupResumeFilename)) {
++counter;
backupResumeFilename = oldResumeFilename + ".bak" + QString::number(counter);
}
QFile::rename(oldResumeFilename, backupResumeFilename);
}
return true;
}

View File

@@ -36,13 +36,22 @@ HEADERS += \
$$PWD/bittorrent/private/bandwidthscheduler.h \
$$PWD/bittorrent/private/filterparserthread.h \
$$PWD/bittorrent/private/statistics.h \
$$PWD/rss/rssmanager.h \
$$PWD/rss/rssfeed.h \
$$PWD/rss/rssfolder.h \
$$PWD/rss/rssfile.h \
$$PWD/rss/rssarticle.h \
$$PWD/rss/rssdownloadrule.h \
$$PWD/rss/rssdownloadrulelist.h \
$$PWD/rss/private/rssparser.h \
$$PWD/utils/fs.h \
$$PWD/utils/gzip.h \
$$PWD/utils/misc.h \
$$PWD/utils/string.h \
$$PWD/unicodestrings.h \
$$PWD/torrentfilter.h \
$$PWD/scanfoldersmodel.h
$$PWD/scanfoldersmodel.h \
$$PWD/searchengine.h
SOURCES += \
$$PWD/tristatebool.cpp \
@@ -78,9 +87,18 @@ SOURCES += \
$$PWD/bittorrent/private/bandwidthscheduler.cpp \
$$PWD/bittorrent/private/filterparserthread.cpp \
$$PWD/bittorrent/private/statistics.cpp \
$$PWD/rss/rssmanager.cpp \
$$PWD/rss/rssfeed.cpp \
$$PWD/rss/rssfolder.cpp \
$$PWD/rss/rssarticle.cpp \
$$PWD/rss/rssdownloadrule.cpp \
$$PWD/rss/rssdownloadrulelist.cpp \
$$PWD/rss/rssfile.cpp \
$$PWD/rss/private/rssparser.cpp \
$$PWD/utils/fs.cpp \
$$PWD/utils/gzip.cpp \
$$PWD/utils/misc.cpp \
$$PWD/utils/string.cpp \
$$PWD/torrentfilter.cpp \
$$PWD/scanfoldersmodel.cpp
$$PWD/scanfoldersmodel.cpp \
$$PWD/searchengine.cpp

View File

@@ -408,3 +408,8 @@ QString PeerInfo::flagsDescription() const
{
return m_flagsDescription;
}
int PeerInfo::downloadingPieceIndex() const
{
return m_nativeInfo.downloading_piece_index;
}

View File

@@ -100,6 +100,7 @@ namespace BitTorrent
#ifndef DISABLE_COUNTRIES_RESOLUTION
QString country() const;
#endif
int downloadingPieceIndex() const;
private:
void calcRelevance(const TorrentHandle *torrent);

View File

@@ -62,10 +62,6 @@ using namespace BitTorrent;
#include <libtorrent/extensions/smart_ban.hpp>
//#include <libtorrent/extensions/metadata_transfer.hpp>
#ifndef DISABLE_COUNTRIES_RESOLUTION
#include "base/net/geoipmanager.h"
#endif
#include "base/utils/misc.h"
#include "base/utils/fs.h"
#include "base/utils/string.h"
@@ -576,7 +572,7 @@ void Session::configure()
m_nativeSession->set_pe_settings(encryptionSettings);
// * Add trackers
m_additionalTrackers.empty();
m_additionalTrackers.clear();
if (pref->isAddTrackersEnabled()) {
foreach (QString tracker, pref->getTrackersList().split("\n")) {
tracker = tracker.trimmed();
@@ -968,6 +964,10 @@ bool Session::addTorrent(QString source, const AddTorrentParams &params)
qDebug("Converting bc link to magnet link");
source = Utils::Misc::bcLinkToMagnet(source);
}
else if (((source.size() == 40) && !source.contains(QRegExp("[^0-9A-Fa-f]")))
|| ((source.size() == 32) && !source.contains(QRegExp("[^2-7A-Za-z]")))) {
source = "magnet:?xt=urn:btih:" + source;
}
if (Utils::Misc::isUrl(source)) {
Logger::instance()->addMessage(tr("Downloading '%1', please wait...", "e.g: Downloading 'xxx.torrent', please wait...").arg(source));
@@ -2336,7 +2336,7 @@ bool loadTorrentResumeData(const QByteArray &data, AddTorrentData &out, MagnetUr
libt::lazy_entry fast;
libt::error_code ec;
libt::lazy_bdecode(data.constData(), data.constData() + data.size(), fast, ec);
if ((fast.type() != libt::lazy_entry::dict_t) && !ec) return false;
if (ec || (fast.type() != libt::lazy_entry::dict_t)) return false;
out.savePath = Utils::Fs::fromNativePath(Utils::String::fromStdString(fast.dict_find_string_value("qBt-savePath")));
out.ratioLimit = Utils::String::fromStdString(fast.dict_find_string_value("qBt-ratioLimit")).toDouble();

View File

@@ -60,6 +60,9 @@ bool fileFilter(const std::string &f)
TorrentCreatorThread::TorrentCreatorThread(QObject *parent)
: QThread(parent)
, m_private(false)
, m_pieceSize(0)
, m_abort(false)
{
}

View File

@@ -43,7 +43,7 @@
#include <boost/bind.hpp>
#ifdef Q_OS_WIN
#include <Windows.h>
#include <windows.h>
#endif
#include "base/logger.h"
@@ -1364,10 +1364,13 @@ void TorrentHandle::handleTorrentCheckedAlert(libtorrent::torrent_checked_alert
qDebug("%s have just finished checking", qPrintable(hash()));
updateStatus();
adjustActualSavePath();
if (progress() < 1.0 && wantedSize() > 0)
if ((progress() < 1.0) && (wantedSize() > 0))
m_hasSeedStatus = false;
else if (progress() == 1.0)
m_hasSeedStatus = true;
adjustActualSavePath();
if (m_pauseAfterRecheck) {
m_pauseAfterRecheck = false;
@@ -1694,7 +1697,7 @@ bool TorrentHandle::isMoveInProgress() const
bool TorrentHandle::useTempPath() const
{
return !m_tempPathDisabled && m_session->isTempPathEnabled() && !isSeed();
return !m_tempPathDisabled && m_session->isTempPathEnabled() && !(isSeed() || m_hasSeedStatus);
}
void TorrentHandle::updateStatus()

View File

@@ -211,6 +211,20 @@ QByteArray TorrentInfo::metadata() const
return QByteArray(m_nativeInfo->metadata().get(), m_nativeInfo->metadata_size());
}
QStringList TorrentInfo::filesForPiece(int pieceIndex) const
{
if (pieceIndex < 0)
return QStringList();
std::vector<libtorrent::file_slice> files(
nativeInfo()->map_block(pieceIndex, 0, nativeInfo()->piece_length()));
QStringList res;
for (const libtorrent::file_slice& s: files) {
res.append(filePath(s.file_index));
}
return res;
}
void TorrentInfo::renameFile(uint index, const QString &newPath)
{
if (!isValid()) return;

View File

@@ -75,6 +75,7 @@ namespace BitTorrent
QList<TrackerEntry> trackers() const;
QList<QUrl> urlSeeds() const;
QByteArray metadata() const;
QStringList filesForPiece(int pieceIndex) const;
void renameFile(uint index, const QString &newPath);
boost::intrusive_ptr<libtorrent::torrent_info> nativeInfo() const;

View File

@@ -319,7 +319,7 @@ bool RequestParser::parseFormData(const QByteArray& data)
ufile.type = disposition["content-type"];
ufile.data = data.mid(header_end + EOH.length());
m_request.files[disposition["name"]] = ufile;
m_request.files.append(ufile);
}
else {
m_request.posts[disposition["name"]] = QString::fromUtf8(data.mid(header_end + EOH.length()));

View File

@@ -32,6 +32,7 @@
#include <QString>
#include <QMap>
#include <QHostAddress>
#include <QVector>
typedef QMap<QString, QString> QStringMap;
@@ -70,7 +71,7 @@ namespace Http
QStringMap headers;
QStringMap gets;
QStringMap posts;
QMap<QString, UploadedFile> files;
QVector<UploadedFile> files;
};
struct ResponseStatus

View File

@@ -2,31 +2,6 @@
#include <QDateTime>
namespace Log
{
Msg::Msg() {}
Msg::Msg(int id, MsgType type, const QString &message)
: id(id)
, timestamp(QDateTime::currentMSecsSinceEpoch())
, type(type)
, message(message)
{
}
Peer::Peer() {}
Peer::Peer(int id, const QString &ip, bool blocked, const QString &reason)
: id(id)
, timestamp(QDateTime::currentMSecsSinceEpoch())
, ip(ip)
, blocked(blocked)
, reason(reason)
{
}
}
Logger* Logger::m_instance = 0;
Logger::Logger()
@@ -61,7 +36,7 @@ void Logger::addMessage(const QString &message, const Log::MsgType &type)
{
QWriteLocker locker(&lock);
Log::Msg temp(msgCounter++, type, message);
Log::Msg temp = { msgCounter++, QDateTime::currentMSecsSinceEpoch(), type, message };
m_messages.push_back(temp);
if (m_messages.size() >= MAX_LOG_MESSAGES)
@@ -74,7 +49,7 @@ void Logger::addPeer(const QString &ip, bool blocked, const QString &reason)
{
QWriteLocker locker(&lock);
Log::Peer temp(peerCounter++, ip, blocked, reason);
Log::Peer temp = { peerCounter++, QDateTime::currentMSecsSinceEpoch(), ip, blocked, reason };
m_peers.push_back(temp);
if (m_peers.size() >= MAX_LOG_MESSAGES)

View File

@@ -20,8 +20,6 @@ namespace Log
struct Msg
{
Msg();
Msg(int id, MsgType type, const QString &message);
int id;
qint64 timestamp;
MsgType type;
@@ -30,8 +28,6 @@ namespace Log
struct Peer
{
Peer(int id, const QString &ip, bool blocked, const QString &reason);
Peer();
int id;
qint64 timestamp;
QString ip;

View File

@@ -28,7 +28,6 @@
* Contact : chris@qbittorrent.org
*/
#include <QNetworkAccessManager>
#include <QDebug>
#include <QRegExp>
#include <QStringList>
@@ -37,6 +36,8 @@
#endif
#include "base/logger.h"
#include "base/net/downloadmanager.h"
#include "base/net/downloadhandler.h"
#include "dnsupdater.h"
using namespace Net;
@@ -76,65 +77,62 @@ DNSUpdater::~DNSUpdater()
void DNSUpdater::checkPublicIP()
{
Q_ASSERT(m_state == OK);
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply *)), SLOT(ipRequestFinished(QNetworkReply *)));
DownloadHandler *handler = DownloadManager::instance()->downloadUrl(
"http://checkip.dyndns.org", false, 0, false,
QString("qBittorrent/%1").arg(VERSION));
connect(handler, SIGNAL(downloadFinished(QString, QByteArray)), SLOT(ipRequestFinished(QString, QByteArray)));
connect(handler, SIGNAL(downloadFailed(QString, QString)), SLOT(ipRequestFailed(QString, QString)));
m_lastIPCheckTime = QDateTime::currentDateTime();
QNetworkRequest request;
request.setUrl(QUrl("http://checkip.dyndns.org"));
request.setRawHeader("User-Agent", "qBittorrent/" VERSION);
manager->get(request);
}
void DNSUpdater::ipRequestFinished(QNetworkReply *reply)
void DNSUpdater::ipRequestFinished(const QString &url, const QByteArray &data)
{
qDebug() << Q_FUNC_INFO;
if (reply->error()) {
// Error
qWarning() << Q_FUNC_INFO << "Error:" << reply->errorString();
}
else {
// Parse response
QRegExp ipregex("Current IP Address:\\s+([^<]+)</body>");
QString ret = reply->readAll();
if (ipregex.indexIn(ret) >= 0) {
QString ip_str = ipregex.cap(1);
qDebug() << Q_FUNC_INFO << "Regular expression captured the following IP:" << ip_str;
QHostAddress new_ip(ip_str);
if (!new_ip.isNull()) {
if (m_lastIP != new_ip) {
qDebug() << Q_FUNC_INFO << "The IP address changed, report the change to DynDNS...";
qDebug() << m_lastIP.toString() << "->" << new_ip.toString();
m_lastIP = new_ip;
updateDNSService();
}
}
else {
qWarning() << Q_FUNC_INFO << "Failed to construct a QHostAddress from the IP string";
Q_UNUSED(url);
// Parse response
QRegExp ipregex("Current IP Address:\\s+([^<]+)</body>");
if (ipregex.indexIn(data) >= 0) {
QString ipStr = ipregex.cap(1);
qDebug() << Q_FUNC_INFO << "Regular expression captured the following IP:" << ipStr;
QHostAddress newIp(ipStr);
if (!newIp.isNull()) {
if (m_lastIP != newIp) {
qDebug() << Q_FUNC_INFO << "The IP address changed, report the change to DynDNS...";
qDebug() << m_lastIP.toString() << "->" << newIp.toString();
m_lastIP = newIp;
updateDNSService();
}
}
else {
qWarning() << Q_FUNC_INFO << "Regular expression failed to capture the IP address";
qWarning() << Q_FUNC_INFO << "Failed to construct a QHostAddress from the IP string";
}
}
// Clean up
reply->deleteLater();
sender()->deleteLater();
else {
qWarning() << Q_FUNC_INFO << "Regular expression failed to capture the IP address";
}
}
void DNSUpdater::ipRequestFailed(const QString &url, const QString &error)
{
Q_UNUSED(url);
qWarning() << "IP request failed:" << error;
}
void DNSUpdater::updateDNSService()
{
qDebug() << Q_FUNC_INFO;
// Prepare request
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply *)), SLOT(ipUpdateFinished(QNetworkReply *)));
m_lastIPCheckTime = QDateTime::currentDateTime();
QNetworkRequest request;
request.setUrl(getUpdateUrl());
request.setRawHeader("User-Agent", "qBittorrent/" VERSION);
manager->get(request);
DownloadHandler *handler = DownloadManager::instance()->downloadUrl(
getUpdateUrl(), false, 0, false,
QString("qBittorrent/%1").arg(VERSION));
connect(handler, SIGNAL(downloadFinished(QString, QByteArray)), SLOT(ipUpdateFinished(QString, QByteArray)));
connect(handler, SIGNAL(downloadFailed(QString, QString)), SLOT(ipUpdateFailed(QString, QString)));
}
QUrl DNSUpdater::getUpdateUrl() const
QString DNSUpdater::getUpdateUrl() const
{
QUrl url;
#ifdef QT_NO_OPENSSL
@@ -172,22 +170,20 @@ QUrl DNSUpdater::getUpdateUrl() const
Q_ASSERT(url.isValid());
qDebug() << Q_FUNC_INFO << url.toString();
return url;
return url.toString();
}
void DNSUpdater::ipUpdateFinished(QNetworkReply *reply)
void DNSUpdater::ipUpdateFinished(const QString &url, const QByteArray &data)
{
if (reply->error()) {
// Error
qWarning() << Q_FUNC_INFO << "Error:" << reply->errorString();
}
else {
// Parse reply
processIPUpdateReply(reply->readAll());
}
// Clean up
reply->deleteLater();
sender()->deleteLater();
Q_UNUSED(url);
// Parse reply
processIPUpdateReply(data);
}
void DNSUpdater::ipUpdateFailed(const QString &url, const QString &error)
{
Q_UNUSED(url);
qWarning() << "IP update failed:" << error;
}
void DNSUpdater::processIPUpdateReply(const QString &reply)
@@ -196,16 +192,19 @@ void DNSUpdater::processIPUpdateReply(const QString &reply)
qDebug() << Q_FUNC_INFO << reply;
QString code = reply.split(" ").first();
qDebug() << Q_FUNC_INFO << "Code:" << code;
if (code == "good" || code == "nochg") {
if ((code == "good") || (code == "nochg")) {
logger->addMessage(tr("Your dynamic DNS was successfully updated."), Log::INFO);
return;
}
if ((code == "911") || (code == "dnserr")) {
logger->addMessage(tr("Dynamic DNS error: The service is temporarily unavailable, it will be retried in 30 minutes."), Log::CRITICAL);
m_lastIP.clear();
// It will retry in 30 minutes because the timer was not stopped
return;
}
// Everything bellow is an error, stop updating until the user updates something
m_ipCheckTimer.stop();
m_lastIP.clear();
@@ -214,23 +213,27 @@ void DNSUpdater::processIPUpdateReply(const QString &reply)
m_state = INVALID_CREDS;
return;
}
if (code == "badauth") {
logger->addMessage(tr("Dynamic DNS error: Invalid username/password."), Log::CRITICAL);
m_state = INVALID_CREDS;
return;
}
if (code == "badagent") {
logger->addMessage(tr("Dynamic DNS error: qBittorrent was blacklisted by the service, please report a bug at http://bugs.qbittorrent.org."),
Log::CRITICAL);
m_state = FATAL;
return;
}
if (code == "!donator") {
logger->addMessage(tr("Dynamic DNS error: %1 was returned by the service, please report a bug at http://bugs.qbittorrent.org.").arg("!donator"),
Log::CRITICAL);
m_state = FATAL;
return;
}
if (code == "abuse") {
logger->addMessage(tr("Dynamic DNS error: Your username was blocked due to abuse."), Log::CRITICAL);
m_state = FATAL;

View File

@@ -33,15 +33,15 @@
#include <QObject>
#include <QHostAddress>
#include <QNetworkReply>
#include <QDateTime>
#include <QTimer>
#include "base/preferences.h"
namespace Net
{
{
// Based on http://www.dyndns.com/developers/specs/
class DNSUpdater : public QObject
class DNSUpdater: public QObject
{
Q_OBJECT
@@ -56,15 +56,25 @@ namespace Net
private slots:
void checkPublicIP();
void ipRequestFinished(QNetworkReply *reply);
void ipRequestFinished(const QString &url, const QByteArray &data);
void ipRequestFailed(const QString &url, const QString &error);
void updateDNSService();
void ipUpdateFinished(QNetworkReply *reply);
void ipUpdateFinished(const QString &url, const QByteArray &data);
void ipUpdateFailed(const QString &url, const QString &error);
private:
QUrl getUpdateUrl() const;
enum State
{
OK,
INVALID_CREDS,
FATAL
};
static const int IP_CHECK_INTERVAL_MS = 1800000; // 30 min
QString getUpdateUrl() const;
void processIPUpdateReply(const QString &reply);
private:
QHostAddress m_lastIP;
QDateTime m_lastIPCheckTime;
QTimer m_ipCheckTimer;
@@ -74,16 +84,6 @@ namespace Net
QString m_domain;
QString m_username;
QString m_password;
private:
static const int IP_CHECK_INTERVAL_MS = 1800000; // 30 min
enum State
{
OK,
INVALID_CREDS,
FATAL
};
};
}

View File

@@ -27,11 +27,13 @@
* exception statement from your version.
*/
#include <QDateTime>
#include <QNetworkRequest>
#include <QNetworkProxy>
#include <QNetworkCookieJar>
#include <QNetworkReply>
#include <QNetworkCookie>
#include <QNetworkCookieJar>
#include <QSslError>
#include <QUrl>
#include <QDebug>
@@ -40,6 +42,85 @@
#include "downloadhandler.h"
#include "downloadmanager.h"
// Spoof Firefox 38 user agent to avoid web server banning
const char DEFAULT_USER_AGENT[] = "Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0";
namespace
{
class NetworkCookieJar: public QNetworkCookieJar
{
public:
explicit NetworkCookieJar(QObject *parent = 0)
: QNetworkCookieJar(parent)
{
QDateTime now = QDateTime::currentDateTime();
QList<QNetworkCookie> cookies = Preferences::instance()->getNetworkCookies();
foreach (const QNetworkCookie &cookie, Preferences::instance()->getNetworkCookies()) {
if (cookie.isSessionCookie() || (cookie.expirationDate() <= now))
cookies.removeAll(cookie);
}
setAllCookies(cookies);
}
~NetworkCookieJar()
{
QDateTime now = QDateTime::currentDateTime();
QList<QNetworkCookie> cookies = allCookies();
foreach (const QNetworkCookie &cookie, allCookies()) {
if (cookie.isSessionCookie() || (cookie.expirationDate() <= now))
cookies.removeAll(cookie);
}
Preferences::instance()->setNetworkCookies(cookies);
}
#ifndef QBT_USES_QT5
virtual bool deleteCookie(const QNetworkCookie &cookie)
{
auto myCookies = allCookies();
QList<QNetworkCookie>::Iterator it;
for (it = myCookies.begin(); it != myCookies.end(); ++it) {
if ((it->name() == cookie.name())
&& (it->domain() == cookie.domain())
&& (it->path() == cookie.path())) {
myCookies.erase(it);
setAllCookies(myCookies);
return true;
}
}
return false;
}
#endif
QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const override
{
QDateTime now = QDateTime::currentDateTime();
QList<QNetworkCookie> cookies = QNetworkCookieJar::cookiesForUrl(url);
foreach (const QNetworkCookie &cookie, QNetworkCookieJar::cookiesForUrl(url)) {
if (!cookie.isSessionCookie() && (cookie.expirationDate() <= now))
cookies.removeAll(cookie);
}
return cookies;
}
bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url) override
{
QDateTime now = QDateTime::currentDateTime();
QList<QNetworkCookie> cookies = cookieList;
foreach (const QNetworkCookie &cookie, cookieList) {
if (!cookie.isSessionCookie() && (cookie.expirationDate() <= now))
cookies.removeAll(cookie);
}
return QNetworkCookieJar::setCookiesFromUrl(cookies, url);
}
};
}
using namespace Net;
DownloadManager *DownloadManager::m_instance = 0;
@@ -50,10 +131,7 @@ DownloadManager::DownloadManager(QObject *parent)
#ifndef QT_NO_OPENSSL
connect(&m_networkManager, SIGNAL(sslErrors(QNetworkReply *, QList<QSslError>)), this, SLOT(ignoreSslErrors(QNetworkReply *, QList<QSslError>)));
#endif
}
DownloadManager::~DownloadManager()
{
m_networkManager.setCookieJar(new NetworkCookieJar(this));
}
void DownloadManager::initInstance()
@@ -75,7 +153,7 @@ DownloadManager *DownloadManager::instance()
return m_instance;
}
DownloadHandler *DownloadManager::downloadUrl(const QString &url, bool saveToFile, qint64 limit, bool handleRedirectToMagnet)
DownloadHandler *DownloadManager::downloadUrl(const QString &url, bool saveToFile, qint64 limit, bool handleRedirectToMagnet, const QString &userAgent)
{
// Update proxy settings
applyProxySettings();
@@ -85,29 +163,36 @@ DownloadHandler *DownloadManager::downloadUrl(const QString &url, bool saveToFil
const QUrl qurl = QUrl::fromEncoded(url.toUtf8());
QNetworkRequest request(qurl);
// Spoof Firefox 38 user agent to avoid web server banning
request.setRawHeader("User-Agent", "Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 Firefox/38.0");
if (userAgent.isEmpty())
request.setRawHeader("User-Agent", DEFAULT_USER_AGENT);
else
request.setRawHeader("User-Agent", userAgent.toUtf8());
// Spoof HTTP Referer to allow adding torrent link from Torcache/KickAssTorrents
request.setRawHeader("Referer", request.url().toEncoded().data());
qDebug("Downloading %s...", request.url().toEncoded().data());
qDebug() << "Cookies:" << m_networkManager.cookieJar()->cookiesForUrl(request.url());
// accept gzip
request.setRawHeader("Accept-Encoding", "gzip");
return new DownloadHandler(m_networkManager.get(request), this, saveToFile, limit, handleRedirectToMagnet);
}
QList<QNetworkCookie> DownloadManager::cookiesForUrl(const QString &url) const
QList<QNetworkCookie> DownloadManager::cookiesForUrl(const QUrl &url) const
{
return m_networkManager.cookieJar()->cookiesForUrl(url);
}
bool DownloadManager::setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url)
{
qDebug("Setting %d cookies for url: %s", cookieList.size(), qPrintable(url.toString()));
return m_networkManager.cookieJar()->setCookiesFromUrl(cookieList, url);
}
bool DownloadManager::deleteCookie(const QNetworkCookie &cookie)
{
return static_cast<NetworkCookieJar *>(m_networkManager.cookieJar())->deleteCookie(cookie);
}
void DownloadManager::applyProxySettings()
{
QNetworkProxy proxy;

View File

@@ -33,12 +33,10 @@
#include <QObject>
#include <QNetworkAccessManager>
QT_BEGIN_NAMESPACE
class QNetworkReply;
class QNetworkCookie;
class QSslError;
class QUrl;
QT_END_NAMESPACE
namespace Net
{
@@ -53,9 +51,10 @@ namespace Net
static void freeInstance();
static DownloadManager *instance();
DownloadHandler *downloadUrl(const QString &url, bool saveToFile = false, qint64 limit = 0, bool handleRedirectToMagnet = false);
QList<QNetworkCookie> cookiesForUrl(const QString &url) const;
DownloadHandler *downloadUrl(const QString &url, bool saveToFile = false, qint64 limit = 0, bool handleRedirectToMagnet = false, const QString &userAgent = "");
QList<QNetworkCookie> cookiesForUrl(const QUrl &url) const;
bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl &url);
bool deleteCookie(const QNetworkCookie &cookie);
private slots:
#ifndef QT_NO_OPENSSL
@@ -63,8 +62,7 @@ namespace Net
#endif
private:
DownloadManager(QObject *parent = 0);
~DownloadManager();
explicit DownloadManager(QObject *parent = 0);
void applyProxySettings();

View File

@@ -131,16 +131,15 @@ QString GeoIPManager::lookup(const QHostAddress &hostAddr) const
return QString();
}
// http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm
QString GeoIPManager::CountryName(const QString &countryISOCode)
{
static QHash<QString, QString> countries;
static bool initialized = false;
// ISO 3166-1 alpha-2 codes
// http://www.iso.org/iso/home/standards/country_codes/country_names_and_code_elements_txt-temp.htm
if (!initialized) {
countries[QString()] = tr("N/A");
countries["AP"] = tr("Asia/Pacific Region");
countries["EU"] = tr("Europe");
// Officially assigned
countries["AD"] = tr("Andorra");
countries["AE"] = tr("United Arab Emirates");
countries["AF"] = tr("Afghanistan");
@@ -148,7 +147,6 @@ QString GeoIPManager::CountryName(const QString &countryISOCode)
countries["AI"] = tr("Anguilla");
countries["AL"] = tr("Albania");
countries["AM"] = tr("Armenia");
countries["AN"] = tr("Netherlands Antilles");
countries["AO"] = tr("Angola");
countries["AQ"] = tr("Antarctica");
countries["AR"] = tr("Argentina");
@@ -156,6 +154,7 @@ QString GeoIPManager::CountryName(const QString &countryISOCode)
countries["AT"] = tr("Austria");
countries["AU"] = tr("Australia");
countries["AW"] = tr("Aruba");
countries["AX"] = tr("Aland Islands");
countries["AZ"] = tr("Azerbaijan");
countries["BA"] = tr("Bosnia and Herzegovina");
countries["BB"] = tr("Barbados");
@@ -166,9 +165,11 @@ QString GeoIPManager::CountryName(const QString &countryISOCode)
countries["BH"] = tr("Bahrain");
countries["BI"] = tr("Burundi");
countries["BJ"] = tr("Benin");
countries["BL"] = tr("Saint Barthelemy");
countries["BM"] = tr("Bermuda");
countries["BN"] = tr("Brunei Darussalam");
countries["BO"] = tr("Bolivia");
countries["BO"] = tr("Bolivia, Plurinational State of");
countries["BQ"] = tr("Bonaire, Sint Eustatius and Saba");
countries["BR"] = tr("Brazil");
countries["BS"] = tr("Bahamas");
countries["BT"] = tr("Bhutan");
@@ -182,7 +183,7 @@ QString GeoIPManager::CountryName(const QString &countryISOCode)
countries["CF"] = tr("Central African Republic");
countries["CG"] = tr("Congo");
countries["CH"] = tr("Switzerland");
countries["CI"] = tr("Cote D'Ivoire");
countries["CI"] = tr("Cote d'Ivoire");
countries["CK"] = tr("Cook Islands");
countries["CL"] = tr("Chile");
countries["CM"] = tr("Cameroon");
@@ -191,6 +192,7 @@ QString GeoIPManager::CountryName(const QString &countryISOCode)
countries["CR"] = tr("Costa Rica");
countries["CU"] = tr("Cuba");
countries["CV"] = tr("Cape Verde");
countries["CW"] = tr("Curacao");
countries["CX"] = tr("Christmas Island");
countries["CY"] = tr("Cyprus");
countries["CZ"] = tr("Czech Republic");
@@ -213,12 +215,12 @@ QString GeoIPManager::CountryName(const QString &countryISOCode)
countries["FM"] = tr("Micronesia, Federated States of");
countries["FO"] = tr("Faroe Islands");
countries["FR"] = tr("France");
countries["FX"] = tr("France, Metropolitan");
countries["GA"] = tr("Gabon");
countries["GB"] = tr("United Kingdom");
countries["GD"] = tr("Grenada");
countries["GE"] = tr("Georgia");
countries["GF"] = tr("French Guiana");
countries["GG"] = tr("Guernsey");
countries["GH"] = tr("Ghana");
countries["GI"] = tr("Gibraltar");
countries["GL"] = tr("Greenland");
@@ -241,12 +243,14 @@ QString GeoIPManager::CountryName(const QString &countryISOCode)
countries["ID"] = tr("Indonesia");
countries["IE"] = tr("Ireland");
countries["IL"] = tr("Israel");
countries["IM"] = tr("Isle of Man");
countries["IN"] = tr("India");
countries["IO"] = tr("British Indian Ocean Territory");
countries["IQ"] = tr("Iraq");
countries["IR"] = tr("Iran, Islamic Republic of");
countries["IS"] = tr("Iceland");
countries["IT"] = tr("Italy");
countries["JE"] = tr("Jersey");
countries["JM"] = tr("Jamaica");
countries["JO"] = tr("Jordan");
countries["JP"] = tr("Japan");
@@ -271,17 +275,19 @@ QString GeoIPManager::CountryName(const QString &countryISOCode)
countries["LT"] = tr("Lithuania");
countries["LU"] = tr("Luxembourg");
countries["LV"] = tr("Latvia");
countries["LY"] = tr("Libyan Arab Jamahiriya");
countries["LY"] = tr("Libya");
countries["MA"] = tr("Morocco");
countries["MC"] = tr("Monaco");
countries["MD"] = tr("Moldova, Republic of");
countries["ME"] = tr("Montenegro");
countries["MF"] = tr("Saint Martin (French part)");
countries["MG"] = tr("Madagascar");
countries["MH"] = tr("Marshall Islands");
countries["MK"] = tr("Macedonia");
countries["MK"] = tr("Macedonia, The Former Yugoslav Republic of");
countries["ML"] = tr("Mali");
countries["MM"] = tr("Myanmar");
countries["MN"] = tr("Mongolia");
countries["MO"] = tr("Macau");
countries["MO"] = tr("Macao");
countries["MP"] = tr("Northern Mariana Islands");
countries["MQ"] = tr("Martinique");
countries["MR"] = tr("Mauritania");
@@ -314,15 +320,16 @@ QString GeoIPManager::CountryName(const QString &countryISOCode)
countries["PK"] = tr("Pakistan");
countries["PL"] = tr("Poland");
countries["PM"] = tr("Saint Pierre and Miquelon");
countries["PN"] = tr("Pitcairn Islands");
countries["PN"] = tr("Pitcairn");
countries["PR"] = tr("Puerto Rico");
countries["PS"] = tr("Palestinian Territory");
countries["PS"] = tr("Palestine, State of");
countries["PT"] = tr("Portugal");
countries["PW"] = tr("Palau");
countries["PY"] = tr("Paraguay");
countries["QA"] = tr("Qatar");
countries["RE"] = tr("Reunion");
countries["RO"] = tr("Romania");
countries["RS"] = tr("Serbia");
countries["RU"] = tr("Russian Federation");
countries["RW"] = tr("Rwanda");
countries["SA"] = tr("Saudi Arabia");
@@ -331,7 +338,7 @@ QString GeoIPManager::CountryName(const QString &countryISOCode)
countries["SD"] = tr("Sudan");
countries["SE"] = tr("Sweden");
countries["SG"] = tr("Singapore");
countries["SH"] = tr("Saint Helena");
countries["SH"] = tr("Saint Helena, Ascension and Tristan da Cunha");
countries["SI"] = tr("Slovenia");
countries["SJ"] = tr("Svalbard and Jan Mayen");
countries["SK"] = tr("Slovakia");
@@ -340,8 +347,10 @@ QString GeoIPManager::CountryName(const QString &countryISOCode)
countries["SN"] = tr("Senegal");
countries["SO"] = tr("Somalia");
countries["SR"] = tr("Suriname");
countries["SS"] = tr("South Sudan");
countries["ST"] = tr("Sao Tome and Principe");
countries["SV"] = tr("El Salvador");
countries["SX"] = tr("Sint Maarten (Dutch part)");
countries["SY"] = tr("Syrian Arab Republic");
countries["SZ"] = tr("Swaziland");
countries["TC"] = tr("Turks and Caicos Islands");
@@ -351,10 +360,10 @@ QString GeoIPManager::CountryName(const QString &countryISOCode)
countries["TH"] = tr("Thailand");
countries["TJ"] = tr("Tajikistan");
countries["TK"] = tr("Tokelau");
countries["TL"] = tr("Timor-Leste");
countries["TM"] = tr("Turkmenistan");
countries["TN"] = tr("Tunisia");
countries["TO"] = tr("Tonga");
countries["TL"] = tr("Timor-Leste");
countries["TR"] = tr("Turkey");
countries["TT"] = tr("Trinidad and Tobago");
countries["TV"] = tr("Tuvalu");
@@ -368,30 +377,20 @@ QString GeoIPManager::CountryName(const QString &countryISOCode)
countries["UZ"] = tr("Uzbekistan");
countries["VA"] = tr("Holy See (Vatican City State)");
countries["VC"] = tr("Saint Vincent and the Grenadines");
countries["VE"] = tr("Venezuela");
countries["VE"] = tr("Venezuela, Bolivarian Republic of");
countries["VG"] = tr("Virgin Islands, British");
countries["VI"] = tr("Virgin Islands, U.S.");
countries["VN"] = tr("Vietnam");
countries["VN"] = tr("Viet Nam");
countries["VU"] = tr("Vanuatu");
countries["WF"] = tr("Wallis and Futuna");
countries["WS"] = tr("Samoa");
countries["YE"] = tr("Yemen");
countries["YT"] = tr("Mayotte");
countries["RS"] = tr("Serbia");
countries["ZA"] = tr("South Africa");
countries["ZM"] = tr("Zambia");
countries["ME"] = tr("Montenegro");
countries["ZW"] = tr("Zimbabwe");
countries["A1"] = tr("Anonymous Proxy");
countries["A2"] = tr("Satellite Provider");
countries["O1"] = tr("Other");
countries["AX"] = tr("Aland Islands");
countries["GG"] = tr("Guernsey");
countries["IM"] = tr("Isle of Man");
countries["JE"] = tr("Jersey");
countries["BL"] = tr("Saint Barthelemy");
countries["MF"] = tr("Saint Martin");
countries[QString()] = tr("N/A");
initialized = true;
}

View File

@@ -96,6 +96,7 @@ Smtp::Smtp(QObject *parent)
: QObject(parent)
, m_state(Init)
, m_useSsl(false)
, m_authType(AuthPlain)
{
#ifndef QT_NO_OPENSSL
m_socket = new QSslSocket(this);

View File

@@ -47,10 +47,14 @@
#endif
#ifdef Q_OS_WIN
#include <ShlObj.h>
#include <shlobj.h>
#include <winreg.h>
#endif
#ifdef Q_OS_MAC
#include <CoreServices/CoreServices.h>
#endif
#include <cstdlib>
#include "base/utils/fs.h"
#include "base/utils/misc.h"
@@ -475,46 +479,15 @@ void Preferences::addTorrentsInPause(bool b)
setValue("Preferences/Downloads/StartInPause", b);
}
QStringList Preferences::getScanDirs() const
QVariantHash Preferences::getScanDirs() const
{
QStringList originalList = value("Preferences/Downloads/ScanDirs").toStringList();
if (originalList.isEmpty())
return originalList;
QStringList newList;
foreach (const QString& s, originalList)
newList << Utils::Fs::fromNativePath(s);
return newList;
return value("Preferences/Downloads/ScanDirsV2").toHash();
}
// This must be called somewhere with data from the model
void Preferences::setScanDirs(const QStringList &dirs)
void Preferences::setScanDirs(const QVariantHash &dirs)
{
QStringList newList;
if (!dirs.isEmpty())
foreach (const QString& s, dirs)
newList << Utils::Fs::fromNativePath(s);
setValue("Preferences/Downloads/ScanDirs", newList);
}
QList<bool> Preferences::getDownloadInScanDirs() const
{
return Utils::Misc::boolListfromStringList(value("Preferences/Downloads/DownloadInScanDirs").toStringList());
}
void Preferences::setDownloadInScanDirs(const QList<bool> &list)
{
setValue("Preferences/Downloads/DownloadInScanDirs", Utils::Misc::toStringList(list));
}
void Preferences::setScanDirsDownloadPaths(const QStringList &downloadpaths)
{
setValue("Preferences/Downloads/ScanDirsDownloadPaths", downloadpaths);
}
QStringList Preferences::getScanDirsDownloadPaths() const
{
return value("Preferences/Downloads/ScanDirsDownloadPaths").toStringList();
setValue("Preferences/Downloads/ScanDirsV2", dirs);
}
QString Preferences::getScanDirsLastPath() const
@@ -1027,12 +1000,12 @@ void Preferences::setFilteringEnabled(bool enabled)
bool Preferences::isFilteringTrackerEnabled() const
{
return value("Preferences/IPFilter/FilterTracker", false).toBool();
return value("Preferences/IPFilter/FilterTracker", false).toBool();
}
void Preferences::setFilteringTrackerEnabled(bool enabled)
{
setValue("Preferences/IPFilter/FilterTracker", enabled);
setValue("Preferences/IPFilter/FilterTracker", enabled);
}
QString Preferences::getFilter() const
@@ -1910,6 +1883,62 @@ void Preferences::setMagnetLinkAssoc(bool set)
}
#endif
#ifdef Q_OS_MAC
namespace
{
CFStringRef torrentExtension = CFSTR("torrent");
CFStringRef magnetUrlScheme = CFSTR("magnet");
}
bool Preferences::isTorrentFileAssocSet()
{
bool isSet = false;
CFStringRef torrentId = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, torrentExtension, NULL);
if (torrentId != NULL) {
CFStringRef defaultHandlerId = LSCopyDefaultRoleHandlerForContentType(torrentId, kLSRolesViewer);
if (defaultHandlerId != NULL) {
CFStringRef myBundleId = CFBundleGetIdentifier(CFBundleGetMainBundle());
isSet = CFStringCompare(myBundleId, defaultHandlerId, 0) == kCFCompareEqualTo;
CFRelease(defaultHandlerId);
}
CFRelease(torrentId);
}
return isSet;
}
bool Preferences::isMagnetLinkAssocSet()
{
bool isSet = false;
CFStringRef defaultHandlerId = LSCopyDefaultHandlerForURLScheme(magnetUrlScheme);
if (defaultHandlerId != NULL) {
CFStringRef myBundleId = CFBundleGetIdentifier(CFBundleGetMainBundle());
isSet = CFStringCompare(myBundleId, defaultHandlerId, 0) == kCFCompareEqualTo;
CFRelease(defaultHandlerId);
}
return isSet;
}
void Preferences::setTorrentFileAssoc()
{
if (isTorrentFileAssocSet())
return;
CFStringRef torrentId = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, torrentExtension, NULL);
if (torrentId != NULL) {
CFStringRef myBundleId = CFBundleGetIdentifier(CFBundleGetMainBundle());
LSSetDefaultRoleHandlerForContentType(torrentId, kLSRolesViewer, myBundleId);
CFRelease(torrentId);
}
}
void Preferences::setMagnetLinkAssoc()
{
if (isMagnetLinkAssocSet())
return;
CFStringRef myBundleId = CFBundleGetIdentifier(CFBundleGetMainBundle());
LSSetDefaultHandlerForURLScheme(magnetUrlScheme, myBundleId);
}
#endif
bool Preferences::isTrackerEnabled() const
{
return value("Preferences/Advanced/trackerEnabled", false).toBool();
@@ -2525,45 +2554,57 @@ void Preferences::setToolbarTextPosition(const int position)
setValue("Toolbar/textPosition", position);
}
QList<QByteArray> Preferences::getHostNameCookies(const QString &host_name) const
void Preferences::moveRSSCookies()
{
QMap<QString, QVariant> hosts_table = value("Rss/hosts_cookies").toMap();
if (!hosts_table.contains(host_name)) return QList<QByteArray>();
QByteArray raw_cookies = hosts_table.value(host_name).toByteArray();
return raw_cookies.split(':');
}
QList<QNetworkCookie> Preferences::getHostNameQNetworkCookies(const QString& host_name) const
{
QList<QNetworkCookie> cookies;
const QList<QByteArray> raw_cookies = getHostNameCookies(host_name);
foreach (const QByteArray& raw_cookie, raw_cookies) {
QList<QByteArray> cookie_parts = raw_cookie.split('=');
if (cookie_parts.size() == 2) {
qDebug("Loading cookie: %s = %s", cookie_parts.first().constData(), cookie_parts.last().constData());
cookies << QNetworkCookie(cookie_parts.first(), cookie_parts.last());
QList<QNetworkCookie> cookies = getNetworkCookies();
QVariantMap hostsTable = value("Rss/hosts_cookies").toMap();
foreach (const QString &key, hostsTable.keys()) {
QVariant value = hostsTable[key];
QList<QByteArray> rawCookies = value.toByteArray().split(':');
foreach (const QByteArray &rawCookie, rawCookies) {
foreach (QNetworkCookie cookie, QNetworkCookie::parseCookies(rawCookie)) {
cookie.setDomain(key);
cookie.setPath("/");
cookie.setExpirationDate(QDateTime::currentDateTime().addYears(10));
cookies << cookie;
}
}
}
setNetworkCookies(cookies);
QWriteLocker locker(&lock);
dirty = true;
timer.start();
m_data.remove("Rss/hosts_cookies");
}
QList<QNetworkCookie> Preferences::getNetworkCookies() const
{
QList<QNetworkCookie> cookies;
QStringList rawCookies = value("Network/Cookies").toStringList();
foreach (const QString &rawCookie, rawCookies)
cookies << QNetworkCookie::parseCookies(rawCookie.toUtf8());
return cookies;
}
void Preferences::setHostNameCookies(const QString &host_name, const QList<QByteArray> &cookies)
void Preferences::setNetworkCookies(const QList<QNetworkCookie> &cookies)
{
QMap<QString, QVariant> hosts_table = value("Rss/hosts_cookies").toMap();
QByteArray raw_cookies = "";
foreach (const QByteArray& cookie, cookies)
raw_cookies += cookie + ":";
if (raw_cookies.endsWith(":"))
raw_cookies.chop(1);
hosts_table.insert(host_name, raw_cookies);
setValue("Rss/hosts_cookies", hosts_table);
QStringList rawCookies;
foreach (const QNetworkCookie &cookie, cookies)
rawCookies << cookie.toRawForm();
setValue("Network/Cookies", rawCookies);
}
int Preferences::getSpeedWidgetPeriod() const {
int Preferences::getSpeedWidgetPeriod() const
{
return value("SpeedWidget/period", 1).toInt();
}
void Preferences::setSpeedWidgetPeriod(const int period) {
void Preferences::setSpeedWidgetPeriod(const int period)
{
setValue("SpeedWidget/period", period);
}

View File

@@ -176,13 +176,9 @@ public:
void additionDialogFront(bool b);
bool addTorrentsInPause() const;
void addTorrentsInPause(bool b);
QStringList getScanDirs() const;
void setScanDirs(const QStringList &dirs);
QList<bool> getDownloadInScanDirs() const;
void setDownloadInScanDirs(const QList<bool> &list);
QVariantHash getScanDirs() const;
void setScanDirs(const QVariantHash &dirs);
QString getScanDirsLastPath() const;
void setScanDirsDownloadPaths(const QStringList &downloadpaths);
QStringList getScanDirsDownloadPaths() const;
void setScanDirsLastPath(const QString &path);
bool isTorrentExportEnabled() const;
QString getTorrentExportDir() const;
@@ -421,6 +417,12 @@ public:
static bool isMagnetLinkAssocSet();
static void setTorrentFileAssoc(bool set);
static void setMagnetLinkAssoc(bool set);
#endif
#ifdef Q_OS_MAC
static bool isTorrentFileAssocSet();
static bool isMagnetLinkAssocSet();
static void setTorrentFileAssoc();
static void setMagnetLinkAssoc();
#endif
bool isTrackerEnabled() const;
void setTrackerEnabled(bool enabled);
@@ -538,9 +540,12 @@ public:
void setRssFeedsUrls(const QStringList &rssFeeds);
QStringList getRssFeedsAliases() const;
void setRssFeedsAliases(const QStringList &rssAliases);
QList<QByteArray> getHostNameCookies(const QString &host_name) const;
QList<QNetworkCookie> getHostNameQNetworkCookies(const QString& host_name) const;
void setHostNameCookies(const QString &host_name, const QList<QByteArray> &cookies);
// Network
QList<QNetworkCookie> getNetworkCookies() const;
void setNetworkCookies(const QList<QNetworkCookie> &cookies);
// Temporary method for upgrade purposes
void moveRSSCookies();
// SpeedWidget
int getSpeedWidgetPeriod() const;

View File

@@ -0,0 +1,467 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2012 Christophe Dumez <chris@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* Contact : chris@qbittorrent.org
*/
#include <QDebug>
#include <QDateTime>
#include <QRegExp>
#include <QStringList>
#include <QVariant>
#include <QXmlStreamReader>
#include "rssparser.h"
namespace
{
const char shortDay[][4] = {
"Mon", "Tue", "Wed",
"Thu", "Fri", "Sat",
"Sun"
};
const char longDay[][10] = {
"Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday",
"Sunday"
};
const char shortMonth[][4] = {
"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"
};
// Ported to Qt from KDElibs4
QDateTime parseDate(const QString &string)
{
const QString str = string.trimmed();
if (str.isEmpty())
return QDateTime::currentDateTime();
int nyear = 6; // indexes within string to values
int nmonth = 4;
int nday = 2;
int nwday = 1;
int nhour = 7;
int nmin = 8;
int nsec = 9;
// Also accept obsolete form "Weekday, DD-Mon-YY HH:MM:SS ±hhmm"
QRegExp rx("^(?:([A-Z][a-z]+),\\s*)?(\\d{1,2})(\\s+|-)([^-\\s]+)(\\s+|-)(\\d{2,4})\\s+(\\d\\d):(\\d\\d)(?::(\\d\\d))?\\s+(\\S+)$");
QStringList parts;
if (!str.indexOf(rx)) {
// Check that if date has '-' separators, both separators are '-'.
parts = rx.capturedTexts();
bool h1 = (parts[3] == QLatin1String("-"));
bool h2 = (parts[5] == QLatin1String("-"));
if (h1 != h2)
return QDateTime::currentDateTime();
}
else {
// Check for the obsolete form "Wdy Mon DD HH:MM:SS YYYY"
rx = QRegExp("^([A-Z][a-z]+)\\s+(\\S+)\\s+(\\d\\d)\\s+(\\d\\d):(\\d\\d):(\\d\\d)\\s+(\\d\\d\\d\\d)$");
if (str.indexOf(rx))
return QDateTime::currentDateTime();
nyear = 7;
nmonth = 2;
nday = 3;
nwday = 1;
nhour = 4;
nmin = 5;
nsec = 6;
parts = rx.capturedTexts();
}
bool ok[4];
const int day = parts[nday].toInt(&ok[0]);
int year = parts[nyear].toInt(&ok[1]);
const int hour = parts[nhour].toInt(&ok[2]);
const int minute = parts[nmin].toInt(&ok[3]);
if (!ok[0] || !ok[1] || !ok[2] || !ok[3])
return QDateTime::currentDateTime();
int second = 0;
if (!parts[nsec].isEmpty()) {
second = parts[nsec].toInt(&ok[0]);
if (!ok[0])
return QDateTime::currentDateTime();
}
bool leapSecond = (second == 60);
if (leapSecond)
second = 59; // apparently a leap second - validate below, once time zone is known
int month = 0;
for ( ; (month < 12) && (parts[nmonth] != shortMonth[month]); ++month);
int dayOfWeek = -1;
if (!parts[nwday].isEmpty()) {
// Look up the weekday name
while (++dayOfWeek < 7 && (shortDay[dayOfWeek] != parts[nwday]));
if (dayOfWeek >= 7)
for (dayOfWeek = 0; dayOfWeek < 7 && (longDay[dayOfWeek] != parts[nwday]); ++dayOfWeek);
}
// if (month >= 12 || dayOfWeek >= 7
// || (dayOfWeek < 0 && format == RFCDateDay))
// return QDateTime;
int i = parts[nyear].size();
if (i < 4) {
// It's an obsolete year specification with less than 4 digits
year += (i == 2 && year < 50) ? 2000 : 1900;
}
// Parse the UTC offset part
int offset = 0; // set default to '-0000'
bool negOffset = false;
if (parts.count() > 10) {
rx = QRegExp("^([+-])(\\d\\d)(\\d\\d)$");
if (!parts[10].indexOf(rx)) {
// It's a UTC offset ±hhmm
parts = rx.capturedTexts();
offset = parts[2].toInt(&ok[0]) * 3600;
int offsetMin = parts[3].toInt(&ok[1]);
if (!ok[0] || !ok[1] || offsetMin > 59)
return QDateTime();
offset += offsetMin * 60;
negOffset = (parts[1] == QLatin1String("-"));
if (negOffset)
offset = -offset;
}
else {
// Check for an obsolete time zone name
QByteArray zone = parts[10].toLatin1();
if (zone.length() == 1 && isalpha(zone[0]) && toupper(zone[0]) != 'J') {
negOffset = true; // military zone: RFC 2822 treats as '-0000'
}
else if (zone != "UT" && zone != "GMT") { // treated as '+0000'
offset = (zone == "EDT")
? -4 * 3600
: ((zone == "EST") || (zone == "CDT"))
? -5 * 3600
: ((zone == "CST") || (zone == "MDT"))
? -6 * 3600
: (zone == "MST" || zone == "PDT")
? -7 * 3600
: (zone == "PST")
? -8 * 3600
: 0;
if (!offset) {
// Check for any other alphabetic time zone
bool nonalpha = false;
for (int i = 0, end = zone.size(); (i < end) && !nonalpha; ++i)
nonalpha = !isalpha(zone[i]);
if (nonalpha)
return QDateTime();
// TODO: Attempt to recognize the time zone abbreviation?
negOffset = true; // unknown time zone: RFC 2822 treats as '-0000'
}
}
}
}
QDate qdate(year, month + 1, day); // convert date, and check for out-of-range
if (!qdate.isValid())
return QDateTime::currentDateTime();
QTime qTime(hour, minute, second);
QDateTime result(qdate, qTime, Qt::UTC);
if (offset)
result = result.addSecs(-offset);
if (!result.isValid())
return QDateTime::currentDateTime(); // invalid date/time
if (leapSecond) {
// Validate a leap second time. Leap seconds are inserted after 23:59:59 UTC.
// Convert the time to UTC and check that it is 00:00:00.
if ((hour*3600 + minute*60 + 60 - offset + 86400*5) % 86400) // (max abs(offset) is 100 hours)
return QDateTime::currentDateTime(); // the time isn't the last second of the day
}
return result;
}
}
using namespace Rss::Private;
// read and create items from a rss document
void Parser::parse(const QByteArray &feedData)
{
qDebug() << Q_FUNC_INFO;
QXmlStreamReader xml(feedData);
bool foundChannel = false;
while (xml.readNextStartElement()) {
if (xml.name() == "rss") {
// Find channels
while (xml.readNextStartElement()) {
if (xml.name() == "channel") {
parseRSSChannel(xml);
foundChannel = true;
break;
}
else {
qDebug() << "Skip rss item: " << xml.name();
xml.skipCurrentElement();
}
}
break;
}
else if (xml.name() == "feed") { // Atom feed
parseAtomChannel(xml);
foundChannel = true;
break;
}
else {
qDebug() << "Skip root item: " << xml.name();
xml.skipCurrentElement();
}
}
if (xml.hasError())
emit finished(xml.errorString());
else if (!foundChannel)
emit finished(tr("Invalid RSS feed."));
else
emit finished(QString());
}
void Parser::parseRssArticle(QXmlStreamReader &xml)
{
QVariantHash article;
while(!xml.atEnd()) {
xml.readNext();
if(xml.isEndElement() && xml.name() == "item")
break;
if (xml.isStartElement()) {
if (xml.name() == "title") {
article["title"] = xml.readElementText().trimmed();
}
else if (xml.name() == "enclosure") {
if (xml.attributes().value("type") == "application/x-bittorrent")
article["torrent_url"] = xml.attributes().value("url").toString();
}
else if (xml.name() == "link") {
QString link = xml.readElementText().trimmed();
if (link.startsWith("magnet:", Qt::CaseInsensitive))
article["torrent_url"] = link; // magnet link instead of a news URL
else
article["news_link"] = link;
}
else if (xml.name() == "description") {
article["description"] = xml.readElementText().trimmed();
}
else if (xml.name() == "pubDate") {
article["date"] = parseDate(xml.readElementText().trimmed());
}
else if (xml.name() == "author") {
article["author"] = xml.readElementText().trimmed();
}
else if (xml.name() == "guid") {
article["id"] = xml.readElementText().trimmed();
}
}
}
if (!article.contains("torrent_url") && article.contains("news_link"))
article["torrent_url"] = article["news_link"];
if (!article.contains("id")) {
// Item does not have a guid, fall back to some other identifier
const QString link = article.value("news_link").toString();
if (!link.isEmpty()) {
article["id"] = link;
}
else {
const QString title = article.value("title").toString();
if (!title.isEmpty()) {
article["id"] = title;
}
else {
qWarning() << "Item has no guid, link or title, ignoring it...";
return;
}
}
}
emit newArticle(article);
}
void Parser::parseRSSChannel(QXmlStreamReader &xml)
{
qDebug() << Q_FUNC_INFO;
Q_ASSERT(xml.isStartElement() && xml.name() == "channel");
while(!xml.atEnd()) {
xml.readNext();
if (xml.isStartElement()) {
if (xml.name() == "title") {
QString title = xml.readElementText();
emit feedTitle(title);
}
else if (xml.name() == "lastBuildDate") {
QString lastBuildDate = xml.readElementText();
if (!lastBuildDate.isEmpty()) {
if (m_lastBuildDate == lastBuildDate) {
qDebug() << "The RSS feed has not changed since last time, aborting parsing.";
return;
}
m_lastBuildDate = lastBuildDate;
}
}
else if (xml.name() == "item") {
parseRssArticle(xml);
}
}
}
}
void Parser::parseAtomArticle(QXmlStreamReader &xml)
{
QVariantHash article;
bool doubleContent = false;
while(!xml.atEnd()) {
xml.readNext();
if(xml.isEndElement() && (xml.name() == "entry"))
break;
if (xml.isStartElement()) {
if (xml.name() == "title") {
article["title"] = xml.readElementText().trimmed();
}
else if (xml.name() == "link") {
QString link = ( xml.attributes().isEmpty() ?
xml.readElementText().trimmed() :
xml.attributes().value("href").toString() );
if (link.startsWith("magnet:", Qt::CaseInsensitive))
article["torrent_url"] = link; // magnet link instead of a news URL
else
// Atom feeds can have relative links, work around this and
// take the stress of figuring article full URI from UI
// Assemble full URI
article["news_link"] = ( m_baseUrl.isEmpty() ? link : m_baseUrl + link );
}
else if ((xml.name() == "summary") || (xml.name() == "content")){
if (doubleContent) { // Duplicate content -> ignore
xml.readNext();
while ((xml.name() != "summary") && (xml.name() != "content"))
xml.readNext();
continue;
}
// Try to also parse broken articles, which don't use html '&' escapes
// Actually works great for non-broken content too
QString feedText = xml.readElementText(QXmlStreamReader::IncludeChildElements);
if (!feedText.isEmpty())
article["description"] = feedText.trimmed();
doubleContent = true;
}
else if (xml.name() == "updated") {
// ATOM uses standard compliant date, don't do fancy stuff
QDateTime articleDate = QDateTime::fromString(xml.readElementText().trimmed(), Qt::ISODate);
article["date"] = (articleDate.isValid() ? articleDate : QDateTime::currentDateTime());
}
else if (xml.name() == "author") {
xml.readNext();
while(xml.name() != "author") {
if(xml.name() == "name")
article["author"] = xml.readElementText().trimmed();
xml.readNext();
}
}
else if (xml.name() == "id") {
article["id"] = xml.readElementText().trimmed();
}
}
}
if (!article.contains("torrent_url") && article.contains("news_link"))
article["torrent_url"] = article["news_link"];
if (!article.contains("id")) {
// Item does not have a guid, fall back to some other identifier
const QString link = article.value("news_link").toString();
if (!link.isEmpty()) {
article["id"] = link;
}
else {
const QString title = article.value("title").toString();
if (!title.isEmpty()) {
article["id"] = title;
}
else {
qWarning() << "Item has no guid, link or title, ignoring it...";
return;
}
}
}
emit newArticle(article);
}
void Parser::parseAtomChannel(QXmlStreamReader &xml)
{
qDebug() << Q_FUNC_INFO;
Q_ASSERT(xml.isStartElement() && xml.name() == "feed");
m_baseUrl = xml.attributes().value("xml:base").toString();
while (!xml.atEnd()) {
xml.readNext();
if (xml.isStartElement()) {
if (xml.name() == "title") {
QString title = xml.readElementText();
emit feedTitle(title);
}
else if (xml.name() == "updated") {
QString lastBuildDate = xml.readElementText();
if (!lastBuildDate.isEmpty()) {
if (m_lastBuildDate == lastBuildDate) {
qDebug() << "The RSS feed has not changed since last time, aborting parsing.";
return;
}
m_lastBuildDate = lastBuildDate;
}
}
else if (xml.name() == "entry") {
parseAtomArticle(xml);
}
}
}
}

View File

@@ -1,6 +1,7 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2012 Christophe Dumez
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2012 Christophe Dumez <chris@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -31,47 +32,38 @@
#ifndef RSSPARSER_H
#define RSSPARSER_H
#include "rssarticle.h"
#include <QMutex>
#include <QQueue>
#include <QThread>
#include <QWaitCondition>
#include <QObject>
#include <QString>
#include <QVariantHash>
struct ParsingJob;
class QXmlStreamReader;
class RssParser : public QThread
namespace Rss
{
Q_OBJECT
namespace Private
{
class Parser: public QObject
{
Q_OBJECT
public:
explicit RssParser(QObject *parent = 0);
virtual ~RssParser();
public slots:
void parse(const QByteArray &feedData);
signals:
void newArticle(const QString& feedUrl, const QVariantHash& rssArticle);
void feedTitle(const QString& feedUrl, const QString& title);
void feedParsingFinished(const QString& feedUrl, const QString& error);
signals:
void newArticle(const QVariantHash &rssArticle);
void feedTitle(const QString &title);
void finished(const QString &error);
public slots:
void parseRssFile(const QString& feedUrl, const QString& filePath);
void clearFeedData(const QString& feedUrl);
private:
void parseRssArticle(QXmlStreamReader &xml);
void parseRSSChannel(QXmlStreamReader &xml);
void parseAtomArticle(QXmlStreamReader &xml);
void parseAtomChannel(QXmlStreamReader &xml);
protected:
virtual void run();
static QDateTime parseDate(const QString& string);
void parseRssArticle(QXmlStreamReader& xml, const QString& feedUrl);
void parseRSSChannel(QXmlStreamReader& xml, const QString& feedUrl);
void parseAtomArticle(QXmlStreamReader& xml, const QString& feedUrl, const QString& baseUrl);
void parseAtomChannel(QXmlStreamReader& xml, const QString& feedUrl);
void parseFeed(const ParsingJob& job);
void reportFailure(const ParsingJob& job, const QString& error);
private:
bool m_running;
QMutex m_mutex;
QQueue<ParsingJob> m_queue;
QWaitCondition m_waitCondition;
QHash<QString/*feedUrl*/, QString/*lastBuildDate*/> m_lastBuildDates; // Optimization
};
QString m_lastBuildDate; // Optimization
QString m_baseUrl;
};
}
}
#endif // RSSPARSER_H

143
src/base/rss/rssarticle.cpp Normal file
View File

@@ -0,0 +1,143 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
* Copyright (C) 2010 Arnaud Demaiziere <arnaud@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* Contact: chris@qbittorrent.org, arnaud@qbittorrent.org
*/
#include <QVariant>
#include <QDebug>
#include <iostream>
#include "rssfeed.h"
#include "rssarticle.h"
using namespace Rss;
// public constructor
Article::Article(Feed *parent, const QString &guid)
: m_parent(parent)
, m_guid(guid)
, m_read(false)
{
}
bool Article::hasAttachment() const
{
return !m_torrentUrl.isEmpty();
}
QVariantHash Article::toHash() const
{
QVariantHash item;
item["title"] = m_title;
item["id"] = m_guid;
item["torrent_url"] = m_torrentUrl;
item["news_link"] = m_link;
item["description"] = m_description;
item["date"] = m_date;
item["author"] = m_author;
item["read"] = m_read;
return item;
}
ArticlePtr Article::fromHash(Feed *parent, const QVariantHash &h)
{
const QString guid = h.value("id").toString();
if (guid.isEmpty())
return ArticlePtr();
ArticlePtr art(new Article(parent, guid));
art->m_title = h.value("title", "").toString();
art->m_torrentUrl = h.value("torrent_url", "").toString();
art->m_link = h.value("news_link", "").toString();
art->m_description = h.value("description").toString();
art->m_date = h.value("date").toDateTime();
art->m_author = h.value("author").toString();
art->m_read = h.value("read", false).toBool();
return art;
}
Feed *Article::parent() const
{
return m_parent;
}
const QString &Article::author() const
{
return m_author;
}
const QString &Article::torrentUrl() const
{
return m_torrentUrl;
}
const QString &Article::link() const
{
return m_link;
}
QString Article::description() const
{
return m_description.isNull() ? "" : m_description;
}
const QDateTime &Article::date() const
{
return m_date;
}
bool Article::isRead() const
{
return m_read;
}
void Article::markAsRead()
{
if (!m_read) {
m_read = true;
emit articleWasRead();
}
}
const QString &Article::guid() const
{
return m_guid;
}
const QString &Article::title() const
{
return m_title;
}
void Article::handleTorrentDownloadSuccess(const QString &url)
{
if (url == m_torrentUrl)
markAsRead();
}

View File

@@ -1,6 +1,7 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Copyright (C) 2010 Christophe Dumez, Arnaud Demaiziere
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
* Copyright (C) 2010 Arnaud Demaiziere <arnaud@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -31,58 +32,60 @@
#ifndef RSSARTICLE_H
#define RSSARTICLE_H
#include <QXmlStreamReader>
#include <QDateTime>
#include <QVariantHash>
#include <QSharedPointer>
class RssFeed;
class RssArticle;
namespace Rss
{
class Feed;
class Article;
typedef QSharedPointer<RssArticle> RssArticlePtr;
typedef QSharedPointer<Article> ArticlePtr;
// Item of a rss stream, single information
class RssArticle : public QObject {
Q_OBJECT
// Item of a rss stream, single information
class Article: public QObject
{
Q_OBJECT
public:
RssArticle(RssFeed* parent, const QString& guid);
// Accessors
bool hasAttachment() const;
const QString& guid() const;
RssFeed* parent() const;
const QString& title() const;
const QString& author() const;
const QString& torrentUrl() const;
const QString& link() const;
QString description() const;
const QDateTime& date() const;
bool isRead() const;
// Setters
void markAsRead();
// Serialization
QVariantHash toHash() const;
public:
Article(Feed *parent, const QString &guid);
signals:
void articleWasRead();
// Accessors
bool hasAttachment() const;
const QString &guid() const;
Feed *parent() const;
const QString &title() const;
const QString &author() const;
const QString &torrentUrl() const;
const QString &link() const;
QString description() const;
const QDateTime &date() const;
bool isRead() const;
// Setters
void markAsRead();
public slots:
void handleTorrentDownloadSuccess(const QString& url);
// Serialization
QVariantHash toHash() const;
static ArticlePtr fromHash(Feed *parent, const QVariantHash &hash);
friend RssArticlePtr hashToRssArticle(RssFeed* parent, const QVariantHash& hash);
signals:
void articleWasRead();
private:
RssFeed* m_parent;
QString m_guid;
QString m_title;
QString m_torrentUrl;
QString m_link;
QString m_description;
QDateTime m_date;
QString m_author;
bool m_read;
};
public slots:
void handleTorrentDownloadSuccess(const QString &url);
RssArticlePtr hashToRssArticle(RssFeed* parent, const QVariantHash& hash);
private:
Feed *m_parent;
QString m_guid;
QString m_title;
QString m_torrentUrl;
QString m_link;
QString m_description;
QDateTime m_date;
QString m_author;
bool m_read;
};
}
#endif // RSSARTICLE_H

View File

@@ -0,0 +1,312 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* Contact : chris@qbittorrent.org
*/
#include <QRegExp>
#include <QDebug>
#include <QDir>
#include "base/preferences.h"
#include "base/utils/fs.h"
#include "rssfeed.h"
#include "rssarticle.h"
#include "rssdownloadrule.h"
using namespace Rss;
DownloadRule::DownloadRule()
: m_enabled(false)
, m_useRegex(false)
, m_apstate(USE_GLOBAL)
, m_ignoreDays(0)
{
}
bool DownloadRule::matches(const QString &articleTitle) const
{
foreach (const QString &token, m_mustContain) {
if (!token.isEmpty()) {
QRegExp reg(token, Qt::CaseInsensitive, m_useRegex ? QRegExp::RegExp : QRegExp::Wildcard);
if (reg.indexIn(articleTitle) < 0)
return false;
}
}
qDebug("Checking not matching tokens");
// Checking not matching
foreach (const QString &token, m_mustNotContain) {
if (!token.isEmpty()) {
QRegExp reg(token, Qt::CaseInsensitive, m_useRegex ? QRegExp::RegExp : QRegExp::Wildcard);
if (reg.indexIn(articleTitle) > -1)
return false;
}
}
if (!m_episodeFilter.isEmpty()) {
qDebug("Checking episode filter");
QRegExp f("(^\\d{1,4})x(.*;$)");
int pos = f.indexIn(m_episodeFilter);
if (pos < 0)
return false;
QString s = f.cap(1);
QStringList eps = f.cap(2).split(";");
QString expStr;
expStr += "s0?" + s + "[ -_\\.]?" + "e0?";
foreach (const QString &ep, eps) {
if (ep.isEmpty())
continue;
if (ep.indexOf('-') != -1) { // Range detected
QString partialPattern = "s0?" + s + "[ -_\\.]?" + "e(0?\\d{1,4})";
QRegExp reg(partialPattern, Qt::CaseInsensitive);
if (ep.endsWith('-')) { // Infinite range
int epOurs = ep.left(ep.size() - 1).toInt();
// Extract partial match from article and compare as digits
pos = reg.indexIn(articleTitle);
if (pos != -1) {
int epTheirs = reg.cap(1).toInt();
if (epTheirs >= epOurs)
return true;
}
}
else { // Normal range
QStringList range = ep.split('-');
Q_ASSERT(range.size() == 2);
if (range.first().toInt() > range.last().toInt())
continue; // Ignore this subrule completely
int epOursFirst = range.first().toInt();
int epOursLast = range.last().toInt();
// Extract partial match from article and compare as digits
pos = reg.indexIn(articleTitle);
if (pos != -1) {
int epTheirs = reg.cap(1).toInt();
if (epOursFirst <= epTheirs && epOursLast >= epTheirs)
return true;
}
}
}
else { // Single number
QRegExp reg(expStr + ep + "\\D", Qt::CaseInsensitive);
if (reg.indexIn(articleTitle) != -1)
return true;
}
}
return false;
}
return true;
}
void DownloadRule::setMustContain(const QString &tokens)
{
if (m_useRegex)
m_mustContain = QStringList() << tokens;
else
m_mustContain = tokens.split(" ");
}
void DownloadRule::setMustNotContain(const QString &tokens)
{
if (m_useRegex)
m_mustNotContain = QStringList() << tokens;
else
m_mustNotContain = tokens.split("|");
}
QStringList DownloadRule::rssFeeds() const
{
return m_rssFeeds;
}
void DownloadRule::setRssFeeds(const QStringList &rssFeeds)
{
m_rssFeeds = rssFeeds;
}
QString DownloadRule::name() const
{
return m_name;
}
void DownloadRule::setName(const QString &name)
{
m_name = name;
}
QString DownloadRule::savePath() const
{
return m_savePath;
}
DownloadRulePtr DownloadRule::fromVariantHash(const QVariantHash &ruleHash)
{
DownloadRulePtr rule(new DownloadRule);
rule->setName(ruleHash.value("name").toString());
rule->setUseRegex(ruleHash.value("use_regex", false).toBool());
rule->setMustContain(ruleHash.value("must_contain").toString());
rule->setMustNotContain(ruleHash.value("must_not_contain").toString());
rule->setEpisodeFilter(ruleHash.value("episode_filter").toString());
rule->setRssFeeds(ruleHash.value("affected_feeds").toStringList());
rule->setEnabled(ruleHash.value("enabled", false).toBool());
rule->setSavePath(ruleHash.value("save_path").toString());
rule->setLabel(ruleHash.value("label_assigned").toString());
rule->setAddPaused(AddPausedState(ruleHash.value("add_paused").toUInt()));
rule->setLastMatch(ruleHash.value("last_match").toDateTime());
rule->setIgnoreDays(ruleHash.value("ignore_days").toInt());
return rule;
}
QVariantHash DownloadRule::toVariantHash() const
{
QVariantHash hash;
hash["name"] = m_name;
hash["must_contain"] = m_mustContain.join(" ");
hash["must_not_contain"] = m_mustNotContain.join("|");
hash["save_path"] = m_savePath;
hash["affected_feeds"] = m_rssFeeds;
hash["enabled"] = m_enabled;
hash["label_assigned"] = m_label;
hash["use_regex"] = m_useRegex;
hash["add_paused"] = m_apstate;
hash["episode_filter"] = m_episodeFilter;
hash["last_match"] = m_lastMatch;
hash["ignore_days"] = m_ignoreDays;
return hash;
}
bool DownloadRule::operator==(const DownloadRule &other) const
{
return m_name == other.name();
}
void DownloadRule::setSavePath(const QString &savePath)
{
if (!savePath.isEmpty() && (QDir(savePath) != QDir(Preferences::instance()->getSavePath())))
m_savePath = Utils::Fs::fromNativePath(savePath);
else
m_savePath = QString();
}
DownloadRule::AddPausedState DownloadRule::addPaused() const
{
return m_apstate;
}
void DownloadRule::setAddPaused(const DownloadRule::AddPausedState &aps)
{
m_apstate = aps;
}
QString DownloadRule::label() const
{
return m_label;
}
void DownloadRule::setLabel(const QString &label)
{
m_label = label;
}
bool DownloadRule::isEnabled() const
{
return m_enabled;
}
void DownloadRule::setEnabled(bool enable)
{
m_enabled = enable;
}
void DownloadRule::setLastMatch(const QDateTime &d)
{
m_lastMatch = d;
}
QDateTime DownloadRule::lastMatch() const
{
return m_lastMatch;
}
void DownloadRule::setIgnoreDays(int d)
{
m_ignoreDays = d;
}
int DownloadRule::ignoreDays() const
{
return m_ignoreDays;
}
QString DownloadRule::mustContain() const
{
return m_mustContain.join(" ");
}
QString DownloadRule::mustNotContain() const
{
return m_mustNotContain.join("|");
}
bool DownloadRule::useRegex() const
{
return m_useRegex;
}
void DownloadRule::setUseRegex(bool enabled)
{
m_useRegex = enabled;
}
QString DownloadRule::episodeFilter() const
{
return m_episodeFilter;
}
void DownloadRule::setEpisodeFilter(const QString &e)
{
m_episodeFilter = e;
}
QStringList DownloadRule::findMatchingArticles(const FeedPtr &feed) const
{
QStringList ret;
const ArticleHash &feedArticles = feed->articleHash();
ArticleHash::ConstIterator artIt = feedArticles.begin();
ArticleHash::ConstIterator artItend = feedArticles.end();
for ( ; artIt != artItend ; ++artIt) {
const QString title = artIt.value()->title();
if (matches(title))
ret << title;
}
return ret;
}

View File

@@ -0,0 +1,106 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* Contact : chris@qbittorrent.org
*/
#ifndef RSSDOWNLOADRULE_H
#define RSSDOWNLOADRULE_H
#include <QStringList>
#include <QVariantHash>
#include <QSharedPointer>
#include <QDateTime>
namespace Rss
{
class Feed;
typedef QSharedPointer<Feed> FeedPtr;
class DownloadRule;
typedef QSharedPointer<DownloadRule> DownloadRulePtr;
class DownloadRule
{
public:
enum AddPausedState
{
USE_GLOBAL = 0,
ALWAYS_PAUSED,
NEVER_PAUSED
};
DownloadRule();
static DownloadRulePtr fromVariantHash(const QVariantHash &ruleHash);
QVariantHash toVariantHash() const;
bool matches(const QString &articleTitle) const;
void setMustContain(const QString &tokens);
void setMustNotContain(const QString &tokens);
QStringList rssFeeds() const;
void setRssFeeds(const QStringList &rssFeeds);
QString name() const;
void setName(const QString &name);
QString savePath() const;
void setSavePath(const QString &savePath);
AddPausedState addPaused() const;
void setAddPaused(const AddPausedState &aps);
QString label() const;
void setLabel(const QString &label);
bool isEnabled() const;
void setEnabled(bool enable);
void setLastMatch(const QDateTime &d);
QDateTime lastMatch() const;
void setIgnoreDays(int d);
int ignoreDays() const;
QString mustContain() const;
QString mustNotContain() const;
bool useRegex() const;
void setUseRegex(bool enabled);
QString episodeFilter() const;
void setEpisodeFilter(const QString &e);
QStringList findMatchingArticles(const FeedPtr &feed) const;
// Operators
bool operator==(const DownloadRule &other) const;
private:
QString m_name;
QStringList m_mustContain;
QStringList m_mustNotContain;
QString m_episodeFilter;
QString m_savePath;
QString m_label;
bool m_enabled;
QStringList m_rssFeeds;
bool m_useRegex;
AddPausedState m_apstate;
QDateTime m_lastMatch;
int m_ignoreDays;
};
}
#endif // RSSDOWNLOADRULE_H

View File

@@ -0,0 +1,185 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* Contact : chris@qbittorrent.org
*/
#include <QFile>
#include <QDataStream>
#include <QDebug>
#include "base/preferences.h"
#include "base/qinisettings.h"
#include "rssdownloadrulelist.h"
using namespace Rss;
DownloadRuleList::DownloadRuleList()
{
loadRulesFromStorage();
}
DownloadRulePtr DownloadRuleList::findMatchingRule(const QString &feedUrl, const QString &articleTitle) const
{
Q_ASSERT(Preferences::instance()->isRssDownloadingEnabled());
QStringList ruleNames = m_feedRules.value(feedUrl);
foreach (const QString &rule_name, ruleNames) {
DownloadRulePtr rule = m_rules[rule_name];
if (rule->isEnabled() && rule->matches(articleTitle)) return rule;
}
return DownloadRulePtr();
}
void DownloadRuleList::replace(DownloadRuleList *other)
{
m_rules.clear();
m_feedRules.clear();
foreach (const QString &name, other->ruleNames()) {
saveRule(other->getRule(name));
}
}
void DownloadRuleList::saveRulesToStorage()
{
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
qBTRSS.setValue("download_rules", toVariantHash());
}
void DownloadRuleList::loadRulesFromStorage()
{
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
loadRulesFromVariantHash(qBTRSS.value("download_rules").toHash());
}
QVariantHash DownloadRuleList::toVariantHash() const
{
QVariantHash ret;
foreach (const DownloadRulePtr &rule, m_rules.values()) {
ret.insert(rule->name(), rule->toVariantHash());
}
return ret;
}
void DownloadRuleList::loadRulesFromVariantHash(const QVariantHash &h)
{
QVariantHash::ConstIterator it = h.begin();
QVariantHash::ConstIterator itend = h.end();
for ( ; it != itend; ++it) {
DownloadRulePtr rule = DownloadRule::fromVariantHash(it.value().toHash());
if (rule && !rule->name().isEmpty())
saveRule(rule);
}
}
void DownloadRuleList::saveRule(const DownloadRulePtr &rule)
{
qDebug() << Q_FUNC_INFO << rule->name();
Q_ASSERT(rule);
if (m_rules.contains(rule->name())) {
qDebug("This is an update, removing old rule first");
removeRule(rule->name());
}
m_rules.insert(rule->name(), rule);
// Update feedRules hashtable
foreach (const QString &feedUrl, rule->rssFeeds()) {
m_feedRules[feedUrl].append(rule->name());
}
qDebug() << Q_FUNC_INFO << "EXIT";
}
void DownloadRuleList::removeRule(const QString &name)
{
qDebug() << Q_FUNC_INFO << name;
if (!m_rules.contains(name)) return;
DownloadRulePtr rule = m_rules.take(name);
// Update feedRules hashtable
foreach (const QString &feedUrl, rule->rssFeeds()) {
m_feedRules[feedUrl].removeOne(rule->name());
}
}
void DownloadRuleList::renameRule(const QString &oldName, const QString &newName)
{
if (!m_rules.contains(oldName)) return;
DownloadRulePtr rule = m_rules.take(oldName);
rule->setName(newName);
m_rules.insert(newName, rule);
// Update feedRules hashtable
foreach (const QString &feedUrl, rule->rssFeeds()) {
m_feedRules[feedUrl].replace(m_feedRules[feedUrl].indexOf(oldName), newName);
}
}
DownloadRulePtr DownloadRuleList::getRule(const QString &name) const
{
return m_rules.value(name);
}
QStringList DownloadRuleList::ruleNames() const
{
return m_rules.keys();
}
bool DownloadRuleList::isEmpty() const
{
return m_rules.isEmpty();
}
bool DownloadRuleList::serialize(const QString &path)
{
QFile f(path);
if (f.open(QIODevice::WriteOnly)) {
QDataStream out(&f);
out.setVersion(QDataStream::Qt_4_5);
out << toVariantHash();
f.close();
return true;
}
return false;
}
bool DownloadRuleList::unserialize(const QString &path)
{
QFile f(path);
if (f.open(QIODevice::ReadOnly)) {
QDataStream in(&f);
in.setVersion(QDataStream::Qt_4_5);
QVariantHash tmp;
in >> tmp;
f.close();
if (tmp.isEmpty())
return false;
qDebug("Processing was successful!");
loadRulesFromVariantHash(tmp);
return true;
} else {
qDebug("Error: could not open file at %s", qPrintable(path));
return false;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Bittorrent Client using Qt4 and libtorrent.
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2010 Christophe Dumez
*
* This program is free software; you can redistribute it and/or
@@ -34,36 +34,40 @@
#include <QList>
#include <QHash>
#include <QVariantHash>
#include "rssdownloadrule.h"
class RssDownloadRuleList
namespace Rss
{
Q_DISABLE_COPY(RssDownloadRuleList)
class DownloadRuleList
{
Q_DISABLE_COPY(DownloadRuleList)
public:
RssDownloadRuleList();
RssDownloadRulePtr findMatchingRule(const QString &feed_url, const QString &article_title) const;
// Operators
void saveRule(const RssDownloadRulePtr &rule);
void removeRule(const QString &name);
void renameRule(const QString &old_name, const QString &new_name);
RssDownloadRulePtr getRule(const QString &name) const;
inline QStringList ruleNames() const { return m_rules.keys(); }
inline bool isEmpty() const { return m_rules.isEmpty(); }
void saveRulesToStorage();
bool serialize(const QString& path);
bool unserialize(const QString& path);
void replace(RssDownloadRuleList* other);
public:
DownloadRuleList();
private:
void loadRulesFromStorage();
void loadRulesFromVariantHash(const QVariantHash& l);
QVariantHash toVariantHash() const;
DownloadRulePtr findMatchingRule(const QString &feedUrl, const QString &articleTitle) const;
// Operators
void saveRule(const DownloadRulePtr &rule);
void removeRule(const QString &name);
void renameRule(const QString &oldName, const QString &newName);
DownloadRulePtr getRule(const QString &name) const;
QStringList ruleNames() const;
bool isEmpty() const;
void saveRulesToStorage();
bool serialize(const QString &path);
bool unserialize(const QString &path);
void replace(DownloadRuleList *other);
private:
QHash<QString, RssDownloadRulePtr> m_rules;
QHash<QString, QStringList> m_feedRules;
private:
void loadRulesFromStorage();
void loadRulesFromVariantHash(const QVariantHash &l);
QVariantHash toVariantHash() const;
};
private:
QHash<QString, DownloadRulePtr> m_rules;
QHash<QString, QStringList> m_feedRules;
};
}
#endif // RSSDOWNLOADFILTERLIST_H

449
src/base/rss/rssfeed.cpp Normal file
View File

@@ -0,0 +1,449 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
* Copyright (C) 2010 Arnaud Demaiziere <arnaud@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* Contact: chris@qbittorrent.org, arnaud@qbittorrent.org
*/
#include <QDebug>
#include "base/preferences.h"
#include "base/qinisettings.h"
#include "base/logger.h"
#include "base/bittorrent/session.h"
#include "base/bittorrent/magneturi.h"
#include "base/utils/misc.h"
#include "base/utils/fs.h"
#include "base/net/downloadmanager.h"
#include "base/net/downloadhandler.h"
#include "private/rssparser.h"
#include "rssdownloadrulelist.h"
#include "rssarticle.h"
#include "rssfolder.h"
#include "rssmanager.h"
#include "rssfeed.h"
namespace Rss
{
bool articleDateRecentThan(const ArticlePtr &left, const ArticlePtr &right)
{
return left->date() > right->date();
}
}
using namespace Rss;
Feed::Feed(const QString &url, Manager *manager)
: m_manager(manager)
, m_url (QUrl::fromEncoded(url.toUtf8()).toString())
, m_icon(":/icons/oxygen/application-rss+xml.png")
, m_unreadCount(0)
, m_dirty(false)
, m_inErrorState(false)
, m_loading(false)
{
qDebug() << Q_FUNC_INFO << m_url;
m_parser = new Private::Parser;
m_parser->moveToThread(m_manager->workingThread());
connect(this, SIGNAL(destroyed()), m_parser, SLOT(deleteLater()));
// Listen for new RSS downloads
connect(m_parser, SIGNAL(feedTitle(QString)), SLOT(handleFeedTitle(QString)));
connect(m_parser, SIGNAL(newArticle(QVariantHash)), SLOT(handleNewArticle(QVariantHash)));
connect(m_parser, SIGNAL(finished(QString)), SLOT(handleParsingFinished(QString)));
// Download the RSS Feed icon
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(iconUrl(), true);
connect(handler, SIGNAL(downloadFinished(QString, QString)), this, SLOT(handleIconDownloadFinished(QString, QString)));
// Load old RSS articles
loadItemsFromDisk();
refresh();
}
Feed::~Feed()
{
if (!m_icon.startsWith(":/") && QFile::exists(m_icon))
Utils::Fs::forceRemove(m_icon);
}
void Feed::saveItemsToDisk()
{
qDebug() << Q_FUNC_INFO << m_url;
if (!m_dirty) return;
m_dirty = false;
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
QVariantList oldItems;
ArticleHash::ConstIterator it = m_articles.begin();
ArticleHash::ConstIterator itend = m_articles.end();
for ( ; it != itend; ++it) {
oldItems << it.value()->toHash();
}
qDebug("Saving %d old items for feed %s", oldItems.size(), qPrintable(displayName()));
QHash<QString, QVariant> allOldItems = qBTRSS.value("old_items", QHash<QString, QVariant>()).toHash();
allOldItems[m_url] = oldItems;
qBTRSS.setValue("old_items", allOldItems);
}
void Feed::loadItemsFromDisk()
{
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
QHash<QString, QVariant> allOldItems = qBTRSS.value("old_items", QHash<QString, QVariant>()).toHash();
const QVariantList oldItems = allOldItems.value(m_url, QVariantList()).toList();
qDebug("Loading %d old items for feed %s", oldItems.size(), qPrintable(displayName()));
foreach (const QVariant &var_it, oldItems) {
QVariantHash item = var_it.toHash();
ArticlePtr rssItem = Article::fromHash(this, item);
if (rssItem)
addArticle(rssItem);
}
}
void Feed::addArticle(const ArticlePtr &article)
{
int maxArticles = Preferences::instance()->getRSSMaxArticlesPerFeed();
if (!m_articles.contains(article->guid())) {
m_dirty = true;
// Update unreadCount
if (!article->isRead())
++m_unreadCount;
// Insert in hash table
m_articles[article->guid()] = article;
if (!article->isRead()) // Optimization
connect(article.data(), SIGNAL(articleWasRead()), SLOT(handleArticleRead()), Qt::UniqueConnection);
// Insertion sort
ArticleList::Iterator lowerBound = qLowerBound(m_articlesByDate.begin(), m_articlesByDate.end(), article, articleDateRecentThan);
m_articlesByDate.insert(lowerBound, article);
int lbIndex = m_articlesByDate.indexOf(article);
if (m_articlesByDate.size() > maxArticles) {
ArticlePtr oldestArticle = m_articlesByDate.takeLast();
m_articles.remove(oldestArticle->guid());
// Update unreadCount
if (!oldestArticle->isRead())
--m_unreadCount;
}
// Check if article was inserted at the end of the list and will break max_articles limit
if (Preferences::instance()->isRssDownloadingEnabled()) {
if ((lbIndex < maxArticles) && !article->isRead())
downloadArticleTorrentIfMatching(article);
}
}
else {
// m_articles.contains(article->guid())
// Try to download skipped articles
if (Preferences::instance()->isRssDownloadingEnabled()) {
ArticlePtr skipped = m_articles.value(article->guid(), ArticlePtr());
if (skipped) {
if (!skipped->isRead())
downloadArticleTorrentIfMatching(skipped);
}
}
}
}
bool Feed::refresh()
{
if (m_loading) {
qWarning() << Q_FUNC_INFO << "Feed" << displayName() << "is already being refreshed, ignoring request";
return false;
}
m_loading = true;
// Download the RSS again
Net::DownloadHandler *handler = Net::DownloadManager::instance()->downloadUrl(m_url);
connect(handler, SIGNAL(downloadFinished(QString, QByteArray)), this, SLOT(handleRssDownloadFinished(QString, QByteArray)));
connect(handler, SIGNAL(downloadFailed(QString, QString)), this, SLOT(handleRssDownloadFailed(QString, QString)));
return true;
}
QString Feed::id() const
{
return m_url;
}
void Feed::removeAllSettings()
{
qDebug() << "Removing all settings / history for feed: " << m_url;
QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss");
QVariantHash feedsWDownloader = qBTRSS.value("downloader_on", QVariantHash()).toHash();
if (feedsWDownloader.contains(m_url)) {
feedsWDownloader.remove(m_url);
qBTRSS.setValue("downloader_on", feedsWDownloader);
}
QVariantHash allFeedsFilters = qBTRSS.value("feed_filters", QVariantHash()).toHash();
if (allFeedsFilters.contains(m_url)) {
allFeedsFilters.remove(m_url);
qBTRSS.setValue("feed_filters", allFeedsFilters);
}
QVariantHash allOldItems = qBTRSS.value("old_items", QVariantHash()).toHash();
if (allOldItems.contains(m_url)) {
allOldItems.remove(m_url);
qBTRSS.setValue("old_items", allOldItems);
}
}
bool Feed::isLoading() const
{
return m_loading;
}
QString Feed::title() const
{
return m_title;
}
void Feed::rename(const QString &newName)
{
qDebug() << "Renaming stream to" << newName;
m_alias = newName;
}
// Return the alias if the stream has one, the url if it has no alias
QString Feed::displayName() const
{
if (!m_alias.isEmpty())
return m_alias;
if (!m_title.isEmpty())
return m_title;
return m_url;
}
QString Feed::url() const
{
return m_url;
}
QString Feed::iconPath() const
{
if (m_inErrorState)
return QLatin1String(":/icons/oxygen/unavailable.png");
return m_icon;
}
bool Feed::hasCustomIcon() const
{
return !m_icon.startsWith(":/");
}
void Feed::setIconPath(const QString &path)
{
if (!path.isEmpty() && QFile::exists(path))
m_icon = path;
}
ArticlePtr Feed::getItem(const QString &guid) const
{
return m_articles.value(guid);
}
uint Feed::count() const
{
return m_articles.size();
}
void Feed::markAsRead()
{
ArticleHash::ConstIterator it = m_articles.begin();
ArticleHash::ConstIterator itend = m_articles.end();
for ( ; it != itend; ++it) {
it.value()->markAsRead();
}
m_unreadCount = 0;
m_manager->forwardFeedInfosChanged(m_url, displayName(), 0);
}
uint Feed::unreadCount() const
{
return m_unreadCount;
}
ArticleList Feed::articleListByDateDesc() const
{
return m_articlesByDate;
}
const ArticleHash &Feed::articleHash() const
{
return m_articles;
}
ArticleList Feed::unreadArticleListByDateDesc() const
{
ArticleList unreadNews;
ArticleList::ConstIterator it = m_articlesByDate.begin();
ArticleList::ConstIterator itend = m_articlesByDate.end();
for ( ; it != itend; ++it) {
if (!(*it)->isRead())
unreadNews << *it;
}
return unreadNews;
}
// download the icon from the address
QString Feed::iconUrl() const
{
// XXX: This works for most sites but it is not perfect
return QString("http://%1/favicon.ico").arg(QUrl(m_url).host());
}
void Feed::handleIconDownloadFinished(const QString &url, const QString &filePath)
{
Q_UNUSED(url);
m_icon = filePath;
qDebug() << Q_FUNC_INFO << "icon path:" << m_icon;
m_manager->forwardFeedIconChanged(m_url, m_icon);
}
void Feed::handleRssDownloadFinished(const QString &url, const QByteArray &data)
{
Q_UNUSED(url);
qDebug() << Q_FUNC_INFO << "Successfully downloaded RSS feed at" << m_url;
// Parse the download RSS
QMetaObject::invokeMethod(m_parser, "parse", Qt::QueuedConnection, Q_ARG(QByteArray, data));
}
void Feed::handleRssDownloadFailed(const QString &url, const QString &error)
{
Q_UNUSED(url);
m_inErrorState = true;
m_loading = false;
m_manager->forwardFeedInfosChanged(m_url, displayName(), m_unreadCount);
qWarning() << "Failed to download RSS feed at" << m_url;
qWarning() << "Reason:" << error;
}
void Feed::handleFeedTitle(const QString &title)
{
if (m_title == title) return;
m_title = title;
// Notify that we now have something better than a URL to display
if (m_alias.isEmpty())
m_manager->forwardFeedInfosChanged(m_url, title, m_unreadCount);
}
void Feed::downloadArticleTorrentIfMatching(const ArticlePtr &article)
{
Q_ASSERT(Preferences::instance()->isRssDownloadingEnabled());
DownloadRuleList *rules = m_manager->downloadRules();
DownloadRulePtr matchingRule = rules->findMatchingRule(m_url, article->title());
if (!matchingRule) return;
if (matchingRule->ignoreDays() > 0) {
QDateTime lastMatch = matchingRule->lastMatch();
if (lastMatch.isValid()) {
if (QDateTime::currentDateTime() < lastMatch.addDays(matchingRule->ignoreDays())) {
article->markAsRead();
return;
}
}
}
matchingRule->setLastMatch(QDateTime::currentDateTime());
rules->saveRulesToStorage();
// Download the torrent
const QString &torrentUrl = article->torrentUrl();
if (torrentUrl.isEmpty()) {
Logger::instance()->addMessage(tr("Automatic download of '%1' from '%2' RSS feed failed because it doesn't contain a torrent or a magnet link...").arg(article->title()).arg(displayName()), Log::WARNING);
article->markAsRead();
return;
}
Logger::instance()->addMessage(tr("Automatically downloading '%1' torrent from '%2' RSS feed...").arg(article->title()).arg(displayName()));
if (BitTorrent::MagnetUri(torrentUrl).isValid())
article->markAsRead();
else
connect(BitTorrent::Session::instance(), SIGNAL(downloadFromUrlFinished(QString)), article.data(), SLOT(handleTorrentDownloadSuccess(const QString&)), Qt::UniqueConnection);
BitTorrent::AddTorrentParams params;
params.savePath = matchingRule->savePath();
params.label = matchingRule->label();
if (matchingRule->addPaused() == DownloadRule::ALWAYS_PAUSED)
params.addPaused = TriStateBool::True;
else if (matchingRule->addPaused() == DownloadRule::NEVER_PAUSED)
params.addPaused = TriStateBool::False;
BitTorrent::Session::instance()->addTorrent(torrentUrl, params);
}
void Feed::recheckRssItemsForDownload()
{
Q_ASSERT(Preferences::instance()->isRssDownloadingEnabled());
foreach (const ArticlePtr &article, m_articlesByDate) {
if (!article->isRead())
downloadArticleTorrentIfMatching(article);
}
}
void Feed::handleNewArticle(const QVariantHash &articleData)
{
ArticlePtr article = Article::fromHash(this, articleData);
if (article.isNull()) {
qDebug() << "Article hash corrupted or guid is uncomputable; feed url: " << m_url;
return;
}
Q_ASSERT(article);
addArticle(article);
m_manager->forwardFeedInfosChanged(m_url, displayName(), m_unreadCount);
// FIXME: We should forward the information here but this would seriously decrease
// performance with current design.
//m_manager->forwardFeedContentChanged(m_url);
}
void Feed::handleParsingFinished(const QString &error)
{
if (!error.isEmpty()) {
qWarning() << "Failed to parse RSS feed at" << m_url;
qWarning() << "Reason:" << error;
}
m_loading = false;
m_inErrorState = !error.isEmpty();
m_manager->forwardFeedInfosChanged(m_url, displayName(), m_unreadCount);
// XXX: Would not be needed if we did this in handleNewArticle() instead
m_manager->forwardFeedContentChanged(m_url);
saveItemsToDisk();
}
void Feed::handleArticleRead()
{
--m_unreadCount;
m_dirty = true;
m_manager->forwardFeedInfosChanged(m_url, displayName(), m_unreadCount);
}

122
src/base/rss/rssfeed.h Normal file
View File

@@ -0,0 +1,122 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2010 Christophe Dumez <chris@qbittorrent.org>
* Copyright (C) 2010 Arnaud Demaiziere <arnaud@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* In addition, as a special exception, the copyright holders give permission to
* link this program with the OpenSSL project's "OpenSSL" library (or with
* modified versions of it that use the same license as the "OpenSSL" library),
* and distribute the linked executables. You must obey the GNU General Public
* License in all respects for all of the code used other than "OpenSSL". If you
* modify file(s), you may extend this exception to your version of the file(s),
* but you are not obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*
* Contact: chris@qbittorrent.org, arnaud@qbittorrent.org
*/
#ifndef RSSFEED_H
#define RSSFEED_H
#include <QHash>
#include <QSharedPointer>
#include <QVariantHash>
#include <QXmlStreamReader>
#include <QNetworkCookie>
#include "rssfile.h"
namespace Rss
{
class Folder;
class Feed;
class Manager;
class DownloadRuleList;
typedef QHash<QString, ArticlePtr> ArticleHash;
typedef QSharedPointer<Feed> FeedPtr;
typedef QList<FeedPtr> FeedList;
namespace Private
{
class Parser;
}
bool articleDateRecentThan(const ArticlePtr &left, const ArticlePtr &right);
class Feed: public QObject, public File
{
Q_OBJECT
public:
Feed(const QString &url, Manager *manager);
~Feed();
bool refresh();
QString id() const;
void removeAllSettings();
void saveItemsToDisk();
bool isLoading() const;
QString title() const;
void rename(const QString &newName);
QString displayName() const;
QString url() const;
QString iconPath() const;
bool hasCustomIcon() const;
void setIconPath(const QString &pathHierarchy);
ArticlePtr getItem(const QString &guid) const;
uint count() const;
void markAsRead();
uint unreadCount() const;
ArticleList articleListByDateDesc() const;
const ArticleHash &articleHash() const;
ArticleList unreadArticleListByDateDesc() const;
void recheckRssItemsForDownload();
private slots:
void handleIconDownloadFinished(const QString &url, const QString &filePath);
void handleRssDownloadFinished(const QString &url, const QByteArray &data);
void handleRssDownloadFailed(const QString &url, const QString &error);
void handleFeedTitle(const QString &title);
void handleNewArticle(const QVariantHash &article);
void handleParsingFinished(const QString &error);
void handleArticleRead();
private:
QString iconUrl() const;
void loadItemsFromDisk();
void addArticle(const ArticlePtr &article);
void downloadArticleTorrentIfMatching(const ArticlePtr &article);
private:
Manager *m_manager;
Private::Parser *m_parser;
ArticleHash m_articles;
ArticleList m_articlesByDate; // Articles sorted by date (more recent first)
QString m_title;
QString m_url;
QString m_alias;
QString m_icon;
uint m_unreadCount;
bool m_dirty;
bool m_inErrorState;
bool m_loading;
};
}
#endif // RSSFEED_H

Some files were not shown because too many files have changed in this diff Show More