private FSEntry GetEntry(string uri) { // Request URIs must never contain \ (only /) if (uri.Contains("\\")) { return(null); } // Make sure the URI starts with the service URI, and prodived it does, strip // off that part. if (!uri.StartsWith(ServiceURI)) { return(null); } uri = uri.Substring(ServiceURI.Length); // Get the file or directory from the URI string[] parts = uri.Split( new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); FSDir dir = m_root, parent = null; for (int i = 0; i < parts.Length; i++) { parent = dir; dir = dir.GetDir(parts[i]); // Should we get a null directory we have 2 cases: // 1. This is NOT the last loop iteration, implying that we've hit a not found. // 2. This IS the last loop iteration, meaning that the last part of the file // string may be a file name and/or may be a not found. We fall through to // the code after this loop in that case. if (null == dir && i != parts.Length - 1) { return(null); } } // If 'dir' is non-null at this point then we return it if (null != dir) { return(dir); } // Coming here implies it's a file name return(parent.GetFile(parts[parts.Length - 1])); }
/// <summary> /// Request handler function /// </summary> public override void Handler(WebRequest req) { if (m_disposed) { throw new ObjectDisposedException("FileWebServer"); } if ("POST" == req.Method) { HandlePost(req); return; } // Handle uploads if ("PUT" == req.Method) { HandlePut(req); return; } // If it's anything other than GET at this point then it's not implemented if (req.Method != "GET") { m_logger.WriteLine( " Method was \"" + req.Method + "\" -> sending not implemented response"); req.WriteNotImplementedResponse( "<html><h1>HTTP method "" + req.Method + "" is not implemented</h1></html>"); return; } // First get rid of formatting on requested file string toGet = req.URIDecoded; // Requested file/content name must never contain \ (only /) if (toGet.Contains("\\")) { m_logger.WriteLine( " URI contains \"\\\" -> sending 400 response"); req.WriteBadRequestResponse(); return; } m_logger.WriteLine("Got request for \"" + toGet + "\""); // Make sure the URL starts with the service URL, and prodived it does, strip // off that part. if (!toGet.StartsWith(ServiceURI)) { req.WriteNotFoundResponse(); return; } toGet = toGet.Substring(ServiceURI.Length); // Get the file or directory that we need to serve string[] parts = toGet.Split( new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); FSDir dir = m_root, parent = null; for (int i = 0; i < parts.Length; i++) { parent = dir; dir = dir.GetDir(parts[i]); // Should we get a null directory we have 2 cases: // 1. This is NOT the last loop iteration, implying that we've hit a not found. // 2. This IS the last loop iteration, meaning that the last part of the file // string may be a file name and/or may be a not found. We fall through to // the code after this loop in that case. if (null == dir && i != parts.Length - 1) { if (null != m_onFileNotFound) { // Invoke custom handler m_onFileNotFound(this, toGet, req); } else { req.WriteNotFoundResponse(); } return; } } // If 'dir' is non-null at this point then it's a request for a listing of files in // that directory. if (null != dir) { m_logger.WriteLine(" Sending directory listing as response"); // Build response and send it string response = m_onNeedDirList(dir); req.WriteHTMLResponse(response); // That's all we need for a directory listing return; } // Coming here implies a file name FSFile file = parent.GetFile(parts[parts.Length - 1]); // If it doesn't exist then we respond with a file-not-found response if (null == file) { if (null != m_onFileNotFound) // custom handler { m_logger.WriteLine(" File not found -> invoking external handler"); m_onFileNotFound(this, parts[parts.Length - 1], req); } else { m_logger.WriteLine(" File not found -> sending 404 response"); // If we don't have a handler for file-not-found then we use the generic 404 req.WriteNotFoundResponse(); } return; } // File DOES exist, so we write the file data as the response m_logger.WriteLine(" Sending file contents as response"); WriteFileResponse(req, file); }
private void HandlePut(WebRequest req) { if (!m_allowUploads) { req.WriteBadRequestResponse(); return; } // For now, don't allow overwriting if (GetEntry(req.URIDecoded) != null) { req.WriteBadRequestResponse(); //req.WriteHTMLResponse("<html>Cannot overwrite files</html>"); return; } // Make sure it starts with the service URI then remove that part string toPut = req.URIDecoded; if (!toPut.StartsWith(ServiceURI)) { req.WriteBadRequestResponse(); return; } toPut = toPut.Substring(ServiceURI.Length); // Parse the path and get the directories string[] pieces = toPut.Split('/'); FSDir dir = m_root; for (int i = 0; i < pieces.Length - 1; i++) { dir = dir.GetDir(pieces[i]); if (dir == null) { req.WriteBadRequestResponse(); return; } } // By the time we get here we expected the last piece of the URI to be the file name FSFile theUploadedFile = dir.CreateFile(pieces[pieces.Length - 1]); if (null == theUploadedFile) { // If we can't create the file at this point, we'll call it a bad request (because // it's most likely because of a bad file name) req.WriteBadRequestResponse(); return; } // Stream in the body of request from the socket and out to the file Stream outS = theUploadedFile.OpenReadWrite(); if (outS == null) { req.WriteInternalServerErrorResponse(); return; } byte[] buf = new byte[8192]; while (true) { int bytesRead = req.Body.Read(buf, 0, buf.Length); if (bytesRead <= 0) { break; } outS.Write(buf, 0, bytesRead); } long fileLength = outS.Length; outS.Dispose(); req.WriteHTMLResponse(string.Format("<html>OK: Uploaded {0} bytes</html>", fileLength)); }