private void PrintDirectory(string path, HandlePackage package) { if (!package.Server.Settings.ListDirectories) { this.Write404(package); return; } if (!Directory.Exists(path)) { return; } Pages.BrowserPage page = new Pages.BrowserPage(); page.Filename = path.Replace(package.Server.Settings.DocumentRoot, "").Replace("\\", "/"); page.ParentDirectory = path == package.Server.Settings.DocumentRoot ? "/" : "../"; foreach (string dir in Directory.GetDirectories(path)) { string truncated = StringUtil.TruncatePath(dir); page.AddFile(new Pages.BrowserPage.BrowserFile(StringUtil.WindowsToURL(truncated) + "/", truncated, false)); } foreach (string file in Directory.GetFiles(path)) { string truncated = StringUtil.TruncatePath(file); page.AddFile(new Pages.BrowserPage.BrowserFile(StringUtil.WindowsToURL(truncated), truncated, true)); } page.DumpToStream(package.ContentStream); }
private void PrintFile(string path, HandlePackage package) { if (!File.Exists(path)) { return; } try { FileStream fs = File.Open(path, FileMode.Open); fs.CopyTo(package.ContentStream); try { fs.Close(); } catch (Exception ex) { Log.e("Failed to close file {0}:\n {1}", path, ex.Message); } string ext = StringUtil.GetExtension(path).ToLower(); package.ResponseHeader.SetField("Content-Type", MIME.GetContentType(ext)); } catch (Exception ex) { Log.e("Failed to write file to HTTP {0}", ex.Message); } }
private bool HandleResource(string resourceName, HandlePackage package) { switch (resourceName) { case "corecss.css": package.ResponseHeader.SetField("Content-Type", MIME.GetContentType("css", "text/css")); package.ContentStream.Write(Properties.Resources.CoreCSS); return(true); case "ubuntu-r.ttf": package.ResponseHeader.SetField("Content-Type", MIME.GetContentType("ttf", "x/application-font")); package.ContentStream.Write(Properties.Resources.Ubuntu_R, 0, Properties.Resources.Ubuntu_R.Length); return(true); case "folder.png": package.ResponseHeader.SetField("Content-Type", MIME.GetContentType("png", "image/png")); Properties.Resources.appbar_folder.Save(package.ContentStream, System.Drawing.Imaging.ImageFormat.Png); return(true); case "page.png": package.ResponseHeader.SetField("Content-Type", MIME.GetContentType("png", "image/png")); Properties.Resources.appbar_page_bold.Save(package.ContentStream, System.Drawing.Imaging.ImageFormat.Png); return(true); default: return(false); } }
public bool HandleRequest(HandlePackage package) { string host = package.RequestHeader.Host.ToLower(); if (MachineData.HostNames.ContainsName(host)) { // Prevent a giant messy loop of requests return(false); } string completeURL = string.Format("http://{0}{1}{2}", host, package.RequestHeader.URL, package.RequestHeader.ConcatGetValues()); WebClient webClient = new WebClient(); try { // Download the data and dump it into the stream byte[] proxyData = webClient.DownloadData(completeURL); package.ContentStream.Write(proxyData, 0, proxyData.Length); package.ResponseHeader.SetField("Content-Type", MIME.GetContentType(StringUtil.GetExtension(completeURL))); webClient.Dispose(); // Well, that's all folks! return(true); } catch (Exception ex) { Log.e("Failed to do proxy magic:\n{0}", ex.Message); package.ContentStream.Write("Well something went wrong"); return(true); } }
public override bool HandleRequest(HandlePackage package) { string url_lower = package.RequestHeader.URL.ToLower(); if (!url_lower.StartsWith(this.coreString)) { return(false); } string[] url_exploded = url_lower.Substring(1).Split('/'); if (url_exploded.Length < 3) { return(false); } switch (url_exploded[1]) { case "resource": return(this.HandleResource(url_exploded[2], package)); default: return(false); } }
private void Write404(HandlePackage package) { package.ResponseHeader.StatusCode = 404; package.ResponseHeader.StatusMessage = "Not Found"; package.ContentStream.WriteLine("404 not found: the requested file does not exist"); }
public virtual bool HandleRequest(HandlePackage package) { bool validRoot = false; if (Directory.Exists(package.Server.Settings.DocumentRoot)) { validRoot = true; } else { try { Directory.CreateDirectory(package.Server.Settings.DocumentRoot); } catch (Exception ex) { Log.e("Could not create DocumentRoot: {0}", ex.Message); } } if (!validRoot) { package.ContentStream.WriteLine("Server error: Invalid root path"); package.ResponseHeader.StatusCode = 500; package.ResponseHeader.StatusMessage = "Internal Server Error"; return(true); } string path = package.Server.Settings.DocumentRoot; string url = package.RequestHeader.URL; string url_lower = url.ToLower(); if (url == "/") { string index_html = path + "\\index.html"; if (File.Exists(index_html)) { path = index_html; } } else { if (url.StartsWith("/")) { path = path + StringUtil.URLToWindows(url); } else { path = path + "\\" + StringUtil.URLToWindows(url); } } if (File.Exists(path)) { this.PrintFile(path, package); return(true); } else { if (Directory.Exists(path)) { string index_html = path + "\\index.html"; if (File.Exists(index_html)) { package.ResponseHeader.StatusCode = 301; package.ResponseHeader.StatusMessage = "Moved Permanently"; string furl = url; if (!url.EndsWith("/")) { furl += "/"; } furl += "index.html"; package.ResponseHeader.SetField("Location", furl); return(true); } else { this.PrintDirectory(path, package); return(true); } } else { this.Write404(package); return(true); } } }
private void PullRequest() { // Just cache this value in case it randomly decides to change int bufSize = this.BufferSize; // Shove the message in here, so we can peek around freely MemoryStream fullMessage = new MemoryStream(); byte[] readBuffer = new byte[bufSize]; // Reserve a bit of memory we can receive data in while (true) { int readCount = 0; try { readCount = this.inputStream.Read(readBuffer, 0, bufSize); // Read data from the TCP stream } catch (Exception ex) { Log.e("Could not read from TCP stream: {0}", ex.Message); this.QuitProcessor(); return; } if (readCount == 0) { break; } // When we get zero bytes, we can assume it is the end of the stream fullMessage.Write(readBuffer, 0, readCount); // Take the data we got, and put it in our own stream object if (readCount < bufSize) { break; } // If the received data length is smaller then the buffer, assume end of stream } fullMessage.Seek(0, SeekOrigin.Begin); // Set the cursor of our own stream to the start if (fullMessage.Length <= 0) // We can't do anything with empty requests, kill the stream { if (this.handlingServer.Settings.ChargenOnEmptyStream) { Log.m("Got an empty stream, shoving through a load of characters before quitting"); Random aRandom = new Random((int)DateTime.Now.Ticks); try { for (int i = 0; i < this.handlingServer.Settings.ChargenLength; i++) { this.outputStream.WriteByte((byte)aRandom.Next(0, 254)); } this.outputStream.Flush(); } catch (Exception ex) { Log.e("Failed to shove a bunch of characters", ex.Message); } } else { Log.e("Got an empty message from a remote client, aborting processing stream"); } this.QuitProcessor(); return; } StringBuilder requestString = new StringBuilder(); // StringBuilers are faster than just appending strings or chars ^^ int lastByte = -1; while (fullMessage.CanRead) { int readByte = fullMessage.ReadByte(); // Get one byte from the received message if (readByte == 13) { // We're going to ignore carriage returns continue; } if (lastByte == readByte && readByte == 10) { // We've got two newlines, end of request! break; } requestString.Append((char)(byte)readByte); // Just throw the received byte onto the end of our string lastByte = readByte; } int contentLength = 0; HTTPHeader requestHeader = HTTPHeader.ParseRequest(requestString.ToString()); // Turn our request string into a header object, so we can do stuff Log.d("Connection mode is {0}", requestHeader.Connection[0]); this.KeepAlive = requestHeader.Connection.Contains("keep-alive"); // We have to keep pulling requests until specified otherwise this.closeConnection = requestHeader.Connection.Contains("close"); // Have a license to kill if (requestHeader.HTTPFields.ContainsKey("Content-Length")) { contentLength = requestHeader.ContentLength; } Log.d("Got request:\n{0}", requestHeader.ToString()); // Read the http message content from the stream // If we get no content, we're wasting some resources // cri ContentStream requestContent = new ContentStream(); if (requestContent.Length > 0) { while (fullMessage.CanRead) { requestContent.WriteByte((byte)fullMessage.ReadByte()); if (requestContent.Length >= contentLength) { break; } } } // Finish the stream boogaloo for this request fullMessage.Dispose(); // We've got from the stream what we needed, get rid of it fullMessage = null; // this.inputStream.Seek(0, SeekOrigin.End); // Skip the buffered stream to the end // Set up the data containers for the response HTTPHeader responseHeader = HTTPHeader.GenerateResponse(); responseHeader.SetField("Server", this.handlingServer.Settings.Server); ContentStream responseContent = new ContentStream(); // Shove all of our junk in one neat little strucht Handlers.HandlePackage handlePackage = new Handlers.HandlePackage(requestHeader, responseHeader, requestContent, responseContent, this.handlingServer); if (this.handlingServer.Settings.AutoProxy && !MachineData.HostNames.ContainsName(requestHeader.Host)) { Log.m("Autoproxying for {0}", requestHeader.Host); if (!this.handlingServer.AutoProxyHandler.HandleRequest(handlePackage)) { responseContent.Write("wah"); } } else { if (!this.handlingServer.CoreHandler.HandleRequest(handlePackage)) // Allow the core handler a try first { bool notExecuted = true; foreach (IHTTPHandler handler in this.handlingServer.HTTPHandlers) { notExecuted = !handler.HandleRequest(handlePackage); // Might have to put a break in here some day } if (notExecuted) { // Nothing handled our request, shove it through the default handler this.handlingServer.DefaultHTTPHandler.HandleRequest(handlePackage); } } } responseHeader.SetField("Content-Length", responseContent.Length.ToString()); // We have to set the content length on the response header responseHeader.SetField("Connection", "closed"); string statusString = string.Format("HTTP/{2} {0} {1}\r\n", responseHeader.StatusCode, responseHeader.StatusMessage, responseHeader.Version); byte[] statusStringBytes = Encoding.UTF8.GetBytes(statusString); this.outputStream.Write(statusStringBytes, 0, statusStringBytes.Length); Log.d("Response header: {0}\n", responseHeader.ToString()); responseHeader.DumpFields(this.outputStream); this.outputStream.WriteByte(13); // CRLF the really stupid way this.outputStream.WriteByte(10); if (requestHeader.Method == HTTP_Method.HEAD) { // WELL OK } else { // Copy the content generated by our other stuff into the TCP stream byte[] contentBytes = new byte[responseContent.Length]; if (responseContent.Length > 0) { responseContent.Seek(0, SeekOrigin.Begin); responseContent.Read(contentBytes, 0, (int)responseContent.Length); } try { this.outputStream.Write(contentBytes, 0, contentBytes.Length); } catch (Exception ex) { Log.e(ex.Message); } } this.KeepAlive = false; // heh... // this.outputStream.Flush(); }