diff --git a/ChangeLog b/ChangeLog
index 29d1bcf8..57108310 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,36 @@
-nzbget-21.1:
+nzbget-21.2-testing:
   - please see repository change log at
     https://github.com/nzbget/nzbget/commits/develop
 
+nzbget-21.1:
+  - fixed crash on systems with 64-bit time;
+  - corrected icon in Windows "uninstall program" list;
+  - allow special characters in URL for username and password;
+  - improved reporting for binding errors on Windows;
+  - fixed unicode space characters in javascript files, which could cause issues
+    with nginx proxy;
+  - fixed negative values for "FileSizeLo" in json-rpc;
+  - corrected url detection in rpc-method "append";
+  - added support for new error messages in unrar 5.80;
+  - now always using snapshots when reading directory contents:
+    - in previous versions snapshots were used on macOS only;
+    - now they are used on all OSes;
+    - this solves issue with leftovers during directory cleanup, which could
+      happen on certain OSes when working with network drives;
+  - fixed file allocating on file systems where sparse files are not supported:
+    - the issue could happen when InterDir was located on a network drive;
+  - fixed crash caused by malformed nzb files;
+  - fixed GROUP command in nserv;
+  - updated url of the global certificate storage file in the build scripts;
+  - fixed: file selector in WebKit based browsers doesn't allow to choose the
+    same file again;
+  - removed outdated links from web interface;
+  - fixed PC sleep mode not working (Windows only);
+  - set "SameSite" attribute for cookies;
+  - corrected typo in about dialog of web interface;
+  - updated license text: changed address of Free Software Foundation and minor
+    formatting changes.
+
 nzbget-21.0:
   - reworked duplicate handling to support URLs, especially when using RSS
     feeds:
diff --git a/README.md b/README.md
index 373e9400..d9a76485 100644
--- a/README.md
+++ b/README.md
@@ -11,14 +11,9 @@
 NZBGet is a binary downloader, which downloads files from Usenet
 based on information given in nzb-files. 
 
-NZBGet is written in C++ and is known for its extraordinary performance and efficiency.
+NZBGet is written in C++ and is known for its performance and efficiency.
 
-NZBGet can be run on almost every device - classic PCs, NAS, media players, SAT-receivers, WLAN-routers, etc.
-The download area provides precompiled binaries
-for Windows, macOS, Linux (compatible with many CPUs and platform variants), FreeBSD and Android. For other platforms
-the program can be compiled from sources.
-
-- [Home page (nzbget.net)](http://nzbget.net) - learn more about NZBGet;
-- [Downloads](http://nzbget.net/download) - get compiled binaries and sources;
-- [Documentation](http://nzbget.net/documentation) - installation manuals, HOW-TOs, API;
-- [Forum](http://forum.nzbget.net) - get support, share your ideas, scripts, add-ons.
+NZBGet can run on almost any device - classic PC, NAS, media player, SAT-receiver, WLAN-router, etc.
+The download area provides precompiled binaries for Windows, macOS, Linux (compatible with
+many CPUs and platform variants), FreeBSD and Android. For other platforms
+the program can be compiled from sources.
\ No newline at end of file
diff --git a/config.h.in b/config.h.in
index f1d49937..b757759c 100644
--- a/config.h.in
+++ b/config.h.in
@@ -3,10 +3,6 @@
 /* Define to 1 to include debug-code */
 #undef DEBUG
 
-/* Define to 1 if deleting of files during reading of directory is not
-   properly supported by OS */
-#undef DIRBROWSER_SNAPSHOT
-
 /* Define to 1 to not use curses */
 #undef DISABLE_CURSES
 
diff --git a/configure b/configure
index ad26e189..bcf18d3d 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for nzbget 21.1-testing.
+# Generated by GNU Autoconf 2.69 for nzbget 21.2-testing.
 #
 # Report bugs to <hugbug@users.sourceforge.net>.
 #
@@ -580,8 +580,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='nzbget'
 PACKAGE_TARNAME='nzbget'
-PACKAGE_VERSION='21.1-testing'
-PACKAGE_STRING='nzbget 21.1-testing'
+PACKAGE_VERSION='21.2-testing'
+PACKAGE_STRING='nzbget 21.2-testing'
 PACKAGE_BUGREPORT='hugbug@users.sourceforge.net'
 PACKAGE_URL=''
 
@@ -1348,7 +1348,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures nzbget 21.1-testing to adapt to many kinds of systems.
+\`configure' configures nzbget 21.2-testing to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1419,7 +1419,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of nzbget 21.1-testing:";;
+     short | recursive ) echo "Configuration of nzbget 21.2-testing:";;
    esac
   cat <<\_ACEOF
 
@@ -1584,7 +1584,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-nzbget configure 21.1-testing
+nzbget configure 21.2-testing
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2053,7 +2053,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by nzbget $as_me 21.1-testing, which was
+It was created by nzbget $as_me 21.2-testing, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3026,7 +3026,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='nzbget'
- VERSION='21.1-testing'
+ VERSION='21.2-testing'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -6611,20 +6611,6 @@ _ACEOF
 
 
 
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether dir-browser snapshot workaround is needed" >&5
-$as_echo_n "checking whether dir-browser snapshot workaround is needed... " >&6; }
-if test "$target_vendor" == "apple"; then
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-
-$as_echo "#define DIRBROWSER_SNAPSHOT 1" >>confdefs.h
-
-else
-	{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cpu cores via sysconf" >&5
 $as_echo_n "checking for cpu cores via sysconf... " >&6; }
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
@@ -9177,7 +9163,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by nzbget $as_me 21.1-testing, which was
+This file was extended by nzbget $as_me 21.2-testing, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -9243,7 +9229,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-nzbget config.status 21.1-testing
+nzbget config.status 21.2-testing
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
index 2745362c..fd3d6123 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
 #
 #  This file is part of nzbget. See <http://nzbget.net>.
 #
-# Copyright (C) 2008-2019 Andrey Prygunkov <hugbug@users.sourceforge.net>
+# Copyright (C) 2008-2021 Andrey Prygunkov <hugbug@users.sourceforge.net>
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.65)
-AC_INIT(nzbget, 21.1-testing, hugbug@users.sourceforge.net)
+AC_INIT(nzbget, 21.2-testing, hugbug@users.sourceforge.net)
 AC_CONFIG_AUX_DIR(posix)
 AC_CANONICAL_TARGET
 AM_INIT_AUTOMAKE([foreign subdir-objects])
@@ -222,18 +222,6 @@ AC_TRY_COMPILE([
 AC_DEFINE_UNQUOTED(SOCKLEN_T, $SOCKLEN_T, [Determine what socket length (socklen_t) data type is])
 
 
-dnl
-dnl Dir-browser's snapshot
-dnl
-AC_MSG_CHECKING(whether dir-browser snapshot workaround is needed)
-if test "$target_vendor" == "apple"; then
-	AC_MSG_RESULT([[yes]])
-	AC_DEFINE([DIRBROWSER_SNAPSHOT], 1, [Define to 1 if deleting of files during reading of directory is not properly supported by OS])
-else
-	AC_MSG_RESULT([[no]])
-fi
-
-
 dnl
 dnl check cpu cores via sysconf
 dnl
diff --git a/daemon/connect/Connection.cpp b/daemon/connect/Connection.cpp
index 6a0a4d31..3267f129 100644
--- a/daemon/connect/Connection.cpp
+++ b/daemon/connect/Connection.cpp
@@ -209,6 +209,8 @@ bool Connection::Bind()
 		return true;
 	}
 
+	int errcode = 0;
+
 #ifndef WIN32
 	if (m_host && m_host[0] == '/')
 	{
@@ -280,6 +282,7 @@ bool Connection::Bind()
 					break;
 				}
 				// Connection failed
+				errcode = GetLastNetworkError();
 				closesocket(m_socket);
 				m_socket = INVALID_SOCKET;
 			}
@@ -320,6 +323,7 @@ bool Connection::Bind()
 		if (res == -1)
 		{
 			// Connection failed
+			errcode = GetLastNetworkError();
 			closesocket(m_socket);
 			m_socket = INVALID_SOCKET;
 		}
@@ -328,7 +332,7 @@ bool Connection::Bind()
 
 	if (m_socket == INVALID_SOCKET)
 	{
-		ReportError("Binding socket failed for %s", m_host, true);
+		ReportError("Binding socket failed for %s", m_host, true, errcode);
 		return false;
 	}
 
@@ -785,18 +789,15 @@ bool Connection::ConnectWithTimeout(void* address, int address_len)
 	ret = connect(m_socket, (struct sockaddr*)address, address_len);
 	if (ret < 0)
 	{
+		int err = GetLastNetworkError();
 #ifdef WIN32
-		int err = WSAGetLastError();
 		if (err != WSAEWOULDBLOCK)
-		{
-			return false;
-		}
 #else
-		if (errno != EINPROGRESS)
+		if (err != EINPROGRESS)
+#endif
 		{
 			return false;
 		}
-#endif
 	}
 
 	//connect succeeded right away?
@@ -916,7 +917,16 @@ void Connection::Cancel()
 	}
 }
 
-void Connection::ReportError(const char* msgPrefix, const char* msgArg, bool PrintErrCode, int herrno, const char* herrMsg)
+int Connection::GetLastNetworkError()
+{
+#ifdef WIN32
+	return WSAGetLastError();
+#else
+	return errno;
+#endif
+}
+
+void Connection::ReportError(const char* msgPrefix, const char* msgArg, bool printErrCode, int errCode, const char* errMsg)
 {
 #ifndef DISABLE_TLS
 	if (m_tlsError)
@@ -929,34 +939,34 @@ void Connection::ReportError(const char* msgPrefix, const char* msgArg, bool Pri
 
 	BString<1024> errPrefix(msgPrefix, msgArg);
 
-	if (PrintErrCode)
+	if (printErrCode)
 	{
-#ifdef WIN32
-		int ErrCode = WSAGetLastError();
-		char errMsg[1024];
-		errMsg[0] = '\0';
-		FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, ErrCode, 0, errMsg, 1024, nullptr);
-		errMsg[1024-1] = '\0';
-#else
-		const char* errMsg = herrMsg;
-		int ErrCode = herrno;
-		if (herrno == 0)
+		BString<1024> printErrMsg;
+		if (errCode == 0)
 		{
-			ErrCode = errno;
-			errMsg = strerror(ErrCode);
+			errCode = GetLastNetworkError();
 		}
-		else if (!herrMsg)
+		if (errMsg)
 		{
-			errMsg = hstrerror(ErrCode);
+			printErrMsg = errMsg;
 		}
+		else
+		{
+#ifdef WIN32
+			FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, errCode, 0, printErrMsg, printErrMsg.Capacity(), nullptr);
+			printErrMsg[1024-1] = '\0';
+#else
+			printErrMsg = strerror(errCode);
 #endif
+		}
+
 		if (m_suppressErrors)
 		{
-			debug("%s: ErrNo %i, %s", *errPrefix, ErrCode, errMsg);
+			debug("%s: Error %i - %s", *errPrefix, errCode, (const char*)printErrMsg);
 		}
 		else
 		{
-			PrintError(BString<1024>("%s: ErrNo %i, %s", *errPrefix, ErrCode, errMsg));
+			PrintError(BString<1024>("%s: Error %i - %s", *errPrefix, errCode, (const char*)printErrMsg));
 		}
 	}
 	else
@@ -1074,7 +1084,7 @@ in_addr_t Connection::ResolveHostAddr(const char* host)
 #endif
 		if (err)
 		{
-			ReportError("Could not resolve hostname %s", host, true, h_errnop);
+			ReportError("Could not resolve hostname %s", host, true, h_errnop, hstrerror(h_errnop));
 			return INADDR_NONE;
 		}
 
diff --git a/daemon/connect/Connection.h b/daemon/connect/Connection.h
index 046174fe..1b703b5b 100644
--- a/daemon/connect/Connection.h
+++ b/daemon/connect/Connection.h
@@ -136,9 +136,10 @@ protected:
 #endif
 #endif
 
-	void ReportError(const char* msgPrefix, const char* msgArg, bool PrintErrCode, int herrno = 0,
-		const char* herrMsg = nullptr);
+	void ReportError(const char* msgPrefix, const char* msgArg, bool printErrCode, int errCode = 0,
+		const char* errMsg = nullptr);
 	virtual void PrintError(const char* errMsg);
+	int GetLastNetworkError();
 	bool DoConnect();
 	bool DoDisconnect();
 	bool InitSocketOpts(SOCKET socket);
diff --git a/daemon/nserv/NntpServer.cpp b/daemon/nserv/NntpServer.cpp
index a34b9f26..aefb02f1 100644
--- a/daemon/nserv/NntpServer.cpp
+++ b/daemon/nserv/NntpServer.cpp
@@ -172,7 +172,7 @@ void NntpProcessor::Run()
 		}
 		else if (!strncasecmp(line, "GROUP ", 6))
 		{
-			m_connection->WriteLine(CString::FormatStr("211 0 0 0 %s\r\n", line + 7));
+			m_connection->WriteLine(CString::FormatStr("211 0 0 0 %s\r\n", line + 6));
 		}
 		else if (!strncasecmp(line, "AUTHINFO ", 9))
 		{
diff --git a/daemon/postprocess/Unpack.cpp b/daemon/postprocess/Unpack.cpp
index 1c0f0267..423d5ed2 100644
--- a/daemon/postprocess/Unpack.cpp
+++ b/daemon/postprocess/Unpack.cpp
@@ -888,7 +888,8 @@ void UnpackController::AddMessage(Message::EKind kind, const char* text)
 		m_unpackDecryptError = true;
 	}
 
-	if (m_unpacker == upUnrar && !strncmp(text, "Unrar: The specified password is incorrect.", 43))
+	if (m_unpacker == upUnrar && (!strncmp(text, "Unrar: The specified password is incorrect.", 43) ||
+		!strncmp(text, "Unrar: Incorrect password for", 29)))
 	{
 		m_unpackPasswordError = true;
 	}
diff --git a/daemon/queue/NzbFile.cpp b/daemon/queue/NzbFile.cpp
index 0630fd93..cd2f9e1e 100644
--- a/daemon/queue/NzbFile.cpp
+++ b/daemon/queue/NzbFile.cpp
@@ -117,6 +117,12 @@ void NzbFile::ParseSubject(FileInfo* fileInfo, bool TryQuotes)
 {
 	// Example subject: some garbage "title" yEnc (10/99)
 
+	if (!fileInfo->GetSubject())
+	{
+		// Malformed file element without subject. We generate subject using internal element id.
+		fileInfo->SetSubject(CString::FormatStr("%d", fileInfo->GetId()));
+	}
+
 	// strip the "yEnc (10/99)"-suffix
 	BString<1024> subject = fileInfo->GetSubject();
 	char* end = subject + strlen(subject) - 1;
diff --git a/daemon/remote/WebServer.cpp b/daemon/remote/WebServer.cpp
index 7f7d6bc8..8db12cec 100644
--- a/daemon/remote/WebServer.cpp
+++ b/daemon/remote/WebServer.cpp
@@ -222,18 +222,11 @@ void WebProcessor::ParseUrl()
 	if (pauth1 && pauth1 < pauth2)
 	{
 		char* pstart = m_url + 1;
-		int len = 0;
-		char* pend = strchr(pstart + 1, '/');
-		if (pend)
-		{
-			len = (int)(pend - pstart < (int)sizeof(m_authInfo) - 1 ? pend - pstart : (int)sizeof(m_authInfo) - 1);
-		}
-		else
-		{
-			len = strlen(pstart);
-		}
+		char* pend = pauth2;
+		int len = std::min((int)(pend - pstart), (int)sizeof(m_authInfo) - 1);
 		strncpy(m_authInfo, pstart, len);
 		m_authInfo[len] = '\0';
+		WebUtil::UrlDecode(m_authInfo);
 		m_url = CString(pend);
 	}
 
@@ -466,8 +459,8 @@ void WebProcessor::SendBodyResponse(const char* body, int bodyLen, const char* c
 		"Access-Control-Allow-Credentials: true\r\n"
 		"Access-Control-Max-Age: 86400\r\n"
 		"Access-Control-Allow-Headers: Content-Type, Authorization\r\n"
-		"Set-Cookie: Auth-Type=%s\r\n"
-		"Set-Cookie: Auth-Token=%s; HttpOnly\r\n"
+		"Set-Cookie: Auth-Type=%s; SameSite=Lax\r\n"
+		"Set-Cookie: Auth-Token=%s; HttpOnly; SameSite=Lax\r\n"
 		"Content-Length: %i\r\n"
 		"%s"					// Content-Type: xxx
 		"%s"					// Content-Encoding: gzip
diff --git a/daemon/remote/XmlRpc.cpp b/daemon/remote/XmlRpc.cpp
index e348e5de..0686f296 100644
--- a/daemon/remote/XmlRpc.cpp
+++ b/daemon/remote/XmlRpc.cpp
@@ -1443,7 +1443,7 @@ void LogXmlCommand::Execute()
 
 		AppendCondResponse(",\n", IsJson() && index++ > 0);
 		AppendFmtResponse(IsJson() ? JSON_LOG_ITEM : XML_LOG_ITEM,
-			message.GetId(), messageType[message.GetKind()], message.GetTime(),
+			message.GetId(), messageType[message.GetKind()], (int)message.GetTime(),
 			*EncodeStr(message.GetText()));
 	}
 
@@ -1550,7 +1550,7 @@ void ListFilesXmlCommand::Execute()
 				AppendCondResponse(",\n", IsJson() && index++ > 0);
 				AppendFmtResponse(IsJson() ? JSON_LIST_ITEM : XML_LIST_ITEM,
 					fileInfo->GetId(), fileSizeLo, fileSizeHi, remainingSizeLo, remainingSizeHi,
-					fileInfo->GetTime(), BoolToStr(fileInfo->GetFilenameConfirmed()),
+					(int)fileInfo->GetTime(), BoolToStr(fileInfo->GetFilenameConfirmed()),
 					BoolToStr(fileInfo->GetPaused()), fileInfo->GetNzbInfo()->GetId(),
 					*xmlNzbNicename, *xmlNzbNicename, *EncodeStr(fileInfo->GetNzbInfo()->GetFilename()),
 					*EncodeStr(fileInfo->GetSubject()), *EncodeStr(fileInfo->GetFilename()),
@@ -1748,14 +1748,14 @@ void NzbInfoXmlCommand::AppendNzbInfoFields(NzbInfo* nzbInfo)
 			deleteStatusName[nzbInfo->GetDeleteStatus()], markStatusName[nzbInfo->GetMarkStatus()],
 			urlStatusName[nzbInfo->GetUrlStatus()],
 			fileSizeLo, fileSizeHi, fileSizeMB, nzbInfo->GetFileCount(),
-			nzbInfo->GetMinTime(), nzbInfo->GetMaxTime(),
+			(int)nzbInfo->GetMinTime(), (int)nzbInfo->GetMaxTime(),
 			nzbInfo->GetTotalArticles(), nzbInfo->GetCurrentSuccessArticles(), nzbInfo->GetCurrentFailedArticles(),
 			nzbInfo->CalcHealth(), nzbInfo->CalcCriticalHealth(false),
 			*EncodeStr(nzbInfo->GetDupeKey()), nzbInfo->GetDupeScore(), dupeModeName[nzbInfo->GetDupeMode()],
 			BoolToStr(nzbInfo->GetDeleteStatus() != NzbInfo::dsNone),
 			downloadedSizeLo, downloadedSizeHi, downloadedSizeMB, nzbInfo->GetDownloadSec(),
-			nzbInfo->GetPostTotalSec() + (nzbInfo->GetPostInfo() && nzbInfo->GetPostInfo()->GetStartTime() ?
-				Util::CurrentTime() - nzbInfo->GetPostInfo()->GetStartTime() : 0),
+			(int)(nzbInfo->GetPostTotalSec() + (nzbInfo->GetPostInfo() && nzbInfo->GetPostInfo()->GetStartTime() ?
+				Util::CurrentTime() - nzbInfo->GetPostInfo()->GetStartTime() : 0)),
 			nzbInfo->GetParSec(), nzbInfo->GetRepairSec(), nzbInfo->GetUnpackSec(), messageCount, nzbInfo->GetExtraParBlocks());
 
 	// Post-processing parameters
@@ -1856,8 +1856,8 @@ void NzbInfoXmlCommand::AppendPostInfoFields(PostInfo* postInfo, int logEntries,
 
 		AppendFmtResponse(itemStart, *EncodeStr(postInfo->GetProgressLabel()),
 			postInfo->GetStageProgress(),
-			postInfo->GetStageTime() ? curTime - postInfo->GetStageTime() : 0,
-			postInfo->GetStartTime() ? curTime - postInfo->GetStartTime() : 0);
+			(int)(postInfo->GetStageTime() ? curTime - postInfo->GetStageTime() : 0),
+			(int)(postInfo->GetStartTime() ? curTime - postInfo->GetStartTime() : 0));
 	}
 	else
 	{
@@ -1884,7 +1884,7 @@ void NzbInfoXmlCommand::AppendPostInfoFields(PostInfo* postInfo, int logEntries,
 
 				AppendCondResponse(",\n", IsJson() && index++ > 0);
 				AppendFmtResponse(IsJson() ? JSON_LOG_ITEM : XML_LOG_ITEM,
-					message.GetId(), messageType[message.GetKind()], message.GetTime(),
+					message.GetId(), messageType[message.GetKind()], (int)message.GetTime(),
 					*EncodeStr(message.GetText()));
 			}
 		}
@@ -2238,7 +2238,7 @@ void DownloadXmlCommand::Execute()
 		}
 	}
 
-	if (!strncasecmp(nzbContent, "http://", 6) || !strncasecmp(nzbContent, "https://", 7))
+	if (!strncasecmp(nzbContent, "http://", 7) || !strncasecmp(nzbContent, "https://", 8))
 	{
 		// add url
 		std::unique_ptr<NzbInfo> nzbInfo = std::make_unique<NzbInfo>();
@@ -2464,8 +2464,8 @@ void HistoryXmlCommand::Execute()
 		"\"Kind\" : \"%s\",\n"
 		"\"Name\" : \"%s\",\n"
 		"\"HistoryTime\" : %i,\n"
-		"\"FileSizeLo\" : %i,\n"
-		"\"FileSizeHi\" : %i,\n"
+		"\"FileSizeLo\" : %u,\n"
+		"\"FileSizeHi\" : %u,\n"
 		"\"FileSizeMB\" : %i,\n"
 		"\"DupeKey\" : \"%s\",\n"
 		"\"DupeScore\" : %i,\n"
@@ -2502,7 +2502,7 @@ void HistoryXmlCommand::Execute()
 
 			AppendFmtResponse(IsJson() ? JSON_HISTORY_ITEM_START : XML_HISTORY_ITEM_START,
 				historyInfo->GetId(), *EncodeStr(historyInfo->GetName()), nzbInfo->GetParkedFileCount(),
-				BoolToStr(nzbInfo->GetCompletedFiles()->size()), historyInfo->GetTime(), status);
+				BoolToStr(nzbInfo->GetCompletedFiles()->size()), (int)historyInfo->GetTime(), status);
 		}
 		else if (historyInfo->GetKind() == HistoryInfo::hkDup)
 		{
@@ -2514,7 +2514,7 @@ void HistoryXmlCommand::Execute()
 
 			AppendFmtResponse(IsJson() ? JSON_HISTORY_DUP_ITEM : XML_HISTORY_DUP_ITEM,
 				historyInfo->GetId(), historyInfo->GetId(), "DUP", *EncodeStr(historyInfo->GetName()),
-				historyInfo->GetTime(), fileSizeLo, fileSizeHi, fileSizeMB,
+				(int)historyInfo->GetTime(), fileSizeLo, fileSizeHi, fileSizeMB,
 				*EncodeStr(dupInfo->GetDupeKey()), dupInfo->GetDupeScore(),
 				dupeModeName[dupInfo->GetDupeMode()], dupStatusName[dupInfo->GetStatus()],
 				status);
@@ -2836,8 +2836,8 @@ void ViewFeedXmlCommand::Execute()
 		"<member><name>Title</name><value><string>%s</string></value></member>\n"
 		"<member><name>Filename</name><value><string>%s</string></value></member>\n"
 		"<member><name>URL</name><value><string>%s</string></value></member>\n"
-		"<member><name>SizeLo</name><value><i4>%i</i4></value></member>\n"
-		"<member><name>SizeHi</name><value><i4>%i</i4></value></member>\n"
+		"<member><name>SizeLo</name><value><i4>%u</i4></value></member>\n"
+		"<member><name>SizeHi</name><value><i4>%u</i4></value></member>\n"
 		"<member><name>SizeMB</name><value><i4>%i</i4></value></member>\n"
 		"<member><name>Category</name><value><string>%s</string></value></member>\n"
 		"<member><name>AddCategory</name><value><string>%s</string></value></member>\n"
@@ -2857,8 +2857,8 @@ void ViewFeedXmlCommand::Execute()
 		"\"Title\" : \"%s\",\n"
 		"\"Filename\" : \"%s\",\n"
 		"\"URL\" : \"%s\",\n"
-		"\"SizeLo\" : %i,\n"
-		"\"SizeHi\" : %i,\n"
+		"\"SizeLo\" : %u,\n"
+		"\"SizeHi\" : %u,\n"
 		"\"SizeMB\" : %i,\n"
 		"\"Category\" : \"%s\",\n"
 		"\"AddCategory\" : \"%s\",\n"
@@ -2893,7 +2893,7 @@ void ViewFeedXmlCommand::Execute()
 				*EncodeStr(feedItemInfo.GetTitle()), *EncodeStr(feedItemInfo.GetFilename()),
 				*EncodeStr(feedItemInfo.GetUrl()), sizeLo, sizeHi, sizeMB,
 				*EncodeStr(feedItemInfo.GetCategory()), *EncodeStr(feedItemInfo.GetAddCategory()),
-				BoolToStr(feedItemInfo.GetPauseNzb()), feedItemInfo.GetPriority(), feedItemInfo.GetTime(),
+				BoolToStr(feedItemInfo.GetPauseNzb()), feedItemInfo.GetPriority(), (int)feedItemInfo.GetTime(),
 				matchStatusType[feedItemInfo.GetMatchStatus()], feedItemInfo.GetMatchRule(),
 				*EncodeStr(feedItemInfo.GetDupeKey()), feedItemInfo.GetDupeScore(),
 				dupeModeType[feedItemInfo.GetDupeMode()], statusType[feedItemInfo.GetStatus()]);
@@ -3119,11 +3119,11 @@ void ServerVolumesXmlCommand::Execute()
 	"\"ServerID\" : %i,\n"
 	"\"DataTime\" : %i,\n"
 	"\"FirstDay\" : %i,\n"
-	"\"TotalSizeLo\" : %i,\n"
-	"\"TotalSizeHi\" : %i,\n"
+	"\"TotalSizeLo\" : %u,\n"
+	"\"TotalSizeHi\" : %u,\n"
 	"\"TotalSizeMB\" : %i,\n"
-	"\"CustomSizeLo\" : %i,\n"
-	"\"CustomSizeHi\" : %i,\n"
+	"\"CustomSizeLo\" : %u,\n"
+	"\"CustomSizeHi\" : %u,\n"
 	"\"CustomSizeMB\" : %i,\n"
 	"\"CustomTime\" : %i,\n"
 	"\"SecSlot\" : %i,\n"
diff --git a/daemon/util/FileSystem.cpp b/daemon/util/FileSystem.cpp
index 99099826..c1c05265 100644
--- a/daemon/util/FileSystem.cpp
+++ b/daemon/util/FileSystem.cpp
@@ -304,10 +304,29 @@ bool FileSystem::AllocateFile(const char* filename, int64 size, bool sparse, CSt
 			errmsg = GetLastErrorMessage();
 			return false;
 		}
-		char c = '0';
-		fwrite(&c, 1, size, file);
+
+		// write zeros in 16K chunks
+		CharBuffer zeros(16 * 1024);
+		memset(zeros, 0, zeros.Size());
+		for (int64 remaining = size; remaining > 0;)
+		{
+			int64 needbytes = std::min(remaining, (int64)zeros.Size());
+			int64 written = fwrite(zeros, 1, needbytes, file);
+			if (written != needbytes)
+			{
+				errmsg = GetLastErrorMessage();
+				fclose(file);
+				return false;
+			}
+			remaining -= written;
+		}
 		fclose(file);
+
 		ok = FileSize(filename) == size;
+		if (!ok)
+		{
+			errmsg = "created file has wrong size";
+		}
 	}
 #endif
 	return ok;
@@ -1020,52 +1039,9 @@ CString FileSystem::WidePathToUtfPath(const wchar_t* wpath)
 #endif
 
 
-#ifdef WIN32
-DirBrowser::DirBrowser(const char* path)
-{
-	BString<1024> mask("%s%c*.*", path, PATH_SEPARATOR);
-	m_file = FindFirstFileW(FileSystem::UtfPathToWidePath(mask), &m_findData);
-	m_first = true;
-}
-
-DirBrowser::~DirBrowser()
-{
-	if (m_file != INVALID_HANDLE_VALUE)
-	{
-		FindClose(m_file);
-	}
-}
-
-const char* DirBrowser::InternNext()
-{
-	bool ok = false;
-	if (m_first)
-	{
-		ok = m_file != INVALID_HANDLE_VALUE;
-		m_first = false;
-	}
-	else
-	{
-		ok = FindNextFileW(m_file, &m_findData) != 0;
-	}
-	if (ok)
-	{
-		m_filename = FileSystem::WidePathToUtfPath(m_findData.cFileName);
-		return m_filename;
-	}
-	return nullptr;
-}
-
-#else
-
-#ifdef DIRBROWSER_SNAPSHOT
 DirBrowser::DirBrowser(const char* path, bool snapshot) :
 	m_snapshot(snapshot)
-#else
-DirBrowser::DirBrowser(const char* path)
-#endif
 {
-#ifdef DIRBROWSER_SNAPSHOT
 	if (m_snapshot)
 	{
 		DirBrowser dir(path, false);
@@ -1076,35 +1052,57 @@ DirBrowser::DirBrowser(const char* path)
 		m_snapshotIter = m_snapshotFiles.begin();
 	}
 	else
-#endif
 	{
+#ifdef WIN32
+		BString<1024> mask("%s%c*.*", path, PATH_SEPARATOR);
+		m_file = FindFirstFileW(FileSystem::UtfPathToWidePath(mask), &m_findData);
+		m_first = true;
+#else
 		m_dir = opendir(path);
+#endif
 	}
 }
 
 DirBrowser::~DirBrowser()
 {
-#ifdef DIRBROWSER_SNAPSHOT
-	if (!m_snapshot)
-#endif
+#ifdef WIN32
+	if (m_file != INVALID_HANDLE_VALUE)
 	{
-		if (m_dir)
-		{
-			closedir(m_dir);
-		}
+		FindClose(m_file);
 	}
+#else
+	if (m_dir)
+	{
+		closedir(m_dir);
+	}
+#endif
 }
 
 const char* DirBrowser::InternNext()
 {
-#ifdef DIRBROWSER_SNAPSHOT
 	if (m_snapshot)
 	{
 		return m_snapshotIter == m_snapshotFiles.end() ? nullptr : **m_snapshotIter++;
 	}
 	else
-#endif
 	{
+#ifdef WIN32
+		bool ok = false;
+		if (m_first)
+		{
+			ok = m_file != INVALID_HANDLE_VALUE;
+			m_first = false;
+		}
+		else
+		{
+			ok = FindNextFileW(m_file, &m_findData) != 0;
+		}
+		if (ok)
+		{
+			m_filename = FileSystem::WidePathToUtfPath(m_findData.cFileName);
+			return m_filename;
+		}
+#else
 		if (m_dir)
 		{
 			m_findData = readdir(m_dir);
@@ -1113,10 +1111,10 @@ const char* DirBrowser::InternNext()
 				return m_findData->d_name;
 			}
 		}
+#endif
 		return nullptr;
 	}
 }
-#endif
 
 const char* DirBrowser::Next()
 {
diff --git a/daemon/util/FileSystem.h b/daemon/util/FileSystem.h
index 60d62493..be267fef 100644
--- a/daemon/util/FileSystem.h
+++ b/daemon/util/FileSystem.h
@@ -84,18 +84,14 @@ public:
 class DirBrowser
 {
 public:
-#ifdef DIRBROWSER_SNAPSHOT
 	DirBrowser(const char* path, bool snapshot = true);
-#else
-	DirBrowser(const char* path);
-#endif
 	~DirBrowser();
 	const char* Next();
 
 private:
 #ifdef WIN32
 	WIN32_FIND_DATAW m_findData;
-	HANDLE m_file;
+	HANDLE m_file = INVALID_HANDLE_VALUE;
 	bool m_first;
 	CString m_filename;
 #else
@@ -103,12 +99,10 @@ private:
 	struct dirent* m_findData;
 #endif
 
-#ifdef DIRBROWSER_SNAPSHOT
 	bool m_snapshot;
 	typedef std::deque<CString> FileList;
 	FileList m_snapshotFiles;
 	FileList::iterator m_snapshotIter;
-#endif
 
 	const char* InternNext();
 };
diff --git a/debian/changelog b/debian/changelog
index 59431c9b..aabb50a5 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+nzbget (21.2~r2333-1) UNRELEASED; urgency=low
+
+  * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk>  Wed, 16 Mar 2022 01:37:58 -0000
+
 nzbget (21.1~r2311+dfsg-2) experimental; urgency=medium
 
   * Update standards version
diff --git a/debian/patches/0001-dont-embed-libraries.patch b/debian/patches/0001-dont-embed-libraries.patch
index bfa4254e..b66a64a0 100644
--- a/debian/patches/0001-dont-embed-libraries.patch
+++ b/debian/patches/0001-dont-embed-libraries.patch
@@ -3,10 +3,10 @@ Author: Andreas Moog <amoog@ubuntu.com>
 Forwarded: not-needed
 Last-Update: 2013-07-18
 
-Index: nzbget-debian/Makefile.am
+Index: nzbget/Makefile.am
 ===================================================================
---- nzbget-debian.orig/Makefile.am
-+++ nzbget-debian/Makefile.am
+--- nzbget.orig/Makefile.am
++++ nzbget/Makefile.am
 @@ -355,9 +355,7 @@ doc_FILES = \
  	ChangeLog \
  	COPYING
diff --git a/linux/build-nzbget b/linux/build-nzbget
index ed91d592..5ecad36e 100755
--- a/linux/build-nzbget
+++ b/linux/build-nzbget
@@ -183,7 +183,9 @@ UpdateFromRepository()
 
         echo "Updating root certificates"
         cd ../setup
-        curl --remote-name --time-cond cacert.pem https://curl.haxx.se/ca/cacert.pem
+        curl --remote-name --time-cond cacert.pem https://curl.se/ca/cacert.pem
+        # remove expired DST Root CA X3 certificate
+        sed '/^DST Root CA X3$/,/^-----END CERTIFICATE-----$/d;' -i cacert.pem
         cd $BUILDDIR
     fi
 }
diff --git a/nzbget.vcxproj b/nzbget.vcxproj
index b9ae1b3e..bead8af3 100755
--- a/nzbget.vcxproj
+++ b/nzbget.vcxproj
@@ -80,7 +80,7 @@
     <ClCompile>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>.\daemon\connect;.\daemon\extension;.\daemon\feed;.\daemon\frontend;.\daemon\main;.\daemon\nserv;.\daemon\nntp;.\daemon\postprocess;.\daemon\queue;.\daemon\remote;.\daemon\util;.\daemon\windows;.\lib\par2;.\lib\yencode;.\windows\resources;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;PACKAGE="nzbget";VERSION="21.1-testing";_DEBUG;_CONSOLE;DEBUG;_WIN32_WINNT=0x0403;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;PACKAGE="nzbget";VERSION="21.2-testing";_DEBUG;_CONSOLE;DEBUG;_WIN32_WINNT=0x0403;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <MinimalRebuild>false</MinimalRebuild>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@@ -101,7 +101,7 @@
     <ClCompile>
       <Optimization>Disabled</Optimization>
       <AdditionalIncludeDirectories>.\daemon\connect;.\daemon\extension;.\daemon\feed;.\daemon\frontend;.\daemon\main;.\daemon\nserv;.\daemon\nntp;.\daemon\postprocess;.\daemon\queue;.\daemon\remote;.\daemon\util;.\daemon\windows;.\lib\par2;.\lib\yencode;.\windows\resources;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;PACKAGE="nzbget";VERSION="21.1-testing";_DEBUG;_CONSOLE;DEBUG;_WIN32_WINNT=0x0403;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;PACKAGE="nzbget";VERSION="21.2-testing";_DEBUG;_CONSOLE;DEBUG;_WIN32_WINNT=0x0403;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <MinimalRebuild>false</MinimalRebuild>
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@@ -120,7 +120,7 @@
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
     <ClCompile>
       <AdditionalIncludeDirectories>.\daemon\connect;.\daemon\extension;.\daemon\feed;.\daemon\frontend;.\daemon\main;.\daemon\nserv;.\daemon\nntp;.\daemon\postprocess;.\daemon\queue;.\daemon\remote;.\daemon\util;.\daemon\windows;.\lib\par2;.\lib\yencode;.\windows\resources;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;PACKAGE="nzbget";VERSION="21.1-testing";NDEBUG;_CONSOLE;_WIN32_WINNT=0x0403;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;PACKAGE="nzbget";VERSION="21.2-testing";NDEBUG;_CONSOLE;_WIN32_WINNT=0x0403;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExceptionHandling>Sync</ExceptionHandling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <PrecompiledHeader>Use</PrecompiledHeader>
@@ -151,7 +151,7 @@
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
     <ClCompile>
       <AdditionalIncludeDirectories>.\daemon\connect;.\daemon\extension;.\daemon\feed;.\daemon\frontend;.\daemon\main;.\daemon\nserv;.\daemon\nntp;.\daemon\postprocess;.\daemon\queue;.\daemon\remote;.\daemon\util;.\daemon\windows;.\lib\par2;.\lib\yencode;.\windows\resources;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
-      <PreprocessorDefinitions>WIN32;PACKAGE="nzbget";VERSION="21.1-testing";NDEBUG;_CONSOLE;_WIN32_WINNT=0x0403;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <PreprocessorDefinitions>WIN32;PACKAGE="nzbget";VERSION="21.2-testing";NDEBUG;_CONSOLE;_WIN32_WINNT=0x0403;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <ExceptionHandling>Sync</ExceptionHandling>
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
       <PrecompiledHeader>Use</PrecompiledHeader>
diff --git a/webui/config.js b/webui/config.js
index c83872f2..81ed0842 100644
--- a/webui/config.js
+++ b/webui/config.js
@@ -504,7 +504,6 @@ var Config = (new function($)
 	var $ConfigTabBadgeEmpty;
 	var $ConfigContent;
 	var $ConfigInfo;
-	var $ConfigAbout;
 	var $ConfigTitle;
 	var $ConfigTable;
 	var $ViewButton;
@@ -533,7 +532,6 @@ var Config = (new function($)
 		$ConfigTabBadgeEmpty = $('#ConfigTabBadgeEmpty');
 		$ConfigContent = $('#ConfigContent');
 		$ConfigInfo = $('#ConfigInfo');
-		$ConfigAbout = $('#ConfigAbout');
 		$ConfigTitle = $('#ConfigTitle');
 		$ViewButton = $('#Config_ViewButton');
 		$LeaveConfigDialog = $('#LeaveConfigDialog');
@@ -1211,10 +1209,9 @@ var Config = (new function($)
 		$('li', $ConfigNav).removeClass('active');
 		link.closest('li').addClass('active');
 		$ConfigContent.removeClass('search');
-		Util.show($ViewButton, sectionId !== 'Config-Info' && sectionId !== 'Config-About');
+		Util.show($ViewButton, sectionId !== 'Config-Info');
 
 		$ConfigInfo.hide();
-		$ConfigAbout.hide();
 
 		if (sectionId === 'Search')
 		{
@@ -1228,15 +1225,7 @@ var Config = (new function($)
 		{
 			$ConfigInfo.show();
 			$ConfigData.children().hide();
-			$ConfigTitle.text('INFO: SETTINGS');
-			return;
-		}
-
-		if (sectionId === 'Config-About')
-		{
-			$ConfigAbout.show();
-			$ConfigData.children().hide();
-			$ConfigTitle.text('NZBGET ' + Options.option('version'));
+			$ConfigTitle.text('INFO');
 			return;
 		}
 
diff --git a/webui/fasttable.js b/webui/fasttable.js
index 1bb28391..99f25080 100644
--- a/webui/fasttable.js
+++ b/webui/fasttable.js
@@ -683,7 +683,7 @@
 	function itemCheckClick(data, event)
 	{
 		var checkmark = $(event.target).hasClass('check');
-		if (data.dragging || (!checkmark && !data.config.rowSelect))
+		if (data.dragging || (!checkmark && !data.config.rowSelect))
 		{
 			return;
 		}
@@ -712,7 +712,7 @@
 	function titleCheckClick(data, event)
 	{
 		var checkmark = $(event.target).hasClass('check');
-		if (data.dragging || (!checkmark && !data.config.rowSelect))
+		if (data.dragging || (!checkmark && !data.config.rowSelect))
 		{
 			return;
 		}
diff --git a/webui/index.html b/webui/index.html
index a839cb49..99344171 100644
--- a/webui/index.html
+++ b/webui/index.html
@@ -538,7 +538,6 @@
 						<div class="span3">
 							<ul class="nav nav-list" id="ConfigNav">
 							<li class="config-static"><a href="#Config-Info">INFO</a></li>
-							<li class="config-static"><a href="#Config-About">ABOUT NZBGET</a></li>
 							<li class="config-static"><a href="#Config-System">SYSTEM</a></li>
 							</ul>
 						</div>
@@ -547,7 +546,7 @@
 							<div>
 
 								<div class="config-header clearfix">
-									<div class="pull-left" id="ConfigTitle">INFO: SETTINGS</div>
+									<div class="pull-left" id="ConfigTitle">INFO</div>
 									<div class="btn-group pull-right">
 										<a class="btn dropdown-toggle" id="Config_ViewButton" data-toggle="dropdown">View <span class="caret"></span></a>
 										<ul class="dropdown-menu footer-button-menu" id="Config_ViewMenu">
@@ -569,12 +568,6 @@
 									When you configure NZBGet for the first time you need
 									to check at least the option <a class="option" href="#" data-category="S" onclick="Config.scrollToOption(event, this)">MainDir</a> and configure one news server.
 									</p>
-									<p>
-									There are many configuration options affecting performance. If you use
-									NZBGet on a computer with limited capabilities, such as NAS, media player,
-									router, etc. you should take your time to configure NZBGet for best
-									performance - see <a href="http://nzbget.net/performance-tips">Performance tips</a>.
-									</p>
 
 									<h4>Extension scripts settings</h4>
 									<p>
@@ -595,11 +588,6 @@
 									<p>
 									This can be done in section <em><strong>SYSTEM</strong></em>.
 									</p>
-								</div>
-
-								<div id="ConfigAbout">
-									<p>For info on NZBGet project please visit <a href="http://nzbget.net">NZBGet Home Page</a>. Among other things the developers of third-party apps find there complete docs about RPC interface.</p>
-									<p>Should you need help, have suggestions or want to share your improvements - <a href="http://nzbget.net/forum">NZBGet Forum</a> is a place to do that.</p>
 
 									<h4>Copyright</h4>
 									<p>This program is free software; you can redistribute it and/or modify
diff --git a/webui/upload.js b/webui/upload.js
index f3582a38..92747eaf 100644
--- a/webui/upload.js
+++ b/webui/upload.js
@@ -172,13 +172,9 @@ var Upload = (new function($)
 	{
 		var inp = $('#AddDialog_Input');
 
-		// Reset file input control; needed for IE10 but produce problems with opera (the old non-webkit one).
-		if ($.browser.msie)
-		{
-			inp.wrap('<form>').closest('form').get(0).reset();
-			inp.unwrap();
-		}
-		
+		// Reset file input control
+		inp.val('');		
+
 		inp.click();
 	}