private static void MaintainCamerasLoop() { try { while (true) { try { foreach (CameraSpec cs in cfg.cameras) { if (cs.enabled) { try { CameraMaintenance.MaintainCamera(cs); } catch (ThreadAbortException) { return; } catch (Exception ex) { Logger.Debug(ex); } } } } catch (ThreadAbortException) { return; } catch (Exception ex) { Logger.Debug(ex); } Thread.Sleep(60000 * 10); } } catch (ThreadAbortException) { return; } catch (Exception ex) { Logger.Debug(ex); } }
public override void handleGETRequest(HttpProcessor p) { try { string requestedPageLower = p.requestedPage.ToLower(); if (p.requestedPage == "errors") { string errors = File.ReadAllText(Globals.ErrorFilePath); p.writeSuccess(); p.outputStream.Write(HttpUtility.HtmlEncode(errors).Replace("\r\n", "<br/>").Replace("\r", "<br/>").Replace("\n", "<br/>")); return; } if (p.requestedPage == "error") { Logger.Debug("/error page loaded"); p.writeSuccess(); p.outputStream.Write("Error written to log"); return; } if (p.requestedPage == "admin") { p.writeRedirect("admin/main"); return; } if (p.requestedPage == "login") { LogOutUser(p, null); return; } if (p.requestedPage == "testip") { p.writeSuccess("text/plain; charset=utf-8"); p.outputStream.Write(p.RemoteIPAddressStr); return; } Session s = sm.GetSession(p.requestCookies.GetValue("tlsess"), p.requestCookies.GetValue("tlauth"), p.GetParam("rawauth")); if (s != null && s.sid != null && s.sid.Length == 16) { p.responseCookies.Add("tlsess", s.sid, TimeSpan.FromMinutes(s.sessionLengthMinutes)); } if (p.requestedPage == "logout") { LogOutUser(p, s); return; } if (p.requestedPage.StartsWith("admin/")) { string adminPage = p.requestedPage == "admin" ? "" : p.requestedPage.Substring("admin/".Length); if (string.IsNullOrWhiteSpace(adminPage)) { adminPage = "main"; } int idxQueryStringStart = adminPage.IndexOf('?'); if (idxQueryStringStart == -1) { idxQueryStringStart = adminPage.Length; } adminPage = adminPage.Substring(0, idxQueryStringStart); Pages.Admin.AdminPage.HandleRequest(adminPage, p, s); return; } else if (p.requestedPage == "Navigation" || p.requestedPage == "NavigationNextDay") { if (HandlePublicServiceDisabled(p)) { return; } CameraSpec cs = TimelapseWrapper.cfg.GetCameraSpec(p.GetParam("cam")); if (cs == null || cs.type != CameraType.FTP) { p.writeFailure("400 Bad Request"); } else if (cs != null && !IpWhitelist.IsWhitelisted(p.RemoteIPAddressStr, cs.ipWhitelist)) { p.writeFailure("403 Forbidden"); } else { string path = p.GetParam("path"); p.writeSuccess(); try { if (p.requestedPage == "Navigation") { p.outputStream.Write(Navigation.GetNavHtml(cs, path)); } else { p.outputStream.Write(Navigation.GetNavHtmlForNextDay(cs, path)); } } catch (NavigationException) { p.outputStream.Write("Server busy. Please reload this page later."); } } } else if (p.requestedPage == "TimeZoneList") { if (HandlePublicServiceDisabled(p)) { return; } p.writeSuccess(); p.outputStream.Write(Pages.TimeZoneList.GetHtml()); } else if (requestedPageLower.StartsWith(TimelapseGlobals.ImageArchiveFolderNameLower + "/")) { p.writeFailure(); } else if (p.requestedPage == "GetFileListUrls") { if (HandlePublicServiceDisabled(p)) { return; } CameraSpec cs = TimelapseWrapper.cfg.GetCameraSpec(p.GetParam("cam")); if (cs == null || cs.type != CameraType.FTP) { p.writeFailure("400 Bad Request"); } else if (cs != null && !IpWhitelist.IsWhitelisted(p.RemoteIPAddressStr, cs.ipWhitelist)) { p.writeFailure("403 Forbidden"); } else { string path = p.GetParam("path"); try { string response = Navigation.GetFileListUrls(cs, path); p.writeSuccess("text/plain"); p.outputStream.Write(response); } catch (NavigationException) { p.writeFailure("503 Service Unavailable"); p.outputStream.Write(""); } catch (Exception ex) { Logger.Debug(ex); p.writeFailure("500 Internal Server Error"); } } } else { if (p.requestedPage.StartsWith("TimelapseAPI/", StringComparison.OrdinalIgnoreCase)) { mvcApi.ProcessRequest(p, p.requestedPage.Substring("TimelapseAPI/".Length)); return; } CameraSpec cs = null; if (p.request_url.Segments.Length > 1) { cs = TimelapseWrapper.cfg.GetCameraSpec(p.request_url.Segments[1].Trim('/')); } if (cs != null) { if (HandlePublicServiceDisabled(p)) { return; } if (cs != null && !IpWhitelist.IsWhitelisted(p.RemoteIPAddressStr, cs.ipWhitelist)) { p.writeFailure("403 Forbidden"); } else { // This page is something involving a camera we have configured if (p.request_url.Segments.Length == 2) { if (cs.type == CameraType.ThirdPartyHosted) { p.writeFailure("400 Bad Request"); } else { p.writeRedirect("Camera.html?cam=" + cs.id); // Redirect to the camera page for this camera } } else if (p.request_url.Segments.Length >= 3) { if (p.request_url.Segments.Length == 3 && p.request_url.Segments[2] == "latest.jpg") { if (cs.type == CameraType.ThirdPartyHosted) { if (!string.IsNullOrWhiteSpace(cs.path_3rdpartyimgzippedURL)) { WebServerUtil.Handle3rdPartyZippedImage(p, cs); return; } else { p.writeFailure("400 Bad Request"); return; } } if (!CameraMaintenance.MaintainCamera(cs)) { p.writeFailure("500 Internal Server Error"); return; } string latestImgTime; DateTime dateTime; string latestImagePathPart; try { latestImagePathPart = Navigation.GetLatestImagePath(cs, out latestImgTime, out dateTime); } catch (NavigationException) { p.writeFailure("503 Service Unavailable"); return; } string path = cs.id + "/" + latestImagePathPart; List <KeyValuePair <string, string> > headers = WebServerUtil.GetCacheEtagHeaders(TimeSpan.Zero, path); FileInfo imgFile = new FileInfo(TimelapseGlobals.ImageArchiveDirectoryBase + path); headers.Add(new KeyValuePair <string, string>("Content-Disposition", "inline; filename=\"" + cs.name + " " + imgFile.Name.Substring(0, imgFile.Name.Length - imgFile.Extension.Length) + ".jpg\"")); if (path == p.GetHeaderValue("if-none-match")) { p.writeSuccess("image/jpeg", -1, "304 Not Modified"); return; } byte[] data = WebServerUtil.GetImageData(path); p.writeSuccess("image/jpeg", data.Length, additionalHeaders: headers); p.outputStream.Flush(); p.tcpStream.Write(data, 0, data.Length); } else { if (cs.type != CameraType.FTP) { p.writeFailure("400 Bad Request"); return; } List <KeyValuePair <string, string> > headers = WebServerUtil.GetCacheEtagHeaders(TimeSpan.FromDays(365), p.requestedPage); FileInfo imgFile = new FileInfo(TimelapseGlobals.ImageArchiveDirectoryBase + p.requestedPage); headers.Add(new KeyValuePair <string, string>("Content-Disposition", "inline; filename=\"" + cs.name + " " + imgFile.Name.Substring(0, imgFile.Name.Length - imgFile.Extension.Length) + ".jpg\"")); if (p.requestedPage == p.GetHeaderValue("if-none-match")) { p.writeSuccess("image/jpeg", -1, "304 Not Modified"); return; } byte[] data = WebServerUtil.GetImageData(p.requestedPage); p.writeSuccess("image/jpeg", data.Length, additionalHeaders: headers); p.outputStream.Flush(); p.tcpStream.Write(data, 0, data.Length); } } else { p.writeFailure(); } } } else { #region www DirectoryInfo WWWDirectory = new DirectoryInfo(TimelapseGlobals.WWWDirectoryBase); DirectoryInfo debugWWW = GetDebugWWW(); if (debugWWW != null) { WWWDirectory = debugWWW; } string wwwDirectoryBase = WWWDirectory.FullName.Replace('\\', '/').TrimEnd('/') + '/'; string reqPage = p.requestedPage; //if (reqPage == "") // reqPage = "Default.html"; FileInfo fi = new FileInfo(wwwDirectoryBase + reqPage); string targetFilePath = fi.FullName.Replace('\\', '/'); if (!targetFilePath.StartsWith(wwwDirectoryBase) || targetFilePath.Contains("../")) { if (WebServerUtil.HandleAdminConfiguredRedirect(p)) { return; } p.writeFailure("400 Bad Request"); return; } //if (webpackProxy != null) //{ // // Handle hot module reload provided by webpack dev server. // switch (fi.Extension.ToLower()) // { // case ".js": // case ".map": // case ".css": // case ".json": // webpackProxy.Proxy(p); // return; // } //} if (!fi.Exists) { if (WebServerUtil.HandleAdminConfiguredRedirect(p)) { return; } //fi = new FileInfo(wwwDirectoryBase + "Default.html"); //if (!fi.Exists) //{ p.writeFailure("404 Not Found"); return; //} } if ((fi.Extension == ".html" || fi.Extension == ".htm") && fi.Length < 256000) { string html = File.ReadAllText(fi.FullName); if (fi.Name.ToLower() == "camera.html") { // camera.html triggers special behavior if (HandlePublicServiceDisabled(p)) { return; } string camId = p.GetParam("cam"); cs = TimelapseWrapper.cfg.GetCameraSpec(camId); if (cs == null || cs.type == CameraType.ThirdPartyHosted || !CameraMaintenance.MaintainCamera(cs)) { p.writeFailure("400 Bad Request"); return; } if (cs != null && !IpWhitelist.IsWhitelisted(p.RemoteIPAddressStr, cs.ipWhitelist)) { p.writeFailure("403 Forbidden"); return; } string latestImgTime = ""; DateTime dateTime = DateTime.MinValue; string navMenu; string latestImagePathPart; try { navMenu = Navigation.GetNavHtml(cs, Navigation.GetLatestPath(cs, out latestImgTime, out dateTime)); latestImagePathPart = Navigation.GetLatestImagePath(cs, out latestImgTime, out dateTime); } catch (NavigationException) { navMenu = "Server busy. Please reload this page later."; latestImagePathPart = "latest"; } html = html.Replace("%NAVMENU%", navMenu); html = html.Replace("%TOPMENU%", cs.topMenuHtml); html = html.Replace("%CAMID%", cs.id); html = html.Replace("%CAMNAME%", cs.name); html = html.Replace("%CSS%", WebServerUtil.GetCameraPageStyleCSS(cs)); html = html.Replace("%CAMFRAME_GRADIENT%", cs.imgBackgroundGradient ? "true" : "false"); html = html.Replace("%CAMNAME_HTML%", WebServerUtil.GetCameraNameHtml(cs)); string latestImagePath = cs.id + "/" + latestImagePathPart + ".jpg"; html = html.Replace("%LATEST_IMAGE%", latestImagePath); html = html.Replace("%LATEST_IMAGE_TIME%", HttpUtility.JavaScriptStringEncode(latestImgTime)); } else if (fi.Name.ToLower() == "all.html") { // all.html triggers special macro strings html = html.Replace("%ALL_CAMERAS_JS_ARRAY%", WebServerUtil.GetAllCamerasJavascriptArray(p.RemoteIPAddressStr)); html = html.Replace("%ALL_PAGE_HEADER%", TimelapseWrapper.cfg.options.allPageHeading); } try { html = html.Replace("%REMOTEIP%", p.RemoteIPAddressStr); html = html.Replace("%SYSTEM_NAME%", TimelapseWrapper.cfg.options.systemName); html = html.Replace("%APP_VERSION%", TimelapseGlobals.Version); } catch (Exception ex) { Logger.Debug(ex); } p.writeSuccess(Mime.GetMimeType(fi.Extension)); p.outputStream.Write(html); p.outputStream.Flush(); } else { string mime = Mime.GetMimeType(fi.Extension); if (p.requestedPage.StartsWith(".well-known/acme-challenge/")) { mime = "text/plain"; } if (fi.LastWriteTimeUtc.ToString("R") == p.GetHeaderValue("if-modified-since")) { p.writeSuccess(mime, -1, "304 Not Modified"); return; } p.writeSuccess(mime, fi.Length, additionalHeaders: WebServerUtil.GetCacheLastModifiedHeaders(TimeSpan.FromHours(1), fi.LastWriteTimeUtc)); p.outputStream.Flush(); using (FileStream fs = fi.OpenRead()) { fs.CopyTo(p.tcpStream); } p.tcpStream.Flush(); } #endregion } } } catch (Exception ex) { if (!HttpProcessor.IsOrdinaryDisconnectException(ex)) { Logger.Debug(ex); } } }