diff --git a/Duplicati/Library/Utility/Uri.cs b/Duplicati/Library/Utility/Uri.cs
index e6505f57d..d5e02686c 100644
--- a/Duplicati/Library/Utility/Uri.cs
+++ b/Duplicati/Library/Utility/Uri.cs
@@ -328,7 +328,7 @@ namespace Duplicati.Library.Utility
///
/// The regular expression that matches %20 type values in a querystring
///
- private static System.Text.RegularExpressions.Regex RE_ESCAPECHAR = new System.Text.RegularExpressions.Regex(@"[^0-9a-zA-Z]", System.Text.RegularExpressions.RegexOptions.Compiled);
+ private static System.Text.RegularExpressions.Regex RE_ESCAPECHAR = new System.Text.RegularExpressions.Regex(@"[^0-9a-zA-Z\-\_]", System.Text.RegularExpressions.RegexOptions.Compiled);
///
/// Encodes a URL, like System.Web.HttpUtility.UrlEncode
@@ -356,9 +356,8 @@ namespace Duplicati.Library.Utility
var encoder = encoding.GetEncoder();
var inbuf = new char[1];
- var outbuf = new byte[2];
- var shortout = new byte[1];
-
+ var outbuf = new byte[4];
+
return RE_ESCAPECHAR.Replace(value, (m) => {
if (m.Value == " ")
return spacevalue;
@@ -368,13 +367,7 @@ namespace Duplicati.Library.Utility
try
{
var len = encoder.GetBytes(inbuf, 0, 1, outbuf, 0, true);
- if (len == 1)
- {
- shortout[0] = outbuf[0];
- return "%" + Utility.ByteArrayAsHexString(shortout).ToLower();
- }
- else if (len == 2)
- return "%u" + Utility.ByteArrayAsHexString(outbuf).ToLower();
+ return "%" + BitConverter.ToString(outbuf, 0, len).Replace("-", "%");
}
catch
{
@@ -389,12 +382,7 @@ namespace Duplicati.Library.Utility
///
/// The regular expression that matches %20 type values in a querystring
///
- private static System.Text.RegularExpressions.Regex RE_NUMBER = new System.Text.RegularExpressions.Regex(@"(\%(?([0-9]|[a-z]|[A-Z]){2}))|(\+)|(\%u(?([0-9]|[a-z]|[A-Z]){4}))", System.Text.RegularExpressions.RegexOptions.Compiled);
-
- ///
- /// A helper for converting byte arrays to hex, vice versa
- ///
- private const string HEX_DIGITS_UPPER = "0123456789ABCDEF";
+ private static System.Text.RegularExpressions.Regex RE_NUMBER = new System.Text.RegularExpressions.Regex(@"(\%(?([0-9]|[a-f]|[A-F]){2}))|(\+)|(\%u(?([0-9]|[a-f]|[A-F]){2,4,6,8}))", System.Text.RegularExpressions.RegexOptions.Compiled);
///
/// Encodes a URL, like System.Web.HttpUtility.UrlEncode
@@ -410,20 +398,20 @@ namespace Duplicati.Library.Utility
encoding = encoding ?? System.Text.Encoding.UTF8;
var decoder = encoding.GetDecoder();
- var inbuf = new byte[2];
- var outbuf = new char[1];
-
- return RE_NUMBER.Replace(value, (m) => {
+ var inbuf = new byte[8];
+ var outbuf = new char[8];
+
+ return RE_NUMBER.Replace(value, (m) => {
if (m.Value == "+")
return " ";
try
{
var hex = m.Groups["number"].Value;
+ var bytelen = hex.Length / 2;
Utility.HexStringAsByteArray(hex, inbuf);
-
- decoder.GetChars(inbuf, 0, hex.Length / 2, outbuf, 0);
- return outbuf[0].ToString();
+ var c = decoder.GetChars(inbuf, 0, bytelen, outbuf, 0);
+ return new string(outbuf, 0, c);
}
catch
{
diff --git a/Duplicati/Library/Utility/Utility.cs b/Duplicati/Library/Utility/Utility.cs
index 8ba07889b..d84e89fe8 100644
--- a/Duplicati/Library/Utility/Utility.cs
+++ b/Duplicati/Library/Utility/Utility.cs
@@ -626,67 +626,29 @@ namespace Duplicati.Library.Utility
}
///
- /// A helper for converting byte arrays to hex, vice versa
- ///
- private const string HEX_DIGITS_UPPER = "0123456789ABCDEF";
-
- ///
- /// Converts the byte array to hex digits
+ /// Converts a sequence of bytes to a hex string
///
+ /// The array as hex string.
/// The data to convert
- /// The data as a string of hex digits
public static string ByteArrayAsHexString(byte[] data)
{
- if (data == null || data.Length == 0)
- return "";
-
- StringBuilder sb = new StringBuilder();
- foreach(byte b in data)
- {
- sb.Append(HEX_DIGITS_UPPER[(b >> 4) & 0xF]);
- sb.Append(HEX_DIGITS_UPPER[b & 0xF]);
- }
-
- return sb.ToString();
+ return BitConverter.ToString(data).Replace("-", string.Empty);
}
-
///
- /// Converts the given hex string into a byte array
+ /// Converts a hex string to a byte array
///
+ /// The string as byte array.
/// The hex string
- /// A pre-allocated output data array, or null
- /// The byte array
- public static byte[] HexStringAsByteArray(string hex, byte[] data = null)
+ /// The parsed data
+ public static byte[] HexStringAsByteArray(string hex, byte[] data)
{
- if (string.IsNullOrEmpty(hex))
- return new byte[0];
-
- hex = hex.Trim().ToUpper();
-
- if (hex.Length % 2 != 0)
- throw new Exception(Strings.Utility.InvalidHexStringLengthError);
-
- if (data == null)
- data = new byte[hex.Length / 2];
- else if (data.Length < hex.Length / 2)
- throw new ArgumentOutOfRangeException("data");
-
- for(int i = 0; i < hex.Length; i+= 2)
- {
- int upper = HEX_DIGITS_UPPER.IndexOf(hex[i]);
- int lower = HEX_DIGITS_UPPER.IndexOf(hex[i + 1]);
-
- if (upper < 0)
- throw new Exception(string.Format(Strings.Utility.InvalidHexDigitError, hex[i]));
- if (lower < 0)
- throw new Exception(string.Format(Strings.Utility.InvalidHexDigitError, hex[i + 1]));
-
- data[i % 2] = (byte)((upper << 4) | lower);
- }
+ for (var i = 0; i < hex.Length; i += 2)
+ data[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
return data;
}
+
public static bool Which(string appname)
{
diff --git a/Duplicati/Server/WebServer/IndexHtmlHandler.cs b/Duplicati/Server/WebServer/IndexHtmlHandler.cs
index d1481f9c6..0cd3f8ffe 100644
--- a/Duplicati/Server/WebServer/IndexHtmlHandler.cs
+++ b/Duplicati/Server/WebServer/IndexHtmlHandler.cs
@@ -33,7 +33,7 @@ namespace Duplicati.Server.WebServer
{
response.Status = System.Net.HttpStatusCode.OK;
response.Reason = "OK";
- response.ContentType = "text/html";
+ response.ContentType = "text/html; charset=utf-8";
using (var fs = System.IO.File.OpenRead(m_defaultdoc))
{
diff --git a/Duplicati/Server/WebServer/Server.cs b/Duplicati/Server/WebServer/Server.cs
index a159d2731..19ce81fd5 100644
--- a/Duplicati/Server/WebServer/Server.cs
+++ b/Duplicati/Server/WebServer/Server.cs
@@ -174,6 +174,8 @@ namespace Duplicati.Server.WebServer
customized_files.MimeTypes.Add("htc", "text/x-component");
customized_files.MimeTypes.Add("json", "application/json");
customized_files.MimeTypes.Add("map", "application/json");
+ customized_files.MimeTypes["htm"] = "text/html; charset=utf-8";
+ customized_files.MimeTypes["html"] = "text/html; charset=utf-8";
server.Add(customized_files);
}
@@ -182,13 +184,14 @@ namespace Duplicati.Server.WebServer
fh.MimeTypes.Add("htc", "text/x-component");
fh.MimeTypes.Add("json", "application/json");
fh.MimeTypes.Add("map", "application/json");
+ fh.MimeTypes["htm"] = "text/html; charset=utf-8";
+ fh.MimeTypes["html"] = "text/html; charset=utf-8";
server.Add(fh);
server.Add(new IndexHtmlHandler(System.IO.Path.Combine(webroot, "index.html")));
#if DEBUG
//For debugging, it is nice to know when we get a 404
server.Add(new DebugReportHandler());
#endif
-
return server;
}
diff --git a/thirdparty/HttpServer/Homepage.txt b/thirdparty/HttpServer/Homepage.txt
index c0d8fec2b..43b623b1f 100644
--- a/thirdparty/HttpServer/Homepage.txt
+++ b/thirdparty/HttpServer/Homepage.txt
@@ -1 +1 @@
-http://webserver.codeplex.com/
\ No newline at end of file
+https://github.com/duplicati/httpserver
\ No newline at end of file
diff --git a/thirdparty/HttpServer/HttpServer.dll b/thirdparty/HttpServer/HttpServer.dll
index 24ed031f6..80434ed19 100644
Binary files a/thirdparty/HttpServer/HttpServer.dll and b/thirdparty/HttpServer/HttpServer.dll differ
diff --git a/thirdparty/HttpServer/Upgrade-readme.txt b/thirdparty/HttpServer/Upgrade-readme.txt
deleted file mode 100644
index bc152592d..000000000
--- a/thirdparty/HttpServer/Upgrade-readme.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-The file HttpServer.dll has been patched from the tags/v1.1 version,
-to prevent a crash where multiple threads access the file collection on a form.
-
-If you upgrade, make sure to apply the patch.
\ No newline at end of file
diff --git a/thirdparty/HttpServer/fix-filemodule-crash.patch b/thirdparty/HttpServer/fix-filemodule-crash.patch
deleted file mode 100644
index 6704a53eb..000000000
--- a/thirdparty/HttpServer/fix-filemodule-crash.patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 4ef5d02d06c5297469d814462daf6aa449628467 Mon Sep 17 00:00:00 2001
-From: Kenneth Skovhede
-Date: Tue, 5 Aug 2014 10:06:31 +0200
-Subject: [PATCH] Fixed bug that causes FileModule to crash
-
----
- HttpServer/HttpModules/FileModule.cs | 6 ++++--
- 1 file changed, 4 insertions(+), 2 deletions(-)
-
-diff --git a/HttpServer/HttpModules/FileModule.cs b/HttpServer/HttpModules/FileModule.cs
-index 071fd01..8efa5a4 100755
---- a/HttpServer/HttpModules/FileModule.cs
-+++ b/HttpServer/HttpModules/FileModule.cs
-@@ -120,10 +120,12 @@ namespace HttpServer.HttpModules
- {
- if (Contains(uri.AbsolutePath, _forbiddenChars))
- return false;
--
-+
-+ if (!uri.AbsolutePath.StartsWith(_baseUri))
-+ return false;
-+
- string path = GetPath(uri);
- return
-- uri.AbsolutePath.StartsWith(_baseUri) && // Correct directory
- File.Exists(path) && // File exists
- (File.GetAttributes(path) & FileAttributes.ReparsePoint) == 0; // Not a symlink
- }
---
-1.8.4.2
-
diff --git a/thirdparty/HttpServer/licensedata.json b/thirdparty/HttpServer/licensedata.json
index 2eba21b2d..e0fb5de03 100644
--- a/thirdparty/HttpServer/licensedata.json
+++ b/thirdparty/HttpServer/licensedata.json
@@ -1,7 +1,7 @@
{
"name": "C# WebServer",
"description": "A HTTP Compliant WebServer in C#",
- "link": "http://webserver.codeplex.com/",
+ "link": "https://github.com/duplicati/httpserver",
"license": "Apache 2.0",
- "notes": "Patched to fix a crash"
+ "notes": "Patched from http://webserver.codeplex.com/"
}
\ No newline at end of file
diff --git a/thirdparty/HttpServer/removed-urlencode-usage.diff b/thirdparty/HttpServer/removed-urlencode-usage.diff
deleted file mode 100644
index 1ebd818de..000000000
--- a/thirdparty/HttpServer/removed-urlencode-usage.diff
+++ /dev/null
@@ -1,266 +0,0 @@
-From 4e4239cf74e23e13c3bee808104d8d213e40fe39 Mon Sep 17 00:00:00 2001
-From: Kenneth Skovhede
-Date: Wed, 23 Jul 2014 15:04:20 +0200
-Subject: [PATCH] Removed usage of HttpUtility UrlEncode and
- HttpUtility.UrlDecode as these has issues on Mono.
-
----
- HttpServer/HttpHelper.cs | 2 +-
- HttpServer/HttpRequest.cs | 4 +-
- HttpServer/HttpServer.csproj | 1 +
- HttpServer/HttpUtilityHelper.cs | 171 ++++++++++++++++++++++++++++++++++++++++
- HttpServer/RequestCookie.cs | 2 +-
- HttpServer/ResponseCookie.cs | 2 +-
- 6 files changed, 177 insertions(+), 5 deletions(-)
- create mode 100644 HttpServer/HttpUtilityHelper.cs
-
-diff --git a/HttpServer/HttpHelper.cs b/HttpServer/HttpHelper.cs
-index 8d11daa..a0d286f 100755
---- a/HttpServer/HttpHelper.cs
-+++ b/HttpServer/HttpHelper.cs
-@@ -165,7 +165,7 @@ namespace HttpServer
-
- private static void Add(IHttpInput input, string name, string value)
- {
-- input.Add(HttpUtility.UrlDecode(name), HttpUtility.UrlDecode(value));
-+ input.Add(HttpUtilityHelper.UrlDecode(name), HttpUtilityHelper.UrlDecode(value));
- }
- }
- }
-diff --git a/HttpServer/HttpRequest.cs b/HttpServer/HttpRequest.cs
-index a52dbed..cacbb7d 100755
---- a/HttpServer/HttpRequest.cs
-+++ b/HttpServer/HttpRequest.cs
-@@ -54,12 +54,12 @@ namespace HttpServer
- _queryString = HttpHelper.ParseQueryString(_uriPath.Substring(pos + 1));
- _param.SetQueryString(_queryString);
- string path = _uriPath.Substring(0, pos);
-- _uriPath = System.Web.HttpUtility.UrlDecode(path) + "?" + _uriPath.Substring(pos + 1);
-+ _uriPath = HttpUtilityHelper.UrlDecode(path) + "?" + _uriPath.Substring(pos + 1);
- UriParts = value.Substring(0, pos).Split(UriSplitters, StringSplitOptions.RemoveEmptyEntries);
- }
- else
- {
-- _uriPath = System.Web.HttpUtility.UrlDecode(_uriPath);
-+ _uriPath = HttpUtilityHelper.UrlDecode(_uriPath);
- UriParts = value.Split(UriSplitters, StringSplitOptions.RemoveEmptyEntries);
- }
- }
-diff --git a/HttpServer/HttpServer.csproj b/HttpServer/HttpServer.csproj
-index 81bb2eb..431c406 100644
---- a/HttpServer/HttpServer.csproj
-+++ b/HttpServer/HttpServer.csproj
-@@ -134,6 +134,7 @@
-
-
-
-+
-
-
-
-+
-+
-+
-
-\ No newline at end of file
-diff --git a/HttpServer/httpserver.pfx b/HttpServer/httpserver.pfx
-deleted file mode 100755
-index 2ba33088b51785a8dbf88106abf0ec3dd7a54994..0000000000000000000000000000000000000000
-GIT binary patch
-literal 0
-HcmV?d00001
-
-literal 1756
-zcmY+DeK^zm8^^!juNgM-Sou+mQu2`R6k2pLTIFH;$?!W!GUGT()AF!n7l!$fB&?QB
-zO((|DD33*XN`<2(x$4;RkVeaM#Zt1<`POwFu5*2^`*Yv->%Q;L_4(s|!yNP=1ggLs
-zbP-y^io2h?qy?&hB^-1nii1u=FdOEmH2$lkQjX%NTtlz`u}f&|pHrF`5Gvt7jW7qQ
-zh1a1me_`bDRVei*dsTfO@!?4bQhS2pK>4v(nvZ(m->x{ukuARbs-5CAvx~Odw=Us@
-zHHEuWyb>e4zy4H7c`2i!-x8iqIy^cuzWrRWu*hd((}SF*$Nm{IVU0tGPkA1w}DKewdTx{k#_6FH6@`-P~O49^#UuQPTYF49;krZ}UN5r8U?pbQha{Ql@L+|pl9S#M=Z6t|l
-zKfk`Z>B8FVa}m1_-sb1O;+*dBvGAnt&{XLq=Ybi;wV~B{E`1?K(s5F^`p#Lr$Yz5*
-zv~RO?e1K50Q01G7;jbO>(TqBWdoZ9LZN)aSiuLC;FWQaq!(}Nt^3p81R#97UOyy4R
-z-|_p`ujAtGbYm6*xn^Bt_7myNajS^Wk&}Zq_qB{q6V2!5MLo+kH#;_(v)k-auM2B~
-zoyxv9o=-d@KGrU-pbw=RB%EvsVq9Q|Kz;bUB7LOUmGJPuchG#0JI*0jlXlq4HQ4@XV({ZoJ=U&0hV$rxrSp>4``XckDKS%DSoRxUvs`Z5O>nQJP4B-X
-z{rPhPUZ=uJK~_F_B!gIYilUFZUFI|dkS;zaJe$N)Sm#Y=&RvB0kI`jWyoN8Hy_t7qb)s=9~$lsGw^cGlUQ@s4-Zu(r!KKQo@;7@vFUS4i=p
-zTrB3{)B0ikzt>!2H6D#ZfdBx&!T&%5JjKKtI0e9fJ>ZBOJm3zv0R+GnAR^2i$!&q{
-zh$jGhzp?FzCnAwOLiZx(fZUG2HlzbaJPBaKA!rS2G>8H@PP!o8$AkiqfggczfC(^w
-z6Np6uaR3gWBKKEv4EO=b+>!Vs5Q{Jdk~4uYB#!zvg#&!P^(7z~9f$y!h!WfW{=FI+
-z5$8<=i69U_T-iSr@LzI8f0ZlW(-L$2=g-Ms<(kTYSS!?c5AsuitcZL2~DGuaURhGUU)idEHbtKpL$yYq3UbK
-z%KO&A&o#83L$m7wNSk2GjKRck7xs-?_yF_Frmc+djXVb_Gq72G%wcQGdDFVlf%myn
-z?Jc_40Q!NHlq+rQL?YSl04s8#-zl!Dmz5mR>ovZo+~Priuko_mE%12erZ1+ts)JOV
-zOi|UX|9?JxC`%CPQ{mFh-*`6u1hYHlRfwb4yCLwdf}rOe?P=rRlx)VG;3eHFHVFxx|79-3m_y}N9mQY1
-zaD#X6P)EGKl6);zmysusr$?tSm0hh#f@-R^gQB%oF;kWeJHw{18d}wQl?r5pGDzzU
-wttb-R{;yd~$(5O1HS>f0S=&(t-0ZzaPrWSnZT7qu`SceL-kH&*xUY-*2gkbk^#A|>
-
-diff --git a/HttpServer/test.snk b/HttpServer/test.snk
-deleted file mode 100755
-index 8da3182b4ebfb542507eb7ef48ffbfce2bf3995b..0000000000000000000000000000000000000000
-GIT binary patch
-literal 0
-HcmV?d00001
-
-literal 596
-zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50097bzgeh{8PZA&elL^}7m-6lG|{kbaa9P5
-z6e@YDGh=|GP9%|kZDq^AxDp8i8ol~tW*zyPCUH^Y0q!HZ`nqyF+b?rNIuOl6sJ%lW
-zlMb&1^h=-twO35$90By~P4G-7iifzzpVSD}Bs+gQv@iL2u8^ioiXa*UMGvLryokaD
-zUd}+4OdXNRIong?<<6!9K$)!7
-zByqNO1qp1^_%$`#e+>@`pd;RK{7uWBj<2KCFZnO%#TTJDxSw+v(~D(u#{CaVH$Nxr
-zzyiIV;fL=Bs+Gq!@zn0M*%Ne)SNZFA@!M-ZJ$2Q%g3NUhR!8qA0#}
-zSJY#IGkNYv4L$XLA)9v59%3fY#qPdXYvdKy)H
-iTkg*w>*3ZPja^HsjVZRb
-Date: Sat, 28 Jun 2014 16:52:33 +0200
-Subject: [PATCH] Fixed Tempfolder to use the system tempfolder instead of
- hardcoded /var/tmp
-
----
- HttpServer/FormDecoders/MultipartDecoder.cs | 12 +++++++-----
- HttpServer/HttpServer.cs | 10 ++++++----
- 2 files changed, 13 insertions(+), 9 deletions(-)
-
-diff --git a/HttpServer/FormDecoders/MultipartDecoder.cs b/HttpServer/FormDecoders/MultipartDecoder.cs
-index b4a6dbb..6da4967 100755
---- a/HttpServer/FormDecoders/MultipartDecoder.cs
-+++ b/HttpServer/FormDecoders/MultipartDecoder.cs
-@@ -22,6 +22,12 @@ namespace HttpServer.FormDecoders
- /// form-data
- ///
- public const string FormData = "form-data";
-+
-+ ///
-+ /// Gets the temp folder used to store multi-part uploads
-+ ///
-+ public static readonly string Tempfolder = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "HttpServer");
-+
- #region IFormDecoder Members
-
- ///
-@@ -73,11 +79,7 @@ namespace HttpServer.FormDecoders
-
- // Generate a filename
- string filename = element.Filename;
-- string internetCache = Environment.GetFolderPath(Environment.SpecialFolder.InternetCache);
-- // if the internet path doesn't exist, assume mono and /var/tmp
-- string path = string.IsNullOrEmpty(internetCache)
-- ? Path.Combine("var", "tmp")
-- : Path.Combine(internetCache.Replace("\\\\", "\\"), "tmp");
-+ string path = Tempfolder;
- element.Filename = Path.Combine(path, Math.Abs(element.Filename.GetHashCode()) + ".tmp");
-
- // If the file exists generate a new filename
-diff --git a/HttpServer/HttpServer.cs b/HttpServer/HttpServer.cs
-index 9dd4215..4ecf16a 100755
---- a/HttpServer/HttpServer.cs
-+++ b/HttpServer/HttpServer.cs
-@@ -476,15 +476,17 @@ namespace HttpServer
- _components.AddInstance(new HttpContextFactory(LogWriter, 16384,
- _components.Get()));
-
-- // the special folder does not exist on mono
-- string tempPath = Environment.GetFolderPath(Environment.SpecialFolder.InternetCache);
-- if (string.IsNullOrEmpty(tempPath))
-- tempPath = "/var/tmp/";
-+ string tempPath = System.IO.Path.GetTempPath();
- if (!Directory.Exists(tempPath))
- {
- WriteLog(this, LogPrio.Warning, "Temp path do not exist: " + tempPath);
- return;
- }
-+
-+ tempPath = MultipartDecoder.Tempfolder;
-+ if (!Directory.Exists(tempPath))
-+ Directory.CreateDirectory(tempPath);
-+
- DirectoryInfo info = new DirectoryInfo(tempPath);
- foreach (FileInfo file in info.GetFiles("*.tmp"))
- file.Delete();
---
-1.8.4.2
-
diff --git a/thirdparty/HttpServer/webserver-thread-fix.patch b/thirdparty/HttpServer/webserver-thread-fix.patch
deleted file mode 100644
index 2b1dd0b98..000000000
--- a/thirdparty/HttpServer/webserver-thread-fix.patch
+++ /dev/null
@@ -1,92 +0,0 @@
-diff -urN webserver-clean/HttpServer/HttpForm.cs webserver-modified/HttpServer/HttpForm.cs
---- webserver-clean/HttpServer/HttpForm.cs 2014-01-10 12:08:32.000000000 +0100
-+++ webserver-modified/HttpServer/HttpForm.cs 2014-01-18 23:32:04.000000000 +0100
-@@ -10,6 +10,9 @@
- public static readonly HttpForm EmptyForm = new HttpForm("EmptyForm", true);
-
- private readonly Dictionary _files = new Dictionary();
-+
-+ // A lock to prevent concurrent access to the _files dict
-+ private object _lock = new object();
-
- /// Initializes a form container with the specified name
- public HttpForm() : base("form")
-@@ -45,7 +48,8 @@
- if(_files.ContainsKey(file.Name))
- throw new ArgumentException("File named '" + file.Name + "' already exists!");
-
-- _files.Add(file.Name, file);
-+ lock(_lock)
-+ _files.Add(file.Name, file);
- }
-
- ///
-@@ -72,16 +76,19 @@
- /// If name is null or empty
- /// If the instance is HttpForm.EmptyForm which cannot be modified
- public HttpFile GetFile(string name)
-- {
-- if (_ignoreChanges)
-- throw new InvalidOperationException("Cannot retrieve files from instance HttpForm.EmptyForm.");
-- if(string.IsNullOrEmpty(name))
-- throw new ArgumentNullException("name");
-+ {
-+ if (_ignoreChanges)
-+ throw new InvalidOperationException("Cannot retrieve files from instance HttpForm.EmptyForm.");
-+ if (string.IsNullOrEmpty(name))
-+ throw new ArgumentNullException("name");
-
-- if(!_files.ContainsKey(name))
-- return null;
-+ lock(_lock)
-+ {
-+ if (!_files.ContainsKey(name))
-+ return null;
-
-- return _files[name];
-+ return _files[name];
-+ }
- }
-
- ///
-@@ -95,10 +102,13 @@
- if (_files.Count == 0)
- return EmptyFileCollection;
-
-- List files = new List();
-- foreach (HttpFile file in _files.Values)
-- files.Add(file);
-- return files.AsReadOnly();
-+ lock(_lock)
-+ {
-+ List files = new List();
-+ foreach(HttpFile file in _files.Values)
-+ files.Add(file);
-+ return files.AsReadOnly();
-+ }
- }
- }
-
-@@ -106,13 +116,16 @@
-
- /// Disposes all held HttpFile's and resets values
- public override void Clear()
-- {
-- base.Clear();
-+ {
-+ base.Clear();
-
-- foreach (KeyValuePair pair in _files)
-- pair.Value.Dispose();
-+ lock(_lock)
-+ {
-+ foreach(KeyValuePair pair in _files)
-+ pair.Value.Dispose();
-
-- _files.Clear();
-+ _files.Clear();
-+ }
- }
- }
- }
-