Fixed handling of multi-byte characters in both HttpServer and Duplicati.

This fixes issue #1085 and issue #1063.
This commit is contained in:
Kenneth Skovhede
2014-08-13 23:42:26 +02:00
parent 00a11ebc33
commit b8199ad1c4
13 changed files with 30 additions and 736 deletions
+12 -24
View File
@@ -328,7 +328,7 @@ namespace Duplicati.Library.Utility
/// <summary>
/// The regular expression that matches %20 type values in a querystring
/// </summary>
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);
/// <summary>
/// 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
/// <summary>
/// The regular expression that matches %20 type values in a querystring
/// </summary>
private static System.Text.RegularExpressions.Regex RE_NUMBER = new System.Text.RegularExpressions.Regex(@"(\%(?<number>([0-9]|[a-z]|[A-Z]){2}))|(\+)|(\%u(?<number>([0-9]|[a-z]|[A-Z]){4}))", System.Text.RegularExpressions.RegexOptions.Compiled);
/// <summary>
/// A helper for converting byte arrays to hex, vice versa
/// </summary>
private const string HEX_DIGITS_UPPER = "0123456789ABCDEF";
private static System.Text.RegularExpressions.Regex RE_NUMBER = new System.Text.RegularExpressions.Regex(@"(\%(?<number>([0-9]|[a-f]|[A-F]){2}))|(\+)|(\%u(?<number>([0-9]|[a-f]|[A-F]){2,4,6,8}))", System.Text.RegularExpressions.RegexOptions.Compiled);
/// <summary>
/// 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
{
+10 -48
View File
@@ -626,67 +626,29 @@ namespace Duplicati.Library.Utility
}
/// <summary>
/// A helper for converting byte arrays to hex, vice versa
/// </summary>
private const string HEX_DIGITS_UPPER = "0123456789ABCDEF";
/// <summary>
/// Converts the byte array to hex digits
/// Converts a sequence of bytes to a hex string
/// </summary>
/// <returns>The array as hex string.</returns>
/// <param name="data">The data to convert</param>
/// <returns>The data as a string of hex digits</returns>
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);
}
/// <summary>
/// Converts the given hex string into a byte array
/// Converts a hex string to a byte array
/// </summary>
/// <returns>The string as byte array.</returns>
/// <param name="hex">The hex string</param>
/// <param name="data">A pre-allocated output data array, or null</param>
/// <returns>The byte array</returns>
public static byte[] HexStringAsByteArray(string hex, byte[] data = null)
/// <param name="data">The parsed data</param>
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)
{
@@ -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))
{
+4 -1
View File
@@ -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;
}
+1 -1
View File
@@ -1 +1 @@
http://webserver.codeplex.com/
https://github.com/duplicati/httpserver
Binary file not shown.
-4
View File
@@ -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.
-31
View File
@@ -1,31 +0,0 @@
From 4ef5d02d06c5297469d814462daf6aa449628467 Mon Sep 17 00:00:00 2001
From: Kenneth Skovhede <kenneth@hexad.dk>
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
+2 -2
View File
@@ -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/"
}
-266
View File
@@ -1,266 +0,0 @@
From 4e4239cf74e23e13c3bee808104d8d213e40fe39 Mon Sep 17 00:00:00 2001
From: Kenneth Skovhede <kenneth@hexad.dk>
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 @@
<Compile Include="Sessions\MemorySessionStore.cs" />
<Compile Include="Templates\SmartyEngine.cs" />
<Compile Include="Templates\TemplateEngine.cs" />
+ <Compile Include="HttpUtilityHelper.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
diff --git a/HttpServer/HttpUtilityHelper.cs b/HttpServer/HttpUtilityHelper.cs
new file mode 100644
index 0000000..9f63b1c
--- /dev/null
+++ b/HttpServer/HttpUtilityHelper.cs
@@ -0,0 +1,171 @@
+using System;
+using System.Collections.Specialized;
+
+namespace HttpServer
+{
+ public static class HttpUtilityHelper
+ {
+ /// <summary>
+ /// The regular expression that matches %20 type values in a querystring
+ /// </summary>
+ private static System.Text.RegularExpressions.Regex RE_ESCAPECHAR = new System.Text.RegularExpressions.Regex(@"[^0-9a-zA-Z]", System.Text.RegularExpressions.RegexOptions.Compiled);
+
+ /// <summary>
+ /// Encodes a URL, like System.Web.HttpUtility.UrlEncode
+ /// </summary>
+ /// <returns>The encoded URL</returns>
+ /// <param name="value">The URL fragment to encode</param>
+ /// <param name="encoding">The encoding to use</param>
+ public static string UrlPathEncode(string value, System.Text.Encoding encoding = null)
+ {
+ return UrlEncode(value, encoding, "%20");
+ }
+
+ /// <summary>
+ /// Converts a sequence of bytes to a hex string
+ /// </summary>
+ /// <returns>The array as hex string.</returns>
+ /// <param name="data">The data to convert</param>
+ private static string ByteArrayAsHexString(byte[] data)
+ {
+ return BitConverter.ToString(data).Replace("-", string.Empty);
+ }
+
+ /// <summary>
+ /// Converts a hex string to a byte array
+ /// </summary>
+ /// <returns>The string as byte array.</returns>
+ /// <param name="hex">The hex string</param>
+ /// <param name="data">The parsed data</param>
+ public static byte[] HexStringAsByteArray(string hex, byte[] data)
+ {
+ for (var i = 0; i < hex.Length; i += 2)
+ data[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
+
+ return data;
+ }
+
+ /// <summary>
+ /// Encodes a URL, like System.Web.HttpUtility.UrlEncode
+ /// </summary>
+ /// <returns>The encoded URL</returns>
+ /// <param name="value">The URL fragment to encode</param>
+ /// <param name="encoding">The encoding to use</param>
+ /// <param name="spacevalue">The value to encode a space as</param>
+ public static string UrlEncode(string value, System.Text.Encoding encoding = null, string spacevalue = "+")
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ encoding = encoding ?? System.Text.Encoding.UTF8;
+
+ var encoder = encoding.GetEncoder();
+ var inbuf = new char[1];
+ var outbuf = new byte[2];
+ var shortout = new byte[1];
+
+ return RE_ESCAPECHAR.Replace(value, (m) => {
+ if (m.Value == " ")
+ return spacevalue;
+
+ inbuf[0] = m.Value[0];
+
+ try
+ {
+ var len = encoder.GetBytes(inbuf, 0, 1, outbuf, 0, true);
+ if (len == 1)
+ {
+ shortout[0] = outbuf[0];
+ return "%" + ByteArrayAsHexString(shortout).ToLower();
+ }
+ else if (len == 2)
+ return "%u" + ByteArrayAsHexString(outbuf).ToLower();
+ }
+ catch
+ {
+ }
+
+ //Fallback
+ return m.Value;
+ });
+
+ }
+
+ /// <summary>
+ /// The regular expression that matches %20 type values in a querystring
+ /// </summary>
+ private static System.Text.RegularExpressions.Regex RE_NUMBER = new System.Text.RegularExpressions.Regex(@"(\%(?<number>([0-9]|[a-z]|[A-Z]){2}))|(\+)|(\%u(?<number>([0-9]|[a-z]|[A-Z]){4}))", System.Text.RegularExpressions.RegexOptions.Compiled);
+
+ /// <summary>
+ /// A helper for converting byte arrays to hex, vice versa
+ /// </summary>
+ private const string HEX_DIGITS_UPPER = "0123456789ABCDEF";
+
+ /// <summary>
+ /// Encodes a URL, like System.Web.HttpUtility.UrlEncode
+ /// </summary>
+ /// <returns>The decoded URL</returns>
+ /// <param name="url">The URL fragment to decode</param>
+ /// <param name="encoding">The encoding to use</param>
+ public static string UrlDecode(string value, System.Text.Encoding encoding = null)
+ {
+ if (value == null)
+ throw new ArgumentNullException("value");
+
+ 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) => {
+ if (m.Value == "+")
+ return " ";
+
+ try
+ {
+ var hex = m.Groups["number"].Value;
+ HexStringAsByteArray(hex, inbuf);
+
+ decoder.GetChars(inbuf, 0, hex.Length / 2, outbuf, 0);
+ return outbuf[0].ToString();
+ }
+ catch
+ {
+ }
+
+ //Fallback
+ return m.Value;
+ });
+
+ }
+
+ /// <summary>
+ /// The regular expression that matches a=b type values in a querystring
+ /// </summary>
+ private static System.Text.RegularExpressions.Regex RE_URLPARAM = new System.Text.RegularExpressions.Regex(@"(?<key>[^\=\&]+)(\=(?<value>[^\&]*))?", System.Text.RegularExpressions.RegexOptions.Compiled);
+
+ /// <summary>
+ /// Parses the query string.
+ /// This is a duplicate of the System.Web.HttpUtility.ParseQueryString that does not work well on Mono
+ /// </summary>
+ /// <returns>The parsed query string</returns>
+ /// <param name="query">The query to parse</param>
+ public static NameValueCollection ParseQueryString(string query)
+ {
+ if (query == null)
+ throw new ArgumentNullException("query");
+ if (query.StartsWith("?"))
+ query = query.Substring(1);
+ if (string.IsNullOrEmpty(query))
+ return new NameValueCollection(StringComparer.InvariantCultureIgnoreCase);
+
+ var result = new NameValueCollection(StringComparer.InvariantCultureIgnoreCase);
+ foreach(System.Text.RegularExpressions.Match m in RE_URLPARAM.Matches(query))
+ result.Add(UrlDecode(m.Groups["key"].Value), UrlDecode(m.Groups["value"].Success ? m.Groups["value"].Value : ""));
+
+ return result;
+ }
+ }
+}
+
diff --git a/HttpServer/RequestCookie.cs b/HttpServer/RequestCookie.cs
index 5db5b3e..2deb448 100755
--- a/HttpServer/RequestCookie.cs
+++ b/HttpServer/RequestCookie.cs
@@ -37,7 +37,7 @@ namespace HttpServer
/// <returns>cookie string</returns>
public override string ToString()
{
- return string.Format("{0}={1}; ", HttpUtility.UrlEncode(_name), HttpUtility.UrlEncode(_value));
+ return string.Format("{0}={1}; ", HttpUtilityHelper.UrlEncode(_name), HttpUtilityHelper.UrlEncode(_value));
}
#endregion
diff --git a/HttpServer/ResponseCookie.cs b/HttpServer/ResponseCookie.cs
index 53c38aa..8fddee6 100755
--- a/HttpServer/ResponseCookie.cs
+++ b/HttpServer/ResponseCookie.cs
@@ -70,7 +70,7 @@ namespace HttpServer
/// <returns>cookie string</returns>
public override string ToString()
{
- string temp = string.Format("{0}={1}; ", HttpUtility.UrlEncode(Name), HttpUtility.UrlEncode(Value));
+ string temp = string.Format("{0}={1}; ", HttpUtilityHelper.UrlEncode(Name), HttpUtilityHelper.UrlEncode(Value));
if (_persistant)
{
// Fixed by Albert, Team MediaPortal
--
1.8.4.2
-196
View File
@@ -1,196 +0,0 @@
From 5632607b6b15623849efb64ac2e93a62766c6ff3 Mon Sep 17 00:00:00 2001
From: Kenneth Skovhede <kenneth@hexad.dk>
Date: Wed, 23 Jul 2014 15:03:38 +0200
Subject: [PATCH] Changed to use Duplicati key-file for signing
---
HttpServer.sln | 10 +++++-----
HttpServer/Duplicati.snk | Bin 0 -> 596 bytes
HttpServer/HttpServer.csproj | 21 +++++++++++----------
HttpServer/httpserver.pfx | Bin 1756 -> 0 bytes
HttpServer/test.snk | Bin 596 -> 0 bytes
5 files changed, 16 insertions(+), 15 deletions(-)
create mode 100644 HttpServer/Duplicati.snk
mode change 100755 => 100644 HttpServer/HttpServer.csproj
delete mode 100755 HttpServer/httpserver.pfx
delete mode 100755 HttpServer/test.snk
diff --git a/HttpServer.sln b/HttpServer.sln
index c725924..a398e46 100644
--- a/HttpServer.sln
+++ b/HttpServer.sln
@@ -1,6 +1,6 @@

-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual Studio 2008
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual C# Express 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HttpServer", "HttpServer\HttpServer.csproj", "{455E7D70-1C85-4D7F-9F01-DC801B8B8C34}"
EndProject
Global
@@ -17,10 +17,10 @@ Global
{455E7D70-1C85-4D7F-9F01-DC801B8B8C34}.Test|Any CPU.ActiveCfg = Test|Any CPU
{455E7D70-1C85-4D7F-9F01-DC801B8B8C34}.Test|Any CPU.Build.0 = Test|Any CPU
EndGlobalSection
- GlobalSection(MonoDevelopProperties) = preSolution
- StartupItem = HttpServer\HttpServer.csproj
- EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(MonoDevelopProperties) = preSolution
+ StartupItem = HttpServer\HttpServer.csproj
+ EndGlobalSection
EndGlobal
diff --git a/HttpServer/Duplicati.snk b/HttpServer/Duplicati.snk
new file mode 100644
index 0000000000000000000000000000000000000000..e0c1e2dd86119728adaeefc5f14f2e597dabceeb
GIT binary patch
literal 596
zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50098e&YbeASI`aP2sa|^c*=Vgk~YB=15kLM
z6B<YiWvwUE<(|pH%%wkswD9()^!1)?2<TO8%B4*tiA_O)JKtg3mYe#cEJRtAufRSd
zp*O}dkA17H>le7?%rzf5lQi@8^2-|;@G9`<QW0-U-++qMA2UFqpl}*gRm+5<rR$#Y
z`mC{oH`rBPm}y-b_=)eQ2xg6URklBIbvh;{sNYL`<5N!9%-k?#uBsQ+{OJEkI<Qwb
z$|So|iI{;k686jCQ4Xb|;Kg7tg$P&|hZ52cQ8GHhE-`7YH<B}PJcp9|;2l9FD)bZm
zXJ`R;(~ORzX0|XIrrQe+4<giBvUkU^;DeIXTj(<Trrrjq61ReBH|bqmNj^sJ@e7zu
z3qYe`6@Gbj2toJ^pr#9(UP@|$CVA3uW~aDv8qPOSV(0-u0WeznB_NK-10qV7)e?Z|
z@pRLiRcQW<BjMtoX%$E@W{Zn5E@K|AID>V-z=FMF_PcZSs*&!F`tUQUDaR;O!QV57
zcL#UCLy6{4TM42#Sq8wU(0JEJwaKaO08k_-0(e*zaa9dM^Ns<3pXG+PwGl!LEd7mN
zppXdDRR2f;AT-tHwTXQzHH^`&uIWnZ%w;A3xd8awj#n6GqmX}=Pk0ssHUW#6fQ#+z
z_S|XnhcE>JGe7M>W()k5s}qyKQA=h=DrsUx<aA#JIm;D(`F7OE$J+;dTnocY;8v;M
i+Wck*xKNK{xU`2iSPLjN<SzIp{9kbAxOXkZB3*11JsH9P
literal 0
HcmV?d00001
diff --git a/HttpServer/HttpServer.csproj b/HttpServer/HttpServer.csproj
old mode 100755
new mode 100644
index 576e62a..81bb2eb
--- a/HttpServer/HttpServer.csproj
+++ b/HttpServer/HttpServer.csproj
@@ -1,23 +1,23 @@
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="2.0">
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ProductVersion>9.0.30729</ProductVersion>
+ <ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{455E7D70-1C85-4D7F-9F01-DC801B8B8C34}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>HttpServer</RootNamespace>
<AssemblyName>HttpServer</AssemblyName>
- <StartupObject>
- </StartupObject>
<SignAssembly>true</SignAssembly>
- <AssemblyOriginatorKeyFile>test.snk</AssemblyOriginatorKeyFile>
+ <AssemblyOriginatorKeyFile>Duplicati.snk</AssemblyOriginatorKeyFile>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
- <OldToolsVersion>2.0</OldToolsVersion>
+ <OldToolsVersion>3.5</OldToolsVersion>
+ <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -46,6 +46,8 @@
<DebugType>full</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <Optimize>false</Optimize>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
@@ -133,10 +135,6 @@
<Compile Include="Templates\SmartyEngine.cs" />
<Compile Include="Templates\TemplateEngine.cs" />
</ItemGroup>
- <ItemGroup>
- <None Include="httpserver.pfx" />
- <None Include="test.snk" />
- </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
@@ -145,4 +143,7 @@
<Target Name="AfterBuild">
</Target>
-->
+ <ItemGroup>
+ <None Include="Duplicati.snk" />
+ </ItemGroup>
</Project>
\ 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
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
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}+4OdXNRIo<d9Psku(J*E_#SphiN7^Uo}%XJej*FLvAz~w@6Ba=e$`J_&=(mOtw
z`_j<^FX;6A5~lOzA??rdf9H|oGE}qP%M{roR}vb-PiO8rA-NWirc`DaVe&@lqt6M0
zNYTev1im3KTiiGLf_?ECRq8OoNM+0oKL+y@NhJxZ&|w*?*^T!;j>ng?<<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%<cUXT9{m^1JbQUGTQkK}SAHIt
zuVP~u36&u3fOR<Ec(#28TfDQ!b+a|eFU2`@f4)(wJ=UfqtnhiWMfz%!2n&+JO=N=4
zRsK9!_0wHJqo`jldFP~oDN-(;rSGAEZ_fU(hUt$Zf%3o7<{(V?N>g3NUhR!8qA0#}
zSJY#IGkNY<GBvgO-4-YSKpvY^NzV=oMVg+V=>v4L$XLA)9v59%3fY#qPdXYvdKy)H
iTkg*w>*3ZPja^HsjVZRb<eow3IYN|8+vu9umTNsdQXNqM
--
1.8.4.2
-70
View File
@@ -1,70 +0,0 @@
From e7be6967b6d14b5cca67018dd1a30e4fc302001a Mon Sep 17 00:00:00 2001
From: Kenneth Skovhede <kenneth@hexad.dk>
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
/// </summary>
public const string FormData = "form-data";
+
+ /// <summary>
+ /// Gets the temp folder used to store multi-part uploads
+ /// </summary>
+ public static readonly string Tempfolder = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "HttpServer");
+
#region IFormDecoder Members
/// <summary>
@@ -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<IHttpContextFactory>(new HttpContextFactory(LogWriter, 16384,
_components.Get<IRequestParserFactory>()));
- // 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
-92
View File
@@ -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<string, HttpFile> _files = new Dictionary<string, HttpFile>();
+
+ // A lock to prevent concurrent access to the _files dict
+ private object _lock = new object();
/// <summary>Initializes a form container with the specified name</summary>
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);
}
/// <summary>
@@ -72,16 +76,19 @@
/// <exception cref="ArgumentNullException">If name is null or empty</exception>
/// <exception cref="InvalidOperationException">If the instance is HttpForm.EmptyForm which cannot be modified</exception>
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];
+ }
}
/// <summary>
@@ -95,10 +102,13 @@
if (_files.Count == 0)
return EmptyFileCollection;
- List<HttpFile> files = new List<HttpFile>();
- foreach (HttpFile file in _files.Values)
- files.Add(file);
- return files.AsReadOnly();
+ lock(_lock)
+ {
+ List<HttpFile> files = new List<HttpFile>();
+ foreach(HttpFile file in _files.Values)
+ files.Add(file);
+ return files.AsReadOnly();
+ }
}
}
@@ -106,13 +116,16 @@
/// <summary>Disposes all held HttpFile's and resets values</summary>
public override void Clear()
- {
- base.Clear();
+ {
+ base.Clear();
- foreach (KeyValuePair<string, HttpFile> pair in _files)
- pair.Value.Dispose();
+ lock(_lock)
+ {
+ foreach(KeyValuePair<string, HttpFile> pair in _files)
+ pair.Value.Dispose();
- _files.Clear();
+ _files.Clear();
+ }
}
}
}