private static void build_file_index_from_scratch() { lock (l) { file_index.Clear(); GC.Collect(); try { foreach (string board in ThreadStore.GetStorageEngine().GetExistingBoards()) { var threads = ThreadStore.GetStorageEngine().GetIndexIDOnly(board); foreach (string thread_id in threads) { if (thread_id == null) { continue; } var thread_data = ThreadStore.GetStorageEngine().GetThread(board, thread_id); int tid = int.Parse(thread_id); foreach (var post in thread_data) { if (post.MyFile != null) { FileIndexInfo w; if (file_index.ContainsKey(post.MyFile.Hash)) { w = file_index[post.MyFile.Hash]; } else { w = new FileIndexInfo(post.MyFile.Hash); file_index.Add(post.MyFile.Hash, w); } w.MarkPost(board, tid, post.PostID, post.MyFile.FileName); } } } } } catch (Exception ex) { file_index.Clear(); Console.WriteLine("Error occured while building file index:\n{0}\n{1}", ex.Message, ex.StackTrace); Console.Beep(); } } }
private void save_thread_container(ThreadContainer tc) { savePost(tc.Instance); if (tc.Instance.File != null) { Program.dump_files(tc.Instance.File, this.ThumbOnly); } int count = tc.Replies.Count(); int with_image = 0; for (int i = 0; i < count; i++) { GenericPost reply = tc.Replies[i]; savePost(reply); if (reply.File != null) { ++with_image; Program.dump_files(tc.Replies[i].File, this.ThumbOnly); } } log(new LogEntry() { Level = LogEntry.LogLevel.Success, Message = string.Format("Static thread {0} was saved successfully.", this.ID), Sender = "ThreadWorker", Title = string.Format("/{0}/ - {1}", this.Board.Board, this.ID) }); log(new LogEntry() { Level = LogEntry.LogLevel.Info, Message = "Optimizing thread data." }); ThreadStore.GetStorageEngine().OptimizeThread(this.Board.Board, this.ID); log(new LogEntry() { Level = LogEntry.LogLevel.Success, Message = "Optimisation done." }); }
private void savePost(GenericPost gp) { ThreadStore.GetStorageEngine().savePost(this.Board.Board, this.ID, gp.ID, gp); }
private void worker_DoWork(object sender, DoWorkEventArgs e) { string thread_folder = Path.Combine(Program.post_files_dir, this.Board.Board, this.ID.ToString()); Directory.CreateDirectory(thread_folder); System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); while (running) { sw.Reset(); try { sw.Start(); log(new LogEntry() { Level = LogEntry.LogLevel.Info, Message = "Updating thread...", Sender = "ThreadWorker", Title = string.Format("/{0}/ - {1}", this.Board.Board, this.ID) }); var tc = Program.aw.GetThreadData(this.Board.Board, this.ID); this.ThreadTitle = tc.Title; if (!can_i_run(tc.Instance)) { log(new LogEntry() { Level = LogEntry.LogLevel.Info, Message = "ThreadWorker stopped because of a filter", Sender = "ThreadWorker", Title = string.Format("/{0}/ - {1}", this.Board.Board, this.ID) }); running = false; ThreadStore.GetStorageEngine().DeleteThread(this.Board.Board, this.ID.ToString()); break; } if (this.AddedAutomatically && this.Board.Mode == BoardWatcher.BoardMode.Harvester) { if (tc.Instance.File != null) { if (this.Board.IsFileAllowed(tc.Instance.File.ext)) { savePost(tc.Instance); Program.dump_files(tc.Instance.File, this.ThumbOnly); } } } else { savePost(tc.Instance); if (tc.Instance.File != null) { Program.dump_files(tc.Instance.File, this.ThumbOnly); } } int count = tc.Replies.Count(); int with_image = 0; for (int i = 0; i < count; i++) { if (this.AddedAutomatically && this.Board.Mode == BoardWatcher.BoardMode.None) { continue; } if (this.AddedAutomatically && this.Board.Mode == BoardWatcher.BoardMode.Harvester) { if (tc.Replies[i].File != null) { if (!this.Board.IsFileAllowed(tc.Replies[i].File.ext)) { continue; } } else { continue; } } GenericPost replyPost = tc.Replies[i]; savePost(replyPost); if (tc.Replies[i].File != null) { ++with_image; Program.dump_files(tc.Replies[i].File, this.ThumbOnly); } } sw.Stop(); this.ImageLimitReached = with_image >= this.ImageLimit; int new_rc = count - old_replies_count; log(new LogEntry() { Level = LogEntry.LogLevel.Success, Message = string.Format("Updated in {0} seconds {1}", sw.Elapsed.Seconds, new_rc > 0 ? ", + " + new_rc.ToString() + " new replies" : ""), Sender = "ThreadWorker", Title = string.Format("/{0}/ - {1}", this.Board.Board, this.ID) }); old_replies_count = count; this.LastUpdated = DateTime.Now; if (count >= this.BumpLimit) { this.AutoSage = true; //auto-sage mode, we must archive faster if (this.Board.Speed == BoardWatcher.BoardSpeed.Fast) { this.UpdateInterval = 0.16; //each 10 sec } else if (this.Board.Speed == BoardWatcher.BoardSpeed.Normal) { this.UpdateInterval = 1; //each 60 sec } } if (tc.Instance.IsSticky) { this.UpdateInterval = 5; } if (tc.Instance.IsArchived) { log(new LogEntry() { Level = LogEntry.LogLevel.Info, Message = string.Format("Thread entered archived state."), Sender = "ThreadWorker", Title = string.Format("/{0}/ - {1}", this.Board.Board, this.ID) }); ThreadStore.GetStorageEngine().OptimizeThread(this.Board.Board, this.ID); this.Stop(); if (Settings.RemoveThreadsWhenTheyEnterArchivedState && !this.AddedAutomatically) { Thread404(this); } else { goto stop; } } if (this.Board.Mode == BoardWatcher.BoardMode.Harvester) { this.UpdateInterval = 2; } System.Threading.Thread.Sleep(Convert.ToInt32(this.UpdateInterval * 60 * 1000)); } catch (Exception ex) { if (ex.Message.Contains("404")) { log(new LogEntry() { Level = LogEntry.LogLevel.Info, Message = string.Format("Optimizing thread data..."), Sender = "ThreadWorker", Title = string.Format("/{0}/ - {1}", this.Board.Board, this.ID) }); if (!(this.AddedAutomatically && this.Board.Mode == BoardWatcher.BoardMode.Harvester)) { ThreadStore.GetStorageEngine().OptimizeThread(this.Board.Board, this.ID); } this.Stop(); Thread404(this); goto stop; } else { log(new LogEntry() { Level = LogEntry.LogLevel.Fail, Message = string.Format("An error occured '{0}' @ '{1}', retrying", ex.Message, ex.StackTrace), Sender = "ThreadWorker", Title = string.Format("/{0}/ - {1}", this.Board.Board, this.ID) }); System.Threading.Thread.Sleep(1000); } } } stop: log(new LogEntry() { Level = LogEntry.LogLevel.Success, Message = "Stopped thread worker successfully", Sender = "ThreadWorker", Title = string.Format("/{0}/ - {1}", this.Board.Board, this.ID) }); }
public override bool Process(HttpServer.IHttpRequest request, HttpServer.IHttpResponse response, HttpServer.Sessions.IHttpSession session) { string command = request.UriPath.ToString(); #region Thread & Index View if (command.StartsWith("/boards/")) { response.Encoding = System.Text.Encoding.UTF8; string[] parame = command.Split('?')[0].Split('/'); if (parame.Length == 3) { //board index view mode string board = parame[2]; if (string.IsNullOrEmpty(board)) { response.Redirect("/boards"); return(true); } ThreadStore.GetStorageEngine().UpdateThreadStoreStats(); int board_thread_count = ThreadStore.GetStorageEngine().StoreStats[board]; if (board_thread_count == 0) { response.Redirect("/boards"); return(true); } int rem = (board_thread_count % ThreadPerPage); int page_count = ((board_thread_count - rem) / ThreadPerPage) + (rem > 0 ? 1 : 0); if (page_count <= 0) { page_count = 1; } int page_offset = 0; Int32.TryParse(request.QueryString["pn"].Value, out page_offset); page_offset = Math.Abs(page_offset); int start = page_offset * (ThreadPerPage); PostFormatter[] board_index = ThreadStore.GetStorageEngine().GetIndex(board, start, ThreadPerPage); StringBuilder s = new StringBuilder(); foreach (var pf in board_index) { s.Append("<div class='row'>"); s.Append ( pf.ToString() .Replace("{post:link}", string.Format("/boards/{0}/{1}", board, pf.PostID)) ); s.Append("</div>"); } StringBuilder page_numbers = new StringBuilder(); for (int i = 0; i < page_count; i++) { if (i == page_offset) { page_numbers.AppendFormat("<li class=\"active\"><a href=\"?pn={0}\">{1}</a></li>", i, i + 1); } else { page_numbers.AppendFormat("<li><a href=\"?pn={0}\">{1}</a></li>", i, i + 1); } } byte[] data = Encoding.UTF8.GetBytes( Properties.Resources.board_index_page .Replace("{po}", Convert.ToString(page_offset == 0 ? 0 : page_offset - 1)) .Replace("{no}", Convert.ToString(page_offset == page_count - 1 ? page_count : page_offset + 1)) .Replace("{pagen}", page_numbers.ToString()) .Replace("{Items}", s.ToString())); response.ContentType = ServerConstants.HtmlContentType; response.Encoding = Encoding.UTF8; response.Status = System.Net.HttpStatusCode.OK; response.ContentLength = data.Length; response.SendHeaders(); response.SendBody(data); return(true); } else if (parame.Length >= 4) { //thread view mode string board = parame[2]; string threadid = parame[3]; int parsedThreadId = -1; int.TryParse(threadid, out parsedThreadId); if (string.IsNullOrEmpty(board) || string.IsNullOrEmpty(threadid)) { _404(response); return(true); } if (parsedThreadId <= 0) { _404(response); return(true); } StringBuilder pageHtml = new StringBuilder(Properties.Resources.page_template); StringBuilder body = new StringBuilder(); { PostFormatter[] thread_data = ThreadStore.GetStorageEngine().GetThread(board, threadid); if (thread_data.Length == 0) { _404(response); return(true); } body.Append(thread_data[0]); body.Replace("{post:link}", string.Format("#p{0}", thread_data[0].PostID)); for (int i = 1; i < thread_data.Length; i++) { body.Append(thread_data[i]); } } string thread_notes = ThreadStore.GetStorageEngine().GetThreadNotes(board, parsedThreadId); thread_notes = System.Web.HttpUtility.HtmlEncode(thread_notes); pageHtml.Replace("{board-title}", string.Format("[ChanArchiver] - /{0}/ Thread No. {1}", board, threadid)); pageHtml.Replace("{board-letter}", board); pageHtml.Replace("{thread-id}", threadid); pageHtml.Replace("{{notes}}", thread_notes); pageHtml.Replace("{thread-posts}", body.ToString()); byte[] content = Encoding.UTF8.GetBytes(pageHtml.ToString()); response.ContentType = ServerConstants.HtmlContentType; response.ContentLength = content.Length; response.Encoding = Encoding.UTF8; response.SendHeaders(); response.SendBody(content); return(true); } } if (command.StartsWith("/getfilelist?")) { string board = request.QueryString["board"].Value; string threadid = request.QueryString["thread"].Value; if (string.IsNullOrEmpty(board) || string.IsNullOrEmpty(threadid)) { _404(response); } PostFormatter[] thread_data = ThreadStore.GetStorageEngine().GetThread(board, threadid); if (thread_data.Length == 0) { _404(response); return(true); } StringBuilder sb = new StringBuilder(); for (int i = 0; i < thread_data.Length; i++) { PostFormatter pf = thread_data[i]; if (pf.MyFile != null) { string url_name = System.Web.HttpUtility.UrlEncodeUnicode(pf.MyFile.FileName); string url = string.Format("/filecn/{0}.{1}?cn={2}", pf.MyFile.Hash, pf.MyFile.Extension, url_name); sb.AppendFormat("<a href='{0}'>{1}</a><br/>", url, pf.MyFile.FileName); } } byte[] data = Encoding.UTF8.GetBytes(sb.ToString()); response.ContentType = ServerConstants.HtmlContentType; response.ContentLength = data.Length; response.Encoding = Encoding.UTF8; response.SendHeaders(); response.SendBody(data); return(true); } if (command.StartsWith("/deletethread/?")) { lock (delete_thread_lock) { string board = request.QueryString["board"].Value; string threadid = request.QueryString["thread"].Value; if (string.IsNullOrEmpty(board) || string.IsNullOrEmpty(threadid)) { _404(response); } PostFormatter[] thread_data = ThreadStore.GetStorageEngine().GetThread(board, threadid); //delete the files foreach (var post in thread_data) { if (post.MyFile != null) { var state = FileIndex.GetIndexState(post.MyFile.Hash); if (state != null) { if (state.RepostCount == 1) { string path = FileOperations.MapFullFile(post.MyFile.Hash, post.MyFile.Extension); if (File.Exists(path)) { File.Delete(path); } else if (File.Exists(path + ".webm")) { File.Exists(path + ".webm"); } path = FileOperations.MapThumbFile(post.MyFile.Hash); File.Delete(path); FileIndex.RemovePost(post.MyFile.Hash, post.PostID); } } } } //delete the thread ThreadStore.GetStorageEngine().DeleteThread(board, threadid); response.Redirect("/boards/" + board); return(true); } } if (command == "/boards" || command == "/boards/") { if (Directory.Exists(Program.post_files_dir)) { StringBuilder s = new StringBuilder(); foreach (string folder_path in Directory.EnumerateDirectories(Program.post_files_dir)) { string folder_name = Path.GetFileName(folder_path); s.Append("<div class=\"col-6 col-sm-6 col-lg-4\">"); s.AppendFormat("<h2>/{0}/</h2>", folder_name); s.AppendFormat("<p>Thread Count: {0}</p>", ThreadStore.GetStorageEngine().StoreStats[folder_name]); s.AppendFormat("<p><a class=\"btn btn-default\" href=\"/boards/{0}\" role=\"button\">browse ยป</a></p>", folder_name); s.Append("</div>"); } byte[] data = Encoding.UTF8.GetBytes(Properties.Resources.archivedboard_page.Replace("{Items}", s.ToString())); response.Encoding = System.Text.Encoding.UTF8; response.ContentType = "text/html; charset=utf-8"; response.Status = System.Net.HttpStatusCode.OK; response.ContentLength = data.Length; response.SendHeaders(); response.SendBody(data); } else { response.Redirect("/"); } return(true); } #endregion #region File Queue Actions if (command.StartsWith("/set/maxfilequeue/")) { if (string.IsNullOrEmpty(request.QueryString["count"].Value)) { response.Redirect("/fq"); } else { int t = Program.file_stp.MaxThreads; Int32.TryParse(request.QueryString["count"].Value, out t); if (t != Program.file_stp.MaxThreads) { if (t > Program.file_stp.MinThreads) { Program.file_stp.MaxThreads = t; } } response.Redirect("/fq"); } return(true); } if (command == "/action/removecompletefiles") { List <string> hashes_to_remove = new List <string>(); for (int index = 0; index < Program.queued_files.Count(); index++) { try { FileQueueStateInfo f = Program.queued_files.ElementAt(index).Value; if (f.Status == FileQueueStateInfo.DownloadStatus.Complete) { hashes_to_remove.Add(Program.queued_files.ElementAt(index).Key); } } catch (Exception) { if (index > Program.queued_files.Count()) { break; } } } foreach (string s in hashes_to_remove) { Program.queued_files.Remove(s); } response.Redirect("/fq"); return(true); } if (command == "/action/removefailedfiles") { List <string> hashes_to_remove = new List <string>(); for (int index = 0; index < Program.queued_files.Count(); index++) { try { FileQueueStateInfo f = Program.queued_files.ElementAt(index).Value; if (f.Status == FileQueueStateInfo.DownloadStatus.Error || f.Status == FileQueueStateInfo.DownloadStatus.NotFound) { hashes_to_remove.Add(Program.queued_files.ElementAt(index).Key); } } catch (Exception) { if (index > Program.queued_files.Count()) { break; } } } foreach (string s in hashes_to_remove) { Program.queued_files.Remove(s); } response.Redirect("/fq"); return(true); } if (command == "/action/restartfailedfiles") { List <KeyValuePair <string, FileQueueStateInfo> > files_to_restart = new List <KeyValuePair <string, FileQueueStateInfo> >(); for (int index = 0; index < Program.queued_files.Count(); index++) { try { FileQueueStateInfo f = Program.queued_files.ElementAt(index).Value; if (f.Status == FileQueueStateInfo.DownloadStatus.Error) { files_to_restart.Add(Program.queued_files.ElementAt(index)); } } catch (Exception) { if (index > Program.queued_files.Count()) { break; } } } foreach (KeyValuePair <string, FileQueueStateInfo> s in files_to_restart) { Program.queued_files.Remove(s.Key); Program.dump_files(s.Value.PostFile, s.Value.IsThumbOnly); } response.Redirect("/fq"); return(true); } #endregion #region Watch Jobs Actions if (command.StartsWith("/add/")) { string[] rdata = command.Split('/'); string mode = rdata[2].ToLower(); if (mode == "board") { if (string.IsNullOrEmpty(request.QueryString["boardletter"].Value)) { _404(response); } string board = request.QueryString["boardletter"].Value; string mon_type = request.QueryString["montype"].Value; BoardWatcher.BoardMode m = BoardWatcher.BoardMode.None; if (mon_type == "white") { m = BoardWatcher.BoardMode.Whitelist; } if (mon_type == "black") { m = BoardWatcher.BoardMode.Blacklist; } if (mon_type == "full") { m = BoardWatcher.BoardMode.FullBoard; } if (mon_type == "harvest") { m = BoardWatcher.BoardMode.Harvester; } Program.archive_board(board, m); response.Status = System.Net.HttpStatusCode.OK; response.Redirect("/monboards"); } else if (mode == "thread") { if (string.IsNullOrEmpty(request.QueryString["urlorformat"].Value)) { _404(response); } string input = request.QueryString["urlorformat"].Value; bool thumbOnly = request.QueryString["to"].Value == "1"; string board = ""; int id = -1; if (input.ToLower().StartsWith("http")) { //http://boards.4chan.org/g/res/39075359 string temp = input.ToLower().Replace("https://", "").Replace("http://", ""); //boards.4chan.org/g/res/int // 0 1 2 3 string[] data = temp.Split('/'); if (data.Length >= 4) { board = data[1]; Int32.TryParse(data[3].Split('#')[0], out id); } } else { string[] data = input.Split(':'); if (data.Length >= 2) { board = data[0]; Int32.TryParse(data[1], out id); } } if (id > 0 & !string.IsNullOrEmpty(board)) { Program.archive_single(board, id, thumbOnly); response.Status = System.Net.HttpStatusCode.OK; response.Redirect("/wjobs"); } else { _404(response); } } else if (mode == "threadfromarchive") { try { string ai_index_str = request.QueryString["ai_index"].Value; string board = request.QueryString["board"].Value; string threadid_str = request.QueryString["threadid"].Value; if (!string.IsNullOrEmpty(ai_index_str) && !string.IsNullOrEmpty(board) && !string.IsNullOrEmpty(threadid_str)) { int ai_index = -1; int tid = -1; if (int.TryParse(ai_index_str, out ai_index) && int.TryParse(threadid_str, out tid)) { ArchiveInfo info = ArchivesProvider.GetAllArchives().ElementAt(ai_index); var status = ArchivedThreadAdder.AddThreadFromArchive(board, tid, false, info); if (status != AddThreadFromArchiveStatus.Success) { write_text("Unable to add thread, reason: " + status.ToString(), response); return(true); } else { response.Redirect("/wjobs"); return(true); } } } } catch (FormatException) { write_text("Unable to add thread, reason: Invalid thread id", response); return(true); } catch (IndexOutOfRangeException) { write_text("Unable to add thread, reason: Invalid archvie info index", response); return(true); } write_text("Unable to add thread, reason: possible malformed parameters", response); return(true); } else { _404(response); } return(true); } if (command.StartsWith("/cancel/")) { string[] data = command.Split('/'); string mode = data[2]; if (mode == "bw") { string board = data[3]; if (Program.active_dumpers.ContainsKey(board)) { BoardWatcher bw = Program.active_dumpers[board]; bw.StopMonitoring(); response.Redirect("/monboards"); } } if (mode == "bwr") { string board = data[3]; if (Program.active_dumpers.ContainsKey(board)) { BoardWatcher bw = Program.active_dumpers[board]; bw.StartMonitoring(BoardWatcher.BoardMode.FullBoard); response.Redirect("/monboards"); } } if (mode == "tw") { string board = data[3]; string tid = data[4]; if (Program.active_dumpers.ContainsKey(board)) { BoardWatcher bw = Program.active_dumpers[board]; int id = Convert.ToInt32(tid); if (bw.watched_threads.ContainsKey(id)) { ThreadWorker tw = bw.watched_threads[id]; tw.Stop(); response.Redirect("/wjobs"); } } } if (mode == "twr") { string board = data[3]; string tid = data[4]; if (Program.active_dumpers.ContainsKey(board)) { BoardWatcher bw = Program.active_dumpers[board]; int id = Convert.ToInt32(tid); if (bw.watched_threads.ContainsKey(id)) { ThreadWorker tw = bw.watched_threads[id]; tw.Start(); response.Redirect("/wjobs"); } } } return(true); } if (command.StartsWith("/action/removethreadworker/")) { string board = request.QueryString["board"].Value; string tid = request.QueryString["id"].Value; if (Program.active_dumpers.ContainsKey(board)) { BoardWatcher bw = Program.active_dumpers[board]; int id = -1; Int32.TryParse(tid, out id); if (bw.watched_threads.ContainsKey(id)) { ThreadWorker tw = bw.watched_threads[id]; tw.Stop(); bw.watched_threads.Remove(id); } } response.Redirect("/wjobs"); return(true); } #endregion #region File Actions if (command.StartsWith("/action/restartfile/")) { string workid = command.Split('/').Last(); FileQueueStateInfo f = Program.get_file_state(workid); if (f != null) { f.ForceStop = true; Program.queued_files.Remove(workid); Program.dump_files(f.PostFile, f.IsThumbOnly); response.Redirect("/fileinfo/" + workid); } else { response.Redirect("/fq"); } return(true); } if (command.StartsWith("/action/stopandbanfile/")) { string workid = command.Split('/').Last(); FileQueueStateInfo f = Program.get_file_state(workid); if (f != null) { f.ForceStop = true; Program.ban_file(f.Hash); f.Log(new LogEntry() { Level = LogEntry.LogLevel.Success, Message = "File was banned", Sender = "-", Title = "" }); // Program.queued_files.Remove(workid); response.Redirect("/fileinfo/" + workid); } else { response.Redirect("/fq"); } return(true); } if (command.StartsWith("/action/banfile")) { string hash = request.QueryString["hash"].Value; if (!string.IsNullOrEmpty(hash)) { Program.ban_file(hash); } string referrer = request.Headers["referer"]; if (!string.IsNullOrEmpty(referrer)) { response.Redirect(referrer); } return(true); } if (command.StartsWith("/action/showfilereposts")) { string hash = request.QueryString["hash"].Value; if (!string.IsNullOrWhiteSpace(hash)) { FileIndexInfo info = FileIndex.GetIndexState(hash); if (info != null) { StringBuilder sb = new StringBuilder(); var rposts = info.GetRepostsData(); for (int i = 0; i < rposts.Length; i++) { sb.Append("<tr>"); sb.AppendFormat("<td>{0}</td>", rposts[i].FileName); sb.AppendFormat("<td><a href='/boards/{0}'></a>{0}</td>", rposts[i].Board); sb.AppendFormat("<td><code><a href='/boards/{0}/{1}'>{1}</a></code></td>", rposts[i].Board, rposts[i].ThreadID); sb.AppendFormat("<td><code><a href='/boards/{0}/{1}#p{2}'>{2}</a></code></td>", rposts[i].Board, rposts[i].ThreadID, rposts[i].PostID); sb.Append("</tr>"); } write_text(Properties.Resources.file_reposts_page .Replace("{thumbsource}", string.Format("/thumb/{0}.jpg", hash)) .Replace("{md5}", hash) .Replace("{rinfo}", sb.ToString()), response); return(true); } } else { _404(response); return(true); } return(true); } if (command.StartsWith("/action/removefile/")) { string workid = command.Split('/').Last(); FileQueueStateInfo f = Program.get_file_state(workid); if (f != null) { Program.queued_files.Remove(workid); response.Redirect("/fq"); } else { response.Redirect("/fq"); } return(true); } if (command.StartsWith("/action/resetfileretrycount/")) { string workid = command.Split('/').Last(); FileQueueStateInfo f = Program.get_file_state(workid); if (f != null) { f.RetryCount = 0; response.Redirect("/fileinfo/" + workid); } else { response.Redirect("/fq"); } return(true); } if (command.StartsWith("/action/forcestopfile/")) { string workid = command.Split('/').Last(); FileQueueStateInfo f = Program.get_file_state(workid); if (f != null) { f.ForceStop = true; response.Redirect("/fileinfo/" + workid); } else { response.Redirect("/fq"); } return(true); } if (command.StartsWith("/action/forcestopfile_thread/")) { string workid = command.Split('/').Last(); FileQueueStateInfo f = Program.get_file_state(workid); if (f != null) { f.ThreadBG.Cancel(true); response.Redirect("/fileinfo/" + workid); } else { response.Redirect("/fq"); } return(true); } if (command.StartsWith("/action/unbanfile")) { string hash = request.QueryString["hash"].Value; Program.unban_file(hash); response.Redirect("/bannedfiles"); return(true); } #endregion if (command == "/ua") { string ua = request.Headers["User-Agent"].ToLower(); write_text(string.Format("Your user agent: {0}<br/>Device support WebM: {1}", ua, !ChanArchiver.HttpServerHandlers.FileHandler.device_not_support_webm(ua)), response); return(true); } if (command == "/ua/t") { string ua = request.Headers["User-Agent"].ToLower(); if (!Program.uas_always_mp4.Contains(ua)) { Program.uas_always_mp4.Add(ua); write_text("added to mp4 list", response); return(true); } else { Program.uas_always_mp4.Remove(ua); write_text("removed from mp4 list", response); return(true); } } if (command.StartsWith("/get_archive_info/")) { string board = request.QueryString["b"].Value; StringBuilder sb = new StringBuilder(); var data = ArchivesProvider.GetArchivesForBoard(board, true); sb.AppendFormat("Result count: {0}<br/>", data.Count()); foreach (var d in data) { sb.AppendFormat("HOST: {0} <br/>", d.Domain); } write_text(sb.ToString(), response); return(true); } return(false); }