From: <ge...@us...> - 2009-10-02 16:57:48
|
Revision: 3101 http://mp-plugins.svn.sourceforge.net/mp-plugins/?rev=3101&view=rev Author: gemx Date: 2009-10-02 16:57:37 +0000 (Fri, 02 Oct 2009) Log Message: ----------- Initial commit Added Paths: ----------- trunk/plugins/MediaPortal WebServices/ trunk/plugins/MediaPortal WebServices/MediaPortalWebServices.sln trunk/plugins/MediaPortal WebServices/MiniWebServer/ trunk/plugins/MediaPortal WebServices/MiniWebServer/ByteParser.cs trunk/plugins/MediaPortal WebServices/MiniWebServer/ByteString.cs trunk/plugins/MediaPortal WebServices/MiniWebServer/Connection.cs trunk/plugins/MediaPortal WebServices/MiniWebServer/Host.cs trunk/plugins/MediaPortal WebServices/MiniWebServer/Messages.cs trunk/plugins/MediaPortal WebServices/MiniWebServer/MiniWebServer.csproj trunk/plugins/MediaPortal WebServices/MiniWebServer/Properties/ trunk/plugins/MediaPortal WebServices/MiniWebServer/Properties/AssemblyInfo.cs trunk/plugins/MediaPortal WebServices/MiniWebServer/Request.cs trunk/plugins/MediaPortal WebServices/MiniWebServer/Server.cs trunk/plugins/MediaPortal WebServices/MiniWebServer/bin/ trunk/plugins/MediaPortal WebServices/MiniWebServer/bin/Debug/ trunk/plugins/MediaPortal WebServices/WebApp/ trunk/plugins/MediaPortal WebServices/WebApp/App_Code/ trunk/plugins/MediaPortal WebServices/WebApp/App_Code/BasicStream.cs trunk/plugins/MediaPortal WebServices/WebApp/App_Code/CRCTool.cs trunk/plugins/MediaPortal WebServices/WebApp/App_Code/Classes.cs trunk/plugins/MediaPortal WebServices/WebApp/App_Code/EncoderConfig.cs trunk/plugins/MediaPortal WebServices/WebApp/App_Code/EncoderWrapper.cs trunk/plugins/MediaPortal WebServices/WebApp/App_Code/NamedPipe.cs trunk/plugins/MediaPortal WebServices/WebApp/App_Code/State.cs trunk/plugins/MediaPortal WebServices/WebApp/App_Code/TransportMethod.cs trunk/plugins/MediaPortal WebServices/WebApp/App_Code/TransportStream.cs trunk/plugins/MediaPortal WebServices/WebApp/App_Code/TsBuffer.cs trunk/plugins/MediaPortal WebServices/WebApp/App_Code/TvServiceWebServices.asmx.cs trunk/plugins/MediaPortal WebServices/WebApp/App_Code/Utils.cs trunk/plugins/MediaPortal WebServices/WebApp/App_Data/ trunk/plugins/MediaPortal WebServices/WebApp/Bin/ trunk/plugins/MediaPortal WebServices/WebApp/Bin/DirectShowLib.dll trunk/plugins/MediaPortal WebServices/WebApp/Bin/DirectShowLib.dll.refresh trunk/plugins/MediaPortal WebServices/WebApp/Bin/DirectShowLib.pdb trunk/plugins/MediaPortal WebServices/WebApp/Bin/Gentle.Common.dll trunk/plugins/MediaPortal WebServices/WebApp/Bin/Gentle.Common.dll.refresh trunk/plugins/MediaPortal WebServices/WebApp/Bin/Gentle.Framework.dll trunk/plugins/MediaPortal WebServices/WebApp/Bin/Gentle.Framework.dll.refresh trunk/plugins/MediaPortal WebServices/WebApp/Bin/Gentle.Provider.MySQL.dll trunk/plugins/MediaPortal WebServices/WebApp/Bin/Gentle.Provider.MySQL.dll.refresh trunk/plugins/MediaPortal WebServices/WebApp/Bin/Gentle.Provider.SQLServer.dll trunk/plugins/MediaPortal WebServices/WebApp/Bin/Gentle.Provider.SQLServer.dll.refresh trunk/plugins/MediaPortal WebServices/WebApp/Bin/MySql.Data.dll trunk/plugins/MediaPortal WebServices/WebApp/Bin/MySql.Data.dll.refresh trunk/plugins/MediaPortal WebServices/WebApp/Bin/System.Data.SQLite.dll trunk/plugins/MediaPortal WebServices/WebApp/Bin/System.Data.SQLite.dll.refresh trunk/plugins/MediaPortal WebServices/WebApp/Bin/System.Data.SQLite.xml trunk/plugins/MediaPortal WebServices/WebApp/Bin/TVDatabase.dll trunk/plugins/MediaPortal WebServices/WebApp/Bin/TVDatabase.dll.refresh trunk/plugins/MediaPortal WebServices/WebApp/Bin/TVDatabase.pdb trunk/plugins/MediaPortal WebServices/WebApp/Bin/TvBusinessLayer.dll trunk/plugins/MediaPortal WebServices/WebApp/Bin/TvBusinessLayer.dll.refresh trunk/plugins/MediaPortal WebServices/WebApp/Bin/TvBusinessLayer.pdb trunk/plugins/MediaPortal WebServices/WebApp/Bin/TvControl.dll trunk/plugins/MediaPortal WebServices/WebApp/Bin/TvControl.dll.refresh trunk/plugins/MediaPortal WebServices/WebApp/Bin/TvControl.pdb trunk/plugins/MediaPortal WebServices/WebApp/Bin/TvControl.xml trunk/plugins/MediaPortal WebServices/WebApp/Bin/TvLibrary.Interfaces.dll trunk/plugins/MediaPortal WebServices/WebApp/Bin/TvLibrary.Interfaces.dll.refresh trunk/plugins/MediaPortal WebServices/WebApp/Bin/TvLibrary.Interfaces.pdb trunk/plugins/MediaPortal WebServices/WebApp/Bin/TvLibrary.Interfaces.xml trunk/plugins/MediaPortal WebServices/WebApp/Bin/log4net.dll trunk/plugins/MediaPortal WebServices/WebApp/Bin/log4net.dll.refresh trunk/plugins/MediaPortal WebServices/WebApp/ChannelEPG.aspx trunk/plugins/MediaPortal WebServices/WebApp/ChannelEPG.aspx.cs trunk/plugins/MediaPortal WebServices/WebApp/Default.aspx trunk/plugins/MediaPortal WebServices/WebApp/Default.aspx.cs trunk/plugins/MediaPortal WebServices/WebApp/Gentle.config trunk/plugins/MediaPortal WebServices/WebApp/PictureStreamer.aspx trunk/plugins/MediaPortal WebServices/WebApp/PictureStreamer.aspx.cs trunk/plugins/MediaPortal WebServices/WebApp/PictureViewer.aspx trunk/plugins/MediaPortal WebServices/WebApp/PictureViewer.aspx.cs trunk/plugins/MediaPortal WebServices/WebApp/ScheduleEditor.aspx trunk/plugins/MediaPortal WebServices/WebApp/ScheduleEditor.aspx.cs trunk/plugins/MediaPortal WebServices/WebApp/Streamer.aspx trunk/plugins/MediaPortal WebServices/WebApp/Streamer.aspx.cs trunk/plugins/MediaPortal WebServices/WebApp/TvServerStatus.aspx trunk/plugins/MediaPortal WebServices/WebApp/TvServerStatus.aspx.cs trunk/plugins/MediaPortal WebServices/WebApp/TvServiceWebServices.asmx trunk/plugins/MediaPortal WebServices/WebApp/Web.config trunk/plugins/MediaPortal WebServices/WebApp/Web.config.org trunk/plugins/MediaPortal WebServices/WebApp/config.xml trunk/plugins/MediaPortal WebServices/WebApp/pics/ trunk/plugins/MediaPortal WebServices/WebApp/pics/btnDelete.gif trunk/plugins/MediaPortal WebServices/WebApp/pics/btnEdit.gif trunk/plugins/MediaPortal WebServices/WebApp/pics/play_enabled.gif trunk/plugins/MediaPortal WebServices/WebApp/pics/rec.gif trunk/plugins/MediaPortal WebServices/WebServerHost/ trunk/plugins/MediaPortal WebServices/WebServerHost/EncoderConfig.cs trunk/plugins/MediaPortal WebServices/WebServerHost/Program.cs trunk/plugins/MediaPortal WebServices/WebServerHost/Properties/ trunk/plugins/MediaPortal WebServices/WebServerHost/Properties/AssemblyInfo.cs trunk/plugins/MediaPortal WebServices/WebServerHost/Properties/Resources.Designer.cs trunk/plugins/MediaPortal WebServices/WebServerHost/Properties/Resources.resx trunk/plugins/MediaPortal WebServices/WebServerHost/Properties/Settings.Designer.cs trunk/plugins/MediaPortal WebServices/WebServerHost/Properties/Settings.settings trunk/plugins/MediaPortal WebServices/WebServerHost/TransportMethod.cs trunk/plugins/MediaPortal WebServices/WebServerHost/WebServerHost.csproj trunk/plugins/MediaPortal WebServices/WebServerHost/bin/ trunk/plugins/MediaPortal WebServices/WebServerHost/bin/Debug/ trunk/plugins/MediaPortal WebServices/WebServerHost/frmMain.Designer.cs trunk/plugins/MediaPortal WebServices/WebServerHost/frmMain.cs trunk/plugins/MediaPortal WebServices/WebServerHost/frmMain.resx Added: trunk/plugins/MediaPortal WebServices/MediaPortalWebServices.sln =================================================================== --- trunk/plugins/MediaPortal WebServices/MediaPortalWebServices.sln (rev 0) +++ trunk/plugins/MediaPortal WebServices/MediaPortalWebServices.sln 2009-10-02 16:57:37 UTC (rev 3101) @@ -0,0 +1,73 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "WebApp", "WebApp\", "{959D3D07-D4EA-4E74-AF77-2E15A1D760E5}" + ProjectSection(WebsiteProperties) = preProject + TargetFramework = "3.5" + Debug.AspNetCompiler.VirtualPath = "/WebApp" + Debug.AspNetCompiler.PhysicalPath = "WebApp" + Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\WebApp\" + Debug.AspNetCompiler.Updateable = "true" + Debug.AspNetCompiler.ForceOverwrite = "true" + Debug.AspNetCompiler.FixedNames = "false" + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.VirtualPath = "/WebApp" + Release.AspNetCompiler.PhysicalPath = "WebApp" + Release.AspNetCompiler.TargetPath = "PrecompiledWeb\WebApp\" + Release.AspNetCompiler.Updateable = "true" + Release.AspNetCompiler.ForceOverwrite = "true" + Release.AspNetCompiler.FixedNames = "false" + Release.AspNetCompiler.Debug = "False" + VWDPort = "1902" + DefaultWebSiteLanguage = "Visual C#" + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MiniWebServer", "MiniWebServer\MiniWebServer.csproj", "{AC169225-21E5-4375-A21D-A3779512A26C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebServerHost", "WebServerHost\WebServerHost.csproj", "{CB4CBCC4-8A35-42BB-88F9-C15036805EB9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|.NET = Debug|.NET + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Release|.NET = Release|.NET + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {959D3D07-D4EA-4E74-AF77-2E15A1D760E5}.Debug|.NET.ActiveCfg = Debug|.NET + {959D3D07-D4EA-4E74-AF77-2E15A1D760E5}.Debug|.NET.Build.0 = Debug|.NET + {959D3D07-D4EA-4E74-AF77-2E15A1D760E5}.Debug|Any CPU.ActiveCfg = Debug|.NET + {959D3D07-D4EA-4E74-AF77-2E15A1D760E5}.Debug|Mixed Platforms.ActiveCfg = Debug|.NET + {959D3D07-D4EA-4E74-AF77-2E15A1D760E5}.Debug|Mixed Platforms.Build.0 = Debug|.NET + {959D3D07-D4EA-4E74-AF77-2E15A1D760E5}.Release|.NET.ActiveCfg = Debug|.NET + {959D3D07-D4EA-4E74-AF77-2E15A1D760E5}.Release|.NET.Build.0 = Debug|.NET + {959D3D07-D4EA-4E74-AF77-2E15A1D760E5}.Release|Any CPU.ActiveCfg = Debug|.NET + {959D3D07-D4EA-4E74-AF77-2E15A1D760E5}.Release|Mixed Platforms.ActiveCfg = Debug|.NET + {959D3D07-D4EA-4E74-AF77-2E15A1D760E5}.Release|Mixed Platforms.Build.0 = Debug|.NET + {AC169225-21E5-4375-A21D-A3779512A26C}.Debug|.NET.ActiveCfg = Debug|Any CPU + {AC169225-21E5-4375-A21D-A3779512A26C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AC169225-21E5-4375-A21D-A3779512A26C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AC169225-21E5-4375-A21D-A3779512A26C}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {AC169225-21E5-4375-A21D-A3779512A26C}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {AC169225-21E5-4375-A21D-A3779512A26C}.Release|.NET.ActiveCfg = Release|Any CPU + {AC169225-21E5-4375-A21D-A3779512A26C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AC169225-21E5-4375-A21D-A3779512A26C}.Release|Any CPU.Build.0 = Release|Any CPU + {AC169225-21E5-4375-A21D-A3779512A26C}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {AC169225-21E5-4375-A21D-A3779512A26C}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {CB4CBCC4-8A35-42BB-88F9-C15036805EB9}.Debug|.NET.ActiveCfg = Debug|Any CPU + {CB4CBCC4-8A35-42BB-88F9-C15036805EB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CB4CBCC4-8A35-42BB-88F9-C15036805EB9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CB4CBCC4-8A35-42BB-88F9-C15036805EB9}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {CB4CBCC4-8A35-42BB-88F9-C15036805EB9}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {CB4CBCC4-8A35-42BB-88F9-C15036805EB9}.Release|.NET.ActiveCfg = Release|Any CPU + {CB4CBCC4-8A35-42BB-88F9-C15036805EB9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CB4CBCC4-8A35-42BB-88F9-C15036805EB9}.Release|Any CPU.Build.0 = Release|Any CPU + {CB4CBCC4-8A35-42BB-88F9-C15036805EB9}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {CB4CBCC4-8A35-42BB-88F9-C15036805EB9}.Release|Mixed Platforms.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal Added: trunk/plugins/MediaPortal WebServices/MiniWebServer/ByteParser.cs =================================================================== --- trunk/plugins/MediaPortal WebServices/MiniWebServer/ByteParser.cs (rev 0) +++ trunk/plugins/MediaPortal WebServices/MiniWebServer/ByteParser.cs 2009-10-02 16:57:37 UTC (rev 3101) @@ -0,0 +1,56 @@ +/*======================================================================= +\xA0 Copyright (C) Microsoft Corporation.\xA0 All rights reserved. +\xA0 + THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A + PARTICULAR PURPOSE. +=======================================================================*/ + +namespace Cassini { + using System; + using System.Collections; + using System.Text; + + // + // Helper class to parse a byte array into lines without converting to strings + // + internal class ByteParser { + private byte[] _bytes; + private int _pos; + + public ByteParser(byte[] bytes) { + _bytes = bytes; + _pos = 0; + } + + public int CurrentOffset { + get { + return _pos; + } + } + + public ByteString ReadLine() { + ByteString line = null; + + for (int i = _pos; i < _bytes.Length; i++) { + if (_bytes[i] == (byte)'\n') { + int len = i-_pos; + if (len > 0 && _bytes[i-1] == (byte)'\r') + len--; + + line = new ByteString(_bytes, _pos, len); + _pos = i+1; + return line; + } + } + + if (_pos < _bytes.Length) + line = new ByteString(_bytes, _pos, _bytes.Length-_pos); + + _pos = _bytes.Length; + return line; + } + + } +} Added: trunk/plugins/MediaPortal WebServices/MiniWebServer/ByteString.cs =================================================================== --- trunk/plugins/MediaPortal WebServices/MiniWebServer/ByteString.cs (rev 0) +++ trunk/plugins/MediaPortal WebServices/MiniWebServer/ByteString.cs 2009-10-02 16:57:37 UTC (rev 3101) @@ -0,0 +1,128 @@ +/*======================================================================= +\xA0 Copyright (C) Microsoft Corporation.\xA0 All rights reserved. +\xA0 + THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A + PARTICULAR PURPOSE. +=======================================================================*/ + +namespace Cassini { + using System; + using System.Collections; + using System.Text; + + // + // Helper class to expose string-like functionality on top + // of a byte array. Used in parsing of HTTP requests. + // + internal class ByteString { + private byte[] _bytes; + private int _offset; + private int _length; + + public ByteString(byte[] bytes, int offset, int length) { + _bytes = bytes; + _offset = offset; + _length = length; + } + + public byte[] Bytes { + get { + return _bytes; + } + } + + public bool IsEmpty { + get { + return (_bytes == null || _length == 0); + } + } + + public int Length { + get { + return _length; + } + } + + public int Offset { + get { + return _offset; + } + } + + public byte this[int index] { + get { + return _bytes[_offset+index]; + } + } + + public String GetString() { + return GetString(Encoding.UTF8); + } + + public String GetString(Encoding enc) { + if (IsEmpty) + return String.Empty; + return enc.GetString(_bytes, _offset, _length); + } + + public byte[] GetBytes() { + byte[] bytes = new byte[_length]; + if (_length > 0) + Buffer.BlockCopy(_bytes, _offset, bytes, 0, _length); + return bytes; + } + + public int IndexOf(char ch) { + return IndexOf(ch, 0); + } + + public int IndexOf(char ch, int offset) { + for (int i = offset; i < _length; i++) { + if (this[i] == (byte)ch) + return i; + } + + return -1; + } + + public ByteString Substring(int offset) { + return Substring(offset, _length-offset); + } + + public ByteString Substring(int offset, int len) { + return new ByteString(_bytes, _offset+offset, len); + } + + public ByteString[] Split(char sep) { + ArrayList list = new ArrayList(); + + int pos = 0; + + while (pos < _length) { + int i = IndexOf(sep, pos); + + if (i < 0) + break; + + list.Add(Substring(pos, i-pos)); + pos = i+1; + + while (this[pos] == (byte)sep && pos < _length) + pos++; + } + + if (pos < _length) + list.Add(Substring(pos)); + + int n = list.Count; + ByteString[] result = new ByteString[n]; + + for (int i = 0; i < n; i++) + result[i] = (ByteString)list[i]; + + return result; + } + } +} Added: trunk/plugins/MediaPortal WebServices/MiniWebServer/Connection.cs =================================================================== --- trunk/plugins/MediaPortal WebServices/MiniWebServer/Connection.cs (rev 0) +++ trunk/plugins/MediaPortal WebServices/MiniWebServer/Connection.cs 2009-10-02 16:57:37 UTC (rev 3101) @@ -0,0 +1,240 @@ +/*======================================================================= +\xA0 Copyright (C) Microsoft Corporation.\xA0 All rights reserved. +\xA0 + THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A + PARTICULAR PURPOSE. +=======================================================================*/ + +namespace Cassini { + using System; + using System.Collections; + using System.Globalization; + using System.IO; + using System.Net; + using System.Net.Sockets; + using System.Text; + using System.Threading; + using System.Web; + using System.Web.Hosting; + + // + // Internal class to handle HTTP connections using System.Net + // + internal class Connection { + private Host _host; + private Socket _socket; + + public Connection(Host host, Socket socket) { + _host = host; + _socket = socket; + } + + public bool Connected { + get { return _socket.Connected; } + } + + public String LocalIP { + get { + IPEndPoint endPoint = (IPEndPoint)_socket.LocalEndPoint; + if (endPoint != null && endPoint.Address != null) + return endPoint.Address.ToString(); + else + return "127.0.0.1"; + } + } + + public String RemoteIP { + get { + IPEndPoint endPoint = (IPEndPoint)_socket.RemoteEndPoint; + if (endPoint != null && endPoint.Address != null) + return endPoint.Address.ToString(); + else + return "127.0.0.1"; + } + } + + public bool IsLocal { + get { + return (LocalIP == RemoteIP); + } + } + + public void Close() { + try { + _socket.Shutdown(SocketShutdown.Both); + _socket.Close(); + } + catch { + } + finally { + _socket = null; + } + } + + private static String MakeResponseHeaders(int statusCode, String moreHeaders, int contentLength, bool keepAlive) { + StringBuilder sb = new StringBuilder(); + sb.Append("HTTP/1.1 " + statusCode + " " + HttpWorkerRequest.GetStatusDescription(statusCode) + "\r\n"); + sb.Append("Server: Microsoft-Cassini/"+Messages.VersionString+"\r\n"); + sb.Append("Date: " + DateTime.Now.ToUniversalTime().ToString("R", DateTimeFormatInfo.InvariantInfo) + "\r\n"); + if (contentLength >= 0) + sb.Append("Content-Length: " + contentLength + "\r\n"); + if (moreHeaders != null) + sb.Append(moreHeaders); + if (!keepAlive) + sb.Append("Connection: Close\r\n"); + sb.Append("\r\n"); + return sb.ToString(); + } + + private static String MakeContentTypeHeader(String fileName) { + String contentType = null; + + int lastDot = fileName.LastIndexOf('.'); + + if (lastDot >= 0) { + switch (fileName.Substring(lastDot)) { + case ".js": contentType = "application/x-javascript"; break; + case ".gif": contentType = "image/gif"; break; + case ".jpg": contentType = "image/jpeg"; break; + } + } + + if (contentType == null) + return null; + + return "Content-Type: " + contentType + "\r\n"; + } + + public void ProcessOneRequest() { + // wait for at least some input + if (WaitForRequestBytes() == 0) { + WriteErrorAndClose(400); + return; + } + + Request request = new Request(_host, this); + request.Process(); + } + + public byte[] ReadRequestBytes(int maxBytes) { + try { + if (WaitForRequestBytes() == 0) + return null; + + int numBytes = _socket.Available; + if (numBytes > maxBytes) + numBytes = maxBytes; + + int numReceived = 0; + byte[] buffer = new byte[numBytes]; + + if (numBytes > 0) { + numReceived = _socket.Receive(buffer, 0, numBytes, SocketFlags.None); + } + + if (numReceived < numBytes) { + byte[] tempBuffer = new byte[numReceived]; + + if (numReceived > 0) { + Buffer.BlockCopy(buffer, 0, tempBuffer, 0, numReceived); + } + + buffer = tempBuffer; + } + + return buffer; + } + catch { + return null; + } + } + + public void Write100Continue() { + WriteEntireResponseFromString(100, null, null, true); + } + + public void WriteBody(byte[] data, int offset, int length) { + _socket.Send(data, offset, length, SocketFlags.None); + } + + public void WriteEntireResponseFromString(int statusCode, String extraHeaders, String body, bool keepAlive) { + try { + int bodyLength = (body != null) ? Encoding.UTF8.GetByteCount(body) : 0; + String headers = MakeResponseHeaders(statusCode, extraHeaders, bodyLength, keepAlive); + _socket.Send(Encoding.UTF8.GetBytes(headers + body)); + } + finally { + if (!keepAlive) + Close(); + } + } + + public void WriteEntireResponseFromFile(String fileName, bool keepAlive) { + if (!File.Exists(fileName)) { + WriteErrorAndClose(404); + return; + } + + bool completed = false; + FileStream fs = null; + + try { + fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read); + int len = (int)fs.Length; + byte[] fileBytes = new byte[len]; + int bytesRead = fs.Read(fileBytes, 0, len); + + String headers = MakeResponseHeaders(200, MakeContentTypeHeader(fileName), bytesRead, keepAlive); + _socket.Send(Encoding.UTF8.GetBytes(headers)); + + _socket.Send(fileBytes, 0, bytesRead, SocketFlags.None); + + completed = true; + } + finally { + if (!keepAlive || !completed) + Close(); + + if (fs != null) + fs.Close(); + } + } + + public void WriteErrorAndClose(int statusCode, string message) { + String body = Messages.FormatErrorMessageBody(statusCode, _host.VirtualPath); + if (message != null && message.Length > 0) + body += "\r\n<!--\r\n" + message + "\r\n-->"; + WriteEntireResponseFromString(statusCode, null, body, false); + } + + public void WriteErrorAndClose(int statusCode) { + WriteErrorAndClose(statusCode, null); + } + + private int WaitForRequestBytes() { + int availBytes = 0; + + try { + if (_socket.Available == 0) { + // poll until there is data + _socket.Poll(100000 /* 100ms */, SelectMode.SelectRead); + if (_socket.Available == 0 && _socket.Connected) + _socket.Poll(10000000 /* 10sec */, SelectMode.SelectRead); + } + + availBytes = _socket.Available; + } + catch { + } + + return availBytes; + } + + public void WriteHeaders(int statusCode, String extraHeaders) { + String headers = MakeResponseHeaders(statusCode, extraHeaders, -1, false); + _socket.Send(Encoding.UTF8.GetBytes(headers)); + } + } +} Added: trunk/plugins/MediaPortal WebServices/MiniWebServer/Host.cs =================================================================== --- trunk/plugins/MediaPortal WebServices/MiniWebServer/Host.cs (rev 0) +++ trunk/plugins/MediaPortal WebServices/MiniWebServer/Host.cs 2009-10-02 16:57:37 UTC (rev 3101) @@ -0,0 +1,227 @@ +/*======================================================================= +\xA0 Copyright (C) Microsoft Corporation.\xA0 All rights reserved. +\xA0 + THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A + PARTICULAR PURPOSE. +=======================================================================*/ + +namespace Cassini { + using System; + using System.Collections; + using System.Diagnostics; + using System.Globalization; + using System.IO; + using System.Net; + using System.Net.Sockets; + using System.Text; + using System.Threading; + using System.Web; + using System.Web.Hosting; + + // + // Instances of an internal Host class are created in the App Domain + // processing HTTP request. Typeof(Host) is passed to CreateApplicationHost() + // + // Host uses System.Net to listen to the configured port and accept + // incoming HTTP connections. + // + internal class Host : MarshalByRefObject { + private bool _started; + private bool _stopped; + + private Server _server; + + private int _port; + private String _virtualPath; + private String _lowerCasedVirtualPath; + private String _lowerCasedVirtualPathWithTrailingSlash; + private String _physicalPath; + private String _installPath; + private String _physicalClientScriptPath; + private String _lowerCasedClientScriptPathWithTrailingSlashV10; + private String _lowerCasedClientScriptPathWithTrailingSlashV11; + + private Socket _socket; + + private WaitCallback _onStart; + private WaitCallback _onSocketAccept; + private EventHandler _onAppDomainUnload; + + public override Object InitializeLifetimeService() { + return null; // never expire lease + } + + public void Configure(Server server, int port, String virtualPath, String physicalPath, String installPath) { + _server = server; + + _port = port; + _virtualPath = virtualPath; + _lowerCasedVirtualPath = CultureInfo.InvariantCulture.TextInfo.ToLower(_virtualPath); + _lowerCasedVirtualPathWithTrailingSlash = virtualPath.EndsWith("/") ? virtualPath : virtualPath + "/"; + _lowerCasedVirtualPathWithTrailingSlash = CultureInfo.InvariantCulture.TextInfo.ToLower(_lowerCasedVirtualPathWithTrailingSlash); + _physicalPath = physicalPath; + _installPath = installPath; + _physicalClientScriptPath = installPath + "\\asp.netclientfiles\\"; + + String version4 = FileVersionInfo.GetVersionInfo(typeof(HttpRuntime).Module.FullyQualifiedName).FileVersion; + String version3 = version4.Substring(0, version4.LastIndexOf('.')); + _lowerCasedClientScriptPathWithTrailingSlashV10 = "/aspnet_client/system_web/" + version4.Replace('.', '_') + "/"; + _lowerCasedClientScriptPathWithTrailingSlashV11 = "/aspnet_client/system_web/" + version3.Replace('.', '_') + "/"; + + _onSocketAccept = new WaitCallback(OnSocketAccept); + _onStart = new WaitCallback(OnStart); + + // start watching for app domain unloading + _onAppDomainUnload = new EventHandler(OnAppDomainUnload); + Thread.GetDomain().DomainUnload += _onAppDomainUnload; + } + + public String NormalizedVirtualPath { + get { return _lowerCasedVirtualPathWithTrailingSlash; } + } + + public String PhysicalPath { + get { return _physicalPath; } + } + + public String InstallPath { + get { return _installPath; } + } + + public String PhysicalClientScriptPath { + get { return _physicalClientScriptPath; } + } + + public int Port { + get { return _port; } + } + + public String VirtualPath { + get { return _virtualPath; } + } + + public bool IsVirtualPathInApp(String path) { + bool isClientScriptPath; + String clientScript; + return IsVirtualPathInApp(path, out isClientScriptPath, out clientScript); + } + + public bool IsVirtualPathInApp(String path, out bool isClientScriptPath, out String clientScript) { + isClientScriptPath = false; + clientScript = null; + + if (path == null) + return false; + + if (_virtualPath == "/" && path.StartsWith("/")) { + if (path.StartsWith(_lowerCasedClientScriptPathWithTrailingSlashV10)) { + isClientScriptPath = true; + clientScript = path.Substring(_lowerCasedClientScriptPathWithTrailingSlashV10.Length); + } + + if (path.StartsWith(_lowerCasedClientScriptPathWithTrailingSlashV11)) { + isClientScriptPath = true; + clientScript = path.Substring(_lowerCasedClientScriptPathWithTrailingSlashV11.Length); + } + + return true; + } + + path = CultureInfo.InvariantCulture.TextInfo.ToLower(path); + + if (path.StartsWith(_lowerCasedVirtualPathWithTrailingSlash)) + return true; + + if (path == _lowerCasedVirtualPath) + return true; + + if (path.StartsWith(_lowerCasedClientScriptPathWithTrailingSlashV10)) { + isClientScriptPath = true; + clientScript = path.Substring(_lowerCasedClientScriptPathWithTrailingSlashV10.Length); + return true; + } + + if (path.StartsWith(_lowerCasedClientScriptPathWithTrailingSlashV11)) { + isClientScriptPath = true; + clientScript = path.Substring(_lowerCasedClientScriptPathWithTrailingSlashV11.Length); + return true; + } + + return false; + } + + public bool IsVirtualPathAppPath(String path) { + if (path == null) + return false; + + path = CultureInfo.InvariantCulture.TextInfo.ToLower(path); + return (path == _lowerCasedVirtualPath || path == _lowerCasedVirtualPathWithTrailingSlash); + } + + private void OnAppDomainUnload(Object unusedObject, EventArgs unusedEventArgs) { + Thread.GetDomain().DomainUnload -= _onAppDomainUnload; + + if (_stopped) + return; + + Stop(); + + _server.Restart(); + _server = null; + } + + private void OnSocketAccept(Object acceptedSocket) { + Connection conn = new Connection(this, (Socket)acceptedSocket); + conn.ProcessOneRequest(); + } + + private void OnStart(Object unused) { + while (_started) { + try { + Socket socket = _socket.Accept(); + ThreadPool.QueueUserWorkItem(_onSocketAccept, socket); + } + catch { + Thread.Sleep(100); + } + } + + _stopped = true; + } + + public void Start() { + if (_started) + throw new InvalidOperationException(); + + _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + _socket.Bind(new IPEndPoint(IPAddress.Any, _port)); + _socket.Listen((int)SocketOptionName.MaxConnections); + + _started = true; + ThreadPool.QueueUserWorkItem(_onStart); + } + + public void Stop() { + if (!_started) + return; + + _started = false; + + try { + // _socket.Shutdown(SocketShutdown.Both); /* blocks! */ + _socket.Close(); + } + catch { + } + finally { + _socket = null; + } + + while (!_stopped) + Thread.Sleep(100); + } + + } +} Added: trunk/plugins/MediaPortal WebServices/MiniWebServer/Messages.cs =================================================================== --- trunk/plugins/MediaPortal WebServices/MiniWebServer/Messages.cs (rev 0) +++ trunk/plugins/MediaPortal WebServices/MiniWebServer/Messages.cs 2009-10-02 16:57:37 UTC (rev 3101) @@ -0,0 +1,149 @@ +/*======================================================================= +\xA0 Copyright (C) Microsoft Corporation.\xA0 All rights reserved. +\xA0 + THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A + PARTICULAR PURPOSE. +=======================================================================*/ + +namespace Cassini { + using System; + using System.Collections; + using System.Globalization; + using System.IO; + using System.Text; + using System.Web; + using System.Web.Hosting; + + // + // Internal class provides helpers for string formatting of HTTP responses + // + internal class Messages { + + private const String _httpErrorFormat1 = +@"<html> + <head> + <title>{0}</title> +"; + + public static String VersionString = typeof(Server).Assembly.GetName().Version.ToString(); + + private const String _httpStyle = +@" <style> + body {font-family:""Verdana"";font-weight:normal;font-size: 8pt;color:black;} + p {font-family:""Verdana"";font-weight:normal;color:black;margin-top: -5px} + b {font-family:""Verdana"";font-weight:bold;color:black;margin-top: -5px} + H1 { font-family:""Verdana"";font-weight:normal;font-size:18pt;color:red } + H2 { font-family:""Verdana"";font-weight:normal;font-size:14pt;color:maroon } + pre {font-family:""Lucida Console"";font-size: 8pt} + .marker {font-weight: bold; color: black;text-decoration: none;} + .version {color: gray;} + .error {margin-bottom: 10px;} + .expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; } + </style> +"; + + private static String _httpErrorFormat2 = +@" </head> + <body bgcolor=""white""> + + <span><H1>Server Error in '{0}' Application.<hr width=100% size=1 color=silver></H1> + + <h2> <i>HTTP Error {1} - {2}.</i> </h2></span> + + <hr width=100% size=1 color=silver> + + <b>Version Information:</b> Cassini Web Server " + VersionString + @" + + </font> + + </body> +</html> +"; + + private const String _dirListingFormat1 = +@"<html> + <head> + <title>Directory Listing -- {0}</title> +"; + + private const String _dirListingFormat2 = +@" </head> + <body bgcolor=""white""> + + <h2> <i>Directory Listing -- {0}</i> </h2></span> + + <hr width=100% size=1 color=silver> + +<PRE> +"; + + private static String _dirListingTail = +@"</PRE> + <hr width=100% size=1 color=silver> + + <b>Version Information:</b> Cassini Web Server " + VersionString + @" + + </font> + + </body> +</html> +"; + + private const String _dirListingParentFormat = +@"<A href=""{0}"">[To Parent Directory]</A> + +"; + + private const String _dirListingFileFormat = +@"{0,38:dddd, MMMM dd, yyyy hh:mm tt} {1,12:n0} <A href=""{2}"">{3}</A> +"; + + private const String _dirListingDirFormat = +@"{0,38:dddd, MMMM dd, yyyy hh:mm tt} <dir> <A href=""{1}/"">{2}</A> +"; + + + public static String FormatErrorMessageBody(int statusCode, String appName) { + String desc = HttpWorkerRequest.GetStatusDescription(statusCode); + + return String.Format(_httpErrorFormat1, desc) + + _httpStyle + + String.Format(_httpErrorFormat2, appName, statusCode, desc); + } + + public static String FormatDirectoryListing(String dirPath, String parentPath, FileSystemInfo[] elements) { + StringBuilder sb = new StringBuilder(); + + sb.Append(String.Format(_dirListingFormat1, dirPath)); + sb.Append(_httpStyle); + sb.Append(String.Format(_dirListingFormat2, dirPath)); + + if (parentPath != null) { + if (!parentPath.EndsWith("/")) + parentPath += "/"; + sb.Append(String.Format(_dirListingParentFormat, parentPath)); + } + + if (elements != null) { + for (int i = 0; i < elements.Length; i++) { + if (elements[i] is FileInfo) { + FileInfo fi = (FileInfo)elements[i]; + sb.Append(String.Format(_dirListingFileFormat, + fi.LastWriteTime, fi.Length, fi.Name, fi.Name)); + } + else if (elements[i] is DirectoryInfo) { + DirectoryInfo di = (DirectoryInfo)elements[i]; + sb.Append(String.Format(_dirListingDirFormat, + di.LastWriteTime, di.Name, di.Name)); + } + } + } + + sb.Append(_dirListingTail); + return sb.ToString(); + } + + } +} Added: trunk/plugins/MediaPortal WebServices/MiniWebServer/MiniWebServer.csproj =================================================================== --- trunk/plugins/MediaPortal WebServices/MiniWebServer/MiniWebServer.csproj (rev 0) +++ trunk/plugins/MediaPortal WebServices/MiniWebServer/MiniWebServer.csproj 2009-10-02 16:57:37 UTC (rev 3101) @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.21022</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{AC169225-21E5-4375-A21D-A3779512A26C}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>MiniWebServer</RootNamespace> + <AssemblyName>MiniWebServer</AssemblyName> + <TargetFrameworkVersion>v2.0</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Data" /> + <Reference Include="System.Web" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="ByteParser.cs" /> + <Compile Include="ByteString.cs" /> + <Compile Include="Connection.cs" /> + <Compile Include="Host.cs" /> + <Compile Include="Messages.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Request.cs" /> + <Compile Include="Server.cs" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\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. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project> \ No newline at end of file Added: trunk/plugins/MediaPortal WebServices/MiniWebServer/Properties/AssemblyInfo.cs =================================================================== --- trunk/plugins/MediaPortal WebServices/MiniWebServer/Properties/AssemblyInfo.cs (rev 0) +++ trunk/plugins/MediaPortal WebServices/MiniWebServer/Properties/AssemblyInfo.cs 2009-10-02 16:57:37 UTC (rev 3101) @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MiniWebServer")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Avaya")] +[assembly: AssemblyProduct("MiniWebServer")] +[assembly: AssemblyCopyright("Copyright © Avaya 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("d7f17007-5dac-4377-af91-bfbddfa2392c")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] Added: trunk/plugins/MediaPortal WebServices/MiniWebServer/Request.cs =================================================================== --- trunk/plugins/MediaPortal WebServices/MiniWebServer/Request.cs (rev 0) +++ trunk/plugins/MediaPortal WebServices/MiniWebServer/Request.cs 2009-10-02 16:57:37 UTC (rev 3101) @@ -0,0 +1,735 @@ +/*======================================================================= +\xA0 Copyright (C) Microsoft Corporation.\xA0 All rights reserved. +\xA0 + THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY + KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A + PARTICULAR PURPOSE. +=======================================================================*/ + +namespace Cassini { + using System; + using System.Collections; + using System.Globalization; + using System.IO; + using System.Net; + using System.Net.Sockets; + using System.Text; + using System.Threading; + using System.Web; + using System.Web.Hosting; + + // + // Internal Request class provides the implementation of + // HttpWorkerRequest (by deriving from SimpleWorkerRequest). + // + // Request object are create one per client request as passed to + // ASP.NET using HttpRuntime.ProcessRequest + // + internal class Request : SimpleWorkerRequest { + private Host _host; + private Connection _conn; + + // raw request data + private const int maxHeaderBytes = 32*1024; + private byte[] _headerBytes; + private int _startHeadersOffset; + private int _endHeadersOffset; + private ArrayList _headerByteStrings; + + // parsed request data + private String _verb; + private String _url; + private String _prot; + + private String _path; + private String _filePath; + private String _pathInfo; + private String _pathTranslated; + private String _queryString; + private byte[] _queryStringBytes; + + private int _contentLength; + private int _preloadedContentLength; + private byte[] _preloadedContent; + + private String _allRawHeaders; + private String[][] _unknownRequestHeaders; + private String[] _knownRequestHeaders; + + // cached response + private bool _headersSent; + private int _responseStatus; + private StringBuilder _responseHeadersBuilder; + private ArrayList _responseBodyBytes; + + private bool _specialCaseStaticFileHeaders; + + + public Request(Host host, Connection conn) : base(String.Empty, String.Empty, null) { + _host = host; + _conn = conn; + } + + public void Process() { + + ReadAllHeaders(); + + if (_headerBytes == null || _endHeadersOffset < 0 || + _headerByteStrings == null || _headerByteStrings.Count == 0) { + _conn.WriteErrorAndClose(400); + return; + } + + ParseRequestLine(); + + // Check for bad path + if (IsBadPath()) { + _conn.WriteErrorAndClose(400); + return; + } + + // Limit to local requests only + /*if (!_conn.IsLocal) { + _conn.WriteErrorAndClose(403); + return; + }*/ + + // Check if the path is not well formed or is not for the current app + bool isClientScriptPath = false; + String clientScript = null; + + if (!_host.IsVirtualPathInApp(_path, out isClientScriptPath, out clientScript)) { + _conn.WriteErrorAndClose(404); + return; + } + + ParseHeaders(); + + ParsePostedContent(); + + if (_verb == "POST" && _contentLength > 0 && _preloadedContentLength < _contentLength) { + _conn.Write100Continue(); + } + + // special case for client script + if (isClientScriptPath) { + _conn.WriteEntireResponseFromFile(_host.PhysicalClientScriptPath + clientScript, false); + return; + } + + // special case for directory listing + if (ProcessDirectoryListingRequest()) { + return; + } + + PrepareResponse(); + + // Hand the processing over to HttpRuntime + + HttpRuntime.ProcessRequest(this); + } + + private bool TryReadAllHeaders() { + // read the first packet (up to 32K) + byte[] headerBytes = _conn.ReadRequestBytes(maxHeaderBytes); + + if (headerBytes == null || headerBytes.Length == 0) + return false; + + if (_headerBytes != null) { + // previous partial read + int len = headerBytes.Length + _headerBytes.Length; + if (len > maxHeaderBytes) + return false; + + byte[] bytes = new byte[len]; + Buffer.BlockCopy(_headerBytes, 0, bytes, 0, _headerBytes.Length); + Buffer.BlockCopy(headerBytes, 0, bytes, _headerBytes.Length, headerBytes.Length); + _headerBytes = bytes; + } + else { + _headerBytes = headerBytes; + } + + // start parsing + _startHeadersOffset = -1; + _endHeadersOffset = -1; + _headerByteStrings = new ArrayList(); + + // find the end of headers + ByteParser parser = new ByteParser(_headerBytes); + + for (;;) { + ByteString line = parser.ReadLine(); + + if (line == null) + break; + + if (_startHeadersOffset < 0) { + _startHeadersOffset = parser.CurrentOffset; + } + + if (line.IsEmpty) { + _endHeadersOffset = parser.CurrentOffset; + break; + } + + _headerByteStrings.Add(line); + } + + return true; + } + + private void ReadAllHeaders() { + _headerBytes = null; + + do { + if (!TryReadAllHeaders()) + break; // something bad happened + } + while (_endHeadersOffset < 0); // found \r\n\r\n + } + + private void ParseRequestLine() { + ByteString requestLine = (ByteString)_headerByteStrings[0]; + ByteString[] elems = requestLine.Split(' '); + + if (elems == null || elems.Length < 2 || elems.Length > 3) { + return; + } + + _verb = elems[0].GetString(); + + ByteString urlBytes = elems[1]; + _url = urlBytes.GetString(); + + if (elems.Length == 3) + _prot = elems[2].GetString(); + else + _prot = "HTTP/1.0"; + + // query string + + int iqs = urlBytes.IndexOf('?'); + if (iqs > 0) + _queryStringBytes = urlBytes.Substring(iqs+1).GetBytes(); + else + _queryStringBytes = new byte[0]; + + iqs = _url.IndexOf('?'); + if (iqs > 0) { + _path = _url.Substring(0, iqs); + _queryString = _url.Substring(iqs+1); + } + else { + _path = _url; + _queryStringBytes = new byte[0]; + } + + // url-decode path + + if (_path.IndexOf('%') >= 0) { + _path = HttpUtility.UrlDecode(_path); + } + + // path info + + int lastDot = _path.LastIndexOf('.'); + int lastSlh = _path.LastIndexOf('/'); + + if (lastDot >= 0 && lastSlh >= 0 && lastDot < lastSlh) { + int ipi = _path.IndexOf('/', lastDot); + _filePath = _path.Substring(0, ipi); + _pathInfo = _path.Substring(ipi); + } + else { + _filePath = _path; + _pathInfo = String.Empty; + } + + _pathTranslated = MapPath(_filePath); + } + + private static char[] s_badPathChars = new char[] { '%', '>', '<', '$', ':' }; + private bool IsBadPath() { + if (_path == null) + return true; + + if (_path.IndexOfAny(s_badPathChars) >= 0) + return true; + + if (_path.IndexOf("..") >= 0) + return true; + + return false; + } + + private void ParseHeaders() { + _knownRequestHeaders = new String[RequestHeaderMaximum]; + + // construct unknown headers as array list of name1,value1,... + ArrayList headers = new ArrayList(); + + for (int i = 1; i < _headerByteStrings.Count; i++) { + String s = ((ByteString)_headerByteStrings[i]).GetString(); + + int c = s.IndexOf(':'); + + if (c >= 0) { + String name = s.Substring(0, c).Trim(); + String value = s.Substring(c+1).Trim(); + + // remember + int knownIndex = GetKnownRequestHeaderIndex(name); + if (knownIndex >= 0) { + _knownRequestHeaders[knownIndex] = value; + } + else { + headers.Add(name); + headers.Add(value); + } + } + } + + // copy to array unknown headers + + int n = headers.Count / 2; + _unknownRequestHeaders = new String[n][]; + int j = 0; + + for (int i = 0; i < n; i++) { + _unknownRequestHeaders[i] = new String[2]; + _unknownRequestHeaders[i][0] = (String)headers[j++]; + _unknownRequestHeaders[i][1] = (String)headers[j++]; + } + + // remember all raw headers as one string + + if (_headerByteStrings.Count > 1) + _allRawHeaders = Encoding.UTF8.GetString(_headerBytes, _startHeadersOffset, _endHeadersOffset-_startHeadersOffset); + else + _allRawHeaders = String.Empty; + } + + private void ParsePostedContent() { + _contentLength = 0; + _preloadedContentLength = 0; + + String contentLengthValue = _knownRequestHeaders[HttpWorkerRequest.HeaderContentLength]; + if (contentLengthValue != null) { + try { + _contentLength = Int32.Parse(contentLengthValue); + } + catch { + } + } + + if (_headerBytes.Length > _endHeadersOffset) { + _preloadedContentLength = _headerBytes.Length - _endHeadersOffset; + + if (_preloadedContentLength > _contentLength && _contentLength > 0) + _preloadedContentLength = _contentLength; // don't read more than the content-length + + _preloadedContent = new byte[_preloadedContentLength]; + Buffer.BlockCopy(_headerBytes, _endHeadersOffset, _preloadedContent, 0, _preloadedContentLength); + } + } + + private static String[] s_defaultFilenames = new String[] { "default.aspx", "default.htm", "default.html" }; + + private bool ProcessDirectoryListingRequest() { + if (_verb != "GET") + return false; + + // last element extension-less? + int i1 = _pathTranslated.LastIndexOf('\\'); + int i2 = _pathTranslated.IndexOf('.', i1); + if (i2 >= i1) + return false; + + // now check if directory + if (!Directory.Exists(_pathTranslated)) + return false; + + // have to redirect /foo to /foo/ to allow relative links to work + if (!_path.EndsWith("/")) { + String newPath = _path + "/"; + String location = "Location: " + newPath + "\r\n"; + String body = "<html><head><title>Object moved</title></head><body>\r\n" + + "<h2>Object moved to <a href='" + newPath + "'>here</a>.</h2>\r\n" + + "</body></html>\r\n"; + + _conn.WriteEntireResponseFromString(302, location, body, false); + return true; + } + + // check for the default file + foreach (String filename in s_defaultFilenames) { + String defaultFilePath = _pathTranslated + "\\" + filename; + + if (File.Exists(defaultFilePath)) { + // pretend the request is for the default file path + _path += filename; + _filePath = _path; + _url = (_queryString != null) ? (_path + "?" + _queryString) : _path; + _pathTranslated = defaultFilePath; + return false; // go through normal processing + } + } + + // get all files and subdirs + FileSystemInfo[] infos = null; + try { + infos = (new DirectoryInfo(_pathTranslated)).GetFileSystemInfos(); + } + catch { + } + + // determine if parent is appropriate + String parentPath = null; + + if (_path.Length > 1) { + int i = _path.LastIndexOf('/', _path.Length-2); + parentPath = (i > 0) ?_path.Substring(0, i) : "/"; + if (!_host.IsVirtualPathInApp(parentPath)) + parentPath = null; + } + + _conn.WriteEntireResponseFromString(200, "Content-type: text/html; charset=utf-8\r\n", + Messages.FormatDirectoryListing(_path, parentPath, infos), false); + return true; + } + + private void PrepareResponse() { + _headersSent = false; + _responseStatus = 200; + _responseHeadersBuilder = new StringBuilder(); + _responseBodyBytes = new ArrayList(); + } + + /////////////////////////////////////////////////////////////////////////////////////////////// + // + // Implementation of HttpWorkerRequest + // + /////////////////////////////////////////////////////////////////////////////////////////////// + + public override String GetUriPath() { + return _path; + } + + public override String GetQueryString() { + return _queryString; + } + + public override byte[] GetQueryStringRawBytes() { + return _queryStringBytes; + } + + public override String GetRawUrl() { + return _url; + } + + public override String GetHttpVerbName() { + return _verb; + } + + public override String GetHttpVersion() { + return _prot; + }... [truncated message content] |