3 BEGIN { require 'wakautils.pl' }
11 use constant S_NAVIGATION
=> 'Navigation:';
12 use constant S_RETURN
=> 'Return';
13 use constant S_ENTIRE
=> 'Entire thread';
14 use constant S_LAST50
=> 'Last 50 posts';
15 use constant S_FIRST100
=> 'First 100 posts';
16 use constant S_PREV100
=> 'Previous 100 posts';
17 use constant S_NEXT100
=> 'Next 100 posts';
18 use constant S_TOP
=> 'Thread list';
19 use constant S_BOARDLOOK
=> 'Board look:';
20 use constant S_MANAGE
=> 'Manage';
21 use constant S_REBUILD
=> 'Rebuild caches';
22 use constant S_ALLTHREADS
=> 'All threads';
23 use constant S_NEWTHREAD_TITLE
=> 'New thread';
24 use constant S_NAME
=> 'Name:';
25 use constant S_LINK
=> 'Link:';
26 use constant S_FORCEDANON
=> '(Anonymous posting is being enforced)';
27 use constant S_CAPTCHA
=> 'Verification:';
28 use constant S_TITLE
=> 'Title:';
29 use constant S_NEWTHREAD
=> 'Create new thread';
30 use constant S_IMAGE
=> 'Image:';
31 use constant S_IMAGEDIM
=> 'Image: ';
32 use constant S_NOTHUMBNAIL
=> 'No<br />thumbnail';
33 use constant S_REPLY
=> 'Reply';
34 use constant S_LISTEXPL
=> 'Jump to thread list';
35 use constant S_PREVEXPL
=> 'Jump to previous thread';
36 use constant S_NEXTEXPL
=> 'Jump to next thread';
37 use constant S_LISTBUTTON
=> '■';
38 use constant S_PREVBUTTON
=> '▲';
39 use constant S_NEXTBUTTON
=> '▼';
40 use constant S_TRUNC
=> 'Post too long. Click to view the <a href="%s" rel="nofollow">whole post</a> or the <a href="%s">thread page</a>.';
41 use constant S_PERMASAGED
=> ', permasaged';
42 use constant S_POSTERNAME
=> 'Name:';
43 use constant S_DELETE
=> 'Del';
44 use constant S_USERDELETE
=> 'Post deleted by user.';
45 use constant S_MODDELETE
=> 'Post deleted by moderator.';
46 use constant S_CLOSEDTHREAD
=> 'This thread has been closed. You cannot post in this thread any longer.';
47 use constant S_SPAMTRAP
=> 'Leave these fields empty (spam trap): ';
49 use constant S_MOREOPTS
=> "More options...";
50 use constant S_FORMATTING
=> "Formatting:";
51 use constant S_SAVE_FORMATTING
=> "Always use this formatting";
52 use constant S_FORMATS
=> {none
=>"None",waka
=>"WakabaMark",html
=>"HTML",raw
=>"Raw HTML",aa
=>"Text Art"};
53 use constant S_DESCRIBE_FORMATS
=> {
54 none
=>'Only auto-links URLs and >> references.',
55 waka
=>'Simple text formatting. See the description <a href="http://wakaba.c3.cx/docs/docs.html#WakabaMark">here</a>.',
56 html
=>'Allowed tags: <em>'.describe_allowed
(ALLOWED_HTML
).'</em>.',
57 aa
=>'Only auto-links URLs and >> references, and sets the font to be suitable for SJIS art.',
60 use constant S_COL_NUM
=> "Num";
61 use constant S_COL_TITLE
=> "Title";
62 use constant S_COL_POSTS
=> "Posts";
63 use constant S_COL_DATE
=> "Last post";
64 use constant S_COL_SIZE
=> "File size";
65 use constant S_LIST_PERMASAGED
=> 'permasaged';
66 use constant S_LIST_CLOSED
=> 'closed';
68 use constant S_FRONT
=> 'Front page'; # Title of the front page in page list
75 use constant S_BADCAPTCHA
=> 'Wrong verification code entered.'; # Error message when the captcha is wrong
76 use constant S_UNJUST
=> 'Posting must be done through a POST request.'; # Error message on an unjust POST - prevents floodbots or ways not using POST method?
77 use constant S_NOTEXT
=> 'No text entered.'; # Error message for no text entered in to title/comment
78 use constant S_NOTITLE
=> 'No title entered.'; # Error message for no title entered
79 use constant S_NOTALLOWED
=> 'Posting not allowed.'; # Error message when the posting type is forbidden for non-admins
80 use constant S_TOOLONG
=> 'The %s field is too long, by %d characters.'; # Error message for too many characters in a given field
81 use constant S_UNUSUAL
=> 'Abnormal reply.'; # Error message for abnormal reply? (this is a mystery!)
82 use constant S_SPAM
=> 'Spammers are not welcome here!'; # Error message when detecting spam
83 use constant S_THREADCOLL
=> 'Somebody else tried to post a thread at the same time. Please try again.'; # If two people create threads during the same second
84 use constant S_NOTHREADERR
=> 'Thread specified does not exist.'; # Error message when a non-existant thread is accessed
85 use constant S_BADDELPASS
=> 'Password incorrect.'; # Error message for wrong password (when user tries to delete file)
86 use constant S_NOTWRITE
=> 'Cannot write to directory.'; # Error message when the script cannot write to the directory, the chmod (777) is wrong
87 use constant S_NOTASK
=> 'Script error; no valid task specified.'; # Error message when calling the script incorrectly
88 use constant S_NOLOG
=> 'Couldn\'t write to log.txt.'; # Error message when log.txt is not writeable or similar
89 use constant S_TOOBIG
=> 'The file you tried to upload is too large.'; # Error message when the image file is larger than MAX_KB
90 use constant S_EMPTY
=> 'The file you tried to upload is empty.'; # Error message when the image file is 0 bytes
91 use constant S_BADFORMAT
=> 'File format not allowed.'; # Error message when the file is not in a supported format.
92 use constant S_DUPE
=> 'This file has already been posted <a href="%s">here</a>.'; # Error message when an md5 checksum already exists.
93 use constant S_DUPENAME
=> 'A file with the same name already exists.'; # Error message when an filename already exists.
94 use constant S_THREADCLOSED
=> 'This thread is closed.'; # Error message when posting in a legen^H^H^H^H^H closed thread
102 use constant GLOBAL_HEAD_INCLUDE
=> q{
104 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
105 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
107 <title><if $title><var $title> - </if><const TITLE></title>
108 <meta http-equiv="Content-Type" content="text/html;charset=<const CHARSET>" />
109 <link rel="shortcut icon" href="<const expand_filename(FAVICON)>" />
112 <link rel="alternate" title="RSS feed" href="<const expand_filename(RSS_FILE)>" type="application/rss+xml" />
116 <link rel="<if !$default>alternate </if>stylesheet" type="text/css" href="<var expand_filename($filename)>" title="<var $title>" />
119 <script type="text/javascript">
120 var self="<var $self>";
121 var style_cookie="<const STYLE_COOKIE>";
122 var markup_descriptions={
123 <loop $markup_formats><var $id>:<var js_string(S_DESCRIBE_FORMATS-\>{$id})>,</loop>dummy:''
126 <script type="text/javascript" src="<const expand_filename(JS_FILE)>"></script>
127 <script type="text/javascript">require_script_version("3.a");</script>
133 use constant GLOBAL_FOOT_INCLUDE => include(INCLUDE_DIR."footer.html").q{
139 use constant POSTING_FORM_TEMPLATE
=> compile_template
(q{
141 <td><const S_TITLE></td>
143 <input type="text" name="title" size="46" maxlength="<const MAX_FIELD_LENGTH>" />
144 <input type="submit" value="<const S_NEWTHREAD>" />
150 <if !FORCED_ANON><const S_NAME></if>
151 <if FORCED_ANON><const S_LINK></if>
153 <if !FORCED_ANON><input type="text" name="field_a" size="19" maxlength="<const MAX_FIELD_LENGTH>" /> <const S_LINK> </if>
154 <if FORCED_ANON><input type="hidden" name="field_a" /></if>
155 <input type="text" name="field_b" size="19" maxlength="<const MAX_FIELD_LENGTH>" />
156 <if $thread><input type="submit" value="<const S_REPLY>" /></if>
157 <if SPAM_TRAP><div style="display:none"><const S_SPAMTRAP><input type="text" name="name" size="19" autocomplete="off" /><input type="text" name="link" size="19" autocomplete="off" /></div></if>
158 <small><a href="javascript:show('options<var $thread>')"><const S_MOREOPTS></a></small>
162 <if ENABLE_CAPTCHA><tr>
163 <td><const S_CAPTCHA></td>
165 <input type="text" name="captcha" size="19" />
166 <img class="<var $captchaclass>" src="<const expand_filename('captcha.pl')>?selector=.<var $captchaclass>" />
170 <tr style="display:none;vertical-align:top" id="options<var $thread>">
171 <td><const S_FORMATTING></td>
173 <select name="markup" onchange="select_markup(this)"><loop $markup_formats>
174 <option value="<var $id>" <if DEFAULT_MARKUP eq $id>selected="selected"</if>><var S_FORMATS-\>{$id}></option>
176 <label><input type="checkbox" name="savemarkup" /> <const S_SAVE_FORMATTING></label>
177 <input type="button" value="Preview post" onclick="preview_post('<var $formid>','<var $thread>')" />
178 <br /><small></small>
179 <div id="preview<var $thread>" class="replytext" style="display:none"></div>
185 <td><textarea name="comment" cols="64" rows="5" onfocus="size_field('<var $formid>',15)" onblur="size_field('<var $formid>',5)"></textarea></td>
188 <if $allowimages><tr>
189 <td><const S_IMAGE></td>
190 <td><input name="file" size="49" type="file" /></td>
196 use constant MAIN_PAGE_TEMPLATE => compile_template( GLOBAL_HEAD_INCLUDE.q{
197 <body class="mainpage">
199 }.include
(INCLUDE_DIR
."header.html").q{
201 <div id="titlebox" class="outerbox"><div class="innerbox">
204 <if SHOWTITLEIMG==1><img src="<var expand_filename(TITLEIMG)>" alt="<const TITLE>" /></if>
205 <if SHOWTITLEIMG==2><img src="<var expand_filename(TITLEIMG)>" onclick="this.src=this.src;" alt="<const TITLE>" /></if>
206 <if SHOWTITLEIMG and SHOWTITLETXT><br /></if>
207 <if SHOWTITLETXT><const TITLE></if>
210 <div class="threadnavigation">
211 <a href="#menu" title="<const S_LISTEXPL>"><const S_LISTBUTTON></a>
212 <a href="#1" title="<const S_NEXTEXPL>"><const S_NEXTBUTTON></a>
216 }.include
(INCLUDE_DIR
."rules.html").q{
221 <div id="stylebox" class="outerbox"><div class="innerbox">
223 <strong><const S_BOARDLOOK></strong>
225 <a href="javascript:set_stylesheet('<var $title>')"><var $title></a>
232 }.include(INCLUDE_DIR."mid.html").q{
234 <div id="threadbox" class="outerbox"><div class="innerbox">
236 <div id="threadlist">
237 <loop $allthreads><if $num<=THREADS_LISTED>
238 <span class="threadlink">
239 <a href="<var $self>/<var $thread>/l50" rel="nofollow"><var $num>:
240 <if $num<=THREADS_DISPLAYED></a><a href="#<var $num>"></if>
241 <var $title> (<var $postcount>)</a>
246 <div id="threadlinks">
247 <a href="#newthread"><const S_NEWTHREAD_TITLE></a>
248 <a href="<const expand_filename(HTML_BACKLOG)>"><const S_ALLTHREADS></a>
256 <a name="<var $num>"></a>
257 <if $permasage><div class="sagethread"></if>
258 <if !$permasage><div class="thread"></if>
259 <h2><a href="<var $self>/<var $thread>/l50" rel="nofollow"><var $title>
260 <small>(<var $postcount><if $permasage>, permasaged</if>)</small></a></h2>
262 <div class="threadnavigation">
263 <a href="#menu" title="<const S_LISTEXPL>"><const S_LISTBUTTON></a>
264 <a href="#<var $prevnum>" title="<const S_PREVEXPL>"><const S_PREVBUTTON></a>
265 <a href="#<var $nextnum>" title="<const S_NEXTEXPL>"><const S_NEXTBUTTON></a>
268 <div class="replies">
270 <if $omit><div class="firstreply"></if>
271 <if !$omit><div class="allreplies"></if>
276 <div class="replyabbrev">
277 <var sprintf(S_TRUNC,"$self/$thread/$num","$self/$thread/l50")>
281 <if $omit and $num==1>
282 </div><div class="repliesomitted"></div><div class="finalreplies">
289 <form id="postform<var $thread>" action="<var $self>" method="post" enctype="multipart/form-data">
290 <input type="hidden" name="task" value="post" />
291 <input type="hidden" name="thread" value="<var $thread>" />
292 <input type="hidden" name="password" value="" />
294 <if !$closed><var POSTING_FORM_TEMPLATE-\>(thread=\>$thread,captchaclass=\>"postcaptcha",formid=\>"postform$thread",allowimages=\>ALLOW_IMAGE_REPLIES)></if>
295 <if $closed><tr><td></td><td><big><const S_CLOSEDTHREAD></big></td></tr></if>
298 <td><div class="threadlinks">
299 <a href="<var $self>/<var $thread>/"><const S_ENTIRE></a>
300 <a href="<var $self>/<var $thread>/l50" rel="nofollow"><const S_LAST50></a>
301 <a href="<var $self>/<var $thread>/-100" rel="nofollow"><const S_FIRST100></a>
302 <a href="#menu"><const S_TOP></a>
307 <script type="text/javascript">set_new_inputs("postform<var $thread>");</script>
314 <a name="newthread"></a>
316 <div id="createbox" class="outerbox"><div class="innerbox">
317 <h2><const S_NEWTHREAD_TITLE></h2>
319 <form id="threadform" action="<var $self>" method="post" enctype="multipart/form-data">
321 <input type="hidden" name="task" value="post" />
322 <input type="hidden" name="password" value="" />
324 <var POSTING_FORM_TEMPLATE-\>(captchaclass=\>"threadcaptcha",formid=\>"threadform",allowimages=\>ALLOW_IMAGE_THREADS)>
330 <script type="text/javascript">set_new_inputs("threadform");</script>
332 }.GLOBAL_FOOT_INCLUDE,KEEP_MAINPAGE_NEWLINES);
337 use constant THREAD_HEAD_TEMPLATE => compile_template( GLOBAL_HEAD_INCLUDE.q{
338 <body class="threadpage">
340 }.include
(INCLUDE_DIR
."header.html").q{
342 <div id="navigation">
343 <strong><const S_NAVIGATION></strong>
344 <a href="<const expand_filename(HTML_SELF)>"><const S_RETURN></a>
345 <a href="<var $self>/<var $thread>/"><const S_ENTIRE></a>
346 <a href="<var $self>/<var $thread>/-100" rel="nofollow"><const S_FIRST100></a>
347 <loop [map {+{'start'=\>$_*100+1}} (1..($postcount-1)/100)]>
348 <a href="<var $self>/<var $thread>/<var $start>-<var $start+99<$postcount?$start+99:$postcount>" rel="nofollow"><var $start>-</a>
350 <a href="<var $self>/<var $thread>/l50" rel="nofollow"><const S_LAST50></a>
355 <if $permasage><div class="sagethread"></if>
356 <if !$permasage><div class="thread"></if>
357 <h2><var $title> <small>(<var $postcount><if $permasage><const S_PERMASAGED></if>)</small></h2>
359 <div class="replies">
360 <div class="allreplies">
365 use constant THREAD_FOOT_TEMPLATE => compile_template( q{
371 <h4><var int($size/1024)> kb</h4>
374 <form id="postform<var $thread>" action="<var $self>" method="post" enctype="multipart/form-data">
376 <input type="hidden" name="task" value="post" />
377 <input type="hidden" name="thread" value="<var $thread>" />
378 <input type="hidden" name="password" value="" />
382 <td><div class="threadlinks">
383 <a href="<const expand_filename(HTML_SELF)>"><const S_RETURN></a>
384 <a href="<var $self>/<var $thread>/"><const S_ENTIRE></a>
385 <if $prevpost><a href="<var $self>/<var $thread>/<var $prevpost\>99?$prevpost-99:1>-<var $prevpost>" rel="nofollow"><const S_PREV100></a></if>
386 <if $nextpost><a href="<var $self>/<var $thread>/<var $nextpost>-<var $nextpost<$postcount-99?$nextpost+99:$postcount>" rel="nofollow"><const S_NEXT100></a></if>
387 <a href="<var $self>/<var $thread>/l50" rel="nofollow"><const S_LAST50></a>
390 <if !$closed><var POSTING_FORM_TEMPLATE-\>(thread=\>$thread,captchaclass=\>"postcaptcha",formid=\>"postform$thread",allowimages=\>ALLOW_IMAGE_REPLIES)></if>
391 <if $closed><tr><td></td><td><big><const S_CLOSEDTHREAD></big></td></tr></if>
396 <script type="text/javascript">set_new_inputs("postform<var $thread>");</script>
401 }.GLOBAL_FOOT_INCLUDE);
405 use constant REPLY_TEMPLATE => compile_template( q{
410 <span class="replynum"><a title="Quote post number in reply" href="javascript:insert('>><var $num>',<var $thread>)"><var $num></a></span>
412 <if $link><span class="postername"><a href="<var $link>" rel="nofollow"><var $name></a></span><span class="postertrip"><a href="<var $link>" rel="nofollow"><if !$capped><var $trip></if><if $capped><var $capped></if></a></span></if>
413 <if !$link><span class="postername"><var $name></span><span class="postertrip"><if !$capped><var $trip></if><if $capped><var $capped></if></span></if>
415 <if $image><span class="filesize">(<const S_IMAGEDIM><em><var $width>x<var $height> <var $ext>, <var int($size/1024)> kb</em>)</span></if>
416 <span class="deletebutton">
417 <if ENABLE_DELETION>[<a href="javascript:delete_post(<var $thread>,<var $num><if $image>,true</if>)"><const S_DELETE></a>]</if>
418 <if !ENABLE_DELETION><span class="manage" style="display:none;">[<a href="javascript:delete_post(<var $thread>,<var $num><if $image>,true</if>)"><const S_DELETE></a>]</span></if>
424 <a href="<var expand_filename(clean_path($image))>">
425 <img src="<var expand_filename($thumbnail)>" width="<var $tn_width>" height="<var $tn_height>"
426 alt="<var clean_string($image)>: <var $width>x<var $height>, <var int($size/1024)> kb"
427 title="<var clean_string($image)>: <var $width>x<var $height>, <var int($size/1024)> kb"
429 </if><if !$thumbnail>
430 <div class="nothumbnail">
431 <a href="<var expand_filename(clean_path($image))>"><const S_NOTHUMBNAIL></a>
436 <div class="replytext"><var $comment></div>
443 use constant DELETED_TEMPLATE => compile_template( q{
444 <div class="deletedreply">
446 <span class="replynum"><var $num></span>
447 <if $reason eq 'user'><const S_USERDELETE></if>
448 <if $reason eq 'mod'><const S_MODDELETE></if>
455 use constant BACKLOG_PAGE_TEMPLATE => compile_template( GLOBAL_HEAD_INCLUDE.q{
456 <body class="backlogpage">
458 }.include
(INCLUDE_DIR
."header.html").q{
460 <div id="navigation">
461 <strong><const S_NAVIGATION></strong>
462 <a href="<const expand_filename(HTML_SELF)>"><const S_RETURN></a>
467 <h1><const TITLE></h1>
469 <table id="oldthreadlist">
473 <th><const S_COL_NUM></th>
474 <th><const S_COL_TITLE></th>
475 <th><const S_COL_POSTS></th>
476 <th><const S_COL_DATE></th>
477 <th><const S_COL_SIZE></th>
483 <tr class="line<var $num&1>">
485 <td align="right"><var $num>:</td>
486 <td><a href="<var $self>/<var $thread>/l50" rel="nofollow"><var $title><if $closed or $permasage> <small>(<if $closed><const S_LIST_CLOSED></if><if !$closed and $permasage><const S_LIST_PERMASAGED></if>)</small></if></a></td>
487 <td align="right"><a href="<var $self>/<var $thread>/"><var $postcount></a></td>
488 <td><var make_date($lastmod,DATE_STYLE)></td>
489 <td align="right"><var int($size/1024)> kb</td>
497 }.GLOBAL_FOOT_INCLUDE);
501 use constant RSS_TEMPLATE => compile_template( q{
502 <?xml version="1.0" encoding="<const CHARSET>"?>
506 <title><const TITLE></title>
507 <link><var $absolute_path><const HTML_SELF></link>
508 <description>Posts on <const TITLE> at <var $ENV{SERVER_NAME}>.</description>
510 <loop $threads><if $num<=THREADS_DISPLAYED>
512 <title><var $title> (<var $postcount>)</title>
513 <link><var $absolute_self>/<var $thread>/</link>
514 <guid><var $absolute_self>/<var $thread>/</guid>
515 <comments><var $absolute_self>/<var $thread>/</comments>
516 <author><var $author></author>
517 <description><![CDATA[
518 <var $$posts[0]{abbreviation}=~m!<div class="replytext".(.*?)</div!; $1 >
519 <if $abbreviated><p><small>Post too long, full version <a href="<var $absolute_self>/<var $thread>/">here</a>.</small></p>
531 use constant ERROR_TEMPLATE => compile_template( GLOBAL_HEAD_INCLUDE.q{
532 <body class="errorpage">
534 }.include
(INCLUDE_DIR
."header.html").q{
536 <div id="navigation">
537 <strong><const S_NAVIGATION></strong>
538 <a href="<var escamp($ENV{HTTP_REFERER})>"><const S_RETURN></a>
541 <h1><var $error></h1>
543 <h2><a href="<var escamp($ENV{HTTP_REFERER})>"><const S_RETURN></a></h2>
545 }.GLOBAL_FOOT_INCLUDE);