From: b Date: Fri, 18 Sep 2015 12:00:00 +0000 (+0000) Subject: Initial state as of 18.09.2015. X-Git-Tag: v1.0.0~17 X-Git-Url: http://bicyclesonthemoon.info/git-projects/?a=commitdiff_plain;h=44057234ce6be46e9dd835b0639cea230284e85d;p=ott%2Fpost Initial state as of 18.09.2015. --- 44057234ce6be46e9dd835b0639cea230284e85d diff --git a/bb2html.awk b/bb2html.awk new file mode 100644 index 0000000..b051bcc --- /dev/null +++ b/bb2html.awk @@ -0,0 +1,688 @@ +#// bb2html.awk +#// converts bbcode to html. +#// 30.03.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero General Public License as +#// published by the Free Software Foundation, either version 3 of the +#// License, or (at your option) any later version. +#// +#// This program is distributed in the hope that it will be useful, +#// but WITHOUT ANY WARRANTY; without even the implied warranty of +#// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#// GNU Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + FS="=" + debug="debug=bb2html.awk:" + automome="/eizm/pro/ong1/mome.pl" + memepath="/eizm/mem/ong1/mome.txt" + + for(i=0;i<256;++i) + { + ch=sprintf("%c",i) + hex=sprintf("%02X",i) + dec=sprintf("%u",i) + ch2hex[ch]=hex + ch2dec[ch]=dec + } +}; +{ + eq=index($0,"=") + argtab[substr($0,1,eq-1)]=substr($0,eq+1) +}; +END{ + if(argtab["disable_bbcode"]!="") + { + debug=debug"###nl;BBcode disabled" + print debug>>outfile + exit 0 + } + text=argtab["BB"] + html=bb2html(text) + print "HTML="html>>outfile + print debug>>outfile + + # if(tempfile!="") + # { + # text=argtab["message"] + # gsub(/%5Bbr%5D/,"\n",text) + # while(sub(/%5Bong%5D/,ong(),text)>0){print text} + # while(sub(/%5Bung%5D/,ung(),text)>0){print text} + # while(sub(/%5Bong%3Ddecree%5D/,ong("decree"),text)>0){print text} + # while(sub(/%5Bung%3Ddecree%5D/,ung("decree"),text)>0){print text} + # if(text!=argtab["message"]) + # print "message="text >> outfile + # } +}; + +function bb2html(text, depth,count,bbtree,html,tag,tagstart,taglength,elm,tagv,tagname,tagvalue,matchname) +{ + depth=0 + count[0]=1 + bbtree["0"]="" + bbtree["0.n"]=0 + bbtree["0.t"]="post" + bbtree["0.v"]=argtab["subject"] + html="" + gsub(/=/,"=",text) + debug = debug "###nl;###nl;Build BBcode tree:" + while(length(text)!=0) + { + tag=match(text, /\[\/?[a-z0-9\*]+(=(([^\[<>\"\]]*)|(\"[^\"<>]*\")))?\]/) + #"#\"" + # debug = debug "###nl;" RSTART " " RLENGTH + if (tag==0) + { + debug = debug "###nl;text: " text + bbtree[ind(count,depth)]=text + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + text="" + break; + } + tagstart=RSTART + taglength=RLENGTH + if(tagstart>1) + { + elm=substr(text,1,tagstart-1) + debug = debug "###nl;text: " elm + bbtree[ind(count,depth)]=elm + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + } + tag=substr(text,tagstart,taglength) + text=substr(text,tagstart+taglength) + debug = debug "###nl;tag: " tag + if(tag!~/^\[\//) + { + tagv=index(tag,"=") + if(tagv<2) + { + tagname=substr(tag,2,length(tag)-2) + tagvalue="" + } + else + { + tagname=substr(tag,2,tagv-2) + tagvalue=substr(tag,tagv+1,length(tag)-tagv-1) + } + if(tagname !~ /^((quote)|b|i|u|(code)|(img)|(url)|(size)|(color)|(center)|(right)|(sub)|(sup)|(s)|(spoiler)|(list)|(\*))$/) + { + debug = debug "###nl;unknown tag" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + if((bbtree[indt(count,depth)".t"] == "code" && tagname!="code")||bbtree[indt(count,depth)".t"] == "img"||(bbtree[indt(count,depth)".t"] == "spoiler" && tagname=="spoiler")||(bbtree[indt(count,depth)".t"] == "size" && tagname=="size")) + { + debug = debug "###nl;this tag forbidden here" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + if(tagname=="*") + { + if(bbtree[indt(count,depth)".t"]==tagname) + { + debug = debug "###nl;implied tag: [/"tagname"]" + debug = debug "###nl;matched" + bbtree[ind(count,depth)]="[/"tagname"]" + bbtree[ind(count,depth)".k"]="e" + bbtree[ind(count,depth)".m"]=1 + bbtree[ind(count,depth)".t"]=tagname + bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + bbtree[indt(count,depth)".n"]=count[depth] + bbtree[indt(count,depth)".m"]=1 + count[depth]="" + --depth + ++count[depth] + } + else if(bbtree[indt(count,depth)".t"]!="list") + { + debug = debug "###nl;this tag forbidden here" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + } + debug = debug "###nl;name: " tagname " value: " tagvalue + bbtree[ind(count,depth)]=tagname" "tagvalue + bbtree[ind(count,depth)".k"]="s" + bbtree[indt(count,depth)".n"]=count[depth] + ++depth + count[depth]=1 + bbtree[indt(count,depth)]=tag + bbtree[indt(count,depth)".n"]=0 + bbtree[indt(count,depth)".t"]=tagname + bbtree[indt(count,depth)".v"]=tagvalue + } + else + { + if(depth<=0) + { + debug = debug "###nl;""unmatched" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + tagname=substr(tag,3,length(tag)-3) + if(tagname=="list"&&bbtree[indt(count,depth)".t"]=="*") + { + debug = debug "###nl;implied tag: [/*]" + debug = debug "###nl;matched" + bbtree[ind(count,depth)]="[/*]" + bbtree[ind(count,depth)".k"]="e" + bbtree[ind(count,depth)".m"]=1 + bbtree[ind(count,depth)".t"]="*" + bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + bbtree[indt(count,depth)".n"]=count[depth] + bbtree[indt(count,depth)".m"]=1 + count[depth]="" + --depth + ++count[depth] + } + debug = debug "###nl;name: " tagname + matchname=bbtree[indt(count,depth)".t"] + if((bbtree[indt(count,depth)".t"] == "code" && tagname!="code")||(bbtree[indt(count,depth)".t"] == "img" && tagname != "img")) + { + debug = debug "###nl;this tag forbidden here" + bbtree[ind(count,depth)]=tag + bbtree[indt(count,depth)".n"]=count[depth] + ++count[depth] + continue + } + if(tagname!=matchname) + { + debug = debug "###nl;mismatched: " matchname + # bbtree[ind(count,depth)]=tag + # bbtree[indt(count,depth)".n"]=count[depth] + # ++count[depth] + # continue + bbtree[ind(count,depth)]=tag + bbtree[ind(count,depth)".k"]="e" + bbtree[ind(count,depth)".t"]=bbtree[indt(count,depth)".t"] + bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + bbtree[indt(count,depth)".n"]=count[depth] + count[depth]="" + --depth + ++count[depth] + continue + } + debug = debug "###nl;matched" + bbtree[ind(count,depth)]=tag + bbtree[ind(count,depth)".k"]="e" + bbtree[ind(count,depth)".m"]=1 + bbtree[ind(count,depth)".t"]=tagname + bbtree[ind(count,depth)".v"]=bbtree[indt(count,depth)".v"] + bbtree[indt(count,depth)".n"]=count[depth] + bbtree[indt(count,depth)".m"]=1 + count[depth]="" + --depth + ++count[depth] + } + } + if(depth>0) + debug = debug "###nl;unclosed tags: " depth + + debug = debug "###nl;###nl;""generate HTML:" + depth=0 + count[0]=0 + while(count[0]<=bbtree["0.n"]&&depth>=0) + { + if(count[depth]==0) + { + tag=bbtree[indt(count,depth)] + tagname=bbtree[indt(count,depth)".t"] + tagvalue=bbtree[indt(count,depth)".v"] + debug = debug "###nl;name: "tagname" value: "tagvalue" elements: "bbtree[indt(count,depth)".n"] + if(tagname == "post") + { + } + else if(bbtree[indt(count,depth)".m"]=="") + { + debug = debug "###nl;unmatched" + html = html tag + } + else if(tagname == "quote") + { + if (tagvalue=="") + { + html = html "
" + } + else + { + if(tagvalue !~ /^\".*\"$/) + #"#\"" + tagvalue="You forgot about the quote marks, "tagvalue + else + tagvalue=bb2html(substr(tagvalue,2,length(tagvalue)-2)) + html = html "
"tagvalue" wrote:
" + } + } + else if (tagname == "b") + { + html = html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "i") + { + html = html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "u") + { + html = html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname == "code") + { + if(bbtree[indtu(count,depth)".t"] == "code") + { + html=html tag + debug = debug "###nl;not a tag, actually" + } + else + { + html=html"
Code: Select all
" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + } + else if (tagname == "img") + html=html"" + } + else if (tagname == "size") + { + if (tagvalue==""||(tagvalue !~ /^[0-9]+$/)||(tagvalue+0)>200) + html=html" This tag should have a correct value. " + else + html=html"" + } + else if (tagname == "color") + { + if (tagvalue==""||tagvalue !~ /^#[0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F][0-9A-F]$/) #for some reason /^([0-9A-F]{6})$/ doesn't work. + html=html" This tag should have a correct value. " + else + html=html"" + } + else if (tagname ~ /^((center)|(right))$/) + { + html=html"
" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname =="s") + { + html=html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname =="sub") + { + html=html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname =="sup") + { + html=html"" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname=="spoiler") + { + html=html"
Spoiler:
" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if (tagname=="list") + { + if(tagvalue=="") + html=html"
    " + else + { + if (tagvalue=="1") + tagvalue="decimal" + else if (tagvalue=="i") + tagvalue="lower-roman" + else if (tagvalue=="I") + tagvalue="upper-roman" + else if (tagvalue=="a") + tagvalue="lower-alpha" + else if (tagvalue=="A") + tagvalue="upper-alpha" + else + { + html=html"This tag should have a correct value. " + tagvalue="decimal" + } + html=html"
      " + } + } + else if (tagname=="*") + { + html=html"
    1. " + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else + { + debug = debug "###nl;unknown tag" + html = html tag + } + ++count[depth] + } + else if(bbtree[ind(count,depth)".k"]=="s") + { + debug = debug "###nl;entering tag:" + ++depth + count[depth]=0 + } + else if(bbtree[ind(count,depth)".k"]=="e") + { + debug = debug "###nl;leaving tag:" + tag=bbtree[ind(count,depth)] + tagname=bbtree[ind(count,depth)".t"] + tagvalue=bbtree[ind(count,depth)".v"] + debug = debug "###nl;name: "tagname" value: "tagvalue + if (tagname == "post") + { + } + else if(bbtree[ind(count,depth)".m"]=="") + { + debug = debug "###nl;unmatched" + html = html tag + } + else if(tagname == "quote") + html = html "
" + else if (tagname ~/^(b|i|u|(size)|(color))$/) + html = html"" + else if (tagname == "code") + { + if(bbtree[indtu(count,depth)".t"] == "code") + { + html=html tag + debug = debug "###nl;not a tag, actually" + } + else + html = html"" + } + else if (tagname == "img") + { + html = html"\" alt=\"Image\" />" + if(tagvalue!="") + html=html"This tag shouldn't have any value. " + } + else if(tagname=="url") + html=html"" + else if (tagname ~ /^((center)|(right))$/) + html=html"
" + else if (tagname =="s") + html=html"" + else if (tagname =="sub") + html=html"" + else if (tagname =="sup") + html=html"" + else if (tagname=="spoiler") + html=html"" + else if (tagname=="list") + { + if (tagvalue=="") + html=html"" + else + html=html"" + } + else if (tagname=="*") + html=html"" + else + { + debug = debug "###nl;unknown tag" + html = html tag + } + count[depth]="" + --depth + ++count[depth] + } + else if(count[depth]>bbtree[indt(count,depth)".n"]) + { + debug = debug "###nl;run out of elements in this tag; leaving" + count[depth]="" + --depth + ++count[depth] + } + else + { + tag=bbtree[ind(count,depth)] + debug = debug "###nl;text: "tag + if(bbtree[indt(count,depth)".t"] == "code") + { + # gsub(/ ?
?/,"
",tag) + gsub(/ /,"\\ ",tag) + gsub(/\t/,"\\ \\ ",tag) + } + if(argtab["disable_magic_url"]==""&& bbtree[indt(count,depth)".t"] !~ /^((code)|(img)|(url))$/) + gsub(/https?:\/\/[^\n\r\t<> ]+/,"&",tag) + if(argtab["disable_smilies"]=="" && bbtree[indt(count,depth)".t"] !~ /^((code)|(img))$/) + { + gsub(/(^|[\n\r\t ]):D($|[\n\r\t ])/," \":D\" ",tag) + gsub(/(^|[\n\r\t ]):\)($|[\n\r\t ])/," \":)\" ",tag) + gsub(/(^|[\n\r\t ]):\(($|[\n\r\t ])/," \":(\" ",tag) + gsub(/(^|[\n\r\t ]):o($|[\n\r\t ])/," \":o\" ",tag) + gsub(/(^|[\n\r\t ]):shock:($|[\n\r\t ])/," \":shock:\" ",tag) + gsub(/(^|[\n\r\t ]):\?($|[\n\r\t ])/," \":?\" ",tag) + gsub(/(^|[\n\r\t ])8-\)($|[\n\r\t ])/," \"8-)\" ",tag) + gsub(/(^|[\n\r\t ]):lol:($|[\n\r\t ])/," \":lol:\" ",tag) + gsub(/(^|[\n\r\t ]):x($|[\n\r\t ])/," \":x\" ",tag) + gsub(/(^|[\n\r\t ]):P($|[\n\r\t ])/," \":P\" ",tag) + gsub(/(^|[\n\r\t ]):oops:($|[\n\r\t ])/," \":oops:\" ",tag) + gsub(/(^|[\n\r\t ]):cry:($|[\n\r\t ])/," \":cry:\" ",tag) + gsub(/(^|[\n\r\t ]):evil:($|[\n\r\t ])/," \":evil:\" ",tag) + gsub(/(^|[\n\r\t ]):twisted:($|[\n\r\t ])/," \":twisted:\" ",tag) + gsub(/(^|[\n\r\t ]):roll:($|[\n\r\t ])/," \":roll:\" ",tag) + gsub(/(^|[\n\r\t ]):wink:($|[\n\r\t ])/," \":wink:\" ",tag) + gsub(/(^|[\n\r\t ]);\)($|[\n\r\t ])/," \":wink:\" ",tag) + gsub(/(^|[\n\r\t ]):!:($|[\n\r\t ])/," \":!:\" ",tag) + gsub(/(^|[\n\r\t ]):\?:($|[\n\r\t ])/," \":?:\" ",tag) + gsub(/(^|[\n\r\t ]):idea:($|[\n\r\t ])/," \":idea:\" ",tag) + gsub(/(^|[\n\r\t ]):arrow:($|[\n\r\t ])/," \":arrow:\" ",tag) + gsub(/(^|[\n\r\t ]):\|($|[\n\r\t ])/," \":|\" ",tag) + gsub(/(^|[\n\r\t ]):mrgreen:($|[\n\r\t ])/," \":mrgreen:\" ",tag) + } + + html = html tag + ++count[depth] + } + } + debug = debug "###nl;done" + return html +} + +function ind(count,depth, ii,iindex) +{ + iindex = "" + for(ii=0;ii<=depth;++ii) + { + if(ii!=0) + iindex = iindex "." + iindex = iindex count[ii] + } + # debug = debug "###nl;" iindex + return iindex +} +function indt(count,depth, ii,iindex) +{ + iindex = "" + for(ii=0;ii0) + iindex=iindex"." + iindex = iindex "0" + # debug = debug "###nl;" iindex + return iindex +} +function indtu(count,depth, ii,iindex) +{ + iindex = "" + for(ii=0;ii0) + iindex=iindex"." + iindex = iindex "0" + # debug = debug "###nl;" iindex + return iindex +} +function ong(decree, line) +{ + system (automome" -lc 256 -n 67 -d "memepath(decree!=""?" -t \"[decr]\"":"")" > "tempfile) + + while((getline line < tempfile)>0) + { + gsub(/[\r\n]/,"",line) + if(sub(/[AEIOUY]-N-G/,"#O-N-G#",line)>0) + { + close(tempfile) + return preparebb(line) + } + if(sub(/O+N+G+/,"#&#",line)>0) + { + close(tempfile) + return preparebb(line) + } + if(sub(/DON'T/,"D#ON'G#T",line)>0) + { + close(tempfile) + return preparebb(line) + } + if(sub(/[AEIOUY]NG/,"#ONG#",line)>0) + { + if($0!~/TH\[b\]ONG/) + return preparebb(line) + } + if(sub(/ON /,"#ONG# ",line)>0) + { + close(tempfile) + return preparebb(line) + } + if(sub(/O\.?$/,"#ONG# ",$0)>0) + { + close(tempfile) + return preparebb(line) + } + } + close(tempfile) + return "Ong" +} + +function ung(decree, line) +{ + system (automome" -lc 256 -n 67 -d "memepath(decree!=""?" -t \"[decr]\"":"")" > "tempfile) + + while((getline line < tempfile)>0) + { + gsub(/[\r\n]/,"",line) + if(sub(/[AEIOUY]-N-G/,"#U-N-G#",line)>0) + { + close(tempfile) + return preparebb(line) + } + if(sub(/U+N+G+/,"#&#",line)>0) + { + close(tempfile) + return preparebb(line) + } + if(sub(/[AEIOUY]NG/,"#UNG#",line)>0) + { + close(tempfile) + return preparebb(line) + } + if(sub(/UN /,"#UNG# ",line)>0) + { + close(tempfile) + return preparebb(line) + } + if(sub(/U\.?$/,"#UNG# ",$0)>0) + { + close(tempfile) + return preparebb(line) + } + } + close(tempfile) + return "Ung" +} + +function preparebb(rh) +{ + if(nobb=="") + { + gsub(/\*\*/,"¤",rh) + gsub(/\*[^\*]+\*/,"±&±",rh) + gsub(/±\*/,"[i]",rh) + gsub(/\*±/,"[/i]",rh) + gsub(/¤/,"*",rh) + + gsub(/__/,"¤",rh) + gsub(/_[^_]+_/,"±&±",rh) + gsub(/±_/,"[u]",rh) + gsub(/_±/,"[/u]",rh) + gsub(/¤/,"_",rh) + + gsub(/##/,"¤",rh) + gsub(/#[^#]+#/,"±&±",rh) + gsub(/±#/,"[b]",rh) + gsub(/#±/,"[/b]",rh) + gsub(/¤/,"#",rh) + + gsub(/\$\$/,"¤",rh) + gsub(/\$[^\$]+\$/,"±&±",rh) + gsub(/±\$/,"[size=80]",rh) + gsub(/\$±/,"[/size]",rh) + gsub(/¤/,"$",rh) + } + + return rh (nobb==""?" -- [url=http://mrob.com/time/automome]automome[/url]":" -- automome") +} +function urlencode(name,all, len,iii,escaped,ch) +{ + len=length(name) + escaped="" + for(iii=1;iii<=len;++iii) + { + ch=substr(name,iii,1); + if ((ch ~ /[a-zA-Z0-9\.\-_~]/)&&(all=="")) + escaped = escaped ch + else + escaped = escaped "%" ch2hex[ch] + } + return escaped +} diff --git a/bot5.c b/bot5.c new file mode 100644 index 0000000..c0cfa5d --- /dev/null +++ b/bot5.c @@ -0,0 +1,399 @@ +// bot5.c +// SilentBot +// 24.03.2015 +// +// Copyright (C) 2015 Balthasar Szczepański +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include +#include +#include +#include +#include + +#define TEMP_PATH "/eizm/tmp/t1i/bot5." +#define LOG_PATH "/eizm/log/t1i/bot5.log" +#define WAIT_PATH "/eizm/mem/t1i/mpost/" +#define SENT_PATH "/eizm/mem/t1i/mpost/sent/" +#define TEMPFILE_PATH "/eizm/tmp/t1i/bot5temp" +#define POSTDATA_PATH "/eizm/tmp/t1i/bot5post" +#define COOKIE_PATH "/eizm/tmp/t1i/bot5cook" +#define STOP_PATH "/eizm/tmp/t1i/bot5stop" +#define LS_PATH "/bin/ls" +#define MV_PATH "/bin/mv" +#define RM_PATH "/bin/rm" +#define MAWK_PATH "/usr/bin/mawk" +#define WGET_PATH "/usr/bin/wget" +#define AWK_POST "/eizm/pro/t1i/post.awk" +#define AWK_MPOST "/eizm/pro/t1i/mpost.awk" +#define AWK_LASTPOST "/eizm/pro/t1i/lastpost.awk" +#define PWAIT 15 +#define LASTPOST_ADDRESS "http://forums.xkcd.com/viewtopic.php?f=7&t=101043&sd=d" +#define USERAGENT "SilentBot (http://1190.bicyclesonthemoon.info/silentbot/; the Silent Chronotransponder bot)" + +pid_t sub; +int r; + +int main(int argc, char **argv) +{ + time_t t; + struct tm *nowS; + int yarg; + unsigned char text=0; + unsigned char newlog=0; + FILE *list; + FILE *post; + FILE *stopfile; + char temppath[256]; + unsigned char logopen=0; + unsigned char i; + char line[256]; + char value[256]; + char inpath[256]; + char outpath[256]; + char argp1[256]; + char argp2[256]; + char argp3[256]; + char argp4[256]; + char argp5[256]; + unsigned char d,m,h; + unsigned short y; + unsigned char another=0; + unsigned char edit; + + t=time(NULL); + sprintf(temppath,"%s%lu",TEMP_PATH,(unsigned long)getpid()); + + while((yarg = getopt(argc,argv,"tn")) != -1) + { + switch(yarg) + { + case 't': + text=1; + break; + case 'n': + newlog=1; + break; + default: + + break; + } + } + if(!text) + { + if(freopen(LOG_PATH,newlog?"wt":"at",stdout)!=NULL) + logopen=1; + } + setvbuf(stdout, NULL, _IONBF, 0); + dup2(fileno(stdout),fileno(stderr)); + printf("\n%s",ctime(&t)); + + stopfile=fopen(STOP_PATH,"wt"); + if (stopfile==NULL) + { + printf("FULL STOPFULL STOP\n"); + return 1; + } + if (lockf(fileno(stopfile),F_TLOCK,0)!=0) + { + printf("FULL STOPFULL STOP\n"); + return 1; + } + fprintf(stopfile,"%hu.FULL STOPFULL STOP\n",0); + + + sub=fork(); + if(sub==0) + { + if(freopen(temppath,"wt",stdout)==NULL) + exit(255); + r=execl(LS_PATH,LS_PATH,"-1","--color=never",WAIT_PATH,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + printf("ls fail.\n"); + else + { + list=fopen(temppath,"rt"); + if(list==NULL) + printf("list fail.\n"); + else + { + for(i=0; fgets(line,255,list)!=NULL; ++i) + { + sscanf(line,"%s",value); + if(value[0]>'9'||value[0]<'0') + { + --i; + continue; + } + printf("%s",value); + sprintf(inpath,"%s%s",WAIT_PATH,value); + post=fopen(inpath,"rt"); + if(post==NULL) + { + printf(" fail.\n"); + continue; + } + for(h=0xff,d=0xff,m=0xff,y=0xffff;fgets(line,31,post)!=NULL;) + { + if(line[strlen(line)-1]!='\n') + continue; + if(line[0]=='h'&&line[1]=='=') + { + sscanf(line+2,"%hhu",&h); + //printf("\n h%hhu d%hhu %s",h,d,line); + } + else if(line[0]=='d'&&line[1]=='=') + { + sscanf(line+2,"%hhu",&d); + //printf("\n d%hhu d%hhu %s",d,d,line); + } + else if(line[0]=='m'&&line[1]=='=') + { + sscanf(line+2,"%hhu",&m); + //printf("\n m%hhu d%hhu %s",m,d,line); + } + else if(line[0]=='y'&&line[1]=='=') + { + sscanf(line+2,"%hu",&y); + //printf("\n y%hu d%hhu %s",y,d,line); + } + } + fclose(post); + printf(" %02hhu.%02hhu.%04hu %02hhu:00",d,m,y,h); + nowS=gmtime(&t); + + if((1900+nowS->tm_year-y)>=2) + { + printf(" timer mustard"); + continue; + } + + if(y>1900+nowS->tm_year) + { + printf(" wait\n"); + continue; + } + else if(y==1900+nowS->tm_year) + { + if(m>1+nowS->tm_mon) + { + printf(" wait\n"); + continue; + } + else if(m==1+nowS->tm_mon) + { + if(d>nowS->tm_mday) + { + printf(" wait\n"); + continue; + } + else if(d==nowS->tm_mday) + { + if(h>nowS->tm_hour) + { + printf(" wait\n"); + continue; + } + } + + } + } + + printf(" deliver"); + + do + {//test latest post + edit=0; + sub=fork(); + if(sub==0) + { + r=execl(WGET_PATH,WGET_PATH, "-q","-t", "3","-U", USERAGENT, "-O", TEMPFILE_PATH,LASTPOST_ADDRESS, (char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + break; + + sub=fork(); + if(sub==0) + { + if(freopen(temppath,"wt",stdout)==NULL) + exit(255); + r=execl(MAWK_PATH,MAWK_PATH, "-f",AWK_LASTPOST, TEMPFILE_PATH, (char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + break; + + post=fopen(temppath,"rt"); + if(post==NULL) + break; + + if(fgets(argp1,255,post)!=NULL) + { + sscanf(argp1,"%s",argp2); + sprintf(argp4,"edit=%s",argp2); + } + else + { + fclose(post); + break; + } + if(fgets(argp1,255,post)!=NULL) + { + sscanf(argp1,"%s",argp2); + sprintf(argp5,"user=%s",argp2); + } + else + { + fclose(post); + break; + } + fclose(post); + edit=1; + }while(0); + + sprintf(argp1 ,"postfile=%s",POSTDATA_PATH); + sprintf(argp2,"cookiefile=%s",COOKIE_PATH); + sprintf(argp3,"tempfile=%s",TEMPFILE_PATH); + // sprintf(argp4,"name=%s",name); + // sprintf(argp5,"pass=%s",pass); + + //no longer necessary - bot can now edit + //ETA: not true, still have to wait but only 15s - so that phpBB doesn't + if(another) + sleep(PWAIT); + + sprintf(outpath,"%s%s",SENT_PATH,value); + + sub=fork(); + if(sub==0) + { + r=execl(MV_PATH,MV_PATH,inpath,outpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + printf(" mv fail.\n"); + + sub=fork(); + if(!sub) + { + if(edit) + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_POST,"-v",argp1,"-v",argp2,"-v",argp3,"-v",argp4,"-v",argp5,outpath,(char *)0); + else + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_POST,"-v",argp1,"-v",argp2,"-v",argp3,outpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + { + sub=fork(); + if(!sub) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_MPOST,"-v",argp1,"-v",argp2,"-v",argp3,outpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + { + another=0; + continue; + } + } + else + { + post=fopen(POSTDATA_PATH,"rt"); + if(post!=NULL) + { + if(fgets(line,255,post)!=NULL) + { + sscanf(line,"%s",value); + fclose(post); + + post=fopen(outpath,"at"); + if(post!=NULL) + { + fprintf(post,"ID=%s\n",value); + fclose (post); + } + } + else + fclose(post); + } + + } + printf(" ok\n"); + another=1; + + } + + if(i==0) + printf("Nothing.\n"); + fclose(list); + sub=fork(); + if(sub==0) + { + r=execl(RM_PATH,RM_PATH,"-f",temppath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + printf("rm fail.\n"); + + + sub=fork(); + if(!sub) + { + r=execl(RM_PATH,RM_PATH,"-f",COOKIE_PATH,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + sub=fork(); + if(!sub) + { + r=execl(RM_PATH,RM_PATH,"-f",POSTDATA_PATH,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + sub=fork(); + if(!sub) + { + r=execl(RM_PATH,RM_PATH,"-f",TEMPFILE_PATH,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + + lockf(fileno(stopfile),F_ULOCK,0); + fclose(stopfile); + + sub=fork(); + if(!sub) + { + r=execl(RM_PATH,RM_PATH,"-f",STOP_PATH,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + } + } + if(logopen) + fclose(stdout); + return 0; +} diff --git a/lastpost.awk b/lastpost.awk new file mode 100644 index 0000000..9b93751 --- /dev/null +++ b/lastpost.awk @@ -0,0 +1,46 @@ +#// lastpost.awk +#// what was the last post? +#// 20.03.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero General Public License as +#// published by the Free Software Foundation, either version 3 of the +#// License, or (at your option) any later version. +#// +#// This program is distributed in the hope that it will be useful, +#// but WITHOUT ANY WARRANTY; without even the implied warranty of +#// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#// GNU Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + FS="" +} +{ + if ((i=match($0, /id=\"p[0-9]+\"/))!=0) #" + { + temp=substr($0, i+5) + postid=substr(temp, 1, index(temp,"\"")-1) + } + + if ($0 ~ /class=\"postprofile\"/) #" + postprofile = "1" + + else if (postprofile=="") + next + + if($0 ~ /memberlist\.php.*mode=viewprofile[^<>]*>[^<>]+<\/a/) + { + temp=substr($0, index($0, ">")+1) + username=substr(temp, 1, index(temp,"<")-1) + exit + } +} +END{ + print postid + print username +} \ No newline at end of file diff --git a/makefile b/makefile new file mode 100644 index 0000000..3e1f397 --- /dev/null +++ b/makefile @@ -0,0 +1,34 @@ +CC=gcc +CC2=g++ +CF=-g -Wall +# LF=-lIL +LF2=-lcgi + +all: posted mpview remove post bot5 upload viewer enable + +bot5: bot5.c post.awk mpost.awk makefile + $(CC) $(CF) -o bot5 bot5.c + +# deliver: deliver.c +# $(CC) $(CF) -o deliver deliver.c + +remove: remove.c verify.awk + $(CC) $(CF) -o remove remove.c $(LF2) + +mpview: mpview.c mview.awk verify.awk makefile + $(CC) $(CF) -o mpview mpview.c $(LF2) + +posted: posted.c posted.awk makefile + $(CC) $(CF) -o posted posted.c $(LF2) + +post: post.cpp preview.awk bb2html.awk verify.awk makefile + $(CC2) $(CF) -o post post.cpp $(LF2) + +upload: upload.c upload.awk makefile + $(CC) $(CF) -o upload upload.c $(LF2) + +viewer: viewer.c makefile + $(CC) $(CF) -o viewer viewer.c $(LF2) + +enable: posted mpview remove post upload viewer + chmod u+s posted mpview remove post upload viewer diff --git a/mpost.awk b/mpost.awk new file mode 100644 index 0000000..7f90979 --- /dev/null +++ b/mpost.awk @@ -0,0 +1,77 @@ +#// mpost.awk +#// The tool to post to the mirror +#// 23.11.2014 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero General Public License as +#// published by the Free Software Foundation, either version 3 of the +#// License, or (at your option) any later version. +#// +#// This program is distributed in the hope that it will be useful, +#// but WITHOUT ANY WARRANTY; without even the implied warranty of +#// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#// GNU Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + FS="=" + fora="http://1190.bicyclesonthemoon.info/ott" + useragent="\"SilentBot (http://1190.bicyclesonthemoon.info/silentbot/; Time thread post bot)\"" +}; +{ + eq=index($0,"=") + argtab[substr($0,1,eq-1)]=substr($0,eq+1) +}; +END{ + printf ("username=%s",argtab["username"])>postfile + printf ("&password=%s",argtab["password"])>>postfile + printf ("&subject=%s",argtab["subject"])>>postfile + if("&addbbcode20" in argtab) + printf ("&addbbcode20=%s",argtab["addbbcode20"])>>postfile + printf ("&message=%s",argtab["message"])>>postfile + printf ("&post=%s","Submit")>>postfile + if("disable_bbcode" in argtab) + printf ("&disable_bbcode=%s",argtab["disable_bbcode"])>>postfile + if("disable_smilies" in argtab) + printf ("&disable_smilies=%s",argtab["disable_smilies"])>>postfile + if("disable_magic_url" in argtab) + printf ("&disable_magic_url=%s",argtab["disable_magic_url"])>>postfile + if("attach_sig" in argtab) + printf ("&attach_sig=%s",argtab["attach_sig"])>>postfile + if("notify" in argtab) + printf ("¬ify=%s",argtab["notify"])>>postfile + printf ("&creation_time=%s",argtab["creation_time"])>>postfile + printf ("&form_token=%s",argtab["form_token"])>>postfile + close(postfile) + + if(system("wget -q -t 3 --connect-timeout=60 --post-file=" postfile " -U " useragent " -O " tempfile " \""fora "/post\"")) + { + print "Submit fail." + exit 1 + } + + while((getline temp < tempfile)>0) + { + if (temp ~ /

information/) + { + success=1 + } + } + close(tempfile) + + if (success!=1) + { + print "Sent back to preview!" + exit INDELIVERABLE + } +} diff --git a/mpview.c b/mpview.c new file mode 100644 index 0000000..6995887 --- /dev/null +++ b/mpview.c @@ -0,0 +1,127 @@ +// mpview.c (1190.bicyclesonthemoon.info/silentbot/view) +// Display one post +// 25.04.2015 +// +// Copyright (C) 2015 Balthasar Szczepański +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include +#include +#include +#include + +#define RM_PATH "/bin/rm" +#define CAT_PATH "/bin/cat" +#define MAWK_PATH "/usr/bin/mawk" + +#define SENT_PATH "/eizm/mem/t1i/mpost/sent/" +#define WAIT_PATH "/eizm/mem/t1i/mpost/" + +#define AWK_MVIEW "/eizm/pro/t1i/mview.awk" +#define TEMP_PATH "/eizm/tmp/t1i/mpview." + +int main() +{ + s_cgi *cgi; + pid_t sub; + int r; + + char line[32]; + char filename[32]; + char postpath[256]; + char cat[8]; + + char *arg; + char key[64]; + + char path2[256]; + + cgi=cgiInit(); + + dup2(fileno(stdout),fileno(stderr)); + + printf("Content-type: text/html\n\n"); + + arg=cgiGetValue(cgi,"v"); + sprintf(line,"%s",arg?arg:"???"); + + arg=cgiGetValue(cgi,"key"); + sprintf(key,"key=%s",arg?arg:"???"); + + if(line[0]=='s' && line[1]=='t') + { + sprintf(filename,"%s",line+2); + sprintf(cat,"cat=%s","st"); + sprintf(postpath,"%s%s",SENT_PATH,filename); + } + else if(line[0]=='w' && line[1]=='t') + { + sprintf(filename,"%s",line+2); + sprintf(cat,"cat=%s","wt"); + sprintf(postpath,"%s%s",WAIT_PATH,filename); + } + else + { + sprintf(filename,"%s","???"); + sprintf(postpath,"%s","???"); + sprintf(cat,"cat=%s","???"); + } + + sprintf(path2,"%s%lu",TEMP_PATH,(unsigned long)getpid()); + + printf("\n"); + printf("\n"); + printf("the Silent Chronotransponder • Bicycles on the Moon\n"); + printf("\n"); + printf("\n"); + printf("\n"); + printf("\n"); + printf("\"1190.bicyclesonthemoon.info\"\n"); + printf("

the Silent Chronotransponder

\n"); + + fflush(stdout); + sub=fork(); + if(sub==0) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_MVIEW,"-v","bg=1","-v",cat,"-v","s=1","-v",key,postpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + // if(r) + // { + // printf("
\n",line); + // printf("
\n"); + // printf("%s %s POST NOT FOUND.\n",AWK_MVIEW,postpath); + // printf("\n
\n"); + // printf("
\n"); + // } + + printf("
back to the Silent Chronotransponder
\n"); + printf("
1190.bicyclesonthemoon.info\n"); + + fflush(stdout); + sub=fork(); + if(sub==0) + { + r=execl(RM_PATH,RM_PATH,"-f",path2,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + printf("

Ch*rpin* M*stard! file not deleted!

"); + + return 0; +} diff --git a/mview.awk b/mview.awk new file mode 100644 index 0000000..f122227 --- /dev/null +++ b/mview.awk @@ -0,0 +1,38 @@ +#// mview.awk +#// Display one post +#// 25.04.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero General Public License as +#// published by the Free Software Foundation, either version 3 of the +#// License, or (at your option) any later version. +#// +#// This program is distributed in the hope that it will be useful, +#// but WITHOUT ANY WARRANTY; without even the implied warranty of +#// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#// GNU Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + FS="=" +}; +{ + eq=index($0,"=") + argtab[substr($0,1,eq-1)]=substr($0,eq+1) +}; +END{ + if(key!=argtab["key"]&&cat=="wt"&&argtab["key"]!="") + { + print"Invalid key.

" + exit + } + print "
" + print "
"argtab["subject_h"]"
" + print "
"argtab["username_h"]" • "argtab["y"]"-"argtab["m"]"-"argtab["d"]" "argtab["h"]":00
quote "((cat=="wt")?("edit "):"")"remove "(argtab["ID"]!=""?" OTT":"")"
" + print "
"((argtab["HTML"]!="")?argtab["HTML"]:argtab["BBHTML"])"
" + print "
" +} diff --git a/notice.awk b/notice.awk new file mode 100644 index 0000000..56e6355 --- /dev/null +++ b/notice.awk @@ -0,0 +1,50 @@ +#// notice.awk +#// Display "Did you notice..." post in viewer +#// 31.03.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero General Public License as +#// published by the Free Software Foundation, either version 3 of the +#// License, or (at your option) any later version. +#// +#// This program is distributed in the hope that it will be useful, +#// but WITHOUT ANY WARRANTY; without even the implied warranty of +#// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#// GNU Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + timecmd="date -u +\"%Y%m%d%H\"" +} +{ + real=1 + eq=index($0,"=") + argtab[substr($0,1,eq-1)]=substr($0,eq+1) +} +END{ + if(real=="") + exit 1 + + posttime=argtab["y"]argtab["m"]argtab["d"]argtab["h"] + timecmd | getline thistime + close(timecmd) + + if (thistime"argtab["subject_h"]" "(argtab["ID"]!=""?"        (OTT time travel)":"")"" + print""((argtab["HTML"]!="")?argtab["HTML"]:argtab["BBHTML"])"" + } + else if (int(argtab["round"])==int(round)+1) + { + print ""argtab["subject_h"]"" + } + +} \ No newline at end of file diff --git a/notice2.awk b/notice2.awk new file mode 100755 index 0000000..7024872 --- /dev/null +++ b/notice2.awk @@ -0,0 +1,18 @@ +#! /usr/bin/mawk -f + +#notice2.awk +#28.03.2015 +#find SilentBot's "Did you notice..." posts +#replaced by the aftertime system, notice4.awk + +BEGIN{ + mawk="/usr/bin/mawk" + wget="/usr/bin/wget" + tempfile="/eizm/tmp/t1i/notice" + postlist="\"http://forums.xkcd.com/search.php?st=0&sk=t&sd=d&sr=posts&author_id=560926\"" + useragent="\"t1i - did you notice...(http://1190.bicyclesonthemoon.info/bluet1i/viewer)\"" + noticeawk="/eizm/pro/t1i/notice3.awk" + + system(wget" -q -O "tempfile" -U "useragent" "postlist) + system(mawk" -f "noticeawk" "tempfile) +} \ No newline at end of file diff --git a/notice3.awk b/notice3.awk new file mode 100644 index 0000000..f0daea6 --- /dev/null +++ b/notice3.awk @@ -0,0 +1,17 @@ +#notice3.awk +#28.03.2015 +#used by notice2,awk + +{ + if($0 ~ /

TimeAfterTime Revisited/) + { + post=substr($0, index($0,"#p")+2) + post=substr(post, 1, index(post, "\"")-1) + + frame=substr($0, index($0, "t1i-")+4, 4) + + file="/eizm/mem/t1i/notice/"frame + printf("%s",post) > file + close(file) + } +} diff --git a/notice4.awk b/notice4.awk new file mode 100755 index 0000000..01d420d --- /dev/null +++ b/notice4.awk @@ -0,0 +1,107 @@ +#! /usr/bin/mawk -f + +#// notice4.awk +#// Add SilentBot's posts' ID to the viewer +#// 31.03.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero General Public License as +#// published by the Free Software Foundation, either version 3 of the +#// License, or (at your option) any later version. +#// +#// This program is distributed in the hope that it will be useful, +#// but WITHOUT ANY WARRANTY; without even the implied warranty of +#// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#// GNU Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + lasttime="/eizm/mem/t1i/notice/lasttime" + list="/eizm/mem/t1i/mpost/sent/" + list2="/eizm/mem/aftertime/mpost/" + + listcmd="/bin/ls -1 --color=never "list + + + getline lastpost < lasttime + close(lasttime) + + if(lastpost=="") + lastpost="0000000000" + + while ((listcmd | getline postid)>0) + { + if (postid !~ /^[0-9A-F]+_53696C656E7454696D6572/) + continue + + number=substr(postid,1,index(postid,"_")-1) + + if (number<=lasttime) + continue + + postfile=list postid + + split("", argtab, ":") + while((getline line < postfile)>0) + { + f=1 + gsub(/[\r\n]/,"",line) + eq=index(line,"=") + argtab[substr(line,1,eq-1)]=substr(line,eq+1) + } + close (postfile) + if(argtab["ID"]=="") + continue + + if(argtab["subject_h"]!~/t1i-[0-9][0-9][0-9][0-9]$/) + continue + + ottid=argtab["ID"] + + frame=substr(argtab["subject_h"], length(argtab["subject_h"])-3) + + y=substr(number,1,4) + m=substr(number,5,2) + d=substr(number,7,2) + h=substr(number,9,2) + + + for(i=1;i<100;++i) + { + postfile=list2 "t1i-"frame"-"sprintf("%02u",i) + + split("", argtab, ":") + while((getline line < postfile)>0) + { + f=1 + gsub(/[\r\n]/,"",line) + eq=index(line,"=") + argtab[substr(line,1,eq-1)]=substr(line,eq+1) + } + close (postfile) + + if(argtab["timenumber"]=="") + break; + + if(argtab["y"]!=y || argtab["m"]!=m || argtab["d"]!=d || argtab["h"]!=h) + continue + + if(argtab["ID"]!="") + break; + + print "ID="ottid >> postfile + close(postfile) + + #print argtab["timenumber"] + + print number > lasttime + close(lasttime) + + } + } + close(listcmd) +} \ No newline at end of file diff --git a/post.awk b/post.awk new file mode 100644 index 0000000..32542e3 --- /dev/null +++ b/post.awk @@ -0,0 +1,311 @@ +#// post.awk +#// The tool to post to the OTT +#// 25.04.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero General Public License as +#// published by the Free Software Foundation, either version 3 of the +#// License, or (at your option) any later version. +#// +#// This program is distributed in the hope that it will be useful, +#// but WITHOUT ANY WARRANTY; without even the implied warranty of +#// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#// GNU Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + FS="=" + fora="http://forums.xkcd.com" + useragent="\"SilentBot (http://1190.bicyclesonthemoon.info/silentbot/; the Silent Chronotransponder bot)\"" + timecmd="date -u +\"%d %b %Y, %k:%M UTC\"" + + for(i=0;i<256;++i) + { + ch=sprintf("%c",i) + hex=sprintf("%02X",i); + ch2hex[ch]=hex + hex2ch[hex]=ch + } +}; +{ + eq=index($0,"=") + argtab[substr($0,1,eq-1)]=substr($0,eq+1) +}; +END{ + if(entitydecode(user)!=urldecode(argtab["username"])) + edit="" + + if(system("wget -q -t 3 --connect-timeout=60 --save-cookies=" cookiefile " -U " useragent " -O " tempfile " " fora "/ucp.php?mode=login")) + { + print "Pre-login fail." + exit 1 + } + while((getline cookie < cookiefile)>0) + { + if(cookie ~ /_sid/) + { + split(cookie,arr,"_sid[ \t]*") + SID=arr[2] + } + } + close(cookiefile) + print "username=" argtab["username"] "&password=" argtab["password"] "&sid=" SID "&login=Login" > postfile + close(postfile) + if(system("wget -q -t 3 --connect-timeout=60 --save-cookies=" cookiefile " --post-file=" postfile " -U " useragent " -O " tempfile " \"" fora "/ucp.php?mode=login\"")) + { + print "Login fail." + exit 1 + } + + while((getline temp < tempfile)>0) + { + if (temp ~ /
0) + { + if (tolower(line) ~ /

information/) + { + print "Unexpected h2: information\n" + getline line < tempfile + print line + exit 1 + } + + while (line!="") + { + i=match(line, //) + if(i!=0) + { + tag=substr(line,1,i) + line=substr(line,i+1) + } + else #oh no tag doesn't end on this line - whatever, I don't care. + { + tag=line + line="" + } + + + if(tag ~ /^postfile + if("&addbbcode20" in argtab) + printf ("&addbbcode20=%s",argtab["addbbcode20"])>>postfile + if(edit!="") + printf ("&message=%s",argtab["old_message"] "%0A%5Bsize%3D110%5D%5Bb%5D" argtab["subject"] "%5B%2Fb%5D%5B%2Fsize%5D%0A%5Bsize%3D80%5D" urlencode(posttime) "%5B%2Fsize%5D%0A" argtab["message"])>>postfile + else + printf ("&message=%s",argtab["message"])>>postfile + printf ("&post=%s","Submit")>>postfile + if("disable_bbcode" in argtab) + printf ("&disable_bbcode=%s",argtab["disable_bbcode"])>>postfile + if("disable_smilies" in argtab) + printf ("&disable_smilies=%s",argtab["disable_smilies"])>>postfile + if("disable_magic_url" in argtab) + printf ("&disable_magic_url=%s",argtab["disable_magic_url"])>>postfile + if("attach_sig" in argtab) + printf ("&attach_sig=%s",argtab["attach_sig"])>>postfile + if("notify" in argtab) + printf ("¬ify=%s",argtab["notify"])>>postfile + printf ("&creation_time=%s",argtab["creation_time"])>>postfile + printf ("&form_token=%s",argtab["form_token"])>>postfile + for(i=0; i>postfile + + close(postfile) + + system("sleep 1") + if(system("wget -q -t 3 --connect-timeout=60 --load-cookies=" cookiefile " --save-cookies=" cookiefile " --post-file=" postfile " -U " useragent " -O " tempfile " \"" fora "/posting.php?mode="((edit!="")?"edit&f=7&p="edit:"reply&f=7&t=101043")"\"")) + { + print "Submit fail." + exit 1 + } + + while((getline temp < tempfile)>0) + { + if (temp ~ /

information/) + { + success=1 + } + if ((temp ~ /]*p=/) && (postid=="")) + { + postid = substr (temp , index(temp, "#p")+2) + postid = substr (postid, 1, index(postid, "\"") - 1) + } + } + close(tempfile) + + print postid > postfile + close(postfile) + + if (success!=1) + { + print "Sent back to preview!" + exit INDELIVERABLE + } + + while((getline cookie < cookiefile)>0) + { + if(cookie ~ /_sid/) + { + split(cookie,arr,"_sid[ \t]*") + SID=arr[2] + break + } + } + close(cookiefile) + if(system("wget -q -t 3 --connect-timeout=60 -U " useragent " -O " tempfile " \"" fora "/ucp.php?mode=logout&sid=" SID"\"")) + { + print "Logout fail." + } + + +} +function urlencode(name,all, len,iii,escaped,ch) +{ + len=length(name) + escaped="" + for(iii=1;iii<=len;++iii) + { + ch=substr(name,iii,1); + if ((ch ~ /[a-zA-Z0-9\.\-_~]/)&&(all=="")) + escaped = escaped ch + else + escaped = escaped "%" ch2hex[ch] + } + return escaped +} +function entitydecode(ht ,i,j,un,num) +# quot, amp, lt, gt, nbsp, and decimal numbered. +{ + while ((i=match(ht, /&((#[0-9]+)|([a-zA-Z]+));/))!=0)# + { + un=un substr(ht, 1, i-1) + ht=substr(ht, i) + j=index(ht, ";") + + if(ht~/^&#/) + { + num=int(substr(ht, 3, j-3)) + un=un sprintf("%c",num) + } + else + { + num=tolower(substr(ht, 2, j-2)) + if(num == "quot") + un=un "\"" + else if(num == "amp") + un=un "&" + else if(num == "lt") + un=un "<" + else if(num == "gt") + un=un ">" + else if(num == "nbsp") + un=un "\xA0" + else + un = un ht + } + ht=substr(ht, j+1) + } + un=un ht + return un +} +function urldecode(ht ,i,j,un,num) +{ + while ((i=match(ht, /%[0-9a-fA-F][0-9a-fA-F]/))!=0)# + { + un=un substr(ht, 1, i-1) + ht=substr(ht, i) + num=toupper(substr(ht, 2, 2)) + un=un hex2ch[num] + ht=substr(ht, 4) + } + un=un ht + return un +} diff --git a/post.cpp b/post.cpp new file mode 100644 index 0000000..89fb04a --- /dev/null +++ b/post.cpp @@ -0,0 +1,612 @@ +// post.cpp (1190.bicyclesonthemoon.info/aftertime/post) +// The post edit interface +// 25.04.2015 +// +// Copyright (C) 2015 Balthasar Szczepański +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include +#include +#include +#include +#include +#include + +#define RM_PATH "/bin/rm" +#define MV_PATH "/bin/mv" +#define CAT_PATH "/bin/cat" +#define MAWK_PATH "/usr/bin/mawk" + +#define POST_PATH "/eizm/www/time/silentbot/post.htm" +#define INFO_PATH "/eizm/www/time/silentbot/info.htm" +#define MPOST_PATH "/eizm/mem/t1i/mpost/" + +#define AWK_PREVIEW "/eizm/pro/t1i/preview.awk" +#define AWK_VIEW "/eizm/pro/t1i/view.awk" +#define TEMP_PATH "/eizm/tmp/t1i/preview." +#define AWK_B2H "/eizm/pro/t1i/bb2html.awk" +#define AWK_VERIFY "/eizm/pro/t1i/verify.awk" + +s_cgi *cgi; +pid_t sub; +int r; +FILE *tempfile; +FILE *postfile; +bool tf=false; +bool pf=false; +char temppath[256]=""; +char temppath2[256]=""; +char postpath[512]=""; + +char zero='\0'; +char *username = &zero; +char *password = &zero; +char *subject = &zero; +char *message = &zero; +char *y = &zero; +char *m = &zero; +char *d = &zero; +char *h = &zero; +char *disable_bbcode = &zero; +char *disable_smilies = &zero; +char *disable_magic_url = &zero; +char *attach_sig = &zero; +char *notify = &zero; +char *Preview = &zero; +char *post =&zero; +char *addquote =&zero; +char *edit =&zero; +char *forceID =&zero; +char *silent =&zero; +char *key =&zero; +char *forcekey =&zero; + +char wrong[256]; + +void submit(); +void preview (const char *text); +void writeArg(FILE *file,const char *name,const char *value, bool all); +void writeArg(FILE *file,const char *name,const char *value, const char *insert); +void writeArgH(FILE *file,const char *name,const char *value, unsigned char br); +void writeArgH(FILE *file,const char *value); +void end(int m); +void id(char *timenumber,unsigned short y, unsigned char m, unsigned short d, unsigned char h, char *name); + +void end(int m) +{ + if(tf) + fclose(tempfile); + if(pf) + fclose(postfile); + sub=fork(); + if(sub==0) + { + r=execl(RM_PATH,RM_PATH,"-f",temppath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + sub=fork(); + if(sub==0) + { + r=execl(RM_PATH,RM_PATH,"-f",temppath2,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(pf) + { + sub=fork(); + if(sub==0) + { + r=execl(RM_PATH,RM_PATH,"-f",postpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + } + exit(m); +} + +void writeArg(FILE *file,const char *name,const char *value, bool all=false) +{ + unsigned short length, i, v; + fprintf(file,"%s=",name); + for(i=0, length=strlen(value);i='0'&&value[i]<='9')||(value[i]>='A'&&value[i]<='Z')||(value[i]>='a'&&value[i]<='z') + ||value[i]=='.'||value[i]=='~'||value[i]=='-'||value[i]=='_')&&(!all)) + fputc(v,file); + else + fprintf(file,"%%%02X",v); + } + fputc('\n',file); +} + +void writeArg(FILE *file,const char *name,const char *value, const char *insert) +{ + unsigned short length, i, v; + fprintf(file,"%s=",name); + for(i=0, length=strlen(value);i='0'&&value[i]<='9')||(value[i]>='A'&&value[i]<='Z')||(value[i]>='a'&&value[i]<='z') + ||value[i]=='.'||value[i]=='~'||value[i]=='-'||value[i]=='_') + fputc(v,file); + else + fprintf(file,"%%%02X",v); + } + for(i=0, length=strlen(insert);i='0'&&insert[i]<='9')||(insert[i]>='A'&&insert[i]<='Z')||(insert[i]>='a'&&insert[i]<='z') + ||insert[i]=='.'||insert[i]=='~'||insert[i]=='-'||insert[i]=='_') + fputc(v,file); + else + fprintf(file,"%%%02X",v); + } + fputc('\n',file); +} + +void writeArgH(FILE *file,const char *name,const char *value, unsigned char br=0) +{ + unsigned short length, i, v; + fprintf(file,"%s=",name); + for(i=0, length=strlen(value);i"); + case '\r': + if(br&0x01) + break; + case '=': + case '<': + case '>': + case '&': + fprintf(file,"&#%hu;",v); + break; + default: + fputc(v,file); + } + } + fputc('\n',file); +} + +void writeArgH(FILE *file,const char *value) +{ + unsigned short length, i, v; + for(i=0, length=strlen(value);i': + case ' ': + case '\r': + case '\n': + case '=': + fprintf(file,"&#%hu;",v); + break; + default: + fputc(v,file); + } + } +} + +void submit() +{ + time_t posttime; + struct tm *nowS; + char timenumber[256]; + char forcepath[512]; + char yy[8]; + char mm[4]; + char dd[4]; + char hh[4]; + char arg1[256]; + char arg2[256]; + char newkey[33]; + unsigned char tm, td, th; + unsigned short ty; + + posttime=time(NULL); + nowS=gmtime(&posttime); + + if(forcekey[0]=='\0') + sprintf(newkey,"%04X%04X%04X%04X%04X%04X%04X%04X", + (unsigned short)rand(),(unsigned short)rand(),(unsigned short)rand(),(unsigned short)rand(), + (unsigned short)rand(),(unsigned short)rand(),(unsigned short)rand(),(unsigned short)rand()); + else + sprintf(newkey,"%s",forcekey); + + if(y[0]!='\0'){sscanf(y,"%hu",&ty); sprintf(yy,"%04hu",ty); } + if(m[0]!='\0'){sscanf(m,"%hhu",&tm);sprintf(mm,"%02hhu",tm);} + if(d[0]!='\0'){sscanf(d,"%hhu",&td);sprintf(dd,"%02hhu",td);} + if(h[0]!='\0'){sscanf(h,"%hhu",&th);sprintf(hh,"%02hhu",th);} + + if((ty>0x0fff)||(tm>0x0f)||(td>0x1f)||(th>0x1f)) + preview("Time too long"); + // I accept invalid time as long as it's not too long + + + if(ty<1900+nowS->tm_year) + preview("Can't send this post to the past."); + else if(ty==1900+nowS->tm_year) + { + if(tm<1+nowS->tm_mon) + preview("Can't send this post to the past."); + else if(tm==1+nowS->tm_mon) + { + if(tdtm_mday) + preview("Can't send this post to the past."); + else if (td==nowS->tm_mday) + { + if (th<1+nowS->tm_hour) + preview("Can't send this post to the past."); + } + } + } + + + // sprintf(timenumber,"%04hu%02hhu%02hhu%02hhu_%llu",ty,tm,td,th,(unsigned long long)posttime); + id(timenumber,ty,tm,td,th,username); + sprintf(postpath,"%s%s",MPOST_PATH,timenumber); + if(forceID[0]!='\0') + sprintf(forcepath,"%s%s",MPOST_PATH,forceID); + + tempfile=fopen(temppath,"wt"); + if(tempfile==NULL) + preview("Couldn't create file."); + tf=true; + writeArgH(tempfile,"timenumber",timenumber); + writeArgH(tempfile,"key",newkey); + writeArgH(tempfile,"BBHTML",message,1); + writeArgH(tempfile,"BB",message,3); + writeArgH(tempfile,"username_h",username); + writeArgH(tempfile,"subject_h",subject); + if(h[0]!='\0')writeArgH(tempfile,"h",hh); + if(d[0]!='\0')writeArgH(tempfile,"d",dd); + if(m[0]!='\0')writeArgH(tempfile,"m",mm); + if(y[0]!='\0')writeArgH(tempfile,"y",yy); + writeArg (tempfile,"username",username); + writeArg (tempfile,"password",password,1); + writeArg (tempfile,"subject",subject); + writeArg (tempfile,"message",message,(silent[0]!='\0')?"":((disable_bbcode[0]!='\0')?"\n\n-- posted by SilentBot":"[right][size=80]-- posted by SilentBot [img]http://forums.xkcd.com/download/file.php?id=47884[/img][/size][/right]")); + if(disable_bbcode[0]!='\0') + writeArg(tempfile,"disable_bbcode",disable_bbcode); + if(disable_smilies[0]!='\0') + writeArg(tempfile,"disable_smilies",disable_smilies); + if(disable_magic_url[0]!='\0') + writeArg(tempfile,"disable_magic_url",disable_magic_url); + if(attach_sig[0]!='\0') + writeArg(tempfile,"attach_sig",attach_sig); + if(notify[0]!='\0') + writeArg(tempfile,"notify",notify); + if(silent[0]!='\0') + writeArgH(tempfile,"silent",silent); + fclose(tempfile); + tf=false; + + sprintf(arg1,"outfile=%s",temppath); + sprintf(arg2,"tempfile=%s",temppath2); + fflush(stdout); + sub=fork(); + if(sub==0) + { + setvbuf(stdout, NULL, _IONBF, 0); + dup2(fileno(stdout),fileno(stderr)); + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_B2H,"-v",arg1,"-v",arg2,temppath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + + sprintf(arg1,"name=%s",username); + sprintf(arg2,"pass=%s",password); + sub=fork(); + if(sub==0) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_VERIFY,"-v",arg1,"-v",arg2,"-v","reversed=1",(forceID[0]!='\0')?forcepath:postpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(!r) + preview("Can't replace this post. Not yours or wrong password?"); + + if(forceID[0]!='\0') + { + sub=fork(); + if(sub==0) + { + r=execl(RM_PATH,RM_PATH,forcepath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + } + + sub=fork(); + if(sub==0) + { + r=execl(MV_PATH,MV_PATH,temppath,postpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + // preview("Couldn't add post to queue."); + preview(postpath); + + printf("Content-type: text/html\n\n"); + sprintf(arg1,"info=

This message has been sent successfully.

View your submitted message

Return to the Silent Chronotransponder

",timenumber,newkey); + // printf("Content-type: text/html\n\n"); + fflush(stdout); + sub=fork(); + if(sub==0) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_VIEW,"-v",arg1,INFO_PATH,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + printf("%s",arg1); + end(0); +} +void preview (const char *text) +{ + char arg1[256]; + char arg2[256]; + char yy[8]; + char mm[4]; + char dd[4]; + char hh[4]; + unsigned short ty; + unsigned char tm,td,th; + if(y[0]!='\0'){sscanf(y,"%hu",&ty); ty&=0x0fff;sprintf(yy,"%04hu",ty); } + if(m[0]!='\0'){sscanf(m,"%hhu",&tm);tm&= 0x0f;sprintf(mm,"%02hhu",tm);} + if(d[0]!='\0'){sscanf(d,"%hhu",&td);td&= 0x1f;sprintf(dd,"%02hhu",td);} + if(h[0]!='\0'){sscanf(h,"%hhu",&th);th&= 0x1f;sprintf(hh,"%02hhu",th);} + + tempfile=fopen(temppath,"wt"); + if(tempfile==NULL) + end(1); + tf=true; + + writeArgH(tempfile,"HTML",message,1); + writeArgH(tempfile,"BB",message,3); + writeArgH(tempfile,"wrong",text); + writeArgH(tempfile,"username",username); + writeArgH(tempfile,"subject",subject); + writeArgH(tempfile,"message",message); + if(h[0]!='\0')writeArgH(tempfile,"h",hh); + if(d[0]!='\0')writeArgH(tempfile,"d",dd); + if(m[0]!='\0')writeArgH(tempfile,"m",mm); + if(y[0]!='\0')writeArgH(tempfile,"y",yy); + writeArgH(tempfile,"disable_bbcode",disable_bbcode); + writeArgH(tempfile,"disable_smilies",disable_smilies); + writeArgH(tempfile,"disable_magic_url",disable_magic_url); + writeArgH(tempfile,"attach_sig",attach_sig); + writeArgH(tempfile,"notify",notify); + writeArgH(tempfile,"silent",silent); + writeArgH(tempfile,"addquote",addquote); + writeArgH(tempfile,"edit",edit); + writeArgH(tempfile,"forceID",forceID); + writeArgH(tempfile,"key",forcekey); + fclose(tempfile); + tf=false; + + printf("Content-type: text/html\n\n"); + + sprintf(arg1,"outfile=%s",temppath); + sprintf(arg2,"tempfile=%s",temppath2); + + fflush(stdout); + sub=fork(); + if(sub==0) + { + setvbuf(stdout, NULL, _IONBF, 0); + dup2(fileno(stdout),fileno(stderr)); + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_B2H,"-v",arg1,"-v",arg2,temppath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + + // printf("Content-type: text/html\n\n"); + sprintf(arg1,"argfile=%s",temppath); + sprintf(arg2,"key=%s",key[0]?key:"???"); + fflush(stdout); + sub=fork(); + if(sub==0) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_PREVIEW,"-v",arg1,"-v",arg2,POST_PATH,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + printf("

Ch*rpin* M*stard

"); + end(0); +} + +int main() +{ + bool missing=false; + + char *arg; + + cgi=cgiInit(); + srand (time (NULL) + getpid()); + + sprintf(temppath,"%s%lu",TEMP_PATH,(unsigned long)getpid()); + sprintf(temppath2,"%s_%lu",TEMP_PATH,(unsigned long)getpid()); + + arg=cgiGetValue(cgi,"password"); + if(arg!=NULL) + password=arg; + else + { + missing=true; + strcpy(wrong,"Password is missing."); + } + + arg=cgiGetValue(cgi,"username"); + if(arg!=NULL) + username=arg; + else + { + missing=true; + strcpy(wrong,"Name is missing."); + } + + arg=cgiGetValue(cgi,"subject"); + if(arg!=NULL) + subject=arg; + else + { + missing=true; + strcpy(wrong,"Subject was missing. Replaced with default value."); + } + + arg=cgiGetValue(cgi,"message"); + if(arg!=NULL) + message=arg; + else + { + missing=true; + strcpy(wrong,"Post is empty."); + } + + arg=cgiGetValue(cgi,"y"); + if(arg!=NULL) + y=arg; + else + { + missing=true; + strcpy(wrong,"Time not specified."); + } + + arg=cgiGetValue(cgi,"m"); + if(arg!=NULL) + m=arg; + else + { + missing=true; + strcpy(wrong,"Time not specified."); + } + + arg=cgiGetValue(cgi,"d"); + if(arg!=NULL) + d=arg; + else + { + missing=true; + strcpy(wrong,"Time not specified."); + } + + arg=cgiGetValue(cgi,"h"); + if(arg!=NULL) + h=arg; + else + { + missing=true; + strcpy(wrong,"Time not specified."); + } + + arg=cgiGetValue(cgi,"disable_bbcode"); + if(arg!=NULL) + disable_bbcode=arg; + + arg=cgiGetValue(cgi,"disable_smilies"); + if(arg!=NULL) + disable_smilies=arg; + + arg=cgiGetValue(cgi,"disable_magic_url"); + if(arg!=NULL) + disable_magic_url=arg; + + arg=cgiGetValue(cgi,"attach_sig"); + if(arg!=NULL) + attach_sig=arg; + + arg=cgiGetValue(cgi,"notify"); + if(arg!=NULL) + notify=arg; + + arg=cgiGetValue(cgi,"silent"); + if(arg!=NULL) + silent=arg; + + arg=cgiGetValue(cgi,"Preview"); + if(arg!=NULL) + Preview=arg; + + arg=cgiGetValue(cgi,"post"); + if(arg!=NULL) + post=arg; + + arg=cgiGetValue(cgi,"q"); + if(arg!=NULL) + addquote=arg; + + arg=cgiGetValue(cgi,"e"); + if(arg!=NULL) + edit=arg; + + arg=cgiGetValue(cgi,"forceID"); + if(arg!=NULL) + forceID=arg; + + arg=cgiGetValue(cgi,"key"); + if(arg!=NULL) + key=arg; + + arg=cgiGetValue(cgi,"forcekey"); + if(arg!=NULL) + forcekey=arg; + + if(strcmp(post,"Submit")==0) + { + if(missing) + preview(wrong); + else + submit(); + } + else + preview(""); + + return 0; + +} + +void id(char *timenumber,unsigned short y, unsigned char m, unsigned short d, unsigned char h, char *name) +{ + sprintf(timenumber,"%04hu%02hhu%02hhu%02hhu_",y,m,d,h); + for(unsigned short j=0, k=strlen(name);j. + + +BEGIN{ + FS="=" + for(i=0;i<256;++i) + { + ch=sprintf("%c",i) + hex=sprintf("%02X",i); + ch2hex[ch]=hex + } +}; +{ + gsub(/[\r\n]/,"",$0) + eq=index($0,"=") + argtab[substr($0,1,eq-1)]=substr($0,eq+1) +}; +END{ + if(((pass,!=urldecode(argtab["password"]))||(name!=urldecode(argtab["username"])))&&cat!="st") + exit 1; + if (r2==0) + class="plw" + else + class="plv" + print ""argtab["y"]"-"argtab["m"]"-"argtab["d"]" "argtab["h"]":00"argtab["username_h"]""argtab["subject_h"]"view quote "(cat=="wt"?"edit ":"")"remove"(argtab["ID"]!=""?" OTT":"")"" +} +# function urlencode(name,all, len,iii,escaped,ch) +# { + # len=length(name) + # escaped="" + # for(iii=1;iii<=len;++iii) + # { + # ch=substr(name,iii,1); + # if ((ch ~ /[a-zA-Z0-9\.\-_~]/)&&(all=="")) + # escaped = escaped ch + # else + # escaped = escaped "%" ch2hex[ch] + # } + # return escaped +# } +function urldecode(ht ,i,j,un,num) +{ + while ((i=match(ht, /%[0-9a-fA-F][0-9a-fA-F]/))!=0)# + { + un=un substr(ht, 1, i-1) + ht=substr(ht, i) + num=toupper(substr(ht, 2, 2)) + un=un hex2ch[num] + ht=substr(ht, 4) + } + un=un ht + return un +} \ No newline at end of file diff --git a/posted.c b/posted.c new file mode 100644 index 0000000..08cf4fb --- /dev/null +++ b/posted.c @@ -0,0 +1,187 @@ +// posted.c (1190.bicyclesonthemoon.info/silentbot/list) +// Display the post list +// 26.04.2015 +// +// Copyright (C) 2015 Balthasar Szczepański +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include +#include +#include +#include +#include + +#define TEMP_PATH "/eizm/tmp/t1i/posted." +#define SENT_PATH "/eizm/mem/t1i/mpost/sent/" +#define WAIT_PATH "/eizm/mem/t1i/mpost/" +#define LS_PATH "/bin/ls" +#define RM_PATH "/bin/rm" +#define MAWK_PATH "/usr/bin/mawk" +#define AWK_POSTED "/eizm/pro/t1i/posted.awk" + +s_cgi *cgi; +pid_t sub; +int r; + +int main(int argc, char **argv) +{ + char temppath[256]=""; + char line[512]; + char filename[512]; + char postpath[512]; + char argp1[256]; + char argp2[256]; + FILE *tempfile; + // FILE *postfile; + unsigned char i; + unsigned char sent; + char zero='\0'; + char *value; + char *username; + char *password; + // dup2(fileno(stdout),fileno(stderr)); + cgi=cgiInit(); + + username=((value=cgiGetValue(cgi,"username"))?value:&zero); + password=((value=cgiGetValue(cgi,"password"))?value:&zero); + sent=cgiGetValue(cgi,"sent"); + sprintf(argp1,"name=%s",username); + sprintf(argp2,"pass=%s",password); + + + sprintf(temppath,"%s%lu",TEMP_PATH,(unsigned long)getpid()); + + printf("Content-type: text/html\n\n"); + printf("\n"); + printf("\n"); + printf("the Silent Chronotransponder • Bicycles on the Moon\n"); + printf("\n"); + printf("\n"); + printf("\n"); + printf("\"1190.bicyclesonthemoon.info\"\n"); + printf("

the Silent Chronotransponder

\n"); + printf("(some explanation)
\n"); + printf("
\n"); + printf("\n",username); + printf("\n"); + printf("\n",sent?" checked":""); + printf("
Username:
Password:
Sent posts:
\n"); + printf("Write a post

\n"); + printf("
\n"); + printf("
(file format - 23.03.2015)


\n"); + + fflush(stdout); + sub=fork(); + if(sub==0) + { + if(freopen(temppath,"wt",stdout)==NULL) + exit(255); + r=execl(LS_PATH,LS_PATH,"-1","--color=never",WAIT_PATH,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + printf("No messages.
\n"); + else + { + printf("\n"); + printf("\n"); + + tempfile=fopen(temppath,"rt"); + if(tempfile!=NULL) + { + for(i=0; fgets(line,511,tempfile)!=NULL; ++i) + { + sscanf(line,"%s",filename); + sprintf(postpath,"%s%s",WAIT_PATH,filename); + + fflush(stdout); + sub=fork(); + if(!sub) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_POSTED,"-v",i&0x1?"r2=1":"r2=0","-v","cat=wt","-v",argp1,"-v",argp2,postpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + --i; + + } + fclose(tempfile); + } + printf("
Waiting
post timeauthorsubjectaction

\n"); + + } + + if(sent) + { + fflush(stdout); + sub=fork(); + if(sub==0) + { + if(freopen(temppath,"wt",stdout)==NULL) + exit(255); + r=execl(LS_PATH,LS_PATH,"-1","--color=never",SENT_PATH,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + printf("No messages.
\n"); + else + { + printf("
\n"); + printf("\n"); + + tempfile=fopen(temppath,"rt"); + if(tempfile!=NULL) + { + for(i=0; fgets(line,511,tempfile)!=NULL; ++i) + { + sscanf(line,"%s",filename); + sprintf(postpath,"%s%s",SENT_PATH,filename); + + fflush(stdout); + sub=fork(); + if(!sub) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_POSTED,"-v",i&0x1?"r2=1":"r2=0","-v","cat=st","-v",argp1,"-v",argp2,postpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + --i; + + } + fclose(tempfile); + } + + printf("
Sent
post timeauthorsubjectaction
\n"); + } + } + + printf("
Aftertime ONGsystem

1190.bicyclesonthemoon.info\n"); + + fflush(stdout); + sub=fork(); + if(sub==0) + { + r=execl(RM_PATH,RM_PATH,"-f",temppath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + + return 0; +} diff --git a/postid.awk b/postid.awk new file mode 100644 index 0000000..c5b4946 --- /dev/null +++ b/postid.awk @@ -0,0 +1,31 @@ +#postid.awk +#24.04.2015 +#replaced by notice4.awk + +BEGIN{ + postpath="/eizm/mem/t1i/mpost/sent/" + noticepath="/eizm/mem/t1i/notice/" + tab_len=0 +} +{ + ID=$1 + frame =$NF + + if(frame !~ /t1i-[0-9][0-9][0-9][0-9]/) + next + + frame=substr(frame, 5, 4) + + notice=noticepath frame + + getline OTT < notice + close (notice) + + if(OTT=="") + next + + post=postpath ID + + print "ID="OTT >> post + close(post) +} \ No newline at end of file diff --git a/preview.awk b/preview.awk new file mode 100644 index 0000000..677418e --- /dev/null +++ b/preview.awk @@ -0,0 +1,204 @@ +#// preview.awk +#// Preview a post in the post edit interface +#// 25.04.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero General Public License as +#// published by the Free Software Foundation, either version 3 of the +#// License, or (at your option) any later version. +#// +#// This program is distributed in the hope that it will be useful, +#// but WITHOUT ANY WARRANTY; without even the implied warranty of +#// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#// GNU Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + sentpath="/eizm/mem/t1i/mpost/sent/" + waitpath="/eizm/mem/t1i/mpost/" + + HTML="
Preview: %s
%s

" + wrong="
%s
\n" + subject="\n" + username="\n" + time="Y: M: D: H: \n" + message="\n" + # forcetime1="\n" + # forcetime2="fTime: day: month: year: \n" + # img="" + back="back to the Silent Chronotransponder" + + disable_bbcode=" Disable BBcode
\n" + disable_smilies=" Disable smilies
\n" + disable_magic_url=" Do not automatically parse URLs
\n" + attach_sig=" Attach a signature
\n" + notify=" Notify me when a reply is posted
\n" + silent=" Very silent
\n" + + forceID="\n" + forcekey="\n" + + addquote="" + + # print "" + close(argfile) + if(argtab["edit"] ~ /^wt[0-9]+_[0-9a-fA-F]+$/) + { + argtab["forceID"]=substr(argtab["edit"],3) + argfile= waitpath argtab["forceID"] + + while((getline argline < argfile)>0) + { + gsub(/[\r\n]/,"",argline) + eq=index(argline,"=") + if(argline ~ /^key=/) + { + if(substr(argline,eq+1)!=key && argtab["addquote"]~/^wt/) + { + argtab["wrong"]="Invalid key." + break; + } + argtab["key"]=substr(argline,eq+1) + } + else if(argline ~ /^((username)|(subject))_h=/) + argtab[substr(argline,1,eq-3)]=substr(argline,eq+1) + else if(argline ~ /^BBHTML=/) + { + argtab["message"]=substr(argline,eq+1) + gsub(/
/,"\n",argtab["message"]) + } + else if(argline ~ /^((BB)|(username)|(subject)|(message)|(HTML)|(debug))=/) + {} + else + argtab[substr(argline,1,eq-1)]=substr(argline,eq+1) + } + close(argfile) + } + else if(argtab["addquote"] ~ /^[sw]t[0-9]+_[0-9a-fA-F]+$/) + { + if(argtab["addquote"] ~ /^st[0-9]+_[0-9a-fA-F]+$/) + argfile= sentpath substr(argtab["addquote"],3) + if(argtab["addquote"] ~ /^wt[0-9]+_[0-9a-fA-F]+$/) + argfile= waitpath substr(argtab["addquote"],3) + #else + #argfile is not changed = quote self? + while((getline argline < argfile)>0) + { + gsub(/[\r\n]/,"",argline) + eq=index(argline,"=") + if(argline ~ /^key=/) + { + if(substr(argline,eq+1)!=key && argtab["addquote"]~/^wt/) + { + argtab["wrong"]="Invalid key." + break; + } + } + if(argline ~ /^BBHTML=/) + { + addquotehtml=substr(argline,eq+1) + gsub(/
/,"\n",addquotehtml) + } + if(argline ~ /^username_h=/) + addquotename=substr(argline,eq+1) + if(argline ~ /^subject_h/) + { + addquotesub=substr(argline,eq+1) + if(addquotesub ~ /^Re:/) + argtab["subject"]=addquotesub + else + argtab["subject"]="Re: "addquotesub + } + if(argline ~ /^y=/) + { + argtab["y"]=substr(argline,eq+1) + } + if(argline ~ /^d=/) + { + argtab["d"]=substr(argline,eq+1) + } + if(argline ~ /^m=/) + { + argtab["m"]=substr(argline,eq+1) + } + if(argline ~ /^h=/) + { + argtab["h"]=substr(argline,eq+1) + } + } + close(argfile) + if(addquotehtml!="") + addquote="[quote=""addquotename""]"addquotehtml"[/quote]" + } +}; +{ + if ($0 ~ /^###HTML/) + { + if((argtab["HTML"]!="")&&(argtab["wrong"]=="")) + printf(HTML,argtab["subject"],argtab["HTML"]) + } + else if ($0 ~ /^###wrong/) + { + if(argtab["wrong"]!="") + printf(wrong,argtab["wrong"]) + } + else if ($0 ~ /^###subject/) + printf(subject,((argtab["subject"]=="")?"Wait for it.":argtab["subject"])) + else if ($0 ~ /^###username/) + printf(username,argtab["username"]) + else if ($0 ~ /^###message/) + printf(message,argtab["message"],addquote) + else if ($0 ~ /^###time/) + printf(time,argtab["y"],argtab["m"],argtab["d"],argtab["h"]) + + else if ($0 ~ /^###future/) + { + ###no longer supported + } + else if ($0 ~ /^###forceID/) + { + if(argtab["forceID"]!="") + printf(forceID,argtab["forceID"]) + } + else if ($0 ~ /^###forcekey/) + { + if(argtab["key"]!="") + printf(forcekey,argtab["key"]) + } + else if ($0 ~ /^###back/) + { + print back + } + else if ($0 ~ /^###debug/) + { + gsub(/###nl;/,"\n",argtab["debug"]) + gsub(/-/," - ",argtab["debug"]) + print "" + } + else if ($0 ~ /^###disable_bbcode/) + printf(disable_bbcode,(argtab["disable_bbcode"]=="on")?"checked=\"checked\"":"") + else if ($0 ~ /^###disable_smilies/) + printf(disable_smilies,(argtab["disable_smilies"]=="on")?"checked=\"checked\"":"") + else if ($0 ~ /^###disable_magic_url/) + printf(disable_magic_url,(argtab["disable_magic_url"]=="on")?"checked=\"checked\"":"") + else if ($0 ~ /^###attach_sig/) + printf(attach_sig,(argtab["attach_sig"]=="on")?"checked=\"checked\"":"") + else if ($0 ~ /^###notify/) + printf(notify,(argtab["notify"]=="on")?"checked=\"checked\"":"") + else if ($0 ~ /^###silent/) + printf(silent,(argtab["silent"]=="on")?"checked=\"checked\"":"") + else + print $0 +}; diff --git a/remove.c b/remove.c new file mode 100644 index 0000000..4b5a10b --- /dev/null +++ b/remove.c @@ -0,0 +1,115 @@ +// remove.c (1190.bicyclesonthemoon.info/silentbot/remove) +// remove a post +// 25.04.2015 +// +// Copyright (C) 2015 Balthasar Szczepański +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include +#include +#include +#include + +#define SENT_PATH "/eizm/mem/t1i/mpost/sent/" +#define WAIT_PATH "/eizm/mem/t1i/mpost/" +#define RMOV_PATH "/eizm/mem/t1i/mpost/rm/" +#define MV_PATH "/bin/mv" +#define MAWK_PATH "/usr/bin/mawk" +#define AWK_VERIFY "/eizm/pro/t1i/verify.awk" + +int main(int argc, char **argv) +{ + s_cgi *cgi; + pid_t sub; + int r; + + char zero='\0'; + char *rmov = &zero; + char *arg; + char *username; + char *password; + char inpath[256]; + char outpath[256]; + char argp1[256]; + char argp2[256]; + + cgi=cgiInit(); + + rmov=((arg=cgiGetValue(cgi,"r"))?arg:&zero); + + username=((arg=cgiGetValue(cgi,"username"))?arg:&zero); + password=((arg=cgiGetValue(cgi,"password"))?arg:&zero); + if(username[0]=='\0'||password[0]=='\0') + { + arg=cgiGetValue(cgi,"r"); + if(arg!=NULL) + rmov=arg; + printf("Content-type: text/html\n\n"); + printf("\n"); + printf("\n"); + printf("the Silent Chronotransponder • Bicycles on the Moon\n"); + printf("\n"); + printf("\n"); + printf("\n"); + printf("\n"); + printf("\"1190.bicyclesonthemoon.info\"\n"); + printf("

the Silent Chronotransponder interface

\n"); + printf("
\n"); + printf("Remove post %s?\n",rmov); + printf("\n",username); + printf("\n"); + printf("
Username:
Password:
\n",rmov); + printf("
1190.bicyclesonthemoon.info\n"); + return 0; + } + + if(rmov[0]=='s'&&rmov[1]=='t') + sprintf(inpath,"%s%s",SENT_PATH,rmov+2); + else if(rmov[0]=='w'&&rmov[1]=='t') + sprintf(inpath,"%s%s",WAIT_PATH,rmov+2); + else + { + cgiRedirect("/silentbot/list"); + return(0); + } + + sprintf(argp1,"name=%s",username); + sprintf(argp2,"pass=%s",password); + + sub=fork(); + if(sub==0) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_VERIFY,"-v",argp1,"-v",argp2,inpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + { + cgiRedirect("/silentbot/list"); + return(0); + } + sprintf(outpath,"%s%s",RMOV_PATH,rmov+2); + + sub=fork(); + if(sub==0) + { + r=execl(MV_PATH,MV_PATH,inpath,outpath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + cgiRedirect("/silentbot/list"); + return 0; +} \ No newline at end of file diff --git a/upload.awk b/upload.awk new file mode 100644 index 0000000..4e9dc44 --- /dev/null +++ b/upload.awk @@ -0,0 +1,894 @@ +#// upload.awk +#// The post upload interface +#// 05.06.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero General Public License as +#// published by the Free Software Foundation, either version 3 of the +#// License, or (at your option) any later version. +#// +#// This program is distributed in the hope that it will be useful, +#// but WITHOUT ANY WARRANTY; without even the implied warranty of +#// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#// GNU Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + postpath="/eizm/mem/t1i/mpost/" + stpath="/eizm/mem/t1i/mpost/sent/" + rmpath="/eizm/mem/t1i/mpost/rm/" + bb2html="/eizm/pro/t1i/bb2html.awk" + automome="/eizm/pro/ong1/mome.pl" + memepath="/eizm/mem/ong1/mome.txt" + timecmd="date -u +\"%s\"" + + timecmd | getline thistime + close(timecmd) + + srand(int(thistime) + int( PROCINFO["pid"])) + + for(i=0;i<256;++i) + { + ch=sprintf("%c",i) + hex=sprintf("%02X",i) + hexl=sprintf("%02x",i) + dec=sprintf("%u",i) + ch2hex[ch]=hex + hex2ch[hex]=ch + ch2hexl[ch]=hexl + ch2dec[ch]=dec + } + + year=substr(timetext,1,4) + month=substr(timetext,5,2) + day=substr(timetext,7,2) + hour=substr(timetext,9,2) + + yyy=year+0 + mmm=month+0 + ddd=day+0 + hhh=hour+0 + + ln=0 + memenumber=8 +} +{ + gsub(/[\r\n]/,"",$0) + if (FNR==1) + { + name=$0 + # print "username: "name + next + } + if (FNR==2) + { + pass=$0 + gsub(/./,"*", $0) + # print "password: "$0 + next + } + + if($0=="") + { + if(ln!=0) + { + post() + ln=0 + nobb="" + nosmil="" + nourl="" + sig="" + notify="" + silent="" + quot="" + rmov="" + lst="" + flst="" + h="" + d="" + m="" + y="" + subject="" + content="" + options="" + # replace="" + } + next + } + + ++ln + if(ln==1) + { + y=substr($0,1,4) + m=substr($0,6,2) + d=substr($0,9,2) + h=substr($0,12,2) + # #xxxx-xx-xx xx xxxx-xx-xx xx + # if(length($0)>=27) + # replace=substr($0,15,4)substr($0,20,2)substr($0,23,2)substr($0,26,2) + } + else if(ln==2) + { + options=tolower($0) + if(options ~ /b/) + nobb=1 + if(options ~ /s/) + nosmil=1 + if(options ~ /u/) + nourl=1 + if(options ~ /a/) + sig=1 + if(options ~ /n/) + notify=1 + if(options ~ /v/) + silent=1 + if(options ~ /r/) + rmov=1 + if(options ~ /q/) + quot=1 + if(options ~ /l/) + lst=1 + if(options ~ /f/) + flst=1 + } + else if(ln==3) + { + subject=$0 + } + else + { + if(ln!=4) + content=content "\n" $0 + else + content=$0 + } + +} +END{ + if(ln!=0) + post() +} +function remove( postid,postfile,rmfile,stfile,temp,f,tn,eq,tv) +{ + postid=sprintf("%04d%02d%02d%02d_%s",y,m,d,h,hexencode(name)) + postfile=postpath postid + rmfile=rmpath postid + stfile=stpath postid + printf("%s",postid" ") + + while((getline temp < postfile)>0) + { + f=1 + gsub(/[\r\n]/,"",temp) + eq=index(temp,"=") + tn=substr(temp,1,eq-1) + tv=substr(temp,eq+1) + if(tn=="username") + { + if(urldecode(tv)!=name) + { + # print "Can't remove, post belongs to "substr(temp,eq+1)"." + print "not removed."substr(temp,eq+1)"." + close(postfile) + return + } + } + else if(tn=="password") + { + if(urldecode(tv)!=pass) + { + # print "Can't remove, wrong password." + print "not removed" + #I shouldn't tell why - the user can't be able to determine if post exists. + close(postfile) + return + } + } + } + + if(f!="") + { + close(postfile) + if(system("mv -f "postfile" "rmfile)==0) + { + print "removed." + return + } + } + f="" + while((getline temp < stfile)>0) + { + f=1 + gsub(/[\r\n]/,"",temp) + eq=index(temp,"=") + tn=substr(temp,1,eq-1) + tv=substr(temp,eq+1) + if(tn=="username") + { + if(urldecode(tv)!=name) + { + print "Can't remove, post belongs to "substr(temp,eq+1)"." + close(stfile) + return + } + } + else if(tn=="password") + { + if(urldecode(tv)!=pass) + { + print "Can't remove, wrong password." + close(stfile) + return + } + } + } + if(f!="") + { + close(stfile) + if(system("mv -f "stfile" "rmfile)==0) + { + print "removed." + return + } + } + print "not removed." +} + +function quote( postid,postfile,stfile,temp,f,opt,cont,ongt,subj,eq,tn,tv,id) +{ + postid=sprintf("%04d%02d%02d%02d_%s",y,m,d,h,hexencode(name)) + postfile=postpath postid + stfile=stpath postid + + while((getline temp < postfile)>0) + { + f=1 + gsub(/[\r\n]/,"",temp) + eq=index(temp,"=") + tn=substr(temp,1,eq-1) + tv=substr(temp,eq+1) + if(tn=="username") + { + if(urldecode(tv)!=name) + { + #print "Can't quote, post belongs to "substr(temp,eq+1)"." + print " can't. quote." #I shouldn't tell why + close(postfile) + return + } + } + else if(tn=="password") + { + if(urldecode(tv)!=pass) + { + #print "Can't quote, wrong password." + print " can't quote." #I shouldn't tell why + close(postfile) + return + } + } + else if(tn=="BB") + cont=unhtml(tv) + else if(tn=="brtext") + ongt=tv + else if(tn=="subject_h") + subj=unhtml(tv) + else if(tn=="disable_bbcode") + { + if(tv=="on") + opt=opt"B" + } + else if(tn=="disable_smilies") + { + if(tv=="on") + opt=opt"S" + } + else if(tn=="disable_magic_url") + { + if(tv=="on") + opt=opt"U" + } + else if(tn=="attach_sig") + { + if(tv=="on") + opt=opt"A" + } + else if(tn=="notify") + { + if(tv=="on") + opt=opt"N" + } + else if(tn=="silent") + { + if(tv=="on") + opt=opt"V" + } + } + if(f!="") + { + close(postfile) + if (opt=="") + opt="_" + print postid" subject "subj + print postid" options "opt + print postid" content "((ongt!="")?ongt:cont) + return + } + + while((getline temp < stfile)>0) + { + f=1 + gsub(/[\r\n]/,"",temp) + eq=index(temp,"=") + tn=substr(temp,1,eq-1) + tv=substr(temp,eq+1) + if(tn=="BB") + cont=unhtml(tv) + else if(tn=="brtext") + ongt=tv + else if(tn=="subject_h") + subj=unhtml(tv) + else if(tn=="ID") + id=tv + else if(tn=="disable_bbcode") + { + if(tv=="on") + opt=opt"B" + } + else if(tn=="disable_smilies") + { + if(tv=="on") + opt=opt"S" + } + else if(tn=="disable_magic_url") + { + if(tv=="on") + opt=opt"U" + } + else if(tn=="attach_sig") + { + if(tv=="on") + opt=opt"A" + } + else if(tn=="notify") + { + if(tv=="on") + opt=opt"N" + } + else if(tn=="silent") + { + if(tv=="on") + opt=opt"V" + } + } + if(f!="") + { + close(stfile) + if (opt=="") + opt="_" + print postid" subject "subj + print postid" options "opt + print postid" content "((ongt!="")?ongt:cont) + if(id!="") + print postid" ID "id + return + } + + else + print postid " can't quote." #I shouldn't tell why +} + +function list( cmd,id,postfile,temp,mt,f,eq,tn,tv) +{ + + if (flst!="") + { + cmd="/bin/ls -1 --color=never "stpath + while ((cmd | getline id)>0) + { + f="" + mt="[0-9]*_"hexencode(name) + if(id !~ mt) + continue + stfile = stpath id + #print id + + while((getline temp < stfile)>0) + { + f=1 + gsub(/[\r\n]/,"",temp) + eq=index(temp,"=") + tn=substr(temp,1,eq-1) + tv=substr(temp,eq+1) + if(tn=="subject_h") + subj=unhtml(tv) + } + if(f!="") + { + close(stfile) + print id" subject "subj + } + } + close (cmd) + } + + cmd="/bin/ls -1 --color=never "postpath + while ((cmd | getline id)>0) + { + f="" + mt="[0-9]*_"hexencode(name) + if(id !~ mt) + continue + postfile = postpath id + #print id + + while((getline temp < postfile)>0) + { + f=1 + gsub(/[\r\n]/,"",temp) + eq=index(temp,"=") + tn=substr(temp,1,eq-1) + tv=substr(temp,eq+1) + if(tn=="username") + { + if(urldecode(tv)!=name) + { + close(postfile) + f="" + break + } + } + else if(tn=="password") + { + if(urldecode(tv)!=pass) + { + close(postfile) + f="" + break + } + } + else if(tn=="subject_h") + subj=unhtml(tv) + } + if(f!="") + { + close(postfile) + print id" subject "subj + } + + + + ########33 + } + close (cmd) +} + +function post( postid,replaceid,postfile,replacefile,temp,i,eq,tn,tv) +{ + if(lst!="") + return list() + if(quot!="") + return quote() + if(rmov!="") + return remove() + postid=sprintf("%04d%02d%02d%02d_%s",y,m,d,h,hexencode(name)) + printf("%s",postid" ") + postfile=postpath postid + + if(options=="") + { + print "No options defined." + return + } + + # if(replace!="") + # { + # replaceid=replace"_"hexencode(name) + # replacefile=postpath replaceid + # } + + if (name=="") + { + print "Username missing." + return + } + if (pass=="") + { + print "Password missing." + return + } + if (subject=="") + { + print "Subject missing." + return + } + if (content=="") + { + print "Post is empty." + return + } + + yy=y+0 + mm=m+0 + dd=d+0 + hh=h+0 + + if(yy0) + { + gsub(/[\r\n]/,"",temp) + eq=index(temp,"=") + tn=substr(temp,1,eq-1) + tv=substr(temp,eq+1) + if(tn=="username") + { + if(urldecode(tv)!=name) + { + print "Can't replace, post belongs to "substr(temp,eq+1) + close(postfile) + return + } + } + else if(tn=="password") + { + if(urldecode(tv)!=pass) + { + print "Can't replace, wrong password" + close(postfile) + return + } + } + else if(tn ~ /^[ou]ngd?-[0-9]+$/) + { + ongtable[tn]=brunescape(tv) + } + else if(tn == "key") + key=tv + } + close(postfile) + + # if(replace!="") + # { + # #print "Repalce post "replaceid + # while((getline temp < replacefile)>0) + # { + # gsub(/[\r\n]/,"",temp) + # eq=index(temp,"=") + # if(substr(temp,1,eq-1)=="username") + # { + # if(substr(temp,eq+1)!=urlencode(name)) + # { + # print "Can't replace, post belongs to "substr(temp,eq+1) + # close(replacefile) + # return + # } + # } + # else if(substr(temp,1,eq-1)=="password") + # { + # if(substr(temp,eq+1)!=urlencode(pass,"all")) + # { + # print "Can't replace, wrong password" + # close(replacefile) + # return + # } + # } + # } + # close(replacefile) + # system("rm -f " replacefile) + + # } + printf("")>postfile + + print "timenumber="htmlescape(postid) >> postfile + print "key="(key==""?newkey():key) >> postfile + print "username="urlencode(name) >> postfile + print "password="urlencode(pass,"all") >> postfile + print "username_h="htmlescape(name) >> postfile + + # print("Post time:\n"d"."m"."y" "h":00") + print "h="htmlescape(h) >> postfile + print "d="htmlescape(d) >> postfile + print "m="htmlescape(m) >> postfile + print "y="htmlescape(y) >> postfile + + if(nobb!="") + print "disable_bbcode=on" >> postfile + if(nosmil!="") + print "disable_smilies=on" >> postfile + if(nourl!="") + print "disable_magic_url=on" >> postfile + if(sig!="") + print "attach_sig=on" >> postfile + if(notify!="") + print "notify=on" >> postfile + if(silent!="") + print "silent=on" >> postfile + + print "subject="urlencode(subject) >> postfile + print "subject_h="htmlescape(subject) >> postfile + + print "brtext="brescape(content) >> postfile + + gsub(/\[br\]/,"\n",content) + + for(i=0; content~/\[ong\]/; ++i) + { + tn=sprintf("ong-%u",i) + ongtext = ongtable[tn] + if (ongtext == "") + ongtext=ong() + print(tn"="brescape(ongtext)) >> postfile + sub(/\[ong\]/,subescape(ongtext),content) + } + for(i=0; content~/\[ung\]/; ++i) + { + tn=sprintf("ung-%u",i) + ongtext = ongtable[tn] + if (ongtext == "") + ongtext=ung() + print(tn"="brescape(ongtext)) >> postfile + sub(/\[ung\]/,subescape(ongtext),content) + } + for(i=0; content~/\[ong=decree\]/; ++i) + { + tn=sprintf("ongd-%u",i) + ongtext = ongtable[tn] + if (ongtext == "") + ongtext=ong("decree") + print(tn"="brescape(ongtext)) >> postfile + sub(/\[ong=decree\]/,subescape(ongtext),content) + } + for(i=0; content~/\[ung=decree\]/; ++i) + { + tn=sprintf("ungd-%u",i) + ongtext = ongtable[tn] + if (ongtext == "") + ongtext=ung("decree") + print(tn"="brescape(ongtext)) >> postfile + sub(/\[ung=decree\]/,subescape(ongtext),content) + } + + # print "content:\n"content + print "BBHTML="htmlescape(content,"","br") >> postfile + print "BB="htmlescape(content,"less","br") >> postfile + print "message="urlencode(content ((silent=="")?(nobb==""?"[right][size=80]-- posted by SilentBot [img]http://forums.xkcd.com/download/file.php?id=47884[/img][/size][/right]":"\n\n-- posted by SilentBot"):"")) >> postfile + + print "posted." + system ("mawk -f "bb2html" -v outfile=\""postfile"\" \""postfile"\"") + system ("wait 1") + close (postfile) +} + +function urlencode(name,all, len,iii,escaped,ch) +{ + len=length(name) + escaped="" + for(iii=1;iii<=len;++iii) + { + ch=substr(name,iii,1); + if ((ch ~ /[a-zA-Z0-9\.\-_~]/)&&(all=="")) + escaped = escaped ch + else + escaped = escaped "%" ch2hex[ch] + } + return escaped +} +function hexencode(name, len,iii,escaped,ch) +{ + len=length(name) + escaped="" + for(iii=1;iii<=len;++iii) + { + ch=substr(name,iii,1) + escaped = escaped ch2hex[ch] + } + return escaped +} +function subescape(subtext) +{ + gsub(/&/,"\\\\\\&",subtext) + return subtext +} + +function htmlescape(name,less,br, len,iii,escaped,ch) +{ + len=length(name) + escaped="" + for(iii=1;iii<=len;++iii) + { + ch=substr(name,iii,1); + if(ch == "\n") + escaped = escaped ((br!="")?"
":"&#"ch2dec[ch]";") + else if(ch =="\r") + escaped = escaped ((br!="")?"":"&#"ch2dec[ch]";") + else if(ch ~ /[\" ]/ && less=="")#"#"\"" + escaped = escaped "&#"ch2dec[ch]";" + else if(ch ~ /[=<>&]/) + escaped = escaped "&#"ch2dec[ch]";" + else + escaped = escaped ch + } + return escaped +} + +function getmeme(decree ,meme,i) +{ + if(decree!="" && lastdecr=="") + { + close(tempfile) + system (automome" -lc 256 -n "memenumber" -d "memepath" -t \"[decr]\" > "tempfile) + } + else if(decree=="" && lastdecr!="") + { + close(tempfile) + system (automome" -lc 256 -n "memenumber" -d "memepath" > "tempfile) + } + for(i=0; ((getline meme < tempfile)<=0) && (i<3); ++i) + { + memenumber=memenumber*2 + close(tempfile) + if(decree!="") + system (automome" -lc 256 -n "memenumber" -d "memepath" -t \"[decr]\" > "tempfile) + else + system (automome" -lc 256 -n "memenumber" -d "memepath" > "tempfile) + } + lastdecr=decree + return meme +} + +function ong(decree, line) +{ + # system (automome" -lc 256 -n 67 -d "memepath(decree!=""?" -t \"[decr]\"":"")" > "tempfile) + + while((line=getmeme(decree))!="") + { + gsub(/[\r\n]/,"",line) + if(sub(/[AEIOUY]-N-G/,"#O-N-G#",line)>0) + return preparebb(line) + if(sub(/O+N+G+/,"#&#",line)>0) + return preparebb(line) + if(sub(/DON'T/,"D#ON'G#T",line)>0) + return preparebb(line) + if(sub(/[AEIOUY]NG/,"#ONG#",line)>0) + { + if($0!~/TH\[b\]ONG/) + return preparebb(line) + } + if(sub(/ON /,"#ONG# ",line)>0) + return preparebb(line) + if(sub(/O\.?$/,"#ONG# ",$0)>0) + return preparebb(line) + } + return "Ong" +} + +function ung(decree, line) +{ + # system (automome" -lc 256 -n 67 -d "memepath(decree!=""?" -t \"[decr]\"":"")" > "tempfile) + + while((line=getmeme(decree))!="")#((getline line < tempfile)>0) + { + gsub(/[\r\n]/,"",line) + if(sub(/[AEIOUY]-N-G/,"#U-N-G#",line)>0) + return preparebb(line) + if(sub(/U+N+G+/,"#&#",line)>0) + return preparebb(line) + if(sub(/[AEIOUY]NG/,"#UNG#",line)>0) + return preparebb(line) + if(sub(/UN /,"#UNG# ",line)>0) + return preparebb(line) + if(sub(/U\.?$/,"#UNG# ",$0)>0) + return preparebb(line) + } + return "Ung" +} +function preparebb(rh) +{ + if(nobb=="") + { + gsub(/\*\*/,"¤",rh) + gsub(/\*[^\*]+\*/,"±&±",rh) + gsub(/±\*/,"[i]",rh) + gsub(/\*±/,"[/i]",rh) + gsub(/¤/,"*",rh) + + gsub(/&&/,"¤",rh) + gsub(/&[^&]+&/,"±&±",rh) + gsub(/±&/,"[center][b]",rh) + gsub(/&±/,"[/b][/center]",rh) + gsub(/¤/,"\\&",rh) + + gsub(/__/,"¤",rh) + gsub(/_[^_]+_/,"±&±",rh) + gsub(/±_/,"[u]",rh) + gsub(/_±/,"[/u]",rh) + gsub(/¤/,"_",rh) + + gsub(/##/,"¤",rh) + gsub(/#[^#]+#/,"±&±",rh) + gsub(/±#/,"[b]",rh) + gsub(/#±/,"[/b]",rh) + gsub(/¤/,"#",rh) + + gsub(/\$\$/,"¤",rh) + gsub(/\$[^\$]+\$/,"±&±",rh) + gsub(/±\$/,"[size=80]",rh) + gsub(/\$±/,"[/size]",rh) + gsub(/¤/,"$",rh) + } + + return rh (nobb==""?" -- [url=http://1190.bicyclesonthemoon.info/ongtext?b=on][b]ong[/b]o[/url][url=http://mrob.com/time/automome/]mome[/url]":" -- ongomome") +} +function unhtml(ht ,i,j,un,num) +{ + gsub(//,"[br]",ht) + while ((i=match(ht, /&#[0-9]+;/))!=0)# + { + un=un substr(ht, 1, i-1) + ht=substr(ht, i) + j=index(ht, ";") + num=int(substr(ht, 3, j-3)) + un=un sprintf("%c",num) + ht=substr(ht, j+1) + } + un=un ht + return un +} +function brescape(text) #there will be more +{ + gsub(/\r/,"",text) + gsub(/\n/,"[br]",text) + return text +} +function brunescape(text) #there will be more +{ + gsub(/\[br\]/,"\n",text) + return text +} +function urldecode(ht ,i,j,un,num) +{ + while ((i=match(ht, /%[0-9a-fA-F][0-9a-fA-F]/))!=0)# + { + un=un substr(ht, 1, i-1) + ht=substr(ht, i) + num=toupper(substr(ht, 2, 2)) + un=un hex2ch[num] + ht=substr(ht, 4) + } + un=un ht + return un +} +function newkey( key,i,rn) +{ + for(i=0; i<8; ++i) + { + rn=int(rand()*65536) + key = key sprintf("%04X",rn) + } + return key +} \ No newline at end of file diff --git a/upload.c b/upload.c new file mode 100644 index 0000000..24c5d09 --- /dev/null +++ b/upload.c @@ -0,0 +1,97 @@ +// upload.c (1190.bicyclesonthemoon.info/silentbot/upload) +// The post upload interface +// 28.03.2015 +// +// Copyright (C) 2015 Balthasar Szczepański +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include +#include +#include +#include +#include + +#define RM_PATH "/bin/rm" +#define MAWK_PATH "/usr/bin/mawk" +#define AWK_UPLOAD "/eizm/pro/t1i/upload.awk" +#define TEMP_PATH "/eizm/tmp/t1i/upload." +#define RM_PATH "/bin/rm" + +s_cgi *cgi; +pid_t sub; +int r; + +int main(int argc, char **argv) +{ + char *temppath; + char **up; + time_t posttime; + struct tm *nowS; + char timetext[64]; + char timenumber[64]; + char temppath2[247]; + char temppath3[256]; + + setvbuf(stdout, NULL, _IONBF, 0); + dup2(fileno(stdout),fileno(stderr)); + + cgi=cgiInit(); + + sprintf(temppath2,"%s%lu",TEMP_PATH,(unsigned long)getpid()); + sprintf(temppath3,"tempfile=%s",temppath2); + + printf("Content-type: text\n\n"); + up=cgiGetFiles(cgi); + if (up) + { + temppath=cgiGetFile(cgi,up[0])->tmpfile; + + posttime=time(NULL); + nowS=gmtime(&posttime); + + sprintf(timenumber,"timenumber=%lu",(unsigned long)posttime); + sprintf(timetext,"timetext=%04d%02d%02d%02d",nowS->tm_year+1900,nowS->tm_mon+1,nowS->tm_mday,nowS->tm_hour); + + // printf("%s\n%s\n%s\n",timenumber,timetext,temppath); + + sub=fork(); + if(!sub) + { + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_UPLOAD,"-v",timetext,"-v",timenumber,"-v",temppath3,temppath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + + sub=fork(); + if(!sub) + { + r=execl(RM_PATH,RM_PATH,"-f",temppath,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + sub=fork(); + if(!sub) + { + r=execl(RM_PATH,RM_PATH,"-f",temppath2,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + + return 0; + } + printf("File missing\n"); + return 0; +} diff --git a/verify.awk b/verify.awk new file mode 100644 index 0000000..a0ffc4e --- /dev/null +++ b/verify.awk @@ -0,0 +1,77 @@ +#// verify.awk +#// Check if post belongs to user +#// 25.04.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepański +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero General Public License as +#// published by the Free Software Foundation, either version 3 of the +#// License, or (at your option) any later version. +#// +#// This program is distributed in the hope that it will be useful, +#// but WITHOUT ANY WARRANTY; without even the implied warranty of +#// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#// GNU Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + +BEGIN{ + FS="=" + for(i=0;i<256;++i) + { + ch=sprintf("%c",i) + hex=sprintf("%02X",i); + ch2hex[ch]=hex + hex2ch[hex]=ch + } + if(reversed!="") + { + ok=1 + fail=0 + } + else + { + ok=0 + fail=1 + } +} +{ + gsub(/[\r\n]/,"",$0) + eq=index($0,"=") + argtab[substr($0,1,eq-1)]=substr($0,eq+1) +} +END{ + if(argtab["username"]==""||argtab["password"]==""||(urldecode(argtab["username"])==name&&urldecode(argtab["password"])==pass)) + exit ok + else + exit fail +} +# function urlencode(name,all, len,iii,escaped,ch) +# { + # len=length(name) + # escaped="" + # for(iii=1;iii<=len;++iii) + # { + # ch=substr(name,iii,1); + # if ((ch ~ /[a-zA-Z0-9\.\-_~]/)&&(all=="")) + # escaped = escaped ch + # else + # escaped = escaped "%" ch2hex[ch] + # } + # return escaped +# } +function urldecode(ht ,i,j,un,num) +{ + while ((i=match(ht, /%[0-9a-fA-F][0-9a-fA-F]/))!=0)# + { + un=un substr(ht, 1, i-1) + ht=substr(ht, i) + num=toupper(substr(ht, 2, 2)) + un=un hex2ch[num] + ht=substr(ht, 4) + } + un=un ht + return un +} diff --git a/view.awk b/view.awk new file mode 100644 index 0000000..fcccc6d --- /dev/null +++ b/view.awk @@ -0,0 +1,59 @@ +#// view.awk +#// insert text +#// 27.03.2015 +#// +#// Copyright (C) 2015 Balthasar Szczepañski +#// +#// This program is free software: you can redistribute it and/or modify +#// it under the terms of the GNU Affero General Public License as +#// published by the Free Software Foundation, either version 3 of the +#// License, or (at your option) any later version. +#// +#// This program is distributed in the hope that it will be useful, +#// but WITHOUT ANY WARRANTY; without even the implied warranty of +#// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +#// GNU Affero General Public License for more details. +#// +#// You should have received a copy of the GNU Affero General Public License +#// along with this program. If not, see . + + +###reusedfrommirror; + +{ + # if ($0 ~ /^###sig&/) + # { + # split ($0 ,arr,"&") + # system("cat " sig arr[2]) + # } + # else if ($0 ~ /^###inf&/) + # { + # split ($0 ,arr,"&") + # system("cat " otterinf arr[2]) + # } + # else if ($0 ~ /^###prev/) + # { + # print left + # } + # else if ($0 ~ /^###next/) + # { + # print right + # } + # else if ($0 ~ /^###links/) + # { + # system ("cat " links); + # } + # else + if ($0 ~ /^###info/) + { + print info; + } + else if ($0 ~ /^###title/) + { + print title; + } + else + { + print $0 + } +}; diff --git a/viewer.c b/viewer.c new file mode 100644 index 0000000..2bed7e5 --- /dev/null +++ b/viewer.c @@ -0,0 +1,246 @@ +// viewer.c (1190.bicyclesonthemoon.info/bluet1i/viewer) +// The viewer +// 08.04.2015 +// +// Copyright (C) 2015 Balthasar Szczepań +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#define MAX 1414 +#define NOTICE_PATH "/eizm/mem/aftertime/mpost/" +#define OLD_NOTICE_PATH "/eizm/mem/t1i/notice/" +#define AWK_NOTICE "/eizm/pro/t1i/notice.awk" +#define MAWK_PATH "/usr/bin/mawk" +#define REDIRECT "/aftertime/viewer?story=t1i" + +#include +#include +#include +#include +#include +#include + +s_cgi *cgi; + +int main (int argc, char *argv[]) +{ + s_cgi *cgi; + pid_t sub; + int r; + + char *value; + char *bb; + char *spoiler; + char *blue; + char *nn; + + unsigned char round; + unsigned short cgiFrame; + unsigned char bl; + char alttext[256]; + char notice[256]; + char arg1[256]; + char arg2[256]; + char redirect[256]; + + FILE *file; + unsigned char i; + + cgi=cgiInit(); + + value=cgiGetValue(cgi,"f"); + if(value!=NULL) + sscanf(value,"%hu",&cgiFrame); + else + cgiFrame=0; + + nn=cgiGetValue(cgi,"n"); + if(nn!=NULL) + sscanf(nn,"%hhu",&round); + else + round=0; + + blue=cgiGetValue(cgi,"blue"); + if(blue!=NULL) + sscanf(blue,"%hhu",&bl); + else + bl=1; + + bb=cgiGetValue(cgi,"b"); + spoiler=cgiGetValue(cgi,"s"); + +#if defined REDIRECT + strcpy(redirect,REDIRECT); + if(value!=NULL) + sprintf(redirect+strlen(redirect),"&f=%s",value); + if(nn!=NULL) + sprintf(redirect+strlen(redirect),"&n=%s",nn); + if(blue!=NULL) + sprintf(redirect+strlen(redirect),"&e=%s",blue); + if(bb!=NULL) + sprintf(redirect+strlen(redirect),"&b=%s",bb); + cgiRedirect(redirect); + return 0; +#endif + + if(cgiFrame<0) + cgiFrame=0; + else if(cgiFrame>MAX) + cgiFrame=MAX; + + if(cgiFrame>=1400) + strcpy(alttext,"The end."); + else if(cgiFrame>=1381) + strcpy(alttext,"..."); + else if(cgiFrame>=1196) + strcpy(alttext,"Wait for it."); + else if(cgiFrame>=1192) + strcpy(alttext,"..."); + else if(cgiFrame>=1185) + strcpy(alttext,"Wait for it."); + else if(cgiFrame>=1174) + strcpy(alttext,"..."); + else if(cgiFrame>=1172) + strcpy(alttext,"LOOK OUT!"); + else if(cgiFrame>=1158) + strcpy(alttext,"..."); + else if(cgiFrame>=1046) + strcpy(alttext,"LOOK OUT!"); + else if(cgiFrame>=1039) + strcpy(alttext,"..."); + else if(cgiFrame>=1007) + strcpy(alttext,"Wait for it."); + else if(cgiFrame>=1002) + strcpy(alttext,"..."); + else if(cgiFrame>=972) + strcpy(alttext,"LOOK OUT!"); + else if(cgiFrame>=961) + strcpy(alttext,"..."); + else if(cgiFrame>=715) + strcpy(alttext,"Wait for it."); + else if(cgiFrame>=687) + strcpy(alttext,"..."); + else if(cgiFrame>=653) + strcpy(alttext,"LOOK OUT!"); + else if(cgiFrame>=633) + strcpy(alttext,"..."); + else + strcpy(alttext,"Wait for it."); + + printf("Content-type: text/html\n\n"); + + puts("\n"); + puts("\n"); + printf("%04hu • bluet1i viewer • Bicycles on the Moon\n", cgiFrame); + puts("\n"); + puts("\n"); + puts("\n"); + puts("
\n"); + puts("\"1190.bicyclesonthemoon.info\"
\n"); + printf("

%st1i-%04hu

\n",bl?((bl>1)?((bl>2)?"no fading ":"very blue "):"blue "):"",cgiFrame); + puts("\n",bl); + if(cgiFrame>0) + printf("\n"); + if(cgiFrame%hu >\n",cgiFrame+1,bl,cgiFrame+1); + else + puts("\n"); + printf("\n",MAX,bl,MAX); + + puts("\n"); + + for(i=0;i<=round;++i) + { + sprintf(notice,"%st1i-%04hu-%02hhu",NOTICE_PATH,cgiFrame,i+1); + sprintf(arg1,"url=/bluet1i/viewer?f=%hu&blue=%hhu&n=%hhu",cgiFrame,bl,i+1); + sprintf(arg2,"round=%hhu",round); + + fflush(stdout); + sub=fork(); + if(sub==0) + { + // setvbuf(stdout, NULL, _IONBF, 0); + // dup2(fileno(stdout),fileno(stderr)); + r=execl(MAWK_PATH,MAWK_PATH,"-f",AWK_NOTICE,"-v",arg1,"-v",arg2,notice,(char *)0); + exit(r); + } + waitpid(sub,&r,0); + if(r) + { + if(!i) + { + sprintf(notice,"%s%04hu",OLD_NOTICE_PATH,cgiFrame); + file=fopen(notice,"rt"); + if(file!=NULL) + { + fgets(notice,255,file); + fclose(file); + printf("\n",notice,notice); + } + } + break; + } + + } + + if(bb!=NULL) + { + printf("\n"); + if(spoiler==NULL) + printf("\n",cgiFrame,bl); + } + else + printf("\n",cgiFrame,bl); + + printf("\n",cgiFrame); + + printf("\n",bl); + + puts("
\n"); + + printf("\"the
\n",bl?((bl>1)?((bl>2)?"nofading":"hyperblue"):"bluet1i"):"t1i",cgiFrame,alttext); + + printf("
| < 0< %hu\n",cgiFrame-1,bl,cgiFrame-1); + else + puts("%hu >|
[ "); + if(bl!=0) + printf("original",cgiFrame); + else + puts("original"); + puts(" | "); + if(bl!=1) + printf("blue",cgiFrame); + else + puts("blue"); + puts(" | "); + if(bl!=2) + printf("very blue",cgiFrame); + else + puts("very blue"); + puts(" | "); + if(bl!=3) + printf("no fading",cgiFrame); + else + puts("no fading"); + puts(" ]
Did you notice . . . .
[url=http://1190.bicyclesonthemoon.info/bluet1i/viewer?f=%hu&blue=%hhu][img]http://1190.bicyclesonthemoon.info/bluet1i/%s-%04hu.png[/img][/url]",cgiFrame,bl,bl?((bl>1)?((bl>2)?"nofading":"hyperblue"):"bluet1i"):"t1i",cgiFrame); + if(spoiler!=NULL) + printf("[spoiler]%s[/spoiler]",alttext); + printf("
[spoiler]
[bbcode]
[this frame in mscha's viewer]
go to frame:

\n"); + puts("1190.bicyclesonthemoon.info\n"); + puts("\n"); + puts("
\n"); + + return 0; +} \ No newline at end of file