aboutsummaryrefslogtreecommitdiff
path: root/cgi/templates
diff options
context:
space:
mode:
authorLibravatar bai 2019-03-29 02:14:43 +0000
committerLibravatar bai 2019-03-29 02:14:43 +0000
commit95dfe14528663923ca2a88ec928f1d8d9df2402b (patch)
tree5bc88d1466957f1aa39043b056bde5c439648022 /cgi/templates
downloadweabot-95dfe14528663923ca2a88ec928f1d8d9df2402b.tar.gz
weabot-95dfe14528663923ca2a88ec928f1d8d9df2402b.tar.xz
weabot-95dfe14528663923ca2a88ec928f1d8d9df2402b.zip
Init
Diffstat (limited to 'cgi/templates')
-rw-r--r--cgi/templates/anarkia.html329
-rw-r--r--cgi/templates/banned.html34
-rw-r--r--cgi/templates/base_bottom.html3
-rw-r--r--cgi/templates/base_top.html55
-rw-r--r--cgi/templates/board.0.html230
-rw-r--r--cgi/templates/board.html264
-rw-r--r--cgi/templates/board.jp.html271
-rw-r--r--cgi/templates/catalog.html30
-rw-r--r--cgi/templates/error.html7
-rw-r--r--cgi/templates/exception.html36
-rw-r--r--cgi/templates/home.rss24
-rw-r--r--cgi/templates/htaccess24
-rw-r--r--cgi/templates/kako.html60
-rw-r--r--cgi/templates/manage/addboard.html21
-rw-r--r--cgi/templates/manage/bans.html92
-rw-r--r--cgi/templates/manage/boardoptions.html195
-rw-r--r--cgi/templates/manage/changepassword.html24
-rw-r--r--cgi/templates/manage/delete.html23
-rw-r--r--cgi/templates/manage/filters.html119
-rw-r--r--cgi/templates/manage/ipdelete.html24
-rw-r--r--cgi/templates/manage/ipshow.html73
-rw-r--r--cgi/templates/manage/lockboard.html20
-rw-r--r--cgi/templates/manage/login.html21
-rw-r--r--cgi/templates/manage/logs.html17
-rw-r--r--cgi/templates/manage/manage.html22
-rw-r--r--cgi/templates/manage/menu.html30
-rw-r--r--cgi/templates/manage/message.html8
-rw-r--r--cgi/templates/manage/mod.html96
-rw-r--r--cgi/templates/manage/move.html60
-rw-r--r--cgi/templates/manage/quotes.html12
-rw-r--r--cgi/templates/manage/rebuild.html20
-rw-r--r--cgi/templates/manage/recent_images.html24
-rw-r--r--cgi/templates/manage/recyclebin.html72
-rw-r--r--cgi/templates/manage/reports.html58
-rw-r--r--cgi/templates/manage/search.html27
-rw-r--r--cgi/templates/manage/staff.html63
-rw-r--r--cgi/templates/mobile/base_top.html14
-rw-r--r--cgi/templates/mobile/board.html55
-rw-r--r--cgi/templates/mobile/error.html6
-rw-r--r--cgi/templates/mobile/latest.html14
-rw-r--r--cgi/templates/mobile/newest.html14
-rw-r--r--cgi/templates/mobile/threadlist.html43
-rw-r--r--cgi/templates/mobile/txt_newthread.html35
-rw-r--r--cgi/templates/mobile/txt_thread.html74
-rw-r--r--cgi/templates/mobile/txt_threadlist.html26
-rw-r--r--cgi/templates/mod.html86
-rw-r--r--cgi/templates/navbar.html16
-rw-r--r--cgi/templates/paint.html79
-rw-r--r--cgi/templates/redirect.html12
-rw-r--r--cgi/templates/report.html29
-rw-r--r--cgi/templates/revision.html1
-rw-r--r--cgi/templates/stats.html163
-rw-r--r--cgi/templates/txt_archive.html104
-rw-r--r--cgi/templates/txt_base_top.html44
-rw-r--r--cgi/templates/txt_board.en.html137
-rw-r--r--cgi/templates/txt_board.html137
-rw-r--r--cgi/templates/txt_error.html50
-rw-r--r--cgi/templates/txt_thread.en.html105
-rw-r--r--cgi/templates/txt_thread.html101
-rw-r--r--cgi/templates/txt_threadlist.html67
60 files changed, 3900 insertions, 0 deletions
diff --git a/cgi/templates/anarkia.html b/cgi/templates/anarkia.html
new file mode 100644
index 0000000..3ded9da
--- /dev/null
+++ b/cgi/templates/anarkia.html
@@ -0,0 +1,329 @@
+<?py include('templates/base_top.html') ?>
+<?py from tenjin.helpers.html import * ?>
+<style>.anarkiahead {width:1000px; text-align:left}
+.anarkiahead h2 {margin-top: 0}
+.anarkiamenu a {font-size:20pt;display:inline-block;width:300px;padding:10px 0}
+.logs {font-size:small;max-height:300px;overflow-y:auto;width:600px}
+.long {white-space:nowrap}
+.full {width:100%}
+.return {font-size:24pt}</style>
+<center>
+<div class="replymode" style="font-size:26pt;color:red;font-weight:bold">ⒶⒶⒶⒶⒶⒶⒶⒶⒶⒶⒶⒶⒶⒶ</div>
+<br />
+<?py if mode == 0: ?>
+ <div class="anarkiahead">
+ <h2 style="border-bottom:1px solid;width:100%;">Anarkía @ B.a.I.</h2>
+ <p>Anarkía es una sección especial sin moderación y con acceso libre a su panel de administración.</p>
+ <ul>
+ <li>El staff de B.a.I. no interferirá de ninguna manera en esta sección y cualquiera es libre de modificar
+ sus parámetros, de eliminar mensajes o banear usuarios dentro de ella.</li>
+ <li>Los hilos de otras secciones que sean eliminados por su baja calidad, denuncias u otra razón, caerán por defecto a esta sección.</li>
+ <li>Los bans en esta sección son independientes del resto del sitio. Es decir, usuarios baneados en BaI son libres de usar esta sección.</li>
+ <li>Cualquier problema en su funcionamiento por favor reportar en la sección <a href="/bai/">Meta</a>.</li>
+ </div>
+ <div class="anarkiamenu">
+ <a href="#{cgi_url}anarkia/opt"><img src="#{boards_url}anarkia/opt.jpg" width="250" height="175"><br />Opciones generales</a>
+ <a href="#{cgi_url}anarkia/mod"><img src="#{boards_url}anarkia/mod.jpg" width="250" height="175"><br />Panel de moderación</a>
+ <a href="#{cgi_url}anarkia/css"><img src="#{boards_url}anarkia/css.jpg" width="250" height="175"><br />Editar CSS</a>
+ <br />
+ <a href="#{cgi_url}anarkia/emojis"><img src="#{boards_url}anarkia/emojis.jpg" width="250" height="175"><br />Emojis</a>
+ <a href="#{cgi_url}anarkia/bans"><img src="#{boards_url}anarkia/bans.jpg" width="250" height="175"><br />Bans</a>
+ <a href="#{cgi_url}anarkia/type"><img src="#{boards_url}anarkia/type.jpg" width="250" height="175"><br />Cambiar tipo de board</a>
+ </div>
+ <hr />
+ <input type="hidden" name="board" value="anarkia" />
+ <div class="logs">
+ <table class="managertable full">
+ <tr><th colspan="2">Logs</th></tr>
+ <tr><th>Fecha</th><th class="full">Acción</th></tr>
+ <?py for log in logs: ?>
+ <tr><td class="date" data-unix="${log['timestamp']}">${log['timestamp_formatted']}</td><td>${log['action']}</td></tr>
+ <?py #endfor ?>
+ </table>
+ </div>
+ <hr /><a href="#{boards_url}anarkia" class="return">Volver a la sección</a>
+<?py elif mode == 1: ?>
+<div class="replymode">Opciones de Board</div>
+<form action="#{cgi_url}anarkia/opt" method="post">
+<table>
+ <tr>
+ <td class="postblock">Nombre de sección</td>
+ <td><input type="text" name="longname" size="50" value="${boardopts['longname']}" maxlength="128" class="full" /></td>
+ </tr>
+ <tr>
+ <td class="postblock">Descripción</td>
+ <td>
+ <textarea id="patop" name="postarea_desc" rows="10" cols="50" class="full" oninput="pvw('patop')">${boardopts['postarea_desc']}</textarea>
+ <div id="p_patop" style="border:1px dotted gray;width:100%;"></div>
+ </td>
+ </tr>
+ <tr>
+ <td class="postblock">Caja extra</td>
+ <td><textarea name="postarea_extra" rows="5" cols="50" class="full">${boardopts['postarea_extra']}</textarea></td>
+ </tr>
+ <tr>
+ <td class="postblock">Nombre por defecto</td>
+ <td><input type="text" name="anonymous" size="50" maxlength="128" value="${boardopts['anonymous']}" class="full" /></td>
+ </tr>
+ <tr>
+ <td class="postblock">Título por defecto</td>
+ <td><input type="text" name="subject" size="50" maxlength="64" value="${boardopts['subject']}" class="full" /></td>
+ </tr>
+ <tr>
+ <td class="postblock">Mensaje por defecto</td>
+ <td><input type="text" name="message" size="50" maxlength="128" value="${boardopts['message']}" class="full" /></td>
+ </tr>
+ <tr>
+ <td class="postblock">ID</td>
+ <td>
+ <select name="useid" class="full">
+ <option value="0">Desactivado</option>
+ <option value="1"#{selected(boardopts['useid'] == '1')}>Activado</option>
+ <option value="2"#{selected(boardopts['useid'] == '2')}>Activado siempre</option>
+ <option value="3"#{selected(boardopts['useid'] == '3')}>Activado siempre, detallado</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td class="postblock">Desactivar nombre</td>
+ <td><input type="checkbox" name="disable_name" id="noname" value="1"#{checked(boardopts['disable_name'] == '1')} /><label for="noname"></label></td>
+ </tr>
+ <tr>
+ <td class="postblock">Desactivar asunto</td>
+ <td><input type="checkbox" name="disable_subject" id="nosub" value="1"#{checked(boardopts['disable_subject'] == '1')} /><label for="nosub"></label></td>
+ </tr>
+ <tr>
+ <td class="postblock">Permitir crear hilos sin imagen</td>
+ <td><input type="checkbox" name="allow_noimage" id="noimgallow" value="1"#{checked(boardopts['allow_noimage'] == '1')} /><label for="noimgallow"></label></td>
+ </tr>
+ <tr>
+ <td class="postblock">Permitir subida</td>
+ <td><input type="checkbox" name="allow_images" id="img" value="1"#{checked(boardopts['allow_images'] == '1')} /><label for="img">Al crear un hilo</label><br /><input type="checkbox" name="allow_image_replies" id="imgres" value="1"#{checked(boardopts['allow_image_replies'] == '1')} /><label for="imgres">Al responder</label></td>
+ </tr>
+ <tr>
+ <td class="postblock">Tipos de archivo</td>
+ <td>
+ <?py for filetype in filetypes: ?>
+ <input type="checkbox" name="filetype#{filetype['ext']}" id="#{filetype['ext']}" value="1"#{checked(filetype['ext'] in supported_filetypes)} /><label for="#{filetype['ext']}">${filetype['ext'].upper()}</label><br />
+ <?py #endfor ?>
+ </td>
+ </tr>
+ <tr>
+ <td class="postblock">Tamaño máximo <span style="font-weight:normal;">(KB)</span></td>
+ <td><input type="text" name="maxsize" value="#{boardopts['maxsize']}" maxlength="5" size="11" /></td>
+ </tr>
+ <tr>
+ <td class="postblock">Dimensión de miniatura <span style="font-weight:normal;">(px)</span></td>
+ <td><input type="text" name="thumb_px" value="#{boardopts['thumb_px']}" maxlength="3" size="11" /></td>
+ </tr>
+ <tr>
+ <td class="postblock">Hilos en página frontal</td>
+ <td><input type="text" name="numthreads" value="#{boardopts['numthreads']}" maxlength="2" size="11" /></td>
+ </tr>
+ <tr>
+ <td class="postblock">Respuestas a mostrar</td>
+ <td><input type="text" name="numcont" value="#{boardopts['numcont']}" maxlength="2" size="11" /></td>
+ </tr>
+</table>
+<hr />
+<input type="submit" value="Guardar cambios" />
+</form>
+<hr />
+<a href="#{cgi_url}anarkia" class="return">Volver al menú</a>
+<?py elif mode == 2: ?>
+<div class="replymode">Denuncias</div>
+<?py if reports: ?>
+ <table class="managertable" style="max-width:1000px">
+ <tr>
+ <th>Post</th>
+ <th>Fecha</th>
+ <th style="min-width:200px;">Razón</th>
+ </tr>
+ <?py for r in reports: ?>
+ <tr>
+ <td><a href="?thread=#{r['parentid'] if r['parentid'] != "0" else r['postid']}##{r['postid']}" style="font-weight:bold">#{r['postid']}</td>
+ <td>${r['timestamp_formatted']}</td>
+ <td>#{r['reason']}</a></td>
+ </tr>
+ <?py #endfor ?>
+ </table>
+<?py else: ?>
+ No hay denuncias.<br />
+<?py #endif ?>
+<br />
+<div class="replymode">Lista de hilos</div>
+<table class="managertable" style="max-width:1000px;">
+<tr>
+ <th>#</th>
+ <th>ID</th>
+ <th style="width:50%;">Asunto</th>
+ <th>Fecha</th>
+ <th style="width:50%;">Mensaje</th>
+ <th>Posts</th>
+ <th>Acción</th>
+</tr>
+<?py i = 1 ?>
+<?py for thread in threads: ?>
+<tr>
+ <td>#{i}</td>
+ <td>#{thread['id']}</td>
+ <td><a href="?thread=#{thread['id']}" style="font-size:16pt;"><b>#{thread['subject'][:30]}</b></a></td>
+ <td>#{thread['timestamp_formatted'][:21]}</td>
+ <td>${thread['message'][:250]}</td>
+ <td>#{thread['length']}</td>
+ <td>[<a href="?lock=#{thread['id']}">#{"<b>Abrir</b>" if thread['locked'] == "1" else "Cerrar"}</a>]</td>
+</tr>
+<?py i += 1 ?>
+<?py #endfor ?>
+</table>
+<hr /><a href="#{cgi_url}anarkia" class="return">Volver al menú</a>
+<?py elif mode == 3: ?>
+<div class="replymode" style="font-size:16pt">Hilo: ${posts[0]['subject']} (#{posts[0]['length']})</div>
+<table class="managertable" style="width:1000px;">
+ <tr>
+ <th>#</th>
+ <th>ID</th>
+ <th>Fecha</th>
+ <th>Nombre</th>
+ <th>Mensaje</th>
+ <th>Usuario</th>
+ </tr>
+<?py i = 1 ?>
+<?py for p in posts: ?>
+<?py if p['IS_DELETED'] == '0': ?>
+ <tr>
+ <td>#{i}</td>
+ <td class="long">
+ <b>#{p['id']}</b>
+ <?py if p['parentid'] != '0': ?>
+ [<a href="?del=#{p['id']}">Eliminar</a>]
+ <?py else: ?>
+ [<a href="?lock=#{p['id']}">#{"<b>Abrir</b>" if p['locked'] == "1" else "Cerrar"}</a>]
+ <?py #endif ?>
+ </td>
+ <td>${p['timestamp_formatted']}</td>
+ <td><span class="postername">${p['name']}</span></td>
+ <td>${p['message']}</td>
+ <td class="long">#{p['ip'][:4]} [<a href="?ban=#{p['id']}">Ban</a>]</td>
+ </tr>
+<?py else: ?>
+ <tr>
+ <td>#{i}</td>
+ <td class="long"><b>#{p['id']}</b> [<a href="?restore=#{p['id']}">Recuperar</a>]</td>
+ <td colspan="4">Eliminado.</td>
+ </tr>
+<?py #endif ?>
+<?py i += 1 ?>
+<?py #endfor ?>
+</table>
+<hr /><a href="#{cgi_url}anarkia/mod" class="return">Volver al panel de moderación</a>
+<?py elif mode == 4: ?>
+<div class="replymode">Colocar ban</div>
+<form action="#{cgi_url}anarkia/mod" name="banform" method="post">
+<input type="hidden" name="banto" value="#{post['id']}" />
+<table>
+ <tr><td class="postblock">Ban para usuario</td><td><b>#{post['ip'][-4:]}</b></td></tr>
+ <tr><td class="postblock">Mensaje</td><td><textarea name="reason" class="full" maxlength="512"></textarea></td></tr>
+ <tr><td class="postblock">Ciego</td><td><input type="checkbox" name="blind" value="1" checked="checked" /></td></tr>
+ <tr><td class="postblock">Expira en <span style="font-weight:normal;">(segundos)</span></td>
+ <td><input type="text" name="seconds" class="full" value="3600" maxlength="8" /><br />
+ <a href="#" onclick="document.banform.seconds.value='0';return false;">Nunca</a>
+ <a href="#" onclick="document.banform.seconds.value='3600';return false;">1hr</a>
+ <a href="#" onclick="document.banform.seconds.value='43200';return false;">12hr</a>
+ <a href="#" onclick="document.banform.seconds.value='86400';return false;">1d</a>
+ <a href="#" onclick="document.banform.seconds.value='259200';return false;">3d</a>
+ <a href="#" onclick="document.banform.seconds.value='604800';return false;">1w</a>
+ <a href="#" onclick="document.banform.seconds.value='2592000';return false;">1m</a>
+ <a href="#" onclick="document.banform.seconds.value='31536000';return false;">1yr</a>
+ </td>
+ </tr>
+ <tr><td colspan="2"><input type="submit" value="Banear" class="full" /></td></tr>
+</table>
+</form>
+<hr />
+<a href="#{cgi_url}anarkia/mod" class="return">Volver al panel de moderación</a>
+<?py elif mode == 5: ?>
+<div class="replymode">Lista de bans</div>
+<table class="managertable" style="max-width:1000px;">
+<tr>
+ <th>ID</th>
+ <th>Usuario</th>
+ <th>Puesto</th>
+ <th>Expira</th>
+ <th>Ciego</th>
+ <th style="min-width:200px;">Razón</th>
+ <th>Acción</th>
+</tr>
+<?py if bans: ?>
+ <?py for ban in bans: ?>
+ <tr>
+ <td class="long">#{ban['id']}</td>
+ <td>#{ban['ip'][-4:]}</td>
+ <td>${ban['added']}</td>
+ <td>${ban['until']}</td>
+ <td>${"Sí" if ban['blind'] == "1" else "No"}</td>
+ <td>${ban['reason']}</td>
+ <td>[<a href="?unban=#{ban['id']}">Eliminar ban</a>]</td>
+ </tr>
+ <?py #endfor ?>
+<?py else: ?>
+ <tr><td colspan="7" style="text-align:center;">No hay bans.</td></tr>
+<?py #endif ?>
+</table>
+<hr />
+<a href="#{cgi_url}anarkia" class="return">Volver al menú</a>
+<?py elif mode == 6: ?>
+<div class="replymode">Editar CSS</div>
+<p><b>Editando:</b> <code>${basename}</code></p>
+<p style="font-size:small">Dominios permitidos: https://bienvenidoainternet.org https://i.imgur.com</p>
+<form action="#{cgi_url}anarkia/css" name="cssform" method="post" style="display:inline-block;">
+<textarea name="cssfile" cols="100" rows="30">${cssfile}</textarea><br />
+<input type="submit" value="Guardar cambios" class="full" />
+</form>
+<hr />
+<a href="#{cgi_url}anarkia" class="return">Volver al menú</a>
+<?py elif mode == 7: ?>
+<div class="replymode">Cambiar tipo de sección</div>
+<h1 style="color:red;font-size:26pt;text-decoration:underline;">ATENCIÓN</h1>
+<p style="font-size:19pt">Estás a punto de cambiar la estructura de esta sección a #{type_do}.</p>
+<p style="font-size:15pt">Esta sección es actualmente un #{type_now} y si prosigues transformarás su estructura a un #{type_do}.</p>
+<p style="color:red;font-size:15pt;">Nótese que este cambio se puede hacer sólo una vez cada 10 minutos.</p>
+<div style="display:inline-block;">
+ <p style="margin-top:0;">¿Seguro que deseas convertir esta sección a #{type_do}?
+ <form method="get">
+ <input type="hidden" name="transform" value="do">
+ <input type="submit" value="Transformar a #{type_do}" class="full" />
+ </form>
+ </p>
+</div>
+<hr />
+<a href="#{cgi_url}anarkia" class="return">Volver al menú</a>
+<?py elif mode == 8: ?>
+<div class="replymode">Emojis</div>
+<table class="managertable">
+ <tr><th>Nombre</th><th>Img</th></tr>
+ <?py for emoji in emojis: ?>
+ <tr><td>${emoji['from']}</td><td>#{emoji['to']}</td></tr>
+ <?py #endfor ?>
+</table>
+<hr />
+<form method="post" action="" enctype="multipart/form-data">
+<table>
+<tr>
+ <td class="postblock">Nombre</td>
+ <td><input type="text" name="name" size="15" maxlength="15" class="full" /></td>
+ <td><input type="submit" name="new" value="Agregar emoji" class="full" /></td>
+</tr>
+<tr><td class="postblock">Archivo</td><td colspan="2"><input type="file" name="file" size="15" class="full" /></td></tr>
+</table>
+<small>(Sólo letras y/o números. Máximo: 500x500px, 500 KB.)</small>
+</form>
+<hr />
+<a href="#{cgi_url}anarkia" class="return">Volver al menú</a>
+<?py elif mode == 99: ?>
+<div>${msg}<br /><br /><a href="#{cgi_url}anarkia" class="return">Volver al menú</a></div>
+<?py #endif ?>
+</center>
+<hr />
+<div class="replymode" style="font-size:26pt;color:red;font-weight:bold">ⒶⒶⒶⒶⒶⒶⒶⒶⒶⒶⒶⒶⒶⒶ</div>
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/banned.html b/cgi/templates/banned.html
new file mode 100644
index 0000000..23b6636
--- /dev/null
+++ b/cgi/templates/banned.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Acceso prohibido@B.a.I.</title>
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+<style type="text/css">
+html { text-align:center; }
+body { background:#fe7777;color:#6a0000;display:inline-block;font-size:13pt;max-width:1000px;text-align:left; }
+h1 { color:red;margin:0; }
+h2 { margin:0.5em 0; }
+</style>
+</head>
+<body>
+<h1>Mensaje de Bienvenido a Internet BBS/IB</h1>
+<h2>Se te ha prohibido el acceso :-(</h2>
+<p>¡Tu IP (o rango) ha sido bloqueado!</p>
+<?py if reason != "": ?>
+ <p>La razón dejada fue: <b>#{reason}</b> y tu ban fue puesto el <b>#{added}</b> para las siguientes secciones: <b>#{boards_str}</b></p>
+<?py else: ?>
+ <p>No sabemos qué es lo que pudo causar tu ban, ¿qué hiciste?</p>
+ <p>Tu ban fue puesto el <b>#{added}</b> para las siguientes secciones: <b>#{boards_str}</b></p>
+<?py #endif ?>
+<?py if expire != "": ?>
+ <p>Pero no te preocupes, se te concederá nuevamente el acceso en la siguiente fecha y hora: <b>#{expire}</b>.</p>
+<?py #endif ?>
+<p>Si tu expulsión fue puesta incorrectamente no dudes en <a href="mailto:burocracia@bienvenidoainternet.org">contactarnos</a> dando tu IP, razón y explicación de los hechos.</p>
+<p>¡Gracias por usar Bienvenido a Internet BBS/IB!</p>
+<hr />
+<p><small><i>En muchos casos a pesar de que hayas sido expulsado del sitio se concede el acceso a las secciones <a href="/bai/">Meta</a> y Anarkía. Bajo cualquier consulta o reclamo <a href="mailto:burocracia@bienvenidoainternet.org">contáctanos</a>.</i></small></p>
+<hr />
+<div style="text-align:right;">Bienvenido a Internet 2010-2018</div>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/base_bottom.html b/cgi/templates/base_bottom.html
new file mode 100644
index 0000000..102f8f2
--- /dev/null
+++ b/cgi/templates/base_bottom.html
@@ -0,0 +1,3 @@
+<div class="footer">- <a href="//www.bienvenidoainternet.org" target="_top">weabot</a> <?py include('templates/revision.html') ?> -</div>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/base_top.html b/cgi/templates/base_top.html
new file mode 100644
index 0000000..5389617
--- /dev/null
+++ b/cgi/templates/base_top.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<?py if 'matome' in _context: ?>
+ <title>#{matome} - #{board_long}</title>
+<?py elif board: ?>
+ <title>#{board_long}</title>
+ <?py else: ?>
+ <title>#{title}</title>
+<?py #endif ?>
+ <meta http-equiv="Content-Type" content="application/xhtml+xml;charset=utf-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+<?py if replythread and 'threads' in _context and 'preview' in _context: ?>
+ <meta property="og:site_name" content="Bienvenido a Internet IB" />
+ <meta property="twitter:site" content="Bienvenido a Internet IB" />
+ <meta name="description" content="${preview}" />
+ <meta property="og:title" content="${threads[0]['posts'][0]['subject']} - ${board_name}" />
+ <meta property="og:description" content="${preview}" />
+ <?py if threads[0]['posts'][0]['thumb']: ?>
+ <meta property="twitter:image" content="https://bienvenidoainternet.org/#{board}/thumb/#{threads[0]['posts'][0]['thumb']}" />
+ <meta property="og:image" content="https://bienvenidoainternet.org/#{board}/thumb/#{threads[0]['posts'][0]['thumb']}" />
+ <?py #endif ?>
+ <meta property="twitter:title" content="${threads[0]['posts'][0]['subject']} - ${board_name}" />
+ <meta name="twitter:description" content="${preview}" />
+<?py #endif ?>
+ <meta name="robots" content="#{"noindex" if noindex else "index, follow"}" />
+ <link rel="shortcut icon" href="/favicon.ico" />
+ <link rel="stylesheet" href="#{static_url}css/ib.css" />
+<?py if not force_css: ?>
+ <link rel="stylesheet" id="css" href="#{static_url}css/#{styles[styles_default].lower()}.css" />
+<?py else: ?>
+ <link rel="stylesheet" type="text/css" href="#{force_css}" />
+<?py #endif ?>
+<?py if board == "2d": ?>
+ <link rel="stylesheet" href="#{static_url}css/txt/sjis.css" />
+<?py #endif ?>
+ <script type="text/javascript" src="#{static_url}js/weabot.js?v=5"></script>
+ <script type="text/javascript" src="#{static_url}js/aquiencitas.js"></script>
+ <script type="text/javascript" src="#{static_url}js/autorefresh.js?v=3"></script>
+</head>
+<body#{' class="res"' if replythread else ''}>
+ <div id="main_nav">[<a href="/" target="_top">Bienvenido a Internet</a>] [<?py include('templates/navbar.html') ?>]
+ <?py if not force_css: ?>
+ <span>[<span>Apariencia:</span>
+ <?py for title in styles: ?> <a href="#" class="ss">#{title}</a><?py #endfor ?>]</span>
+ <?py #endif ?></div>
+ <div class="logo">
+ <?py if board: ?>
+ #{board_long}
+ <?py else: ?>
+ <img src="/static/img/default.png" width="500" height="81" />
+ <?py #endif ?>
+ </div>
+ <hr width="90%" size="1" />
diff --git a/cgi/templates/board.0.html b/cgi/templates/board.0.html
new file mode 100644
index 0000000..1557cbc
--- /dev/null
+++ b/cgi/templates/board.0.html
@@ -0,0 +1,230 @@
+<?py include('templates/base_top.html') ?>
+<?py if replythread or oek_finish: ?>
+ &#91;<a href="#{boards_url}#{board}/">Volver al IB</a>&#93;
+<?py #endif ?>
+<?py if replythread: ?>
+ &#91;<a href="/cgi/catalog/${board}">Catálogo</a>&#93;
+ &#91;<a href="#bottom" name="top">Bajar</a>&#93;
+ <div class="replymode">Modo Respuesta</div>
+<?py #endif ?>
+<a name="postbox"></a>
+<div class="postarea">
+<?py if allow_oekaki and not oek_finish: ?>
+ <center><form class="oekform" action="#{cgi_url}oekaki/paint" method="post" enctype="multipart/form-data">
+ <input type="hidden" name="board" value="#{board}" />
+ <?py if replythread: ?>
+ <input type="hidden" name="parent" value="#{replythread}" />
+ <?py #endif ?>
+ Usar: <select name="oek_applet">
+ <option value="neo">PaintBBS NEO</option>
+ <option value="tegaki">Tegaki</option>
+ <option value="wpaint">wPaint</option>
+ <option value="shipainter|n|n">Shi-Painter</option>
+ <option value="shipainter|y|n">Shi-Painter Pro</option>
+ </select>
+ <span id="oek_size"><input type="text" name="oek_x" size="4" maxlength="4" value="300" /> x <input type="text" name="oek_y" size="4" maxlength="4" value="300" /></span>
+ <input type="submit" value="Dibujar" /><br /><a href="#{cgi_url}oekaki/finish/#{board}/#{replythread}">Recuperar dibujo guardado</a>
+ </form></center>
+<?py #endif ?>
+<?py if oek_finish: ?>
+<center style="margin-bottom:0.5em;"><table border=""><tr><td>
+ <?py if oek_finish == "no": ?>
+ <font size="+3">No hay dibujo</font>
+ <?py else: ?>
+ <img src="#{boards_url}oek_temp/#{oek_finish}.png?ts=#{ts}" />
+ <?py #endif ?>
+</td></tr></table></center>
+<?py #endif ?>
+<form name="postform" id="postform" action="#{cgi_url}post" method="post" enctype="multipart/form-data">
+ <input type="hidden" name="board" value="#{board}" />
+ <?py if replythread: ?>
+ <input type="hidden" name="parent" value="#{replythread}" />
+ <input type="hidden" name="default_subject" value="#{default_subject}" />
+ <?py #endif ?>
+ <div style="display:none;"><input type="text" name="name" size="25" /> <input type="text" name="email" size="25" /></div>
+ <table class="postform">
+ <tr>
+ <td class="postblock">mediumo</td>
+ <td>
+ <input type="text" name="fieldb" size="25" accesskey="e" />
+ <?py if disable_subject: ?>
+ <?py if replythread: ?>
+ <input type="submit" value="🤡" accesskey="z" />
+ <?py else: ?>
+ <input type="submit" value="🤡" accesskey="z" />
+ <?py #endif ?>
+ <?py #endif ?>
+ </td>
+ </tr>
+ <?py if not disable_subject: ?>
+ <tr>
+ <td class="postblock">Asunto</td>
+ <td>
+ <input type="text" name="subject" size="35" maxlength="100" accesskey="s" />
+ <?py if replythread: ?>
+ <input type="submit" value="Responder" accesskey="z" />
+ <?py else: ?>
+ <input type="submit" value="Crear hilo" accesskey="z" />
+ <?py #endif ?>
+ </td>
+ </tr>
+ <?py #endif ?>
+ <tr>
+ <td class="postblock">molekuloj</td>
+ <td><textarea name="message" cols="50" rows="6" accesskey="m"></textarea></td>
+ </tr>
+ <?py if (replythread and allow_image_replies) or (not replythread and allow_images): ?>
+ <tr>
+ <td class="postblock">amiko</td>
+ <td>
+ <input type="file" name="file" id="file" accesskey="f" />
+ <span id="filepreview" style="display:none;"></span>
+ <?py if allow_spoilers: ?>
+ <label>[<input type="checkbox" name="spoil" id="spoil" />Spoiler]</label>
+ <?py #endif ?>
+ <?py if allow_noimage and not replythread: ?>
+ <label>[<input type="checkbox" name="noimage" id="noimage" />Sin imagen]</label>
+ <?py #endif ?>
+ </td>
+ </tr>
+ <?py #endif ?>
+ <tr class="pass">
+ <td class="postblock">timo</td>
+ <td><input type="password" name="password" size="8" accesskey="p" /> (uzata por post forigo)</td>
+ </tr>
+ <tr>
+ <td colspan="2" class="rules">
+ <ul>
+ #{postarea_desc}
+ <li>ni ne vivas timi, ni vivas konekti.</li>
+ <?py if supported_filetypes: ?>
+ <li>elekti la veneno: <span id="filetypes">#{', '.join(supported_filetypes).upper()}</span>. ĝis: <span id="maxsize">#{maxsize}</span>KB. paŝo: #{maxdimensions}x#{maxdimensions}px</li>
+ <?py #endif ?>
+ </ul>
+ </td>
+ </tr>
+ </table>
+</form>
+</div>
+<hr />
+<?py if postarea_extra: ?>
+<center>#{postarea_extra}</center>
+<hr />
+<?py #endif ?>
+<form id="delform" action="#{cgi_url}delete" method="post">
+ <input type="hidden" name="board" value="#{board}" />
+ <?py if threads: ?>
+ <?py for thread in threads: ?>
+ <?py if not replythread: ?>
+ <span id="unhide#{thread['id']}#{board}" style="display:none;">Hilo <a href="#{boards_url}#{board}/res/#{thread['id']}.html">#{thread['id']}</a> oculto. <a class="tt" href="#">Ver hilo</a></span>
+ <?py #endif ?>
+ <div id="thread#{thread['id']}#{board}" class="thread" data-length="#{thread['length']}">
+ <?py for post in thread['posts']: ?>
+ <?py if int(post['parentid']) != 0: ?>
+ <table><tr><td class="ell">…</td>
+ <td class="reply" id="reply#{post['id']}">
+ <?py elif post['file']: ?>
+ <?py if post['image_width'] != '0': ?>
+ <div class="fs"><span>Nombre de archivo:</span><a href="#{images_url}#{board}/src/#{post['file']}" class="expimg" target="_blank" data-id="#{post['id']}" data-thumb="#{images_url}#{board}/thumb/#{post['thumb']}" data-w="#{post['image_width']}" data-h="#{post['image_height']}" data-tw="#{post['thumb_width']}" data-th="#{post['thumb_height']}">#{post['file']}</a>-(#{post['file_size']} B, #{post['image_width']}x#{post['image_height']})
+ <?py else: ?>
+ <div class="fs"><span>Nombre de archivo:</span><a href="#{images_url}#{board}/src/#{post['file']}" target="_blank">#{post['file']}</a>-(#{post['file_size']} B)
+ <?py #endif ?>
+ <?py if not replythread: ?>
+ [<a href="#" title="Ocultar hilo" class="tt">Ocultar hilo</a>]
+ <?py #endif ?>
+ </div>
+ <a target="_blank" href="#{images_url}#{board}/src/#{post['file']}" id="thumb#{post['id']}">
+ <?py if post['thumb'].startswith('mime'): ?>
+ <img class="thumb" alt="#{post['id']}" src="/static/#{post['thumb']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py elif post['file'][-3:] == 'gif': ?>
+ <img class="thumb" alt="#{post['id']}" src="#{images_url}#{board}/src/#{post['file']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py else: ?>
+ <img class="thumb" alt="#{post['id']}" src="#{images_url}#{board}/thumb/#{post['thumb']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py #endif ?>
+ </a>
+ <?py #endif ?>
+ <a name="#{post['id']}"></a>
+ <?py if post['IS_DELETED'] == '1': ?>
+ <span class="deleted">No.#{post['id']} eliminado por usuario.</span>
+ <?py elif post['IS_DELETED'] == '2': ?>
+ <span class="deleted">No.#{post['id']} eliminado por miembro del staff.</span>
+ <?py else: ?>
+ <div class="info"><label><input type="checkbox" name="delete" value="#{post['id']}" />
+ <?py if post['subject'] : ?>
+ <span class="subj">#{post['subject']}</span>
+ <?py #endif ?></label>
+ <?py if post['tripcode']: ?>
+ <span class="name"><b>#{post['name']}</b> #{post['tripcode']}</span>
+ <?py else: ?>
+ <span class="name"><b>#{post['name']}</b></span>
+ <?py #endif ?>
+ <span class="date" data-unix="#{random.randint(1,2147483647)}">#{post['timestamp_formatted']}</span>
+ <span class="reflink"><a>No.#{random.randint(1,999999)}</a></span>
+ <a class="rep" href="#{cgi_url}report/#{board}/#{post['id']}" rel="nofollow">rep</a>
+ <?py if int(post['parentid']) != 0: ?>
+ <?py if post['file']: ?>
+ <div class="fs">
+ <?py if post['image_width'] != '0': ?>
+ <a href="#{images_url}#{board}/src/#{post['file']}" class="expimg" target="_blank" data-id="#{post['id']}" data-thumb="#{images_url}#{board}/thumb/#{post['thumb']}" data-w="#{post['image_width']}" data-h="#{post['image_height']}" data-tw="#{post['thumb_width']}" data-th="#{post['thumb_height']}">#{post['file']}</a>-(#{post['file_size']} B, #{post['image_width']}x#{post['image_height']})
+ <?py else: ?>
+ <a href="#{images_url}#{board}/src/#{post['file']}" target="_blank">#{post['file']}</a>-(#{post['file_size']} B)
+ <?py #endif ?>
+ </div>
+ <a target="_blank" href="#{images_url}#{board}/src/#{post['file']}" id="thumb#{post['id']}">
+ <?py if post['thumb'].startswith('mime'): ?>
+ <img class="thumb" alt="#{post['id']}" src="/static/#{post['thumb']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py elif post['file'][-3:] == 'gif': ?>
+ <img class="thumb" alt="#{post['id']}" src="#{images_url}#{board}/src/#{post['file']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py else: ?>
+ <img class="thumb" alt="#{post['id']}" src="#{images_url}#{board}/thumb/#{post['thumb']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py #endif ?>
+ </a>
+ <?py #endif ?>
+ <?py #endif ?>
+ <?py if int(post['parentid']) == 0 and not replythread: ?>
+ [<a href="#{boards_url}#{board}/res/#{post['id']}.html" class="hsbn">Responder</a>]
+ <?py if post['file'] == '': ?>
+ [<a href="#" title="Ocultar Hilo" class="tt">Ocultar</a>]
+ <?py #endif ?>
+ <?py #endif ?>
+ </div>
+ <?py if post['thumb_width'] != '0' and post['parentid'] != '0': ?>
+ <blockquote style="margin-left:#{int(post['thumb_width'])+40}px;">
+ <?py else: ?>
+ <blockquote>
+ <?py #endif ?>
+ #{post['message']}
+ </blockquote>
+ <?py if not replythread and post['shortened']: ?>
+ <blockquote class="abbrev">(Post muy largo... Presiona <a href="#{boards_url}#{board}/res/#{post['id'] if post['parentid'] == "0" else post['parentid']}.html##{post['id']}">aqu&iacute;</a> para verlo completo.)</blockquote>
+ <?py #endif ?>
+ <?py #endif ?>
+ <?py if post['parentid'] == "0": ?>
+ <?py if not replythread: ?>
+ <?py if int(thread['omitted']) == 1: ?>
+ <div class="omitted">Un post omitido. Haz clic en Responder para ver.</div>
+ <?py elif int(thread['omitted']) > 1: ?>
+ <div class="omitted">#{thread['omitted']} posts omitidos. Haz clic en Responder para ver.</div>
+ <?py #endif ?>
+ <?py #endif ?>
+ <?py else: ?>
+ </td></tr></table>
+ <?py #endif ?>
+ <?py #endfor ?>
+ <div class="cut"></div></div>
+ <?py if replythread: ?>
+ <hr />
+ <div class="nav">&#91;<a href="#{boards_url}#{board}/">Volver al IB</a>&#93;
+ &#91;<a href="/cgi/catalog/${board}">Catálogo</a>&#93;
+ &#91;<a href="#top" name="bottom">Subir</a>&#93;</div>
+ <?py #endif ?>
+ <hr />
+ <?py #endfor ?>
+ <div class="userdel">Eliminar post <label>[<input type="checkbox" name="imageonly" id="imageonly" />Sólo imagen]</label><br />
+ Clave <input type="password" name="password" size="8" /> <input name="deletepost" value="Eliminar" type="submit" /></div>
+ <?py #endif ?>
+</form>
+<?py if pagenav: ?>
+ <div class="pg">#{pagenav}</div>
+<?py #endif ?>
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/board.html b/cgi/templates/board.html
new file mode 100644
index 0000000..e91e187
--- /dev/null
+++ b/cgi/templates/board.html
@@ -0,0 +1,264 @@
+<?py include('templates/base_top.html') ?>
+<?py if replythread or oek_finish: ?>
+ &#91;<a href="#{boards_url}#{board}/">Volver al IB</a>&#93;
+<?py #endif ?>
+<?py if replythread: ?>
+ &#91;<a href="/cgi/catalog/${board}">Catálogo</a>&#93;
+ &#91;<a href="#bottom" name="top">Bajar</a>&#93;
+ <div class="replymode">Modo Respuesta</div>
+<?py #endif ?>
+<a name="postbox"></a>
+<div class="postarea">
+<?py if allow_oekaki and not oek_finish: ?>
+ <center><form class="oekform" action="#{cgi_url}oekaki/paint" method="post" enctype="multipart/form-data">
+ <input type="hidden" name="board" value="#{board}" />
+ <?py if replythread: ?>
+ <input type="hidden" name="parent" value="#{replythread}" />
+ <?py #endif ?>
+ Usar: <select name="oek_applet">
+ <option value="neo">PaintBBS NEO</option>
+ <option value="tegaki">Tegaki</option>
+ <option value="wpaint">wPaint</option>
+ <option value="shipainter|n|n">Shi-Painter</option>
+ <option value="shipainter|y|n">Shi-Painter Pro</option>
+ </select>
+ <span id="oek_size"><input type="text" name="oek_x" size="4" maxlength="4" value="300" /> x <input type="text" name="oek_y" size="4" maxlength="4" value="300" /></span>
+ <input type="submit" value="Dibujar" /><br /><a href="#{cgi_url}oekaki/finish/#{board}/#{replythread}">Recuperar dibujo guardado</a>
+ </form></center>
+<?py #endif ?>
+<?py if oek_finish: ?>
+<center style="margin-bottom:0.5em;"><table border=""><tr><td>
+ <?py if oek_finish == "no": ?>
+ <font size="+3">No hay dibujo</font>
+ <?py else: ?>
+ <img src="#{boards_url}oek_temp/#{oek_finish}.png?ts=#{ts}" />
+ <?py #endif ?>
+</td></tr></table></center>
+<?py #endif ?>
+<form name="postform" id="postform" action="#{cgi_url}post" method="post" enctype="multipart/form-data">
+ <input type="hidden" name="board" value="#{board}" />
+ <?py if replythread: ?>
+ <input type="hidden" name="parent" value="#{replythread}" />
+ <input type="hidden" name="default_subject" value="#{default_subject}" />
+ <?py #endif ?>
+ <div style="display:none;">Trampa: <input type="text" name="name" size="25" /> <input type="text" name="email" size="25" /></div>
+ <table class="postform">
+ <?py if not disable_name: ?>
+ <tr>
+ <td class="postblock">Nombre</td>
+ <td><input type="text" name="fielda" size="25" accesskey="n" /></td>
+ </tr>
+ <?py #endif ?>
+ <tr>
+ <td class="postblock">E-mail</td>
+ <td>
+ <input type="text" name="fieldb" size="25" accesskey="e" />
+ <?py if disable_subject: ?>
+ <?py if replythread: ?>
+ <input type="submit" value="Responder" accesskey="z" />
+ <?py else: ?>
+ <input type="submit" value="Crear hilo" accesskey="z" />
+ <?py #endif ?>
+ <?py #endif ?>
+ </td>
+ </tr>
+ <?py if not disable_subject: ?>
+ <tr>
+ <td class="postblock">Asunto</td>
+ <td>
+ <input type="text" name="subject" size="35" maxlength="100" accesskey="s" />
+ <?py if replythread: ?>
+ <input type="submit" value="Responder" accesskey="z" />
+ <?py else: ?>
+ <input type="submit" value="Crear hilo" accesskey="z" />
+ <?py #endif ?>
+ </td>
+ </tr>
+ <?py #endif ?>
+ <tr>
+ <td class="postblock">Mensaje</td>
+ <td><textarea name="message" cols="50" rows="6" accesskey="m"></textarea></td>
+ </tr>
+ <?py if not oek_finish: ?>
+ <?py if (replythread and allow_image_replies) or (not replythread and allow_images): ?>
+ <tr>
+ <td class="postblock">Archivo</td>
+ <td>
+ <input type="file" name="file" id="file" accesskey="f" />
+ <span id="filepreview" style="display:none;"></span>
+ <?py if allow_spoilers: ?>
+ <label>[<input type="checkbox" name="spoil" id="spoil" />Spoiler]</label>
+ <?py #endif ?>
+ <?py if allow_noimage and not replythread: ?>
+ <label>[<input type="checkbox" name="noimage" id="noimage" />Sin imagen]</label>
+ <?py #endif ?>
+ </td>
+ </tr>
+ <?py #endif ?>
+ <?py elif oek_finish != 'no': ?>
+ <input type="hidden" name="oek_file" value="#{oek_finish}" />
+ <?py #endif ?>
+ <tr class="pass">
+ <td class="postblock">Clave</td>
+ <td><input type="password" name="password" size="8" accesskey="p" /> (para eliminar el post)</td>
+ </tr>
+ <tr>
+ <td colspan="2" class="rules">
+ <ul>
+ #{postarea_desc}
+ <?py if supported_filetypes: ?>
+ <li>Archivos permitidos: <span id="filetypes">#{', '.join(supported_filetypes).upper()}</span>. Hasta <span id="maxsize">#{maxsize}</span>KB. Miniaturas: #{maxdimensions}x#{maxdimensions}px</li>
+ <?py #endif ?>
+ <?py if not replythread: ?>
+ <li><a href="/cgi/catalog/${board}">Catálogo de hilos</a> (Orden: <a href="/cgi/catalog/${board}?sort=1">Nuevo</a>/<a href="/cgi/catalog/${board}?sort=2">Viejo</a>/<a href="/cgi/catalog/${board}?sort=3">Más</a>/<a href="/cgi/catalog/${board}?sort=4">Menos</a>)</li>
+ <?py #endif ?>
+ <?py if int(maxage) != 0: ?>
+ <li>Los hilos son automáticamente eliminados a los <b>#{maxage}</b> días de edad.</li>
+ <?py #endif ?>
+ <li>¿Eres nuevo? <a href="/guia.html">Leer antes de postear</a> · <a href="/faq.html">Preguntas frecuentes</a> · <a href="/bai/">Contacto</a></li>
+ </ul>
+ </td>
+ </tr>
+ </table>
+</form>
+</div>
+<hr />
+<?py if postarea_extra: ?>
+<center>#{postarea_extra}</center>
+<hr />
+<?py #endif ?>
+<form id="delform" action="#{cgi_url}delete" method="post">
+ <input type="hidden" name="board" value="#{board}" />
+ <?py if threads: ?>
+ <?py for thread in threads: ?>
+ <?py if not replythread: ?>
+ <span id="unhide#{thread['id']}#{board}" style="display:none;">Hilo <a href="#{boards_url}#{board}/res/#{thread['id']}.html">#{thread['id']}</a> oculto. <a class="tt" href="#">Ver hilo</a></span>
+ <?py #endif ?>
+ <div id="thread#{thread['id']}#{board}" class="thread" data-length="#{thread['length']}">
+ <?py for post in thread['posts']: ?>
+ <?py if int(post['parentid']) != 0: ?>
+ <table><tr><td class="ell">…</td>
+ <td class="reply" id="reply#{post['id']}">
+ <?py elif post['file']: ?>
+ <?py if post['image_width'] != '0': ?>
+ <div class="fs"><span>Nombre de archivo:</span><a href="#{images_url}#{board}/src/#{post['file']}" class="expimg" target="_blank" data-id="#{post['id']}" data-thumb="#{images_url}#{board}/thumb/#{post['thumb']}" data-w="#{post['image_width']}" data-h="#{post['image_height']}" data-tw="#{post['thumb_width']}" data-th="#{post['thumb_height']}">#{post['file']}</a>-(#{post['file_size']} B, #{post['image_width']}x#{post['image_height']})
+ <?py else: ?>
+ <div class="fs"><span>Nombre de archivo:</span><a href="#{images_url}#{board}/src/#{post['file']}" target="_blank">#{post['file']}</a>-(#{post['file_size']} B)
+ <?py #endif ?>
+ <?py if not replythread: ?>
+ [<a href="#" title="Ocultar hilo" class="tt">Ocultar hilo</a>]
+ <?py #endif ?>
+ </div>
+ <a target="_blank" href="#{images_url}#{board}/src/#{post['file']}" id="thumb#{post['id']}">
+ <?py if post['thumb'].startswith('mime'): ?>
+ <img class="thumb" alt="#{post['id']}" src="/static/#{post['thumb']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py elif post['file'][-3:] == 'gif': ?>
+ <img class="thumb" alt="#{post['id']}" src="#{images_url}#{board}/src/#{post['file']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py else: ?>
+ <img class="thumb" alt="#{post['id']}" src="#{images_url}#{board}/thumb/#{post['thumb']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py #endif ?>
+ </a>
+ <?py #endif ?>
+ <a name="#{post['id']}"></a>
+ <?py if post['IS_DELETED'] == '1': ?>
+ <span class="deleted">No.#{post['id']} eliminado por usuario.</span>
+ <?py elif post['IS_DELETED'] == '2': ?>
+ <span class="deleted">No.#{post['id']} eliminado por miembro del staff.</span>
+ <?py else: ?>
+ <div class="info"><label><input type="checkbox" name="delete" value="#{post['id']}" />
+ <?py if post['subject'] : ?>
+ <span class="subj">#{post['subject']}</span>
+ <?py #endif ?></label>
+ <?py if post['email']: ?>
+ <?py if post['tripcode']: ?>
+ <a href="mailto:#{post['email']}"><span class="name"><b>#{post['name']}</b> #{post['tripcode']}</span></a>
+ <?py else: ?>
+ <a href="mailto:#{post['email']}"><span class="name"><b>#{post['name']}</b></span></a>
+ <?py #endif ?>
+ <?py else: ?>
+ <?py if post['tripcode']: ?>
+ <span class="name"><b>#{post['name']}</b> #{post['tripcode']}</span>
+ <?py else: ?>
+ <span class="name"><b>#{post['name']}</b></span>
+ <?py #endif ?>
+ <?py #endif ?>
+ <span class="date" data-unix="#{post['timestamp']}">#{post['timestamp_formatted']}</span>
+ <?py if replythread: ?>
+ <span class="reflink"><a href="##{post['id']}">No.</a><a href="#" class="postid">#{post['id']}</a></span>
+ <?py else: ?>
+ <span class="reflink"><a href="#{boards_url}#{board}/res/#{post['parentid'] if post['parentid'] != "0" else post['id']}.html##{post['id']}">No.</a><a href="#{boards_url}#{board}/res/#{post['parentid'] if post['parentid'] != "0" else post['id']}.html#i#{post['id']}">#{post['id']}</a></span>
+ <?py #endif ?>
+ <a class="rep" href="#{cgi_url}report/#{board}/#{post['id']}" rel="nofollow">rep</a>
+ <?py if int(post['expires']): ?>
+ <small>Expira el ${post['expires_formatted']}</small>
+ <?py #endif ?>
+ <?py if int(post['parentid']) != 0: ?>
+ <?py if post['file']: ?>
+ <div class="fs">
+ <?py if post['image_width'] != '0': ?>
+ <a href="#{images_url}#{board}/src/#{post['file']}" class="expimg" target="_blank" data-id="#{post['id']}" data-thumb="#{images_url}#{board}/thumb/#{post['thumb']}" data-w="#{post['image_width']}" data-h="#{post['image_height']}" data-tw="#{post['thumb_width']}" data-th="#{post['thumb_height']}">#{post['file']}</a>-(#{post['file_size']} B, #{post['image_width']}x#{post['image_height']})
+ <?py else: ?>
+ <a href="#{images_url}#{board}/src/#{post['file']}" target="_blank">#{post['file']}</a>-(#{post['file_size']} B)
+ <?py #endif ?>
+ </div>
+ <a target="_blank" href="#{images_url}#{board}/src/#{post['file']}" id="thumb#{post['id']}">
+ <?py if post['thumb'].startswith('mime'): ?>
+ <img class="thumb" alt="#{post['id']}" src="/static/#{post['thumb']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py elif post['file'][-3:] == 'gif': ?>
+ <img class="thumb" alt="#{post['id']}" src="#{images_url}#{board}/src/#{post['file']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py else: ?>
+ <img class="thumb" alt="#{post['id']}" src="#{images_url}#{board}/thumb/#{post['thumb']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py #endif ?>
+ </a>
+ <?py #endif ?>
+ <?py #endif ?>
+ <?py if int(post['parentid']) == 0 and not replythread: ?>
+ [<a href="#{boards_url}#{board}/res/#{post['id']}.html" class="hsbn">Responder</a>]
+ <?py if post['file'] == '': ?>
+ [<a href="#" title="Ocultar Hilo" class="tt">Ocultar</a>]
+ <?py #endif ?>
+ <?py #endif ?>
+ </div>
+ <?py if post['thumb_width'] != '0' and post['parentid'] != '0': ?>
+ <blockquote style="margin-left:#{int(post['thumb_width'])+40}px;">
+ <?py else: ?>
+ <blockquote>
+ <?py #endif ?>
+ #{post['message']}
+ </blockquote>
+ <?py if not replythread and post['shortened']: ?>
+ <blockquote class="abbrev">(Post muy largo... Presiona <a href="#{boards_url}#{board}/res/#{post['id'] if post['parentid'] == "0" else post['parentid']}.html##{post['id']}">aqu&iacute;</a> para verlo completo.)</blockquote>
+ <?py #endif ?>
+ <?py if int(post['expires_alert']): ?>
+ <div style="color:red;font-weight:bold;">Este hilo es viejo y desaparecerá pronto.</div>
+ <?py #endif ?>
+ <?py #endif ?>
+ <?py if post['parentid'] == "0": ?>
+ <?py if not replythread: ?>
+ <?py if int(thread['omitted']) == 1: ?>
+ <div class="omitted">Un post omitido. Haz clic en Responder para ver.</div>
+ <?py elif int(thread['omitted']) > 1: ?>
+ <div class="omitted">#{thread['omitted']} posts omitidos. Haz clic en Responder para ver.</div>
+ <?py #endif ?>
+ <?py #endif ?>
+ <?py else: ?>
+ </td></tr></table>
+ <?py #endif ?>
+ <?py #endfor ?>
+ <div class="cut"></div></div>
+ <?py if replythread: ?>
+ <hr />
+ <div class="nav">&#91;<a href="#{boards_url}#{board}/">Volver al IB</a>&#93;
+ &#91;<a href="/cgi/catalog/${board}">Catálogo</a>&#93;
+ &#91;<a href="#top" name="bottom">Subir</a>&#93;</div>
+ <?py #endif ?>
+ <hr />
+ <?py #endfor ?>
+ <div class="userdel">Eliminar post <label>[<input type="checkbox" name="imageonly" id="imageonly" />Sólo imagen]</label><br />
+ Clave <input type="password" name="password" size="8" /> <input name="deletepost" value="Eliminar" type="submit" /></div>
+ <?py #endif ?>
+</form>
+<?py if pagenav: ?>
+ <div class="pg">#{pagenav}</div>
+<?py #endif ?>
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/board.jp.html b/cgi/templates/board.jp.html
new file mode 100644
index 0000000..8045ab1
--- /dev/null
+++ b/cgi/templates/board.jp.html
@@ -0,0 +1,271 @@
+<?py include('templates/base_top.html') ?>
+<?py if replythread or oek_finish: ?>
+ &#91;<a href="#{boards_url}#{board}/">掲示板に戻る</a>&#93;
+<?py #endif ?>
+<?py if replythread: ?>
+ &#91;<a href="/cgi/catalog/${board}">カタログ</a>&#93;
+ &#91;<a href="#bottom" name="top">ボトムへ行く</a>&#93;
+ <div class="replymode">レス送信モード</div>
+<?py #endif ?>
+<a name="postbox"></a>
+<div class="postarea">
+<?py if allow_oekaki and not oek_finish: ?>
+ <center><form class="oekform" action="#{cgi_url}oekaki/paint" method="post" enctype="multipart/form-data">
+ <input type="hidden" name="board" value="#{board}" />
+ <?py if replythread: ?>
+ <input type="hidden" name="parent" value="#{replythread}" />
+ <?py #endif ?>
+ <select name="oek_applet">
+ <option value="neo">PaintBBS NEO</option>
+ <option value="tegaki">Tegaki</option>
+ <option value="wpaint">wPaint</option>
+ <option value="shipainter|n|n">Shi-Painter</option>
+ <option value="shipainter|y|n">Shi-Painter Pro</option>
+ </select>
+ <span id="oek_size"><input type="text" name="oek_x" size="4" maxlength="4" value="300" /> x <input type="text" name="oek_y" size="4" maxlength="4" value="300" /></span>
+ <input type="submit" value="お絵かきする" /><br /><a href="#{cgi_url}oekaki/finish/#{board}/#{replythread}">アップロード途中の画像</a>
+ </form></center>
+<?py #endif ?>
+<?py if oek_finish: ?>
+<center style="margin-bottom:0.5em;"><table border=""><tr><td>
+ <?py if oek_finish == "no": ?>
+ <font size="+3">画像が見当たりません</font>
+ <?py else: ?>
+ <img src="#{boards_url}oek_temp/#{oek_finish}.png?ts=#{ts}" />
+ <?py #endif ?>
+</td></tr></table></center>
+<?py #endif ?>
+<form name="postform" id="postform" action="#{cgi_url}post" method="post" enctype="multipart/form-data">
+ <input type="hidden" name="board" value="#{board}" />
+ <?py if replythread: ?>
+ <input type="hidden" name="parent" value="#{replythread}" />
+ <input type="hidden" name="default_subject" value="#{default_subject}" />
+ <?py #endif ?>
+ <div style="display:none;">Trampa: <input type="text" name="name" size="25" /> <input type="text" name="email" size="25" /></div>
+ <table class="postform">
+ <?py if not disable_name: ?>
+ <tr>
+ <td class="postblock">おなまえ</td>
+ <td><input type="text" name="fielda" size="25" accesskey="n" /></td>
+ </tr>
+ <?py #endif ?>
+ <tr>
+ <td class="postblock">E-mail</td>
+ <td>
+ <input type="text" name="fieldb" size="25" accesskey="e" />
+ <?py if disable_subject: ?>
+ <?py if replythread: ?>
+ <input type="submit" value="返信" accesskey="z" />
+ <?py else: ?>
+ <input type="submit" value="スレッドを立てる" accesskey="z" />
+ <?py #endif ?>
+ <?py #endif ?>
+ </td>
+ </tr>
+ <?py if not disable_subject: ?>
+ <tr>
+ <td class="postblock">題  名</td>
+ <td>
+ <input type="text" name="subject" size="35" maxlength="100" accesskey="s" />
+ <?py if replythread: ?>
+ <input type="submit" value="返信" accesskey="z" />
+ <?py else: ?>
+ <input type="submit" value="スレッドを立てる" accesskey="z" />
+ <?py #endif ?>
+ </td>
+ </tr>
+ <?py #endif ?>
+ <tr>
+ <td class="postblock">コメント</td>
+ <td><textarea name="message" cols="50" rows="6" accesskey="m"></textarea></td>
+ </tr>
+ <?py if not oek_finish: ?>
+ <?py if (replythread and allow_image_replies) or (not replythread and allow_images): ?>
+ <tr>
+ <td class="postblock">添付File</td>
+ <td>
+ <input type="file" name="file" id="file" accesskey="f" />
+ <span id="filepreview" style="display:none;"></span>
+ <?py if allow_spoilers: ?>
+ <label>[<input type="checkbox" name="spoil" id="spoil" />ネタバレ]</label>
+ <?py #endif ?>
+ <?py if allow_noimage and not replythread: ?>
+ <label>[<input type="checkbox" name="noimage" id="noimage" />画像なし]</label>
+ <?py #endif ?>
+ </td>
+ </tr>
+ <?py #endif ?>
+ <?py elif oek_finish != 'no': ?>
+ <input type="hidden" name="oek_file" value="#{oek_finish}" />
+ <?py #endif ?>
+ <tr class="pass">
+ <td class="postblock">削除キー</td>
+ <td><input type="password" name="password" size="8" accesskey="p" /> (削除用)</td>
+ </tr>
+ <tr>
+ <td colspan="2" class="rules">
+ <ul>
+ #{postarea_desc}
+ <?py if supported_filetypes: ?>
+ <li>添付可能:<span id="filetypes">#{', '.join(supported_filetypes).upper()}</span>. <span id="maxsize">#{maxsize}</span>KBまで. #{maxdimensions}x#{maxdimensions}以上は縮小.</li>
+ <?py #endif ?>
+ <?py if not replythread: ?>
+ <li><a href="#{cgi_url}catalog/${board}">カタログ</a> (ソート:<a href="/cgi/catalog/${board}?sort=1">新順</a>/<a href="/cgi/catalog/${board}?sort=2">古順</a>/<a href="/cgi/catalog/${board}?sort=3">多順</a>/<a href="/cgi/catalog/${board}?sort=4">少順</a>)</li>
+ <?py #endif ?>
+ <?py if int(maxage) != 0: ?>
+ <li>スレは<b>#{maxage}</b>日間経つと自動的に消されられます.</li>
+ <?py #endif ?>
+ <li><a href="/guia.html">使い方</a> · <a href="/faq.html">よくある質問</a> · <a href="/bai/">管理人への連絡</a></li>
+ </ul>
+ </td>
+ </tr>
+ </table>
+</form>
+</div>
+<hr />
+<?py if postarea_extra: ?>
+<center>#{postarea_extra}</center>
+<hr />
+<?py #endif ?>
+<form id="delform" action="#{cgi_url}delete" method="post">
+ <input type="hidden" name="board" value="#{board}" />
+ <?py if threads: ?>
+ <?py for thread in threads: ?>
+ <?py if not replythread: ?>
+ <span id="unhide#{thread['id']}#{board}" style="display:none">スレ<a href="#{boards_url}#{board}/res/#{thread['id']}.html">#{thread['id']}</a>は隠しました. <a class="tt" href="#">スレを表示</a></span>
+ <?py #endif ?>
+ <div id="thread#{thread['id']}#{board}" class="thread" data-length="#{thread['length']}">
+ <?py for post in thread['posts']: ?>
+ <?py if int(post['parentid']) != 0: ?>
+ <table><tr><td class="ell">…</td>
+ <td class="reply" id="reply#{post['id']}">
+ <?py elif post['file']: ?>
+ <?py if post['image_width'] != '0': ?>
+ <div class="fs"><span>画像ファイル名:</span><a href="#{images_url}#{board}/src/#{post['file']}" class="expimg" target="_blank" data-id="#{post['id']}" data-thumb="#{images_url}#{board}/thumb/#{post['thumb']}" data-w="#{post['image_width']}" data-h="#{post['image_height']}" data-tw="#{post['thumb_width']}" data-th="#{post['thumb_height']}">#{post['file']}</a>-(#{post['file_size']} B, #{post['image_width']}x#{post['image_height']})
+ <?py else: ?>
+ <div class="fs"><span>画像ファイル名:</span><a href="#{images_url}#{board}/src/#{post['file']}" target="_blank">#{post['file']}</a>-(#{post['file_size']} B)
+ <?py #endif ?>
+ <?py if post['file'][-3:] == 'gif': ?>
+ <small>アニメGIF</small>
+ <?py elif not post['thumb'].startswith('mime'): ?>
+ <small>サムネ表示</small>
+ <?py #endif ?>
+ <?py if not replythread: ?>
+ [<a href="#" title="スレを隠す" class="tt">隠す</a>]
+ <?py #endif ?>
+ </div>
+ <a target="_blank" href="#{images_url}#{board}/src/#{post['file']}" id="thumb#{post['id']}">
+ <?py if post['thumb'].startswith('mime'): ?>
+ <img class="thumb" alt="#{post['id']}" src="/static/#{post['thumb']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py elif post['file'][-3:] == 'gif': ?>
+ <img class="thumb" alt="#{post['id']}" src="#{images_url}#{board}/src/#{post['file']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py else: ?>
+ <img class="thumb" alt="#{post['id']}" src="#{images_url}#{board}/thumb/#{post['thumb']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py #endif ?>
+ </a>
+ <?py #endif ?>
+ <a name="#{post['id']}"></a>
+ <?py if post['IS_DELETED'] == '1': ?>
+ <span class="deleted">No.#{post['id']}はユーザーに削除されました.</span>
+ <?py elif post['IS_DELETED'] == '2': ?>
+ <span class="deleted">No.#{post['id']}は管理人に削除されました.</span>
+ <?py else: ?>
+ <div class="info"><label><input type="checkbox" name="delete" value="#{post['id']}" /><span class="subj">#{post['subject'] if post['subject'] else default_subject}</span></label>
+ <?py if post['email']: ?>
+ <?py if post['tripcode']: ?>
+ Name <a href="mailto:#{post['email']}"><span class="name"><b>#{post['name']}</b> #{post['tripcode']}</span></a>
+ <?py else: ?>
+ Name <a href="mailto:#{post['email']}"><span class="name"><b>#{post['name']}</b></span></a>
+ <?py #endif ?>
+ <?py else: ?>
+ <?py if post['tripcode']: ?>
+ Name <span class="name"><b>#{post['name']}</b> #{post['tripcode']}</span>
+ <?py else: ?>
+ Name <span class="name"><b>#{post['name']}</b></span>
+ <?py #endif ?>
+ <?py #endif ?>
+ <span class="date" data-unix="#{post['timestamp']}">#{post['timestamp_formatted']}</span>
+ <?py if replythread: ?>
+ <span class="reflink"><a href="##{post['id']}">No.</a><a href="#" class="postid">#{post['id']}</a></span>
+ <?py else: ?>
+ <span class="reflink"><a href="#{boards_url}#{board}/res/#{post['parentid'] if post['parentid'] != "0" else post['id']}.html##{post['id']}">No.</a><a href="#{boards_url}#{board}/res/#{post['parentid'] if post['parentid'] != "0" else post['id']}.html#i#{post['id']}">#{post['id']}</a></span>
+ <?py #endif ?>
+ <a class="rep" href="#{cgi_url}report/#{board}/#{post['id']}" rel="nofollow">rep</a>
+ <?py if int(post['expires']): ?>
+ <small>${post['expires_formatted']}頃消えます</small>
+ <?py #endif ?>
+ <?py if int(post['parentid']) != 0: ?>
+ <?py if post['file']: ?>
+ <div class="fs">
+ <?py if post['image_width'] != '0': ?>
+ <a href="#{images_url}#{board}/src/#{post['file']}" class="expimg" target="_blank" data-id="#{post['id']}" data-thumb="#{images_url}#{board}/thumb/#{post['thumb']}" data-w="#{post['image_width']}" data-h="#{post['image_height']}" data-tw="#{post['thumb_width']}" data-th="#{post['thumb_height']}">#{post['file']}</a>-(#{post['file_size']} B, #{post['image_width']}x#{post['image_height']})
+ <?py else: ?>
+ <a href="#{images_url}#{board}/src/#{post['file']}" target="_blank">#{post['file']}</a>-(#{post['file_size']} B)
+ <?py #endif ?>
+ <?py if post['file'][-3:] == 'gif': ?>
+ <small>アニメGIF</small>
+ <?py elif not post['thumb'].startswith('mime'): ?>
+ <small>サムネ表示</small>
+ <?py #endif ?>
+ </div>
+ <a target="_blank" href="#{images_url}#{board}/src/#{post['file']}" id="thumb#{post['id']}">
+ <?py if post['thumb'].startswith('mime'): ?>
+ <img class="thumb" alt="#{post['id']}" src="/static/#{post['thumb']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py elif post['file'][-3:] == 'gif': ?>
+ <img class="thumb" alt="#{post['id']}" src="#{images_url}#{board}/src/#{post['file']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py else: ?>
+ <img class="thumb" alt="#{post['id']}" src="#{images_url}#{board}/thumb/#{post['thumb']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" />
+ <?py #endif ?>
+ </a>
+ <?py #endif ?>
+ <?py #endif ?>
+ <?py if int(post['parentid']) == 0 and not replythread: ?>
+ [<a href="#{boards_url}#{board}/res/#{post['id']}.html" class="hsbn">返信</a>]
+ <?py if post['file'] == '': ?>
+ [<a href="#" title="スレを隠す" class="tt">隠す</a>]
+ <?py #endif ?>
+ <?py #endif ?>
+ </div>
+ <?py if post['thumb_width'] != '0' and post['parentid'] != '0': ?>
+ <blockquote style="margin-left:#{int(post['thumb_width'])+40}px;">
+ <?py else: ?>
+ <blockquote>
+ <?py #endif ?>
+ #{post['message']}
+ </blockquote>
+ <?py if not replythread and post['shortened']: ?>
+ <blockquote class="abbrev">(投稿は長すぎ... 全部読むには<a href="#{boards_url}#{board}/res/#{post['id'] if post['parentid'] == "0" else post['parentid']}.html##{post['id']}">こっちら</a>へ)</blockquote>
+ <?py #endif ?>
+ <?py if int(post['expires_alert']): ?>
+ <div style="color:red;font-weight:bold">このスレは古いので、もうすぐ消えます。</div>
+ <?py #endif ?>
+ <?py #endif ?>
+ <?py if int(post['parentid']) == 0: ?>
+ <?py if not replythread: ?>
+ <?py if int(thread['omitted']) > 0: ?>
+ <span class="omitted">レス${thread['omitted']}件省略。全て読むには返信ボタンを押してください。</span>
+ <?py #endif ?>
+ <?py #endif ?>
+ <?py else: ?>
+ </td></tr></table>
+ <?py #endif ?>
+ <?py #endfor ?>
+ <div class="cut"></div></div>
+ <?py if replythread: ?>
+ <hr />
+ <div class="nav">&#91;<a href="#{boards_url}#{board}/">掲示板に戻る</a>&#93;
+ &#91;<a href="/cgi/catalog/${board}">カタログ</a>&#93;
+ &#91;<a href="#top" name="bottom">トップへ戻る</a>&#93;</div>
+ <?py #endif ?>
+ <hr />
+ <?py #endfor ?>
+ <div class="userdel">
+ 【記事削除】<label>[<input type="checkbox" name="imageonly" id="imageonly" />画像だけ消す]</label><br />
+ 削除キー<input type="password" name="password" size="8" /> <input name="deletepost" value="削除" type="submit" />
+ </div>
+ <?py #endif ?>
+</form>
+<?py if pagenav: ?>
+ <div class="pg">#{pagenav}</div>
+<?py #endif ?>
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/catalog.html b/cgi/templates/catalog.html
new file mode 100644
index 0000000..4faa2d2
--- /dev/null
+++ b/cgi/templates/catalog.html
@@ -0,0 +1,30 @@
+<?py include('templates/base_top.html') ?>
+<div id="ctrl">
+ &#91;<a href="#{boards_url}#{board}/">Volver al IB</a>&#93;
+ &#91;Orden:
+ <a class="cat_sort" data-sort="0" href="?sort=0">#{"<b>Normal</b>" if i_sort == "" else "Normal"}</a>
+ <a class="cat_sort" data-sort="1" href="?sort=1">#{"<b>Nuevo</b>" if i_sort == "1" else "Nuevo"}</a>
+ <a class="cat_sort" data-sort="2" href="?sort=2">#{"<b>Viejo</b>" if i_sort == "2" else "Viejo"}</a>
+ <a class="cat_sort" data-sort="3" href="?sort=3">#{"<b>Más</b>" if i_sort == "3" else "Más"}</a>
+ <a class="cat_sort" data-sort="4" href="?sort=4">#{"<b>Menos</b>" if i_sort == "4" else "Menos"}</a>&#93;
+ &#91;Tamaño: <a id="cat_size" href="#">Pequeño</a>&#93;
+ &#91;Texto: <a id="cat_hide" href="#">Ocultar</a>&#93;
+ &#91;Buscar: <input id="cat_search" type="text"><input type="hidden" name="board" value="#{board}" />
+</div>
+<div class="extramode">Modo Catálogo</div>
+<div id="catalog" style="margin:1em auto;">
+ <?py i = 1 ?>
+ <?py for thread in threads: ?><div id="cat#{thread['id']}#{board}" class="thread" data-num="${i}" data-id="#{thread['id']}" data-res="${thread['length']}">
+ <?py if thread['thumb'] != '': ?>
+ <a href="#{boards_url}#{board}/res/#{thread['id']}.html" rel="nofollow"><img src="#{images_url}#{board}/cat/#{thread['thumb']}" alt="#{thread['id']}" /></a><br />
+ <?py #endif ?>
+ <div class="replies">Respuestas: ${thread['length']}</div>
+ <?py if thread['thumb'] != '': ?>
+ <p><span class="subj">${thread['subject']}</span><br />${thread['message']}</p>
+ <?py else: ?>
+ <p><a href="#{boards_url}#{board}/res/#{thread['id']}.html" rel="nofollow" class="subj">${thread['subject']}</a><br />${thread['message']}</p>
+ <?py #endif ?>
+ <?py i += 1 ?>
+ </div><?py #endfor ?>
+</div>
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/error.html b/cgi/templates/error.html
new file mode 100644
index 0000000..47ef529
--- /dev/null
+++ b/cgi/templates/error.html
@@ -0,0 +1,7 @@
+<?py include('templates/base_top.html') ?>
+<br /><br /><hr size="1">
+<br /><br /><div style="text-align:center;color:red;font-size:x-large;font-weight:bold;">#{error}
+<br /><br /><a href="#{boards_url}#{board}/">Volver</a></div>
+<br /><br /><hr size="1">
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/exception.html b/cgi/templates/exception.html
new file mode 100644
index 0000000..e8453eb
--- /dev/null
+++ b/cgi/templates/exception.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Error@Bienvenido a Internet</title>
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<style type="text/css">.error{color:red;font-weight:bold;font-size:16pt} .sub{font-weight:bold}</style>
+</head>
+<body>
+<?py if exception: ?>
+<p class="error">ERROR : Ha ocurrido un error inesperado.</p>
+<p class="sub">Esto no es normal y te pedimos que reportes el problema en
+<a href="/bai/">Discusión de B.a.I.</a> o a través de
+<a href="mailto:burocracia@bienvenidoainternet.org">nuestro e-mail</a>,
+presentando los siguientes datos y ojalá indicando qué hacer para reproducirlo:</p>
+<p>Versión: weabot
+<?py include('templates/revision.html') ?><br />
+Tipo: ${exception}<br />
+Detalle: ${error}<br />
+Traceback:<br />
+<blockquote>
+ <?py for line in detail: ?>
+ ${line[0]} ${line[1]} ${line[2]} ${line[3]}<br />
+ <?py #endfor ?>
+</blockquote></p>
+<p class="sub">Te recordamos que el software está en desarrollo y estamos siempre haciendo lo posible para arreglar los problemas lo antes posible.<br />Te pedimos las disculpas por cualquier inconveniente.</p>
+<hr />
+<p>weabot dijo "Perdón."<br /><a href="/bai.html">Bienvenido a Internet BBS/IB</a></p>
+<?py else: ?>
+<p class="error">ERROR : #{error}</p>
+<p class="sub">Por favor presiona Atrás y soluciona el problema.</p>
+<hr />
+<p>La página principal está <a href="/bai.html">aquí</a>.<br />Si esto es inusual intenta <a href="/bai/">contactarnos</a>.</p><?py #endif ?>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/home.rss b/cgi/templates/home.rss
new file mode 100644
index 0000000..dc69377
--- /dev/null
+++ b/cgi/templates/home.rss
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<rss version="2.0">
+ <channel>
+ <title>Bienvenido a Internet BBS/IB</title>
+ <link>https://bienvenidoainternet.org/</link>
+ <description>El BBS/IB más activo de la esfera hispana.</description>
+ <language>es</language>
+ <webMaster>burocracia@bienvenidoainternet.org (Staff ★)</webMaster>
+ <image>
+ <url>https://bienvenidoainternet.org/rss_logo.png</url>
+ <title>Bienvenido a Internet BBS/IB</title>
+ <link>https://bienvenidoainternet.org/</link>
+ <width>144</width>
+ <height>144</height>
+ </image>
+<?py for post in posts: ?>
+ <item>
+ <title>${post['board_name']}: #{post['content']}</title>
+ <pubDate>${post['timestamp_formatted']}</pubDate>
+ <link>https://bienvenidoainternet.org#{post['url']}</link>
+ </item>
+<?py #endfor ?>
+ </channel>
+</rss> \ No newline at end of file
diff --git a/cgi/templates/htaccess b/cgi/templates/htaccess
new file mode 100644
index 0000000..469fec0
--- /dev/null
+++ b/cgi/templates/htaccess
@@ -0,0 +1,24 @@
+DirectoryIndex index.html
+<?py if dir == 'clusterfuck': ?>
+
+AuthName "BAI"
+AuthType Basic
+AuthUserFile "/home/z411/.htpasswds/public_html/wiki/passwd"
+<Limit GET>
+require valid-user
+</Limit>
+
+<?py #endif ?>
+<?py if dir == 'anarkia': ?>
+ExpiresByType text/css "access plus 0 seconds"
+<?py #endif ?>
+
+ErrorDocument 403 https://bienvenidoainternet.org/cgi/banned/#{dir}
+<?py if ips: ?>
+
+order allow,deny
+ <?py for ip in ips: ?>
+deny from #{ip}
+ <?py #endfor ?>
+allow from all
+<?py #endif ?>
diff --git a/cgi/templates/kako.html b/cgi/templates/kako.html
new file mode 100644
index 0000000..49d95df
--- /dev/null
+++ b/cgi/templates/kako.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Archivo de #{board_name}@Bienvenido a Internet BBS</title>
+ <meta http-equiv="Content-Type" content="application/xhtml+xml;charset=utf-8" />
+ <meta name="robots" content="index, follow" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <link rel="shortcut icon" href="#{static_url}img/favicon.ico" />
+ <style type="text/css">
+ body {margin:8px}
+ h1 {margin:0 0 20px}
+ pre {margin:0}
+ .fake {color:#0000EE;text-decoration:underline;cursor:pointer}
+ .fake:active {color:#FF0000}
+ img {width:20px;height:22px;margin-right:4px}
+ td {text-align:left;vertical-align:bottom;padding-right:14px}
+ .r {text-align:right}
+ a:link, a:hover {color:#0000EE}
+ a:active {color:#FF0000}
+ a:visited {color:#551A8B}
+ </style>
+</head>
+<body>
+<h1>Índice de /#{board}/kako/</h1>
+<pre>
+ <table style="border-collapse:collapse;">
+ <tr>
+ <th><img src="/blank.png" /></th>
+ <td><span class="fake">Nombre</span></td>
+ <td><span class="fake">Tamaño</span></td>
+ <td><span class="fake">Descripción</span></td>
+ </tr>
+ <tr>
+ <td colspan="4" style="padding:0"><hr /></td>
+ </tr>
+ <tr>
+ <th><img src="/back.png" /></th>
+ <td><a href="/#{board}/">..</a></td>
+ <td class="r">-</td>
+ <td></td>
+ </tr>
+ <?py for thread in threads: ?>
+ <tr>
+ <th><img src="/text.png" /></th>
+ <td><a href="#{boards_url}#{board}/read/#{thread['timestamp']}/">${thread['timestamp']}.json</a></td>
+ <?py if int(thread['length']) > 1000: ?>
+ <td class="r">1KR</td>
+ <?py else: ?>
+ <td class="r">${thread['length']}R</td>
+ <?py #endif ?>
+ <td>${thread['subject']}</td>
+ </tr>
+ <?py #endfor ?>
+ </table>
+ <hr />
+</pre>
+<address>weabot/0.8.4 (CentOS) Servidor ubicado en bienvenidoainternet.org Puerto 443</address>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/manage/addboard.html b/cgi/templates/manage/addboard.html
new file mode 100644
index 0000000..71b3c31
--- /dev/null
+++ b/cgi/templates/manage/addboard.html
@@ -0,0 +1,21 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<center>
+<div class="replymode">Nuevo board</div>
+<form action="#{cgi_url}manage/addboard" method="post">
+ <table>
+ <tr>
+ <td class="postblock">Directorio</td>
+ <td><input type="text" name="dir" maxlength="16" style="width:100%;" /></td>
+ </tr>
+ <tr>
+ <td class="postblock">Nombre</td>
+ <td><input type="text" name="name" maxlength="64" style="width:100%;" /></td>
+ </tr>
+ <tr>
+ <td colspan="2"><input type="submit" name="submit" style="width:100%;" value="Agregar board" /></td>
+ </table>
+</form>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/manage/bans.html b/cgi/templates/manage/bans.html
new file mode 100644
index 0000000..81e0f71
--- /dev/null
+++ b/cgi/templates/manage/bans.html
@@ -0,0 +1,92 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<?py from tenjin.helpers.html import * ?>
+<center>
+<div class="replymode">Bans</div>
+<?py if mode == 0: ?>
+<form action="#{cgi_url}manage/ban/" name="banform" method="post">
+<table>
+<tr>
+ <td class="postblock">Dirección IP</td>
+ <td><input type="text" name="ip" size="20" /></td>
+</tr>
+<tr><td colspan="2"><input type="submit" value="Ir a formulario de ban" style="width:100%;" /></td></tr>
+</table>
+</form>
+<hr />
+<table class="managertable">
+<tr>
+ <th>Dirección IP</th>
+ <th>Máscara de red</th>
+ <th>Boards</th>
+ <th>Agregado</th>
+ <th>Expira</th>
+ <th>Ciego</th>
+ <th>Puesto por</th>
+ <th>Razón</th>
+ <th>Nota</th>
+ <th>Acción</th>
+</tr>
+<?py for ban in bans: ?>
+<tr>
+ <td>${ban['ip']}</td>
+ <td>${ban['netmask']}</td>
+ <td>${ban['boards']}</td>
+ <td>${ban['added']}</td>
+ <td>${ban['until']}</td>
+ <td>${ban['blind']}</td>
+ <td>${ban['staff']}</td>
+ <td>${ban['reason']}</td>
+ <td>${ban['note']}</td>
+ <td>
+ [<a href="#{cgi_url}manage/ipshow?ip=#{ban['ip']}">Ver posts</a>]
+ [<a href="#{cgi_url}manage/ban?ip=#{ban['ip']}&amp;edit=#{ban['id']}">Editar</a>]
+ [<a href="#{cgi_url}manage/bans/delete/#{ban['id']}">Eliminar</a>]
+ </td>
+</tr>
+<?py #endfor ?>
+</table>
+<?py elif mode == 1: ?>
+<form action="#{cgi_url}manage/ban" name="banform" method="post">
+<table>
+ <tr><td class="postblock">IP</td><td><input type="text" name="ip" value="${ip}" size="20" style="width:100%;" /></td></tr>
+ <tr><td class="postblock">Máscara de red</td><td><input type="text" name="netmask" value="${startvalues['netmask']}" style="width:100%;" /></td></tr>
+ <tr>
+ <td class="postblock">Board(s)</td>
+ <td>
+ <input type="checkbox" name="board_all" id="b_all" value="1"#{checked(startvalues['where'] == '')} /><label for="b_all" style="font-weight:bold">Todos los boards</label><hr />
+ <?py for board in boards: ?>
+ <input type="checkbox" name="board_#{board['dir']}" id="b#{board['dir']}" value="1"#{checked(board['dir'] in startvalues['where'])} /><label for="b#{board['dir']}">${board['name']}</label><br />
+ <?py #endfor ?>
+ <?py if edit_id > 0: ?>
+ <input type="hidden" name="edit" value="${edit_id}" />
+ <?py #endif ?>
+ </td>
+ </tr>
+ <tr><td class="postblock">Mensaje</td><td><textarea name="reason" style="width:100%;">${startvalues['reason']}</textarea></td></tr>
+ <tr><td class="postblock">Nota para staff</td><td><input type="text" name="note" value="${startvalues['note']}" style="width:100%;" /></td></tr>
+ <tr><td class="postblock">Ciego</td><td><input type="checkbox" name="blind" id="blind" value="1"#{checked(startvalues['blind'] == '1')} /><label for="blind"></label></td></tr>
+ <tr><td class="postblock">Expira en <span style="font-weight:normal;">(segundos)</span></td><td><input type="text" id="seconds" name="seconds" value="#{startvalues['seconds']}" style="width:100%;" />
+ <br />
+ <div id="timelist">
+ <a href="#" data-secs="0">Nunca</a>
+ <a href="#" data-secs="3600">1h</a>
+ <a href="#" data-secs="21600">6h</a>
+ <a href="#" data-secs="43200">12h</a>
+ <a href="#" data-secs="86400">1d</a>
+ <a href="#" data-secs="259200">3d</a>
+ <a href="#" data-secs="604800">1w</a>
+ <a href="#" data-secs="2592000">30d</a>
+ <a href="#" data-secs="31536000">1y</a>
+ </div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2"><input type="submit" value="Colocar ban" style="width:100%;" /></td>
+ </tr>
+</table>
+</form>
+<?py #endif ?>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/manage/boardoptions.html b/cgi/templates/manage/boardoptions.html
new file mode 100644
index 0000000..436b036
--- /dev/null
+++ b/cgi/templates/manage/boardoptions.html
@@ -0,0 +1,195 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<?py from tenjin.helpers.html import * ?>
+<center>
+<div class="replymode">Opciones de Board</div>
+<?py if mode == 0: ?>
+<table class="managertable">
+ <tr><th colspan="2">Sección</th><th>Accion</th></tr>
+ <?py for board in boards: ?>
+ <tr><td>/#{board['dir']}/</td><td>#{board['name']}</td><td>[<a href="#{cgi_url}manage/board/#{board['dir']}">Configurar</a>]</td></tr>
+ <?py #endfor ?>
+ </table>
+<?py elif mode == 1: ?>
+<form action="#{cgi_url}manage/board/${boardopts['dir']}" method="post">
+<table>
+<tr>
+ <td class="postblock">ID</td>
+ <td><input type="text" name="name" value="${boardopts['id']}" maxlength="16" style="width:100%;" disabled="disabled" /></td>
+</tr>
+<tr>
+ <td class="postblock">Directorio</td>
+ <td><input type="text" name="name" value="${boardopts['dir']}" maxlength="32" style="width:100%;" disabled="disabled" /></td>
+</tr>
+<tr>
+ <td class="postblock">Nombre</td>
+ <td><input type="text" name="name" value="${boardopts['name']}" maxlength="64" style="width:100%;" /></td>
+</tr>
+<tr>
+<td class="postblock">Nombre largo</td>
+<td><input type="text" name="longname" size="50" value="${boardopts['longname']}" maxlength="128" style="width:100%;" /></td>
+</tr>
+<tr>
+<td class="postblock">Sub-nombre</td>
+<td><input type="text" name="subname" value="${boardopts['subname']}" maxlength="3" style="width:100%;" /></td>
+</tr>
+<tr>
+<td class="postblock">Tipo</td>
+<td>
+ <select style="width:100%;" name="type">
+ <option value="0">Imageboard</option>
+ <option value="1"#{selected(boardopts['board_type'] == '1')}>Textboard</option>
+ </select>
+</td>
+</tr>
+<tr>
+<td class="postblock">Descripción / Reglas</td>
+<td>
+ <textarea id="brd_desc" name="postarea_desc" rows="10" cols="50" style="width:100%;">${boardopts['postarea_desc']}</textarea>
+ <div id="prev_desc" style="border:1px dotted gray;display:none;padding:4px;width:100%;" contenteditable="true"></div>
+</td>
+</tr>
+<tr>
+<td class="postblock">Caja extra</td>
+<td><textarea name="postarea_extra" rows="5" cols="50" style="width:100%;">${boardopts['postarea_extra']}</textarea></td>
+</tr>
+<tr>
+<td class="postblock">Forzar CSS <span style="font-weight:normal;">("" = default)</span></td>
+<td><input type="text" name="force_css" size="50" value="#{boardopts['force_css']}" maxlength="255" style="width:100%;" /></td>
+</tr>
+<tr>
+<td class="postblock">Nombre por defecto</td>
+<td><input type="text" name="anonymous" size="50" maxlength="128" value="${boardopts['anonymous']}" style="width:100%;" /></td>
+</tr>
+<tr>
+<td class="postblock">Título por defecto</td>
+<td><input type="text" name="subject" size="50" maxlength="64" value="${boardopts['subject']}" style="width:100%;" /></td>
+</tr>
+<tr>
+<td class="postblock">Mensaje por defecto</td>
+<td><input type="text" name="message" size="50" maxlength="128" value="${boardopts['message']}" style="width:100%;" /></td>
+</tr>
+<tr>
+<td class="postblock">ID</td>
+<td>
+ <select name="useid" style="width:100%;">
+ <option value="0">Desactivado</option>
+ <option value="1"#{selected(boardopts['useid'] == '1')}>Activado</option>
+ <option value="2"#{selected(boardopts['useid'] == '2')}>Activado siempre</option>
+ <option value="3"#{selected(boardopts['useid'] == '3')}>Activado siempre, detallado</option>
+ </select>
+</td>
+</tr>
+<tr>
+<td class="postblock">Slip</td>
+<td>
+ <select name="slip" style="width:100%;">
+ <option value="0">Desactivado</option>
+ <option value="1"#{selected(boardopts['slip'] == '1')}>Activado</option>
+ <option value="2"#{selected(boardopts['slip'] == '2')}>Sólo dominio</option>
+ <option value="3"#{selected(boardopts['slip'] == '3')}>Todo</option>
+ </select>
+</td>
+</tr>
+<tr>
+<td class="postblock">Código de país</td>
+<td>
+ <select name="countrycode" style="width:100%;">
+ <option value="0">Desactivado</option>
+ <option value="1"#{selected(boardopts['countrycode'] == '1')}>Activado</option>
+ </select>
+</td>
+</tr>
+<tr>
+<td class="postblock">Desactivar nombre</td>
+<td><input type="checkbox" name="disable_name" id="noname" value="1"#{checked(boardopts['disable_name'] == '1')} /><label for="noname"></label></td>
+</tr>
+<tr>
+<td class="postblock">Desactivar asunto</td>
+<td><input type="checkbox" name="disable_subject" id="nosub" value="1"#{checked(boardopts['disable_subject'] == '1')} /><label for="nosub"></label></td>
+</tr>
+<tr>
+<td class="postblock">Papelera de reciclaje</td>
+<td><input type="checkbox" name="recyclebin" id="bin" value="1"#{checked(boardopts['recyclebin'] == '1')} /><label for="bin"></label></td>
+</tr>
+<tr>
+<td class="postblock">Cerrado</td>
+<td><input type="checkbox" name="locked" id="locked" value="1"#{checked(boardopts['locked'] == '1')} /><label for="locked"></label></td>
+</tr>
+<tr>
+<td class="postblock">Secreto</td>
+<td><input type="checkbox" name="secret" id="secret" value="1"#{checked(boardopts['secret'] == '1')} /><label for="secret"></label></td>
+</tr>
+<tr>
+<td class="postblock">Permitir spoilers</td>
+<td><input type="checkbox" name="allow_spoilers" id="spoil" value="1"#{checked(boardopts['allow_spoilers'] == '1')} /><label for="spoil"></label></td>
+</tr>
+<tr>
+<td class="postblock">Permitir oekaki</td>
+<td><input type="checkbox" name="allow_oekaki" id="oek" value="1"#{checked(boardopts['allow_oekaki'] == '1')} /><label for="oek"></label></td>
+</tr>
+<tr>
+<td class="postblock">Permitir crear hilos sin imagen</td>
+<td><input type="checkbox" name="allow_noimage" id="noimgallow" value="1"#{checked(boardopts['allow_noimage'] == '1')} /><label for="noimgallow"></label></td>
+</tr>
+<tr>
+<td class="postblock">Permitir subida</td>
+<td><input type="checkbox" name="allow_images" id="img" value="1"#{checked(boardopts['allow_images'] == '1')} /><label for="img">Al crear un hilo</label><br /><input type="checkbox" name="allow_image_replies" id="imgres" value="1"#{checked(boardopts['allow_image_replies'] == '1')} /><label for="imgres">Al responder</label></td>
+</tr>
+<tr>
+<td class="postblock">Tipos de archivo</td>
+<td>
+ <?py for filetype in filetypes: ?>
+ <input type="checkbox" name="filetype#{filetype['ext']}" id="#{filetype['ext']}" value="1"#{checked(filetype['ext'] in supported_filetypes)} /><label for="#{filetype['ext']}">${filetype['ext'].upper()}</label><br />
+ <?py #endfor ?>
+</td>
+</tr>
+<tr>
+<td class="postblock">Tamaño máximo <span style="font-weight:normal;">(KB)</span></td>
+<td><input type="text" name="maxsize" value="#{boardopts['maxsize']}" maxlength="5" size="11" /></td>
+</tr>
+<tr>
+<td class="postblock">Dimensión de miniatura <span style="font-weight:normal;">(px)</span></td>
+<td><input type="text" name="thumb_px" value="#{boardopts['thumb_px']}" maxlength="3" size="11" /></td>
+</tr>
+<tr>
+<td class="postblock">Hilos en página frontal</td>
+<td><input type="text" name="numthreads" value="#{boardopts['numthreads']}" maxlength="2" size="11" /></td>
+</tr>
+<tr>
+<td class="postblock">Respuestas a mostrar</td>
+<td><input type="text" name="numcont" value="#{boardopts['numcont']}" maxlength="2" size="11" /></td>
+</tr>
+<tr>
+<td class="postblock">Máximo de líneas <span style="font-weight:normal;">(frontal)</span></td>
+<td><input type="text" name="numline" value="#{boardopts['numline']}" maxlength="3" size="11" /></td>
+</tr>
+<tr>
+<td class="postblock">Edad máxima de un hilo</td>
+<td><input type="text" name="maxage" value="#{boardopts['maxage']}" maxlength="3" size="11" /> (días; 0 = desactivar)</td>
+</tr>
+<tr>
+<td class="postblock">Inactividad máxima de un hilo</td>
+<td><input type="text" name="maxinactive" value="#{boardopts['maxinactive']}" maxlength="3" size="11" /> (días; 0 = desactivar)</td>
+</tr>
+<tr>
+<td class="postblock">Archivar hilos</td>
+<td><input type="checkbox" name="archive" id="arch" value="1"#{checked(boardopts['archive'] == '1')} /><label for="arch"></label></td>
+</tr>
+<tr>
+<td class="postblock">Espera para crear nuevo hilo</td>
+<td><input type="text" name="threadsecs" value="#{boardopts['threadsecs']}" maxlength="4" size="11" /> (segundos)</td>
+</tr>
+<tr>
+<td class="postblock">Espera entre respuestas</td>
+<td><input type="text" name="postsecs" value="#{boardopts['postsecs']}" maxlength="3" size="11" /> (segundos)</td>
+</tr>
+</table>
+<br />
+<hr />
+<input type="submit" value="Guardar cambios" />
+</form>
+<?py #endif ?>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/manage/changepassword.html b/cgi/templates/manage/changepassword.html
new file mode 100644
index 0000000..977c772
--- /dev/null
+++ b/cgi/templates/manage/changepassword.html
@@ -0,0 +1,24 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<center>
+<div class="replymode">Cambiar contraseña</div>
+<form action="#{cgi_url}manage/changepassword" method="post">
+<table>
+ <tr>
+ <td class="postblock">Clave actual</td>
+ <td><input type="password" name="oldpassword" style="width:100%;" /></td>
+ </tr>
+ <tr>
+ <td class="postblock">Nueva clave</td>
+ <td><input type="password" name="newpassword" style="width:100%;" /></td>
+ </tr>
+ <tr>
+ <td class="postblock">Confirmar nueva clave</td>
+ <td><input type="password" name="newpassword2" style="width:100%;" /></td>
+ </tr>
+ <tr><td colspan="2"><input type="submit" style="width:100%;" value="Cambiar" /></td></tr>
+</table>
+</form>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?>
diff --git a/cgi/templates/manage/delete.html b/cgi/templates/manage/delete.html
new file mode 100644
index 0000000..78c1c5e
--- /dev/null
+++ b/cgi/templates/manage/delete.html
@@ -0,0 +1,23 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<center>
+<div class="replymode">Eliminar Post</div>
+<form action="#{cgi_url}manage/delete_confirmed/#{curboard}/#{postid}" method="get">
+<?py if do_ban: ?>
+ <input type="hidden" name="ban" value="true" />
+<?py #endif ?>
+<p>
+ <b>Post #${postid} de /${curboard}/</b><br />
+ <input id="a" type="checkbox" name="imageonly" value="true" /><label for="a">Eliminar sólo archivo</label><br />
+ <input id="b" type="checkbox" name="perma" value="true" /><label for="b" style="font-weight:bold">Eliminar permanentemente</label><br />
+ <br />
+ <i>Nota: Por favor evitar eliminar <b>permanentemente</b> el post al menos que sea estrictamente necesario.
+ <br />Al eliminar permanentemente un post no queda en papelera y se rompen
+ las referencias que se pueden haber hecho hacia él, especialmente en los BBS.</i>
+ <br /><br />
+ <input type="submit" value="Eliminar" />
+</p>
+</form>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?>
diff --git a/cgi/templates/manage/filters.html b/cgi/templates/manage/filters.html
new file mode 100644
index 0000000..188a741
--- /dev/null
+++ b/cgi/templates/manage/filters.html
@@ -0,0 +1,119 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<?py from tenjin.helpers.html import * ?>
+<center>
+<div class="replymode">Filtros</div>
+<?py if mode == 0: ?>
+<table class="managertable">
+ <tr>
+ <th>ID</th>
+ <th>Boards</th>
+ <th>Tipo</th>
+ <th>Acción</th>
+ <th>Mensaje</th>
+ <th>Modificado</th>
+ <th>Por</th>
+ <th>Acción</th>
+ </tr>
+ <?py for filter in filters: ?>
+ <tr>
+ <td style="text-align:center">#{filter['id']}</td>
+ <td style="text-align:center">${filter['boards']}</td>
+ <td>#{filter['type_formatted']}</td>
+ <td>#{filter['action_formatted']}</td>
+ <td>${filter['reason']}</td>
+ <td style="text-align:center">${filter['added']}</td>
+ <td style="text-align:center">${filter['staff']}</td>
+ <td style="text-align:center">[<a href="#{cgi_url}manage/filters/add?edit=#{filter['id']}">Editar</a>]<br />
+ [<a href="#{cgi_url}manage/filters/delete/#{filter['id']}">Eliminar</a>]</td>
+ </tr>
+ <?py #endfor ?>
+ <tr><td colspan="9" style="text-align:center">
+ <form action="#{cgi_url}manage/filters/add" method="get">
+ <input type="submit" value="Agregar filtro" />
+ </form></td>
+ </tr>
+</table>
+<?py elif mode == 1: ?>
+<form name="banform" method="post">
+<table>
+ <tr><th colspan="3" class="postblock">Tipo de filtro</th></tr>
+ <tr>
+ <td class="postblock"><input type="radio" name="type" id="type1" value="0"#{checked(startvalues['type'] == '0')} /><label for="type1">Palabra</label></td>
+ <td style="text-align:right">Regex:</td>
+ <td><input type="text" name="word" value="${startvalues['word']}" /></td>
+ </tr>
+ <tr>
+ <td rowspan="2" class="postblock"><input type="radio" name="type" id="type2" value="1"#{checked(startvalues['type'] == '1')} /><label for="type2">Nombre/Tripcode</label></td>
+ <td style="text-align:right">Nombre:</td>
+ <td><input type="text" name="name" value="${startvalues['name']}" /> (regex)</td>
+ </tr>
+ <tr>
+ <td style="text-align:right">Tripcode:</td>
+ <td><input type="text" name="trip" value="${startvalues['trip']}" /> (incluir separador)</td>
+ </tr>
+</table>
+<br />
+<div style="text-align:left;display:inline-block;">
+ <div class="postblock" style="display:block;text-align:center;margin-bottom:0.5em;">Aplicar a</div>
+ <div style="padding:0 10px">
+ <input type="checkbox" name="board_all" id="board_all" value="1"#{checked(startvalues['where'] == '')} /><label for="board_all" style="font-weight:bold">Todos los boards</label>
+ <hr />
+ <?py for board in boards: ?>
+ <input type="checkbox" name="board_#{board['dir']}" id="board_#{board['dir']}" value="1"#{checked(board['dir'] in startvalues['where'])} /><label for="board_#{board['dir']}">${board['name']} <span style="opacity:0.5">(/#{board['dir']}/)</span></label><br />
+ <?py #endfor ?>
+ </div>
+</div>
+<br /><br />
+<table>
+ <tr>
+ <th colspan="3" class="postblock">Acción</th>
+ </tr>
+ <tr>
+ <td class="postblock"><input type="radio" name="action" id="act0" value="0"#{checked(startvalues['action'] == '0')} /><label for="act0">Abortar post</label></td>
+ <td colspan="2"></td>
+ </tr>
+ <tr>
+ <td class="postblock"><input type="radio" name="action" id="act1" value="1"#{checked(startvalues['action'] == '1')} /><label for="act1">Reemplazar</label></td>
+ <td colspan="2"><input type="text" name="changeto" value="#{startvalues['changeto']}" size="40" /></td>
+ </tr>
+ <tr>
+ <td rowspan="2" class="postblock"><input type="radio" name="action" id="act2" value="2"#{checked(startvalues['action'] == '2')} /><label for="act2">Autoban</label></td>
+ <td style="text-align:right">Expira en:</td>
+ <td><input type="text" name="seconds" id="seconds" size="6" value="#{startvalues['seconds']}" /> (segundos)<div style="float:right"><input type="checkbox" name="blind" id="blind" value="1"#{checked(startvalues['blind'] == '1')} /><label for="blind">Ban ciego</label></div></td>
+ </tr>
+ <tr>
+ <td style="text-align:right">Preset:</td>
+ <td id="timelist">
+ <a href="#" data-secs="0">Nunca</a>
+ <a href="#" data-secs="3600">1h</a>
+ <a href="#" data-secs="21600">6h</a>
+ <a href="#" data-secs="43200">12h</a>
+ <a href="#" data-secs="86400">1d</a>
+ <a href="#" data-secs="259200">3d</a>
+ <a href="#" data-secs="604800">1w</a>
+ <a href="#" data-secs="2592000">30d</a>
+ <a href="#" data-secs="31536000">1y</a>
+ </td>
+ </tr>
+ <tr>
+ <td rowspan="2" class="postblock"><input type="radio" name="action" id="act3" value="3"#{checked(startvalues['action'] == '3')} /><label for="act3">Redireccionar</label></td>
+ <td colspan="2"><input type="text" name="redirect_url" value="#{startvalues['redirect_url']}" size="40" /></td>
+ </tr>
+ <tr>
+ <td style="text-align:right">Tardar:</td>
+ <td><input type="text" name="redirect_time" size="6" value="#{startvalues['redirect_time']}" /> (segundos)</td>
+ </tr>
+</table>
+<br />
+<table>
+ <tr><th class="postblock" style="padding:2px">Mensaje a mostrar</th></tr>
+ <tr><td><input type="text" size="50" name="reason" value="#{startvalues['reason']}" /></td></tr>
+</table>
+<br />
+<input type="submit" name="add" value="#{submit}" />
+</form>
+<?py #endif ?>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?>
diff --git a/cgi/templates/manage/ipdelete.html b/cgi/templates/manage/ipdelete.html
new file mode 100644
index 0000000..71c043a
--- /dev/null
+++ b/cgi/templates/manage/ipdelete.html
@@ -0,0 +1,24 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<center>
+ <div class="replymode">Eliminar por IP</div>
+ <form action="#{cgi_url}manage/ipdelete" name="ipdeleteform" method="post">
+ <table>
+ <tr>
+ <td class="postblock">Board(s)</td>
+ <td>
+ <input type="checkbox" name="board_all" id="all" value="1" /><label for="all" style="font-weight:bold">Todos los boards</label><hr />
+ <?py for board in boards: ?>
+ <input type="checkbox" name="board_#{board['dir']}" id="#{board['dir']}" value="1" /><label for="#{board['dir']}">#{board['name']} <span style="opacity:0.5">(/#{board['dir']}/)</span></label><br />
+ <?py #endfor ?>
+ </td>
+ </tr>
+ <tr>
+ <td class="postblock">Dirección IP</td>
+ <td><input type="text" name="ip" style="width:100%;" /></td>
+ </tr>
+ <tr><td colspan="2"><input type="submit" style="width:100%;" value="Eliminar posts" /></td></tr>
+ </table>
+ </form>
+</center><hr />
+<?py include('templates/base_bottom.html') ?>
diff --git a/cgi/templates/manage/ipshow.html b/cgi/templates/manage/ipshow.html
new file mode 100644
index 0000000..6937a0e
--- /dev/null
+++ b/cgi/templates/manage/ipshow.html
@@ -0,0 +1,73 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<center>
+ <div class="replymode">Mostrar por IP</div>
+ <?py if mode == 0: ?>
+ <form action="#{cgi_url}manage/ipshow" method="post">
+ <table>
+ <tr><td class="postblock">Dirección IP</td><td><input type="text" name="ip" /></td></tr>
+ <tr><td colspan="2"><input type="submit" style="width:100%;" value="Mostrar posts" /></td></tr>
+ </table>
+ </form>
+ <?py else: ?>
+ <style>td img{max-width:150px;height:auto;}td.z{padding:0}</style>
+ <div class="logo" style="margin:0;">Actividad IP #{ip} (#{len(posts)})</div>
+ <center>
+ Hostname: #{host if host else "Desconocido"} [#{country if country else "??"}]#{" (Nodo Tor)" if tor else ""}<br />
+ <br />
+ <form action="#{cgi_url}manage/ban/" name="banform" method="post"><input type="hidden" name="ip" value="${ip}" /><input type="submit" value="Ir a formulario de ban" /></form>
+ <hr />
+ <?py if posts: ?>
+ <table class="managertable">
+ <tr>
+ <th>Sección</th>
+ <th>Padre</th>
+ <th>ID</th>
+ <th>Fecha</th>
+ <th>Nombre</th>
+ <th>Asunto</th>
+ <th>Mensaje</th>
+ <th>Archivo</th>
+ <th>Acción</th>
+ </tr>
+ <?py for post in posts: ?>
+ <tr>
+ <td>#{post['dir']}</td>
+ <td>#{post['parentid']}</td>
+ <td>#{post['id']}</td>
+ <td class="date" data-unix="${post['timestamp']}">#{post['timestamp_formatted']}</td>
+ <?py if post['tripcode']: ?>
+ <td class="name"><b>#{post['name']}</b> #{post['tripcode']}</td>
+ <?py else: ?>
+ <td class="name"><b>#{post['name']}</b></td>
+ <?py #endif ?>
+ <td>#{post['subject']}</td>
+ <td>#{post['message']}</td>
+ <?py if post['file']: ?>
+ <td class="z"><img src="#{images_url}#{post['dir']}/thumb/#{post['thumb']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" /></td>
+ <?py else: ?>
+ <td></td>
+ <?py #endif ?>
+ <td>
+ <?py if post['IS_DELETED'] == '0': ?>
+ <a href="#{cgi_url}manage/delete/#{post['dir']}/#{post['id']}">Eliminar</a>
+ <?py elif post['IS_DELETED'] == '1': ?>
+ <a href="#{cgi_url}manage/recyclebin/0/restore/#{post['dir']}/#{post['id']}">Rec</a>
+ <abbr title="Eliminado por usuario">[1]</abbr>
+ <?py else: ?>
+ <a href="#{cgi_url}manage/recyclebin/0/restore/#{post['dir']}/#{post['id']}">Rec</a>
+ <abbr title="Eliminado por staff">[2]</abbr>
+ <?py #endif ?>
+ </td>
+ </tr>
+ <?py #endfor ?>
+ </table>
+ <hr />
+ <?py else: ?>
+ <b>Error:</b> No hay posts<br /><br />
+ <?py #endif ?>
+ [<a href="#{cgi_url}manage/ipshow">Volver al panel</a>]
+ <?py #endif ?>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/manage/lockboard.html b/cgi/templates/manage/lockboard.html
new file mode 100644
index 0000000..cebf061
--- /dev/null
+++ b/cgi/templates/manage/lockboard.html
@@ -0,0 +1,20 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<center>
+<div class="replymode">Cerrar o abrir board</div>
+<table class="managertable">
+ <tr><th colspan="2">Sección</th><th>Acción</th></tr>
+ <?py for board in boards: ?>
+ <tr>
+ <td>/#{board['dir']}/</td><td>#{board['name']}</td>
+ <?py if board['locked'] == '0': ?>
+ <td style="text-align:center;">[<a href="#{cgi_url}manage/boardlock/#{board['dir']}">Cerrar</a>]</td>
+ <?py elif board['locked'] == '1': ?>
+ <td style="text-align:center;">[<a href="#{cgi_url}manage/boardlock/#{board['dir']}">Abrir</a>]</td>
+ <?py #endif ?>
+ </tr>
+ <?py #endfor ?>
+</table>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?>
diff --git a/cgi/templates/manage/login.html b/cgi/templates/manage/login.html
new file mode 100644
index 0000000..7ce47a1
--- /dev/null
+++ b/cgi/templates/manage/login.html
@@ -0,0 +1,21 @@
+<?py include('templates/base_top.html') ?>
+<center>
+ #{page}
+ <form action="#{cgi_url}manage" method="post">
+ <table>
+ <tr>
+ <td class="postblock">Usuario</td>
+ <td><input type="text" name="username" /></td>
+ </tr>
+ <tr>
+ <td class="postblock">Contraseña</td>
+ <td><input type="password" name="password" /></td>
+ </tr>
+ <tr>
+ <td colspan="2"><input id="submit" type="submit" name="submit" style="width:100%;" value="Entrar" /></td>
+ </tr>
+ </table>
+ </form>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/manage/logs.html b/cgi/templates/manage/logs.html
new file mode 100644
index 0000000..e11780a
--- /dev/null
+++ b/cgi/templates/manage/logs.html
@@ -0,0 +1,17 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<center>
+<div class="replymode">Registro</div>
+<table class="managertable">
+ <tr><th>Fecha</th><th>Staff</th><th>Acción</th></tr>
+<?py for log in logs: ?>
+ <tr>
+ <td class="date" data-unix="${log['timestamp']}" style="white-space:nowrap;">${log['timestamp_formatted']}</td>
+ <td>${log['staff']}</td>
+ <td>${log['action']}</td>
+ </tr>
+<?py #endfor ?>
+</table>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/manage/manage.html b/cgi/templates/manage/manage.html
new file mode 100644
index 0000000..06b1737
--- /dev/null
+++ b/cgi/templates/manage/manage.html
@@ -0,0 +1,22 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<center>
+ <div style="margin:0.5em 0;"><strong>BANDEJA DE ENTRADA</strong>
+ <br />
+ Denuncias:
+ <?py if int(reports) > 0: ?>
+ <a href="#{cgi_url}manage/reports" style="color:red;font-weight:bold;">#{reports}</a>
+ <?py else: ?>
+ 0
+ <?py #endif ?></div>
+ <hr />
+ <strong>NOTICIAS DEL STAFF</strong>
+</center>
+<dl style="margin:0 2.5%">
+<?py for post in posts: ?>
+ <dt><strong>#{post['title'] if post['title'] else "Sin asunto"}</strong><br />#{post['id']} : <b class="name">${post['name']}</b> : <span class="date" data-unix="${post['timestamp']}"}>${post['timestamp_formatted']}</span></dt>
+ <dd style="margin-bottom:1em;">#{post['message']}</dd>
+<?py #endfor ?>
+</dl>
+<hr />
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/manage/menu.html b/cgi/templates/manage/menu.html
new file mode 100644
index 0000000..d6ffd5e
--- /dev/null
+++ b/cgi/templates/manage/menu.html
@@ -0,0 +1,30 @@
+<style>#adminmenu {text-align:center;}#adminmenu table {display:inline-block;font-size:10pt;margin-top:2px;text-align:left;}
+#adminmenu a {font-weight:bold;}label {vertical-align:top;}dd p {margin:0;}</style>
+<script type="text/javascript" src="/static/js/manage.js"></script>
+<input type="hidden" name="board" value="" />
+<?py if int(rights) < 4: ?>
+<div id="adminmenu">¡Bienvenido, <b><acronym title="Cuenta creada el #{added}">#{username}</acronym></b>! ¡Eres
+<?py if rights == '0': ?><b>Accionista</b>
+<?py elif rights == '1': ?><b>Accionista</b>
+<?py elif rights == '2': ?><span class="developer">Developer</span>
+<?py elif rights == '3': ?><span class="moderator">Moderador</span>
+<?py #endif ?> de #{site_title}!<br />
+<center>
+<table class="reply">
+<tr><td>Principal:</td>
+<td>- <a href="#{cgi_url}manage">Inicio</a> - <a href="#{cgi_url}manage/changepassword">Cambiar contrase&ntilde;a</a> - <a href="#{cgi_url}manage/newschannel">News Channel</a> - <a href="//webmail.bienvenidoainternet.org">Correo</a> - <a href="#{cgi_url}manage/logout">Cerrar sesi&oacute;n</a> -</td></tr>
+<tr><td>Posts:</td>
+<td>- <a href="#{cgi_url}manage/mod">Modbrowse</a> - <a href="#{cgi_url}manage/ipshow">Ver por IP</a> - <a href="#{cgi_url}manage/recyclebin">Papelera de reciclaje</a> - <a href="#{cgi_url}manage/recent_images">Im&aacute;genes recientes</a> -</td></tr>
+<tr><td>Moderaci&oacute;n:</td>
+<td>- <a href="#{cgi_url}manage/reports">Denuncias</a> - <a href="#{cgi_url}manage/ipdelete">Eliminar por IP</a> - <a href="#{cgi_url}manage/bans">Lista de bans</a> - <a href="#{cgi_url}manage/move">Mover hilo</a> - <a href="#{cgi_url}manage/filters">Filtros</a> - <a href="#{cgi_url}manage/quotes">Frases</a> -</td></tr>
+<?py if int(rights) < 3: ?>
+<tr><td>Administraci&oacute;n:</td>
+<td>- <a href="#{cgi_url}manage/rebuild">Reconstruir</a> - <a href="#{cgi_url}manage/news?type=1">Noticias</a> - <a href="#{cgi_url}manage/news?type=2">Twitter</a> - <a href="#{cgi_url}manage/board">Opciones de board</a> - <a href="#{cgi_url}manage/addboard">Agregar board</a> - <a href="#{cgi_url}manage/lockboard">Cerrar board</a> -</td></tr>
+<?py if int(rights) in [0,2]: ?>
+<tr><td>Staff:</td>
+<td>- <a href="#{cgi_url}manage/staff">Miembros</a> - <a href="#{cgi_url}manage/logs">Registro de acciones</a> -</td></tr>
+<?py #endif ?>
+<?py #endif ?>
+</table></center></div>
+<hr />
+<?py #endif ?> \ No newline at end of file
diff --git a/cgi/templates/manage/message.html b/cgi/templates/manage/message.html
new file mode 100644
index 0000000..6c53ecc
--- /dev/null
+++ b/cgi/templates/manage/message.html
@@ -0,0 +1,8 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<center>
+ <div class="replymode">#{title if title else "Mensaje"}</div>
+ <p>#{message}</p>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/manage/mod.html b/cgi/templates/manage/mod.html
new file mode 100644
index 0000000..ddc688f
--- /dev/null
+++ b/cgi/templates/manage/mod.html
@@ -0,0 +1,96 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<center>
+<div class="replymode">Modbrowse</div>
+<?py if mode == 1: ?>
+<table class="managertable">
+ <tr><th colspan="2">Sección</th><th>Acción</th></tr>
+ <?py for board in boards: ?>
+ <tr><td>/#{board['dir']}/</td><td>#{board['name']}</td><td>[<a href="#{cgi_url}manage/mod/#{board['dir']}">Navegar</a>]</td></tr>
+ <?py #endfor ?>
+</table>
+<?py elif mode == 2: ?>
+<table class="managertable">
+<tr>
+ <th>#</th>
+ <th>ID</th>
+ <th style="width:20%;">Asunto</th>
+ <th>Fecha</th>
+ <th style="width:80%;">Mensaje</th>
+ <th>Resp.</th>
+ <th>Acciones</th>
+</tr>
+<?py i = 1 ?>
+<?py for thread in threads: ?>
+<tr>
+ <td>#{i}</td>
+ <td>#{thread['id']}</td>
+ <td><a href="?thread=#{thread['id']}"><b>#{thread['subject']}</b></a></td>
+ <td class="date" data-unix="${thread['timestamp']}">#{thread['timestamp_formatted'][:21]}</td>
+ <td>${thread['message'][:200]}</td>
+ <td>#{thread['length']}</td>
+ <td style="white-space:nowrap;">
+ <a href="#{cgi_url}manage/lock/#{dir}/#{thread['id']}">L#{"-" if thread['locked'] == "1" else "+"}</a>
+ <a href="#{cgi_url}manage/permasage/#{dir}/#{thread['id']}">PS#{"-" if thread['locked'] == "2" else "+"}</a>
+ <a href="#{cgi_url}manage/move/#{dir}/#{thread['id']}">M</a>
+ <a href="#{cgi_url}manage/delete/#{dir}/#{thread['id']}">D</a>
+ <a href="#{cgi_url}manage/delete/#{dir}/#{thread['id']}?ban=true">&</a>
+ <a href="#{cgi_url}manage/ban/#{dir}/#{thread['id']}">B</a>
+ </td>
+</tr>
+<?py i += 1 ?>
+<?py #endfor ?>
+</table>
+<hr />
+[<a href="#{cgi_url}manage/mod" class="return">Volver</a>]
+<?py elif mode == 3: ?>
+<table class="managertable">
+<tr><th colspan="8" style="font-size:16pt;">Hilo: ${posts[0]['subject']} (#{posts[0]['length']})</th></tr>
+<tr><td colspan="8" style="font-size:14pt;text-align:center;"><a href="#{cgi_url}manage/lock/#{dir}/#{posts[0]['id']}">#{"Abrir hilo" if posts[0]['locked'] == "1" else "Cerrar hilo"}</a> /
+<a href="#{cgi_url}manage/permasage/#{dir}/#{posts[0]['id']}">#{"Quitar permasage" if posts[0]['locked'] == "2" else "Permasage"}</a> /
+<a href="#{cgi_url}manage/move/#{dir}/#{posts[0]['id']}">Mover hilo</a></td></tr>
+<tr>
+ <th>#</th>
+ <th>ID</th>
+ <th>Fecha</th>
+ <th>Nombre</th>
+ <th>Mensaje</th>
+ <th>Archivo</th>
+ <th>IP</th>
+ <th>Acción</th>
+</tr>
+<?py i = 1 ?>
+<?py for p in posts: ?>
+<tr>
+ <td>#{i}</td>
+ <td>#{p['id']}</td>
+ <td class="date" data-unix="${p['timestamp']}">${p['timestamp_formatted']}</td>
+ <td><span class="postername">${p['name']}</span></td>
+ <td>${p['message']}</td>
+ <td>
+ <?py if p['file']: ?><a href="/${dir}/src/#{p['file']}" target="_blank"><img src="/${dir}/mobile/${p['thumb']}" /></a><?py #endif ?>
+ </td>
+ <td><a href="#{cgi_url}manage/ipshow?ip=#{p['ip']}">#{p['ip']}</a></td>
+ <td style="white-space:nowrap;">
+ <?py if p['IS_DELETED'] == '0': ?>
+ <a href="#{cgi_url}manage/delete/#{dir}/#{p['id']}">Eliminar</a>
+ <a href="#{cgi_url}manage/delete/#{dir}/#{p['id']}?ban=true">&</a>
+ <a href="/cgi/manage/ban?ip=#{p['ip']}">Ban</a>
+ <?py elif p['IS_DELETED'] == '1': ?>
+ <a href="#{cgi_url}manage/recyclebin/0/restore/#{dir}/#{p['id']}">Recuperar</a>
+ <abbr title="Eliminado por usuario">[1]</abbr>
+ <?py elif p['IS_DELETED'] == '2': ?>
+ <a href="#{cgi_url}manage/recyclebin/0/restore/#{dir}/#{p['id']}">Recuperar</a>
+ <abbr title="Eliminado por staff">[2]</abbr>
+ <?py #endif ?>
+ </td>
+</tr>
+<?py i += 1 ?>
+<?py #endfor ?>
+</table>
+<hr />
+[<a href="#{cgi_url}manage/mod/#{dir}">Volver al panel</a>]
+<?py #endif ?>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/manage/move.html b/cgi/templates/manage/move.html
new file mode 100644
index 0000000..8fcc1e9
--- /dev/null
+++ b/cgi/templates/manage/move.html
@@ -0,0 +1,60 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<center>
+<div class="replymode">Mover hilo</div>
+<?py if oldboardid and oldthread: ?>
+<form action="#{cgi_url}manage/move/#{oldboardid}/#{oldthread}" method="post">
+<?py else: ?>
+<form action="#{cgi_url}manage/move" method="post">
+<?py #endif ?>
+<table>
+ <tr>
+ <td class="postblock">Board actual</td>
+ <td>
+ <?py if oldboardid and oldthread: ?>
+ <select name="oldboardid" style="width:100%;">
+ <?py for board in boards: ?>
+ <option value="#{board['dir']}"#{' selected="selected"' if oldboardid == board['dir'] else ''}>#{board['dir']} - #{board['name']}</option>
+ <?py #endfor ?>
+ </select>
+ <?py else: ?>
+ <select name="oldboardid" style="width:100%;">
+ <?py for board in boards: ?>
+ <option value="#{board['dir']}">#{board['dir']} - #{board['name']}</option>
+ <?py #endfor ?>
+ </select>
+ <?py #endif ?>
+ </td>
+ </tr>
+ <tr>
+ <td class="postblock">ID de hilo</td>
+ <td>
+ <?py if oldboardid and oldthread: ?>
+ <input type="text" name="oldthread" style="width:100%;" value="#{oldthread}" />
+ <?py else: ?>
+ <input type="text" name="oldthread" style="width:100%;" />
+ <?py #endif ?>
+ </td>
+ </tr>
+ <tr>
+ <td class="postblock">Mover a</td>
+ <td>
+ <select name="newboardid" style="width:100%;">
+ <?py for board in boards: ?>
+ <option value="#{board['dir']}">#{board['dir']} - #{board['name']}</option>
+ <?py #endfor ?>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td class="postblock">Insertar mensaje</td>
+ <td>
+ <input type="checkbox" name="msg" value="1" />
+ </td>
+ </tr>
+ <tr><td colspan="2"><input type="submit" name="submit" style="width:100%;" value="Mover" /></td></tr>
+</table>
+</form>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/manage/quotes.html b/cgi/templates/manage/quotes.html
new file mode 100644
index 0000000..d30a403
--- /dev/null
+++ b/cgi/templates/manage/quotes.html
@@ -0,0 +1,12 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<center>
+ <div class="replymode">Quotes</div>
+ <p>Ingresa un mensaje a mostrar por cada linea:</p>
+ <form method="post" action="">
+ <textarea name="data" cols="80" rows="15" style="width:500px;height:250px;">${data}</textarea><br />
+ <input type="submit" name="save" style="width:500px;" value="Guardar" />
+ </form>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?>
diff --git a/cgi/templates/manage/rebuild.html b/cgi/templates/manage/rebuild.html
new file mode 100644
index 0000000..3afc057
--- /dev/null
+++ b/cgi/templates/manage/rebuild.html
@@ -0,0 +1,20 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<center>
+<div class="replymode">Reconstruir board</div>
+<table class="managertable">
+ <tr><th colspan="2">Sección</th><th colspan="2">Acción</th></tr>
+ <tr><td colspan="2"><b>Home</b></td><td colspan="2" style="text-align:center;">[<a href="#{cgi_url}manage/rebuild/!HOME">Reconstruir</a>]</td></tr>
+ <tr><td colspan="2"><b>Noticias</b></td><td colspan="2" style="text-align:center;">[<a href="#{cgi_url}manage/rebuild/!NEWS">Reconstruir</a>]</td></tr>
+ <tr><td colspan="2"><b>Índices de archivos</b></td><td colspan="2" style="text-align:center;">[<a href="#{cgi_url}manage/rebuild/!KAKO">Reconstruir</a>]</td></tr>
+ <tr><td colspan="2"><b>.htaccess</b></td><td colspan="2" style="text-align:center;">[<a href="#{cgi_url}manage/rebuild/!HTACCESS">Reconstruir</a>]</td></tr>
+ <?py for board in boards: ?>
+ <tr><td>/#{board['dir']}/</td><td>#{board['name']}</td><td>[<a href="#{cgi_url}manage/rebuild/#{board['dir']}">Reconstruir frontales</a>]</td><td>[<a href="#{cgi_url}manage/rebuild/#{board['dir']}?everything=1">Reconstruir todo</a>]</td></tr>
+ <?py #endfor ?>
+ <tr><td colspan="4" align="center"><form action="#{cgi_url}manage/rebuild/!ALL" method="get"><input type="submit" style="width:100%" value="Reconstruir todos (frontales)" /></form></td></tr>
+ <tr><td colspan="4" align="center"><form action="#{cgi_url}manage/rebuild/!BBS" method="get"><input type="submit" style="width:100%" value="Reconstruir todos (BBS)" /></form></td></tr>
+ <tr><td colspan="4" align="center"><form action="#{cgi_url}manage/rebuild/!IB" method="get"><input type="submit" style="width:100%" value="Reconstruir todos (IB)" /></form></td></tr>
+</table>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?>
diff --git a/cgi/templates/manage/recent_images.html b/cgi/templates/manage/recent_images.html
new file mode 100644
index 0000000..39f919c
--- /dev/null
+++ b/cgi/templates/manage/recent_images.html
@@ -0,0 +1,24 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<style>.imgs{font-size:0;}.imgs img{vertical-align:top;margin:2px;height:150px;width:auto;}</style>
+<center>
+<div class="replymode">Imágenes recientes</div>
+<form action="#{cgi_url}manage/recent_images" name="recent_images" method="post">
+ <table>
+ <tr><td class="postblock">Número a mostrar</td><td><input type="text" name="images" size="4" /></td></tr>
+ <tr><td colspan="2"><input type="submit" style="width:100%;" value="Enviar" /></td></tr>
+ </table>
+</form>
+<hr />
+<div class="imgs">
+<?py for post in posts: ?>
+ <?py if post['parentid'] != '0': ?>
+ <a href="/#{post['dir']}/res/#{post['parentid']}.html##{post['id']}"><img src="#{boards_url}#{post['dir']}/thumb/#{post['thumb']}" /></a>
+ <?py else: ?>
+ <a href="/#{post['dir']}/res/#{post['id']}.html##{post['id']}"><img src="#{boards_url}#{post['dir']}/thumb/#{post['thumb']}" /></a>
+ <?py #endif ?>
+<?py #endfor ?>
+</div>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/manage/recyclebin.html b/cgi/templates/manage/recyclebin.html
new file mode 100644
index 0000000..b413c9c
--- /dev/null
+++ b/cgi/templates/manage/recyclebin.html
@@ -0,0 +1,72 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<?py from tenjin.helpers.html import * ?>
+<center>
+<div class="replymode">Papelera de Reciclaje</div>
+<form name="boardForm" method="get" action="#{cgi_url}manage/recyclebin/0">
+<table>
+<tr>
+ <td class="postblock">Eliminado por</td>
+ <td>
+ <input type="radio" id="type1" name="type" value="1"#{checked(type == 1)} /><label for="type1">Usuario</label>
+ <input type="radio" id="type2" name="type" value="2"#{checked(type == 2)} /><label for="type2">Staff</label>
+ <input type="radio" id="type0" name="type" value="0"#{checked(type == 0)} /><label for="type0">Ambos</label>
+ </td>
+</tr>
+<tr>
+ <td class="postblock">Board</td><td>
+ <select name="board" style="width:100%;">
+ <option value="all">Todos los boards</option>
+<?py for board in boards: ?>
+ <option value="#{board['dir']}"#{selected(board['checked'])}>#{board['dir']} - ${board['name']}</option>
+<?py #endfor ?>
+ </select>
+ </td>
+</tr>
+<tr><td colspan="2"><input type="submit" style="width:100%;" value="Mostrar" /></td></tr>
+</table>
+</form>
+<hr />
+<?py if message: ?>
+${message}
+<hr />
+<?py #endif ?>
+<?py if not skip: ?>
+<form name="deleteForm" method="post" action="#{cgi_url}manage/recyclebin/#{currentpage}">
+ <?py if curboard: ?>
+ <input type="hidden" name="board" value="#{curboard}" />
+ <?py #endif ?>
+ <table class="managertable">
+ <tr>
+ <th></th>
+ <th></th>
+ <th>ID</th>
+ <th>Timestamp</th>
+ <th>Board</th>
+ <th>Tipo</th>
+ <th>IP</th>
+ <th>Mensaje</th>
+ </tr>
+ <?py for post in posts: ?>
+ <tr>
+ <td><a href="#{cgi_url}manage/recyclebin/#{currentpage}/delete/#{post['dir']}/#{post['id']}">X</a><br /><a href="#{cgi_url}manage/recyclebin/#{currentpage}/restore/#{post['dir']}/#{post['id']}">R</a></td>
+ <td><input type="checkbox" name="!i#{post['dir']}/#{post['id']}" id="#{post['dir']}#{post['id']}" value="1" /><label for="#{post['dir']}#{post['id']}"></label></td>
+ <td>#{post['id']}</td>
+ <td class="date" data-unix="${post['timestamp']}">${post['timestamp_formatted']}</td>
+ <td>${post['dir']}</td>
+ <td>${post['IS_DELETED']}</td>
+ <td>${post['ip']}</td>
+ <td>#{post['message']}</td>
+ </tr>
+ <?py #endfor ?>
+ <tr><td colspan="8" align="center"><input name="deleteall" type="submit" value="Eliminar seleccionados" /></td></tr>
+ </table>
+</form>
+<hr />
+<div style="font-size:larger">#{navigator}</div>
+<?py else: ?>
+ No hay posts.
+<?py #endif ?>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?>
diff --git a/cgi/templates/manage/reports.html b/cgi/templates/manage/reports.html
new file mode 100644
index 0000000..f47ec38
--- /dev/null
+++ b/cgi/templates/manage/reports.html
@@ -0,0 +1,58 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<?py from tenjin.helpers.html import * ?>
+<center>
+<div class="replymode">Reportes</div>
+<?py if message: ?>
+${message}
+<?py #endif ?>
+<form name="boardForm" method="get" action="#{cgi_url}manage/reports/0">
+<table>
+ <tr>
+ <td class="postblock">Board</td>
+ <td>
+ <select name="board">
+ <option value="all">Todos los boards</option>
+<?py for board in boards: ?>
+ <option value="#{board['dir']}"#{selected(board['checked'])}>#{board['dir']} - #{board['name']}</option>
+<?py #endfor ?>
+ </select>
+ <td><input type="submit" value="Mostrar" /></td>
+ </td></tr>
+</table>
+</form>
+
+<form name="ignoreForm" method="post" action="#{cgi_url}manage/reports/#{currentpage}">
+<?py if curboard: ?>
+<input type="hidden" name="board" value="#{board}" />
+<?py #endif ?>
+<hr />
+<table class="managertable">
+<tr>
+ <th></th>
+ <th></th>
+ <th>Fecha</th>
+ <th>Post</th>
+ <th>IP Post</th>
+ <th>Raz&oacute;n</th>
+ <th>IP Denuncia</th>
+</tr>
+<?py for report in reports: ?>
+<tr>
+ <td> <a href="#{cgi_url}manage/reports/#{currentpage}/ignore/#{report['id']}">X</a> </td>
+ <td><input type="checkbox" name="i#{report['id']}" id="i#{report['id']}" value="1" /><label for="i#{report['id']}"></label></td>
+ <td class="date" data-unix="${report['timestamp']}">${report['timestamp_formatted']}</td>
+ <td><a href="#{report['link']}">${report['link']}</a></td>
+ <td><a href="#{cgi_url}manage/ipshow?ip=${report['ip']}">${report['ip']}</a></td>
+ <td>${report['reason']}</td>
+ <td><a href="#{cgi_url}manage/ipshow?ip=${report['reporterip']}">${report['reporterip']}</a></td>
+</tr>
+<?py #endfor ?>
+<tr>
+ <td colspan="8" style="text-align:center;"><input name="ignore" type="submit" value="Ignorar seleccionados" /></td>
+</tr>
+</table>
+</form>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?>
diff --git a/cgi/templates/manage/search.html b/cgi/templates/manage/search.html
new file mode 100644
index 0000000..6c2ec6f
--- /dev/null
+++ b/cgi/templates/manage/search.html
@@ -0,0 +1,27 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<center>
+<div class="replymode">Registro de búsqueda</div>
+<table class="managertable">
+ <tr>
+ <th>ID</th>
+ <th>Fecha</th>
+ <th>Búsqueda</th>
+ <th>En</th>
+ <th>Resultados</th>
+ <th>Por</th>
+ </tr>
+<?py for log in search: ?>
+ <tr>
+ <td>${log['id']}</td>
+ <td class="date" data-unix="${log['timestamp']}">${log['timestamp_formatted']}</td>
+ <td>${log['keyword']}</td>
+ <td>${"[A] " if log['archive'] else ""}${"Global" if log["ita"] == "" else log["ita"]}</td>
+ <td>${log['res']}</td>
+ <td><a href="#{cgi_url}manage/ipshow?ip=${log['ip']}">${log['ip']}</a></td>
+ </tr>
+<?py #endfor ?>
+</table>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/manage/staff.html b/cgi/templates/manage/staff.html
new file mode 100644
index 0000000..787a843
--- /dev/null
+++ b/cgi/templates/manage/staff.html
@@ -0,0 +1,63 @@
+<?py include('templates/base_top.html') ?>
+<?py include('templates/manage/menu.html') ?>
+<?py from tenjin.helpers.html import * ?>
+<center>
+<div class="replymode">Staff</div>
+<?py if mode == 0: ?>
+ <table class="managertable">
+ <tr>
+ <th>ID</th>
+ <th>Nombre</th>
+ <th>Nivel</th>
+ <th>Última actividad</th>
+ <th>Acciones</th>
+ </tr>
+ <?py for member in staff: ?>
+ <tr>
+ <td>${member['id']}</td>
+ <td><b>${member['username']}</b></td>
+ <td>${member['rights']}</td>
+ <td class="date" data-unix="${member['lastactivestamp']}">${member['lastactive']}</td>
+ <td>
+ [<a href="#{cgi_url}manage/staff/edit/#{member['id']}">Editar</a>]
+ [<a href="#{cgi_url}manage/staff/delete/#{member['id']}">Eliminar</a>]
+ </td>
+ </tr>
+ <?py #endfor ?>
+ <tr>
+ <td colspan="5"><form action="#{cgi_url}manage/staff/add" method="get"><input type="submit" style="width:100%;" value="Agregar miembro" /></form></td>
+ </tr>
+ </table>
+<?py elif mode == 1: ?>
+<form action="#{cgi_url}manage/staff/#{action}" method="post">
+<table>
+ <tr>
+ <td class="postblock">Nombre</td>
+ <td><input type="text" name="username" value="${member_username}" style="width:100%;" /></td>
+ </tr>
+ <?py if not member: ?>
+ <tr>
+ <td class="postblock">Contraseña</td>
+ <td><input type="password" name="password" style="width:100%;"/></td>
+ </tr>
+ <?py #endif ?>
+ <tr>
+ <td class="postblock">Nivel</td>
+ <td>
+ <select name="rights" style="width:100%;">
+ <option value="3"#{selected(member_rights == '3')}>Moderador</option>
+ <option value="2"#{selected(member_rights == '2')}>Developer</option>
+ <option value="1"#{selected(member_rights == '1')}>Administrador</option>
+ <option value="0"#{selected(member_rights == '0')}>Super-Administrador</option>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2"><input type="submit" name="submit" style="width:100%;" value="${submit}"/></td>
+ </tr>
+</table>
+</form>
+<?py #endif ?>
+</center>
+<hr />
+<?py include('templates/base_bottom.html') ?> \ No newline at end of file
diff --git a/cgi/templates/mobile/base_top.html b/cgi/templates/mobile/base_top.html
new file mode 100644
index 0000000..6a6c5bd
--- /dev/null
+++ b/cgi/templates/mobile/base_top.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<?py if (replythread and threads) or board: ?>
+ <title>#{board_name}@Bienvenido a Internet Móvil</title>
+<?py else: ?>
+ <title>Bienvenido a Internet Móvil</title>
+<?py #endif ?>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <link rel="shortcut icon" href="#{static_url}img/favicon.ico" />
+ <link rel="stylesheet" type="text/css" href="#{static_url}css/mobile.css?v=8" />
+ <script type="text/javascript" src="#{static_url}js/mobile.js?v=9"></script>
+</head>
diff --git a/cgi/templates/mobile/board.html b/cgi/templates/mobile/board.html
new file mode 100644
index 0000000..70b8461
--- /dev/null
+++ b/cgi/templates/mobile/board.html
@@ -0,0 +1,55 @@
+<?py include('templates/mobile/base_top.html') ?>
+<body class="img"><a name="top"></a>
+<div class="nav"><div><a href="//m.bienvenidoainternet.org">Home</a><a href="#{cgi_url}mobile/#{board}/">Volver</a><a href="#form">&#9660;</a></div></div>
+<?py for thread in threads: ?>
+<div id="thread">
+<?py for post in thread['posts']: ?>
+ <?py if post['IS_DELETED'] == "1": ?>
+ <div class="pst"><h3 class="del"><a name="#{post['id']}"></a>No.#{post['id']} eliminado por el usuario.</h3></div>
+ <?py elif post['IS_DELETED'] == "2": ?>
+ <div class="pst"><h3 class="del"><a name="#{post['id']}"></a>No.#{post['id']} eliminado por miembro del staff.</h3></div>
+ <?py else: ?>
+ <?py if post['parentid'] == "0": ?>
+ <div class="first"><h1>#{post["subject"]} <span>(#{thread['length']})</span></h1>
+ <?py else: ?>
+ <div class="pst">
+ <?py if post['subject']: ?>
+ <h2>#{post["subject"]}</h2>
+ <?py #endif ?>
+ <?py #endif ?><h3><a href="#" class="num" name="#{post['id']}">#{post['id']}</a>#{post['name']} #{post['tripcode']} #{post['timestamp_formatted']}</h3>
+ <?py if post['file']: ?><a href="/#{board}/src/#{post['file']}" target="_blank" class="thm"><img src="/#{board}/mobile/#{post['thumb']}" /><br />#{int(post['file_size'])//1024}KB #{post['file'].split(".")[1].upper()}</a><?py #endif ?>
+ <div class="msg">#{post['message']}</div></div>
+ <?py #endif ?>
+<?py #endfor ?>
+<?py if threads[0]['posts'][0]['locked'] != "1": ?>
+<a href="./#{thread['id']}" id="n">Recargar</a><span id="n2"></span>
+<?py #endif ?>
+<div class="nav"><div><a href="//m.bienvenidoainternet.org">Home</a><a href="#{cgi_url}mobile/#{board}/">Volver</a><a href="#top">&#9650;</a></div></div>
+<?py if threads[0]['posts'][0]['locked'] == "1": ?>
+ <div class="warn red" style="text-align:center;">El hilo ha sido cerrado. Ya no se puede postear en &eacute;l.</div>
+<?py else: ?>
+<form name="postform" id="postform" action="/cgi/post" method="post" enctype="multipart/form-data">
+ <input type="hidden" name="board" value="#{board}" /><input type="hidden" name="parent" value="#{replythread}" /><input type="hidden" name="mobile" value="true" /><input type="hidden" name="password" value="" />
+ <div style="display:none;"><input type="text" name="name" /><input type="text" name="email" /></div>
+ <?py if not disable_subject: ?>
+ <input class="fld" type="text" name="subject" placeholder="Asunto (opcional)" />
+ <?py #endif ?>
+ <?py if not disable_name: ?>
+ <input class="fld" type="text" name="fielda" placeholder="Nombre (opcional)" />
+ <?py #endif ?>
+ <input class="fld" type="text" name="fieldb" placeholder="E-mail (opcional)" />
+ <textarea name="message" rows="6"></textarea>
+<?py if allow_image_replies: ?>
+ <div class="file"><input type="file" name="file" class="fld" />
+ <?py if allow_spoilers: ?>
+ <label class="fld"><input type="checkbox" name="spoil" /> Spoiler</label>
+ <?py #endif ?></div>
+<?py #endif ?>
+ <input id="post" type="submit" value="Responder" />
+</form>
+<?py #endif ?>
+</div>
+<?py #endfor ?>
+<a name="form"></a>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/mobile/error.html b/cgi/templates/mobile/error.html
new file mode 100644
index 0000000..00ae4f4
--- /dev/null
+++ b/cgi/templates/mobile/error.html
@@ -0,0 +1,6 @@
+<?py include('templates/mobile/base_top.html') ?>
+<body class="img">
+<div class="top"><a href="//m.bienvenidoainternet.org"><img src="#{static_url}css/img/0back.png" /><br />Home</a>Error</div><br />
+<hr size="1"><br /><br /><div style="color:red;font-size:x-large;font-weight:bold;text-align:center;">#{error}</div><br /><br /><hr size="1">
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/mobile/latest.html b/cgi/templates/mobile/latest.html
new file mode 100644
index 0000000..615b21c
--- /dev/null
+++ b/cgi/templates/mobile/latest.html
@@ -0,0 +1,14 @@
+<?py include('templates/mobile/base_top.html') ?>
+<body class="txt">
+<div class="top">
+ <a href="/movil.html"><img src="#{static_url}css/img/0info.png" /><br />Info</a>
+ Bienvenido a Internet Móvil
+</div>
+<div class="bar"><a href="//m.bienvenidoainternet.org">Secciones</a><a href="/cgi/mobilehome" class="sel">Hilos activos</a><a href="/cgi/mobilenewest">Nuevos hilos</a></div>
+<div class="list">
+ <?py for thread in latest_age: ?>
+ <a href="/cgi/mobileread${thread['url']}">#{thread['content']}<div>${thread['board_fulln']} <span>R:<span>#{int(thread['length'])-1}</span></span></div></a>
+ <?py #endfor ?>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/mobile/newest.html b/cgi/templates/mobile/newest.html
new file mode 100644
index 0000000..37fd67f
--- /dev/null
+++ b/cgi/templates/mobile/newest.html
@@ -0,0 +1,14 @@
+<?py include('templates/mobile/base_top.html') ?>
+<body class="txt">
+<div class="top">
+ <a href="/movil.html"><img src="#{static_url}css/img/0info.png" /><br />Info</a>
+ Bienvenido a Internet Móvil
+</div>
+<div class="bar"><a href="//m.bienvenidoainternet.org">Secciones</a><a href="/cgi/mobilehome">Hilos activos</a><a href="/cgi/mobilenewest" class="sel">Nuevos hilos</a></div>
+<div class="list">
+ <?py for thread in newthreads: ?>
+ <a href="/cgi/mobileread${thread['url']}">#{thread['content']}<div>${thread['board_fulln']}</div></a>
+ <?py #endfor ?>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/mobile/threadlist.html b/cgi/templates/mobile/threadlist.html
new file mode 100644
index 0000000..edb81eb
--- /dev/null
+++ b/cgi/templates/mobile/threadlist.html
@@ -0,0 +1,43 @@
+<?py include('templates/mobile/base_top.html') ?>
+<body class="img">
+<div class="top">
+ <a href="//m.bienvenidoainternet.org"><img src="#{static_url}css/img/0back.png" /><br />Home</a>
+ #{board_name}
+</div>
+<?py if mode == 1: ?>
+ <div class="bar"><a href="#{cgi_url}mobile/#{board}" class="sel">Portada</a><a href="#{cgi_url}mobilelist/#{board}">Lista</a><a href="#{cgi_url}mobilecat/#{board}">Cat&aacute;logo</a><a href="#{cgi_url}mobilenew/#{board}">Nuevo hilo</a></div>
+ <?py for thread in more_threads: ?>
+ <div class="prev">
+ <a href="#{cgi_url}mobileread/#{board}/#{thread['id']}"><img class="thm" src="/#{board}/mobile/#{thread['thumb']}" />
+ <b>#{thread["subject"]}</b> (R:#{int(thread["length"])-1})</a>
+ <h3>#{thread['name']} #{thread['tripcode']} #{thread['timestamp_formatted']}</h3>
+ #{thread['message']}#{" [...]" if thread['shortened'] else ""}
+ <?py if thread['lastreply']: ?>
+ <div class="pst"><h3>#{thread['lastreply']['name']} #{thread['lastreply']['tripcode']} #{thread['lastreply']['timestamp_formatted']}</h3>
+ #{thread['lastreply']['message']}#{" [...]" if thread['lastreply']['shortened'] else ""}</div>
+ <?py #endif ?>
+ </div>
+ <?py #endfor ?>
+<?py elif mode == 2: ?>
+ <div class="bar"><a href="#{cgi_url}mobile/#{board}">Portada</a><a href="#{cgi_url}mobilelist/#{board}" class="sel">Lista</a><a href="#{cgi_url}mobilecat/#{board}">Cat&aacute;logo</a><a href="#{cgi_url}mobilenew/#{board}">Nuevo hilo</a></div>
+ <div class="search"><input id="search" placeholder="Buscar en asuntos" style="padding:7px;" type="text"></div>
+ <div class="ord"><span>Orden:</span><a data-sort="0" class="sel" href="#">Normal</a><a data-sort="1" href="#">Nuevo</a><a data-sort="2" href="#">Viejo</a><a data-sort="3" href="#">Más</a><a data-sort="4" href="#">Menos</a></div>
+ <div id="to_sort" class="list">
+ <?py i = 1 ?>
+ <?py for thread in more_threads: ?>
+ <a data-num="${i}" data-res="#{thread['length']}" data-id="#{thread['id']}" href="#{cgi_url}mobileread/#{board}/#{thread['id']}"><strong>#{thread["subject"]}</strong>: #{thread['message']}#{" [...]" if thread['shortened'] else ""}<br />
+ <span class="info"><span>&Uacute;ltima: #{thread['lastreply']['timestamp_formatted'] if thread['lastreply'] else thread['timestamp_formatted']}</span> Respuestas: <b>#{int(thread["length"])-1}</b></span></a>
+ <?py i += 1 ?>
+ <?py #endfor ?>
+ </div>
+<?py else: ?>
+ <div class="bar"><a href="#{cgi_url}mobile/#{board}">Portada</a><a href="#{cgi_url}mobilelist/#{board}">Lista</a><a href="#{cgi_url}mobilecat/#{board}" class="sel">Cat&aacute;logo</a><a href="#{cgi_url}mobilenew/#{board}">Nuevo hilo</a></div>
+ <div class="search"><input id="catsearch" placeholder="Buscar en catálogo" style="padding:7px;" type="text"></div>
+ <div class="ord"><span>Orden:</span><a data-sort="0" class="sel" href="#">Normal</a><a data-sort="1" href="#">Nuevo</a><a data-sort="2" href="#">Viejo</a><a data-sort="3" href="#">Más</a><a data-sort="4" href="#">Menos</a></div>
+ <div id="to_sort" style="text-align:center;margin-top:0.5em;">
+ <?py i = 1 ?>
+ <?py for thread in more_threads: ?><a data-num="${i}" data-res="#{thread['length']}" data-id="#{thread['id']}" class="cat" href="#{cgi_url}mobileread/#{board}/#{thread['id']}"><img src="/#{board}/mobile/#{thread['thumb']}" /><br />(#{int(thread["length"])-1}R) <strong>#{thread["subject"]}</strong>: #{thread['message']}#{" [...]" if thread['shortened'] else ""}</a><?py i += 1 ?><?py #endfor ?>
+ </div>
+<?py #endif ?>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/mobile/txt_newthread.html b/cgi/templates/mobile/txt_newthread.html
new file mode 100644
index 0000000..b19d2fa
--- /dev/null
+++ b/cgi/templates/mobile/txt_newthread.html
@@ -0,0 +1,35 @@
+<?py include('templates/mobile/base_top.html') ?>
+<body class="#{"txt" if board_type == '1' else "img"}">
+<div class="top">
+ <a href="//m.bienvenidoainternet.org"><img src="#{static_url}css/img/0back.png" /><br />Home</a>
+ #{board_name}
+</div>
+<?py if board_type == '1': ?>
+<div class="bar"><a href="#{cgi_url}mobile/#{board}">Portada</a><a href="#{cgi_url}mobilelist/#{board}">Todos los hilos</a><a href="#{cgi_url}mobilenew/#{board}" class="sel">Nuevo hilo</a></div>
+<?py else: ?>
+<div class="bar"><a href="#{cgi_url}mobile/#{board}">Portada</a><a href="#{cgi_url}mobilelist/#{board}">Lista</a><a href="#{cgi_url}mobilecat/#{board}">Cat&aacute;logo</a><a href="#{cgi_url}mobilenew/#{board}" class="sel">Nuevo hilo</a></div>
+<?py #endif ?>
+<form name="postform" id="postform" action="/cgi/post" method="post" enctype="multipart/form-data">
+ <input type="hidden" name="board" value="#{board}" /> <input type="hidden" name="mobile" value="true" /><input type="hidden" name="password" value="" />
+ <div style="display:none;"><input type="text" name="name" maxlength="50" /><input type="text" name="email" maxlength="50" /></div>
+ <?py if not disable_subject: ?>
+ <input class="fld imp" type="text" name="subject" placeholder="Asunto#{" (opcional)" if board_type == '0' else ""}" maxlength="100" />
+ <?py #endif ?>
+ <?py if not disable_name: ?>
+ <input class="fld" type="text" name="fielda" placeholder="Nombre (opcional)" maxlength="50" />
+ <?py #endif ?>
+ <input class="fld" type="text" name="fieldb" placeholder="E-mail (opcional)" maxlength="50" />
+ <textarea name="message" rows="#{"8" if board_type == '1' else "6"}"></textarea>
+<?py if allow_images: ?>
+ <div class="file"><input type="file" name="file" class="fld" />
+ <?py if allow_spoilers: ?>
+ <label class="fld"><input type="checkbox" name="spoil" /> Spoiler</label>
+ <?py #endif ?></div>
+<?py #endif ?>
+ <input id="post" type="submit" value="Crear nuevo hilo" />
+</form>
+<?py if allow_images: ?>
+ <div class="rules">Formatos permitidos: #{', '.join(supported_filetypes).upper()}<br />Tamaño máximo: #{maxsize} KB</div>
+<?py #endif ?>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/mobile/txt_thread.html b/cgi/templates/mobile/txt_thread.html
new file mode 100644
index 0000000..8a19a94
--- /dev/null
+++ b/cgi/templates/mobile/txt_thread.html
@@ -0,0 +1,74 @@
+<?py include('templates/mobile/base_top.html') ?>
+<body class="txt">
+<a name="top"></a>
+<?py for thread in threads: ?>
+<div class="nav"><div><a href="//m.bienvenidoainternet.org">Home</a><a href="#{cgi_url}mobile/#{board}/">Volver</a><a href="#form">&#9660;</a></div></div>
+<div id="nav2">
+ <a href="#{cgi_url}mobileread/#{board}/#{thread['timestamp']}">Ver hilo completo</a>
+<?py if thread['length'] > 51: ?>
+ <a href="#{cgi_url}mobileread/#{board}/#{thread['timestamp']}/l25" rel="nofollow">Últimos 25</a>
+<?py #endif ?>
+<?py if thread['length'] > 50: ?>
+ <a href="#{cgi_url}mobileread/#{board}/#{thread['timestamp']}/-50" rel="nofollow">Primeros 50</a>
+<?py #endif ?>
+<?py r = range(thread['length'] / 50) ?>
+<?py for i in r[:-1]: ?>
+ <a href="#{cgi_url}mobileread/#{board}/#{thread['timestamp']}/#{(i+1)*50+1}-#{(i+2)*50}" rel="nofollow">#{(i+1)*50+1}-#{(i+2)*50}</a>
+<?py #endfor ?>
+<?py if r: ?>
+ <a href="#{cgi_url}mobileread/#{board}/#{thread['timestamp']}/#{(r[-1]+1)*50+1}-#{(r[-1]+2)*50}" rel="nofollow">#{(r[-1]+1)*50+1}-</a>
+<?py #endif ?>
+</div>
+<?py if thread['length'] > 1000: ?>
+ <div class="stop red">■ El hilo superó los 1000 mensajes y ha sido cerrado.</div>
+<?py elif thread['length'] > 950: ?>
+ <div class="warn red">■ El hilo ha recibido más de 950 mensajes. Límite: 1000</div>
+<?py elif thread['length'] > 900: ?>
+ <div class="warn yellow">■ El hilo ha recibido más de 900 mensajes. Límite: 1000</div>
+<?py #endif ?>
+<div id="thread">
+<h1>#{thread['subject']} <span>(#{thread['length']})</span></h1>
+<?py for post in thread['posts']: ?>
+<?py if post['IS_DELETED'] == '1': ?>
+<div class="pst"><h3 class="del"><a href="#" class="num">#{str(post['num']).zfill(4)}</a> Eliminado por el usuario.</h3></div>
+<?py elif post['IS_DELETED'] == '2': ?>
+<div class="pst"><h3 class="del"><a href="#" class="num">#{str(post['num']).zfill(4)}</a> Eliminado por miembro del staff.</h3></div>
+<?py else: ?>
+<div id="p#{post['id']}" class="pst">
+ <h3><a href="#" class="num">#{str(post['num']).zfill(4)}</a> #{post['name']} #{post['tripcode']}</h3>
+ <?py if post['file']: ?><a href="/#{board}/src/#{post['file']}" target="_blank" class="thm"><img src="/#{board}/mobile/#{post['thumb']}" /><br />#{int(post['file_size'])//1024}KB #{post['file'].split(".")[1].upper()}</a><?py #endif ?>
+ <div class="msg">#{post['message']}</div>
+ <h4>#{post['timestamp_formatted']}</h4>
+</div>
+<?py #endif ?>
+<?py #endfor ?>
+<?py if thread['locked'] != '1': ?>
+<a href="#{cgi_url}mobileread/#{board}/#{thread['timestamp']}/#{thread['length']}-n" id="n">Ver nuevos posts</a><span id="n2"></span>
+<?py #endif ?>
+<div class="nav">
+ <div><a href="//m.bienvenidoainternet.org">Home</a><a href="#{cgi_url}mobile/#{board}/">Volver</a><a href="#top">&#9650;</a></div>
+ <?py if nextrange: ?>
+ <div><a href="#{cgi_url}mobileread/#{board}/#{thread['timestamp']}">Hilo completo</a><a href="#{cgi_url}mobileread/#{board}/#{thread['timestamp']}/-50">Primeros 50</a><a href="#{cgi_url}mobileread/#{board}/#{thread['timestamp']}/l10">Últimos 25</a></div>
+ <?py #endif ?>
+</div>
+<?py if thread['locked'] != '1': ?>
+ <form name="postform" id="postform" action="/cgi/post" method="post" enctype="multipart/form-data">
+ <input type="hidden" name="board" value="#{board}" /><input type="hidden" name="parent" value="#{thread['id']}" /><input type="hidden" name="mobile" value="true" /><input type="hidden" name="password" value="" />
+ <div style="display:none"><input type="text" name="name" /><input type="text" name="email" /></div>
+ <input class="fld" type="text" name="fielda" placeholder="Nombre (opcional)" />
+ <input class="fld" type="text" name="fieldb" placeholder="E-mail (opcional)" />
+ <textarea name="message" rows="6"></textarea>
+<?py if allow_image_replies: ?>
+ <div class="file"><input type="file" name="file" class="fld" />
+ <?py if allow_spoilers: ?>
+ <label class="fld"><input type="checkbox" name="spoil" /> Spoiler</label>
+ <?py #endif ?></div>
+<?py #endif ?>
+ <input id="post" type="submit" value="Responder" />
+ </form>
+<?py #endif ?>
+</div>
+<a name="form"></a>
+<?py #endfor ?>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/mobile/txt_threadlist.html b/cgi/templates/mobile/txt_threadlist.html
new file mode 100644
index 0000000..5e3d133
--- /dev/null
+++ b/cgi/templates/mobile/txt_threadlist.html
@@ -0,0 +1,26 @@
+<?py include('templates/mobile/base_top.html') ?>
+<body class="txt">
+<div class="top">
+ <a href="//m.bienvenidoainternet.org"><img src="#{static_url}css/img/0back.png" /><br />Home</a>
+ #{board_name}
+</div>
+<?py if mode == 1: ?>
+<div class="bar"><a href="#{cgi_url}mobile/#{board}" class="sel">Portada</a><a href="#{cgi_url}mobilelist/#{board}">Todos los hilos</a><a href="#{cgi_url}mobilenew/#{board}">Nuevo hilo</a></div>
+<?py else: ?>
+<div class="bar"><a href="#{cgi_url}mobile/#{board}">Portada</a><a href="#{cgi_url}mobilelist/#{board}" class="sel">Todos los hilos</a><a href="#{cgi_url}mobilenew/#{board}">Nuevo hilo</a></div>
+<div class="search"><input id="search" placeholder="Buscar en asuntos" type="text"></div>
+<div class="ord"><span>Orden:</span><a data-sort="0" class="sel" href="#">Normal</a><a data-sort="1" href="#">Nuevo</a><a data-sort="2" href="#">Viejo</a><a data-sort="3" href="#">Más</a><a data-sort="4" href="#">Menos</a></div>
+<?py #endif ?>
+<div id="to_sort" class="list">
+ <?py i = 1 ?>
+ <?py for thread in more_threads: ?>
+ <?py if int(thread["length"]) > 10: ?>
+ <a data-num="${i}" data-res="${thread['length']}" data-id="${thread['id']}" href="#{cgi_url}mobileread/#{board}/#{thread['timestamp']}/l10">#{thread['subject']}<br /><span class="info"><span>Última: #{timestamps[i-1][1]}</span> Respuestas: <b>#{thread['length']}</b></span></a>
+ <?py else: ?>
+ <a data-num="${i}" data-res="#{thread['length']}" data-id="#{thread['id']}" href="#{cgi_url}mobileread/#{board}/#{thread['timestamp']}/l10">#{thread['subject']}<br /><span class="info"><span>Última: #{timestamps[i-1][1]}</span> Respuestas: <b>#{thread['length']}</b></span></a>
+ <?py #endif ?>
+ <?py i += 1 ?>
+ <?py #endfor ?>
+</div>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/mod.html b/cgi/templates/mod.html
new file mode 100644
index 0000000..21a35f6
--- /dev/null
+++ b/cgi/templates/mod.html
@@ -0,0 +1,86 @@
+<!-- MOD/S3M/XM module player for Web Audio (c) 2012-2015 Firehawk/TDA (firehawk@haxor.fi) -->
+<!-- Modificado para funcionar con Bienvenido a Internet BBS/IB -->
+<html>
+ <head>
+ <title>MOD/S3M/XM module player for Web Audio</title>
+ <meta name="description" content="A MOD/S3M/XM module player in Javascript using the Web Audio API.">
+ <link rel="stylesheet" href="/firehawk/style.css" type="text/css" media="screen" />
+ <script type="text/javascript" src="/firehawk/jquery-2.1.1.js"></script>
+ <script type="text/javascript" src="/firehawk/utils.js"></script>
+ <script type="text/javascript" src="/firehawk/player.js"></script>
+ <script type="text/javascript" src="/firehawk/pt.js"></script>
+ <script type="text/javascript" src="/firehawk/st3.js"></script>
+ <script type="text/javascript" src="/firehawk/ft2.js"></script>
+ <script type="text/javascript" src="/firehawk/ui.js"></script>
+ </head>
+ <body data-module="/#{board}/src/#{modfile}">
+ <div id="outercontainer">
+ <div id="headercontainer">
+ <div style="margin-left:8px;float:left">MOD/S3M/XM module player for Web Audio</div>
+ <div style="margin-right:8px;float:right">(c) 2012-2015 Firehawk/<a class="tdalink" href="http://tda.haxor.fi/" target="_blank">TDA</a></div>
+ <div style="clear:both;"></div>
+ </div>
+ <div id="innercontainer">
+ <div id="modsamples">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+</div>
+ <div style="position:relative;top:8px;margin-bottom:8px;">
+ <span id="modtitle">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
+ <span id="modinfo">('&nbsp;&nbsp;&nbsp;&nbsp;')</span>
+ <span id="modtimer"></span>
+ <br/><br/>
+ <a href="#" id="go_back">[&lt;&lt;]</a>
+ <a href="#" id="play">[reproducir]</a>
+ <a href="#" id="pause">[pausa]</a>
+ <a href="#" id="go_fwd">[&gt;&gt;]</a>
+ <span style="white-space:pre;"> </span>
+ <a href="#" title="Repeat song" id="modrepeat">[rept]</a>
+ <a class="down" title="Stereo separation" href="#" id="modpaula">[)oo(]</a>
+ <a class="down" title="Visualization type" href="#" id="modvis">[trks]</a>
+ <a title="Amiga A500 lowpass filter" href="#" id="modamiga">[filt]</a>
+ </div>
+ <div id="modchannels"><div id="even-channels"></div><div id="odd-channels"></div></div>
+ <div id="modpattern"></div>
+ <div style="clear:both"></div>
+ <div id="infotext">
+ Esta es una instancia local del reproductor de MODs por Firehawk - <a href="https://twitter.com/janihalme" style="color:#cce;">Twitter</a> / <a href="mailto:firehawk@haxor.fi" style="color:#cce">firehawk@haxor.fi</a>.<br/>Código fuente disponible en <a style="color:#cce;" target="_blank" href="https://github.com/jhalme/webaudio-mod-player">GitHub</a> bajo licencia MIT.
+ <!--
+ The player has been tested on Chrome 14+, Firefox 24+, Safari 6+ and Edge 20+ so far. <span style="color:#faa">Disable AdBlock if you get cuts or stuttering!</span>
+ To report bugs, suggest features or request songs, contact me on <a href="https://twitter.com/janihalme" style="color:#cce;">Twitter</a> or
+ email <a href="mailto:firehawk@haxor.fi" style="color:#cce">firehawk@haxor.fi</a>.
+ Source code available on .-->
+ </div>
+ </div>
+
+
+ </div>
+ </body>
+</html>
diff --git a/cgi/templates/navbar.html b/cgi/templates/navbar.html
new file mode 100644
index 0000000..1655f0b
--- /dev/null
+++ b/cgi/templates/navbar.html
@@ -0,0 +1,16 @@
+<a id="noticias" href="/noticias/">Actualidad</a>
+<a id="tech" href="/tech/">Tecnolog&iacute;a</a>
+<a id="juegos" href="/juegos/">Juegos</a>
+<a id="musica" href="/musica/">M&uacute;sica</a>
+<a id="tv" href="/tv/">TV y Cine</a>
+<a id="letras" href="/letras/">Humanidades</a>
+<a id="zonavip" href="/zonavip/">Club VIP</a>
+<a id="world" href="/world/">World Lobby</a>
+|
+<a id="img" href="/img/">Imágenes</a>
+<a id="2d" href="/2d/">二次元画像</a>
+<a id="n" href="/n/">Naturaleza</a>
+<a id="o" href="/o/">Oekaki</a>
+<a id="0" href="/0/">Cero</a>
+|
+<a id="bai" href="/bai/">Meta</a> \ No newline at end of file
diff --git a/cgi/templates/paint.html b/cgi/templates/paint.html
new file mode 100644
index 0000000..476babe
--- /dev/null
+++ b/cgi/templates/paint.html
@@ -0,0 +1,79 @@
+<?py include('templates/base_top.html') ?>
+<?py if selfy: ?>
+<script type="text/javascript" src="#{static_url}js/palette_selfy.js"></script>
+<?py #endif ?>
+<center>
+<?py if applet == 'shipainter': ?>
+<applet id="oekaki" code="c.ShiPainter.class" archive="#{boards_url}oek_temp/spainter_all.jar" width="#{width+250}" height="#{height+280}" mayscript="">
+ <?py for key, value in params.iteritems(): ?>
+ <param name="#{key}" value="#{value}" />
+ <?py #endfor ?>
+</applet>
+<?py if selfy: ?>
+<script type="text/javascript">palette_selfy();</script>
+<?py #endif ?>
+<?py elif applet == 'neo': ?>
+<link rel="stylesheet" href="#{static_url}js/paintbbs/PaintBBS-1.3.4.css" type="text/css" />
+<script src="#{static_url}js/paintbbs/PaintBBS-1.3.4.js" charset="UTF-8"></script>
+<applet-dummy id="oekaki" name="paintbbs" width="#{width+250}" height="#{height+280}">
+<param name="image_width" value="#{width}">
+<param name="image_height" value="#{height}">
+<param name="image_bkcolor" value="#FFFFFF">
+<param name="image_size" value="0">
+<param name="undo" value="90">
+<param name="undo_in_mg" value="15">
+<param name="color_text" value="#EFEFFF">
+<param name="color_bk" value="#E8EFFF">
+<param name="color_bk2" value="#D5D8EF">
+<param name="color_icon" value="#A1B8D8">
+<param name="color_iconselect" value="#000000">
+<param name="url_save" value="/oek_temp/save.php?applet=paintbbs">
+<param name="url_exit" value="#{cgi_url}oekaki/finish/#{board}/#{replythread}">
+<param name="poo" value="false">
+<param name="send_advance" value="true">
+<param name="thumbnail_width" value="100%">
+<param name="thumbnail_height" value="100%">
+<param name="tool_advance" value="true">
+<param name="tool_color_button" value="#D2D8FF">
+<param name="tool_color_button2" value="#D2D8FF">
+<param name="tool_color_text" value="#5A5781">
+<param name="tool_color_bar" value="#D2D8F0">
+<param name="tool_color_frame" value="#7474AB">
+<?py if edit: ?>
+<param name="image_canvas" value="#{edit}">
+<?py #endif ?>
+</applet-dummy>
+<?py elif applet == 'wpaint': ?>
+<script type="text/javascript" src="#{static_url}js/wpaint/lib/jquery.1.10.2.min.js"></script>
+<script type="text/javascript" src="#{static_url}js/wpaint/lib/jquery.ui.core.1.10.3.min.js"></script>
+<script type="text/javascript" src="#{static_url}js/wpaint/lib/jquery.ui.widget.1.10.3.min.js"></script>
+<script type="text/javascript" src="#{static_url}js/wpaint/lib/jquery.ui.mouse.1.10.3.min.js"></script>
+<script type="text/javascript" src="#{static_url}js/wpaint/lib/jquery.ui.draggable.1.10.3.min.js"></script>
+<link rel="Stylesheet" type="text/css" href="#{static_url}js/wpaint/lib/wColorPicker.min.css" />
+<script type="text/javascript" src="#{static_url}js/wpaint/lib/wColorPicker.min.js"></script>
+<link rel="Stylesheet" type="text/css" href="#{static_url}js/wpaint/wPaint.min.css" />
+<script type="text/javascript" src="#{static_url}js/wpaint/wPaint.min.js"></script>
+<script type="text/javascript" src="#{static_url}js/wpaint/plugins/main/wPaint.menu.main.min.js"></script>
+<script type="text/javascript" src="#{static_url}js/wpaint/plugins/text/wPaint.menu.text.min.js"></script>
+<script type="text/javascript" src="#{static_url}js/wpaint/plugins/shapes/wPaint.menu.main.shapes.min.js"></script>
+<script type="text/javascript" src="#{static_url}js/wpaint/plugins/file/wPaint.menu.main.file.min.js"></script>
+<div id="wPaint" style="position:relative; width:#{width}px; height:#{height}px; background-color:#7a7a7a; margin:70px auto 20px auto;"></div>
+<script type="text/javascript" src="#{static_url}js/wpaint/bai.js"></script>
+<?py elif applet == 'tegaki': ?>
+<form id="imgform" data-w="#{width}" data-h="#{height}" action="#{cgi_url}oekaki/finish/#{board}/#{replythread}" method="post">
+<input type="hidden" name="filebase" id="filebase" />
+</form>
+<link rel="Stylesheet" type="text/css" href="#{static_url}js/tegaki/tegaki.css" />
+<script type="text/javascript" src="#{static_url}js/tegaki/tegaki.js"></script>
+<div id="buttons"><button id="topen">Abrir Tegaki</button></div>
+<div style="font-size:20pt" id="status"></div>
+<?py #endif ?>
+
+<br /><br /><br />
+<div id="links">
+<a href="#{boards_url}#{board}">Volver</a><br />
+<a id="finish" href="#{cgi_url}oekaki/finish/#{board}/#{replythread}">Recuperar dibujo guardado</a>
+</div>
+</center>
+<br />
+<?py include('templates/base_bottom.html') ?>
diff --git a/cgi/templates/redirect.html b/cgi/templates/redirect.html
new file mode 100644
index 0000000..172425d
--- /dev/null
+++ b/cgi/templates/redirect.html
@@ -0,0 +1,12 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Has posteado en Bienvenido a Internet BBS/IB</title>
+<meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8" />
+<meta http-equiv="refresh" content="0;url=#{url}" />
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+</head>
+<body style="text-align:center;">
+<h1>Gracias por tu post</h1><h3>${message}</h3><em>(por favor espera)</em>
+<?py if timetaken: ?><p style="font-size:small">Tiempo usado: #{timetaken}</p><?py #endif ?>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/report.html b/cgi/templates/report.html
new file mode 100644
index 0000000..d37ca6d
--- /dev/null
+++ b/cgi/templates/report.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<?py if finished: ?><title>Post denunciado</title>
+<?py else: ?><title>Denunciar post ${postshow}</title>
+<?py #endif ?>
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<style>*{box-sizing:border-box} body{max-width:350px;margin:0 auto;text-align:justify} h1{text-align:left} a{color:#06C} a:active{color:#F30}
+input{border:1px solid #BBB;width:100%} .long{display:block}</style>
+</head>
+<body>
+<?py if finished: ?>
+<hr /><h1>Post denunciado.</h1>
+<hr /><a href="javascript:void(0)" onclick="history.go(-2);return(false);" class="long">Volver</a><hr />
+<?py else: ?>
+<hr /><h1>Formulario de denuncia</h1>
+<hr />Para pedir que el post <b>${postshow}</b> sea eliminado, indica una razón y presiona el botón [Enviar denuncia].
+<hr /><a href="javascript:void(0)" onclick="history.go(-1);return(false);" class="long">Volver</a>
+<hr /><form method="post" action=""><input type="text" name="reason" placeholder="Razón" maxlength="100" style="margin-bottom:0.5em;" /><input type="submit" value="Enviar denuncia" /></form>
+<hr />Este formulario no es para eliminar tu propio post.
+<?py if txt: ?>Para eliminar tu propio post debes presionar el botón <u>del</u> que aparece a la derecha de tu post cuando le pones el cursor encima. [<a href="/faq.html#del">info</a>]
+<?py else: ?>Para eliminar tu propio post debes chequear la caja que se encuentra en la parte superior izquierda de tu post y luego presionar el botón "Eliminar" que se encuentra al final de la página. [<a href="/faq.html#del">info</a>]<?py #endif ?>
+<hr />Normalmente eliminamos los mensajes que son considerados spam o flood. Si deseas pedir la prohibición de acceso a algún usuario persistente, te recomendamos hacerlo en la sección <a href="/bai/">meta</a>.
+<hr /><a href="mailto:burocracia@bienvenidoainternet.org" class="long">Contacto</a><hr />
+<?py #endif ?>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/revision.html b/cgi/templates/revision.html
new file mode 100644
index 0000000..1e9b46b
--- /dev/null
+++ b/cgi/templates/revision.html
@@ -0,0 +1 @@
+0.8.7
diff --git a/cgi/templates/stats.html b/cgi/templates/stats.html
new file mode 100644
index 0000000..dd0e5ab
--- /dev/null
+++ b/cgi/templates/stats.html
@@ -0,0 +1,163 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Estadísticas@Bienvenido a Internet</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+<style>
+body{font-family:arial,sans-serif;background:#090909;color:#fdfdfd;margin:0;text-align:center}
+a,a:visited{color:#fdfdfd;text-decoration:none}
+a:hover{text-decoration:underline}
+hr{margin:1em 0}
+span{display:inline-block}
+#title{margin-top:1em}
+#title a{text-decoration:none}
+.t1{font-size:1.8em;display:inline-block;line-height:1em}
+.t2{font-size:1em;margin-top:2px}
+h2{font-size:1.5em;margin:0 0 .2em 0}
+table{font-size:1.4em;margin:0 auto 1em}
+th,td{padding:10px;border-top:1px solid #222;border-left:1px solid #222}
+.boards{padding:0}
+td a{display:block;padding:10px}
+.desc tr{text-align:right}
+.desc td{text-align:left}
+.r{text-align:right}
+.l{text-align:left}
+.pos{line-height:0em;text-align:center}
+.uno{font-size:2em;color:red}
+.dos{font-size:1.6em;color:orange}
+.tres{font-size:1.3em;color:yellow}
+.etc{color:grey}
+#foot{margin:1em;font-size:.9em}
+#foot a{color:#999}
+@media (max-width:600px){
+.t1{font-size:1.6em}
+.t2{font-size:.9em}
+h2{font-size:1.2em}
+table{font-size:1.1em}
+table.desc{font-size:.9em}
+th,td{padding:5px}
+td a{display:block;padding:5px}
+.uno{font-size:1.6em}
+.dos{font-size:1.4em}
+.tres{font-size:1.2em}
+#boards th{font-size:.8em}
+.long{word-break:break-all}
+#foot{font-size:12px}
+}
+</style>
+</head>
+<body>
+<div id="title">
+ <div class="t1"><a href="/" style="font-weight:900">Bienvenido a Internet</a> Estadísticas</div>
+ <div class="t2">
+ <span>Última actualización:</span> <span>${timestamp} GMT${tz}</span>
+ <?py if not regenerated: ?>
+ <span>(en caché)</span>
+ <?py #endif ?>
+ </div>
+</div>
+
+<hr />
+
+<h2 class="rot">Mensajes totales <span>(última semana)</span></h2>
+ <table>
+ <tr>
+ <th>D&iacute;a</th>
+ <th class="r">Hilos</th>
+ <th class="r">Resp.</th>
+ <th class="r">Total</th>
+ </tr>
+ <?py allthreads, allposts = 0, 0 ?>
+ <?py for day, posts, threads in reversed(days): ?>
+ <tr>
+ <td>${day}</td>
+ <td class="r">${threads}</td>
+ <td class="r">${int(posts)-int(threads)}</td>
+ <td class="r">${posts}</td>
+ </tr>
+ <?py allthreads += int(threads) ?>
+ <?py allposts += int(posts) ?>
+ <?py #endfor ?>
+ <tr style="font-weight:bold;">
+ <td class="l">Total</td>
+ <td class="r">${allthreads}</td>
+ <td class="r">${allposts-allthreads}</td>
+ <td class="r">${allposts}</td>
+ </tr>
+ </table>
+
+<hr />
+
+<h2 class="rot">Volumen de mensajes por sección <span>(últimos 30 días)</span></h2>
+ <table id="boards">
+ <tr>
+ <th class="pos">#</th>
+ <th class="l">Sección</th>
+ <th>Mensajes</th>
+ <th>Porcentaje</th>
+ </tr>
+ <?py iter = 1 ?>
+ <?py for dir, board, percent, num in boards_percent: ?>
+ <tr>
+ <td class="pos">
+ <?py if iter == 1: ?><span class="uno">${iter}</span>
+ <?py elif iter == 2: ?><span class="dos">${iter}</span>
+ <?py elif iter == 3: ?><span class="tres">${iter}</span>
+ <?py else: ?>${iter}<?py #endif ?>
+ </td>
+ <td class="l boards"><a href="/${dir}/" target="_blank">${board}</a></td>
+ <td class="r">${num}</td>
+ <td class="r">${percent}%</td>
+ </tr>
+ <?py iter += 1 ?>
+ <?py #endfor ?>
+ </table>
+
+<hr />
+
+<h2>Sistema</h2>
+ <table class="desc">
+ <tr><th>Máquina</th>
+ <td>maria (Debian GNU/Linux)</td></tr>
+ <tr><th>OS</th>
+ <td class="long">${uname[0]} ${uname[2]}</td></tr>
+ <tr><th>Release/Arq.</th>
+ <td>${uname[3]} ${uname[4]}</td></tr>
+ <tr><th>Motor BBS/IB</th>
+ <td>weabot ${weabot_ver}</td></tr>
+ <tr><th>Templating</th>
+ <td>tenjin ${tenjin_ver}</td></tr>
+ <tr><th>Versión de Python</th>
+ <td>${python_ver}</td></tr>
+ <tr><th>Implementación</th>
+ <td>${python_impl}</td></tr>
+ <tr><th>Build</th>
+ <td>${python_build}</td></tr>
+ <tr><th>Compilado en</th>
+ <td>${python_compiler}</td></tr>
+ </table>
+
+<hr />
+
+<h2>Base de datos</h2>
+ <table class="desc">
+ <tr><th>Base de Datos</th>
+ <td>MariaDB</td></tr>
+ <tr><th>Versión</th>
+ <td>${mysql_ver} Linux x86_64</td></tr>
+ <tr><th>Mensajes totales activos</th>
+ <td>${total}</td></tr>
+ <tr><th>Archivos totales activos</th>
+ <td>${total_files}</td></tr>
+ <tr><th>Mensajes totales archivados (BBS)</th>
+ <td>${total_archived}</td></tr>
+ <tr><th>Mensajes totales archivados (IB)</th>
+ <td>0 (QEPD)</td></tr>
+ </table>
+
+<hr />
+
+<div id="foot">B.a.I. - 2010-2019 · Contacto: <a href="mailto:burocracia@bienvenidoainternet.org">burocracia@bienvenidoainternet.org</a></div>
+</body>
+</html>
diff --git a/cgi/templates/txt_archive.html b/cgi/templates/txt_archive.html
new file mode 100644
index 0000000..b1e25db
--- /dev/null
+++ b/cgi/templates/txt_archive.html
@@ -0,0 +1,104 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>#{threads[0]['subject']} - Archivo de #{board_name}@Bienvenido a Internet BBS</title>
+ <meta http-equiv="Content-Type" content="application/xhtml+xml;charset=utf-8" />
+<?py if threads: ?>
+ <meta property="og:site_name" content="Bienvenido a Internet BBS" />
+ <meta property="twitter:site" content="Bienvenido a Internet BBS" />
+ <meta name="description" content="${preview}" />
+ <meta property="og:title" content="${threads[0]['subject']} - ${board_name}" />
+ <meta property="og:description" content="${preview}" />
+ <meta property="twitter:title" content="${threads[0]['subject']} - ${board_name}" />
+ <meta name="twitter:description" content="${preview}" />
+<?py #endif ?>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <link rel="shortcut icon" href="#{static_url}img/favicon.ico" />
+ <link rel="stylesheet" href="/static/css/txt/bbs.css" />
+<?py if not force_css: ?>
+ <link rel="stylesheet" id="css" href="#{static_url}css/txt/#{txt_styles[txt_styles_default].lower()}.css" />
+<?py else: ?>
+ <link rel="stylesheet" type="text/css" href="#{force_css}" />
+<?py #endif ?>
+<?py if board in ['zonavip', 'world']: ?>
+ <link rel="stylesheet" href="/static/css/txt/sjis.css" />
+<?py #endif ?>
+ <script type="text/javascript" src="#{static_url}js/weabotxt.js"></script>
+ <script type="text/javascript" src="#{static_url}js/aquiencitas.js"></script>
+</head>
+<body class="threadpage archived" data-brd="#{board}">
+<?py if threads: ?>
+<?py for thread in threads: ?>
+<div id="thread_nav">
+ <a href="/" name="top" target="_top">Bienvenido a Internet</a>
+ <a href="#{boards_url}#{board}/">■Volver al BBS■</a>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/">Hilo completo</a>
+ <?py if thread['length'] > 100: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/-100">1-</a>
+ <?py #endif ?>
+ <?py for i in range(thread['length'] / 100): ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/#{(i+1)*100+1}-#{(i+2)*100}">#{(i+1)*100+1}-</a>
+ <?py #endfor ?>
+ <?py if thread['length'] > 51: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/l50">Últimos 50</a>
+ <?py #endif ?>
+ <a href="#bottom">&#9660;Bajar&#9660;</a>
+</div>
+<hr /><div class="stop red">■ Este hilo se encuentra guardado en el archivo</div><hr />
+<div class="thread" data-length="#{thread['length']}">
+ <h3>#{thread['subject']} <span>(${(str(thread['length'])+" respuestas") if thread['length'] > 1 else "Una respuesta"})</span></h3>
+ <?py for post in thread['posts']: ?>
+ <?py if post['IS_DELETED'] == '1': ?>
+ <h4 class="deleted">#{post['num']} : Mensaje eliminado por el usuario.</h4>
+ <?py elif post['IS_DELETED'] == '2': ?>
+ <h4 class="deleted">#{post['num']} : Mensaje eliminado por miembro del staff.</h4>
+ <?py else: ?>
+ <?py if post['num'] == 1: ?>
+ <div class="reply first" data-n="#{post['num']}">
+ <?py else: ?>
+ <div class="reply" data-n="#{post['num']}">
+ <?py #endif ?>
+ <h4>#{post['num']} :
+ <?py if post['email']: ?>
+ <?py if post['tripcode']: ?>
+ <a href="mailto:#{post['email']}"><span class="name"><b>#{post['name']}</b> #{post['tripcode']}</span></a>
+ <?py else: ?>
+ <a href="mailto:#{post['email']}"><span class="name"><b>#{post['name']}</b></span></a>
+ <?py #endif ?>
+ <?py else: ?>
+ <?py if post['tripcode']: ?>
+ <span class="name"><b>#{post['name']}</b> #{post['tripcode']}</span>
+ <?py else: ?>
+ <span class="name"><b>#{post['name']}</b></span>
+ <?py #endif ?>
+ <?py #endif ?> : <span class="date">#{post['timestamp_formatted']}</span></h4>
+ <div class="msg">#{post['message']}</div>
+ </div>
+ <?py #endif ?>
+ <?py #endfor ?>
+ <?py if 'size' in thread: ?>
+ <div class="size">#{thread['size']}</div>
+ <?py #endif ?>
+</div>
+<hr /><div class="stop red">■ Este hilo se encuentra guardado en el archivo</div><hr />
+<form class="threadlinks">
+ <a href="#{boards_url}#{board}/">■Volver al BBS■</a>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/">Hilo completo</a>
+ <?py if prevrange: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/#{prevrange}">Anteriores 100</a>
+ <?py #endif ?>
+ <?py if nextrange: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/#{nextrange}">Próximos 100</a>
+ <?py #endif ?>
+ <?py if thread['length'] > 51: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/l50">Últimos 50</a>
+ <?py #endif ?>
+ <a href="#top">&#9650;Subir&#9650;</a>
+</form>
+<?py #endfor ?>
+<?py #endif ?>
+<div class="end">weabot.py ver <?py include('templates/revision.html') ?> Bienvenido a Internet BBS/IB</div>
+<a name="bottom"></a>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/txt_base_top.html b/cgi/templates/txt_base_top.html
new file mode 100644
index 0000000..eb3c37b
--- /dev/null
+++ b/cgi/templates/txt_base_top.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<?py if replythread and threads: ?>
+ <title>#{threads[0]['subject']} - #{board_name}@Bienvenido a Internet BBS</title>
+<?py elif board: ?>
+ <title>#{board_long}</title>
+<?py else: ?>
+ <title>#{title}</title>
+<?py #endif ?>
+ <meta http-equiv="Content-Type" content="application/xhtml+xml;charset=utf-8" />
+<?py if replythread and threads: ?>
+ <meta property="og:site_name" content="Bienvenido a Internet BBS" />
+ <meta property="twitter:site" content="Bienvenido a Internet BBS" />
+ <meta name="description" content="${preview}" />
+ <meta property="og:title" content="${threads[0]['subject']} - ${board_name}" />
+ <meta property="og:description" content="${preview}" />
+ <meta property="twitter:title" content="${threads[0]['subject']} - ${board_name}" />
+ <meta name="twitter:description" content="${preview}" />
+<?py #endif ?>
+ <meta name="robots" content="#{"noindex" if noindex else "index, follow"}" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <link rel="shortcut icon" href="/favicon.ico" />
+ <link rel="stylesheet" href="/static/css/txt/bbs.css" />
+<?py if not force_css: ?>
+ <link rel="stylesheet" id="css" href="#{static_url}css/txt/#{txt_styles[txt_styles_default].lower()}.css" />
+<?py else: ?>
+ <link rel="stylesheet" type="text/css" href="#{force_css}" />
+<?py #endif ?>
+<?py if board in ['zonavip', 'world']: ?>
+ <link rel="stylesheet" href="/static/css/txt/sjis.css" />
+<?py #endif ?>
+<?py if board == 'polka': ?>
+ <script type="text/javascript" src="#{static_url}js/weabotxt.test.js"></script>
+<?py else: ?>
+ <script type="text/javascript" src="#{static_url}js/weabotxt.js"></script>
+<?py #endif ?>
+ <script type="text/javascript" src="#{static_url}js/aquiencitas.js"></script>
+ <script type="text/javascript" src="#{static_url}js/shobon.js"></script>
+<?py if replythread and board != 'polka': ?>
+ <script type="text/javascript" src="#{static_url}js/autorefresh.js"></script>
+<?py #endif ?>
+</head>
diff --git a/cgi/templates/txt_board.en.html b/cgi/templates/txt_board.en.html
new file mode 100644
index 0000000..8e3c421
--- /dev/null
+++ b/cgi/templates/txt_board.en.html
@@ -0,0 +1,137 @@
+<?py include('templates/txt_base_top.html') ?>
+<body class="mainpage" data-brd="#{board}">
+<div id="main_nav"><a href="/" target="_top">Bienvenido a Internet</a> | <?py include('templates/navbar.html') ?></div>
+<?py if banner_url: ?>
+ <img class="banner" src="#{banner_url}" style="width:#{banner_width}px;height:#{banner_height}px;" />
+<?py #endif ?>
+<div id="titlebox" class="outerbox">
+ <div class="innerbox">
+ <div class="threadnav"><a href="#menu" title="Thread list">&#9632;</a><a href="#1" title="Next thread">&#9660;</a></div>
+ <h1>#{board_long}</h1>
+ <?py if postarea_desc: ?>
+ <div id="rules">#{postarea_desc}</div>
+ <?py #endif ?>
+ <form method="get" action="/tools/search.py" id="search"><input type="text" name="q" value="" /><input type="hidden" name="board" value="#{board}" /><input type="submit" value="Search active posts" /><input type="submit" value="Search archives" formaction="/tools/search_kako.py" /></form>
+ </div>
+ <div class="innerbox links"><a href="/guia.html"><b>C&oacute;mo postear</b></a> | <a href="/faq.html"><b>Preguntas frecuentes</b></a> | <a href="/bai/"><b>Contacto</b></a>
+ <?py if not force_css: ?>| <b>Styles:</b>
+ <?py for title in txt_styles: ?><a href="#" class="ss">#{title}</a> <?py #endfor ?>
+ <?py #endif ?></div>
+</div>
+<?py if postarea_extra: ?>
+<div class="outerbox"><div class="innerbox">#{postarea_extra}</div></div>
+<?py #endif ?>
+<a name="menu"></a>
+<?py if threads: ?>
+<div id="threadbox" class="outerbox"><div class="innerbox">
+ <div id="threadlinks"><a href="#{cgi_url}threadlist/#{board}"><b>View all threads</b></a> <a href="kako/"><b>View archive</b></a> <a href="#newthread"><b>Create new thread</b></a></div>
+ <div id="threadlist">
+ <?py iter = 1 ?>
+ <?py for thread in threads: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/#{'l50' if thread['length'] > 50 else ''}">#{iter}: </a><a href="##{iter}"> <b>#{thread['posts'][0]['subject']}</b> (#{thread['length']})</a><br />
+ <?py iter += 1 ?>
+ <?py #endfor ?>
+ <?py for thread in more_threads: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/#{'l50' if thread['length'] > 50 else ''}">#{iter}: <b>#{thread["subject"]}</b> (#{thread["length"]})</a><br />
+ <?py iter += 1 ?>
+ <?py #endfor ?>
+ </div>
+</div></div>
+<?py titer = 1 ?>
+<?py for thread in threads: ?>
+<a name="#{titer}"></a>
+<div class="thread"><div class="innerbox">
+<div class="threadnav"><a href="#menu" title="Thread list">&#9632;</a><a href="##{(titer-1) if titer>1 else len(threads)}" title="Previous thread">&#9650;</a><a href="##{(titer+1) if titer<len(threads) else '1'}" title="Next thread">&#9660;</a></div>
+<h2><small>[#{titer}:#{thread['length']}]</small><a href="#{boards_url}#{board}/read/#{thread['timestamp']}/#{'l50' if thread['length'] > 50 else ''}">#{thread['posts'][0]['subject']}</a></h2>
+<?py for post in thread['posts']: ?>
+<?py if post['IS_DELETED'] == '1': ?>
+ <h4 class="deleted">#{post['num']} : Post deleted by user.</h4>
+<?py elif post['IS_DELETED'] == '2': ?>
+ <h4 class="deleted">#{post['num']} : Post deleted by staff.</h4>
+<?py else: ?>
+ <div class="reply#{' first' if post['num'] == 1 else ''}" data-n="#{post['num']}">
+ <h4>#{post['num']} :
+ <?py if post['email']: ?>
+ <?py if post['tripcode']: ?>
+ <a href="mailto:#{post['email']}"><span class="name"><b>#{post['name']}</b> #{post['tripcode']}</span></a>
+ <?py else: ?>
+ <a href="mailto:#{post['email']}"><span class="name"><b>#{post['name']}</b></span></a>
+ <?py #endif ?>
+ <?py else: ?>
+ <?py if post['tripcode']: ?>
+ <span class="name"><b>#{post['name']}</b> #{post['tripcode']}</span>
+ <?py else: ?>
+ <span class="name"><b>#{post['name']}</b></span>
+ <?py #endif ?>
+ <?py #endif ?> : <span class="date" data-unix="#{post['timestamp']}">#{post['timestamp_formatted']}</span></h4>
+ <?py if post['file']: ?>
+ <a href="#{images_url}#{board}/src/#{post['file']}" target="_blank" class="thumb"><img src="#{images_url}#{board}/thumb/#{post['thumb']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" /><div>${int(post['file_size'])//1024}KB ${post['file'].split(".")[1].upper()}</div></a>
+ <?py #endif ?>
+ <div class="msg">
+ #{post['message']}
+ <?py if post['shortened']: ?>
+ <div class="abbrev">(Post is too long... Click <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/#{post['num']}">here</a> to view the whole post.)</div>
+ <?py #endif ?>
+ </div>
+</div>
+<?py #endif ?>
+<?py #endfor ?>
+<?py if thread['locked'] != '1': ?>
+<form id="postform#{thread['id']}" class="postform" action="#{cgi_url}post" method="post" enctype="multipart/form-data">
+ <input type="hidden" name="board" value="#{board}" /><input type="hidden" name="parent" value="#{thread['id']}" /><input type="hidden" name="password" value="" />
+ <div style="display:none"><input type="text" name="name" size="15" /> <input type="text" name="email" size="15" /></div>
+ <span><input type="submit" value="Reply" /></span> <span><span>Name:&nbsp;</span><input type="text" name="fielda" size="15" /><span>&nbsp;E-mail:&nbsp;</span><input type="text" name="fieldb" size="15" /></span><br />
+ <div class="formpad">
+ <textarea name="message" cols="70" rows="5"></textarea>
+ <?py if allow_image_replies: ?><br /><input type="file" name="file" /><?py #endif ?>
+<?py else: ?>
+<form class="postform"><div class="locked">This thread has been closed. You cannot post in it any longer.</div><div class="formpad">
+<?py #endif ?>
+ <div class="threadlinks">
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/"><b>Entire thread</b></a>
+ <?py if thread['length'] > 51: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/l50"><b>Last 50</b></a>
+ <?py #endif ?>
+ <?py if thread['length'] > 101: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/-100"><b>First 100</b></a>
+ <?py #endif ?>
+ <a href="#menu"><b>Thread list</b></a>
+ <a href="#newthread"><b>New thread</b></a>
+ </div>
+</div></form>
+</div></div>
+<?py titer += 1 ?>
+<?py #endfor ?>
+<?py #endif ?>
+<a name="newthread"></a>
+<div id="createbox" class="outerbox">
+ <div class="extrabox"></div>
+ <div class="innerbox">
+ <div class="threadnav"><a href="#menu" title="Thread list">&#9632;</a></div>
+ <h5>New thread form</h5>
+ <form id="postform0" action="#{cgi_url}post" method="post" enctype="multipart/form-data">
+ <input type="hidden" name="board" value="#{board}" /><input type="hidden" name="password" value="" />
+ <table style="max-width:600px">
+ <tr>
+ <td class="pblock">Subject:</td>
+ <td colspan="3" style="width:100%"><input type="text" name="subject" size="50" maxlength="100" /></td>
+ <td><input type="submit" value="Create new thread" /></td>
+ </tr>
+ <tr>
+ <td class="pblock">Name:</td><td><input type="text" name="fielda" /></td>
+ <td class="pblock">E-mail:</td><td><input type="text" name="fieldb" /></td>
+ <td><input type="button" name="preview" value="Preview" /></td>
+ </tr>
+ <tr id="options" style="display:none"><td></td><td colspan="4"><div id="preview0" class="msg"></div></td></tr>
+ <tr><td class="pblock">Body:</td><td colspan="4"><textarea name="message" cols="70" rows="10"></textarea></td></tr>
+ <?py if allow_images: ?>
+ <tr><td class="pblock">File:</td><td colspan="4"><input type="file" name="file" /></td></tr>
+ <?py #endif ?>
+ </table>
+ <div style="display:none">Trampa: <input type="text" name="name" maxlength="50" /> <input type="text" name="email" maxlength="50" /></div>
+ </form>
+ </div>
+</div>
+<center id="footer"><a href="/" target="_top">Bienvenido a Internet BBS/IB</a> weabot.py <?py include('templates/revision.html') ?> + FastCGI + tenjin<br />それがBaIクオリティー!</center>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/txt_board.html b/cgi/templates/txt_board.html
new file mode 100644
index 0000000..097e255
--- /dev/null
+++ b/cgi/templates/txt_board.html
@@ -0,0 +1,137 @@
+<?py include('templates/txt_base_top.html') ?>
+<body class="mainpage" data-brd="#{board}">
+<div id="main_nav"><a href="/" target="_top">Bienvenido a Internet</a> | <?py include('templates/navbar.html') ?></div>
+<?py if banner_url: ?>
+ <img class="banner" src="#{banner_url}" style="width:#{banner_width}px;height:#{banner_height}px;" />
+<?py #endif ?>
+<div id="titlebox" class="outerbox">
+ <div class="innerbox">
+ <div class="threadnav"><a href="#menu" title="Ir a lista de hilos">&#9632;</a><a href="#1" title="Ir a primer hilo">&#9660;</a></div>
+ <h1>#{board_long}</h1>
+ <?py if postarea_desc: ?>
+ <div id="rules">#{postarea_desc}</div>
+ <?py #endif ?>
+ <form method="get" action="/tools/search.py" id="search"><input type="text" name="q" value="" /><input type="hidden" name="board" value="#{board}" /><input type="submit" value="Buscar en mensajes activos" /><input type="submit" value="Buscar en archivo" formaction="/tools/search_kako.py" /></form>
+ </div>
+ <div class="innerbox links"><b>¿Eres nuevo?</b> <a href="/guia.html"><b>C&oacute;mo postear</b></a> | <a href="/faq.html"><b>Preguntas frecuentes</b></a> | <a href="/bai/"><b>Contacto</b></a>
+ <?py if not force_css: ?>| <b>Estilo:</b>
+ <?py for title in txt_styles: ?><a href="#" class="ss">#{title}</a> <?py #endfor ?>
+ <?py #endif ?></div>
+</div>
+<?py if postarea_extra: ?>
+<div class="outerbox"><div class="innerbox">#{postarea_extra}</div></div>
+<?py #endif ?>
+<a name="menu"></a>
+<?py if threads: ?>
+<div id="threadbox" class="outerbox"><div class="innerbox">
+ <div id="threadlinks"><a href="#{cgi_url}threadlist/#{board}"><b>Ver todos los hilos</b></a> <a href="kako/"><b>Ver hilos archivados</b></a> <a href="#newthread"><b>Crear nuevo hilo</b></a></div>
+ <div id="threadlist">
+ <?py iter = 1 ?>
+ <?py for thread in threads: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/#{'l50' if thread['length'] > 50 else ''}">#{iter}: </a><a href="##{iter}"> <b>#{thread['posts'][0]['subject']}</b> (#{thread['length']})</a><br />
+ <?py iter += 1 ?>
+ <?py #endfor ?>
+ <?py for thread in more_threads: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/#{'l50' if thread['length'] > 50 else ''}">#{iter}: <b>#{thread["subject"]}</b> (#{thread["length"]})</a><br />
+ <?py iter += 1 ?>
+ <?py #endfor ?>
+ </div>
+</div></div>
+<?py titer = 1 ?>
+<?py for thread in threads: ?>
+<a name="#{titer}"></a>
+<div class="thread"><div class="innerbox">
+<div class="threadnav"><a href="#menu" title="Lista de hilos">&#9632;</a><a href="##{(titer-1) if titer>1 else len(threads)}" title="Hilo anterior">&#9650;</a><a href="##{(titer+1) if titer<len(threads) else '1'}" title="Hilo siguiente">&#9660;</a></div>
+<h2><span>[#{titer}:#{thread['length']}]</span><a href="#{boards_url}#{board}/read/#{thread['timestamp']}/#{'l50' if thread['length'] > 50 else ''}">#{thread['posts'][0]['subject']}</a></h2>
+<?py for post in thread['posts']: ?>
+<?py if post['IS_DELETED'] == '1': ?>
+ <h4 class="deleted">#{post['num']} Mensaje eliminado por el usuario.</h4>
+<?py elif post['IS_DELETED'] == '2': ?>
+ <h4 class="deleted">#{post['num']} Mensaje eliminado por miembro del staff.</h4>
+<?py else: ?>
+ <div class="reply#{' first' if post['num'] == 1 else ''}" data-n="#{post['num']}">
+ <h4>#{post['num']} :
+ <?py if post['email']: ?>
+ <?py if post['tripcode']: ?>
+ <a href="mailto:#{post['email']}"><span class="name"><b>#{post['name']}</b> #{post['tripcode']}</span></a>
+ <?py else: ?>
+ <a href="mailto:#{post['email']}"><span class="name"><b>#{post['name']}</b></span></a>
+ <?py #endif ?>
+ <?py else: ?>
+ <?py if post['tripcode']: ?>
+ <span class="name"><b>#{post['name']}</b> #{post['tripcode']}</span>
+ <?py else: ?>
+ <span class="name"><b>#{post['name']}</b></span>
+ <?py #endif ?>
+ <?py #endif ?> : <span class="date" data-unix="#{post['timestamp']}">#{post['timestamp_formatted']}</span></h4>
+ <?py if post['file']: ?>
+ <a href="/#{board}/src/#{post['file']}" target="_blank" class="thumb"><img src="#{'/static/' if post['thumb'].startswith('mime') else ('/'+board+'/thumb/')}#{post['thumb']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" /><div>${int(post['file_size'])//1024}KB ${post['file'].split(".")[1].upper()}</div></a>
+ <?py #endif ?>
+ <div class="msg">
+ #{post['message']}
+ <?py if post['shortened']: ?>
+ <div class="abbrev">(Post muy largo... Presiona <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/#{post['num']}">aquí</a> para verlo completo.)</div>
+ <?py #endif ?>
+ </div>
+</div>
+<?py #endif ?>
+<?py #endfor ?>
+<?py if thread['locked'] != '1': ?>
+<form id="postform#{thread['id']}" class="postform" action="#{cgi_url}post" method="post" enctype="multipart/form-data">
+ <input type="hidden" name="board" value="#{board}" /><input type="hidden" name="parent" value="#{thread['id']}" /><input type="hidden" name="password" value="" />
+ <div style="display:none"><input type="text" name="name" size="15" /> <input type="text" name="email" size="15" /></div>
+ <span><input type="submit" value="Responder" /></span> <span><span>Nombre:&nbsp;</span><input type="text" name="fielda" size="15" /><span>&nbsp;E-mail:&nbsp;</span><input type="text" name="fieldb" size="15" /></span>
+ <div class="formpad">
+ <textarea name="message" cols="70" rows="5"></textarea>
+ <?py if allow_image_replies: ?><br /><input type="file" name="file" /><?py #endif ?>
+<?py else: ?>
+<form class="postform"><div class="locked">El hilo ha sido cerrado. Ya no se puede postear en él.</div><div class="formpad">
+<?py #endif ?>
+ <div class="threadlinks">
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/"><b>Hilo completo</b></a>
+ <?py if thread['length'] > 51: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/l50"><b>&Uacute;ltimos 50</b></a>
+ <?py #endif ?>
+ <?py if thread['length'] > 101: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/-100"><b>Primeros 100</b></a>
+ <?py #endif ?>
+ <a href="#menu"><b>Lista de hilos</b></a>
+ <a href="#newthread"><b>Nuevo hilo</b></a>
+ </div>
+</div></form>
+</div></div>
+<?py titer += 1 ?>
+<?py #endfor ?>
+<?py #endif ?>
+<a name="newthread"></a>
+<div id="createbox" class="outerbox">
+ <div class="extrabox"></div>
+ <div class="innerbox">
+ <div class="threadnav"><a href="#menu" title="Lista de hilos">&#9632;</a></div>
+ <h5>Formulario de nuevo hilo</h5>
+ <form id="postform0" action="#{cgi_url}post" method="post" enctype="multipart/form-data">
+ <input type="hidden" name="board" value="#{board}" /><input type="hidden" name="password" value="" />
+ <table style="max-width:600px">
+ <tr>
+ <td class="pblock">Asunto:</td>
+ <td colspan="3" style="width:100%"><input type="text" name="subject" size="50" maxlength="100" /></td>
+ <td><input type="submit" value="Crear nuevo hilo" /></td>
+ </tr>
+ <tr>
+ <td class="pblock">Nombre:</td><td><input type="text" name="fielda" /></td>
+ <td class="pblock">E-mail:</td><td><input type="text" name="fieldb" /></td>
+ <td><input type="button" name="preview" value="Previsualizar" /></td>
+ </tr>
+ <tr id="options" style="display:none"><td></td><td colspan="4"><div id="preview0" class="msg"></div></td></tr>
+ <tr><td class="pblock">Mensaje:</td><td colspan="4"><textarea name="message" cols="70" rows="10"></textarea></td></tr>
+ <?py if allow_images: ?>
+ <tr><td class="pblock">Archivo:</td><td colspan="4"><input type="file" name="file" /></td></tr>
+ <?py #endif ?>
+ </table>
+ <div style="display:none">Trampa: <input type="text" name="name" maxlength="50" /> <input type="text" name="email" maxlength="50" /></div>
+ </form>
+ </div>
+</div>
+<center id="footer"><a href="/" target="_top">Bienvenido a Internet BBS/IB</a> weabot.py <?py include('templates/revision.html') ?> + FastCGI + tenjin<br />No se ponga sensible, baisano...</center>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/txt_error.html b/cgi/templates/txt_error.html
new file mode 100644
index 0000000..8a16a63
--- /dev/null
+++ b/cgi/templates/txt_error.html
@@ -0,0 +1,50 @@
+<html>
+<head>
+<title>Error</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0" />
+<style type="text/css">
+* {word-wrap:break-word;}
+body {margin:8px;}
+.h {font-weight:bold; font-size:large;}
+.err {color:red;}
+.sub1 {color:#00AA00;} .sub2 {color:#DD00DD;}
+blockquote {margin-left:40px; margin-right:40px;}
+ul {padding-left:40px;}
+@media(max-width:650px){
+ blockquote {margin-left:20px; margin-right:20px;}
+ ul {padding-left:20px;}
+}
+</style>
+</head>
+<body>
+<div class="h err">ERROR: #{error}</div>
+<blockquote>
+ Host <b>${info['host']}</b><br>
+ <blockquote>
+ Nombre: <b>${info['name']}</b><br>
+ E-mail: ${info['email']}<br>
+ Mensaje: <br>
+ ${info['message']}
+ </blockquote>
+</blockquote>
+<hr>
+<ul>
+ <div class="h sub1">¿No sabes qué sucede?</div>
+ <ul style="line-height:1.5;">
+ ¡Revisemos!<br>
+ <b>
+ [<a href="/guia.html">¿Eres nuevo?</a>]<br />
+ [<a href="/faq.html">Preguntas frecuentes</a>]<br />
+ [<a href="#{boards_url}#{board}">Ir a la sección</a>]<br />
+ [<a href="#{cgi_url}threadlist/#{board}">Ir a la lista de hilos</a>]<br />
+ </b>
+ </ul><br>
+ <div class="h sub2">Contacto</div>
+ <ul style="line-height:1.5;">
+ Cualquier problema con el sitio por favor hacerlo llegar al staff de BaI.<br />
+ Para ello contáctanos en la <a href="/bai/">sección de discusión</a>.
+ </ul>
+</ul>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/txt_thread.en.html b/cgi/templates/txt_thread.en.html
new file mode 100644
index 0000000..2e811cb
--- /dev/null
+++ b/cgi/templates/txt_thread.en.html
@@ -0,0 +1,105 @@
+<?py include('templates/txt_base_top.html') ?>
+<body class="threadpage" data-brd="#{board}">
+<?py if threads: ?>
+<?py for thread in threads: ?>
+<div id="thread_nav">
+ <a href="/" name="top" target="_top">Bienvenido a Internet</a>
+ <a href="#{boards_url}#{board}/">■Return to BBS■</a>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/">Entire thread</a>
+ <?py if thread['length'] > 100: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/-100">First 100</a>
+ <?py #endif ?>
+ <?py if thread['length'] > 51: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/l50">Last 50</a>
+ <?py #endif ?>
+ <a href="#bottom">&#9660;Bottom&#9660;</a>
+</div>
+<hr />
+<?py if thread['length'] > 1000: ?>
+ <div class="stop red">The thread got over 1000 posts and has been closed.</div>
+<?py elif thread['length'] > 900: ?>
+ <div class="warn yellow">The thread has reached 900 posts. When it reaches 1000 posts it will be closed.</div>
+<?py #endif ?>
+<div class="thread" data-length="#{thread['length']}">
+ <h3>#{thread['subject']} <span>(${(str(thread['length'])+" replies") if thread['length']>1 else "1 reply"})</span></h3>
+ <?py for post in thread['posts']: ?>
+ <?py if post['IS_DELETED'] == '1': ?>
+ <h4 class="deleted">#{post['num']} : Post deleted by user.</h4>
+ <?py elif post['IS_DELETED'] == '2': ?>
+ <h4 class="deleted">#{post['num']} : Post deleted by staff.</h4>
+ <?py else: ?>
+ <?py if post['num'] == 1: ?>
+ <div class="reply first" data-n="#{post['num']}">
+ <?py else: ?>
+ <div class="reply" data-n="#{post['num']}">
+ <?py #endif ?>
+ <h4><a href="#" class="num">#{post['num']}</a> :
+ <?py if post['email']: ?>
+ <?py if post['tripcode']: ?>
+ <a href="mailto:#{post['email']}"><span class="name"><b>#{post['name']}</b> #{post['tripcode']}</span></a>
+ <?py else: ?>
+ <a href="mailto:#{post['email']}"><span class="name"><b>#{post['name']}</b></span></a>
+ <?py #endif ?>
+ <?py else: ?>
+ <?py if post['tripcode']: ?>
+ <span class="name"><b>#{post['name']}</b> #{post['tripcode']}</span>
+ <?py else: ?>
+ <span class="name"><b>#{post['name']}</b></span>
+ <?py #endif ?>
+ <?py #endif ?> : <span class="date" data-unix="#{post['timestamp']}">#{post['timestamp_formatted']}</span>
+ <span class="del"><a href="#{cgi_url}report/#{board}/#{post['id']}/#{post['num']}">rep</a> <a href="#">del</a></span></h4>
+ <?py if post['file']: ?>
+ <a href="#{images_url}#{board}/src/#{post['file']}" target="_blank" class="thumb"><img src="#{images_url}#{board}/thumb/#{post['thumb']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" /><div>${int(post['file_size'])//1024}KB ${post['file'].split(".")[1].upper()}</div></a>
+ <?py #endif ?>
+ <div class="msg">
+ #{post['message']}
+ </div>
+ </div>
+ <?py #endif ?>
+ <?py #endfor ?>
+ <div class="size">#{thread['size']}</div>
+</div>
+<hr />
+<?py if thread['locked'] != '1': ?>
+ <div class="lastposts"><a href="#{boards_url}#{board}/read/#{thread['timestamp']}/#{thread['length']}-n" id="n">Show new posts</a></div>
+ <hr />
+<?py #endif ?>
+<?py if thread['length'] > 1000: ?>
+ <div class="stop red">The thread got over 1000 posts and has been closed.</div>
+<?py elif thread['length'] > 950: ?>
+ <div class="warn red">The thread has reached 950 posts. When it reaches 1000 posts it will be closed.</div>
+<?py elif thread['length'] > 900: ?>
+ <div class="warn yellow">The thread has reached 900 posts. When it reaches 1000 posts it will be closed.</div>
+<?py #endif ?>
+<form id="postform#{thread['id']}" class="postform" name="postform" action="#{cgi_url}post" method="post" enctype="multipart/form-data">
+ <div class="threadlinks">
+ <a href="#{boards_url}#{board}">■Return to BBS■</a>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/">Entire thread</a>
+ <?py if prevrange: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/#{prevrange}">Previous 100</a>
+ <?py #endif ?>
+ <?py if nextrange: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/#{nextrange}">Next 100</a>
+ <?py #endif ?>
+ <?py if thread['length'] > 51: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/l50">Last 50</a>
+ <?py #endif ?>
+ <a href="#top">&#9650;Top&#9650;</a>
+ </div>
+ <input type="hidden" name="board" value="#{board}" /><input type="hidden" name="parent" value="#{thread['id']}" /><input type="hidden" name="password" value="" />
+ <?py if thread['locked'] != '1': ?>
+ <div style="display:none"><input type="text" name="name" size="13" /> <input type="text" name="email" size="13" /></div>
+ <span><input type="submit" value="Responder" accesskey="z" /> <input type="button" name="preview" value="Previsualizar" /></span> <span><span>Name:&nbsp;</span><input type="text" name="fielda" size="13" accesskey="n" /><span>&nbsp;E-mail:&nbsp;</span><input type="text" name="fieldb" size="13" accesskey="e" /></span><br />
+ <textarea name="message" cols="80" rows="7" accesskey="m"></textarea><br />
+ <div id="preview#{thread['id']}" class="msg" style="display:none"></div>
+ <?py if allow_image_replies: ?>
+ <input type="file" name="file" />
+ <?py #endif ?>
+ <?py #endif ?>
+</form>
+<?py #endfor ?>
+<?py #endif ?>
+<div class="end">weabot.py ver <?py include('templates/revision.html') ?> Bienvenido a Internet BBS/IB</div>
+<a name="bottom"></a>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/txt_thread.html b/cgi/templates/txt_thread.html
new file mode 100644
index 0000000..c438944
--- /dev/null
+++ b/cgi/templates/txt_thread.html
@@ -0,0 +1,101 @@
+<?py include('templates/txt_base_top.html') ?>
+<body class="threadpage" data-brd="#{board}">
+<?py if threads: ?>
+<?py for thread in threads: ?>
+<div id="thread_nav">
+ <a href="/" name="top" target="_top">Bienvenido a Internet</a>
+ <a href="#{boards_url}#{board}/">■Volver al BBS■</a>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/">Hilo completo</a>
+ <?py if thread['length'] > 100: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/-100">Primeros 100</a>
+ <?py #endif ?>
+ <?py if thread['length'] > 51: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/l50">Últimos 50</a>
+ <?py #endif ?>
+ <a href="#bottom">&#9660;Bajar&#9660;</a>
+</div>
+<hr />
+<?py if thread['length'] > 1000: ?>
+ <div class="stop red">El hilo superó los 1000 mensajes y ha sido cerrado. Ya no se puede postear en él.</div>
+<?py elif thread['length'] > 900: ?>
+ <div class="warn yellow">El hilo ha recibido más de 900 mensajes. Cuando llegue a 1000 será cerrado.</div>
+<?py #endif ?>
+<div class="thread" data-length="#{thread['length']}">
+ <h3>#{thread['subject']} <span>(${(str(thread['length'])+" respuestas") if thread['length']>1 else "Una respuesta"})</span></h3>
+ <?py for post in thread['posts']: ?>
+ <?py if post['IS_DELETED'] == '1': ?>
+ <h4 class="deleted">#{post['num']} : Mensaje eliminado por el usuario.</h4>
+ <?py elif post['IS_DELETED'] == '2': ?>
+ <h4 class="deleted">#{post['num']} : Mensaje eliminado por miembro del staff.</h4>
+ <?py else: ?>
+ <?py if post['num'] == 1: ?>
+ <div class="reply first" data-n="#{post['num']}">
+ <?py else: ?>
+ <div class="reply" data-n="#{post['num']}">
+ <?py #endif ?>
+ <h4><a href="#" class="num">#{post['num']}</a> :
+ <?py if post['email']: ?>
+ <?py if post['tripcode']: ?>
+ <a href="mailto:#{post['email']}"><span class="name"><b>#{post['name']}</b> #{post['tripcode']}</span></a>
+ <?py else: ?>
+ <a href="mailto:#{post['email']}"><span class="name"><b>#{post['name']}</b></span></a>
+ <?py #endif ?>
+ <?py else: ?>
+ <?py if post['tripcode']: ?>
+ <span class="name"><b>#{post['name']}</b> #{post['tripcode']}</span>
+ <?py else: ?>
+ <span class="name"><b>#{post['name']}</b></span>
+ <?py #endif ?>
+ <?py #endif ?> : <span class="date" data-unix="#{post['timestamp']}">#{post['timestamp_formatted']}</span>
+ <span class="del"><a href="#{cgi_url}report/#{board}/#{post['id']}/#{post['num']}">rep</a> <a href="#">del</a></span></h4>
+ <?py if post['file']: ?>
+ <a href="/#{board}/src/#{post['file']}" target="_blank" class="thumb"><img src="#{'/static/' if post['thumb'].startswith('mime') else ('/'+board+'/thumb/')}#{post['thumb']}" width="#{post['thumb_width']}" height="#{post['thumb_height']}" /><div>${int(post['file_size'])//1024}KB ${post['file'].split(".")[1].upper()}</div></a>
+ <?py #endif ?>
+ <div class="msg">#{post['message']}</div>
+ </div>
+ <?py #endif ?>
+ <?py #endfor ?>
+ <div class="size">#{thread['size']}</div>
+</div>
+<hr />
+<?py if thread['locked'] != '1': ?>
+ <div class="lastposts"><a href="#{boards_url}#{board}/read/#{thread['timestamp']}/#{thread['length']}-n" id="n">Ver nuevos posts</a></div>
+ <hr />
+<?py #endif ?>
+<?py if thread['length'] > 1000: ?>
+ <div class="stop red">El hilo superó los 1000 mensajes y ha sido cerrado. Ya no se puede postear en él.</div>
+<?py elif thread['length'] > 900: ?>
+ <div class="warn yellow">El hilo ha recibido más de 900 mensajes. Cuando llegue a 1000 será cerrado.</div>
+<?py #endif ?>
+<form id="postform#{thread['id']}" class="postform" name="postform" action="#{cgi_url}post" method="post" enctype="multipart/form-data">
+ <div class="threadlinks">
+ <a href="#{boards_url}#{board}/">■Volver al BBS■</a>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/">Hilo completo</a>
+ <?py if prevrange: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/#{prevrange}">Anteriores 100</a>
+ <?py #endif ?>
+ <?py if nextrange: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/#{nextrange}">Próximos 100</a>
+ <?py #endif ?>
+ <?py if thread['length'] > 51: ?>
+ <a href="#{boards_url}#{board}/read/#{thread['timestamp']}/l50">Últimos 50</a>
+ <?py #endif ?>
+ <a href="#top">&#9650;Subir&#9650;</a>
+ </div>
+ <input type="hidden" name="board" value="#{board}" /><input type="hidden" name="parent" value="#{thread['id']}" /><input type="hidden" name="password" value="" />
+ <?py if thread['locked'] != '1': ?>
+ <div style="display:none"><input type="text" name="name" size="13" /> <input type="text" name="email" size="13" /></div>
+ <span><input type="submit" value="Responder" accesskey="z" /> <input type="button" name="preview" value="Previsualizar" /></span> <span><span>Nombre:&nbsp;</span><input type="text" name="fielda" size="13" accesskey="n" /><span>&nbsp;E-mail:&nbsp;</span><input type="text" name="fieldb" size="13" accesskey="e" /></span><br />
+ <textarea name="message" cols="80" rows="7" accesskey="m"></textarea><br />
+ <div id="preview#{thread['id']}" class="msg" style="display:none"></div>
+ <?py if allow_image_replies: ?>
+ <input type="file" name="file" />
+ <?py #endif ?>
+ <?py #endif ?>
+</form>
+<?py #endfor ?>
+<?py #endif ?>
+<div class="end">weabot.py ver <?py include('templates/revision.html') ?> Bienvenido a Internet BBS/IB</div>
+<a name="bottom"></a>
+</body>
+</html> \ No newline at end of file
diff --git a/cgi/templates/txt_threadlist.html b/cgi/templates/txt_threadlist.html
new file mode 100644
index 0000000..bb09df4
--- /dev/null
+++ b/cgi/templates/txt_threadlist.html
@@ -0,0 +1,67 @@
+<?py include('templates/txt_base_top.html') ?>
+<body class="threads" data-brd="#{board}">
+<div id="main_nav"><a href="/" target="_top">Bienvenido a Internet</a> | <?py include('templates/navbar.html') ?></div>
+<?py if banner_url: ?>
+ <img class="banner" src="#{banner_url}" style="width:#{banner_width}px;height:#{banner_height}px;" />
+<?py #endif ?>
+<div id="titlebox" class="outerbox">
+ <div class="innerbox"><h1>#{board_long}</h1></div>
+ <div class="innerbox links"><b>¿Eres nuevo?</b> <a href="/guia.html"><b>C&oacute;mo postear</b></a> | <a href="/faq.html"><b>Preguntas frecuentes</b></a> | <a href="/bai/"><b>Contacto</b></a>
+ <?py if not force_css: ?>| <b>Apariencia:</b>
+ <?py for title in txt_styles: ?><a href="#" class="ss">#{title}</a> <?py #endfor ?>
+ <?py #endif ?></div>
+</div>
+<a name="menu"></a>
+<div id="threadbox" class="outerbox"><div class="innerbox">
+ <div id="threadlinks"><a href="#{boards_url}#{board}/"><b>Volver al BBS</b></a> <a href="/#{board}/kako/"><b>Ver hilos archivados</b></a> <a href="#newthread"><b>Crear nuevo hilo</b></a></div>
+ <div id="listmenu">Orden: <a class="l_s" href="#">Normal</a> <a class="l_s" href="#">Edad</a> <a class="l_s" href="#">Largo</a> <a class="l_s" href="#">Rapidez</a> <a class="l_s" href="#">Aleatorio</a> / Modo: <a class="l_d" href="#">Lista</a> <a class="l_d" href="#">Malla</a> / Buscar: <input id="l_sr" style="padding:0px;width:100px;" type="text"></div>
+</div></div>
+<div id="content" class="list">
+<div id="header" class="row">
+ <div>#</div>
+ <div style="width:100%;">Asunto</div>
+ <div>Resp.</div>
+ <div class="hdate">Última respuesta</div>
+</div>
+<?py iter = 1 ?>
+<?py for thread in more_threads: ?>
+<div class="row">
+ <div class="pos">#{iter}:</div>
+ <div class="thread"><a href="#{boards_url}#{board}/read/#{thread['timestamp']}/${'l50' if int(thread['length']) > 50 else ''}">#{thread["subject"]}</a></div>
+ <div class="com">#{thread["length"]}</div>
+ <div class="date" data-unix="#{timestamps[iter-1][0]}">#{timestamps[iter-1][1]}</div>
+</div>
+<?py iter += 1 ?>
+<?py #endfor ?>
+</div>
+<a name="newthread"></a>
+<div id="createbox" class="outerbox">
+ <div class="extrabox"></div>
+ <div class="innerbox">
+ <h5>Formulario de nuevo hilo</h5>
+ <form id="postform0" action="#{cgi_url}post" method="post" enctype="multipart/form-data">
+ <input type="hidden" name="board" value="#{board}" /><input type="hidden" name="password" value="" />
+ <table style="max-width:600px;">
+ <tr>
+ <td style="text-align:right;">Asunto:</td>
+ <td colspan="3" style="width:100%;"><input type="text" name="subject" size="50" maxlength="100" /></td>
+ <td><input type="submit" value="Crear nuevo hilo" /></td>
+ </tr>
+ <tr>
+ <td style="text-align:right;">Nombre:</td><td><input type="text" name="fielda" /></td>
+ <td style="text-align:right;">E-mail:</td><td><input type="text" name="fieldb" /></td>
+ <td><input type="button" name="preview" value="Previsualizar" /></td>
+ </tr>
+ <tr id="options" style="display:none;"><td></td><td colspan="4"><div id="preview0" class="msg"></div></td></tr>
+ <tr><td style="text-align:right;">Mensaje:</td><td colspan="4"><textarea name="message" cols="70" rows="10"></textarea></td></tr>
+ <?py if allow_images: ?>
+ <tr><td style="text-align:right;">Archivo:</td><td colspan="4"><input type="file" name="file" /></td></tr>
+ <?py #endif ?>
+ </table>
+ <div style="display:none;">Trampa: <input type="text" name="name" maxlength="50" /> <input type="text" name="email" maxlength="50" /></div>
+ </form>
+ </div>
+</div>
+<center id="footer"><a href="/" target="_top">Bienvenido a Internet BBS/IB</a> weabot.py <?py include('templates/revision.html') ?> + FastCGI + tenjin<br />No se ponga sensible, baisano...</center>
+</body>
+</html> \ No newline at end of file