diff --git a/package/lean/UnblockNeteaseMusic/Makefile b/package/lean/UnblockNeteaseMusic/Makefile
index 6e31863a6e..847d11aff1 100644
--- a/package/lean/UnblockNeteaseMusic/Makefile
+++ b/package/lean/UnblockNeteaseMusic/Makefile
@@ -11,14 +11,14 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=UnblockNeteaseMusic
-PKG_VERSION:=0.20.4
+PKG_VERSION:=0.22.1
PKG_RELEASE:=1
PKG_LICENSE:=MIT
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/nondanee/UnblockNeteaseMusic.git
-PKG_SOURCE_VERSION:=023a97f0e62d322a8d64c59ef3942da7c8a1b546
+PKG_SOURCE_VERSION:=c727245b8de201b91ae859c6ae1412c77ef25cf0
PKG_SOURCE_SUBDIR:=$(PKG_NAME)
PKG_SOURCE:=$(PKG_SOURCE_SUBDIR)-$(PKG_VERSION).tar.gz
diff --git a/package/lean/luci-app-qbittorrent/Makefile b/package/lean/luci-app-qbittorrent/Makefile
index 70f4703b62..343d888466 100644
--- a/package/lean/luci-app-qbittorrent/Makefile
+++ b/package/lean/luci-app-qbittorrent/Makefile
@@ -1,16 +1,15 @@
# Copyright (C) 2019 Openwrt.org
#
-# This is a free software, use it under Apache Licene 2.0 & GNU General Public License v3.0.
+# This is free software, licensed under the Apache License, Version 2.0 .
#
include $(TOPDIR)/rules.mk
-LUCI_TITLE:=qbittorrent-nox for LuCI
-LUCI_DEPENDS:=+qBittorrent
+LUCI_TITLE:=LuCI support for qBittorrent
+LUCI_DEPENDS:=+qBittorrent +python
LUCI_PKGARCH:=all
-PKG_NAME:=luci-app-qbittorrent
PKG_VERSION=1.0
-PKG_RELEASE:=4
+PKG_RELEASE:=18
include $(TOPDIR)/feeds/luci/luci.mk
diff --git a/package/lean/luci-app-qbittorrent/luasrc/controller/qbittorrent.lua b/package/lean/luci-app-qbittorrent/luasrc/controller/qbittorrent.lua
index 5363ac9786..77d58b971c 100644
--- a/package/lean/luci-app-qbittorrent/luasrc/controller/qbittorrent.lua
+++ b/package/lean/luci-app-qbittorrent/luasrc/controller/qbittorrent.lua
@@ -1,4 +1,16 @@
module("luci.controller.qbittorrent",package.seeall)
+
function index()
- entry({"admin","nas","qbittorrent"},cbi("qbittorrent"),_("qbittorrent"))
+ if not nixio.fs.access("/etc/config/qbittorrent")then
+ return
+ end
+ entry({"admin","nas","qBittorrent"},cbi("qbittorrent"),_("qBittorrent"))
+ entry({"admin","nas","qBittorrent","status"},call("act_status")).leaf=true
end
+
+function act_status()
+ local e={}
+ e.running=luci.sys.call("pgrep qbittorrent-nox >/dev/null")==0
+ luci.http.prepare_content("application/json")
+ luci.http.write_json(e)
+end
\ No newline at end of file
diff --git a/package/lean/luci-app-qbittorrent/luasrc/model/cbi/qbittorrent.lua b/package/lean/luci-app-qbittorrent/luasrc/model/cbi/qbittorrent.lua
index af37d8fb3b..7431394f24 100644
--- a/package/lean/luci-app-qbittorrent/luasrc/model/cbi/qbittorrent.lua
+++ b/package/lean/luci-app-qbittorrent/luasrc/model/cbi/qbittorrent.lua
@@ -1,44 +1,371 @@
-require("luci.sys")
-local e=require"luci.model.uci".cursor()
-local o=e:get_first("qbittorrent","Preferences","port")or 8080
+
+local o=luci.sys.exec("uci get qbittorrent.main.Port | xargs echo -n") or 8080
+
local a=(luci.sys.call("pidof qbittorrent-nox > /dev/null")==0)
+
local t=""
-local e=""
if a then
-t=" "
-end
-if a then
-e=""..translate("Running")..""
-else
-e=""..translate("Not running")..""
+t="
"
end
-m = Map("qbittorrent", translate("qbittorrent"), translate("A BT/PT downloader base on Qt")..t
-.."
"..translate("qbittorrent Run Status").." : "..e.." ")
-
-s_basic = m:section(TypedSection, "basic", translate("Basic Settings"))
-s_basic.anonymous = true
-enable = s_basic:option(Flag, "enable", translate("Enable"))
-profile_dir = s_basic:option(Value,"profile_dir",translate("profile_dir"),translate("Store configuration files in the Path"))
-profile_dir.default = "/tmp"
-program_dir = s_basic:option(Value,"program_dir",translate("program_dir"),translate("Store Program files in the Path"))
-program_dir.default = "/usr/bin"
-library_dir = s_basic:option(Value,"library_dir",translate("library_dir"),translate("Store Library in the Path"))
-library_dir.default = "/usr/lib"
-
-s_download = m:section(TypedSection, "Preferences", translate("Download Settings"))
-s_download.anonymous = true
-download_dir = s_download:option(Value,"download_dir",translate("download_dir"),translate("Store download files in the Path"))
-download_dir.default = "/tmp/download"
-
-s_webui = m:section(TypedSection, "Preferences", translate("WEBUI Settings"))
-s_webui.anonymous = true
-port = s_webui:option(Value,"port",translate("port"),translate("WEBUI listening port"))
-port.default = "8080"
-
-local apply = luci.http.formvalue("cbi.apply")
-if apply then
- io.popen("/etc/init.d/qbittorrent restart")
+function titlesplit(Value)
+ return "
" .. translate(Value) .. "
"
end
+m = Map("qbittorrent", translate("qBittorrent"), translate("qBittorrent is a cross-platform free and open-source BitTorrent client")..t)
+
+s = m:section(NamedSection, "main", "qbittorrent")
+
+s:tab("basic", translate("Basic Settings"))
+
+o = s:taboption("basic", Flag, "enabled", translate("Enabled"))
+o.default = "1"
+
+o = s:taboption("basic", ListValue, "user", translate("Run daemon as user"))
+local u
+for u in luci.util.execi("cat /etc/passwd | cut -d ':' -f1") do
+ o:value(u)
+end
+
+o = s:taboption("basic", Value, "profile", translate("Store configuration files in the Path"))
+o.default = '/tmp'
+
+o = s:taboption("basic", Value, "SavePath", translate("Store download files in the Path"))
+o.placeholder = "/tmp/download"
+
+o = s:taboption("basic", Value, "Port", translate("WEBUI listening port"))
+o.datatype = "port"
+o.placeholder = "8080"
+
+o = s:taboption("basic", Flag, "UseRandomPort", translate("Use Random Port"), translate("Randomly assigns a different port every time qBittorrent starts up"))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("basic", Value, "PortRangeMin", translate("Connection Port"), translate("Incoming connection port"))
+o:depends("UseRandomPort", false)
+o.datatype = "range(1024,65535)"
+
+
+s:tab("connection", translate("Connection Settings"))
+
+o = s:taboption("connection", Flag, "UPnP", translate("Use UPnP for Connections"), translate("Use UPnP/ NAT-PMP port forwarding from my router. Refer to the "
+ .. "wiki."))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+
+o = s:taboption("connection", Value, "GlobalDLLimit", translate("Global Download Speed"), translate("Global Download Speed Limit(KiB/s)."))
+o.datatype = "float"
+o.placeholder = "0"
+
+o = s:taboption("connection", Value, "GlobalUPLimit", translate("Global Upload Speed"), translate("Global Upload Speed Limit(KiB/s)."))
+o.datatype = "float"
+o.placeholder = "0"
+
+o = s:taboption("connection", Value, "GlobalDLLimitAlt", translate("Alternative Download Speed"), translate("Alternative Download Speed Limit(KiB/s)."))
+o.datatype = "float"
+o.placeholder = "10"
+
+o = s:taboption("connection", Value, "GlobalUPLimitAlt", translate("Alternative Upload Speed"), translate("Alternative Upload Speed Limit(KiB/s)."))
+o.datatype = "float"
+o.placeholder = "10"
+
+o = s:taboption("connection", ListValue, "BTProtocol", translate("Enabled protocol"), translate("The protocol that was enabled."))
+o:value("Both", translate("TCP and UTP"))
+o:value("TCP", translate("TCP"))
+o:value("UTP", translate("UTP"))
+o.default = "Both"
+
+o = s:taboption("connection", Value, "InetAddress", translate("Inet Address"), translate("The address that respond to the trackers."))
+
+s:tab("downloads", translate("Download Settings"))
+
+o = s:taboption("downloads", Flag, "CreateTorrentSubfolder", translate("Create Subfolder"), translate("Create subfolder for torrents with multiple files."))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("downloads", Flag, "StartInPause", translate("Start In Pause"), translate("Do not start the download automatically."))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.disabled
+
+o = s:taboption("downloads", Flag, "AutoDeleteAddedTorrentFile", translate("Auto Delete Torrent File"), translate("The .torrent files will be deleted afterwards."))
+o.enabled = "IfAdded"
+o.disabled = "Never"
+o.default = o.disabled
+
+o = s:taboption("downloads", Flag, "PreAllocation", translate("Pre Allocation"), translate("Pre-allocate disk space for all files."))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.disabled
+
+o = s:taboption("downloads", Flag, "UseIncompleteExtension", translate("Use Incomplete Extension"), translate("The incomplete task will be added the extension of !qB."))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.disabled
+
+o = s:taboption("downloads", Flag, "TempPathEnabled", translate("Temp Path Enabled"))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("downloads", Value, "TempPath", translate("Temp Path"), translate("The absolute and relative path can be set."))
+o:depends("TempPathEnabled", "true")
+o.placeholder = "temp/"
+
+o = s:taboption("downloads", Value, "DiskWriteCacheSize", translate("Disk Cache Size (MiB)"), translate("The value -1 is auto and 0 is disable. In default, it is set to 64MiB."))
+o.datatype = "integer"
+o.placeholder = "64"
+
+o = s:taboption("downloads", Value, "DiskWriteCacheTTL", translate("Disk Cache TTL (s)"), translate("In default, it is set to 60s."))
+o.datatype = "integer"
+o.placeholder = "60"
+
+o = s:taboption("downloads", DummyValue, "Saving Management", titlesplit("Saving Management"))
+
+o = s:taboption("downloads", ListValue, "DisableAutoTMMByDefault", translate("Default Torrent Management Mode"))
+o:value("true", translate("Manual"))
+o:value("false", translate("Automaic"))
+o.default = "true"
+
+o = s:taboption("downloads", ListValue, "CategoryChanged", translate("Torrent Category Changed"), translate("Choose the action when torrent category changed."))
+o:value("true", translate("Switch torrent to Manual Mode"))
+o:value("false", translate("Relocate torrent"))
+o.default = "false"
+
+o = s:taboption("downloads", ListValue, "DefaultSavePathChanged", translate("Default Save Path Changed"), translate("Choose the action when default save path changed."))
+o:value("true", translate("Switch affected torrent to Manual Mode"))
+o:value("false", translate("Relocate affected torrent"))
+o.default = "true"
+
+o = s:taboption("downloads", ListValue, "CategorySavePathChanged", translate("Category Save Path Changed"), translate("Choose the action when category save path changed."))
+o:value("true", translate("Switch affected torrent to Manual Mode"))
+o:value("false", translate("Relocate affected torrent"))
+o.default = "true"
+
+o = s:taboption("downloads", Value, "TorrentExportDir", translate("Torrent Export Dir"), translate("The .torrent files will be copied to the target directory."))
+
+o = s:taboption("downloads", Value, "FinishedTorrentExportDir", translate("Finished Torrent Export Dir"), translate("The .torrent files for finished downloads will be copied to the target directory."))
+
+s:tab("bittorrent", translate("Bittorrent Settings"))
+
+o = s:taboption("bittorrent", Flag, "DHT", translate("Enable DHT"), translate("Enable DHT (decentralized network) to find more peers"))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("bittorrent", Flag, "PeX", translate("Enable PeX"), translate("Enable Peer Exchange (PeX) to find more peers"))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("bittorrent", Flag, "LSD", translate("Enable LSD"), translate("Enable Local Peer Discovery to find more peers"))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.disabled
+
+o = s:taboption("bittorrent", Flag, "uTP_rate_limited", translate("uTP Rate Limit"), translate("Apply rate limit to μTP protocol."))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("bittorrent", ListValue, "Encryption", translate("Encryption Mode"), translate("Enable DHT (decentralized network) to find more peers"))
+o:value("0", translate("Prefer Encryption"))
+o:value("1", translate("Require Encryption"))
+o:value("2", translate("Disable Encryption"))
+o.default = "0"
+
+o = s:taboption("bittorrent", Value, "MaxConnecs", translate("Max Connections"), translate("The max number of connections."))
+o.datatype = "integer"
+o.placeholder = "500"
+
+o = s:taboption("bittorrent", Value, "MaxConnecsPerTorrent", translate("Max Connections Per Torrent"), translate("The max number of connections per torrent."))
+o.datatype = "integer"
+o.placeholder = "100"
+
+o = s:taboption("bittorrent", Value, "MaxUploads", translate("Max Uploads"), translate("The max number of connected peers."))
+o.datatype = "integer"
+o.placeholder = "8"
+
+o = s:taboption("bittorrent", Value, "MaxUploadsPerTorrent", translate("Max Uploads Per Torrent"), translate("The max number of connected peers per torrent."))
+o.datatype = "integer"
+o.placeholder = "4"
+
+o = s:taboption("bittorrent", Value, "MaxRatio", translate("Max Ratio"), translate("The max ratio for seeding. -1 is to disable the seeding."))
+o.datatype = "float"
+o.placeholder = "-1"
+
+o = s:taboption("bittorrent", ListValue, "MaxRatioAction", translate("Max Ratio Action"), translate("The action when reach the max seeding ratio."))
+o:value("0", translate("Pause them"))
+o:value("1", translate("Remove them"))
+o.defaule = "0"
+
+o = s:taboption("bittorrent", Value, "GlobalMaxSeedingMinutes", translate("Max Seeding Minutes"), translate("Units: minutes"))
+o.datatype = "integer"
+
+o = s:taboption("bittorrent", DummyValue, "Queueing Setting", titlesplit("Queueing Setting"))
+
+o = s:taboption("bittorrent", Flag, "QueueingEnabled", translate("Enable Torrent Queueing"))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("bittorrent", Value, "MaxActiveDownloads", translate("Maximum Active Downloads"))
+o.datatype = "integer"
+o.placeholder = "3"
+
+o = s:taboption("bittorrent", Value, "MaxActiveUploads", translate("Max Active Uploads"))
+o.datatype = "integer"
+o.placeholder = "3"
+
+o = s:taboption("bittorrent", Value, "MaxActiveTorrents", translate("Max Active Torrents"))
+o.datatype = "integer"
+o.placeholder = "5"
+
+o = s:taboption("bittorrent", Flag, "IgnoreSlowTorrents", translate("Ignore Slow Torrents"), translate("Do not count slow torrents in these limits."))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.disabled
+
+o = s:taboption("bittorrent", Value, "SlowTorrentsDownloadRate", translate("Download rate threshold"), translate("Units: KiB/s"))
+o.datatype = "integer"
+o.placeholder = "2"
+
+o = s:taboption("bittorrent", Value, "SlowTorrentsUploadRate", translate("Upload rate threshold"), translate("Units: KiB/s"))
+o.datatype = "integer"
+o.placeholder = "2"
+
+o = s:taboption("bittorrent", Value, "SlowTorrentsInactivityTimer", translate("Torrent inactivity timer"), translate("Units: seconds"))
+o.datatype = "integer"
+o.placeholder = "60"
+
+s:tab("webgui", translate("WebUI Settings"))
+
+o = s:taboption("webgui", Flag, "UseUPnP", translate("Use UPnP for WebUI"), translate("Using the UPnP / NAT-PMP port of the router for connecting to WebUI."))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.disabled
+
+o = s:taboption("webgui", Value, "Username", translate("Username"), translate("The login name for WebUI."))
+o.placeholder = "admin"
+
+o = s:taboption("webgui", Value, "Password", translate("Password"), translate("The login password for WebUI."))
+o.password = true
+
+o = s:taboption("webgui", Value, "Locale", translate("Locale Language"))
+o:value("en", translate("English"))
+o:value("zh", translate("Chinese"))
+o.default = "en"
+
+o = s:taboption("webgui", Flag, "CSRFProtection", translate("CSRF Protection"), translate("Enable Cross-Site Request Forgery (CSRF) protection."))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("webgui", Flag, "ClickjackingProtection", translate("Clickjacking Protection"), translate("Enable clickjacking protection."))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("webgui", Flag, "HostHeaderValidation", translate("Host Header Validation"), translate("Validate the host header."))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("webgui", Flag, "LocalHostAuth", translate("Local Host Authentication"), translate("Force authentication for clients on localhost."))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("webgui", Flag, "AuthSubnetWhitelistEnabled", translate("Enable Subnet Whitelist"))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.disabled
+
+o = s:taboption("webgui", DynamicList, "AuthSubnetWhitelist", translate("Subnet Whitelist"))
+o:depends("AuthSubnetWhitelistEnabled", "true")
+
+s:tab("advanced", translate("Advance Settings"))
+
+o = s:taboption("advanced", Flag, "AnonymousMode", translate("Anonymous Mode"), translate("When enabled, qBittorrent will take certain measures to try"
+ .. " to mask its identity. Refer to the wiki"))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("advanced", Flag, "SuperSeeding", translate("Super Seeding"), translate("The super seeding mode."))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.disabled
+
+o = s:taboption("advanced", Value, "configuration", translate("Profile Folder Suffix"), translate("Suffix for profile folder"))
+
+o = s:taboption("advanced", Flag, "IncludeOverhead", translate("Limit Overhead Usage"), translate("The overhead usage is been limitted."))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.disabled
+
+o = s:taboption("advanced", Flag, "IgnoreLimitsLAN", translate("Ignore LAN Limit"), translate("Ignore the speed limit to LAN."))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("advanced", Flag, "osCache", translate("Use os Cache"))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("advanced", Value, "OutgoingPortsMax", translate("Max Outgoing Port"), translate("The max outgoing port."))
+o.datatype = "port"
+
+o = s:taboption("advanced", Value, "OutgoingPortsMin", translate("Min Outgoing Port"), translate("The min outgoing port."))
+o.datatype = "port"
+
+o = s:taboption("advanced", ListValue, "SeedChokingAlgorithm", translate("Choking Algorithm"), translate("The strategy of choking algorithm."))
+o:value("RoundRobin", translate("Round Robin"))
+o:value("FastestUpload", translate("Fastest Upload"))
+o:value("AntiLeech", translate("Anti-Leech"))
+o.default = "FastestUpload"
+
+o = s:taboption("advanced", Flag, "AnnounceToAllTrackers", translate("Announce To All Trackers"))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.disabled
+
+o = s:taboption("advanced", Flag, "AnnounceToAllTiers", translate("Announce To All Tiers"))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("advanced", Flag, "Enabled", translate("Enable Log"), translate("Enable logger to log file."))
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("advanced", Value, "Path", translate("Log Path"), translate("The path for qbittorrent log."))
+o:depends("Enabled", "true")
+
+o = s:taboption("advanced", Flag, "Backup", translate("Enable Backup"), translate("Backup log file when oversize the given size."))
+o:depends("Enabled", "true")
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("advanced", Flag, "DeleteOld", translate("Delete Old Backup"), translate("Delete the old log file."))
+o:depends("Enabled", "true")
+o.enabled = "true"
+o.disabled = "false"
+o.default = o.enabled
+
+o = s:taboption("advanced", Value, "MaxSizeBytes", translate("Log Max Size"), translate("The max size for qbittorrent log (Unit: Bytes)."))
+o:depends("Enabled", "true")
+o.placeholder = "66560"
+
+o = s:taboption("advanced", Value, "SaveTime", translate("Log Saving Period"), translate("The log file will be deteted after given time. 1d -- 1 day, 1m -- 1 month, 1y -- 1 year"))
+o:depends("Enabled", "true")
+o.datatype = "string"
+
return m
diff --git a/package/lean/luci-app-qbittorrent/luasrc/view/qbittorrent/qbittorrent_status.htm b/package/lean/luci-app-qbittorrent/luasrc/view/qbittorrent/qbittorrent_status.htm
new file mode 100644
index 0000000000..13ebe1c978
--- /dev/null
+++ b/package/lean/luci-app-qbittorrent/luasrc/view/qbittorrent/qbittorrent_status.htm
@@ -0,0 +1,22 @@
+
+
+
\ No newline at end of file
diff --git a/package/lean/luci-app-qbittorrent/po/zh-cn/qbittorrent.po b/package/lean/luci-app-qbittorrent/po/zh-cn/qbittorrent.po
index d7a834ede1..001a33f599 100644
--- a/package/lean/luci-app-qbittorrent/po/zh-cn/qbittorrent.po
+++ b/package/lean/luci-app-qbittorrent/po/zh-cn/qbittorrent.po
@@ -1,5 +1,5 @@
msgid "qbittorrent"
-msgstr "BT下载器-qb"
+msgstr "qbittorrent"
msgid "Running"
msgstr "运行中"
@@ -16,8 +16,8 @@ msgstr "基本设置"
msgid "Enable"
msgstr "启用"
-msgid "A BT/PT downloader base on Qt"
-msgstr "一个基于QT的BT/PT下载器"
+msgid "qBittorrent is a cross-platform free and open-source BitTorrent client"
+msgstr "qBittorrent是一个基于 QT 的跨平台的开源 BitTorrent 客户端"
msgid "profile_dir"
msgstr "配置文件目录"
@@ -50,4 +50,525 @@ msgid "WEBUI Settings"
msgstr "WEBUI设置"
msgid "WEBUI listening port"
-msgstr "WEBUI监听端口"
+msgstr "WebUI 监听端口"
+
+msgid "Use Random Port"
+msgstr "随机传入连接端口"
+
+msgid "Randomly assigns a different port every time qBittorrent starts up"
+msgstr "在每次启动时使用不同的传入连接端口"
+
+msgid "Connection Port"
+msgstr "用于传入连接的端口"
+
+msgid "Incoming connection port"
+msgstr "推荐在防火墙 -> 流量规则 中,打开这个端口获得更好的下载速度( TCP+UDP )"
+
+msgid "Bittorrent Settings"
+msgstr "Bittorrent 设置"
+
+msgid "WebUI Settings"
+msgstr "WebUI 设置"
+
+msgid "Advance Settings"
+msgstr "高级设置"
+
+
+msgid "Run daemon as user"
+msgstr "用户组"
+
+msgid "Parent Path for Profile Folder"
+msgstr "配置保存路径"
+
+msgid "The path for storing profile folder using by command: --profile [PATH]."
+msgstr "配置文件的保存路径,默认的配置文件夹在/tmp下。例如:/etc/config"
+
+msgid "Profile Folder Suffix"
+msgstr "配置目录后缀"
+
+msgid "Suffix for profile folder, for example, qBittorrent_[NAME]."
+msgstr "配置文件文件夹的后缀。例如: qBittorrent_[NAME]"
+
+msgid "Locale Language"
+msgstr "WebUI语言"
+
+msgid "English"
+msgstr "英文"
+
+msgid "Chinese"
+msgstr "中文"
+
+msgid "Enable Log"
+msgstr "启用日志"
+
+msgid "Enable logger to log file."
+msgstr "qBittorrent的启动和运行信息文档。"
+
+msgid "Log Path"
+msgstr "日志文件"
+
+msgid "The path for qbittorrent log."
+msgstr "日志文件自定义保存路径,默认都在配置文件夹的data下。"
+
+msgid "Enable Backup"
+msgstr "启用备份"
+
+msgid "Backup log file when oversize the given size."
+msgstr "备份日志文件。"
+
+msgid "Delete Old Backup"
+msgstr "删除备份"
+
+msgid "Delete the old log file."
+msgstr "符合下列设定后将删除旧的日志文件。"
+
+msgid "Log Max Size"
+msgstr "日志保存大小"
+
+msgid "Log Saving Period"
+msgstr "日志保存期限"
+
+msgid "The max size for qbittorrent log (Unit: Bytes)."
+msgstr "设定日志文件的大小(单位:字节)"
+
+msgid "The log file will be deteted after given time. 1d -- 1 day, 1m -- 1 month, 1y -- 1 year"
+msgstr "设定日志文件的时间(1d-1天,1m-1个月,1y-1年)"
+
+msgid "Connection Settings"
+msgstr "连接设置"
+
+msgid "Use UPnP for Connections"
+msgstr "端口自动转发"
+
+msgid "Use UPnP/ NAT-PMP port forwarding from my router."
+msgstr "使用路由器的UPnP/NAT-PMP端口自动转发。"
+
+msgid "Use Random Port"
+msgstr "启用随机端口"
+
+msgid "Use different port on each startup voids the first"
+msgstr "在每次启动时使用随机的端口。"
+
+msgid "Connection Port"
+msgstr "自定义端口"
+
+msgid "Generate Randomly"
+msgstr "默认端口:8999"
+
+msgid "Global Download Speed"
+msgstr "全局下载速度限制"
+
+msgid "Global Download Speed Limit(KiB/s)."
+msgstr "全局下载速度限制(KiB/s),0为无限制。"
+
+msgid "Global Upload Speed"
+msgstr "全局上传速度限制"
+
+msgid "Alternative Download Speed"
+msgstr "备用下载速度限制"
+
+msgid "Alternative Upload Speed"
+msgstr "备用上传速度限制"
+
+msgid "Global Upload Speed Limit(KiB/s)."
+msgstr "全局上传速度限制(KiB/s),0为无限制。"
+
+msgid "Alternative Download Speed Limit(KiB/s)."
+msgstr "备用下载速度限制(KiB/s),0为无限制。"
+
+msgid "Alternative Upload Speed Limit(KiB/s)."
+msgstr "备用上传速度限制(KiB/s),0为无限制。"
+
+msgid "Enabled protocol"
+msgstr "启用的协议"
+
+msgid "The protocol that was enabled."
+msgstr "当前已启用的协议。"
+
+msgid "TCP and UTP"
+msgstr "TCP和UTP"
+
+msgid "Inet Address"
+msgstr "输入地址"
+
+msgid "The address that respond to the trackers."
+msgstr "响应跟踪器的地址。"
+
+msgid "When adding seeds"
+msgstr "当添加种子时"
+
+msgid "Downloads Settings"
+msgstr "下载设置"
+
+msgid "Create Subfolder"
+msgstr "创建目录"
+
+msgid "Create subfolder for torrents with multiple files."
+msgstr "为含多个文件的种子创建子文件夹。"
+
+msgid "Start In Pause"
+msgstr "开始暂停"
+
+msgid "Do not start the download automatically."
+msgstr "在下载任务添加后暂停。"
+
+msgid "Auto Delete Torrent File"
+msgstr "删除种子"
+
+msgid "The .torrent files will be deleted afterwards."
+msgstr "下载完成后自动删除这个种子文件。"
+
+msgid "Pre Allocation"
+msgstr "磁盘预分配"
+
+msgid "Pre-allocate disk space for all files."
+msgstr "为刚添加的文件预先分配磁盘空间。"
+
+msgid "Use Incomplete Extension"
+msgstr "使用扩展名"
+
+msgid "The incomplete task will be added the extension of !qB."
+msgstr "为不完整的文件添加后缀名!qB"
+
+msgid "Save Path"
+msgstr "文件保存路径"
+
+msgid "The path to save the download file. For example:/mnt/sda1/download"
+msgstr "下载文件的保存路径。例如:/mnt/sda1/download"
+
+msgid "Temp Path Enabled"
+msgstr "启用临时目录"
+
+msgid "Temp Path"
+msgstr "临时路径"
+
+msgid "The absolute and relative path can be set."
+msgstr "可以设置绝对和相对路径。"
+
+msgid "Disk Cache Size (MiB)"
+msgstr "磁盘缓存"
+
+msgid "The value -1 is auto and 0 is disable. In default, it is set to 64MiB."
+msgstr "数值1是自动的,0是禁用的。默认设置为64MiB。"
+
+msgid "Disk Cache TTL (s)"
+msgstr "磁盘缓存TTL"
+
+msgid "In default, it is set to 60s."
+msgstr "默认设置为60秒。"
+
+msgid "Saving Management"
+msgstr "保存管理"
+
+msgid "Default Torrent Management Mode"
+msgstr "默认种子管理模式"
+
+msgid "Manual"
+msgstr "手动"
+
+msgid "Automaic"
+msgstr "自动"
+
+msgid "Torrent Category Changed"
+msgstr "当种子分类修改时"
+
+msgid "Choose the action when torrent category changed."
+msgstr "选择种子类别更改时的操作。"
+
+msgid "Switch torrent to Manual Mode"
+msgstr "将种子切换到手动模式"
+
+msgid "Relocate torrent"
+msgstr "重新定位种子"
+
+msgid "Default Save Path Changed"
+msgstr "当默认保存路径修改时"
+
+msgid "Choose the action when default save path changed."
+msgstr "选择默认保存路径更改时的操作。"
+
+msgid "Switch affected torrent to Manual Mode"
+msgstr "将受影响的种子切换到手动模式"
+
+msgid "Relocate affected torrent"
+msgstr "重新定位种子"
+
+msgid "Category Save Path Changed"
+msgstr "当分类保存路径修改时"
+
+msgid "Choose the action when category save path changed."
+msgstr "选择分类保存路径更改时的操作。"
+
+msgid "Torrent Export Dir"
+msgstr "种子导出目录"
+
+msgid "The .torrent files will be copied to the target directory."
+msgstr "种子文件将被复制到目标目录。例如:/etc/config"
+
+msgid "Finished Torrent Export Dir"
+msgstr "复制种子文件"
+
+msgid "The .torrent files for finished downloads will be copied to the target directory."
+msgstr "将已下载完成的种子文件复制到目标目录。例如:/etc/config"
+
+msgid "Bittorrent Settings"
+msgstr "BT设置""
+
+msgid "Enable DHT"
+msgstr "启用DHT"
+
+msgid "Enable DHT (decentralized network) to find more peers"
+msgstr "启用DHT(去中心化网络) 以找到更多用户。"
+
+msgid "Enable PeX"
+msgstr "启用PeX"
+
+msgid "Enable Peer Exchange (PeX) to find more peers"
+msgstr "启用用户交换(PeX)以找到更多用户。"
+
+msgid "Enable LSD"
+msgstr "启用LSD"
+
+msgid "Enable Local Peer Discovery to find more peers"
+msgstr "启用本地用户发现以找到更多用户。"
+
+msgid "uTP Rate Limit"
+msgstr "uTP速度限制"
+
+msgid "Apply rate limit to µTP protocol."
+msgstr "针对µTP协议进行速度限制。"
+
+msgid "Encryption Mode"
+msgstr "加密模式"
+
+msgid "Enable DHT (decentralized network) to find more peers"
+msgstr "使DHT(分散网络)能够找到更多的对等点。"
+
+msgid "Prefer Encryption"
+msgstr "偏好加密"
+
+msgid "Require Encryption"
+msgstr "强制加密"
+
+msgid "Disable Encryption"
+msgstr "禁用加密"
+
+msgid "Max Connections"
+msgstr "连接数限制"
+
+msgid "The max number of connections."
+msgstr "全局最大连接数。"
+
+msgid "Max Connections Per Torrent"
+msgstr "种子连接数限制"
+
+msgid "The max number of connections per torrent."
+msgstr "每个种子的最大连接数。"
+
+msgid "Max Uploads"
+msgstr "最大上传数"
+
+msgid "The max number of connected peers."
+msgstr "全局最大上传线程数。"
+
+msgid "Max Uploads Per Torrent"
+msgstr "种子上传限制"
+
+msgid "The max number of connected peers per torrent."
+msgstr "每个种子上传线程最大值。"
+
+msgid "Share rate limit"
+msgstr "分享率限制"
+
+msgid "Max Ratio"
+msgstr "最大的分享率"
+
+msgid "The max ratio for seeding. -1 is to disable the seeding."
+msgstr "分享的最大比例设定。-1是禁用做种。"
+
+msgid "Max Seeding Minutes"
+msgstr "最大做种时间"
+
+msgid "Units: minutes"
+msgstr "做种最大比例设定。单位:分钟"
+
+msgid "Max Ratio Action"
+msgstr "达到后"
+
+msgid "The action when reach the max seeding ratio."
+msgstr "达到设定分享率和时间后的动作。"
+
+msgid "Pause them"
+msgstr "暂停"
+
+msgid "Remove them"
+msgstr "删除"
+
+msgid "Queueing Setting"
+msgstr "种子排队设置"
+
+msgid "Enable Torrent Queueing"
+msgstr "启用种子排队"
+
+msgid "Maximum Active Downloads"
+msgstr "最大活动的下载数"
+
+msgid "Max Active Uploads"
+msgstr "最大活动的上传数"
+
+msgid "Max Active Torrents"
+msgstr "最大活动的种子数"
+
+msgid "Ignore Slow Torrents"
+msgstr "忽略慢速的种子"
+
+msgid "Do not count slow torrents in these limits."
+msgstr "慢速的种子不包在括限制内。"
+
+msgid "Download rate threshold"
+msgstr "下载速度阈值"
+
+msgid "Upload rate threshold"
+msgstr "上传速度阈值"
+
+msgid "Units: KiB/s"
+msgstr "单位:KiB/s"
+
+msgid "Torrent inactivity timer"
+msgstr "种子不活动时间"
+
+msgid "Units: seconds"
+msgstr "时间单位:分钟"
+
+msgid "WebUI Settings"
+msgstr "WebUI设置"
+
+msgid "Username"
+msgstr ""
+
+msgid "Password"
+msgstr ""
+
+msgid "Use UPnP for WebUI"
+msgstr "WebUI端口转发"
+
+msgid "Using the UPnP / NAT-PMP port of the router for connecting to WebUI."
+msgstr "使用路由器的UPnP/NAT-PMP端口转发到WebUI。"
+
+msgid "The login name for WebUI."
+msgstr "WebUI的登录用户名设置。"
+
+msgid "The login password for WebUI."
+msgstr "WebUI用户的登录密码设置。"
+
+msgid "The listening port for WebUI."
+msgstr "WebUI的登录端口设置。默认端口:8080"
+
+msgid "CSRF Protection"
+msgstr "CSRF保护"
+
+msgid "Enable Cross-Site Request Forgery (CSRF) protection."
+msgstr "启用跨站点请求伪造(CSRF)保护。"
+
+msgid "Clickjacking Protection"
+msgstr "劫持保护"
+
+msgid "Enable clickjacking protection."
+msgstr "启用点击劫持保护。"
+
+msgid "Host Header Validation"
+msgstr "主机标头验证"
+
+msgid "Validate the host header."
+msgstr "启用主机标头验证."
+
+msgid "Local Host Authentication"
+msgstr "本地主机认证"
+
+msgid "Force authentication for clients on localhost."
+msgstr "强制对本地主机上的客户端进行身份验证。"
+
+msgid "Enable Subnet Whitelist"
+msgstr "使子网白名单"
+
+msgid "Subnet Whitelist"
+msgstr "输入IP地址"
+
+msgid "Skip authentication for clients in the IP subnet white list."
+msgstr "对IP子网白名单中的客户端跳过身份验证."
+
+msgid "Advance Settings"
+msgstr "高级设置"
+
+msgid "Anonymous Mode"
+msgstr "匿名模式"
+
+msgid "When enabled, qBittorrent will take certain measures to try"
+msgstr "启用后,qBittorrent将采取某些措施隐藏其身份。"
+
+msgid "Super Seeding"
+msgstr "超级种子"
+
+msgid "The super seeding mode."
+msgstr "超级种子模式。"
+
+msgid "Limit Overhead Usage"
+msgstr "开销限制"
+
+msgid "The overhead usage is been limitted."
+msgstr "对传送总开销进行速度限制。"
+
+msgid "Ignore LAN Limit"
+msgstr "LAN限制"
+
+msgid "Ignore the speed limit to LAN."
+msgstr "忽略对LAN的速度限制。"
+
+msgid "Use os Cache"
+msgstr "使用OS操作系统缓存管理"
+
+msgid "Max Outgoing Port"
+msgstr "端口设置"
+
+msgid The max outgoing port.""
+msgstr "最大输出端口。"
+
+msgid "Min Outgoing Port"
+msgstr "端口设置"
+
+msgid "The min outgoing port."
+msgstr "最小输出端口。"
+
+msgid "Choking Algorithm"
+msgstr "数据传输算法"
+
+msgid "The strategy of choking algorithm."
+msgstr "数据传输算法的策略。"
+
+msgid "Round Robin"
+msgstr "负载均衡"
+
+msgid "Fastest Upload"
+msgstr "最快上传"
+
+msgid "Anti-Leech"
+msgstr "反吸血"
+
+msgid "Announce To All Trackers"
+msgstr "对所有Trackers宣告"
+
+msgid "Announce To All Tiers"
+msgstr "对所有Tiers宣告"
+
+msgid "configuration file"
+msgstr "配置文件"
+
+msgid "Operation log"
+msgstr "运行日志"
+
+msgid "This page is the log document content of qbittorrent."
+msgstr "本页是qBittorrent的日志文档内容。"
+
+msgid "This page is the content of the configuration document under /etc/config/qbittorrent."
+msgstr "本页是/etc/config/qbittorrent下的配置文档内容。"
+
diff --git a/package/lean/luci-app-qbittorrent/root/etc/config/qbittorrent b/package/lean/luci-app-qbittorrent/root/etc/config/qbittorrent
index b4fe940c3c..4ec138ff67 100644
--- a/package/lean/luci-app-qbittorrent/root/etc/config/qbittorrent
+++ b/package/lean/luci-app-qbittorrent/root/etc/config/qbittorrent
@@ -1,3 +1,19 @@
-config basic
-config Preferences
+
+config qbittorrent 'main'
+ option user 'root'
+ option Locale 'zh'
+ option BTProtocol 'Both'
+ option DisableAutoTMMByDefault 'true'
+ option CategoryChanged 'false'
+ option DefaultSavePathChanged 'true'
+ option CategorySavePathChanged 'true'
+ option Encryption '0'
+ option MaxRatioAction '0'
+ option CSRFProtection 'false'
+ option SeedChokingAlgorithm 'FastestUpload'
+ option Enabled 'false'
+ option Port '8080'
+ option profile '/opt'
+ option enabled '0'
+
diff --git a/package/lean/luci-app-qbittorrent/root/etc/init.d/qbittorrent b/package/lean/luci-app-qbittorrent/root/etc/init.d/qbittorrent
index 383317165d..274aa45719 100755
--- a/package/lean/luci-app-qbittorrent/root/etc/init.d/qbittorrent
+++ b/package/lean/luci-app-qbittorrent/root/etc/init.d/qbittorrent
@@ -1,67 +1,264 @@
#!/bin/sh /etc/rc.common
+# Licensed to the public under the Apache License 2.0.
+# ubus call service list
+
START=99
-config_qbittorrent()
-{
- local download_dir
- local port
- config_get download_dir $1 download_dir
- config_get port $1 port
- if [ -f $2/qBittorrent/config/qBittorrent.conf ]; then
- sed -i 's/WebUI\\Port=[0-9]*/WebUI\\Port='"$port"'/g' $2/qBittorrent/config/qBittorrent.conf
- sed -i 's/Downloads\\SavePath=[a-z,/]*//g' $2/qBittorrent/config/qBittorrent.conf
- echo "Downloads\SavePath=$down" >> $2/qBittorrent/config/qBittorrent.conf
- else
- cat>$2/qBittorrent/config/qBittorrent.conf<"$QBT_INI_FILE"</dev/null 2>&1;
+ return 1;
+ }
+
+ local confdir="qBittorrent"
+ [ -n "$configuration" ] && {
+ confdir="qBittorrent_$configuration"
+ }
+
+ [ -d "$profile/$confdir/config" ] || {
+ mkdir -m 0755 -p "$profile/$confdir/config"
+ }
+
+ [ "$user" != "root" ] && {
+ [ -d "$confdir" ] && {
+ local groupnow="$(ls -l $profile | grep $confdir | awk '{print $3})"
+ local usernow="$(ls -l $profile | grep $confdir | awk '{print $4})"
+
+ [ "$usernow" != "$user" ] && { _err "Permission denied!"; return 1; }
+ } || {
+ chmod -R g+w "$profile/$confdir"
+ chown -R "$user":"$user" "$profile/$confdir"
+ }
+ }
+
+ [ "$AuthSubnetWhitelistEnabled" = true ] && {
+ AuthSubnetWhitelist="$( echo $AuthSubnetWhitelist | sed 's/ /,/g')"
+ } || {
+ AuthSubnetWhitelist="@Invalid()"
+ }
+
+ QBT_INI_FILE="$profile/$confdir/config/qBittorrent.conf"
+ config_QBT
+
+ procd_open_instance $QBT_INSTANCE
+ procd_set_param command $args
+ procd_append_param command --profile="$profile"
+
+ [ -n "$configuration" ] && {
+ procd_append_param command --configuration="$configuration"
+ }
+
+ procd_set_param respawn
+ procd_set_param user $user
+ procd_set_param file $QBT_INI_FILE
+ procd_set_param pidfile $QBT_PID_FILE
+ procd_close_instance
}
-stop()
+service_triggers()
{
- killall qbittorrent-nox
- return 0
+ procd_add_reload_trigger "$NAME"
+}
+
+start_service() {
+ config_load "$NAME"
+ config_foreach init_QBT "$NAME"
+}
+
+reload_service() {
+ restart
+}
+
+restart() {
+ stop
+ sleep 2
+ start
}
diff --git a/package/lean/luci-app-qbittorrent/root/etc/uci-defaults/luci-qbittorrent b/package/lean/luci-app-qbittorrent/root/etc/uci-defaults/luci-qbittorrent
new file mode 100644
index 0000000000..dd2c37d8d8
--- /dev/null
+++ b/package/lean/luci-app-qbittorrent/root/etc/uci-defaults/luci-qbittorrent
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+uci -q batch <<-EOF >/dev/null
+ delete ucitrack.@qbittorrent[-1]
+ add ucitrack qbittorrent
+ set ucitrack.@qbittorrent[-1].init=qbittorrent
+ commit ucitrack
+EOF
+
+if [ ."$(uci -q get qbittorrent.main)" != ."qbittorrent" ]; then
+ uci -q batch <<-EOF >/dev/null
+ add qbittorrent qbittorrent
+ rename qbittorrent.@qbittorrent[-1]="main"
+ set qbittorrent.main.enabled=0
+ set qbittorrent.main.profile="/tmp"
+ commit qbittorrent
+ EOF
+fi
+
+rm -f /tmp/luci-indexcache
+exit 0
diff --git a/package/lean/luci-app-ssr-plus/Makefile b/package/lean/luci-app-ssr-plus/Makefile
index 77fb0a6c17..2f66356c3a 100644
--- a/package/lean/luci-app-ssr-plus/Makefile
+++ b/package/lean/luci-app-ssr-plus/Makefile
@@ -2,10 +2,11 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-ssr-plus
PKG_VERSION:=1
-PKG_RELEASE:=125
+PKG_RELEASE:=131
PKG_CONFIG_DEPENDS:= CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray \
+ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Trojan \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Socks
@@ -21,6 +22,10 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray
bool "Include V2ray"
default y if x86_64
+config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan
+ bool "Include Trojan"
+ default y if x86_64
+
config PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun
bool "Include Kcptun"
default n
@@ -43,6 +48,8 @@ define Package/luci-app-ssr-plus
DEPENDS:=+shadowsocksr-libev-alt +ipset +ip-full +iptables-mod-tproxy +dnsmasq-full +coreutils +coreutils-base64 +bash +pdnsd-alt +wget \
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks:shadowsocks-libev-ss-redir \
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:v2ray \
+ +PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:trojan \
+ +PACKAGE_$(PKG_NAME)_INCLUDE_Trojan:ipt2socks \
+PACKAGE_$(PKG_NAME)_INCLUDE_Kcptun:openwrt-kcptun-client \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server:shadowsocksr-libev-server \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Socks:shadowsocksr-libev-ssr-local
diff --git a/package/lean/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua b/package/lean/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua
index 5b7dc7fe32..abe8cf90ca 100644
--- a/package/lean/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua
+++ b/package/lean/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua
@@ -114,7 +114,7 @@ s = m:section(NamedSection, sid, "servers")
s.anonymous = true
s.addremove = false
-o = s:option(DummyValue,"ssr_url","SS/SSR/V2RAY URL")
+o = s:option(DummyValue,"ssr_url","SS/SSR/V2RAY/TROJAN URL")
o.rawhtml = true
o.template = "shadowsocksr/ssrurl"
o.value =sid
@@ -127,6 +127,9 @@ end
if nixio.fs.access("/usr/bin/v2ray/v2ray") then
o:value("v2ray", translate("V2Ray"))
end
+if nixio.fs.access("/usr/sbin/trojan") then
+o:value("trojan", translate("Trojan"))
+end
o.description = translate("Using incorrect encryption mothod may causes service fail to start")
o = s:option(Value, "alias", translate("Alias(optional)"))
@@ -149,6 +152,7 @@ o.password = true
o.rmempty = true
o:depends("type", "ssr")
o:depends("type", "ss")
+o:depends("type", "trojan")
o = s:option(ListValue, "encrypt_method", translate("Encrypt Method"))
for _, v in ipairs(encrypt_methods) do o:value(v) end
@@ -327,18 +331,26 @@ o.rmempty = true
o = s:option(Flag, "insecure", translate("allowInsecure"))
o.rmempty = true
o:depends("type", "v2ray")
+o:depends("type", "trojan")
-- [[ TLS ]]--
o = s:option(Flag, "tls", translate("TLS"))
o.rmempty = true
o.default = "0"
o:depends("type", "v2ray")
+o:depends("type", "trojan")
+
+o = s:option(Value, "tls_host", translate("TLS Host"))
+o:depends("tls", "1")
+o.rmempty = true
+o:depends("type", "trojan")
-- [[ Mux ]]--
o = s:option(Flag, "mux", translate("Mux"))
o.rmempty = true
o.default = "0"
o:depends("type", "v2ray")
+o:depends("type", "trojan")
o = s:option(Value, "concurrency", translate("Concurrency"))
o.datatype = "uinteger"
diff --git a/package/lean/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/log.lua b/package/lean/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/log.lua
index 05b4162fc4..914e7e1f62 100644
--- a/package/lean/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/log.lua
+++ b/package/lean/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/log.lua
@@ -2,7 +2,8 @@ local fs = require "nixio.fs"
local conffile = "/tmp/ssrpro.log"
f = SimpleForm("logview")
-
+f.reset = false
+f.submit = false
t = f:field(TextValue, "conf")
t.rmempty = true
t.rows = 20
@@ -12,4 +13,4 @@ function t.cfgvalue()
end
t.readonly="readonly"
-return f
\ No newline at end of file
+return f
diff --git a/package/lean/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm b/package/lean/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm
index 639ef70271..bc7f287172 100644
--- a/package/lean/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm
+++ b/package/lean/luci-app-ssr-plus/luasrc/view/shadowsocksr/ssrurl.htm
@@ -88,7 +88,7 @@
var s = document.getElementById(urlname + '-status');
if (!s)
return false;
- var ssrurl = prompt("在这里黏贴配置链接 ssr:// | ss:// | vmess://", "");
+ var ssrurl = prompt("在这里黏贴配置链接 ssr:// | ss:// | vmess:// | trojan://", "");
if (ssrurl == null || ssrurl == "") {
s.innerHTML = "用户取消";
return false;
@@ -97,7 +97,7 @@
//var ssu = ssrurl.match(/ssr:\/\/([A-Za-z0-9_-]+)/i);
var ssu = ssrurl.split('://');
console.log(ssu.length);
- if ((ssu[0] != "ssr" && ssu[0] != "ss" && ssu[0] != "vmess") || ssu[1] == "") {
+ if ((ssu[0] != "ssr" && ssu[0] != "ss" && ssu[0] != "vmess" && ssu[0] != "trojan") || ssu[1] == "") {
s.innerHTML = "无效格式";
return false;
}
@@ -170,6 +170,29 @@
s.innerHTML = "导入Shadowsocks配置信息成功";
return false;
+ } else if (ssu[0] == "trojan") {
+ var ploc = ssu[1].indexOf("#");
+ if (ploc > 0) {
+ url0 = ssu[1].substr(0, ploc);
+ param = ssu[1].substr(ploc + 1);
+ } else {
+ url0 = ssu[1]
+ }
+ var sstr = b64decsafe(url0);
+ document.getElementById('cbid.shadowsocksr.' + sid + '.type').value = "trojan";
+ document.getElementById('cbid.shadowsocksr.' + sid + '.type').dispatchEvent(event);
+ var team = sstr.split('@');
+ console.log(param);
+ var part1 = team[0].split(':');
+ var part2 = team[1].split(':');
+ document.getElementById('cbid.shadowsocksr.' + sid + '.server').value = part2[0];
+ document.getElementById('cbid.shadowsocksr.' + sid + '.server_port').value = part2[1];
+ document.getElementById('cbid.shadowsocksr.' + sid + '.password').value = part1[1];
+ if (param != undefined) {
+ document.getElementById('cbid.shadowsocksr.' + sid + '.alias').value = decodeURI(param);
+ }
+ s.innerHTML = "导入Trojan配置信息成功";
+ return false;
} else if (ssu[0] == "vmess") {
var sstr = b64DecodeUnicode(ssu[1]);
var ploc = sstr.indexOf("/?");
diff --git a/package/lean/luci-app-ssr-plus/po/zh-cn/ssr-plus.po b/package/lean/luci-app-ssr-plus/po/zh-cn/ssr-plus.po
index 7f92a7f6dc..e028dcb7b0 100644
--- a/package/lean/luci-app-ssr-plus/po/zh-cn/ssr-plus.po
+++ b/package/lean/luci-app-ssr-plus/po/zh-cn/ssr-plus.po
@@ -378,7 +378,7 @@ msgid "GFW List"
msgstr "GFW列表"
msgid "ShadowSocksR Plus+ Settings"
-msgstr "ShadowSocksR Plus+ 设置(支持SS/SSR/V2RAY)"
+msgstr "ShadowSocksR Plus+ 设置(支持SS/SSR/V2RAY/TROJAN)"
msgid "Main Server"
msgstr "主服务器"
@@ -516,10 +516,10 @@ msgid "Ping Latency"
msgstr "Ping延迟"
msgid "Bypass Domain List"
-msgstr "域名白名单"
+msgstr "不走代理的域名"
msgid "Black Domain List"
-msgstr "域名黑名单"
+msgstr "强制走代理的域名"
msgid "Update Subscribe List"
msgstr "更新订阅URL列表"
diff --git a/package/lean/luci-app-ssr-plus/root/etc/init.d/shadowsocksr b/package/lean/luci-app-ssr-plus/root/etc/init.d/shadowsocksr
index c66d1f9d5a..783b1ff24b 100755
--- a/package/lean/luci-app-ssr-plus/root/etc/init.d/shadowsocksr
+++ b/package/lean/luci-app-ssr-plus/root/etc/init.d/shadowsocksr
@@ -43,11 +43,10 @@ uci_get_by_type() {
add_cron()
{
- sed -i '/ssrplus.log/d' $CRON_FILE
- echo '0 1 * * * echo "" > /tmp/ssrplus.log' >> $CRON_FILE
- [ -n "$(grep -w "/usr/share/shadowsocksr/subscribe.sh" $CRON_FILE)" ] && sed -i '/\/usr\/share\/shadowsocksr\/subscribe.sh/d' $CRON_FILE
+ sed -i '/shadowsocksr/d' $CRON_FILE
+ sed -i '/ssrplus.log/d' $CRON_FILE && echo '0 1 * * * echo "" > /tmp/ssrplus.log' >> $CRON_FILE
[ $(uci_get_by_type server_subscribe auto_update 0) -eq 1 ] && echo "0 $(uci_get_by_type server_subscribe auto_update_time) * * * /usr/share/shadowsocksr/subscribe.sh" >> $CRON_FILE
- [ -z "$(grep -w "/usr/share/shadowsocksr/update.sh" $CRON_FILE)" ] && echo "0 5 * * * /usr/share/shadowsocksr/update.sh" >> $CRON_FILE
+ [ $(uci_get_by_type server_subscribe auto_update 0) -eq 1 ] && echo "0 5 * * * /usr/share/shadowsocksr/update.sh" >> $CRON_FILE
crontab $CRON_FILE
}
@@ -67,7 +66,7 @@ gen_config_file() {
elif [ "$host" != "${host#*:[0-9a-fA-F]}" ] ;then
hostip=${host}
else
- hostip=`nslookup ${host} | grep 'Address 1' | sed 's/Address 1: //g'`
+ hostip=`ping ${host} -s 1 -c 1 | grep PING | cut -d'(' -f 2 | cut -d')' -f1`
if echo $hostip|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then
hostip=${hostip}
else
@@ -125,6 +124,9 @@ EOF
elif [ "$stype" == "v2ray" ] ;then
lua /usr/share/shadowsocksr/genv2config.lua $GLOBAL_SERVER tcp $(uci_get_by_name $1 local_port) > /var/etc/v2-ssr-retcp.json
sed -i 's/\\//g' /var/etc/v2-ssr-retcp.json
+ elif [ "$stype" == "trojan" ] ;then
+ lua /usr/share/shadowsocksr/gentrojanconfig.lua $GLOBAL_SERVER nat $(uci_get_by_name $1 local_port) > /var/etc/trojan-ssr-retcp.json
+ sed -i 's/\\//g' /var/etc/trojan-ssr-retcp.json
fi
}
@@ -143,7 +145,7 @@ start_rules() {
elif [ "$server" != "${server#*:[0-9a-fA-F]}" ] ;then
server=${server}
else
- server=`nslookup ${server} | grep 'Address 1' | sed 's/Address 1: //g'`
+ server=`ping ${server} -s 1 -c 1 | grep PING | cut -d'(' -f 2 | cut -d')' -f1`
if echo $server|grep -E "^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$">/dev/null; then
echo $server >/etc/ssr_ip
else
@@ -265,7 +267,7 @@ server {
}
EOF
- /usr/sbin/pdnsd -c /var/etc/pdnsd.conf &
+ /usr/sbin/pdnsd -c /var/etc/pdnsd.conf -d
}
@@ -301,6 +303,8 @@ start_redir() {
sscmd="/usr/bin/ssr-redir"
elif [ "$stype" == "v2ray" ] ;then
sscmd="/usr/bin/v2ray/v2ray"
+ elif [ "$stype" == "trojan" ] ;then
+ sscmd="/usr/sbin/trojan"
fi
local utype=$(uci_get_by_name $UDP_RELAY_SERVER type)
@@ -310,6 +314,8 @@ start_redir() {
ucmd="/usr/bin/ssr-redir"
elif [ "$utype" == "v2ray" ] ;then
ucmd="/usr/bin/v2ray/v2ray"
+ elif [ "$utype" == "trojan" ] ;then
+ ucmd="/usr/sbin/trojan"
fi
if [ "$(uci_get_by_type global threads 0)" = "0" ] ;then
@@ -330,6 +336,9 @@ start_redir() {
elif [ "$stype" == "v2ray" ] ;then
$sscmd -config /var/etc/v2-ssr-retcp.json >/dev/null 2>&1 &
echo "$(date "+%Y-%m-%d %H:%M:%S") $($sscmd -version | head -1) Started!" >> /tmp/ssrplus.log
+ elif [ "$stype" == "trojan" ] ;then
+ $sscmd --config /var/etc/trojan-ssr-retcp.json >/dev/null 2>&1 &
+ echo "$(date "+%Y-%m-%d %H:%M:%S") $($sscmd --version 2>&1 | head -1) Started!" >> /tmp/ssrplus.log
fi
if [ -n "$UDP_RELAY_SERVER" ] ;then
@@ -346,7 +355,12 @@ start_redir() {
elif [ "$utype" == "v2ray" ] ; then
lua /usr/share/shadowsocksr/genv2config.lua $UDP_RELAY_SERVER udp $(uci_get_by_name $UDP_RELAY_SERVER local_port) > /var/etc/v2-ssr-reudp.json
sed -i 's/\\//g' /var/etc/v2-ssr-reudp.json
- $ucmd -config /var/etc/v2-ssr-reudp.json >/dev/null 2>&1 &
+ $ucmd -config /var/etc/v2-ssr-reudp.json >/dev/null 2>&1 &
+ elif [ "$stype" == "trojan" ] ;then
+ lua /usr/share/shadowsocksr/gentrojanconfig.lua $GLOBAL_SERVER client 10801 > /var/etc/trojan-ssr-reudp.json
+ sed -i 's/\\//g' /var/etc/trojan-ssr-reudp.json
+ $ucmd --config /var/etc/trojan-ssr-reudp.json >/dev/null 2>&1 &
+ ipt2socks -U -4 -b 0.0.0.0 -s 127.0.0.1 -p 10801 -l $(uci_get_by_name $UDP_RELAY_SERVER local_port) >/dev/null 2>&1 &
fi
fi
@@ -537,10 +551,16 @@ stop() {
killall -q -9 ss-redir
killall -q -9 ssr-redir
killall -q -9 v2ray
+ killall -q -9 trojan
+ killall -q -9 ipt2socks
killall -q -9 ssr-server
killall -q -9 kcptun-client
killall -q -9 ssr-local
- killall -q -9 pdnsd
+ if [ -f /var/run/pdnsd.pid ] ;then
+ kill $(cat /var/run/pdnsd.pid) >/dev/null 2>&1
+ else
+ kill -9 $(busybox ps -w | grep pdnsd | grep -v grep | awk '{print $1}') >/dev/null 2>&1
+ fi
if [ -f "/tmp/dnsmasq.d/dnsmasq-ssr.conf" ]; then
rm -f /tmp/dnsmasq.d/dnsmasq-ssr.conf
diff --git a/package/lean/luci-app-ssr-plus/root/usr/share/shadowsocksr/gentrojanconfig.lua b/package/lean/luci-app-ssr-plus/root/usr/share/shadowsocksr/gentrojanconfig.lua
new file mode 100644
index 0000000000..9d85bc41d0
--- /dev/null
+++ b/package/lean/luci-app-ssr-plus/root/usr/share/shadowsocksr/gentrojanconfig.lua
@@ -0,0 +1,38 @@
+local ucursor = require "luci.model.uci".cursor()
+local json = require "luci.jsonc"
+local server_section = arg[1]
+local proto = arg[2]
+local local_port = arg[3]
+
+local server = ucursor:get_all("shadowsocksr", server_section)
+
+local trojan = {
+ log_level = 3,
+ run_type = proto,
+ local_addr = "0.0.0.0",
+ local_port = tonumber(local_port),
+ remote_addr = server.server,
+ remote_port = tonumber(server.server_port),
+ udp_timeout = 60,
+ -- 传入连接
+ password = {server.password},
+ -- 传出连接
+ ssl = {
+ verify = false,
+ verify_hostname = (server.tls == "1") and false or true,
+ cert = "",
+ ciper = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:RSA-AES128-GCM-SHA256:RSA-AES256-GCM-SHA384:RSA-AES128-SHA:RSA-AES256-SHA:RSA-3DES-EDE-SHA",
+ sni = server.tls_host,
+ alpn = {"h2", "http/1.1"},
+ curve = "",
+ reuse_session = true,
+ session_ticket = false,
+ },
+ tcp = {
+ no_delay = true,
+ keep_alive = true,
+ fast_open = (server.fast_open == "1") and true or false,
+ fast_open_qlen = 20
+ }
+}
+print(json.stringify(trojan, 1))
diff --git a/package/lean/luci-app-unblockmusic/Makefile b/package/lean/luci-app-unblockmusic/Makefile
index a50de73a3b..f8cdfe9c74 100644
--- a/package/lean/luci-app-unblockmusic/Makefile
+++ b/package/lean/luci-app-unblockmusic/Makefile
@@ -11,7 +11,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-unblockmusic
PKG_VERSION:=2.2.0
-PKG_RELEASE:=9
+PKG_RELEASE:=11
PKG_LICENSE:=Apache-2.0
diff --git a/package/lean/luci-app-unblockmusic/root/etc/init.d/unblockmusic b/package/lean/luci-app-unblockmusic/root/etc/init.d/unblockmusic
index 5be5239562..9ff4963a2f 100755
--- a/package/lean/luci-app-unblockmusic/root/etc/init.d/unblockmusic
+++ b/package/lean/luci-app-unblockmusic/root/etc/init.d/unblockmusic
@@ -25,7 +25,7 @@ add_rule()
$ipt_n -A cloud_music -d 192.168.0.0/16 -j RETURN
$ipt_n -A cloud_music -d 224.0.0.0/4 -j RETURN
$ipt_n -A cloud_music -d 240.0.0.0/4 -j RETURN
- $ipt_n -A cloud_music -p tcp -j REDIRECT --to-ports 5202
+ $ipt_n -A cloud_music -p tcp -j REDIRECT --to-ports 5200
$ipt_n -I PREROUTING -p tcp --dport 80 -m set --match-set music dst -j cloud_music
}
@@ -41,7 +41,7 @@ del_rule(){
set_firewall(){
rm -f /tmp/dnsmasq.d/dnsmasq-163.conf
mkdir -p /tmp/dnsmasq.d
- echo "dhcp-option=252,http://$ROUTE_IP:5200/proxy.pac" > /tmp/dnsmasq.d/dnsmasq-163.conf
+ echo "dhcp-option=252,http://$ROUTE_IP:5201/proxy.pac" > /tmp/dnsmasq.d/dnsmasq-163.conf
echo "ipset=/music.163.com/music" >> /tmp/dnsmasq.d/dnsmasq-163.conf
echo "ipset=/interface.music.163.com/music" >> /tmp/dnsmasq.d/dnsmasq-163.conf
/etc/init.d/dnsmasq restart >/dev/null 2>&1
@@ -82,11 +82,11 @@ start()
fi
if [ $TYPE = "default" ]; then
- node /usr/share/UnblockNeteaseMusic/app.js $endponintset -p 5200:5201 >/tmp/unblockmusic.log 2>&1 &
- node /usr/share/UnblockNeteaseMusic/app.js -p 5202 >>/tmp/unblockmusic.log 2>&1 &
+ node /usr/share/UnblockNeteaseMusic/app.js $endponintset -p 5201:5202 >/tmp/unblockmusic.log 2>&1 &
+ node /usr/share/UnblockNeteaseMusic/app.js -p 5200 >>/tmp/unblockmusic.log 2>&1 &
else
- node /usr/share/UnblockNeteaseMusic/app.js $endponintset -p 5200:5201 -o $TYPE >/tmp/unblockmusic.log 2>&1 &
- node /usr/share/UnblockNeteaseMusic/app.js -p 5202 -o $TYPE >>/tmp/unblockmusic.log 2>&1 &
+ node /usr/share/UnblockNeteaseMusic/app.js $endponintset -p 5201:5202 -o $TYPE >/tmp/unblockmusic.log 2>&1 &
+ node /usr/share/UnblockNeteaseMusic/app.js -p 5200 -o $TYPE >>/tmp/unblockmusic.log 2>&1 &
fi
set_firewall
diff --git a/package/lean/luci-app-unblockmusic/root/lib/upgrade/keep.d/unblockmusic b/package/lean/luci-app-unblockmusic/root/lib/upgrade/keep.d/unblockmusic
new file mode 100644
index 0000000000..4f44321e28
--- /dev/null
+++ b/package/lean/luci-app-unblockmusic/root/lib/upgrade/keep.d/unblockmusic
@@ -0,0 +1,3 @@
+/usr/share/UnblockNeteaseMusic/ca.crt
+/usr/share/UnblockNeteaseMusic/server.crt
+/usr/share/UnblockNeteaseMusic/server.key
\ No newline at end of file
diff --git a/package/lean/luci-app-unblockmusic/root/usr/share/UnblockNeteaseMusic/logcheck.sh b/package/lean/luci-app-unblockmusic/root/usr/share/UnblockNeteaseMusic/logcheck.sh
index 168020537d..4d8eb1001e 100755
--- a/package/lean/luci-app-unblockmusic/root/usr/share/UnblockNeteaseMusic/logcheck.sh
+++ b/package/lean/luci-app-unblockmusic/root/usr/share/UnblockNeteaseMusic/logcheck.sh
@@ -1,11 +1,11 @@
#!/bin/bash
-log_max_size="10" #使用KB计算
+log_max_size="100" #使用KB计算
log_file="/tmp/unblockmusic.log"
while true
do
- sleep 10s
+ sleep 30s
icount=`busybox ps -w | grep app.js |grep -v grep| wc -l`
if [ $icount -ne 2 ] ;then
/etc/init.d/unblockmusic restart
diff --git a/package/lean/luci-app-unblockmusic/root/usr/share/UnblockNeteaseMusic/update_core.sh b/package/lean/luci-app-unblockmusic/root/usr/share/UnblockNeteaseMusic/update_core.sh
index 51705698b8..649c5ac603 100755
--- a/package/lean/luci-app-unblockmusic/root/usr/share/UnblockNeteaseMusic/update_core.sh
+++ b/package/lean/luci-app-unblockmusic/root/usr/share/UnblockNeteaseMusic/update_core.sh
@@ -10,7 +10,7 @@ function clean_log(){
}
function check_latest_version(){
- latest_ver="$(wget -O- https://github.com/nondanee/UnblockNeteaseMusic/commits/master |tr -d '\n' |grep -Eo 'commit\/[0-9a-z]+' |sed -n 1p |sed 's#commit/##g')"
+ latest_ver="$(wget-ssl --no-check-certificate -O- https://github.com/nondanee/UnblockNeteaseMusic/commits/master |tr -d '\n' |grep -Eo 'commit\/[0-9a-z]+' |sed -n 1p |sed 's#commit/##g')"
[ -z "${latest_ver}" ] && echo -e "\nFailed to check latest version, please try again later." >>/tmp/unblockmusic_update.log && exit 1
if [ ! -e "/usr/share/UnblockNeteaseMusic/local_ver" ]; then
clean_log
diff --git a/package/lean/qBittorrent/Makefile b/package/lean/qBittorrent/Makefile
index 5e3650c6ea..3bd02e2658 100644
--- a/package/lean/qBittorrent/Makefile
+++ b/package/lean/qBittorrent/Makefile
@@ -1,14 +1,14 @@
include $(TOPDIR)/rules.mk
-PKG_NAME:=qBittorrent
-PKG_VERSION:=4.1.8
-PKG_RELEASE=1
+PKG_NAME:=qbittorrent
+PKG_VERSION:=4.1.9
+PKG_RELEASE=5
-PKG_SOURCE_PROTO:=git
-PKG_SOURCE_URL:=https://github.com/qbittorrent/qBittorrent.git
-PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
-PKG_SOURCE_VERSION:=0de5cbaa4becf4eb89245324cb76c9a7c9412a33
-PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE:=$(PKG_NAME)-release-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://codeload.github.com/qbittorrent/qBittorrent/tar.gz/release-$(PKG_VERSION)?
+PKG_HASH:=620127f73f88ed3f2b2e4195cbc641f7c27f967d3b045e45f7916c0995fd61fe
+
+PKG_BUILD_DIR:=$(BUILD_DIR)/qBittorrent-release-$(PKG_VERSION)
PKG_LICENSE:=GPL-2.0+
PKG_LICENSE_FILES:=COPYING
@@ -36,17 +36,19 @@ there. qBittorrent is fast, stable and provides unicode support as
well as many features.
endef
-CONFIGURE_VARS += \
- QT_QMAKE="$(TOOLCHAIN_DIR)/bin" \
- PKG_CONFIG_PATH="$(TOOLCHAIN_DIR)/lib/pkgconfig"
-
CONFIGURE_ARGS += \
--disable-gui \
+ --enable-stacktrace=no \
--with-boost=$(STAGING_DIR)/usr
MAKE_VARS += \
INSTALL_ROOT="$(PKG_INSTALL_DIR)"
+define Build/Prepare
+ $(call Build/Prepare/Default)
+ $(SED) '//{:a;N;/<\/context>/!ba;/\/gui\//d}' `ls $(PKG_BUILD_DIR)/src/lang/qbittorrent_*.ts`
+endef
+
define Package/qBittorrent/install
$(INSTALL_DIR) $(1)/usr/man/man1
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/man/man1/qbittorrent-nox.1 $(1)/usr/man/man1/qbittorrent-nox.1
diff --git a/package/lean/qBittorrent/patches/001-remove-ico-not-for-webui.patch b/package/lean/qBittorrent/patches/001-remove-ico-not-for-webui.patch
new file mode 100644
index 0000000000..ee27bbaca4
--- /dev/null
+++ b/package/lean/qBittorrent/patches/001-remove-ico-not-for-webui.patch
@@ -0,0 +1,126 @@
+--- a/src/icons/icons.qrc
++++ b/src/icons/icons.qrc
+@@ -250,38 +250,16 @@
+ flags/zm.svg
+ flags/zw.svg
+ L.gif
+- loading.png
+ qbt-theme/application-exit.svg
+- qbt-theme/application-rss+xml.svg
+- qbt-theme/application-x-mswinurl.svg
+ qbt-theme/checked.svg
+ qbt-theme/configure.svg
+- qbt-theme/dialog-cancel.svg
+- qbt-theme/dialog-information.svg
+- qbt-theme/dialog-warning.svg
+ qbt-theme/document-edit-verify.svg
+ qbt-theme/document-edit.svg
+- qbt-theme/document-encrypt.svg
+- qbt-theme/document-import.svg
+- qbt-theme/document-new.svg
+- qbt-theme/document-properties.svg
+- qbt-theme/document-save.svg
+- qbt-theme/download.svg
+- qbt-theme/edit-clear-history.svg
+ qbt-theme/edit-clear.svg
+ qbt-theme/edit-copy.svg
+- qbt-theme/edit-cut.svg
+ qbt-theme/edit-delete.svg
+- qbt-theme/edit-find-user.svg
+ qbt-theme/edit-find.svg
+- qbt-theme/edit-paste.svg
+ qbt-theme/edit-rename.svg
+- qbt-theme/folder-documents.svg
+- qbt-theme/folder-download.svg
+- qbt-theme/folder-new.svg
+- qbt-theme/folder-remote.svg
+- qbt-theme/gear.svg
+- qbt-theme/gear32.svg
+ qbt-theme/go-bottom.svg
+ qbt-theme/go-down.svg
+ qbt-theme/go-top.svg
+@@ -295,43 +273,15 @@
+ qbt-theme/kt-set-max-upload-speed.png
+ qbt-theme/list-add.svg
+ qbt-theme/list-remove.svg
+- qbt-theme/mail-folder-inbox.svg
+- qbt-theme/mail-mark-read.svg
+ qbt-theme/media-playback-pause.svg
+ qbt-theme/media-playback-start.svg
+ qbt-theme/media-seek-forward.svg
+- qbt-theme/network-server.svg
+- qbt-theme/network-wired.svg
+- qbt-theme/object-locked.svg
+- qbt-theme/office-chart-line.svg
+- qbt-theme/preferences-desktop.svg
+- qbt-theme/preferences-other.svg
+- qbt-theme/preferences-system-network.svg
+- qbt-theme/preferences-web-browser-cookies.svg
+- qbt-theme/rss-config.png
+ qbt-theme/security-high.svg
+ qbt-theme/security-low.svg
+- qbt-theme/services.svg
+- qbt-theme/speedometer.svg
+ qbt-theme/system-log-out.svg
+- qbt-theme/tab-close.svg
+- qbt-theme/task-attention.svg
+- qbt-theme/task-complete.png
+- qbt-theme/task-ongoing.png
+- qbt-theme/task-reject.png
+- qbt-theme/text-plain.svg
+- qbt-theme/tools-report-bug.svg
+- qbt-theme/unavailable.svg
+- qbt-theme/user-group-delete.svg
+- qbt-theme/user-group-new.svg
+- qbt-theme/view-calendar-journal.svg
+ qbt-theme/view-categories.svg
+- qbt-theme/view-filter.svg
+- qbt-theme/view-preview.svg
+- qbt-theme/view-refresh.svg
+ qbt-theme/view-statistics.svg
+ qbt-theme/wallet-open.svg
+- qbt-theme/webui.svg
+ skin/arrow-right.gif
+ skin/bg-dropdown.gif
+ skin/bg-handle-horizontal.gif
+@@ -342,7 +292,6 @@
+ skin/completed.svg
+ skin/connected.svg
+ skin/disconnected.svg
+- skin/dock-tabs.gif
+ skin/download.svg
+ skin/downloading.svg
+ skin/error.svg
+@@ -353,14 +302,11 @@
+ skin/handle-icon-horizontal.gif
+ skin/handle-icon.gif
+ skin/knob.gif
+- skin/logo-blank.gif
+ skin/logo.gif
+ skin/logo2.gif
+ skin/mascot.png
+ skin/paused.svg
+ skin/qbittorrent-tray.svg
+- skin/qbittorrent-tray-dark.svg
+- skin/qbittorrent-tray-light.svg
+ skin/qbittorrent32.png
+ skin/queued.svg
+ skin/ratio.svg
+@@ -370,17 +316,12 @@
+ skin/spacer.gif
+ skin/spinner-placeholder.gif
+ skin/spinner.gif
+- skin/splash.png
+ skin/stalledDL.svg
+ skin/stalledUP.svg
+ skin/tabs.gif
+ skin/toolbox-divider.gif
+- skin/toolbox-divider2.gif
+ skin/uploading.svg
+ slow.png
+ slow_off.png
+- sphere.png
+- sphere2.png
+- url.png
+
+
diff --git a/package/lean/qBittorrent/patches/002-add-autoban-function.patch b/package/lean/qBittorrent/patches/002-add-autoban-function.patch
new file mode 100644
index 0000000000..8de0f1e47b
--- /dev/null
+++ b/package/lean/qBittorrent/patches/002-add-autoban-function.patch
@@ -0,0 +1,807 @@
+--- a/src/base/bittorrent/peerinfo.cpp
++++ b/src/base/bittorrent/peerinfo.cpp
+@@ -186,11 +186,26 @@ PeerAddress PeerInfo::address() const
+ m_nativeInfo.ip.port());
+ }
+
++int PeerInfo::port() const
++{
++ return m_nativeInfo.ip.port();
++}
++
+ QString PeerInfo::client() const
+ {
+ return QString::fromStdString(m_nativeInfo.client);
+ }
+
++QString PeerInfo::pid() const
++{
++ return QString::fromStdString(m_nativeInfo.pid.to_string());
++}
++
++QString PeerInfo::pidtoclient() const
++{
++ return QString::fromStdString(libt::identify_client(m_nativeInfo.pid));
++}
++
+ qreal PeerInfo::progress() const
+ {
+ return m_nativeInfo.progress;
+--- a/src/base/bittorrent/peerinfo.h
++++ b/src/base/bittorrent/peerinfo.h
+@@ -34,6 +34,7 @@
+ #include
+
+ #include
++#include
+
+ namespace BitTorrent
+ {
+@@ -85,7 +86,10 @@ namespace BitTorrent
+ bool isPlaintextEncrypted() const;
+
+ PeerAddress address() const;
++ int port() const;
+ QString client() const;
++ QString pid() const;
++ QString pidtoclient() const;
+ qreal progress() const;
+ int payloadUpSpeed() const;
+ int payloadDownSpeed() const;
+--- a/src/base/bittorrent/session.cpp
++++ b/src/base/bittorrent/session.cpp
+@@ -69,6 +69,7 @@
+ #endif
+
+ #include "base/algorithm.h"
++#include "base/bittorrent/peerinfo.h"
+ #include "base/exceptions.h"
+ #include "base/global.h"
+ #include "base/logger.h"
+@@ -335,6 +336,8 @@ Session::Session(QObject *parent)
+ , m_isAltGlobalSpeedLimitEnabled(BITTORRENT_SESSION_KEY("UseAlternativeGlobalSpeedLimit"), false)
+ , m_isBandwidthSchedulerEnabled(BITTORRENT_SESSION_KEY("BandwidthSchedulerEnabled"), false)
+ , m_saveResumeDataInterval(BITTORRENT_SESSION_KEY("SaveResumeDataInterval"), 60)
++ , m_autoBanUnknownPeer(BITTORRENT_SESSION_KEY("AutoBanUnknownPeer"), true)
++ , m_showTrackerAuthWindow(BITTORRENT_SESSION_KEY("ShowTrackerAuthWindow"), true)
+ , m_port(BITTORRENT_SESSION_KEY("Port"), 8999)
+ , m_useRandomPort(BITTORRENT_SESSION_KEY("UseRandomPort"), false)
+ , m_networkInterface(BITTORRENT_SESSION_KEY("Interface"))
+@@ -502,6 +505,7 @@ Session::Session(QObject *parent)
+ libt::ip_filter filter;
+ processBannedIPs(filter);
+ m_nativeSession->set_ip_filter(filter);
++ loadOfflineFilter();
+ }
+
+ m_categories = map_cast(m_storedCategories);
+@@ -518,6 +522,17 @@ Session::Session(QObject *parent)
+ connect(m_refreshTimer, &QTimer::timeout, this, &Session::refresh);
+ m_refreshTimer->start();
+
++ // Unban Timer
++ m_unbanTimer = new QTimer(this);
++ m_unbanTimer->setInterval(500);
++ connect(m_unbanTimer, &QTimer::timeout, this, &Session::processUnbanRequest);
++
++ // Ban Timer
++ m_banTimer = new QTimer(this);
++ m_banTimer->setInterval(500);
++ connect(m_banTimer, &QTimer::timeout, this, &Session::autoBanBadClient);
++ m_banTimer->start();
++
+ m_statistics = new Statistics(this);
+
+ updateSeedingLimitTimer();
+@@ -1077,6 +1092,7 @@ void Session::configure()
+ enableIPFilter();
+ else
+ disableIPFilter();
++ loadOfflineFilter();
+ m_IPFilteringChanged = false;
+ }
+
+@@ -1905,6 +1921,95 @@ void Session::banIP(const QString &ip)
+ }
+ }
+
++bool Session::checkAccessFlags(const QString &ip)
++{
++ libt::ip_filter filter = m_nativeSession->get_ip_filter();
++ boost::system::error_code ec;
++ libt::address addr = libt::address::from_string(ip.toLatin1().constData(), ec);
++ Q_ASSERT(!ec);
++ if (ec) return false;
++ return filter.access(addr);
++}
++
++void Session::tempblockIP(const QString &ip)
++{
++ libt::ip_filter filter = m_nativeSession->get_ip_filter();
++ boost::system::error_code ec;
++ libt::address addr = libt::address::from_string(ip.toLatin1().constData(), ec);
++ Q_ASSERT(!ec);
++ if (ec) return;
++ filter.add_rule(addr, addr, libt::ip_filter::blocked);
++ m_nativeSession->set_ip_filter(filter);
++ insertQueue(ip);
++}
++
++void Session::removeBlockedIP(const QString &ip)
++{
++ libt::ip_filter filter = m_nativeSession->get_ip_filter();
++ boost::system::error_code ec;
++ libt::address addr = libt::address::from_string(ip.toLatin1().constData(), ec);
++ Q_ASSERT(!ec);
++ if (ec) return;
++ filter.add_rule(addr, addr, 0);
++ m_nativeSession->set_ip_filter(filter);
++}
++
++void Session::eraseIPFilter()
++{
++ q_bannedIPs.clear();
++ q_unbanTime.clear();
++ if (isIPFilteringEnabled()) {
++ enableIPFilter();
++ } else {
++ disableIPFilter();
++ loadOfflineFilter();
++ }
++}
++
++void Session::autoBanBadClient()
++{
++ const BitTorrent::SessionStatus tStatus = BitTorrent::Session::instance()->status();
++ if (tStatus.peersCount > 0) {
++ bool m_AutoBan = BitTorrent::Session::instance()->isAutoBanUnknownPeerEnabled();
++ foreach (BitTorrent::TorrentHandle *const torrent, BitTorrent::Session::instance()->torrents()) {
++ QList peers = torrent->peers();
++ foreach (const BitTorrent::PeerInfo &peer, peers) {
++ BitTorrent::PeerAddress addr = peer.address();
++ if (addr.ip.isNull()) continue;
++ QString ip = addr.ip.toString();
++ int port = peer.port();
++ QString client = peer.client();
++ QString ptoc = peer.pidtoclient();
++ QString pid = peer.pid().left(8);
++ QString country = peer.country();
++
++ QRegExp IDFilter("-(XL|SD|XF|QD|BN|DL)(\\d+)-");
++ QRegExp UAFilter("\\d+.\\d+.\\d+.\\d+");
++ if (IDFilter.exactMatch(pid) || UAFilter.exactMatch(client)) {
++ qDebug("Auto Banning bad Peer %s...", ip.toLocal8Bit().data());
++ Logger::instance()->addMessage(tr("Auto banning bad Peer '%1'...'%2'...'%3'...'%4'").arg(ip).arg(pid).arg(ptoc).arg(country));
++ tempblockIP(ip);
++ continue;
++ }
++
++ if(m_AutoBan) {
++ if (client.contains("Unknown") && country == "CN") {
++ qDebug("Auto Banning Unknown Peer %s...", ip.toLocal8Bit().data());
++ Logger::instance()->addMessage(tr("Auto banning Unknown Peer '%1'...'%2'...'%3'...'%4'").arg(ip).arg(pid).arg(ptoc).arg(country));
++ tempblockIP(ip);
++ continue;
++ }
++ if (port >= 65000 && country == "CN" && client.contains("Transmission")) {
++ qDebug("Auto Banning Offline Downloader %s...", ip.toLocal8Bit().data());
++ Logger::instance()->addMessage(tr("Auto banning Offline Downloader '%1:%2'...'%3'...'%4'...'%5'").arg(ip).arg(port).arg(pid).arg(ptoc).arg(country));
++ tempblockIP(ip);
++ }
++ }
++ }
++ }
++ }
++}
++
+ // Delete a torrent from the session, given its hash
+ // deleteLocalFiles = true means that the torrent will be removed from the hard-drive too
+ bool Session::deleteTorrent(const QString &hash, bool deleteLocalFiles)
+@@ -2787,6 +2892,30 @@ void Session::setSaveResumeDataInterval(
+ }
+ }
+
++bool Session::isAutoBanUnknownPeerEnabled() const
++{
++ return m_autoBanUnknownPeer;
++}
++
++void Session::setAutoBanUnknownPeer(bool value)
++{
++ if (value != isAutoBanUnknownPeerEnabled()) {
++ m_autoBanUnknownPeer = value;
++ }
++}
++
++bool Session::isShowTrackerAuthWindow() const
++{
++ return m_showTrackerAuthWindow;
++}
++
++void Session::setShowTrackerAuthWindow(bool value)
++{
++ if (value != isShowTrackerAuthWindow()) {
++ m_showTrackerAuthWindow = value;
++ }
++}
++
+ int Session::port() const
+ {
+ static int randomPort = Utils::Random::rand(1024, 65535);
+@@ -3877,6 +4006,220 @@ void Session::disableIPFilter()
+ m_nativeSession->set_ip_filter(filter);
+ }
+
++// Insert banned IP to Queue
++void Session::insertQueue(QString ip)
++{
++ q_bannedIPs.enqueue(ip);
++ q_unbanTime.enqueue(QDateTime::currentMSecsSinceEpoch() + 60 * 60 * 1000);
++
++ if (!m_unbanTimer->isActive()) {
++ m_unbanTimer->start();
++ }
++}
++
++// Process Unban Queue
++void Session::processUnbanRequest()
++{
++ if (q_bannedIPs.isEmpty() && q_unbanTime.isEmpty()) {
++ m_unbanTimer->stop();
++ }
++ else if (m_isActive) {
++ return;
++ }
++ else {
++ m_isActive = true;
++ int64_t currentTime = QDateTime::currentMSecsSinceEpoch();
++ int64_t nextTime = q_unbanTime.dequeue();
++ int delayTime = int(nextTime - currentTime);
++ QString nextIP = q_bannedIPs.dequeue();
++ if (delayTime < 0) {
++ QTimer::singleShot(0, [=] { BitTorrent::Session::instance()->removeBlockedIP(nextIP); m_isActive = false; });
++ }
++ else {
++ QTimer::singleShot(delayTime, [=] { BitTorrent::Session::instance()->removeBlockedIP(nextIP); m_isActive = false; });
++ }
++ }
++}
++
++// Handle ipfilter.dat
++int trim(char* const data, int start, int end)
++{
++ if (start >= end) return start;
++ int newStart = start;
++
++ for (int i = start; i <= end; ++i) {
++ if (isspace(data[i]) != 0) {
++ data[i] = '\0';
++ }
++ else {
++ newStart = i;
++ break;
++ }
++ }
++
++ for (int i = end; i >= start; --i) {
++ if (isspace(data[i]) != 0)
++ data[i] = '\0';
++ else
++ break;
++ }
++
++ return newStart;
++}
++
++int findAndNullDelimiter(char *const data, char delimiter, int start, int end)
++{
++ for (int i = start; i <= end; ++i) {
++ if (data[i] == delimiter) {
++ data[i] = '\0';
++ return i;
++ }
++ }
++
++ return -1;
++}
++
++int Session::parseOfflineFilterFile(QString ipDat, libt::ip_filter &filter)
++{
++ int ruleCount = 0;
++ QFile file(ipDat);
++ if (!file.exists()) return ruleCount;
++
++ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
++ LogMsg(tr("I/O Error: Could not open IP filter file in read mode."), Log::CRITICAL);
++ return ruleCount;
++ }
++
++ std::vector buffer(2 * 1024 * 1024, 0); // seems a bit faster than QVector
++ qint64 bytesRead = 0;
++ int offset = 0;
++ int start = 0;
++ int endOfLine = -1;
++ int nbLine = 0;
++
++ while (true) {
++ bytesRead = file.read(buffer.data() + offset, 2 * 1024 * 1024 - offset - 1);
++ if (bytesRead < 0)
++ break;
++ int dataSize = bytesRead + offset;
++ if (bytesRead == 0 && dataSize == 0)
++ break;
++
++ for (start = 0; start < dataSize; ++start) {
++ endOfLine = -1;
++ // The file might have ended without the last line having a newline
++ if (!(bytesRead == 0 && dataSize > 0)) {
++ for (int i = start; i < dataSize; ++i) {
++ if (buffer[i] == '\n') {
++ endOfLine = i;
++ // We need to NULL the newline in case the line has only an IP range.
++ // In that case the parser won't work for the end IP, because it ends
++ // with the newline and not with a number.
++ buffer[i] = '\0';
++ break;
++ }
++ }
++ }
++ else {
++ endOfLine = dataSize;
++ buffer[dataSize] = '\0';
++ }
++
++ if (endOfLine == -1) {
++ // read the next chunk from file
++ // but first move(copy) the leftover data to the front of the buffer
++ offset = dataSize - start;
++ memmove(buffer.data(), buffer.data() + start, offset);
++ break;
++ }
++ else {
++ ++nbLine;
++ }
++
++ if ((buffer[start] == '#')
++ || ((buffer[start] == '/') && ((start + 1 < dataSize) && (buffer[start + 1] == '/')))) {
++ start = endOfLine;
++ continue;
++ }
++
++ // Each line should follow this format:
++ // 001.009.096.105 - 001.009.096.105 , 000 , Some organization
++ // The 3rd entry is access level and if above 127 the IP range isn't blocked.
++ int firstComma = findAndNullDelimiter(buffer.data(), ',', start, endOfLine);
++ if (firstComma != -1)
++ findAndNullDelimiter(buffer.data(), ',', firstComma + 1, endOfLine);
++
++ // Check if there is an access value (apparently not mandatory)
++ if (firstComma != -1) {
++ // There is possibly one
++ const long int nbAccess = strtol(buffer.data() + firstComma + 1, nullptr, 10);
++ // Ignoring this rule because access value is too high
++ if (nbAccess > 127L) {
++ start = endOfLine;
++ continue;
++ }
++ }
++
++ // IP Range should be split by a dash
++ int endOfIPRange = ((firstComma == -1) ? (endOfLine - 1) : (firstComma - 1));
++ int delimIP = findAndNullDelimiter(buffer.data(), '-', start, endOfIPRange);
++ if (delimIP == -1) {
++ start = endOfLine;
++ continue;
++ }
++
++ boost::system::error_code ec;
++ int newStart = trim(buffer.data(), start, delimIP - 1);
++ libt::address startAddr = libt::address::from_string(buffer.data() + newStart, ec);
++ Q_ASSERT(!ec);
++ if (ec) {
++ start = endOfLine;
++ continue;
++ }
++
++ newStart = trim(buffer.data(), delimIP + 1, endOfIPRange);
++ libt::address endAddr = libt::address::from_string(buffer.data() + newStart, ec);
++ Q_ASSERT(!ec);
++ if (ec) {
++ start = endOfLine;
++ continue;
++ }
++
++ if ((startAddr.is_v4() != endAddr.is_v4())
++ || (startAddr.is_v6() != endAddr.is_v6())) {
++ start = endOfLine;
++ continue;
++ }
++
++ start = endOfLine;
++
++ filter.add_rule(startAddr, endAddr, libt::ip_filter::blocked);
++ ++ruleCount;
++ }
++
++ if (start >= dataSize)
++ offset = 0;
++ }
++
++ return ruleCount;
++}
++
++void Session::loadOfflineFilter() {
++ int Count = 0;
++ libt::ip_filter offlineFilter = m_nativeSession->get_ip_filter();
++
++#if defined(Q_OS_WIN)
++ Count = parseOfflineFilterFile("./ipfilter.dat", offlineFilter);
++#endif
++
++#if (defined(Q_OS_UNIX) && !defined(Q_OS_MAC))
++ Count = parseOfflineFilterFile(QDir::home().absoluteFilePath(".config")+"/qBittorrent/ipfilter.dat", offlineFilter);
++#endif
++
++ m_nativeSession->set_ip_filter(offlineFilter);
++ Logger::instance()->addMessage(tr("Successfully parsed the offline downloader IP filter: %1 rules were applied.", "%1 is a number").arg(Count));
++}
++
+ void Session::recursiveTorrentDownload(const InfoHash &hash)
+ {
+ TorrentHandle *const torrent = m_torrents.value(hash);
+@@ -4063,6 +4406,7 @@ void Session::handleIPFilterParsed(int r
+ }
+ Logger::instance()->addMessage(tr("Successfully parsed the provided IP filter: %1 rules were applied.", "%1 is a number").arg(ruleCount));
+ emit IPFilterParsed(false, ruleCount);
++ loadOfflineFilter();
+ }
+
+ void Session::handleIPFilterError()
+--- a/src/base/bittorrent/session.h
++++ b/src/base/bittorrent/session.h
+@@ -40,8 +40,10 @@
+ #include
+ #include
+ #include
++#include
+ #include
+ #include
++#include
+ #include
+ #include
+
+@@ -341,6 +343,10 @@ namespace BitTorrent
+
+ uint saveResumeDataInterval() const;
+ void setSaveResumeDataInterval(uint value);
++ bool isAutoBanUnknownPeerEnabled() const;
++ void setAutoBanUnknownPeer(bool value);
++ bool isShowTrackerAuthWindow() const;
++ void setShowTrackerAuthWindow(bool value);
+ int port() const;
+ void setPort(int port);
+ bool useRandomPort() const;
+@@ -467,6 +473,19 @@ namespace BitTorrent
+ void setMaxRatioAction(MaxRatioAction act);
+
+ void banIP(const QString &ip);
++ bool checkAccessFlags(const QString &ip);
++ void tempblockIP(const QString &ip);
++ void removeBlockedIP(const QString &ip);
++ void eraseIPFilter();
++ void autoBanBadClient();
++
++ // Unban Timer
++ bool m_isActive = false;
++ QQueue q_bannedIPs;
++ QQueue q_unbanTime;
++ QTimer *m_unbanTimer;
++ QTimer *m_banTimer;
++ void insertQueue(QString ip);
+
+ bool isKnownTorrent(const InfoHash &hash) const;
+ bool addTorrent(QString source, const AddTorrentParams ¶ms = AddTorrentParams());
+@@ -546,6 +565,9 @@ namespace BitTorrent
+ void tagAdded(const QString &tag);
+ void tagRemoved(const QString &tag);
+
++ public slots:
++ void processUnbanRequest();
++
+ private slots:
+ void configureDeferred();
+ void readAlerts();
+@@ -601,6 +623,8 @@ namespace BitTorrent
+ void populateAdditionalTrackers();
+ void enableIPFilter();
+ void disableIPFilter();
++ int parseOfflineFilterFile(QString ipDat, libtorrent::ip_filter &filter);
++ void loadOfflineFilter();
+
+ bool addTorrent_impl(CreateTorrentParams params, const MagnetUri &magnetUri,
+ TorrentInfo torrentInfo = TorrentInfo(),
+@@ -713,6 +737,8 @@ namespace BitTorrent
+ CachedSettingValue m_isAltGlobalSpeedLimitEnabled;
+ CachedSettingValue m_isBandwidthSchedulerEnabled;
+ CachedSettingValue m_saveResumeDataInterval;
++ CachedSettingValue m_autoBanUnknownPeer;
++ CachedSettingValue m_showTrackerAuthWindow;
+ CachedSettingValue m_port;
+ CachedSettingValue m_useRandomPort;
+ CachedSettingValue m_networkInterface;
+--- a/src/base/bittorrent/torrenthandle.cpp
++++ b/src/base/bittorrent/torrenthandle.cpp
+@@ -1561,7 +1561,8 @@ void TorrentHandle::handleTrackerErrorAl
+ m_trackerInfos[trackerUrl].lastMessage = message;
+
+ if (p->status_code == 401)
+- m_session->handleTorrentTrackerAuthenticationRequired(this, trackerUrl);
++ if (Preferences::instance()->getShowTrackerAuthWindow())
++ m_session->handleTorrentTrackerAuthenticationRequired(this, trackerUrl);
+
+ m_session->handleTorrentTrackerError(this, trackerUrl);
+ }
+--- a/src/base/preferences.cpp
++++ b/src/base/preferences.cpp
+@@ -1090,6 +1090,26 @@ void Preferences::setTrayIconStyle(TrayI
+ }
+ #endif
+
++bool Preferences::getAutoBanUnknownPeer() const
++{
++ return value("Preferences/Advanced/AutoBanUnknownPeer", false).toBool();
++}
++
++void Preferences::setAutoBanUnknownPeer(const bool checked)
++{
++ setValue("Preferences/Advanced/AutoBanUnknownPeer", checked);
++}
++
++bool Preferences::getShowTrackerAuthWindow() const
++{
++ return value("Preferences/Advanced/ShowTrackerAuthWindow", true).toBool();
++}
++
++void Preferences::setShowTrackerAuthWindow(const bool checked)
++{
++ setValue("Preferences/Advanced/ShowTrackerAuthWindow", checked);
++}
++
+ // Stuff that don't appear in the Options GUI but are saved
+ // in the same file.
+
+--- a/src/base/preferences.h
++++ b/src/base/preferences.h
+@@ -300,6 +300,10 @@ public:
+ TrayIcon::Style trayIconStyle() const;
+ void setTrayIconStyle(TrayIcon::Style style);
+ #endif // Q_OS_MAC
++ bool getAutoBanUnknownPeer() const;
++ void setAutoBanUnknownPeer(const bool checked);
++ bool getShowTrackerAuthWindow() const;
++ void setShowTrackerAuthWindow(const bool checked);
+
+ // Stuff that don't appear in the Options GUI but are saved
+ // in the same file.
+--- a/src/base/settingsstorage.cpp
++++ b/src/base/settingsstorage.cpp
+@@ -91,6 +91,8 @@ namespace
+ {"BitTorrent/Session/InterfaceName", "Preferences/Connection/InterfaceName"},
+ {"BitTorrent/Session/InterfaceAddress", "Preferences/Connection/InterfaceAddress"},
+ {"BitTorrent/Session/SaveResumeDataInterval", "Preferences/Downloads/SaveResumeDataInterval"},
++ {"BitTorrent/Session/AutoBanUnknownPeer", "Preferences/Advanced/AutoBanUnknownPeer"},
++ {"BitTorrent/Session/ShowTrackerAuthWindow", "Preferences/Advanced/ShowTrackerAuthWindow"},
+ {"BitTorrent/Session/Encryption", "Preferences/Bittorrent/Encryption"},
+ {"BitTorrent/Session/ForceProxy", "Preferences/Connection/ProxyForce"},
+ {"BitTorrent/Session/ProxyPeerConnections", "Preferences/Connection/ProxyPeerConnections"},
+--- a/src/gui/advancedsettings.cpp
++++ b/src/gui/advancedsettings.cpp
+@@ -60,6 +60,8 @@ enum AdvSettingsRows
+ NETWORK_LISTEN_IPV6,
+ // behavior
+ SAVE_RESUME_DATA_INTERVAL,
++ CONFIRM_AUTO_BAN,
++ SHOW_TRACKER_AUTH_WINDOW,
+ CONFIRM_RECHECK_TORRENT,
+ RECHECK_COMPLETED,
+ #if defined(Q_OS_WIN) || defined(Q_OS_MAC)
+@@ -215,6 +217,10 @@ void AdvancedSettings::saveAdvancedSetti
+ // Announce IP
+ QHostAddress addr(lineEditAnnounceIP.text().trimmed());
+ session->setAnnounceIP(addr.isNull() ? "" : addr.toString());
++ // Auto ban Unknown Peer
++ session->setAutoBanUnknownPeer(cb_auto_ban_unknown_peer.isChecked());
++ // Show Tracker Authenticaion Window
++ session->setShowTrackerAuthWindow(cb_show_tracker_auth_window.isChecked());
+
+ // Program notification
+ MainWindow *const mainWindow = static_cast(QCoreApplication::instance())->mainWindow();
+@@ -465,6 +471,12 @@ void AdvancedSettings::loadAdvancedSetti
+ // Announce IP
+ lineEditAnnounceIP.setText(session->announceIP());
+ addRow(ANNOUNCE_IP, tr("IP Address to report to trackers (requires restart)"), &lineEditAnnounceIP);
++ // Auto Ban Unknown Peer from China
++ cb_auto_ban_unknown_peer.setChecked(session->isAutoBanUnknownPeerEnabled());
++ addRow(CONFIRM_AUTO_BAN, tr("Auto Ban Unknown Peer from China"), &cb_auto_ban_unknown_peer);
++ // Show Tracker Authenticaion Window
++ cb_show_tracker_auth_window.setChecked(session->isShowTrackerAuthWindow());
++ addRow(SHOW_TRACKER_AUTH_WINDOW, tr("Show Tracker Authenticaion Window"), &cb_show_tracker_auth_window);
+
+ // Program notifications
+ const MainWindow *const mainWindow = static_cast(QCoreApplication::instance())->mainWindow();
+--- a/src/gui/advancedsettings.h
++++ b/src/gui/advancedsettings.h
+@@ -65,7 +65,8 @@ private:
+ QCheckBox checkBoxOsCache, checkBoxRecheckCompleted, checkBoxResolveCountries, checkBoxResolveHosts, checkBoxSuperSeeding,
+ checkBoxProgramNotifications, checkBoxTorrentAddedNotifications, checkBoxTrackerFavicon, checkBoxTrackerStatus,
+ checkBoxConfirmTorrentRecheck, checkBoxConfirmRemoveAllTags, checkBoxListenIPv6, checkBoxAnnounceAllTrackers, checkBoxAnnounceAllTiers,
+- checkBoxGuidedReadCache, checkBoxMultiConnectionsPerIp, checkBoxSuggestMode, checkBoxCoalesceRW, checkBoxSpeedWidgetEnabled;
++ checkBoxGuidedReadCache, checkBoxMultiConnectionsPerIp, checkBoxSuggestMode, checkBoxCoalesceRW, checkBoxSpeedWidgetEnabled,
++ cb_auto_ban_unknown_peer, cb_show_tracker_auth_window;
+ QComboBox comboBoxInterface, comboBoxInterfaceAddress, comboBoxUtpMixedMode, comboBoxChokingAlgorithm, comboBoxSeedChokingAlgorithm;
+ QLineEdit lineEditAnnounceIP;
+
+--- a/src/gui/mainwindow.cpp
++++ b/src/gui/mainwindow.cpp
+@@ -73,6 +73,7 @@
+ #include "addnewtorrentdialog.h"
+ #include "application.h"
+ #include "autoexpandabledialog.h"
++#include "base/bittorrent/peerinfo.h"
+ #include "cookiesdialog.h"
+ #include "downloadfromurldialog.h"
+ #include "executionlogwidget.h"
+--- a/src/gui/properties/peerlistdelegate.h
++++ b/src/gui/properties/peerlistdelegate.h
+@@ -49,6 +49,7 @@ public:
+ CONNECTION,
+ FLAGS,
+ CLIENT,
++ PEERID,
+ PROGRESS,
+ DOWN_SPEED,
+ UP_SPEED,
+--- a/src/gui/properties/peerlistwidget.cpp
++++ b/src/gui/properties/peerlistwidget.cpp
+@@ -75,6 +75,7 @@ PeerListWidget::PeerListWidget(Propertie
+ m_listModel->setHeaderData(PeerListDelegate::FLAGS, Qt::Horizontal, tr("Flags"));
+ m_listModel->setHeaderData(PeerListDelegate::CONNECTION, Qt::Horizontal, tr("Connection"));
+ m_listModel->setHeaderData(PeerListDelegate::CLIENT, Qt::Horizontal, tr("Client", "i.e.: Client application"));
++ m_listModel->setHeaderData(PeerListDelegate::PEERID, Qt::Horizontal, tr("Peer ID", "i.e.: Client Peer ID"));
+ m_listModel->setHeaderData(PeerListDelegate::PROGRESS, Qt::Horizontal, tr("Progress", "i.e: % downloaded"));
+ m_listModel->setHeaderData(PeerListDelegate::DOWN_SPEED, Qt::Horizontal, tr("Down Speed", "i.e: Download speed"));
+ m_listModel->setHeaderData(PeerListDelegate::UP_SPEED, Qt::Horizontal, tr("Up Speed", "i.e: Upload speed"));
+@@ -288,8 +289,13 @@ void PeerListWidget::banSelectedPeers()
+ for (const QModelIndex &index : selectedIndexes) {
+ int row = m_proxyModel->mapToSource(index).row();
+ QString ip = m_listModel->data(m_listModel->index(row, PeerListDelegate::IP_HIDDEN)).toString();
++ QString client = m_listModel->data(m_listModel->index(row, PeerListDelegate::CLIENT)).toString();
++ QString peerid = m_listModel->data(m_listModel->index(row, PeerListDelegate::PEERID)).toString();
++ QHostAddress host;
++ host.setAddress(ip);
++ const QString countryName = Net::GeoIPManager::CountryName(Net::GeoIPManager::instance()->lookup(host));
+ qDebug("Banning peer %s...", ip.toLocal8Bit().data());
+- Logger::instance()->addMessage(tr("Manually banning peer '%1'...").arg(ip));
++ Logger::instance()->addMessage(tr("Manually banning peer '%1'...'%2'...'%3'...'%4'").arg(ip).arg(peerid).arg(client).arg(countryName));
+ BitTorrent::Session::instance()->banIP(ip);
+ }
+ // Refresh list
+@@ -398,6 +404,7 @@ QStandardItem *PeerListWidget::addPeer(c
+ m_listModel->setData(m_listModel->index(row, PeerListDelegate::FLAGS), peer.flags());
+ m_listModel->setData(m_listModel->index(row, PeerListDelegate::FLAGS), peer.flagsDescription(), Qt::ToolTipRole);
+ m_listModel->setData(m_listModel->index(row, PeerListDelegate::CLIENT), peer.client().toHtmlEscaped());
++ m_listModel->setData(m_listModel->index(row, PeerListDelegate::PEERID), peer.pid().left(8).toHtmlEscaped());
+ m_listModel->setData(m_listModel->index(row, PeerListDelegate::PROGRESS), peer.progress());
+ m_listModel->setData(m_listModel->index(row, PeerListDelegate::DOWN_SPEED), peer.payloadDownSpeed());
+ m_listModel->setData(m_listModel->index(row, PeerListDelegate::UP_SPEED), peer.payloadUpSpeed());
+@@ -429,6 +436,7 @@ void PeerListWidget::updatePeer(const QS
+ m_listModel->setData(m_listModel->index(row, PeerListDelegate::FLAGS), peer.flags());
+ m_listModel->setData(m_listModel->index(row, PeerListDelegate::FLAGS), peer.flagsDescription(), Qt::ToolTipRole);
+ m_listModel->setData(m_listModel->index(row, PeerListDelegate::CLIENT), peer.client().toHtmlEscaped());
++ m_listModel->setData(m_listModel->index(row, PeerListDelegate::PEERID), peer.pid().left(8).toHtmlEscaped());
+ m_listModel->setData(m_listModel->index(row, PeerListDelegate::PROGRESS), peer.progress());
+ m_listModel->setData(m_listModel->index(row, PeerListDelegate::DOWN_SPEED), peer.payloadDownSpeed());
+ m_listModel->setData(m_listModel->index(row, PeerListDelegate::UP_SPEED), peer.payloadUpSpeed());
+--- a/src/webui/api/appcontroller.cpp
++++ b/src/webui/api/appcontroller.cpp
+@@ -153,6 +153,7 @@ void AppController::preferencesAction()
+ data["ip_filter_path"] = Utils::Fs::toNativePath(session->IPFilterFile());
+ data["ip_filter_trackers"] = session->isTrackerFilteringEnabled();
+ data["banned_IPs"] = session->bannedIPs().join("\n");
++ data["auto_ban_unknown_peer"] = session->isAutoBanUnknownPeerEnabled();
+
+ // Speed
+ // Global Rate Limits
+@@ -401,6 +402,8 @@ void AppController::setPreferencesAction
+ session->setTrackerFilteringEnabled(m["ip_filter_trackers"].toBool());
+ if (m.contains("banned_IPs"))
+ session->setBannedIPs(m["banned_IPs"].toString().split('\n'));
++ if (m.contains("auto_ban_unknown_peer"))
++ session->setAutoBanUnknownPeer(m["auto_ban_unknown_peer"].toBool());
+
+ // Speed
+ // Global Rate Limits
+--- a/src/webui/api/transfercontroller.cpp
++++ b/src/webui/api/transfercontroller.cpp
+@@ -30,6 +30,7 @@
+
+ #include
+
++#include "base/logger.h"
+ #include "base/bittorrent/session.h"
+
+ const char KEY_TRANSFER_DLSPEED[] = "dl_info_speed";
+@@ -111,3 +112,37 @@ void TransferController::speedLimitsMode
+ {
+ setResult(QString::number(BitTorrent::Session::instance()->isAltGlobalSpeedLimitEnabled()));
+ }
++
++void TransferController::tempblockPeerAction()
++{
++ checkParams({"ip"});
++ QString ip = params()["ip"];
++ boost::system::error_code ec;
++ boost::asio::ip::address addr = boost::asio::ip::address::from_string(ip.toStdString(), ec);
++ bool isBanned = BitTorrent::Session::instance()->checkAccessFlags(QString::fromStdString(addr.to_string()));
++
++ if (ip.isEmpty()) {
++ setResult(QLatin1String("IP field should not be empty."));
++ return;
++ }
++
++ if (ec) {
++ setResult(QLatin1String("The given IP address is not valid."));
++ return;
++ }
++
++ if (isBanned) {
++ setResult(QLatin1String("The given IP address already exists."));
++ return;
++ }
++
++ BitTorrent::Session::instance()->tempblockIP(ip);
++ Logger::instance()->addMessage(tr("Peer '%1' banned via Web API.").arg(ip));
++ setResult(QLatin1String("Done."));
++}
++
++void TransferController::resetIPFilterAction()
++{
++ BitTorrent::Session::instance()->eraseIPFilter();
++ setResult(QLatin1String("Erased."));
++}
+--- a/src/webui/api/transfercontroller.h
++++ b/src/webui/api/transfercontroller.h
+@@ -46,4 +46,6 @@ private slots:
+ void downloadLimitAction();
+ void setUploadLimitAction();
+ void setDownloadLimitAction();
++ void tempblockPeerAction();
++ void resetIPFilterAction();
+ };
+--- a/src/webui/www/private/preferences_content.html
++++ b/src/webui/www/private/preferences_content.html
+@@ -377,6 +377,8 @@
+
+
+
++
++
+
+
+
+@@ -1252,6 +1254,7 @@
+ $('ipfilter_text').setProperty('value', pref.ip_filter_path);
+ $('ipfilter_trackers_checkbox').setProperty('checked', pref.ip_filter_trackers);
+ $('banned_IPs_textarea').setProperty('value', pref.banned_IPs);
++ $('auto_ban_unknown_peer_checkbox').setProperty('checked', pref.auto_ban_unknown_peer);
+ updateFilterSettings();
+
+ // Speed tab
+@@ -1502,6 +1505,7 @@
+ settings.set('ip_filter_path', $('ipfilter_text').getProperty('value'));
+ settings.set('ip_filter_trackers', $('ipfilter_trackers_checkbox').getProperty('checked'));
+ settings.set('banned_IPs', $('banned_IPs_textarea').getProperty('value'));
++ settings.set('auto_ban_unknown_peer', $('auto_ban_unknown_peer_checkbox').getProperty('checked'));
+
+ // Speed tab
+ // Global Rate Limits
diff --git a/package/lean/qt5/Makefile b/package/lean/qt5/Makefile
index 739bfb33f4..8d51639e12 100644
--- a/package/lean/qt5/Makefile
+++ b/package/lean/qt5/Makefile
@@ -1,136 +1,177 @@
#
-# Copyright (C) 2013 Riccardo Ferrazzo
-# Copyright (C) 2017 Paweł Knioła
+# Copyright (C) 2017-2019 Entware
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
+# ported to Entware from
+# https://github.com/KryptonLee/qBittorrent-openwrt-package and
+# https://github.com/pawelkn/qt5-openwrt-package
include $(TOPDIR)/rules.mk
PKG_NAME:=qt5
-PKG_VERSION:=5.13
+PKG_VERSION:=5.9.8
PKG_RELEASE:=1
-PKG_MD5SUM:=d66b1da335d0c25325fdf493e9044c38
-PKG_SOURCE:=qt-everywhere-src-$(PKG_VERSION).$(PKG_RELEASE).tar.xz
-PKG_SOURCE_URL:=http://download.qt-project.org/archive/qt/$(PKG_VERSION)/$(PKG_VERSION).$(PKG_RELEASE)/single
-PKG_BUILD_DIR=$(BUILD_DIR)/qt-everywhere-src-$(PKG_VERSION).$(PKG_RELEASE)
+PKG_SOURCE:=qt-everywhere-opensource-src-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=http://download.qt-project.org/archive/qt/5.9/$(PKG_VERSION)/single
+PKG_HASH:=86aca7dc37f161fc730a9d4f6bddf684962ca560327682e282ff61bf8b859c36
+
PKG_BUILD_PARALLEL:=1
PKG_USE_MIPS16:=0
+PKG_BUILD_DIR=$(BUILD_DIR)/qt-everywhere-opensource-src-$(PKG_VERSION)
include $(INCLUDE_DIR)/package.mk
+ifndef CONFIG_USE_GLIBC
# not using sstrip here as this fucks up the .so's somehow
STRIP:=/bin/true
RSTRIP:= \
- NM="$(TOOLCHAIN_DIR)/bin/$(TARGET_CROSS)nm" \
- STRIP="$(STRIP)" \
- STRIP_KMOD="$(STRIP)" \
- $(SCRIPT_DIR)/rstrip.sh
+ NM="$(TOOLCHAIN_DIR)/bin/$(TARGET_CROSS)nm" \
+ STRIP="$(STRIP)" \
+ STRIP_KMOD="$(STRIP)" \
+ $(SCRIPT_DIR)/rstrip.sh
+endif
define Package/qt5/Default
- SECTION:=libs
- CATEGORY:=Libraries
- SUBMENU:=Qt5
- TITLE:=qt5
- URL:=http://qt-project.org
- DEPENDS:=+libatomic +libstdcpp +libopenssl +zlib +icu @!LINUX_2_6
+ SECTION:=libs
+ CATEGORY:=Libraries
+ SUBMENU:=Qt5
+ TITLE:=qt5
+ URL:=http://qt-project.org
+ DEPENDS:=+librt +libstdcpp +libpthread @!LINUX_2_6_36
endef
define Package/qt5-core
- $(call Package/qt5/Default)
- TITLE+=core
-endef
-
-define Package/qt5-concurrent
- $(call Package/qt5/Default)
- TITLE+=concurrent
- DEPENDS+=+qt5-core
+ $(call Package/qt5/Default)
+ TITLE+=core
+ DEPENDS+=+libatomic +zlib +libpcre2-16 +libdouble-conversion
endef
define Package/qt5-network
- $(call Package/qt5/Default)
- TITLE+=network
- DEPENDS+=+qt5-core
-endef
-
-define Package/qt5-widgets
- $(call Package/qt5/Default)
- TITLE+=widgets
- DEPENDS+=+qt5-core +qt5-network
-endef
-
-define Package/qt5-sql
- $(call Package/qt5/Default)
- TITLE+=sql
- DEPENDS+=+qt5-core +libmariadbclient
+ $(call Package/qt5/Default)
+ TITLE+=network
+ DEPENDS+=+qt5-core +libopenssl
endef
define Package/qt5-xml
- $(call Package/qt5/Default)
- TITLE+=xml
- DEPENDS+=+qt5-core
+ $(call Package/qt5/Default)
+ TITLE+=xml
+ DEPENDS+=+qt5-core
endef
-define Package/qt5-serialport
- $(call Package/qt5/Default)
- TITLE+=serialport
- DEPENDS+=+qt5-core
-endef
-
-define Package/qt5-xmlpatterns
- $(call Package/qt5/Default)
- TITLE+=xmlpatterns
- DEPENDS+=+qt5-core +qt5-network
-endef
-
-define Package/qt5-test
- $(call Package/qt5/Default)
- TITLE+=test
- DEPENDS+=+qt5-core
-endef
+CONFIGURE_ARGS = \
+ -prefix /usr \
+ -sysroot $(STAGING_DIR) \
+ -plugindir /usr/lib/Qt/plugins \
+ -R /usr/lib \
+ -I $(STAGING_DIR)/usr/include \
+ -L $(STAGING_DIR)/usr/lib \
+ -xplatform linux-openwrt-g++ \
+ -release \
+ -shared \
+ -opensource \
+ -confirm-license \
+ -no-use-gold-linker \
+ -strip \
+ -ltcg \
+ -optimized-qmake \
+ -system-doubleconversion \
+ -no-glib \
+ -no-icu \
+ -system-pcre \
+ -system-zlib \
+ -no-slog2 \
+ -openssl-linked \
+ -no-cups \
+ -no-freetype \
+ -no-harfbuzz \
+ -no-gtk \
+ -no-opengl \
+ -no-opengles3 \
+ -no-angle \
+ -no-openvg \
+ -no-directfb \
+ -no-eglfs \
+ -no-egl \
+ -no-iconv \
+ -no-gbm \
+ -no-kms \
+ -no-xcb \
+ -no-pch \
+ -no-libudev \
+ -no-mtdev \
+ -no-tslib \
+ -no-xkbcommon-evdev \
+ -no-libpng \
+ -no-libjpeg \
+ -no-sql-db2 \
+ -no-sql-ibase \
+ -no-sql-mysql \
+ -no-sql-oci \
+ -no-sql-odbc \
+ -no-sql-psql \
+ -no-sql-sqlite \
+ -no-sql-sqlite2 \
+ -no-sqlite \
+ -no-sql-tds \
+ -no-gui \
+ -no-widgets \
+ -no-dbus \
+ -no-qml-debug \
+ -make libs \
+ -nomake examples \
+ -nomake tests \
+ -nomake tools \
+ -no-compile-examples \
+ -skip qt3d \
+ -skip qtactiveqt \
+ -skip qtandroidextras \
+ -skip qtcanvas3d \
+ -skip qtcharts \
+ -skip qtconnectivity \
+ -skip qtdatavis3d \
+ -skip qtdeclarative \
+ -skip qtdoc \
+ -skip qtgamepad \
+ -skip qtgraphicaleffects \
+ -skip qtimageformats \
+ -skip qtlocation \
+ -skip qtmacextras \
+ -skip qtmultimedia \
+ -skip qtnetworkauth \
+ -skip qtpurchasing \
+ -skip qtquickcontrols \
+ -skip qtquickcontrols2 \
+ -skip qtremoteobjects \
+ -skip qtscript \
+ -skip qtscxml \
+ -skip qtsensors \
+ -skip qtserialbus \
+ -skip qtserialport \
+ -skip qtspeech \
+ -skip qtsvg \
+ -skip qttranslations \
+ -skip qtvirtualkeyboard \
+ -skip qtwayland \
+ -skip qtwebchannel \
+ -skip qtwebengine \
+ -skip qtwebsockets \
+ -skip qtwebview \
+ -skip qtwinextras \
+ -skip qtx11extras \
+ -skip qtxmlpatterns \
+ -v
define Build/Configure
- $(INSTALL_DIR) $(PKG_BUILD_DIR)/qtbase/mkspecs/linux-openwrt-g++
- $(CP) ./files/qplatformdefs.h $(PKG_BUILD_DIR)/qtbase/mkspecs/linux-openwrt-g++/qplatformdefs.h
- $(CP) ./files/qmake.conf $(PKG_BUILD_DIR)/qtbase/mkspecs/linux-openwrt-g++/qmake.conf
$(SED) 's@$$$$(TARGET_CROSS)@$(TARGET_CROSS)@g' $(PKG_BUILD_DIR)/qtbase/mkspecs/linux-openwrt-g++/qmake.conf
- ( cd $(PKG_BUILD_DIR) ; \
- ./configure \
- -prefix $(TOOLCHAIN_DIR) \
- -xplatform linux-openwrt-g++ \
- -opensource \
- -confirm-license \
- -no-iconv \
- -no-pch \
- -no-rpath \
- -no-strip \
- -no-cups \
- -no-dbus \
- -no-eglfs \
- -no-kms \
- -no-opengl \
- -no-directfb \
- -no-xcb \
- -openssl-runtime \
- -qt-zlib \
- -qt-pcre \
- -qt-freetype \
- -make libs \
- -nomake examples \
- -nomake tools \
- -nomake tests \
- -skip qtdeclarative \
- -skip qtmultimedia \
- -skip activeqt \
- -skip qtdoc \
- -skip qtconnectivity \
- -skip wayland \
- -skip qtscript \
- -v \
- )
+ $(SED) 's@$$$$(TARGET_CFLAGS)@$(TARGET_CFLAGS)@g' $(PKG_BUILD_DIR)/qtbase/mkspecs/linux-openwrt-g++/qmake.conf
+ $(SED) 's@$$$$(TARGET_CXXFLAGS)@$(TARGET_CXXFLAGS)@g' $(PKG_BUILD_DIR)/qtbase/mkspecs/linux-openwrt-g++/qmake.conf
+ $(SED) 's@$$$$(TARGET_LDFLAGS)@$(TARGET_LDFLAGS)@g' $(PKG_BUILD_DIR)/qtbase/mkspecs/linux-openwrt-g++/qmake.conf
+
+ $(call Build/Configure/Default)
endef
define Build/Compile
@@ -139,95 +180,25 @@ endef
define Build/InstallDev
$(MAKE) -C $(PKG_BUILD_DIR) install
- $(CP) $(PKG_BUILD_DIR)/qtbase/bin/qmake $(TOOLCHAIN_DIR)/bin/
- $(CP) $(PKG_BUILD_DIR)/qtbase/bin/qt.conf $(TOOLCHAIN_DIR)/bin/
+ $(INSTALL_CONF) $(PKG_BUILD_DIR)/qtbase/bin/qt.conf $(STAGING_DIR)/usr/bin
+ $(RM) $(STAGING_DIR)/usr/bin/qt{attributionsscanner,paths,plugininfo}
endef
define Package/qt5-core/install
- $(INSTALL_DIR) $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Core.so* $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Core.prl $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Core.la $(1)/usr/lib/
-endef
-
-define Package/qt5-concurrent/install
- $(INSTALL_DIR) $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Concurrent.so* $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Concurrent.prl $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Concurrent.la $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Core.so* $(1)/usr/lib
endef
define Package/qt5-network/install
- $(INSTALL_DIR) $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Network.so* $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Network.prl $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Network.la $(1)/usr/lib/
-endef
-
-define Package/qt5-widgets/install
- $(INSTALL_DIR) $(1)/usr/lib/
- $(INSTALL_DIR) $(1)/usr/lib/Qt/plugins/generic/
- $(INSTALL_DIR) $(1)/usr/lib/Qt/plugins/platforms/
- $(INSTALL_DIR) $(1)/usr/lib/Qt/plugins/imageformats/
- $(INSTALL_DIR) $(1)/usr/lib/fonts/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Gui.so* $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Gui.prl $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Gui.la $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtsvg/lib/libQt5Svg.so* $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtsvg/lib/libQt5Svg.prl $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtsvg/lib/libQt5Svg.la $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Widgets.so* $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Widgets.prl $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Widgets.la $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/plugins/generic/*.so $(1)/usr/lib/Qt/plugins/generic/
- $(CP) $(PKG_BUILD_DIR)/qtbase/plugins/platforms/*.so $(1)/usr/lib/Qt/plugins/platforms/
- $(CP) $(PKG_BUILD_DIR)/qtbase/plugins/imageformats/*.so $(1)/usr/lib/Qt/plugins/imageformats/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/fonts/* $(1)/usr/lib/fonts/
-endef
-
-define Package/qt5-sql/install
- $(INSTALL_DIR) $(1)/usr/lib/
- $(INSTALL_DIR) $(1)/usr/lib/Qt/plugins/sqldrivers/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Sql.so* $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Sql.prl $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Sql.la $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/plugins/sqldrivers/*.so $(1)/usr/lib/Qt/plugins/sqldrivers/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Network.so* $(1)/usr/lib
endef
define Package/qt5-xml/install
- $(INSTALL_DIR) $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Xml.so* $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Xml.prl $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Xml.la $(1)/usr/lib/
+ $(INSTALL_DIR) $(1)/usr/lib
+ $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Xml.so* $(1)/usr/lib
endef
-define Package/qt5-serialport/install
- $(INSTALL_DIR) $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtserialport/lib/libQt5SerialPort.so* $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtserialport/lib/libQt5SerialPort.prl $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtserialport/lib/libQt5SerialPort.la $(1)/usr/lib/
-endef
-
-define Package/qt5-xmlpatterns/install
- $(INSTALL_DIR) $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtxmlpatterns/lib/libQt5XmlPatterns.so* $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtxmlpatterns/lib/libQt5XmlPatterns.prl $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtxmlpatterns/lib/libQt5XmlPatterns.la $(1)/usr/lib/
-endef
-
-define Package/qt5-test/install
- $(INSTALL_DIR) $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Test.so* $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Test.prl $(1)/usr/lib/
- $(CP) $(PKG_BUILD_DIR)/qtbase/lib/libQt5Test.la $(1)/usr/lib/
-endef
-
-$(eval $(call BuildPackage,qt5-core))
-$(eval $(call BuildPackage,qt5-concurrent))
+$(eval $(call BuildPackage,qt5-core,+zlib,+libpcre2-16,+libdouble-conversion))
$(eval $(call BuildPackage,qt5-network))
-$(eval $(call BuildPackage,qt5-widgets))
-$(eval $(call BuildPackage,qt5-sql))
$(eval $(call BuildPackage,qt5-xml))
-$(eval $(call BuildPackage,qt5-serialport))
-$(eval $(call BuildPackage,qt5-xmlpatterns))
-$(eval $(call BuildPackage,qt5-test))
diff --git a/package/lean/qt5/files/qplatformdefs.h b/package/lean/qt5/files/qplatformdefs.h
deleted file mode 100644
index aedffeb1ef..0000000000
--- a/package/lean/qt5/files/qplatformdefs.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the qmake spec of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "../linux-g++/qplatformdefs.h"
diff --git a/package/lean/qt5/patches/010-pre_3.6_kernels_fix.patch b/package/lean/qt5/patches/010-pre_3.6_kernels_fix.patch
new file mode 100644
index 0000000000..818e4efcdd
--- /dev/null
+++ b/package/lean/qt5/patches/010-pre_3.6_kernels_fix.patch
@@ -0,0 +1,74 @@
+--- a/qtserialbus/src/plugins/canbus/socketcan/socketcanbackend.cpp
++++ b/qtserialbus/src/plugins/canbus/socketcan/socketcanbackend.cpp
+@@ -33,7 +33,6 @@
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+-
+ #include "socketcanbackend.h"
+
+ #include
+@@ -50,29 +49,7 @@
+ #include
+ #include
+
+-#ifndef CANFD_MTU
+-// CAN FD support was added by Linux kernel 3.6
+-// For prior kernels we redefine the missing defines here
+-// they are taken from linux/can/raw.h & linux/can.h
+-
+-enum {
+- CAN_RAW_FD_FRAMES = 5
+-};
+-
+-#define CAN_MAX_DLEN 8
+-#define CANFD_MAX_DLEN 64
+-struct canfd_frame {
+- canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
+- __u8 len; /* frame payload length in byte */
+- __u8 flags; /* additional flags for CAN FD */
+- __u8 __res0; /* reserved / padding */
+- __u8 __res1; /* reserved / padding */
+- __u8 data[CANFD_MAX_DLEN] __attribute__((aligned(8)));
+-};
+-#define CAN_MTU (sizeof(struct can_frame))
+-#define CANFD_MTU (sizeof(struct canfd_frame))
+
+-#endif
+
+ #ifndef CANFD_BRS
+ # define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */
+--- a/qtserialbus/src/plugins/canbus/socketcan/socketcanbackend.h
++++ b/qtserialbus/src/plugins/canbus/socketcan/socketcanbackend.h
+@@ -45,6 +45,31 @@
+ #include
+ #include
+
++#ifndef CANFD_MTU
++// CAN FD support was added by Linux kernel 3.6
++// For prior kernels we redefine the missing defines here
++// they are taken from linux/can/raw.h & linux/can.h
++
++enum {
++ CAN_RAW_FD_FRAMES = 5
++};
++
++#define CAN_MAX_DLEN 8
++#define CANFD_MAX_DLEN 64
++struct canfd_frame {
++ canid_t can_id; /* 32 bit CAN_ID + EFF/RTR/ERR flags */
++ __u8 len; /* frame payload length in byte */
++ __u8 flags; /* additional flags for CAN FD */
++ __u8 __res0; /* reserved / padding */
++ __u8 __res1; /* reserved / padding */
++ __u8 data[CANFD_MAX_DLEN] __attribute__((aligned(8)));
++};
++#define CAN_MTU (sizeof(struct can_frame))
++#define CANFD_MTU (sizeof(struct canfd_frame))
++
++#endif
++
++
+ QT_BEGIN_NAMESPACE
+
+ class SocketCanBackend : public QCanBusDevice
diff --git a/package/lean/qt5/patches/020-disable_unused_libs.patch b/package/lean/qt5/patches/020-disable_unused_libs.patch
new file mode 100644
index 0000000000..e32bae7647
--- /dev/null
+++ b/package/lean/qt5/patches/020-disable_unused_libs.patch
@@ -0,0 +1,91 @@
+This patch disables prinstsupport, sql, concurrent, testlib base libs compilation
+--- a/qtbase/src/src.pro
++++ b/qtbase/src/src.pro
+@@ -66,22 +66,10 @@ src_dbus.target = sub-dbus
+ src_dbus.depends = src_corelib
+ force_dbus_bootstrap: src_dbus.depends += src_tools_bootstrap_dbus # avoid syncqt race
+
+-src_concurrent.subdir = $$PWD/concurrent
+-src_concurrent.target = sub-concurrent
+-src_concurrent.depends = src_corelib
+-
+-src_sql.subdir = $$PWD/sql
+-src_sql.target = sub-sql
+-src_sql.depends = src_corelib
+-
+ src_network.subdir = $$PWD/network
+ src_network.target = sub-network
+ src_network.depends = src_corelib
+
+-src_testlib.subdir = $$PWD/testlib
+-src_testlib.target = sub-testlib
+-src_testlib.depends = src_corelib # testlib links only to corelib, but see below for the headers
+-
+ src_3rdparty_pcre2.subdir = $$PWD/3rdparty/pcre2
+ src_3rdparty_pcre2.target = sub-3rdparty-pcre2
+
+@@ -125,13 +113,6 @@ src_openglextensions.subdir = $$PWD/open
+ src_openglextensions.target = sub-openglextensions
+ src_openglextensions.depends = src_gui
+
+-src_printsupport.subdir = $$PWD/printsupport
+-src_printsupport.target = sub-printsupport
+-src_printsupport.depends = src_corelib src_gui src_widgets src_tools_uic
+-
+-src_plugins.subdir = $$PWD/plugins
+-src_plugins.target = sub-plugins
+-
+ src_android.subdir = $$PWD/android
+
+ # this order is important
+@@ -152,14 +133,8 @@ TOOLS = src_tools_moc src_tools_rcc src_
+ win32:SUBDIRS += src_winmain
+ qtConfig(network) {
+ SUBDIRS += src_network
+- src_plugins.depends += src_network
+-}
+-qtConfig(sql) {
+- SUBDIRS += src_sql
+- src_plugins.depends += src_sql
+ }
+ qtConfig(xml): SUBDIRS += src_xml
+-qtConfig(testlib): SUBDIRS += src_testlib
+ qtConfig(dbus) {
+ force_dbus_bootstrap|qtConfig(private_tests): \
+ SUBDIRS += src_tools_bootstrap_dbus
+@@ -167,9 +142,7 @@ qtConfig(dbus) {
+ TOOLS += src_tools_qdbusxml2cpp src_tools_qdbuscpp2xml
+ qtConfig(accessibility-atspi-bridge): \
+ src_platformsupport.depends += src_dbus src_tools_qdbusxml2cpp
+- src_plugins.depends += src_dbus src_tools_qdbusxml2cpp src_tools_qdbuscpp2xml
+ }
+-qtConfig(concurrent): SUBDIRS += src_concurrent
+ qtConfig(gui) {
+ qtConfig(harfbuzz):!qtConfig(system-harfbuzz) {
+ SUBDIRS += src_3rdparty_harfbuzzng
+@@ -190,24 +163,17 @@ qtConfig(gui) {
+ }
+ SUBDIRS += src_gui src_platformsupport src_platformheaders
+ qtConfig(opengl): SUBDIRS += src_openglextensions
+- src_plugins.depends += src_gui src_platformsupport src_platformheaders
+- src_testlib.depends += src_gui # if QtGui is enabled, QtTest requires QtGui's headers
+ qtConfig(widgets) {
+ SUBDIRS += src_tools_uic src_widgets
+ !android-embedded: SUBDIRS += src_printsupport
+ TOOLS += src_tools_uic
+- src_plugins.depends += src_widgets
+- !android-embedded: src_plugins.depends += src_printsupport
+- src_testlib.depends += src_widgets # if QtWidgets is enabled, QtTest requires QtWidgets's headers
+ qtConfig(opengl) {
+ SUBDIRS += src_opengl
+- src_plugins.depends += src_opengl
+ }
+ }
+ }
+-SUBDIRS += src_plugins
+
+-nacl: SUBDIRS -= src_network src_testlib
++nacl: SUBDIRS -= src_network
+
+ android:!android-embedded: SUBDIRS += src_android src_3rdparty_gradle
+
diff --git a/package/lean/qt5/patches/030-qtbase-fix-compile-with-openssl1.1.1.patch b/package/lean/qt5/patches/030-qtbase-fix-compile-with-openssl1.1.1.patch
new file mode 100644
index 0000000000..b68ac8e335
--- /dev/null
+++ b/package/lean/qt5/patches/030-qtbase-fix-compile-with-openssl1.1.1.patch
@@ -0,0 +1,3985 @@
+commit 2d88fc0ce4ac76924a65ffd797183de9422ba672
+Author: Andreas Rammhold
+Date: Wed Mar 6 00:18:51 2019 +0100
+
+ openssl1.1 compat
+
+diff --git a/qtbase/config.tests/openssl/openssl.cpp b/qtbase/config.tests/openssl/openssl.cpp
+index 6c8a9e8f19..d33b62389c 100644
+--- a/qtbase/config.tests/openssl/openssl.cpp
++++ b/qtbase/config.tests/openssl/openssl.cpp
+@@ -39,8 +39,8 @@
+
+ #include
+
+-#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10000000L || OPENSSL_VERSION_NUMBER-0 >= 0x10100000L
+-# error "OpenSSL >= 1.0.0, and < 1.1.0 is required"
++#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10000000L
++# error "OpenSSL >= 1.0.0 is required"
+ #endif
+
+ #include
+diff --git a/qtbase/config.tests/openssl11/openssl.cpp b/qtbase/config.tests/openssl11/openssl.cpp
+new file mode 100644
+index 0000000000..c20cc59deb
+--- /dev/null
++++ b/qtbase/config.tests/openssl11/openssl.cpp
+@@ -0,0 +1,48 @@
++/****************************************************************************
++**
++** Copyright (C) 2017 The Qt Company Ltd.
++** Contact: https://www.qt.io/licensing/
++**
++** This file is part of the config.tests of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** Commercial License Usage
++** Licensees holding valid commercial Qt licenses may use this file in
++** accordance with the commercial license agreement provided with the
++** Software or, alternatively, in accordance with the terms contained in
++** a written agreement between you and The Qt Company. For licensing terms
++** and conditions see https://www.qt.io/terms-conditions. For further
++** information use the contact form at https://www.qt.io/contact-us.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 3 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL3 included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 3 requirements
++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU
++** General Public License version 2.0 or (at your option) the GNU General
++** Public license version 3 or any later version approved by the KDE Free
++** Qt Foundation. The licenses are as published by the Free Software
++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
++** included in the packaging of this file. Please review the following
++** information to ensure the GNU General Public License requirements will
++** be met: https://www.gnu.org/licenses/gpl-2.0.html and
++** https://www.gnu.org/licenses/gpl-3.0.html.
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include
++
++#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10100000L
++# error "OpenSSL >= 1.1 is required"
++#endif
++
++int main()
++{
++}
+diff --git a/qtbase/config.tests/openssl11/openssl11.pro b/qtbase/config.tests/openssl11/openssl11.pro
+new file mode 100644
+index 0000000000..a023aee4aa
+--- /dev/null
++++ b/qtbase/config.tests/openssl11/openssl11.pro
+@@ -0,0 +1,2 @@
++SOURCES = openssl.cpp
++CONFIG -= x11 qt
+diff --git a/qtbase/src/network/configure.json b/qtbase/src/network/configure.json
+index 2cf90ed94b..a021c0734b 100644
+--- a/qtbase/src/network/configure.json
++++ b/qtbase/src/network/configure.json
+@@ -77,6 +77,17 @@
+ },
+ { "libs": "-lssl -lcrypto", "condition": "!config.win32" }
+ ]
++ },
++ "openssl11": {
++ "label": "OpenSSL v. 1.1 support",
++ "type": "compile",
++ "test": "openssl11",
++ "sources": [
++ {
++ "comment": "placeholder for OPENSSL_PATH",
++ "libs": ""
++ }
++ ]
+ }
+ },
+
+@@ -182,7 +193,7 @@
+ "enable": "input.openssl == 'yes' || input.openssl == 'linked' || input.openssl == 'runtime'",
+ "disable": "input.openssl == 'no' || input.ssl == 'no'",
+ "autoDetect": "!config.winrt",
+- "condition": "!features.securetransport && (features.openssl-linked || libs.openssl_headers)",
++ "condition": "!features.securetransport && (features.openssl-linked || libs.openssl_headers || feature.opensslv11)",
+ "output": [
+ "privateFeature",
+ { "type": "publicQtConfig", "condition": "!features.openssl-linked" },
+@@ -193,7 +204,7 @@
+ "label": " Qt directly linked to OpenSSL",
+ "enable": "input.openssl == 'linked'",
+ "disable": "input.openssl != 'linked'",
+- "condition": "!features.securetransport && libs.openssl",
++ "condition": "!features.securetransport && (libs.openssl || feature.opensslv11)",
+ "output": [
+ "privateFeature",
+ { "type": "define", "name": "QT_LINKED_OPENSSL" }
+@@ -213,6 +224,11 @@
+ "condition": "config.winrt || features.securetransport || features.openssl",
+ "output": [ "publicFeature", "feature" ]
+ },
++ "opensslv11": {
++ "label": "OpenSSL v. 1.1",
++ "condition": "libs.openssl11",
++ "output": ["publicFeature", "feature"]
++ },
+ "sctp": {
+ "label": "SCTP",
+ "autoDetect": false,
+diff --git a/qtbase/src/network/ssl/qsslcertificate_openssl.cpp b/qtbase/src/network/ssl/qsslcertificate_openssl.cpp
+index 28b7eda54a..71e514a025 100644
+--- a/qtbase/src/network/ssl/qsslcertificate_openssl.cpp
++++ b/qtbase/src/network/ssl/qsslcertificate_openssl.cpp
+@@ -1,6 +1,7 @@
+ /****************************************************************************
+ **
+-** Copyright (C) 2016 The Qt Company Ltd.
++** Copyright (C) 2017 The Qt Company Ltd.
++** Copyright (C) 2016 Richard J. Moore
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the QtNetwork module of the Qt Toolkit.
+@@ -64,12 +65,14 @@ bool QSslCertificate::operator==(const QSslCertificate &other) const
+ uint qHash(const QSslCertificate &key, uint seed) Q_DECL_NOTHROW
+ {
+ if (X509 * const x509 = key.d->x509) {
+- (void)q_X509_cmp(x509, x509); // populate x509->sha1_hash
+- // (if someone knows a better way...)
+- return qHashBits(x509->sha1_hash, SHA_DIGEST_LENGTH, seed);
+- } else {
+- return seed;
++ const EVP_MD *sha1 = q_EVP_sha1();
++ unsigned int len = 0;
++ unsigned char md[EVP_MAX_MD_SIZE];
++ q_X509_digest(x509, sha1, md, &len);
++ return qHashBits(md, len, seed);
+ }
++
++ return seed;
+ }
+
+ bool QSslCertificate::isNull() const
+@@ -89,8 +92,7 @@ QByteArray QSslCertificate::version() const
+ {
+ QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
+ if (d->versionString.isEmpty() && d->x509)
+- d->versionString =
+- QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->version)) + 1);
++ d->versionString = QByteArray::number(qlonglong(q_X509_get_version(d->x509)) + 1);
+
+ return d->versionString;
+ }
+@@ -99,7 +101,7 @@ QByteArray QSslCertificate::serialNumber() const
+ {
+ QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
+ if (d->serialNumberString.isEmpty() && d->x509) {
+- ASN1_INTEGER *serialNumber = d->x509->cert_info->serialNumber;
++ ASN1_INTEGER *serialNumber = q_X509_get_serialNumber(d->x509);
+ QByteArray hexString;
+ hexString.reserve(serialNumber->length * 3);
+ for (int a = 0; a < serialNumber->length; ++a) {
+@@ -199,14 +201,15 @@ QMultiMap QSslCertificate::subjectAlter
+ continue;
+ }
+
+- const char *altNameStr = reinterpret_cast(q_ASN1_STRING_data(genName->d.ia5));
++ const char *altNameStr = reinterpret_cast(q_ASN1_STRING_get0_data(genName->d.ia5));
+ const QString altName = QString::fromLatin1(altNameStr, len);
+ if (genName->type == GEN_DNS)
+ result.insert(QSsl::DnsEntry, altName);
+ else if (genName->type == GEN_EMAIL)
+ result.insert(QSsl::EmailEntry, altName);
+ }
+- q_sk_pop_free((STACK*)altNames, reinterpret_cast(q_sk_free));
++
++ q_OPENSSL_sk_pop_free((OPENSSL_STACK*)altNames, reinterpret_cast(q_OPENSSL_sk_free));
+ }
+
+ return result;
+@@ -235,25 +238,26 @@ QSslKey QSslCertificate::publicKey() const
+ QSslKey key;
+
+ key.d->type = QSsl::PublicKey;
+- X509_PUBKEY *xkey = d->x509->cert_info->key;
+- EVP_PKEY *pkey = q_X509_PUBKEY_get(xkey);
++
++ EVP_PKEY *pkey = q_X509_get_pubkey(d->x509);
+ Q_ASSERT(pkey);
++ const int keyType = q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey));
+
+- if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA) {
++ if (keyType == EVP_PKEY_RSA) {
+ key.d->rsa = q_EVP_PKEY_get1_RSA(pkey);
+ key.d->algorithm = QSsl::Rsa;
+ key.d->isNull = false;
+- } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA) {
++ } else if (keyType == EVP_PKEY_DSA) {
+ key.d->dsa = q_EVP_PKEY_get1_DSA(pkey);
+ key.d->algorithm = QSsl::Dsa;
+ key.d->isNull = false;
+ #ifndef OPENSSL_NO_EC
+- } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_EC) {
++ } else if (keyType == EVP_PKEY_EC) {
+ key.d->ec = q_EVP_PKEY_get1_EC_KEY(pkey);
+ key.d->algorithm = QSsl::Ec;
+ key.d->isNull = false;
+ #endif
+- } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_DH) {
++ } else if (keyType == EVP_PKEY_DH) {
+ // DH unsupported
+ } else {
+ // error?
+@@ -275,7 +279,7 @@ static QVariant x509UnknownExtensionToValue(X509_EXTENSION *ext)
+ X509V3_EXT_METHOD *meth = const_cast(q_X509V3_EXT_get(ext));
+ if (!meth) {
+ ASN1_OCTET_STRING *value = q_X509_EXTENSION_get_data(ext);
+- QByteArray result( reinterpret_cast(q_ASN1_STRING_data(value)),
++ QByteArray result( reinterpret_cast(q_ASN1_STRING_get0_data(value)),
+ q_ASN1_STRING_length(value));
+ return result;
+ }
+@@ -371,7 +375,7 @@ static QVariant x509ExtensionToValue(X509_EXTENSION *ext)
+ continue;
+ }
+
+- const char *uriStr = reinterpret_cast(q_ASN1_STRING_data(name->d.uniformResourceIdentifier));
++ const char *uriStr = reinterpret_cast(q_ASN1_STRING_get0_data(name->d.uniformResourceIdentifier));
+ const QString uri = QString::fromUtf8(uriStr, len);
+
+ result[QString::fromUtf8(QSslCertificatePrivate::asn1ObjectName(ad->method))] = uri;
+@@ -380,11 +384,7 @@ static QVariant x509ExtensionToValue(X509_EXTENSION *ext)
+ }
+ }
+
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+- q_sk_pop_free((_STACK*)info, reinterpret_cast(q_sk_free));
+-#else
+- q_sk_pop_free((STACK*)info, reinterpret_cast(q_sk_free));
+-#endif
++ q_OPENSSL_sk_pop_free((OPENSSL_STACK*)info, reinterpret_cast(q_OPENSSL_sk_free));
+ return result;
+ }
+ break;
+@@ -607,7 +607,11 @@ static QMap _q_mapFromX509Name(X509_NAME *name)
+ unsigned char *data = 0;
+ int size = q_ASN1_STRING_to_UTF8(&data, q_X509_NAME_ENTRY_get_data(e));
+ info.insertMulti(name, QString::fromUtf8((char*)data, size));
++#if QT_CONFIG(opensslv11)
++ q_CRYPTO_free(data, 0, 0);
++#else
+ q_CRYPTO_free(data);
++#endif
+ }
+
+ return info;
+@@ -619,8 +623,9 @@ QSslCertificate QSslCertificatePrivate::QSslCertificate_from_X509(X509 *x509)
+ if (!x509 || !QSslSocket::supportsSsl())
+ return certificate;
+
+- ASN1_TIME *nbef = q_X509_get_notBefore(x509);
+- ASN1_TIME *naft = q_X509_get_notAfter(x509);
++ ASN1_TIME *nbef = q_X509_getm_notBefore(x509);
++ ASN1_TIME *naft = q_X509_getm_notAfter(x509);
++
+ certificate.d->notValidBefore = q_getTimeFromASN1(nbef);
+ certificate.d->notValidAfter = q_getTimeFromASN1(naft);
+ certificate.d->null = false;
+diff --git a/qtbase/src/network/ssl/qsslcontext_openssl.cpp b/qtbase/src/network/ssl/qsslcontext_openssl.cpp
+index c92d8fc3f8..cef503710c 100644
+--- a/qtbase/src/network/ssl/qsslcontext_openssl.cpp
++++ b/qtbase/src/network/ssl/qsslcontext_openssl.cpp
+@@ -1,6 +1,6 @@
+ /****************************************************************************
+ **
+-** Copyright (C) 2016 The Qt Company Ltd.
++** Copyright (C) 2017 The Qt Company Ltd.
+ ** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
+ ** Copyright (C) 2014 Governikus GmbH & Co. KG.
+ ** Contact: https://www.qt.io/licensing/
+@@ -41,22 +41,14 @@
+
+
+ #include
+-#include
+-#include
+
+ #include "private/qssl_p.h"
+ #include "private/qsslcontext_openssl_p.h"
+-#include "private/qsslsocket_p.h"
+ #include "private/qsslsocket_openssl_p.h"
+ #include "private/qsslsocket_openssl_symbols_p.h"
+-#include "private/qssldiffiehellmanparameters_p.h"
+
+ QT_BEGIN_NAMESPACE
+
+-// defined in qsslsocket_openssl.cpp:
+-extern int q_X509Callback(int ok, X509_STORE_CTX *ctx);
+-extern QString getErrorsFromOpenSsl();
+-
+ QSslContext::QSslContext()
+ : ctx(0),
+ pkey(0),
+@@ -78,301 +70,6 @@ QSslContext::~QSslContext()
+ q_SSL_SESSION_free(session);
+ }
+
+-static inline QString msgErrorSettingEllipticCurves(const QString &why)
+-{
+- return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
+-}
+-
+-// static
+-void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
+-{
+- sslContext->sslConfiguration = configuration;
+- sslContext->errorCode = QSslError::NoError;
+-
+- bool client = (mode == QSslSocket::SslClientMode);
+-
+- bool reinitialized = false;
+- bool unsupportedProtocol = false;
+-init_context:
+- switch (sslContext->sslConfiguration.protocol()) {
+- case QSsl::SslV2:
+-#ifndef OPENSSL_NO_SSL2
+- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv2_client_method() : q_SSLv2_server_method());
+-#else
+- // SSL 2 not supported by the system, but chosen deliberately -> error
+- sslContext->ctx = 0;
+- unsupportedProtocol = true;
+-#endif
+- break;
+- case QSsl::SslV3:
+-#ifndef OPENSSL_NO_SSL3_METHOD
+- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv3_client_method() : q_SSLv3_server_method());
+-#else
+- // SSL 3 not supported by the system, but chosen deliberately -> error
+- sslContext->ctx = 0;
+- unsupportedProtocol = true;
+-#endif
+- break;
+- case QSsl::SecureProtocols:
+- // SSLv2 and SSLv3 will be disabled by SSL options
+- // But we need q_SSLv23_server_method() otherwise AnyProtocol will be unable to connect on Win32.
+- case QSsl::TlsV1SslV3:
+- // SSLv2 will will be disabled by SSL options
+- case QSsl::AnyProtocol:
+- default:
+- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
+- break;
+- case QSsl::TlsV1_0:
+- sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_client_method() : q_TLSv1_server_method());
+- break;
+- case QSsl::TlsV1_1:
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+- sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_1_client_method() : q_TLSv1_1_server_method());
+-#else
+- // TLS 1.1 not supported by the system, but chosen deliberately -> error
+- sslContext->ctx = 0;
+- unsupportedProtocol = true;
+-#endif
+- break;
+- case QSsl::TlsV1_2:
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+- sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_2_client_method() : q_TLSv1_2_server_method());
+-#else
+- // TLS 1.2 not supported by the system, but chosen deliberately -> error
+- sslContext->ctx = 0;
+- unsupportedProtocol = true;
+-#endif
+- break;
+- case QSsl::TlsV1_0OrLater:
+- // Specific protocols will be specified via SSL options.
+- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
+- break;
+- case QSsl::TlsV1_1OrLater:
+- case QSsl::TlsV1_2OrLater:
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+- // Specific protocols will be specified via SSL options.
+- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
+-#else
+- // TLS 1.1/1.2 not supported by the system, but chosen deliberately -> error
+- sslContext->ctx = 0;
+- unsupportedProtocol = true;
+-#endif
+- break;
+- }
+-
+- if (!sslContext->ctx) {
+- // After stopping Flash 10 the SSL library looses its ciphers. Try re-adding them
+- // by re-initializing the library.
+- if (!reinitialized) {
+- reinitialized = true;
+- if (q_SSL_library_init() == 1)
+- goto init_context;
+- }
+-
+- sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(
+- unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl()
+- );
+- sslContext->errorCode = QSslError::UnspecifiedError;
+- return;
+- }
+-
+- // Enable bug workarounds.
+- long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
+- q_SSL_CTX_set_options(sslContext->ctx, options);
+-
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+- // Tell OpenSSL to release memory early
+- // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
+- if (q_SSLeay() >= 0x10000000L)
+- q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS);
+-#endif
+-
+- // Initialize ciphers
+- QByteArray cipherString;
+- bool first = true;
+- QList ciphers = sslContext->sslConfiguration.ciphers();
+- if (ciphers.isEmpty())
+- ciphers = QSslSocketPrivate::defaultCiphers();
+- for (const QSslCipher &cipher : qAsConst(ciphers)) {
+- if (first)
+- first = false;
+- else
+- cipherString.append(':');
+- cipherString.append(cipher.name().toLatin1());
+- }
+-
+- if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, cipherString.data())) {
+- sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+- sslContext->errorCode = QSslError::UnspecifiedError;
+- return;
+- }
+-
+- const QDateTime now = QDateTime::currentDateTimeUtc();
+-
+- // Add all our CAs to this store.
+- const auto caCertificates = sslContext->sslConfiguration.caCertificates();
+- for (const QSslCertificate &caCertificate : caCertificates) {
+- // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html:
+- //
+- // If several CA certificates matching the name, key identifier, and
+- // serial number condition are available, only the first one will be
+- // examined. This may lead to unexpected results if the same CA
+- // certificate is available with different expiration dates. If a
+- // ``certificate expired'' verification error occurs, no other
+- // certificate will be searched. Make sure to not have expired
+- // certificates mixed with valid ones.
+- //
+- // See also: QSslSocketBackendPrivate::verify()
+- if (caCertificate.expiryDate() >= now) {
+- q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle());
+- }
+- }
+-
+- if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) {
+- // tell OpenSSL the directories where to look up the root certs on demand
+- const QList unixDirs = QSslSocketPrivate::unixRootCertDirectories();
+- for (const QByteArray &unixDir : unixDirs)
+- q_SSL_CTX_load_verify_locations(sslContext->ctx, 0, unixDir.constData());
+- }
+-
+- if (!sslContext->sslConfiguration.localCertificate().isNull()) {
+- // Require a private key as well.
+- if (sslContext->sslConfiguration.privateKey().isNull()) {
+- sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+- sslContext->errorCode = QSslError::UnspecifiedError;
+- return;
+- }
+-
+- // Load certificate
+- if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) {
+- sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+- sslContext->errorCode = QSslError::UnspecifiedError;
+- return;
+- }
+-
+- if (configuration.d->privateKey.algorithm() == QSsl::Opaque) {
+- sslContext->pkey = reinterpret_cast(configuration.d->privateKey.handle());
+- } else {
+- // Load private key
+- sslContext->pkey = q_EVP_PKEY_new();
+- // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
+- // this lead to a memory leak. Now we use the *_set1_* functions which do not
+- // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
+- if (configuration.d->privateKey.algorithm() == QSsl::Rsa)
+- q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast(configuration.d->privateKey.handle()));
+- else if (configuration.d->privateKey.algorithm() == QSsl::Dsa)
+- q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast(configuration.d->privateKey.handle()));
+-#ifndef OPENSSL_NO_EC
+- else if (configuration.d->privateKey.algorithm() == QSsl::Ec)
+- q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast(configuration.d->privateKey.handle()));
+-#endif
+- }
+-
+- if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) {
+- sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+- sslContext->errorCode = QSslError::UnspecifiedError;
+- return;
+- }
+- if (configuration.d->privateKey.algorithm() == QSsl::Opaque)
+- sslContext->pkey = 0; // Don't free the private key, it belongs to QSslKey
+-
+- // Check if the certificate matches the private key.
+- if (!q_SSL_CTX_check_private_key(sslContext->ctx)) {
+- sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+- sslContext->errorCode = QSslError::UnspecifiedError;
+- return;
+- }
+-
+- // If we have any intermediate certificates then we need to add them to our chain
+- bool first = true;
+- for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) {
+- if (first) {
+- first = false;
+- continue;
+- }
+- q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0,
+- q_X509_dup(reinterpret_cast(cert.handle())));
+- }
+- }
+-
+- // Initialize peer verification.
+- if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
+- q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, 0);
+- } else {
+- q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, q_X509Callback);
+- }
+-
+- // Set verification depth.
+- if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
+- q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
+-
+- // set persisted session if the user set it
+- if (!configuration.sessionTicket().isEmpty())
+- sslContext->setSessionASN1(configuration.sessionTicket());
+-
+- // Set temp DH params
+- QSslDiffieHellmanParameters dhparams = configuration.diffieHellmanParameters();
+-
+- if (!dhparams.isValid()) {
+- sslContext->errorStr = QSslSocket::tr("Diffie-Hellman parameters are not valid");
+- sslContext->errorCode = QSslError::UnspecifiedError;
+- return;
+- }
+-
+- if (!dhparams.isEmpty()) {
+- const QByteArray ¶ms = dhparams.d->derData;
+- const char *ptr = params.constData();
+- DH *dh = q_d2i_DHparams(NULL, reinterpret_cast(&ptr), params.length());
+- if (dh == NULL)
+- qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
+- q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh);
+- q_DH_free(dh);
+- }
+-
+-#ifndef OPENSSL_NO_EC
+-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+- if (q_SSLeay() >= 0x10002000L) {
+- q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL);
+- } else
+-#endif
+- {
+- // Set temp ECDH params
+- EC_KEY *ecdh = 0;
+- ecdh = q_EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+- q_SSL_CTX_set_tmp_ecdh(sslContext->ctx, ecdh);
+- q_EC_KEY_free(ecdh);
+- }
+-#endif // OPENSSL_NO_EC
+-
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
+- if (!client)
+- q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData());
+-#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
+-
+- const QVector qcurves = sslContext->sslConfiguration.ellipticCurves();
+- if (!qcurves.isEmpty()) {
+-#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC)
+- // Set the curves to be used
+- if (q_SSLeay() >= 0x10002000L) {
+- // SSL_CTX_ctrl wants a non-const pointer as last argument,
+- // but let's avoid a copy into a temporary array
+- if (!q_SSL_CTX_ctrl(sslContext->ctx,
+- SSL_CTRL_SET_CURVES,
+- qcurves.size(),
+- const_cast(reinterpret_cast(qcurves.data())))) {
+- sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+- sslContext->errorCode = QSslError::UnspecifiedError;
+- }
+- } else
+-#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC)
+- {
+- // specific curves requested, but not possible to set -> error
+- sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version too old, need at least v1.0.2"));
+- sslContext->errorCode = QSslError::UnspecifiedError;
+- }
+- }
+-}
+-
+ QSslContext* QSslContext::fromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
+ {
+ QSslContext *sslContext = new QSslContext();
+@@ -463,7 +160,7 @@ SSL* QSslContext::createSsl()
+ m_npnContext.len = m_supportedNPNVersions.count();
+ m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone;
+ #if OPENSSL_VERSION_NUMBER >= 0x10002000L
+- if (q_SSLeay() >= 0x10002000L) {
++ if (QSslSocket::sslLibraryVersionNumber() >= 0x10002000L) {
+ // Callback's type has a parameter 'const unsigned char ** out'
+ // since it was introduced in 1.0.2. Internally, OpenSSL's own code
+ // (tests/examples) cast it to unsigned char * (since it's 'out').
+@@ -508,7 +205,7 @@ bool QSslContext::cacheSession(SSL* ssl)
+ unsigned char *data = reinterpret_cast(m_sessionASN1.data());
+ if (!q_i2d_SSL_SESSION(session, &data))
+ qCWarning(lcSsl, "could not store persistent version of SSL session");
+- m_sessionTicketLifeTimeHint = session->tlsext_tick_lifetime_hint;
++ m_sessionTicketLifeTimeHint = q_SSL_SESSION_get_ticket_lifetime_hint(session);
+ }
+ }
+
+diff --git a/qtbase/src/network/ssl/qsslcontext_openssl11.cpp b/qtbase/src/network/ssl/qsslcontext_openssl11.cpp
+new file mode 100644
+index 0000000000..787b6ae3f5
+--- /dev/null
++++ b/qtbase/src/network/ssl/qsslcontext_openssl11.cpp
+@@ -0,0 +1,277 @@
++/****************************************************************************
++**
++** Copyright (C) 2017 The Qt Company Ltd.
++** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
++** Copyright (C) 2014 Governikus GmbH & Co. KG.
++** Copyright (C) 2016 Richard J. Moore
++** Contact: https://www.qt.io/licensing/
++**
++** This file is part of the QtNetwork module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** Commercial License Usage
++** Licensees holding valid commercial Qt licenses may use this file in
++** accordance with the commercial license agreement provided with the
++** Software or, alternatively, in accordance with the terms contained in
++** a written agreement between you and The Qt Company. For licensing terms
++** and conditions see https://www.qt.io/terms-conditions. For further
++** information use the contact form at https://www.qt.io/contact-us.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 3 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL3 included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 3 requirements
++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU
++** General Public License version 2.0 or (at your option) the GNU General
++** Public license version 3 or any later version approved by the KDE Free
++** Qt Foundation. The licenses are as published by the Free Software
++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
++** included in the packaging of this file. Please review the following
++** information to ensure the GNU General Public License requirements will
++** be met: https://www.gnu.org/licenses/gpl-2.0.html and
++** https://www.gnu.org/licenses/gpl-3.0.html.
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++
++#include
++#include
++
++#include "private/qssl_p.h"
++#include "private/qsslcontext_openssl_p.h"
++#include "private/qsslsocket_p.h"
++#include "private/qsslsocket_openssl_p.h"
++#include "private/qsslsocket_openssl_symbols_p.h"
++#include "private/qssldiffiehellmanparameters_p.h"
++
++#include
++
++QT_BEGIN_NAMESPACE
++
++// defined in qsslsocket_openssl.cpp:
++extern int q_X509Callback(int ok, X509_STORE_CTX *ctx);
++extern QString getErrorsFromOpenSsl();
++
++static inline QString msgErrorSettingEllipticCurves(const QString &why)
++{
++ return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
++}
++
++// static
++void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
++{
++ sslContext->sslConfiguration = configuration;
++ sslContext->errorCode = QSslError::NoError;
++
++ bool client = (mode == QSslSocket::SslClientMode);
++
++ bool reinitialized = false;
++ bool unsupportedProtocol = false;
++init_context:
++ if (sslContext->sslConfiguration.protocol() == QSsl::SslV2) {
++ // SSL 2 is no longer supported, but chosen deliberately -> error
++ sslContext->ctx = nullptr;
++ unsupportedProtocol = true;
++ } else {
++ // The ssl options will actually control the supported methods
++ sslContext->ctx = q_SSL_CTX_new(client ? q_TLS_client_method() : q_TLS_server_method());
++ }
++
++ if (!sslContext->ctx) {
++ // After stopping Flash 10 the SSL library loses its ciphers. Try re-adding them
++ // by re-initializing the library.
++ if (!reinitialized) {
++ reinitialized = true;
++ if (q_OPENSSL_init_ssl(0, nullptr) == 1)
++ goto init_context;
++ }
++
++ sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(
++ unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl()
++ );
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ // Enable bug workarounds.
++ long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
++ q_SSL_CTX_set_options(sslContext->ctx, options);
++
++ // Tell OpenSSL to release memory early
++ // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
++ q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS);
++
++ // Initialize ciphers
++ QByteArray cipherString;
++ bool first = true;
++ QList ciphers = sslContext->sslConfiguration.ciphers();
++ if (ciphers.isEmpty())
++ ciphers = QSslSocketPrivate::defaultCiphers();
++ for (const QSslCipher &cipher : qAsConst(ciphers)) {
++ if (first)
++ first = false;
++ else
++ cipherString.append(':');
++ cipherString.append(cipher.name().toLatin1());
++ }
++
++ if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, cipherString.data())) {
++ sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ const QDateTime now = QDateTime::currentDateTimeUtc();
++
++ // Add all our CAs to this store.
++ const auto caCertificates = sslContext->sslConfiguration.caCertificates();
++ for (const QSslCertificate &caCertificate : caCertificates) {
++ // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html:
++ //
++ // If several CA certificates matching the name, key identifier, and
++ // serial number condition are available, only the first one will be
++ // examined. This may lead to unexpected results if the same CA
++ // certificate is available with different expiration dates. If a
++ // ``certificate expired'' verification error occurs, no other
++ // certificate will be searched. Make sure to not have expired
++ // certificates mixed with valid ones.
++ //
++ // See also: QSslSocketBackendPrivate::verify()
++ if (caCertificate.expiryDate() >= now) {
++ q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle());
++ }
++ }
++
++ if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) {
++ // tell OpenSSL the directories where to look up the root certs on demand
++ const QList unixDirs = QSslSocketPrivate::unixRootCertDirectories();
++ for (const QByteArray &unixDir : unixDirs)
++ q_SSL_CTX_load_verify_locations(sslContext->ctx, nullptr, unixDir.constData());
++ }
++
++ if (!sslContext->sslConfiguration.localCertificate().isNull()) {
++ // Require a private key as well.
++ if (sslContext->sslConfiguration.privateKey().isNull()) {
++ sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ // Load certificate
++ if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) {
++ sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ if (configuration.d->privateKey.algorithm() == QSsl::Opaque) {
++ sslContext->pkey = reinterpret_cast(configuration.d->privateKey.handle());
++ } else {
++ // Load private key
++ sslContext->pkey = q_EVP_PKEY_new();
++ // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
++ // this lead to a memory leak. Now we use the *_set1_* functions which do not
++ // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
++ if (configuration.d->privateKey.algorithm() == QSsl::Rsa)
++ q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast(configuration.d->privateKey.handle()));
++ else if (configuration.d->privateKey.algorithm() == QSsl::Dsa)
++ q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast(configuration.d->privateKey.handle()));
++#ifndef OPENSSL_NO_EC
++ else if (configuration.d->privateKey.algorithm() == QSsl::Ec)
++ q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast(configuration.d->privateKey.handle()));
++#endif
++ }
++
++ if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) {
++ sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++ if (configuration.d->privateKey.algorithm() == QSsl::Opaque)
++ sslContext->pkey = nullptr; // Don't free the private key, it belongs to QSslKey
++
++ // Check if the certificate matches the private key.
++ if (!q_SSL_CTX_check_private_key(sslContext->ctx)) {
++ sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ // If we have any intermediate certificates then we need to add them to our chain
++ bool first = true;
++ for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) {
++ if (first) {
++ first = false;
++ continue;
++ }
++ q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0,
++ q_X509_dup(reinterpret_cast(cert.handle())));
++ }
++ }
++
++ // Initialize peer verification.
++ if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
++ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, nullptr);
++ } else {
++ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, q_X509Callback);
++ }
++
++ // Set verification depth.
++ if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
++ q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
++
++ // set persisted session if the user set it
++ if (!configuration.sessionTicket().isEmpty())
++ sslContext->setSessionASN1(configuration.sessionTicket());
++
++ // Set temp DH params
++ QSslDiffieHellmanParameters dhparams = configuration.diffieHellmanParameters();
++
++ if (!dhparams.isValid()) {
++ sslContext->errorStr = QSslSocket::tr("Diffie-Hellman parameters are not valid");
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ if (!dhparams.isEmpty()) {
++ const QByteArray ¶ms = dhparams.d->derData;
++ const char *ptr = params.constData();
++ DH *dh = q_d2i_DHparams(NULL, reinterpret_cast(&ptr), params.length());
++ if (dh == NULL)
++ qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
++ q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh);
++ q_DH_free(dh);
++ }
++
++#ifndef OPENSSL_NO_PSK
++ if (!client)
++ q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData());
++#endif // !OPENSSL_NO_PSK
++
++ const QVector qcurves = sslContext->sslConfiguration.ellipticCurves();
++ if (!qcurves.isEmpty()) {
++#ifdef OPENSSL_NO_EC
++ sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version with disabled elliptic curves"));
++ sslContext->errorCode = QSslError::UnspecifiedError;
++#else
++ // Set the curves to be used.
++ std::vector curves;
++ curves.reserve(qcurves.size());
++ for (const auto &sslCurve : qcurves)
++ curves.push_back(sslCurve.id);
++ if (!q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_CURVES, long(curves.size()), &curves[0])) {
++ sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ }
++#endif
++ }
++}
++
++QT_END_NAMESPACE
+diff --git a/qtbase/src/network/ssl/qsslcontext_opensslpre11.cpp b/qtbase/src/network/ssl/qsslcontext_opensslpre11.cpp
+new file mode 100644
+index 0000000000..9c01c2f2dc
+--- /dev/null
++++ b/qtbase/src/network/ssl/qsslcontext_opensslpre11.cpp
+@@ -0,0 +1,354 @@
++/****************************************************************************
++**
++** Copyright (C) 2017 The Qt Company Ltd.
++** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
++** Copyright (C) 2014 Governikus GmbH & Co. KG.
++** Contact: https://www.qt.io/licensing/
++**
++** This file is part of the QtNetwork module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** Commercial License Usage
++** Licensees holding valid commercial Qt licenses may use this file in
++** accordance with the commercial license agreement provided with the
++** Software or, alternatively, in accordance with the terms contained in
++** a written agreement between you and The Qt Company. For licensing terms
++** and conditions see https://www.qt.io/terms-conditions. For further
++** information use the contact form at https://www.qt.io/contact-us.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 3 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL3 included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 3 requirements
++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU
++** General Public License version 2.0 or (at your option) the GNU General
++** Public license version 3 or any later version approved by the KDE Free
++** Qt Foundation. The licenses are as published by the Free Software
++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
++** included in the packaging of this file. Please review the following
++** information to ensure the GNU General Public License requirements will
++** be met: https://www.gnu.org/licenses/gpl-2.0.html and
++** https://www.gnu.org/licenses/gpl-3.0.html.
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++
++#include
++#include
++
++#include "private/qssl_p.h"
++#include "private/qsslcontext_openssl_p.h"
++#include "private/qsslsocket_p.h"
++#include "private/qsslsocket_openssl_p.h"
++#include "private/qsslsocket_openssl_symbols_p.h"
++#include "private/qssldiffiehellmanparameters_p.h"
++
++QT_BEGIN_NAMESPACE
++
++// defined in qsslsocket_openssl.cpp:
++extern int q_X509Callback(int ok, X509_STORE_CTX *ctx);
++extern QString getErrorsFromOpenSsl();
++
++static inline QString msgErrorSettingEllipticCurves(const QString &why)
++{
++ return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
++}
++
++// static
++void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
++{
++ sslContext->sslConfiguration = configuration;
++ sslContext->errorCode = QSslError::NoError;
++
++ bool client = (mode == QSslSocket::SslClientMode);
++
++ bool reinitialized = false;
++ bool unsupportedProtocol = false;
++init_context:
++ switch (sslContext->sslConfiguration.protocol()) {
++ case QSsl::SslV2:
++#ifndef OPENSSL_NO_SSL2
++ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv2_client_method() : q_SSLv2_server_method());
++#else
++ // SSL 2 not supported by the system, but chosen deliberately -> error
++ sslContext->ctx = 0;
++ unsupportedProtocol = true;
++#endif
++ break;
++ case QSsl::SslV3:
++#ifndef OPENSSL_NO_SSL3_METHOD
++ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv3_client_method() : q_SSLv3_server_method());
++#else
++ // SSL 3 not supported by the system, but chosen deliberately -> error
++ sslContext->ctx = 0;
++ unsupportedProtocol = true;
++#endif
++ break;
++ case QSsl::SecureProtocols:
++ // SSLv2 and SSLv3 will be disabled by SSL options
++ // But we need q_SSLv23_server_method() otherwise AnyProtocol will be unable to connect on Win32.
++ case QSsl::TlsV1SslV3:
++ // SSLv2 will will be disabled by SSL options
++ case QSsl::AnyProtocol:
++ default:
++ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
++ break;
++ case QSsl::TlsV1_0:
++ sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_client_method() : q_TLSv1_server_method());
++ break;
++ case QSsl::TlsV1_1:
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++ sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_1_client_method() : q_TLSv1_1_server_method());
++#else
++ // TLS 1.1 not supported by the system, but chosen deliberately -> error
++ sslContext->ctx = 0;
++ unsupportedProtocol = true;
++#endif
++ break;
++ case QSsl::TlsV1_2:
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++ sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_2_client_method() : q_TLSv1_2_server_method());
++#else
++ // TLS 1.2 not supported by the system, but chosen deliberately -> error
++ sslContext->ctx = 0;
++ unsupportedProtocol = true;
++#endif
++ break;
++ case QSsl::TlsV1_0OrLater:
++ // Specific protocols will be specified via SSL options.
++ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
++ break;
++ case QSsl::TlsV1_1OrLater:
++ case QSsl::TlsV1_2OrLater:
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++ // Specific protocols will be specified via SSL options.
++ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
++#else
++ // TLS 1.1/1.2 not supported by the system, but chosen deliberately -> error
++ sslContext->ctx = 0;
++ unsupportedProtocol = true;
++#endif
++ break;
++ }
++
++ if (!sslContext->ctx) {
++ // After stopping Flash 10 the SSL library loses its ciphers. Try re-adding them
++ // by re-initializing the library.
++ if (!reinitialized) {
++ reinitialized = true;
++ if (q_SSL_library_init() == 1)
++ goto init_context;
++ }
++
++ sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(
++ unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl()
++ );
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ // Enable bug workarounds.
++ long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
++ q_SSL_CTX_set_options(sslContext->ctx, options);
++
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++ // Tell OpenSSL to release memory early
++ // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
++ if (q_SSLeay() >= 0x10000000L)
++ q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS);
++#endif
++
++ // Initialize ciphers
++ QByteArray cipherString;
++ bool first = true;
++ QList ciphers = sslContext->sslConfiguration.ciphers();
++ if (ciphers.isEmpty())
++ ciphers = QSslSocketPrivate::defaultCiphers();
++ for (const QSslCipher &cipher : qAsConst(ciphers)) {
++ if (first)
++ first = false;
++ else
++ cipherString.append(':');
++ cipherString.append(cipher.name().toLatin1());
++ }
++
++ if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, cipherString.data())) {
++ sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ const QDateTime now = QDateTime::currentDateTimeUtc();
++
++ // Add all our CAs to this store.
++ const auto caCertificates = sslContext->sslConfiguration.caCertificates();
++ for (const QSslCertificate &caCertificate : caCertificates) {
++ // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html:
++ //
++ // If several CA certificates matching the name, key identifier, and
++ // serial number condition are available, only the first one will be
++ // examined. This may lead to unexpected results if the same CA
++ // certificate is available with different expiration dates. If a
++ // ``certificate expired'' verification error occurs, no other
++ // certificate will be searched. Make sure to not have expired
++ // certificates mixed with valid ones.
++ //
++ // See also: QSslSocketBackendPrivate::verify()
++ if (caCertificate.expiryDate() >= now) {
++ q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle());
++ }
++ }
++
++ if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) {
++ // tell OpenSSL the directories where to look up the root certs on demand
++ const QList unixDirs = QSslSocketPrivate::unixRootCertDirectories();
++ for (const QByteArray &unixDir : unixDirs)
++ q_SSL_CTX_load_verify_locations(sslContext->ctx, 0, unixDir.constData());
++ }
++
++ if (!sslContext->sslConfiguration.localCertificate().isNull()) {
++ // Require a private key as well.
++ if (sslContext->sslConfiguration.privateKey().isNull()) {
++ sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ // Load certificate
++ if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) {
++ sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ if (configuration.d->privateKey.algorithm() == QSsl::Opaque) {
++ sslContext->pkey = reinterpret_cast(configuration.d->privateKey.handle());
++ } else {
++ // Load private key
++ sslContext->pkey = q_EVP_PKEY_new();
++ // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
++ // this lead to a memory leak. Now we use the *_set1_* functions which do not
++ // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
++ if (configuration.d->privateKey.algorithm() == QSsl::Rsa)
++ q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast(configuration.d->privateKey.handle()));
++ else if (configuration.d->privateKey.algorithm() == QSsl::Dsa)
++ q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast(configuration.d->privateKey.handle()));
++#ifndef OPENSSL_NO_EC
++ else if (configuration.d->privateKey.algorithm() == QSsl::Ec)
++ q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast(configuration.d->privateKey.handle()));
++#endif
++ }
++
++ if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) {
++ sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++ if (configuration.d->privateKey.algorithm() == QSsl::Opaque)
++ sslContext->pkey = 0; // Don't free the private key, it belongs to QSslKey
++
++ // Check if the certificate matches the private key.
++ if (!q_SSL_CTX_check_private_key(sslContext->ctx)) {
++ sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ // If we have any intermediate certificates then we need to add them to our chain
++ bool first = true;
++ for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) {
++ if (first) {
++ first = false;
++ continue;
++ }
++ q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0,
++ q_X509_dup(reinterpret_cast(cert.handle())));
++ }
++ }
++
++ // Initialize peer verification.
++ if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
++ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, 0);
++ } else {
++ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, q_X509Callback);
++ }
++
++ // Set verification depth.
++ if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
++ q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
++
++ // set persisted session if the user set it
++ if (!configuration.sessionTicket().isEmpty())
++ sslContext->setSessionASN1(configuration.sessionTicket());
++
++ // Set temp DH params
++ QSslDiffieHellmanParameters dhparams = configuration.diffieHellmanParameters();
++
++ if (!dhparams.isValid()) {
++ sslContext->errorStr = QSslSocket::tr("Diffie-Hellman parameters are not valid");
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ if (!dhparams.isEmpty()) {
++ const QByteArray ¶ms = dhparams.d->derData;
++ const char *ptr = params.constData();
++ DH *dh = q_d2i_DHparams(NULL, reinterpret_cast(&ptr), params.length());
++ if (dh == NULL)
++ qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
++ q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh);
++ q_DH_free(dh);
++ }
++
++#ifndef OPENSSL_NO_EC
++#if OPENSSL_VERSION_NUMBER >= 0x10002000L
++ if (q_SSLeay() >= 0x10002000L) {
++ q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL);
++ } else
++#endif
++ {
++ // Set temp ECDH params
++ EC_KEY *ecdh = 0;
++ ecdh = q_EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
++ q_SSL_CTX_set_tmp_ecdh(sslContext->ctx, ecdh);
++ q_EC_KEY_free(ecdh);
++ }
++#endif // OPENSSL_NO_EC
++
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
++ if (!client)
++ q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData());
++#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
++
++ const QVector qcurves = sslContext->sslConfiguration.ellipticCurves();
++ if (!qcurves.isEmpty()) {
++#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC)
++ // Set the curves to be used
++ if (q_SSLeay() >= 0x10002000L) {
++ // SSL_CTX_ctrl wants a non-const pointer as last argument,
++ // but let's avoid a copy into a temporary array
++ if (!q_SSL_CTX_ctrl(sslContext->ctx,
++ SSL_CTRL_SET_CURVES,
++ qcurves.size(),
++ const_cast(reinterpret_cast(qcurves.data())))) {
++ sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ }
++ } else
++#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC)
++ {
++ // specific curves requested, but not possible to set -> error
++ sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version too old, need at least v1.0.2"));
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ }
++ }
++}
++
++QT_END_NAMESPACE
+diff --git a/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp b/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
+index 90687b05c5..5ebad822f1 100644
+--- a/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
++++ b/qtbase/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
+@@ -1,6 +1,7 @@
+ /****************************************************************************
+ **
+ ** Copyright (C) 2015 Mikkel Krautz
++** Copyright (C) 2016 Richard J. Moore
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the QtNetwork module of the Qt Toolkit.
+@@ -50,8 +51,8 @@
+ #include
+ #endif
+
+-// For q_BN_is_word.
+ #include
++#include
+
+ QT_BEGIN_NAMESPACE
+
+@@ -62,13 +63,6 @@ static bool isSafeDH(DH *dh)
+
+ QSslSocketPrivate::ensureInitialized();
+
+- // Mark p < 1024 bits as unsafe.
+- if (q_BN_num_bits(dh->p) < 1024) {
+- return false;
+- }
+-
+- if (q_DH_check(dh, &status) != 1)
+- return false;
+
+ // From https://wiki.openssl.org/index.php/Diffie-Hellman_parameters:
+ //
+@@ -81,11 +75,39 @@ static bool isSafeDH(DH *dh)
+ // Without the test, the IETF parameters would
+ // fail validation. For details, see Diffie-Hellman
+ // Parameter Check (when g = 2, must p mod 24 == 11?).
++#if QT_CONFIG(opensslv11)
++ // Mark p < 1024 bits as unsafe.
++ if (q_DH_bits(dh) < 1024)
++ return false;
++
++ if (q_DH_check(dh, &status) != 1)
++ return false;
++
++ const BIGNUM *p = nullptr;
++ const BIGNUM *q = nullptr;
++ const BIGNUM *g = nullptr;
++ q_DH_get0_pqg(dh, &p, &q, &g);
++
++ if (q_BN_is_word(const_cast(g), DH_GENERATOR_2)) {
++ long residue = q_BN_mod_word(p, 24);
++ if (residue == 11 || residue == 23)
++ status &= ~DH_NOT_SUITABLE_GENERATOR;
++ }
++
++#else
++ // Mark p < 1024 bits as unsafe.
++ if (q_BN_num_bits(dh->p) < 1024)
++ return false;
++
++ if (q_DH_check(dh, &status) != 1)
++ return false;
++
+ if (q_BN_is_word(dh->g, DH_GENERATOR_2)) {
+ long residue = q_BN_mod_word(dh->p, 24);
+ if (residue == 11 || residue == 23)
+ status &= ~DH_NOT_SUITABLE_GENERATOR;
+ }
++#endif
+
+ bad |= DH_CHECK_P_NOT_PRIME;
+ bad |= DH_CHECK_P_NOT_SAFE_PRIME;
+diff --git a/qtbase/src/network/ssl/qsslellipticcurve.h b/qtbase/src/network/ssl/qsslellipticcurve.h
+index 231566063e..57dda19bad 100644
+--- a/qtbase/src/network/ssl/qsslellipticcurve.h
++++ b/qtbase/src/network/ssl/qsslellipticcurve.h
+@@ -80,6 +80,7 @@ private:
+ friend Q_DECL_CONSTEXPR bool operator==(QSslEllipticCurve lhs, QSslEllipticCurve rhs) Q_DECL_NOTHROW;
+ friend Q_DECL_CONSTEXPR uint qHash(QSslEllipticCurve curve, uint seed) Q_DECL_NOTHROW;
+
++ friend class QSslContext;
+ friend class QSslSocketPrivate;
+ friend class QSslSocketBackendPrivate;
+ };
+diff --git a/qtbase/src/network/ssl/qsslellipticcurve_openssl.cpp b/qtbase/src/network/ssl/qsslellipticcurve_openssl.cpp
+index e18197b703..8cd14837f0 100644
+--- a/qtbase/src/network/ssl/qsslellipticcurve_openssl.cpp
++++ b/qtbase/src/network/ssl/qsslellipticcurve_openssl.cpp
+@@ -1,6 +1,7 @@
+ /****************************************************************************
+ **
+ ** Copyright (C) 2014 Governikus GmbH & Co. KG.
++** Copyright (C) 2016 Richard J. Moore
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the QtNetwork module of the Qt Toolkit.
+@@ -78,17 +79,18 @@ QSslEllipticCurve QSslEllipticCurve::fromShortName(const QString &name)
+ QSslEllipticCurve result;
+
+ #ifndef OPENSSL_NO_EC
+- const QByteArray curveNameLatin1 = name.toLatin1();
+
++ const QByteArray curveNameLatin1 = name.toLatin1();
+ int nid = q_OBJ_sn2nid(curveNameLatin1.data());
+
+ #if OPENSSL_VERSION_NUMBER >= 0x10002000L
+- if (nid == 0 && q_SSLeay() >= 0x10002000L)
++ if (nid == 0 && QSslSocket::sslLibraryVersionNumber() >= 0x10002000L)
+ nid = q_EC_curve_nist2nid(curveNameLatin1.data());
+ #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
+
+ result.id = nid;
+-#endif
++
++#endif // !OPENSSL_NO_EC
+
+ return result;
+ }
+diff --git a/qtbase/src/network/ssl/qsslkey_openssl.cpp b/qtbase/src/network/ssl/qsslkey_openssl.cpp
+index 26119023d1..2b03af9441 100644
+--- a/qtbase/src/network/ssl/qsslkey_openssl.cpp
++++ b/qtbase/src/network/ssl/qsslkey_openssl.cpp
+@@ -1,6 +1,7 @@
+ /****************************************************************************
+ **
+-** Copyright (C) 2016 The Qt Company Ltd.
++** Copyright (C) 2017 The Qt Company Ltd.
++** Copyright (C) 2016 Richard J. Moore
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the QtNetwork module of the Qt Toolkit.
+@@ -87,33 +88,32 @@ bool QSslKeyPrivate::fromEVP_PKEY(EVP_PKEY *pkey)
+ if (pkey == nullptr)
+ return false;
+
+- if (pkey->type == EVP_PKEY_RSA) {
++#if QT_CONFIG(opensslv11)
++ const int keyType = q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey));
++#else
++ const int keyType = pkey->type;
++#endif
++ if (keyType == EVP_PKEY_RSA) {
+ isNull = false;
+ algorithm = QSsl::Rsa;
+ type = QSsl::PrivateKey;
+
+- rsa = q_RSA_new();
+- memcpy(rsa, q_EVP_PKEY_get1_RSA(pkey), sizeof(RSA));
+-
++ rsa = q_EVP_PKEY_get1_RSA(pkey);
+ return true;
+- }
+- else if (pkey->type == EVP_PKEY_DSA) {
++ } else if (keyType == EVP_PKEY_DSA) {
+ isNull = false;
+ algorithm = QSsl::Dsa;
+ type = QSsl::PrivateKey;
+
+- dsa = q_DSA_new();
+- memcpy(dsa, q_EVP_PKEY_get1_DSA(pkey), sizeof(DSA));
+-
++ dsa = q_EVP_PKEY_get1_DSA(pkey);
+ return true;
+ }
+ #ifndef OPENSSL_NO_EC
+- else if (pkey->type == EVP_PKEY_EC) {
++ else if (keyType == EVP_PKEY_EC) {
+ isNull = false;
+ algorithm = QSsl::Ec;
+ type = QSsl::PrivateKey;
+- ec = q_EC_KEY_dup(q_EVP_PKEY_get1_EC_KEY(pkey));
+-
++ ec = q_EVP_PKEY_get1_EC_KEY(pkey);
+ return true;
+ }
+ #endif
+@@ -181,8 +181,8 @@ int QSslKeyPrivate::length() const
+ return -1;
+
+ switch (algorithm) {
+- case QSsl::Rsa: return q_BN_num_bits(rsa->n);
+- case QSsl::Dsa: return q_BN_num_bits(dsa->p);
++ case QSsl::Rsa: return q_RSA_bits(rsa);
++ case QSsl::Dsa: return q_DSA_bits(dsa);
+ #ifndef OPENSSL_NO_EC
+ case QSsl::Ec: return q_EC_GROUP_get_degree(q_EC_KEY_get0_group(ec));
+ #endif
+@@ -276,7 +276,13 @@ Qt::HANDLE QSslKeyPrivate::handle() const
+
+ static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv, int enc)
+ {
+- EVP_CIPHER_CTX ctx;
++#if QT_CONFIG(opensslv11)
++ EVP_CIPHER_CTX *ctx = q_EVP_CIPHER_CTX_new();
++#else
++ EVP_CIPHER_CTX evpCipherContext;
++ EVP_CIPHER_CTX *ctx = &evpCipherContext;
++#endif
++
+ const EVP_CIPHER* type = 0;
+ int i = 0, len = 0;
+
+@@ -294,21 +300,44 @@ static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data,
+
+ QByteArray output;
+ output.resize(data.size() + EVP_MAX_BLOCK_LENGTH);
+- q_EVP_CIPHER_CTX_init(&ctx);
+- q_EVP_CipherInit(&ctx, type, NULL, NULL, enc);
+- q_EVP_CIPHER_CTX_set_key_length(&ctx, key.size());
++
++#if QT_CONFIG(opensslv11)
++ q_EVP_CIPHER_CTX_reset(ctx);
++#else
++ q_EVP_CIPHER_CTX_init(ctx);
++#endif
++
++ q_EVP_CipherInit(ctx, type, NULL, NULL, enc);
++ q_EVP_CIPHER_CTX_set_key_length(ctx, key.size());
+ if (cipher == QSslKeyPrivate::Rc2Cbc)
+- q_EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_SET_RC2_KEY_BITS, 8 * key.size(), NULL);
+- q_EVP_CipherInit(&ctx, NULL,
++ q_EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, 8 * key.size(), NULL);
++
++#if QT_CONFIG(opensslv11)
++ // EVP_CipherInit in 1.1 resets the context thus making the calls above useless.
++ // We call EVP_CipherInit_ex instead.
++ q_EVP_CipherInit_ex(ctx, nullptr, nullptr,
++ reinterpret_cast(key.constData()),
++ reinterpret_cast(iv.constData()),
++ enc);
++#else
++ q_EVP_CipherInit(ctx, NULL,
+ reinterpret_cast(key.constData()),
+ reinterpret_cast(iv.constData()), enc);
+- q_EVP_CipherUpdate(&ctx,
++#endif // opensslv11
++
++ q_EVP_CipherUpdate(ctx,
+ reinterpret_cast(output.data()), &len,
+ reinterpret_cast(data.constData()), data.size());
+- q_EVP_CipherFinal(&ctx,
++ q_EVP_CipherFinal(ctx,
+ reinterpret_cast(output.data()) + len, &i);
+ len += i;
+- q_EVP_CIPHER_CTX_cleanup(&ctx);
++
++#if QT_CONFIG(opensslv11)
++ q_EVP_CIPHER_CTX_reset(ctx);
++ q_EVP_CIPHER_CTX_free(ctx);
++#else
++ q_EVP_CIPHER_CTX_cleanup(ctx);
++#endif
+
+ return output.left(len);
+ }
+diff --git a/qtbase/src/network/ssl/qsslsocket_openssl.cpp b/qtbase/src/network/ssl/qsslsocket_openssl.cpp
+index f5b493897e..45cea490fc 100644
+--- a/qtbase/src/network/ssl/qsslsocket_openssl.cpp
++++ b/qtbase/src/network/ssl/qsslsocket_openssl.cpp
+@@ -1,6 +1,6 @@
+ /****************************************************************************
+ **
+-** Copyright (C) 2016 The Qt Company Ltd.
++** Copyright (C) 2017 The Qt Company Ltd.
+ ** Copyright (C) 2014 Governikus GmbH & Co. KG
+ ** Contact: https://www.qt.io/licensing/
+ **
+@@ -97,70 +97,6 @@ bool QSslSocketPrivate::s_loadRootCertsOnDemand = false;
+ int QSslSocketBackendPrivate::s_indexForSSLExtraData = -1;
+ #endif
+
+-/* \internal
+-
+- From OpenSSL's thread(3) manual page:
+-
+- OpenSSL can safely be used in multi-threaded applications provided that at
+- least two callback functions are set.
+-
+- locking_function(int mode, int n, const char *file, int line) is needed to
+- perform locking on shared data structures. (Note that OpenSSL uses a
+- number of global data structures that will be implicitly shared
+- whenever multiple threads use OpenSSL.) Multi-threaded
+- applications will crash at random if it is not set. ...
+- ...
+- id_function(void) is a function that returns a thread ID. It is not
+- needed on Windows nor on platforms where getpid() returns a different
+- ID for each thread (most notably Linux)
+-*/
+-class QOpenSslLocks
+-{
+-public:
+- inline QOpenSslLocks()
+- : initLocker(QMutex::Recursive),
+- locksLocker(QMutex::Recursive)
+- {
+- QMutexLocker locker(&locksLocker);
+- int numLocks = q_CRYPTO_num_locks();
+- locks = new QMutex *[numLocks];
+- memset(locks, 0, numLocks * sizeof(QMutex *));
+- }
+- inline ~QOpenSslLocks()
+- {
+- QMutexLocker locker(&locksLocker);
+- for (int i = 0; i < q_CRYPTO_num_locks(); ++i)
+- delete locks[i];
+- delete [] locks;
+-
+- QSslSocketPrivate::deinitialize();
+- }
+- inline QMutex *lock(int num)
+- {
+- QMutexLocker locker(&locksLocker);
+- QMutex *tmp = locks[num];
+- if (!tmp)
+- tmp = locks[num] = new QMutex(QMutex::Recursive);
+- return tmp;
+- }
+-
+- QMutex *globalLock()
+- {
+- return &locksLocker;
+- }
+-
+- QMutex *initLock()
+- {
+- return &initLocker;
+- }
+-
+-private:
+- QMutex initLocker;
+- QMutex locksLocker;
+- QMutex **locks;
+-};
+-Q_GLOBAL_STATIC(QOpenSslLocks, openssl_locks)
+-
+ QString QSslSocketBackendPrivate::getErrorsFromOpenSsl()
+ {
+ QString errorString;
+@@ -175,20 +111,6 @@ QString QSslSocketBackendPrivate::getErrorsFromOpenSsl()
+ }
+
+ extern "C" {
+-static void locking_function(int mode, int lockNumber, const char *, int)
+-{
+- QMutex *mutex = openssl_locks()->lock(lockNumber);
+-
+- // Lock or unlock it
+- if (mode & CRYPTO_LOCK)
+- mutex->lock();
+- else
+- mutex->unlock();
+-}
+-static unsigned long id_function()
+-{
+- return (quintptr)QThread::currentThreadId();
+-}
+
+ #if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
+ static unsigned int q_ssl_psk_client_callback(SSL *ssl,
+@@ -227,7 +149,7 @@ QSslSocketBackendPrivate::~QSslSocketBackendPrivate()
+ destroySslContext();
+ }
+
+-QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher)
++QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(const SSL_CIPHER *cipher)
+ {
+ QSslCipher ciph;
+
+@@ -283,6 +205,7 @@ struct QSslErrorList
+ QMutex mutex;
+ QVector errors;
+ };
++
+ Q_GLOBAL_STATIC(QSslErrorList, _q_sslErrorList)
+
+ int q_X509Callback(int ok, X509_STORE_CTX *ctx)
+@@ -312,7 +235,7 @@ int q_X509Callback(int ok, X509_STORE_CTX *ctx)
+ }
+ #endif
+ }
+- // Always return OK to allow verification to continue. We're handle the
++ // Always return OK to allow verification to continue. We handle the
+ // errors gracefully after collecting all errors, after verification has
+ // completed.
+ return 1;
+@@ -397,7 +320,7 @@ bool QSslSocketBackendPrivate::initSslContext()
+ if (configuration.protocol != QSsl::SslV2 &&
+ configuration.protocol != QSsl::SslV3 &&
+ configuration.protocol != QSsl::UnknownProtocol &&
+- mode == QSslSocket::SslClientMode && q_SSLeay() >= 0x00090806fL) {
++ mode == QSslSocket::SslClientMode && QSslSocket::sslLibraryVersionNumber() >= 0x00090806fL) {
+ // Set server hostname on TLS extension. RFC4366 section 3.1 requires it in ACE format.
+ QString tlsHostName = verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName;
+ if (tlsHostName.isEmpty())
+@@ -438,13 +361,13 @@ bool QSslSocketBackendPrivate::initSslContext()
+
+ #if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ // Save a pointer to this object into the SSL structure.
+- if (q_SSLeay() >= 0x10001000L)
++ if (QSslSocket::sslLibraryVersionNumber() >= 0x10001000L)
+ q_SSL_set_ex_data(ssl, s_indexForSSLExtraData, this);
+ #endif
+
+ #if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
+ // Set the client callback for PSK
+- if (q_SSLeay() >= 0x10001000L) {
++ if (QSslSocket::sslLibraryVersionNumber() >= 0x10001000L) {
+ if (mode == QSslSocket::SslClientMode)
+ q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_client_callback);
+ else if (mode == QSslSocket::SslServerMode)
+@@ -464,16 +387,6 @@ void QSslSocketBackendPrivate::destroySslContext()
+ sslContextPointer.clear();
+ }
+
+-/*!
+- \internal
+-*/
+-void QSslSocketPrivate::deinitialize()
+-{
+- q_CRYPTO_set_id_callback(0);
+- q_CRYPTO_set_locking_callback(0);
+- q_ERR_free_strings();
+-}
+-
+ /*!
+ \internal
+
+@@ -486,91 +399,6 @@ bool QSslSocketPrivate::supportsSsl()
+ return ensureLibraryLoaded();
+ }
+
+-bool QSslSocketPrivate::ensureLibraryLoaded()
+-{
+- if (!q_resolveOpenSslSymbols())
+- return false;
+-
+- // Check if the library itself needs to be initialized.
+- QMutexLocker locker(openssl_locks()->initLock());
+-
+- if (!s_libraryLoaded) {
+- s_libraryLoaded = true;
+-
+- // Initialize OpenSSL.
+- q_CRYPTO_set_id_callback(id_function);
+- q_CRYPTO_set_locking_callback(locking_function);
+- if (q_SSL_library_init() != 1)
+- return false;
+- q_SSL_load_error_strings();
+- q_OpenSSL_add_all_algorithms();
+-
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+- if (q_SSLeay() >= 0x10001000L)
+- QSslSocketBackendPrivate::s_indexForSSLExtraData = q_SSL_get_ex_new_index(0L, NULL, NULL, NULL, NULL);
+-#endif
+-
+- // Initialize OpenSSL's random seed.
+- if (!q_RAND_status()) {
+- qWarning("Random number generator not seeded, disabling SSL support");
+- return false;
+- }
+- }
+- return true;
+-}
+-
+-void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
+-{
+- QMutexLocker locker(openssl_locks()->initLock());
+- if (s_loadedCiphersAndCerts)
+- return;
+- s_loadedCiphersAndCerts = true;
+-
+- resetDefaultCiphers();
+- resetDefaultEllipticCurves();
+-
+-#if QT_CONFIG(library)
+- //load symbols needed to receive certificates from system store
+-#if defined(Q_OS_WIN)
+- HINSTANCE hLib = LoadLibraryW(L"Crypt32");
+- if (hLib) {
+- ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW");
+- ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore");
+- ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore");
+- if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
+- qCWarning(lcSsl, "could not resolve symbols in crypt32 library"); // should never happen
+- } else {
+- qCWarning(lcSsl, "could not load crypt32 library"); // should never happen
+- }
+-#elif defined(Q_OS_QNX)
+- s_loadRootCertsOnDemand = true;
+-#elif defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
+- // check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there)
+- QList dirs = unixRootCertDirectories();
+- QStringList symLinkFilter;
+- symLinkFilter << QLatin1String("[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]");
+- for (int a = 0; a < dirs.count(); ++a) {
+- QDirIterator iterator(QLatin1String(dirs.at(a)), symLinkFilter, QDir::Files);
+- if (iterator.hasNext()) {
+- s_loadRootCertsOnDemand = true;
+- break;
+- }
+- }
+-#endif
+-#endif // QT_CONFIG(library)
+- // if on-demand loading was not enabled, load the certs now
+- if (!s_loadRootCertsOnDemand)
+- setDefaultCaCertificates(systemCaCertificates());
+-#ifdef Q_OS_WIN
+- //Enabled for fetching additional root certs from windows update on windows 6+
+- //This flag is set false by setDefaultCaCertificates() indicating the app uses
+- //its own cert bundle rather than the system one.
+- //Same logic that disables the unix on demand cert loading.
+- //Unlike unix, we do preload the certificates from the cert store.
+- if ((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) >= QSysInfo::WV_6_0)
+- s_loadRootCertsOnDemand = true;
+-#endif
+-}
+
+ /*!
+ \internal
+@@ -587,26 +415,6 @@ void QSslSocketPrivate::ensureInitialized()
+ ensureCiphersAndCertsLoaded();
+ }
+
+-long QSslSocketPrivate::sslLibraryVersionNumber()
+-{
+- if (!supportsSsl())
+- return 0;
+-
+- return q_SSLeay();
+-}
+-
+-QString QSslSocketPrivate::sslLibraryVersionString()
+-{
+- if (!supportsSsl())
+- return QString();
+-
+- const char *versionString = q_SSLeay_version(SSLEAY_VERSION);
+- if (!versionString)
+- return QString();
+-
+- return QString::fromLatin1(versionString);
+-}
+-
+ long QSslSocketPrivate::sslLibraryBuildVersionNumber()
+ {
+ return OPENSSL_VERSION_NUMBER;
+@@ -628,7 +436,11 @@ QString QSslSocketPrivate::sslLibraryBuildVersionString()
+ */
+ void QSslSocketPrivate::resetDefaultCiphers()
+ {
++#if QT_CONFIG(opensslv11)
++ SSL_CTX *myCtx = q_SSL_CTX_new(q_TLS_client_method());
++#else
+ SSL_CTX *myCtx = q_SSL_CTX_new(q_SSLv23_client_method());
++#endif
+ SSL *mySsl = q_SSL_new(myCtx);
+
+ QList ciphers;
+@@ -664,7 +476,7 @@ void QSslSocketPrivate::resetDefaultEllipticCurves()
+ QVector curves;
+
+ #ifndef OPENSSL_NO_EC
+- const size_t curveCount = q_EC_get_builtin_curves(NULL, 0);
++ const size_t curveCount = q_EC_get_builtin_curves(nullptr, 0);
+
+ QVarLengthArray builtinCurves(static_cast(curveCount));
+
+@@ -698,13 +510,14 @@ QList QSslSocketPrivate::systemCaCertificates()
+ if (ptrCertOpenSystemStoreW && ptrCertFindCertificateInStore && ptrCertCloseStore) {
+ HCERTSTORE hSystemStore;
+ hSystemStore = ptrCertOpenSystemStoreW(0, L"ROOT");
+- if(hSystemStore) {
+- PCCERT_CONTEXT pc = NULL;
+- while(1) {
+- pc = ptrCertFindCertificateInStore( hSystemStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, pc);
+- if(!pc)
++ if (hSystemStore) {
++ PCCERT_CONTEXT pc = nullptr;
++ while (1) {
++ pc = ptrCertFindCertificateInStore(hSystemStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, nullptr, pc);
++ if (!pc)
+ break;
+- QByteArray der((const char *)(pc->pbCertEncoded), static_cast(pc->cbCertEncoded));
++ QByteArray der(reinterpret_cast(pc->pbCertEncoded),
++ static_cast(pc->cbCertEncoded));
+ QSslCertificate cert(der, QSsl::Der);
+ systemCerts.append(cert);
+ }
+@@ -1504,14 +1317,8 @@ QSslCipher QSslSocketBackendPrivate::sessionCipher() const
+ {
+ if (!ssl)
+ return QSslCipher();
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+- // FIXME This is fairly evil, but needed to keep source level compatibility
+- // with the OpenSSL 0.9.x implementation at maximum -- some other functions
+- // don't take a const SSL_CIPHER* when they should
+- SSL_CIPHER *sessionCipher = const_cast(q_SSL_get_current_cipher(ssl));
+-#else
+- SSL_CIPHER *sessionCipher = q_SSL_get_current_cipher(ssl);
+-#endif
++
++ const SSL_CIPHER *sessionCipher = q_SSL_get_current_cipher(ssl);
+ return sessionCipher ? QSslCipher_from_SSL_CIPHER(sessionCipher) : QSslCipher();
+ }
+
+@@ -1537,112 +1344,6 @@ QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const
+ return QSsl::UnknownProtocol;
+ }
+
+-void QSslSocketBackendPrivate::continueHandshake()
+-{
+- Q_Q(QSslSocket);
+- // if we have a max read buffer size, reset the plain socket's to match
+- if (readBufferMaxSize)
+- plainSocket->setReadBufferSize(readBufferMaxSize);
+-
+- if (q_SSL_ctrl((ssl), SSL_CTRL_GET_SESSION_REUSED, 0, NULL))
+- configuration.peerSessionShared = true;
+-
+-#ifdef QT_DECRYPT_SSL_TRAFFIC
+- if (ssl->session && ssl->s3) {
+- const char *mk = reinterpret_cast(ssl->session->master_key);
+- QByteArray masterKey(mk, ssl->session->master_key_length);
+- const char *random = reinterpret_cast(ssl->s3->client_random);
+- QByteArray clientRandom(random, SSL3_RANDOM_SIZE);
+-
+- // different format, needed for e.g. older Wireshark versions:
+-// const char *sid = reinterpret_cast(ssl->session->session_id);
+-// QByteArray sessionID(sid, ssl->session->session_id_length);
+-// QByteArray debugLineRSA("RSA Session-ID:");
+-// debugLineRSA.append(sessionID.toHex().toUpper());
+-// debugLineRSA.append(" Master-Key:");
+-// debugLineRSA.append(masterKey.toHex().toUpper());
+-// debugLineRSA.append("\n");
+-
+- QByteArray debugLineClientRandom("CLIENT_RANDOM ");
+- debugLineClientRandom.append(clientRandom.toHex().toUpper());
+- debugLineClientRandom.append(" ");
+- debugLineClientRandom.append(masterKey.toHex().toUpper());
+- debugLineClientRandom.append("\n");
+-
+- QString sslKeyFile = QDir::tempPath() + QLatin1String("/qt-ssl-keys");
+- QFile file(sslKeyFile);
+- if (!file.open(QIODevice::Append))
+- qCWarning(lcSsl) << "could not open file" << sslKeyFile << "for appending";
+- if (!file.write(debugLineClientRandom))
+- qCWarning(lcSsl) << "could not write to file" << sslKeyFile;
+- file.close();
+- } else {
+- qCWarning(lcSsl, "could not decrypt SSL traffic");
+- }
+-#endif
+-
+- // Cache this SSL session inside the QSslContext
+- if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionSharing)) {
+- if (!sslContextPointer->cacheSession(ssl)) {
+- sslContextPointer.clear(); // we could not cache the session
+- } else {
+- // Cache the session for permanent usage as well
+- if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionPersistence)) {
+- if (!sslContextPointer->sessionASN1().isEmpty())
+- configuration.sslSession = sslContextPointer->sessionASN1();
+- configuration.sslSessionTicketLifeTimeHint = sslContextPointer->sessionTicketLifeTimeHint();
+- }
+- }
+- }
+-
+-#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
+-
+- configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status;
+- if (sslContextPointer->npnContext().status == QSslConfiguration::NextProtocolNegotiationUnsupported) {
+- // we could not agree -> be conservative and use HTTP/1.1
+- configuration.nextNegotiatedProtocol = QByteArrayLiteral("http/1.1");
+- } else {
+- const unsigned char *proto = 0;
+- unsigned int proto_len = 0;
+-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+- if (q_SSLeay() >= 0x10002000L) {
+- q_SSL_get0_alpn_selected(ssl, &proto, &proto_len);
+- if (proto_len && mode == QSslSocket::SslClientMode) {
+- // Client does not have a callback that sets it ...
+- configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated;
+- }
+- }
+-
+- if (!proto_len) { // Test if NPN was more lucky ...
+-#else
+- {
+-#endif
+- q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len);
+- }
+-
+- if (proto_len)
+- configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast(proto), proto_len);
+- else
+- configuration.nextNegotiatedProtocol.clear();
+- }
+-#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
+-
+-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+- if (q_SSLeay() >= 0x10002000L && mode == QSslSocket::SslClientMode) {
+- EVP_PKEY *key;
+- if (q_SSL_get_server_tmp_key(ssl, &key))
+- configuration.ephemeralServerKey = QSslKey(key, QSsl::PublicKey);
+- }
+-#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ...
+-
+- connectionEncrypted = true;
+- emit q->encrypted();
+- if (autoStartHandshake && pendingClose) {
+- pendingClose = false;
+- q->disconnectFromHost();
+- }
+-}
+-
+ QList QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509)
+ {
+ ensureInitialized();
+@@ -1696,12 +1397,12 @@ QList QSslSocketBackendPrivate::verify(const QList &
+ QMutexLocker sslErrorListMutexLocker(&_q_sslErrorList()->mutex);
+
+ // Register a custom callback to get all verification errors.
+- X509_STORE_set_verify_cb_func(certStore, q_X509Callback);
++ q_X509_STORE_set_verify_cb(certStore, q_X509Callback);
+
+ // Build the chain of intermediate certificates
+ STACK_OF(X509) *intermediates = 0;
+ if (certificateChain.length() > 1) {
+- intermediates = (STACK_OF(X509) *) q_sk_new_null();
++ intermediates = (STACK_OF(X509) *) q_OPENSSL_sk_new_null();
+
+ if (!intermediates) {
+ q_X509_STORE_free(certStore);
+@@ -1715,11 +1416,8 @@ QList QSslSocketBackendPrivate::verify(const QList &
+ first = false;
+ continue;
+ }
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+- q_sk_push( (_STACK *)intermediates, reinterpret_cast(cert.handle()));
+-#else
+- q_sk_push( (STACK *)intermediates, reinterpret_cast(cert.handle()));
+-#endif
++
++ q_OPENSSL_sk_push((OPENSSL_STACK *)intermediates, reinterpret_cast(cert.handle()));
+ }
+ }
+
+@@ -1743,11 +1441,7 @@ QList QSslSocketBackendPrivate::verify(const QList &
+ (void) q_X509_verify_cert(storeContext);
+
+ q_X509_STORE_CTX_free(storeContext);
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+- q_sk_free( (_STACK *) intermediates);
+-#else
+- q_sk_free( (STACK *) intermediates);
+-#endif
++ q_OPENSSL_sk_free((OPENSSL_STACK *)intermediates);
+
+ // Now process the errors
+ const auto errorList = std::move(_q_sslErrorList()->errors);
+@@ -1821,7 +1515,8 @@ bool QSslSocketBackendPrivate::importPkcs12(QIODevice *device,
+ // Convert to Qt types
+ if (!key->d->fromEVP_PKEY(pkey)) {
+ qCWarning(lcSsl, "Unable to convert private key");
+- q_sk_pop_free(reinterpret_cast(ca), reinterpret_cast(q_sk_free));
++ q_OPENSSL_sk_pop_free(reinterpret_cast(ca),
++ reinterpret_cast(q_OPENSSL_sk_free));
+ q_X509_free(x509);
+ q_EVP_PKEY_free(pkey);
+ q_PKCS12_free(p12);
+@@ -1836,7 +1531,11 @@ bool QSslSocketBackendPrivate::importPkcs12(QIODevice *device,
+ *caCertificates = QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates(ca);
+
+ // Clean up
+- q_sk_pop_free(reinterpret_cast(ca), reinterpret_cast(q_sk_free));
++ // TODO: verify ASAP, in the past we had sk_pop_free with q_OPENSSL_sk_free
++ // which seems to be blatantly wrong and even crashes with 1.1.
++ q_OPENSSL_sk_pop_free(reinterpret_cast(ca),
++ reinterpret_cast(q_X509_free));
++
+ q_X509_free(x509);
+ q_EVP_PKEY_free(pkey);
+ q_PKCS12_free(p12);
+diff --git a/qtbase/src/network/ssl/qsslsocket_openssl11.cpp b/qtbase/src/network/ssl/qsslsocket_openssl11.cpp
+new file mode 100644
+index 0000000000..b6d18943a5
+--- /dev/null
++++ b/qtbase/src/network/ssl/qsslsocket_openssl11.cpp
+@@ -0,0 +1,285 @@
++/****************************************************************************
++**
++** Copyright (C) 2017 The Qt Company Ltd.
++** Copyright (C) 2014 Governikus GmbH & Co. KG
++** Copyright (C) 2016 Richard J. Moore
++** Contact: https://www.qt.io/licensing/
++**
++** This file is part of the QtNetwork module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** Commercial License Usage
++** Licensees holding valid commercial Qt licenses may use this file in
++** accordance with the commercial license agreement provided with the
++** Software or, alternatively, in accordance with the terms contained in
++** a written agreement between you and The Qt Company. For licensing terms
++** and conditions see https://www.qt.io/terms-conditions. For further
++** information use the contact form at https://www.qt.io/contact-us.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 3 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL3 included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 3 requirements
++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU
++** General Public License version 2.0 or (at your option) the GNU General
++** Public license version 3 or any later version approved by the KDE Free
++** Qt Foundation. The licenses are as published by the Free Software
++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
++** included in the packaging of this file. Please review the following
++** information to ensure the GNU General Public License requirements will
++** be met: https://www.gnu.org/licenses/gpl-2.0.html and
++** https://www.gnu.org/licenses/gpl-3.0.html.
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++/****************************************************************************
++**
++** In addition, as a special exception, the copyright holders listed above give
++** permission to link the code of its release of Qt with the OpenSSL project's
++** "OpenSSL" library (or modified versions of the "OpenSSL" library that use the
++** same license as the original version), and distribute the linked executables.
++**
++** You must comply with the GNU General Public License version 2 in all
++** respects for all of the code used other than the "OpenSSL" code. If you
++** modify this file, you may extend this exception to your version of the file,
++** but you are not obligated to do so. If you do not wish to do so, delete
++** this exception statement from your version of this file.
++**
++****************************************************************************/
++
++//#define QT_DECRYPT_SSL_TRAFFIC
++
++#include "qssl_p.h"
++#include "qsslsocket_openssl_p.h"
++#include "qsslsocket_openssl_symbols_p.h"
++#include "qsslsocket.h"
++#include "qsslkey.h"
++
++#include
++#include
++#include
++#include
++#include
++#include
++
++QT_BEGIN_NAMESPACE
++
++Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_opensslInitMutex, (QMutex::Recursive))
++
++/*!
++ \internal
++*/
++void QSslSocketPrivate::deinitialize()
++{
++ // This function exists only for compatibility with the pre-11 code,
++ // where deinitialize() actually does some cleanup. To be discarded
++ // once we retire < 1.1.
++}
++
++bool QSslSocketPrivate::ensureLibraryLoaded()
++{
++ if (!q_resolveOpenSslSymbols())
++ return false;
++
++ const QMutexLocker locker(qt_opensslInitMutex);
++
++ if (!s_libraryLoaded) {
++ s_libraryLoaded = true;
++
++ // Initialize OpenSSL.
++ if (q_OPENSSL_init_ssl(0, nullptr) != 1)
++ return false;
++ q_SSL_load_error_strings();
++ q_OpenSSL_add_all_algorithms();
++
++ QSslSocketBackendPrivate::s_indexForSSLExtraData
++ = q_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, 0L, nullptr, nullptr,
++ nullptr, nullptr);
++
++ // Initialize OpenSSL's random seed.
++ if (!q_RAND_status()) {
++ qWarning("Random number generator not seeded, disabling SSL support");
++ return false;
++ }
++ }
++ return true;
++}
++
++void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
++{
++ const QMutexLocker locker(qt_opensslInitMutex);
++
++ if (s_loadedCiphersAndCerts)
++ return;
++ s_loadedCiphersAndCerts = true;
++
++ resetDefaultCiphers();
++ resetDefaultEllipticCurves();
++
++#if QT_CONFIG(library)
++ //load symbols needed to receive certificates from system store
++#if defined(Q_OS_WIN)
++ HINSTANCE hLib = LoadLibraryW(L"Crypt32");
++ if (hLib) {
++ ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW");
++ ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore");
++ ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore");
++ if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
++ qCWarning(lcSsl, "could not resolve symbols in crypt32 library"); // should never happen
++ } else {
++ qCWarning(lcSsl, "could not load crypt32 library"); // should never happen
++ }
++#elif defined(Q_OS_QNX)
++ s_loadRootCertsOnDemand = true;
++#elif defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
++ // check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there)
++ QList dirs = unixRootCertDirectories();
++ QStringList symLinkFilter;
++ symLinkFilter << QLatin1String("[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]");
++ for (int a = 0; a < dirs.count(); ++a) {
++ QDirIterator iterator(QLatin1String(dirs.at(a)), symLinkFilter, QDir::Files);
++ if (iterator.hasNext()) {
++ s_loadRootCertsOnDemand = true;
++ break;
++ }
++ }
++#endif
++#endif // QT_CONFIG(library)
++ // if on-demand loading was not enabled, load the certs now
++ if (!s_loadRootCertsOnDemand)
++ setDefaultCaCertificates(systemCaCertificates());
++#ifdef Q_OS_WIN
++ //Enabled for fetching additional root certs from windows update on windows 6+
++ //This flag is set false by setDefaultCaCertificates() indicating the app uses
++ //its own cert bundle rather than the system one.
++ //Same logic that disables the unix on demand cert loading.
++ //Unlike unix, we do preload the certificates from the cert store.
++ if ((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) >= QSysInfo::WV_6_0)
++ s_loadRootCertsOnDemand = true;
++#endif
++}
++
++long QSslSocketPrivate::sslLibraryVersionNumber()
++{
++ if (!supportsSsl())
++ return 0;
++
++ return q_OpenSSL_version_num();
++}
++
++QString QSslSocketPrivate::sslLibraryVersionString()
++{
++ if (!supportsSsl())
++ return QString();
++
++ const char *versionString = q_OpenSSL_version(OPENSSL_VERSION);
++ if (!versionString)
++ return QString();
++
++ return QString::fromLatin1(versionString);
++}
++
++void QSslSocketBackendPrivate::continueHandshake()
++{
++ Q_Q(QSslSocket);
++ // if we have a max read buffer size, reset the plain socket's to match
++ if (readBufferMaxSize)
++ plainSocket->setReadBufferSize(readBufferMaxSize);
++
++ if (q_SSL_session_reused(ssl))
++ configuration.peerSessionShared = true;
++
++#ifdef QT_DECRYPT_SSL_TRAFFIC
++ if (q_SSL_get_session(ssl)) {
++ size_t master_key_len = q_SSL_SESSION_get_master_key(q_SSL_get_session(ssl), 0, 0);
++ size_t client_random_len = q_SSL_get_client_random(ssl, 0, 0);
++ QByteArray masterKey(int(master_key_len), 0); // Will not overflow
++ QByteArray clientRandom(int(client_random_len), 0); // Will not overflow
++
++ q_SSL_SESSION_get_master_key(q_SSL_get_session(ssl),
++ reinterpret_cast(masterKey.data()),
++ masterKey.size());
++ q_SSL_get_client_random(ssl, reinterpret_cast(clientRandom.data()),
++ clientRandom.size());
++
++ QByteArray debugLineClientRandom("CLIENT_RANDOM ");
++ debugLineClientRandom.append(clientRandom.toHex().toUpper());
++ debugLineClientRandom.append(" ");
++ debugLineClientRandom.append(masterKey.toHex().toUpper());
++ debugLineClientRandom.append("\n");
++
++ QString sslKeyFile = QDir::tempPath() + QLatin1String("/qt-ssl-keys");
++ QFile file(sslKeyFile);
++ if (!file.open(QIODevice::Append))
++ qCWarning(lcSsl) << "could not open file" << sslKeyFile << "for appending";
++ if (!file.write(debugLineClientRandom))
++ qCWarning(lcSsl) << "could not write to file" << sslKeyFile;
++ file.close();
++ } else {
++ qCWarning(lcSsl, "could not decrypt SSL traffic");
++ }
++#endif
++
++ // Cache this SSL session inside the QSslContext
++ if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionSharing)) {
++ if (!sslContextPointer->cacheSession(ssl)) {
++ sslContextPointer.clear(); // we could not cache the session
++ } else {
++ // Cache the session for permanent usage as well
++ if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionPersistence)) {
++ if (!sslContextPointer->sessionASN1().isEmpty())
++ configuration.sslSession = sslContextPointer->sessionASN1();
++ configuration.sslSessionTicketLifeTimeHint = sslContextPointer->sessionTicketLifeTimeHint();
++ }
++ }
++ }
++
++#if !defined(OPENSSL_NO_NEXTPROTONEG)
++
++ configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status;
++ if (sslContextPointer->npnContext().status == QSslConfiguration::NextProtocolNegotiationUnsupported) {
++ // we could not agree -> be conservative and use HTTP/1.1
++ configuration.nextNegotiatedProtocol = QByteArrayLiteral("http/1.1");
++ } else {
++ const unsigned char *proto = 0;
++ unsigned int proto_len = 0;
++
++ q_SSL_get0_alpn_selected(ssl, &proto, &proto_len);
++ if (proto_len && mode == QSslSocket::SslClientMode) {
++ // Client does not have a callback that sets it ...
++ configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated;
++ }
++
++ if (!proto_len) { // Test if NPN was more lucky ...
++ q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len);
++ }
++
++ if (proto_len)
++ configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast(proto), proto_len);
++ else
++ configuration.nextNegotiatedProtocol.clear();
++ }
++#endif // !defined(OPENSSL_NO_NEXTPROTONEG)
++
++ if (mode == QSslSocket::SslClientMode) {
++ EVP_PKEY *key;
++ if (q_SSL_get_server_tmp_key(ssl, &key))
++ configuration.ephemeralServerKey = QSslKey(key, QSsl::PublicKey);
++ }
++
++ connectionEncrypted = true;
++ emit q->encrypted();
++ if (autoStartHandshake && pendingClose) {
++ pendingClose = false;
++ q->disconnectFromHost();
++ }
++}
++
++QT_END_NAMESPACE
+diff --git a/qtbase/src/network/ssl/qsslsocket_openssl11_symbols_p.h b/qtbase/src/network/ssl/qsslsocket_openssl11_symbols_p.h
+new file mode 100644
+index 0000000000..2980b3d23e
+--- /dev/null
++++ b/qtbase/src/network/ssl/qsslsocket_openssl11_symbols_p.h
+@@ -0,0 +1,132 @@
++/****************************************************************************
++**
++** Copyright (C) 2017 The Qt Company Ltd.
++** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
++** Copyright (C) 2016 Richard J. Moore
++** Contact: https://www.qt.io/licensing/
++**
++** This file is part of the QtNetwork module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** Commercial License Usage
++** Licensees holding valid commercial Qt licenses may use this file in
++** accordance with the commercial license agreement provided with the
++** Software or, alternatively, in accordance with the terms contained in
++** a written agreement between you and The Qt Company. For licensing terms
++** and conditions see https://www.qt.io/terms-conditions. For further
++** information use the contact form at https://www.qt.io/contact-us.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 3 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL3 included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 3 requirements
++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU
++** General Public License version 2.0 or (at your option) the GNU General
++** Public license version 3 or any later version approved by the KDE Free
++** Qt Foundation. The licenses are as published by the Free Software
++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
++** included in the packaging of this file. Please review the following
++** information to ensure the GNU General Public License requirements will
++** be met: https://www.gnu.org/licenses/gpl-2.0.html and
++** https://www.gnu.org/licenses/gpl-3.0.html.
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++/****************************************************************************
++**
++** In addition, as a special exception, the copyright holders listed above give
++** permission to link the code of its release of Qt with the OpenSSL project's
++** "OpenSSL" library (or modified versions of the "OpenSSL" library that use the
++** same license as the original version), and distribute the linked executables.
++**
++** You must comply with the GNU General Public License version 2 in all
++** respects for all of the code used other than the "OpenSSL" code. If you
++** modify this file, you may extend this exception to your version of the file,
++** but you are not obligated to do so. If you do not wish to do so, delete
++** this exception statement from your version of this file.
++**
++****************************************************************************/
++
++#ifndef QSSLSOCKET_OPENSSL11_SYMBOLS_P_H
++#define QSSLSOCKET_OPENSSL11_SYMBOLS_P_H
++
++//
++// W A R N I N G
++// -------------
++//
++// This file is not part of the Qt API. It exists purely as an
++// implementation detail. This header file may change from version to
++// version without notice, or even be removed.
++//
++// We mean it.
++//
++
++// Note: this file does not have QT_BEGIN_NAMESPACE/QT_END_NAMESPACE, it's done
++// in qsslsocket_openssl_symbols_p.h.
++
++#ifndef QSSLSOCKET_OPENSSL_SYMBOLS_P_H
++#error "You are not supposed to use this header file, include qsslsocket_openssl_symbols_p.h instead"
++#endif
++
++const unsigned char * q_ASN1_STRING_get0_data(const ASN1_STRING *x);
++
++Q_AUTOTEST_EXPORT BIO *q_BIO_new(const BIO_METHOD *a);
++Q_AUTOTEST_EXPORT const BIO_METHOD *q_BIO_s_mem();
++
++int q_DSA_bits(DSA *a);
++int q_EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c);
++int q_EVP_PKEY_base_id(EVP_PKEY *a);
++int q_RSA_bits(RSA *a);
++int q_OPENSSL_sk_num(OPENSSL_STACK *a);
++void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void (*b)(void *));
++OPENSSL_STACK *q_OPENSSL_sk_new_null();
++void q_OPENSSL_sk_push(OPENSSL_STACK *st, void *data);
++void q_OPENSSL_sk_free(OPENSSL_STACK *a);
++void * q_OPENSSL_sk_value(OPENSSL_STACK *a, int b);
++int q_SSL_session_reused(SSL *a);
++unsigned long q_SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op);
++int q_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
++size_t q_SSL_get_client_random(SSL *a, unsigned char *out, size_t outlen);
++size_t q_SSL_SESSION_get_master_key(const SSL_SESSION *session, unsigned char *out, size_t outlen);
++int q_CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
++const SSL_METHOD *q_TLS_method();
++const SSL_METHOD *q_TLS_client_method();
++const SSL_METHOD *q_TLS_server_method();
++ASN1_TIME *q_X509_getm_notBefore(X509 *a);
++ASN1_TIME *q_X509_getm_notAfter(X509 *a);
++
++long q_X509_get_version(X509 *a);
++EVP_PKEY *q_X509_get_pubkey(X509 *a);
++void q_X509_STORE_set_verify_cb(X509_STORE *ctx, X509_STORE_CTX_verify_cb verify_cb);
++STACK_OF(X509) *q_X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx);
++void q_DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
++int q_DH_bits(DH *dh);
++
++# define q_SSL_load_error_strings() q_OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS \
++ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL)
++
++#define q_SKM_sk_num(type, st) ((int (*)(const STACK_OF(type) *))q_OPENSSL_sk_num)(st)
++#define q_SKM_sk_value(type, st,i) ((type * (*)(const STACK_OF(type) *, int))q_OPENSSL_sk_value)(st, i)
++
++#define q_OPENSSL_add_all_algorithms_conf() q_OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
++ | OPENSSL_INIT_ADD_ALL_DIGESTS \
++ | OPENSSL_INIT_LOAD_CONFIG, NULL)
++#define q_OPENSSL_add_all_algorithms_noconf() q_OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
++ | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)
++
++int q_OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
++void q_CRYPTO_free(void *str, const char *file, int line);
++
++long q_OpenSSL_version_num();
++const char *q_OpenSSL_version(int type);
++
++unsigned long q_SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session);
++
++#endif
+diff --git a/qtbase/src/network/ssl/qsslsocket_openssl_p.h b/qtbase/src/network/ssl/qsslsocket_openssl_p.h
+index b2adb3e547..7f9e884045 100644
+--- a/qtbase/src/network/ssl/qsslsocket_openssl_p.h
++++ b/qtbase/src/network/ssl/qsslsocket_openssl_p.h
+@@ -1,6 +1,6 @@
+ /****************************************************************************
+ **
+-** Copyright (C) 2016 The Qt Company Ltd.
++** Copyright (C) 2017 The Qt Company Ltd.
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the QtNetwork module of the Qt Toolkit.
+@@ -98,8 +98,8 @@
+ #include
+ #include
+
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+-typedef _STACK STACK;
++#if QT_CONFIG(opensslv11)
++#include
+ #endif
+
+ QT_BEGIN_NAMESPACE
+@@ -151,7 +151,7 @@ public:
+ #endif
+
+ Q_AUTOTEST_EXPORT static long setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions);
+- static QSslCipher QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher);
++ static QSslCipher QSslCipher_from_SSL_CIPHER(const SSL_CIPHER *cipher);
+ static QList STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509);
+ static QList verify(const QList &certificateChain, const QString &hostName);
+ static QString getErrorsFromOpenSsl();
+diff --git a/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp b/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp
+index c344a94427..0ef8bf6b5e 100644
+--- a/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp
++++ b/qtbase/src/network/ssl/qsslsocket_openssl_symbols.cpp
+@@ -1,7 +1,8 @@
+ /****************************************************************************
+ **
+-** Copyright (C) 2016 The Qt Company Ltd.
++** Copyright (C) 2017 The Qt Company Ltd.
+ ** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
++** Copyright (C) 2016 Richard J. Moore
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the QtNetwork module of the Qt Toolkit.
+@@ -136,49 +137,195 @@ void qsslSocketCannotResolveSymbolWarning(const char *functionName)
+
+ #endif // QT_LINKED_OPENSSL
+
++#if QT_CONFIG(opensslv11)
++
++// Below are the functions first introduced in version 1.1:
++
++DEFINEFUNC(const unsigned char *, ASN1_STRING_get0_data, const ASN1_STRING *a, a, return 0, return)
++DEFINEFUNC2(int, OPENSSL_init_ssl, uint64_t opts, opts, const OPENSSL_INIT_SETTINGS *settings, settings, return 0, return)
++DEFINEFUNC2(int, OPENSSL_init_crypto, uint64_t opts, opts, const OPENSSL_INIT_SETTINGS *settings, settings, return 0, return)
++DEFINEFUNC(BIO *, BIO_new, const BIO_METHOD *a, a, return 0, return)
++DEFINEFUNC(const BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return)
++DEFINEFUNC2(int, BN_is_word, BIGNUM *a, a, BN_ULONG w, w, return 0, return)
++DEFINEFUNC(int, EVP_CIPHER_CTX_reset, EVP_CIPHER_CTX *c, c, return 0, return)
++DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return)
++DEFINEFUNC(int, RSA_bits, RSA *a, a, return 0, return)
++DEFINEFUNC(int, DSA_bits, DSA *a, a, return 0, return)
++DEFINEFUNC(int, OPENSSL_sk_num, OPENSSL_STACK *a, a, return -1, return)
++DEFINEFUNC2(void, OPENSSL_sk_pop_free, OPENSSL_STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
++DEFINEFUNC(OPENSSL_STACK *, OPENSSL_sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC2(void, OPENSSL_sk_push, OPENSSL_STACK *a, a, void *b, b, return, DUMMYARG)
++DEFINEFUNC(void, OPENSSL_sk_free, OPENSSL_STACK *a, a, return, DUMMYARG)
++DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return 0, return)
++DEFINEFUNC(int, SSL_session_reused, SSL *a, a, return 0, return)
++DEFINEFUNC2(unsigned long, SSL_CTX_set_options, SSL_CTX *ctx, ctx, unsigned long op, op, return 0, return)
++DEFINEFUNC3(size_t, SSL_get_client_random, SSL *a, a, unsigned char *out, out, size_t outlen, outlen, return 0, return)
++DEFINEFUNC3(size_t, SSL_SESSION_get_master_key, const SSL_SESSION *ses, ses, unsigned char *out, out, size_t outlen, outlen, return 0, return)
++DEFINEFUNC6(int, CRYPTO_get_ex_new_index, int class_index, class_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return)
++
++DEFINEFUNC(const SSL_METHOD *, TLS_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(const SSL_METHOD *, TLS_client_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(const SSL_METHOD *, TLS_server_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(ASN1_TIME *, X509_getm_notBefore, X509 *a, a, return 0, return)
++DEFINEFUNC(ASN1_TIME *, X509_getm_notAfter, X509 *a, a, return 0, return)
++DEFINEFUNC(long, X509_get_version, X509 *a, a, return -1, return)
++DEFINEFUNC(EVP_PKEY *, X509_get_pubkey, X509 *a, a, return 0, return)
++DEFINEFUNC2(void, X509_STORE_set_verify_cb, X509_STORE *a, a, X509_STORE_CTX_verify_cb verify_cb, verify_cb, return, DUMMYARG)
++DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get0_chain, X509_STORE_CTX *a, a, return 0, return)
++DEFINEFUNC3(void, CRYPTO_free, void *str, str, const char *file, file, int line, line, return, DUMMYARG)
++DEFINEFUNC(long, OpenSSL_version_num, void, DUMMYARG, return 0, return)
++DEFINEFUNC(const char *, OpenSSL_version, int a, a, return 0, return)
++DEFINEFUNC(unsigned long, SSL_SESSION_get_ticket_lifetime_hint, const SSL_SESSION *session, session, return 0, return)
++DEFINEFUNC4(void, DH_get0_pqg, const DH *dh, dh, const BIGNUM **p, p, const BIGNUM **q, q, const BIGNUM **g, g, return, DUMMYARG)
++DEFINEFUNC(int, DH_bits, DH *dh, dh, return 0, return)
++
++#else // QT_CONFIG(opensslv11)
++
++// Functions below are either deprecated or removed in OpenSSL >= 1.1:
++
++DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return 0, return)
++
+ #ifdef SSLEAY_MACROS
+ DEFINEFUNC3(void *, ASN1_dup, i2d_of_void *a, a, d2i_of_void *b, b, char *c, c, return 0, return)
+ #endif
++DEFINEFUNC2(BIO *, BIO_new_file, const char *filename, filename, const char *mode, mode, return 0, return)
++DEFINEFUNC(void, ERR_clear_error, DUMMYARG, DUMMYARG, return, DUMMYARG)
++DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return 0, return)
++DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return)
++DEFINEFUNC(int, CRYPTO_num_locks, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(void, CRYPTO_set_locking_callback, void (*a)(int, int, const char *, int), a, return, DUMMYARG)
++DEFINEFUNC(void, CRYPTO_set_id_callback, unsigned long (*a)(), a, return, DUMMYARG)
++DEFINEFUNC(void, CRYPTO_free, void *a, a, return, DUMMYARG)
++DEFINEFUNC(unsigned long, ERR_peek_last_error, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(void, ERR_free_strings, void, DUMMYARG, return, DUMMYARG)
++DEFINEFUNC(void, EVP_CIPHER_CTX_cleanup, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
++DEFINEFUNC(void, EVP_CIPHER_CTX_init, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
++
++#ifdef SSLEAY_MACROS
++DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return)
++DEFINEFUNC6(void *, PEM_ASN1_write_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return)
++#endif // SSLEAY_MACROS
++
++DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return)
++DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
++
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++DEFINEFUNC(_STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC2(void, sk_push, _STACK *a, a, void *b, b, return, DUMMYARG)
++DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG)
++DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return 0, return)
++#else
++DEFINEFUNC(STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC2(void, sk_push, STACK *a, a, char *b, b, return, DUMMYARG)
++DEFINEFUNC(void, sk_free, STACK *a, a, return, DUMMYARG)
++DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return 0, return)
++#endif // OPENSSL_VERSION_NUMBER >= 0x10000000L
++
++DEFINEFUNC(int, SSL_library_init, void, DUMMYARG, return -1, return)
++DEFINEFUNC(void, SSL_load_error_strings, void, DUMMYARG, return, DUMMYARG)
++
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++DEFINEFUNC5(int, SSL_get_ex_new_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return)
++#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L
++
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++#ifndef OPENSSL_NO_SSL2
++DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++#ifndef OPENSSL_NO_SSL3_METHOD
++DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++DEFINEFUNC(const SSL_METHOD *, TLSv1_1_client_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(const SSL_METHOD *, TLSv1_2_client_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++#ifndef OPENSSL_NO_SSL2
++DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++#ifndef OPENSSL_NO_SSL3_METHOD
++DEFINEFUNC(const SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++DEFINEFUNC(const SSL_METHOD *, TLSv1_1_server_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(const SSL_METHOD *, TLSv1_2_server_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++#else
++#ifndef OPENSSL_NO_SSL2
++DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++#ifndef OPENSSL_NO_SSL3_METHOD
++DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
++#ifndef OPENSSL_NO_SSL2
++DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++#ifndef OPENSSL_NO_SSL3_METHOD
++DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++
++DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get_chain, X509_STORE_CTX *a, a, return 0, return)
++
++#ifdef SSLEAY_MACROS
++DEFINEFUNC2(int, i2d_DSAPrivateKey, const DSA *a, a, unsigned char **b, b, return -1, return)
++DEFINEFUNC2(int, i2d_RSAPrivateKey, const RSA *a, a, unsigned char **b, b, return -1, return)
++#ifndef OPENSSL_NO_EC
++DEFINEFUNC2(int, i2d_ECPrivateKey, const EC_KEY *a, a, unsigned char **b, b, return -1, return)
++#endif
++DEFINEFUNC3(RSA *, d2i_RSAPrivateKey, RSA **a, a, unsigned char **b, b, long c, c, return 0, return)
++DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, c, return 0, return)
++#ifndef OPENSSL_NO_EC
++DEFINEFUNC3(EC_KEY *, d2i_ECPrivateKey, EC_KEY **a, a, unsigned char **b, b, long c, c, return 0, return)
++#endif
++#endif
++DEFINEFUNC(char *, CONF_get1_default_config_file, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMMYARG)
++DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG)
++DEFINEFUNC(long, SSLeay, void, DUMMYARG, return 0, return)
++DEFINEFUNC(const char *, SSLeay_version, int a, a, return 0, return)
++
++#endif // QT_CONFIG(opensslv11)
++
+ DEFINEFUNC(long, ASN1_INTEGER_get, ASN1_INTEGER *a, a, return 0, return)
+-DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return 0, return)
+ DEFINEFUNC(int, ASN1_STRING_length, ASN1_STRING *a, a, return 0, return)
+-DEFINEFUNC2(int, ASN1_STRING_to_UTF8, unsigned char **a, a, ASN1_STRING *b, b, return 0, return);
++DEFINEFUNC2(int, ASN1_STRING_to_UTF8, unsigned char **a, a, ASN1_STRING *b, b, return 0, return)
+ DEFINEFUNC4(long, BIO_ctrl, BIO *a, a, int b, b, long c, c, void *d, d, return -1, return)
+ DEFINEFUNC(int, BIO_free, BIO *a, a, return 0, return)
+-DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return 0, return)
+ DEFINEFUNC2(BIO *, BIO_new_mem_buf, void *a, a, int b, b, return 0, return)
+ DEFINEFUNC3(int, BIO_read, BIO *a, a, void *b, b, int c, c, return -1, return)
+-DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return)
++
+ DEFINEFUNC3(int, BIO_write, BIO *a, a, const void *b, b, int c, c, return -1, return)
+ DEFINEFUNC(int, BN_num_bits, const BIGNUM *a, a, return 0, return)
+-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
+-DEFINEFUNC2(int, BN_is_word, BIGNUM *a, a, BN_ULONG w, w, return 0, return)
+-#endif
+ DEFINEFUNC2(BN_ULONG, BN_mod_word, const BIGNUM *a, a, BN_ULONG w, w, return static_cast(-1), return)
+ #ifndef OPENSSL_NO_EC
+ DEFINEFUNC(const EC_GROUP*, EC_KEY_get0_group, const EC_KEY* k, k, return 0, return)
+ DEFINEFUNC(int, EC_GROUP_get_degree, const EC_GROUP* g, g, return 0, return)
+ #endif
+-DEFINEFUNC(int, CRYPTO_num_locks, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC(void, CRYPTO_set_locking_callback, void (*a)(int, int, const char *, int), a, return, DUMMYARG)
+-DEFINEFUNC(void, CRYPTO_set_id_callback, unsigned long (*a)(), a, return, DUMMYARG)
+-DEFINEFUNC(void, CRYPTO_free, void *a, a, return, DUMMYARG)
+ DEFINEFUNC(DSA *, DSA_new, DUMMYARG, DUMMYARG, return 0, return)
+ DEFINEFUNC(void, DSA_free, DSA *a, a, return, DUMMYARG)
+ DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, const unsigned char **b, b, long c, c, return 0, return)
+ DEFINEFUNC2(char *, ERR_error_string, unsigned long a, a, char *b, b, return 0, return)
+ DEFINEFUNC(unsigned long, ERR_get_error, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC(void, ERR_free_strings, void, DUMMYARG, return, DUMMYARG)
+-DEFINEFUNC(void, EVP_CIPHER_CTX_cleanup, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
+-DEFINEFUNC(void, EVP_CIPHER_CTX_init, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
+-DEFINEFUNC4(int, EVP_CIPHER_CTX_ctrl, EVP_CIPHER_CTX *ctx, ctx, int type, type, int arg, arg, void *ptr, ptr, return 0, return);
++DEFINEFUNC(EVP_CIPHER_CTX *, EVP_CIPHER_CTX_new, void, DUMMYARG, return 0, return)
++DEFINEFUNC(void, EVP_CIPHER_CTX_free, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
++DEFINEFUNC4(int, EVP_CIPHER_CTX_ctrl, EVP_CIPHER_CTX *ctx, ctx, int type, type, int arg, arg, void *ptr, ptr, return 0, return)
+ DEFINEFUNC2(int, EVP_CIPHER_CTX_set_key_length, EVP_CIPHER_CTX *ctx, ctx, int keylen, keylen, return 0, return)
+-DEFINEFUNC5(int, EVP_CipherInit, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER *type, type, const unsigned char *key, key, const unsigned char *iv, iv, int enc, enc, return 0, return);
+-DEFINEFUNC5(int, EVP_CipherUpdate, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, const unsigned char *in, in, int inl, inl, return 0, return);
+-DEFINEFUNC3(int, EVP_CipherFinal, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, return 0, return);
++DEFINEFUNC5(int, EVP_CipherInit, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER *type, type, const unsigned char *key, key, const unsigned char *iv, iv, int enc, enc, return 0, return)
++DEFINEFUNC6(int, EVP_CipherInit_ex, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER *cipher, cipher, ENGINE *impl, impl, const unsigned char *key, key, const unsigned char *iv, iv, int enc, enc, return 0, return)
++DEFINEFUNC5(int, EVP_CipherUpdate, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, const unsigned char *in, in, int inl, inl, return 0, return)
++DEFINEFUNC3(int, EVP_CipherFinal, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, return 0, return)
+ DEFINEFUNC(const EVP_CIPHER *, EVP_des_cbc, DUMMYARG, DUMMYARG, return 0, return)
+ DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return 0, return)
+ DEFINEFUNC(const EVP_CIPHER *, EVP_rc2_cbc, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(const EVP_MD *, EVP_sha1, DUMMYARG, DUMMYARG, return 0, return)
+ DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, char *c, c, return -1, return)
+ DEFINEFUNC2(int, EVP_PKEY_set1_RSA, EVP_PKEY *a, a, RSA *b, b, return -1, return)
+ DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return)
+@@ -202,10 +349,8 @@ DEFINEFUNC3(int, i2t_ASN1_OBJECT, char *a, a, int b, b, ASN1_OBJECT *c, c, retur
+ DEFINEFUNC4(int, OBJ_obj2txt, char *a, a, int b, b, ASN1_OBJECT *c, c, int d, d, return -1, return)
+
+ DEFINEFUNC(int, OBJ_obj2nid, const ASN1_OBJECT *a, a, return NID_undef, return)
+-#ifdef SSLEAY_MACROS
+-DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return)
+-DEFINEFUNC6(void *, PEM_ASN1_write_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return)
+-#else
++
++#ifndef SSLEAY_MACROS
+ DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PrivateKey, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
+ DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
+ DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
+@@ -218,7 +363,7 @@ DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *b, b, const EVP_CI
+ #ifndef OPENSSL_NO_EC
+ DEFINEFUNC7(int, PEM_write_bio_ECPrivateKey, BIO *a, a, EC_KEY *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return)
+ #endif
+-#endif
++#endif // !SSLEAY_MACROS
+ DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PUBKEY, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
+ DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
+ DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
+@@ -234,23 +379,10 @@ DEFINEFUNC2(void, RAND_seed, const void *a, a, int b, b, return, DUMMYARG)
+ DEFINEFUNC(int, RAND_status, void, DUMMYARG, return -1, return)
+ DEFINEFUNC(RSA *, RSA_new, DUMMYARG, DUMMYARG, return 0, return)
+ DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG)
+-DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return)
+-DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+-DEFINEFUNC(_STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC2(void, sk_push, _STACK *a, a, void *b, b, return, DUMMYARG)
+-DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG)
+-DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return 0, return)
+-#else
+-DEFINEFUNC(STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC2(void, sk_push, STACK *a, a, char *b, b, return, DUMMYARG)
+-DEFINEFUNC(void, sk_free, STACK *a, a, return, DUMMYARG)
+-DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return 0, return)
+-#endif
+ DEFINEFUNC(int, SSL_accept, SSL *a, a, return -1, return)
+ DEFINEFUNC(int, SSL_clear, SSL *a, a, return -1, return)
+-DEFINEFUNC3(char *, SSL_CIPHER_description, SSL_CIPHER *a, a, char *b, b, int c, c, return 0, return)
+-DEFINEFUNC2(int, SSL_CIPHER_get_bits, SSL_CIPHER *a, a, int *b, b, return 0, return)
++DEFINEFUNC3(char *, SSL_CIPHER_description, const SSL_CIPHER *a, a, char *b, b, int c, c, return 0, return)
++DEFINEFUNC2(int, SSL_CIPHER_get_bits, const SSL_CIPHER *a, a, int *b, b, return 0, return)
+ DEFINEFUNC(int, SSL_connect, SSL *a, a, return -1, return)
+ DEFINEFUNC(int, SSL_CTX_check_private_key, const SSL_CTX *a, a, return -1, return)
+ DEFINEFUNC4(long, SSL_CTX_ctrl, SSL_CTX *a, a, int b, b, long c, c, void *d, d, return -1, return)
+@@ -287,8 +419,6 @@ DEFINEFUNC(long, SSL_get_verify_result, const SSL *a, a, return -1, return)
+ #else
+ DEFINEFUNC(long, SSL_get_verify_result, SSL *a, a, return -1, return)
+ #endif
+-DEFINEFUNC(int, SSL_library_init, void, DUMMYARG, return -1, return)
+-DEFINEFUNC(void, SSL_load_error_strings, void, DUMMYARG, return, DUMMYARG)
+ DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return 0, return)
+ DEFINEFUNC4(long, SSL_ctrl, SSL *a, a, int cmd, cmd, long larg, larg, void *parg, parg, return -1, return)
+ DEFINEFUNC3(int, SSL_read, SSL *a, a, void *b, b, int c, c, return -1, return)
+@@ -301,7 +431,6 @@ DEFINEFUNC(void, SSL_SESSION_free, SSL_SESSION *ses, ses, return, DUMMYARG)
+ DEFINEFUNC(SSL_SESSION*, SSL_get1_session, SSL *ssl, ssl, return 0, return)
+ DEFINEFUNC(SSL_SESSION*, SSL_get_session, const SSL *ssl, ssl, return 0, return)
+ #if OPENSSL_VERSION_NUMBER >= 0x10001000L
+-DEFINEFUNC5(int, SSL_get_ex_new_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return)
+ DEFINEFUNC3(int, SSL_set_ex_data, SSL *ssl, ssl, int idx, idx, void *arg, arg, return 0, return)
+ DEFINEFUNC2(void *, SSL_get_ex_data, const SSL *ssl, ssl, int idx, idx, return NULL, return)
+ #endif
+@@ -310,51 +439,9 @@ DEFINEFUNC2(void, SSL_set_psk_client_callback, SSL* ssl, ssl, q_psk_client_callb
+ DEFINEFUNC2(void, SSL_set_psk_server_callback, SSL* ssl, ssl, q_psk_server_callback_t callback, callback, return, DUMMYARG)
+ DEFINEFUNC2(int, SSL_CTX_use_psk_identity_hint, SSL_CTX* ctx, ctx, const char *hint, hint, return 0, return)
+ #endif
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+-#ifndef OPENSSL_NO_SSL2
+-DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+-DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+-DEFINEFUNC(const SSL_METHOD *, TLSv1_1_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC(const SSL_METHOD *, TLSv1_2_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-#ifndef OPENSSL_NO_SSL2
+-DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+-DEFINEFUNC(const SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+-DEFINEFUNC(const SSL_METHOD *, TLSv1_1_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC(const SSL_METHOD *, TLSv1_2_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-#else
+-#ifndef OPENSSL_NO_SSL2
+-DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+-DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC(SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-#ifndef OPENSSL_NO_SSL2
+-DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+-DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+ DEFINEFUNC3(int, SSL_write, SSL *a, a, const void *b, b, int c, c, return -1, return)
+ DEFINEFUNC2(int, X509_cmp, X509 *a, a, X509 *b, b, return -1, return)
++DEFINEFUNC4(int, X509_digest, const X509 *x509, x509, const EVP_MD *type, type, unsigned char *md, md, unsigned int *len, len, return -1, return)
+ #ifndef SSLEAY_MACROS
+ DEFINEFUNC(X509 *, X509_dup, X509 *a, a, return 0, return)
+ #endif
+@@ -378,6 +465,7 @@ DEFINEFUNC2(int, ASN1_STRING_print, BIO *a, a, ASN1_STRING *b, b, return 0, retu
+ DEFINEFUNC2(int, X509_check_issued, X509 *a, a, X509 *b, b, return -1, return)
+ DEFINEFUNC(X509_NAME *, X509_get_issuer_name, X509 *a, a, return 0, return)
+ DEFINEFUNC(X509_NAME *, X509_get_subject_name, X509 *a, a, return 0, return)
++DEFINEFUNC(ASN1_INTEGER *, X509_get_serialNumber, X509 *a, a, return 0, return)
+ DEFINEFUNC(int, X509_verify_cert, X509_STORE_CTX *a, a, return -1, return)
+ DEFINEFUNC(int, X509_NAME_entry_count, X509_NAME *a, a, return 0, return)
+ DEFINEFUNC2(X509_NAME_ENTRY *, X509_NAME_get_entry, X509_NAME *a, a, int b, b, return 0, return)
+@@ -393,25 +481,8 @@ DEFINEFUNC2(int, X509_STORE_CTX_set_purpose, X509_STORE_CTX *a, a, int b, b, ret
+ DEFINEFUNC(int, X509_STORE_CTX_get_error, X509_STORE_CTX *a, a, return -1, return)
+ DEFINEFUNC(int, X509_STORE_CTX_get_error_depth, X509_STORE_CTX *a, a, return -1, return)
+ DEFINEFUNC(X509 *, X509_STORE_CTX_get_current_cert, X509_STORE_CTX *a, a, return 0, return)
+-DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get_chain, X509_STORE_CTX *a, a, return 0, return)
+ DEFINEFUNC(X509_STORE_CTX *, X509_STORE_CTX_new, DUMMYARG, DUMMYARG, return 0, return)
+-#ifdef SSLEAY_MACROS
+-DEFINEFUNC2(int, i2d_DSAPrivateKey, const DSA *a, a, unsigned char **b, b, return -1, return)
+-DEFINEFUNC2(int, i2d_RSAPrivateKey, const RSA *a, a, unsigned char **b, b, return -1, return)
+-#ifndef OPENSSL_NO_EC
+-DEFINEFUNC2(int, i2d_ECPrivateKey, const EC_KEY *a, a, unsigned char **b, b, return -1, return)
+-#endif
+-DEFINEFUNC3(RSA *, d2i_RSAPrivateKey, RSA **a, a, unsigned char **b, b, long c, c, return 0, return)
+-DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, c, return 0, return)
+-#ifndef OPENSSL_NO_EC
+-DEFINEFUNC3(EC_KEY *, d2i_ECPrivateKey, EC_KEY **a, a, unsigned char **b, b, long c, c, return 0, return)
+-#endif
+-#endif
+-DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMMYARG)
+-DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG)
+ DEFINEFUNC3(int, SSL_CTX_load_verify_locations, SSL_CTX *ctx, ctx, const char *CAfile, CAfile, const char *CApath, CApath, return 0, return)
+-DEFINEFUNC(long, SSLeay, void, DUMMYARG, return 0, return)
+-DEFINEFUNC(const char *, SSLeay_version, int a, a, return 0, return)
+ DEFINEFUNC2(int, i2d_SSL_SESSION, SSL_SESSION *in, in, unsigned char **pp, pp, return 0, return)
+ DEFINEFUNC3(SSL_SESSION *, d2i_SSL_SESSION, SSL_SESSION **a, a, const unsigned char **pp, pp, long length, length, return 0, return)
+ #if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
+@@ -694,8 +765,8 @@ static QPair loadOpenSsl()
+ #ifndef Q_OS_DARWIN
+ // second attempt: find the development files libssl.so and libcrypto.so
+ //
+- // disabled on OS X/iOS:
+- // OS X's /usr/lib/libssl.dylib, /usr/lib/libcrypto.dylib will be picked up in the third
++ // disabled on macOS/iOS:
++ // macOS's /usr/lib/libssl.dylib, /usr/lib/libcrypto.dylib will be picked up in the third
+ // attempt, _after_ /Contents/Frameworks has been searched.
+ // iOS does not ship a system libssl.dylib, libcrypto.dylib in the first place.
+ libssl->setFileNameAndVersion(QLatin1String("ssl"), -1);
+@@ -754,7 +825,11 @@ bool q_resolveOpenSslSymbols()
+ static bool symbolsResolved = false;
+ static bool triedToResolveSymbols = false;
+ #ifndef QT_NO_THREAD
++#if QT_CONFIG(opensslv11)
++ QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&q_OPENSSL_init_ssl));
++#else
+ QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&q_SSL_library_init));
++#endif
+ #endif
+ if (symbolsResolved)
+ return true;
+@@ -771,11 +846,145 @@ bool q_resolveOpenSslSymbols()
+ // failed to load them
+ return false;
+
++#if QT_CONFIG(opensslv11)
++
++ RESOLVEFUNC(OPENSSL_init_ssl)
++ RESOLVEFUNC(OPENSSL_init_crypto)
++ RESOLVEFUNC(ASN1_STRING_get0_data)
++ RESOLVEFUNC(EVP_CIPHER_CTX_reset)
++ RESOLVEFUNC(EVP_PKEY_base_id)
++ RESOLVEFUNC(RSA_bits)
++ RESOLVEFUNC(OPENSSL_sk_new_null)
++ RESOLVEFUNC(OPENSSL_sk_push)
++ RESOLVEFUNC(OPENSSL_sk_free)
++ RESOLVEFUNC(OPENSSL_sk_num)
++ RESOLVEFUNC(OPENSSL_sk_pop_free)
++ RESOLVEFUNC(OPENSSL_sk_value)
++ RESOLVEFUNC(DH_get0_pqg)
++ RESOLVEFUNC(SSL_CTX_set_options)
++ RESOLVEFUNC(SSL_get_client_random)
++ RESOLVEFUNC(SSL_SESSION_get_master_key)
++ RESOLVEFUNC(SSL_session_reused)
++ RESOLVEFUNC(SSL_get_session)
++ RESOLVEFUNC(CRYPTO_get_ex_new_index)
++ RESOLVEFUNC(TLS_method)
++ RESOLVEFUNC(TLS_client_method)
++ RESOLVEFUNC(TLS_server_method)
++ RESOLVEFUNC(X509_STORE_CTX_get0_chain)
++ RESOLVEFUNC(X509_getm_notBefore)
++ RESOLVEFUNC(X509_getm_notAfter)
++ RESOLVEFUNC(X509_get_version)
++ RESOLVEFUNC(X509_get_pubkey)
++ RESOLVEFUNC(X509_STORE_set_verify_cb)
++ RESOLVEFUNC(CRYPTO_free)
++ RESOLVEFUNC(OpenSSL_version_num)
++ RESOLVEFUNC(OpenSSL_version)
++ if (!_q_OpenSSL_version) {
++ // Apparently, we were built with OpenSSL 1.1 enabled but are now using
++ // a wrong library.
++ delete libs.first;
++ delete libs.second;
++ qCWarning(lcSsl, "Incompatible version of OpenSSL");
++ return false;
++ }
++
++ RESOLVEFUNC(SSL_SESSION_get_ticket_lifetime_hint)
++ RESOLVEFUNC(DH_bits)
++ RESOLVEFUNC(DSA_bits)
++
++#else // !opensslv11
++
++ RESOLVEFUNC(ASN1_STRING_data)
++
+ #ifdef SSLEAY_MACROS
+ RESOLVEFUNC(ASN1_dup)
++#endif // SSLEAY_MACROS
++ RESOLVEFUNC(BIO_new_file)
++ RESOLVEFUNC(ERR_clear_error)
++ RESOLVEFUNC(CRYPTO_free)
++ RESOLVEFUNC(CRYPTO_num_locks)
++ RESOLVEFUNC(CRYPTO_set_id_callback)
++ RESOLVEFUNC(CRYPTO_set_locking_callback)
++ RESOLVEFUNC(ERR_peek_last_error)
++ RESOLVEFUNC(ERR_free_strings)
++ RESOLVEFUNC(EVP_CIPHER_CTX_cleanup)
++ RESOLVEFUNC(EVP_CIPHER_CTX_init)
++
++#ifdef SSLEAY_MACROS // ### verify
++ RESOLVEFUNC(PEM_ASN1_read_bio)
++#endif // SSLEAY_MACROS
++
++ RESOLVEFUNC(sk_new_null)
++ RESOLVEFUNC(sk_push)
++ RESOLVEFUNC(sk_free)
++ RESOLVEFUNC(sk_num)
++ RESOLVEFUNC(sk_pop_free)
++ RESOLVEFUNC(sk_value)
++ RESOLVEFUNC(SSL_library_init)
++ RESOLVEFUNC(SSL_load_error_strings)
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++ RESOLVEFUNC(SSL_get_ex_new_index)
++#endif
++#ifndef OPENSSL_NO_SSL2
++ RESOLVEFUNC(SSLv2_client_method)
+ #endif
++#ifndef OPENSSL_NO_SSL3_METHOD
++ RESOLVEFUNC(SSLv3_client_method)
++#endif
++ RESOLVEFUNC(SSLv23_client_method)
++ RESOLVEFUNC(TLSv1_client_method)
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++ RESOLVEFUNC(TLSv1_1_client_method)
++ RESOLVEFUNC(TLSv1_2_client_method)
++#endif
++#ifndef OPENSSL_NO_SSL2
++ RESOLVEFUNC(SSLv2_server_method)
++#endif
++#ifndef OPENSSL_NO_SSL3_METHOD
++ RESOLVEFUNC(SSLv3_server_method)
++#endif
++ RESOLVEFUNC(SSLv23_server_method)
++ RESOLVEFUNC(TLSv1_server_method)
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++ RESOLVEFUNC(TLSv1_1_server_method)
++ RESOLVEFUNC(TLSv1_2_server_method)
++#endif
++ RESOLVEFUNC(X509_STORE_CTX_get_chain)
++#ifdef SSLEAY_MACROS
++ RESOLVEFUNC(i2d_DSAPrivateKey)
++ RESOLVEFUNC(i2d_RSAPrivateKey)
++ RESOLVEFUNC(d2i_DSAPrivateKey)
++ RESOLVEFUNC(d2i_RSAPrivateKey)
++#endif
++ RESOLVEFUNC(CONF_get1_default_config_file)
++ RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf)
++ RESOLVEFUNC(OPENSSL_add_all_algorithms_conf)
++ RESOLVEFUNC(SSLeay)
++
++ if (!_q_SSLeay || q_SSLeay() >= 0x10100000L) {
++ // OpenSSL 1.1 has deprecated and removed SSLeay. We consider a failure to
++ // resolve this symbol as a failure to resolve symbols.
++ // The right operand of '||' above is ... a bit of paranoia.
++ delete libs.first;
++ delete libs.second;
++ qCWarning(lcSsl, "Incompatible version of OpenSSL");
++ return false;
++ }
++
++
++ RESOLVEFUNC(SSLeay_version)
++
++#ifndef OPENSSL_NO_EC
++#if OPENSSL_VERSION_NUMBER >= 0x10002000L
++ if (q_SSLeay() >= 0x10002000L)
++ RESOLVEFUNC(EC_curve_nist2nid)
++#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
++#endif // OPENSSL_NO_EC
++
++
++#endif // !opensslv11
++
+ RESOLVEFUNC(ASN1_INTEGER_get)
+- RESOLVEFUNC(ASN1_STRING_data)
+ RESOLVEFUNC(ASN1_STRING_length)
+ RESOLVEFUNC(ASN1_STRING_to_UTF8)
+ RESOLVEFUNC(BIO_ctrl)
+@@ -794,25 +1003,22 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(BN_is_word)
+ #endif
+ RESOLVEFUNC(BN_mod_word)
+- RESOLVEFUNC(CRYPTO_free)
+- RESOLVEFUNC(CRYPTO_num_locks)
+- RESOLVEFUNC(CRYPTO_set_id_callback)
+- RESOLVEFUNC(CRYPTO_set_locking_callback)
+ RESOLVEFUNC(DSA_new)
+ RESOLVEFUNC(DSA_free)
+ RESOLVEFUNC(ERR_error_string)
+ RESOLVEFUNC(ERR_get_error)
+- RESOLVEFUNC(ERR_free_strings)
+- RESOLVEFUNC(EVP_CIPHER_CTX_cleanup)
+- RESOLVEFUNC(EVP_CIPHER_CTX_init)
++ RESOLVEFUNC(EVP_CIPHER_CTX_new)
++ RESOLVEFUNC(EVP_CIPHER_CTX_free)
+ RESOLVEFUNC(EVP_CIPHER_CTX_ctrl)
+ RESOLVEFUNC(EVP_CIPHER_CTX_set_key_length)
+ RESOLVEFUNC(EVP_CipherInit)
++ RESOLVEFUNC(EVP_CipherInit_ex)
+ RESOLVEFUNC(EVP_CipherUpdate)
+ RESOLVEFUNC(EVP_CipherFinal)
+ RESOLVEFUNC(EVP_des_cbc)
+ RESOLVEFUNC(EVP_des_ede3_cbc)
+ RESOLVEFUNC(EVP_rc2_cbc)
++ RESOLVEFUNC(EVP_sha1)
+ RESOLVEFUNC(EVP_PKEY_assign)
+ RESOLVEFUNC(EVP_PKEY_set1_RSA)
+ RESOLVEFUNC(EVP_PKEY_set1_DSA)
+@@ -834,9 +1040,8 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(i2t_ASN1_OBJECT)
+ RESOLVEFUNC(OBJ_obj2txt)
+ RESOLVEFUNC(OBJ_obj2nid)
+-#ifdef SSLEAY_MACROS // ### verify
+- RESOLVEFUNC(PEM_ASN1_read_bio)
+-#else
++
++#ifndef SSLEAY_MACROS
+ RESOLVEFUNC(PEM_read_bio_PrivateKey)
+ RESOLVEFUNC(PEM_read_bio_DSAPrivateKey)
+ RESOLVEFUNC(PEM_read_bio_RSAPrivateKey)
+@@ -849,7 +1054,8 @@ bool q_resolveOpenSslSymbols()
+ #ifndef OPENSSL_NO_EC
+ RESOLVEFUNC(PEM_write_bio_ECPrivateKey)
+ #endif
+-#endif
++#endif // !SSLEAY_MACROS
++
+ RESOLVEFUNC(PEM_read_bio_PUBKEY)
+ RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY)
+ RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY)
+@@ -865,12 +1071,6 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(RAND_status)
+ RESOLVEFUNC(RSA_new)
+ RESOLVEFUNC(RSA_free)
+- RESOLVEFUNC(sk_new_null)
+- RESOLVEFUNC(sk_push)
+- RESOLVEFUNC(sk_free)
+- RESOLVEFUNC(sk_num)
+- RESOLVEFUNC(sk_pop_free)
+- RESOLVEFUNC(sk_value)
+ RESOLVEFUNC(SSL_CIPHER_description)
+ RESOLVEFUNC(SSL_CIPHER_get_bits)
+ RESOLVEFUNC(SSL_CTX_check_private_key)
+@@ -898,8 +1098,6 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(SSL_get_peer_cert_chain)
+ RESOLVEFUNC(SSL_get_peer_certificate)
+ RESOLVEFUNC(SSL_get_verify_result)
+- RESOLVEFUNC(SSL_library_init)
+- RESOLVEFUNC(SSL_load_error_strings)
+ RESOLVEFUNC(SSL_new)
+ RESOLVEFUNC(SSL_ctrl)
+ RESOLVEFUNC(SSL_read)
+@@ -912,7 +1110,6 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(SSL_get1_session)
+ RESOLVEFUNC(SSL_get_session)
+ #if OPENSSL_VERSION_NUMBER >= 0x10001000L
+- RESOLVEFUNC(SSL_get_ex_new_index)
+ RESOLVEFUNC(SSL_set_ex_data)
+ RESOLVEFUNC(SSL_get_ex_data)
+ #endif
+@@ -922,30 +1119,6 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(SSL_CTX_use_psk_identity_hint)
+ #endif
+ RESOLVEFUNC(SSL_write)
+-#ifndef OPENSSL_NO_SSL2
+- RESOLVEFUNC(SSLv2_client_method)
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+- RESOLVEFUNC(SSLv3_client_method)
+-#endif
+- RESOLVEFUNC(SSLv23_client_method)
+- RESOLVEFUNC(TLSv1_client_method)
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+- RESOLVEFUNC(TLSv1_1_client_method)
+- RESOLVEFUNC(TLSv1_2_client_method)
+-#endif
+-#ifndef OPENSSL_NO_SSL2
+- RESOLVEFUNC(SSLv2_server_method)
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+- RESOLVEFUNC(SSLv3_server_method)
+-#endif
+- RESOLVEFUNC(SSLv23_server_method)
+- RESOLVEFUNC(TLSv1_server_method)
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+- RESOLVEFUNC(TLSv1_1_server_method)
+- RESOLVEFUNC(TLSv1_2_server_method)
+-#endif
+ RESOLVEFUNC(X509_NAME_entry_count)
+ RESOLVEFUNC(X509_NAME_get_entry)
+ RESOLVEFUNC(X509_NAME_ENTRY_get_data)
+@@ -961,12 +1134,12 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(X509_STORE_CTX_get_error)
+ RESOLVEFUNC(X509_STORE_CTX_get_error_depth)
+ RESOLVEFUNC(X509_STORE_CTX_get_current_cert)
+- RESOLVEFUNC(X509_STORE_CTX_get_chain)
+ RESOLVEFUNC(X509_cmp)
+ #ifndef SSLEAY_MACROS
+ RESOLVEFUNC(X509_dup)
+ #endif
+ RESOLVEFUNC(X509_print)
++ RESOLVEFUNC(X509_digest)
+ RESOLVEFUNC(X509_EXTENSION_get_object)
+ RESOLVEFUNC(X509_free)
+ RESOLVEFUNC(X509_get_ext)
+@@ -982,20 +1155,11 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(X509_check_issued)
+ RESOLVEFUNC(X509_get_issuer_name)
+ RESOLVEFUNC(X509_get_subject_name)
++ RESOLVEFUNC(X509_get_serialNumber)
+ RESOLVEFUNC(X509_verify_cert)
+ RESOLVEFUNC(d2i_X509)
+ RESOLVEFUNC(i2d_X509)
+-#ifdef SSLEAY_MACROS
+- RESOLVEFUNC(i2d_DSAPrivateKey)
+- RESOLVEFUNC(i2d_RSAPrivateKey)
+- RESOLVEFUNC(d2i_DSAPrivateKey)
+- RESOLVEFUNC(d2i_RSAPrivateKey)
+-#endif
+- RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf)
+- RESOLVEFUNC(OPENSSL_add_all_algorithms_conf)
+ RESOLVEFUNC(SSL_CTX_load_verify_locations)
+- RESOLVEFUNC(SSLeay)
+- RESOLVEFUNC(SSLeay_version)
+ RESOLVEFUNC(i2d_SSL_SESSION)
+ RESOLVEFUNC(d2i_SSL_SESSION)
+ #if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
+@@ -1019,27 +1183,14 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(EC_KEY_new_by_curve_name)
+ RESOLVEFUNC(EC_KEY_free)
+ RESOLVEFUNC(EC_get_builtin_curves)
+-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+- if (q_SSLeay() >= 0x10002000L)
+- RESOLVEFUNC(EC_curve_nist2nid)
+-#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
+ #endif // OPENSSL_NO_EC
+ RESOLVEFUNC(PKCS12_parse)
+ RESOLVEFUNC(d2i_PKCS12_bio)
+ RESOLVEFUNC(PKCS12_free)
+
++ symbolsResolved = true;
+ delete libs.first;
+ delete libs.second;
+- if (!_q_SSLeay || q_SSLeay() >= 0x10100000L) {
+- // OpenSSL 1.1 deprecated and removed SSLeay. We consider a failure to
+- // resolve this symbol as a failure to resolve symbols.
+- // The right operand of '||' above ... a bit of paranoia.
+- qCWarning(lcSsl, "Incompatible version of OpenSSL");
+- return false;
+- }
+-
+- symbolsResolved = true;
+-
+ return true;
+ }
+ #endif // QT_CONFIG(library)
+diff --git a/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h b/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h
+index b35a895d38..796bf2d4f5 100644
+--- a/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h
++++ b/qtbase/src/network/ssl/qsslsocket_openssl_symbols_p.h
+@@ -1,6 +1,6 @@
+ /****************************************************************************
+ **
+-** Copyright (C) 2016 The Qt Company Ltd.
++** Copyright (C) 2017 The Qt Company Ltd.
+ ** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
+ ** Contact: https://www.qt.io/licensing/
+ **
+@@ -56,6 +56,7 @@
+ #ifndef QSSLSOCKET_OPENSSL_SYMBOLS_P_H
+ #define QSSLSOCKET_OPENSSL_SYMBOLS_P_H
+
++
+ //
+ // W A R N I N G
+ // -------------
+@@ -215,17 +216,20 @@ QT_BEGIN_NAMESPACE
+
+ #endif // !defined QT_LINKED_OPENSSL
+
++#if QT_CONFIG(opensslv11)
++#include "qsslsocket_openssl11_symbols_p.h"
++#else
++#include "qsslsocket_opensslpre11_symbols_p.h"
++#endif // QT_CONFIG
++
+ bool q_resolveOpenSslSymbols();
+ long q_ASN1_INTEGER_get(ASN1_INTEGER *a);
+-unsigned char * q_ASN1_STRING_data(ASN1_STRING *a);
+ int q_ASN1_STRING_length(ASN1_STRING *a);
+ int q_ASN1_STRING_to_UTF8(unsigned char **a, ASN1_STRING *b);
+ long q_BIO_ctrl(BIO *a, int b, long c, void *d);
+ Q_AUTOTEST_EXPORT int q_BIO_free(BIO *a);
+-Q_AUTOTEST_EXPORT BIO *q_BIO_new(BIO_METHOD *a);
+ BIO *q_BIO_new_mem_buf(void *a, int b);
+ int q_BIO_read(BIO *a, void *b, int c);
+-Q_AUTOTEST_EXPORT BIO_METHOD *q_BIO_s_mem();
+ Q_AUTOTEST_EXPORT int q_BIO_write(BIO *a, const void *b, int c);
+ int q_BN_num_bits(const BIGNUM *a);
+ #if OPENSSL_VERSION_NUMBER >= 0x10100000L
+@@ -247,26 +251,23 @@ BN_ULONG q_BN_mod_word(const BIGNUM *a, BN_ULONG w);
+ const EC_GROUP* q_EC_KEY_get0_group(const EC_KEY* k);
+ int q_EC_GROUP_get_degree(const EC_GROUP* g);
+ #endif
+-int q_CRYPTO_num_locks();
+-void q_CRYPTO_set_locking_callback(void (*a)(int, int, const char *, int));
+-void q_CRYPTO_set_id_callback(unsigned long (*a)());
+-void q_CRYPTO_free(void *a);
+ DSA *q_DSA_new();
+ void q_DSA_free(DSA *a);
+ X509 *q_d2i_X509(X509 **a, const unsigned char **b, long c);
+ char *q_ERR_error_string(unsigned long a, char *b);
+ unsigned long q_ERR_get_error();
+-void q_ERR_free_strings();
+-void q_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);
+-void q_EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);
++EVP_CIPHER_CTX *q_EVP_CIPHER_CTX_new();
++void q_EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *a);
+ int q_EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
+ int q_EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
+ int q_EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, const unsigned char *key, const unsigned char *iv, int enc);
++int q_EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc);
+ int q_EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl);
+ int q_EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
+ const EVP_CIPHER *q_EVP_des_cbc();
+ const EVP_CIPHER *q_EVP_des_ede3_cbc();
+ const EVP_CIPHER *q_EVP_rc2_cbc();
++const EVP_MD *q_EVP_sha1();
+ int q_EVP_PKEY_assign(EVP_PKEY *a, int b, char *c);
+ Q_AUTOTEST_EXPORT int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b);
+ int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b);
+@@ -310,7 +311,7 @@ int q_PEM_write_bio_RSAPrivateKey(BIO *a, RSA *b, const EVP_CIPHER *c, unsigned
+ int q_PEM_write_bio_ECPrivateKey(BIO *a, EC_KEY *b, const EVP_CIPHER *c, unsigned char *d,
+ int e, pem_password_cb *f, void *g);
+ #endif
+-#endif
++#endif // SSLEAY_MACROS
+ Q_AUTOTEST_EXPORT EVP_PKEY *q_PEM_read_bio_PUBKEY(BIO *a, EVP_PKEY **b, pem_password_cb *c, void *d);
+ DSA *q_PEM_read_bio_DSA_PUBKEY(BIO *a, DSA **b, pem_password_cb *c, void *d);
+ RSA *q_PEM_read_bio_RSA_PUBKEY(BIO *a, RSA **b, pem_password_cb *c, void *d);
+@@ -326,23 +327,10 @@ void q_RAND_seed(const void *a, int b);
+ int q_RAND_status();
+ RSA *q_RSA_new();
+ void q_RSA_free(RSA *a);
+-int q_sk_num(STACK *a);
+-void q_sk_pop_free(STACK *a, void (*b)(void *));
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+-_STACK *q_sk_new_null();
+-void q_sk_push(_STACK *st, void *data);
+-void q_sk_free(_STACK *a);
+-void * q_sk_value(STACK *a, int b);
+-#else
+-STACK *q_sk_new_null();
+-void q_sk_push(STACK *st, char *data);
+-void q_sk_free(STACK *a);
+-char * q_sk_value(STACK *a, int b);
+-#endif
+ int q_SSL_accept(SSL *a);
+ int q_SSL_clear(SSL *a);
+-char *q_SSL_CIPHER_description(SSL_CIPHER *a, char *b, int c);
+-int q_SSL_CIPHER_get_bits(SSL_CIPHER *a, int *b);
++char *q_SSL_CIPHER_description(const SSL_CIPHER *a, char *b, int c);
++int q_SSL_CIPHER_get_bits(const SSL_CIPHER *a, int *b);
+ int q_SSL_connect(SSL *a);
+ int q_SSL_CTX_check_private_key(const SSL_CTX *a);
+ long q_SSL_CTX_ctrl(SSL_CTX *a, int b, long c, void *d);
+@@ -374,8 +362,6 @@ int q_SSL_get_error(SSL *a, int b);
+ STACK_OF(X509) *q_SSL_get_peer_cert_chain(SSL *a);
+ X509 *q_SSL_get_peer_certificate(SSL *a);
+ long q_SSL_get_verify_result(const SSL *a);
+-int q_SSL_library_init();
+-void q_SSL_load_error_strings();
+ SSL *q_SSL_new(SSL_CTX *a);
+ long q_SSL_ctrl(SSL *ssl,int cmd, long larg, void *parg);
+ int q_SSL_read(SSL *a, void *b, int c);
+@@ -388,7 +374,6 @@ void q_SSL_SESSION_free(SSL_SESSION *ses);
+ SSL_SESSION *q_SSL_get1_session(SSL *ssl);
+ SSL_SESSION *q_SSL_get_session(const SSL *ssl);
+ #if OPENSSL_VERSION_NUMBER >= 0x10001000L
+-int q_SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+ int q_SSL_set_ex_data(SSL *ssl, int idx, void *arg);
+ void *q_SSL_get_ex_data(const SSL *ssl, int idx);
+ #endif
+@@ -399,49 +384,6 @@ typedef unsigned int (*q_psk_server_callback_t)(SSL *ssl, const char *identity,
+ void q_SSL_set_psk_server_callback(SSL *ssl, q_psk_server_callback_t callback);
+ int q_SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *hint);
+ #endif // OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+-#ifndef OPENSSL_NO_SSL2
+-const SSL_METHOD *q_SSLv2_client_method();
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+-const SSL_METHOD *q_SSLv3_client_method();
+-#endif
+-const SSL_METHOD *q_SSLv23_client_method();
+-const SSL_METHOD *q_TLSv1_client_method();
+-const SSL_METHOD *q_TLSv1_1_client_method();
+-const SSL_METHOD *q_TLSv1_2_client_method();
+-#ifndef OPENSSL_NO_SSL2
+-const SSL_METHOD *q_SSLv2_server_method();
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+-const SSL_METHOD *q_SSLv3_server_method();
+-#endif
+-const SSL_METHOD *q_SSLv23_server_method();
+-const SSL_METHOD *q_TLSv1_server_method();
+-const SSL_METHOD *q_TLSv1_1_server_method();
+-const SSL_METHOD *q_TLSv1_2_server_method();
+-#else
+-#ifndef OPENSSL_NO_SSL2
+-SSL_METHOD *q_SSLv2_client_method();
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+-SSL_METHOD *q_SSLv3_client_method();
+-#endif
+-SSL_METHOD *q_SSLv23_client_method();
+-SSL_METHOD *q_TLSv1_client_method();
+-SSL_METHOD *q_TLSv1_1_client_method();
+-SSL_METHOD *q_TLSv1_2_client_method();
+-#ifndef OPENSSL_NO_SSL2
+-SSL_METHOD *q_SSLv2_server_method();
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+-SSL_METHOD *q_SSLv3_server_method();
+-#endif
+-SSL_METHOD *q_SSLv23_server_method();
+-SSL_METHOD *q_TLSv1_server_method();
+-SSL_METHOD *q_TLSv1_1_server_method();
+-SSL_METHOD *q_TLSv1_2_server_method();
+-#endif
+ int q_SSL_write(SSL *a, const void *b, int c);
+ int q_X509_cmp(X509 *a, X509 *b);
+ #ifdef SSLEAY_MACROS
+@@ -452,6 +394,7 @@ void *q_ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, char *x);
+ X509 *q_X509_dup(X509 *a);
+ #endif
+ void q_X509_print(BIO *a, X509*b);
++int q_X509_digest(const X509 *x509, const EVP_MD *type, unsigned char *md, unsigned int *len);
+ ASN1_OBJECT *q_X509_EXTENSION_get_object(X509_EXTENSION *a);
+ void q_X509_free(X509 *a);
+ X509_EXTENSION *q_X509_get_ext(X509 *a, int b);
+@@ -471,6 +414,7 @@ int q_ASN1_STRING_print(BIO *a, ASN1_STRING *b);
+ int q_X509_check_issued(X509 *a, X509 *b);
+ X509_NAME *q_X509_get_issuer_name(X509 *a);
+ X509_NAME *q_X509_get_subject_name(X509 *a);
++ASN1_INTEGER *q_X509_get_serialNumber(X509 *a);
+ int q_X509_verify_cert(X509_STORE_CTX *ctx);
+ int q_X509_NAME_entry_count(X509_NAME *a);
+ X509_NAME_ENTRY *q_X509_NAME_get_entry(X509_NAME *a,int b);
+@@ -488,7 +432,6 @@ int q_X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
+ int q_X509_STORE_CTX_get_error(X509_STORE_CTX *ctx);
+ int q_X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx);
+ X509 *q_X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx);
+-STACK_OF(X509) *q_X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx);
+
+ // Diffie-Hellman support
+ DH *q_DH_new();
+@@ -522,34 +465,9 @@ int q_PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
+ PKCS12 *q_d2i_PKCS12_bio(BIO *bio, PKCS12 **pkcs12);
+ void q_PKCS12_free(PKCS12 *pkcs12);
+
+-
+ #define q_BIO_get_mem_data(b, pp) (int)q_BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)pp)
+ #define q_BIO_pending(b) (int)q_BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL)
+-#ifdef SSLEAY_MACROS
+-int q_i2d_DSAPrivateKey(const DSA *a, unsigned char **pp);
+-int q_i2d_RSAPrivateKey(const RSA *a, unsigned char **pp);
+-RSA *q_d2i_RSAPrivateKey(RSA **a, unsigned char **pp, long length);
+-DSA *q_d2i_DSAPrivateKey(DSA **a, unsigned char **pp, long length);
+-#define q_PEM_read_bio_RSAPrivateKey(bp, x, cb, u) \
+- (RSA *)q_PEM_ASN1_read_bio( \
+- (void *(*)(void**, const unsigned char**, long int))q_d2i_RSAPrivateKey, PEM_STRING_RSA, bp, (void **)x, cb, u)
+-#define q_PEM_read_bio_DSAPrivateKey(bp, x, cb, u) \
+- (DSA *)q_PEM_ASN1_read_bio( \
+- (void *(*)(void**, const unsigned char**, long int))q_d2i_DSAPrivateKey, PEM_STRING_DSA, bp, (void **)x, cb, u)
+-#define q_PEM_write_bio_RSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
+- PEM_ASN1_write_bio((int (*)(void*, unsigned char**))q_i2d_RSAPrivateKey,PEM_STRING_RSA,\
+- bp,(char *)x,enc,kstr,klen,cb,u)
+-#define q_PEM_write_bio_DSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
+- PEM_ASN1_write_bio((int (*)(void*, unsigned char**))q_i2d_DSAPrivateKey,PEM_STRING_DSA,\
+- bp,(char *)x,enc,kstr,klen,cb,u)
+-#define q_PEM_read_bio_DHparams(bp, dh, cb, u) \
+- (DH *)q_PEM_ASN1_read_bio( \
+- (void *(*)(void**, const unsigned char**, long int))q_d2i_DHparams, PEM_STRING_DHPARAMS, bp, (void **)x, cb, u)
+-#endif
+-#define q_SSL_CTX_set_options(ctx,op) q_SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
+ #define q_SSL_CTX_set_mode(ctx,op) q_SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
+-#define q_SKM_sk_num(type, st) ((int (*)(const STACK_OF(type) *))q_sk_num)(st)
+-#define q_SKM_sk_value(type, st,i) ((type * (*)(const STACK_OF(type) *, int))q_sk_value)(st, i)
+ #define q_sk_GENERAL_NAME_num(st) q_SKM_sk_num(GENERAL_NAME, (st))
+ #define q_sk_GENERAL_NAME_value(st, i) q_SKM_sk_value(GENERAL_NAME, (st), (i))
+ #define q_sk_X509_num(st) q_SKM_sk_num(X509, (st))
+@@ -558,18 +476,12 @@ DSA *q_d2i_DSAPrivateKey(DSA **a, unsigned char **pp, long length);
+ #define q_sk_SSL_CIPHER_value(st, i) q_SKM_sk_value(SSL_CIPHER, (st), (i))
+ #define q_SSL_CTX_add_extra_chain_cert(ctx,x509) \
+ q_SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509)
+-#define q_X509_get_notAfter(x) X509_get_notAfter(x)
+-#define q_X509_get_notBefore(x) X509_get_notBefore(x)
+ #define q_EVP_PKEY_assign_RSA(pkey,rsa) q_EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\
+ (char *)(rsa))
+ #define q_EVP_PKEY_assign_DSA(pkey,dsa) q_EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\
+ (char *)(dsa))
+ #define q_OpenSSL_add_all_algorithms() q_OPENSSL_add_all_algorithms_conf()
+-void q_OPENSSL_add_all_algorithms_noconf();
+-void q_OPENSSL_add_all_algorithms_conf();
+ int q_SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath);
+-long q_SSLeay();
+-const char *q_SSLeay_version(int type);
+ int q_i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp);
+ SSL_SESSION *q_d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length);
+
+diff --git a/qtbase/src/network/ssl/qsslsocket_opensslpre11.cpp b/qtbase/src/network/ssl/qsslsocket_opensslpre11.cpp
+new file mode 100644
+index 0000000000..e51888c5f2
+--- /dev/null
++++ b/qtbase/src/network/ssl/qsslsocket_opensslpre11.cpp
+@@ -0,0 +1,424 @@
++/****************************************************************************
++**
++** Copyright (C) 2017 The Qt Company Ltd.
++** Copyright (C) 2014 Governikus GmbH & Co. KG
++** Contact: https://www.qt.io/licensing/
++**
++** This file is part of the QtNetwork module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** Commercial License Usage
++** Licensees holding valid commercial Qt licenses may use this file in
++** accordance with the commercial license agreement provided with the
++** Software or, alternatively, in accordance with the terms contained in
++** a written agreement between you and The Qt Company. For licensing terms
++** and conditions see https://www.qt.io/terms-conditions. For further
++** information use the contact form at https://www.qt.io/contact-us.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 3 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL3 included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 3 requirements
++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU
++** General Public License version 2.0 or (at your option) the GNU General
++** Public license version 3 or any later version approved by the KDE Free
++** Qt Foundation. The licenses are as published by the Free Software
++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
++** included in the packaging of this file. Please review the following
++** information to ensure the GNU General Public License requirements will
++** be met: https://www.gnu.org/licenses/gpl-2.0.html and
++** https://www.gnu.org/licenses/gpl-3.0.html.
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++/****************************************************************************
++**
++** In addition, as a special exception, the copyright holders listed above give
++** permission to link the code of its release of Qt with the OpenSSL project's
++** "OpenSSL" library (or modified versions of the "OpenSSL" library that use the
++** same license as the original version), and distribute the linked executables.
++**
++** You must comply with the GNU General Public License version 2 in all
++** respects for all of the code used other than the "OpenSSL" code. If you
++** modify this file, you may extend this exception to your version of the file,
++** but you are not obligated to do so. If you do not wish to do so, delete
++** this exception statement from your version of this file.
++**
++****************************************************************************/
++
++//#define QT_DECRYPT_SSL_TRAFFIC
++
++#include "qssl_p.h"
++#include "qsslsocket_openssl_p.h"
++#include "qsslsocket_openssl_symbols_p.h"
++#include "qsslsocket.h"
++#include "qsslkey.h"
++
++#include
++#include
++#include
++#include
++#include
++#include
++#include
++
++QT_BEGIN_NAMESPACE
++
++/* \internal
++
++ From OpenSSL's thread(3) manual page:
++
++ OpenSSL can safely be used in multi-threaded applications provided that at
++ least two callback functions are set.
++
++ locking_function(int mode, int n, const char *file, int line) is needed to
++ perform locking on shared data structures. (Note that OpenSSL uses a
++ number of global data structures that will be implicitly shared
++ whenever multiple threads use OpenSSL.) Multi-threaded
++ applications will crash at random if it is not set. ...
++ ...
++ id_function(void) is a function that returns a thread ID. It is not
++ needed on Windows nor on platforms where getpid() returns a different
++ ID for each thread (most notably Linux)
++*/
++
++class QOpenSslLocks
++{
++public:
++ QOpenSslLocks()
++ : initLocker(QMutex::Recursive),
++ locksLocker(QMutex::Recursive)
++ {
++ QMutexLocker locker(&locksLocker);
++ int numLocks = q_CRYPTO_num_locks();
++ locks = new QMutex *[numLocks];
++ memset(locks, 0, numLocks * sizeof(QMutex *));
++ }
++ ~QOpenSslLocks()
++ {
++ QMutexLocker locker(&locksLocker);
++ for (int i = 0; i < q_CRYPTO_num_locks(); ++i)
++ delete locks[i];
++ delete [] locks;
++
++ QSslSocketPrivate::deinitialize();
++ }
++ QMutex *lock(int num)
++ {
++ QMutexLocker locker(&locksLocker);
++ QMutex *tmp = locks[num];
++ if (!tmp)
++ tmp = locks[num] = new QMutex(QMutex::Recursive);
++ return tmp;
++ }
++
++ QMutex *globalLock()
++ {
++ return &locksLocker;
++ }
++
++ QMutex *initLock()
++ {
++ return &initLocker;
++ }
++
++private:
++ QMutex initLocker;
++ QMutex locksLocker;
++ QMutex **locks;
++};
++
++Q_GLOBAL_STATIC(QOpenSslLocks, openssl_locks)
++
++extern "C" {
++static void locking_function(int mode, int lockNumber, const char *, int)
++{
++ QMutex *mutex = openssl_locks()->lock(lockNumber);
++
++ // Lock or unlock it
++ if (mode & CRYPTO_LOCK)
++ mutex->lock();
++ else
++ mutex->unlock();
++}
++static unsigned long id_function()
++{
++ return (quintptr)QThread::currentThreadId();
++}
++
++} // extern "C"
++
++static void q_OpenSSL_add_all_algorithms_safe()
++{
++#ifdef Q_OS_WIN
++ // Prior to version 1.0.1m an attempt to call OpenSSL_add_all_algorithms on
++ // Windows could result in 'exit' call from OPENSSL_config (QTBUG-43843).
++ // We can predict this and avoid OPENSSL_add_all_algorithms call.
++ // From OpenSSL docs:
++ // "An application does not need to add algorithms to use them explicitly,
++ // for example by EVP_sha1(). It just needs to add them if it (or any of
++ // the functions it calls) needs to lookup algorithms.
++ // The cipher and digest lookup functions are used in many parts of the
++ // library. If the table is not initialized several functions will
++ // misbehave and complain they cannot find algorithms. This includes the
++ // PEM, PKCS#12, SSL and S/MIME libraries. This is a common query in
++ // the OpenSSL mailing lists."
++ //
++ // Anyway, as a result, we chose not to call this function if it would exit.
++
++ if (q_SSLeay() < 0x100010DFL)
++ {
++ // Now, before we try to call it, check if an attempt to open config file
++ // will result in exit:
++ if (char *confFileName = q_CONF_get1_default_config_file()) {
++ BIO *confFile = q_BIO_new_file(confFileName, "r");
++ const auto lastError = q_ERR_peek_last_error();
++ q_CRYPTO_free(confFileName);
++ if (confFile) {
++ q_BIO_free(confFile);
++ } else {
++ q_ERR_clear_error();
++ if (ERR_GET_REASON(lastError) == ERR_R_SYS_LIB) {
++ qCWarning(lcSsl, "failed to open openssl.conf file");
++ return;
++ }
++ }
++ }
++ }
++#endif // Q_OS_WIN
++
++ q_OpenSSL_add_all_algorithms();
++}
++
++
++/*!
++ \internal
++*/
++void QSslSocketPrivate::deinitialize()
++{
++ q_CRYPTO_set_id_callback(0);
++ q_CRYPTO_set_locking_callback(0);
++ q_ERR_free_strings();
++}
++
++
++bool QSslSocketPrivate::ensureLibraryLoaded()
++{
++ if (!q_resolveOpenSslSymbols())
++ return false;
++
++ // Check if the library itself needs to be initialized.
++ QMutexLocker locker(openssl_locks()->initLock());
++
++ if (!s_libraryLoaded) {
++ s_libraryLoaded = true;
++
++ // Initialize OpenSSL.
++ q_CRYPTO_set_id_callback(id_function);
++ q_CRYPTO_set_locking_callback(locking_function);
++ if (q_SSL_library_init() != 1)
++ return false;
++ q_SSL_load_error_strings();
++ q_OpenSSL_add_all_algorithms_safe();
++
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++ if (q_SSLeay() >= 0x10001000L)
++ QSslSocketBackendPrivate::s_indexForSSLExtraData = q_SSL_get_ex_new_index(0L, NULL, NULL, NULL, NULL);
++#endif
++
++ // Initialize OpenSSL's random seed.
++ if (!q_RAND_status()) {
++ qWarning("Random number generator not seeded, disabling SSL support");
++ return false;
++ }
++ }
++ return true;
++}
++
++void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
++{
++ QMutexLocker locker(openssl_locks()->initLock());
++ if (s_loadedCiphersAndCerts)
++ return;
++ s_loadedCiphersAndCerts = true;
++
++ resetDefaultCiphers();
++ resetDefaultEllipticCurves();
++
++#if QT_CONFIG(library)
++ //load symbols needed to receive certificates from system store
++#if defined(Q_OS_WIN)
++ HINSTANCE hLib = LoadLibraryW(L"Crypt32");
++ if (hLib) {
++ ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW");
++ ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore");
++ ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore");
++ if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
++ qCWarning(lcSsl, "could not resolve symbols in crypt32 library"); // should never happen
++ } else {
++ qCWarning(lcSsl, "could not load crypt32 library"); // should never happen
++ }
++#elif defined(Q_OS_QNX)
++ s_loadRootCertsOnDemand = true;
++#elif defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
++ // check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there)
++ QList dirs = unixRootCertDirectories();
++ QStringList symLinkFilter;
++ symLinkFilter << QLatin1String("[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]");
++ for (int a = 0; a < dirs.count(); ++a) {
++ QDirIterator iterator(QLatin1String(dirs.at(a)), symLinkFilter, QDir::Files);
++ if (iterator.hasNext()) {
++ s_loadRootCertsOnDemand = true;
++ break;
++ }
++ }
++#endif
++#endif // QT_CONFIG(library)
++ // if on-demand loading was not enabled, load the certs now
++ if (!s_loadRootCertsOnDemand)
++ setDefaultCaCertificates(systemCaCertificates());
++#ifdef Q_OS_WIN
++ //Enabled for fetching additional root certs from windows update on windows 6+
++ //This flag is set false by setDefaultCaCertificates() indicating the app uses
++ //its own cert bundle rather than the system one.
++ //Same logic that disables the unix on demand cert loading.
++ //Unlike unix, we do preload the certificates from the cert store.
++ if ((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) >= QSysInfo::WV_6_0)
++ s_loadRootCertsOnDemand = true;
++#endif
++}
++
++long QSslSocketPrivate::sslLibraryVersionNumber()
++{
++ if (!supportsSsl())
++ return 0;
++
++ return q_SSLeay();
++}
++
++QString QSslSocketPrivate::sslLibraryVersionString()
++{
++ if (!supportsSsl())
++ return QString();
++
++ const char *versionString = q_SSLeay_version(SSLEAY_VERSION);
++ if (!versionString)
++ return QString();
++
++ return QString::fromLatin1(versionString);
++}
++
++void QSslSocketBackendPrivate::continueHandshake()
++{
++ Q_Q(QSslSocket);
++ // if we have a max read buffer size, reset the plain socket's to match
++ if (readBufferMaxSize)
++ plainSocket->setReadBufferSize(readBufferMaxSize);
++
++ if (q_SSL_ctrl((ssl), SSL_CTRL_GET_SESSION_REUSED, 0, NULL))
++ configuration.peerSessionShared = true;
++
++#ifdef QT_DECRYPT_SSL_TRAFFIC
++ if (ssl->session && ssl->s3) {
++ const char *mk = reinterpret_cast(ssl->session->master_key);
++ QByteArray masterKey(mk, ssl->session->master_key_length);
++ const char *random = reinterpret_cast(ssl->s3->client_random);
++ QByteArray clientRandom(random, SSL3_RANDOM_SIZE);
++
++ // different format, needed for e.g. older Wireshark versions:
++// const char *sid = reinterpret_cast(ssl->session->session_id);
++// QByteArray sessionID(sid, ssl->session->session_id_length);
++// QByteArray debugLineRSA("RSA Session-ID:");
++// debugLineRSA.append(sessionID.toHex().toUpper());
++// debugLineRSA.append(" Master-Key:");
++// debugLineRSA.append(masterKey.toHex().toUpper());
++// debugLineRSA.append("\n");
++
++ QByteArray debugLineClientRandom("CLIENT_RANDOM ");
++ debugLineClientRandom.append(clientRandom.toHex().toUpper());
++ debugLineClientRandom.append(" ");
++ debugLineClientRandom.append(masterKey.toHex().toUpper());
++ debugLineClientRandom.append("\n");
++
++ QString sslKeyFile = QDir::tempPath() + QLatin1String("/qt-ssl-keys");
++ QFile file(sslKeyFile);
++ if (!file.open(QIODevice::Append))
++ qCWarning(lcSsl) << "could not open file" << sslKeyFile << "for appending";
++ if (!file.write(debugLineClientRandom))
++ qCWarning(lcSsl) << "could not write to file" << sslKeyFile;
++ file.close();
++ } else {
++ qCWarning(lcSsl, "could not decrypt SSL traffic");
++ }
++#endif
++
++ // Cache this SSL session inside the QSslContext
++ if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionSharing)) {
++ if (!sslContextPointer->cacheSession(ssl)) {
++ sslContextPointer.clear(); // we could not cache the session
++ } else {
++ // Cache the session for permanent usage as well
++ if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionPersistence)) {
++ if (!sslContextPointer->sessionASN1().isEmpty())
++ configuration.sslSession = sslContextPointer->sessionASN1();
++ configuration.sslSessionTicketLifeTimeHint = sslContextPointer->sessionTicketLifeTimeHint();
++ }
++ }
++ }
++
++#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
++
++ configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status;
++ if (sslContextPointer->npnContext().status == QSslConfiguration::NextProtocolNegotiationUnsupported) {
++ // we could not agree -> be conservative and use HTTP/1.1
++ configuration.nextNegotiatedProtocol = QByteArrayLiteral("http/1.1");
++ } else {
++ const unsigned char *proto = 0;
++ unsigned int proto_len = 0;
++#if OPENSSL_VERSION_NUMBER >= 0x10002000L
++ if (q_SSLeay() >= 0x10002000L) {
++ q_SSL_get0_alpn_selected(ssl, &proto, &proto_len);
++ if (proto_len && mode == QSslSocket::SslClientMode) {
++ // Client does not have a callback that sets it ...
++ configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated;
++ }
++ }
++
++ if (!proto_len) { // Test if NPN was more lucky ...
++#else
++ {
++#endif
++ q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len);
++ }
++
++ if (proto_len)
++ configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast(proto), proto_len);
++ else
++ configuration.nextNegotiatedProtocol.clear();
++ }
++#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
++
++#if OPENSSL_VERSION_NUMBER >= 0x10002000L
++ if (q_SSLeay() >= 0x10002000L && mode == QSslSocket::SslClientMode) {
++ EVP_PKEY *key;
++ if (q_SSL_get_server_tmp_key(ssl, &key))
++ configuration.ephemeralServerKey = QSslKey(key, QSsl::PublicKey);
++ }
++#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ...
++
++ connectionEncrypted = true;
++ emit q->encrypted();
++ if (autoStartHandshake && pendingClose) {
++ pendingClose = false;
++ q->disconnectFromHost();
++ }
++}
++
++QT_END_NAMESPACE
+diff --git a/qtbase/src/network/ssl/ssl.pri b/qtbase/src/network/ssl/ssl.pri
+index d2b0c2d60d..2783effaf1 100644
+--- a/qtbase/src/network/ssl/ssl.pri
++++ b/qtbase/src/network/ssl/ssl.pri
+@@ -60,13 +60,25 @@ qtConfig(ssl) {
+ HEADERS += ssl/qsslcontext_openssl_p.h \
+ ssl/qsslsocket_openssl_p.h \
+ ssl/qsslsocket_openssl_symbols_p.h
+- SOURCES += ssl/qsslcertificate_openssl.cpp \
+- ssl/qsslcontext_openssl.cpp \
++ SOURCES += ssl/qsslsocket_openssl_symbols.cpp \
+ ssl/qssldiffiehellmanparameters_openssl.cpp \
++ ssl/qsslcertificate_openssl.cpp \
+ ssl/qsslellipticcurve_openssl.cpp \
+ ssl/qsslkey_openssl.cpp \
+ ssl/qsslsocket_openssl.cpp \
+- ssl/qsslsocket_openssl_symbols.cpp
++ ssl/qsslcontext_openssl.cpp
++
++ qtConfig(opensslv11) {
++ HEADERS += ssl/qsslsocket_openssl11_symbols_p.h
++ SOURCES += ssl/qsslsocket_openssl11.cpp \
++ ssl/qsslcontext_openssl11.cpp
++
++ QMAKE_CXXFLAGS += -DOPENSSL_API_COMPAT=0x10100000L
++ } else {
++ HEADERS += ssl/qsslsocket_opensslpre11_symbols_p.h
++ SOURCES += ssl/qsslsocket_opensslpre11.cpp \
++ ssl/qsslcontext_opensslpre11.cpp
++ }
+
+ darwin:SOURCES += ssl/qsslsocket_mac_shared.cpp
+
diff --git a/package/lean/qt5/files/qmake.conf b/package/lean/qt5/src/qtbase/mkspecs/linux-openwrt-g++/qmake.conf
similarity index 66%
rename from package/lean/qt5/files/qmake.conf
rename to package/lean/qt5/src/qtbase/mkspecs/linux-openwrt-g++/qmake.conf
index 20491903ac..8aec5b857f 100644
--- a/package/lean/qt5/files/qmake.conf
+++ b/package/lean/qt5/src/qtbase/mkspecs/linux-openwrt-g++/qmake.conf
@@ -14,20 +14,18 @@ include(../common/g++-unix.conf)
QMAKE_CC = $(TARGET_CROSS)gcc
QMAKE_CXX = $(TARGET_CROSS)g++
-QMAKE_CFLAGS += $$(TARGET_CFLAGS)
-QMAKE_CXXFLAGS += $$(TARGET_CXXFLAGS)
-QMAKE_LFLAGS += $$(TARGET_LDFLAGS)
+QMAKE_CFLAGS += $(TARGET_CFLAGS)
+QMAKE_CXXFLAGS += $(TARGET_CXXFLAGS)
+QMAKE_LFLAGS += $(TARGET_LDFLAGS)
-QMAKE_LINK_C = $$QMAKE_CC
-QMAKE_LINK_C_SHLIB = $$QMAKE_CC
-QMAKE_LINK = $$QMAKE_CXX
-QMAKE_LINK_SHLIB = $$QMAKE_CXX
+QMAKE_LINK_C = $(TARGET_CROSS)gcc
+QMAKE_LINK_C_SHLIB = $(TARGET_CROSS)gcc
+QMAKE_LINK = $(TARGET_CROSS)g++
+QMAKE_LINK_SHLIB = $(TARGET_CROSS)g++
# modifications to linux.conf
QMAKE_AR = $(TARGET_CROSS)ar cqs
QMAKE_OBJCOPY = $(TARGET_CROSS)objcopy
QMAKE_NM = $(TARGET_CROSS)nm -P
QMAKE_STRIP = $(TARGET_CROSS)strip
-
-
load(qt_config)
diff --git a/package/lean/qt5/src/qtbase/mkspecs/linux-openwrt-g++/qplatformdefs.h b/package/lean/qt5/src/qtbase/mkspecs/linux-openwrt-g++/qplatformdefs.h
new file mode 100644
index 0000000000..02e77c9a37
--- /dev/null
+++ b/package/lean/qt5/src/qtbase/mkspecs/linux-openwrt-g++/qplatformdefs.h
@@ -0,0 +1,9 @@
+#include "../linux-g++/qplatformdefs.h"
+
+#undef QT_SOCKLEN_T
+
+#if defined(__GLIBC__) && (__GLIBC__ < 2)
+#define QT_SOCKLEN_T int
+#else
+#define QT_SOCKLEN_T socklen_t
+#endif
diff --git a/package/lienol/ipt2socks/Makefile b/package/lienol/ipt2socks/Makefile
new file mode 100644
index 0000000000..3e9e281fb8
--- /dev/null
+++ b/package/lienol/ipt2socks/Makefile
@@ -0,0 +1,48 @@
+#
+# Copyright (C) 2014 OpenWrt-dist
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=ipt2socks
+PKG_VERSION:=1.0.1
+PKG_RELEASE:=2
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/zfl9/ipt2socks.git
+PKG_SOURCE_VERSION:=b9bd7d888f2f95a6d7306030c8a5e252732dc451
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION)
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
+PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)/$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION)
+
+include $(INCLUDE_DIR)/package.mk
+
+define Package/ipt2socks
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=Utility for converting iptables (REDIRECT/TPROXY) to SOCKS5
+ URL:=https://github.com/zfl9/ipt2socks
+ DEPENDS:=+libuv
+endef
+
+define Package/ipt2socks/description
+Utility for converting iptables (REDIRECT/TPROXY) to SOCKS5.
+endef
+
+define Package/ipt2socks/conffiles
+/etc/config/ipt2socks
+endef
+
+#MAKE_FLAGS += INCLUDES="-I$(STAGING_DIR)/usr/include"
+#MAKE_FLAGS += LDFLAGS="-L$(STAGING_DIR)/usr/lib"
+MAKE_FLAGS += LIBS="-l:libuv_a.a"
+
+define Package/ipt2socks/install
+ $(INSTALL_DIR) $(1)/usr/bin
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/ipt2socks $(1)/usr/bin
+endef
+
+$(eval $(call BuildPackage,ipt2socks))
diff --git a/package/lienol/trojan/Makefile b/package/lienol/trojan/Makefile
new file mode 100644
index 0000000000..c17c136ed6
--- /dev/null
+++ b/package/lienol/trojan/Makefile
@@ -0,0 +1,66 @@
+#
+# Copyright (C) 2018-2019 wongsyrone
+#
+# This is free software, licensed under the GNU General Public License v3.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=trojan
+PKG_VERSION:=1.13.0
+PKG_RELEASE:=2
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/trojan-gfw/trojan.git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=98533aa1003979862763f4225266de78581e40bc
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
+
+CMAKE_INSTALL:=1
+PKG_BUILD_PARALLEL:=0
+PKG_BUILD_DEPENDS:=openssl
+
+PKG_LICENSE:=GPL-3.0
+PKG_MAINTAINER:=GreaterFire
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/cmake.mk
+
+TARGET_CXXFLAGS += -Wall -Wextra
+TARGET_CXXFLAGS += $(FPIC)
+
+# LTO
+TARGET_CXXFLAGS += -flto
+TARGET_LDFLAGS += -flto
+
+# CXX standard
+TARGET_CXXFLAGS += -std=c++11
+TARGET_CXXFLAGS := $(filter-out -O%,$(TARGET_CXXFLAGS)) -O3
+TARGET_CXXFLAGS += -ffunction-sections -fdata-sections
+TARGET_LDFLAGS += -Wl,--gc-sections
+
+CMAKE_OPTIONS += \
+ -DENABLE_MYSQL=OFF \
+ -DENABLE_SSL_KEYLOG=ON \
+ -DENABLE_NAT=ON \
+ -DFORCE_TCP_FASTOPEN=OFF \
+ -DSYSTEMD_SERVICE=OFF \
+ -DOPENSSL_USE_STATIC_LIBS=FALSE \
+ -DBoost_DEBUG=OFF \
+ -DBoost_NO_BOOST_CMAKE=ON
+
+define Package/trojan
+ SECTION:=net
+ CATEGORY:=Network
+ TITLE:=An unidentifiable mechanism that helps you bypass GFW
+ URL:=https://github.com/trojan-gfw/trojan
+ DEPENDS:=+libpthread +libstdcpp +libopenssl \
+ +boost +boost-system +boost-program_options +boost-date_time
+endef
+
+define Package/trojan/install
+ $(INSTALL_DIR) $(1)/usr/sbin
+ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/trojan $(1)/usr/sbin/trojan
+endef
+
+$(eval $(call BuildPackage,trojan))
diff --git a/package/lienol/trojan/patches/001-force-openssl-version.patch b/package/lienol/trojan/patches/001-force-openssl-version.patch
new file mode 100644
index 0000000000..0a7291261b
--- /dev/null
+++ b/package/lienol/trojan/patches/001-force-openssl-version.patch
@@ -0,0 +1,11 @@
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -43,7 +43,7 @@ if(MSVC)
+ add_definitions(-DBOOST_DATE_TIME_NO_LIB)
+ endif()
+
+-find_package(OpenSSL 1.0.2 REQUIRED)
++find_package(OpenSSL 1.1.1 REQUIRED)
+ include_directories(${OPENSSL_INCLUDE_DIR})
+ target_link_libraries(trojan ${OPENSSL_LIBRARIES})
+ if(OPENSSL_VERSION VERSION_GREATER_EQUAL 1.1.1)