Compare commits

...

31 Commits

Author SHA1 Message Date
sledgehammer999
83ae15550d Bump to 3.3.14 2017-07-18 22:52:48 +03:00
sledgehammer999
3783541c30 Update Changelog. 2017-07-18 22:50:18 +03:00
sledgehammer999
cc388fe772 Bump API_VERSION and API_VERSION_MIN to 15. 2017-07-18 22:47:13 +03:00
sledgehammer999
78f2afa239 Fix duplicate variable name in .ui file. 2017-07-18 22:47:02 +03:00
sledgehammer999
245e8e09bb Fix Qt4 compilation. 2017-07-18 16:04:50 +03:00
sledgehammer999
986cff9e66 Fix typo. 2017-07-18 03:33:40 +03:00
Tom Piccirello
73f477072f Add Status column to webui (addresses #6815) (#7032)
* Add Status column to webui (addresses #6815)
2017-07-18 03:22:46 +03:00
Chocobo1
7e9ece2701 Load the domain list at least once on startup.
Fixup of 0532d546d7
2017-07-18 03:22:41 +03:00
Eugene Shalygin
ba8641f1ac Set interface for outgoing traffic.
This sets interface for outgoing traffic to the same as for ingoing
(listetning) with libtorrent 1.1.x.
2017-07-18 03:21:31 +03:00
Chocobo1
76c6041031 Implement HTTP host header filtering
This filtering is required to defend against DNS rebinding attack.
2017-07-18 03:21:26 +03:00
Chocobo1
2ae8472a78 Avoid modifing request headers 2017-07-18 02:53:58 +03:00
Chocobo1
dc9df6d681 Revert back to intended fallthrough
Partial revert a7f4ea8b18
2017-07-18 02:53:57 +03:00
Chocobo1
aed9e8f1b7 Fix value comparison. Closes #7081.
`category` could be 'undefined'.
Fixup of a7f4ea8b18.
2017-07-18 02:53:55 +03:00
sledgehammer999
a94d14acaf Update Travis to use the new macOS packages for qt and libtorrent. 2017-07-18 02:53:37 +03:00
Thomas Piccirello
317689bd5d Fix javascript errors and follow best practices 2017-07-18 02:51:42 +03:00
Thomas Piccirello
1ad66ba791 Skip username/password check for active sessions (closes #6860) 2017-07-18 02:51:34 +03:00
sledgehammer999
b4fb193d4a Fix Qt 5.2 build. 2017-07-03 18:17:27 +03:00
sledgehammer999
ab47559bf2 Switch appveyor to msvc2017. 2017-07-03 18:17:25 +03:00
sledgehammer999
ac87728150 Leave a comment about boost DEFINE and RC_1_1. Issues #7050 #6761. 2017-07-03 18:17:24 +03:00
scootergrisen
1559205114 Added danish translation 2017-07-03 18:17:23 +03:00
Anton-Latukha
54e8b6944e systemd service with user switch.
rm previous systemd unit service

cmake now placing new file 'qbittorrent-nox@.service.in'

systemd service now "Type=simple"
2017-07-03 18:17:22 +03:00
Chocobo1
164e8156db Separate "Release mode" linker options 2017-07-03 18:17:21 +03:00
Chocobo1
c83bb22e80 Raise total stack size on Windows to 8 MB. Closes #7021.
MSVC default was 1 MB.
2017-07-03 18:17:20 +03:00
Andrei Stepanov
166c2a72ac Update russian.nsi 2017-07-03 18:17:19 +03:00
sledgehammer999
6b659804c7 Pad shorter python versions. Closes #6877. 2017-07-03 18:17:18 +03:00
Chocobo1
0831320f17 [WebAPI] Convert all header name constants to lowercase
This save us another transition when some day we implements HTTP/2
(which all headers are in lowercase).
2017-06-26 01:33:17 +03:00
Chocobo1
8d2fb06f65 [WebUI] relax CSRF defense. Closes #6882.
Allow HTTP request which has neither Origin nor Referer header included
2017-06-26 01:33:16 +03:00
Chocobo1
bf6f103142 Fix KEEP_ALIVE_DURATION value
I intended to specify 7 seconds, which should be 7000 milliseconds
2017-06-26 01:33:15 +03:00
thalieht
c4b12b854e Add greek translation for windows installer 2017-06-26 01:33:13 +03:00
Burak Yavuz
de514e29c2 Updated turkish installer 2017-06-26 01:33:12 +03:00
KingLucius
03d020f0f2 Installer Arabic language update 2017-06-26 01:33:05 +03:00
45 changed files with 443 additions and 288 deletions

View File

@@ -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%"

View File

@@ -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+git20172003.8736a59adc.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+git20172003.8736a59adc.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
- |

View File

@@ -1,3 +1,19 @@
* 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)

4
configure vendored
View File

@@ -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

View File

@@ -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
View File

@@ -45,7 +45,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>3.3.13</string>
<string>3.3.14</string>
<key>CFBundleSignature</key>
<string>qBit</string>
<key>CFBundleExecutable</key>

View File

@@ -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)

View File

@@ -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

View 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

View File

@@ -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 بت"
;------------------------------------

View File

@@ -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:"

View File

@@ -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} "Δεν θα καταργηθεί η συσχέτιση με τους μαγνητικούς συνδέσμους. Είναι συσχετισμένοι με το:"

View File

@@ -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-ссылок не сброшены. Уже ассоциированы с:"

View File

@@ -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."
;------------------------------------

View File

@@ -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.14"
!define MUI_FINISHPAGE_RUN
!define MUI_FINISHPAGE_RUN_FUNCTION PageFinishRun

View File

@@ -933,6 +933,7 @@ void Session::configure(libtorrent::settings_pack &settingsPack)
}
}
settingsPack.set_str(libt::settings_pack::outgoing_interfaces, networkInterface().toStdString());
m_listenInterfaceChanged = false;
}

View File

@@ -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";

View File

@@ -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
{

View File

@@ -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

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;

View File

@@ -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());

View File

@@ -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>

View File

@@ -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,45 @@ 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_X_FORWARDED_HOST, 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 +482,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 +492,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();

View File

@@ -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);

View File

@@ -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"))

View File

@@ -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);

View File

@@ -33,7 +33,7 @@
cursor: pointer;
}
#transferList img.statusIcon {
#transferList img.stateIcon {
margin-bottom: -4px;
margin-bottom: -1px;
}

View File

@@ -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]");

View File

@@ -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();
}

View File

@@ -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);
});

View File

@@ -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();

View File

@@ -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));

View File

@@ -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;
};
}

View File

@@ -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();
});
});
}
};

View File

@@ -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();
}
}
});
});

View File

@@ -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'));

View File

@@ -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();
}
};

View File

@@ -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]",

View File

@@ -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'));

View File

@@ -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
}

View File

@@ -4,7 +4,7 @@ PROJECT_NAME = qbittorrent
# Define version numbers here
VER_MAJOR = 3
VER_MINOR = 3
VER_BUGFIX = 13
VER_BUGFIX = 14
VER_BUILD = 0
VER_STATUS = # Should be empty for stable releases!

View File

@@ -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

View File

@@ -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