1
mirror of https://github.com/qbittorrent/qBittorrent synced 2025-11-04 16:42:38 +01:00

Compare commits

..

79 Commits

Author SHA1 Message Date
sledgehammer999
0188e11dd7 Bump to 5.0.3 2024-12-16 01:51:32 +02:00
sledgehammer999
1dc348539b Update Changelog 2024-12-16 01:49:38 +02:00
sledgehammer999
241a0e91bf Sync translations from Transifex and run lupdate 2024-12-16 01:49:09 +02:00
Vladimir Golovnev
68f7295500 Avoid race condition when update tracker entries
PR #21995.
2024-12-15 17:50:19 +03:00
Vladimir Golovnev
53adb7bfa8 Backport changes to v5.0.x branch
PR #21898.
2024-12-09 07:04:06 +03:00
Giacomo411
6128f6eecc NSIS: Update Italian translation
PR #21920.
2024-12-08 12:18:07 +02:00
sledgehammer999
d156a44f8d WebUI: Fix reloading page after login
Manual backport of PR  #21832
Original author: Evgenii Ryshkov
See commit: 1e851b3637
2024-12-08 12:15:15 +02:00
Thomas Piccirello
c3c7f28bad WebUI: Fix removing tracker URL with '|' character
Closes #19074.
PR #21346.
2024-12-07 23:47:49 +02:00
Chocobo1
9ac14cdf9f Don't follow symlink when creating torrents on Windows
Now on Windows, it won't follow/include .lnk files when creating torrents.
Note that libtorrent will throw errors if we force adding .lnk files.

Non-Windows OS will still follow symlinks.

Closes #13286.
PR #21944.
2024-12-07 21:19:46 +03:00
Vladimir Golovnev
b899ea8c40 Use cached current time when parse RSS feed
PR #21959.
2024-12-07 11:12:31 +03:00
Vladimir Golovnev
0d7c367332 Avoid redundant requests of announce entries from libtorrent
PR #21949.
2024-12-06 20:00:27 +03:00
wavygecko
22826499d5 Don't add duplicate episodes to previously matched
PR #21917.
2024-11-28 15:12:17 +03:00
Vladimir Golovnev
dbfd830b56 Avoid repeatedly creating the same QDateTime values
PR #21904.
2024-11-26 15:11:07 +03:00
Vladimir Golovnev
ad3348b95f Fix incorrect SQL column definition
PR #21874.
2024-11-23 11:25:40 +03:00
Bartu Özen
44b08fcb74 WebAPI: Fix incorrect key in torrent creator
PR #21879.
2024-11-23 11:22:04 +03:00
Vladimir Golovnev
71b752baf3 Discard obsolete "state update" events after torrent is reloaded
PR #21873.
Closes #21827.
2024-11-23 11:21:17 +03:00
sledgehammer999
15b6091261 Bump to 5.0.2 2024-11-17 23:25:16 +02:00
sledgehammer999
abe457389d Update Changelog 2024-11-17 23:22:51 +02:00
sledgehammer999
abce4cd1bc Sync translations from Transifex and run lupdate 2024-11-17 23:22:09 +02:00
3gf8jv4dv
2bfb336905 NSIS: Update Traditional Chinese translation
PR #21694.

---------

Co-authored-by: Chocobo1 <Chocobo1@users.noreply.github.com>
2024-11-17 22:45:24 +02:00
3gf8jv4dv
2dee65fa52 NSIS: Update Simplified Chinese translation
PR #21693.

---------

Co-authored-by: Chocobo1 <Chocobo1@users.noreply.github.com>
2024-11-17 22:45:23 +02:00
Ikko Eltociear Ashimine
423b3ed9bf NSIS: update luxembourgish
PR #21456.
2024-11-17 22:45:18 +02:00
Vladimir Golovnev
3454f064f0 Backport changes in v5.0.x branch
PR #21698.
2024-11-17 10:50:54 +03:00
Chocobo1
ac9ca4f452 Don't apply Mark-of-the-Web on existing files
`TorrentImpl::isDownloading()` was excessively broad which included unexpected events for the
case here. So use the underlying state directly.

Closes #21788.
PR #21836.
2024-11-16 16:04:51 +03:00
Chocobo1
09899a7d0d Avoid reapplying Mark-of-the-Web when it already exists
Also use scope guards to handle resources.

Related #21788.
PR #21806.
2024-11-14 10:14:52 +03:00
Hanabishi
9ab3c573dc WebUI: fix color scheme for iframes
A backport of #21750 as a follow up to #21748.

Original PR #21750.
PR #21810.
2024-11-11 19:03:40 +08:00
Vladimir Golovnev
993eb25323 Preserve initial torrent progress while checking resume data
PR #21784.
2024-11-10 12:51:17 +03:00
sledgehammer999
1e27e6504e Merge pull request #21748 from sledgehammer999/backport_webui_color_switcher
WebUI: Add color scheme switcher (v5_0_x)

Bacport of #21613
2024-11-09 12:15:47 +02:00
Vladimir Golovnev
330dce6aa2 Correctly handle "torrent finished" events
PR #21786.
Closes #21699.
2024-11-08 11:47:37 +03:00
Vladimir Golovnev
39b965af48 Check real palette darkness to detect "dark theme"
`QStyleHints::colorScheme()` returns chosen color scheme even if current style doesn't support it and uses different palette.

PR #21771.
2024-11-08 11:47:26 +03:00
Vladimir Golovnev
5e105b0348 Optimize checking for outdated tracker endpoints
PR #21768.
2024-11-07 09:42:53 +03:00
Vladimir Golovnev
f2b2a2b034 Optimize converting TCP endpoints to strings
There may be quite a few endpoint names (one for each available network card), and they usually remain unchanged throughout the session, while previously producing such names was performed every time they were accessed. Now they are retrieved from the cache.

PR #21770.
2024-11-07 09:42:43 +03:00
Vladimir Golovnev
10499dffe9 Optimize conversion of time points from libtorrent to Qt clocks
Obtain current date time of Qt and libtorrent clocks only once
for processing entire current libtorrent alerts bunch.

PR #21764.
2024-11-05 16:46:28 +03:00
Vladimir Golovnev
eea01b94a3 Reset tracker entries when pause the session
PR #21738.
2024-11-04 16:28:04 +03:00
Vladimir Golovnev
374951f6f2 Handle Qt style names in a case insensitive way
PR #21720.
Closes #21716.
2024-11-03 10:06:30 +03:00
sledgehammer999
6d6f9bc619 Reorder code to match UI 2024-11-02 17:52:13 +02:00
sledgehammer999
84ee620fdc Webui: Add color scheme switcher
Closes #21600
2024-11-02 17:32:55 +02:00
Vladimir Golovnev
6079b25419 Fix .torrent file could not be deleted when torrent is canceled
PR #21735.
Closes #21723.
2024-11-02 16:42:11 +03:00
Vladimir Golovnev
fe24bc825b Remove trackers from previous category when moved to new one
PR #21717.
Closes #21637.
2024-11-02 16:42:07 +03:00
sledgehammer999
94136262a8 Bump to 5.0.1 2024-10-28 18:12:20 +02:00
sledgehammer999
f52947e27e Update Changelog 2024-10-28 18:09:38 +02:00
sledgehammer999
315e88aee9 Sync translations from Transifex and run lupdate 2024-10-28 18:08:55 +02:00
Vladimir Golovnev
565c6d843a Correctly delete the moved search tab
PR #21687.
Closes #21675.
2024-10-28 09:45:23 +03:00
Vladimir Golovnev
9104351c89 Backport changes to v5.0.x branch
PR #21679.
2024-10-24 12:55:50 +03:00
sledgehammer999
e58b0a65d2 Merge pull request #21663 from sledgehammer999/backport_dont_ignore_ssl_errors
Don't ignore SSL errors
2024-10-24 11:02:31 +03:00
Chocobo1
878d829904 Fix button state for SSL certificate check
A copy paste error was introduced in PR #20338.

PR #21659.
2024-10-23 08:56:55 +03:00
sledgehammer999
063f77bc6c Allow to use Qt's default QStyle
Relevant prior PR #21553

PR #21605.
2024-10-21 20:05:54 +03:00
sledgehammer999
2a4077414f Reorder code to match UI 2024-10-21 19:53:28 +03:00
sledgehammer999
2a44253802 Don't ignore SSL errors 2024-10-21 19:45:32 +03:00
Chocobo1
4712eba0dc Don't change combobox index after selection
Also keep the list sorted.

PR #21599.
2024-10-21 15:49:18 +03:00
Hanabishi
983b7814aa Add "Simple pread/pwrite" disk IO type
PR #21300.
2024-10-21 15:47:28 +03:00
Vladimir Golovnev
e082a21751 Improve color scheme change detection
* Fix pieces bars won't correctly detect color scheme change with Qt 6.8.
* Update RSS article content view on color scheme changed.

PR #21625.
Closes #21327.
2024-10-21 09:51:37 +03:00
dyseg
7dd1d1bac8 Free resources allocated by web session once it is destructed
PR #21618.
Closes #20873.
2024-10-21 09:48:24 +03:00
Chocobo1
49f57b1049 WebUI: fix 'rename files' dialog cannot be opened more than once
Added an IIFE around the whole script to suppress variable redeclaration errors.

Closes #21614.
Original PR #21620.
PR #21621.
2024-10-20 16:07:13 +08:00
Vladimir Golovnev
fbf68a0649 Correctly apply filename filter when !qB extension is enabled
PR #21628.
Closes #21624.
2024-10-19 13:39:12 +03:00
xavier2k6
39229dc06a Sync flag icons with upstream
* Release: 7.2.3
* Contains bug fixes & additional flags

PR #21220.
2024-10-14 11:54:52 +03:00
Vladimir Golovnev
bb314e1555 Correctly handle "torrent finished after move" event
PR #21596.
Closes #21576.
2024-10-14 11:52:56 +03:00
Vladimir Golovnev
a3a8b15828 Always notify user about duplicate torrent
PR #21480.
Closes #21475.
2024-10-14 11:52:47 +03:00
Vladimir Golovnev
b579afe1aa Allow to choose Qt style
PR #21553.
2024-10-11 16:09:59 +03:00
stalkerok
93096dba56 Disable the ability to create torrents with a piece size of 256MiB
Disabling will reduce the number of users experiencing this issue.
https://github.com/qbittorrent/qBittorrent/issues/21011

PR #21295.
2024-10-10 15:40:05 +03:00
Vladimir Golovnev
6379c33964 Disable "Move to trash" option by default
PR #21528.
2024-10-10 14:16:37 +03:00
Chocobo1
84372de675 Import correct libraries
Fixes "plugin not supported" errors with python 3.8.

PR #21539.
2024-10-10 16:29:51 +08:00
skomerko
403b7c7c35 WebUI: Use proper text color to highlight items in all filter lists
Previously, text color of selected filter items was not applied correctly in all situations, making them difficult to read.
This improves existing styles so that text is always correctly distinguished from the background.

This fixes issue from second post in https://github.com/qbittorrent/qBittorrent/issues/21426

PR #21507.
2024-10-07 22:13:50 +08:00
skomerko
b2fab43865 WebUI: Don't load Tabs & dynamicTable stylesheets in Properties panel
This removes duplicate stylesheet imports that caused the transfer list to be completely collapsed in Chrome-based browsers.

Closes #21426.
PR #21506.
2024-10-07 22:03:54 +08:00
Vladimir Golovnev
387821267f Don't try to apply Mark-of-the-Web to nonexistent files
Trying to apply it to a nonexistent file is unacceptable, as it may unexpectedly create such a file.

PR #21488.
Closes #21440.
2024-10-05 12:28:09 +03:00
Vladimir Golovnev
dd7ef8e934 WebUI: Fix incorrect row ID
Incorrect row ID prevented the "Torrent content removing mode" option from being displayed on some platforms.

PR #21481.
2024-10-04 14:11:45 +03:00
sledgehammer999
cce295faeb Bump to 5.0.0 2024-09-29 20:53:45 +03:00
sledgehammer999
db5479ea01 Update Changelog 2024-09-29 20:49:43 +03:00
sledgehammer999
e1216c4c9a Sync translations from Transifex and run lupdate 2024-09-29 20:36:58 +03:00
sledgehammer999
f4a0868426 Make Program Updater choose the same build for download
We're probably stuck offering the duo of RC_1_2 and RC_2_0 for some
time in the future. So hardcode the choices and make the Program Updater
choose the variant the user currently uses.
2024-09-29 20:28:10 +03:00
sledgehammer999
59a5fcf7d0 Sync translations from Transifex and run lupdate 2024-09-13 11:10:38 +03:00
Vladimir Golovnev
f9a2b02a8d Backport changes to v5.0.x branch
PR #21241.
2024-09-12 08:42:52 +03:00
skomerko
04f6a565f3 WebUI: Provide 'Merge trackers to existing torrent' option
PR #21302.
2024-09-11 19:18:17 +03:00
Vladimir Golovnev
3e96048ee4 Apply "merge trackers" logic regardless of way the torrent is added
PR #21299.
2024-09-07 09:13:19 +04:00
Prince Gupta
d4ccf3001c Fix highlighted piece color
PR #20971.
2024-09-02 16:17:57 +03:00
skomerko
64506f16bd WebUI: Provide 'Use Category paths in Manual Mode' option
PR #21223.
2024-08-26 13:10:05 +03:00
sledgehammer999
24a7a835af Create new resources for this branch for Transifex 2024-08-26 01:11:05 +03:00
sledgehammer999
93b9bf9552 Sync translations from Transifex and run lupdate 2024-08-26 01:05:21 +03:00
Vladimir Golovnev
f4125601de Refresh search results colors once color scheme is changed
* Refresh search results colors once color scheme is changed
* Improve color of visited search result items

PR #21189.
Closes #21187.
2024-08-21 15:12:07 +03:00
598 changed files with 121968 additions and 111556 deletions

View File

@@ -95,7 +95,7 @@ jobs:
- name: Install Qt
uses: jurplel/install-qt-action@v4
with:
version: "6.7.0"
version: "6.7.3"
archives: qtbase qtsvg qttools
cache: true

View File

@@ -1,7 +1,7 @@
[main]
host = https://www.transifex.com
[o:sledgehammer999:p:qbittorrent:r:qbittorrent_master]
[o:sledgehammer999:p:qbittorrent:r:qbittorrent_v50x]
file_filter = src/lang/qbittorrent_<lang>.ts
source_file = src/lang/qbittorrent_en.ts
source_lang = en
@@ -9,7 +9,7 @@ type = QT
minimum_perc = 23
lang_map = pt: pt_PT, zh: zh_CN
[o:sledgehammer999:p:qbittorrent:r:qbittorrent_webui]
[o:sledgehammer999:p:qbittorrent:r:qbittorrent_webui_v50x]
file_filter = src/webui/www/translations/webui_<lang>.ts
source_file = src/webui/www/translations/webui_en.ts
source_lang = en

View File

@@ -1,4 +1,50 @@
Unreleased - sledgehammer999 <sledgehammer999@qbittorrent.org> - v5.0.0
Mon Dec 16th 2024 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v5.0.3
- BUGFIX: Discard obsolete "state update" events after torrent is reloaded (glassez)
- BUGFIX: Fix incorrect SQL column definition (glassez)
- BUGFIX: Avoid redundant requests of announce entries from libtorrent (glassez)
- WEBUI: Fix removing tracker URL with '|' character (Thomas Piccirello)
- WEBUI: Fix reloading page after login (Evgenii Ryshkov)
- WEBAPI: Fix incorrect key in torrent creator (Bartu Özen)
- RSS: Don't add duplicate episodes to previously matched (wavygecko)
- RSS: Use cached current time when parsing RSS feed (glassez)
- WINDOWS: Don't follow symlink when creating torrents on Windows (Chocobo1)
- WINDOWS: NSIS: Update Italian translation (Giacomo411)
Sun Nov 17th 2024 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v5.0.2
- BUGFIX: Remove trackers from previous category when moved to new one (glassez)
- BUGFIX: Fix `.torrent` file could not be deleted when torrent is canceled (glassez)
- BUGFIX: Reset tracker entries when pausing the session (glassez)
- BUGFIX: Check real palette darkness to detect "dark theme" (glassez)
- BUGFIX: Correctly handle "torrent finished" events (glassez)
- BUGFIX: Preserve initial torrent progress while checking resume data (glassez)
- BUGFIX: Avoid reapplying Mark-of-the-Web when it already exists (Chocobo1)
- BUGFIX: Don't apply Mark-of-the-Web on existing files (Chocobo1)
- WEBUI: Add color scheme switcher (sledgehammer999)
- SEARCH: Correctly delete the moved search tab (glassez)
- WINDOWS: Correctly save and restore Qt style setting (glassez)
- WINDOWS: NSIS: update Luxembourgish, Simplified Chinese and Traditional Chinese translations (Ikko Eltociear Ashimine, 3gf8jv4dv)
Mon Oct 28th 2024 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v5.0.1
- FEATURE: Add "Simple pread/pwrite" disk IO type (Hanabishi)
- BUGFIX: Don't ignore SSL errors (sledgehammer999)
- BUGFIX: Don't try to apply Mark-of-the-Web to nonexistent files (glassez)
- BUGFIX: Disable "Move to trash" option by default (glassez)
- BUGFIX: Disable the ability to create torrents with a piece size of 256MiB (stalkerok)
- BUGFIX: Allow to choose Qt style (glassez)
- BUGFIX: Always notify user about duplicate torrent (glassez)
- BUGFIX: Correctly handle "torrent finished after move" event (glassez)
- BUGFIX: Correctly apply filename filter when `!qB` extension is enabled (glassez)
- BUGFIX: Improve color scheme change detection (glassez)
- BUGFIX: Fix button state for SSL certificate check (Chocobo1)
- WEBUI: Fix CSS that results in hidden torrent list in some browsers (skomerko)
- WEBUI: Use proper text color to highlight items in all filter lists (skomerko)
- WEBUI: Fix 'rename files' dialog cannot be opened more than once (Chocobo1)
- WEBUI: Fix UI of Advanced Settings to show all settings (glassez)
- WEBUI: Free resources allocated by web session once it is destructed (dyseg)
- SEARCH: Import correct libraries (Chocobo1)
- OTHER: Sync flag icons with upstream (xavier2k6)
Sun Sep 29th 2024 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v5.0.0
- FEATURE: Support creating .torrent with larger piece size (Chocobo1)
- FEATURE: Improve tracker entries handling (glassez)
- FEATURE: Add separate filter item for tracker errors (glassez)
@@ -34,6 +80,8 @@ Unreleased - sledgehammer999 <sledgehammer999@qbittorrent.org> - v5.0.0
- BUGFIX: Sanitize peer client names (Hanabishi)
- BUGFIX: Apply share limits immediately when torrent downloading is finished (glassez)
- BUGFIX: Show download progress for folders with zero byte size as 100 instead of 0 (vikas_c)
- BUGFIX: Fix highlighted piece color (Prince Gupta)
- BUGFIX: Apply "merge trackers" logic regardless of way the torrent is added (glassez)
- WEBUI: Improve WebUI responsiveness (Chocobo1)
- WEBUI: Do not exit the app when WebUI has failed to start (Hanabishi)
- WEBUI: Add `Moving` filter to side panel (xavier2k6)
@@ -49,10 +97,12 @@ Unreleased - sledgehammer999 <sledgehammer999@qbittorrent.org> - v5.0.0
- WEBUI: Improve table scrolling and selection on mobile (Thomas Piccirello)
- WEBUI: Restore search tabs on load (Thomas Piccirello)
- WEBUI: Restore previously used tab on load (Thomas Piccirello)
- WEBUI: Increase default height of 'Share ratio limit' dialog (thalieht)
- WEBUI: Increase default height of `Share ratio limit` dialog (thalieht)
- WEBUI: Use enabled search plugins by default (Thomas Piccirello)
- WEBUI: Add columns `Incomplete Save Path`, `Info Hash v1`, `Info Hash v2` (thalieht)
- WEBUI: Always create generic filter items (skomerko)
- WEBUI: Provide `Use Category paths in Manual Mode` option (skomerko)
- WEBUI: Provide `Merge trackers to existing torrent` option (skomerko)
- WEBAPI: Fix wrong timestamp values (Chocobo1)
- WEBAPI: Send binary data with filename and mime type specified (glassez)
- WEBAPI: Expose API for the torrent creator (glassez, Radu Carpa)

2
dist/mac/Info.plist vendored
View File

@@ -55,7 +55,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>5.0.0</string>
<string>5.0.3</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>

File diff suppressed because it is too large Load Diff

View File

@@ -62,6 +62,6 @@
<url type="contribute">https://github.com/qbittorrent/qBittorrent/blob/master/CONTRIBUTING.md</url>
<content_rating type="oars-1.1"/>
<releases>
<release version="5.0.0~rc1" date="2024-08-18"/>
<release version="5.0.3" date="2024-12-16"/>
</releases>
</component>

View File

@@ -14,7 +14,7 @@
; 4.5.1.3 -> good
; 4.5.1.3.2 -> bad
; 4.5.0beta -> bad
!define /ifndef QBT_VERSION "5.0.0"
!define /ifndef QBT_VERSION "5.0.3"
; Option that controls the installer's window name
; If set, its value will be used like this:

View File

@@ -29,7 +29,7 @@ LangString launch_qbt ${LANG_ITALIAN} "Esegui qBittorrent."
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
LangString inst_requires_64bit ${LANG_ITALIAN} "Questo installer funziona solo con versioni di Windows a 64bit."
;LangString inst_requires_win10 ${LANG_ENGLISH} "This installer requires at least Windows 10 (1809) / Windows Server 2019."
LangString inst_requires_win10 ${LANG_ITALIAN} "This installer requires at least Windows 10 (1809) / Windows Server 2019."
LangString inst_requires_win10 ${LANG_ITALIAN} "Questo installer richiede almeno Windows 10 (1809) / Windows Server 2019."
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
LangString inst_uninstall_link_description ${LANG_ITALIAN} "Disinstalla qBittorrent"

View File

@@ -15,7 +15,7 @@ LangString inst_magnet ${LANG_LUXEMBOURGISH} "Magnet-Linken mat qBittorrent opma
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
LangString inst_firewall ${LANG_LUXEMBOURGISH} "Reegel an der Windows Firewall dobäisetzen"
;LangString inst_pathlimit ${LANG_ENGLISH} "Disable Windows path length limit (260 character MAX_PATH limitation, requires Windows 10 1607 or later)"
LangString inst_pathlimit ${LANG_LUXEMBOURGISH} "D'Windows path lenght (Padlängtbeschränkung) desaktivéieren (260 Zeechen MAX_PATH Beschränkung, erfuerdert min. Windows 10 1607)"
LangString inst_pathlimit ${LANG_LUXEMBOURGISH} "D'Windows path length (Padlängtbeschränkung) desaktivéieren (260 Zeechen MAX_PATH Beschränkung, erfuerdert min. Windows 10 1607)"
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
LangString inst_firewallinfo ${LANG_LUXEMBOURGISH} "Reegel an der Windows Firewall dobäisetzen"
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."

View File

@@ -23,13 +23,13 @@ LangString inst_warning ${LANG_SIMPCHINESE} "qBittorrent 正在运行。 安装
;LangString inst_uninstall_question ${LANG_ENGLISH} "Current version will be uninstalled. User settings and torrents will remain intact."
LangString inst_uninstall_question ${LANG_SIMPCHINESE} "当前版本会被卸载。 用户设置和种子会被完整保留。"
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
LangString inst_unist ${LANG_SIMPCHINESE} "卸载以前的版本。"
LangString inst_unist ${LANG_SIMPCHINESE} "正在卸载以前的版本。"
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
LangString launch_qbt ${LANG_SIMPCHINESE} "启动 qBittorrent。"
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
LangString inst_requires_64bit ${LANG_SIMPCHINESE} "此安装程序仅支持 64 位 Windows 系统。"
;LangString inst_requires_win10 ${LANG_ENGLISH} "This installer requires at least Windows 10 (1809) / Windows Server 2019."
LangString inst_requires_win10 ${LANG_SIMPCHINESE} "This installer requires at least Windows 10 (1809) / Windows Server 2019."
LangString inst_requires_win10 ${LANG_SIMPCHINESE} "此安装程序仅支持 Windows 10 (1809) / Windows Server 2019 或更新的系统。"
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
LangString inst_uninstall_link_description ${LANG_SIMPCHINESE} "卸载 qBittorrent"

View File

@@ -29,7 +29,7 @@ LangString launch_qbt ${LANG_TRADCHINESE} "啟動 qBittorrent"
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
LangString inst_requires_64bit ${LANG_TRADCHINESE} "此安裝程式僅支援 64 位元版本的 Windows。"
;LangString inst_requires_win10 ${LANG_ENGLISH} "This installer requires at least Windows 10 (1809) / Windows Server 2019."
LangString inst_requires_win10 ${LANG_TRADCHINESE} "This installer requires at least Windows 10 (1809) / Windows Server 2019."
LangString inst_requires_win10 ${LANG_TRADCHINESE} "此安裝程式僅支援 Windows 10 (1809) / Windows Server 2019 以上的系統。"
;LangString inst_uninstall_link_description ${LANG_ENGLISH} "Uninstall qBittorrent"
LangString inst_uninstall_link_description ${LANG_TRADCHINESE} "移除 qBittorrent"

View File

@@ -1,6 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2014-2023 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2014-2024 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2006 Christophe Dumez <chris@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
@@ -58,10 +58,6 @@
#include <QSplashScreen>
#include <QTimer>
#ifdef Q_OS_WIN
#include <QOperatingSystemVersion>
#endif
#ifdef QBT_STATIC_QT
#include <QtPlugin>
Q_IMPORT_PLUGIN(QICOPlugin)
@@ -189,11 +185,6 @@ int main(int argc, char *argv[])
// We must save it here because QApplication constructor may change it
const bool isOneArg = (argc == 2);
#if !defined(DISABLE_GUI) && defined(Q_OS_WIN)
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10)
QApplication::setStyle(u"Fusion"_s);
#endif
// `app` must be declared out of try block to allow display message box in case of exception
std::unique_ptr<Application> app;
try

View File

@@ -157,10 +157,36 @@ void AddTorrentManager::handleAddTorrentFailed(const QString &source, const QStr
emit addTorrentFailed(source, reason);
}
void AddTorrentManager::handleDuplicateTorrent(const QString &source, BitTorrent::Torrent *torrent, const QString &message)
void AddTorrentManager::handleDuplicateTorrent(const QString &source
, const BitTorrent::TorrentDescriptor &torrentDescr, BitTorrent::Torrent *existingTorrent)
{
const bool hasMetadata = torrentDescr.info().has_value();
if (hasMetadata)
{
// Trying to set metadata to existing torrent in case if it has none
existingTorrent->setMetadata(*torrentDescr.info());
}
const bool isPrivate = existingTorrent->isPrivate() || (hasMetadata && torrentDescr.info()->isPrivate());
QString message;
if (!btSession()->isMergeTrackersEnabled())
{
message = tr("Merging of trackers is disabled");
}
else if (isPrivate)
{
message = tr("Trackers cannot be merged because it is a private torrent");
}
else
{
// merge trackers and web seeds
existingTorrent->addTrackers(torrentDescr.trackers());
existingTorrent->addUrlSeeds(torrentDescr.urlSeeds());
message = tr("Trackers are merged from new source");
}
LogMsg(tr("Detected an attempt to add a duplicate torrent. Source: %1. Existing torrent: %2. Result: %3")
.arg(source, torrent->name(), message));
.arg(source, existingTorrent->name(), message));
emit addTorrentFailed(source, message);
}
@@ -169,11 +195,9 @@ void AddTorrentManager::setTorrentFileGuard(const QString &source, std::shared_p
m_guardedTorrentFiles.emplace(source, std::move(torrentFileGuard));
}
void AddTorrentManager::releaseTorrentFileGuard(const QString &source)
std::shared_ptr<TorrentFileGuard> AddTorrentManager::releaseTorrentFileGuard(const QString &source)
{
auto torrentFileGuard = m_guardedTorrentFiles.take(source);
if (torrentFileGuard)
torrentFileGuard->setAutoRemove(false);
return m_guardedTorrentFiles.take(source);
}
bool AddTorrentManager::processTorrent(const QString &source, const BitTorrent::TorrentDescriptor &torrentDescr
@@ -184,32 +208,7 @@ bool AddTorrentManager::processTorrent(const QString &source, const BitTorrent::
if (BitTorrent::Torrent *torrent = btSession()->findTorrent(infoHash))
{
// a duplicate torrent is being added
const bool hasMetadata = torrentDescr.info().has_value();
if (hasMetadata)
{
// Trying to set metadata to existing torrent in case if it has none
torrent->setMetadata(*torrentDescr.info());
}
if (!btSession()->isMergeTrackersEnabled())
{
handleDuplicateTorrent(source, torrent, tr("Merging of trackers is disabled"));
return false;
}
const bool isPrivate = torrent->isPrivate() || (hasMetadata && torrentDescr.info()->isPrivate());
if (isPrivate)
{
handleDuplicateTorrent(source, torrent, tr("Trackers cannot be merged because it is a private torrent"));
return false;
}
// merge trackers and web seeds
torrent->addTrackers(torrentDescr.trackers());
torrent->addUrlSeeds(torrentDescr.urlSeeds());
handleDuplicateTorrent(source, torrent, tr("Trackers are merged from new source"));
handleDuplicateTorrent(source, torrentDescr, torrent);
return false;
}

View File

@@ -72,9 +72,9 @@ protected:
bool addTorrentToSession(const QString &source, const BitTorrent::TorrentDescriptor &torrentDescr
, const BitTorrent::AddTorrentParams &addTorrentParams);
void handleAddTorrentFailed(const QString &source, const QString &reason);
void handleDuplicateTorrent(const QString &source, BitTorrent::Torrent *torrent, const QString &message);
void handleDuplicateTorrent(const QString &source, const BitTorrent::TorrentDescriptor &torrentDescr, BitTorrent::Torrent *existingTorrent);
void setTorrentFileGuard(const QString &source, std::shared_ptr<TorrentFileGuard> torrentFileGuard);
void releaseTorrentFileGuard(const QString &source);
std::shared_ptr<TorrentFileGuard> releaseTorrentFileGuard(const QString &source);
private:
void onDownloadFinished(const Net::DownloadResult &result);

View File

@@ -67,7 +67,7 @@ namespace
{
const QString DB_CONNECTION_NAME = u"ResumeDataStorage"_s;
const int DB_VERSION = 7;
const int DB_VERSION = 8;
const QString DB_TABLE_META = u"meta"_s;
const QString DB_TABLE_TORRENTS = u"torrents"_s;
@@ -628,7 +628,31 @@ void BitTorrent::DBResumeDataStorage::updateDB(const int fromVersion) const
}
if (fromVersion <= 6)
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_SHARE_LIMIT_ACTION, "TEXTNOT NULL DEFAULT `Default`");
addColumn(DB_TABLE_TORRENTS, DB_COLUMN_SHARE_LIMIT_ACTION, "TEXT NOT NULL DEFAULT `Default`");
if (fromVersion == 7)
{
const QString TEMP_COLUMN_NAME = DB_COLUMN_SHARE_LIMIT_ACTION.name + u"_temp";
auto queryStr = u"ALTER TABLE %1 ADD %2 %3"_s
.arg(quoted(DB_TABLE_TORRENTS), TEMP_COLUMN_NAME, u"TEXT NOT NULL DEFAULT `Default`");
if (!query.exec(queryStr))
throw RuntimeError(query.lastError().text());
queryStr = u"UPDATE %1 SET %2 = %3"_s
.arg(quoted(DB_TABLE_TORRENTS), quoted(TEMP_COLUMN_NAME), quoted(DB_COLUMN_SHARE_LIMIT_ACTION.name));
if (!query.exec(queryStr))
throw RuntimeError(query.lastError().text());
queryStr = u"ALTER TABLE %1 DROP %2"_s.arg(quoted(DB_TABLE_TORRENTS), quoted(DB_COLUMN_SHARE_LIMIT_ACTION.name));
if (!query.exec(queryStr))
throw RuntimeError(query.lastError().text());
queryStr = u"ALTER TABLE %1 RENAME %2 TO %3"_s
.arg(quoted(DB_TABLE_TORRENTS), quoted(TEMP_COLUMN_NAME), quoted(DB_COLUMN_SHARE_LIMIT_ACTION.name));
if (!query.exec(queryStr))
throw RuntimeError(query.lastError().text());
}
const QString updateMetaVersionQuery = makeUpdateStatement(DB_TABLE_META, {DB_COLUMN_NAME, DB_COLUMN_VALUE});
if (!query.prepare(updateMetaVersionQuery))

View File

@@ -92,7 +92,8 @@ namespace BitTorrent
{
Default = 0,
MMap = 1,
Posix = 2
Posix = 2,
SimplePreadPwrite = 3
};
Q_ENUM_NS(DiskIOType)

File diff suppressed because it is too large Load Diff

View File

@@ -41,6 +41,7 @@
#include <QElapsedTimer>
#include <QHash>
#include <QMap>
#include <QMutex>
#include <QPointer>
#include <QSet>
#include <QVector>
@@ -475,6 +476,8 @@ namespace BitTorrent
void addMappedPorts(const QSet<quint16> &ports);
void removeMappedPorts(const QSet<quint16> &ports);
QDateTime fromLTTimePoint32(const lt::time_point32 &timePoint) const;
template <typename Func>
void invoke(Func &&func)
{
@@ -539,7 +542,6 @@ namespace BitTorrent
void populateAdditionalTrackers();
void enableIPFilter();
void disableIPFilter();
void processTrackerStatuses();
void processTorrentShareLimits(TorrentImpl *torrent);
void populateExcludedFileNamesRegExpList();
void prepareStartup();
@@ -593,6 +595,7 @@ namespace BitTorrent
void moveTorrentStorage(const MoveStorageJob &job) const;
void handleMoveTorrentStorageJobFinished(const Path &newPath);
void processPendingFinishedTorrents();
void loadCategories();
void storeCategories() const;
@@ -602,7 +605,7 @@ namespace BitTorrent
void saveStatistics() const;
void loadStatistics();
void updateTrackerEntryStatuses(lt::torrent_handle torrentHandle, QHash<std::string, QHash<lt::tcp::endpoint, QMap<int, int>>> updatedTrackers);
void updateTrackerEntryStatuses(lt::torrent_handle torrentHandle);
void handleRemovedTorrent(const TorrentID &torrentID, const QString &partfileRemoveError = {});
@@ -791,6 +794,7 @@ namespace BitTorrent
// This field holds amounts of peers reported by trackers in their responses to announces
// (torrent.tracker_name.tracker_local_endpoint.protocol_version.num_peers)
QHash<lt::torrent_handle, QHash<std::string, QHash<lt::tcp::endpoint, QMap<int, int>>>> m_updatedTrackerStatuses;
QMutex m_updatedTrackerStatusesMutex;
// I/O errored torrents
QSet<TorrentID> m_recentErroredTorrents;
@@ -819,6 +823,9 @@ namespace BitTorrent
QList<TorrentImpl *> m_pendingFinishedTorrents;
QDateTime m_qNow;
lt::clock_type::time_point m_ltNow;
friend void Session::initInstance();
friend void Session::freeInstance();
friend Session *Session::instance();

View File

@@ -215,7 +215,15 @@ namespace BitTorrent
virtual int piecesCount() const = 0;
virtual int piecesHave() const = 0;
virtual qreal progress() const = 0;
virtual QDateTime addedTime() const = 0;
virtual QDateTime completedTime() const = 0;
virtual QDateTime lastSeenComplete() const = 0;
virtual qlonglong activeTime() const = 0;
virtual qlonglong finishedTime() const = 0;
virtual qlonglong timeSinceUpload() const = 0;
virtual qlonglong timeSinceDownload() const = 0;
virtual qlonglong timeSinceActivity() const = 0;
// Share limits
virtual qreal ratioLimit() const = 0;
@@ -254,8 +262,6 @@ namespace BitTorrent
virtual QString error() const = 0;
virtual qlonglong totalDownload() const = 0;
virtual qlonglong totalUpload() const = 0;
virtual qlonglong activeTime() const = 0;
virtual qlonglong finishedTime() const = 0;
virtual qlonglong eta() const = 0;
virtual int seedsCount() const = 0;
virtual int peersCount() const = 0;
@@ -263,11 +269,6 @@ namespace BitTorrent
virtual int totalSeedsCount() const = 0;
virtual int totalPeersCount() const = 0;
virtual int totalLeechersCount() const = 0;
virtual QDateTime lastSeenComplete() const = 0;
virtual QDateTime completedTime() const = 0;
virtual qlonglong timeSinceUpload() const = 0;
virtual qlonglong timeSinceDownload() const = 0;
virtual qlonglong timeSinceActivity() const = 0;
virtual int downloadLimit() const = 0;
virtual int uploadLimit() const = 0;
virtual bool superSeeding() const = 0;

View File

@@ -36,6 +36,7 @@
#include <libtorrent/file_storage.hpp>
#include <libtorrent/torrent_info.hpp>
#include <QtSystemDetection>
#include <QDirIterator>
#include <QFileInfo>
#include <QHash>
@@ -123,7 +124,14 @@ void TorrentCreator::run()
// need to sort the file names by natural sort order
QStringList dirs = {m_params.sourcePath.data()};
QDirIterator dirIter {m_params.sourcePath.data(), (QDir::AllDirs | QDir::NoDotAndDotDot), QDirIterator::Subdirectories};
#ifdef Q_OS_WIN
// libtorrent couldn't handle .lnk files on Windows
// Also, Windows users do not expect torrent creator to traverse into .lnk files so skip over them
const QDir::Filters dirFilters {QDir::AllDirs | QDir::NoDotAndDotDot | QDir::NoSymLinks};
#else
const QDir::Filters dirFilters {QDir::AllDirs | QDir::NoDotAndDotDot};
#endif
QDirIterator dirIter {m_params.sourcePath.data(), dirFilters, QDirIterator::Subdirectories};
while (dirIter.hasNext())
{
const QString filePath = dirIter.next();
@@ -138,7 +146,12 @@ void TorrentCreator::run()
{
QStringList tmpNames; // natural sort files within each dir
QDirIterator fileIter {dir, QDir::Files};
#ifdef Q_OS_WIN
const QDir::Filters fileFilters {QDir::Files | QDir::NoSymLinks};
#else
const QDir::Filters fileFilters {QDir::Files};
#endif
QDirIterator fileIter {dir, fileFilters};
while (fileIter.hasNext())
{
const QFileInfo fileInfo = fileIter.nextFileInfo();

View File

@@ -1,6 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015-2023 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2015-2024 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
@@ -35,9 +35,7 @@
#include <libtorrent/write_resume_data.hpp>
#include <QByteArray>
#include <QDateTime>
#include <QRegularExpression>
#include <QString>
#include <QUrl>
#include "base/global.h"
@@ -147,7 +145,13 @@ BitTorrent::TorrentDescriptor::TorrentDescriptor(lt::add_torrent_params ltAddTor
: m_ltAddTorrentParams {std::move(ltAddTorrentParams)}
{
if (m_ltAddTorrentParams.ti && m_ltAddTorrentParams.ti->is_valid())
{
m_info.emplace(*m_ltAddTorrentParams.ti);
if (m_ltAddTorrentParams.ti->creation_date() > 0)
m_creationDate = QDateTime::fromSecsSinceEpoch(m_ltAddTorrentParams.ti->creation_date());
m_creator = QString::fromStdString(m_ltAddTorrentParams.ti->creator());
m_comment = QString::fromStdString(m_ltAddTorrentParams.ti->comment());
}
}
BitTorrent::InfoHash BitTorrent::TorrentDescriptor::infoHash() const
@@ -166,18 +170,17 @@ QString BitTorrent::TorrentDescriptor::name() const
QDateTime BitTorrent::TorrentDescriptor::creationDate() const
{
return ((m_ltAddTorrentParams.ti->creation_date() != 0)
? QDateTime::fromSecsSinceEpoch(m_ltAddTorrentParams.ti->creation_date()) : QDateTime());
return m_creationDate;
}
QString BitTorrent::TorrentDescriptor::creator() const
{
return QString::fromStdString(m_ltAddTorrentParams.ti->creator());
return m_creator;
}
QString BitTorrent::TorrentDescriptor::comment() const
{
return QString::fromStdString(m_ltAddTorrentParams.ti->comment());
return m_comment;
}
const std::optional<BitTorrent::TorrentInfo> &BitTorrent::TorrentDescriptor::info() const

View File

@@ -33,7 +33,9 @@
#include <libtorrent/add_torrent_params.hpp>
#include <QtContainerFwd>
#include <QDateTime>
#include <QMetaType>
#include <QString>
#include "base/3rdparty/expected.hpp"
#include "base/path.h"
@@ -41,8 +43,6 @@
#include "torrentinfo.h"
class QByteArray;
class QDateTime;
class QString;
class QUrl;
namespace BitTorrent
@@ -78,6 +78,9 @@ namespace BitTorrent
lt::add_torrent_params m_ltAddTorrentParams;
std::optional<TorrentInfo> m_info;
QDateTime m_creationDate;
QString m_creator;
QString m_comment;
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -138,7 +138,15 @@ namespace BitTorrent
int piecesCount() const override;
int piecesHave() const override;
qreal progress() const override;
QDateTime addedTime() const override;
QDateTime completedTime() const override;
QDateTime lastSeenComplete() const override;
qlonglong activeTime() const override;
qlonglong finishedTime() const override;
qlonglong timeSinceUpload() const override;
qlonglong timeSinceDownload() const override;
qlonglong timeSinceActivity() const override;
qreal ratioLimit() const override;
void setRatioLimit(qreal limit) override;
@@ -181,8 +189,6 @@ namespace BitTorrent
QString error() const override;
qlonglong totalDownload() const override;
qlonglong totalUpload() const override;
qlonglong activeTime() const override;
qlonglong finishedTime() const override;
qlonglong eta() const override;
QVector<qreal> filesProgress() const override;
int seedsCount() const override;
@@ -191,11 +197,6 @@ namespace BitTorrent
int totalSeedsCount() const override;
int totalPeersCount() const override;
int totalLeechersCount() const override;
QDateTime lastSeenComplete() const override;
QDateTime completedTime() const override;
qlonglong timeSinceUpload() const override;
qlonglong timeSinceDownload() const override;
qlonglong timeSinceActivity() const override;
int downloadLimit() const override;
int uploadLimit() const override;
bool superSeeding() const override;
@@ -342,6 +343,14 @@ namespace BitTorrent
InfoHash m_infoHash;
QDateTime m_creationDate;
QString m_creator;
QString m_comment;
QDateTime m_addedTime;
QDateTime m_completedTime;
QDateTime m_lastSeenComplete;
// m_moveFinishedTriggers is activated only when the following conditions are met:
// all file rename jobs complete, all file move jobs complete
QQueue<EventTrigger> m_moveFinishedTriggers;

View File

@@ -148,10 +148,20 @@ Net::DownloadManager::DownloadManager(QObject *parent)
QStringList errorList;
for (const QSslError &error : errors)
errorList += error.errorString();
LogMsg(tr("Ignoring SSL error, URL: \"%1\", errors: \"%2\"").arg(reply->url().toString(), errorList.join(u". ")), Log::WARNING);
// Ignore all SSL errors
reply->ignoreSslErrors();
QString errorMsg;
if (!Preferences::instance()->isIgnoreSSLErrors())
{
errorMsg = tr("SSL error, URL: \"%1\", errors: \"%2\"");
}
else
{
errorMsg = tr("Ignoring SSL error, URL: \"%1\", errors: \"%2\"");
// Ignore all SSL errors
reply->ignoreSslErrors();
}
LogMsg(errorMsg.arg(reply->url().toString(), errorList.join(u". ")), Log::WARNING);
});
connect(ProxyConfigurationManager::instance(), &ProxyConfigurationManager::proxyConfigurationChanged

View File

@@ -43,7 +43,6 @@ class QSslSocket;
#else
class QTcpSocket;
#endif
class QTextCodec;
namespace Net
{

View File

@@ -429,6 +429,19 @@ void Preferences::setWinStartup(const bool b)
settings.remove(profileID);
}
}
QString Preferences::getStyle() const
{
return value<QString>(u"Appearance/Style"_s);
}
void Preferences::setStyle(const QString &styleName)
{
if (styleName == getStyle())
return;
setValue(u"Appearance/Style"_s, styleName);
}
#endif // Q_OS_WIN
// Downloads
@@ -1330,6 +1343,19 @@ void Preferences::setMarkOfTheWebEnabled(const bool enabled)
setValue(u"Preferences/Advanced/markOfTheWeb"_s, enabled);
}
bool Preferences::isIgnoreSSLErrors() const
{
return value(u"Preferences/Advanced/IgnoreSSLErrors"_s, false);
}
void Preferences::setIgnoreSSLErrors(const bool enabled)
{
if (enabled == isIgnoreSSLErrors())
return;
setValue(u"Preferences/Advanced/IgnoreSSLErrors"_s, enabled);
}
Path Preferences::getPythonExecutablePath() const
{
return value(u"Preferences/Search/pythonExecutablePath"_s, Path());

View File

@@ -130,6 +130,8 @@ public:
#ifdef Q_OS_WIN
bool WinStartup() const;
void setWinStartup(bool b);
QString getStyle() const;
void setStyle(const QString &styleName);
#endif
// Downloads
@@ -293,6 +295,8 @@ public:
void setTrackerPortForwardingEnabled(bool enabled);
bool isMarkOfTheWebEnabled() const;
void setMarkOfTheWebEnabled(bool enabled);
bool isIgnoreSSLErrors() const;
void setIgnoreSSLErrors(bool enabled);
Path getPythonExecutablePath() const;
void setPythonExecutablePath(const Path &path);
#if defined(Q_OS_WIN) || defined(Q_OS_MACOS)

View File

@@ -396,6 +396,8 @@ bool AutoDownloadRule::matchesSmartEpisodeFilter(const QString &articleTitle) co
m_dataPtr->lastComputedEpisodes.append(episodeStr + u"-REPACK");
m_dataPtr->lastComputedEpisodes.append(episodeStr + u"-PROPER");
}
return true;
}
m_dataPtr->lastComputedEpisodes.append(episodeStr);

View File

@@ -1,6 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2012 Christophe Dumez <chris@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
@@ -29,11 +29,8 @@
#include "rss_parser.h"
#include <QDateTime>
#include <QDebug>
#include <QGlobalStatic>
#include <QHash>
#include <QMetaObject>
#include <QRegularExpression>
#include <QStringList>
#include <QVariant>
@@ -359,7 +356,7 @@ namespace
};
// Ported to Qt from KDElibs4
QDateTime parseDate(const QString &string)
QDateTime parseDate(const QString &string, const QDateTime &fallbackDate)
{
const char16_t shortDay[][4] =
{
@@ -382,7 +379,7 @@ namespace
const QString str = string.trimmed();
if (str.isEmpty())
return QDateTime::currentDateTime();
return fallbackDate;
int nyear = 6; // indexes within string to values
int nmonth = 4;
@@ -402,14 +399,14 @@ namespace
const bool h1 = (parts[3] == u"-");
const bool h2 = (parts[5] == u"-");
if (h1 != h2)
return QDateTime::currentDateTime();
return fallbackDate;
}
else
{
// Check for the obsolete form "Wdy Mon DD HH:MM:SS YYYY"
rx = QRegularExpression {u"^([A-Z][a-z]+)\\s+(\\S+)\\s+(\\d\\d)\\s+(\\d\\d):(\\d\\d):(\\d\\d)\\s+(\\d\\d\\d\\d)$"_s};
if (str.indexOf(rx, 0, &rxMatch) != 0)
return QDateTime::currentDateTime();
return fallbackDate;
nyear = 7;
nmonth = 2;
@@ -427,14 +424,14 @@ namespace
const int hour = parts[nhour].toInt(&ok[2]);
const int minute = parts[nmin].toInt(&ok[3]);
if (!ok[0] || !ok[1] || !ok[2] || !ok[3])
return QDateTime::currentDateTime();
return fallbackDate;
int second = 0;
if (!parts[nsec].isEmpty())
{
second = parts[nsec].toInt(&ok[0]);
if (!ok[0])
return QDateTime::currentDateTime();
return fallbackDate;
}
const bool leapSecond = (second == 60);
@@ -518,21 +515,21 @@ namespace
const QDate qDate(year, month + 1, day); // convert date, and check for out-of-range
if (!qDate.isValid())
return QDateTime::currentDateTime();
return fallbackDate;
const QTime qTime(hour, minute, second);
QDateTime result(qDate, qTime, Qt::UTC);
if (offset)
result = result.addSecs(-offset);
if (!result.isValid())
return QDateTime::currentDateTime(); // invalid date/time
return fallbackDate; // invalid date/time
if (leapSecond)
{
// Validate a leap second time. Leap seconds are inserted after 23:59:59 UTC.
// Convert the time to UTC and check that it is 00:00:00.
if ((hour*3600 + minute*60 + 60 - offset + 86400*5) % 86400) // (max abs(offset) is 100 hours)
return QDateTime::currentDateTime(); // the time isn't the last second of the day
return fallbackDate; // the time isn't the last second of the day
}
return result;
@@ -550,6 +547,7 @@ RSS::Private::Parser::Parser(const QString &lastBuildDate)
void RSS::Private::Parser::parse(const QByteArray &feedData)
{
QXmlStreamReader xml {feedData};
m_fallbackDate = QDateTime::currentDateTime();
XmlStreamEntityResolver resolver;
xml.setEntityResolver(&resolver);
bool foundChannel = false;
@@ -641,7 +639,7 @@ void RSS::Private::Parser::parseRssArticle(QXmlStreamReader &xml)
}
else if (name == u"pubDate")
{
article[Article::KeyDate] = parseDate(xml.readElementText().trimmed());
article[Article::KeyDate] = parseDate(xml.readElementText().trimmed(), m_fallbackDate);
}
else if (name == u"author")
{
@@ -755,7 +753,7 @@ void RSS::Private::Parser::parseAtomArticle(QXmlStreamReader &xml)
{
// ATOM uses standard compliant date, don't do fancy stuff
const QDateTime articleDate = QDateTime::fromString(xml.readElementText().trimmed(), Qt::ISODate);
article[Article::KeyDate] = (articleDate.isValid() ? articleDate : QDateTime::currentDateTime());
article[Article::KeyDate] = (articleDate.isValid() ? articleDate : m_fallbackDate);
}
else if (name == u"author")
{

View File

@@ -1,6 +1,6 @@
/*
* Bittorrent Client using Qt and libtorrent.
* Copyright (C) 2015 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2015-2024 Vladimir Golovnev <glassez@yandex.ru>
* Copyright (C) 2012 Christophe Dumez <chris@qbittorrent.org>
*
* This program is free software; you can redistribute it and/or
@@ -29,6 +29,7 @@
#pragma once
#include <QDateTime>
#include <QList>
#include <QObject>
#include <QSet>
@@ -66,6 +67,7 @@ namespace RSS::Private
void parseAtomChannel(QXmlStreamReader &xml);
void addArticle(QVariantHash article);
QDateTime m_fallbackDate;
QString m_baseUrl;
ParsingResult m_result;
QSet<QString> m_articleIDs;

View File

@@ -31,6 +31,8 @@
#include "os.h"
#ifdef Q_OS_WIN
#include <algorithm>
#include <windows.h>
#include <powrprof.h>
#include <shlobj.h>
@@ -42,6 +44,8 @@
#include <CoreServices/CoreServices.h>
#endif // Q_OS_MACOS
#include <QScopeGuard>
#ifdef QBT_USES_DBUS
#include <QDBusInterface>
#endif // QBT_USES_DBUS
@@ -271,6 +275,11 @@ Path Utils::OS::windowsSystemPath()
#if defined(Q_OS_MACOS) || defined(Q_OS_WIN)
bool Utils::OS::applyMarkOfTheWeb(const Path &file, const QString &url)
{
// Trying to apply this to a non-existent file is unacceptable,
// as it may unexpectedly create such a file.
if (!file.exists())
return false;
Q_ASSERT(url.isEmpty() || url.startsWith(u"http:") || url.startsWith(u"https:"));
#ifdef Q_OS_MACOS
@@ -278,34 +287,49 @@ bool Utils::OS::applyMarkOfTheWeb(const Path &file, const QString &url)
// https://searchfox.org/mozilla-central/rev/ffdc4971dc18e1141cb2a90c2b0b776365650270/xpcom/io/CocoaFileUtils.mm#230
// https://github.com/transmission/transmission/blob/f62f7427edb1fd5c430e0ef6956bbaa4f03ae597/macosx/Torrent.mm#L1945-L1955
const CFStringRef fileString = file.toString().toCFString();
[[maybe_unused]] const auto fileStringGuard = qScopeGuard([&fileString] { ::CFRelease(fileString); });
const CFURLRef fileURL = ::CFURLCreateWithFileSystemPath(kCFAllocatorDefault
, fileString, kCFURLPOSIXPathStyle, false);
[[maybe_unused]] const auto fileURLGuard = qScopeGuard([&fileURL] { ::CFRelease(fileURL); });
if (CFDictionaryRef currentProperties = nullptr;
::CFURLCopyResourcePropertyForKey(fileURL, kCFURLQuarantinePropertiesKey, &currentProperties, NULL)
&& currentProperties)
{
[[maybe_unused]] const auto currentPropertiesGuard = qScopeGuard([&currentProperties] { ::CFRelease(currentProperties); });
if (CFStringRef quarantineType = nullptr;
::CFDictionaryGetValueIfPresent(currentProperties, kLSQuarantineTypeKey, reinterpret_cast<const void **>(&quarantineType))
&& quarantineType)
{
if (::CFStringCompare(quarantineType, kLSQuarantineTypeOtherDownload, 0) == kCFCompareEqualTo)
return true;
}
}
CFMutableDictionaryRef properties = ::CFDictionaryCreateMutable(kCFAllocatorDefault, 0
, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (properties == NULL)
if (!properties)
return false;
[[maybe_unused]] const auto propertiesGuard = qScopeGuard([&properties] { ::CFRelease(properties); });
::CFDictionarySetValue(properties, kLSQuarantineTypeKey, kLSQuarantineTypeOtherDownload);
if (!url.isEmpty())
::CFDictionarySetValue(properties, kLSQuarantineDataURLKey, url.toCFString());
const CFStringRef fileString = file.toString().toCFString();
const CFURLRef fileURL = ::CFURLCreateWithFileSystemPath(kCFAllocatorDefault
, fileString, kCFURLPOSIXPathStyle, false);
const Boolean success = ::CFURLSetResourcePropertyForKey(fileURL, kCFURLQuarantinePropertiesKey
, properties, NULL);
::CFRelease(fileURL);
::CFRelease(fileString);
::CFRelease(properties);
return success;
#elif defined(Q_OS_WIN)
const QString zoneIDStream = file.toString() + u":Zone.Identifier";
HANDLE handle = ::CreateFileW(zoneIDStream.toStdWString().c_str(), GENERIC_WRITE
HANDLE handle = ::CreateFileW(zoneIDStream.toStdWString().c_str(), (GENERIC_READ | GENERIC_WRITE)
, (FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE)
, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (handle == INVALID_HANDLE_VALUE)
return false;
[[maybe_unused]] const auto handleGuard = qScopeGuard([&handle] { ::CloseHandle(handle); });
// 5.6.1 Zone.Identifier Stream Name
// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/6e3f7352-d11c-4d76-8c39-2516a9df36e8
@@ -313,10 +337,27 @@ bool Utils::OS::applyMarkOfTheWeb(const Path &file, const QString &url)
const QByteArray zoneID = QByteArrayLiteral("[ZoneTransfer]\r\nZoneId=3\r\n")
+ u"HostUrl=%1\r\n"_s.arg(hostURL).toUtf8();
if (LARGE_INTEGER streamSize = {0};
::GetFileSizeEx(handle, &streamSize) && (streamSize.QuadPart > 0))
{
const DWORD expectedReadSize = std::min<LONGLONG>(streamSize.QuadPart, 1024);
QByteArray buf {expectedReadSize, '\0'};
if (DWORD actualReadSize = 0;
::ReadFile(handle, buf.data(), expectedReadSize, &actualReadSize, nullptr) && (actualReadSize == expectedReadSize))
{
if (buf.startsWith("[ZoneTransfer]\r\n") && buf.contains("\r\nZoneId=3\r\n") && buf.contains("\r\nHostUrl="))
return true;
}
}
if (!::SetFilePointerEx(handle, {0}, nullptr, FILE_BEGIN))
return false;
if (!::SetEndOfFile(handle))
return false;
DWORD written = 0;
const BOOL writeResult = ::WriteFile(handle, zoneID.constData(), zoneID.size(), &written, nullptr);
::CloseHandle(handle);
return writeResult && (written == zoneID.size());
#endif
}

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