mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-20 15:37:26 -06:00
Compare commits
50 Commits
release-3.
...
v3_3_x
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b2083b18f | ||
|
|
27e793b4e1 | ||
|
|
cc85806316 | ||
|
|
d955e40531 | ||
|
|
9b7dc87a99 | ||
|
|
dbfaf35db4 | ||
|
|
f3b4c4acfc | ||
|
|
b37c395118 | ||
|
|
d6ab0d6f02 | ||
|
|
1b8c61c390 | ||
|
|
cbfdc8f721 | ||
|
|
cfae8c6399 | ||
|
|
246a19d685 | ||
|
|
8b6e06cfff | ||
|
|
7e8f2ecc76 | ||
|
|
0f061aa40d | ||
|
|
256211c16a | ||
|
|
bd684df315 | ||
|
|
8eb9117033 | ||
|
|
83ae15550d | ||
|
|
3783541c30 | ||
|
|
cc388fe772 | ||
|
|
78f2afa239 | ||
|
|
245e8e09bb | ||
|
|
986cff9e66 | ||
|
|
73f477072f | ||
|
|
7e9ece2701 | ||
|
|
ba8641f1ac | ||
|
|
76c6041031 | ||
|
|
2ae8472a78 | ||
|
|
dc9df6d681 | ||
|
|
aed9e8f1b7 | ||
|
|
a94d14acaf | ||
|
|
317689bd5d | ||
|
|
1ad66ba791 | ||
|
|
b4fb193d4a | ||
|
|
ab47559bf2 | ||
|
|
ac87728150 | ||
|
|
1559205114 | ||
|
|
54e8b6944e | ||
|
|
164e8156db | ||
|
|
c83bb22e80 | ||
|
|
166c2a72ac | ||
|
|
6b659804c7 | ||
|
|
0831320f17 | ||
|
|
8d2fb06f65 | ||
|
|
bf6f103142 | ||
|
|
c4b12b854e | ||
|
|
de514e29c2 | ||
|
|
03d020f0f2 |
@@ -3,7 +3,7 @@ version: '{branch}-{build}'
|
||||
# Do not build on tags (GitHub only)
|
||||
skip_tags: true
|
||||
|
||||
os: Visual Studio 2015
|
||||
image: Visual Studio 2017
|
||||
|
||||
environment:
|
||||
REPO_DIR: &REPO_DIR c:\qbittorrent
|
||||
@@ -36,7 +36,7 @@ install:
|
||||
|
||||
before_build:
|
||||
# setup env
|
||||
- CALL "c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\vcvars32.bat"
|
||||
- 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%"
|
||||
|
||||
14
.travis.yml
14
.travis.yml
@@ -132,15 +132,15 @@ install:
|
||||
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.0.10.el_capitan.bottle.tar.gz ;
|
||||
wget https://builds.shiki.hu/homebrew/qt5.rb ;
|
||||
wget https://builds.shiki.hu/homebrew/qt5-5.7.1_1.el_capitan.bottle.tar.gz ;
|
||||
wget https://builds.shiki.hu/homebrew/libtorrent-rasterbar-1.0.11+git20170910.6d5625e0ea.el_capitan.bottle.tar.gz
|
||||
wget https://builds.shiki.hu/homebrew/qt.rb
|
||||
wget https://builds.shiki.hu/homebrew/qt-5.9.1.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.0.10.el_capitan.bottle.tar.gz" "$(brew --cache)" ;
|
||||
cp "$HOME/hombebrew_cache/libtorrent-rasterbar-1.0.11+git20170910.6d5625e0ea.el_capitan.bottle.tar.gz" "$(brew --cache)"
|
||||
brew install "$HOME/hombebrew_cache/libtorrent-rasterbar.rb" ;
|
||||
|
||||
# Qt
|
||||
@@ -149,9 +149,9 @@ install:
|
||||
# Copy custom qt5 bottle to homebrew's cache so it can find and install it
|
||||
# Also install our custom qt5 formula by passing the local path to it
|
||||
# These 2 files are restored from Travis' cache.
|
||||
cp "$HOME/hombebrew_cache/qt5-5.7.1_1.el_capitan.bottle.tar.gz" "$(brew --cache)" ;
|
||||
brew install "$HOME/hombebrew_cache/qt5.rb" ;
|
||||
brew link --force qt5 ;
|
||||
cp "$HOME/hombebrew_cache/qt-5.9.1.el_capitan.bottle.tar.gz" "$(brew --cache)"
|
||||
brew install "$HOME/hombebrew_cache/qt.rb"
|
||||
brew link --force qt
|
||||
fi
|
||||
fi
|
||||
- |
|
||||
|
||||
28
Changelog
28
Changelog
@@ -1,3 +1,31 @@
|
||||
* Thu Sep 07 2017 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.3.16
|
||||
- BUGFIX: Better memory footprint when using libtorrent 1.1.x. The cache is turned off by default(`0 (disabled)` value in the settings). The value `-1 (auto)` makes it use 1/8 of your RAM. (sledgehammer999)
|
||||
- BUGFIX: Skip user input events when adding torrent. Closes #7327. (glassez)
|
||||
- BUGFIX: Avoid memory leak in the speed graph. (Chocobo1)
|
||||
- WEBUI: Fix validating wrong header field. X-Forwarded-Host is a foreign proxy setting, it isn't the same as qbt's local setting and thus it makes no sense to verify it. Closes #7311. (Chocobo1)
|
||||
- WINDOWS: Fix connection problems when a specific interface/ip is configured. (sledgehammer999)
|
||||
- WINDOWS: Disable skipping of loopback interfaces. This fixes the absence of VPN tunnel interfaces under Windows and works around the QTBUG-32349. Fixes #7291. (Evengard)
|
||||
- WINDOWS: The installer detects the 64bit running process too. (vlakoff)
|
||||
|
||||
* Thu Aug 03 2017 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.3.15
|
||||
- BUGFIX: Temporary subfolder wasn't being deleted. (glassez)
|
||||
|
||||
* Tue Jul 18 2017 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.3.14
|
||||
- BUGFIX: Set interface for outgoing traffic(libtorrent 1.1.x series). (evsh)
|
||||
- WEBUI: Fix KEEP_ALIVE_DURATION value (Chocobo1)
|
||||
- WEBUI: Relax CSRF defense. Closes #6882. Allow HTTP request which has neither Origin nor Referer header included. (Chocobo1)
|
||||
- WEBUI: Skip username/password check for active sessions (closes #6860) (Thomas Piccirello)
|
||||
- WEBUI: Fix javascript errors and follow best practices (Thomas Piccirello)
|
||||
- WEBUI: Fix value comparison. Closes #7081. (Chocobo1)
|
||||
- WEBUI: Avoid modifying request headers (Chocobo1)
|
||||
- WEBUI: Implement HTTP host header filtering. This filtering is required to defend against DNS rebinding attack. Fixes security issues reported by @beardog108 privately. (Chocobo1)
|
||||
- WEBUI: Add Status column to webui (addresses #6815) (#7032) (Tom Piccirello)
|
||||
- WEBUI: Bump API_VERSION and API_VERSION_MIN to 15.
|
||||
- SEARCH: Pad shorter python versions. Closes #6877. (sledgehammer999)
|
||||
- WINDOWS: Updated Arabic, Turkish, Greek, Russian, Danish languages of the installer. (KingLucius, BouRock, thalieht, Andrei Stepanov, scootergrisen)
|
||||
- WINDOWS: Raise total stack size on Windows to 8 MB. Closes #7021. (Chocobo1)
|
||||
- LINUX: Systemd service with user switch and other fixes/optimizations. (anton.latukha)
|
||||
|
||||
* Thu Jun 01 2017 - sledgehammer999 <sledgehammer999@qbittorrent.org> - v3.3.13
|
||||
- BUGFIX: Fixed UI glitch about torrent numbers in the sidepanel. Fixes #6454. (evsh)
|
||||
- BUGFIX: Fix downloaded/uploaded columns were not highlighted properly when selected. (Chocobo1)
|
||||
|
||||
@@ -30,9 +30,9 @@ IF(QT4_FOUND)
|
||||
NAMES ${QTSINGLEAPPLICATION_NAMES}
|
||||
PATHS ${QT_LIBRARY_DIR}
|
||||
)
|
||||
ELSEIF(Qt5Widgets_FOUND)
|
||||
ELSEIF(Qt5Core_FOUND)
|
||||
message(STATUS "Looking for Qt5 single application library")
|
||||
FOREACH(TOP_INCLUDE_PATH in ${Qt5Widgets_INCLUDE_DIRS} ${FRAMEWORK_INCLUDE_DIR})
|
||||
FOREACH(TOP_INCLUDE_PATH in ${Qt5Core_INCLUDE_DIRS} ${FRAMEWORK_INCLUDE_DIR})
|
||||
FIND_PATH(QTSINGLEAPPLICATION_INCLUDE_DIR QtSingleApplication ${TOP_INCLUDE_PATH}/QtSolutions)
|
||||
|
||||
IF(QTSINGLEAPPLICATION_INCLUDE_DIR)
|
||||
@@ -43,12 +43,12 @@ ELSEIF(Qt5Widgets_FOUND)
|
||||
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_WIDGETSLIBRARY Qt5::Widgets LOCATION)
|
||||
GET_FILENAME_COMPONENT(QT5_WIDGETSLIBRARYPATH ${QT5_WIDGETSLIBRARY} PATH)
|
||||
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_WIDGETSLIBRARYPATH}
|
||||
PATHS ${_QT5_CORELIBRARYPATH}
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
|
||||
4
configure
vendored
4
configure
vendored
@@ -6962,7 +6962,7 @@ $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
|
||||
fi
|
||||
|
||||
if test "x$enable_systemd" = "xyes"; then :
|
||||
ac_config_files="$ac_config_files dist/unix/systemd/qbittorrent-nox.service"
|
||||
ac_config_files="$ac_config_files dist/unix/systemd/qbittorrent-nox@.service"
|
||||
|
||||
cat >confcache <<\_ACEOF
|
||||
# This file is a shell script that caches the results of configure
|
||||
@@ -7716,7 +7716,7 @@ do
|
||||
case $ac_config_target in
|
||||
"depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
|
||||
"conf.pri") CONFIG_FILES="$CONFIG_FILES conf.pri" ;;
|
||||
"dist/unix/systemd/qbittorrent-nox.service") CONFIG_FILES="$CONFIG_FILES dist/unix/systemd/qbittorrent-nox.service" ;;
|
||||
"dist/unix/systemd/qbittorrent-nox@.service") CONFIG_FILES="$CONFIG_FILES dist/unix/systemd/qbittorrent-nox@.service" ;;
|
||||
|
||||
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
|
||||
esac
|
||||
|
||||
@@ -260,7 +260,7 @@ AC_SUBST(QBT_REMOVE_DEFINES)
|
||||
|
||||
AC_OUTPUT(conf.pri)
|
||||
AS_IF([test "x$enable_systemd" = "xyes"],
|
||||
[AC_OUTPUT(dist/unix/systemd/qbittorrent-nox.service)])
|
||||
[AC_OUTPUT(dist/unix/systemd/qbittorrent-nox@.service)])
|
||||
|
||||
|
||||
|
||||
|
||||
2
dist/mac/Info.plist
vendored
2
dist/mac/Info.plist
vendored
@@ -45,7 +45,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>3.3.13</string>
|
||||
<string>3.3.16</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>qBit</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
|
||||
4
dist/unix/CMakeLists.txt
vendored
4
dist/unix/CMakeLists.txt
vendored
@@ -2,8 +2,8 @@ if (SYSTEMD)
|
||||
find_package(Systemd)
|
||||
if (SYSTEMD_FOUND)
|
||||
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
|
||||
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}
|
||||
COMPONENT data)
|
||||
endif(SYSTEMD_FOUND)
|
||||
|
||||
11
dist/unix/systemd/qbittorrent-nox.service.in
vendored
11
dist/unix/systemd/qbittorrent-nox.service.in
vendored
@@ -1,11 +0,0 @@
|
||||
[Unit]
|
||||
Description=qBittorrent Daemon Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
User=1000
|
||||
ExecStart=@EXPAND_BINDIR@/qbittorrent-nox -d
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
14
dist/unix/systemd/qbittorrent-nox@.service.in
vendored
Normal file
14
dist/unix/systemd/qbittorrent-nox@.service.in
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=qBittorrenti-nox service for user %I
|
||||
|
||||
Documentation=man:qbittorrent-nox(1)
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
PrivateTmp=false
|
||||
User=%i
|
||||
ExecStart=@EXPAND_BINDIR@/qbittorrent-nox
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -17,13 +17,13 @@ LangString inst_firewallinfo ${LANG_ARABIC} "جاري اضافة القاعدة
|
||||
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
||||
LangString inst_warning ${LANG_ARABIC} "البرنامج يعمل. يرجى اغلاقه قبل البدء في التنصيب"
|
||||
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
|
||||
LangString inst_uninstall_question ${LANG_ARABIC} "A previous installation was detected. It will be uninstalled without deleting user settings."
|
||||
LangString inst_uninstall_question ${LANG_ARABIC} "يوجد نسخة سابقة من البرنامج. سيتم إزالتها دون حذف إعدادات المستخدم"
|
||||
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
||||
LangString inst_unist ${LANG_ARABIC} "جاري ازالة النسخة السابقة من البرنامج"
|
||||
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
||||
LangString launch_qbt ${LANG_ARABIC} "تشغيل البرنامج"
|
||||
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
||||
LangString inst_requires_64bit ${LANG_ARABIC} "This installer works only in 64-bit Windows versions."
|
||||
LangString inst_requires_64bit ${LANG_ARABIC} "هذا المثبت يعمل فقط في نسخ ويندوز 64 بت"
|
||||
|
||||
|
||||
;------------------------------------
|
||||
|
||||
46
dist/windows/installer-translations/danish.nsi
vendored
46
dist/windows/installer-translations/danish.nsi
vendored
@@ -1,53 +1,53 @@
|
||||
;Installer strings
|
||||
|
||||
;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)"
|
||||
LangString inst_qbt_req ${LANG_DANISH} "qBittorrent (required)"
|
||||
LangString inst_qbt_req ${LANG_DANISH} "qBittorrent (påkrævet)"
|
||||
;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut"
|
||||
LangString inst_dekstop ${LANG_DANISH} "Create Desktop Shortcut"
|
||||
LangString inst_dekstop ${LANG_DANISH} "Opret skrivebordsgenvej"
|
||||
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
||||
LangString inst_startmenu ${LANG_DANISH} "Create Start Menu Shortcut"
|
||||
LangString inst_startmenu ${LANG_DANISH} "Opret genvej i menuen Start"
|
||||
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
||||
LangString inst_torrent ${LANG_DANISH} "Open .torrent files with qBittorrent"
|
||||
LangString inst_torrent ${LANG_DANISH} "Åbn .torrent-filer med qBittorrent"
|
||||
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
|
||||
LangString inst_magnet ${LANG_DANISH} "Open magnet links with qBittorrent"
|
||||
LangString inst_magnet ${LANG_DANISH} "Åbn magnet-links med qBittorrent"
|
||||
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
||||
LangString inst_firewall ${LANG_DANISH} "Add Windows Firewall rule"
|
||||
LangString inst_firewall ${LANG_DANISH} "Tilføj Windows Firewall-regel"
|
||||
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
||||
LangString inst_firewallinfo ${LANG_DANISH} "Adding Windows Firewall rule"
|
||||
LangString inst_firewallinfo ${LANG_DANISH} "Tilføjer Windows Firewall-regel"
|
||||
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
||||
LangString inst_warning ${LANG_DANISH} "qBittorrent is running. Please close the application before installing."
|
||||
LangString inst_warning ${LANG_DANISH} "qBittorrent kører. Luk venligst programmet inden installation."
|
||||
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
|
||||
LangString inst_uninstall_question ${LANG_DANISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
|
||||
LangString inst_uninstall_question ${LANG_DANISH} "En tidligere installation blev registreret. Den vil blive afinstalleret uden at brugerindstillingerne slettes."
|
||||
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
||||
LangString inst_unist ${LANG_DANISH} "Uninstalling previous version."
|
||||
LangString inst_unist ${LANG_DANISH} "Afinstallerer tidligere version."
|
||||
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
||||
LangString launch_qbt ${LANG_DANISH} "Launch qBittorrent."
|
||||
LangString launch_qbt ${LANG_DANISH} "Start qBittorrent."
|
||||
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
||||
LangString inst_requires_64bit ${LANG_DANISH} "This installer works only in 64-bit Windows versions."
|
||||
LangString inst_requires_64bit ${LANG_DANISH} "Dette installationsprogram virker kun i 64-bit Windows versioner."
|
||||
|
||||
|
||||
;------------------------------------
|
||||
;Uninstaller strings
|
||||
|
||||
;LangString remove_files ${LANG_ENGLISH} "Remove files"
|
||||
LangString remove_files ${LANG_DANISH} "Remove files"
|
||||
LangString remove_files ${LANG_DANISH} "Fjern filer"
|
||||
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
||||
LangString remove_shortcuts ${LANG_DANISH} "Remove shortcuts"
|
||||
LangString remove_shortcuts ${LANG_DANISH} "Fjern genveje"
|
||||
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
||||
LangString remove_associations ${LANG_DANISH} "Remove file associations"
|
||||
LangString remove_associations ${LANG_DANISH} "Fjern filtilknytninger"
|
||||
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
||||
LangString remove_registry ${LANG_DANISH} "Remove registry keys"
|
||||
LangString remove_registry ${LANG_DANISH} "Fjern registreringsnøgler"
|
||||
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
||||
LangString remove_conf ${LANG_DANISH} "Remove configuration files"
|
||||
LangString remove_conf ${LANG_DANISH} "Fjern konfigurationsfiler"
|
||||
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
|
||||
LangString remove_firewall ${LANG_DANISH} "Remove Windows Firewall rule"
|
||||
LangString remove_firewall ${LANG_DANISH} "Fjern Windows Firewall-regel"
|
||||
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
|
||||
LangString remove_firewallinfo ${LANG_DANISH} "Removing Windows Firewall rule"
|
||||
LangString remove_firewallinfo ${LANG_DANISH} "Fjerner Windows Firewall-regel"
|
||||
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
|
||||
LangString remove_cache ${LANG_DANISH} "Remove torrents and cached data"
|
||||
LangString remove_cache ${LANG_DANISH} "Fjern torrents og mellemlagret data"
|
||||
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
|
||||
LangString uninst_warning ${LANG_DANISH} "qBittorrent is running. Please close the application before uninstalling."
|
||||
LangString uninst_warning ${LANG_DANISH} "qBittorrent kører. Luk venligst programmet inden afinstallation."
|
||||
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
|
||||
LangString uninst_tor_warn ${LANG_DANISH} "Not removing .torrent association. It is associated with:"
|
||||
LangString uninst_tor_warn ${LANG_DANISH} "Fjerner ikke .torrent-tilknytning. Det er tilknyttet:"
|
||||
;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:"
|
||||
LangString uninst_mag_warn ${LANG_DANISH} "Not removing magnet association. It is associated with:"
|
||||
LangString uninst_mag_warn ${LANG_DANISH} "Fjerner ikke magnet-tilknytning. Det er tilknyttet:"
|
||||
|
||||
46
dist/windows/installer-translations/greek.nsi
vendored
46
dist/windows/installer-translations/greek.nsi
vendored
@@ -1,53 +1,53 @@
|
||||
;Installer strings
|
||||
|
||||
;LangString inst_qbt_req ${LANG_ENGLISH} "qBittorrent (required)"
|
||||
LangString inst_qbt_req ${LANG_GREEK} "qBittorrent (required)"
|
||||
LangString inst_qbt_req ${LANG_GREEK} "qBittorrent (απαιτείται)"
|
||||
;LangString inst_dekstop ${LANG_ENGLISH} "Create Desktop Shortcut"
|
||||
LangString inst_dekstop ${LANG_GREEK} "Create Desktop Shortcut"
|
||||
LangString inst_dekstop ${LANG_GREEK} "Δημιουργία συντόμευσης στην Επιφάνεια Εργασίας"
|
||||
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
||||
LangString inst_startmenu ${LANG_GREEK} "Create Start Menu Shortcut"
|
||||
LangString inst_startmenu ${LANG_GREEK} "Δημιουργία συντόμευσης στο Μενού Έναρξης"
|
||||
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
||||
LangString inst_torrent ${LANG_GREEK} "Open .torrent files with qBittorrent"
|
||||
LangString inst_torrent ${LANG_GREEK} "Άνοιγμα των αρχείων .torrent με το qBittorrent"
|
||||
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
|
||||
LangString inst_magnet ${LANG_GREEK} "Open magnet links with qBittorrent"
|
||||
LangString inst_magnet ${LANG_GREEK} "Άνοιγμα των μαγνητικών συνδέσμων με το qBittorrent"
|
||||
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
||||
LangString inst_firewall ${LANG_GREEK} "Add Windows Firewall rule"
|
||||
LangString inst_firewall ${LANG_GREEK} "Προσθήκη κανόνα εξαίρεσης στο Τείχος Προστασίας των Windows"
|
||||
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
||||
LangString inst_firewallinfo ${LANG_GREEK} "Adding Windows Firewall rule"
|
||||
LangString inst_firewallinfo ${LANG_GREEK} "Προστίθεται κανόνας εξαίρεσης στο Τείχος Προστασίας των Windows"
|
||||
;LangString inst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before installing."
|
||||
LangString inst_warning ${LANG_GREEK} "qBittorrent is running. Please close the application before installing."
|
||||
LangString inst_warning ${LANG_GREEK} "Το qBittorrent βρίσκεται σε εκτέλεση. Παρακαλούμε κλείστε την εφαρμογή πριν την εγκατάσταση."
|
||||
;LangString inst_uninstall_question ${LANG_ENGLISH} "A previous installation was detected. It will be uninstalled without deleting user settings."
|
||||
LangString inst_uninstall_question ${LANG_GREEK} "A previous installation was detected. It will be uninstalled without deleting user settings."
|
||||
LangString inst_uninstall_question ${LANG_GREEK} "Ανιχνεύθηκε προηγούμενη εγκατάσταση. Θα απεγκατασταθεί χωρίς να διαγραφούν οι ρυθμίσεις του χρήστη."
|
||||
;LangString inst_unist ${LANG_ENGLISH} "Uninstalling previous version."
|
||||
LangString inst_unist ${LANG_GREEK} "Uninstalling previous version."
|
||||
LangString inst_unist ${LANG_GREEK} "Γίνεται απεγκατάσταση της προηγούμενης έκδοσης."
|
||||
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
||||
LangString launch_qbt ${LANG_GREEK} "Launch qBittorrent."
|
||||
LangString launch_qbt ${LANG_GREEK} "Εκκίνηση του qBittorrent."
|
||||
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
||||
LangString inst_requires_64bit ${LANG_GREEK} "This installer works only in 64-bit Windows versions."
|
||||
LangString inst_requires_64bit ${LANG_GREEK} "Αυτό το αρχείο εγκατάστασης λειτουργεί μόνο σε 64-bit εκδόσεις των Windows."
|
||||
|
||||
|
||||
;------------------------------------
|
||||
;Uninstaller strings
|
||||
|
||||
;LangString remove_files ${LANG_ENGLISH} "Remove files"
|
||||
LangString remove_files ${LANG_GREEK} "Remove files"
|
||||
LangString remove_files ${LANG_GREEK} "Να διαγραφούν τα αρχεία"
|
||||
;LangString remove_shortcuts ${LANG_ENGLISH} "Remove shortcuts"
|
||||
LangString remove_shortcuts ${LANG_GREEK} "Remove shortcuts"
|
||||
LangString remove_shortcuts ${LANG_GREEK} "Να διαγραφούν οι συντομεύσεις"
|
||||
;LangString remove_associations ${LANG_ENGLISH} "Remove file associations"
|
||||
LangString remove_associations ${LANG_GREEK} "Remove file associations"
|
||||
LangString remove_associations ${LANG_GREEK} "Να καταργηθούν οι συσχετίσεις αρχείων"
|
||||
;LangString remove_registry ${LANG_ENGLISH} "Remove registry keys"
|
||||
LangString remove_registry ${LANG_GREEK} "Remove registry keys"
|
||||
LangString remove_registry ${LANG_GREEK} "Να διαγραφούν τα κλειδιά μητρώου"
|
||||
;LangString remove_conf ${LANG_ENGLISH} "Remove configuration files"
|
||||
LangString remove_conf ${LANG_GREEK} "Remove configuration files"
|
||||
LangString remove_conf ${LANG_GREEK} "Να διαγραφούν τα αρχεία ρυθμίσεων"
|
||||
;LangString remove_firewall ${LANG_ENGLISH} "Remove Windows Firewall rule"
|
||||
LangString remove_firewall ${LANG_GREEK} "Remove Windows Firewall rule"
|
||||
LangString remove_firewall ${LANG_GREEK} "Να διαγραφεί ο κανόνας εξαίρεσης στο Τείχος Προστασίας των Windows"
|
||||
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
|
||||
LangString remove_firewallinfo ${LANG_GREEK} "Removing Windows Firewall rule"
|
||||
LangString remove_firewallinfo ${LANG_GREEK} "Γίνεται διαγραφή του κανόνα εξαίρεσης στο Τείχος Προστασίας των Windows"
|
||||
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
|
||||
LangString remove_cache ${LANG_GREEK} "Remove torrents and cached data"
|
||||
LangString remove_cache ${LANG_GREEK} "Να διαγραφούν τα torrents και τα δεδομένα προσωρινής αποθήκευσης"
|
||||
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
|
||||
LangString uninst_warning ${LANG_GREEK} "qBittorrent is running. Please close the application before uninstalling."
|
||||
LangString uninst_warning ${LANG_GREEK} "Το qBittorrent βρίσκεται σε εκτέλεση. Παρακαλούμε κλείστε την εφαρμογή πριν την απεγκατάσταση."
|
||||
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
|
||||
LangString uninst_tor_warn ${LANG_GREEK} "Not removing .torrent association. It is associated with:"
|
||||
LangString uninst_tor_warn ${LANG_GREEK} "Δεν θα καταργηθεί η συσχέτιση με τα αρχεία .torrent. Είναι συσχετισμένα με το:"
|
||||
;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:"
|
||||
LangString uninst_mag_warn ${LANG_GREEK} "Not removing magnet association. It is associated with:"
|
||||
LangString uninst_mag_warn ${LANG_GREEK} "Δεν θα καταργηθεί η συσχέτιση με τους μαγνητικούς συνδέσμους. Είναι συσχετισμένοι με το:"
|
||||
|
||||
12
dist/windows/installer-translations/russian.nsi
vendored
12
dist/windows/installer-translations/russian.nsi
vendored
@@ -7,9 +7,9 @@ LangString inst_dekstop ${LANG_RUSSIAN} "Создать ярлык на рабо
|
||||
;LangString inst_startmenu ${LANG_ENGLISH} "Create Start Menu Shortcut"
|
||||
LangString inst_startmenu ${LANG_RUSSIAN} "Создать ярлык в меню Пуск"
|
||||
;LangString inst_torrent ${LANG_ENGLISH} "Open .torrent files with qBittorrent"
|
||||
LangString inst_torrent ${LANG_RUSSIAN} "Открывать торрент файлы с помощью qBittorrent"
|
||||
LangString inst_torrent ${LANG_RUSSIAN} "Открывать торрент-файлы с помощью qBittorrent"
|
||||
;LangString inst_magnet ${LANG_ENGLISH} "Open magnet links with qBittorrent"
|
||||
LangString inst_magnet ${LANG_RUSSIAN} "Открывать magnet ссылки с помощью qBittorrent"
|
||||
LangString inst_magnet ${LANG_RUSSIAN} "Открывать magnet-ссылки с помощью qBittorrent"
|
||||
;LangString inst_firewall ${LANG_ENGLISH} "Add Windows Firewall rule"
|
||||
LangString inst_firewall ${LANG_RUSSIAN} "Добавить в список исключений брандмауера"
|
||||
;LangString inst_firewallinfo ${LANG_ENGLISH} "Adding Windows Firewall rule"
|
||||
@@ -23,7 +23,7 @@ LangString inst_unist ${LANG_RUSSIAN} "Деинсталлируем старую
|
||||
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
||||
LangString launch_qbt ${LANG_RUSSIAN} "Запустить qBittorrent."
|
||||
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
||||
LangString inst_requires_64bit ${LANG_RUSSIAN} "This installer works only in 64-bit Windows versions."
|
||||
LangString inst_requires_64bit ${LANG_RUSSIAN} "Этот установщик работает только на 64-битных версиях Windows."
|
||||
|
||||
|
||||
;------------------------------------
|
||||
@@ -44,10 +44,10 @@ LangString remove_firewall ${LANG_RUSSIAN} "Удалить из списка и
|
||||
;LangString remove_firewallinfo ${LANG_ENGLISH} "Removing Windows Firewall rule"
|
||||
LangString remove_firewallinfo ${LANG_RUSSIAN} "Удаление из списка исключений брандмауера"
|
||||
;LangString remove_cache ${LANG_ENGLISH} "Remove torrents and cached data"
|
||||
LangString remove_cache ${LANG_RUSSIAN} "Удалить сохраненные торрент файлы"
|
||||
LangString remove_cache ${LANG_RUSSIAN} "Удалить сохранённые торрент-файлы"
|
||||
;LangString uninst_warning ${LANG_ENGLISH} "qBittorrent is running. Please close the application before uninstalling."
|
||||
LangString uninst_warning ${LANG_RUSSIAN} "qBittorrent запущен. Пожалуйста, закройте qBittorrent и перезапустите программу удаления."
|
||||
;LangString uninst_tor_warn ${LANG_ENGLISH} "Not removing .torrent association. It is associated with:"
|
||||
LangString uninst_tor_warn ${LANG_RUSSIAN} "Ассоциации торрент файлов не сброшены. Уже ассоциированы с:"
|
||||
LangString uninst_tor_warn ${LANG_RUSSIAN} "Ассоциации торрент-файлов не сброшены. Уже ассоциированы с:"
|
||||
;LangString uninst_mag_warn ${LANG_ENGLISH} "Not removing magnet association. It is associated with:"
|
||||
LangString uninst_mag_warn ${LANG_RUSSIAN} "Ассоциации magnet ссылок не сброшены. Уже ассоциированы с:"
|
||||
LangString uninst_mag_warn ${LANG_RUSSIAN} "Ассоциации magnet-ссылок не сброшены. Уже ассоциированы с:"
|
||||
|
||||
@@ -23,7 +23,7 @@ LangString inst_unist ${LANG_TURKISH} "Önceki sürüm kaldırılıyor."
|
||||
;LangString launch_qbt ${LANG_ENGLISH} "Launch qBittorrent."
|
||||
LangString launch_qbt ${LANG_TURKISH} "qBittorrent'i çalıştır."
|
||||
;LangString inst_requires_64bit ${LANG_ENGLISH} "This installer works only in 64-bit Windows versions."
|
||||
LangString inst_requires_64bit ${LANG_TURKISH} "This installer works only in 64-bit Windows versions."
|
||||
LangString inst_requires_64bit ${LANG_TURKISH} "Bu yükleyici sadece 64-bit Windows sürümlerinde çalışır."
|
||||
|
||||
|
||||
;------------------------------------
|
||||
|
||||
Binary file not shown.
Binary file not shown.
BIN
dist/windows/nsis plugins/FindProcDLL_mod_by_hnedka.7z
vendored
Normal file
BIN
dist/windows/nsis plugins/FindProcDLL_mod_by_hnedka.7z
vendored
Normal file
Binary file not shown.
2
dist/windows/options.nsi
vendored
2
dist/windows/options.nsi
vendored
@@ -27,7 +27,7 @@ XPStyle on
|
||||
!define CSIDL_LOCALAPPDATA '0x1C' ;Local Application Data path
|
||||
|
||||
; Program specific
|
||||
!define PROG_VERSION "3.3.13"
|
||||
!define PROG_VERSION "3.3.16"
|
||||
|
||||
!define MUI_FINISHPAGE_RUN
|
||||
!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include <QString>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
#include <QUuid>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <queue>
|
||||
@@ -88,6 +89,14 @@
|
||||
#include "tracker.h"
|
||||
#include "trackerentry.h"
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <iphlpapi.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WIN) && (_WIN32_WINNT < 0x0600)
|
||||
using NETIO_STATUS = LONG;
|
||||
#endif
|
||||
|
||||
static const char PEER_ID[] = "qB";
|
||||
static const char RESUME_FOLDER[] = "BT_backup";
|
||||
static const char USER_AGENT[] = "qBittorrent/" QBT_VERSION_2;
|
||||
@@ -105,6 +114,10 @@ namespace
|
||||
void torrentQueuePositionTop(const libt::torrent_handle &handle);
|
||||
void torrentQueuePositionBottom(const libt::torrent_handle &handle);
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
QString convertIfaceNameToGuid(const QString &name);
|
||||
#endif
|
||||
|
||||
inline SettingsStorage *settings() { return SettingsStorage::instance(); }
|
||||
|
||||
QStringMap map_cast(const QVariantMap &map)
|
||||
@@ -313,6 +326,10 @@ Session::Session(QObject *parent)
|
||||
sessionSettings.connection_speed = 20; // default is 10
|
||||
sessionSettings.no_connect_privileged_ports = false;
|
||||
sessionSettings.seed_choking_algorithm = libt::session_settings::fastest_upload;
|
||||
// Disk cache pool is rarely tested in libtorrent and doesn't free buffers
|
||||
// Soon to be deprecated there
|
||||
// More info: https://github.com/arvidn/libtorrent/issues/2251
|
||||
sessionSettings.use_disk_cache_pool = false;
|
||||
configure(sessionSettings);
|
||||
m_nativeSession->set_settings(sessionSettings);
|
||||
configureListeningInterface();
|
||||
@@ -340,6 +357,10 @@ Session::Session(QObject *parent)
|
||||
pack.set_int(libt::settings_pack::connection_speed, 20); // default is 10
|
||||
pack.set_bool(libt::settings_pack::no_connect_privileged_ports, false);
|
||||
pack.set_int(libt::settings_pack::seed_choking_algorithm, libt::settings_pack::fastest_upload);
|
||||
// Disk cache pool is rarely tested in libtorrent and doesn't free buffers
|
||||
// Soon to be deprecated there
|
||||
// More info: https://github.com/arvidn/libtorrent/issues/2251
|
||||
pack.set_bool(libt::settings_pack::use_disk_cache_pool, false);
|
||||
configure(pack);
|
||||
|
||||
m_nativeSession = new libt::session(pack, 0);
|
||||
@@ -900,6 +921,10 @@ void Session::configure(libtorrent::settings_pack &settingsPack)
|
||||
{
|
||||
Logger* const logger = Logger::instance();
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
QString chosenIP;
|
||||
#endif
|
||||
|
||||
if (m_listenInterfaceChanged) {
|
||||
const ushort port = this->port();
|
||||
std::pair<int, int> ports(port, port);
|
||||
@@ -929,10 +954,31 @@ void Session::configure(libtorrent::settings_pack &settingsPack)
|
||||
.arg(ip).arg(port)
|
||||
, Log::INFO);
|
||||
settingsPack.set_str(libt::settings_pack::listen_interfaces, interfacesStr);
|
||||
#ifdef Q_OS_WIN
|
||||
chosenIP = ip;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
// On Vista+ versions and after Qt 5.5 QNetworkInterface::name() returns
|
||||
// the interface's Luid and not the GUID.
|
||||
// Libtorrent expects GUIDs for the 'outgoing_interfaces' setting.
|
||||
if (!networkInterface().isEmpty()) {
|
||||
QString guid = convertIfaceNameToGuid(networkInterface());
|
||||
if (!guid.isEmpty()) {
|
||||
settingsPack.set_str(libt::settings_pack::outgoing_interfaces, guid.toStdString());
|
||||
}
|
||||
else {
|
||||
settingsPack.set_str(libt::settings_pack::outgoing_interfaces, chosenIP.toStdString());
|
||||
LogMsg(tr("Could not get GUID of configured network interface. Binding to IP %1").arg(chosenIP)
|
||||
, Log::WARNING);
|
||||
}
|
||||
}
|
||||
#else
|
||||
settingsPack.set_str(libt::settings_pack::outgoing_interfaces, networkInterface().toStdString());
|
||||
#endif
|
||||
m_listenInterfaceChanged = false;
|
||||
}
|
||||
|
||||
@@ -998,8 +1044,8 @@ void Session::configure(libtorrent::settings_pack &settingsPack)
|
||||
settingsPack.set_bool(libt::settings_pack::announce_to_all_trackers, announceToAll);
|
||||
settingsPack.set_bool(libt::settings_pack::announce_to_all_tiers, announceToAll);
|
||||
|
||||
const int cacheSize = diskCacheSize();
|
||||
settingsPack.set_int(libt::settings_pack::cache_size, (cacheSize > 0) ? cacheSize * 64 : -1);
|
||||
const int cacheSize = (diskCacheSize() > -1) ? diskCacheSize() * 64 : -1;
|
||||
settingsPack.set_int(libt::settings_pack::cache_size, cacheSize);
|
||||
settingsPack.set_int(libt::settings_pack::cache_expiry, diskCacheTTL());
|
||||
qDebug() << "Using a disk cache size of" << cacheSize << "MiB";
|
||||
|
||||
@@ -1145,8 +1191,8 @@ void Session::configure(libtorrent::session_settings &sessionSettings)
|
||||
bool announceToAll = announceToAllTrackers();
|
||||
sessionSettings.announce_to_all_trackers = announceToAll;
|
||||
sessionSettings.announce_to_all_tiers = announceToAll;
|
||||
int cacheSize = diskCacheSize();
|
||||
sessionSettings.cache_size = (cacheSize > 0) ? cacheSize * 64 : -1;
|
||||
const int cacheSize = (diskCacheSize() > -1) ? diskCacheSize() * 64 : -1;
|
||||
sessionSettings.cache_size = cacheSize;
|
||||
sessionSettings.cache_expiry = diskCacheTTL();
|
||||
qDebug() << "Using a disk cache size of" << cacheSize << "MiB";
|
||||
libt::session_settings::io_buffer_mode_t mode = useOSCache() ? libt::session_settings::enable_os_cache
|
||||
@@ -1715,7 +1761,7 @@ bool Session::findIncompleteFiles(TorrentInfo &torrentInfo, QString &savePath) c
|
||||
torrentInfo.renameFile(i, filePath + QB_EXT);
|
||||
}
|
||||
if ((i % 100) == 0)
|
||||
qApp->processEvents();
|
||||
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
}
|
||||
|
||||
return found;
|
||||
@@ -2216,10 +2262,10 @@ QString Session::networkInterface() const
|
||||
return m_networkInterface;
|
||||
}
|
||||
|
||||
void Session::setNetworkInterface(const QString &interface)
|
||||
void Session::setNetworkInterface(const QString &iface)
|
||||
{
|
||||
if (interface != networkInterface()) {
|
||||
m_networkInterface = interface;
|
||||
if (iface != networkInterface()) {
|
||||
m_networkInterface = iface;
|
||||
configureListeningInterface();
|
||||
}
|
||||
}
|
||||
@@ -2412,27 +2458,27 @@ void Session::setAnnounceToAllTrackers(bool val)
|
||||
}
|
||||
}
|
||||
|
||||
uint Session::diskCacheSize() const
|
||||
int Session::diskCacheSize() const
|
||||
{
|
||||
uint size = m_diskCacheSize;
|
||||
int size = m_diskCacheSize;
|
||||
// These macros may not be available on compilers other than MSVC and GCC
|
||||
#if defined(__x86_64__) || defined(_M_X64)
|
||||
size = qMin(size, 4096u); // 4GiB
|
||||
size = qMin(size, 4096); // 4GiB
|
||||
#else
|
||||
// When build as 32bit binary, set the maximum at less than 2GB to prevent crashes
|
||||
// allocate 1536MiB and leave 512MiB to the rest of program data in RAM
|
||||
size = qMin(size, 1536u);
|
||||
size = qMin(size, 1536);
|
||||
#endif
|
||||
return size;
|
||||
}
|
||||
|
||||
void Session::setDiskCacheSize(uint size)
|
||||
void Session::setDiskCacheSize(int size)
|
||||
{
|
||||
#if defined(__x86_64__) || defined(_M_X64)
|
||||
size = qMin(size, 4096u); // 4GiB
|
||||
size = qMin(size, 4096); // 4GiB
|
||||
#else
|
||||
// allocate 1536MiB and leave 512MiB to the rest of program data in RAM
|
||||
size = qMin(size, 1536u);
|
||||
size = qMin(size, 1536);
|
||||
#endif
|
||||
if (size != m_diskCacheSize) {
|
||||
m_diskCacheSize = size;
|
||||
@@ -3601,4 +3647,32 @@ namespace
|
||||
qDebug() << Q_FUNC_INFO << " fails: " << exc.what();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
QString convertIfaceNameToGuid(const QString &name)
|
||||
{
|
||||
// Under Windows XP or on Qt version <= 5.5 'name' will be a GUID already.
|
||||
QUuid uuid(name);
|
||||
if (!uuid.isNull())
|
||||
return uuid.toString().toUpper(); // Libtorrent expects the GUID in uppercase
|
||||
|
||||
using PCONVERTIFACENAMETOLUID = NETIO_STATUS (WINAPI *)(const WCHAR *, PNET_LUID);
|
||||
PCONVERTIFACENAMETOLUID ConvertIfaceNameToLuid = reinterpret_cast<PCONVERTIFACENAMETOLUID>(::GetProcAddress(::GetModuleHandleW(L"Iphlpapi.dll"), "ConvertInterfaceNameToLuidW"));
|
||||
if (!ConvertIfaceNameToLuid) return QString();
|
||||
|
||||
using PCONVERTIFACELUIDTOGUID = NETIO_STATUS (WINAPI *)(const NET_LUID *, GUID *);
|
||||
PCONVERTIFACELUIDTOGUID ConvertIfaceLuidToGuid = reinterpret_cast<PCONVERTIFACELUIDTOGUID>(::GetProcAddress(::GetModuleHandleW(L"Iphlpapi.dll"), "ConvertInterfaceLuidToGuid"));
|
||||
if (!ConvertIfaceLuidToGuid) return QString();
|
||||
|
||||
NET_LUID luid;
|
||||
LONG res = ConvertIfaceNameToLuid(name.toStdWString().c_str(), &luid);
|
||||
if (res == 0) {
|
||||
GUID guid;
|
||||
if (ConvertIfaceLuidToGuid(&luid, &guid) == 0)
|
||||
return QUuid(guid).toString().toUpper();
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -279,8 +279,8 @@ namespace BitTorrent
|
||||
void setIPFilterFile(QString path);
|
||||
bool announceToAllTrackers() const;
|
||||
void setAnnounceToAllTrackers(bool val);
|
||||
uint diskCacheSize() const;
|
||||
void setDiskCacheSize(uint size);
|
||||
int diskCacheSize() const;
|
||||
void setDiskCacheSize(int size);
|
||||
uint diskCacheTTL() const;
|
||||
void setDiskCacheTTL(uint ttl);
|
||||
bool useOSCache() const;
|
||||
@@ -508,7 +508,7 @@ namespace BitTorrent
|
||||
CachedSettingValue<bool> m_isTrackerFilteringEnabled;
|
||||
CachedSettingValue<QString> m_IPFilterFile;
|
||||
CachedSettingValue<bool> m_announceToAllTrackers;
|
||||
CachedSettingValue<uint> m_diskCacheSize;
|
||||
CachedSettingValue<int> m_diskCacheSize;
|
||||
CachedSettingValue<uint> m_diskCacheTTL;
|
||||
CachedSettingValue<bool> m_useOSCache;
|
||||
CachedSettingValue<bool> m_isAnonymousModeEnabled;
|
||||
|
||||
@@ -1330,7 +1330,7 @@ void TorrentHandle::handleStorageMovedAlert(libtorrent::storage_moved_alert *p)
|
||||
}
|
||||
|
||||
qDebug("Torrent is successfully moved from %s to %s", qPrintable(m_oldPath), qPrintable(m_newPath));
|
||||
if (m_oldPath == m_session->torrentTempPath(hash())) {
|
||||
if (QDir(m_oldPath) == QDir(m_session->torrentTempPath(hash()))) {
|
||||
qDebug() << "Removing torrent temp folder:" << m_oldPath;
|
||||
Utils::Fs::smartRemoveEmptyFolderTree(m_oldPath);
|
||||
}
|
||||
|
||||
@@ -77,8 +77,8 @@ void Connection::read()
|
||||
break;
|
||||
|
||||
case RequestParser::NoError:
|
||||
Environment env;
|
||||
env.clientAddress = m_socket->peerAddress();
|
||||
const Environment env {m_socket->localAddress(), m_socket->localPort(), m_socket->peerAddress(), m_socket->peerPort()};
|
||||
|
||||
Response response = m_requestHandler->processRequest(request, env);
|
||||
if (acceptsGzipEncoding(request.headers["accept-encoding"]))
|
||||
response.headers[HEADER_CONTENT_ENCODING] = "gzip";
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
#include "connection.h"
|
||||
|
||||
static const int KEEP_ALIVE_DURATION = 7; // seconds
|
||||
static const int KEEP_ALIVE_DURATION = 7 * 1000; // milliseconds
|
||||
static const int CONNECTIONS_LIMIT = 500;
|
||||
static const int CONNECTIONS_SCAN_INTERVAL = 2; // seconds
|
||||
|
||||
@@ -126,7 +126,7 @@ bool Server::setupHttps(const QByteArray &certificates, const QByteArray &key)
|
||||
{
|
||||
QSslKey sslKey(key, QSsl::Rsa);
|
||||
if (sslKey.isNull())
|
||||
#ifdef QBT_USES_QT5
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
|
||||
sslKey = QSslKey(key, QSsl::Ec);
|
||||
#else
|
||||
{
|
||||
|
||||
@@ -37,20 +37,20 @@
|
||||
|
||||
namespace Http
|
||||
{
|
||||
const char HEADER_CACHE_CONTROL[] = "Cache-Control";
|
||||
const char HEADER_CONTENT_ENCODING[] = "Content-Encoding";
|
||||
const char HEADER_CONTENT_LENGTH[] = "Content-Length";
|
||||
const char HEADER_CONTENT_SECURITY_POLICY[] = "Content-Security-Policy";
|
||||
const char HEADER_CONTENT_TYPE[] = "Content-Type";
|
||||
const char HEADER_DATE[] = "Date";
|
||||
const char HEADER_CACHE_CONTROL[] = "cache-control";
|
||||
const char HEADER_CONTENT_ENCODING[] = "content-encoding";
|
||||
const char HEADER_CONTENT_LENGTH[] = "content-length";
|
||||
const char HEADER_CONTENT_SECURITY_POLICY[] = "content-security-policy";
|
||||
const char HEADER_CONTENT_TYPE[] = "content-type";
|
||||
const char HEADER_DATE[] = "date";
|
||||
const char HEADER_HOST[] = "host";
|
||||
const char HEADER_ORIGIN[] = "origin";
|
||||
const char HEADER_REFERER[] = "referer";
|
||||
const char HEADER_SET_COOKIE[] = "Set-Cookie";
|
||||
const char HEADER_X_CONTENT_TYPE_OPTIONS[] = "X-Content-Type-Options";
|
||||
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";
|
||||
const char HEADER_X_FRAME_OPTIONS[] = "X-Frame-Options";
|
||||
const char HEADER_X_XSS_PROTECTION[] = "X-XSS-Protection";
|
||||
const char HEADER_X_FRAME_OPTIONS[] = "x-frame-options";
|
||||
const char HEADER_X_XSS_PROTECTION[] = "x-xss-protection";
|
||||
|
||||
const char CONTENT_TYPE_CSS[] = "text/css; charset=UTF-8";
|
||||
const char CONTENT_TYPE_GIF[] = "image/gif";
|
||||
@@ -65,7 +65,11 @@ namespace Http
|
||||
|
||||
struct Environment
|
||||
{
|
||||
QHostAddress localAddress;
|
||||
quint16 localPort;
|
||||
|
||||
QHostAddress clientAddress;
|
||||
quint16 clientPort;
|
||||
};
|
||||
|
||||
struct UploadedFile
|
||||
|
||||
@@ -90,3 +90,8 @@ QVector<Log::Peer> Logger::getPeers(int lastKnownId) const
|
||||
|
||||
return m_peers.mid(size - diff);
|
||||
}
|
||||
|
||||
void LogMsg(const QString &message, const Log::MsgType &type)
|
||||
{
|
||||
Logger::instance()->addMessage(message, type);
|
||||
}
|
||||
|
||||
@@ -71,4 +71,7 @@ private:
|
||||
int peerCounter;
|
||||
};
|
||||
|
||||
// Helper function
|
||||
void LogMsg(const QString &message, const Log::MsgType &type = Log::NORMAL);
|
||||
|
||||
#endif // LOGGER_H
|
||||
|
||||
@@ -439,6 +439,16 @@ void Preferences::setWebUiLocalAuthEnabled(bool enabled)
|
||||
setValue("Preferences/WebUI/LocalHostAuth", enabled);
|
||||
}
|
||||
|
||||
QString Preferences::getServerDomains() const
|
||||
{
|
||||
return value("Preferences/WebUI/ServerDomains", "*").toString();
|
||||
}
|
||||
|
||||
void Preferences::setServerDomains(const QString &str)
|
||||
{
|
||||
setValue("Preferences/WebUI/ServerDomains", str);
|
||||
}
|
||||
|
||||
quint16 Preferences::getWebUiPort() const
|
||||
{
|
||||
return value("Preferences/WebUI/Port", 8080).toInt();
|
||||
|
||||
@@ -175,6 +175,8 @@ public:
|
||||
void setWebUiEnabled(bool enabled);
|
||||
bool isWebUiLocalAuthEnabled() const;
|
||||
void setWebUiLocalAuthEnabled(bool enabled);
|
||||
QString getServerDomains() const;
|
||||
void setServerDomains(const QString &str);
|
||||
quint16 getWebUiPort() const;
|
||||
void setWebUiPort(quint16 port);
|
||||
bool useUPnPForWebUIPort() const;
|
||||
|
||||
@@ -313,11 +313,24 @@ QString Utils::Misc::pythonVersionComplete()
|
||||
// Software 'Anaconda' installs its own python interpreter
|
||||
// and `python --version` returns a string like this:
|
||||
// `Python 3.4.3 :: Anaconda 2.3.0 (64-bit)`
|
||||
const QList<QByteArray> verSplit = output.split(' ');
|
||||
if (verSplit.size() > 1) {
|
||||
version = verSplit.at(1).trimmed();
|
||||
const QList<QByteArray> outSplit = output.split(' ');
|
||||
if (outSplit.size() > 1) {
|
||||
version = outSplit.at(1).trimmed();
|
||||
Logger::instance()->addMessage(QCoreApplication::translate("misc", "Python version: %1").arg(version), Log::INFO);
|
||||
}
|
||||
|
||||
// If python doesn't report a 3-piece version e.g. 3.6.1
|
||||
// then fill the missing pieces with zero
|
||||
const QStringList verSplit = version.split('.', QString::SkipEmptyParts);
|
||||
if (verSplit.size() < 3) {
|
||||
for (int i = verSplit.size(); i < 3; ++i) {
|
||||
if (version.endsWith('.'))
|
||||
version.append('0');
|
||||
else
|
||||
version.append(".0");
|
||||
}
|
||||
Logger::instance()->addMessage(QCoreApplication::translate("misc", "Normalized Python version: %1").arg(version), Log::INFO);
|
||||
}
|
||||
}
|
||||
}
|
||||
return version;
|
||||
|
||||
@@ -190,7 +190,9 @@ void AdvancedSettings::saveAdvancedSettings()
|
||||
|
||||
void AdvancedSettings::updateCacheSpinSuffix(int value)
|
||||
{
|
||||
if (value <= 0)
|
||||
if (value == 0)
|
||||
spin_cache.setSuffix(tr(" (disabled)"));
|
||||
else if (value < 0)
|
||||
spin_cache.setSuffix(tr(" (auto)"));
|
||||
else
|
||||
spin_cache.setSuffix(tr(" MiB"));
|
||||
@@ -251,7 +253,7 @@ void AdvancedSettings::loadAdvancedSettings()
|
||||
labelLibtorrentLink.setText(QString("<a href=\"%1\">%2</a>").arg("http://www.libtorrent.org/reference.html").arg(tr("Open documentation")));
|
||||
labelLibtorrentLink.setOpenExternalLinks(true);
|
||||
// Disk write cache
|
||||
spin_cache.setMinimum(0);
|
||||
spin_cache.setMinimum(-1);
|
||||
// When build as 32bit binary, set the maximum at less than 2GB to prevent crashes.
|
||||
// These macros may not be available on compilers other than MSVC and GCC
|
||||
#if defined(__x86_64__) || defined(_M_X64)
|
||||
@@ -323,7 +325,6 @@ void AdvancedSettings::loadAdvancedSettings()
|
||||
// https://github.com/qbittorrent/qBittorrent/pull/5135
|
||||
if (iface.addressEntries().isEmpty()) continue;
|
||||
|
||||
if (iface.flags() & QNetworkInterface::IsLoopBack) continue;
|
||||
combo_iface.addItem(iface.humanReadableName(), iface.name());
|
||||
if (!current_iface.isEmpty() && (iface.name() == current_iface)) {
|
||||
combo_iface.setCurrentIndex(i);
|
||||
|
||||
@@ -319,6 +319,7 @@ OptionsDialog::OptionsDialog(QWidget *parent)
|
||||
connect(m_ui->textTrackers, SIGNAL(textChanged()), this, SLOT(enableApplyButton()));
|
||||
#ifndef DISABLE_WEBUI
|
||||
// Web UI tab
|
||||
connect(m_ui->textServerDomains, SIGNAL(textChanged(QString)), this, SLOT(enableApplyButton()));
|
||||
connect(m_ui->checkWebUi, SIGNAL(toggled(bool)), this, SLOT(enableApplyButton()));
|
||||
connect(m_ui->spinWebUiPort, SIGNAL(valueChanged(int)), this, SLOT(enableApplyButton()));
|
||||
connect(m_ui->checkWebUIUPnP, SIGNAL(toggled(bool)), SLOT(enableApplyButton()));
|
||||
@@ -603,6 +604,7 @@ void OptionsDialog::saveOptions()
|
||||
// Web UI
|
||||
pref->setWebUiEnabled(isWebUiEnabled());
|
||||
if (isWebUiEnabled()) {
|
||||
pref->setServerDomains(m_ui->textServerDomains->text());
|
||||
pref->setWebUiPort(webUiPort());
|
||||
pref->setUPnPForWebUIPort(m_ui->checkWebUIUPnP->isChecked());
|
||||
pref->setWebUiHttpsEnabled(m_ui->checkWebUiHttps->isChecked());
|
||||
@@ -975,6 +977,7 @@ void OptionsDialog::loadOptions()
|
||||
// End Bittorrent preferences
|
||||
|
||||
// Web UI preferences
|
||||
m_ui->textServerDomains->setText(pref->getServerDomains());
|
||||
m_ui->checkWebUi->setChecked(pref->isWebUiEnabled());
|
||||
m_ui->spinWebUiPort->setValue(pref->getWebUiPort());
|
||||
m_ui->checkWebUIUPnP->setChecked(pref->useUPnPForWebUIPort());
|
||||
|
||||
@@ -2605,8 +2605,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>438</width>
|
||||
<height>543</height>
|
||||
<width>518</width>
|
||||
<height>602</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_23">
|
||||
@@ -2622,6 +2622,28 @@
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_1">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelServerDomains">
|
||||
<property name="text">
|
||||
<string>Server domains:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="textServerDomains">
|
||||
<property name="toolTip">
|
||||
<string>Whitelist for filtering HTTP Host header values.
|
||||
In order to defend against DNS rebinding attack,
|
||||
you should put in domain names used by WebUI server.
|
||||
|
||||
Use ';' to split multiple entries. Can use wildcard '*'.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
|
||||
@@ -86,7 +86,7 @@ SpeedWidget::SpeedWidget(PropertiesWidget *parent)
|
||||
m_graphsMenu->addAction(tr("Tracker Download"));
|
||||
|
||||
m_graphsMenuActions = m_graphsMenu->actions();
|
||||
m_graphsSignalMapper = new QSignalMapper();
|
||||
m_graphsSignalMapper = new QSignalMapper(this);
|
||||
|
||||
for (int id = SpeedPlotView::UP; id < SpeedPlotView::NB_GRAPHS; ++id) {
|
||||
QAction *action = m_graphsMenuActions.at(id);
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#include "abstractwebapplication.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
@@ -91,6 +93,9 @@ AbstractWebApplication::AbstractWebApplication(QObject *parent)
|
||||
QTimer *timer = new QTimer(this);
|
||||
connect(timer, SIGNAL(timeout()), SLOT(removeInactiveSessions()));
|
||||
timer->start(60 * 1000); // 1 min.
|
||||
|
||||
reloadDomainList();
|
||||
connect(Preferences::instance(), SIGNAL(changed()), this, SLOT(reloadDomainList()));
|
||||
}
|
||||
|
||||
AbstractWebApplication::~AbstractWebApplication()
|
||||
@@ -115,7 +120,7 @@ Http::Response AbstractWebApplication::processRequest(const Http::Request &reque
|
||||
header(Http::HEADER_CONTENT_SECURITY_POLICY, "default-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; script-src 'self' 'unsafe-inline'; object-src 'none';");
|
||||
|
||||
// block cross-site requests
|
||||
if (isCrossSiteRequest(request_)) {
|
||||
if (isCrossSiteRequest(request_) || !validateHostHeader(request_, env, domainList)) {
|
||||
status(401, "Unauthorized");
|
||||
return response();
|
||||
}
|
||||
@@ -153,6 +158,12 @@ void AbstractWebApplication::removeInactiveSessions()
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractWebApplication::reloadDomainList()
|
||||
{
|
||||
domainList = Preferences::instance()->getServerDomains().split(';', QString::SkipEmptyParts);
|
||||
std::for_each(domainList.begin(), domainList.end(), [](QString &entry){ entry = entry.trimmed(); });
|
||||
}
|
||||
|
||||
bool AbstractWebApplication::sessionInitialize()
|
||||
{
|
||||
if (session_ == 0)
|
||||
@@ -391,14 +402,14 @@ bool AbstractWebApplication::isCrossSiteRequest(const Http::Request &request) co
|
||||
&& (left.host() == right.host()));
|
||||
};
|
||||
|
||||
const QString targetOrigin = request.headers.value(Http::HEADER_X_FORWARDED_HOST, request.headers[Http::HEADER_HOST]);
|
||||
const QString targetOrigin = request.headers.value(Http::HEADER_X_FORWARDED_HOST, request.headers.value(Http::HEADER_HOST));
|
||||
const QString originValue = request.headers.value(Http::HEADER_ORIGIN);
|
||||
const QString refererValue = request.headers.value(Http::HEADER_REFERER);
|
||||
|
||||
if (originValue.isEmpty() && refererValue.isEmpty()) {
|
||||
if ((request.path == QLatin1String("/")) || (request.path == QLatin1String("/favicon.ico")))
|
||||
return false; // normal request
|
||||
return true;
|
||||
// owasp.org recommends to block this request, but doing so will inevitably lead Web API users to spoof headers
|
||||
// so lets be permissive here
|
||||
return false;
|
||||
}
|
||||
|
||||
// sent with CORS requests, as well as with POST requests
|
||||
@@ -411,6 +422,44 @@ bool AbstractWebApplication::isCrossSiteRequest(const Http::Request &request) co
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AbstractWebApplication::validateHostHeader(const Http::Request &request, const Http::Environment &env, const QStringList &domains) const
|
||||
{
|
||||
const QUrl hostHeader = QUrl::fromUserInput(request.headers.value(Http::HEADER_HOST));
|
||||
|
||||
// (if present) try matching host header's port with local port
|
||||
const int requestPort = hostHeader.port();
|
||||
if ((requestPort != -1) && (env.localPort != requestPort))
|
||||
return false;
|
||||
|
||||
// try matching host header with local address
|
||||
const QString requestHost = hostHeader.host();
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
|
||||
const bool sameAddr = env.localAddress.isEqual(QHostAddress(requestHost));
|
||||
#else
|
||||
const auto equal = [](const Q_IPV6ADDR &l, const Q_IPV6ADDR &r) -> bool {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
if (l[i] != r[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
const bool sameAddr = equal(env.localAddress.toIPv6Address(), QHostAddress(requestHost).toIPv6Address());
|
||||
#endif
|
||||
|
||||
if (sameAddr)
|
||||
return true;
|
||||
|
||||
// try matching host header with domain list
|
||||
for (const auto &domain : domains) {
|
||||
QRegExp domainRegex(domain, Qt::CaseInsensitive, QRegExp::Wildcard);
|
||||
if (requestHost.contains(domainRegex))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringMap AbstractWebApplication::initializeContentTypeByExtMap()
|
||||
{
|
||||
QStringMap map;
|
||||
@@ -432,7 +481,7 @@ QStringMap AbstractWebApplication::parseCookie(const Http::Request &request) con
|
||||
// [rfc6265] 4.2.1. Syntax
|
||||
QStringMap ret;
|
||||
const QString cookieStr = request.headers.value(QLatin1String("cookie"));
|
||||
#ifdef QBT_USES_QT5
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
|
||||
const QVector<QStringRef> cookies = cookieStr.splitRef(';', QString::SkipEmptyParts);
|
||||
#else
|
||||
const QStringList cookies = cookieStr.split(';', QString::SkipEmptyParts);
|
||||
@@ -442,7 +491,7 @@ QStringMap AbstractWebApplication::parseCookie(const Http::Request &request) con
|
||||
const int idx = cookie.indexOf('=');
|
||||
if (idx < 0)
|
||||
continue;
|
||||
#ifdef QBT_USES_QT5
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
|
||||
const QString name = cookie.left(idx).trimmed().toString();
|
||||
const QString value = Utils::String::unquote(cookie.mid(idx + 1).trimmed())
|
||||
.toString();
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
#include <QHash>
|
||||
#include <QMap>
|
||||
#include <QObject>
|
||||
#ifndef QBT_USES_QT5
|
||||
#include <QStringList>
|
||||
#endif
|
||||
|
||||
#include "base/http/irequesthandler.h"
|
||||
#include "base/http/responsebuilder.h"
|
||||
@@ -86,6 +89,8 @@ private slots:
|
||||
void UnbanTimerEvent();
|
||||
void removeInactiveSessions();
|
||||
|
||||
void reloadDomainList();
|
||||
|
||||
private:
|
||||
// Persistent data
|
||||
QMap<QString, WebSession *> sessions_;
|
||||
@@ -97,11 +102,14 @@ private:
|
||||
Http::Request request_;
|
||||
Http::Environment env_;
|
||||
|
||||
QStringList domainList;
|
||||
|
||||
QString generateSid();
|
||||
bool sessionInitialize();
|
||||
|
||||
QStringMap parseCookie(const Http::Request &request) const;
|
||||
bool isCrossSiteRequest(const Http::Request &request) const;
|
||||
bool validateHostHeader(const Http::Request &request, const Http::Environment &env, const QStringList &domains) const;
|
||||
|
||||
static void translateDocument(QString &data);
|
||||
|
||||
|
||||
@@ -159,6 +159,7 @@ QByteArray prefjson::getPreferences()
|
||||
// Language
|
||||
data["locale"] = pref->getLocale();
|
||||
// HTTP Server
|
||||
data["web_ui_domain_list"] = pref->getServerDomains();
|
||||
data["web_ui_port"] = pref->getWebUiPort();
|
||||
data["web_ui_upnp"] = pref->useUPnPForWebUIPort();
|
||||
data["use_https"] = pref->isWebUiHttpsEnabled();
|
||||
@@ -387,6 +388,8 @@ void prefjson::setPreferences(const QString& json)
|
||||
}
|
||||
}
|
||||
// HTTP Server
|
||||
if (m.contains("web_ui_domain_list"))
|
||||
pref->setServerDomains(m["web_ui_domain_list"].toString());
|
||||
if (m.contains("web_ui_port"))
|
||||
pref->setWebUiPort(m["web_ui_port"].toUInt());
|
||||
if (m.contains("web_ui_upnp"))
|
||||
|
||||
@@ -49,8 +49,8 @@
|
||||
#include "websessiondata.h"
|
||||
#include "webapplication.h"
|
||||
|
||||
static const int API_VERSION = 14;
|
||||
static const int API_VERSION_MIN = 14;
|
||||
static const int API_VERSION = 15;
|
||||
static const int API_VERSION_MIN = 15;
|
||||
|
||||
const QString WWW_FOLDER = ":/www/public/";
|
||||
const QString PRIVATE_FOLDER = ":/www/private/";
|
||||
@@ -172,6 +172,11 @@ void WebApplication::action_public_webui()
|
||||
|
||||
void WebApplication::action_public_login()
|
||||
{
|
||||
if (sessionActive()) {
|
||||
print(QByteArray("Ok."), Http::CONTENT_TYPE_TXT);
|
||||
return;
|
||||
}
|
||||
|
||||
const Preferences* const pref = Preferences::instance();
|
||||
QCryptographicHash md5(QCryptographicHash::Md5);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#transferList img.statusIcon {
|
||||
#transferList img.stateIcon {
|
||||
margin-bottom: -4px;
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
@@ -378,6 +378,7 @@
|
||||
|
||||
<fieldset class="settings">
|
||||
<legend>QBT_TR(Web User Interface (Remote control))QBT_TR[CONTEXT=OptionsDialog]</legend>
|
||||
<label for="webui_domain_textarea">QBT_TR(Server domains:)QBT_TR[CONTEXT=OptionsDialog]</label><textarea id="webui_domain_textarea" rows="1" cols="70"></textarea><br/>
|
||||
<label for="webui_port_value">QBT_TR(Port:)QBT_TR[CONTEXT=OptionsDialog]</label><input type="text" id="webui_port_value" style="width: 4em;"/><br/>
|
||||
<input type="checkbox" id="webui_upnp_checkbox"/>
|
||||
<label for="webui_upnp_checkbox">QBT_TR(Use UPnP / NAT-PMP to forward the port from my router)QBT_TR[CONTEXT=OptionsDialog]</label><br/>
|
||||
@@ -1003,6 +1004,7 @@ loadPreferences = function() {
|
||||
$('locale_select').setProperty('value', pref.locale);
|
||||
|
||||
// HTTP Server
|
||||
$('webui_domain_textarea').setProperty('value', pref.web_ui_domain_list);
|
||||
$('webui_port_value').setProperty('value', pref.web_ui_port);
|
||||
$('webui_upnp_checkbox').setProperty('checked', pref.web_ui_upnp);
|
||||
$('use_https_checkbox').setProperty('checked', pref.use_https);
|
||||
@@ -1257,6 +1259,7 @@ applyPreferences = function() {
|
||||
settings.set('locale', $('locale_select').getProperty('value'));
|
||||
|
||||
// HTTP Server
|
||||
settings.set('web_ui_domain_list', $('webui_domain_textarea').getProperty('value'));
|
||||
var web_ui_port = $('webui_port_value').getProperty('value').toInt();
|
||||
if(isNaN(web_ui_port) || web_ui_port < 1 || web_ui_port > 65535) {
|
||||
alert("QBT_TR(The port used for the Web UI must be between 1 and 65535.)QBT_TR[CONTEXT=HttpServer]");
|
||||
|
||||
@@ -70,7 +70,7 @@ window.addEvent('load', function () {
|
||||
var properties_height_rel = $('propertiesPanel').getSize().y / Window.getSize().y;
|
||||
localStorage.setItem('filters_width', filters_width);
|
||||
localStorage.setItem('properties_height_rel', properties_height_rel);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEvent('resize', function() {
|
||||
// Resizing might takes some time.
|
||||
@@ -128,7 +128,7 @@ window.addEvent('load', function () {
|
||||
// Reload torrents
|
||||
if (typeof torrentsTable.tableBody != 'undefined')
|
||||
updateMainData();
|
||||
}
|
||||
};
|
||||
|
||||
new MochaUI.Panel({
|
||||
id : 'Filters',
|
||||
@@ -151,10 +151,9 @@ window.addEvent('load', function () {
|
||||
initializeWindows();
|
||||
|
||||
// Show Top Toolbar is enabled by default
|
||||
if (localStorage.getItem('show_top_toolbar') == null)
|
||||
var showTopToolbar = true;
|
||||
else
|
||||
var showTopToolbar = localStorage.getItem('show_top_toolbar') == "true";
|
||||
var showTopToolbar = true;
|
||||
if (localStorage.getItem('show_top_toolbar') !== null)
|
||||
showTopToolbar = localStorage.getItem('show_top_toolbar') == "true";
|
||||
if (!showTopToolbar) {
|
||||
$('showTopToolbarLink').firstChild.style.opacity = '0';
|
||||
$('mochaToolbar').addClass('invisible');
|
||||
@@ -171,7 +170,7 @@ window.addEvent('load', function () {
|
||||
var serverState = {};
|
||||
|
||||
var removeTorrentFromCategoryList = function(hash) {
|
||||
if (hash == null || hash == "")
|
||||
if (hash === null || hash === "")
|
||||
return false;
|
||||
var removed = false;
|
||||
Object.each(category_list, function(category) {
|
||||
@@ -185,14 +184,14 @@ window.addEvent('load', function () {
|
||||
|
||||
var addTorrentToCategoryList = function(torrent) {
|
||||
var category = torrent['category'];
|
||||
if (category == null)
|
||||
if (typeof category === 'undefined')
|
||||
return false;
|
||||
if (category.length === 0) { // Empty category
|
||||
removeTorrentFromCategoryList(torrent['hash']);
|
||||
return true;
|
||||
}
|
||||
var categoryHash = genHash(category);
|
||||
if (category_list[categoryHash] == null) // This should not happen
|
||||
if (category_list[categoryHash] === null) // This should not happen
|
||||
category_list[categoryHash] = {name: category, torrents: []};
|
||||
if (!Object.contains(category_list[categoryHash].torrents, torrent['hash'])) {
|
||||
removeTorrentFromCategoryList(torrent['hash']);
|
||||
@@ -242,7 +241,7 @@ window.addEvent('load', function () {
|
||||
categoryList.appendChild(create_link(CATEGORIES_ALL, 'QBT_TR(All)QBT_TR[CONTEXT=CategoryFilterModel]', all));
|
||||
categoryList.appendChild(create_link(CATEGORIES_UNCATEGORIZED, 'QBT_TR(Uncategorized)QBT_TR[CONTEXT=CategoryFilterModel]', uncategorized));
|
||||
|
||||
var sortedCategories = []
|
||||
var sortedCategories = [];
|
||||
Object.each(category_list, function(category) {
|
||||
sortedCategories.push(category.name);
|
||||
});
|
||||
@@ -268,7 +267,7 @@ window.addEvent('load', function () {
|
||||
else
|
||||
childrens[i].className = "";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var syncMainDataTimer;
|
||||
var syncMainData = function () {
|
||||
@@ -287,7 +286,7 @@ window.addEvent('load', function () {
|
||||
$('error_div').set('html', '');
|
||||
if (response) {
|
||||
var update_categories = false;
|
||||
var full_update = (response['full_update'] == true);
|
||||
var full_update = (response['full_update'] === true);
|
||||
if (full_update) {
|
||||
torrentsTable.clear();
|
||||
category_list = {};
|
||||
@@ -313,6 +312,8 @@ window.addEvent('load', function () {
|
||||
for (var key in response['torrents']) {
|
||||
response['torrents'][key]['hash'] = key;
|
||||
response['torrents'][key]['rowId'] = key;
|
||||
if (response['torrents'][key]['state'])
|
||||
response['torrents'][key]['status'] = response['torrents'][key]['state'];
|
||||
torrentsTable.updateRowData(response['torrents'][key]);
|
||||
if (addTorrentToCategoryList(response['torrents'][key]))
|
||||
update_categories = true;
|
||||
@@ -328,8 +329,8 @@ window.addEvent('load', function () {
|
||||
torrentsTable.altRow();
|
||||
if (response['server_state']) {
|
||||
var tmp = response['server_state'];
|
||||
for(var key in tmp)
|
||||
serverState[key] = tmp[key];
|
||||
for(var k in tmp)
|
||||
serverState[k] = tmp[k];
|
||||
processServerState();
|
||||
}
|
||||
updateFiltersList();
|
||||
@@ -348,7 +349,7 @@ window.addEvent('load', function () {
|
||||
torrentsTable.updateTable();
|
||||
clearTimeout(syncMainDataTimer);
|
||||
syncMainDataTimer = syncMainData.delay(100);
|
||||
}
|
||||
};
|
||||
|
||||
var processServerState = function () {
|
||||
var transfer_info = friendlyUnit(serverState.dl_info_speed, true);
|
||||
@@ -368,7 +369,7 @@ window.addEvent('load', function () {
|
||||
document.title = "qBittorrent ${VERSION} QBT_TR(Web UI)QBT_TR[CONTEXT=OptionsDialog]";
|
||||
$('DHTNodes').set('html', 'QBT_TR(DHT: %1 nodes)QBT_TR[CONTEXT=StatusBar]'.replace("%1", serverState.dht_nodes));
|
||||
|
||||
<!-- Statistics dialog -->
|
||||
// Statistics dialog
|
||||
if (document.getElementById("statisticspage")) {
|
||||
$('AlltimeDL').set('html', 'QBT_TR(Alltime download:)QBT_TR[CONTEXT=StatsDialog]' + " " + friendlyUnit(serverState.alltime_dl, false));
|
||||
$('AlltimeUL').set('html', 'QBT_TR(Alltime upload:)QBT_TR[CONTEXT=StatsDialog]' + " " + friendlyUnit(serverState.alltime_ul, false));
|
||||
@@ -421,8 +422,8 @@ window.addEvent('load', function () {
|
||||
if (enabled)
|
||||
$('alternativeSpeedLimits').src = "images/slow.png";
|
||||
else
|
||||
$('alternativeSpeedLimits').src = "images/slow_off.png"
|
||||
}
|
||||
$('alternativeSpeedLimits').src = "images/slow_off.png";
|
||||
};
|
||||
|
||||
$('alternativeSpeedLimits').addEvent('click', function() {
|
||||
// Change icon immediately to give some feedback
|
||||
@@ -436,7 +437,7 @@ window.addEvent('load', function () {
|
||||
},
|
||||
onFailure: function() {
|
||||
// Restore icon in case of failure
|
||||
updateAltSpeedIcon(alternativeSpeedLimits)
|
||||
updateAltSpeedIcon(alternativeSpeedLimits);
|
||||
}
|
||||
}).send();
|
||||
});
|
||||
@@ -493,7 +494,7 @@ window.addEvent('load', function () {
|
||||
if ($defined(prop_h))
|
||||
prop_h = prop_h.toFloat() * Window.getSize().y;
|
||||
else
|
||||
prop_h = Window.getSize().y / 2.;
|
||||
prop_h = Window.getSize().y / 2.0;
|
||||
new MochaUI.Panel({
|
||||
id : 'propertiesPanel',
|
||||
title : 'Panel',
|
||||
@@ -524,7 +525,7 @@ window.addEvent('load', function () {
|
||||
updateWebSeedsData();
|
||||
else if (!$('prop_files').hasClass('invisible'))
|
||||
updateTorrentFilesData();
|
||||
}
|
||||
};
|
||||
|
||||
$('PropGeneralLink').addEvent('click', function(e){
|
||||
$('prop_general').removeClass("invisible");
|
||||
@@ -587,7 +588,7 @@ window.addEvent('load', function () {
|
||||
|
||||
function closeWindows() {
|
||||
MochaUI.closeAll();
|
||||
};
|
||||
}
|
||||
|
||||
var keyboardEvents = new Keyboard({
|
||||
defaultEventType: 'keydown',
|
||||
@@ -616,7 +617,7 @@ var loadTorrentPeersData = function(){
|
||||
return;
|
||||
}
|
||||
var current_hash = torrentsTable.getCurrentTorrentHash();
|
||||
if (current_hash == "") {
|
||||
if (current_hash === "") {
|
||||
syncTorrentPeersLastResponseId = 0;
|
||||
torrentPeersTable.clear();
|
||||
clearTimeout(loadTorrentPeersTimer);
|
||||
@@ -638,7 +639,7 @@ var loadTorrentPeersData = function(){
|
||||
onSuccess: function(response) {
|
||||
$('error_div').set('html', '');
|
||||
if (response) {
|
||||
var full_update = (response['full_update'] == true);
|
||||
var full_update = (response['full_update'] === true);
|
||||
if (full_update) {
|
||||
torrentPeersTable.clear();
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ var ContextMenu = new Class({
|
||||
//initialization
|
||||
initialize: function(options) {
|
||||
//set options
|
||||
this.setOptions(options)
|
||||
this.setOptions(options);
|
||||
|
||||
//option diffs menu
|
||||
this.menu = $(this.options.menu);
|
||||
@@ -69,19 +69,19 @@ var ContextMenu = new Class({
|
||||
});
|
||||
|
||||
// position the menu
|
||||
var xPos = e.page.x + this.options.offsets.x;
|
||||
var yPos = e.page.y + this.options.offsets.y;
|
||||
if (xPos + this.menu.offsetWidth > document.documentElement.clientWidth)
|
||||
xPos -= this.menu.offsetWidth;
|
||||
if (yPos + this.menu.offsetHeight > document.documentElement.clientHeight)
|
||||
yPos = document.documentElement.clientHeight - this.menu.offsetHeight;
|
||||
if (xPos < 0)
|
||||
xPos = 0;
|
||||
if (yPos < 0)
|
||||
yPos = 0;
|
||||
var xPosMenu = e.page.x + this.options.offsets.x;
|
||||
var yPosMenu = e.page.y + this.options.offsets.y;
|
||||
if (xPosMenu + this.menu.offsetWidth > document.documentElement.clientWidth)
|
||||
xPosMenu -= this.menu.offsetWidth;
|
||||
if (yPosMenu + this.menu.offsetHeight > document.documentElement.clientHeight)
|
||||
yPosMenu = document.documentElement.clientHeight - this.menu.offsetHeight;
|
||||
if (xPosMenu < 0)
|
||||
xPosMenu = 0;
|
||||
if (yPosMenu < 0)
|
||||
yPosMenu = 0;
|
||||
this.menu.setStyles({
|
||||
left: xPos,
|
||||
top: yPos,
|
||||
left: xPosMenu,
|
||||
top: yPosMenu,
|
||||
position: 'absolute',
|
||||
'z-index': '2000'
|
||||
});
|
||||
@@ -260,19 +260,19 @@ var TorrentsTableContextMenu = new Class({
|
||||
h.each(function(item, index){
|
||||
var data = torrentsTable.rows.get(item).full_data;
|
||||
|
||||
if (data['seq_dl'] != true)
|
||||
if (data['seq_dl'] !== true)
|
||||
all_are_seq_dl = false;
|
||||
else
|
||||
there_are_seq_dl = true;
|
||||
|
||||
if (data['f_l_piece_prio'] != true)
|
||||
if (data['f_l_piece_prio'] !== true)
|
||||
all_are_f_l_piece_prio = false;
|
||||
else
|
||||
there_are_f_l_piece_prio = true;
|
||||
|
||||
if (data['progress'] != 1.0) // not downloaded
|
||||
all_are_downloaded = false;
|
||||
else if (data['super_seeding'] != true)
|
||||
else if (data['super_seeding'] !== true)
|
||||
all_are_super_seeding = false;
|
||||
|
||||
if (data['state'] != 'pausedUP' && data['state'] != 'pausedDL')
|
||||
@@ -280,7 +280,7 @@ var TorrentsTableContextMenu = new Class({
|
||||
else
|
||||
there_are_paused = true;
|
||||
|
||||
if (data['force_start'] != true)
|
||||
if (data['force_start'] !== true)
|
||||
all_are_force_start = false;
|
||||
else
|
||||
there_are_force_start = true;
|
||||
@@ -344,7 +344,7 @@ var TorrentsTableContextMenu = new Class({
|
||||
categoryList.appendChild(new Element('li', {html: '<a href="javascript:torrentNewCategoryFN();"><img src="theme/list-add" alt="QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(New...)QBT_TR[CONTEXT=TransferListWidget]</a>'}));
|
||||
categoryList.appendChild(new Element('li', {html: '<a href="javascript:torrentSetCategoryFN(0);"><img src="theme/edit-clear" alt="QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]"/> QBT_TR(Reset)QBT_TR[CONTEXT=TransferListWidget]</a>'}));
|
||||
|
||||
var sortedCategories = []
|
||||
var sortedCategories = [];
|
||||
Object.each(category_list, function (category) {
|
||||
sortedCategories.push(category.name);
|
||||
});
|
||||
|
||||
@@ -22,20 +22,20 @@
|
||||
*/
|
||||
|
||||
getSavePath = function() {
|
||||
var req = new Request({
|
||||
url: 'command/getSavePath',
|
||||
method: 'get',
|
||||
noCache: true,
|
||||
onFailure: function() {
|
||||
alert("Could not contact qBittorrent");
|
||||
},
|
||||
onSuccess: function(data) {
|
||||
if (data) {
|
||||
$('savepath').setProperty('value', data);
|
||||
}
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
var req = new Request({
|
||||
url: 'command/getSavePath',
|
||||
method: 'get',
|
||||
noCache: true,
|
||||
onFailure: function() {
|
||||
alert("Could not contact qBittorrent");
|
||||
},
|
||||
onSuccess: function(data) {
|
||||
if (data) {
|
||||
$('savepath').setProperty('value', data);
|
||||
}
|
||||
}
|
||||
}).send();
|
||||
};
|
||||
|
||||
$(window).addEventListener("load", function() {
|
||||
getSavePath();
|
||||
|
||||
@@ -45,8 +45,8 @@ var DynamicTable = new Class({
|
||||
this.hiddenTableHeader = $(dynamicTableDivId).getElements('tr')[0];
|
||||
this.tableBody = $(dynamicTableDivId).getElements('tbody')[0];
|
||||
this.rows = new Hash();
|
||||
this.selectedRows = new Array();
|
||||
this.columns = new Array();
|
||||
this.selectedRows = [];
|
||||
this.columns = [];
|
||||
this.contextMenu = contextMenu;
|
||||
this.sortedColumn = getLocalStorageItem('sorted_column_' + this.dynamicTableDivId, 0);
|
||||
this.reverseSort = getLocalStorageItem('reverse_sort_' + this.dynamicTableDivId, '0');
|
||||
@@ -116,7 +116,7 @@ var DynamicTable = new Class({
|
||||
el.setStyle('border-right-color', '');
|
||||
el.setStyle('border-right-width', '');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var mouseMoveFn = function (e) {
|
||||
var brect = e.target.getBoundingClientRect();
|
||||
@@ -250,7 +250,7 @@ var DynamicTable = new Class({
|
||||
onDrag : onDrag,
|
||||
onComplete : onComplete,
|
||||
onCancel : onCancel
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -331,7 +331,7 @@ var DynamicTable = new Class({
|
||||
column['width'] = getLocalStorageItem('column_' + name + '_width_' + this.dynamicTableDivId, defaultWidth);
|
||||
column['dataProperties'] = [name];
|
||||
column['getRowValue'] = function (row, pos) {
|
||||
if (pos == undefined)
|
||||
if (pos === undefined)
|
||||
pos = 0;
|
||||
return row['full_data'][this.dataProperties[pos]];
|
||||
};
|
||||
@@ -429,8 +429,8 @@ var DynamicTable = new Class({
|
||||
else {
|
||||
ths[pos].addClass('invisible');
|
||||
fths[pos].addClass('invisible');
|
||||
for (var i = 0; i < trs.length; i++)
|
||||
trs[i].getElements('td')[pos].addClass('invisible');
|
||||
for (var j = 0; j < trs.length; j++)
|
||||
trs[j].getElements('td')[pos].addClass('invisible');
|
||||
}
|
||||
if (this.columns[pos].onResize !== null)
|
||||
{
|
||||
@@ -527,7 +527,7 @@ var DynamicTable = new Class({
|
||||
},
|
||||
|
||||
getFilteredAndSortedRows : function () {
|
||||
var filteredRows = new Array();
|
||||
var filteredRows = [];
|
||||
|
||||
var rows = this.rows.getValues();
|
||||
|
||||
@@ -557,7 +557,7 @@ var DynamicTable = new Class({
|
||||
},
|
||||
|
||||
updateTable : function (fullUpdate) {
|
||||
if (fullUpdate == undefined)
|
||||
if (fullUpdate === undefined)
|
||||
fullUpdate = false;
|
||||
|
||||
var rows = this.getFilteredAndSortedRows();
|
||||
@@ -573,7 +573,7 @@ var DynamicTable = new Class({
|
||||
for (var rowPos = 0; rowPos < rows.length; rowPos++) {
|
||||
var rowId = rows[rowPos]['rowId'];
|
||||
tr_found = false;
|
||||
for (j = rowPos; j < trs.length; j++)
|
||||
for (var j = rowPos; j < trs.length; j++)
|
||||
if (trs[j]['rowId'] == rowId) {
|
||||
tr_found = true;
|
||||
if (rowPos == j)
|
||||
@@ -635,7 +635,7 @@ var DynamicTable = new Class({
|
||||
tr.addClass('selected');
|
||||
}
|
||||
else
|
||||
tr.removeClass('selected')
|
||||
tr.removeClass('selected');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -648,9 +648,9 @@ var DynamicTable = new Class({
|
||||
|
||||
this.setupTr(tr);
|
||||
|
||||
for (var j = 0 ; j < this.columns.length; j++) {
|
||||
for (var k = 0 ; k < this.columns.length; k++) {
|
||||
var td = new Element('td');
|
||||
if ((this.columns[j].visible == '0') || this.columns[j].force_hide)
|
||||
if ((this.columns[k].visible == '0') || this.columns[k].force_hide)
|
||||
td.addClass('invisible');
|
||||
td.injectInside(tr);
|
||||
}
|
||||
@@ -698,7 +698,7 @@ var DynamicTable = new Class({
|
||||
removeRow : function (rowId) {
|
||||
this.selectedRows.erase(rowId);
|
||||
var tr = this.getTrByRowId(rowId);
|
||||
if (tr != null) {
|
||||
if (tr !== null) {
|
||||
tr.dispose();
|
||||
this.rows.erase(rowId);
|
||||
return true;
|
||||
@@ -734,6 +734,7 @@ var TorrentsTable = new Class({
|
||||
this.newColumn('name', '', 'QBT_TR(Name)QBT_TR[CONTEXT=TorrentModel]', 200, true);
|
||||
this.newColumn('size', '', 'QBT_TR(Size)QBT_TR[CONTEXT=TorrentModel]', 100, true);
|
||||
this.newColumn('progress', '', 'QBT_TR(Done)QBT_TR[CONTEXT=TorrentModel]', 85, true);
|
||||
this.newColumn('status', '', 'QBT_TR(Status)QBT_TR[CONTEXT=TorrentModel]', 100, true);
|
||||
this.newColumn('num_seeds', '', 'QBT_TR(Seeds)QBT_TR[CONTEXT=TorrentModel]', 100, true);
|
||||
this.newColumn('num_leechs', '', 'QBT_TR(Peers)QBT_TR[CONTEXT=TorrentModel]', 100, true);
|
||||
this.newColumn('dlspeed', '', 'QBT_TR(Down Speed)QBT_TR[CONTEXT=TorrentModel]', 100, true);
|
||||
@@ -771,26 +772,25 @@ var TorrentsTable = new Class({
|
||||
initColumnsFunctions : function () {
|
||||
|
||||
// state_icon
|
||||
|
||||
this.columns['state_icon'].updateTd = function (td, row) {
|
||||
var state = this.getRowValue(row);
|
||||
|
||||
if (state == "forcedDL" || state == "metaDL")
|
||||
if ((state === "forcedDL") || (state === "metaDL"))
|
||||
state = "downloading";
|
||||
else if (state == "allocating")
|
||||
else if (state === "allocating")
|
||||
state = "stalledDL";
|
||||
else if (state == "forcedUP")
|
||||
else if (state === "forcedUP")
|
||||
state = "uploading";
|
||||
else if (state == "pausedDL")
|
||||
else if (state === "pausedDL")
|
||||
state = "paused";
|
||||
else if (state == "pausedUP")
|
||||
else if (state === "pausedUP")
|
||||
state = "completed";
|
||||
else if (state == "queuedDL" || state == "queuedUP")
|
||||
else if ((state === "queuedDL") || (state === "queuedUP"))
|
||||
state = "queued";
|
||||
else if (state == "checkingDL" || state == "checkingUP" ||
|
||||
state == "queuedForChecking" || state == "checkingResumeData")
|
||||
else if ((state === "checkingDL") || (state === "checkingUP") ||
|
||||
(state === "queuedForChecking") || (state === "checkingResumeData"))
|
||||
state = "checking";
|
||||
else if (state == "unknown" || state == "error" || state == "missingFiles")
|
||||
else if ((state === "unknown") || (state === "error") || (state === "missingFiles"))
|
||||
state = "error";
|
||||
|
||||
var img_path = 'images/skin/' + state + '.png';
|
||||
@@ -803,12 +803,37 @@ var TorrentsTable = new Class({
|
||||
else
|
||||
td.adopt(new Element('img', {
|
||||
'src' : img_path,
|
||||
'class' : 'statusIcon'
|
||||
'class' : 'stateIcon'
|
||||
}));
|
||||
};
|
||||
|
||||
// priority
|
||||
// status
|
||||
this.columns['status'].updateTd = function (td, row) {
|
||||
var status = this.getRowValue(row);
|
||||
if (!status) return;
|
||||
|
||||
if ((status === "downloading") || (status === "forcedDL") || (status === "metaDL"))
|
||||
status = "Downloading";
|
||||
else if ((status === "stalledDL") || (status === "stalledUP") || (status === "allocating"))
|
||||
status = "Stalled";
|
||||
else if ((status === "uploading") || (status === "forcedUP"))
|
||||
status = "Uploading";
|
||||
else if (status === "pausedDL")
|
||||
status = "Paused";
|
||||
else if (status === "pausedUP")
|
||||
status = "Completed";
|
||||
else if ((status === "queuedDL") || (status === "queuedUP"))
|
||||
status = "Queued";
|
||||
else if ((status === "checkingDL") || (status === "checkingUP") ||
|
||||
(status === "queuedForChecking") || (status === "checkingResumeData"))
|
||||
status = "Checking";
|
||||
else if ((status === "unknown") || (status === "error") || (status === "missingFiles"))
|
||||
status = "Error";
|
||||
|
||||
td.set('html', status);
|
||||
};
|
||||
|
||||
// priority
|
||||
this.columns['priority'].updateTd = function (td, row) {
|
||||
var priority = this.getRowValue(row);
|
||||
td.set('html', priority < 1 ? '*' : priority);
|
||||
@@ -829,21 +854,18 @@ var TorrentsTable = new Class({
|
||||
};
|
||||
|
||||
// name, category
|
||||
|
||||
this.columns['name'].updateTd = function (td, row) {
|
||||
td.set('html', escapeHtml(this.getRowValue(row)));
|
||||
};
|
||||
this.columns['category'].updateTd = this.columns['name'].updateTd;
|
||||
|
||||
// size
|
||||
|
||||
this.columns['size'].updateTd = function (td, row) {
|
||||
var size = this.getRowValue(row);
|
||||
td.set('html', friendlyUnit(size, false));
|
||||
};
|
||||
|
||||
// progress
|
||||
|
||||
this.columns['progress'].updateTd = function (td, row) {
|
||||
var progress = this.getRowValue(row);
|
||||
var progressFormated = (progress * 100).round(1);
|
||||
@@ -883,7 +905,6 @@ var TorrentsTable = new Class({
|
||||
}.bind(this);
|
||||
|
||||
// num_seeds
|
||||
|
||||
this.columns['num_seeds'].updateTd = function (td, row) {
|
||||
var num_seeds = this.getRowValue(row, 0);
|
||||
var num_complete = this.getRowValue(row, 1);
|
||||
@@ -911,30 +932,25 @@ var TorrentsTable = new Class({
|
||||
};
|
||||
|
||||
// num_leechs
|
||||
|
||||
this.columns['num_leechs'].updateTd = this.columns['num_seeds'].updateTd;
|
||||
this.columns['num_leechs'].compareRows = this.columns['num_seeds'].compareRows;
|
||||
|
||||
// dlspeed
|
||||
|
||||
this.columns['dlspeed'].updateTd = function (td, row) {
|
||||
var speed = this.getRowValue(row);
|
||||
td.set('html', friendlyUnit(speed, true));
|
||||
};
|
||||
|
||||
// upspeed
|
||||
|
||||
this.columns['upspeed'].updateTd = this.columns['dlspeed'].updateTd;
|
||||
|
||||
// eta
|
||||
|
||||
this.columns['eta'].updateTd = function (td, row) {
|
||||
var eta = this.getRowValue(row);
|
||||
td.set('html', friendlyDuration(eta, true));
|
||||
};
|
||||
|
||||
// ratio
|
||||
|
||||
this.columns['ratio'].updateTd = function (td, row) {
|
||||
var ratio = this.getRowValue(row);
|
||||
var html = null;
|
||||
@@ -946,14 +962,12 @@ var TorrentsTable = new Class({
|
||||
};
|
||||
|
||||
// added on
|
||||
|
||||
this.columns['added_on'].updateTd = function (td, row) {
|
||||
var date = new Date(this.getRowValue(row) * 1000).toLocaleString();
|
||||
td.set('html', date);
|
||||
};
|
||||
|
||||
// completion_on
|
||||
|
||||
this.columns['completion_on'].updateTd = function (td, row) {
|
||||
var val = this.getRowValue(row);
|
||||
if (val === 0xffffffff || val < 0)
|
||||
@@ -965,15 +979,13 @@ var TorrentsTable = new Class({
|
||||
};
|
||||
|
||||
// seen_complete
|
||||
|
||||
this.columns['seen_complete'].updateTd = this.columns['completion_on'].updateTd;
|
||||
|
||||
// dl_limit, up_limit
|
||||
|
||||
this.columns['dl_limit'].updateTd = function (td, row) {
|
||||
var speed = this.getRowValue(row);
|
||||
if (speed === 0)
|
||||
td.set('html', '∞')
|
||||
td.set('html', '∞');
|
||||
else
|
||||
td.set('html', friendlyUnit(speed, true));
|
||||
};
|
||||
@@ -981,7 +993,6 @@ var TorrentsTable = new Class({
|
||||
this.columns['up_limit'].updateTd = this.columns['dl_limit'].updateTd;
|
||||
|
||||
// downloaded, uploaded, downloaded_session, uploaded_session, amount_left, completed, total_size
|
||||
|
||||
this.columns['downloaded'].updateTd = this.columns['size'].updateTd;
|
||||
this.columns['uploaded'].updateTd = this.columns['size'].updateTd;
|
||||
this.columns['downloaded_session'].updateTd = this.columns['size'].updateTd;
|
||||
@@ -992,16 +1003,13 @@ var TorrentsTable = new Class({
|
||||
this.columns['total_size'].updateTd = this.columns['size'].updateTd;
|
||||
|
||||
// save_path, tracker
|
||||
|
||||
this.columns['save_path'].updateTd = this.columns['name'].updateTd;
|
||||
this.columns['tracker'].updateTd = this.columns['name'].updateTd;
|
||||
|
||||
// ratio_limit
|
||||
|
||||
this.columns['ratio_limit'].updateTd = this.columns['ratio'].updateTd;
|
||||
|
||||
// last_activity
|
||||
|
||||
this.columns['last_activity'].updateTd = function (td, row) {
|
||||
var val = this.getRowValue(row);
|
||||
if (val < 1)
|
||||
@@ -1039,9 +1047,10 @@ var TorrentsTable = new Class({
|
||||
break;
|
||||
case 'inactive':
|
||||
inactive = true;
|
||||
// fallthrough
|
||||
case 'active':
|
||||
if (state == 'stalledDL')
|
||||
r = (row['full_data'].upspeed > 0)
|
||||
r = (row['full_data'].upspeed > 0);
|
||||
else
|
||||
r = state == 'metaDL' || state == 'downloading' || state == 'forcedDL' || state == 'uploading' || state == 'forcedUP';
|
||||
if (r == inactive)
|
||||
@@ -1086,7 +1095,7 @@ var TorrentsTable = new Class({
|
||||
},
|
||||
|
||||
getFilteredAndSortedRows : function () {
|
||||
var filteredRows = new Array();
|
||||
var filteredRows = [];
|
||||
|
||||
var rows = this.rows.getValues();
|
||||
|
||||
@@ -1218,7 +1227,7 @@ var TorrentPeersTable = new Class({
|
||||
|
||||
this.columns['dl_speed'].updateTd = function (td, row) {
|
||||
var speed = this.getRowValue(row);
|
||||
if (speed == 0)
|
||||
if (speed === 0)
|
||||
td.set('html', '');
|
||||
else
|
||||
td.set('html', friendlyUnit(speed, true));
|
||||
|
||||
@@ -16,8 +16,8 @@ function friendlyUnit(value, isSpeed) {
|
||||
return "QBT_TR(Unknown)QBT_TR[CONTEXT=misc]";
|
||||
|
||||
var i = 0;
|
||||
while (value >= 1024. && i < 6) {
|
||||
value /= 1024.;
|
||||
while (value >= 1024.0 && i < 6) {
|
||||
value /= 1024.0;
|
||||
++i;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ function friendlyUnit(value, isSpeed) {
|
||||
}
|
||||
|
||||
var ret;
|
||||
if (i == 0)
|
||||
if (i === 0)
|
||||
ret = value + " " + units[i];
|
||||
else
|
||||
ret = (Math.floor(10 * value) / 10).toFixed(friendlyUnitPrecision(i)) //Don't round up
|
||||
@@ -46,7 +46,7 @@ function friendlyDuration(seconds) {
|
||||
var MAX_ETA = 8640000;
|
||||
if (seconds < 0 || seconds >= MAX_ETA)
|
||||
return "∞";
|
||||
if (seconds == 0)
|
||||
if (seconds === 0)
|
||||
return "0";
|
||||
if (seconds < 60)
|
||||
return "QBT_TR(< 1m)QBT_TR[CONTEXT=misc]";
|
||||
@@ -56,11 +56,11 @@ function friendlyDuration(seconds) {
|
||||
var hours = minutes / 60;
|
||||
minutes = minutes % 60;
|
||||
if (hours < 24)
|
||||
return "QBT_TR(%1h %2m)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(hours)).replace("%2", parseInt(minutes))
|
||||
return "QBT_TR(%1h %2m)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(hours)).replace("%2", parseInt(minutes));
|
||||
var days = hours / 24;
|
||||
hours = hours % 24;
|
||||
if (days < 100)
|
||||
return "QBT_TR(%1d %2h)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(days)).replace("%2", parseInt(hours))
|
||||
return "QBT_TR(%1d %2h)QBT_TR[CONTEXT=misc]".replace("%1", parseInt(days)).replace("%2", parseInt(hours));
|
||||
return "∞";
|
||||
}
|
||||
|
||||
@@ -96,11 +96,11 @@ if (!Date.prototype.toISOString) {
|
||||
*/
|
||||
function parseHtmlLinks(text) {
|
||||
var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
|
||||
return text.replace(exp,"<a target='_blank' href='$1'>$1</a>");
|
||||
return text.replace(exp,"<a target='_blank' href='$1'>$1</a>");
|
||||
}
|
||||
|
||||
function escapeHtml(str) {
|
||||
var div = document.createElement('div');
|
||||
div.appendChild(document.createTextNode(str));
|
||||
return div.innerHTML;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ if (typeof localStorage == 'undefined') {
|
||||
duration: 365 * 10
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function getLocalStorageItem(name, defaultVal) {
|
||||
@@ -116,7 +116,7 @@ initializeWindows = function() {
|
||||
width: 424,
|
||||
height: 80
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
uploadLimitFN = function() {
|
||||
var h = torrentsTable.selectedRowsIds();
|
||||
@@ -210,7 +210,7 @@ initializeWindows = function() {
|
||||
width: 424,
|
||||
height: 80
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
StatisticsLinkFN = function() {
|
||||
new MochaUI.Window({
|
||||
@@ -224,8 +224,8 @@ initializeWindows = function() {
|
||||
width: 275,
|
||||
height: 370,
|
||||
padding: 10
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
downloadLimitFN = function() {
|
||||
var h = torrentsTable.selectedRowsIds();
|
||||
@@ -340,8 +340,8 @@ initializeWindows = function() {
|
||||
|
||||
torrentSetCategoryFN = function (categoryHash) {
|
||||
var categoryName = '';
|
||||
if (categoryHash != 0)
|
||||
var categoryName = category_list[categoryHash].name;
|
||||
if (categoryHash !== 0)
|
||||
categoryName = category_list[categoryHash].name;
|
||||
var h = torrentsTable.selectedRowsIds();
|
||||
if (h.length) {
|
||||
new Request({
|
||||
@@ -387,7 +387,7 @@ initializeWindows = function() {
|
||||
deleteUnusedCategoriesFN = function () {
|
||||
var categories = [];
|
||||
for (var hash in category_list) {
|
||||
if (torrentsTable.getFilteredTorrentsNumber('all', hash) == 0)
|
||||
if (torrentsTable.getFilteredTorrentsNumber('all', hash) === 0)
|
||||
categories.push(category_list[hash].name);
|
||||
}
|
||||
new Request({
|
||||
@@ -499,7 +499,7 @@ initializeWindows = function() {
|
||||
}).send();
|
||||
updateMainData();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
addClickEvent('about', function(e) {
|
||||
new Event(e).stop();
|
||||
@@ -544,4 +544,4 @@ initializeWindows = function() {
|
||||
new Event(e).stop();
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@ Script: Parametrics.js
|
||||
Initializes the GUI property sliders.
|
||||
|
||||
Copyright:
|
||||
Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.
|
||||
Copyright (c) 2007-2008 Greg Houston, <http://greghoustondesign.com/>.
|
||||
|
||||
License:
|
||||
MIT-style license.
|
||||
@@ -28,7 +28,7 @@ MochaUI.extend({
|
||||
if (data) {
|
||||
var tmp = data.toInt();
|
||||
if (tmp > 0) {
|
||||
maximum = tmp / 1024.
|
||||
maximum = tmp / 1024.0;
|
||||
}
|
||||
else {
|
||||
if (hashes[0] == "global")
|
||||
@@ -59,7 +59,7 @@ MochaUI.extend({
|
||||
}.bind(this)
|
||||
});
|
||||
// Set default value
|
||||
if (up_limit == 0) {
|
||||
if (up_limit === 0) {
|
||||
$('uplimitUpdatevalue').value = '∞';
|
||||
$('upLimitUnit').style.visibility = "hidden";
|
||||
}
|
||||
@@ -88,7 +88,7 @@ MochaUI.extend({
|
||||
var mochaSlide = new Slider($('uplimitSliderarea'), $('uplimitSliderknob'), {
|
||||
steps: maximum,
|
||||
offset: 0,
|
||||
initialStep: (up_limit / 1024.).round(),
|
||||
initialStep: (up_limit / 1024.0).round(),
|
||||
onChange: function(pos) {
|
||||
if (pos > 0) {
|
||||
$('uplimitUpdatevalue').value = pos;
|
||||
@@ -101,12 +101,12 @@ MochaUI.extend({
|
||||
}.bind(this)
|
||||
});
|
||||
// Set default value
|
||||
if (up_limit == 0) {
|
||||
if (up_limit === 0) {
|
||||
$('uplimitUpdatevalue').value = '∞';
|
||||
$('upLimitUnit').style.visibility = "hidden";
|
||||
}
|
||||
else {
|
||||
$('uplimitUpdatevalue').value = (up_limit / 1024.).round();
|
||||
$('uplimitUpdatevalue').value = (up_limit / 1024.0).round();
|
||||
$('upLimitUnit').style.visibility = "visible";
|
||||
}
|
||||
}
|
||||
@@ -132,7 +132,7 @@ MochaUI.extend({
|
||||
if (data) {
|
||||
var tmp = data.toInt();
|
||||
if (tmp > 0) {
|
||||
maximum = tmp / 1024.
|
||||
maximum = tmp / 1024.0;
|
||||
}
|
||||
else {
|
||||
if (hashes[0] == "global")
|
||||
@@ -163,7 +163,7 @@ MochaUI.extend({
|
||||
}.bind(this)
|
||||
});
|
||||
// Set default value
|
||||
if (dl_limit == 0) {
|
||||
if (dl_limit === 0) {
|
||||
$('dllimitUpdatevalue').value = '∞';
|
||||
$('dlLimitUnit').style.visibility = "hidden";
|
||||
}
|
||||
@@ -192,7 +192,7 @@ MochaUI.extend({
|
||||
var mochaSlide = new Slider($('dllimitSliderarea'), $('dllimitSliderknob'), {
|
||||
steps: maximum,
|
||||
offset: 0,
|
||||
initialStep: (dl_limit / 1024.).round(),
|
||||
initialStep: (dl_limit / 1024.0).round(),
|
||||
onChange: function(pos) {
|
||||
if (pos > 0) {
|
||||
$('dllimitUpdatevalue').value = pos;
|
||||
@@ -205,12 +205,12 @@ MochaUI.extend({
|
||||
}.bind(this)
|
||||
});
|
||||
// Set default value
|
||||
if (dl_limit == 0) {
|
||||
if (dl_limit === 0) {
|
||||
$('dllimitUpdatevalue').value = '∞';
|
||||
$('dlLimitUnit').style.visibility = "hidden";
|
||||
}
|
||||
else {
|
||||
$('dllimitUpdatevalue').value = (dl_limit / 1024.).round();
|
||||
$('dllimitUpdatevalue').value = (dl_limit / 1024.0).round();
|
||||
$('dlLimitUnit').style.visibility = "visible";
|
||||
}
|
||||
}
|
||||
@@ -221,4 +221,4 @@ MochaUI.extend({
|
||||
}).send();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -40,7 +40,7 @@ var setCBState = function(state) {
|
||||
$("tristate_cb").checked = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var switchCBState = function() {
|
||||
// Uncheck
|
||||
@@ -69,7 +69,7 @@ var switchCBState = function() {
|
||||
item.set("checked", "checked");
|
||||
setFilePriority(index, 1);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var allCBChecked = function() {
|
||||
var CBs = $$('input.DownloadedCB');
|
||||
@@ -79,7 +79,7 @@ var allCBChecked = function() {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
var allCBUnchecked = function() {
|
||||
var CBs = $$('input.DownloadedCB');
|
||||
@@ -89,10 +89,10 @@ var allCBUnchecked = function() {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
var setFilePriority = function(id, priority) {
|
||||
if (current_hash == "") return;
|
||||
if (current_hash === "") return;
|
||||
new Request({
|
||||
url: 'command/setFilePrio',
|
||||
method: 'post',
|
||||
@@ -110,7 +110,7 @@ var setFilePriority = function(id, priority) {
|
||||
else {
|
||||
$('comboPrio' + id).addClass("invisible");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var createDownloadedCB = function(id, downloaded) {
|
||||
var CB = new Element('input');
|
||||
@@ -137,7 +137,7 @@ var createDownloadedCB = function(id, downloaded) {
|
||||
}
|
||||
});
|
||||
return CB;
|
||||
}
|
||||
};
|
||||
|
||||
var createPriorityCombo = function(id, selected_prio) {
|
||||
var select = new Element('select');
|
||||
@@ -147,19 +147,19 @@ var createPriorityCombo = function(id, selected_prio) {
|
||||
setFilePriority(id, new_prio);
|
||||
});
|
||||
var opt = new Element("option");
|
||||
opt.set('value', '1')
|
||||
opt.set('value', '1');
|
||||
opt.set('html', "QBT_TR(Normal)QBT_TR[CONTEXT=PropListDelegate]");
|
||||
if (selected_prio <= 1)
|
||||
opt.setAttribute('selected', '');
|
||||
opt.injectInside(select);
|
||||
opt = new Element("option");
|
||||
opt.set('value', '2')
|
||||
opt.set('value', '2');
|
||||
opt.set('html', "QBT_TR(High)QBT_TR[CONTEXT=PropListDelegate]");
|
||||
if (selected_prio == 2)
|
||||
opt.setAttribute('selected', '');
|
||||
opt.injectInside(select);
|
||||
opt = new Element("option");
|
||||
opt.set('value', '7')
|
||||
opt.set('value', '7');
|
||||
opt.set('html', "QBT_TR(Maximum)QBT_TR[CONTEXT=PropListDelegate]");
|
||||
if (selected_prio == 7)
|
||||
opt.setAttribute('selected', '');
|
||||
@@ -172,7 +172,7 @@ var createPriorityCombo = function(id, selected_prio) {
|
||||
}
|
||||
select.addClass("combo_priority");
|
||||
return select;
|
||||
}
|
||||
};
|
||||
|
||||
var filesDynTable = new Class({
|
||||
|
||||
@@ -231,8 +231,8 @@ var filesDynTable = new Class({
|
||||
|
||||
insertRow: function(id, row) {
|
||||
if (this.rows.has(id)) {
|
||||
var tr = this.rows.get(id);
|
||||
this.updateRow(tr, row, id);
|
||||
var tableRow = this.rows.get(id);
|
||||
this.updateRow(tableRow, row, id);
|
||||
return;
|
||||
}
|
||||
//this.removeRow(id);
|
||||
@@ -279,7 +279,7 @@ var loadTorrentFilesData = function() {
|
||||
return;
|
||||
}
|
||||
var new_hash = torrentsTable.getCurrentTorrentHash();
|
||||
if (new_hash == "") {
|
||||
if (new_hash === "") {
|
||||
fTable.removeAllRows();
|
||||
clearTimeout(loadTorrentFilesDataTimer);
|
||||
loadTorrentFilesDataTimer = loadTorrentFilesData.delay(5000);
|
||||
@@ -305,17 +305,17 @@ var loadTorrentFilesData = function() {
|
||||
// Update Trackers data
|
||||
var i = 0;
|
||||
files.each(function(file) {
|
||||
if (i == 0) {
|
||||
if (i === 0) {
|
||||
is_seed = file.is_seed;
|
||||
}
|
||||
var row = new Array();
|
||||
var row = [];
|
||||
row.length = 4;
|
||||
row[0] = file.priority;
|
||||
row[1] = escapeHtml(file.name);
|
||||
row[2] = friendlyUnit(file.size, false);
|
||||
row[3] = (file.progress * 100).round(1);
|
||||
if (row[3] == 100.0 && file.progress < 1.0)
|
||||
row[3] = 99.9
|
||||
row[3] = 99.9;
|
||||
row[4] = file.priority;
|
||||
fTable.insertRow(i, row);
|
||||
i++;
|
||||
@@ -340,12 +340,12 @@ var loadTorrentFilesData = function() {
|
||||
loadTorrentFilesDataTimer = loadTorrentFilesData.delay(5000);
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
};
|
||||
|
||||
var updateTorrentFilesData = function() {
|
||||
clearTimeout(loadTorrentFilesDataTimer);
|
||||
loadTorrentFilesData();
|
||||
}
|
||||
};
|
||||
|
||||
fTable = new filesDynTable();
|
||||
fTable.setup($('filesTable'));
|
||||
|
||||
@@ -23,7 +23,7 @@ var clearData = function() {
|
||||
$('torrent_hash').set('html', '');
|
||||
$('save_path').set('html', '');
|
||||
$('comment').set('html', '');
|
||||
}
|
||||
};
|
||||
|
||||
var loadTorrentDataTimer;
|
||||
var loadTorrentData = function() {
|
||||
@@ -33,7 +33,7 @@ var loadTorrentData = function() {
|
||||
return;
|
||||
}
|
||||
var current_hash = torrentsTable.getCurrentTorrentHash();
|
||||
if (current_hash == "") {
|
||||
if (current_hash === "") {
|
||||
clearData();
|
||||
clearTimeout(loadTorrentDataTimer);
|
||||
loadTorrentDataTimer = loadTorrentData.delay(5000);
|
||||
@@ -59,26 +59,26 @@ var loadTorrentData = function() {
|
||||
if (data.seeding_time > 0)
|
||||
temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]"
|
||||
.replace("%1", friendlyDuration(data.time_elapsed))
|
||||
.replace("%2", friendlyDuration(data.seeding_time))
|
||||
.replace("%2", friendlyDuration(data.seeding_time));
|
||||
else
|
||||
temp = friendlyDuration(data.time_elapsed)
|
||||
temp = friendlyDuration(data.time_elapsed);
|
||||
$('time_elapsed').set('html', temp);
|
||||
|
||||
$('eta').set('html', friendlyDuration(data.eta));
|
||||
|
||||
temp = "QBT_TR(%1 (%2 max))QBT_TR[CONTEXT=PropertiesWidget]"
|
||||
.replace("%1", data.nb_connections)
|
||||
.replace("%2", data.nb_connections_limit < 0 ? "∞" : data.nb_connections_limit)
|
||||
.replace("%2", data.nb_connections_limit < 0 ? "∞" : data.nb_connections_limit);
|
||||
$('nb_connections').set('html', temp);
|
||||
|
||||
temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]"
|
||||
.replace("%1", friendlyUnit(data.total_downloaded))
|
||||
.replace("%2", friendlyUnit(data.total_downloaded_session))
|
||||
.replace("%2", friendlyUnit(data.total_downloaded_session));
|
||||
$('total_downloaded').set('html', temp);
|
||||
|
||||
temp = "QBT_TR(%1 (%2 this session))QBT_TR[CONTEXT=PropertiesWidget]"
|
||||
.replace("%1", friendlyUnit(data.total_uploaded))
|
||||
.replace("%2", friendlyUnit(data.total_uploaded_session))
|
||||
.replace("%2", friendlyUnit(data.total_uploaded_session));
|
||||
$('total_uploaded').set('html', temp);
|
||||
|
||||
temp = "QBT_TR(%1 (%2 avg.))QBT_TR[CONTEXT=PropertiesWidget]"
|
||||
@@ -161,9 +161,9 @@ var loadTorrentData = function() {
|
||||
loadTorrentDataTimer = loadTorrentData.delay(5000);
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
};
|
||||
|
||||
var updateTorrentData = function() {
|
||||
clearTimeout(loadTorrentDataTimer);
|
||||
loadTorrentData();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -34,8 +34,8 @@ var trackersDynTable = new Class({
|
||||
insertRow: function(row) {
|
||||
var url = row[0];
|
||||
if (this.rows.has(url)) {
|
||||
var tr = this.rows.get(url);
|
||||
this.updateRow(tr, row);
|
||||
var tableRow = this.rows.get(url);
|
||||
this.updateRow(tableRow, row);
|
||||
return;
|
||||
}
|
||||
//this.removeRow(id);
|
||||
@@ -60,7 +60,7 @@ var loadTrackersData = function() {
|
||||
return;
|
||||
}
|
||||
var new_hash = torrentsTable.getCurrentTorrentHash();
|
||||
if (new_hash == "") {
|
||||
if (new_hash === "") {
|
||||
tTable.removeAllRows();
|
||||
clearTimeout(loadTrackersDataTimer);
|
||||
loadTrackersDataTimer = loadTrackersData.delay(10000);
|
||||
@@ -85,7 +85,7 @@ var loadTrackersData = function() {
|
||||
if (trackers) {
|
||||
// Update Trackers data
|
||||
trackers.each(function(tracker) {
|
||||
var row = new Array();
|
||||
var row = [];
|
||||
row.length = 4;
|
||||
row[0] = escapeHtml(tracker.url);
|
||||
row[1] = tracker.status;
|
||||
@@ -101,19 +101,19 @@ var loadTrackersData = function() {
|
||||
loadTrackersDataTimer = loadTrackersData.delay(10000);
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
};
|
||||
|
||||
var updateTrackersData = function() {
|
||||
clearTimeout(loadTrackersDataTimer);
|
||||
loadTrackersData();
|
||||
}
|
||||
};
|
||||
|
||||
tTable = new trackersDynTable();
|
||||
tTable.setup($('trackersTable'));
|
||||
|
||||
// Add trackers code
|
||||
$('addTrackersPlus').addEvent('click', function addTrackerDlg() {
|
||||
if (current_hash.length == 0) return;
|
||||
if (current_hash.length === 0) return;
|
||||
new MochaUI.Window({
|
||||
id: 'trackersPage',
|
||||
title: "QBT_TR(Trackers addition dialog)QBT_TR[CONTEXT=TrackersAdditionDlg]",
|
||||
|
||||
@@ -34,8 +34,8 @@ var webseedsDynTable = new Class({
|
||||
insertRow: function(row) {
|
||||
var url = row[0];
|
||||
if (this.rows.has(url)) {
|
||||
var tr = this.rows.get(url);
|
||||
this.updateRow(tr, row);
|
||||
var tableRow = this.rows.get(url);
|
||||
this.updateRow(tableRow, row);
|
||||
return;
|
||||
}
|
||||
//this.removeRow(id);
|
||||
@@ -60,7 +60,7 @@ var loadWebSeedsData = function() {
|
||||
return;
|
||||
}
|
||||
var new_hash = torrentsTable.getCurrentTorrentHash();
|
||||
if (new_hash == "") {
|
||||
if (new_hash === "") {
|
||||
wsTable.removeAllRows();
|
||||
clearTimeout(loadWebSeedsDataTimer);
|
||||
loadWebSeedsDataTimer = loadWebSeedsData.delay(10000);
|
||||
@@ -85,7 +85,7 @@ var loadWebSeedsData = function() {
|
||||
if (webseeds) {
|
||||
// Update WebSeeds data
|
||||
webseeds.each(function(webseed) {
|
||||
var row = new Array();
|
||||
var row = [];
|
||||
row.length = 1;
|
||||
row[0] = webseed.url;
|
||||
wsTable.insertRow(row);
|
||||
@@ -98,12 +98,12 @@ var loadWebSeedsData = function() {
|
||||
loadWebSeedsDataTimer = loadWebSeedsData.delay(10000);
|
||||
}
|
||||
}).send();
|
||||
}
|
||||
};
|
||||
|
||||
var updateWebSeedsData = function() {
|
||||
clearTimeout(loadWebSeedsDataTimer);
|
||||
loadWebSeedsData();
|
||||
}
|
||||
};
|
||||
|
||||
wsTable = new webseedsDynTable();
|
||||
wsTable.setup($('webseedsTable'));
|
||||
|
||||
@@ -32,7 +32,7 @@ DIST_PATH = ../dist/unix
|
||||
|
||||
# Systemd Service file
|
||||
nogui:systemd {
|
||||
systemdService.files = $$DIST_PATH/systemd/qbittorrent-nox.service
|
||||
systemdService.files = $$DIST_PATH/systemd/qbittorrent-nox@.service
|
||||
systemdService.path = $$PREFIX/lib/systemd/system/
|
||||
INSTALLS += systemdService
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ PROJECT_NAME = qbittorrent
|
||||
# Define version numbers here
|
||||
VER_MAJOR = 3
|
||||
VER_MINOR = 3
|
||||
VER_BUGFIX = 13
|
||||
VER_BUGFIX = 16
|
||||
VER_BUILD = 0
|
||||
VER_STATUS = # Should be empty for stable releases!
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@ strace_win {
|
||||
}
|
||||
|
||||
CONFIG -= embed_manifest_exe
|
||||
QMAKE_LFLAGS += "/OPT:REF /OPT:ICF /MANIFEST:EMBED /MANIFESTINPUT:$$quote($${PWD}/src/qbittorrent.exe.manifest)"
|
||||
QMAKE_LFLAGS += "/MANIFEST:EMBED /MANIFESTINPUT:$$quote($${PWD}/src/qbittorrent.exe.manifest) /STACK:0x800000"
|
||||
QMAKE_LFLAGS_RELEASE += "/OPT:REF /OPT:ICF"
|
||||
|
||||
RC_FILE = qbittorrent.rc
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ LIBS += $$quote(-LC:/qBittorrent/openssl/lib)
|
||||
# BOOST DEFINES
|
||||
DEFINES += BOOST_ALL_NO_LIB
|
||||
DEFINES += BOOST_ASIO_HASH_MAP_BUCKETS=1021
|
||||
# Disable this if building against libtorrent 1.1.x (RC_1_1)
|
||||
DEFINES += BOOST_ASIO_SEPARATE_COMPILATION
|
||||
# After 1.55 some Windows users reported regular UI freezes.
|
||||
# This makes ASIO use the pre-1.56 way of doing things. See issue #2003
|
||||
|
||||
Reference in New Issue
Block a user