/// <summary> /// This is used to process a client. /// </summary> /// <param name="directory">The requested directory.</param> /// <param name="file">The requested file.</param> /// <param name="version">The HTTP version to play back.</param> /// <param name="address">The address of the client.</param> /// <param name="ns">The transport.</param> /// <returns></returns> private async Task Process(string directory, string file, string version, string address, Stream ns) { if (!directory.Contains("..")) // Only root ('/') is allowed. { var cleanedPath = GetLocalPath(file, directory); if (!(cleanedPath.Contains("players.csv") || cleanedPath.Contains("logs")) && cleanedPath.Contains("?")) { cleanedPath = cleanedPath.Remove( cleanedPath.IndexOf("?", StringComparison.InvariantCultureIgnoreCase), cleanedPath.Length - cleanedPath.IndexOf("?", StringComparison.InvariantCultureIgnoreCase)); } if (File.Exists(cleanedPath)) { var mimeType = ParseMime(cleanedPath); //COMPARISION : If the file type is supported, move on to the next comparision. If not, send the error. if (mimeType != null) { //COMPARISION : Send client from memory or an unloaded file from the disk. if (cleanedPath.Contains("client.html")) { await WriteDocument(Document, "text/html", ns, version).ConfigureAwait(false); } else { var document = await File.ReadAllBytesAsync(cleanedPath).ConfigureAwait(false); await WriteDocument(document, mimeType, ns, version).ConfigureAwait(false); } } else { await WriteDocument(DocumentTypeNotSupported, "text/html", ns, version, StatusCodes.NotImplemented501).ConfigureAwait(false); } } else { List <string> handlers; lock (InvalidPageHandlers) handlers = InvalidPageHandlers.ToList(); if (cleanedPath.Contains("players.csv") && cleanedPath.Contains('?')) { var key = cleanedPath.Substring(cleanedPath.IndexOf('?') + 1); if (ApiServer.CheckKey(key)) { var response = Encoding.UTF8.GetBytes(MainClass.CompilePlayers()); await WriteDocument(response, "text/csv", ns, version).ConfigureAwait(false); } else { var data = Encoding.UTF8.GetBytes("<h1>You have entered an invalid key. Please stop trying to break into our system!</h1>"); await WriteDocument(data, "text/html", ns, version).ConfigureAwait(false); } } else if (cleanedPath.Contains("logs.csv") && cleanedPath.Contains('?')) { var requestData = cleanedPath.Substring(cleanedPath.IndexOf('?') + 1).Split('&'); if (requestData.Length == 2 && !string.IsNullOrEmpty(requestData[0]) && !string.IsNullOrEmpty(requestData[1])) { var key = requestData[0]; if (!ApiServer.CheckKey(key)) { var data = Encoding.UTF8.GetBytes( "<h1>You have entered an invalid key. Please stop trying to break into our system!</h1>"); await WriteHeader(version, "text/html", data.Length, " 200 OK", ns).ConfigureAwait(false); await ns.WriteAsync(data, 0, data.Length).ConfigureAwait(false); } else { var requestedLog = Path.Combine("hqlogs", Path.GetFileNameWithoutExtension(requestData[1]) + ".self"); var logs = MainClass.LogManager.GetLogNames(); if (!logs.Contains(requestedLog)) { var data = Encoding.UTF8.GetBytes( "<h1>Could not find the logs you requested.</h1>"); await WriteHeader(version, "text/html", data.Length, " 404 Not Found", ns).ConfigureAwait(false); await ns.WriteAsync(data, 0, data.Length).ConfigureAwait(false); } else { byte[] data; using (FileStream fs = new FileStream(requestedLog, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { //we don't want to read while it is writing. lock (MainClass.LogManager.FileLock) { data = new byte[fs.Length]; fs.Read(data, 0, (int)fs.Length); } } //i am not doing it directly off the stream so i don't lock the manager for too long... //should not be a problem, logs will be quite small. var logData = GetCsv(data); await WriteHeader(version, "text/csv", logData.Length, " 200 OK", ns).ConfigureAwait(false); await ns.WriteAsync(logData, 0, logData.Length).ConfigureAwait(false); } } } } else if (handlers.Contains(cleanedPath)) { OnSpecialHandlerInvoked?.Invoke( cleanedPath.Replace("dashboard\\", "").Replace("dashboard/", ""), ns, version, address); } else { await WriteHeader(version, "text/html", Document404Error.Length, " 404 Not Found", ns).ConfigureAwait(false); await ns.WriteAsync(Document404Error, 0, Document404Error.Length).ConfigureAwait(false); } } } else { await WriteHeader(version, "text/html", Document404Error.Length, " 404 Not Found", ns).ConfigureAwait(false); await ns.WriteAsync(Document404Error, 0, Document404Error.Length).ConfigureAwait(false); } }