Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- module mspatest;
- import std.string, sqlite3, std.boehm, std.zlib, std.http, std.util, std.file;
- static import c.stdlib;
- import std.fun, std.cgi, std.process;
- import mspa;
- alias FOURSTRING = (string, string, string, string); // small shortcut
- alias FIVESTRING = (string, string, string, string, string);
- string filterTag(string tag) {
- char[auto~] filtered-tagname;
- for auto ch <- tag {
- if ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch >= "0" && ch <= "9"
- || "_- .,".find(""~ch) != -1
- filtered-tagname ~= ch;
- }
- return filtered-tagname[];
- }
- string getThreadName(string url) {
- url = url.between("?", "");
- if (auto first = url.between("", "/")) url = first;
- return url.between("-", "");
- }
- int counter;
- string reformatPost(string content, bool spoilers, string idText, bool linkToAnchors, noNyud = false) {
- /* strip out existing anchor links */
- do {
- auto startpos = content.find("#post");
- } while (startpos) {
- content = content[0 .. startpos] ~ "\"" ~ content[startpos .. $].between("\"", "");
- }
- if (linkToAnchors) {
- content = content.replace("href=\"showthread.php?p=", "href=\"#post");
- } else {
- content = content.replace("href=\"showthread.php?p=", "href=\"$idText");
- }
- string startMarker = "<!-- BEGIN TEMPLATE: bbcode_quote";
- string endMarker = "<!-- END TEMPLATE: bbcode_quote";
- string handleQuotes(string str) {
- do {
- auto quotePos = str.find(startMarker);
- auto endPos = str.find(endMarker);
- } while (quotePos && endPos && quotePos < endPos) {
- auto startPos = quotePos + startMarker.length;
- while (str[startPos .. endPos].find startMarker) != -1 {
- str = str[0 .. startPos] ~ handleQuotes str[startPos .. $]; // recurse
- endPos = str.find(endMarker);
- if (endPos == -1) {
- raise new Error "end marker no longer found after recursion step! unbalanced? $content";
- }
- }
- auto end = int:endPos;
- end += str[end .. $].find(">") + 1;
- auto quote = str[quotePos .. end];
- auto name = quote.between("<strong>", "</strong>");
- auto ref = quote.between("href=\"", "\"");
- auto msg = quote.between("class=\"message\">", "\t\t</div");
- auto newtext = "<table><tr><td valign=\"top\">></td><td><div style=\"border: 1px solid; \"><div><span style=\"border-bottom: 1px solid; \">Originally posted by <a href=\"$ref\">$name</a></span></div>";
- newtext = "$newtext$msg</td></tr></table>";
- str = str[0..quotePos] ~ newtext ~ str[end .. $];
- }
- return str;
- }
- string nyudImages(string src, string baseUrl) {
- int offset;
- do {
- int srcpos = src[offset .. $].find("src=\"");
- } while (srcpos != -1) {
- srcpos += offset;
- srcpos += 5;
- int endpos = src[srcpos .. $].find("\"");
- if (endpos == -1) raise new Error "Unterminated img src string wtf!! ";
- endpos += srcpos;
- auto tag = src[srcpos .. endpos];
- tag = baseUrl.followLink tag;
- tag = tag.startsWith "http://";
- tag = "http://" ~ slice(&tag, "/") ~ ".nyud.net/" ~ tag; // lol side effect abuse
- src = src[0 .. srcpos] ~ tag ~ src[endpos .. $];
- offset = srcpos + tag.length;
- }
- return src;
- }
- content = handleQuotes content;
- if (!noNyud) content = nyudImages (content, "http://www.mspaforums.com/");
- do {
- auto spoilerpos = content.find spoilertext;
- } while spoilerpos != -1 {
- string replacement;
- if (spoilers) {
- replacement = `<div style="border: 1px solid gray; padding: 1px; margin: 2px; "><span style="border: 1px dotted; ">Spoiler</span><div>`;
- } else {
- int id = counter ++;
- replacement = `<div style="border: 1px solid gray; padding: 1px; margin: 2px; "><span style="border: 1px dotted; ">
- <span class="box" id="??C_plus" onclick="javascript: css_show('??C'); css_show('??C_minus'); css_hide('??C_plus'); ">Show Spoiler</span>
- <span class="box" id="??C_minus" onclick="javascript: css_hide('??C'); css_show('??C_plus'); css_hide('??C_minus'); " style="display: none; ">Hide spoiler</span>
- </span><div id="??C" style="display: none; ">`.replace("??C", "spoilerdiv$id");
- }
- content = content[0..spoilerpos] ~ replacement ~ content[spoilerpos + spoilertext.length .. $];
- }
- content = content.replace("src=\"images/smilies", "src=\"http://www.mspaforums.com/images/smilies");
- content = content.replace("<b>", "<div class=\"inline bold\">").replace("</b>", "</div>");
- return content;
- }
- // prevent google from following links that potentially go to very large pages
- alias sharedCSS = `
- <meta name="robots" content="index, nofollow" />
- <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
- <link rel="shortcut icon" href="favicon.ico" />
- <style type="text/css">
- table.boxed {
- border: 1px solid black;
- border-collapse: collapse;
- }
- th {
- border-bottom: 2px solid black;
- }
- th.first, th.mid, td.first, td.mid {
- border-right: 1px solid gray;
- }
- tr.even {
- background-color: #def;
- }
- div.plustag:hover *.hidden {
- visibility: visible;
- }
- div.minustag:hover *.hidden {
- visibility: visible;
- }
- div.inline {
- display: inline;
- }
- *.bold {
- font-weight: bold;
- }
- *.box {
- border: 1px solid;
- background-color: #fff;
- padding: 0px 2px 0px 2px;
- margin: 1px;
- }
- *.box_outer {
- border: 1px solid;
- background-color: #fff;
- padding: 0px 2px 0px 2px;
- margin: 5px;
- }
- *.box_inner {
- border: 1px solid;
- padding: 0px 2px 0px 2px;
- margin: 1px;
- background-color: #efe;
- }
- *.hidden {
- visibility: hidden;
- position: absolute;
- background-color: #ddd;
- }
- div.mewdiv {
- position: absolute;
- display: inline;
- background-color: #eef;
- visibility: hidden;
- width: 60%; height: 90%;
- }
- table.mewtable {
- width: 100%; height: 100%;
- border-collapse: collapse;
- }
- iframe.mewframe {
- width: 100%; height: 100%;
- background-color: #ffe;
- }
- </style>`;
- alias sharedJS = `
- <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
- <script type="text/javascript">
- function submitForm(name) {
- document.getElementById(name).submit();
- }
- function loadFrame(name, divname, url) {
- $('.mewdiv').css('visibility', 'hidden');
- var frame = document.getElementById(name), div = document.getElementById(divname);
- frame.src = url;
- div.style.visibility = "visible";
- scrollToThingy (div);
- }
- function scrollToThingy (thing) {
- var targetY = 0;
- while (thing) {
- targetY += thing.offsetTop;
- thing = thing.offsetParent;
- }
- window.scroll(0, targetY);
- }
- function css_show (name) {
- document.getElementById(name).style.display = "inline";
- }
- function css_hide (name) {
- document.getElementById(name).style.display = "none";
- }
- </script>`;
- import c.stdio, std.time;
- extern(C) { int fprintf(void*, char*, ...); void* stderr; }
- void main(string[] args) {
- sqlite3.profile = false;
- bool wroteHeader;
- void writeHTMLHeader(bool doctype = true) {
- if (wroteHeader) return;
- writeln "Content-type: text/html; charset=utf-8";
- writeln "";
- if (doctype) {
- writeln `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">`;
- writeln `<html xmlns="http://www.w3.org/1999/xhtml">`;
- } else {
- writeln `<html>`;
- }
- wroteHeader = true;
- }
- set-handler (Error err) {
- writeHTMLHeader();
- writeln "<head><title>Error</title></head><body>";
- writeln "<h2>An error has occurred! </h2>";
- writeln "$err";
- writeln "</body></html>";
- invoke-exit "return";
- }
- set-handler (SQLiteBusy) {
- fprintf(FILE*:stderr, "Database busy. \n");
- sleep 1;
- fprintf(FILE*:stderr, "Retrying. \n");
- invoke-exit "retry";
- }
- define-exit "return" return;
- initBoehm();
- auto db = new Database "threads.sqlite3";
- onExit db.close;
- db.mkfast;
- onSuccess if sqlite3.profile {
- void errprint(string s) fprintf(FILE*:stderr, toStringz "$s\n");
- errprint "profile: ";
- for auto tup <- profiledata {
- errprint " $(tup[2]): $(tup[1]): $(tup[0])";
- }
- }
- string getEnvVar(string name) {
- return CToString c.stdlib.getenv toStringz name;
- }
- auto query_string = getEnvVar "QUERY_STRING";
- auto http_cookie = getEnvVar "HTTP_COOKIE";
- // lol wtf
- while (query_string.find("&") != -1) {
- query_string = query_string.replace("&", "&");
- }
- (string, string)[auto~] params;
- for auto part <- query_string.split "&" {
- if (part.find("=") != -1)
- params ~= slice(part, "=");
- else
- params ~= (part, "");
- }
- void processCookie() {
- if (http_cookie) {
- (string, string)[auto~] cookieparts;
- for auto part <- http_cookie.split(";") {
- auto name = slice(&part, "=");
- cookieparts ~= (strip name, strip part);
- }
- for (string name, string value) <- cookieparts if name == "idmask" {
- bool hit;
- for int i <- 0..params.length if !hit {
- if (params[i][0] == "idmask") {
- params[i][1] = "$value";
- hit = true;
- }
- }
- if !hit params ~= ("idmask", "$value");
- }
- }
- }
- string getParam(string name, deflt = null) {
- for auto par <- params
- if (par[0] == name) return par[1].urldecode();
- return deflt;
- }
- void removeParam(string name) {
- (string, string)[auto~] newparams;
- for auto par <- params
- if (par[0] != name) newparams ~= par;
- params = newparams;
- }
- bool noNyud = getParam("nyud") == "0";
- string urlWithParams((string, string)[] array) {
- string[auto~] res;
- auto handledEntries = new bool[] array.length;
- for auto par <- params {
- bool foundReplacement;
- for (int i, (string, string) tup) <- zip(ints, array) if !foundReplacement {
- if (par[0] == tup[0]) {
- if (tup[1]) res ~= "$(tup[0])=$(tup[1])";
- handledEntries[i] = true;
- foundReplacement = true;
- }
- }
- if !foundReplacement res ~= "$(par[0])=$(par[1])";
- }
- for (int i, bool handled) <- zip(ints, handledEntries)
- if !handled res ~= "$(array[i][0])=$(array[i][1])";
- return "?" ~ join!(string[auto~], string)(res, "&");
- }
- string urlWithParam(string name, value) {
- return urlWithParams [(name, value)];
- }
- string authormask, authormask-sql = "and not length(?)";
- if auto author = getParam "author" {
- auto alts = author.split("|");
- int offs;
- authormask = author;
- authormask-sql = "select ? AUTHORMASK where 0";
- for auto alt <- alts {
- authormask-sql ~= " or posts.name = substr(AUTHORMASK, $(offs+1), $(alt.length))";
- offs += alt.length + 1; // for "|"
- }
- authormask-sql = "and exists ($authormask-sql)";
- }
- string threadmask, threadmask-sql = "and not length(?)";
- if auto thread = getParam "thread" {
- threadmask = thread;
- threadmask-sql = "and thread_ids.thread_id = ?";
- }
- string tagmask, tagmask-sql = "and not length(?)";
- if auto tag = getParam "tag" {
- tagmask = tag;
- tagmask-sql = "and tags.tag = ?";
- }
- bool textmask;
- string textmask-sql = "where 1";
- if "yes" == getParam ("noTextPosts", "no") {
- textmask = true;
- textmask-sql = "join image_post on thread_ids.msgid = image_post.msgid where 1";
- }
- string idmask, idmask-sql = "and not length(?)";
- if auto id = getParam "idmask" {
- idmask-sql = "select ? IDMASK where 0";
- while (id.length) {
- if (auto rest = id.startsWith "from_") {
- int from = atoi slice(&rest, "_");
- id = rest;
- auto start = idmask.length;
- idmask ~= "$from";
- auto len = idmask.length - start;
- idmask-sql ~= " or abs(posts.msgid) >= abs(substr(IDMASK, $(start+1), $(len)))";
- } else {
- raise new Error "Invalid id: $id (cookie $http_cookie)";
- }
- }
- idmask-sql = "and exists ($idmask-sql)";
- }
- int count = -1;
- if auto c = getParam "count"
- count = atoi c;
- bool showSpoilers;
- if (getParam("spoilers") == "visible") showSpoilers = true;
- void writeSiteHeader(bool handleSpoilers, linkToOverview, linkToList, linkToFullView, showRSS = true, floatIt = true, showFilters = true, string additionalText = null) {
- if (floatIt) writeln "<div style=\"background-color: #eef; position: fixed; top: 0px; border: 1px solid; \">";
- else writeln "<div style=\"background-color: #eef; border: 1px solid; \">";
- bool firstLine = true;
- int linecount;
- void myWriteLine(string msg, bool sameLine = false) {
- if (firstLine) { firstLine = false; linecount = 1; }
- else if (!sameLine) {
- writeln "<br />";
- linecount ++;
- }
- writeln msg;
- }
- if (linkToOverview) myWriteLine "<a href=\"$(urlWithParam(\"site\", \"main\"))\">Back to overview</a> | ";
- if (handleSpoilers) {
- string spoiler-change;
- if showSpoilers {
- spoiler-change = "<a href=\"$(urlWithParam(\"spoilers\", null))\">Hide Spoilers</a> ";
- } else {
- spoiler-change = "<a href=\"$(urlWithParam(\"spoilers\", \"visible\"))\">Always Show Spoilers</a> |";
- }
- myWriteLine ("$spoiler-change", true);
- }
- if (linkToList) myWriteLine ("<a href=\"$(urlWithParam(\"site\", \"overview\"))\">Go to post list</a> |", true);
- if (linkToFullView) myWriteLine ("<a href=\"$(urlWithParams [(\"site\", \"full-html\"), (\"count\", \"50\")])\">
- Go to full HTML view</a> |", true);
- if (showRSS) myWriteLine ("<a href=\"$(urlWithParams [(\"site\", \"rss\"), (\"count\", string:null)])\">RSS</a> |", true);
- myWriteLine ("<a href=\"$(urlWithParam(\"noTextPosts\", \"yes\"))\">No Text Posts</a>", true);
- myWriteLine (additionalText, true);
- if (showFilters) {
- if (authormask) {
- myWriteLine "Filter by author: $authormask (<a href=\"$(urlWithParam(\"author\", null))\">remove</a>)";
- }
- if (threadmask) {
- myWriteLine "Filter by thread: $threadmask (<a href=\"$(urlWithParam(\"thread\", null))\">remove</a>)";
- }
- if (tagmask) {
- myWriteLine "Filter by tag: $tagmask (<a href=\"$(urlWithParam(\"tag\", null))\">remove</a>)";
- }
- if (idmask) {
- myWriteLine "Only show posts after $idmask (<a href=\"$(urlWithParam(\"id\", null))\">remove</a>)";
- }
- if (count != -1) {
- myWriteLine "Only show $count posts (<a href=\"$(urlWithParam(\"count\", null))\">remove</a>)";
- }
- if (textmask) {
- myWriteLine "Filter: show only image posts (<a href=\"$(urlWithParam(\"noTextPosts\", null))\">remove</a>)";
- }
- }
- writeln "</div>";
- if floatIt
- for 0..linecount
- writeln "<br style=\"clear: both; \" />";
- }
- void writeFooter() {
- writeln "<div style=\"color: #aaa; font-size: 70%; \">disclaimer: all copyrights remain with the respective owners. this site acts merely as a caching layer for mspaforums.com and tgchan.org;
- the creator disclaims all liability for the site itself or the content displayed within. </div>";
- }
- auto site = getParam ("site");
- if (!site || site == "main") {
- removeParam("id"); // cleanup
- writeHTMLHeader();
- writeln "<head><title>Thread Overview</title>";
- writeln sharedCSS;
- writeln sharedJS;
- writeln "</head><body>";
- onSuccess {
- p \{
- a.href "http://validator.w3.org/check?uri=referer"
- $img #.src "http://www.w3.org/Icons/valid-xhtml10" #.alt "Valid XHTML 1.0 Transitional" #.height 31 #.width 88;
- a.href "http://jigsaw.w3.org/css-validator/check/referer"
- $img #.style "border:0;width:88px;height:31px" #.src "http://jigsaw.w3.org/css-validator/images/vcss" #.alt "Valid CSS!";
- $img #.src "valid-rss-rogers.png" #.height 31 #.alt "RSS feeds validated";
- }
- writeFooter();
- writeln "</body></html>";
- }
- writeln "<div>";
- writeSiteHeader(handleSpoilers => false, linkToOverview => false, linkToList => true, linkToFullView => true, showRSS => eval authormask || threadmask || tagmask);
- writeln "</div>";
- writeln "<p>";
- (string, string)[] postParams;
- string getPostParam(string name, deflt = null) {
- for auto par <- postParams
- if (par[0] == name) return par[1];
- return deflt;
- }
- if (getEnvVar "REQUEST_METHOD") == "POST" {
- auto postText = string: join readfile 0;
- // wtf some more
- while (postText.find("&") != -1) {
- postText = postText.replace("&", "&");
- }
- // writeln "Post mode <br />";
- // writeln "$postText";
- for auto part <- postText.split "&" {
- (string name, string value) = slice(part, "=");
- value = urldecode value;
- postParams ~= (name, value);
- }
- auto action = getPostParam("action");
- if (action == "add_tag") {
- string tagname = filterTag getPostParam "tagname";
- if (!tagname.length)
- writeln "Tag invalid! debug $postParams";
- else {
- int threadId = getPostParam "threadId" #.atoi();
- db.exec("insert or replace into tags(thread_id, tag) values(?, ?)", threadId, tagname);
- }
- }
- if (action == "rm_tag") {
- string tagname = filterTag getPostParam "tagname";
- if (!tagname.length)
- writeln "Tag invalid! ";
- else {
- int threadId = getPostParam "threadId" #.atoi();
- db.exec("delete from tags where thread_id=? and tag=?", threadId, tagname);
- }
- }
- if (action == "add_thread") {
- string url = getPostParam "url";
- string[] tags = getPostParam "tags" #.split "," #.map &strip #.eval[];
- void addThread(string url) {
- db.exec("insert or replace into page_urls (msgid, page_url) values(null, ?)", url);
- }
- void update(string[] urls) {
- join readback("./mspa_update.sh", urls);
- }
- void setTags(string url) {
- eval int id <- db.exec("select distinct thread_id from page_urls left outer join thread_ids where page_url = ? and page_urls.msgid = thread_ids.msgid", url);
- if tags.length && tags[0] {
- db.exec("delete from tags where thread_id = ?", id);
- for auto tag <- tags
- db.exec("insert or replace into tags(thread_id, tag) values(?, ?)", id, tag);
- }
- }
- if (url.find("tgchan.org/wiki/")) {
- auto links = string: url.downloadCached() #.betweens("href=\"", "\"") #.select \(string s) -> s.find "tgchan.org/kusaba/quest/" #.eval;
- for auto link <- links addThread (link);
- update links[];
- for auto link <- links setTags (link);
- writeln "$(links.length) threads added! ";
- } else if (!url.startsWith("http://www.mspaforums.com/showthread.php?") && !url.startsWith "http://tgchan.org/kusaba/") {
- writeln "Can only submit MSPA or tgchan threads/wiki pages! ";
- } else {
- if (auto base = url.between("", "/page")) url = base;
- addThread (url);
- update [url];
- setTags (url);
- writeln "Thread added!";
- }
- }
- }
- writeln "</p>";
- form #.action "?site=main" #.method "post" p \{
- text "URL";
- input #.type "text" #.name "url" #.size 40;
- input #.type "submit" #.value "Add Thread";
- br;
- text "Tags";
- input #.type "text" #.name "tags" #.size 28;
- input #.type "hidden" #.name "action" #.value "add_thread";
- }
- p \{
- writeln "Hint: You can add Tags to threads! To do this, use the + symbol next to the threads. Then, by clicking on the tag name, you can select only threads that have the same tag."; br;
- writeln "This is useful if you want to follow a quest that spans multiple threads."; br;
- }
- writeln "<table class=\"boxed\">";
- onSuccess writeln "</table>";
- tr \{
- th #.class "first" "Thread";
- th #.class "mid" "Starter";
- th #.class "mid" "Posts";
- th #.class "mid" "First post date";
- th #.class "mid" "Last post date";
- th #.class "last" "Tags";
- }
- auto evenodd_iter = loop ["even", "odd"];
- int formid;
- if (getParam("hax") == "yes") {
- for (int msgid, ubyte[] data) <- db.exec "select msgid, content from content" {
- auto pureText = removeSpoilers string: inflate data;
- bool hasVisiblePics = eval pureText.find("img src=\"http") != -1;
- if (hasVisiblePics) {
- db.exec("insert or replace into image_post (msgid) values(?)", msgid);
- } else {
- db.exec("insert or replace into text_post (msgid) values(?)", msgid);
- }
- }
- return;
- }
- for (string thread, int thread_id, string threadname) <- db.exec ("
- select page_url, A.thread_id, titles.title from (
- select thread_ids.thread_id, thread_ids.msgid from thread_ids
- left outer join tags on thread_ids.thread_id = tags.thread_id
- $textmask-sql $tagmask-sql $threadmask-sql
- group by thread_ids.thread_id
- ) A
- join page_urls B on A.msgid=B.msgid
- join posts on A.msgid=posts.msgid
- left outer join titles on A.thread_id=titles.thread_id
- order by A.thread_id desc", tagmask, threadmask)
- {
- (thread, string bogus) = slice(thread, "/page");
- if (!threadname)
- threadname = getThreadName thread;
- db.openStatementList();
- eval (string threadStarter, int threadStarterId) <- db.exec("
- select name, A.msgid from thread_ids A
- join postnums B on A.msgid = B.msgid
- join posts C on A.msgid = C.msgid
- where A.thread_id=? and B.postnr=1", thread_id);
- if (!authormask || authormask == threadStarter) {
- eval int posts <- db.exec("select count(*) from thread_ids join posts on thread_ids.msgid = posts.msgid $textmask-sql and thread_id=? $authormask-sql", thread_id, authormask);
- eval int maxPostNum <- db.exec("
- select max(postnr) from thread_ids A
- join posts on A.msgid = posts.msgid
- join postnums B on A.msgid = B.msgid
- where thread_id=? $authormask-sql", thread_id, authormask);
- eval string firstDate <- db.exec ("select date from posts where msgid=? $authormask-sql", threadStarterId, authormask);
- eval (string lastDate, int lastDateId) <- db.exec("
- select posts.date, posts.msgid from thread_ids A
- join postnums B on A.msgid = B.msgid
- join posts on A.msgid = posts.msgid
- where A.thread_id=? and B.postnr=? $authormask-sql", thread_id, maxPostNum, authormask);
- string[auto~] tags;
- for string tag <- db.exec("select tag from tags where thread_id = ?", thread_id)
- tags ~= tag.dup;
- string genTag(string tag) {
- string res = "<div class=\"inline box\"><a href=\"$(urlWithParam(\"tag\", \"$tag\"))\">$tag</a></div>";
- /*string minus;
- using scoped outputfn = \(string s) minus ~= s; {
- b "-";
- div #.class "hidden box inline" \{
- form #.id "form$formid" #.method "post" #.action "#" \{
- input #.type "hidden" #.name "threadId" #.value "$thread_id");
- input #.type "hidden" #.name "tagname" #.value "$tag";
- input #.type "hidden" #.name "action" #.value "rm_tag";
- a #.href "javascript:submitForm('form$formid');" "Remove Tag";
- }
- }
- }
- res = "$res<div class=\"minustag inline box\" style=\"vertical-align: super; \">$minus</div>";*/
- formid ++;
- return res;
- }
- string tagstr = [for str <- tags extra &genTag: extra(str)].join ", ";
- string firstDateText = "$firstDate";
- string lastDateText = "$lastDate";
- if (thread_id >= 0) {
- firstDateText = "<a href=\"http://www.mspaforums.com/showthread.php?$thread_id\">$firstDate</a>";
- lastDateText = "<a href=\"http://www.mspaforums.com/showthread.php?$thread_id&p=$lastDateId&viewfull=1#post$lastDateId\">$lastDate</a>";
- }
- eval string evenodd <- evenodd_iter;
- // writeln "TEST <<$evenodd>>";
- tr .class evenodd \{
- td .class "first" a .href urlWithParam("thread", "$thread_id") threadname;
- td .class "mid" a .href urlWithParam("author", threadStarter) threadStarter;
- td .class "mid" "$posts";
- td .class "mid" firstDateText;
- td .class "mid" lastDateText;
- td .class "last" \{
- text tagstr;
- div .class "plustag inline box" \{
- text "+";
- div #.class "hidden box inline " #.style "position: absolute; " \{
- form #.id "form$formid" #.method "post" #.action "#" \{
- input #.type "text" #.name "tagname";
- input #.type "hidden" #.name "threadId" #.value "$thread_id";
- input #.type "hidden" #.name "action" #.value "add_tag";
- a #.href "javascript:submitForm('form$formid');" "Add Tag";
- }
- }
- }
- }
- formid ++;
- }
- }
- db.finStatementList();
- }
- return;
- }
- if (site == "overview") {
- writeHTMLHeader(doctype => false);
- std.cgi.head \{
- title "Overview";
- text sharedCSS;
- text sharedJS;
- }
- writeln "<body>";
- onSuccess {
- writeFooter();
- writeln "</body></html>";
- }
- writeSiteHeader(handleSpoilers => true, linkToOverview => true, linkToList => false, linkToFullView => true, floatIt => false);
- {
- writeln "<table class=\"boxed\">";
- tr \{
- th.class "first" "Thread";
- th.class "mid" "Name";
- th.class "mid" "Date";
- th.class "last" "Post ID";
- }
- auto evenodd_iter = loop ["even", "odd"];
- int iframe_id;
- void writeRowFor(string page_url, int next_msg_id, msg_id, prev_msg_id, string name, string date, bool showSpoilers) {
- eval string evenodd <- evenodd_iter;
- string threadname = getThreadName page_url;
- string spoilerpar;
- if (showSpoilers) spoilerpar = "&spoilers";
- string next_post_link = "?site=rss&id=$next_msg_id$spoilerpar";
- string post_link = "?site=rss&id=$msg_id$spoilerpar";
- string prev_post_link = "?site=rss&id=$prev_msg_id$spoilerpar";
- tr.class evenodd \{
- td.class "first" threadname;
- td.class "mid" a.href urlWithParam("author", name) name;
- td.class "mid" date;
- td.class "last" \{
- a.href "javascript: loadFrame('mewframe$iframe_id', 'mewdiv$iframe_id', '$post_link'); " "$msg_id";
- div #.class "mewdiv" #.id "mewdiv$iframe_id" \{
- table.class "mewtable boxed" \{
- tr.style "height: 20px; " \{
- td.onclick "javascript:loadFrame('mewframe$(iframe_id-1)', 'mewdiv$(iframe_id-1)', '$prev_post_link');" "< Back";
- td.onclick "javascript:loadFrame('mewframe$(iframe_id+1)', 'mewdiv$(iframe_id+1)', '$next_post_link');" "Forth >";
- }
- tr td.colspan 2 $ iframe #.class "mewframe" #.id "mewframe$iframe_id" #.src "" #.scrolling "auto" #.frameborder 0 "mew!";
- }
- }
- }
- }
- writeln("");
- iframe_id ++;
- }
- {
- auto first = cat([true], loop [false]);
- string page_url;
- int msg_id = -1, prev_msg_id = -1;
- string name, date;
- bool aborted;
- alias limit = 64;
- string sqltext = "
- select page_urls.page_url, posts.msgid, name, date from posts
- join thread_ids on posts.msgid = thread_ids.msgid
- join page_urls on posts.msgid = page_urls.msgid
- join (
- select thread_ids.thread_id, thread_ids.msgid from thread_ids
- left outer join tags on thread_ids.thread_id = tags.thread_id
- where 1 $tagmask-sql $threadmask-sql
- group by thread_ids.thread_id
- ) B on thread_ids.thread_id = B.thread_id
- join date_codes on posts.msgid = date_codes.msgid
- $textmask-sql $authormask-sql
- order by date_codes.datecode asc";
- for (int i, (string next_page_url, int next_msg_id, string next_name, string next_date)) <- zip(0..limit, db.exec!FOURSTRING!(string, int, string, string)(sqltext, tagmask, threadmask, authormask))
- {
- eval bool b <- first;
- if !b {
- writeRowFor (page_url, next_msg_id, msg_id, prev_msg_id, name, date, showSpoilers);
- prev_msg_id = msg_id;
- }
- (page_url, msg_id, name, date) = (next_page_url.dup, next_msg_id, next_name.dup, next_date.dup);
- if (i == limit - 1) aborted = true;
- }
- if (aborted) {
- writeln "</table>";
- writeln "<br />";
- writeln "Rest omitted due to sanity checking. ";
- } else {
- writeRowFor (page_url, -1, msg_id, prev_msg_id, name, date, showSpoilers);
- writeln "</table>";
- }
- // writeln ">> $sqltext";
- }
- }
- return;
- }
- alias base_url = "http://demented.no-ip.org/~feep/threadfeed.cgi";
- if (site == "rss") {
- processCookie();
- if auto id = getParam "id" {
- bool spoilers = eval getParam ("spoilers");
- writeHTMLHeader();
- writeln "<head><title>Post view</title>";
- writeln sharedCSS;
- writeln sharedJS;
- writeln "</head><body>";
- onSuccess {
- writeFooter();
- writeln "</body></html>";
- }
- auto msgid = id.atoi;
- eval int thread_id <- db.exec("select thread_id from thread_ids where msgid = ?", msgid);
- string backlink = "| <a href=\"http://www.mspaforums.com/showthread.php?$thread_id&p=$msgid&viewfull=1#post$msgid\">MSPA forum link</a>";
- writeSiteHeader(handleSpoilers => true, linkToOverview => true, linkToList => false, linkToFullView => false,
- showRSS => false, floatIt => false, showFilters => false, additionalText => backlink);
- for ubyte[] data <- db.exec("select content from content where msgid = ?", msgid)
- {
- string idText = urlWithParam("id", "");
- string content = reformatPost (string: inflate data, spoilers, idText, linkToAnchors => false, noNyud => noNyud);
- writeln "$content";
- }
- return;
- }
- string sqlcode = "
- select posts.msgid, postnr, A.thread_id, name, date, content from
- (
- select thread_ids.thread_id, msgid from thread_ids
- left outer join tags on thread_ids.thread_id = tags.thread_id
- where 1 $tagmask-sql $threadmask-sql
- group by thread_ids.thread_id
- ) A
- join thread_ids on A.thread_id = thread_ids.thread_id
- join posts on posts.msgid = thread_ids.msgid
- join postnums C on C.msgid = thread_ids.msgid
- join content D on D.msgid = thread_ids.msgid
- join date_codes on date_codes.msgid = thread_ids.msgid
- $textmask-sql $authormask-sql $idmask-sql
- order by date_codes.datecode asc";
- alias Tup = (int, int, int, string, string, string);
- auto qit = db.exec!FIVESTRING!Tup(sqlcode, tagmask, threadmask, authormask, idmask);
- int lastMsgId;
- for (int msgId, int postId, int threadId, string name, string date, string content) <- qit {
- lastMsgId = msgId;
- }
- writeln "Content-type: application/rss+xml";
- if (lastMsgId != 0)
- writeln "Set-Cookie: idmask=from_$lastMsgId";
- writeln "";
- writeln "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>";
- writeln "<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">";
- onSuccess writeln "</rss>";
- writeln "<channel>";
- onSuccess writeln "</channel>";
- writeln "<title>Thread Feed</title>";
- writeln "<link>$base_url</link>";
- writeln "<description>RSS feed for MSPA and tgchan forums</description>";
- // writeln "<atom:link href=\"$base_url?$query_string\" rel=\"self\" type=\"application/rss+xml\" />";
- qit = db.exec!FIVESTRING!Tup(sqlcode, tagmask, threadmask, authormask, idmask);
- for (int msgId, int postId, int threadId, string name, string date, string content) <- qit
- {
- // parse the date
- date.cleanupDate();
- writeln "<item>";
- onSuccess writeln "</item>";
- writeln "<title>$name</title>";
- writeln "<pubDate>$date</pubDate>";
- writeln "<guid isPermaLink=\"false\">mspa_forum_post_id_on_feeps_rss_$msgId</guid>";
- writeln "<link>$base_url$(urlWithParam(\"id\", \"\\$msgId\"))</link>"; // .replace("&", "&"); /* not necessary for rss */
- // writeln "<link>$base_url?id=$msgId</link>";
- }
- return;
- }
- if (site == "full-html") {
- string sqlcode = "
- select content, name, date, posts.msgid, thread_ids.thread_id from
- (
- select thread_ids.thread_id, msgid from thread_ids
- left outer join tags on thread_ids.thread_id = tags.thread_id
- where 1 $tagmask-sql $threadmask-sql
- group by thread_ids.thread_id
- ) A
- join thread_ids on A.thread_id = thread_ids.thread_id
- join posts on thread_ids.msgid = posts.msgid
- join content B on posts.msgid = B.msgid
- join date_codes on posts.msgid = date_codes.msgid
- $textmask-sql $authormask-sql $idmask-sql
- order by date_codes.datecode asc";
- auto qit = db.exec!FIVESTRING!(ubyte[], string, string, int, int)(sqlcode, tagmask, threadmask, authormask, idmask);
- if (getParam("funtimemode") == "yes") {
- writeln "Content-type: text/html";
- writeln "";
- for (ubyte[] data, string name, string date, int postId, int threadId) <- qit {
- auto text = string: inflate data #.dup;
- // writeln "[$name]";
- /*char[auto~] newtext;
- while (text.length) {
- void flush(int to) { newtext ~= text[0 .. to]; }
- auto bpos = text.find("<b>");
- auto bcpos = text.find("</b>");
- if (bpos != -1 && bpos < bcpos) {
- text = text[bpos + 3 .. $];
- }
- else if (bcpos != -1 && bcpos < bpos) {
- flush bcpos;
- text = text[bcpos + 4 .. $];
- } else text = new char[] 0;
- }
- text = newtext[];*/
- writeln string:text;
- }
- return;
- }
- writeHTMLHeader();
- writeln "<head><title>Full HTML View</title>";
- writeln sharedCSS;
- writeln sharedJS;
- writeln "</head><body>";
- // writeln ">> $sqlcode";
- onSuccess {
- writeFooter();
- writeln "</body></html>";
- }
- writeSiteHeader(handleSpoilers => true, linkToOverview => true, linkToList => true, linkToFullView => false, floatIt => false);
- if (!authormask && !tagmask && !threadmask) {
- writeln "Uh-oh! You loaded the Full-HTML view but no author, thread or tag mask is set! <br />
- This means that I should by all rights dump my entire post database at your feet now. <br />
- Since I'm a nice person and don't want to crash your system, I'm not going to do that. <br />
- You should go back. There is nothing for you here. ";
- return;
- }
- void loopBody(ubyte[] data, string name, date, int postId, threadId) {
- string idText = urlWithParam("id", "");
- string content = reformatPost (string: inflate data #.dup, showSpoilers, idText, linkToAnchors => true, noNyud => noNyud);
- a.name "post$postId" "";
- div.class "box_outer" \{
- string backlink = "http://www.mspaforums.com/showthread.php?$threadId&p=$postId&viewfull=1#post$postId";
- div.class "box_inner" \{
- b "Name: ";
- text name;
- text " ";
- b "Date: ";
- text date;
- text " ";
- b \{ if (postId >= 0) a.href backlink "MSPA link"; } // otherwise non-mspa
- a #.style "text-decoration: none; color: #cdc; " #.href urlWithParam("idmask", "from_$postId") "▼";
- }
- text content;
- }
- }
- if (count == -1) {
- for (ubyte[] data, string name, string date, int postId, int threadId) <- qit {
- loopBody(data, name, date, postId, threadId);
- }
- } else {
- int lastPostId = 0;
- for (int k, (ubyte[] data, string name, string date, int postId, int threadId)) <- zip(0..count + 1, qit) {
- if (k != count) loopBody(data, name, date, postId, threadId);
- else lastPostId = postId;
- }
- if (lastPostId != 0) {
- int left = 1;
- int[auto~] restIds;
- for (ubyte[] data, string name, string date, int postId, int threadId) <- qit { restIds ~= postId; }
- left += restIds.length;
- string extralink;
- a .href urlWithParam("idmask", "from_$lastPostId") "Next";
- if (restIds.length) {
- int lastpage;
- if (count < restIds.length) lastpage = restIds[$-count+1];
- else lastpage = restIds[0];
- text "($left posts left)";
- a.href urlWithParam("idmask", "from_$lastpage") "Last Page";
- }
- br;
- }
- }
- return;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment