mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-17 06:01:33 -06:00
Compare commits
502 Commits
release-4.
...
release-4.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eea38e7c9e | ||
|
|
5c933c9734 | ||
|
|
102b7fa78e | ||
|
|
b5ee908f6c | ||
|
|
7825d8627f | ||
|
|
b798c591e7 | ||
|
|
9e7d21d7aa | ||
|
|
38a15b27f0 | ||
|
|
cb31684a66 | ||
|
|
850cde19f7 | ||
|
|
fc5b3b4f70 | ||
|
|
73fd4d83af | ||
|
|
811b525b1d | ||
|
|
0f8def9a49 | ||
|
|
359b464958 | ||
|
|
b5b0d68dd9 | ||
|
|
f48c49c248 | ||
|
|
11ca744548 | ||
|
|
82e6fc700e | ||
|
|
59fd70c638 | ||
|
|
617bf767df | ||
|
|
55180e3598 | ||
|
|
56b62e6573 | ||
|
|
b37e7b0340 | ||
|
|
21aebaf16f | ||
|
|
5792465317 | ||
|
|
e98f44af63 | ||
|
|
40cf0203fb | ||
|
|
05a82afeb6 | ||
|
|
a456f1b0f9 | ||
|
|
4acc44a5b0 | ||
|
|
9c2a1146df | ||
|
|
807abeae87 | ||
|
|
dd2a0d0484 | ||
|
|
3f3400f43b | ||
|
|
334b57a89a | ||
|
|
00d6c83ee5 | ||
|
|
e8850c7a70 | ||
|
|
2ef96eb218 | ||
|
|
4682e31ab7 | ||
|
|
988f7e2ef8 | ||
|
|
6007913291 | ||
|
|
cdcc7a210b | ||
|
|
a466ff5057 | ||
|
|
e954835579 | ||
|
|
3e9be3a0e8 | ||
|
|
4ab32a76f6 | ||
|
|
bad60058df | ||
|
|
31a6ad1eb6 | ||
|
|
a8bfec081e | ||
|
|
ae21d0f1e2 | ||
|
|
c599976b6f | ||
|
|
bcee784097 | ||
|
|
697fc626cd | ||
|
|
2f15ea9b54 | ||
|
|
d03209a73d | ||
|
|
ac9ba255d8 | ||
|
|
9a7e79bd0e | ||
|
|
e8be3bf939 | ||
|
|
74e52746b1 | ||
|
|
8d26a221e0 | ||
|
|
3fdab88eb7 | ||
|
|
d376d912b3 | ||
|
|
e329c41ef2 | ||
|
|
01e4179555 | ||
|
|
06f503b5df | ||
|
|
e2f3dad7b8 | ||
|
|
377f31085c | ||
|
|
ec13d195f8 | ||
|
|
c01aed8d90 | ||
|
|
ad7b8a9bfa | ||
|
|
5bba1ed208 | ||
|
|
fe94e14bcc | ||
|
|
b0af479ab9 | ||
|
|
24ff369f29 | ||
|
|
979c9a7094 | ||
|
|
7b90ac52c1 | ||
|
|
ecfbda78bc | ||
|
|
9ba7470815 | ||
|
|
6394467cc7 | ||
|
|
f6d72fa79f | ||
|
|
32ed5f1c8e | ||
|
|
5026da5773 | ||
|
|
ef130e4438 | ||
|
|
4fbd52c2d5 | ||
|
|
8f29b70c1e | ||
|
|
9a4dd3ea9d | ||
|
|
fcd3bb6918 | ||
|
|
9f69fd8750 | ||
|
|
ea7e47d113 | ||
|
|
294bb26996 | ||
|
|
4b2e9dba51 | ||
|
|
1d9dcde99b | ||
|
|
32bf448725 | ||
|
|
732d5d6db9 | ||
|
|
3b325106da | ||
|
|
3aeca37c5d | ||
|
|
4253515736 | ||
|
|
e365d57063 | ||
|
|
df6df20969 | ||
|
|
4e5a85dda5 | ||
|
|
bad603454b | ||
|
|
7b006a47ba | ||
|
|
11da8b82e8 | ||
|
|
383a5f11bc | ||
|
|
76ab5f12c5 | ||
|
|
be74987084 | ||
|
|
8f6c305d14 | ||
|
|
e29b9655eb | ||
|
|
ae7fa9ea82 | ||
|
|
fee9030337 | ||
|
|
f48d057c47 | ||
|
|
f14573307c | ||
|
|
560ba8c0b8 | ||
|
|
4b2376c4fd | ||
|
|
76faed3818 | ||
|
|
62657d9fda | ||
|
|
5877308a49 | ||
|
|
24dcbe7d43 | ||
|
|
7649fe0a0e | ||
|
|
b3b334da77 | ||
|
|
03a55da260 | ||
|
|
1a9eadf8e6 | ||
|
|
7b3fb2a35a | ||
|
|
a55ea29919 | ||
|
|
264b689912 | ||
|
|
684cf82f89 | ||
|
|
3f0e0a319a | ||
|
|
0b4d9c72a7 | ||
|
|
ff71f6bcd9 | ||
|
|
7a5c5baad1 | ||
|
|
a18976d0b5 | ||
|
|
6d836ea49c | ||
|
|
2e97311147 | ||
|
|
57bc564b2c | ||
|
|
1295f1e31f | ||
|
|
4916ed0efb | ||
|
|
f15f99cb27 | ||
|
|
93365d3b20 | ||
|
|
c756ab021d | ||
|
|
34528dd544 | ||
|
|
9380209afb | ||
|
|
be2895ac6f | ||
|
|
e26d4642b8 | ||
|
|
f470972bd4 | ||
|
|
443378c041 | ||
|
|
e20dbe34a4 | ||
|
|
86bde47a06 | ||
|
|
e273c777c7 | ||
|
|
17845c6b25 | ||
|
|
27827ce16a | ||
|
|
b444ecc6af | ||
|
|
34995350ee | ||
|
|
73ceee52f8 | ||
|
|
85a3ba0eed | ||
|
|
86cce76e9d | ||
|
|
3358fd8e91 | ||
|
|
120965f823 | ||
|
|
e70ee9a5b6 | ||
|
|
a2d8e84e83 | ||
|
|
4a3648a693 | ||
|
|
baad45e638 | ||
|
|
d9cb00aab2 | ||
|
|
d703d98836 | ||
|
|
2f0646e7f0 | ||
|
|
1a8a6dcef7 | ||
|
|
990f961126 | ||
|
|
06f04dea19 | ||
|
|
8eced2ef1f | ||
|
|
1e486ea92e | ||
|
|
b47f38675e | ||
|
|
864f3393a0 | ||
|
|
cebef74326 | ||
|
|
e257b35cac | ||
|
|
1f33991e4b | ||
|
|
794053f212 | ||
|
|
3a130e1f74 | ||
|
|
3423f93230 | ||
|
|
2219167253 | ||
|
|
a0a32b89a6 | ||
|
|
59162bf426 | ||
|
|
dfd148f55f | ||
|
|
3af720b3bc | ||
|
|
11240d0837 | ||
|
|
e64fd9c544 | ||
|
|
50ef812427 | ||
|
|
bd4d2fa424 | ||
|
|
e2ee928017 | ||
|
|
62e71a15a4 | ||
|
|
c62127e9f1 | ||
|
|
2171d579ee | ||
|
|
6e5a969e2d | ||
|
|
bfbc7ef28a | ||
|
|
b1cefbf9b5 | ||
|
|
201638854e | ||
|
|
847ecdeedb | ||
|
|
acc159fa60 | ||
|
|
bb7e80a8a6 | ||
|
|
39973f1bb1 | ||
|
|
1e9151364a | ||
|
|
fd50d6e9af | ||
|
|
427acf0c46 | ||
|
|
f0a50424be | ||
|
|
aded9afc0e | ||
|
|
060b7480db | ||
|
|
7f2a01dcd6 | ||
|
|
fef0e70c9f | ||
|
|
9cc112aa4e | ||
|
|
44d4d41365 | ||
|
|
a21c386dbf | ||
|
|
1c4139906a | ||
|
|
1a21f45c75 | ||
|
|
0061b75200 | ||
|
|
420c93a99e | ||
|
|
93f1183cd7 | ||
|
|
b8fcc1fed2 | ||
|
|
2b91be1905 | ||
|
|
7c9ef96ef8 | ||
|
|
37b4b69199 | ||
|
|
fc18e6f8df | ||
|
|
4793a35e0b | ||
|
|
4599da3ce1 | ||
|
|
dec4e41fdd | ||
|
|
780ece0c25 | ||
|
|
aac8bfc398 | ||
|
|
1a06a18336 | ||
|
|
2d4f963d65 | ||
|
|
b54fe08201 | ||
|
|
d1d0300491 | ||
|
|
7fff06f07b | ||
|
|
3f9351042d | ||
|
|
9e01dbab0f | ||
|
|
d4a4b02cf6 | ||
|
|
1f2c7a6671 | ||
|
|
5a7b88c16c | ||
|
|
93351476e4 | ||
|
|
e1bfa95a63 | ||
|
|
7030cc08e7 | ||
|
|
a1da9812a5 | ||
|
|
8ebc0f529c | ||
|
|
e0d47649bc | ||
|
|
524d503860 | ||
|
|
cffafa8e9f | ||
|
|
0fda919268 | ||
|
|
7d98c34e17 | ||
|
|
93147e787b | ||
|
|
80435bae7e | ||
|
|
b367e5c197 | ||
|
|
5336c71da5 | ||
|
|
27f6db976d | ||
|
|
8223d61fa7 | ||
|
|
3eef12bd8f | ||
|
|
9e70a6c499 | ||
|
|
fec3a87421 | ||
|
|
59aac32eb9 | ||
|
|
5ef3917769 | ||
|
|
2f767d96d9 | ||
|
|
de24fdfdc2 | ||
|
|
3bb6a68c9d | ||
|
|
f2406eb2f3 | ||
|
|
4923ed7da0 | ||
|
|
82056355f6 | ||
|
|
f3bd2a295f | ||
|
|
cc96760839 | ||
|
|
ae95943f69 | ||
|
|
d3067f939e | ||
|
|
b6addd304c | ||
|
|
d1ae6e8d58 | ||
|
|
4445c2dab2 | ||
|
|
fcc1564a62 | ||
|
|
615eeb7144 | ||
|
|
855bb118b5 | ||
|
|
9f1eb3600a | ||
|
|
fb885d89c1 | ||
|
|
a846916beb | ||
|
|
a574c4a70a | ||
|
|
1e367f818d | ||
|
|
00599c8f02 | ||
|
|
332a836746 | ||
|
|
a1992acc16 | ||
|
|
c3f002a544 | ||
|
|
c28cbe0a74 | ||
|
|
435daaceed | ||
|
|
e29ab0087b | ||
|
|
aadd5a3312 | ||
|
|
7e354ffad3 | ||
|
|
ee6a071fb6 | ||
|
|
bc8b838953 | ||
|
|
5251d93b3d | ||
|
|
84f0dbecfe | ||
|
|
bba0c8b2cc | ||
|
|
2f90be8bd2 | ||
|
|
cb6b6296aa | ||
|
|
9d25fdce2a | ||
|
|
12b2732f1a | ||
|
|
8c9ece73ee | ||
|
|
a7db786387 | ||
|
|
e5bf65c9bd | ||
|
|
900e7d3a14 | ||
|
|
f1ff74a926 | ||
|
|
30bc4b837e | ||
|
|
050a4f8b23 | ||
|
|
487103d58f | ||
|
|
eeea69d4c1 | ||
|
|
00360ad418 | ||
|
|
a733253ae5 | ||
|
|
9788ee042b | ||
|
|
e9c9ea3bba | ||
|
|
312dfb989d | ||
|
|
75deafe5b1 | ||
|
|
4ca257a389 | ||
|
|
03375a78f2 | ||
|
|
423c7066d7 | ||
|
|
5cd5cc71a8 | ||
|
|
45d4d22055 | ||
|
|
916a92aa0d | ||
|
|
d1ebbcb35d | ||
|
|
2743d998a8 | ||
|
|
dbbfbaff9f | ||
|
|
0be8439cf6 | ||
|
|
66982c5524 | ||
|
|
85af8547f7 | ||
|
|
e26977ab2c | ||
|
|
ec1cc783a6 | ||
|
|
03b00ec045 | ||
|
|
5e90156e9e | ||
|
|
052206efa1 | ||
|
|
305d73180b | ||
|
|
80000bf0fd | ||
|
|
06ebe756e8 | ||
|
|
5fa3d9f19c | ||
|
|
5b4c6d3665 | ||
|
|
77bd0f17d1 | ||
|
|
03a702cfbd | ||
|
|
a932cd2ec1 | ||
|
|
8e5743380a | ||
|
|
8001eb0368 | ||
|
|
f214dc88fc | ||
|
|
5cff5ab135 | ||
|
|
82ba154b64 | ||
|
|
4ea44bbd2b | ||
|
|
a5e68a8725 | ||
|
|
70291014d1 | ||
|
|
1aabcfc30c | ||
|
|
aba80e2b1c | ||
|
|
be683fbcd3 | ||
|
|
2bcf09cfa5 | ||
|
|
697325af63 | ||
|
|
c21bd77be5 | ||
|
|
d5430adaaa | ||
|
|
9e99a0d3f5 | ||
|
|
d088ab6f43 | ||
|
|
820d510c12 | ||
|
|
676847fcd0 | ||
|
|
0204630ee6 | ||
|
|
b515c7eda4 | ||
|
|
73fcecac76 | ||
|
|
a7b82ebcb5 | ||
|
|
f8598b010d | ||
|
|
93779bcc4b | ||
|
|
938f5b9dd9 | ||
|
|
3b4d9f49d5 | ||
|
|
171c93af50 | ||
|
|
6f81e40106 | ||
|
|
e19b5cb2ce | ||
|
|
2c69faca58 | ||
|
|
9272151d0a | ||
|
|
d45ebf5a43 | ||
|
|
8074be7644 | ||
|
|
c99ac99a99 | ||
|
|
976e2450ec | ||
|
|
7e4db8fafd | ||
|
|
115a409d92 | ||
|
|
c203ab3d16 | ||
|
|
5dff96496d | ||
|
|
f813935011 | ||
|
|
2be719449f | ||
|
|
2094c870d5 | ||
|
|
4fe93ae8b8 | ||
|
|
fff1103cf4 | ||
|
|
8cede43a45 | ||
|
|
9b1fa3a5af | ||
|
|
409e73c074 | ||
|
|
c893729d62 | ||
|
|
945466968c | ||
|
|
54f080b755 | ||
|
|
bfad14d552 | ||
|
|
2972e1596d | ||
|
|
987d2aae88 | ||
|
|
4707d34fad | ||
|
|
2ffc09d097 | ||
|
|
afa8d6bb8f | ||
|
|
a37ead98e8 | ||
|
|
c73cd8d618 | ||
|
|
800a3aa61e | ||
|
|
ebd815be75 | ||
|
|
ef669acf89 | ||
|
|
ac6426eab1 | ||
|
|
b107b745f2 | ||
|
|
3d851a448f | ||
|
|
ce133f01aa | ||
|
|
492d378537 | ||
|
|
7ece484423 | ||
|
|
be5ad63e21 | ||
|
|
bdac8f8db8 | ||
|
|
bb893e70c5 | ||
|
|
57ec9db532 | ||
|
|
0287481001 | ||
|
|
0167496ecb | ||
|
|
d86cf193a0 | ||
|
|
246cad1108 | ||
|
|
23bf86a8a8 | ||
|
|
6ce4c885b9 | ||
|
|
faf84e483a | ||
|
|
576004c840 | ||
|
|
c93b05c293 | ||
|
|
55c3813fac | ||
|
|
725c6857be | ||
|
|
86767c9ab4 | ||
|
|
46aa631d2b | ||
|
|
7c61a937c9 | ||
|
|
b8d65dcc45 | ||
|
|
b9ab83eaf2 | ||
|
|
8b7b563992 | ||
|
|
b813a878d7 | ||
|
|
54e486c389 | ||
|
|
12d0a3acc1 | ||
|
|
6ad2a13386 | ||
|
|
2a9c401db9 | ||
|
|
ea5a29018f | ||
|
|
c8d0a715e8 | ||
|
|
2cfc6514ab | ||
|
|
1d78bc7206 | ||
|
|
e5577e43f8 | ||
|
|
17c0463906 | ||
|
|
4168772904 | ||
|
|
44f2186749 | ||
|
|
0c918bcc3a | ||
|
|
0a8925dc75 | ||
|
|
a446597597 | ||
|
|
54354a2732 | ||
|
|
d94b8f08ab | ||
|
|
0d8189efeb | ||
|
|
00c886e426 | ||
|
|
551fc35439 | ||
|
|
9ff17c8d9d | ||
|
|
ec37732e99 | ||
|
|
8a414f32a8 | ||
|
|
bac06acb49 | ||
|
|
ae1e3c2a81 | ||
|
|
67940eb0f9 | ||
|
|
007aa8480e | ||
|
|
dedec10c58 | ||
|
|
75219e21be | ||
|
|
10f5964f8e | ||
|
|
a4a64d51c0 | ||
|
|
1014313d88 | ||
|
|
e486bb4c29 | ||
|
|
5c3d9ffb46 | ||
|
|
2e474fd8db | ||
|
|
b2b110ae1f | ||
|
|
68a34e0738 | ||
|
|
38fa575958 | ||
|
|
6cfeefe054 | ||
|
|
8007971a53 | ||
|
|
d66bd30fae | ||
|
|
3fa59b1b12 | ||
|
|
20e7aff393 | ||
|
|
4b7ce87f57 | ||
|
|
2075533468 | ||
|
|
a4ad5c8d11 | ||
|
|
35f2f56757 | ||
|
|
e6f4aa6a2f | ||
|
|
92fc62bb0d | ||
|
|
44b57a59f5 | ||
|
|
97b8e02bf5 | ||
|
|
5df42420cb | ||
|
|
0ede11a1b7 | ||
|
|
7d9c282db9 | ||
|
|
bc0e0813a4 | ||
|
|
f3aebb3001 | ||
|
|
800f966df9 | ||
|
|
e33df4dd8c | ||
|
|
96d9d810fd | ||
|
|
8707a1bc86 | ||
|
|
0c988a5fd4 | ||
|
|
b396ca771d | ||
|
|
a37dfcf961 | ||
|
|
31989740cd | ||
|
|
501191289b | ||
|
|
8971e92d78 | ||
|
|
0c96e79d0d | ||
|
|
0704c0f5e6 | ||
|
|
9cb190ebe7 | ||
|
|
667f84995c | ||
|
|
7a93fae6e4 | ||
|
|
0d6deca15c | ||
|
|
f54d7d46f2 | ||
|
|
8cf00ba5e1 | ||
|
|
ecc9c6bbd9 | ||
|
|
e11199f988 | ||
|
|
e9ed621178 |
@@ -45,8 +45,7 @@ before_build:
|
||||
- CALL "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars32.bat"
|
||||
- SET PATH=%PATH%;c:\qbt\qt5_32\bin;%CACHE_DIR%\jom;
|
||||
# setup project
|
||||
- COPY /Y "%CACHE_DIR%\winconf.pri" "%REPO_DIR%"
|
||||
- COPY /Y "%CACHE_DIR%\winconf-msvc.pri" "%REPO_DIR%"
|
||||
- COPY /Y "%CACHE_DIR%\conf.pri" "%REPO_DIR%"
|
||||
# workarounds
|
||||
- MKLINK /J "c:\qbt\base" "%CACHE_DIR%\base"
|
||||
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -22,6 +22,7 @@ qrc_*.cpp
|
||||
ui_*.h
|
||||
*.moc
|
||||
src/lang/qbittorrent_*.qm
|
||||
src/webui/www/translations/webui_*.qm
|
||||
.DS_Store
|
||||
.qmake.stash
|
||||
src/qbittorrent.app
|
||||
|
||||
79
.travis.yml
79
.travis.yml
@@ -3,7 +3,8 @@ language: cpp
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
osx_image: xcode7.3
|
||||
|
||||
dist: xenial
|
||||
|
||||
env:
|
||||
matrix:
|
||||
@@ -38,11 +39,6 @@ cache:
|
||||
directories:
|
||||
- $HOME/hombebrew_cache
|
||||
|
||||
# opt-in Ubuntu Trusty
|
||||
dist: trusty
|
||||
# container-based builds
|
||||
sudo: false
|
||||
|
||||
addons:
|
||||
coverity_scan:
|
||||
project:
|
||||
@@ -54,34 +50,30 @@ addons:
|
||||
notification_email: sledgehammer999@qbittorrent.org
|
||||
apt:
|
||||
sources:
|
||||
# sources list: https://github.com/travis-ci/apt-source-whitelist/blob/master/ubuntu.json
|
||||
- ubuntu-toolchain-r-test
|
||||
#- boost-latest
|
||||
# sources list: https://github.com/travis-ci/apt-source-safelist/blob/master/ubuntu.json
|
||||
- sourceline: 'ppa:qbittorrent-team/qbittorrent-stable'
|
||||
- sourceline: 'ppa:beineri/opt-qt551-trusty'
|
||||
- sourceline: 'ppa:adrozdoff/cmake'
|
||||
packages:
|
||||
# packages list: https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise
|
||||
# packages list: https://github.com/travis-ci/apt-package-safelist/blob/master/ubuntu-trusty
|
||||
- [autoconf, automake, colormake]
|
||||
- [cmake, ninja-build]
|
||||
- [ninja-build]
|
||||
- libssl-dev
|
||||
- [libboost-dev, libboost-system-dev]
|
||||
- libtorrent-rasterbar-dev
|
||||
- [qt55base, qt55svg, qt55tools]
|
||||
- [gcc-6, g++-6]
|
||||
- [qtbase5-dev, qttools5-dev-tools, libqt5svg5-dev]
|
||||
|
||||
before_install:
|
||||
# only allow specific build for coverity scan, others will stop
|
||||
- if [ "$TRAVIS_BRANCH" = "$coverity_branch" ] && ! [ "$TRAVIS_OS_NAME" = "linux" -a "$lt_branch" = "RC_1_0" -a "$gui" = true -a "$build_system" = "qmake" ]; then exit ; fi
|
||||
|
||||
- shopt -s expand_aliases
|
||||
- alias make="colormake -j3" # Using nprocs/2 sometimes may fail (gcc is killed by system)
|
||||
- alias make="colormake -j2" # Using nprocs/2 sometimes may fail (gcc is killed by system)
|
||||
- qbt_path="$HOME/qbt_install"
|
||||
- |
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
qbtconf="$qbtconf --prefix="$qbt_path" PKG_CONFIG_PATH=/opt/qt55/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
else
|
||||
qbtconf="$qbtconf --prefix="$qbt_path""
|
||||
qbtconf="$qbtconf --prefix="$qbt_path" PKG_CONFIG_PATH=/usr/local/opt/openssl/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
CXXFLAGS="$CXXFLAGS -Wno-unused-local-typedefs -Wno-inconsistent-missing-override"
|
||||
fi
|
||||
|
||||
# options for specific branches
|
||||
@@ -90,14 +82,6 @@ before_install:
|
||||
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
|
||||
# setup virtual display for after_success target
|
||||
if [ "$gui" = true ]; 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 ;
|
||||
|
||||
# Qt 5
|
||||
PATH=/opt/qt55/bin:${PATH}
|
||||
|
||||
if [ "$build_system" = "cmake" ]; then
|
||||
COMPILER_VERSION=6
|
||||
export CXX="${CXX}-${COMPILER_VERSION}" CC="${CC}-${COMPILER_VERSION}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# print settings
|
||||
@@ -121,41 +105,24 @@ install:
|
||||
# dependencies
|
||||
brew update > /dev/null
|
||||
brew outdated "pkg-config" || brew upgrade "pkg-config"
|
||||
brew install colormake ccache zlib qt
|
||||
brew install colormake ccache zlib qt openssl libtorrent-rasterbar
|
||||
PATH="/usr/local/opt/ccache/libexec:$PATH"
|
||||
brew link --force zlib qt
|
||||
|
||||
wget https://builds.shiki.hu/homebrew/version
|
||||
if ! cmp --quiet "version" "$HOME/hombebrew_cache/version" ; then
|
||||
echo "Cached files are different from server. Downloading new ones."
|
||||
# First delete old files
|
||||
rm -r "$HOME/hombebrew_cache"
|
||||
mkdir "$HOME/hombebrew_cache"
|
||||
cp "version" $HOME/hombebrew_cache
|
||||
cd "$HOME/hombebrew_cache"
|
||||
wget https://builds.shiki.hu/homebrew/libtorrent-rasterbar.rb
|
||||
wget https://builds.shiki.hu/homebrew/libtorrent-rasterbar-1.1.7+git20180422.3ede0b9c20+patched-configure.el_capitan.bottle.tar.gz
|
||||
fi
|
||||
|
||||
# Copy custom libtorrent bottle to homebrew's cache so it can find and install it
|
||||
# Also install our custom libtorrent formula by passing the local path to it
|
||||
# These 2 files are restored from Travis' cache.
|
||||
cp "$HOME/hombebrew_cache/libtorrent-rasterbar-1.1.7+git20180422.3ede0b9c20+patched-configure.el_capitan.bottle.tar.gz" "$(brew --cache)"
|
||||
brew install "$HOME/hombebrew_cache/libtorrent-rasterbar.rb"
|
||||
|
||||
if [ "$build_system" = "cmake" ]; then
|
||||
brew outdated cmake || brew upgrade cmake
|
||||
brew install ninja
|
||||
|
||||
ln -s /usr/local/opt/qt/mkspecs /usr/local/mkspecs
|
||||
ln -s /usr/local/opt/qt/plugins /usr/local/plugins
|
||||
sudo ln -s /usr/local/opt/qt/mkspecs /usr/local/mkspecs
|
||||
sudo ln -s /usr/local/opt/qt/plugins /usr/local/plugins
|
||||
|
||||
MY_CMAKE_OPENSSL_HINT="-DOPENSSL_ROOT_DIR=/usr/local/opt/openssl/"
|
||||
fi
|
||||
|
||||
MY_CMAKE_OPENSSL_HINT="-DOPENSSL_ROOT_DIR=/usr/local/opt/openssl/"
|
||||
fi
|
||||
- |
|
||||
if [ "$TRAVIS_BRANCH" != "$coverity_branch" ]; then
|
||||
export use_ccache=true
|
||||
ccache -M 512M
|
||||
ccache -V && ccache --show-stats && ccache --zero-stats
|
||||
fi
|
||||
|
||||
@@ -166,21 +133,15 @@ script:
|
||||
if [ "$build_system" = "cmake" ]; then
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DGUI=${gui} -DCMAKE_INSTALL_PREFIX="$qbt_path" "$MY_CMAKE_OPENSSL_HINT" \
|
||||
if [ "$gui" = "false" ]; then
|
||||
DISABLE_GUI_OPTION="-DCMAKE_DISABLE_FIND_PACKAGE_Qt5Widgets=ON"
|
||||
fi
|
||||
cmake $DISABLE_GUI_OPTION -DCMAKE_INSTALL_PREFIX="$qbt_path" "$MY_CMAKE_OPENSSL_HINT" \
|
||||
-G "Ninja" -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=TRUE ..
|
||||
BUILD_TOOL="ninja"
|
||||
fi
|
||||
if [ "$build_system" = "qmake" ]; then
|
||||
if [ "$TRAVIS_OS_NAME" = "osx" ]; then
|
||||
# For some reason for RC_1_1 we need to also specify the OpenSSL compiler/linker flags
|
||||
# Homebrew doesn't symlink OpenSSL for security reasons
|
||||
./bootstrap.sh && ./configure $qbtconf CXXFLAGS="$(PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig:$PKG_CONFIG_PATH" pkg-config --cflags openssl)" LDFLAGS="$(PKG_CONFIG_PATH="/usr/local/opt/openssl/lib/pkgconfig:$PKG_CONFIG_PATH" pkg-config --libs openssl)"
|
||||
sed -i "" -e "s/^\(CC.*&&\).*$/\1 $CC/" src/Makefile # workaround for Qt & ccache: https://bugreports.qt.io/browse/QTBUG-31034
|
||||
sed -i "" -e "s/^\(CXX.*&&\).*$/\1 $CXX/" src/Makefile
|
||||
sed -i "" -e 's/^\(CXXFLAGS.*\)$/\1 -Wno-unused-local-typedefs -Wno-inconsistent-missing-override/' src/Makefile
|
||||
else
|
||||
./bootstrap.sh && ./configure $qbtconf
|
||||
fi
|
||||
./bootstrap.sh && ./configure $qbtconf CXXFLAGS="$CXXFLAGS"
|
||||
BUILD_TOOL="make"
|
||||
fi
|
||||
- $BUILD_TOOL && $BUILD_TOOL install
|
||||
|
||||
12
.tx/config
12
.tx/config
@@ -10,10 +10,18 @@ type = QT
|
||||
minimum_perc = 23
|
||||
mode = developer
|
||||
|
||||
|
||||
[qbittorrent.qbittorrentdesktop_master]
|
||||
source_file = src/icons/qBittorrent.desktop
|
||||
source_file = dist/unix/org.qbittorrent.qBittorrent.desktop
|
||||
source_lang = en
|
||||
type = DESKTOP
|
||||
minimum_perc = 23
|
||||
mode = developer
|
||||
|
||||
[qbittorrent.qbittorrent_webui]
|
||||
file_filter = src/webui/www/translations/webui_<lang>.ts
|
||||
lang_map = pt: pt_PT
|
||||
source_file = src/webui/www/translations/webui_en.ts
|
||||
source_lang = en
|
||||
type = QT
|
||||
minimum_perc = 23
|
||||
mode = developer
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
cmake_policy(VERSION 3.5)
|
||||
cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
|
||||
|
||||
message(AUTHOR_WARNING "If the build fails, please try the autotools/qmake method.")
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules)
|
||||
include(FunctionReadVersion)
|
||||
@@ -25,32 +26,29 @@ add_definitions(-DQBT_VERSION_BUILD=${VER_BUILD})
|
||||
add_definitions(-DQBT_VERSION="v${PROJECT_VERSION}")
|
||||
add_definitions(-DQBT_VERSION_2="${PROJECT_VERSION}")
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
include(GNUInstallDirs)
|
||||
endif (UNIX AND NOT APPLE)
|
||||
include(GNUInstallDirs)
|
||||
include(FeatureSummary)
|
||||
|
||||
# version requirements
|
||||
set(requiredBoostVersion 1.35)
|
||||
set(requiredQtVersion 5.5.1)
|
||||
|
||||
if(WIN32)
|
||||
include(winconf)
|
||||
endif(WIN32)
|
||||
|
||||
# we need options here, because they are used not only in "src" subdir, but in the "dist" dir too
|
||||
include(CMakeDependentOption)
|
||||
|
||||
option(SYSTEM_QTSINGLEAPPLICATION
|
||||
"Use the system qtsingleapplication library or shipped one otherwise")
|
||||
|
||||
option(GUI "Allows to disable GUI for headless running. Disables QtDBus and the GeoIP Database" ON)
|
||||
|
||||
option(WEBUI "Allows to disable the WebUI." ON)
|
||||
|
||||
option(STACKTRACE "Enable stacktrace feature" ON)
|
||||
|
||||
if (UNIX)
|
||||
cmake_dependent_option(SYSTEMD "Install the systemd service file (headless only)" OFF
|
||||
"NOT GUI" OFF)
|
||||
cmake_dependent_option(DBUS "Enable use of QtDBus (GUI only)" ON "GUI" OFF)
|
||||
endif(UNIX)
|
||||
# we need options here, at the top level, because they are used not only in "src" subdir, but in the "dist" dir too
|
||||
include(CompileFeature)
|
||||
|
||||
optional_compile_definitions(COUNTRIES_RESOLUTION FEATURE DESCRIPTION "Enable resolving peers IP addresses to countries"
|
||||
DEFAULT ON DISABLED DISABLE_COUNTRIES_RESOLUTION)
|
||||
optional_compile_definitions(STACKTRACE FEATURE DESCRIPTION "Enable stacktraces"
|
||||
DEFAULT ON ENABLED STACKTRACE)
|
||||
optional_compile_definitions(WEBUI FEATURE DESCRIPTION "Enables built-in HTTP server for headless use"
|
||||
DEFAULT ON DISABLED DISABLE_WEBUI)
|
||||
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(dist)
|
||||
|
||||
feature_summary(DESCRIPTION "\nConfiguration results:" WHAT ALL)
|
||||
|
||||
@@ -6,6 +6,31 @@ For programming languages other than C++ (e.g. JavaScript) used in this reposito
|
||||
**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.
|
||||
|
||||
### Table Of Contents
|
||||
|
||||
* [1. New lines & curly braces](#1-new-lines--curly-braces)
|
||||
* [a. Function blocks, class/struct definitions, namespaces](#a-function-blocks-classstruct-definitions-namespaces)
|
||||
* [b. Other code blocks](#b-other-code-blocks)
|
||||
* [c. Blocks in switch's case labels](#c-blocks-in-switchs-case-labels)
|
||||
* [d. If-else statements](#d-if-else-statements)
|
||||
* [e. Single statement if blocks](#e-single-statement-if-blocks)
|
||||
* [f. Acceptable conditions to omit braces](#f-acceptable-conditions-to-omit-braces)
|
||||
* [g. Brace enclosed initializers](#g-brace-enclosed-initializers)
|
||||
* [2. Indentation](#2-indentation)
|
||||
* [3. File encoding and line endings](#3-file-encoding-and-line-endings)
|
||||
* [4. Initialization lists](#4-initialization-lists)
|
||||
* [5. Enums](#5-enums)
|
||||
* [6. Names](#6-names)
|
||||
* [a. Type names and namespaces](#a-type-names-and-namespaces)
|
||||
* [b. Variable names](#b-variable-names)
|
||||
* [c. Private member variable names](#c-private-member-variable-names)
|
||||
* [7. Header inclusion order](#7-header-inclusion-order)
|
||||
* [8. Include guard](#8-include-guard)
|
||||
* [9. Misc](#9-misc)
|
||||
* [10. Git commit message](#10-git-commit-message)
|
||||
* [11. Not covered above](#11-not-covered-above)
|
||||
---
|
||||
|
||||
### 1. New lines & curly braces ###
|
||||
|
||||
#### a. Function blocks, class/struct definitions, namespaces ####
|
||||
@@ -165,11 +190,11 @@ QVariantMap map {{"key1", 5}, {"key2", 10}};
|
||||
### 2. Indentation ###
|
||||
4 spaces.
|
||||
|
||||
### 3. File encoding and line endings. ###
|
||||
### 3. File encoding and line endings ###
|
||||
|
||||
UTF-8 and Unix-like line ending (LF). Unless some platform specific files need other encodings/line endings.
|
||||
|
||||
### 4. Initialization lists. ###
|
||||
### 4. Initialization lists ###
|
||||
Initialization lists should be vertical. This will allow for more easily readable diffs. The initialization colon should be indented and in its own line along with first argument. The rest of the arguments should be indented too and have the comma prepended.
|
||||
```c++
|
||||
myClass::myClass(int a, int b, int c, int d)
|
||||
@@ -182,7 +207,7 @@ myClass::myClass(int a, int b, int c, int d)
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Enums. ###
|
||||
### 5. Enums ###
|
||||
Enums should be vertical. This will allow for more easily readable diffs. The members should be indented.
|
||||
```c++
|
||||
enum Days
|
||||
@@ -197,7 +222,7 @@ enum Days
|
||||
};
|
||||
```
|
||||
|
||||
### 6. Names. ###
|
||||
### 6. Names ###
|
||||
All names should be camelCased.
|
||||
|
||||
#### a. Type names and namespaces ####
|
||||
@@ -231,7 +256,7 @@ class MyClass
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Header inclusion order. ###
|
||||
### 7. Header inclusion order ###
|
||||
The headers should be placed in the following group order:
|
||||
1. Module header (in .cpp)
|
||||
2. C++ Standard Library headers
|
||||
@@ -239,11 +264,11 @@ The headers should be placed in the following group order:
|
||||
4. Boost library headers
|
||||
5. Libtorrent headers
|
||||
6. Qt headers
|
||||
7. qBittorrent own headers, starting from *base* headers.
|
||||
7. qBittorrent's own headers, starting from the *base* headers.
|
||||
|
||||
The headers should be ordered alphabetically within each group.
|
||||
If there are conditionals for the same header group, then put them at the bottom of the respective group.
|
||||
If there are conditionals for the different header groups, then put them above of the "qBittorrent own headers" group.
|
||||
If there are conditionals that contain headers from several different header groups, then put them above the "qBittorrent's own headers" group.
|
||||
|
||||
One exception is the header containing the library version (for example, QtGlobal), this particular header isn't constrained by the aforementioned order.
|
||||
|
||||
@@ -285,19 +310,19 @@ Example:
|
||||
#include <QFont>
|
||||
#endif
|
||||
|
||||
// conditional for the different header groups
|
||||
// conditional that contains headers from several different header groups
|
||||
#if LIBTORRENT_VERSION_NUM >= 10100
|
||||
#include <memory>
|
||||
#include <QElapsedTimer>
|
||||
#endif
|
||||
|
||||
// qBittorrent own headers
|
||||
// qBittorrent's own headers
|
||||
#include "base/bittorrent/infohash.h"
|
||||
#include "anothermodule.h"
|
||||
#include "ui_examplewidget.h"
|
||||
```
|
||||
|
||||
### 8. Include guard. ###
|
||||
### 8. Include guard ###
|
||||
`#pragma once` should be used instead of "include guard" in new code:
|
||||
```c++
|
||||
// examplewidget.h
|
||||
@@ -313,7 +338,7 @@ class ExampleWidget : public QWidget
|
||||
|
||||
```
|
||||
|
||||
### 9. Misc. ###
|
||||
### 9. Misc ###
|
||||
|
||||
* Line breaks for long lines with operation:
|
||||
|
||||
|
||||
273
Changelog
273
Changelog
@@ -1,3 +1,276 @@
|
||||
* Thu Oct 31 2019 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.9.1
|
||||
- WINDOWS: Fix a problem with bigger dialogs due to wrong DPI reported by the system (Chocobo1)
|
||||
|
||||
* Sun Oct 27 2019 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.9
|
||||
- BUGFIX: Preserve relative order when moving to top/bottom in queue (Chocobo1)
|
||||
- WINDOWS: Use real physical screen DPI (Chocobo1)
|
||||
- WEBUI: Bump Web API version
|
||||
|
||||
* Mon Sep 23 2019 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.8
|
||||
- BUGFIX: Fix filename validation on non-Windows OS (Chocobo1)
|
||||
- BUGFIX: ScanFolders/FileSystemWatcher now detect magnet files with case insensitivity in filename (Chocobo1)
|
||||
- BUGFIX: Fix failed seeding after creating a torrent and auto-adding it to the session (Chocobo1)
|
||||
|
||||
* Sun Aug 04 2019 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.7
|
||||
- FEATURE: Add 12 hour and 24 hour speed graphs (dzmat)
|
||||
- FEATURE: Change "Add new torrent" dialog to horizontal layout (Evgeny Lensky)
|
||||
- BUGFIX: Fix messed up symbols in log (Chocobo1)
|
||||
- BUGFIX: Fix incomplete file extension not applied for new torrents (Chocobo1)
|
||||
- BUGFIX: Save updated resume data for completed torrents (Vladimir Golovnev (Glassez))
|
||||
- BUGFIX: Fix requested torrent resume data handling (Vladimir Golovnev (Glassez))
|
||||
- BUGFIX: Prevent command injection via "Run external program" function (Chocobo1)
|
||||
- BUGFIX: Avoid race conditions when adding torrent (Vladimir Golovnev (Glassez))
|
||||
- BUGFIX: Fix torrent checking issues (Vladimir Golovnev (Glassez))
|
||||
- BUGFIX: Use proper log message when there are no error (Chocobo1)
|
||||
- BUGFIX: Fix torrent properties not saved for paused torrents (Chocobo1)
|
||||
- BUGFIX: Some improvements on qtsingleapplication code (Chocobo1)
|
||||
- BUGFIX: Remove limits of "Disk cache expiry interval" setting (Chocobo1)
|
||||
- BUGFIX: Remove upper limit of "Disk cache" setting (Chocobo1)
|
||||
- BUGFIX: Fix crash when removing phantom tags (Chocobo1)
|
||||
- BUGFIX: Improve handleFileErrorAlert error message (Chocobo1)
|
||||
- BUGFIX: Fix updated save path not saved for paused torrents (Chocobo1)
|
||||
- BUGFIX: Log save_resume_data_failed_alert (Chocobo1)
|
||||
- BUGFIX: Don't remove parent directories (Chocobo1)
|
||||
- BUGFIX: Properly remove empty leftover folders after rename (Chocobo1)
|
||||
- BUGFIX: Focus behavior row in Options dialog (silverqx)
|
||||
- BUGFIX: Fix unable to rename folder on Windows when same is used in different case(Chocobo1)
|
||||
- BUGFIX: Fix unable to control add torrent dialogs when opened simultaneously (Chocobo1)
|
||||
- BUGFIX: Disable "Upload mode" when start preloaded torrent (Vladimir Golovnev (Glassez))
|
||||
- BUGFIX: Fix wrong comparison result when sorting items(Chocobo1)
|
||||
- BUGFIX: Fix sequential downloading when redirected (Vladimir Golovnev (Glassez))
|
||||
- BUGFIX: Fix typos (Chocobo1)
|
||||
- BUGFIX: Fix assertion fail (Chocobo1)
|
||||
- BUGFIX: Change number of time axis divisions from 5 to 6 for convenience (dzmat)
|
||||
- BUGFIX: Don't turn window blank when closed to system tray (Ekin Dursun)
|
||||
- WEBUI: Fix WebUI encoding of special characters (Thomas Piccirello)
|
||||
- WEBUI: Change the speed unit from Bytes/s to KiB/s for the rate limiter(jerrymakesjelly)
|
||||
- WEBUI: Fix '+' char not decoded to space correctly (Chocobo1)
|
||||
- RSS: Ignore RSS articles with non-unique identifiers (Vladimir Golovnev (Glassez))
|
||||
- RSS: Perform more RSS parsing in working thread (Vladimir Golovnev (Glassez))
|
||||
- RSS: Download RSS enclosure element if no proper MIME type is found (Matan Bareket)
|
||||
|
||||
* Sun May 05 2019 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.6
|
||||
- BUGFIX: Force recheck multiple torrents one by one in all possible cases. Closes #9120 (glassez)
|
||||
- BUGFIX: Don't query Google for tracker favicons, for privacy reasons (sledgehammer999)
|
||||
- BUGFIX: Work around the crash occurred in QTimer. Closes #9985 (Chocobo1)
|
||||
- BUGFIX: Increase the .torrent file download size limit to 100 MiB (thalieht)
|
||||
- BUGFIX: Disable downloading tracker favicons by default. Works around reported crashes in Linux. Closes #9667 (Chocobo1)
|
||||
- WEBUI: Separate URL components before percent-decoding. Allow special characters in query string parameters. Closes #9116 (glassez)
|
||||
- WEBUI: Prevent login credential appearing in URL. Closes #10221 (Chocobo1)
|
||||
- WEBUI: Display warning when Javascript is disabled (Chocobo1)
|
||||
- WEBUI: Fix translatable strings (Chocobo1)
|
||||
- WEBUI: Correctly handle '+' sign in x-www-form-urlencoded data. Closes #10451 (Chocobo1)
|
||||
- WEBUI: Remove closed connections immediately. Closes #10487 (Chocobo1)
|
||||
- WEBUI: Fix "Create subfolder" option is not working. Closes ##10392 (Chocobo1)
|
||||
- SEARCH: Make num enter key work the same as return in searchjobwidget (thalieht)
|
||||
- LINUX: Make window title bar icon work in Wayland (Peter Eszlari)
|
||||
- LINUX: Update appdata.xml file (Chocobo1)
|
||||
- MACOS: Fix progress bar drawing by using different style than native (Nick Korotysh)
|
||||
- MACOS: Updated and cleaned up fields in Info.plist (Nick Korotysh)
|
||||
- OTHER: Mention more translators in the about tab. Closes #10043 (sledgehammer999)
|
||||
|
||||
* Mon Dec 24 2018 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.5
|
||||
- FEATURE: Add checking_mem_usage option to AdvancedSettings (FranciscoPombal)
|
||||
- FEATURE: Save torrents queue in separate file. Now a new file named 'queue' is created, saving on each line the infohash of each queued torrent in sorted order. (glassez)
|
||||
- BUGFIX: Fix regression on resuming torrents without metadata (thalieht)
|
||||
- BUGFIX: Reorder and rename Tracker list context menu option (Thomas Piccirello)
|
||||
- BUGFIX: Rename Tracker List columns (Thomas Piccirello)
|
||||
- BUGFIX: Show error message when Session failed to start (glassez)
|
||||
- BUGFIX: Embedded tracker: Use ip parameter from tracker request if provided (Chocobo1)
|
||||
- BUGFIX: Fix weekday names translations (Chocobo1)
|
||||
- BUGFIX: Fix strings not translated (Chocobo1)
|
||||
- WEBUI: Change qBittorrent exit message to HTML5 (Chocobo1)
|
||||
- WEBUI: Revise CSP header (Chocobo1)
|
||||
- WEBUI: Enforce referrer-policy in WebUI (Chocobo1)
|
||||
- WEBUI: Add torrent name filtering to WebUI (Thomas Piccirello)
|
||||
- WEBUI: Send numeric status without translation (Thomas Piccirello)
|
||||
- WEBUI: Add WebUI Trackers context menu (Thomas Piccirello)
|
||||
- WEBUI: Add DHT, PeX, and LSD to WebUI Tracker list (Thomas Piccirello)
|
||||
- WEBUI: Add additional Tracker columns to WebUI (Thomas Piccirello)
|
||||
- WEBUI: Bump Web API version
|
||||
- WEBUI: Fix display bugs in WebUI Files tab. Remove <IE9 support (Thomas Piccirello)
|
||||
- WEBUI: Fix incorrect priority value sent from WebUI (Thomas Piccirello)
|
||||
- WEBUI: Set priority for multiple files in one WebAPI request (Thomas Piccirello)
|
||||
- WEBUI: Match WebUI Peers table column order to GUI (Thomas Piccirello)
|
||||
- WEBUI: Fetch data less frequently when torrents tab isn't visible (Thomas Piccirello)
|
||||
- WEBUI: Add Search tab to WebUI (Thomas Piccirello)
|
||||
- WEBUI: Add ability to pass urls to the webui download page (Thomas Piccirello)
|
||||
- WEBUI: Fix JavaScript error (Tom Piccirello)
|
||||
- WEBUI: Disallow setting a blank alternative WebUI location (Thomas Piccirello)
|
||||
- WEBUI: Add slow torrent options (Thomas Piccirello)
|
||||
- WEBUI: Add "Use alternative Web UI" option (Thomas Piccirello)
|
||||
- WEBUI: Add "Apply rate limit to peers on LAN" option (Thomas Piccirello)
|
||||
- WEBUI: Add email "From" option (Thomas Piccirello)
|
||||
- WEBUI: Set WebUI download options using set preferences (Thomas Piccirello)
|
||||
- WEBUI: Show list of categories on WebUI download page (Thomas Piccirello)
|
||||
- WEBUI: Hide WebUI text input for custom monitor save locations (Thomas Piccirello)
|
||||
- WEBUI: Add "When adding a torrent" options (Thomas Piccirello)
|
||||
- WEBUI: Add WebUI Auto TMM options (Thomas Piccirello)
|
||||
- WEBUI: Add speed limit icons to WebUI Speed options (Thomas Piccirello)
|
||||
- WEBUI: Add WebUI Random port button and proxy unencrypted password notice (Thomas Piccirello)
|
||||
- WEBUI: Replace WebUI Options fixed-width labels (Thomas Piccirello)
|
||||
- WEBUI: Reorder WebUI options to match GUI (Thomas Piccirello)
|
||||
- WEBUI: Allow WebUI sidebar to be collapsed (Thomas Piccirello)
|
||||
- WEBUI: Show ellipsis when WebUI sidebar is too narrow (Thomas Piccirello)
|
||||
- WEBUI: Fix WebUI bug on override of Start Download option.Closes #9855. (Tom Piccirello)
|
||||
- WEBUI: Fix missing words in WebUI (Chocobo1)
|
||||
- WEBUI: Add SameSite attribute to WebUI session cookie (Thomas Piccirello)
|
||||
- WEBUI: Put WebUI security related options into a groupbox (Chocobo1)
|
||||
- WEBUI: Add option for WebUI Host header validation (Chocobo1)
|
||||
- WEBUI: Show icon in WebUI sorted column (Thomas Piccirello)
|
||||
- RSS: Keep track of REPACK/PROPER downloads. Closes #9898. (Stephen Dawkins)
|
||||
- SEARCH: Only instantiate SearchPluginManager as needed (Thomas Piccirello)
|
||||
- MACOS: Make file icon look like other macOS icons (Nick Korotysh)
|
||||
- MACOS: Save option to start minimized in Mac (thalieht)
|
||||
|
||||
* Mon Nov 19 2018 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.4
|
||||
- FEATURE: Recognize *.ts files as previewable (silver)
|
||||
- FEATURE: Allow to disable speed graphs (dzmat)
|
||||
- FEATURE: Clear LineEdit on ESC (silverqx)
|
||||
- BUGFIX: Fix divide-by-zero crash (Chocobo1)
|
||||
- BUGFIX: Remove speed limit checkbox in Options dialog (Chocobo1)
|
||||
- BUGFIX: Fix speed graph "high speeds" bug (dzmat)
|
||||
- BUGFIX: Don't update torrent status unnecessarily (glassez)
|
||||
- BUGFIX: Improve force recheck of paused torrent (glassez)
|
||||
- BUGFIX: Restore torrent in two steps (glassez)
|
||||
- BUGFIX: Improve scaling of speed graphs (dzmat)
|
||||
- BUGFIX: Add isNetworkFileSystem() detection on Windows. This allows network mounts to be monitored correctly by polling timer. (Chocobo1)
|
||||
- BUGFIX: Reduce horizontal graphs resolution. Improves perfomance. (dzmat)
|
||||
- BUGFIX: Don't recheck just checked torrent (mj-p, glassez)
|
||||
- BUGFIX: Add SMB2 magic number (Chocobo1)
|
||||
- BUGFIX: Restore startup perfomance to v4.1.2 times. Needs at least libtorrent 1.1.10 (sledgehammer999)
|
||||
- BUGFIX: Make strings actually translatable (sledgehammer999)
|
||||
- WEBUI: Handle downloading .torrent file as success (Tom Piccirello)
|
||||
- WEBUI: Fix Alternative Web UI to be available (glassez)
|
||||
- WEBUI: Consider empty locale setting as not set (glassez)
|
||||
- WEBUI: Add free disk space to WebUI status bar (Thomas Piccirello)
|
||||
- WEBUI: Add WebUI search API controller (Thomas Piccirello)
|
||||
- WEBUI: Fix WebUI Auto TMM context menu bug (Thomas Piccirello)
|
||||
- WEBUI: Use independent translation for WebUI (glassez)
|
||||
- WEBUI: Add categories WebAPI (Thomas Piccirello)
|
||||
- WEBUI: Fix minor JavaScript defects (Thomas Piccirello)
|
||||
- WEBUI: Add locale to js file path (Thomas Piccirello)
|
||||
- WEBUI: Translate WebUI torrents Status column (Thomas Piccirello)
|
||||
- WEBUI: Bump Web API version
|
||||
- RSS: Allow to disable downloading REPACK/PROPER matches (Stephen Dawkins)
|
||||
- RSS: Improve RSS Feed updating (glassez)
|
||||
- SEARCH: Allow resizing search filter in search job (thalieht)
|
||||
- SEARCH: Improve parser for search engine versions.txt (Chocobo1)
|
||||
- SEARCH: Update Python URLs (Chocobo1)
|
||||
- SEARCH: Fix asking to install Python (Chocobo1)
|
||||
- SEARCH: Reformat python code to be compliant with PEP8 (Chocobo1)
|
||||
- OTHER: cmake: restore out-of-source build (Eugene Shalygin)
|
||||
- OTHER: cmake: cmake: use C++14 when available (Eugene Shalygin)
|
||||
|
||||
* Tue Sep 18 2018 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.3
|
||||
- FEATURE: Preselect name without extension when renaming files (thalieht)
|
||||
- FEATURE: Allow setting seq & first/last from context menu without metadata (thalieht)
|
||||
- BUGFIX: Show "N/A" if there is no scrape (thalieht)
|
||||
- BUGFIX: Save option about tracker favicons under correct key (sledgehammer999)
|
||||
- BUGFIX: When file data are unreachable pause torrent and show "Missing Files" status (temporary fix) (sledgehammer999)
|
||||
- BUGFIX: Don't disable DHT when using force proxy (Thomas Piccirello)
|
||||
- BUGFIX: Correctly save torrent queue position/state/priority changes in fastresume (glassez, thalieht, sledgehammer999)
|
||||
- BUGFIX: Fix icon height/width ratio (Chocobo1)
|
||||
- BUGFIX: Fix values sorted wrong in "Last Activity" column (Chocobo1)
|
||||
- BUGFIX: Replace png icons with svg (Chocobo1)
|
||||
- WEBUI: Allow WebUI sidebar filters to be hidden (Thomas Piccirello)
|
||||
- WEBUI: Increase WebUI Options initial height (Thomas Piccirello)
|
||||
- WEBUI: Adjust WebUI Options form alignment (Thomas Piccirello)
|
||||
- WEBUI: Fix WebUI unreachable issue (Chocobo1)
|
||||
- WEBUI: Require torrent category creation to be explicit (Thomas Piccirello)
|
||||
- WEBUI: Include category save path in web api sync data (Thomas Piccirello)
|
||||
- WEBUI: Add save path and editing to WebUI new category dialog (Thomas Piccirello)
|
||||
- WEBUI: Bump Web API version
|
||||
- SEARCH: Refactor in searchjob to always color visited entries (thalieht)
|
||||
- SEARCH: Set "enter" as shortcut to download the selected torrents in search job (thalieht)
|
||||
- SEARCH: Add regex option in the search filter's context menu (thalieht)
|
||||
- LINUX: Fix GUI scaling issue on Linux (Chocobo1)
|
||||
- LINUX: Fix regression that broke installing desktop file (Eli Schwartz)
|
||||
- OPENBSD: Better filesystem support for filewatcher (Elias M. Mariani)
|
||||
|
||||
* Sun Aug 12 2018 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.2
|
||||
- FEATURE: New options for "inhibit sleep" (Lukas Greib)
|
||||
- FEATURE: Add option for regexps in the transferlist search filter's context menu (thalieht)
|
||||
- FEATURE: Add async io threads option to AdvancedSettings (tjjh89017)
|
||||
- FEATURE: Allow save resume interval to be disabled (Chocobo1)
|
||||
- FEATURE: Add checkbox for recursive download dialog (Chocobo1)
|
||||
- FEATURE: Add changelog link in program updater (Chocobo1)
|
||||
- BUGFIX: Avoid allocating large memory when loading a .torrent file (Couchy)
|
||||
- BUGFIX: Notify users on 1st time close/minimize to tray (sledgehammer999)
|
||||
- BUGFIX: Fix I/O error after fetching magnet metadata (Chocobo1)
|
||||
- BUGFIX: Never save resume data for already paused torrents (glassez)
|
||||
- BUGFIX: Make ProgramUpdater upgrade to 64-bit qbt when running on 64-bit Windows (Chocobo1)
|
||||
- BUGFIX: Put temporary files in qbt own temp folder (Chocobo1)
|
||||
- BUGFIX: Avoid potentially setting the wrong piece priorities (Chocobo1)
|
||||
- BUGFIX: Various code refactorings/improvements (Chocobo1, thalieht, glassez)
|
||||
- BUGFIX: Add options "Download in sequential order" and "Download first and last pieces first" in AddNewTorrentDialog (Chocobo1)
|
||||
- BUGFIX: Download favicon using appropriate protocol (glassez)
|
||||
- BUGFIX: Apply proxy settings on DownloadManager creation (glassez)
|
||||
- BUGFIX: Improve torrent initialization (glassez)
|
||||
- BUGFIX: Save resume data on torrent change events (glassez)
|
||||
- BUGFIX: Increase default resume data save interval (Chocobo1)
|
||||
- BUGFIX: Work around crash when procesing recursive download. Closes #9086 (Chocobo1)
|
||||
- BUGFIX: Reduce queries to python version (Chocobo1)
|
||||
- BUGFIX: Disable certain mouse wheel events in Options dialog (Chocobo1)
|
||||
- WEBUI: Send all rechecks in one request (Thomas Piccirello)
|
||||
- WEBUI: Add WebUI Force Reannounce option (Thomas Piccirello)
|
||||
- WEBUI: Create non-existing path in setLocationAction() (Goshik)
|
||||
- WEBUI: Add WebUI support for Mac ⌘ (Command) key (Thomas Piccirello)
|
||||
- WEBUI: Show current save path in 'Set location' window (Goshik)
|
||||
- WEBUI: Fix WebUI cache behavior for css files (Chocobo1)
|
||||
- WEBUI: Send Cache-Control header in WebUI responses (Chocobo1)
|
||||
- WEBUI: Add form-action to CSP (Thomas Piccirello)
|
||||
- WEBUI: Add upgrade-insecure-requests to CSP when HTTPS is enabled (Thomas Piccirello)
|
||||
- WEBUI: Reset WebUI ban counter on login success (Chocobo1)
|
||||
- WEBUI: Add logging messages in WebUI login action (Chocobo1)
|
||||
- WEBUI: Add option to control CSRF protection (Chocobo1)
|
||||
- WEBUI: Add option to control WebUI clickjacking protection (Chocobo1)
|
||||
- RSS: Implement "Sequential downloading" feature. Closes #6835 (glassez)
|
||||
- RSS: Don't use RSS feed URLs as base for file names. Closes #8399 (glassez)
|
||||
- SEARCH: Add a name filter for search results (thalieht)
|
||||
- SEARCH: Fix python version detection (Chocobo1)
|
||||
- SEARCH: Clear python cache conditionally (Chocobo1)
|
||||
- SEARCH: Properly normalize version string before parsing it (hannsen)
|
||||
- WINDOWS: Turn on Control Flow Guard for MSVC builds (Chocobo1)
|
||||
- MACOS: Replace deprecated function IOPMAssertionCreate() on macOS (Chocobo1)
|
||||
- OTHER: Fix CMake build with QtSingleApplication. Fixes #9196 (Eugene Shalygin)
|
||||
|
||||
* Sun May 27 2018 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.1
|
||||
- FEATURE: Add 'Moving' state for torrents being relocated/moved (sledgehammer999)
|
||||
- FEATURE: Show rechecking progress (sledgehammer999)
|
||||
- FEATURE: Add option to remember last used save path (glassez)
|
||||
- FEATURE: Torrent name is also renamed if the content was renamed in the "Add New Torrent" dialog (glassez)
|
||||
- FEATURE: Relax behavior of "Download first and last piece first". It applies to all files and not only to the previewable. (Chocobo1)
|
||||
- BUGFIX: Fix issues with translatable strings (Chocobo1)
|
||||
- BUGFIX: Fix displayed tracker messages (Chocobo1)
|
||||
- BUGFIX: Make settings file recovery more robust (Chocobo1)
|
||||
- BUGFIX: Retry saving settings when operation failed (Chocobo1)
|
||||
- BUGFIX: Log successful torrent move (sledgehammer999)
|
||||
- BUGFIX: Fix deletion of old logs (sledgehammer999)
|
||||
- BUGFIX: Delete non-commited fastresume files (sledgehammer999)
|
||||
- BUGFIX: Don't migrate torrents that have newer fastresumes (sledgehammer999)
|
||||
- BUGFIX: Fix adding multiple torrents at once from WebUI (glassez)
|
||||
- BUGFIX: Improve "Run External Program" behavior. On Windows, a backslash isn't appended to paths from path variables (Chocobo1)
|
||||
- BUGFIX: Suppress multiple I/O errors for the same torrent (sledgehammer999)
|
||||
- BUGFIX: Replace raster qbt logo with vector version (Chocobo1)
|
||||
- WEBUI: Fix wrong API method names (glassez)
|
||||
- WEBUI: Filter torrent info endpoint by hashes (Marcel Petersen)
|
||||
- WEBUI: Fix invalid API calls in WebUI (glassez)
|
||||
- WEBUI: Improve legacy API params handling (glassez)
|
||||
- WEBUI: Fix params handling for some legacy API methods (glassez)
|
||||
- WEBUI: Apply locale changes immediately in WebUI (Chocobo1)
|
||||
- WEBUI: Use 32px icons for favicon (Chocobo1)
|
||||
- WEBUI/RSS: Properly set RSS settings via API (glassez)
|
||||
- RSS: Fix auto-downloading rule when Smart filter with regular Episode filter are used (glassez)
|
||||
- RSS: Make "Ignoring days" to behave like other filters (glassez)
|
||||
- RSS: Place "Use Smart Episode Filter" more correctly (glassez)
|
||||
- RSS: Use RSS feed update time as a fallback (glassez)
|
||||
- COSMETIC: Fix Stats dialog size (sledgehammer999)
|
||||
- MACOS: Fix GUI scaling factor on macOS (Chocobo1)
|
||||
- WINDOWS: Update icons (adem4ik)
|
||||
- LINUX: Fix open destination folder with Nautilus > 3.28 (Evgeny Lensky)
|
||||
- OTHER: Code improvements and refactoring (thalieht, Nick Korotysh, Chocobo1)
|
||||
|
||||
* Sat May 05 2018 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v4.1.0
|
||||
- FEATURE: Add "Coalesce reads & writes" checkbox in advanced options (Chocobo1)
|
||||
- FEATURE: Smart Filter for RSS (Stephen Dawkins)
|
||||
|
||||
49
INSTALL
49
INSTALL
@@ -1,54 +1,49 @@
|
||||
qBittorrent - A BitTorrent client in C++ / Qt4
|
||||
qBittorrent - A BitTorrent client in C++ / Qt
|
||||
------------------------------------------
|
||||
|
||||
1) Compile and install qBittorrent with Qt4 Graphical Interface
|
||||
1) Compile and install qBittorrent with Qt graphical interface
|
||||
|
||||
$ ./configure
|
||||
$ make && make install
|
||||
$ qbittorrent
|
||||
|
||||
will install and execute qBittorrent hopefully without any problems.
|
||||
will install and execute qBittorrent.
|
||||
|
||||
Dependencies:
|
||||
- Qt >= 4.6.0 (libqtgui, libqtcore, libqtnetwork, libqtxml, libqtdbus/optional)
|
||||
- Qt >= 5.5.1
|
||||
|
||||
- pkg-config executable
|
||||
- pkg-config
|
||||
|
||||
- libtorrent-rasterbar by Arvid Norberg (>= 1.0.6)
|
||||
-> http://www.libtorrent.net
|
||||
Be careful: another library (the one used by rTorrent) uses a similar name.
|
||||
- libtorrent-rasterbar >= 1.0.6 (by Arvid Norberg)
|
||||
* https://www.libtorrent.org/
|
||||
* Be careful: another library (the one used by rTorrent) uses a similar name
|
||||
|
||||
- libboost >= 1.35.x (libboost-system)
|
||||
- Boost >= 1.35
|
||||
|
||||
- python >= 2.3 (needed by search engine)
|
||||
* Run time only dependency
|
||||
- Python >= 2.7.9 / 3.3.0 (optional, runtime only)
|
||||
* Required by the internal search engine
|
||||
|
||||
- geoip-database (optional)
|
||||
* If qBittorrent cannot find this database, it will try to resolve countries using the Internet but it will be a lot slower.
|
||||
* Run time only dependency
|
||||
|
||||
2) Compile and install qBittorrent without Qt4 Graphical interface
|
||||
2) Compile and install qBittorrent without Qt graphical interface
|
||||
|
||||
$ ./configure --disable-gui
|
||||
$ make && make install
|
||||
$ qbittorrent
|
||||
$ qbittorrent-nox
|
||||
|
||||
will install and execute qBittorrent hopefully without any problems.
|
||||
will install and execute qBittorrent.
|
||||
|
||||
Dependencies:
|
||||
- Qt >= 4.4.0 (libqt-devel, libqtcore, libqtnetwork)
|
||||
- Qt >= 5.5.1
|
||||
|
||||
- pkg-config executable
|
||||
- pkg-config
|
||||
|
||||
- libtorrent-rasterbar by Arvid Norberg (>= v1.0.6)
|
||||
-> http://www.libtorrent.net
|
||||
Be careful: another library (the one used by rTorrent) uses a similar name.
|
||||
|
||||
- libboost: libboost-filesystem, libboost-date-time, libboost-thread, libboost-serialization
|
||||
- libtorrent-rasterbar >= 1.0.6 (by Arvid Norberg)
|
||||
* https://www.libtorrent.org/
|
||||
* Be careful: another library (the one used by rTorrent) uses a similar name
|
||||
|
||||
- Boost >= 1.35
|
||||
|
||||
DOCUMENTATION:
|
||||
Please note that there is a documentation with a "compiling howto" at http://wiki.qbittorrent.org.
|
||||
Please note that there is a "Compilation" section at http://wiki.qbittorrent.org.
|
||||
|
||||
------------------------------------------
|
||||
Christophe Dumez <chris@qbittorrent.org>
|
||||
sledgehammer999 <sledgehammer999@qbittorrent.org>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand '-c -o'.
|
||||
|
||||
scriptversion=2012-10-14.11; # UTC
|
||||
scriptversion=2018-03-07.03; # UTC
|
||||
|
||||
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1999-2018 Free Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
@@ -17,7 +17,7 @@ scriptversion=2012-10-14.11; # UTC
|
||||
# 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, see <http://www.gnu.org/licenses/>.
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
@@ -255,7 +255,8 @@ EOF
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
|
||||
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \
|
||||
icl | *[/\\]icl | icl.exe | *[/\\]icl.exe )
|
||||
func_cl_wrapper "$@" # Doesn't return...
|
||||
;;
|
||||
esac
|
||||
@@ -339,9 +340,9 @@ exit $ret
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
|
||||
966
build-aux/config.guess
vendored
966
build-aux/config.guess
vendored
File diff suppressed because it is too large
Load Diff
2770
build-aux/config.sub
vendored
2770
build-aux/config.sub
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2013-12-25.23; # UTC
|
||||
scriptversion=2018-03-11.20; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
@@ -271,15 +271,18 @@ do
|
||||
fi
|
||||
dst=$dst_arg
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
# If destination is a directory, append the input filename.
|
||||
if test -d "$dst"; then
|
||||
if test "$is_target_a_directory" = never; then
|
||||
echo "$0: $dst_arg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dst=$dstdir/`basename "$src"`
|
||||
dstbase=`basename "$src"`
|
||||
case $dst in
|
||||
*/) dst=$dst$dstbase;;
|
||||
*) dst=$dst/$dstbase;;
|
||||
esac
|
||||
dstdir_status=0
|
||||
else
|
||||
dstdir=`dirname "$dst"`
|
||||
@@ -288,6 +291,11 @@ do
|
||||
fi
|
||||
fi
|
||||
|
||||
case $dstdir in
|
||||
*/) dstdirslash=$dstdir;;
|
||||
*) dstdirslash=$dstdir/;;
|
||||
esac
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
@@ -324,34 +332,43 @@ do
|
||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||
;;
|
||||
*)
|
||||
# Note that $RANDOM variable is not portable (e.g. dash); Use it
|
||||
# here however when possible just to lower collision chance.
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
# Because "mkdir -p" follows existing symlinks and we likely work
|
||||
# directly in world-writeable /tmp, make sure that the '$tmpdir'
|
||||
# directory is successfully created first before we actually test
|
||||
# 'mkdir -p' feature.
|
||||
if (umask $mkdir_umask &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
|
||||
$mkdirprog $mkdir_mode "$tmpdir" &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
ls_ld_tmpdir=`ls -ld "$tmpdir"`
|
||||
test_tmpdir="$tmpdir/a"
|
||||
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
|
||||
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/d" "$tmpdir"
|
||||
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
|
||||
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac;;
|
||||
@@ -427,8 +444,8 @@ do
|
||||
else
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
dsttmp=${dstdirslash}_inst.$$_
|
||||
rmtmp=${dstdirslash}_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
@@ -493,9 +510,9 @@ do
|
||||
done
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#! /bin/sh
|
||||
# Common wrapper for a few potentially missing GNU programs.
|
||||
|
||||
scriptversion=2013-10-28.13; # UTC
|
||||
scriptversion=2018-03-07.03; # UTC
|
||||
|
||||
# Copyright (C) 1996-2014 Free Software Foundation, Inc.
|
||||
# Copyright (C) 1996-2018 Free Software Foundation, Inc.
|
||||
# Originally written by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
@@ -17,7 +17,7 @@ scriptversion=2013-10-28.13; # UTC
|
||||
# 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, see <http://www.gnu.org/licenses/>.
|
||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
@@ -101,9 +101,9 @@ else
|
||||
exit $st
|
||||
fi
|
||||
|
||||
perl_URL=http://www.perl.org/
|
||||
flex_URL=http://flex.sourceforge.net/
|
||||
gnu_software_URL=http://www.gnu.org/software
|
||||
perl_URL=https://www.perl.org/
|
||||
flex_URL=https://github.com/westes/flex
|
||||
gnu_software_URL=https://www.gnu.org/software
|
||||
|
||||
program_details ()
|
||||
{
|
||||
@@ -207,9 +207,9 @@ give_advice "$1" | sed -e '1s/^/WARNING: /' \
|
||||
exit $st
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# eval: (add-hook 'before-save-hook 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
||||
|
||||
22
cmake/Modules/CompileFeature.cmake
Normal file
22
cmake/Modules/CompileFeature.cmake
Normal file
@@ -0,0 +1,22 @@
|
||||
# Helper function for coupling add_feature_info(), option(), and add_definitions()
|
||||
|
||||
function(optional_compile_definitions _name)
|
||||
set(options FEATURE)
|
||||
set(oneValueArgs DESCRIPTION DEFAULT)
|
||||
set(multiValueArgs ENABLED DISABLED)
|
||||
cmake_parse_arguments(OCD "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
option(${_name} "${OCD_DESCRIPTION}" ${OCD_DEFAULT})
|
||||
if (${${_name}})
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY COMPILE_DEFINITIONS ${OCD_ENABLED})
|
||||
else()
|
||||
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY COMPILE_DEFINITIONS ${OCD_DISABLED})
|
||||
endif()
|
||||
if(${OCD_FEATURE})
|
||||
add_feature_info(${_name} ${_name} "${OCD_DESCRIPTION}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
macro(feature_option _name _description _default)
|
||||
option(${_name} "${_description}" ${_default})
|
||||
add_feature_info(${_name} ${_name} "${_description}")
|
||||
endmacro()
|
||||
@@ -99,6 +99,7 @@ list(FIND LibtorrentRasterbar_DEFINITIONS -DTORRENT_USE_OPENSSL LibtorrentRaster
|
||||
if(LibtorrentRasterbar_ENCRYPTION_INDEX GREATER -1)
|
||||
find_package(OpenSSL REQUIRED)
|
||||
set(LibtorrentRasterbar_LIBRARIES ${LibtorrentRasterbar_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto)
|
||||
list(APPEND LibtorrentRasterbar_INCLUDE_DIRS "${OPENSSL_INCLUDE_DIR}")
|
||||
set(LibtorrentRasterbar_OPENSSL_ENABLED ON)
|
||||
endif()
|
||||
|
||||
@@ -113,10 +114,10 @@ mark_as_advanced(LibtorrentRasterbar_INCLUDE_DIR LibtorrentRasterbar_LIBRARY
|
||||
LibtorrentRasterbar_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES
|
||||
LibtorrentRasterbar_ENCRYPTION_INDEX)
|
||||
|
||||
if (LibtorrentRasterbar_FOUND AND NOT TARGET LibtorrentRasterbar::LibTorrent)
|
||||
add_library(LibtorrentRasterbar::LibTorrent UNKNOWN IMPORTED)
|
||||
if (LibtorrentRasterbar_FOUND AND NOT TARGET LibtorrentRasterbar::torrent-rasterbar)
|
||||
add_library(LibtorrentRasterbar::torrent-rasterbar UNKNOWN IMPORTED)
|
||||
|
||||
set_target_properties(LibtorrentRasterbar::LibTorrent PROPERTIES
|
||||
set_target_properties(LibtorrentRasterbar::torrent-rasterbar PROPERTIES
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
|
||||
IMPORTED_LOCATION "${LibtorrentRasterbar_LIBRARY}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${LibtorrentRasterbar_INCLUDE_DIRS}"
|
||||
|
||||
@@ -1,94 +1,79 @@
|
||||
# - Try to find the QtSingleApplication includes and library
|
||||
# which defines
|
||||
#
|
||||
# QTSINGLEAPPLICATION_FOUND - system has QtSingleApplication
|
||||
# QTSINGLEAPPLICATION_INCLUDE_DIR - where to find header QtSingleApplication
|
||||
# QTSINGLEAPPLICATION_LIBRARIES - the libraries to link against to use QtSingleApplication
|
||||
# QTSINGLEAPPLICATION_LIBRARY - where to find the QtSingleApplication library (not for general use)
|
||||
# QtSingleApplication_FOUND - system has QtSingleApplication
|
||||
# QtSingleApplication_INCLUDE_DIR - where to find header QtSingleApplication
|
||||
# QtSingleApplication_LIBRARIES - the libraries to link against to use QtSingleApplication
|
||||
# QtSingleApplication_LIBRARY - where to find the QtSingleApplication library (not for general use)
|
||||
|
||||
# copyright (c) 2013 TI_Eugene ti.eugene@gmail.com
|
||||
#
|
||||
# Redistribution and use is allowed according to the terms of the FreeBSD license.
|
||||
|
||||
SET(QTSINGLEAPPLICATION_FOUND FALSE)
|
||||
SET(QtSingleApplication_FOUND FALSE)
|
||||
|
||||
IF(QT4_FOUND)
|
||||
message(STATUS "Looking for Qt4 single application library")
|
||||
FIND_PATH(QTSINGLEAPPLICATION_INCLUDE_DIR QtSingleApplication
|
||||
# standard locations
|
||||
/usr/include
|
||||
/usr/include/QtSolutions
|
||||
# qt4 location except mac's frameworks
|
||||
"${QT_INCLUDE_DIR}/QtSolutions"
|
||||
# mac's frameworks
|
||||
${FRAMEWORK_INCLUDE_DIR}/QtSolutions
|
||||
)
|
||||
if (Qt5Widgets_FOUND)
|
||||
set(_includeFileName qtsingleapplication.h)
|
||||
else()
|
||||
set(_includeFileName qtsinglecoreapplication.h)
|
||||
endif()
|
||||
|
||||
SET(QTSINGLEAPPLICATION_NAMES ${QTSINGLEAPPLICATION_NAMES}
|
||||
QtSolutions_SingleApplication-2.6 libQtSolutions_SingleApplication-2.6)
|
||||
FIND_LIBRARY(QTSINGLEAPPLICATION_LIBRARY
|
||||
NAMES ${QTSINGLEAPPLICATION_NAMES}
|
||||
PATHS ${QT_LIBRARY_DIR}
|
||||
)
|
||||
ELSEIF(Qt5Core_FOUND)
|
||||
message(STATUS "Looking for Qt5 single application library")
|
||||
FOREACH(TOP_INCLUDE_PATH in ${Qt5Core_INCLUDE_DIRS} ${FRAMEWORK_INCLUDE_DIR})
|
||||
FIND_PATH(QTSINGLEAPPLICATION_INCLUDE_DIR QtSingleApplication ${TOP_INCLUDE_PATH}/QtSolutions)
|
||||
FOREACH(TOP_INCLUDE_PATH in ${Qt5Core_INCLUDE_DIRS} ${FRAMEWORK_INCLUDE_DIR})
|
||||
FIND_PATH(QtSingleApplication_INCLUDE_DIR ${_includeFileName} ${TOP_INCLUDE_PATH}/QtSolutions)
|
||||
|
||||
IF(QTSINGLEAPPLICATION_INCLUDE_DIR)
|
||||
BREAK()
|
||||
ENDIF()
|
||||
ENDFOREACH()
|
||||
IF(QtSingleApplication_INCLUDE_DIR)
|
||||
BREAK()
|
||||
ENDIF()
|
||||
ENDFOREACH()
|
||||
|
||||
SET(QTSINGLEAPPLICATION_NAMES ${QTSINGLEAPPLICATION_NAMES}
|
||||
Qt5Solutions_SingleApplication-2.6 libQt5Solutions_SingleApplication-2.6
|
||||
QtSolutions_SingleApplication-2.6 libQtSolutions_SingleApplication-2.6)
|
||||
GET_TARGET_PROPERTY(_QT5_CORELIBRARY Qt5::Core LOCATION)
|
||||
GET_FILENAME_COMPONENT(_QT5_CORELIBRARYPATH ${_QT5_CORELIBRARY} PATH)
|
||||
SET(QtSingleApplication_NAMES ${QtSingleApplication_NAMES}
|
||||
Qt5Solutions_SingleApplication-2.6 libQt5Solutions_SingleApplication-2.6
|
||||
QtSolutions_SingleApplication-2.6 libQtSolutions_SingleApplication-2.6)
|
||||
GET_TARGET_PROPERTY(_QT5_CORELIBRARY Qt5::Core LOCATION)
|
||||
GET_FILENAME_COMPONENT(_QT5_CORELIBRARYPATH ${_QT5_CORELIBRARY} PATH)
|
||||
|
||||
FIND_LIBRARY(QTSINGLEAPPLICATION_LIBRARY
|
||||
NAMES ${QTSINGLEAPPLICATION_NAMES}
|
||||
PATHS ${_QT5_CORELIBRARYPATH}
|
||||
)
|
||||
ENDIF()
|
||||
FIND_LIBRARY(QtSingleApplication_LIBRARY
|
||||
NAMES ${QtSingleApplication_NAMES}
|
||||
PATHS ${_QT5_CORELIBRARYPATH}
|
||||
)
|
||||
|
||||
IF (QTSINGLEAPPLICATION_LIBRARY AND QTSINGLEAPPLICATION_INCLUDE_DIR)
|
||||
IF (QtSingleApplication_LIBRARY AND QtSingleApplication_INCLUDE_DIR)
|
||||
|
||||
SET(QTSINGLEAPPLICATION_LIBRARIES ${QTSINGLEAPPLICATION_LIBRARY})
|
||||
SET(QTSINGLEAPPLICATION_FOUND TRUE)
|
||||
SET(QtSingleApplication_LIBRARIES ${QtSingleApplication_LIBRARY})
|
||||
SET(QtSingleApplication_FOUND TRUE)
|
||||
|
||||
IF (CYGWIN)
|
||||
IF(BUILD_SHARED_LIBS)
|
||||
# No need to define QTSINGLEAPPLICATION_USE_DLL here, because it's default for Cygwin.
|
||||
# No need to define QtSingleApplication_USE_DLL here, because it's default for Cygwin.
|
||||
ELSE(BUILD_SHARED_LIBS)
|
||||
SET (QTSINGLEAPPLICATION_DEFINITIONS -DQTSINGLEAPPLICATION_STATIC)
|
||||
SET (QtSingleApplication_DEFINITIONS -DQTSINGLEAPPLICATION_STATIC)
|
||||
ENDIF(BUILD_SHARED_LIBS)
|
||||
ENDIF (CYGWIN)
|
||||
|
||||
ENDIF (QTSINGLEAPPLICATION_LIBRARY AND QTSINGLEAPPLICATION_INCLUDE_DIR)
|
||||
ENDIF (QtSingleApplication_LIBRARY AND QtSingleApplication_INCLUDE_DIR)
|
||||
|
||||
IF (QTSINGLEAPPLICATION_FOUND)
|
||||
IF (NOT QtSingleApplication_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found QtSingleApplication: ${QTSINGLEAPPLICATION_LIBRARY}")
|
||||
MESSAGE(STATUS " includes: ${QTSINGLEAPPLICATION_INCLUDE_DIR}")
|
||||
ENDIF (NOT QtSingleApplication_FIND_QUIETLY)
|
||||
ELSE (QTSINGLEAPPLICATION_FOUND)
|
||||
IF (QtSingleApplication_FOUND)
|
||||
IF (NOT QtSingleApplication_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found QtSingleApplication: ${QtSingleApplication_LIBRARY}")
|
||||
MESSAGE(STATUS " includes: ${QtSingleApplication_INCLUDE_DIR}")
|
||||
ENDIF (NOT QtSingleApplication_FIND_QUIETLY)
|
||||
if(NOT TARGET QtSingleApplication::QtSingleApplication)
|
||||
add_library(QtSingleApplication::QtSingleApplication UNKNOWN IMPORTED)
|
||||
set_target_properties(QtSingleApplication::QtSingleApplication PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${QtSingleApplication_INCLUDE_DIR}"
|
||||
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${QtSingleApplication_INCLUDE_DIR}"
|
||||
)
|
||||
if(EXISTS "${QtSingleApplication_LIBRARY}")
|
||||
set_target_properties(QtSingleApplication::QtSingleApplication PROPERTIES
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
|
||||
IMPORTED_LOCATION "${QtSingleApplication_LIBRARY}")
|
||||
endif()
|
||||
endif(NOT TARGET QtSingleApplication::QtSingleApplication)
|
||||
|
||||
ELSE (QtSingleApplication_FOUND)
|
||||
IF (QtSingleApplication_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find QtSingleApplication library")
|
||||
ENDIF (QtSingleApplication_FIND_REQUIRED)
|
||||
ENDIF (QTSINGLEAPPLICATION_FOUND)
|
||||
ENDIF (QtSingleApplication_FOUND)
|
||||
|
||||
MARK_AS_ADVANCED(QTSINGLEAPPLICATION_INCLUDE_DIR QTSINGLEAPPLICATION_LIBRARY)
|
||||
|
||||
if(NOT TARGET QtSingleApplication::QtSingleApplication)
|
||||
add_library(QtSingleApplication::QtSingleApplication UNKNOWN IMPORTED)
|
||||
set_target_properties(QtSingleApplication::QtSingleApplication PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${QTSINGLEAPPLICATION_INCLUDE_DIR}"
|
||||
INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${QTSINGLEAPPLICATION_INCLUDE_DIR}"
|
||||
)
|
||||
if(EXISTS "${QTSINGLEAPPLICATION_LIBRARY}")
|
||||
set_target_properties(QtSingleApplication::QtSingleApplication PROPERTIES
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
|
||||
IMPORTED_LOCATION "${QTSINGLEAPPLICATION_LIBRARY}")
|
||||
endif()
|
||||
endif(NOT TARGET QtSingleApplication::QtSingleApplication)
|
||||
MARK_AS_ADVANCED(QtSingleApplication_INCLUDE_DIR QtSingleApplication_LIBRARY)
|
||||
|
||||
@@ -11,18 +11,17 @@ macro(qbt_set_compiler_options)
|
||||
#-Wshadow -Wconversion ?
|
||||
set(_GCC_COMMON_C_AND_CXX_FLAGS "-Wall -Wextra"
|
||||
"-Wfloat-equal -Wcast-qual -Wcast-align"
|
||||
"-Wsign-conversion -Winvalid-pch -Werror=return-type -Wno-long-long"
|
||||
# -fstack-protector-all
|
||||
"-Werror -Wno-error=deprecated-declarations"
|
||||
"-Wsign-conversion -Winvalid-pch -Wno-long-long"
|
||||
#"-fstack-protector-all"
|
||||
#"-Werror -Wno-error=deprecated-declarations"
|
||||
)
|
||||
set (_GCC_COMMON_CXX_FLAGS "-fexceptions -frtti"
|
||||
set(_GCC_COMMON_CXX_FLAGS "-fexceptions -frtti"
|
||||
"-Woverloaded-virtual -Wold-style-cast"
|
||||
"-Wnon-virtual-dtor -Wfloat-equal -Wcast-qual -Wcast-align"
|
||||
"-Werror=overloaded-virtual"
|
||||
# "-Weffc++"
|
||||
"-Werror -Wno-error=cpp"
|
||||
#"-Weffc++"
|
||||
#"-Werror -Wno-error=cpp"
|
||||
# we should modify code to make these ones obsolete
|
||||
"-Wno-error=sign-conversion -Wno-error=float-equal"
|
||||
#"-Wno-error=sign-conversion -Wno-error=float-equal"
|
||||
)
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9)
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
# a helper function which appends source to the main qBt target
|
||||
# sources file names are relative to the the ${qBittorrent_SOURCE_DIR}
|
||||
# a helper function which appends source to the target
|
||||
# sources file names are relative to the the target source dir
|
||||
|
||||
function (qbt_target_sources)
|
||||
set (_sources_rel "")
|
||||
foreach (_source IN ITEMS ${ARGN})
|
||||
if (IS_ABSOLUTE "${_source}")
|
||||
set(source_abs "${_source}")
|
||||
function (qbt_target_sources _target _scope)
|
||||
get_target_property(targetSourceDir ${_target} SOURCE_DIR)
|
||||
set(sourcesRelative "")
|
||||
foreach(source IN ITEMS ${ARGN})
|
||||
if(IS_ABSOLUTE "${source}")
|
||||
set(sourceAbsolutePath "${source}")
|
||||
else()
|
||||
get_filename_component(_source_abs "${_source}" ABSOLUTE)
|
||||
get_filename_component(sourceAbsolutePath "${source}" ABSOLUTE)
|
||||
endif()
|
||||
file (RELATIVE_PATH _source_rel "${qbt_executable_SOURCE_DIR}" "${_source_abs}")
|
||||
list (APPEND _sources_rel "${_source_rel}")
|
||||
file(RELATIVE_PATH sourceRelativePath "${targetSourceDir}" "${sourceAbsolutePath}")
|
||||
list(APPEND sourcesRelative "${sourceRelativePath}")
|
||||
endforeach()
|
||||
target_sources (qBittorrent PRIVATE "${_sources_rel}")
|
||||
endfunction (qbt_target_sources)
|
||||
target_sources(${_target} ${_scope} "${sourcesRelative}")
|
||||
endfunction(qbt_target_sources)
|
||||
|
||||
48
cmake/Modules/QbtTranslations.cmake
Normal file
48
cmake/Modules/QbtTranslations.cmake
Normal file
@@ -0,0 +1,48 @@
|
||||
# macros to handle translation files
|
||||
|
||||
# qbt_add_translations(<target> QRC_FILE <filename> TS_FILES <filenames>)
|
||||
# handles out of source builds for Qt resource files that include translations
|
||||
# The function generates translations out of the supplied list of .ts files in the build directory,
|
||||
# copies the .qrc file there, calls qt5_add_resources() adds its output to the target sources list.
|
||||
function(qbt_add_translations _target)
|
||||
set(oneValueArgs QRC_FILE)
|
||||
set(multiValueArgs TS_FILES)
|
||||
cmake_parse_arguments(QBT_TR "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||
|
||||
get_target_property(_binaryDir ${_target} BINARY_DIR)
|
||||
|
||||
if (NOT QBT_TR_QRC_FILE)
|
||||
message(FATAL_ERROR "QRC file is empty")
|
||||
endif()
|
||||
if (NOT QBT_TR_TS_FILES)
|
||||
message(FATAL_ERROR "TS_FILES files are empty")
|
||||
endif()
|
||||
|
||||
if(IS_ABSOLUTE "${QBT_TR_QRC_FILE}")
|
||||
file(RELATIVE_PATH _qrcToTs "${CMAKE_CURRENT_SOURCE_DIR}" "${QBT_TR_QRC_FILE}")
|
||||
else()
|
||||
set(_qrcToTs "${QBT_TR_QRC_FILE}")
|
||||
endif()
|
||||
|
||||
get_filename_component(_qrcToTsDir "${_qrcToTs}" DIRECTORY)
|
||||
|
||||
get_filename_component(_qmFilesBinaryDir "${CMAKE_CURRENT_BINARY_DIR}/${_qrcToTsDir}" ABSOLUTE)
|
||||
# to make qt5_add_translation() work as we need
|
||||
set_source_files_properties(${QBT_TR_TS_FILES} PROPERTIES OUTPUT_LOCATION "${_qmFilesBinaryDir}")
|
||||
qt5_add_translation(_qmFiles ${QBT_TR_TS_FILES})
|
||||
|
||||
set(_qrc_dest_dir "${_binaryDir}/${_qrcToTsDir}")
|
||||
set(_qrc_dest_file "${_binaryDir}/${QBT_TR_QRC_FILE}")
|
||||
|
||||
message(STATUS "copying ${QBT_TR_QRC_FILE} to ${_qrc_dest_dir}")
|
||||
file(COPY ${QBT_TR_QRC_FILE} DESTINATION ${_qrc_dest_dir})
|
||||
|
||||
set_source_files_properties("${_qrc_dest_file}" PROPERTIES
|
||||
GENERATED True
|
||||
OBJECT_DEPENDS "${_qmFiles}")
|
||||
|
||||
# With AUTORCC enabled rcc is ran by cmake before language files are generated,
|
||||
# and thus we call rcc explicitly
|
||||
qt5_add_resources(_resources "${_qrc_dest_file}")
|
||||
target_sources(${_target} PRIVATE "${_resources}")
|
||||
endfunction()
|
||||
@@ -1,9 +1,9 @@
|
||||
if (STACKTRACE_WIN)
|
||||
if (STACKTRACE)
|
||||
if ("${WINXXBITS}" NOT STREQUAL "Win64")
|
||||
add_compile_options(-fno-omit-frame-pointer)
|
||||
endif ("${WINXXBITS}" NOT STREQUAL "Win64")
|
||||
link_libraries(libdbghelp -Wl,--export-all-symbols)
|
||||
endif (STACKTRACE_WIN)
|
||||
endif (STACKTRACE)
|
||||
|
||||
if (("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") OR ("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo"))
|
||||
link_libraries(-Wl,--dynamicbase)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
if (STACKTRACE_WIN)
|
||||
if (STACKTRACE)
|
||||
if ("${WINXXBITS}" STREQUAL "Win64")
|
||||
add_compile_options(-Zi)
|
||||
else ("${WINXXBITS}" STREQUAL "Win64")
|
||||
@@ -6,7 +6,7 @@ if (STACKTRACE_WIN)
|
||||
add_compile_options(-Oy-)
|
||||
endif ("${WINXXBITS}" STREQUAL "Win64")
|
||||
link_libraries(dbghelp.lib)
|
||||
endif (STACKTRACE_WIN)
|
||||
endif (STACKTRACE)
|
||||
|
||||
# Enable Wide characters
|
||||
add_definitions(-DTORRENT_USE_WPATH)
|
||||
|
||||
@@ -5,6 +5,8 @@ BINDIR = @EXPAND_BINDIR@
|
||||
DATADIR = @EXPAND_DATADIR@
|
||||
MANPREFIX = @EXPAND_MANDIR@
|
||||
|
||||
QMAKE_CC = @QBT_CC@
|
||||
QMAKE_CXX = @QBT_CXX@
|
||||
QMAKE_CXXFLAGS += @QBT_CONF_EXTRA_CFLAGS@
|
||||
|
||||
EXTERNAL_INCLUDES = @QBT_CONF_INCLUDES@
|
||||
|
||||
@@ -50,6 +50,8 @@ DEFINES += BOOST_USE_WINAPI_VERSION=0x0501
|
||||
#DEFINES += BOOST_ASIO_SEPARATE_COMPILATION
|
||||
# Enable if building against libtorrent 1.0.x (RC_1_0) (dynamic linking)
|
||||
#DEFINES += BOOST_ASIO_DYN_LINK
|
||||
# Enable if encountered build error with boost version <= 1.59
|
||||
#DEFINES += BOOST_NO_CXX11_RVALUE_REFERENCES
|
||||
|
||||
# Enable if building against libtorrent 1.1.x (RC_1_1)
|
||||
# built with this flag defined
|
||||
@@ -58,4 +60,10 @@ DEFINES += BOOST_USE_WINAPI_VERSION=0x0501
|
||||
#DEFINES += TORRENT_LINKING_SHARED
|
||||
|
||||
# Enable stack trace support
|
||||
CONFIG += strace_win
|
||||
CONFIG += stacktrace
|
||||
|
||||
win32-msvc* {
|
||||
QMAKE_CXXFLAGS += "/guard:cf"
|
||||
QMAKE_LFLAGS += "/guard:cf"
|
||||
QMAKE_LFLAGS_RELEASE += "/OPT:REF /OPT:ICF"
|
||||
}
|
||||
|
||||
493
configure
vendored
493
configure
vendored
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for qbittorrent v4.1.0alpha.
|
||||
# Generated by GNU Autoconf 2.69 for qbittorrent v4.1.9.1.
|
||||
#
|
||||
# Report bugs to <bugs.qbittorrent.org>.
|
||||
#
|
||||
@@ -580,8 +580,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='qbittorrent'
|
||||
PACKAGE_TARNAME='qbittorrent'
|
||||
PACKAGE_VERSION='v4.1.0alpha'
|
||||
PACKAGE_STRING='qbittorrent v4.1.0alpha'
|
||||
PACKAGE_VERSION='v4.1.9.1'
|
||||
PACKAGE_STRING='qbittorrent v4.1.9.1'
|
||||
PACKAGE_BUGREPORT='bugs.qbittorrent.org'
|
||||
PACKAGE_URL='https://www.qbittorrent.org/'
|
||||
|
||||
@@ -595,6 +595,8 @@ QBT_REMOVE_CONFIG
|
||||
QBT_ADD_CONFIG
|
||||
QBT_CONF_EXTRA_CFLAGS
|
||||
QBT_CONF_INCLUDES
|
||||
QBT_CXX
|
||||
QBT_CC
|
||||
EXPAND_MANDIR
|
||||
EXPAND_DATADIR
|
||||
EXPAND_BINDIR
|
||||
@@ -626,7 +628,6 @@ am__nodep
|
||||
AMDEPBACKSLASH
|
||||
AMDEP_FALSE
|
||||
AMDEP_TRUE
|
||||
am__quote
|
||||
am__include
|
||||
DEPDIR
|
||||
am__untar
|
||||
@@ -709,7 +710,8 @@ PACKAGE_VERSION
|
||||
PACKAGE_TARNAME
|
||||
PACKAGE_NAME
|
||||
PATH_SEPARATOR
|
||||
SHELL'
|
||||
SHELL
|
||||
am__quote'
|
||||
ac_subst_files=''
|
||||
ac_user_opts='
|
||||
enable_option_checking
|
||||
@@ -1297,7 +1299,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures qbittorrent v4.1.0alpha to adapt to many kinds of systems.
|
||||
\`configure' configures qbittorrent v4.1.9.1 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1368,7 +1370,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of qbittorrent v4.1.0alpha:";;
|
||||
short | recursive ) echo "Configuration of qbittorrent v4.1.9.1:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1503,7 +1505,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
qbittorrent configure v4.1.0alpha
|
||||
qbittorrent configure v4.1.9.1
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -1642,7 +1644,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by qbittorrent $as_me v4.1.0alpha, which was
|
||||
It was created by qbittorrent $as_me v4.1.9.1, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -3274,7 +3276,7 @@ IFS=$ac_save_IFS
|
||||
case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
|
||||
|
||||
|
||||
am__api_version='1.15'
|
||||
am__api_version='1.16'
|
||||
|
||||
# Find a good install program. We prefer a C program (faster),
|
||||
# so one script is as good as another. But avoid the broken or
|
||||
@@ -3700,45 +3702,45 @@ DEPDIR="${am__leading_dot}deps"
|
||||
|
||||
ac_config_commands="$ac_config_commands depfiles"
|
||||
|
||||
|
||||
am_make=${MAKE-make}
|
||||
cat > confinc << 'END'
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5
|
||||
$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; }
|
||||
cat > confinc.mk << 'END'
|
||||
am__doit:
|
||||
@echo this is the am__doit target
|
||||
@echo this is the am__doit target >confinc.out
|
||||
.PHONY: am__doit
|
||||
END
|
||||
# If we don't find an include directive, just comment out the code.
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5
|
||||
$as_echo_n "checking for style of include used by $am_make... " >&6; }
|
||||
am__include="#"
|
||||
am__quote=
|
||||
_am_result=none
|
||||
# First try GNU make style include.
|
||||
echo "include confinc" > confmf
|
||||
# Ignore all kinds of additional output from 'make'.
|
||||
case `$am_make -s -f confmf 2> /dev/null` in #(
|
||||
*the\ am__doit\ target*)
|
||||
am__include=include
|
||||
am__quote=
|
||||
_am_result=GNU
|
||||
;;
|
||||
esac
|
||||
# Now try BSD make style include.
|
||||
if test "$am__include" = "#"; then
|
||||
echo '.include "confinc"' > confmf
|
||||
case `$am_make -s -f confmf 2> /dev/null` in #(
|
||||
*the\ am__doit\ target*)
|
||||
am__include=.include
|
||||
am__quote="\""
|
||||
_am_result=BSD
|
||||
# BSD make does it like this.
|
||||
echo '.include "confinc.mk" # ignored' > confmf.BSD
|
||||
# Other make implementations (GNU, Solaris 10, AIX) do it like this.
|
||||
echo 'include confinc.mk # ignored' > confmf.GNU
|
||||
_am_result=no
|
||||
for s in GNU BSD; do
|
||||
{ echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5
|
||||
(${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }
|
||||
case $?:`cat confinc.out 2>/dev/null` in #(
|
||||
'0:this is the am__doit target') :
|
||||
case $s in #(
|
||||
BSD) :
|
||||
am__include='.include' am__quote='"' ;; #(
|
||||
*) :
|
||||
am__include='include' am__quote='' ;;
|
||||
esac ;; #(
|
||||
*) :
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5
|
||||
$as_echo "$_am_result" >&6; }
|
||||
rm -f confinc confmf
|
||||
esac
|
||||
if test "$am__include" != "#"; then
|
||||
_am_result="yes ($s style)"
|
||||
break
|
||||
fi
|
||||
done
|
||||
rm -f confinc.* confmf.*
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5
|
||||
$as_echo "${_am_result}" >&6; }
|
||||
|
||||
# Check whether --enable-dependency-tracking was given.
|
||||
if test "${enable_dependency_tracking+set}" = set; then :
|
||||
@@ -3820,7 +3822,7 @@ fi
|
||||
|
||||
# Define the identity of the package.
|
||||
PACKAGE='qbittorrent'
|
||||
VERSION='v4.1.0alpha'
|
||||
VERSION='v4.1.9.1'
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
@@ -3850,8 +3852,8 @@ MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
|
||||
|
||||
# For better backward compatibility. To be removed once Automake 1.9.x
|
||||
# dies out for good. For more background, see:
|
||||
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
|
||||
# <http://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
|
||||
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00001.html>
|
||||
# <https://lists.gnu.org/archive/html/automake/2012-07/msg00014.html>
|
||||
mkdir_p='$(MKDIR_P)'
|
||||
|
||||
# We need awk for the "check" target (and possibly the TAP driver). The
|
||||
@@ -4158,7 +4160,7 @@ END
|
||||
Aborting the configuration process, to ensure you take notice of the issue.
|
||||
|
||||
You can download and install GNU coreutils to get an 'rm' implementation
|
||||
that behaves properly: <http://www.gnu.org/software/coreutils/>.
|
||||
that behaves properly: <https://www.gnu.org/software/coreutils/>.
|
||||
|
||||
If you want to complete the configuration process using your problematic
|
||||
'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
|
||||
@@ -4170,11 +4172,12 @@ END
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# use compiler from env variables if available
|
||||
QBT_CC="$CC"
|
||||
QBT_CXX="$CXX"
|
||||
|
||||
# Define --wth-* and --enable-* arguments
|
||||
|
||||
|
||||
# Check whether --with-qtsingleapplication was given.
|
||||
if test "${with_qtsingleapplication+set}" = set; then :
|
||||
withval=$with_qtsingleapplication;
|
||||
@@ -4745,7 +4748,9 @@ fi
|
||||
case ${host_cpu} in #(
|
||||
x86_64) :
|
||||
libsubdirs="lib64 libx32 lib lib64" ;; #(
|
||||
ppc64|s390x|sparc64|aarch64|ppc64le) :
|
||||
mips*64*) :
|
||||
libsubdirs="lib64 lib32 lib lib64" ;; #(
|
||||
ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64) :
|
||||
libsubdirs="lib64 lib lib64" ;; #(
|
||||
*) :
|
||||
libsubdirs="lib"
|
||||
@@ -4997,10 +5002,10 @@ $as_echo "$as_me: Your boost libraries seems to old (version $_version)." >&6;}
|
||||
$as_echo "#define HAVE_BOOST /**/" >>confdefs.h
|
||||
|
||||
# execute ACTION-IF-FOUND (if present):
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: Boost CPPFLAGS: \"$BOOST_CPPFLAGS\"
|
||||
Boost LDFLAGS: \"$BOOST_LDFLAGS\"" >&5
|
||||
$as_echo "$as_me: Boost CPPFLAGS: \"$BOOST_CPPFLAGS\"
|
||||
Boost LDFLAGS: \"$BOOST_LDFLAGS\"" >&6;}
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: Boost CXXFLAGS: \"$BOOST_CPPFLAGS\"" >&5
|
||||
$as_echo "$as_me: Boost CXXFLAGS: \"$BOOST_CPPFLAGS\"" >&6;}
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: Boost LDFLAGS: \"$BOOST_LDFLAGS\"" >&5
|
||||
$as_echo "$as_me: Boost LDFLAGS: \"$BOOST_LDFLAGS\"" >&6;}
|
||||
fi
|
||||
|
||||
CPPFLAGS="$CPPFLAGS_SAVED"
|
||||
@@ -5011,9 +5016,31 @@ fi
|
||||
|
||||
|
||||
|
||||
CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS"
|
||||
CXXFLAGS="$BOOST_CPPFLAGS $CXXFLAGS"
|
||||
LDFLAGS="$BOOST_LDFLAGS $LDFLAGS"
|
||||
|
||||
# add workaround for problematic boost version
|
||||
# taken from ax_boost_base.m4
|
||||
|
||||
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
#include <boost/version.hpp>
|
||||
int
|
||||
main ()
|
||||
{
|
||||
(void) ((void)sizeof(char[1 - 2*!!((BOOST_VERSION) < (106000))]));
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||
|
||||
else
|
||||
QBT_ADD_DEFINES="$QBT_ADD_DEFINES BOOST_NO_CXX11_RVALUE_REFERENCES"
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
|
||||
|
||||
# Check whether --with-boost-system was given.
|
||||
@@ -5245,7 +5272,7 @@ fi
|
||||
|
||||
fi
|
||||
if test "x$ax_lib" = "x"; then
|
||||
as_fn_error $? "Could not find a version of the library!" "$LINENO" 5
|
||||
as_fn_error $? "Could not find a version of the Boost::System library!" "$LINENO" 5
|
||||
fi
|
||||
if test "x$link_system" = "xno"; then
|
||||
as_fn_error $? "Could not link against $ax_lib !" "$LINENO" 5
|
||||
@@ -5366,7 +5393,7 @@ else
|
||||
libtorrent_LIBS=$pkg_cv_libtorrent_LIBS
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
CPPFLAGS="$libtorrent_CFLAGS $CPPFLAGS"
|
||||
CXXFLAGS="$libtorrent_CFLAGS $CXXFLAGS"
|
||||
LIBS="$libtorrent_LIBS $LIBS"
|
||||
fi
|
||||
|
||||
@@ -5459,10 +5486,116 @@ else
|
||||
zlib_LIBS=$pkg_cv_zlib_LIBS
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
CPPFLAGS="$zlib_CFLAGS $CPPFLAGS"
|
||||
CXXFLAGS="$zlib_CFLAGS $CXXFLAGS"
|
||||
LIBS="$zlib_LIBS $LIBS"
|
||||
fi
|
||||
|
||||
# Check if already in >= C++11 mode because of the flags returned by one of the above packages
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler is using C++11 or later mode" >&5
|
||||
$as_echo_n "checking if compiler is using C++11 or later mode... " >&6; }
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error "This is not a C++ compiler"
|
||||
#elif __cplusplus < 201103L
|
||||
#error "This is not a C++11 compiler"
|
||||
#endif
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_ACEOF
|
||||
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
QBT_CXX11_FOUND="yes"
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
QBT_CXX11_FOUND="no"
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
# In case of no, check if the compiler can support at least C++11
|
||||
# and if yes, enable it leaving a warning to the user
|
||||
if test "x$QBT_CXX11_FOUND" = "xno"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler supports C++11" >&5
|
||||
$as_echo_n "checking if compiler supports C++11... " >&6; }
|
||||
TMP_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS -std=c++11"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error "This is not a C++ compiler"
|
||||
#elif __cplusplus < 201103L
|
||||
#error "This is not a C++11 compiler"
|
||||
#endif
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_ACEOF
|
||||
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if C++11 is disabled by the set compiler flags" >&5
|
||||
$as_echo_n "checking if C++11 is disabled by the set compiler flags... " >&6; }
|
||||
# prepend the flag so it won't override conflicting user defined flags
|
||||
CXXFLAGS="-std=c++11 $TMP_CXXFLAGS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
#ifndef __cplusplus
|
||||
#error "This is not a C++ compiler"
|
||||
#elif __cplusplus < 201103L
|
||||
#error "This is not a C++11 compiler"
|
||||
#endif
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
|
||||
_ACEOF
|
||||
if ac_fn_cxx_try_compile "$LINENO"; then :
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
CXXFLAGS="$TMP_CXXFLAGS -std=c++11"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: C++11 mode is now force enabled.
|
||||
Make sure you use the same C++ mode for qBittorrent and its dependencies.
|
||||
To explicitly set qBittorrent to a later mode use CXXFLAGS.
|
||||
Example: \`CXXFLAGS=\"\$CXXFLAGS -std=c++14\" ./configure\`" >&5
|
||||
$as_echo "$as_me: WARNING: C++11 mode is now force enabled.
|
||||
Make sure you use the same C++ mode for qBittorrent and its dependencies.
|
||||
To explicitly set qBittorrent to a later mode use CXXFLAGS.
|
||||
Example: \`CXXFLAGS=\"\$CXXFLAGS -std=c++14\" ./configure\`" >&2;}
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
as_fn_error $? "The compiler supports C++11 but the user or a dependency has explicitly enabled a lower mode." "$LINENO" 5
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
as_fn_error $? "A compiler supporting C++11 is required." "$LINENO" 5
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
|
||||
fi
|
||||
|
||||
# These are required because autoconf doesn't expand these **particular**
|
||||
# vars automatically. And qmake cannot autoexpand them.
|
||||
|
||||
@@ -5549,15 +5682,15 @@ extract() {
|
||||
for i in $string; do
|
||||
case "$(echo "$i" | cut -c1)" in
|
||||
'') ;;
|
||||
D) QBT_CONF_DEFINES="$(echo $i | cut -c2-) $QBT_CONF_DEFINES";;
|
||||
I) QBT_CONF_INCLUDES="$(echo $i | cut -c2-) $QBT_CONF_INCLUDES";;
|
||||
*) QBT_CONF_EXTRA_CFLAGS="-$i $QBT_CONF_EXTRA_CFLAGS";;
|
||||
D) QBT_CONF_DEFINES="$QBT_CONF_DEFINES $(echo $i | cut -c2-)";;
|
||||
I) QBT_CONF_INCLUDES="$QBT_CONF_INCLUDES $(echo $i | cut -c2-)";;
|
||||
*) QBT_CONF_EXTRA_CFLAGS="$QBT_CONF_EXTRA_CFLAGS -$i";;
|
||||
esac
|
||||
done
|
||||
IFS=$SAVEIFS
|
||||
}
|
||||
|
||||
extract "$CFLAGS $CPPFLAGS $CXXFLAGS"
|
||||
extract "$CFLAGS $CXXFLAGS"
|
||||
QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES"
|
||||
|
||||
# Substitute the values of these vars in conf.pri.in
|
||||
@@ -5568,6 +5701,8 @@ QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ac_config_files="$ac_config_files conf.pri"
|
||||
|
||||
cat >confcache <<\_ACEOF
|
||||
@@ -6140,7 +6275,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by qbittorrent $as_me v4.1.0alpha, which was
|
||||
This file was extended by qbittorrent $as_me v4.1.9.1, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -6198,7 +6333,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
qbittorrent config.status v4.1.0alpha
|
||||
qbittorrent config.status v4.1.9.1
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
@@ -6306,7 +6441,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
#
|
||||
# INIT-COMMANDS
|
||||
#
|
||||
AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
|
||||
AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"
|
||||
|
||||
_ACEOF
|
||||
|
||||
@@ -6751,29 +6886,35 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
|
||||
# Older Autoconf quotes --file arguments for eval, but not when files
|
||||
# are listed without --file. Let's play safe and only enable the eval
|
||||
# if we detect the quoting.
|
||||
case $CONFIG_FILES in
|
||||
*\'*) eval set x "$CONFIG_FILES" ;;
|
||||
*) set x $CONFIG_FILES ;;
|
||||
esac
|
||||
# TODO: see whether this extra hack can be removed once we start
|
||||
# requiring Autoconf 2.70 or later.
|
||||
case $CONFIG_FILES in #(
|
||||
*\'*) :
|
||||
eval set x "$CONFIG_FILES" ;; #(
|
||||
*) :
|
||||
set x $CONFIG_FILES ;; #(
|
||||
*) :
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
for mf
|
||||
# Used to flag and report bootstrapping failures.
|
||||
am_rc=0
|
||||
for am_mf
|
||||
do
|
||||
# Strip MF so we end up with the name of the file.
|
||||
mf=`echo "$mf" | sed -e 's/:.*$//'`
|
||||
# Check whether this is an Automake generated Makefile or not.
|
||||
# We used to match only the files named 'Makefile.in', but
|
||||
# some people rename them; so instead we look at the file content.
|
||||
# Grep'ing the first line is not enough: some people post-process
|
||||
# each Makefile.in and add a new line on top of each file to say so.
|
||||
# Grep'ing the whole file is not good either: AIX grep has a line
|
||||
am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'`
|
||||
# Check whether this is an Automake generated Makefile which includes
|
||||
# dependency-tracking related rules and includes.
|
||||
# Grep'ing the whole file directly is not great: AIX grep has a line
|
||||
# limit of 2048, but all sed's we know have understand at least 4000.
|
||||
if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
|
||||
dirpart=`$as_dirname -- "$mf" ||
|
||||
$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$mf" : 'X\(//\)[^/]' \| \
|
||||
X"$mf" : 'X\(//\)$' \| \
|
||||
X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
$as_echo X"$mf" |
|
||||
sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
|
||||
|| continue
|
||||
am_dirpart=`$as_dirname -- "$am_mf" ||
|
||||
$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$am_mf" : 'X\(//\)[^/]' \| \
|
||||
X"$am_mf" : 'X\(//\)$' \| \
|
||||
X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
$as_echo X"$am_mf" |
|
||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
@@ -6791,53 +6932,48 @@ $as_echo X"$mf" |
|
||||
q
|
||||
}
|
||||
s/.*/./; q'`
|
||||
else
|
||||
continue
|
||||
fi
|
||||
# Extract the definition of DEPDIR, am__include, and am__quote
|
||||
# from the Makefile without running 'make'.
|
||||
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
|
||||
test -z "$DEPDIR" && continue
|
||||
am__include=`sed -n 's/^am__include = //p' < "$mf"`
|
||||
test -z "$am__include" && continue
|
||||
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
|
||||
# Find all dependency output files, they are included files with
|
||||
# $(DEPDIR) in their names. We invoke sed twice because it is the
|
||||
# simplest approach to changing $(DEPDIR) to its actual value in the
|
||||
# expansion.
|
||||
for file in `sed -n "
|
||||
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
|
||||
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
|
||||
# Make sure the directory exists.
|
||||
test -f "$dirpart/$file" && continue
|
||||
fdir=`$as_dirname -- "$file" ||
|
||||
$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$file" : 'X\(//\)[^/]' \| \
|
||||
X"$file" : 'X\(//\)$' \| \
|
||||
X"$file" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
$as_echo X"$file" |
|
||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||
am_filepart=`$as_basename -- "$am_mf" ||
|
||||
$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
|
||||
X"$am_mf" : 'X\(//\)$' \| \
|
||||
X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
$as_echo X/"$am_mf" |
|
||||
sed '/^.*\/\([^/][^/]*\)\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)[^/].*/{
|
||||
/^X\/\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\).*/{
|
||||
/^X\/\(\/\).*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
s/.*/./; q'`
|
||||
as_dir=$dirpart/$fdir; as_fn_mkdir_p
|
||||
# echo "creating $dirpart/$file"
|
||||
echo '# dummy' > "$dirpart/$file"
|
||||
done
|
||||
{ echo "$as_me:$LINENO: cd "$am_dirpart" \
|
||||
&& sed -e '/# am--include-marker/d' "$am_filepart" \
|
||||
| $MAKE -f - am--depfiles" >&5
|
||||
(cd "$am_dirpart" \
|
||||
&& sed -e '/# am--include-marker/d' "$am_filepart" \
|
||||
| $MAKE -f - am--depfiles) >&5 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } || am_rc=$?
|
||||
done
|
||||
if test $am_rc -ne 0; then
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||
as_fn_error $? "Something went wrong bootstrapping makefile fragments
|
||||
for automatic dependency tracking. Try re-running configure with the
|
||||
'--disable-dependency-tracking' option to at least be able to build
|
||||
the package (albeit without support for automatic dependency tracking).
|
||||
See \`config.log' for more details" "$LINENO" 5; }
|
||||
fi
|
||||
{ am_dirpart=; unset am_dirpart;}
|
||||
{ am_filepart=; unset am_filepart;}
|
||||
{ am_mf=; unset am_mf;}
|
||||
{ am_rc=; unset am_rc;}
|
||||
rm -f conftest-deps.mk
|
||||
}
|
||||
;;
|
||||
|
||||
@@ -7455,7 +7591,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by qbittorrent $as_me v4.1.0alpha, which was
|
||||
This file was extended by qbittorrent $as_me v4.1.9.1, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -7513,7 +7649,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
qbittorrent config.status v4.1.0alpha
|
||||
qbittorrent config.status v4.1.9.1
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
@@ -7621,7 +7757,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
#
|
||||
# INIT-COMMANDS
|
||||
#
|
||||
AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
|
||||
AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"
|
||||
|
||||
_ACEOF
|
||||
|
||||
@@ -8067,29 +8203,35 @@ $as_echo "$as_me: executing $ac_file commands" >&6;}
|
||||
# Older Autoconf quotes --file arguments for eval, but not when files
|
||||
# are listed without --file. Let's play safe and only enable the eval
|
||||
# if we detect the quoting.
|
||||
case $CONFIG_FILES in
|
||||
*\'*) eval set x "$CONFIG_FILES" ;;
|
||||
*) set x $CONFIG_FILES ;;
|
||||
esac
|
||||
# TODO: see whether this extra hack can be removed once we start
|
||||
# requiring Autoconf 2.70 or later.
|
||||
case $CONFIG_FILES in #(
|
||||
*\'*) :
|
||||
eval set x "$CONFIG_FILES" ;; #(
|
||||
*) :
|
||||
set x $CONFIG_FILES ;; #(
|
||||
*) :
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
for mf
|
||||
# Used to flag and report bootstrapping failures.
|
||||
am_rc=0
|
||||
for am_mf
|
||||
do
|
||||
# Strip MF so we end up with the name of the file.
|
||||
mf=`echo "$mf" | sed -e 's/:.*$//'`
|
||||
# Check whether this is an Automake generated Makefile or not.
|
||||
# We used to match only the files named 'Makefile.in', but
|
||||
# some people rename them; so instead we look at the file content.
|
||||
# Grep'ing the first line is not enough: some people post-process
|
||||
# each Makefile.in and add a new line on top of each file to say so.
|
||||
# Grep'ing the whole file is not good either: AIX grep has a line
|
||||
am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'`
|
||||
# Check whether this is an Automake generated Makefile which includes
|
||||
# dependency-tracking related rules and includes.
|
||||
# Grep'ing the whole file directly is not great: AIX grep has a line
|
||||
# limit of 2048, but all sed's we know have understand at least 4000.
|
||||
if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
|
||||
dirpart=`$as_dirname -- "$mf" ||
|
||||
$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$mf" : 'X\(//\)[^/]' \| \
|
||||
X"$mf" : 'X\(//\)$' \| \
|
||||
X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
$as_echo X"$mf" |
|
||||
sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \
|
||||
|| continue
|
||||
am_dirpart=`$as_dirname -- "$am_mf" ||
|
||||
$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$am_mf" : 'X\(//\)[^/]' \| \
|
||||
X"$am_mf" : 'X\(//\)$' \| \
|
||||
X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
$as_echo X"$am_mf" |
|
||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
@@ -8107,53 +8249,48 @@ $as_echo X"$mf" |
|
||||
q
|
||||
}
|
||||
s/.*/./; q'`
|
||||
else
|
||||
continue
|
||||
fi
|
||||
# Extract the definition of DEPDIR, am__include, and am__quote
|
||||
# from the Makefile without running 'make'.
|
||||
DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
|
||||
test -z "$DEPDIR" && continue
|
||||
am__include=`sed -n 's/^am__include = //p' < "$mf"`
|
||||
test -z "$am__include" && continue
|
||||
am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
|
||||
# Find all dependency output files, they are included files with
|
||||
# $(DEPDIR) in their names. We invoke sed twice because it is the
|
||||
# simplest approach to changing $(DEPDIR) to its actual value in the
|
||||
# expansion.
|
||||
for file in `sed -n "
|
||||
s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
|
||||
sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do
|
||||
# Make sure the directory exists.
|
||||
test -f "$dirpart/$file" && continue
|
||||
fdir=`$as_dirname -- "$file" ||
|
||||
$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
|
||||
X"$file" : 'X\(//\)[^/]' \| \
|
||||
X"$file" : 'X\(//\)$' \| \
|
||||
X"$file" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
$as_echo X"$file" |
|
||||
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
|
||||
am_filepart=`$as_basename -- "$am_mf" ||
|
||||
$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \
|
||||
X"$am_mf" : 'X\(//\)$' \| \
|
||||
X"$am_mf" : 'X\(/\)' \| . 2>/dev/null ||
|
||||
$as_echo X/"$am_mf" |
|
||||
sed '/^.*\/\([^/][^/]*\)\/*$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)[^/].*/{
|
||||
/^X\/\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\/\)$/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
/^X\(\/\).*/{
|
||||
/^X\/\(\/\).*/{
|
||||
s//\1/
|
||||
q
|
||||
}
|
||||
s/.*/./; q'`
|
||||
as_dir=$dirpart/$fdir; as_fn_mkdir_p
|
||||
# echo "creating $dirpart/$file"
|
||||
echo '# dummy' > "$dirpart/$file"
|
||||
done
|
||||
{ echo "$as_me:$LINENO: cd "$am_dirpart" \
|
||||
&& sed -e '/# am--include-marker/d' "$am_filepart" \
|
||||
| $MAKE -f - am--depfiles" >&5
|
||||
(cd "$am_dirpart" \
|
||||
&& sed -e '/# am--include-marker/d' "$am_filepart" \
|
||||
| $MAKE -f - am--depfiles) >&5 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } || am_rc=$?
|
||||
done
|
||||
if test $am_rc -ne 0; then
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||
as_fn_error $? "Something went wrong bootstrapping makefile fragments
|
||||
for automatic dependency tracking. Try re-running configure with the
|
||||
'--disable-dependency-tracking' option to at least be able to build
|
||||
the package (albeit without support for automatic dependency tracking).
|
||||
See \`config.log' for more details" "$LINENO" 5; }
|
||||
fi
|
||||
{ am_dirpart=; unset am_dirpart;}
|
||||
{ am_filepart=; unset am_filepart;}
|
||||
{ am_mf=; unset am_mf;}
|
||||
{ am_rc=; unset am_rc;}
|
||||
rm -f conftest-deps.mk
|
||||
}
|
||||
;;
|
||||
|
||||
|
||||
67
configure.ac
67
configure.ac
@@ -1,4 +1,4 @@
|
||||
AC_INIT([qbittorrent], [v4.1.0alpha], [bugs.qbittorrent.org], [], [https://www.qbittorrent.org/])
|
||||
AC_INIT([qbittorrent], [v4.1.9.1], [bugs.qbittorrent.org], [], [https://www.qbittorrent.org/])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_PROG_CC
|
||||
@@ -8,7 +8,9 @@ AC_LANG(C++)
|
||||
AC_CANONICAL_HOST
|
||||
AM_INIT_AUTOMAKE
|
||||
|
||||
|
||||
# use compiler from env variables if available
|
||||
QBT_CC="$CC"
|
||||
QBT_CXX="$CXX"
|
||||
|
||||
# Define --wth-* and --enable-* arguments
|
||||
|
||||
@@ -162,12 +164,21 @@ AS_CASE(["x$enable_qt_dbus"],
|
||||
|
||||
|
||||
AX_BOOST_BASE([1.35],
|
||||
[AC_MSG_NOTICE([Boost CPPFLAGS: "$BOOST_CPPFLAGS"
|
||||
Boost LDFLAGS: "$BOOST_LDFLAGS"])],
|
||||
[AC_MSG_NOTICE([Boost CXXFLAGS: "$BOOST_CPPFLAGS"])
|
||||
AC_MSG_NOTICE([Boost LDFLAGS: "$BOOST_LDFLAGS"])],
|
||||
[AC_MSG_ERROR([Could not find Boost])])
|
||||
CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS"
|
||||
CXXFLAGS="$BOOST_CPPFLAGS $CXXFLAGS"
|
||||
LDFLAGS="$BOOST_LDFLAGS $LDFLAGS"
|
||||
|
||||
# add workaround for problematic boost version
|
||||
# taken from ax_boost_base.m4
|
||||
m4_define([DETECT_BOOST_VERSION_PROGRAM],
|
||||
[AC_LANG_PROGRAM([[#include <boost/version.hpp>]],
|
||||
[[(void) ((void)sizeof(char[1 - 2*!!((BOOST_VERSION) < ($1))]));]])])
|
||||
|
||||
AC_COMPILE_IFELSE([DETECT_BOOST_VERSION_PROGRAM(106000)], [],
|
||||
[QBT_ADD_DEFINES="$QBT_ADD_DEFINES BOOST_NO_CXX11_RVALUE_REFERENCES"])
|
||||
|
||||
AX_BOOST_SYSTEM()
|
||||
AC_MSG_NOTICE([Boost.System LIB: "$BOOST_SYSTEM_LIB"])
|
||||
LIBS="$BOOST_SYSTEM_LIB $LIBS"
|
||||
@@ -185,14 +196,46 @@ AS_CASE(["x$with_qtsingleapplication"],
|
||||
|
||||
PKG_CHECK_MODULES(libtorrent,
|
||||
[libtorrent-rasterbar >= 1.0.6],
|
||||
[CPPFLAGS="$libtorrent_CFLAGS $CPPFLAGS"
|
||||
[CXXFLAGS="$libtorrent_CFLAGS $CXXFLAGS"
|
||||
LIBS="$libtorrent_LIBS $LIBS"])
|
||||
|
||||
PKG_CHECK_MODULES(zlib,
|
||||
[zlib >= 1.2.5.2],
|
||||
[CPPFLAGS="$zlib_CFLAGS $CPPFLAGS"
|
||||
[CXXFLAGS="$zlib_CFLAGS $CXXFLAGS"
|
||||
LIBS="$zlib_LIBS $LIBS"])
|
||||
|
||||
# Check if already in >= C++11 mode because of the flags returned by one of the above packages
|
||||
AC_MSG_CHECKING([if compiler is using C++11 or later mode])
|
||||
AC_COMPILE_IFELSE([DETECT_CPP11_PROGRAM()],
|
||||
[AC_MSG_RESULT([yes])
|
||||
QBT_CXX11_FOUND="yes"],
|
||||
[AC_MSG_RESULT([no])
|
||||
QBT_CXX11_FOUND="no"])
|
||||
|
||||
# In case of no, check if the compiler can support at least C++11
|
||||
# and if yes, enable it leaving a warning to the user
|
||||
AS_IF([test "x$QBT_CXX11_FOUND" = "xno"],
|
||||
[AC_MSG_CHECKING([if compiler supports C++11])
|
||||
TMP_CXXFLAGS="$CXXFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS -std=c++11"
|
||||
AC_COMPILE_IFELSE([DETECT_CPP11_PROGRAM()],
|
||||
[AC_MSG_RESULT([yes])
|
||||
AC_MSG_CHECKING([if C++11 is disabled by the set compiler flags])
|
||||
# prepend the flag so it won't override conflicting user defined flags
|
||||
CXXFLAGS="-std=c++11 $TMP_CXXFLAGS"
|
||||
AC_COMPILE_IFELSE([DETECT_CPP11_PROGRAM()],
|
||||
[AC_MSG_RESULT([no])
|
||||
CXXFLAGS="$TMP_CXXFLAGS -std=c++11"
|
||||
AC_MSG_WARN([C++11 mode is now force enabled.
|
||||
Make sure you use the same C++ mode for qBittorrent and its dependencies.
|
||||
To explicitly set qBittorrent to a later mode use CXXFLAGS.
|
||||
Example: `CXXFLAGS="\$CXXFLAGS -std=c++14" ./configure`])],
|
||||
[AC_MSG_RESULT([yes])
|
||||
AC_MSG_ERROR([The compiler supports C++11 but the user or a dependency has explicitly enabled a lower mode.])])],
|
||||
[AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([A compiler supporting C++11 is required.])])
|
||||
])
|
||||
|
||||
# These are required because autoconf doesn't expand these **particular**
|
||||
# vars automatically. And qmake cannot autoexpand them.
|
||||
AX_DEFINE_DIR([EXPAND_PREFIX], [prefix])
|
||||
@@ -219,18 +262,20 @@ extract() {
|
||||
for i in $string; do
|
||||
case "$(echo "$i" | cut -c1)" in
|
||||
'') ;;
|
||||
D) QBT_CONF_DEFINES="$(echo $i | cut -c2-) $QBT_CONF_DEFINES";;
|
||||
I) QBT_CONF_INCLUDES="$(echo $i | cut -c2-) $QBT_CONF_INCLUDES";;
|
||||
*) QBT_CONF_EXTRA_CFLAGS="-$i $QBT_CONF_EXTRA_CFLAGS";;
|
||||
D) QBT_CONF_DEFINES="$QBT_CONF_DEFINES $(echo $i | cut -c2-)";;
|
||||
I) QBT_CONF_INCLUDES="$QBT_CONF_INCLUDES $(echo $i | cut -c2-)";;
|
||||
*) QBT_CONF_EXTRA_CFLAGS="$QBT_CONF_EXTRA_CFLAGS -$i";;
|
||||
esac
|
||||
done
|
||||
IFS=$SAVEIFS
|
||||
}
|
||||
|
||||
extract "$CFLAGS $CPPFLAGS $CXXFLAGS"
|
||||
extract "$CFLAGS $CXXFLAGS"
|
||||
QBT_ADD_DEFINES="$QBT_ADD_DEFINES $QBT_CONF_DEFINES"
|
||||
|
||||
# Substitute the values of these vars in conf.pri.in
|
||||
AC_SUBST(QBT_CC)
|
||||
AC_SUBST(QBT_CXX)
|
||||
AC_SUBST(QBT_CONF_INCLUDES)
|
||||
AC_SUBST(QBT_CONF_EXTRA_CFLAGS)
|
||||
AC_SUBST(QBT_ADD_CONFIG)
|
||||
|
||||
2
dist/CMakeLists.txt
vendored
2
dist/CMakeLists.txt
vendored
@@ -1,3 +1,5 @@
|
||||
find_package(Qt5Widgets ${requiredQtVersion}) # to conditionally install desktop-related files
|
||||
|
||||
if (APPLE)
|
||||
add_subdirectory(mac)
|
||||
else (APPLE)
|
||||
|
||||
22
dist/mac/Info.plist
vendored
22
dist/mac/Info.plist
vendored
@@ -2,6 +2,10 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>qBittorrent</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
@@ -21,6 +25,10 @@
|
||||
<array>
|
||||
<string>org.bittorrent.torrent</string>
|
||||
</array>
|
||||
<key>NSExportableTypes</key>
|
||||
<array>
|
||||
<string>org.bittorrent.torrent</string>
|
||||
</array>
|
||||
<key>LSIsAppleDefaultForType</key>
|
||||
<true/>
|
||||
</dict>
|
||||
@@ -28,6 +36,8 @@
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>magnet</string>
|
||||
@@ -45,21 +55,19 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>4.1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>qBit</string>
|
||||
<string>4.1.9</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>@EXECUTABLE@</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.qbittorrent</string>
|
||||
<string>org.qbittorrent.qBittorrent</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>${MACOSX_DEPLOYMENT_TARGET}.0</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>True</string>
|
||||
<key>NSAppleScriptEnabled</key>
|
||||
<string>YES</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2006-2018 The qBittorrent project</string>
|
||||
<string>Copyright © 2006-2019 The qBittorrent project</string>
|
||||
<key>UTExportedTypeDeclarations</key>
|
||||
<array>
|
||||
<dict>
|
||||
|
||||
BIN
dist/mac/qBitTorrentDocument.icns
vendored
BIN
dist/mac/qBitTorrentDocument.icns
vendored
Binary file not shown.
34
dist/unix/CMakeLists.txt
vendored
34
dist/unix/CMakeLists.txt
vendored
@@ -1,36 +1,42 @@
|
||||
if (SYSTEMD)
|
||||
find_package(Systemd)
|
||||
if (SYSTEMD_FOUND)
|
||||
if (NOT Qt5Widgets_FOUND)
|
||||
feature_option(SYSTEMD "Install systemd service file (headless only)" OFF)
|
||||
if (SYSTEMD)
|
||||
if (NOT Systemd_SERVICES_INSTALL_DIR)
|
||||
find_package(Systemd)
|
||||
if (NOT Systemd_FOUND)
|
||||
message(FATAL_ERROR "Could not locate systemd services install dir."
|
||||
" Either pass -DSystemd_SERVICES_INSTALL_DIR=/path/to/systemd/services option or install systemd pkg-config")
|
||||
endif(NOT Systemd_FOUND)
|
||||
endif(NOT Systemd_SERVICES_INSTALL_DIR)
|
||||
set(EXPAND_BINDIR ${CMAKE_INSTALL_FULL_BINDIR})
|
||||
configure_file(systemd/qbittorrent-nox@.service.in ${CMAKE_CURRENT_BINARY_DIR}/qbittorrent-nox@.service @ONLY)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qbittorrent-nox@.service
|
||||
DESTINATION ${SYSTEMD_SERVICES_INSTALL_DIR}
|
||||
DESTINATION ${Systemd_SERVICES_INSTALL_DIR}
|
||||
COMPONENT data)
|
||||
endif(SYSTEMD_FOUND)
|
||||
endif(SYSTEMD)
|
||||
endif(SYSTEMD)
|
||||
endif()
|
||||
|
||||
|
||||
if (GUI)
|
||||
if (Qt5Widgets_FOUND)
|
||||
list(APPEND MAN_FILES ${qBittorrent_SOURCE_DIR}/doc/qbittorrent.1)
|
||||
else (GUI)
|
||||
else (Qt5Widgets_FOUND)
|
||||
list(APPEND MAN_FILES ${qBittorrent_SOURCE_DIR}/doc/qbittorrent-nox.1)
|
||||
endif (GUI)
|
||||
endif (Qt5Widgets_FOUND)
|
||||
|
||||
install(FILES ${MAN_FILES}
|
||||
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
|
||||
COMPONENT doc)
|
||||
|
||||
if (GUI)
|
||||
if (Qt5Widgets_FOUND)
|
||||
install(DIRECTORY menuicons/
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor
|
||||
FILES_MATCHING PATTERN "*.png")
|
||||
|
||||
install(FILES ${qBittorrent_SOURCE_DIR}/src/icons/qbittorrent.desktop
|
||||
install(FILES org.qbittorrent.qBittorrent.desktop
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications/
|
||||
COMPONENT data)
|
||||
|
||||
install(FILES qbittorrent.appdata.xml
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/appdata/
|
||||
install(FILES org.qbittorrent.qBittorrent.appdata.xml
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/metainfo/
|
||||
COMPONENT data)
|
||||
|
||||
install(FILES
|
||||
|
||||
75
dist/unix/org.qbittorrent.qBittorrent.appdata.xml
vendored
Normal file
75
dist/unix/org.qbittorrent.qBittorrent.appdata.xml
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright 2014 sledgehammer999 <sledgehammer999@qbittorrent.org> -->
|
||||
<component type="desktop">
|
||||
<id>org.qbittorrent.qBittorrent</id>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>GPL-2.0 and OpenSSL</project_license>
|
||||
<name>qBittorrent</name>
|
||||
<summary>An open-source Bittorrent client</summary>
|
||||
<description>
|
||||
<p>
|
||||
The qBittorrent project aims to provide an open-source software alternative to µTorrent.
|
||||
Additionally, qBittorrent runs and provides the same features on all major platforms (FreeBSD, Linux, macOS, OS/2, Windows).
|
||||
qBittorrent is based on the Qt toolkit and libtorrent-rasterbar library.
|
||||
</p>
|
||||
<ul>
|
||||
<li>Polished µTorrent-like User Interface</li>
|
||||
<li>
|
||||
Well-integrated and extensible Search Engine
|
||||
<ul>
|
||||
<li>Simultaneous search in many Torrent search sites</li>
|
||||
<li>Category-specific search requests (e.g. Books, Music, Software)</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>RSS feed support with advanced download filters (incl. regex)</li>
|
||||
<li>
|
||||
Many Bittorrent extensions supported:
|
||||
<ul>
|
||||
<li>Magnet links</li>
|
||||
<li>Distributed hash table (DHT), peer exchange protocol (PEX), local peer discovery (LSD)</li>
|
||||
<li>Private torrents</li>
|
||||
<li>Encrypted connections</li>
|
||||
<li>and many more...</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Remote control through Web user interface, written with AJAX</li>
|
||||
<li>Sequential downloading (Download in order)</li>
|
||||
<li>
|
||||
Advanced control over torrents, trackers and peers
|
||||
<ul>
|
||||
<li>Torrents queueing and prioritizing</li>
|
||||
<li>Torrent content selection and prioritizing</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>Bandwidth scheduler</li>
|
||||
<li>Torrent creation tool</li>
|
||||
<li>IP Filtering (eMule & PeerGuardian format compatible)</li>
|
||||
<li>IPv6 compliant</li>
|
||||
<li>UPnP / NAT-PMP port forwarding support</li>
|
||||
<li>Available on all platforms: Windows, Linux, macOS, FreeBSD, OS/2</li>
|
||||
<li>Available in ~70 languages</li>
|
||||
</ul>
|
||||
</description>
|
||||
<launchable type="desktop-id">org.qbittorrent.qBittorrent.desktop</launchable>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image height="675" width="1200">https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_01.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image height="675" width="1200">https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_02.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image height="675" width="1200">https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_03.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image height="675" width="1200">https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_04.png</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<update_contact>sledgehammer999@qbittorrent.org</update_contact>
|
||||
<developer_name>The qBittorrent Project</developer_name>
|
||||
<url type="homepage">https://www.qbittorrent.org/</url>
|
||||
<url type="bugtracker">http://bugs.qbittorrent.org/</url>
|
||||
<url type="donation">https://www.qbittorrent.org/donate</url>
|
||||
<url type="help">http://forum.qbittorrent.org/</url>
|
||||
<url type="translate">https://github.com/qbittorrent/qBittorrent/wiki/How-to-translate-qBittorrent</url>
|
||||
</component>
|
||||
66
dist/unix/qbittorrent.appdata.xml
vendored
66
dist/unix/qbittorrent.appdata.xml
vendored
@@ -1,66 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright 2014 sledgehammer999 <sledgehammer999@qbittorrent.org> -->
|
||||
<component type="desktop">
|
||||
<id>qbittorrent.desktop</id>
|
||||
<metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>GPL-2.0 and OpenSSL</project_license>
|
||||
<name>qBittorrent</name>
|
||||
<summary>A Bittorrent Client</summary>
|
||||
<description>
|
||||
<p>
|
||||
Aiming to be a good alternative to all other bittorrent clients out
|
||||
there, qBittorrent is fast, stable and provides unicode support as well
|
||||
as many other features. Additionally, qBittorrent runs and provides those
|
||||
same features on all major platforms (Linux, Mac OS X, Windows, FreeBSD).
|
||||
</p>
|
||||
<p>
|
||||
It is programmed in C++ / Qt and uses libtorrent (sometimes called
|
||||
libtorrent-rasterbar) by Arvid Norberg. GeoLite data, created by MaxMind,
|
||||
are included in qBittorrent. Its features include:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Polished µTorrent-like User Interface</li>
|
||||
<li>Well-integrated and extensible Search Engine</li>
|
||||
<li>All Bittorrent extensions (DHT, Peer Exchange, Full encryption, Magnet/BitComet URIs, ...)</li>
|
||||
<li>Remote control through a Web user interface</li>
|
||||
<li>Advanced control over trackers, peers and torrents</li>
|
||||
<li>UPnP / NAT-PMP port forwarding support</li>
|
||||
<li>Available in ~25 languages (Unicode support)</li>
|
||||
<li>Torrent creation tool</li>
|
||||
<li>Advanced RSS support with download filters (inc. regex)</li>
|
||||
<li>Bandwidth scheduler</li>
|
||||
<li>IP Filtering (eMule and PeerGuardian compatible)</li>
|
||||
<li>IPv6 compliant</li>
|
||||
<li>Sequential downloading (aka "Download in order")</li>
|
||||
</ul>
|
||||
</description>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image height="675" width="1200">
|
||||
https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_01.png
|
||||
</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image height="675" width="1200">
|
||||
https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_02.png
|
||||
</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image height="675" width="1200">
|
||||
https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_03.png
|
||||
</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<image height="675" width="1200">
|
||||
https://alexpl.fedorapeople.org/AppData/qbittorrent/screens/qbittorrent_04.png
|
||||
</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<url type="homepage">https://www.qbittorrent.org/</url>
|
||||
<update_contact>sledgehammer999@qbittorrent.org</update_contact>
|
||||
<developer_name>The qBittorrent Project</developer_name>
|
||||
<url type="bugtracker">http://bugs.qbittorrent.org/</url>
|
||||
<url type="donation">https://www.qbittorrent.org/donate</url>
|
||||
<url type="help">http://forum.qbittorrent.org/</url>
|
||||
<url type="translate">https://github.com/qbittorrent/qBittorrent/wiki/How-to-translate-qBittorrent</url>
|
||||
</component>
|
||||
6
dist/windows/options.nsi
vendored
6
dist/windows/options.nsi
vendored
@@ -27,7 +27,7 @@ XPStyle on
|
||||
!define CSIDL_LOCALAPPDATA '0x1C' ;Local Application Data path
|
||||
|
||||
; Program specific
|
||||
!define PROG_VERSION "4.1.0"
|
||||
!define PROG_VERSION "4.1.9.1"
|
||||
|
||||
!define MUI_FINISHPAGE_RUN
|
||||
!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun
|
||||
@@ -50,11 +50,11 @@ XPStyle on
|
||||
;Installer Version Information
|
||||
VIAddVersionKey "ProductName" "qBittorrent"
|
||||
VIAddVersionKey "CompanyName" "The qBittorrent project"
|
||||
VIAddVersionKey "LegalCopyright" "Copyright ©2006-2018 The qBittorrent project"
|
||||
VIAddVersionKey "LegalCopyright" "Copyright ©2006-2019 The qBittorrent project"
|
||||
VIAddVersionKey "FileDescription" "qBittorrent - A Bittorrent Client"
|
||||
VIAddVersionKey "FileVersion" "${PROG_VERSION}"
|
||||
|
||||
VIProductVersion "${PROG_VERSION}.0"
|
||||
VIProductVersion "${PROG_VERSION}.1"
|
||||
|
||||
; The default installation directory. It changes depending if we install in the 64bit dir or not.
|
||||
; A caveat of this is if a user has installed a 32bit version and then runs the 64bit installer
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 42
|
||||
#serial 47
|
||||
|
||||
# example boost program (need to pass version)
|
||||
m4_define([_AX_BOOST_BASE_PROGRAM],
|
||||
@@ -113,7 +113,8 @@ AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[
|
||||
dnl are found, e.g. when only header-only libraries are installed!
|
||||
AS_CASE([${host_cpu}],
|
||||
[x86_64],[libsubdirs="lib64 libx32 lib lib64"],
|
||||
[ppc64|s390x|sparc64|aarch64|ppc64le],[libsubdirs="lib64 lib lib64"],
|
||||
[mips*64*],[libsubdirs="lib64 lib32 lib lib64"],
|
||||
[ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64],[libsubdirs="lib64 lib lib64"],
|
||||
[libsubdirs="lib"]
|
||||
)
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
# and this notice are preserved. This file is offered as-is, without any
|
||||
# warranty.
|
||||
|
||||
#serial 19
|
||||
#serial 20
|
||||
|
||||
AC_DEFUN([AX_BOOST_SYSTEM],
|
||||
[
|
||||
@@ -108,7 +108,7 @@ AC_DEFUN([AX_BOOST_SYSTEM],
|
||||
|
||||
fi
|
||||
if test "x$ax_lib" = "x"; then
|
||||
AC_MSG_ERROR(Could not find a version of the library!)
|
||||
AC_MSG_ERROR(Could not find a version of the Boost::System library!)
|
||||
fi
|
||||
if test "x$link_system" = "xno"; then
|
||||
AC_MSG_ERROR(Could not link against $ax_lib !)
|
||||
|
||||
@@ -36,3 +36,16 @@ AC_DEFUN([FIND_QTDBUS],
|
||||
[AC_MSG_RESULT([not found])
|
||||
HAVE_QTDBUS=[false]])
|
||||
])
|
||||
|
||||
# DETECT_CPP11_PROGRAM()
|
||||
# Detects if at least C++11 mode is enabled.
|
||||
# --------------------------------------
|
||||
AC_DEFUN([DETECT_CPP11_PROGRAM],
|
||||
[AC_LANG_PROGRAM([[
|
||||
#ifndef __cplusplus
|
||||
#error "This is not a C++ compiler"
|
||||
#elif __cplusplus < 201103L
|
||||
#error "This is not a C++11 compiler"
|
||||
#endif]],
|
||||
[[]])
|
||||
])
|
||||
|
||||
@@ -3,7 +3,6 @@ TEMPLATE = subdirs
|
||||
SUBDIRS += src
|
||||
|
||||
include(version.pri)
|
||||
include(qm_gen.pri)
|
||||
|
||||
# Make target to create release tarball. Use 'make tarball'
|
||||
tarball.commands += rm -fR ../$${PROJECT_NAME}-$${PROJECT_VERSION}/ &&
|
||||
@@ -18,6 +17,10 @@ tarball.commands += rm -fR $${PROJECT_NAME}-$${PROJECT_VERSION}
|
||||
|
||||
QMAKE_EXTRA_TARGETS += tarball
|
||||
|
||||
# Translations included here (at top level) is to avoid regenerating the .qm files
|
||||
# every time when src.pro is processed
|
||||
include(src/lang/lang.pri)
|
||||
|
||||
# For Qt Creator beautifier
|
||||
DISTFILES += \
|
||||
uncrustify.cfg
|
||||
|
||||
21
qm_gen.pri
21
qm_gen.pri
@@ -1,21 +0,0 @@
|
||||
TS_IN = $$fromfile(src/src.pro,TRANSLATIONS)
|
||||
TS_IN_NOEXT = $$replace(TS_IN,".ts","")
|
||||
|
||||
isEmpty(QMAKE_LRELEASE) {
|
||||
win32:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]\\lrelease.exe
|
||||
else:QMAKE_LRELEASE = $$[QT_INSTALL_BINS]/lrelease
|
||||
unix {
|
||||
equals(QT_MAJOR_VERSION, 5) {
|
||||
!exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease-qt5 }
|
||||
}
|
||||
} else {
|
||||
!exists($$QMAKE_LRELEASE) { QMAKE_LRELEASE = lrelease }
|
||||
}
|
||||
}
|
||||
|
||||
message("Building translations")
|
||||
for(L,TS_IN_NOEXT) {
|
||||
message("Processing $${L}")
|
||||
system("$$QMAKE_LRELEASE -silent src/$${L}.ts -qm src/$${L}.qm")
|
||||
!exists("src/$${L}.qm"):error("Building translations failed, cannot continue")
|
||||
}
|
||||
@@ -1,40 +1,53 @@
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||
set(CMAKE_CXX_STANDARD "11")
|
||||
add_definitions(-DBOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
|
||||
# If C++14 is available, use it as libtorent ABI depends on 11/14 version
|
||||
if (cxx_std_14 IN_LIST CMAKE_CXX_COMPILE_FEATURES)
|
||||
message(STATUS "Building in C++14 mode")
|
||||
set(CMAKE_CXX_STANDARD "14")
|
||||
else()
|
||||
message(STATUS "Building in C++11 mode")
|
||||
set(CMAKE_CXX_STANDARD "11")
|
||||
endif()
|
||||
|
||||
include(MacroQbtCompilerSettings)
|
||||
qbt_set_compiler_options()
|
||||
|
||||
include(MacroLinkQtComponents)
|
||||
include(QbtTargetSources)
|
||||
|
||||
find_package(Boost ${requiredBoostVersion} REQUIRED)
|
||||
find_package(LibtorrentRasterbar REQUIRED)
|
||||
|
||||
# Qt
|
||||
list(APPEND QBT_QT_COMPONENTS Core Network Xml)
|
||||
if (GUI)
|
||||
list (APPEND QBT_QT_COMPONENTS Gui Svg Widgets)
|
||||
if (WIN32)
|
||||
list (APPEND QBT_QT_COMPONENTS WinExtras)
|
||||
endif(WIN32)
|
||||
if (APPLE)
|
||||
list (APPEND QBT_GUI_OPTIONAL_LINK_LIBRARIES objc)
|
||||
list (APPEND QBT_QT_COMPONENTS MacExtras)
|
||||
endif (APPLE)
|
||||
endif (GUI)
|
||||
if (DBUS)
|
||||
list (APPEND QBT_QT_COMPONENTS DBus)
|
||||
endif (DBUS)
|
||||
find_package(Qt5 5.5.1 COMPONENTS ${QBT_QT_COMPONENTS} REQUIRED)
|
||||
if (Boost_VERSION VERSION_LESS 106000)
|
||||
add_definitions(-DBOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
endif()
|
||||
|
||||
if (GUI AND APPLE)
|
||||
# Fix MOC inability to detect macOS. This seems to only affect cmake.
|
||||
# Relevant issue: https://bugreports.qt.io/browse/QTBUG-58325
|
||||
set(CMAKE_AUTOMOC_MOC_OPTIONS ${CMAKE_AUTOMOC_MOC_OPTIONS} -DQ_OS_MAC)
|
||||
endif ()
|
||||
find_package(Qt5 ${requiredQtVersion} REQUIRED COMPONENTS Core Network Xml LinguistTools)
|
||||
find_package(Qt5Widgets ${requiredQtVersion})
|
||||
if (Qt5Widgets_FOUND)
|
||||
find_package(Qt5DBus ${requiredQtVersion})
|
||||
else()
|
||||
add_definitions(-DDISABLE_GUI)
|
||||
endif()
|
||||
|
||||
set_package_properties(Qt5Widgets PROPERTIES
|
||||
DESCRIPTION "Set of components for creating classic desktop-style UIs for the Qt5 framework"
|
||||
PURPOSE "Enables qBittorrent GUI. Unneeded for headless configuration."
|
||||
TYPE OPTIONAL
|
||||
)
|
||||
|
||||
set_package_properties(Qt5DBus PROPERTIES
|
||||
DESCRIPTION "Qt5 module for inter-process communication over the D-Bus protocol"
|
||||
PURPOSE "Enables communication with other system components (e.g. notification service) via D-Bus. "
|
||||
TYPE RECOMMENDED
|
||||
)
|
||||
|
||||
set(CMAKE_AUTOMOC True)
|
||||
list(APPEND CMAKE_AUTORCC_OPTIONS -compress 9 -threshold 5)
|
||||
if (APPLE)
|
||||
# Workaround CMake bug (autogen does not pass required parameters to moc)
|
||||
# Relevant issue: https://gitlab.kitware.com/cmake/cmake/issues/18041
|
||||
list(APPEND CMAKE_AUTOMOC_MOC_OPTIONS -DQ_OS_MAC -DQ_OS_DARWIN)
|
||||
endif ()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
@@ -43,56 +56,34 @@ add_definitions(-DQT_NO_CAST_TO_ASCII)
|
||||
# Efficient construction for QString & QByteArray (Qt >= 4.8)
|
||||
add_definitions(-DQT_USE_QSTRINGBUILDER)
|
||||
|
||||
if (NOT GUI)
|
||||
add_definitions(-DDISABLE_GUI -DDISABLE_COUNTRIES_RESOLUTION)
|
||||
endif (NOT GUI)
|
||||
|
||||
if (NOT WEBUI)
|
||||
add_definitions(-DDISABLE_WEBUI)
|
||||
endif (NOT WEBUI)
|
||||
|
||||
if (STACKTRACE)
|
||||
add_definitions(-DSTACKTRACE)
|
||||
endif(STACKTRACE)
|
||||
# nogui {
|
||||
# TARGET = qbittorrent-nox
|
||||
# } else {
|
||||
# CONFIG(static) {
|
||||
# DEFINES += QBT_STATIC_QT
|
||||
# QTPLUGIN += qico
|
||||
# }
|
||||
# TARGET = qbittorrent
|
||||
# }
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
add_compile_options(-Wformat -Wformat-security)
|
||||
endif ()
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
if (CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||
message(STATUS "Project is built in DEBUG mode.")
|
||||
else (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
else()
|
||||
message(STATUS "Project is built in RELEASE mode.")
|
||||
message(STATUS "Disabling debug output.")
|
||||
add_definitions(-DQT_NO_DEBUG_OUTPUT)
|
||||
endif (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
|
||||
set(QBT_USE_GUI ${GUI})
|
||||
set(QBT_USE_WEBUI ${WEBUI})
|
||||
endif()
|
||||
|
||||
configure_file(config.h.cmakein ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
|
||||
if (SYSTEM_QTSINGLEAPPLICATION)
|
||||
find_package(QtSingleApplication REQUIRED)
|
||||
else (SYSTEM_QTSINGLEAPPLICATION)
|
||||
find_package(QtSingleApplication)
|
||||
set_package_properties(QtSingleApplication PROPERTIES
|
||||
URL "https://code.qt.io/cgit/qt-solutions/qt-solutions.git/"
|
||||
DESCRIPTION "Qt library to start applications only once per user"
|
||||
TYPE RECOMMENDED
|
||||
PURPOSE "Use the system qtsingleapplication library or shipped one otherwise"
|
||||
)
|
||||
|
||||
if (NOT QtSingleApplication_FOUND)
|
||||
add_subdirectory(app/qtsingleapplication)
|
||||
endif (SYSTEM_QTSINGLEAPPLICATION)
|
||||
endif ()
|
||||
|
||||
add_subdirectory(app)
|
||||
add_subdirectory(base)
|
||||
|
||||
if (GUI)
|
||||
if (Qt5Widgets_FOUND)
|
||||
add_subdirectory(gui)
|
||||
endif (GUI)
|
||||
endif ()
|
||||
|
||||
if (WEBUI)
|
||||
add_subdirectory(webui)
|
||||
|
||||
@@ -1,43 +1,41 @@
|
||||
project(qbt_executable)
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
set(QBT_APP_HEADERS
|
||||
add_executable(qBittorrent
|
||||
application.h
|
||||
cmdoptions.h
|
||||
filelogger.h
|
||||
)
|
||||
|
||||
set(QBT_APP_SOURCES
|
||||
upgrade.h
|
||||
application.cpp
|
||||
cmdoptions.cpp
|
||||
filelogger.cpp
|
||||
main.cpp
|
||||
)
|
||||
|
||||
target_include_directories(qBittorrent PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||
target_link_libraries(qBittorrent
|
||||
PRIVATE
|
||||
qbt_base
|
||||
)
|
||||
|
||||
set_target_properties(qBittorrent
|
||||
PROPERTIES
|
||||
AUTOUIC True
|
||||
AUTORCC True
|
||||
MACOSX_BUNDLE True
|
||||
)
|
||||
|
||||
# translations
|
||||
include(QbtTranslations)
|
||||
|
||||
file(GLOB QBT_TS_FILES ../lang/*.ts)
|
||||
get_filename_component(QBT_QM_FILES_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/../lang" ABSOLUTE)
|
||||
set_source_files_properties(${QBT_TS_FILES} PROPERTIES OUTPUT_LOCATION "${QBT_QM_FILES_BINARY_DIR}")
|
||||
qbt_add_translations(qBittorrent QRC_FILE "../lang/lang.qrc" TS_FILES ${QBT_TS_FILES})
|
||||
|
||||
find_package(Qt5 COMPONENTS LinguistTools REQUIRED)
|
||||
qt5_add_translation(QBT_QM_FILES ${QBT_TS_FILES})
|
||||
|
||||
get_filename_component(_lang_qrc_src "${CMAKE_CURRENT_SOURCE_DIR}/../lang.qrc" ABSOLUTE)
|
||||
get_filename_component(_lang_qrc_dst "${CMAKE_CURRENT_BINARY_DIR}/../lang.qrc" ABSOLUTE)
|
||||
get_filename_component(_lang_qrc_dst_dir "${CMAKE_CURRENT_BINARY_DIR}/../" ABSOLUTE)
|
||||
|
||||
message(STATUS "copying ${_lang_qrc_src} -> ${_lang_qrc_dst}")
|
||||
file(COPY ${_lang_qrc_src} DESTINATION ${_lang_qrc_dst_dir})
|
||||
|
||||
set_source_files_properties("${_lang_qrc_dst}" PROPERTIES GENERATED True)
|
||||
foreach(qm_file ${QBT_QM_FILES})
|
||||
set_source_files_properties("${_lang_qrc_dst}" PROPERTIES OBJECT_DEPENDS ${qm_file})
|
||||
endforeach()
|
||||
if (WEBUI)
|
||||
file(GLOB QBT_WEBUI_TS_FILES ../webui/www/translations/*.ts)
|
||||
qbt_add_translations(qBittorrent QRC_FILE "../webui/www/translations/webui_translations.qrc" TS_FILES ${QBT_WEBUI_TS_FILES})
|
||||
endif()
|
||||
|
||||
set(QBT_APP_RESOURCES
|
||||
../icons.qrc
|
||||
../searchengine.qrc
|
||||
"${_lang_qrc_dst}"
|
||||
../icons/icons.qrc
|
||||
../searchengine/searchengine.qrc
|
||||
)
|
||||
|
||||
# With AUTORCC rcc is ran by cmake before language files are generated,
|
||||
@@ -46,51 +44,41 @@ qt5_add_resources(QBT_APP_RESOURCE_SOURCE ${QBT_APP_RESOURCES})
|
||||
|
||||
if (WIN32)
|
||||
if (MINGW)
|
||||
list (APPEND QBT_APP_SOURCES ../qbittorrent_mingw.rc)
|
||||
target_sources(qBittorrent PRIVATE ../qbittorrent_mingw.rc)
|
||||
else (MINGW)
|
||||
list (APPEND QBT_APP_SOURCES ../qbittorrent.rc)
|
||||
target_sources(qBittorrent PRIVATE ../qbittorrent.rc)
|
||||
endif (MINGW)
|
||||
list(APPEND QBT_APP_SOURCES ../qbittorrent.exe.manifest)
|
||||
target_sources(qBittorrent PRIVATE ../qbittorrent.exe.manifest)
|
||||
endif (WIN32)
|
||||
|
||||
if (STACKTRACE)
|
||||
if (UNIX)
|
||||
list(APPEND QBT_APP_HEADERS stacktrace.h)
|
||||
target_sources(qBittorrent PRIVATE stacktrace.h)
|
||||
else (UNIX)
|
||||
list(APPEND QBT_APP_HEADERS stacktrace_win.h)
|
||||
if (GUI)
|
||||
list(APPEND QBT_APP_HEADERS stacktrace_win_dlg.h)
|
||||
endif (GUI)
|
||||
target_sources(qBittorrent PRIVATE stacktrace_win.h)
|
||||
if (Qt5Widgets_FOUND)
|
||||
target_sources(qBittorrent PRIVATE stacktracedialog.h)
|
||||
endif (Qt5Widgets_FOUND)
|
||||
endif (UNIX)
|
||||
endif (STACKTRACE)
|
||||
|
||||
# usesystemqtsingleapplication {
|
||||
# nogui {
|
||||
# CONFIG += qtsinglecoreapplication
|
||||
# } else {
|
||||
# CONFIG += qtsingleapplication
|
||||
# }
|
||||
# } else {
|
||||
# nogui {
|
||||
# include(qtsingleapplication/qtsinglecoreapplication.pri)
|
||||
# } else {
|
||||
# include(qtsingleapplication/qtsingleapplication.pri)
|
||||
# }
|
||||
# }
|
||||
|
||||
# upgrade code
|
||||
list(APPEND QBT_APP_HEADERS upgrade.h)
|
||||
list(APPEND QBT_TARGET_LIBRARIES qbt_base)
|
||||
|
||||
if (GUI)
|
||||
list(APPEND QBT_TARGET_LIBRARIES qbt_searchengine qbt_gui)
|
||||
include_directories(../gui
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../gui
|
||||
if (Qt5Widgets_FOUND)
|
||||
target_link_libraries(qBittorrent PRIVATE qbt_searchengine qbt_gui)
|
||||
set_target_properties(qBittorrent
|
||||
PROPERTIES
|
||||
OUTPUT_NAME qbittorrent
|
||||
WIN32_EXECUTABLE True
|
||||
)
|
||||
endif (GUI)
|
||||
else(Qt5Widgets_FOUND)
|
||||
set_target_properties(qBittorrent
|
||||
PROPERTIES
|
||||
OUTPUT_NAME qbittorrent-nox
|
||||
)
|
||||
endif (Qt5Widgets_FOUND)
|
||||
|
||||
if (WEBUI)
|
||||
list(APPEND QBT_TARGET_LIBRARIES qbt_webui)
|
||||
target_link_libraries(qBittorrent PRIVATE qbt_webui)
|
||||
endif (WEBUI)
|
||||
|
||||
# we have to include resources into the bundle
|
||||
@@ -142,30 +130,11 @@ if (APPLE)
|
||||
PROPERTIES MACOSX_PACKAGE_LOCATION translations)
|
||||
endif (APPLE)
|
||||
|
||||
add_executable(qBittorrent ${QBT_APP_HEADERS} ${QBT_APP_SOURCES} ${QBT_QM_FILES} ${QBT_APP_RESOURCE_SOURCE})
|
||||
if (GUI)
|
||||
set_target_properties(qBittorrent
|
||||
PROPERTIES
|
||||
OUTPUT_NAME qbittorrent
|
||||
WIN32_EXECUTABLE True
|
||||
)
|
||||
else (GUI)
|
||||
set_target_properties(qBittorrent
|
||||
PROPERTIES
|
||||
OUTPUT_NAME qbittorrent-nox
|
||||
)
|
||||
endif (GUI)
|
||||
|
||||
set_target_properties(qBittorrent
|
||||
PROPERTIES
|
||||
AUTOUIC True
|
||||
AUTORCC True
|
||||
MACOSX_BUNDLE True
|
||||
)
|
||||
target_sources(qBittorrent PRIVATE ${QBT_QM_FILES} ${QBT_APP_RESOURCE_SOURCE})
|
||||
|
||||
get_target_property(QBT_EXECUTABLE_NAME qBittorrent OUTPUT_NAME)
|
||||
|
||||
target_link_libraries(qBittorrent ${QBT_TARGET_LIBRARIES} QtSingleApplication::QtSingleApplication)
|
||||
target_link_libraries(qBittorrent PRIVATE ${QBT_TARGET_LIBRARIES} QtSingleApplication::QtSingleApplication)
|
||||
|
||||
if (APPLE)
|
||||
set(qbt_BUNDLE_NAME ${QBT_EXECUTABLE_NAME})
|
||||
@@ -186,6 +155,7 @@ install(TARGETS qBittorrent
|
||||
BUNDLE DESTINATION .
|
||||
COMPONENT runtime)
|
||||
|
||||
if (GUI AND APPLE)
|
||||
if (Qt5Widgets_FOUND AND APPLE)
|
||||
find_package(Qt5Svg REQUIRED)
|
||||
include(bundle)
|
||||
endif (GUI AND APPLE)
|
||||
endif (Qt5Widgets_FOUND AND APPLE)
|
||||
|
||||
@@ -32,8 +32,8 @@ stacktrace {
|
||||
else {
|
||||
HEADERS += $$PWD/stacktrace_win.h
|
||||
!nogui {
|
||||
HEADERS += $$PWD/stacktrace_win_dlg.h
|
||||
FORMS += $$PWD/stacktrace_win_dlg.ui
|
||||
HEADERS += $$PWD/stacktracedialog.h
|
||||
FORMS += $$PWD/stacktracedialog.ui
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,20 +31,38 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <memory>
|
||||
#endif
|
||||
|
||||
#include <QAtomicInt>
|
||||
#include <QDebug>
|
||||
#include <QFileInfo>
|
||||
#include <QLibraryInfo>
|
||||
#include <QLocale>
|
||||
#include <QProcess>
|
||||
#include <QSysInfo>
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <memory>
|
||||
#include <Shellapi.h>
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
#include <QMessageBox>
|
||||
#ifdef Q_OS_WIN
|
||||
#include <QSessionManager>
|
||||
#include <QSharedMemory>
|
||||
#endif // Q_OS_WIN
|
||||
#ifdef Q_OS_MAC
|
||||
#include <QFileOpenEvent>
|
||||
#endif // Q_OS_MAC
|
||||
#include "addnewtorrentdialog.h"
|
||||
#include "gui/guiiconprovider.h"
|
||||
#include "mainwindow.h"
|
||||
#include "shutdownconfirmdialog.h"
|
||||
#else // DISABLE_GUI
|
||||
#include <cstdio>
|
||||
#endif // DISABLE_GUI
|
||||
|
||||
#include "base/bittorrent/session.h"
|
||||
#include "base/bittorrent/torrenthandle.h"
|
||||
#include "base/exceptions.h"
|
||||
#include "base/iconprovider.h"
|
||||
#include "base/logger.h"
|
||||
#include "base/net/downloadmanager.h"
|
||||
@@ -56,34 +74,13 @@
|
||||
#include "base/rss/rss_autodownloader.h"
|
||||
#include "base/rss/rss_session.h"
|
||||
#include "base/scanfoldersmodel.h"
|
||||
#include "base/search/searchpluginmanager.h"
|
||||
#include "base/settingsstorage.h"
|
||||
#include "base/utils/fs.h"
|
||||
#include "base/utils/misc.h"
|
||||
#include "base/utils/string.h"
|
||||
#include "filelogger.h"
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
#ifdef Q_OS_WIN
|
||||
#include <QSessionManager>
|
||||
#include <QSharedMemory>
|
||||
#endif // Q_OS_WIN
|
||||
#ifdef Q_OS_MAC
|
||||
#include <QFileOpenEvent>
|
||||
#include <QFont>
|
||||
#include <QUrl>
|
||||
#endif // Q_OS_MAC
|
||||
#include "addnewtorrentdialog.h"
|
||||
#include "gui/guiiconprovider.h"
|
||||
#include "mainwindow.h"
|
||||
#include "shutdownconfirmdlg.h"
|
||||
#else // DISABLE_GUI
|
||||
#include <cstdio>
|
||||
#endif // DISABLE_GUI
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <Shellapi.h>
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_WEBUI
|
||||
#include "webui/webui.h"
|
||||
#endif
|
||||
@@ -93,7 +90,7 @@ namespace
|
||||
#define SETTINGS_KEY(name) "Application/" name
|
||||
|
||||
// FileLogger properties keys
|
||||
#define FILELOGGER_SETTINGS_KEY(name) SETTINGS_KEY("FileLogger/") name
|
||||
#define FILELOGGER_SETTINGS_KEY(name) QStringLiteral(SETTINGS_KEY("FileLogger/") name)
|
||||
const QString KEY_FILELOGGER_ENABLED = FILELOGGER_SETTINGS_KEY("Enabled");
|
||||
const QString KEY_FILELOGGER_PATH = FILELOGGER_SETTINGS_KEY("Path");
|
||||
const QString KEY_FILELOGGER_BACKUP = FILELOGGER_SETTINGS_KEY("Backup");
|
||||
@@ -102,13 +99,13 @@ namespace
|
||||
const QString KEY_FILELOGGER_AGE = FILELOGGER_SETTINGS_KEY("Age");
|
||||
const QString KEY_FILELOGGER_AGETYPE = FILELOGGER_SETTINGS_KEY("AgeType");
|
||||
|
||||
//just a shortcut
|
||||
// just a shortcut
|
||||
inline SettingsStorage *settings() { return SettingsStorage::instance(); }
|
||||
|
||||
const QString LOG_FOLDER("logs");
|
||||
const char PARAMS_SEPARATOR[] = "|";
|
||||
const QString LOG_FOLDER = QStringLiteral("logs");
|
||||
const QChar PARAMS_SEPARATOR = '|';
|
||||
|
||||
const QString DEFAULT_PORTABLE_MODE_PROFILE_DIR = QLatin1String("profile");
|
||||
const QString DEFAULT_PORTABLE_MODE_PROFILE_DIR = QStringLiteral("profile");
|
||||
|
||||
const int MIN_FILELOG_SIZE = 1024; // 1KiB
|
||||
const int MAX_FILELOG_SIZE = 1000 * 1024 * 1024; // 1000MiB
|
||||
@@ -127,6 +124,7 @@ Application::Application(const QString &id, int &argc, char **argv)
|
||||
qRegisterMetaType<Log::Msg>("Log::Msg");
|
||||
|
||||
setApplicationName("qBittorrent");
|
||||
setOrganizationDomain("qbittorrent.org");
|
||||
validateCommandLineParameters();
|
||||
|
||||
QString profileDir = m_commandLineArgs.portableMode
|
||||
@@ -148,14 +146,17 @@ Application::Application(const QString &id, int &argc, char **argv)
|
||||
#if !defined(DISABLE_GUI)
|
||||
setAttribute(Qt::AA_UseHighDpiPixmaps, true); // opt-in to the high DPI pixmap support
|
||||
setQuitOnLastWindowClosed(false);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
|
||||
setDesktopFileName("org.qbittorrent.qBittorrent");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WIN) && !defined(DISABLE_GUI)
|
||||
connect(this, SIGNAL(commitDataRequest(QSessionManager &)), this, SLOT(shutdownCleanup(QSessionManager &)), Qt::DirectConnection);
|
||||
connect(this, &QGuiApplication::commitDataRequest, this, &Application::shutdownCleanup, Qt::DirectConnection);
|
||||
#endif
|
||||
|
||||
connect(this, SIGNAL(messageReceived(const QString &)), SLOT(processMessage(const QString &)));
|
||||
connect(this, SIGNAL(aboutToQuit()), SLOT(cleanup()));
|
||||
connect(this, &Application::messageReceived, this, &Application::processMessage);
|
||||
connect(this, &QCoreApplication::aboutToQuit, this, &Application::cleanup);
|
||||
|
||||
if (isFileLoggerEnabled())
|
||||
m_fileLogger = new FileLogger(fileLoggerPath(), isFileLoggerBackup(), fileLoggerMaxSize(), isFileLoggerDeleteOld(), fileLoggerAge(), static_cast<FileLogger::FileLogAgeType>(fileLoggerAgeType()));
|
||||
@@ -261,17 +262,17 @@ void Application::setFileLoggerAge(const int value)
|
||||
int Application::fileLoggerAgeType() const
|
||||
{
|
||||
int val = settings()->loadValue(KEY_FILELOGGER_AGETYPE, 1).toInt();
|
||||
return (val < 0 || val > 2) ? 1 : val;
|
||||
return ((val < 0) || (val > 2)) ? 1 : val;
|
||||
}
|
||||
|
||||
void Application::setFileLoggerAgeType(const int value)
|
||||
{
|
||||
settings()->storeValue(KEY_FILELOGGER_AGETYPE, (value < 0 || value > 2) ? 1 : value);
|
||||
settings()->storeValue(KEY_FILELOGGER_AGETYPE, ((value < 0) || (value > 2)) ? 1 : value);
|
||||
}
|
||||
|
||||
void Application::processMessage(const QString &message)
|
||||
{
|
||||
QStringList params = message.split(QLatin1String(PARAMS_SEPARATOR), QString::SkipEmptyParts);
|
||||
QStringList params = message.split(PARAMS_SEPARATOR, QString::SkipEmptyParts);
|
||||
// If Application is not running (i.e., other
|
||||
// components are not ready) store params
|
||||
if (m_running)
|
||||
@@ -290,9 +291,21 @@ void Application::runExternalProgram(const BitTorrent::TorrentHandle *torrent) c
|
||||
std::sort(tags.begin(), tags.end(), Utils::String::naturalLessThan<Qt::CaseInsensitive>);
|
||||
program.replace("%G", tags.join(','));
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
const auto chopPathSep = [](const QString &str) -> QString
|
||||
{
|
||||
if (str.endsWith('\\'))
|
||||
return str.mid(0, (str.length() -1));
|
||||
return str;
|
||||
};
|
||||
program.replace("%F", chopPathSep(Utils::Fs::toNativePath(torrent->contentPath())));
|
||||
program.replace("%R", chopPathSep(Utils::Fs::toNativePath(torrent->rootPath())));
|
||||
program.replace("%D", chopPathSep(Utils::Fs::toNativePath(torrent->savePath())));
|
||||
#else
|
||||
program.replace("%F", Utils::Fs::toNativePath(torrent->contentPath()));
|
||||
program.replace("%R", Utils::Fs::toNativePath(torrent->rootPath()));
|
||||
program.replace("%D", Utils::Fs::toNativePath(torrent->savePath()));
|
||||
#endif
|
||||
program.replace("%C", QString::number(torrent->filesCount()));
|
||||
program.replace("%Z", QString::number(torrent->totalSize()));
|
||||
program.replace("%T", torrent->currentTracker());
|
||||
@@ -301,9 +314,7 @@ void Application::runExternalProgram(const BitTorrent::TorrentHandle *torrent) c
|
||||
Logger *logger = Logger::instance();
|
||||
logger->addMessage(tr("Torrent: %1, running external program, command: %2").arg(torrent->name(), program));
|
||||
|
||||
#if defined(Q_OS_UNIX)
|
||||
QProcess::startDetached(QLatin1String("/bin/sh"), {QLatin1String("-c"), program});
|
||||
#else
|
||||
#if defined(Q_OS_WIN)
|
||||
std::unique_ptr<wchar_t[]> programWchar(new wchar_t[program.length() + 1] {});
|
||||
program.toWCharArray(programWchar.get());
|
||||
|
||||
@@ -320,18 +331,24 @@ void Application::runExternalProgram(const BitTorrent::TorrentHandle *torrent) c
|
||||
QProcess::startDetached(QString::fromWCharArray(args[0]), argList);
|
||||
|
||||
::LocalFree(args);
|
||||
#else
|
||||
// Cannot give users shell environment by default, as doing so could
|
||||
// enable command injection via torrent name and other arguments
|
||||
// (especially when some automated download mechanism has been setup).
|
||||
// See: https://github.com/qbittorrent/qBittorrent/issues/10925
|
||||
QProcess::startDetached(program);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Application::sendNotificationEmail(const BitTorrent::TorrentHandle *torrent)
|
||||
{
|
||||
// Prepare mail content
|
||||
const QString content = tr("Torrent name: %1").arg(torrent->name()) + "\n"
|
||||
+ tr("Torrent size: %1").arg(Utils::Misc::friendlyUnit(torrent->wantedSize())) + "\n"
|
||||
const QString content = tr("Torrent name: %1").arg(torrent->name()) + '\n'
|
||||
+ tr("Torrent size: %1").arg(Utils::Misc::friendlyUnit(torrent->wantedSize())) + '\n'
|
||||
+ tr("Save path: %1").arg(torrent->savePath()) + "\n\n"
|
||||
+ tr("The torrent was downloaded in %1.", "The torrent was downloaded in 1 hour and 20 seconds")
|
||||
.arg(Utils::Misc::userFriendlyDuration(torrent->activeTime())) + "\n\n\n"
|
||||
+ tr("Thank you for using qBittorrent.") + "\n";
|
||||
+ tr("Thank you for using qBittorrent.") + '\n';
|
||||
|
||||
// Send the notification email
|
||||
const Preferences *pref = Preferences::instance();
|
||||
@@ -382,7 +399,7 @@ void Application::allTorrentsFinished()
|
||||
// do nothing & skip confirm
|
||||
}
|
||||
else {
|
||||
if (!ShutdownConfirmDlg::askForConfirmation(m_window, action)) return;
|
||||
if (!ShutdownConfirmDialog::askForConfirmation(m_window, action)) return;
|
||||
}
|
||||
#endif // DISABLE_GUI
|
||||
|
||||
@@ -403,7 +420,7 @@ void Application::allTorrentsFinished()
|
||||
|
||||
bool Application::sendParams(const QStringList ¶ms)
|
||||
{
|
||||
return sendMessage(params.join(QLatin1String(PARAMS_SEPARATOR)));
|
||||
return sendMessage(params.join(PARAMS_SEPARATOR));
|
||||
}
|
||||
|
||||
// As program parameters, we can get paths or urls.
|
||||
@@ -421,7 +438,7 @@ void Application::processParams(const QStringList ¶ms)
|
||||
BitTorrent::AddTorrentParams torrentParams;
|
||||
TriStateBool skipTorrentDialog;
|
||||
|
||||
foreach (QString param, params) {
|
||||
for (QString param : params) {
|
||||
param = param.trimmed();
|
||||
|
||||
// Process strings indicating options specified by the user.
|
||||
@@ -488,30 +505,46 @@ int Application::exec(const QStringList ¶ms)
|
||||
GuiIconProvider::initInstance();
|
||||
#endif
|
||||
|
||||
BitTorrent::Session::initInstance();
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(torrentFinished(BitTorrent::TorrentHandle *const)), SLOT(torrentFinished(BitTorrent::TorrentHandle *const)));
|
||||
connect(BitTorrent::Session::instance(), SIGNAL(allTorrentsFinished()), SLOT(allTorrentsFinished()), Qt::QueuedConnection);
|
||||
try {
|
||||
BitTorrent::Session::initInstance();
|
||||
connect(BitTorrent::Session::instance(), &BitTorrent::Session::torrentFinished, this, &Application::torrentFinished);
|
||||
connect(BitTorrent::Session::instance(), &BitTorrent::Session::allTorrentsFinished, this, &Application::allTorrentsFinished, Qt::QueuedConnection);
|
||||
|
||||
#ifndef DISABLE_COUNTRIES_RESOLUTION
|
||||
Net::GeoIPManager::initInstance();
|
||||
Net::GeoIPManager::initInstance();
|
||||
#endif
|
||||
ScanFoldersModel::initInstance(this);
|
||||
ScanFoldersModel::initInstance(this);
|
||||
|
||||
#ifndef DISABLE_WEBUI
|
||||
m_webui = new WebUI;
|
||||
m_webui = new WebUI;
|
||||
#ifdef DISABLE_GUI
|
||||
if (m_webui->isErrored())
|
||||
return 1;
|
||||
connect(m_webui, &WebUI::fatalError, this, []() { QCoreApplication::exit(1); });
|
||||
if (m_webui->isErrored())
|
||||
return 1;
|
||||
connect(m_webui, &WebUI::fatalError, this, []() { QCoreApplication::exit(1); });
|
||||
#endif // DISABLE_GUI
|
||||
#endif // DISABLE_WEBUI
|
||||
|
||||
new RSS::Session; // create RSS::Session singleton
|
||||
new RSS::AutoDownloader; // create RSS::AutoDownloader singleton
|
||||
new RSS::Session; // create RSS::Session singleton
|
||||
new RSS::AutoDownloader; // create RSS::AutoDownloader singleton
|
||||
}
|
||||
catch (const RuntimeError &err) {
|
||||
#ifdef DISABLE_GUI
|
||||
fprintf(stderr, "%s", err.what());
|
||||
#else
|
||||
QMessageBox msgBox;
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setText(tr("Application failed to start."));
|
||||
msgBox.setInformativeText(err.message());
|
||||
msgBox.show(); // Need to be shown or to moveToCenter does not work
|
||||
msgBox.move(Utils::Misc::screenCenter(&msgBox));
|
||||
msgBox.exec();
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef DISABLE_GUI
|
||||
#ifndef DISABLE_WEBUI
|
||||
Preferences* const pref = Preferences::instance();
|
||||
Preferences *const pref = Preferences::instance();
|
||||
// Display some information to the user
|
||||
const QString mesg = QString("\n******** %1 ********\n").arg(tr("Information"))
|
||||
+ tr("To control qBittorrent, access the Web UI at %1")
|
||||
@@ -607,7 +640,7 @@ bool Application::notify(QObject *receiver, QEvent *event)
|
||||
|
||||
void Application::initializeTranslation()
|
||||
{
|
||||
Preferences* const pref = Preferences::instance();
|
||||
Preferences *const pref = Preferences::instance();
|
||||
// Load translation
|
||||
QString localeStr = pref->getLocale();
|
||||
|
||||
@@ -660,7 +693,7 @@ void Application::shutdownCleanup(QSessionManager &manager)
|
||||
// According to the qt docs we shouldn't call quit() inside a slot.
|
||||
// aboutToQuit() is never emitted if the user hits "Cancel" in
|
||||
// the above dialog.
|
||||
QTimer::singleShot(0, qApp, SLOT(quit()));
|
||||
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -673,7 +706,7 @@ void Application::cleanup()
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
if (m_window) {
|
||||
// Hide the window and not leave it on screen as
|
||||
// Hide the window and don't leave it on screen as
|
||||
// unresponsive. Also for Windows take the WinId
|
||||
// after it's hidden, because hide() may cause a
|
||||
// WinId change.
|
||||
@@ -717,6 +750,7 @@ void Application::cleanup()
|
||||
delete m_fileLogger;
|
||||
Logger::freeInstance();
|
||||
IconProvider::freeInstance();
|
||||
SearchPluginManager::freeInstance();
|
||||
Utils::Fs::removeDirRecursive(Utils::Fs::tempPath());
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
|
||||
@@ -40,15 +40,13 @@ typedef QtSingleApplication BaseApplication;
|
||||
class MainWindow;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QSessionManager;
|
||||
QT_END_NAMESPACE
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
#else
|
||||
#include "qtsinglecoreapplication.h"
|
||||
typedef QtSingleCoreApplication BaseApplication;
|
||||
#endif
|
||||
#endif // DISABLE_GUI
|
||||
|
||||
#include "base/utils/misc.h"
|
||||
#include "cmdoptions.h"
|
||||
@@ -110,9 +108,9 @@ public:
|
||||
protected:
|
||||
#ifndef DISABLE_GUI
|
||||
#ifdef Q_OS_MAC
|
||||
bool event(QEvent *);
|
||||
bool event(QEvent *) override;
|
||||
#endif
|
||||
bool notify(QObject* receiver, QEvent* event) override;
|
||||
bool notify(QObject *receiver, QEvent *event) override;
|
||||
#endif
|
||||
|
||||
private slots:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2016 Eugene Shalygin <eugene.shalygin@gmail.com>
|
||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
* Copyright (C) 2006 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
|
||||
@@ -26,8 +26,6 @@
|
||||
* 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 "cmdoptions.h"
|
||||
@@ -43,6 +41,7 @@
|
||||
#include <QMessageBox>
|
||||
#endif
|
||||
|
||||
#include "base/global.h"
|
||||
#include "base/utils/misc.h"
|
||||
#include "base/utils/string.h"
|
||||
|
||||
@@ -100,7 +99,7 @@ namespace
|
||||
};
|
||||
|
||||
// Boolean option.
|
||||
class BoolOption: protected Option
|
||||
class BoolOption : protected Option
|
||||
{
|
||||
public:
|
||||
constexpr BoolOption(const char *name, char shortcut = 0)
|
||||
@@ -118,7 +117,7 @@ namespace
|
||||
{
|
||||
QString val = env.value(envVarName());
|
||||
// we accept "1" and "true" (upper or lower cased) as boolean 'true' values
|
||||
return (val == QLatin1String("1") || val.toUpper() == QLatin1String("TRUE"));
|
||||
return ((val == QLatin1String("1")) || (val.toUpper() == QLatin1String("TRUE")));
|
||||
}
|
||||
|
||||
QString usage() const
|
||||
@@ -137,7 +136,7 @@ namespace
|
||||
}
|
||||
|
||||
// Option with string value. May not have a shortcut
|
||||
struct StringOption: protected Option
|
||||
struct StringOption : protected Option
|
||||
{
|
||||
public:
|
||||
constexpr StringOption(const char *name)
|
||||
@@ -184,7 +183,7 @@ namespace
|
||||
}
|
||||
|
||||
// Option with integer value. May not have a shortcut
|
||||
class IntOption: protected StringOption
|
||||
class IntOption : protected StringOption
|
||||
{
|
||||
public:
|
||||
constexpr IntOption(const char *name)
|
||||
@@ -230,7 +229,7 @@ namespace
|
||||
|
||||
// Option that is explicitly set to true or false, and whose value is undefined when unspecified.
|
||||
// May not have a shortcut.
|
||||
class TriStateBoolOption: protected Option
|
||||
class TriStateBoolOption : protected Option
|
||||
{
|
||||
public:
|
||||
constexpr TriStateBoolOption(const char *name, bool defaultValue)
|
||||
@@ -260,10 +259,10 @@ namespace
|
||||
else if (parts.size() == 2) {
|
||||
QString val = parts[1];
|
||||
|
||||
if (val.toUpper() == QLatin1String("TRUE") || val == QLatin1String("1")) {
|
||||
if ((val.toUpper() == QLatin1String("TRUE")) || (val == QLatin1String("1"))) {
|
||||
return TriStateBool::True;
|
||||
}
|
||||
else if (val.toUpper() == QLatin1String("FALSE") || val == QLatin1String("0")) {
|
||||
else if ((val.toUpper() == QLatin1String("FALSE")) || (val == QLatin1String("0"))) {
|
||||
return TriStateBool::False;
|
||||
}
|
||||
}
|
||||
@@ -285,10 +284,10 @@ namespace
|
||||
else if (val == QLatin1String("-1")) {
|
||||
return TriStateBool::Undefined;
|
||||
}
|
||||
else if (val.toUpper() == QLatin1String("TRUE") || val == QLatin1String("1")) {
|
||||
else if ((val.toUpper() == QLatin1String("TRUE")) || (val == QLatin1String("1"))) {
|
||||
return TriStateBool::True;
|
||||
}
|
||||
else if (val.toUpper() == QLatin1String("FALSE") || val == QLatin1String("0")) {
|
||||
else if ((val.toUpper() == QLatin1String("FALSE")) || (val == QLatin1String("0"))) {
|
||||
return TriStateBool::False;
|
||||
}
|
||||
else {
|
||||
@@ -360,7 +359,7 @@ QStringList QBtCommandLineParameters::paramList() const
|
||||
// the user has specified. Here we place special strings that are
|
||||
// almost certainly not going to collide with a file path or URL
|
||||
// specified by the user, and placing them at the beginning of the
|
||||
// string listr so that they will be processed before the list of
|
||||
// string list so that they will be processed before the list of
|
||||
// torrent paths or URLs.
|
||||
|
||||
if (!savePath.isEmpty())
|
||||
@@ -404,9 +403,9 @@ QBtCommandLineParameters parseCommandLine(const QStringList &args)
|
||||
const QString &arg = args[i];
|
||||
|
||||
if ((arg.startsWith("--") && !arg.endsWith(".torrent"))
|
||||
|| (arg.startsWith("-") && (arg.size() == 2))) {
|
||||
|| (arg.startsWith('-') && (arg.size() == 2))) {
|
||||
// Parse known parameters
|
||||
if ((arg == SHOW_HELP_OPTION)) {
|
||||
if (arg == SHOW_HELP_OPTION) {
|
||||
result.showHelp = true;
|
||||
}
|
||||
#ifndef Q_OS_WIN
|
||||
@@ -488,7 +487,7 @@ CommandLineParameterError::CommandLineParameterError(const QString &messageForUs
|
||||
{
|
||||
}
|
||||
|
||||
const QString& CommandLineParameterError::messageForUser() const
|
||||
const QString &CommandLineParameterError::messageForUser() const
|
||||
{
|
||||
return m_messageForUser;
|
||||
}
|
||||
@@ -499,9 +498,9 @@ QString wrapText(const QString &text, int initialIndentation = USAGE_TEXT_COLUMN
|
||||
QStringList lines = {words.first()};
|
||||
int currentLineMaxLength = wrapAtColumn - initialIndentation;
|
||||
|
||||
foreach (const QString &word, words.mid(1)) {
|
||||
for (const QString &word : asConst(words.mid(1))) {
|
||||
if (lines.last().length() + word.length() + 1 < currentLineMaxLength) {
|
||||
lines.last().append(" " + word);
|
||||
lines.last().append(' ' + word);
|
||||
}
|
||||
else {
|
||||
lines.append(QString(initialIndentation, ' ') + word);
|
||||
@@ -509,7 +508,7 @@ QString wrapText(const QString &text, int initialIndentation = USAGE_TEXT_COLUMN
|
||||
}
|
||||
}
|
||||
|
||||
return lines.join("\n");
|
||||
return lines.join('\n');
|
||||
}
|
||||
|
||||
QString makeUsage(const QString &prgName)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2016 Eugene Shalygin <eugene.shalygin@gmail.com>
|
||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
* Copyright (C) 2006 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
|
||||
@@ -26,8 +26,6 @@
|
||||
* 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 APP_OPTIONS_H
|
||||
@@ -62,11 +60,11 @@ struct QBtCommandLineParameters
|
||||
QStringList paramList() const;
|
||||
};
|
||||
|
||||
class CommandLineParameterError: public std::runtime_error
|
||||
class CommandLineParameterError : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
CommandLineParameterError(const QString &messageForUser);
|
||||
const QString& messageForUser() const;
|
||||
const QString &messageForUser() const;
|
||||
|
||||
private:
|
||||
const QString m_messageForUser;
|
||||
|
||||
@@ -26,11 +26,14 @@
|
||||
* exception statement from your version.
|
||||
*/
|
||||
|
||||
#include "filelogger.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include "filelogger.h"
|
||||
|
||||
#include "base/global.h"
|
||||
#include "base/logger.h"
|
||||
#include "base/utils/fs.h"
|
||||
|
||||
@@ -41,17 +44,17 @@ FileLogger::FileLogger(const QString &path, const bool backup, const int maxSize
|
||||
{
|
||||
m_flusher.setInterval(0);
|
||||
m_flusher.setSingleShot(true);
|
||||
connect(&m_flusher, SIGNAL(timeout()), SLOT(flushLog()));
|
||||
connect(&m_flusher, &QTimer::timeout, this, &FileLogger::flushLog);
|
||||
|
||||
changePath(path);
|
||||
if (deleteOld)
|
||||
this->deleteOld(age, ageType);
|
||||
|
||||
const Logger* const logger = Logger::instance();
|
||||
foreach (const Log::Msg& msg, logger->getMessages())
|
||||
const Logger *const logger = Logger::instance();
|
||||
for (const Log::Msg &msg : asConst(logger->getMessages()))
|
||||
addLogMessage(msg);
|
||||
|
||||
connect(logger, SIGNAL(newLogMessage(const Log::Msg &)), SLOT(addLogMessage(const Log::Msg &)));
|
||||
connect(logger, &Logger::newLogMessage, this, &FileLogger::addLogMessage);
|
||||
}
|
||||
|
||||
FileLogger::~FileLogger()
|
||||
@@ -61,7 +64,7 @@ FileLogger::~FileLogger()
|
||||
delete m_logFile;
|
||||
}
|
||||
|
||||
void FileLogger::changePath(const QString& newPath)
|
||||
void FileLogger::changePath(const QString &newPath)
|
||||
{
|
||||
QString tmpPath = Utils::Fs::fromNativePath(newPath);
|
||||
QDir dir(tmpPath);
|
||||
@@ -83,21 +86,21 @@ void FileLogger::changePath(const QString& newPath)
|
||||
void FileLogger::deleteOld(const int age, const FileLogAgeType ageType)
|
||||
{
|
||||
QDateTime date = QDateTime::currentDateTime();
|
||||
QDir dir(m_path);
|
||||
QDir dir(Utils::Fs::branchPath(m_path));
|
||||
|
||||
switch (ageType) {
|
||||
case DAYS:
|
||||
date = date.addDays(age);
|
||||
break;
|
||||
case MONTHS:
|
||||
date = date.addMonths(age);
|
||||
break;
|
||||
default:
|
||||
date = date.addYears(age);
|
||||
}
|
||||
|
||||
foreach (const QFileInfo file, dir.entryInfoList(QStringList("qbittorrent.log.bak*"), QDir::Files | QDir::Writable, QDir::Time | QDir::Reversed)) {
|
||||
if (file.lastModified() < date)
|
||||
for (const QFileInfo &file : asConst(dir.entryInfoList(QStringList("qbittorrent.log.bak*"), QDir::Files | QDir::Writable, QDir::Time | QDir::Reversed))) {
|
||||
QDateTime modificationDate = file.lastModified();
|
||||
switch (ageType) {
|
||||
case DAYS:
|
||||
modificationDate = modificationDate.addDays(age);
|
||||
break;
|
||||
case MONTHS:
|
||||
modificationDate = modificationDate.addMonths(age);
|
||||
break;
|
||||
default:
|
||||
modificationDate = modificationDate.addYears(age);
|
||||
}
|
||||
if (modificationDate > date)
|
||||
break;
|
||||
Utils::Fs::forceRemove(file.absoluteFilePath());
|
||||
}
|
||||
|
||||
@@ -76,4 +76,3 @@ private:
|
||||
};
|
||||
|
||||
#endif // FILELOGGER_H
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Christophe Dumez
|
||||
* Copyright (C) 2006 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
|
||||
@@ -25,8 +25,6 @@
|
||||
* 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 <cstdlib>
|
||||
@@ -63,14 +61,14 @@ Q_IMPORT_PLUGIN(QICOPlugin)
|
||||
#include "stacktrace.h"
|
||||
#else
|
||||
#include "stacktrace_win.h"
|
||||
#include "stacktrace_win_dlg.h"
|
||||
#include "stacktracedialog.h"
|
||||
#endif // Q_OS_UNIX
|
||||
#endif //STACKTRACE
|
||||
|
||||
#include "application.h"
|
||||
#include "base/preferences.h"
|
||||
#include "base/profile.h"
|
||||
#include "base/utils/misc.h"
|
||||
#include "base/preferences.h"
|
||||
#include "application.h"
|
||||
#include "cmdoptions.h"
|
||||
#include "upgrade.h"
|
||||
|
||||
@@ -95,7 +93,7 @@ const char *sysSigName[] = {
|
||||
};
|
||||
|
||||
#if !defined Q_OS_WIN && !defined Q_OS_HAIKU
|
||||
void reportToUser(const char* str);
|
||||
void reportToUser(const char *str);
|
||||
#endif
|
||||
|
||||
void displayVersion();
|
||||
@@ -104,10 +102,6 @@ void displayBadArgMessage(const QString &message);
|
||||
|
||||
#if !defined(DISABLE_GUI)
|
||||
void showSplashScreen();
|
||||
|
||||
#if defined(Q_OS_UNIX)
|
||||
void setupDpi();
|
||||
#endif // Q_OS_UNIX
|
||||
#endif // DISABLE_GUI
|
||||
|
||||
// Main
|
||||
@@ -122,10 +116,6 @@ int main(int argc, char *argv[])
|
||||
macMigratePlists();
|
||||
#endif
|
||||
|
||||
#if !defined(DISABLE_GUI) && defined(Q_OS_UNIX)
|
||||
setupDpi();
|
||||
#endif
|
||||
|
||||
try {
|
||||
// Create Application
|
||||
QString appId = QLatin1String("qBittorrent-") + Utils::Misc::getUserIDString();
|
||||
@@ -212,7 +202,7 @@ int main(int argc, char *argv[])
|
||||
// this is the default in Qt6
|
||||
app->setAttribute(Qt::AA_DisableWindowContextHelpButton);
|
||||
#endif
|
||||
#endif
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
#if defined(Q_OS_MAC)
|
||||
// Since Apple made difficult for users to set PATH, we set here for convenience.
|
||||
@@ -236,7 +226,7 @@ int main(int argc, char *argv[])
|
||||
#ifdef DISABLE_GUI
|
||||
if (params.shouldDaemonize) {
|
||||
app.reset(); // Destroy current application
|
||||
if ((daemon(1, 0) == 0)) {
|
||||
if (daemon(1, 0) == 0) {
|
||||
app.reset(new Application(appId, argc, argv));
|
||||
if (app->isRunning()) {
|
||||
// Another instance had time to start.
|
||||
@@ -269,7 +259,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
#if !defined Q_OS_WIN && !defined Q_OS_HAIKU
|
||||
void reportToUser(const char* str)
|
||||
void reportToUser(const char *str)
|
||||
{
|
||||
const size_t strLen = strlen(str);
|
||||
if (write(STDERR_FILENO, str, strLen) < static_cast<ssize_t>(strLen)) {
|
||||
@@ -308,7 +298,7 @@ void sigAbnormalHandler(int signum)
|
||||
#endif
|
||||
|
||||
#if defined Q_OS_WIN
|
||||
StraceDlg dlg; // unsafe
|
||||
StacktraceDialog dlg; // unsafe
|
||||
dlg.setStacktraceString(QLatin1String(sigName), straceWin::getBacktrace());
|
||||
dlg.exec();
|
||||
#endif
|
||||
@@ -321,25 +311,17 @@ void sigAbnormalHandler(int signum)
|
||||
#if !defined(DISABLE_GUI)
|
||||
void showSplashScreen()
|
||||
{
|
||||
QPixmap splash_img(":/icons/skin/splash.png");
|
||||
QPainter painter(&splash_img);
|
||||
QPixmap splashImg(":/icons/skin/splash.png");
|
||||
QPainter painter(&splashImg);
|
||||
QString version = QBT_VERSION;
|
||||
painter.setPen(QPen(Qt::white));
|
||||
painter.setFont(QFont("Arial", 22, QFont::Black));
|
||||
painter.drawText(224 - painter.fontMetrics().width(version), 270, version);
|
||||
QSplashScreen *splash = new QSplashScreen(splash_img);
|
||||
QSplashScreen *splash = new QSplashScreen(splashImg);
|
||||
splash->show();
|
||||
QTimer::singleShot(1500, splash, SLOT(deleteLater()));
|
||||
QTimer::singleShot(1500, splash, &QObject::deleteLater);
|
||||
qApp->processEvents();
|
||||
}
|
||||
|
||||
#if defined(Q_OS_UNIX)
|
||||
void setupDpi()
|
||||
{
|
||||
if (qEnvironmentVariableIsEmpty("QT_AUTO_SCREEN_SCALE_FACTOR"))
|
||||
qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1");
|
||||
}
|
||||
#endif // Q_OS_UNIX
|
||||
#endif // DISABLE_GUI
|
||||
|
||||
void displayVersion()
|
||||
@@ -347,7 +329,7 @@ void displayVersion()
|
||||
printf("%s %s\n", qUtf8Printable(qApp->applicationName()), QBT_VERSION);
|
||||
}
|
||||
|
||||
void displayBadArgMessage(const QString& message)
|
||||
void displayBadArgMessage(const QString &message)
|
||||
{
|
||||
QString help = QObject::tr("Run application with -h option to read about command line parameters.");
|
||||
#ifdef Q_OS_WIN
|
||||
@@ -366,7 +348,7 @@ void displayBadArgMessage(const QString& message)
|
||||
|
||||
bool userAgreesWithLegalNotice()
|
||||
{
|
||||
Preferences* const pref = Preferences::instance();
|
||||
Preferences *const pref = Preferences::instance();
|
||||
if (pref->getAcceptedLegal()) // Already accepted once
|
||||
return true;
|
||||
|
||||
@@ -378,7 +360,7 @@ bool userAgreesWithLegalNotice()
|
||||
printf("%s", qUtf8Printable(eula));
|
||||
|
||||
char ret = getchar(); // Read pressed key
|
||||
if (ret == 'y' || ret == 'Y') {
|
||||
if ((ret == 'y') || (ret == 'Y')) {
|
||||
// Save the answer
|
||||
pref->setAcceptedLegal(true);
|
||||
return true;
|
||||
@@ -388,16 +370,16 @@ bool userAgreesWithLegalNotice()
|
||||
msgBox.setText(QObject::tr("qBittorrent is a file sharing program. When you run a torrent, its data will be made available to others by means of upload. Any content you share is your sole responsibility.\n\nNo further notices will be issued."));
|
||||
msgBox.setWindowTitle(QObject::tr("Legal notice"));
|
||||
msgBox.addButton(QObject::tr("Cancel"), QMessageBox::RejectRole);
|
||||
QAbstractButton *agree_button = msgBox.addButton(QObject::tr("I Agree"), QMessageBox::AcceptRole);
|
||||
QAbstractButton *agreeButton = msgBox.addButton(QObject::tr("I Agree"), QMessageBox::AcceptRole);
|
||||
msgBox.show(); // Need to be shown or to moveToCenter does not work
|
||||
msgBox.move(Utils::Misc::screenCenter(&msgBox));
|
||||
msgBox.exec();
|
||||
if (msgBox.clickedButton() == agree_button) {
|
||||
if (msgBox.clickedButton() == agreeButton) {
|
||||
// Save the answer
|
||||
pref->setAcceptedLegal(true);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif // DISABLE_GUI
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -8,24 +8,24 @@ set(QBT_QTSINGLEAPPLICATION_SOURCES
|
||||
qtlocalpeer.cpp
|
||||
)
|
||||
|
||||
if (GUI)
|
||||
if (Qt5Widgets_FOUND)
|
||||
list(APPEND QBT_QTSINGLEAPPLICATION_HEADERS qtsingleapplication.h)
|
||||
list(APPEND QBT_QTSINGLEAPPLICATION_SOURCES qtsingleapplication.cpp)
|
||||
else (GUI)
|
||||
else (Qt5Widgets_FOUND)
|
||||
list(APPEND QBT_QTSINGLEAPPLICATION_HEADERS qtsinglecoreapplication.h)
|
||||
list(APPEND QBT_QTSINGLEAPPLICATION_SOURCES qtsinglecoreapplication.cpp)
|
||||
endif (GUI)
|
||||
endif (Qt5Widgets_FOUND)
|
||||
|
||||
add_library(qtsingleapplication STATIC ${QBT_QTSINGLEAPPLICATION_HEADERS} ${QBT_QTSINGLEAPPLICATION_SOURCES})
|
||||
target_include_directories(qtsingleapplication INTERFACE "${qtsingleapplication_SOURCE_DIR}")
|
||||
target_link_qt_components(qtsingleapplication Network)
|
||||
target_link_libraries(qtsingleapplication PRIVATE Qt5::Network)
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
target_compile_options(qtsingleapplication PRIVATE "-w") # disable warning for 3rdparty code
|
||||
endif()
|
||||
|
||||
if (GUI)
|
||||
target_link_qt_components(qtsingleapplication Widgets)
|
||||
endif (GUI)
|
||||
if (Qt5Widgets_FOUND)
|
||||
target_link_libraries(qtsingleapplication PRIVATE Qt5::Widgets)
|
||||
endif (Qt5Widgets_FOUND)
|
||||
|
||||
add_library(QtSingleApplication::QtSingleApplication ALIAS qtsingleapplication)
|
||||
|
||||
@@ -101,6 +101,7 @@ QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId)
|
||||
#endif
|
||||
|
||||
server = new QLocalServer(this);
|
||||
server->setSocketOptions(QLocalServer::UserAccessOption);
|
||||
QString lockName = QDir(QDir::tempPath()).absolutePath()
|
||||
+ QLatin1Char('/') + socketName
|
||||
+ QLatin1String("-lockfile");
|
||||
@@ -191,6 +192,12 @@ void QtLocalPeer::receiveConnection()
|
||||
QByteArray uMsg;
|
||||
quint32 remaining;
|
||||
ds >> remaining;
|
||||
if (remaining > 65535) {
|
||||
// drop suspiciously large data
|
||||
delete socket;
|
||||
return;
|
||||
}
|
||||
|
||||
uMsg.resize(remaining);
|
||||
int got = 0;
|
||||
char* uMsgBuf = uMsg.data();
|
||||
|
||||
@@ -138,7 +138,7 @@ bool straceWin::makeRelativePath(const QString& dir, QString& file)
|
||||
|
||||
QString straceWin::getSourcePathAndLineNumber(HANDLE hProcess, DWORD64 addr)
|
||||
{
|
||||
IMAGEHLP_LINE64 line = {0};
|
||||
IMAGEHLP_LINE64 line {};
|
||||
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||
DWORD dwDisplacement = 0;
|
||||
|
||||
|
||||
@@ -27,20 +27,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef STACKTRACE_WIN_DLG_H
|
||||
#define STACKTRACE_WIN_DLG_H
|
||||
#ifndef STACKTRACEDIALOG_H
|
||||
#define STACKTRACEDIALOG_H
|
||||
|
||||
#include <QString>
|
||||
#include <QDialog>
|
||||
#include "base/utils/misc.h"
|
||||
#include "ui_stacktrace_win_dlg.h"
|
||||
|
||||
class StraceDlg : public QDialog, private Ui::errorDialog
|
||||
#include "base/utils/misc.h"
|
||||
#include "ui_stacktracedialog.h"
|
||||
|
||||
class StacktraceDialog : public QDialog, private Ui::StacktraceDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
StraceDlg(QWidget *parent = nullptr)
|
||||
StacktraceDialog(QWidget *parent = nullptr)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
@@ -83,4 +84,4 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // STACKTRACEDIALOG_H
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>errorDialog</class>
|
||||
<widget class="QDialog" name="errorDialog">
|
||||
<class>StacktraceDialog</class>
|
||||
<widget class="QDialog" name="StacktraceDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
@@ -29,34 +29,34 @@
|
||||
#ifndef UPGRADE_H
|
||||
#define UPGRADE_H
|
||||
|
||||
#include <libtorrent/version.hpp>
|
||||
#if LIBTORRENT_VERSION_NUM >= 10100
|
||||
#include <libtorrent/bdecode.hpp>
|
||||
#endif
|
||||
#include <libtorrent/bencode.hpp>
|
||||
#include <libtorrent/entry.hpp>
|
||||
#if LIBTORRENT_VERSION_NUM < 10100
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM >= 10100
|
||||
#include <libtorrent/bdecode.hpp>
|
||||
#else
|
||||
#include <libtorrent/lazy_entry.hpp>
|
||||
#endif
|
||||
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QRegularExpression>
|
||||
#include <QString>
|
||||
|
||||
#ifndef DISABLE_GUI
|
||||
#include <QMessageBox>
|
||||
#endif
|
||||
#include <QRegExp>
|
||||
#include <QString>
|
||||
#ifdef Q_OS_MAC
|
||||
#include <QSettings>
|
||||
#endif
|
||||
|
||||
#include "base/logger.h"
|
||||
#include "base/preferences.h"
|
||||
#include "base/profile.h"
|
||||
#include "base/utils/fs.h"
|
||||
#include "base/utils/misc.h"
|
||||
#include "base/utils/string.h"
|
||||
#include "base/preferences.h"
|
||||
|
||||
bool userAcceptsUpgrade()
|
||||
{
|
||||
@@ -83,7 +83,7 @@ bool userAcceptsUpgrade()
|
||||
msgBox.move(Utils::Misc::screenCenter(&msgBox));
|
||||
if (msgBox.exec() == QMessageBox::Ok)
|
||||
return true;
|
||||
#endif
|
||||
#endif // DISABLE_GUI
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -114,12 +114,28 @@ bool upgradeResumeFile(const QString &filepath, const QVariantHash &oldTorrent =
|
||||
bool v3_3 = false;
|
||||
int queuePosition = 0;
|
||||
QString outFilePath = filepath;
|
||||
QRegExp rx(QLatin1String("([A-Fa-f0-9]{40})\\.fastresume\\.(\\d+)$"));
|
||||
if (rx.indexIn(filepath) != -1) {
|
||||
// old v3.3.x format
|
||||
queuePosition = rx.cap(2).toInt();
|
||||
static const QRegularExpression rx(QLatin1String("([A-Fa-f0-9]{40})\\.fastresume\\.(.+)$"));
|
||||
const QRegularExpressionMatch rxMatch = rx.match(filepath);
|
||||
if (rxMatch.hasMatch()) {
|
||||
// Old v3.3.x format had a number at the end indicating the queue position.
|
||||
// The naming scheme was '<infohash>.fastresume.<queueposition>'.
|
||||
// However, QSaveFile, which uses QTemporaryFile internally, might leave
|
||||
// non-commited files behind eg after a crash. These files have the
|
||||
// naming scheme '<infohash>.fastresume.XXXXXX' where each X is a random
|
||||
// character. So we detect if the last part is present. Then check if it
|
||||
// is 6 chars long. If all the 6 chars are digits we assume it is an old
|
||||
// v3.3.x format. Otherwise it is considered a non-commited fastresume
|
||||
// and is deleted, because it may be a corrupted/incomplete fastresume.
|
||||
// NOTE: When the upgrade code is removed, we must continue to perform
|
||||
// cleanup of non-commited QSaveFile/QTemporaryFile fastresumes
|
||||
queuePosition = rxMatch.captured(2).toInt();
|
||||
if ((rxMatch.captured(2).size() == 6) && (queuePosition <= 99999)) {
|
||||
Utils::Fs::forceRemove(filepath);
|
||||
return true;
|
||||
}
|
||||
|
||||
v3_3 = true;
|
||||
outFilePath.replace(QRegExp("\\.\\d+$"), "");
|
||||
outFilePath.replace(QRegularExpression("\\.fastresume\\..+$"), ".fastresume");
|
||||
}
|
||||
else {
|
||||
queuePosition = fastOld.dict_find_int_value("qBt-queuePosition", 0);
|
||||
@@ -130,6 +146,15 @@ bool upgradeResumeFile(const QString &filepath, const QVariantHash &oldTorrent =
|
||||
// in versions < 3.3 we have -1 for seeding torrents, so we convert it to 0
|
||||
fastNew["qBt-queuePosition"] = (queuePosition >= 0 ? queuePosition : 0);
|
||||
|
||||
if (v3_3) {
|
||||
QFileInfo oldFile(filepath);
|
||||
QFileInfo newFile(outFilePath);
|
||||
if (newFile.exists()
|
||||
&& (oldFile.lastModified() < newFile.lastModified())) {
|
||||
Utils::Fs::forceRemove(filepath);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
QFile file2(outFilePath);
|
||||
QVector<char> out;
|
||||
libtorrent::bencode(std::back_inserter(out), fastNew);
|
||||
@@ -154,9 +179,9 @@ bool upgrade(bool ask = true)
|
||||
|
||||
// ****************************************************************************************
|
||||
// Silently converts old v3.3.x .fastresume files
|
||||
QStringList backupFiles_3_3 = backupFolderDir.entryList(
|
||||
const QStringList backupFiles_3_3 = backupFolderDir.entryList(
|
||||
QStringList(QLatin1String("*.fastresume.*")), QDir::Files, QDir::Unsorted);
|
||||
foreach (const QString &backupFile, backupFiles_3_3)
|
||||
for (const QString &backupFile : backupFiles_3_3)
|
||||
upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile));
|
||||
// ****************************************************************************************
|
||||
|
||||
@@ -172,15 +197,17 @@ bool upgrade(bool ask = true)
|
||||
|
||||
if (ask && !userAcceptsUpgrade()) return false;
|
||||
|
||||
QStringList backupFiles = backupFolderDir.entryList(
|
||||
const QStringList backupFiles = backupFolderDir.entryList(
|
||||
QStringList(QLatin1String("*.fastresume")), QDir::Files, QDir::Unsorted);
|
||||
QRegExp rx(QLatin1String("^([A-Fa-f0-9]{40})\\.fastresume$"));
|
||||
foreach (QString backupFile, backupFiles) {
|
||||
if (rx.indexIn(backupFile) != -1) {
|
||||
if (upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile), oldResumeData[rx.cap(1)].toHash()))
|
||||
oldResumeData.remove(rx.cap(1));
|
||||
const QRegularExpression rx(QLatin1String("^([A-Fa-f0-9]{40})\\.fastresume$"));
|
||||
for (const QString &backupFile : backupFiles) {
|
||||
const QRegularExpressionMatch rxMatch = rx.match(backupFile);
|
||||
if (rxMatch.hasMatch()) {
|
||||
const QString hashStr = rxMatch.captured(1);
|
||||
if (upgradeResumeFile(backupFolderDir.absoluteFilePath(backupFile), oldResumeData[hashStr].toHash()))
|
||||
oldResumeData.remove(hashStr);
|
||||
else
|
||||
Logger::instance()->addMessage(QObject::tr("Couldn't migrate torrent with hash: %1").arg(rx.cap(1)), Log::WARNING);
|
||||
Logger::instance()->addMessage(QObject::tr("Couldn't migrate torrent with hash: %1").arg(hashStr), Log::WARNING);
|
||||
}
|
||||
else {
|
||||
Logger::instance()->addMessage(QObject::tr("Couldn't migrate torrent. Invalid fastresume file name: %1").arg(backupFile), Log::WARNING);
|
||||
@@ -238,7 +265,7 @@ void migratePlistToIni(const QString &application)
|
||||
plistFile->setFallbacksEnabled(false);
|
||||
const QStringList plist = plistFile->allKeys();
|
||||
if (!plist.isEmpty()) {
|
||||
foreach (const QString &key, plist)
|
||||
for (const QString &key : plist)
|
||||
iniFile.setValue(key, plistFile->value(key));
|
||||
plistFile->clear();
|
||||
}
|
||||
@@ -272,6 +299,6 @@ void migrateRSS()
|
||||
qBTRSSLegacy->remove("old_items");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif // DISABLE_GUI
|
||||
|
||||
#endif // UPGRADE_H
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
find_package(ZLIB 1.2.5.2 REQUIRED)
|
||||
|
||||
set(QBT_BASE_HEADERS
|
||||
add_library(qbt_base STATIC
|
||||
# headers
|
||||
bittorrent/addtorrentparams.h
|
||||
bittorrent/cachestatus.h
|
||||
bittorrent/filepriority.h
|
||||
bittorrent/infohash.h
|
||||
bittorrent/magneturi.h
|
||||
bittorrent/peerinfo.h
|
||||
@@ -48,6 +50,7 @@ search/searchdownloadhandler.h
|
||||
search/searchhandler.h
|
||||
search/searchpluginmanager.h
|
||||
utils/bytearray.h
|
||||
utils/foreignapps.h
|
||||
utils/fs.h
|
||||
utils/gzip.h
|
||||
utils/misc.h
|
||||
@@ -72,9 +75,9 @@ torrentfilter.h
|
||||
tristatebool.h
|
||||
types.h
|
||||
unicodestrings.h
|
||||
)
|
||||
|
||||
set(QBT_BASE_SOURCES
|
||||
# sources
|
||||
bittorrent/filepriority.cpp
|
||||
bittorrent/infohash.cpp
|
||||
bittorrent/magneturi.cpp
|
||||
bittorrent/peerinfo.cpp
|
||||
@@ -117,6 +120,7 @@ search/searchdownloadhandler.cpp
|
||||
search/searchhandler.cpp
|
||||
search/searchpluginmanager.cpp
|
||||
utils/bytearray.cpp
|
||||
utils/foreignapps.cpp
|
||||
utils/fs.cpp
|
||||
utils/gzip.cpp
|
||||
utils/misc.cpp
|
||||
@@ -137,16 +141,20 @@ torrentfilter.cpp
|
||||
tristatebool.cpp
|
||||
)
|
||||
|
||||
add_library(qbt_base STATIC ${QBT_BASE_HEADERS} ${QBT_BASE_SOURCES})
|
||||
target_link_libraries(qbt_base PRIVATE ZLIB::ZLIB PUBLIC LibtorrentRasterbar::LibTorrent)
|
||||
target_link_qt_components(qbt_base PUBLIC Core Network Xml)
|
||||
target_link_libraries(qbt_base
|
||||
PRIVATE
|
||||
ZLIB::ZLIB
|
||||
PUBLIC
|
||||
LibtorrentRasterbar::torrent-rasterbar
|
||||
Qt5::Core Qt5::Network Qt5::Xml
|
||||
)
|
||||
|
||||
if (GUI)
|
||||
if (Qt5Widgets_FOUND)
|
||||
target_link_libraries(qbt_base PUBLIC Qt5::Gui Qt5::Widgets)
|
||||
endif (GUI)
|
||||
endif (Qt5Widgets_FOUND)
|
||||
|
||||
if (DBUS)
|
||||
target_link_qt_components(qbt_base PRIVATE DBus)
|
||||
if (Qt5DBus_FOUND)
|
||||
target_link_libraries(qbt_base PRIVATE Qt5::DBus)
|
||||
endif ()
|
||||
|
||||
if (APPLE)
|
||||
|
||||
@@ -38,12 +38,12 @@ AsyncFileStorage::AsyncFileStorage(const QString &storageFolderPath, QObject *pa
|
||||
, m_lockFile(m_storageDir.absoluteFilePath(QStringLiteral("storage.lock")))
|
||||
{
|
||||
if (!m_storageDir.mkpath(m_storageDir.absolutePath()))
|
||||
throw AsyncFileStorageError(
|
||||
QString("Could not create directory '%1'.").arg(m_storageDir.absolutePath()));
|
||||
throw AsyncFileStorageError {tr("Could not create directory '%1'.")
|
||||
.arg(m_storageDir.absolutePath())};
|
||||
|
||||
// TODO: This folder locking approach does not work for UNIX systems. Implement it.
|
||||
if (!m_lockFile.open(QFile::WriteOnly))
|
||||
throw AsyncFileStorageError(m_lockFile.errorString());
|
||||
throw AsyncFileStorageError {m_lockFile.errorString()};
|
||||
}
|
||||
|
||||
AsyncFileStorage::~AsyncFileStorage()
|
||||
@@ -76,13 +76,3 @@ void AsyncFileStorage::store_impl(const QString &fileName, const QByteArray &dat
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AsyncFileStorageError::AsyncFileStorageError(const QString &message)
|
||||
: std::runtime_error(message.toUtf8().data())
|
||||
{
|
||||
}
|
||||
|
||||
QString AsyncFileStorageError::message() const
|
||||
{
|
||||
return what();
|
||||
}
|
||||
|
||||
@@ -28,22 +28,22 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QObject>
|
||||
|
||||
class AsyncFileStorageError: public std::runtime_error
|
||||
#include "base/exceptions.h"
|
||||
|
||||
class AsyncFileStorageError : public RuntimeError
|
||||
{
|
||||
public:
|
||||
explicit AsyncFileStorageError(const QString &message);
|
||||
QString message() const;
|
||||
using RuntimeError::RuntimeError;
|
||||
};
|
||||
|
||||
class AsyncFileStorage: public QObject
|
||||
class AsyncFileStorage : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(AsyncFileStorage)
|
||||
|
||||
public:
|
||||
explicit AsyncFileStorage(const QString &storageFolderPath, QObject *parent = nullptr);
|
||||
|
||||
@@ -3,6 +3,7 @@ HEADERS += \
|
||||
$$PWD/asyncfilestorage.h \
|
||||
$$PWD/bittorrent/addtorrentparams.h \
|
||||
$$PWD/bittorrent/cachestatus.h \
|
||||
$$PWD/bittorrent/filepriority.h \
|
||||
$$PWD/bittorrent/infohash.h \
|
||||
$$PWD/bittorrent/magneturi.h \
|
||||
$$PWD/bittorrent/peerinfo.h \
|
||||
@@ -64,6 +65,7 @@ HEADERS += \
|
||||
$$PWD/types.h \
|
||||
$$PWD/unicodestrings.h \
|
||||
$$PWD/utils/bytearray.h \
|
||||
$$PWD/utils/foreignapps.h \
|
||||
$$PWD/utils/fs.h \
|
||||
$$PWD/utils/gzip.h \
|
||||
$$PWD/utils/misc.h \
|
||||
@@ -74,6 +76,7 @@ HEADERS += \
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/asyncfilestorage.cpp \
|
||||
$$PWD/bittorrent/filepriority.cpp \
|
||||
$$PWD/bittorrent/infohash.cpp \
|
||||
$$PWD/bittorrent/magneturi.cpp \
|
||||
$$PWD/bittorrent/peerinfo.cpp \
|
||||
@@ -127,6 +130,7 @@ SOURCES += \
|
||||
$$PWD/torrentfilter.cpp \
|
||||
$$PWD/tristatebool.cpp \
|
||||
$$PWD/utils/bytearray.cpp \
|
||||
$$PWD/utils/foreignapps.cpp \
|
||||
$$PWD/utils/fs.cpp \
|
||||
$$PWD/utils/gzip.cpp \
|
||||
$$PWD/utils/misc.cpp \
|
||||
|
||||
46
src/base/bittorrent/filepriority.cpp
Normal file
46
src/base/bittorrent/filepriority.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2018 Thomas Piccirello <thomas.piccirello@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "filepriority.h"
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
bool isValidFilePriority(const BitTorrent::FilePriority priority)
|
||||
{
|
||||
switch (priority) {
|
||||
case BitTorrent::FilePriority::Ignored:
|
||||
case BitTorrent::FilePriority::Normal:
|
||||
case BitTorrent::FilePriority::High:
|
||||
case BitTorrent::FilePriority::Maximum:
|
||||
case BitTorrent::FilePriority::Mixed:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
43
src/base/bittorrent/filepriority.h
Normal file
43
src/base/bittorrent/filepriority.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2018 Thomas Piccirello <thomas.piccirello@gmail.com>
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
enum class FilePriority : int
|
||||
{
|
||||
Ignored = 0,
|
||||
Normal = 1,
|
||||
High = 6,
|
||||
Maximum = 7,
|
||||
Mixed = -1
|
||||
};
|
||||
|
||||
bool isValidFilePriority(BitTorrent::FilePriority priority);
|
||||
}
|
||||
@@ -26,9 +26,10 @@
|
||||
* exception statement from your version.
|
||||
*/
|
||||
|
||||
#include <QHash>
|
||||
#include "infohash.h"
|
||||
|
||||
#include <QHash>
|
||||
|
||||
using namespace BitTorrent;
|
||||
|
||||
InfoHash::InfoHash()
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
#ifndef BITTORRENT_INFOHASH_H
|
||||
#define BITTORRENT_INFOHASH_H
|
||||
|
||||
#include <QString>
|
||||
#include <libtorrent/sha1_hash.hpp>
|
||||
#include <QString>
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
|
||||
@@ -26,16 +26,17 @@
|
||||
* exception statement from your version.
|
||||
*/
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QRegExp>
|
||||
#include <QStringList>
|
||||
#include "magneturi.h"
|
||||
|
||||
#include <libtorrent/bencode.hpp>
|
||||
#include <libtorrent/error_code.hpp>
|
||||
#include <libtorrent/magnet_uri.hpp>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QRegularExpression>
|
||||
#include <QStringList>
|
||||
|
||||
#include "base/utils/string.h"
|
||||
#include "magneturi.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -45,7 +46,7 @@ namespace
|
||||
rawBc = rawBc.mid(8); // skip bc://bt/
|
||||
rawBc = QByteArray::fromBase64(rawBc); // Decode base64
|
||||
// Format is now AA/url_encoded_filename/size_bytes/info_hash/ZZ
|
||||
QStringList parts = QString(rawBc).split("/");
|
||||
QStringList parts = QString(rawBc).split('/');
|
||||
if (parts.size() != 5) return QString();
|
||||
|
||||
QString filename = parts.at(1);
|
||||
@@ -69,8 +70,8 @@ MagnetUri::MagnetUri(const QString &source)
|
||||
qDebug("Creating magnet link from bc link");
|
||||
m_url = bcLinkToMagnet(source);
|
||||
}
|
||||
else if (((source.size() == 40) && !source.contains(QRegExp("[^0-9A-Fa-f]")))
|
||||
|| ((source.size() == 32) && !source.contains(QRegExp("[^2-7A-Za-z]")))) {
|
||||
else if (((source.size() == 40) && !source.contains(QRegularExpression("[^0-9A-Fa-f]")))
|
||||
|| ((source.size() == 32) && !source.contains(QRegularExpression("[^2-7A-Za-z]")))) {
|
||||
m_url = "magnet:?xt=urn:btih:" + source;
|
||||
}
|
||||
|
||||
@@ -82,10 +83,10 @@ MagnetUri::MagnetUri(const QString &source)
|
||||
m_hash = m_addTorrentParams.info_hash;
|
||||
m_name = QString::fromStdString(m_addTorrentParams.name);
|
||||
|
||||
foreach (const std::string &tracker, m_addTorrentParams.trackers)
|
||||
for (const std::string &tracker : m_addTorrentParams.trackers)
|
||||
m_trackers.append(QString::fromStdString(tracker));
|
||||
|
||||
foreach (const std::string &urlSeed, m_addTorrentParams.url_seeds)
|
||||
for (const std::string &urlSeed : m_addTorrentParams.url_seeds)
|
||||
m_urlSeeds.append(QUrl(urlSeed.c_str()));
|
||||
}
|
||||
|
||||
|
||||
@@ -246,8 +246,8 @@ QString PeerInfo::connectionType() const
|
||||
|
||||
void PeerInfo::calcRelevance(const TorrentHandle *torrent)
|
||||
{
|
||||
const QBitArray &allPieces = torrent->pieces();
|
||||
const QBitArray &peerPieces = pieces();
|
||||
const QBitArray allPieces = torrent->pieces();
|
||||
const QBitArray peerPieces = pieces();
|
||||
|
||||
int localMissing = 0;
|
||||
int remoteHaves = 0;
|
||||
@@ -377,7 +377,7 @@ void PeerInfo::determineFlags()
|
||||
|
||||
// L = Peer is local
|
||||
if (fromLSD()) {
|
||||
m_flags += "L";
|
||||
m_flags += 'L';
|
||||
flagsDescriptionList += "L = "
|
||||
+ tr("peer from LSD");
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ void BandwidthScheduler::start()
|
||||
|
||||
bool BandwidthScheduler::isTimeForAlternative() const
|
||||
{
|
||||
const Preferences* const pref = Preferences::instance();
|
||||
const Preferences *const pref = Preferences::instance();
|
||||
|
||||
QTime start = pref->getSchedulerStartTime();
|
||||
QTime end = pref->getSchedulerEndTime();
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
class BandwidthScheduler: public QObject
|
||||
class BandwidthScheduler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(BandwidthScheduler)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libt.
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
@@ -147,13 +147,13 @@ int FilterParserThread::parseDATFilterFile()
|
||||
if (bytesRead < 0)
|
||||
break;
|
||||
int dataSize = bytesRead + offset;
|
||||
if (bytesRead == 0 && dataSize == 0)
|
||||
if ((bytesRead == 0) && (dataSize == 0))
|
||||
break;
|
||||
|
||||
for (start = 0; start < dataSize; ++start) {
|
||||
endOfLine = -1;
|
||||
// The file might have ended without the last line having a newline
|
||||
if (!(bytesRead == 0 && dataSize > 0)) {
|
||||
if (!((bytesRead == 0) && (dataSize > 0))) {
|
||||
for (int i = start; i < dataSize; ++i) {
|
||||
if (buffer[i] == '\n') {
|
||||
endOfLine = i;
|
||||
@@ -295,13 +295,13 @@ int FilterParserThread::parseP2PFilterFile()
|
||||
if (bytesRead < 0)
|
||||
break;
|
||||
int dataSize = bytesRead + offset;
|
||||
if (bytesRead == 0 && dataSize == 0)
|
||||
if ((bytesRead == 0) && (dataSize == 0))
|
||||
break;
|
||||
|
||||
for (start = 0; start < dataSize; ++start) {
|
||||
endOfLine = -1;
|
||||
// The file might have ended without the last line having a newline
|
||||
if (!(bytesRead == 0 && dataSize > 0)) {
|
||||
if (!((bytesRead == 0) && (dataSize > 0))) {
|
||||
for (int i = start; i < dataSize; ++i) {
|
||||
if (buffer[i] == '\n') {
|
||||
endOfLine = i;
|
||||
@@ -407,24 +407,24 @@ int FilterParserThread::parseP2PFilterFile()
|
||||
int FilterParserThread::getlineInStream(QDataStream &stream, std::string &name, char delim)
|
||||
{
|
||||
char c;
|
||||
int total_read = 0;
|
||||
int totalRead = 0;
|
||||
int read;
|
||||
do {
|
||||
read = stream.readRawData(&c, 1);
|
||||
total_read += read;
|
||||
totalRead += read;
|
||||
if (read > 0) {
|
||||
if (c != delim) {
|
||||
name += c;
|
||||
}
|
||||
else {
|
||||
// Delim found
|
||||
return total_read;
|
||||
return totalRead;
|
||||
}
|
||||
}
|
||||
}
|
||||
while(read > 0);
|
||||
while (read > 0);
|
||||
|
||||
return total_read;
|
||||
return totalRead;
|
||||
}
|
||||
|
||||
// Parser for PeerGuardian ip filter in p2p format
|
||||
@@ -455,7 +455,7 @@ int FilterParserThread::parseP2BFilterFile()
|
||||
unsigned int start, end;
|
||||
|
||||
std::string name;
|
||||
while(getlineInStream(stream, name, '\0') && !m_abort) {
|
||||
while (getlineInStream(stream, name, '\0') && !m_abort) {
|
||||
if (!stream.readRawData(reinterpret_cast<char*>(&start), sizeof(start))
|
||||
|| !stream.readRawData(reinterpret_cast<char*>(&end), sizeof(end))) {
|
||||
LogMsg(tr("Parsing Error: The filter file is not a valid PeerGuardian P2B file."), Log::CRITICAL);
|
||||
@@ -610,7 +610,7 @@ int FilterParserThread::findAndNullDelimiter(char *const data, char delimiter, i
|
||||
return -1;
|
||||
}
|
||||
|
||||
int FilterParserThread::trim(char* const data, int start, int end)
|
||||
int FilterParserThread::trim(char *const data, int start, int end)
|
||||
{
|
||||
if (start >= end) return start;
|
||||
int newStart = start;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2015, 2018 Vladimir Golovnev <glassez@yandex.ru>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -26,30 +26,36 @@
|
||||
* exception statement from your version.
|
||||
*/
|
||||
|
||||
#include "resumedatasavingmanager.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSaveFile>
|
||||
|
||||
#include "base/logger.h"
|
||||
#include "base/utils/fs.h"
|
||||
#include "resumedatasavingmanager.h"
|
||||
|
||||
ResumeDataSavingManager::ResumeDataSavingManager(const QString &resumeFolderPath)
|
||||
: m_resumeDataDir(resumeFolderPath)
|
||||
{
|
||||
}
|
||||
|
||||
void ResumeDataSavingManager::saveResumeData(QString infoHash, QByteArray data) const
|
||||
void ResumeDataSavingManager::save(const QString &filename, const QByteArray &data) const
|
||||
{
|
||||
QString filename = QString("%1.fastresume").arg(infoHash);
|
||||
QString filepath = m_resumeDataDir.absoluteFilePath(filename);
|
||||
const QString filepath = m_resumeDataDir.absoluteFilePath(filename);
|
||||
|
||||
qDebug() << "Saving resume data in" << filepath;
|
||||
QSaveFile resumeFile(filepath);
|
||||
if (resumeFile.open(QIODevice::WriteOnly)) {
|
||||
resumeFile.write(data);
|
||||
if (!resumeFile.commit()) {
|
||||
Logger::instance()->addMessage(QString("Couldn't save resume data in %1. Error: %2")
|
||||
.arg(filepath, resumeFile.errorString()), Log::WARNING);
|
||||
QSaveFile file {filepath};
|
||||
if (file.open(QIODevice::WriteOnly)) {
|
||||
file.write(data);
|
||||
if (!file.commit()) {
|
||||
Logger::instance()->addMessage(QString("Couldn't save data in '%1'. Error: %2")
|
||||
.arg(filepath, file.errorString()), Log::WARNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ResumeDataSavingManager::remove(const QString &filename) const
|
||||
{
|
||||
const QString filepath = m_resumeDataDir.absoluteFilePath(filename);
|
||||
|
||||
Utils::Fs::forceRemove(filepath);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2015, 2018 Vladimir Golovnev <glassez@yandex.ru>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@@ -26,8 +26,7 @@
|
||||
* exception statement from your version.
|
||||
*/
|
||||
|
||||
#ifndef RESUMEDATASAVINGMANAGER_H
|
||||
#define RESUMEDATASAVINGMANAGER_H
|
||||
#pragma once
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QDir>
|
||||
@@ -36,15 +35,15 @@
|
||||
class ResumeDataSavingManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(ResumeDataSavingManager)
|
||||
|
||||
public:
|
||||
explicit ResumeDataSavingManager(const QString &resumeFolderPath);
|
||||
|
||||
public slots:
|
||||
void saveResumeData(QString infoHash, QByteArray data) const;
|
||||
void save(const QString &filename, const QByteArray &data) const;
|
||||
void remove(const QString &filename) const;
|
||||
|
||||
private:
|
||||
QDir m_resumeDataDir;
|
||||
};
|
||||
|
||||
#endif // RESUMEDATASAVINGMANAGER_H
|
||||
|
||||
@@ -22,7 +22,7 @@ Statistics::Statistics(Session *session)
|
||||
, m_dirty(false)
|
||||
{
|
||||
load();
|
||||
connect(&m_timer, SIGNAL(timeout()), this, SLOT(gather()));
|
||||
connect(&m_timer, &QTimer::timeout, this, &Statistics::gather);
|
||||
m_timer.start(60 * 1000);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace BitTorrent
|
||||
class Session;
|
||||
}
|
||||
|
||||
class Statistics : QObject
|
||||
class Statistics : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_DISABLE_COPY(Statistics)
|
||||
@@ -28,7 +28,6 @@ private:
|
||||
void save() const;
|
||||
void load();
|
||||
|
||||
private:
|
||||
BitTorrent::Session *m_session;
|
||||
// Will overflow at 15.9 EiB
|
||||
quint64 m_alltimeUL;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -30,18 +30,14 @@
|
||||
#ifndef BITTORRENT_SESSION_H
|
||||
#define BITTORRENT_SESSION_H
|
||||
|
||||
#include <vector>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM >= 10100
|
||||
#include <QElapsedTimer>
|
||||
#endif
|
||||
#include <vector>
|
||||
|
||||
#include <QFile>
|
||||
#include <QHash>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#if LIBTORRENT_VERSION_NUM < 10100
|
||||
#include <QMutex>
|
||||
#endif
|
||||
#include <QNetworkConfigurationManager>
|
||||
#include <QPointer>
|
||||
#include <QSet>
|
||||
@@ -49,6 +45,12 @@
|
||||
#include <QVector>
|
||||
#include <QWaitCondition>
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM < 10100
|
||||
#include <QMutex>
|
||||
#else
|
||||
#include <QElapsedTimer>
|
||||
#endif
|
||||
|
||||
#include "base/settingvalue.h"
|
||||
#include "base/tristatebool.h"
|
||||
#include "base/types.h"
|
||||
@@ -111,7 +113,6 @@ class QTimer;
|
||||
class QStringList;
|
||||
class QString;
|
||||
class QUrl;
|
||||
template<typename T> class QList;
|
||||
|
||||
class FilterParserThread;
|
||||
class BandwidthScheduler;
|
||||
@@ -137,7 +138,7 @@ namespace BitTorrent
|
||||
class Tracker;
|
||||
class MagnetUri;
|
||||
class TrackerEntry;
|
||||
struct AddTorrentData;
|
||||
struct CreateTorrentParams;
|
||||
|
||||
struct TorrentStatusReport
|
||||
{
|
||||
@@ -236,7 +237,7 @@ namespace BitTorrent
|
||||
int diskJobTime = 0;
|
||||
} disk;
|
||||
};
|
||||
#endif
|
||||
#endif // LIBTORRENT_VERSION_NUM >= 10100
|
||||
|
||||
class Session : public QObject
|
||||
{
|
||||
@@ -374,6 +375,10 @@ namespace BitTorrent
|
||||
void setAnnounceToAllTrackers(bool val);
|
||||
bool announceToAllTiers() const;
|
||||
void setAnnounceToAllTiers(bool val);
|
||||
int asyncIOThreads() const;
|
||||
void setAsyncIOThreads(int num);
|
||||
int checkingMemUsage() const;
|
||||
void setCheckingMemUsage(int size);
|
||||
int diskCacheSize() const;
|
||||
void setDiskCacheSize(int size);
|
||||
int diskCacheTTL() const;
|
||||
@@ -451,6 +456,7 @@ namespace BitTorrent
|
||||
TorrentStatusReport torrentStatusReport() const;
|
||||
bool hasActiveTorrents() const;
|
||||
bool hasUnfinishedTorrents() const;
|
||||
bool hasRunningSeed() const;
|
||||
const SessionStatus &status() const;
|
||||
const CacheStatus &cacheStatus() const;
|
||||
quint64 getAlltimeDL() const;
|
||||
@@ -476,7 +482,9 @@ namespace BitTorrent
|
||||
void bottomTorrentsPriority(const QStringList &hashes);
|
||||
|
||||
// TorrentHandle interface
|
||||
void handleTorrentSaveResumeDataRequested(TorrentHandle *const torrent);
|
||||
void handleTorrentShareLimitChanged(TorrentHandle *const torrent);
|
||||
void handleTorrentNameChanged(TorrentHandle *const torrent);
|
||||
void handleTorrentSavePathChanged(TorrentHandle *const torrent);
|
||||
void handleTorrentCategoryChanged(TorrentHandle *const torrent, const QString &oldCategory);
|
||||
void handleTorrentTagAdded(TorrentHandle *const torrent, const QString &tag);
|
||||
@@ -546,7 +554,7 @@ namespace BitTorrent
|
||||
void generateResumeData(bool final = false);
|
||||
void handleIPFilterParsed(int ruleCount);
|
||||
void handleIPFilterError();
|
||||
void handleDownloadFinished(const QString &url, const QString &filePath);
|
||||
void handleDownloadFinished(const QString &url, const QByteArray &data);
|
||||
void handleDownloadFailed(const QString &url, const QString &reason);
|
||||
void handleRedirectedToMagnet(const QString &url, const QString &magnetUri);
|
||||
|
||||
@@ -562,7 +570,7 @@ namespace BitTorrent
|
||||
bool requestedFileDeletion;
|
||||
};
|
||||
|
||||
explicit Session(QObject *parent = 0);
|
||||
explicit Session(QObject *parent = nullptr);
|
||||
~Session();
|
||||
|
||||
bool hasPerTorrentRatioLimit() const;
|
||||
@@ -594,20 +602,20 @@ namespace BitTorrent
|
||||
void enableIPFilter();
|
||||
void disableIPFilter();
|
||||
|
||||
bool addTorrent_impl(AddTorrentData addData, const MagnetUri &magnetUri,
|
||||
bool addTorrent_impl(CreateTorrentParams params, const MagnetUri &magnetUri,
|
||||
TorrentInfo torrentInfo = TorrentInfo(),
|
||||
const QByteArray &fastresumeData = QByteArray());
|
||||
bool findIncompleteFiles(TorrentInfo &torrentInfo, QString &savePath) const;
|
||||
|
||||
void updateSeedingLimitTimer();
|
||||
void exportTorrentFile(TorrentHandle *const torrent, TorrentExportFolder folder = TorrentExportFolder::Regular);
|
||||
void saveTorrentResumeData(TorrentHandle *const torrent, bool finalSave = false);
|
||||
|
||||
void handleAlert(libtorrent::alert *a);
|
||||
void dispatchTorrentAlert(libtorrent::alert *a);
|
||||
void handleAddTorrentAlert(libtorrent::add_torrent_alert *p);
|
||||
void handleStateUpdateAlert(libtorrent::state_update_alert *p);
|
||||
void handleMetadataReceivedAlert(libtorrent::metadata_received_alert *p);
|
||||
void handleMetadataReceivedAlert(const libtorrent::metadata_received_alert *p);
|
||||
void handleTorrentPausedAlert(const libtorrent::torrent_paused_alert *p);
|
||||
void handleFileErrorAlert(libtorrent::file_error_alert *p);
|
||||
void handleTorrentRemovedAlert(libtorrent::torrent_removed_alert *p);
|
||||
void handleTorrentDeletedAlert(libtorrent::torrent_deleted_alert *p);
|
||||
@@ -627,6 +635,8 @@ namespace BitTorrent
|
||||
void createTorrentHandle(const libtorrent::torrent_handle &nativeHandle);
|
||||
|
||||
void saveResumeData();
|
||||
void saveTorrentsQueue();
|
||||
void removeTorrentsQueue();
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM < 10100
|
||||
void dispatchAlerts(libtorrent::alert *alertPtr);
|
||||
@@ -650,6 +660,8 @@ namespace BitTorrent
|
||||
CachedSettingValue<QString> m_IPFilterFile;
|
||||
CachedSettingValue<bool> m_announceToAllTrackers;
|
||||
CachedSettingValue<bool> m_announceToAllTiers;
|
||||
CachedSettingValue<int> m_asyncIOThreads;
|
||||
CachedSettingValue<int> m_checkingMemUsage;
|
||||
CachedSettingValue<int> m_diskCacheSize;
|
||||
CachedSettingValue<int> m_diskCacheTTL;
|
||||
CachedSettingValue<bool> m_useOSCache;
|
||||
@@ -753,13 +765,17 @@ namespace BitTorrent
|
||||
|
||||
QHash<InfoHash, TorrentInfo> m_loadedMetadata;
|
||||
QHash<InfoHash, TorrentHandle *> m_torrents;
|
||||
QHash<InfoHash, AddTorrentData> m_addingTorrents;
|
||||
QHash<InfoHash, CreateTorrentParams> m_addingTorrents;
|
||||
QHash<QString, AddTorrentParams> m_downloadedTorrents;
|
||||
QHash<InfoHash, RemovingTorrentData> m_removingTorrents;
|
||||
TorrentStatusReport m_torrentStatusReport;
|
||||
QStringMap m_categories;
|
||||
QSet<QString> m_tags;
|
||||
|
||||
// I/O errored torrents
|
||||
QSet<InfoHash> m_recentErroredTorrents;
|
||||
QTimer *m_recentErroredTorrentsTimer;
|
||||
|
||||
#if LIBTORRENT_VERSION_NUM < 10100
|
||||
QMutex m_alertsMutex;
|
||||
QWaitCondition m_alertsWaitCondition;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2010 Christophe Dumez
|
||||
* Copyright (C) 2010 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
|
||||
@@ -24,8 +24,6 @@
|
||||
* 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 "torrentcreatorthread.h"
|
||||
@@ -91,7 +89,7 @@ void TorrentCreatorThread::run()
|
||||
emit updateProgress(0);
|
||||
|
||||
try {
|
||||
const QString parentPath = Utils::Fs::branchPath(m_params.inputPath) + "/";
|
||||
const QString parentPath = Utils::Fs::branchPath(m_params.inputPath) + '/';
|
||||
|
||||
// Adding files to the torrent
|
||||
libt::file_storage fs;
|
||||
@@ -112,7 +110,7 @@ void TorrentCreatorThread::run()
|
||||
QStringList fileNames;
|
||||
QHash<QString, boost::int64_t> fileSizeMap;
|
||||
|
||||
for (const auto &dir : qAsConst(dirs)) {
|
||||
for (const auto &dir : asConst(dirs)) {
|
||||
QStringList tmpNames; // natural sort files within each dir
|
||||
|
||||
QDirIterator fileIter(dir, QDir::Files);
|
||||
@@ -128,7 +126,7 @@ void TorrentCreatorThread::run()
|
||||
fileNames += tmpNames;
|
||||
}
|
||||
|
||||
for (const auto &fileName : qAsConst(fileNames))
|
||||
for (const auto &fileName : asConst(fileNames))
|
||||
fs.add_file(fileName.toStdString(), fileSizeMap[fileName]);
|
||||
}
|
||||
|
||||
@@ -143,14 +141,14 @@ void TorrentCreatorThread::run()
|
||||
#endif
|
||||
|
||||
// Add url seeds
|
||||
foreach (QString seed, m_params.urlSeeds) {
|
||||
for (QString seed : asConst(m_params.urlSeeds)) {
|
||||
seed = seed.trimmed();
|
||||
if (!seed.isEmpty())
|
||||
newTorrent.add_url_seed(seed.toStdString());
|
||||
}
|
||||
|
||||
int tier = 0;
|
||||
foreach (const QString &tracker, m_params.trackers) {
|
||||
for (const QString &tracker : asConst(m_params.trackers)) {
|
||||
if (tracker.isEmpty())
|
||||
++tier;
|
||||
else
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2010 Christophe Dumez
|
||||
* Copyright (C) 2010 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
|
||||
@@ -24,8 +24,6 @@
|
||||
* 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 BITTORRENT_TORRENTCREATORTHREAD_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -88,10 +88,10 @@ namespace BitTorrent
|
||||
class TrackerEntry;
|
||||
struct AddTorrentParams;
|
||||
|
||||
struct AddTorrentData
|
||||
struct CreateTorrentParams
|
||||
{
|
||||
bool resumed;
|
||||
// for both new and resumed torrents
|
||||
bool restored; // is existing torrent job?
|
||||
// for both new and restored torrents
|
||||
QString name;
|
||||
QString category;
|
||||
QSet<QString> tags;
|
||||
@@ -102,18 +102,18 @@ namespace BitTorrent
|
||||
bool hasSeedStatus;
|
||||
bool skipChecking;
|
||||
bool hasRootFolder;
|
||||
bool addForced;
|
||||
bool addPaused;
|
||||
bool forced;
|
||||
bool paused;
|
||||
int uploadLimit;
|
||||
int downloadLimit;
|
||||
// for new torrents
|
||||
QVector<int> filePriorities;
|
||||
// for resumed torrents
|
||||
// for restored torrents
|
||||
qreal ratioLimit;
|
||||
int seedingTimeLimit;
|
||||
|
||||
AddTorrentData();
|
||||
AddTorrentData(const AddTorrentParams ¶ms);
|
||||
CreateTorrentParams();
|
||||
CreateTorrentParams(const AddTorrentParams ¶ms);
|
||||
};
|
||||
|
||||
struct TrackerInfo
|
||||
@@ -149,6 +149,8 @@ namespace BitTorrent
|
||||
PausedDownloading,
|
||||
PausedUploading,
|
||||
|
||||
Moving,
|
||||
|
||||
MissingFiles,
|
||||
Error
|
||||
};
|
||||
@@ -156,6 +158,7 @@ namespace BitTorrent
|
||||
class TorrentHandle : public QObject
|
||||
{
|
||||
Q_DISABLE_COPY(TorrentHandle)
|
||||
Q_DECLARE_TR_FUNCTIONS(BitTorrent::TorrentHandle)
|
||||
|
||||
public:
|
||||
static const qreal USE_GLOBAL_RATIO;
|
||||
@@ -168,7 +171,7 @@ namespace BitTorrent
|
||||
static const int MAX_SEEDING_TIME;
|
||||
|
||||
TorrentHandle(Session *session, const libtorrent::torrent_handle &nativeHandle,
|
||||
const AddTorrentData &data);
|
||||
const CreateTorrentParams ¶ms);
|
||||
~TorrentHandle();
|
||||
|
||||
bool isValid() const;
|
||||
@@ -331,7 +334,7 @@ namespace BitTorrent
|
||||
void setName(const QString &name);
|
||||
void setSequentialDownload(bool b);
|
||||
void toggleSequentialDownload();
|
||||
void setFirstLastPiecePriority(bool b);
|
||||
void setFirstLastPiecePriority(bool enabled);
|
||||
void toggleFirstLastPiecePriority();
|
||||
void pause();
|
||||
void resume(bool forced = false);
|
||||
@@ -345,7 +348,6 @@ namespace BitTorrent
|
||||
void renameFile(int index, const QString &name);
|
||||
bool saveTorrentFile(const QString &path);
|
||||
void prioritizeFiles(const QVector<int> &priorities);
|
||||
void setFilePriority(int index, int priority);
|
||||
void setRatioLimit(qreal limit);
|
||||
void setSeedingTimeLimit(int limit);
|
||||
void setUploadLimit(int limit);
|
||||
@@ -353,7 +355,7 @@ namespace BitTorrent
|
||||
void setSuperSeeding(bool enable);
|
||||
void flushCache();
|
||||
void addTrackers(const QList<TrackerEntry> &trackers);
|
||||
void replaceTrackers(QList<TrackerEntry> trackers);
|
||||
void replaceTrackers(const QList<TrackerEntry> &trackers);
|
||||
void addUrlSeeds(const QList<QUrl> &urlSeeds);
|
||||
void removeUrlSeeds(const QList<QUrl> &urlSeeds);
|
||||
bool connectPeer(const PeerAddress &peerAddress);
|
||||
@@ -370,7 +372,7 @@ namespace BitTorrent
|
||||
void handleTempPathChanged();
|
||||
void handleCategorySavePathChanged();
|
||||
void handleAppendExtensionToggled();
|
||||
void saveResumeData(bool updateStatus = false);
|
||||
void saveResumeData();
|
||||
|
||||
/**
|
||||
* @brief fraction of file pieces that are available at least from one peer
|
||||
@@ -383,30 +385,36 @@ namespace BitTorrent
|
||||
private:
|
||||
typedef boost::function<void ()> EventTrigger;
|
||||
|
||||
#if (LIBTORRENT_VERSION_NUM < 10200)
|
||||
using LTFileIndex = int;
|
||||
#else
|
||||
using LTFileIndex = lt::file_index_t;
|
||||
#endif
|
||||
|
||||
void updateStatus();
|
||||
void updateStatus(const libtorrent::torrent_status &nativeStatus);
|
||||
void updateState();
|
||||
void updateTorrentInfo();
|
||||
|
||||
void handleStorageMovedAlert(libtorrent::storage_moved_alert *p);
|
||||
void handleStorageMovedFailedAlert(libtorrent::storage_moved_failed_alert *p);
|
||||
void handleTrackerReplyAlert(libtorrent::tracker_reply_alert *p);
|
||||
void handleTrackerWarningAlert(libtorrent::tracker_warning_alert *p);
|
||||
void handleTrackerErrorAlert(libtorrent::tracker_error_alert *p);
|
||||
void handleTorrentCheckedAlert(libtorrent::torrent_checked_alert *p);
|
||||
void handleTorrentFinishedAlert(libtorrent::torrent_finished_alert *p);
|
||||
void handleTorrentPausedAlert(libtorrent::torrent_paused_alert *p);
|
||||
void handleTorrentResumedAlert(libtorrent::torrent_resumed_alert *p);
|
||||
void handleSaveResumeDataAlert(libtorrent::save_resume_data_alert *p);
|
||||
void handleSaveResumeDataFailedAlert(libtorrent::save_resume_data_failed_alert *p);
|
||||
void handleFastResumeRejectedAlert(libtorrent::fastresume_rejected_alert *p);
|
||||
void handleFileRenamedAlert(libtorrent::file_renamed_alert *p);
|
||||
void handleFileRenameFailedAlert(libtorrent::file_rename_failed_alert *p);
|
||||
void handleFileCompletedAlert(libtorrent::file_completed_alert *p);
|
||||
void handleMetadataReceivedAlert(libtorrent::metadata_received_alert *p);
|
||||
void handleStatsAlert(libtorrent::stats_alert *p);
|
||||
void handleStorageMovedAlert(const libtorrent::storage_moved_alert *p);
|
||||
void handleStorageMovedFailedAlert(const libtorrent::storage_moved_failed_alert *p);
|
||||
void handleTrackerReplyAlert(const libtorrent::tracker_reply_alert *p);
|
||||
void handleTrackerWarningAlert(const libtorrent::tracker_warning_alert *p);
|
||||
void handleTrackerErrorAlert(const libtorrent::tracker_error_alert *p);
|
||||
void handleTorrentCheckedAlert(const libtorrent::torrent_checked_alert *p);
|
||||
void handleTorrentFinishedAlert(const libtorrent::torrent_finished_alert *p);
|
||||
void handleTorrentPausedAlert(const libtorrent::torrent_paused_alert *p);
|
||||
void handleTorrentResumedAlert(const libtorrent::torrent_resumed_alert *p);
|
||||
void handleSaveResumeDataAlert(const libtorrent::save_resume_data_alert *p);
|
||||
void handleSaveResumeDataFailedAlert(const libtorrent::save_resume_data_failed_alert *p);
|
||||
void handleFastResumeRejectedAlert(const libtorrent::fastresume_rejected_alert *p);
|
||||
void handleFileRenamedAlert(const libtorrent::file_renamed_alert *p);
|
||||
void handleFileRenameFailedAlert(const libtorrent::file_rename_failed_alert *p);
|
||||
void handleFileCompletedAlert(const libtorrent::file_completed_alert *p);
|
||||
void handleMetadataReceivedAlert(const libtorrent::metadata_received_alert *p);
|
||||
void handleStatsAlert(const libtorrent::stats_alert *p);
|
||||
|
||||
void resume_impl(bool forced, bool uploadMode);
|
||||
void resume_impl(bool forced);
|
||||
bool isMoveInProgress() const;
|
||||
QString nativeActualSavePath() const;
|
||||
|
||||
@@ -418,6 +426,7 @@ namespace BitTorrent
|
||||
bool addTracker(const TrackerEntry &tracker);
|
||||
bool addUrlSeed(const QUrl &urlSeed);
|
||||
bool removeUrlSeed(const QUrl &urlSeed);
|
||||
void setFirstLastPiecePriorityImpl(bool enabled, const QVector<int> &updatedFilePrio = {});
|
||||
|
||||
Session *const m_session;
|
||||
libtorrent::torrent_handle m_nativeHandle;
|
||||
@@ -443,6 +452,10 @@ namespace BitTorrent
|
||||
QQueue<EventTrigger> m_moveFinishedTriggers;
|
||||
int m_renameCount;
|
||||
|
||||
// Until libtorrent provide an "old_name" field in `file_renamed_alert`
|
||||
// we will rely on this workaround to remove empty leftover folders
|
||||
QHash<LTFileIndex, QVector<QString>> m_oldPath;
|
||||
|
||||
bool m_useAutoTMM;
|
||||
|
||||
// Persistent data
|
||||
@@ -454,13 +467,26 @@ namespace BitTorrent
|
||||
qreal m_ratioLimit;
|
||||
int m_seedingTimeLimit;
|
||||
bool m_tempPathDisabled;
|
||||
bool m_fastresumeDataRejected;
|
||||
bool m_hasMissingFiles;
|
||||
bool m_hasRootFolder;
|
||||
bool m_needsToSetFirstLastPiecePriority;
|
||||
bool m_needsToStartForced;
|
||||
|
||||
bool m_pauseAfterRecheck;
|
||||
bool m_needSaveResumeData;
|
||||
QHash<QString, TrackerInfo> m_trackerInfos;
|
||||
|
||||
enum StartupState
|
||||
{
|
||||
Preparing, // torrent is preparing to start regular processing
|
||||
Starting, // torrent is prepared and starting to perform regular processing
|
||||
Started // torrent is performing regular processing
|
||||
};
|
||||
StartupState m_startupState = Preparing;
|
||||
// Handle torrent state when it starts performing some service job
|
||||
// being in Paused state so it might be unpaused internally and then paused again
|
||||
bool m_pauseWhenReady;
|
||||
|
||||
bool m_unchecked = false;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -26,20 +26,21 @@
|
||||
* exception statement from your version.
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include <QUrl>
|
||||
#include <QDateTime>
|
||||
#include "torrentinfo.h"
|
||||
|
||||
#include <libtorrent/error_code.hpp>
|
||||
|
||||
#include "base/utils/misc.h"
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
|
||||
#include "base/global.h"
|
||||
#include "base/utils/fs.h"
|
||||
#include "base/utils/misc.h"
|
||||
#include "base/utils/string.h"
|
||||
#include "infohash.h"
|
||||
#include "trackerentry.h"
|
||||
#include "torrentinfo.h"
|
||||
|
||||
namespace libt = libtorrent;
|
||||
using namespace BitTorrent;
|
||||
@@ -62,46 +63,6 @@ TorrentInfo &TorrentInfo::operator=(const TorrentInfo &other)
|
||||
|
||||
TorrentInfo TorrentInfo::load(const QByteArray &data, QString *error) noexcept
|
||||
{
|
||||
libt::error_code ec;
|
||||
TorrentInfo info(NativePtr(new libt::torrent_info(data.constData(), data.size(), ec)));
|
||||
if (error) {
|
||||
if (ec)
|
||||
*error = QString::fromStdString(ec.message());
|
||||
else
|
||||
error->clear();
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString *error) noexcept
|
||||
{
|
||||
if (error)
|
||||
error->clear();
|
||||
|
||||
QFile file {path};
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
if (error)
|
||||
*error = file.errorString();
|
||||
return TorrentInfo();
|
||||
}
|
||||
|
||||
const qint64 fileSizeLimit = 100 * 1024 * 1024; // 100 MB
|
||||
if (file.size() > fileSizeLimit) {
|
||||
if (error)
|
||||
*error = tr("File size exceeds max limit %1").arg(fileSizeLimit);
|
||||
return TorrentInfo();
|
||||
}
|
||||
|
||||
const QByteArray data = file.read(fileSizeLimit);
|
||||
if (data.size() != file.size()) {
|
||||
if (error)
|
||||
*error = tr("Torrent file read error");
|
||||
return TorrentInfo();
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
// 2-step construction to overcome default limits of `depth_limit` & `token_limit` which are
|
||||
// used in `torrent_info()` constructor
|
||||
const int depthLimit = 100;
|
||||
@@ -133,6 +94,44 @@ TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString *error) noexc
|
||||
return info;
|
||||
}
|
||||
|
||||
TorrentInfo TorrentInfo::loadFromFile(const QString &path, QString *error) noexcept
|
||||
{
|
||||
if (error)
|
||||
error->clear();
|
||||
|
||||
QFile file {path};
|
||||
if (!file.open(QIODevice::ReadOnly)) {
|
||||
if (error)
|
||||
*error = file.errorString();
|
||||
return TorrentInfo();
|
||||
}
|
||||
|
||||
if (file.size() > MAX_TORRENT_SIZE) {
|
||||
if (error)
|
||||
*error = tr("File size exceeds max limit %1").arg(Utils::Misc::friendlyUnit(MAX_TORRENT_SIZE));
|
||||
return TorrentInfo();
|
||||
}
|
||||
|
||||
QByteArray data;
|
||||
try {
|
||||
data = file.readAll();
|
||||
}
|
||||
catch (const std::bad_alloc &e) {
|
||||
if (error)
|
||||
*error = tr("Torrent file read error: %1").arg(e.what());
|
||||
return TorrentInfo();
|
||||
}
|
||||
if (data.size() != file.size()) {
|
||||
if (error)
|
||||
*error = tr("Torrent file read error: size mismatch");
|
||||
return TorrentInfo();
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
return load(data, error);
|
||||
}
|
||||
|
||||
bool TorrentInfo::isValid() const
|
||||
{
|
||||
return (m_nativeInfo && m_nativeInfo->is_valid() && (m_nativeInfo->num_files() > 0));
|
||||
@@ -248,7 +247,7 @@ QList<TrackerEntry> TorrentInfo::trackers() const
|
||||
if (!isValid()) return QList<TrackerEntry>();
|
||||
|
||||
QList<TrackerEntry> trackers;
|
||||
foreach (const libt::announce_entry &tracker, m_nativeInfo->trackers())
|
||||
for (const libt::announce_entry &tracker : m_nativeInfo->trackers())
|
||||
trackers.append(tracker);
|
||||
|
||||
return trackers;
|
||||
@@ -259,7 +258,7 @@ QList<QUrl> TorrentInfo::urlSeeds() const
|
||||
if (!isValid()) return QList<QUrl>();
|
||||
|
||||
QList<QUrl> urlSeeds;
|
||||
foreach (const libt::web_seed_entry &webSeed, m_nativeInfo->web_seeds())
|
||||
for (const libt::web_seed_entry &webSeed : m_nativeInfo->web_seeds())
|
||||
if (webSeed.type == libt::web_seed_entry::url_seed)
|
||||
urlSeeds.append(QUrl(webSeed.url.c_str()));
|
||||
|
||||
@@ -315,7 +314,7 @@ QVector<QByteArray> TorrentInfo::pieceHashes() const
|
||||
return hashes;
|
||||
}
|
||||
|
||||
TorrentInfo::PieceRange TorrentInfo::filePieces(const QString& file) const
|
||||
TorrentInfo::PieceRange TorrentInfo::filePieces(const QString &file) const
|
||||
{
|
||||
if (!isValid()) // if we do not check here the debug message will be printed, which would be not correct
|
||||
return {};
|
||||
@@ -340,21 +339,26 @@ TorrentInfo::PieceRange TorrentInfo::filePieces(int fileIndex) const
|
||||
|
||||
const libt::file_storage &files = nativeInfo()->files();
|
||||
const auto fileSize = files.file_size(fileIndex);
|
||||
const auto firstOffset = files.file_offset(fileIndex);
|
||||
return makeInterval(static_cast<int>(firstOffset / pieceLength()),
|
||||
static_cast<int>((firstOffset + fileSize - 1) / pieceLength()));
|
||||
const auto fileOffset = files.file_offset(fileIndex);
|
||||
|
||||
const int beginIdx = (fileOffset / pieceLength());
|
||||
const int endIdx = ((fileOffset + fileSize - 1) / pieceLength());
|
||||
|
||||
if (fileSize <= 0)
|
||||
return {beginIdx, 0};
|
||||
return makeInterval(beginIdx, endIdx);
|
||||
}
|
||||
|
||||
void TorrentInfo::renameFile(uint index, const QString &newPath)
|
||||
void TorrentInfo::renameFile(const int index, const QString &newPath)
|
||||
{
|
||||
if (!isValid()) return;
|
||||
nativeInfo()->rename_file(index, Utils::Fs::toNativePath(newPath).toStdString());
|
||||
}
|
||||
|
||||
int BitTorrent::TorrentInfo::fileIndex(const QString& fileName) const
|
||||
int BitTorrent::TorrentInfo::fileIndex(const QString &fileName) const
|
||||
{
|
||||
// the check whether the object valid is not needed here
|
||||
// because filesCount() returns -1 in that case and the loop exits immediately
|
||||
// the check whether the object is valid is not needed here
|
||||
// because if filesCount() returns -1 the loop exits immediately
|
||||
for (int i = 0; i < filesCount(); ++i)
|
||||
if (fileName == filePath(i))
|
||||
return i;
|
||||
@@ -362,24 +366,29 @@ int BitTorrent::TorrentInfo::fileIndex(const QString& fileName) const
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool TorrentInfo::hasRootFolder() const
|
||||
QString TorrentInfo::rootFolder() const
|
||||
{
|
||||
QString testRootFolder;
|
||||
QString rootFolder;
|
||||
for (int i = 0; i < filesCount(); ++i) {
|
||||
const QString filePath = this->filePath(i);
|
||||
if (QDir::isAbsolutePath(filePath)) continue;
|
||||
|
||||
const auto filePathElements = filePath.splitRef('/');
|
||||
// if at least one file has no root folder, no common root folder exists
|
||||
if (filePathElements.count() <= 1) return false;
|
||||
if (filePathElements.count() <= 1) return "";
|
||||
|
||||
if (testRootFolder.isEmpty())
|
||||
testRootFolder = filePathElements.at(0).toString();
|
||||
else if (testRootFolder != filePathElements.at(0))
|
||||
return false;
|
||||
if (rootFolder.isEmpty())
|
||||
rootFolder = filePathElements.at(0).toString();
|
||||
else if (rootFolder != filePathElements.at(0))
|
||||
return "";
|
||||
}
|
||||
|
||||
return true;
|
||||
return rootFolder;
|
||||
}
|
||||
|
||||
bool TorrentInfo::hasRootFolder() const
|
||||
{
|
||||
return !rootFolder().isEmpty();
|
||||
}
|
||||
|
||||
void TorrentInfo::stripRootFolder()
|
||||
|
||||
@@ -29,21 +29,21 @@
|
||||
#ifndef BITTORRENT_TORRENTINFO_H
|
||||
#define BITTORRENT_TORRENTINFO_H
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QtGlobal>
|
||||
|
||||
#include <libtorrent/torrent_info.hpp>
|
||||
#include <libtorrent/version.hpp>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QList>
|
||||
#include <QtGlobal>
|
||||
#include <QVector>
|
||||
|
||||
#include "base/indexrange.h"
|
||||
|
||||
class QString;
|
||||
class QUrl;
|
||||
class QDateTime;
|
||||
class QStringList;
|
||||
class QByteArray;
|
||||
template<typename T> class QList;
|
||||
template<typename T> class QVector;
|
||||
class QDateTime;
|
||||
class QString;
|
||||
class QStringList;
|
||||
class QUrl;
|
||||
|
||||
namespace BitTorrent
|
||||
{
|
||||
@@ -52,7 +52,7 @@ namespace BitTorrent
|
||||
|
||||
class TorrentInfo
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS("TorrentInfo")
|
||||
Q_DECLARE_TR_FUNCTIONS(TorrentInfo)
|
||||
|
||||
public:
|
||||
#if LIBTORRENT_VERSION_NUM < 10100
|
||||
@@ -102,8 +102,9 @@ namespace BitTorrent
|
||||
PieceRange filePieces(const QString &file) const;
|
||||
PieceRange filePieces(int fileIndex) const;
|
||||
|
||||
void renameFile(uint index, const QString &newPath);
|
||||
void renameFile(int index, const QString &newPath);
|
||||
|
||||
QString rootFolder() const;
|
||||
bool hasRootFolder() const;
|
||||
void stripRootFolder();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt4 and libtorrent.
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
|
||||
*
|
||||
@@ -27,17 +27,13 @@
|
||||
* exception statement from your version.
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
#include "tracker.h"
|
||||
|
||||
#include <libtorrent/bencode.hpp>
|
||||
#include <libtorrent/entry.hpp>
|
||||
|
||||
#include "base/global.h"
|
||||
#include "base/http/server.h"
|
||||
#include "base/preferences.h"
|
||||
#include "base/utils/bytearray.h"
|
||||
#include "base/utils/string.h"
|
||||
#include "tracker.h"
|
||||
|
||||
// static limits
|
||||
static const int MAX_TORRENTS = 100;
|
||||
@@ -59,7 +55,7 @@ bool Peer::operator==(const Peer &other) const
|
||||
|
||||
QString Peer::uid() const
|
||||
{
|
||||
return ip + ":" + QString::number(port);
|
||||
return ip.toString() + ':' + QString::number(port);
|
||||
}
|
||||
|
||||
libtorrent::entry Peer::toEntry(bool noPeerId) const
|
||||
@@ -67,7 +63,7 @@ libtorrent::entry Peer::toEntry(bool noPeerId) const
|
||||
libtorrent::entry::dictionary_type peerMap;
|
||||
if (!noPeerId)
|
||||
peerMap["id"] = libtorrent::entry(peerId.toStdString());
|
||||
peerMap["ip"] = libtorrent::entry(ip.toStdString());
|
||||
peerMap["ip"] = libtorrent::entry(ip.toString().toStdString());
|
||||
peerMap["port"] = libtorrent::entry(port);
|
||||
|
||||
return libtorrent::entry(peerMap);
|
||||
@@ -132,22 +128,13 @@ Http::Response Tracker::processRequest(const Http::Request &request, const Http:
|
||||
|
||||
void Tracker::respondToAnnounceRequest()
|
||||
{
|
||||
QMap<QString, QByteArray> queryParams;
|
||||
// Parse GET parameters
|
||||
using namespace Utils::ByteArray;
|
||||
for (const QByteArray ¶m : copyAsConst(splitToViews(m_request.query, "&"))) {
|
||||
const int sepPos = param.indexOf('=');
|
||||
if (sepPos <= 0) continue; // ignores params without name
|
||||
|
||||
const QString paramName {QString::fromUtf8(param.constData(), sepPos)};
|
||||
const QByteArray paramValue {param.mid(sepPos + 1)};
|
||||
queryParams[paramName] = paramValue;
|
||||
}
|
||||
|
||||
TrackerAnnounceRequest annonceReq;
|
||||
const QMap<QString, QByteArray> &queryParams = m_request.query;
|
||||
TrackerAnnounceRequest announceReq;
|
||||
|
||||
// IP
|
||||
annonceReq.peer.ip = m_env.clientAddress.toString();
|
||||
// Use the "ip" parameter provided from tracker request first, then fall back to client IP if invalid
|
||||
const QHostAddress paramIP {QString::fromLatin1(queryParams.value("ip"))};
|
||||
announceReq.peer.ip = paramIP.isNull() ? m_env.clientAddress : paramIP;
|
||||
|
||||
// 1. Get info_hash
|
||||
if (!queryParams.contains("info_hash")) {
|
||||
@@ -155,7 +142,7 @@ void Tracker::respondToAnnounceRequest()
|
||||
status(101, "Missing info_hash");
|
||||
return;
|
||||
}
|
||||
annonceReq.infoHash = queryParams.value("info_hash");
|
||||
announceReq.infoHash = queryParams.value("info_hash");
|
||||
// info_hash cannot be longer than 20 bytes
|
||||
/*if (annonce_req.info_hash.toLatin1().length() > 20) {
|
||||
qDebug("Tracker: Info_hash is not 20 byte long: %s (%d)", qUtf8Printable(annonce_req.info_hash), annonce_req.info_hash.toLatin1().length());
|
||||
@@ -169,7 +156,7 @@ void Tracker::respondToAnnounceRequest()
|
||||
status(102, "Missing peer_id");
|
||||
return;
|
||||
}
|
||||
annonceReq.peer.peerId = queryParams.value("peer_id");
|
||||
announceReq.peer.peerId = queryParams.value("peer_id");
|
||||
// peer_id cannot be longer than 20 bytes
|
||||
/*if (annonce_req.peer.peer_id.length() > 20) {
|
||||
qDebug("Tracker: peer_id is not 20 byte long: %s", qUtf8Printable(annonce_req.peer.peer_id));
|
||||
@@ -184,52 +171,52 @@ void Tracker::respondToAnnounceRequest()
|
||||
return;
|
||||
}
|
||||
bool ok = false;
|
||||
annonceReq.peer.port = queryParams.value("port").toInt(&ok);
|
||||
if (!ok || (annonceReq.peer.port < 0) || (annonceReq.peer.port > 65535)) {
|
||||
qDebug("Tracker: Invalid port number (%d)", annonceReq.peer.port);
|
||||
announceReq.peer.port = queryParams.value("port").toInt(&ok);
|
||||
if (!ok || (announceReq.peer.port < 0) || (announceReq.peer.port > 65535)) {
|
||||
qDebug("Tracker: Invalid port number (%d)", announceReq.peer.port);
|
||||
status(103, "Missing port");
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. Get event
|
||||
annonceReq.event = "";
|
||||
announceReq.event = "";
|
||||
if (queryParams.contains("event")) {
|
||||
annonceReq.event = queryParams.value("event");
|
||||
qDebug("Tracker: event is %s", qUtf8Printable(annonceReq.event));
|
||||
announceReq.event = queryParams.value("event");
|
||||
qDebug("Tracker: event is %s", qUtf8Printable(announceReq.event));
|
||||
}
|
||||
|
||||
// 5. Get numwant
|
||||
annonceReq.numwant = 50;
|
||||
announceReq.numwant = 50;
|
||||
if (queryParams.contains("numwant")) {
|
||||
int tmp = queryParams.value("numwant").toInt();
|
||||
if (tmp > 0) {
|
||||
qDebug("Tracker: numwant = %d", tmp);
|
||||
annonceReq.numwant = tmp;
|
||||
announceReq.numwant = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// 6. no_peer_id (extension)
|
||||
annonceReq.noPeerId = false;
|
||||
announceReq.noPeerId = false;
|
||||
if (queryParams.contains("no_peer_id"))
|
||||
annonceReq.noPeerId = true;
|
||||
announceReq.noPeerId = true;
|
||||
|
||||
// 7. TODO: support "compact" extension
|
||||
|
||||
// Done parsing, now let's reply
|
||||
if (annonceReq.event == "stopped") {
|
||||
unregisterPeer(annonceReq);
|
||||
if (announceReq.event == "stopped") {
|
||||
unregisterPeer(announceReq);
|
||||
}
|
||||
else {
|
||||
registerPeer(annonceReq);
|
||||
replyWithPeerList(annonceReq);
|
||||
registerPeer(announceReq);
|
||||
replyWithPeerList(announceReq);
|
||||
}
|
||||
}
|
||||
|
||||
void Tracker::registerPeer(const TrackerAnnounceRequest &annonceReq)
|
||||
void Tracker::registerPeer(const TrackerAnnounceRequest &announceReq)
|
||||
{
|
||||
if (annonceReq.peer.port == 0) return;
|
||||
if (announceReq.peer.port == 0) return;
|
||||
|
||||
if (!m_torrents.contains(annonceReq.infoHash)) {
|
||||
if (!m_torrents.contains(announceReq.infoHash)) {
|
||||
// Unknown torrent
|
||||
if (m_torrents.size() == MAX_TORRENTS) {
|
||||
// Reached max size, remove a random torrent
|
||||
@@ -238,34 +225,34 @@ void Tracker::registerPeer(const TrackerAnnounceRequest &annonceReq)
|
||||
}
|
||||
|
||||
// Register the user
|
||||
PeerList &peers = m_torrents[annonceReq.infoHash];
|
||||
if (!peers.contains(annonceReq.peer.uid())) {
|
||||
PeerList &peers = m_torrents[announceReq.infoHash];
|
||||
if (!peers.contains(announceReq.peer.uid())) {
|
||||
// Unknown peer
|
||||
if (peers.size() == MAX_PEERS_PER_TORRENT) {
|
||||
// Too many peers, remove a random one
|
||||
peers.erase(peers.begin());
|
||||
}
|
||||
}
|
||||
peers[annonceReq.peer.uid()] = annonceReq.peer;
|
||||
peers[announceReq.peer.uid()] = announceReq.peer;
|
||||
}
|
||||
|
||||
void Tracker::unregisterPeer(const TrackerAnnounceRequest &annonceReq)
|
||||
void Tracker::unregisterPeer(const TrackerAnnounceRequest &announceReq)
|
||||
{
|
||||
if (annonceReq.peer.port == 0) return;
|
||||
if (announceReq.peer.port == 0) return;
|
||||
|
||||
if (m_torrents[annonceReq.infoHash].remove(annonceReq.peer.uid()) > 0)
|
||||
if (m_torrents[announceReq.infoHash].remove(announceReq.peer.uid()) > 0)
|
||||
qDebug("Tracker: Peer stopped downloading, deleting it from the list");
|
||||
}
|
||||
|
||||
void Tracker::replyWithPeerList(const TrackerAnnounceRequest &annonceReq)
|
||||
void Tracker::replyWithPeerList(const TrackerAnnounceRequest &announceReq)
|
||||
{
|
||||
// Prepare the entry for bencoding
|
||||
libtorrent::entry::dictionary_type replyDict;
|
||||
replyDict["interval"] = libtorrent::entry(ANNOUNCE_INTERVAL);
|
||||
|
||||
libtorrent::entry::list_type peerList;
|
||||
for (const Peer &p : m_torrents.value(annonceReq.infoHash))
|
||||
peerList.push_back(p.toEntry(annonceReq.noPeerId));
|
||||
for (const Peer &p : m_torrents.value(announceReq.infoHash))
|
||||
peerList.push_back(p.toEntry(announceReq.noPeerId));
|
||||
replyDict["peers"] = libtorrent::entry(peerList);
|
||||
|
||||
const libtorrent::entry replyEntry(replyDict);
|
||||
@@ -277,5 +264,3 @@ void Tracker::replyWithPeerList(const TrackerAnnounceRequest &annonceReq)
|
||||
// HTTP reply
|
||||
print(reply, Http::CONTENT_TYPE_TXT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -32,10 +32,10 @@
|
||||
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <QHostAddress>
|
||||
|
||||
#include "base/http/irequesthandler.h"
|
||||
#include "base/http/responsebuilder.h"
|
||||
#include "base/http/types.h"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
@@ -51,7 +51,7 @@ namespace BitTorrent
|
||||
{
|
||||
struct Peer
|
||||
{
|
||||
QString ip;
|
||||
QHostAddress ip;
|
||||
QByteArray peerId;
|
||||
int port;
|
||||
|
||||
@@ -90,9 +90,9 @@ namespace BitTorrent
|
||||
|
||||
private:
|
||||
void respondToAnnounceRequest();
|
||||
void registerPeer(const TrackerAnnounceRequest &annonceReq);
|
||||
void unregisterPeer(const TrackerAnnounceRequest &annonceReq);
|
||||
void replyWithPeerList(const TrackerAnnounceRequest &annonceReq);
|
||||
void registerPeer(const TrackerAnnounceRequest &announceReq);
|
||||
void unregisterPeer(const TrackerAnnounceRequest &announceReq);
|
||||
void replyWithPeerList(const TrackerAnnounceRequest &announceReq);
|
||||
|
||||
Http::Server *m_server;
|
||||
TorrentList m_torrents;
|
||||
|
||||
@@ -26,11 +26,12 @@
|
||||
* exception statement from your version.
|
||||
*/
|
||||
|
||||
#include "trackerentry.h"
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "base/utils/misc.h"
|
||||
#include "base/utils/string.h"
|
||||
#include "trackerentry.h"
|
||||
|
||||
using namespace BitTorrent;
|
||||
|
||||
|
||||
@@ -44,10 +44,10 @@ namespace BitTorrent
|
||||
public:
|
||||
enum Status
|
||||
{
|
||||
NotContacted,
|
||||
Working,
|
||||
Updating,
|
||||
NotWorking
|
||||
NotContacted = 1,
|
||||
Working = 2,
|
||||
Updating = 3,
|
||||
NotWorking = 4
|
||||
};
|
||||
|
||||
TrackerEntry(const QString &url);
|
||||
|
||||
@@ -30,11 +30,10 @@
|
||||
|
||||
RuntimeError::RuntimeError(const QString &message)
|
||||
: std::runtime_error {message.toUtf8().data()}
|
||||
, m_message {message}
|
||||
{
|
||||
}
|
||||
|
||||
QString RuntimeError::message() const
|
||||
{
|
||||
return m_message;
|
||||
return what();
|
||||
}
|
||||
|
||||
@@ -36,7 +36,4 @@ class RuntimeError : public std::runtime_error
|
||||
public:
|
||||
explicit RuntimeError(const QString &message = "");
|
||||
QString message() const;
|
||||
|
||||
private:
|
||||
const QString m_message;
|
||||
};
|
||||
|
||||
@@ -28,18 +28,19 @@
|
||||
|
||||
#include "filesystemwatcher.h"
|
||||
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_FREEBSD)
|
||||
#include <QtGlobal>
|
||||
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
|
||||
#include <cstring>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
#include "base/algorithm.h"
|
||||
#include "base/bittorrent/magneturi.h"
|
||||
#include "base/bittorrent/torrentinfo.h"
|
||||
#include "base/global.h"
|
||||
#include "base/logger.h"
|
||||
#include "base/preferences.h"
|
||||
#include "base/utils/fs.h"
|
||||
|
||||
@@ -57,18 +58,14 @@ FileSystemWatcher::FileSystemWatcher(QObject *parent)
|
||||
m_partialTorrentTimer.setSingleShot(true);
|
||||
connect(&m_partialTorrentTimer, &QTimer::timeout, this, &FileSystemWatcher::processPartialTorrents);
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
connect(&m_watchTimer, &QTimer::timeout, this, &FileSystemWatcher::scanNetworkFolders);
|
||||
#endif
|
||||
}
|
||||
|
||||
QStringList FileSystemWatcher::directories() const
|
||||
{
|
||||
QStringList dirs = QFileSystemWatcher::directories();
|
||||
#ifndef Q_OS_WIN
|
||||
for (const QDir &dir : qAsConst(m_watchedFolders))
|
||||
for (const QDir &dir : asConst(m_watchedFolders))
|
||||
dirs << dir.canonicalPath();
|
||||
#endif
|
||||
return dirs;
|
||||
}
|
||||
|
||||
@@ -76,15 +73,14 @@ void FileSystemWatcher::addPath(const QString &path)
|
||||
{
|
||||
if (path.isEmpty()) return;
|
||||
|
||||
#if !defined Q_OS_WIN && !defined Q_OS_HAIKU
|
||||
#if !defined Q_OS_HAIKU
|
||||
const QDir dir(path);
|
||||
if (!dir.exists()) return;
|
||||
|
||||
// Check if the path points to a network file system or not
|
||||
if (Utils::Fs::isNetworkFileSystem(path)) {
|
||||
// Network mode
|
||||
qDebug("Network folder detected: %s", qUtf8Printable(path));
|
||||
qDebug("Using file polling mode instead of inotify...");
|
||||
LogMsg(tr("Watching remote folder: \"%1\"").arg(Utils::Fs::toNativePath(path)));
|
||||
m_watchedFolders << dir;
|
||||
|
||||
m_watchTimer.start(WATCH_INTERVAL);
|
||||
@@ -93,20 +89,19 @@ void FileSystemWatcher::addPath(const QString &path)
|
||||
#endif
|
||||
|
||||
// Normal mode
|
||||
qDebug("FS Watcher is watching %s in normal mode", qUtf8Printable(path));
|
||||
LogMsg(tr("Watching local folder: \"%1\"").arg(Utils::Fs::toNativePath(path)));
|
||||
QFileSystemWatcher::addPath(path);
|
||||
scanLocalFolder(path);
|
||||
}
|
||||
|
||||
void FileSystemWatcher::removePath(const QString &path)
|
||||
{
|
||||
#ifndef Q_OS_WIN
|
||||
if (m_watchedFolders.removeOne(path)) {
|
||||
if (m_watchedFolders.isEmpty())
|
||||
m_watchTimer.stop();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Normal mode
|
||||
QFileSystemWatcher::removePath(path);
|
||||
}
|
||||
@@ -116,13 +111,11 @@ void FileSystemWatcher::scanLocalFolder(const QString &path)
|
||||
QTimer::singleShot(2000, this, [this, path]() { processTorrentsInDir(path); });
|
||||
}
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
void FileSystemWatcher::scanNetworkFolders()
|
||||
{
|
||||
for (const QDir &dir : qAsConst(m_watchedFolders))
|
||||
for (const QDir &dir : asConst(m_watchedFolders))
|
||||
processTorrentsInDir(dir);
|
||||
}
|
||||
#endif
|
||||
|
||||
void FileSystemWatcher::processPartialTorrents()
|
||||
{
|
||||
@@ -169,7 +162,7 @@ void FileSystemWatcher::processTorrentsInDir(const QDir &dir)
|
||||
const QStringList files = dir.entryList({"*.torrent", "*.magnet"}, QDir::Files);
|
||||
for (const QString &file : files) {
|
||||
const QString fileAbsPath = dir.absoluteFilePath(file);
|
||||
if (file.endsWith(".magnet"))
|
||||
if (file.endsWith(".magnet", Qt::CaseInsensitive))
|
||||
torrents << fileAbsPath;
|
||||
else if (BitTorrent::TorrentInfo::loadFromFile(fileAbsPath).isValid())
|
||||
torrents << fileAbsPath;
|
||||
|
||||
@@ -56,9 +56,7 @@ signals:
|
||||
protected slots:
|
||||
void scanLocalFolder(const QString &path);
|
||||
void processPartialTorrents();
|
||||
#ifndef Q_OS_WIN
|
||||
void scanNetworkFolders();
|
||||
#endif
|
||||
|
||||
private:
|
||||
void processTorrentsInDir(const QDir &dir);
|
||||
@@ -67,10 +65,8 @@ private:
|
||||
QHash<QString, int> m_partialTorrents;
|
||||
QTimer m_partialTorrentTimer;
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
QList<QDir> m_watchedFolders;
|
||||
QTimer m_watchTimer;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // FILESYSTEMWATCHER_H
|
||||
|
||||
@@ -32,17 +32,15 @@
|
||||
#include <QtGlobal>
|
||||
|
||||
const char C_TORRENT_FILE_EXTENSION[] = ".torrent";
|
||||
const int MAX_TORRENT_SIZE = 100 * 1024 * 1024; // 100 MiB
|
||||
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 7, 0)
|
||||
template <typename T>
|
||||
constexpr typename std::add_const<T>::type &qAsConst(T &t) noexcept { return t; }
|
||||
constexpr typename std::add_const<T>::type &asConst(T &t) noexcept { return t; }
|
||||
|
||||
// prevent rvalue arguments:
|
||||
// Forward rvalue as const
|
||||
template <typename T>
|
||||
void qAsConst(const T &&) = delete;
|
||||
#endif
|
||||
constexpr typename std::add_const<T>::type asConst(T &&t) noexcept { return std::move(t); }
|
||||
|
||||
// returns a const object copy
|
||||
// Prevent const rvalue arguments
|
||||
template <typename T>
|
||||
constexpr typename std::add_const<T>::type copyAsConst(T &&t) noexcept { return std::move(t); }
|
||||
void asConst(const T &&) = delete;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2018 Mike Tzou (Chocobo1)
|
||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Ishan Arora and Christophe Dumez
|
||||
* Copyright (C) 2006 Ishan Arora and 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
|
||||
@@ -26,13 +26,10 @@
|
||||
* 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 "connection.h"
|
||||
|
||||
#include <QRegExp>
|
||||
#include <QTcpSocket>
|
||||
|
||||
#include "base/logger.h"
|
||||
@@ -69,7 +66,7 @@ void Connection::read()
|
||||
case RequestParser::ParseStatus::Incomplete: {
|
||||
const long bufferLimit = RequestParser::MAX_CONTENT_SIZE * 1.1; // some margin for headers
|
||||
if (m_receivedData.size() > bufferLimit) {
|
||||
Logger::instance()->addMessage(tr("Http request size exceeds limiation, closing socket. Limit: %ld, IP: %s")
|
||||
Logger::instance()->addMessage(tr("Http request size exceeds limiation, closing socket. Limit: %1, IP: %2")
|
||||
.arg(bufferLimit).arg(m_socket->peerAddress().toString()), Log::WARNING);
|
||||
|
||||
Response resp(413, "Payload Too Large");
|
||||
@@ -82,7 +79,7 @@ void Connection::read()
|
||||
return;
|
||||
|
||||
case RequestParser::ParseStatus::BadRequest: {
|
||||
Logger::instance()->addMessage(tr("Bad Http request, closing socket. IP: %s")
|
||||
Logger::instance()->addMessage(tr("Bad Http request, closing socket. IP: %1")
|
||||
.arg(m_socket->peerAddress().toString()), Log::WARNING);
|
||||
|
||||
Response resp(400, "Bad Request");
|
||||
@@ -136,7 +133,7 @@ bool Connection::acceptsGzipEncoding(QString codings)
|
||||
|
||||
const auto isCodingAvailable = [](const QStringList &list, const QString &encoding) -> bool
|
||||
{
|
||||
foreach (const QString &str, list) {
|
||||
for (const QString &str : list) {
|
||||
if (!str.startsWith(encoding))
|
||||
continue;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Bittorrent Client using Qt and libtorrent.
|
||||
* Copyright (C) 2014 Vladimir Golovnev <glassez@yandex.ru>
|
||||
* Copyright (C) 2006 Ishan Arora and Christophe Dumez
|
||||
* Copyright (C) 2006 Ishan Arora and 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
|
||||
@@ -25,8 +25,6 @@
|
||||
* 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
|
||||
*/
|
||||
|
||||
|
||||
@@ -50,7 +48,7 @@ namespace Http
|
||||
Q_DISABLE_COPY(Connection)
|
||||
|
||||
public:
|
||||
Connection(QTcpSocket *socket, IRequestHandler *requestHandler, QObject *parent = 0);
|
||||
Connection(QTcpSocket *socket, IRequestHandler *requestHandler, QObject *parent = nullptr);
|
||||
~Connection();
|
||||
|
||||
bool hasExpired(qint64 timeout) const;
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <QUrl>
|
||||
#include <QUrlQuery>
|
||||
|
||||
#include "base/global.h"
|
||||
#include "base/utils/bytearray.h"
|
||||
#include "base/utils/string.h"
|
||||
|
||||
@@ -180,11 +181,29 @@ bool RequestParser::parseRequestLine(const QString &line)
|
||||
m_request.method = match.captured(1);
|
||||
|
||||
// Request Target
|
||||
const QByteArray decodedUrl {QByteArray::fromPercentEncoding(match.captured(2).toLatin1())};
|
||||
const int sepPos = decodedUrl.indexOf('?');
|
||||
m_request.path = QString::fromUtf8(decodedUrl.constData(), (sepPos == -1 ? decodedUrl.size() : sepPos));
|
||||
if (sepPos >= 0)
|
||||
m_request.query = decodedUrl.mid(sepPos + 1);
|
||||
const QByteArray url {match.captured(2).toLatin1()};
|
||||
const int sepPos = url.indexOf('?');
|
||||
const QByteArray pathComponent = ((sepPos == -1) ? url : midView(url, 0, sepPos));
|
||||
|
||||
m_request.path = QString::fromUtf8(QByteArray::fromPercentEncoding(pathComponent));
|
||||
|
||||
if (sepPos >= 0) {
|
||||
const QByteArray query = midView(url, (sepPos + 1));
|
||||
|
||||
// [rfc3986] 2.4 When to Encode or Decode
|
||||
// URL components should be separated before percent-decoding
|
||||
for (const QByteArray ¶m : asConst(splitToViews(query, "&"))) {
|
||||
const int eqCharPos = param.indexOf('=');
|
||||
if (eqCharPos <= 0) continue; // ignores params without name
|
||||
|
||||
const QByteArray nameComponent = midView(param, 0, eqCharPos);
|
||||
const QByteArray valueComponent = midView(param, (eqCharPos + 1));
|
||||
const QString paramName = QString::fromUtf8(QByteArray::fromPercentEncoding(nameComponent).replace('+', ' '));
|
||||
const QByteArray paramValue = QByteArray::fromPercentEncoding(valueComponent).replace('+', ' ');
|
||||
|
||||
m_request.query[paramName] = paramValue;
|
||||
}
|
||||
}
|
||||
|
||||
// HTTP-version
|
||||
m_request.version = match.captured(3);
|
||||
@@ -200,7 +219,10 @@ bool RequestParser::parsePostMessage(const QByteArray &data)
|
||||
|
||||
// application/x-www-form-urlencoded
|
||||
if (contentTypeLower.startsWith(CONTENT_TYPE_FORM_ENCODED)) {
|
||||
QListIterator<QStringPair> i(QUrlQuery(data).queryItems(QUrl::FullyDecoded));
|
||||
// [URL Standard] 5.1 application/x-www-form-urlencoded parsing
|
||||
const QByteArray processedData = QByteArray(data).replace('+', ' ');
|
||||
|
||||
QListIterator<QStringPair> i(QUrlQuery(processedData).queryItems(QUrl::FullyDecoded));
|
||||
while (i.hasNext()) {
|
||||
const QStringPair pair = i.next();
|
||||
m_request.posts[pair.first] = pair.second;
|
||||
@@ -291,7 +313,7 @@ bool RequestParser::parseFormData(const QByteArray &data)
|
||||
const QLatin1String name("name");
|
||||
|
||||
if (headersMap.contains(filename)) {
|
||||
m_request.files.append({filename, headersMap[HEADER_CONTENT_TYPE], payload});
|
||||
m_request.files.append({headersMap[filename], headersMap[HEADER_CONTENT_TYPE], payload});
|
||||
}
|
||||
else if (headersMap.contains(name)) {
|
||||
m_request.posts[headersMap[name]] = payload;
|
||||
|
||||
@@ -97,16 +97,23 @@ void Server::incomingConnection(qintptr socketDescriptor)
|
||||
#endif
|
||||
|
||||
Connection *c = new Connection(serverSocket, m_requestHandler, this);
|
||||
m_connections.append(c);
|
||||
m_connections.insert(c);
|
||||
connect(serverSocket, &QAbstractSocket::disconnected, this, [c, this]() { removeConnection(c); });
|
||||
}
|
||||
|
||||
void Server::removeConnection(Connection *connection)
|
||||
{
|
||||
m_connections.remove(connection);
|
||||
connection->deleteLater();
|
||||
}
|
||||
|
||||
void Server::dropTimedOutConnection()
|
||||
{
|
||||
QMutableListIterator<Connection *> i(m_connections);
|
||||
QMutableSetIterator<Connection *> i(m_connections);
|
||||
while (i.hasNext()) {
|
||||
auto connection = i.next();
|
||||
if (connection->isClosed() || connection->hasExpired(KEEP_ALIVE_DURATION)) {
|
||||
delete connection;
|
||||
Connection *connection = i.next();
|
||||
if (connection->hasExpired(KEEP_ALIVE_DURATION)) {
|
||||
connection->deleteLater();
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
@@ -146,9 +153,9 @@ QList<QSslCipher> Server::safeCipherList() const
|
||||
const QStringList badCiphers = {"idea", "rc4"};
|
||||
const QList<QSslCipher> allCiphers = QSslSocket::supportedCiphers();
|
||||
QList<QSslCipher> safeCiphers;
|
||||
foreach (const QSslCipher &cipher, allCiphers) {
|
||||
for (const QSslCipher &cipher : allCiphers) {
|
||||
bool isSafe = true;
|
||||
foreach (const QString &badCipher, badCiphers) {
|
||||
for (const QString &badCipher : badCiphers) {
|
||||
if (cipher.name().contains(badCipher, Qt::CaseInsensitive)) {
|
||||
isSafe = false;
|
||||
break;
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#ifndef HTTP_SERVER_H
|
||||
#define HTTP_SERVER_H
|
||||
|
||||
#include <QSet>
|
||||
#include <QTcpServer>
|
||||
|
||||
#ifndef QT_NO_OPENSSL
|
||||
@@ -63,9 +64,10 @@ namespace Http
|
||||
|
||||
private:
|
||||
void incomingConnection(qintptr socketDescriptor);
|
||||
void removeConnection(Connection *connection);
|
||||
|
||||
IRequestHandler *m_requestHandler;
|
||||
QList<Connection *> m_connections; // for tracking persistent connections
|
||||
QSet<Connection *> m_connections; // for tracking persistent connections
|
||||
|
||||
#ifndef QT_NO_OPENSSL
|
||||
QList<QSslCipher> safeCipherList() const;
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace Http
|
||||
const char HEADER_HOST[] = "host";
|
||||
const char HEADER_ORIGIN[] = "origin";
|
||||
const char HEADER_REFERER[] = "referer";
|
||||
const char HEADER_REFERRER_POLICY[] = "referrer-policy";
|
||||
const char HEADER_SET_COOKIE[] = "set-cookie";
|
||||
const char HEADER_X_CONTENT_TYPE_OPTIONS[] = "x-content-type-options";
|
||||
const char HEADER_X_FORWARDED_HOST[] = "x-forwarded-host";
|
||||
@@ -63,10 +64,12 @@ namespace Http
|
||||
const char HEADER_REQUEST_METHOD_POST[] = "POST";
|
||||
|
||||
const char CONTENT_TYPE_HTML[] = "text/html";
|
||||
const char CONTENT_TYPE_CSS[] = "text/css";
|
||||
const char CONTENT_TYPE_TXT[] = "text/plain";
|
||||
const char CONTENT_TYPE_JS[] = "application/javascript";
|
||||
const char CONTENT_TYPE_JSON[] = "application/json";
|
||||
const char CONTENT_TYPE_GIF[] = "image/gif";
|
||||
const char CONTENT_TYPE_PNG[] = "image/png";
|
||||
const char CONTENT_TYPE_TXT[] = "text/plain";
|
||||
const char CONTENT_TYPE_FORM_ENCODED[] = "application/x-www-form-urlencoded";
|
||||
const char CONTENT_TYPE_FORM_DATA[] = "multipart/form-data";
|
||||
|
||||
@@ -94,8 +97,8 @@ namespace Http
|
||||
QString version;
|
||||
QString method;
|
||||
QString path;
|
||||
QByteArray query;
|
||||
QStringMap headers;
|
||||
QMap<QString, QByteArray> query;
|
||||
QStringMap posts;
|
||||
QVector<UploadedFile> files;
|
||||
};
|
||||
@@ -105,7 +108,7 @@ namespace Http
|
||||
uint code;
|
||||
QString text;
|
||||
|
||||
ResponseStatus(uint code = 200, const QString& text = "OK"): code(code), text(text) {}
|
||||
ResponseStatus(uint code = 200, const QString &text = "OK"): code(code), text(text) {}
|
||||
};
|
||||
|
||||
struct Response
|
||||
@@ -114,7 +117,7 @@ namespace Http
|
||||
QStringMap headers;
|
||||
QByteArray content;
|
||||
|
||||
Response(uint code = 200, const QString& text = "OK"): status(code, text) {}
|
||||
Response(uint code = 200, const QString &text = "OK"): status(code, text) {}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -27,9 +27,10 @@
|
||||
* exception statement from your version.
|
||||
*/
|
||||
|
||||
#include <QString>
|
||||
#include "iconprovider.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
|
||||
IconProvider::IconProvider(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
@@ -47,7 +48,7 @@ void IconProvider::freeInstance()
|
||||
{
|
||||
if (m_instance) {
|
||||
delete m_instance;
|
||||
m_instance = 0;
|
||||
m_instance = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,9 +57,15 @@ IconProvider *IconProvider::instance()
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
QString IconProvider::getIconPath(const QString &iconId)
|
||||
QString IconProvider::getIconPath(const QString &iconId) const
|
||||
{
|
||||
return ":/icons/qbt-theme/" + iconId + ".png";
|
||||
// there are a few icons not available in svg
|
||||
const QString pathSvg = ":/icons/qbt-theme/" + iconId + ".svg";
|
||||
if (QFileInfo::exists(pathSvg))
|
||||
return pathSvg;
|
||||
|
||||
const QString pathPng = ":/icons/qbt-theme/" + iconId + ".png";
|
||||
return pathPng;
|
||||
}
|
||||
|
||||
IconProvider *IconProvider::m_instance = 0;
|
||||
IconProvider *IconProvider::m_instance = nullptr;
|
||||
|
||||
@@ -31,8 +31,7 @@
|
||||
#define ICONPROVIDER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
class QString;
|
||||
#include <QString>
|
||||
|
||||
class IconProvider : public QObject
|
||||
{
|
||||
@@ -43,10 +42,10 @@ public:
|
||||
static void freeInstance();
|
||||
static IconProvider *instance();
|
||||
|
||||
virtual QString getIconPath(const QString &iconId);
|
||||
virtual QString getIconPath(const QString &iconId) const;
|
||||
|
||||
protected:
|
||||
explicit IconProvider(QObject *parent = 0);
|
||||
explicit IconProvider(QObject *parent = nullptr);
|
||||
~IconProvider();
|
||||
|
||||
static IconProvider *m_instance;
|
||||
|
||||
@@ -38,30 +38,30 @@ class IndexInterval
|
||||
public:
|
||||
using IndexType = Index;
|
||||
|
||||
IndexInterval(IndexType first, IndexType last)
|
||||
IndexInterval(IndexType first, IndexType last) // add constexpr when using C++14
|
||||
: m_first {first}
|
||||
, m_last {last}
|
||||
{
|
||||
Q_ASSERT(first <= last);
|
||||
}
|
||||
|
||||
IndexType first() const
|
||||
constexpr IndexType first() const
|
||||
{
|
||||
return m_first;
|
||||
}
|
||||
|
||||
IndexType last() const
|
||||
constexpr IndexType last() const
|
||||
{
|
||||
return m_last;
|
||||
}
|
||||
|
||||
private:
|
||||
IndexType m_first;
|
||||
IndexType m_last;
|
||||
const IndexType m_first;
|
||||
const IndexType m_last;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline IndexInterval<T> makeInterval(T first, T last)
|
||||
constexpr IndexInterval<T> makeInterval(T first, T last)
|
||||
{
|
||||
return {first, last};
|
||||
}
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
|
||||
constexpr IndexType end() const
|
||||
{
|
||||
return m_first + m_size;
|
||||
return (m_first + m_size);
|
||||
}
|
||||
|
||||
constexpr IndexDiffType size() const
|
||||
@@ -114,12 +114,12 @@ public:
|
||||
|
||||
constexpr IndexType last() const
|
||||
{
|
||||
return m_first + m_size - 1;
|
||||
return (m_first + m_size - 1);
|
||||
}
|
||||
|
||||
constexpr bool isEmpty() const
|
||||
{
|
||||
return m_size == 0;
|
||||
return (m_size == 0);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
#include <QDateTime>
|
||||
#include "base/utils/string.h"
|
||||
|
||||
Logger* Logger::m_instance = 0;
|
||||
Logger *Logger::m_instance = nullptr;
|
||||
|
||||
Logger::Logger()
|
||||
: lock(QReadWriteLock::Recursive)
|
||||
, msgCounter(0)
|
||||
, peerCounter(0)
|
||||
: m_lock(QReadWriteLock::Recursive)
|
||||
, m_msgCounter(0)
|
||||
, m_peerCounter(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -29,15 +29,15 @@ void Logger::freeInstance()
|
||||
{
|
||||
if (m_instance) {
|
||||
delete m_instance;
|
||||
m_instance = 0;
|
||||
m_instance = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::addMessage(const QString &message, const Log::MsgType &type)
|
||||
{
|
||||
QWriteLocker locker(&lock);
|
||||
QWriteLocker locker(&m_lock);
|
||||
|
||||
Log::Msg temp = { msgCounter++, QDateTime::currentMSecsSinceEpoch(), type, message.toHtmlEscaped() };
|
||||
Log::Msg temp = {m_msgCounter++, QDateTime::currentMSecsSinceEpoch(), type, message.toHtmlEscaped()};
|
||||
m_messages.push_back(temp);
|
||||
|
||||
if (m_messages.size() >= MAX_LOG_MESSAGES)
|
||||
@@ -48,9 +48,9 @@ void Logger::addMessage(const QString &message, const Log::MsgType &type)
|
||||
|
||||
void Logger::addPeer(const QString &ip, bool blocked, const QString &reason)
|
||||
{
|
||||
QWriteLocker locker(&lock);
|
||||
QWriteLocker locker(&m_lock);
|
||||
|
||||
Log::Peer temp = { peerCounter++, QDateTime::currentMSecsSinceEpoch(), ip.toHtmlEscaped(), blocked, reason.toHtmlEscaped() };
|
||||
Log::Peer temp = {m_peerCounter++, QDateTime::currentMSecsSinceEpoch(), ip.toHtmlEscaped(), blocked, reason.toHtmlEscaped()};
|
||||
m_peers.push_back(temp);
|
||||
|
||||
if (m_peers.size() >= MAX_LOG_MESSAGES)
|
||||
@@ -61,9 +61,9 @@ void Logger::addPeer(const QString &ip, bool blocked, const QString &reason)
|
||||
|
||||
QVector<Log::Msg> Logger::getMessages(int lastKnownId) const
|
||||
{
|
||||
QReadLocker locker(&lock);
|
||||
QReadLocker locker(&m_lock);
|
||||
|
||||
int diff = msgCounter - lastKnownId - 1;
|
||||
int diff = m_msgCounter - lastKnownId - 1;
|
||||
int size = m_messages.size();
|
||||
|
||||
if ((lastKnownId == -1) || (diff >= size))
|
||||
@@ -77,9 +77,9 @@ QVector<Log::Msg> Logger::getMessages(int lastKnownId) const
|
||||
|
||||
QVector<Log::Peer> Logger::getPeers(int lastKnownId) const
|
||||
{
|
||||
QReadLocker locker(&lock);
|
||||
QReadLocker locker(&m_lock);
|
||||
|
||||
int diff = peerCounter - lastKnownId - 1;
|
||||
int diff = m_peerCounter - lastKnownId - 1;
|
||||
int size = m_peers.size();
|
||||
|
||||
if ((lastKnownId == -1) || (diff >= size))
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
#ifndef LOGGER_H
|
||||
#define LOGGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QReadWriteLock>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QReadWriteLock>
|
||||
#include <QObject>
|
||||
|
||||
const int MAX_LOG_MESSAGES = 20000;
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Log
|
||||
NORMAL = 0x1,
|
||||
INFO = 0x2,
|
||||
WARNING = 0x4,
|
||||
CRITICAL = 0x8 //ERROR is defined by libtorrent and results in compiler error
|
||||
CRITICAL = 0x8 // ERROR is defined by libtorrent and results in compiler error
|
||||
};
|
||||
Q_DECLARE_FLAGS(MsgTypes, MsgType)
|
||||
|
||||
@@ -63,12 +63,12 @@ private:
|
||||
Logger();
|
||||
~Logger();
|
||||
|
||||
static Logger* m_instance;
|
||||
static Logger *m_instance;
|
||||
QVector<Log::Msg> m_messages;
|
||||
QVector<Log::Peer> m_peers;
|
||||
mutable QReadWriteLock lock;
|
||||
int msgCounter;
|
||||
int peerCounter;
|
||||
mutable QReadWriteLock m_lock;
|
||||
int m_msgCounter;
|
||||
int m_peerCounter;
|
||||
};
|
||||
|
||||
// Helper function
|
||||
|
||||
@@ -26,15 +26,15 @@
|
||||
* exception statement from your version.
|
||||
*/
|
||||
|
||||
#include "dnsupdater.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QRegExp>
|
||||
#include <QStringList>
|
||||
#include <QRegularExpression>
|
||||
#include <QUrlQuery>
|
||||
|
||||
#include "base/logger.h"
|
||||
#include "base/net/downloadhandler.h"
|
||||
#include "base/net/downloadmanager.h"
|
||||
#include "dnsupdater.h"
|
||||
|
||||
using namespace Net;
|
||||
|
||||
@@ -52,7 +52,7 @@ DNSUpdater::DNSUpdater(QObject *parent)
|
||||
|
||||
// Start IP checking timer
|
||||
m_ipCheckTimer.setInterval(IP_CHECK_INTERVAL_MS);
|
||||
connect(&m_ipCheckTimer, SIGNAL(timeout()), SLOT(checkPublicIP()));
|
||||
connect(&m_ipCheckTimer, &QTimer::timeout, this, &DNSUpdater::checkPublicIP);
|
||||
m_ipCheckTimer.start();
|
||||
|
||||
// Check lastUpdate to avoid flooding
|
||||
@@ -74,11 +74,11 @@ void DNSUpdater::checkPublicIP()
|
||||
{
|
||||
Q_ASSERT(m_state == OK);
|
||||
|
||||
DownloadHandler *handler = DownloadManager::instance()->downloadUrl(
|
||||
"http://checkip.dyndns.org", false, 0, false,
|
||||
"qBittorrent/" QBT_VERSION_2);
|
||||
connect(handler, SIGNAL(downloadFinished(QString, QByteArray)), SLOT(ipRequestFinished(QString, QByteArray)));
|
||||
connect(handler, SIGNAL(downloadFailed(QString, QString)), SLOT(ipRequestFailed(QString, QString)));
|
||||
DownloadHandler *handler = DownloadManager::instance()->download(
|
||||
DownloadRequest("http://checkip.dyndns.org").userAgent("qBittorrent/" QBT_VERSION_2));
|
||||
connect(handler, static_cast<void (Net::DownloadHandler::*)(const QString &, const QByteArray &)>(&Net::DownloadHandler::downloadFinished)
|
||||
, this, &DNSUpdater::ipRequestFinished);
|
||||
connect(handler, &Net::DownloadHandler::downloadFailed, this, &DNSUpdater::ipRequestFailed);
|
||||
|
||||
m_lastIPCheckTime = QDateTime::currentDateTime();
|
||||
}
|
||||
@@ -88,9 +88,9 @@ void DNSUpdater::ipRequestFinished(const QString &url, const QByteArray &data)
|
||||
Q_UNUSED(url);
|
||||
|
||||
// Parse response
|
||||
QRegExp ipregex("Current IP Address:\\s+([^<]+)</body>");
|
||||
if (ipregex.indexIn(data) >= 0) {
|
||||
QString ipStr = ipregex.cap(1);
|
||||
const QRegularExpressionMatch ipRegexMatch = QRegularExpression("Current IP Address:\\s+([^<]+)</body>").match(data);
|
||||
if (ipRegexMatch.hasMatch()) {
|
||||
QString ipStr = ipRegexMatch.captured(1);
|
||||
qDebug() << Q_FUNC_INFO << "Regular expression captured the following IP:" << ipStr;
|
||||
QHostAddress newIp(ipStr);
|
||||
if (!newIp.isNull()) {
|
||||
@@ -121,11 +121,11 @@ void DNSUpdater::updateDNSService()
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
m_lastIPCheckTime = QDateTime::currentDateTime();
|
||||
DownloadHandler *handler = DownloadManager::instance()->downloadUrl(
|
||||
getUpdateUrl(), false, 0, false,
|
||||
"qBittorrent/" QBT_VERSION_2);
|
||||
connect(handler, SIGNAL(downloadFinished(QString, QByteArray)), SLOT(ipUpdateFinished(QString, QByteArray)));
|
||||
connect(handler, SIGNAL(downloadFailed(QString, QString)), SLOT(ipUpdateFailed(QString, QString)));
|
||||
DownloadHandler *handler = DownloadManager::instance()->download(
|
||||
DownloadRequest(getUpdateUrl()).userAgent("qBittorrent/" QBT_VERSION_2));
|
||||
connect(handler, static_cast<void (Net::DownloadHandler::*)(const QString &, const QByteArray &)>(&Net::DownloadHandler::downloadFinished)
|
||||
, this, &DNSUpdater::ipUpdateFinished);
|
||||
connect(handler, &Net::DownloadHandler::downloadFailed, this, &DNSUpdater::ipUpdateFailed);
|
||||
}
|
||||
|
||||
QString DNSUpdater::getUpdateUrl() const
|
||||
@@ -181,7 +181,7 @@ void DNSUpdater::processIPUpdateReply(const QString &reply)
|
||||
{
|
||||
Logger *const logger = Logger::instance();
|
||||
qDebug() << Q_FUNC_INFO << reply;
|
||||
QString code = reply.split(" ").first();
|
||||
QString code = reply.split(' ').first();
|
||||
qDebug() << Q_FUNC_INFO << "Code:" << code;
|
||||
|
||||
if ((code == "good") || (code == "nochg")) {
|
||||
@@ -244,8 +244,8 @@ void DNSUpdater::updateCredentials()
|
||||
}
|
||||
if (m_domain != pref->getDynDomainName()) {
|
||||
m_domain = pref->getDynDomainName();
|
||||
QRegExp domain_regex("^(?:(?!\\d|-)[a-zA-Z0-9\\-]{1,63}\\.)+[a-zA-Z]{2,}$");
|
||||
if (domain_regex.indexIn(m_domain) < 0) {
|
||||
const QRegularExpressionMatch domainRegexMatch = QRegularExpression("^(?:(?!\\d|-)[a-zA-Z0-9\\-]{1,63}\\.)+[a-zA-Z]{2,}$").match(m_domain);
|
||||
if (!domainRegexMatch.hasMatch()) {
|
||||
logger->addMessage(tr("Dynamic DNS error: supplied domain name is invalid."), Log::CRITICAL);
|
||||
m_lastIP.clear();
|
||||
m_ipCheckTimer.stop();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user