From 95dfe14528663923ca2a88ec928f1d8d9df2402b Mon Sep 17 00:00:00 2001 From: bai Date: Fri, 29 Mar 2019 02:14:43 +0000 Subject: Init --- cgi/.htaccess | 9 + cgi/BeautifulSoup.py | 2017 +++++++ cgi/GeoIP.dat | Bin 0 -> 878459 bytes cgi/anarkia.py | 439 ++ cgi/api.py | 392 ++ cgi/database.py | 69 + cgi/fcgi.py | 1332 +++++ cgi/formatting.py | 425 ++ cgi/framework.py | 467 ++ cgi/geoip.py | 128 + cgi/img.py | 416 ++ cgi/locale/es/LC_MESSAGES/weabot.mo | Bin 0 -> 17305 bytes cgi/manage.py | 1823 ++++++ cgi/markdown.py | 2044 +++++++ cgi/oekaki.py | 176 + cgi/post.py | 1260 ++++ cgi/proxy.txt | 3251 +++++++++++ cgi/quotes.conf | 13 + cgi/template.py | 117 + cgi/templates/anarkia.html | 329 ++ cgi/templates/banned.html | 34 + cgi/templates/base_bottom.html | 3 + cgi/templates/base_top.html | 55 + cgi/templates/board.0.html | 230 + cgi/templates/board.html | 264 + cgi/templates/board.jp.html | 271 + cgi/templates/catalog.html | 30 + cgi/templates/error.html | 7 + cgi/templates/exception.html | 36 + cgi/templates/home.rss | 24 + cgi/templates/htaccess | 24 + cgi/templates/kako.html | 60 + cgi/templates/manage/addboard.html | 21 + cgi/templates/manage/bans.html | 92 + cgi/templates/manage/boardoptions.html | 195 + cgi/templates/manage/changepassword.html | 24 + cgi/templates/manage/delete.html | 23 + cgi/templates/manage/filters.html | 119 + cgi/templates/manage/ipdelete.html | 24 + cgi/templates/manage/ipshow.html | 73 + cgi/templates/manage/lockboard.html | 20 + cgi/templates/manage/login.html | 21 + cgi/templates/manage/logs.html | 17 + cgi/templates/manage/manage.html | 22 + cgi/templates/manage/menu.html | 30 + cgi/templates/manage/message.html | 8 + cgi/templates/manage/mod.html | 96 + cgi/templates/manage/move.html | 60 + cgi/templates/manage/quotes.html | 12 + cgi/templates/manage/rebuild.html | 20 + cgi/templates/manage/recent_images.html | 24 + cgi/templates/manage/recyclebin.html | 72 + cgi/templates/manage/reports.html | 58 + cgi/templates/manage/search.html | 27 + cgi/templates/manage/staff.html | 63 + cgi/templates/mobile/base_top.html | 14 + cgi/templates/mobile/board.html | 55 + cgi/templates/mobile/error.html | 6 + cgi/templates/mobile/latest.html | 14 + cgi/templates/mobile/newest.html | 14 + cgi/templates/mobile/threadlist.html | 43 + cgi/templates/mobile/txt_newthread.html | 35 + cgi/templates/mobile/txt_thread.html | 74 + cgi/templates/mobile/txt_threadlist.html | 26 + cgi/templates/mod.html | 86 + cgi/templates/navbar.html | 16 + cgi/templates/paint.html | 79 + cgi/templates/redirect.html | 12 + cgi/templates/report.html | 29 + cgi/templates/revision.html | 1 + cgi/templates/stats.html | 163 + cgi/templates/txt_archive.html | 104 + cgi/templates/txt_base_top.html | 44 + cgi/templates/txt_board.en.html | 137 + cgi/templates/txt_board.html | 137 + cgi/templates/txt_error.html | 50 + cgi/templates/txt_thread.en.html | 105 + cgi/templates/txt_thread.html | 101 + cgi/templates/txt_threadlist.html | 67 + cgi/tenjin.py | 2118 +++++++ cgi/tor.txt | 1140 ++++ cgi/weabot.py | 1021 ++++ static/css/buri.css | 23 + static/css/cyber.css | 39 + static/css/dickgirl.css | 23 + static/css/easymodo.css | 25 + static/css/futaba.css | 22 + static/css/guro.css | 24 + static/css/ib.css | 72 + static/css/img/0back.png | Bin 0 -> 148 bytes static/css/img/0info.png | Bin 0 -> 284 bytes static/css/img/0pc.png | Bin 0 -> 276 bytes static/css/img/ba.gif | Bin 0 -> 856 bytes static/css/img/barra_dulce.png | Bin 0 -> 1266 bytes static/css/img/bg_deportes.gif | Bin 0 -> 3584 bytes static/css/img/bg_madera.png | Bin 0 -> 4216 bytes static/css/img/bg_oculto.gif | Bin 0 -> 871 bytes static/css/img/bgtb.gif | Bin 0 -> 854 bytes static/css/img/checked.png | Bin 0 -> 110 bytes static/css/img/cyb.png | Bin 0 -> 4844 bytes static/css/img/cyba.png | Bin 0 -> 201 bytes static/css/img/fondo2012.gif | Bin 0 -> 72620 bytes static/css/img/green.gif | Bin 0 -> 37408 bytes static/css/img/hand.png | Bin 0 -> 213 bytes static/css/img/luz.gif | Bin 0 -> 3413 bytes static/css/img/muro.jpg | Bin 0 -> 37725 bytes static/css/img/nieve.png | Bin 0 -> 2394 bytes static/css/img/picnicbdy.gif | Bin 0 -> 1049 bytes static/css/img/picnicbg.gif | Bin 0 -> 10945 bytes static/css/img/picnicbtm.gif | Bin 0 -> 3923 bytes static/css/img/picnicbtn.gif | Bin 0 -> 436 bytes static/css/img/picnicfg.gif | Bin 0 -> 1044 bytes static/css/img/picnichr.gif | Bin 0 -> 1368 bytes static/css/img/picnicmid.gif | Bin 0 -> 9502 bytes static/css/img/picnicthr1.gif | Bin 0 -> 12688 bytes static/css/img/picnicthr2.gif | Bin 0 -> 2946 bytes static/css/img/picnicthr3.gif | Bin 0 -> 12154 bytes static/css/img/picnictop.gif | Bin 0 -> 6939 bytes static/css/img/scan.png | Bin 0 -> 182 bytes static/css/img/scroller1.gif | Bin 0 -> 3456 bytes static/css/img/tanasinn.gif | Bin 0 -> 1176 bytes static/css/img/vndb1.jpg | Bin 0 -> 36419 bytes static/css/img/vndb2.jpg | Bin 0 -> 4366 bytes static/css/img/vndb3.png | Bin 0 -> 2791 bytes static/css/kraut.css | 24 + static/css/mobile.css | 129 + static/css/night.css | 22 + static/css/photon.css | 22 + static/css/putaba.css | 46 + static/css/red.css | 21 + static/css/rene.css | 22 + static/css/spc/base.css | 269 + static/css/spc/halloween.css | 47 + static/css/spc/layout.css | 58 + static/css/spc/navidad.css | 161 + static/css/spc/skeleton.css | 242 + static/css/spc/valentin.css | 170 + static/css/spc/valentin2.css | 177 + static/css/txt/4am.css | 42 + static/css/txt/amber.css | 44 + static/css/txt/ayashii.css | 52 + static/css/txt/baisano.css | 43 + static/css/txt/bbs.css | 95 + static/css/txt/bios.css | 51 + static/css/txt/blue moon.css | 61 + static/css/txt/ciber.css | 55 + static/css/txt/futanari.css | 49 + static/css/txt/headline.css | 41 + static/css/txt/postal.css | 47 + static/css/txt/sjis.css | 1 + static/css/txt/ventanas.css | 48 + static/css/vndb.css | 30 + static/ico/1372836.gif | Bin 0 -> 374 bytes static/ico/1k.gif | Bin 0 -> 101 bytes static/ico/2-1.gif | Bin 0 -> 1012 bytes static/ico/2ppa.gif | Bin 0 -> 285 bytes static/ico/2syobo_2.gif | Bin 0 -> 270 bytes static/ico/3-2.gif | Bin 0 -> 19802 bytes static/ico/3.gif | Bin 0 -> 1006 bytes static/ico/3na.gif | Bin 0 -> 324 bytes static/ico/4-2.gif | Bin 0 -> 1107 bytes static/ico/4248688.gif | Bin 0 -> 8947 bytes static/ico/5007629.gif | Bin 0 -> 14263 bytes static/ico/5296219.gif | Bin 0 -> 4028 bytes static/ico/5ta.gif | Bin 0 -> 364 bytes static/ico/6396408.gif | Bin 0 -> 8590 bytes static/ico/6za.gif | Bin 0 -> 395 bytes static/ico/8028885.gif | Bin 0 -> 41133 bytes static/ico/8toushinnomonar16.gif | Bin 0 -> 118 bytes static/ico/8toushinnomonar32.gif | Bin 0 -> 247 bytes static/ico/ace.gif | Bin 0 -> 317 bytes static/ico/af1.gif | Bin 0 -> 254 bytes static/ico/af2.gif | Bin 0 -> 228 bytes static/ico/ahya_xmas_2.gif | Bin 0 -> 227 bytes static/ico/aka.gif | Bin 0 -> 307 bytes static/ico/ame.gif | Bin 0 -> 224 bytes static/ico/anime_buun02.gif | Bin 0 -> 2036 bytes static/ico/anime_charhan01.gif | Bin 0 -> 2257 bytes static/ico/anime_charhan02.gif | Bin 0 -> 10274 bytes static/ico/anime_giko01.gif | Bin 0 -> 2183 bytes static/ico/anime_giko04.gif | Bin 0 -> 1516 bytes static/ico/anime_giko10.gif | Bin 0 -> 2250 bytes static/ico/anime_giko11.gif | Bin 0 -> 2291 bytes static/ico/anime_giko12.gif | Bin 0 -> 1760 bytes static/ico/anime_giko13.gif | Bin 0 -> 3135 bytes static/ico/anime_hossyu01.gif | Bin 0 -> 1300 bytes static/ico/anime_imanouchi01.gif | Bin 0 -> 1459 bytes static/ico/anime_iyou02.gif | Bin 0 -> 3351 bytes static/ico/anime_jien01.gif | Bin 0 -> 3345 bytes static/ico/anime_jien02.gif | Bin 0 -> 3403 bytes static/ico/anime_jien03.gif | Bin 0 -> 3231 bytes static/ico/anime_jyorujyu01.gif | Bin 0 -> 1431 bytes static/ico/anime_jyorujyu02.gif | Bin 0 -> 1441 bytes static/ico/anime_jyorujyu03.gif | Bin 0 -> 1450 bytes static/ico/anime_kukkuru01.gif | Bin 0 -> 1665 bytes static/ico/anime_kuma01.gif | Bin 0 -> 2099 bytes static/ico/anime_kumaface01.gif | Bin 0 -> 3924 bytes static/ico/anime_loop.gif | Bin 0 -> 20749 bytes static/ico/anime_marara02.gif | Bin 0 -> 1925 bytes static/ico/anime_matanki01.gif | Bin 0 -> 1392 bytes static/ico/anime_matanki02.gif | Bin 0 -> 4616 bytes static/ico/anime_miruna01.gif | Bin 0 -> 1567 bytes static/ico/anime_monar02.gif | Bin 0 -> 1594 bytes static/ico/anime_monar03.gif | Bin 0 -> 2564 bytes static/ico/anime_monar05.gif | Bin 0 -> 5846 bytes static/ico/anime_morara01.gif | Bin 0 -> 1576 bytes static/ico/anime_morara02.gif | Bin 0 -> 1734 bytes static/ico/anime_morara04.gif | Bin 0 -> 1634 bytes static/ico/anime_nokar01.gif | Bin 0 -> 2334 bytes static/ico/anime_okashi01.gif | Bin 0 -> 5999 bytes static/ico/anime_okashi02.gif | Bin 0 -> 4348 bytes static/ico/anime_onigiri04.gif | Bin 0 -> 8654 bytes static/ico/anime_saitama01.gif | Bin 0 -> 1440 bytes static/ico/anime_saitama02.gif | Bin 0 -> 1348 bytes static/ico/anime_saitama03.gif | Bin 0 -> 1454 bytes static/ico/anime_sasuga01.gif | Bin 0 -> 1546 bytes static/ico/anime_sasuga03.gif | Bin 0 -> 9729 bytes static/ico/anime_sasuga04.gif | Bin 0 -> 16392 bytes static/ico/anime_shii01.gif | Bin 0 -> 11664 bytes static/ico/anime_shii02.gif | Bin 0 -> 8324 bytes static/ico/anime_shii03.gif | Bin 0 -> 1506 bytes static/ico/anime_syobon01.gif | Bin 0 -> 2156 bytes static/ico/anime_syobon03.gif | Bin 0 -> 2361 bytes static/ico/anime_tarn01.gif | Bin 0 -> 3754 bytes static/ico/anime_uwan01.gif | Bin 0 -> 1966 bytes static/ico/anime_uwan02.gif | Bin 0 -> 1441 bytes static/ico/anime_uwan03.gif | Bin 0 -> 2216 bytes static/ico/anime_youkanman01.gif | Bin 0 -> 1915 bytes static/ico/anime_youkanman02.gif | Bin 0 -> 1882 bytes static/ico/anime_youkanman03.gif | Bin 0 -> 1365 bytes static/ico/anime_zonu01.gif | Bin 0 -> 1426 bytes static/ico/anime_zonu02.gif | Bin 0 -> 1476 bytes static/ico/aramaki.gif | Bin 0 -> 236 bytes static/ico/aroeri-na32.gif | Bin 0 -> 268 bytes static/ico/asopasomaso.gif | Bin 0 -> 247 bytes static/ico/bikyakusan32.gif | Bin 0 -> 213 bytes static/ico/bs.gif | Bin 0 -> 378 bytes static/ico/button1_03.gif | Bin 0 -> 218 bytes static/ico/buun.gif | Bin 0 -> 251 bytes static/ico/chahan.gif | Bin 0 -> 279 bytes static/ico/dokuo1.gif | Bin 0 -> 414 bytes static/ico/file2_01.gif | Bin 0 -> 282 bytes static/ico/fujisan.gif | Bin 0 -> 216 bytes static/ico/fuun.gif | Bin 0 -> 244 bytes static/ico/gaku.gif | Bin 0 -> 196 bytes static/ico/gaku2.gif | Bin 0 -> 252 bytes static/ico/gaku3.gif | Bin 0 -> 199 bytes static/ico/gekisya1.gif | Bin 0 -> 333 bytes static/ico/giko1.gif | Bin 0 -> 407 bytes static/ico/gikog_gomibako.gif | Bin 0 -> 233 bytes static/ico/gikog_gyunyupack.gif | Bin 0 -> 277 bytes static/ico/gikog_pimiento.gif | Bin 0 -> 279 bytes static/ico/gikoinu.gif | Bin 0 -> 252 bytes static/ico/gikoneko.gif | Bin 0 -> 997 bytes static/ico/gikoneko2.gif | Bin 0 -> 1021 bytes static/ico/gikoneko_1.gif | Bin 0 -> 200 bytes static/ico/gocchin_face.gif | Bin 0 -> 256 bytes static/ico/gomiopen.gif | Bin 0 -> 425 bytes static/ico/goo_1.gif | Bin 0 -> 209 bytes static/ico/goo_3.gif | Bin 0 -> 213 bytes static/ico/gya-.gif | Bin 0 -> 129 bytes static/ico/hagenin-shuriken.gif | Bin 0 -> 8609 bytes static/ico/hagurumaou.gif | Bin 0 -> 283 bytes static/ico/hikky.gif | Bin 0 -> 246 bytes static/ico/hikky_xmas_2.gif | Bin 0 -> 250 bytes static/ico/hyou.gif | Bin 0 -> 212 bytes static/ico/iirasan_face.gif | Bin 0 -> 283 bytes static/ico/imanouchi_1.gif | Bin 0 -> 232 bytes static/ico/iyahoo.gif | Bin 0 -> 1456 bytes static/ico/iyou.gif | Bin 0 -> 233 bytes static/ico/jisakujien_2.gif | Bin 0 -> 181 bytes static/ico/jisakujien_xmas.gif | Bin 0 -> 219 bytes static/ico/kantoku1.gif | Bin 0 -> 314 bytes static/ico/kappappa1.gif | Bin 0 -> 416 bytes static/ico/kasa-ri.gif | Bin 0 -> 196 bytes static/ico/kashiwamo-chi32.gif | Bin 0 -> 352 bytes static/ico/kinokorusensei32.gif | Bin 0 -> 337 bytes static/ico/kita_.gif | Bin 0 -> 260 bytes static/ico/kodomona.gif | Bin 0 -> 237 bytes static/ico/konkon_folder.gif | Bin 0 -> 373 bytes static/ico/kossorisan.gif | Bin 0 -> 99 bytes static/ico/kotatu.gif | Bin 0 -> 248 bytes static/ico/kuma.gif | Bin 0 -> 3875 bytes static/ico/kuma2.gif | Bin 0 -> 484 bytes static/ico/maimai.gif | Bin 0 -> 327 bytes static/ico/makotan2_folder.gif | Bin 0 -> 389 bytes static/ico/mona.gif | Bin 0 -> 254 bytes static/ico/mona_shiri.gif | Bin 0 -> 238 bytes static/ico/mona_tya.gif | Bin 0 -> 298 bytes static/ico/monaazarashi_1.gif | Bin 0 -> 168 bytes static/ico/namaetukenai.gif | Bin 0 -> 3331 bytes static/ico/naoruyo.gif | Bin 0 -> 257 bytes static/ico/nida.gif | Bin 0 -> 254 bytes static/ico/nigete.gif | Bin 0 -> 2304 bytes static/ico/nono_ie.gif | Bin 0 -> 365 bytes static/ico/nurupo_ga_2.gif | Bin 0 -> 1270 bytes static/ico/onigiri_seito.gif | Bin 0 -> 288 bytes static/ico/otiketu48.gif | Bin 0 -> 378 bytes static/ico/pc3.gif | Bin 0 -> 288 bytes static/ico/pgya.gif | Bin 0 -> 288 bytes static/ico/sasuga1.gif | Bin 0 -> 15680 bytes static/ico/seito_2.gif | Bin 0 -> 216 bytes static/ico/soon.gif | Bin 0 -> 245 bytes static/ico/tasukete.gif | Bin 0 -> 312 bytes static/ico/torimasu1.gif | Bin 0 -> 317 bytes static/ico/torimasu2.gif | Bin 0 -> 313 bytes static/ico/u_ame.gif | Bin 0 -> 3608 bytes static/ico/u_hoshi.gif | Bin 0 -> 3076 bytes static/ico/u_naoruyo_bath.gif | Bin 0 -> 4552 bytes static/ico/u_okotowari_a.gif | Bin 0 -> 6831 bytes static/ico/u_sofa.gif | Bin 0 -> 1280 bytes static/ico/wakannai1.gif | Bin 0 -> 304 bytes static/ico/yakimochi.gif | Bin 0 -> 242 bytes static/ico/youkan.gif | Bin 0 -> 254 bytes static/ico/zonu_1.gif | Bin 0 -> 179 bytes static/ico/zuzagiko48.gif | Bin 0 -> 368 bytes static/img/anarkia.jpg | Bin 0 -> 35677 bytes static/img/bai.jpg | Bin 0 -> 38030 bytes static/img/cero.gif | Bin 0 -> 80262 bytes static/img/default.png | Bin 0 -> 9073 bytes static/img/juegos1.jpg | Bin 0 -> 43984 bytes static/img/juegos2.jpg | Bin 0 -> 35649 bytes static/img/juegos3.png | Bin 0 -> 10301 bytes static/img/juegos4.gif | Bin 0 -> 24664 bytes static/img/letras1.png | Bin 0 -> 52461 bytes static/img/letras2.png | Bin 0 -> 69712 bytes static/img/letras3.png | Bin 0 -> 97055 bytes static/img/letras4.jpg | Bin 0 -> 46084 bytes static/img/letras5.jpg | Bin 0 -> 50947 bytes static/img/musica1.jpg | Bin 0 -> 24487 bytes static/img/noticias.png | Bin 0 -> 13249 bytes static/img/old/2d_1.jpg | Bin 0 -> 29384 bytes static/img/old/2d_2.jpg | Bin 0 -> 36070 bytes static/img/old/2d_3.png | Bin 0 -> 5899 bytes static/img/old/2d_4.jpg | Bin 0 -> 29392 bytes static/img/old/argentina1.png | Bin 0 -> 27794 bytes static/img/old/chile1.png | Bin 0 -> 44923 bytes static/img/old/chile2.jpg | Bin 0 -> 44202 bytes static/img/old/g0.jpg | Bin 0 -> 39681 bytes static/img/old/g1.jpg | Bin 0 -> 45641 bytes static/img/old/g2.jpg | Bin 0 -> 38041 bytes static/img/old/g3.jpg | Bin 0 -> 52934 bytes static/img/old/g4.jpg | Bin 0 -> 36197 bytes static/img/old/g5.jpg | Bin 0 -> 23641 bytes static/img/old/peli.jpg | Bin 0 -> 36293 bytes static/img/old/salon2d_3.jpg | Bin 0 -> 35496 bytes static/img/old/salon2d_4.png | Bin 0 -> 4978 bytes static/img/old/salon2d_5.jpg | Bin 0 -> 25550 bytes static/img/old/zine.png | Bin 0 -> 75774 bytes static/img/salon2d_1.png | Bin 0 -> 15409 bytes static/img/salon2d_3.jpg | Bin 0 -> 35496 bytes static/img/salon2d_4.png | Bin 0 -> 4978 bytes static/img/salon2d_5.jpg | Bin 0 -> 25550 bytes static/img/tech1.png | Bin 0 -> 7802 bytes static/img/tech2.jpg | Bin 0 -> 36871 bytes static/img/tech3.png | Bin 0 -> 42940 bytes static/img/tech4.jpg | Bin 0 -> 48759 bytes static/img/tech5.jpg | Bin 0 -> 37524 bytes static/img/tech6.png | Bin 0 -> 17938 bytes static/img/tv1.png | Bin 0 -> 3501 bytes static/img/weird-al.jpg | Bin 0 -> 14523 bytes static/img/world.gif | Bin 0 -> 100563 bytes static/img/zonavip1.jpg | Bin 0 -> 45584 bytes static/img/zonavip2.gif | Bin 0 -> 38269 bytes static/img/zonavip3.png | Bin 0 -> 85601 bytes static/img/zonavip4.jpg | Bin 0 -> 41923 bytes static/img/zonavip5.gif | Bin 0 -> 35591 bytes static/img/zonavip6.png | Bin 0 -> 13149 bytes static/img/zonavip7.gif | Bin 0 -> 50028 bytes static/img/zonavip8.png | Bin 0 -> 53463 bytes static/img/zonavip9.gif | Bin 0 -> 19603 bytes static/img/zonavip9.jpg | Bin 0 -> 46773 bytes static/img/zonavip_halloween.jpg | Bin 0 -> 38379 bytes static/img/zonavip_nav.jpg | Bin 0 -> 51171 bytes static/js/aquiencitas.js | 168 + static/js/autorefresh.js | 275 + static/js/home.js | 173 + static/js/jquery.js | 545 ++ static/js/manage.js | 22 + static/js/mobile.js | 447 ++ static/js/paintbbs/PaintBBS-1.1.11.css | 535 ++ static/js/paintbbs/PaintBBS-1.1.11.js | 5686 ++++++++++++++++++ static/js/paintbbs/PaintBBS-1.3.4.css | 547 ++ static/js/paintbbs/PaintBBS-1.3.4.js | 6171 ++++++++++++++++++++ static/js/palette_selfy.js | 972 +++ static/js/shobon.js | 408 ++ static/js/tegaki/tegaki.css | 187 + static/js/tegaki/tegaki.js | 1947 ++++++ static/js/weabot.js | 456 ++ static/js/weabotxt.js | 299 + static/js/wpaint/.gitignore | 3 + static/js/wpaint/README.md | 421 ++ static/js/wpaint/bai.js | 23 + static/js/wpaint/demo/demo.css | 266 + static/js/wpaint/demo/img/facebook-icon.png | Bin 0 -> 274 bytes static/js/wpaint/demo/img/favicon.ico | Bin 0 -> 1150 bytes .../js/wpaint/demo/img/forkme_right_darkblue.png | Bin 0 -> 7791 bytes static/js/wpaint/demo/img/github-icon.png | Bin 0 -> 596 bytes static/js/wpaint/demo/img/googleplus-icon.png | Bin 0 -> 522 bytes static/js/wpaint/demo/img/linkedin-icon.png | Bin 0 -> 380 bytes static/js/wpaint/demo/img/rss-icon.png | Bin 0 -> 521 bytes static/js/wpaint/demo/img/stumbleupon-icon.png | Bin 0 -> 537 bytes static/js/wpaint/demo/img/twitter-icon.png | Bin 0 -> 514 bytes .../demo/img/websanova-logo-small-full-black.png | Bin 0 -> 1028 bytes static/js/wpaint/demo/img/youtube-icon.png | Bin 0 -> 587 bytes static/js/wpaint/gruntfile.js | 90 + static/js/wpaint/index.html | 136 + static/js/wpaint/lib/jquery.1.10.2.min.js | 6 + static/js/wpaint/lib/jquery.ui.core.1.10.3.min.js | 4 + .../wpaint/lib/jquery.ui.draggable.1.10.3.min.js | 4 + static/js/wpaint/lib/jquery.ui.mouse.1.10.3.min.js | 4 + .../js/wpaint/lib/jquery.ui.widget.1.10.3.min.js | 4 + static/js/wpaint/lib/mixins.styl | 7 + static/js/wpaint/lib/wColorPicker.min.css | 42 + static/js/wpaint/lib/wColorPicker.min.js | 2 + static/js/wpaint/package.json | 25 + .../plugins/file/img/icons-menu-main-file.png | Bin 0 -> 835 bytes .../plugins/file/src/wPaint.menu.main.file.js | 75 + .../plugins/file/wPaint.menu.main.file.min.js | 1 + .../js/wpaint/plugins/main/img/cursor-bucket.png | Bin 0 -> 450 bytes .../wpaint/plugins/main/img/cursor-crosshair.png | Bin 0 -> 208 bytes .../js/wpaint/plugins/main/img/cursor-dropper.png | Bin 0 -> 403 bytes .../js/wpaint/plugins/main/img/cursor-eraser1.png | Bin 0 -> 193 bytes .../js/wpaint/plugins/main/img/cursor-eraser10.png | Bin 0 -> 247 bytes .../js/wpaint/plugins/main/img/cursor-eraser2.png | Bin 0 -> 200 bytes .../js/wpaint/plugins/main/img/cursor-eraser3.png | Bin 0 -> 206 bytes .../js/wpaint/plugins/main/img/cursor-eraser4.png | Bin 0 -> 209 bytes .../js/wpaint/plugins/main/img/cursor-eraser5.png | Bin 0 -> 225 bytes .../js/wpaint/plugins/main/img/cursor-eraser6.png | Bin 0 -> 229 bytes .../js/wpaint/plugins/main/img/cursor-eraser7.png | Bin 0 -> 236 bytes .../js/wpaint/plugins/main/img/cursor-eraser8.png | Bin 0 -> 240 bytes .../js/wpaint/plugins/main/img/cursor-eraser9.png | Bin 0 -> 244 bytes .../js/wpaint/plugins/main/img/cursor-pencil.png | Bin 0 -> 449 bytes .../wpaint/plugins/main/img/icon-group-arrow.png | Bin 0 -> 208 bytes .../js/wpaint/plugins/main/img/icons-menu-main.png | Bin 0 -> 2836 bytes static/js/wpaint/plugins/main/src/fillArea.min.js | 1 + .../js/wpaint/plugins/main/src/wPaint.menu.main.js | 338 ++ .../js/wpaint/plugins/main/wPaint.menu.main.min.js | 1 + .../plugins/shapes/img/icons-menu-main-shapes.png | Bin 0 -> 903 bytes static/js/wpaint/plugins/shapes/src/shapes.min.js | 1 + .../plugins/shapes/src/wPaint.menu.main.shapes.js | 207 + .../plugins/shapes/wPaint.menu.main.shapes.min.js | 1 + .../js/wpaint/plugins/text/img/icons-menu-text.png | Bin 0 -> 802 bytes .../js/wpaint/plugins/text/src/wPaint.menu.text.js | 227 + .../js/wpaint/plugins/text/wPaint.menu.text.min.js | 1 + static/js/wpaint/src/wPaint.css | 348 ++ static/js/wpaint/src/wPaint.js | 1181 ++++ static/js/wpaint/src/wPaint.utils.js | 70 + static/js/wpaint/test/dev.html | 123 + static/js/wpaint/test/fullscreen.html | 79 + static/js/wpaint/test/upload.php | 11 + static/js/wpaint/test/uploads/test1.png | Bin 0 -> 432 bytes static/js/wpaint/test/uploads/test2.png | Bin 0 -> 462 bytes static/js/wpaint/test/uploads/test3.png | Bin 0 -> 454 bytes static/js/wpaint/test/uploads/wPaint.png | Bin 0 -> 3096 bytes static/js/wpaint/wPaint.jquery.json | 38 + static/js/wpaint/wPaint.min.css | 66 + static/js/wpaint/wPaint.min.js | 1 + static/meta/bbs.png | Bin 0 -> 7192 bytes static/meta/faq_1.png | Bin 0 -> 18358 bytes static/meta/faq_2.png | Bin 0 -> 12504 bytes static/meta/faq_3.png | Bin 0 -> 19818 bytes static/meta/ib.png | Bin 0 -> 10709 bytes static/meta/portada_6.jpg | Bin 0 -> 368440 bytes static/meta/portada_7.jpg | Bin 0 -> 51433 bytes static/meta/portada_8.jpg | Bin 0 -> 266858 bytes static/meta/portada_asp.gif | Bin 0 -> 441933 bytes static/meta/portada_cap1.jpg | Bin 0 -> 101119 bytes static/meta/portada_orig5.jpg | Bin 0 -> 67175 bytes static/meta/portada_toesca.jpg | Bin 0 -> 35123 bytes static/meta/portadaphil.jpg | Bin 0 -> 102067 bytes static/meta/primeraportada.png | Bin 0 -> 385869 bytes static/meta/sanvalentin2013.jpg | Bin 0 -> 98509 bytes static/meta/welcome.gif | Bin 0 -> 238888 bytes static/meta/welcome.jpg | Bin 0 -> 28985 bytes static/mime/epub.png | Bin 0 -> 1320 bytes static/mime/epub_small.png | Bin 0 -> 1019 bytes static/mime/mod.png | Bin 0 -> 1362 bytes static/mime/mod_small.png | Bin 0 -> 1058 bytes static/mime/pdf.png | Bin 0 -> 1264 bytes static/mime/pdf_small.png | Bin 0 -> 984 bytes static/mime/s3m.png | Bin 0 -> 1397 bytes static/mime/s3m_small.png | Bin 0 -> 1104 bytes static/mime/swf.png | Bin 0 -> 1375 bytes static/mime/swf_small.png | Bin 0 -> 1067 bytes static/mime/torrent.png | Bin 0 -> 1377 bytes static/mime/torrent_small.png | Bin 0 -> 1070 bytes static/mime/xm.png | Bin 0 -> 1318 bytes static/mime/xm_small.png | Bin 0 -> 1011 bytes 489 files changed, 47499 insertions(+) create mode 100644 cgi/.htaccess create mode 100644 cgi/BeautifulSoup.py create mode 100644 cgi/GeoIP.dat create mode 100644 cgi/anarkia.py create mode 100644 cgi/api.py create mode 100644 cgi/database.py create mode 100644 cgi/fcgi.py create mode 100644 cgi/formatting.py create mode 100644 cgi/framework.py create mode 100644 cgi/geoip.py create mode 100644 cgi/img.py create mode 100644 cgi/locale/es/LC_MESSAGES/weabot.mo create mode 100644 cgi/manage.py create mode 100644 cgi/markdown.py create mode 100644 cgi/oekaki.py create mode 100644 cgi/post.py create mode 100644 cgi/proxy.txt create mode 100644 cgi/quotes.conf create mode 100644 cgi/template.py create mode 100644 cgi/templates/anarkia.html create mode 100644 cgi/templates/banned.html create mode 100644 cgi/templates/base_bottom.html create mode 100644 cgi/templates/base_top.html create mode 100644 cgi/templates/board.0.html create mode 100644 cgi/templates/board.html create mode 100644 cgi/templates/board.jp.html create mode 100644 cgi/templates/catalog.html create mode 100644 cgi/templates/error.html create mode 100644 cgi/templates/exception.html create mode 100644 cgi/templates/home.rss create mode 100644 cgi/templates/htaccess create mode 100644 cgi/templates/kako.html create mode 100644 cgi/templates/manage/addboard.html create mode 100644 cgi/templates/manage/bans.html create mode 100644 cgi/templates/manage/boardoptions.html create mode 100644 cgi/templates/manage/changepassword.html create mode 100644 cgi/templates/manage/delete.html create mode 100644 cgi/templates/manage/filters.html create mode 100644 cgi/templates/manage/ipdelete.html create mode 100644 cgi/templates/manage/ipshow.html create mode 100644 cgi/templates/manage/lockboard.html create mode 100644 cgi/templates/manage/login.html create mode 100644 cgi/templates/manage/logs.html create mode 100644 cgi/templates/manage/manage.html create mode 100644 cgi/templates/manage/menu.html create mode 100644 cgi/templates/manage/message.html create mode 100644 cgi/templates/manage/mod.html create mode 100644 cgi/templates/manage/move.html create mode 100644 cgi/templates/manage/quotes.html create mode 100644 cgi/templates/manage/rebuild.html create mode 100644 cgi/templates/manage/recent_images.html create mode 100644 cgi/templates/manage/recyclebin.html create mode 100644 cgi/templates/manage/reports.html create mode 100644 cgi/templates/manage/search.html create mode 100644 cgi/templates/manage/staff.html create mode 100644 cgi/templates/mobile/base_top.html create mode 100644 cgi/templates/mobile/board.html create mode 100644 cgi/templates/mobile/error.html create mode 100644 cgi/templates/mobile/latest.html create mode 100644 cgi/templates/mobile/newest.html create mode 100644 cgi/templates/mobile/threadlist.html create mode 100644 cgi/templates/mobile/txt_newthread.html create mode 100644 cgi/templates/mobile/txt_thread.html create mode 100644 cgi/templates/mobile/txt_threadlist.html create mode 100644 cgi/templates/mod.html create mode 100644 cgi/templates/navbar.html create mode 100644 cgi/templates/paint.html create mode 100644 cgi/templates/redirect.html create mode 100644 cgi/templates/report.html create mode 100644 cgi/templates/revision.html create mode 100644 cgi/templates/stats.html create mode 100644 cgi/templates/txt_archive.html create mode 100644 cgi/templates/txt_base_top.html create mode 100644 cgi/templates/txt_board.en.html create mode 100644 cgi/templates/txt_board.html create mode 100644 cgi/templates/txt_error.html create mode 100644 cgi/templates/txt_thread.en.html create mode 100644 cgi/templates/txt_thread.html create mode 100644 cgi/templates/txt_threadlist.html create mode 100644 cgi/tenjin.py create mode 100644 cgi/tor.txt create mode 100755 cgi/weabot.py create mode 100644 static/css/buri.css create mode 100644 static/css/cyber.css create mode 100644 static/css/dickgirl.css create mode 100644 static/css/easymodo.css create mode 100644 static/css/futaba.css create mode 100644 static/css/guro.css create mode 100644 static/css/ib.css create mode 100644 static/css/img/0back.png create mode 100644 static/css/img/0info.png create mode 100644 static/css/img/0pc.png create mode 100644 static/css/img/ba.gif create mode 100644 static/css/img/barra_dulce.png create mode 100644 static/css/img/bg_deportes.gif create mode 100644 static/css/img/bg_madera.png create mode 100644 static/css/img/bg_oculto.gif create mode 100644 static/css/img/bgtb.gif create mode 100644 static/css/img/checked.png create mode 100644 static/css/img/cyb.png create mode 100644 static/css/img/cyba.png create mode 100644 static/css/img/fondo2012.gif create mode 100644 static/css/img/green.gif create mode 100644 static/css/img/hand.png create mode 100644 static/css/img/luz.gif create mode 100644 static/css/img/muro.jpg create mode 100644 static/css/img/nieve.png create mode 100644 static/css/img/picnicbdy.gif create mode 100644 static/css/img/picnicbg.gif create mode 100644 static/css/img/picnicbtm.gif create mode 100644 static/css/img/picnicbtn.gif create mode 100644 static/css/img/picnicfg.gif create mode 100644 static/css/img/picnichr.gif create mode 100644 static/css/img/picnicmid.gif create mode 100644 static/css/img/picnicthr1.gif create mode 100644 static/css/img/picnicthr2.gif create mode 100644 static/css/img/picnicthr3.gif create mode 100644 static/css/img/picnictop.gif create mode 100644 static/css/img/scan.png create mode 100644 static/css/img/scroller1.gif create mode 100644 static/css/img/tanasinn.gif create mode 100644 static/css/img/vndb1.jpg create mode 100644 static/css/img/vndb2.jpg create mode 100644 static/css/img/vndb3.png create mode 100644 static/css/kraut.css create mode 100644 static/css/mobile.css create mode 100644 static/css/night.css create mode 100644 static/css/photon.css create mode 100644 static/css/putaba.css create mode 100644 static/css/red.css create mode 100644 static/css/rene.css create mode 100644 static/css/spc/base.css create mode 100644 static/css/spc/halloween.css create mode 100644 static/css/spc/layout.css create mode 100644 static/css/spc/navidad.css create mode 100644 static/css/spc/skeleton.css create mode 100644 static/css/spc/valentin.css create mode 100644 static/css/spc/valentin2.css create mode 100644 static/css/txt/4am.css create mode 100644 static/css/txt/amber.css create mode 100644 static/css/txt/ayashii.css create mode 100644 static/css/txt/baisano.css create mode 100644 static/css/txt/bbs.css create mode 100644 static/css/txt/bios.css create mode 100644 static/css/txt/blue moon.css create mode 100644 static/css/txt/ciber.css create mode 100644 static/css/txt/futanari.css create mode 100644 static/css/txt/headline.css create mode 100644 static/css/txt/postal.css create mode 100644 static/css/txt/sjis.css create mode 100644 static/css/txt/ventanas.css create mode 100644 static/css/vndb.css create mode 100644 static/ico/1372836.gif create mode 100644 static/ico/1k.gif create mode 100644 static/ico/2-1.gif create mode 100644 static/ico/2ppa.gif create mode 100644 static/ico/2syobo_2.gif create mode 100644 static/ico/3-2.gif create mode 100644 static/ico/3.gif create mode 100644 static/ico/3na.gif create mode 100644 static/ico/4-2.gif create mode 100644 static/ico/4248688.gif create mode 100644 static/ico/5007629.gif create mode 100644 static/ico/5296219.gif create mode 100644 static/ico/5ta.gif create mode 100644 static/ico/6396408.gif create mode 100644 static/ico/6za.gif create mode 100644 static/ico/8028885.gif create mode 100644 static/ico/8toushinnomonar16.gif create mode 100644 static/ico/8toushinnomonar32.gif create mode 100644 static/ico/ace.gif create mode 100644 static/ico/af1.gif create mode 100644 static/ico/af2.gif create mode 100644 static/ico/ahya_xmas_2.gif create mode 100644 static/ico/aka.gif create mode 100644 static/ico/ame.gif create mode 100644 static/ico/anime_buun02.gif create mode 100644 static/ico/anime_charhan01.gif create mode 100644 static/ico/anime_charhan02.gif create mode 100644 static/ico/anime_giko01.gif create mode 100644 static/ico/anime_giko04.gif create mode 100644 static/ico/anime_giko10.gif create mode 100644 static/ico/anime_giko11.gif create mode 100644 static/ico/anime_giko12.gif create mode 100644 static/ico/anime_giko13.gif create mode 100644 static/ico/anime_hossyu01.gif create mode 100644 static/ico/anime_imanouchi01.gif create mode 100644 static/ico/anime_iyou02.gif create mode 100644 static/ico/anime_jien01.gif create mode 100644 static/ico/anime_jien02.gif create mode 100644 static/ico/anime_jien03.gif create mode 100644 static/ico/anime_jyorujyu01.gif create mode 100644 static/ico/anime_jyorujyu02.gif create mode 100644 static/ico/anime_jyorujyu03.gif create mode 100644 static/ico/anime_kukkuru01.gif create mode 100644 static/ico/anime_kuma01.gif create mode 100644 static/ico/anime_kumaface01.gif create mode 100644 static/ico/anime_loop.gif create mode 100644 static/ico/anime_marara02.gif create mode 100644 static/ico/anime_matanki01.gif create mode 100644 static/ico/anime_matanki02.gif create mode 100644 static/ico/anime_miruna01.gif create mode 100644 static/ico/anime_monar02.gif create mode 100644 static/ico/anime_monar03.gif create mode 100644 static/ico/anime_monar05.gif create mode 100644 static/ico/anime_morara01.gif create mode 100644 static/ico/anime_morara02.gif create mode 100644 static/ico/anime_morara04.gif create mode 100644 static/ico/anime_nokar01.gif create mode 100644 static/ico/anime_okashi01.gif create mode 100644 static/ico/anime_okashi02.gif create mode 100644 static/ico/anime_onigiri04.gif create mode 100644 static/ico/anime_saitama01.gif create mode 100644 static/ico/anime_saitama02.gif create mode 100644 static/ico/anime_saitama03.gif create mode 100644 static/ico/anime_sasuga01.gif create mode 100644 static/ico/anime_sasuga03.gif create mode 100644 static/ico/anime_sasuga04.gif create mode 100644 static/ico/anime_shii01.gif create mode 100644 static/ico/anime_shii02.gif create mode 100644 static/ico/anime_shii03.gif create mode 100644 static/ico/anime_syobon01.gif create mode 100644 static/ico/anime_syobon03.gif create mode 100644 static/ico/anime_tarn01.gif create mode 100644 static/ico/anime_uwan01.gif create mode 100644 static/ico/anime_uwan02.gif create mode 100644 static/ico/anime_uwan03.gif create mode 100644 static/ico/anime_youkanman01.gif create mode 100644 static/ico/anime_youkanman02.gif create mode 100644 static/ico/anime_youkanman03.gif create mode 100644 static/ico/anime_zonu01.gif create mode 100644 static/ico/anime_zonu02.gif create mode 100644 static/ico/aramaki.gif create mode 100644 static/ico/aroeri-na32.gif create mode 100644 static/ico/asopasomaso.gif create mode 100644 static/ico/bikyakusan32.gif create mode 100644 static/ico/bs.gif create mode 100644 static/ico/button1_03.gif create mode 100644 static/ico/buun.gif create mode 100644 static/ico/chahan.gif create mode 100644 static/ico/dokuo1.gif create mode 100644 static/ico/file2_01.gif create mode 100644 static/ico/fujisan.gif create mode 100644 static/ico/fuun.gif create mode 100644 static/ico/gaku.gif create mode 100644 static/ico/gaku2.gif create mode 100644 static/ico/gaku3.gif create mode 100644 static/ico/gekisya1.gif create mode 100644 static/ico/giko1.gif create mode 100644 static/ico/gikog_gomibako.gif create mode 100644 static/ico/gikog_gyunyupack.gif create mode 100644 static/ico/gikog_pimiento.gif create mode 100644 static/ico/gikoinu.gif create mode 100644 static/ico/gikoneko.gif create mode 100644 static/ico/gikoneko2.gif create mode 100644 static/ico/gikoneko_1.gif create mode 100644 static/ico/gocchin_face.gif create mode 100644 static/ico/gomiopen.gif create mode 100644 static/ico/goo_1.gif create mode 100644 static/ico/goo_3.gif create mode 100644 static/ico/gya-.gif create mode 100644 static/ico/hagenin-shuriken.gif create mode 100644 static/ico/hagurumaou.gif create mode 100644 static/ico/hikky.gif create mode 100644 static/ico/hikky_xmas_2.gif create mode 100644 static/ico/hyou.gif create mode 100644 static/ico/iirasan_face.gif create mode 100644 static/ico/imanouchi_1.gif create mode 100644 static/ico/iyahoo.gif create mode 100644 static/ico/iyou.gif create mode 100644 static/ico/jisakujien_2.gif create mode 100644 static/ico/jisakujien_xmas.gif create mode 100644 static/ico/kantoku1.gif create mode 100644 static/ico/kappappa1.gif create mode 100644 static/ico/kasa-ri.gif create mode 100644 static/ico/kashiwamo-chi32.gif create mode 100644 static/ico/kinokorusensei32.gif create mode 100644 static/ico/kita_.gif create mode 100644 static/ico/kodomona.gif create mode 100644 static/ico/konkon_folder.gif create mode 100644 static/ico/kossorisan.gif create mode 100644 static/ico/kotatu.gif create mode 100644 static/ico/kuma.gif create mode 100644 static/ico/kuma2.gif create mode 100644 static/ico/maimai.gif create mode 100644 static/ico/makotan2_folder.gif create mode 100644 static/ico/mona.gif create mode 100644 static/ico/mona_shiri.gif create mode 100644 static/ico/mona_tya.gif create mode 100644 static/ico/monaazarashi_1.gif create mode 100644 static/ico/namaetukenai.gif create mode 100644 static/ico/naoruyo.gif create mode 100644 static/ico/nida.gif create mode 100644 static/ico/nigete.gif create mode 100644 static/ico/nono_ie.gif create mode 100644 static/ico/nurupo_ga_2.gif create mode 100644 static/ico/onigiri_seito.gif create mode 100644 static/ico/otiketu48.gif create mode 100644 static/ico/pc3.gif create mode 100644 static/ico/pgya.gif create mode 100644 static/ico/sasuga1.gif create mode 100644 static/ico/seito_2.gif create mode 100644 static/ico/soon.gif create mode 100644 static/ico/tasukete.gif create mode 100644 static/ico/torimasu1.gif create mode 100644 static/ico/torimasu2.gif create mode 100644 static/ico/u_ame.gif create mode 100644 static/ico/u_hoshi.gif create mode 100644 static/ico/u_naoruyo_bath.gif create mode 100644 static/ico/u_okotowari_a.gif create mode 100644 static/ico/u_sofa.gif create mode 100644 static/ico/wakannai1.gif create mode 100644 static/ico/yakimochi.gif create mode 100644 static/ico/youkan.gif create mode 100644 static/ico/zonu_1.gif create mode 100644 static/ico/zuzagiko48.gif create mode 100644 static/img/anarkia.jpg create mode 100644 static/img/bai.jpg create mode 100644 static/img/cero.gif create mode 100644 static/img/default.png create mode 100644 static/img/juegos1.jpg create mode 100644 static/img/juegos2.jpg create mode 100644 static/img/juegos3.png create mode 100644 static/img/juegos4.gif create mode 100644 static/img/letras1.png create mode 100644 static/img/letras2.png create mode 100644 static/img/letras3.png create mode 100644 static/img/letras4.jpg create mode 100644 static/img/letras5.jpg create mode 100644 static/img/musica1.jpg create mode 100644 static/img/noticias.png create mode 100644 static/img/old/2d_1.jpg create mode 100644 static/img/old/2d_2.jpg create mode 100644 static/img/old/2d_3.png create mode 100644 static/img/old/2d_4.jpg create mode 100644 static/img/old/argentina1.png create mode 100644 static/img/old/chile1.png create mode 100644 static/img/old/chile2.jpg create mode 100644 static/img/old/g0.jpg create mode 100644 static/img/old/g1.jpg create mode 100644 static/img/old/g2.jpg create mode 100644 static/img/old/g3.jpg create mode 100644 static/img/old/g4.jpg create mode 100644 static/img/old/g5.jpg create mode 100644 static/img/old/peli.jpg create mode 100644 static/img/old/salon2d_3.jpg create mode 100644 static/img/old/salon2d_4.png create mode 100644 static/img/old/salon2d_5.jpg create mode 100644 static/img/old/zine.png create mode 100644 static/img/salon2d_1.png create mode 100644 static/img/salon2d_3.jpg create mode 100644 static/img/salon2d_4.png create mode 100644 static/img/salon2d_5.jpg create mode 100644 static/img/tech1.png create mode 100644 static/img/tech2.jpg create mode 100644 static/img/tech3.png create mode 100644 static/img/tech4.jpg create mode 100644 static/img/tech5.jpg create mode 100644 static/img/tech6.png create mode 100644 static/img/tv1.png create mode 100644 static/img/weird-al.jpg create mode 100644 static/img/world.gif create mode 100644 static/img/zonavip1.jpg create mode 100644 static/img/zonavip2.gif create mode 100644 static/img/zonavip3.png create mode 100644 static/img/zonavip4.jpg create mode 100644 static/img/zonavip5.gif create mode 100644 static/img/zonavip6.png create mode 100644 static/img/zonavip7.gif create mode 100644 static/img/zonavip8.png create mode 100644 static/img/zonavip9.gif create mode 100644 static/img/zonavip9.jpg create mode 100644 static/img/zonavip_halloween.jpg create mode 100644 static/img/zonavip_nav.jpg create mode 100644 static/js/aquiencitas.js create mode 100644 static/js/autorefresh.js create mode 100644 static/js/home.js create mode 100644 static/js/jquery.js create mode 100644 static/js/manage.js create mode 100644 static/js/mobile.js create mode 100644 static/js/paintbbs/PaintBBS-1.1.11.css create mode 100644 static/js/paintbbs/PaintBBS-1.1.11.js create mode 100644 static/js/paintbbs/PaintBBS-1.3.4.css create mode 100644 static/js/paintbbs/PaintBBS-1.3.4.js create mode 100755 static/js/palette_selfy.js create mode 100644 static/js/shobon.js create mode 100644 static/js/tegaki/tegaki.css create mode 100644 static/js/tegaki/tegaki.js create mode 100644 static/js/weabot.js create mode 100644 static/js/weabotxt.js create mode 100644 static/js/wpaint/.gitignore create mode 100644 static/js/wpaint/README.md create mode 100644 static/js/wpaint/bai.js create mode 100644 static/js/wpaint/demo/demo.css create mode 100644 static/js/wpaint/demo/img/facebook-icon.png create mode 100644 static/js/wpaint/demo/img/favicon.ico create mode 100644 static/js/wpaint/demo/img/forkme_right_darkblue.png create mode 100644 static/js/wpaint/demo/img/github-icon.png create mode 100644 static/js/wpaint/demo/img/googleplus-icon.png create mode 100644 static/js/wpaint/demo/img/linkedin-icon.png create mode 100644 static/js/wpaint/demo/img/rss-icon.png create mode 100644 static/js/wpaint/demo/img/stumbleupon-icon.png create mode 100644 static/js/wpaint/demo/img/twitter-icon.png create mode 100644 static/js/wpaint/demo/img/websanova-logo-small-full-black.png create mode 100644 static/js/wpaint/demo/img/youtube-icon.png create mode 100644 static/js/wpaint/gruntfile.js create mode 100644 static/js/wpaint/index.html create mode 100644 static/js/wpaint/lib/jquery.1.10.2.min.js create mode 100644 static/js/wpaint/lib/jquery.ui.core.1.10.3.min.js create mode 100644 static/js/wpaint/lib/jquery.ui.draggable.1.10.3.min.js create mode 100644 static/js/wpaint/lib/jquery.ui.mouse.1.10.3.min.js create mode 100644 static/js/wpaint/lib/jquery.ui.widget.1.10.3.min.js create mode 100644 static/js/wpaint/lib/mixins.styl create mode 100644 static/js/wpaint/lib/wColorPicker.min.css create mode 100644 static/js/wpaint/lib/wColorPicker.min.js create mode 100644 static/js/wpaint/package.json create mode 100644 static/js/wpaint/plugins/file/img/icons-menu-main-file.png create mode 100644 static/js/wpaint/plugins/file/src/wPaint.menu.main.file.js create mode 100644 static/js/wpaint/plugins/file/wPaint.menu.main.file.min.js create mode 100644 static/js/wpaint/plugins/main/img/cursor-bucket.png create mode 100644 static/js/wpaint/plugins/main/img/cursor-crosshair.png create mode 100644 static/js/wpaint/plugins/main/img/cursor-dropper.png create mode 100644 static/js/wpaint/plugins/main/img/cursor-eraser1.png create mode 100644 static/js/wpaint/plugins/main/img/cursor-eraser10.png create mode 100644 static/js/wpaint/plugins/main/img/cursor-eraser2.png create mode 100644 static/js/wpaint/plugins/main/img/cursor-eraser3.png create mode 100644 static/js/wpaint/plugins/main/img/cursor-eraser4.png create mode 100644 static/js/wpaint/plugins/main/img/cursor-eraser5.png create mode 100644 static/js/wpaint/plugins/main/img/cursor-eraser6.png create mode 100644 static/js/wpaint/plugins/main/img/cursor-eraser7.png create mode 100644 static/js/wpaint/plugins/main/img/cursor-eraser8.png create mode 100644 static/js/wpaint/plugins/main/img/cursor-eraser9.png create mode 100644 static/js/wpaint/plugins/main/img/cursor-pencil.png create mode 100644 static/js/wpaint/plugins/main/img/icon-group-arrow.png create mode 100644 static/js/wpaint/plugins/main/img/icons-menu-main.png create mode 100644 static/js/wpaint/plugins/main/src/fillArea.min.js create mode 100644 static/js/wpaint/plugins/main/src/wPaint.menu.main.js create mode 100644 static/js/wpaint/plugins/main/wPaint.menu.main.min.js create mode 100644 static/js/wpaint/plugins/shapes/img/icons-menu-main-shapes.png create mode 100644 static/js/wpaint/plugins/shapes/src/shapes.min.js create mode 100644 static/js/wpaint/plugins/shapes/src/wPaint.menu.main.shapes.js create mode 100644 static/js/wpaint/plugins/shapes/wPaint.menu.main.shapes.min.js create mode 100644 static/js/wpaint/plugins/text/img/icons-menu-text.png create mode 100644 static/js/wpaint/plugins/text/src/wPaint.menu.text.js create mode 100644 static/js/wpaint/plugins/text/wPaint.menu.text.min.js create mode 100644 static/js/wpaint/src/wPaint.css create mode 100644 static/js/wpaint/src/wPaint.js create mode 100644 static/js/wpaint/src/wPaint.utils.js create mode 100644 static/js/wpaint/test/dev.html create mode 100644 static/js/wpaint/test/fullscreen.html create mode 100644 static/js/wpaint/test/upload.php create mode 100644 static/js/wpaint/test/uploads/test1.png create mode 100644 static/js/wpaint/test/uploads/test2.png create mode 100644 static/js/wpaint/test/uploads/test3.png create mode 100644 static/js/wpaint/test/uploads/wPaint.png create mode 100644 static/js/wpaint/wPaint.jquery.json create mode 100644 static/js/wpaint/wPaint.min.css create mode 100644 static/js/wpaint/wPaint.min.js create mode 100644 static/meta/bbs.png create mode 100644 static/meta/faq_1.png create mode 100644 static/meta/faq_2.png create mode 100644 static/meta/faq_3.png create mode 100644 static/meta/ib.png create mode 100644 static/meta/portada_6.jpg create mode 100644 static/meta/portada_7.jpg create mode 100644 static/meta/portada_8.jpg create mode 100644 static/meta/portada_asp.gif create mode 100644 static/meta/portada_cap1.jpg create mode 100644 static/meta/portada_orig5.jpg create mode 100644 static/meta/portada_toesca.jpg create mode 100644 static/meta/portadaphil.jpg create mode 100644 static/meta/primeraportada.png create mode 100644 static/meta/sanvalentin2013.jpg create mode 100644 static/meta/welcome.gif create mode 100644 static/meta/welcome.jpg create mode 100644 static/mime/epub.png create mode 100644 static/mime/epub_small.png create mode 100644 static/mime/mod.png create mode 100644 static/mime/mod_small.png create mode 100644 static/mime/pdf.png create mode 100644 static/mime/pdf_small.png create mode 100644 static/mime/s3m.png create mode 100644 static/mime/s3m_small.png create mode 100644 static/mime/swf.png create mode 100644 static/mime/swf_small.png create mode 100644 static/mime/torrent.png create mode 100644 static/mime/torrent_small.png create mode 100644 static/mime/xm.png create mode 100644 static/mime/xm_small.png diff --git a/cgi/.htaccess b/cgi/.htaccess new file mode 100644 index 0000000..97a4f17 --- /dev/null +++ b/cgi/.htaccess @@ -0,0 +1,9 @@ +AddHandler cgi-script .py +Options +ExecCGI + +# Uncomment if you want pretty URL (ie cgi/post) +#RewriteEngine On +#RewriteBase /cgi/ +#RewriteRule ^weabot\.py/ - [L] +#RewriteRule ^(.*)$ weabot.py/$1 [L] + diff --git a/cgi/BeautifulSoup.py b/cgi/BeautifulSoup.py new file mode 100644 index 0000000..7278215 --- /dev/null +++ b/cgi/BeautifulSoup.py @@ -0,0 +1,2017 @@ +"""Beautiful Soup +Elixir and Tonic +"The Screen-Scraper's Friend" +http://www.crummy.com/software/BeautifulSoup/ + +Beautiful Soup parses a (possibly invalid) XML or HTML document into a +tree representation. It provides methods and Pythonic idioms that make +it easy to navigate, search, and modify the tree. + +A well-formed XML/HTML document yields a well-formed data +structure. An ill-formed XML/HTML document yields a correspondingly +ill-formed data structure. If your document is only locally +well-formed, you can use this library to find and process the +well-formed part of it. + +Beautiful Soup works with Python 2.2 and up. It has no external +dependencies, but you'll have more success at converting data to UTF-8 +if you also install these three packages: + +* chardet, for auto-detecting character encodings + http://chardet.feedparser.org/ +* cjkcodecs and iconv_codec, which add more encodings to the ones supported + by stock Python. + http://cjkpython.i18n.org/ + +Beautiful Soup defines classes for two main parsing strategies: + + * BeautifulStoneSoup, for parsing XML, SGML, or your domain-specific + language that kind of looks like XML. + + * BeautifulSoup, for parsing run-of-the-mill HTML code, be it valid + or invalid. This class has web browser-like heuristics for + obtaining a sensible parse tree in the face of common HTML errors. + +Beautiful Soup also defines a class (UnicodeDammit) for autodetecting +the encoding of an HTML or XML document, and converting it to +Unicode. Much of this code is taken from Mark Pilgrim's Universal Feed Parser. + +For more than you ever wanted to know about Beautiful Soup, see the +documentation: +http://www.crummy.com/software/BeautifulSoup/documentation.html + +Here, have some legalese: + +Copyright (c) 2004-2010, Leonard Richardson + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of the the Beautiful Soup Consortium and All + Night Kosher Bakery nor the names of its contributors may be + used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE, DAMMIT. + +""" +from __future__ import generators + +__author__ = "Leonard Richardson (leonardr@segfault.org)" +__version__ = "3.2.1" +__copyright__ = "Copyright (c) 2004-2012 Leonard Richardson" +__license__ = "New-style BSD" + +from sgmllib import SGMLParser, SGMLParseError +import codecs +import markupbase +import types +import re +import sgmllib +try: + from htmlentitydefs import name2codepoint +except ImportError: + name2codepoint = {} +try: + set +except NameError: + from sets import Set as set + +#These hacks make Beautiful Soup able to parse XML with namespaces +sgmllib.tagfind = re.compile('[a-zA-Z][-_.:a-zA-Z0-9]*') +markupbase._declname_match = re.compile(r'[a-zA-Z][-_.:a-zA-Z0-9]*\s*').match + +DEFAULT_OUTPUT_ENCODING = "utf-8" + +def _match_css_class(str): + """Build a RE to match the given CSS class.""" + return re.compile(r"(^|.*\s)%s($|\s)" % str) + +# First, the classes that represent markup elements. + +class PageElement(object): + """Contains the navigational information for some part of the page + (either a tag or a piece of text)""" + + def _invert(h): + "Cheap function to invert a hash." + i = {} + for k,v in h.items(): + i[v] = k + return i + + XML_ENTITIES_TO_SPECIAL_CHARS = { "apos" : "'", + "quot" : '"', + "amp" : "&", + "lt" : "<", + "gt" : ">" } + + XML_SPECIAL_CHARS_TO_ENTITIES = _invert(XML_ENTITIES_TO_SPECIAL_CHARS) + + def setup(self, parent=None, previous=None): + """Sets up the initial relations between this element and + other elements.""" + self.parent = parent + self.previous = previous + self.next = None + self.previousSibling = None + self.nextSibling = None + if self.parent and self.parent.contents: + self.previousSibling = self.parent.contents[-1] + self.previousSibling.nextSibling = self + + def replaceWith(self, replaceWith): + oldParent = self.parent + myIndex = self.parent.index(self) + if hasattr(replaceWith, "parent")\ + and replaceWith.parent is self.parent: + # We're replacing this element with one of its siblings. + index = replaceWith.parent.index(replaceWith) + if index and index < myIndex: + # Furthermore, it comes before this element. That + # means that when we extract it, the index of this + # element will change. + myIndex = myIndex - 1 + self.extract() + oldParent.insert(myIndex, replaceWith) + + def replaceWithChildren(self): + myParent = self.parent + myIndex = self.parent.index(self) + self.extract() + reversedChildren = list(self.contents) + reversedChildren.reverse() + for child in reversedChildren: + myParent.insert(myIndex, child) + + def extract(self): + """Destructively rips this element out of the tree.""" + if self.parent: + try: + del self.parent.contents[self.parent.index(self)] + except ValueError: + pass + + #Find the two elements that would be next to each other if + #this element (and any children) hadn't been parsed. Connect + #the two. + lastChild = self._lastRecursiveChild() + nextElement = lastChild.next + + if self.previous: + self.previous.next = nextElement + if nextElement: + nextElement.previous = self.previous + self.previous = None + lastChild.next = None + + self.parent = None + if self.previousSibling: + self.previousSibling.nextSibling = self.nextSibling + if self.nextSibling: + self.nextSibling.previousSibling = self.previousSibling + self.previousSibling = self.nextSibling = None + return self + + def _lastRecursiveChild(self): + "Finds the last element beneath this object to be parsed." + lastChild = self + while hasattr(lastChild, 'contents') and lastChild.contents: + lastChild = lastChild.contents[-1] + return lastChild + + def insert(self, position, newChild): + if isinstance(newChild, basestring) \ + and not isinstance(newChild, NavigableString): + newChild = NavigableString(newChild) + + position = min(position, len(self.contents)) + if hasattr(newChild, 'parent') and newChild.parent is not None: + # We're 'inserting' an element that's already one + # of this object's children. + if newChild.parent is self: + index = self.index(newChild) + if index > position: + # Furthermore we're moving it further down the + # list of this object's children. That means that + # when we extract this element, our target index + # will jump down one. + position = position - 1 + newChild.extract() + + newChild.parent = self + previousChild = None + if position == 0: + newChild.previousSibling = None + newChild.previous = self + else: + previousChild = self.contents[position-1] + newChild.previousSibling = previousChild + newChild.previousSibling.nextSibling = newChild + newChild.previous = previousChild._lastRecursiveChild() + if newChild.previous: + newChild.previous.next = newChild + + newChildsLastElement = newChild._lastRecursiveChild() + + if position >= len(self.contents): + newChild.nextSibling = None + + parent = self + parentsNextSibling = None + while not parentsNextSibling: + parentsNextSibling = parent.nextSibling + parent = parent.parent + if not parent: # This is the last element in the document. + break + if parentsNextSibling: + newChildsLastElement.next = parentsNextSibling + else: + newChildsLastElement.next = None + else: + nextChild = self.contents[position] + newChild.nextSibling = nextChild + if newChild.nextSibling: + newChild.nextSibling.previousSibling = newChild + newChildsLastElement.next = nextChild + + if newChildsLastElement.next: + newChildsLastElement.next.previous = newChildsLastElement + self.contents.insert(position, newChild) + + def append(self, tag): + """Appends the given tag to the contents of this tag.""" + self.insert(len(self.contents), tag) + + def findNext(self, name=None, attrs={}, text=None, **kwargs): + """Returns the first item that matches the given criteria and + appears after this Tag in the document.""" + return self._findOne(self.findAllNext, name, attrs, text, **kwargs) + + def findAllNext(self, name=None, attrs={}, text=None, limit=None, + **kwargs): + """Returns all items that match the given criteria and appear + after this Tag in the document.""" + return self._findAll(name, attrs, text, limit, self.nextGenerator, + **kwargs) + + def findNextSibling(self, name=None, attrs={}, text=None, **kwargs): + """Returns the closest sibling to this Tag that matches the + given criteria and appears after this Tag in the document.""" + return self._findOne(self.findNextSiblings, name, attrs, text, + **kwargs) + + def findNextSiblings(self, name=None, attrs={}, text=None, limit=None, + **kwargs): + """Returns the siblings of this Tag that match the given + criteria and appear after this Tag in the document.""" + return self._findAll(name, attrs, text, limit, + self.nextSiblingGenerator, **kwargs) + fetchNextSiblings = findNextSiblings # Compatibility with pre-3.x + + def findPrevious(self, name=None, attrs={}, text=None, **kwargs): + """Returns the first item that matches the given criteria and + appears before this Tag in the document.""" + return self._findOne(self.findAllPrevious, name, attrs, text, **kwargs) + + def findAllPrevious(self, name=None, attrs={}, text=None, limit=None, + **kwargs): + """Returns all items that match the given criteria and appear + before this Tag in the document.""" + return self._findAll(name, attrs, text, limit, self.previousGenerator, + **kwargs) + fetchPrevious = findAllPrevious # Compatibility with pre-3.x + + def findPreviousSibling(self, name=None, attrs={}, text=None, **kwargs): + """Returns the closest sibling to this Tag that matches the + given criteria and appears before this Tag in the document.""" + return self._findOne(self.findPreviousSiblings, name, attrs, text, + **kwargs) + + def findPreviousSiblings(self, name=None, attrs={}, text=None, + limit=None, **kwargs): + """Returns the siblings of this Tag that match the given + criteria and appear before this Tag in the document.""" + return self._findAll(name, attrs, text, limit, + self.previousSiblingGenerator, **kwargs) + fetchPreviousSiblings = findPreviousSiblings # Compatibility with pre-3.x + + def findParent(self, name=None, attrs={}, **kwargs): + """Returns the closest parent of this Tag that matches the given + criteria.""" + # NOTE: We can't use _findOne because findParents takes a different + # set of arguments. + r = None + l = self.findParents(name, attrs, 1) + if l: + r = l[0] + return r + + def findParents(self, name=None, attrs={}, limit=None, **kwargs): + """Returns the parents of this Tag that match the given + criteria.""" + + return self._findAll(name, attrs, None, limit, self.parentGenerator, + **kwargs) + fetchParents = findParents # Compatibility with pre-3.x + + #These methods do the real heavy lifting. + + def _findOne(self, method, name, attrs, text, **kwargs): + r = None + l = method(name, attrs, text, 1, **kwargs) + if l: + r = l[0] + return r + + def _findAll(self, name, attrs, text, limit, generator, **kwargs): + "Iterates over a generator looking for things that match." + + if isinstance(name, SoupStrainer): + strainer = name + # (Possibly) special case some findAll*(...) searches + elif text is None and not limit and not attrs and not kwargs: + # findAll*(True) + if name is True: + return [element for element in generator() + if isinstance(element, Tag)] + # findAll*('tag-name') + elif isinstance(name, basestring): + return [element for element in generator() + if isinstance(element, Tag) and + element.name == name] + else: + strainer = SoupStrainer(name, attrs, text, **kwargs) + # Build a SoupStrainer + else: + strainer = SoupStrainer(name, attrs, text, **kwargs) + results = ResultSet(strainer) + g = generator() + while True: + try: + i = g.next() + except StopIteration: + break + if i: + found = strainer.search(i) + if found: + results.append(found) + if limit and len(results) >= limit: + break + return results + + #These Generators can be used to navigate starting from both + #NavigableStrings and Tags. + def nextGenerator(self): + i = self + while i is not None: + i = i.next + yield i + + def nextSiblingGenerator(self): + i = self + while i is not None: + i = i.nextSibling + yield i + + def previousGenerator(self): + i = self + while i is not None: + i = i.previous + yield i + + def previousSiblingGenerator(self): + i = self + while i is not None: + i = i.previousSibling + yield i + + def parentGenerator(self): + i = self + while i is not None: + i = i.parent + yield i + + # Utility methods + def substituteEncoding(self, str, encoding=None): + encoding = encoding or "utf-8" + return str.replace("%SOUP-ENCODING%", encoding) + + def toEncoding(self, s, encoding=None): + """Encodes an object to a string in some encoding, or to Unicode. + .""" + if isinstance(s, unicode): + if encoding: + s = s.encode(encoding) + elif isinstance(s, str): + if encoding: + s = s.encode(encoding) + else: + s = unicode(s) + else: + if encoding: + s = self.toEncoding(str(s), encoding) + else: + s = unicode(s) + return s + + BARE_AMPERSAND_OR_BRACKET = re.compile("([<>]|" + + "&(?!#\d+;|#x[0-9a-fA-F]+;|\w+;)" + + ")") + + def _sub_entity(self, x): + """Used with a regular expression to substitute the + appropriate XML entity for an XML special character.""" + return "&" + self.XML_SPECIAL_CHARS_TO_ENTITIES[x.group(0)[0]] + ";" + + +class NavigableString(unicode, PageElement): + + def __new__(cls, value): + """Create a new NavigableString. + + When unpickling a NavigableString, this method is called with + the string in DEFAULT_OUTPUT_ENCODING. That encoding needs to be + passed in to the superclass's __new__ or the superclass won't know + how to handle non-ASCII characters. + """ + if isinstance(value, unicode): + return unicode.__new__(cls, value) + return unicode.__new__(cls, value, DEFAULT_OUTPUT_ENCODING) + + def __getnewargs__(self): + return (NavigableString.__str__(self),) + + def __getattr__(self, attr): + """text.string gives you text. This is for backwards + compatibility for Navigable*String, but for CData* it lets you + get the string without the CData wrapper.""" + if attr == 'string': + return self + else: + raise AttributeError, "'%s' object has no attribute '%s'" % (self.__class__.__name__, attr) + + def __unicode__(self): + return str(self).decode(DEFAULT_OUTPUT_ENCODING) + + def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING): + # Substitute outgoing XML entities. + data = self.BARE_AMPERSAND_OR_BRACKET.sub(self._sub_entity, self) + if encoding: + return data.encode(encoding) + else: + return data + +class CData(NavigableString): + + def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING): + return "" % NavigableString.__str__(self, encoding) + +class ProcessingInstruction(NavigableString): + def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING): + output = self + if "%SOUP-ENCODING%" in output: + output = self.substituteEncoding(output, encoding) + return "" % self.toEncoding(output, encoding) + +class Comment(NavigableString): + def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING): + return "" % NavigableString.__str__(self, encoding) + +class Declaration(NavigableString): + def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING): + return "" % NavigableString.__str__(self, encoding) + +class Tag(PageElement): + + """Represents a found HTML tag with its attributes and contents.""" + + def _convertEntities(self, match): + """Used in a call to re.sub to replace HTML, XML, and numeric + entities with the appropriate Unicode characters. If HTML + entities are being converted, any unrecognized entities are + escaped.""" + x = match.group(1) + if self.convertHTMLEntities and x in name2codepoint: + return unichr(name2codepoint[x]) + elif x in self.XML_ENTITIES_TO_SPECIAL_CHARS: + if self.convertXMLEntities: + return self.XML_ENTITIES_TO_SPECIAL_CHARS[x] + else: + return u'&%s;' % x + elif len(x) > 0 and x[0] == '#': + # Handle numeric entities + if len(x) > 1 and x[1] == 'x': + return unichr(int(x[2:], 16)) + else: + return unichr(int(x[1:])) + + elif self.escapeUnrecognizedEntities: + return u'&%s;' % x + else: + return u'&%s;' % x + + def __init__(self, parser, name, attrs=None, parent=None, + previous=None): + "Basic constructor." + + # We don't actually store the parser object: that lets extracted + # chunks be garbage-collected + self.parserClass = parser.__class__ + self.isSelfClosing = parser.isSelfClosingTag(name) + self.name = name + if attrs is None: + attrs = [] + elif isinstance(attrs, dict): + attrs = attrs.items() + self.attrs = attrs + self.contents = [] + self.setup(parent, previous) + self.hidden = False + self.containsSubstitutions = False + self.convertHTMLEntities = parser.convertHTMLEntities + self.convertXMLEntities = parser.convertXMLEntities + self.escapeUnrecognizedEntities = parser.escapeUnrecognizedEntities + + # Convert any HTML, XML, or numeric entities in the attribute values. + convert = lambda(k, val): (k, + re.sub("&(#\d+|#x[0-9a-fA-F]+|\w+);", + self._convertEntities, + val)) + self.attrs = map(convert, self.attrs) + + def getString(self): + if (len(self.contents) == 1 + and isinstance(self.contents[0], NavigableString)): + return self.contents[0] + + def setString(self, string): + """Replace the contents of the tag with a string""" + self.clear() + self.append(string) + + string = property(getString, setString) + + def getText(self, separator=u""): + if not len(self.contents): + return u"" + stopNode = self._lastRecursiveChild().next + strings = [] + current = self.contents[0] + while current is not stopNode: + if isinstance(current, NavigableString): + strings.append(current.strip()) + current = current.next + return separator.join(strings) + + text = property(getText) + + def get(self, key, default=None): + """Returns the value of the 'key' attribute for the tag, or + the value given for 'default' if it doesn't have that + attribute.""" + return self._getAttrMap().get(key, default) + + def clear(self): + """Extract all children.""" + for child in self.contents[:]: + child.extract() + + def index(self, element): + for i, child in enumerate(self.contents): + if child is element: + return i + raise ValueError("Tag.index: element not in tag") + + def has_key(self, key): + return self._getAttrMap().has_key(key) + + def __getitem__(self, key): + """tag[key] returns the value of the 'key' attribute for the tag, + and throws an exception if it's not there.""" + return self._getAttrMap()[key] + + def __iter__(self): + "Iterating over a tag iterates over its contents." + return iter(self.contents) + + def __len__(self): + "The length of a tag is the length of its list of contents." + return len(self.contents) + + def __contains__(self, x): + return x in self.contents + + def __nonzero__(self): + "A tag is non-None even if it has no contents." + return True + + def __setitem__(self, key, value): + """Setting tag[key] sets the value of the 'key' attribute for the + tag.""" + self._getAttrMap() + self.attrMap[key] = value + found = False + for i in range(0, len(self.attrs)): + if self.attrs[i][0] == key: + self.attrs[i] = (key, value) + found = True + if not found: + self.attrs.append((key, value)) + self._getAttrMap()[key] = value + + def __delitem__(self, key): + "Deleting tag[key] deletes all 'key' attributes for the tag." + for item in self.attrs: + if item[0] == key: + self.attrs.remove(item) + #We don't break because bad HTML can define the same + #attribute multiple times. + self._getAttrMap() + if self.attrMap.has_key(key): + del self.attrMap[key] + + def __call__(self, *args, **kwargs): + """Calling a tag like a function is the same as calling its + findAll() method. Eg. tag('a') returns a list of all the A tags + found within this tag.""" + return apply(self.findAll, args, kwargs) + + def __getattr__(self, tag): + #print "Getattr %s.%s" % (self.__class__, tag) + if len(tag) > 3 and tag.rfind('Tag') == len(tag)-3: + return self.find(tag[:-3]) + elif tag.find('__') != 0: + return self.find(tag) + raise AttributeError, "'%s' object has no attribute '%s'" % (self.__class__, tag) + + def __eq__(self, other): + """Returns true iff this tag has the same name, the same attributes, + and the same contents (recursively) as the given tag. + + NOTE: right now this will return false if two tags have the + same attributes in a different order. Should this be fixed?""" + if other is self: + return True + if not hasattr(other, 'name') or not hasattr(other, 'attrs') or not hasattr(other, 'contents') or self.name != other.name or self.attrs != other.attrs or len(self) != len(other): + return False + for i in range(0, len(self.contents)): + if self.contents[i] != other.contents[i]: + return False + return True + + def __ne__(self, other): + """Returns true iff this tag is not identical to the other tag, + as defined in __eq__.""" + return not self == other + + def __repr__(self, encoding=DEFAULT_OUTPUT_ENCODING): + """Renders this tag as a string.""" + return self.__str__(encoding) + + def __unicode__(self): + return self.__str__(None) + + def __str__(self, encoding=DEFAULT_OUTPUT_ENCODING, + prettyPrint=False, indentLevel=0): + """Returns a string or Unicode representation of this tag and + its contents. To get Unicode, pass None for encoding. + + NOTE: since Python's HTML parser consumes whitespace, this + method is not certain to reproduce the whitespace present in + the original string.""" + + encodedName = self.toEncoding(self.name, encoding) + + attrs = [] + if self.attrs: + for key, val in self.attrs: + fmt = '%s="%s"' + if isinstance(val, basestring): + if self.containsSubstitutions and '%SOUP-ENCODING%' in val: + val = self.substituteEncoding(val, encoding) + + # The attribute value either: + # + # * Contains no embedded double quotes or single quotes. + # No problem: we enclose it in double quotes. + # * Contains embedded single quotes. No problem: + # double quotes work here too. + # * Contains embedded double quotes. No problem: + # we enclose it in single quotes. + # * Embeds both single _and_ double quotes. This + # can't happen naturally, but it can happen if + # you modify an attribute value after parsing + # the document. Now we have a bit of a + # problem. We solve it by enclosing the + # attribute in single quotes, and escaping any + # embedded single quotes to XML entities. + if '"' in val: + fmt = "%s='%s'" + if "'" in val: + # TODO: replace with apos when + # appropriate. + val = val.replace("'", "&squot;") + + # Now we're okay w/r/t quotes. But the attribute + # value might also contain angle brackets, or + # ampersands that aren't part of entities. We need + # to escape those to XML entities too. + val = self.BARE_AMPERSAND_OR_BRACKET.sub(self._sub_entity, val) + + attrs.append(fmt % (self.toEncoding(key, encoding), + self.toEncoding(val, encoding))) + close = '' + closeTag = '' + if self.isSelfClosing: + close = ' /' + else: + closeTag = '' % encodedName + + indentTag, indentContents = 0, 0 + if prettyPrint: + indentTag = indentLevel + space = (' ' * (indentTag-1)) + indentContents = indentTag + 1 + contents = self.renderContents(encoding, prettyPrint, indentContents) + if self.hidden: + s = contents + else: + s = [] + attributeString = '' + if attrs: + attributeString = ' ' + ' '.join(attrs) + if prettyPrint: + s.append(space) + s.append('<%s%s%s>' % (encodedName, attributeString, close)) + if prettyPrint: + s.append("\n") + s.append(contents) + if prettyPrint and contents and contents[-1] != "\n": + s.append("\n") + if prettyPrint and closeTag: + s.append(space) + s.append(closeTag) + if prettyPrint and closeTag and self.nextSibling: + s.append("\n") + s = ''.join(s) + return s + + def decompose(self): + """Recursively destroys the contents of this tree.""" + self.extract() + if len(self.contents) == 0: + return + current = self.contents[0] + while current is not None: + next = current.next + if isinstance(current, Tag): + del current.contents[:] + current.parent = None + current.previous = None + current.previousSibling = None + current.next = None + current.nextSibling = None + current = next + + def prettify(self, encoding=DEFAULT_OUTPUT_ENCODING): + return self.__str__(encoding, True) + + def renderContents(self, encoding=DEFAULT_OUTPUT_ENCODING, + prettyPrint=False, indentLevel=0): + """Renders the contents of this tag as a string in the given + encoding. If encoding is None, returns a Unicode string..""" + s=[] + for c in self: + text = None + if isinstance(c, NavigableString): + text = c.__str__(encoding) + elif isinstance(c, Tag): + s.append(c.__str__(encoding, prettyPrint, indentLevel)) + if text and prettyPrint: + text = text.strip() + if text: + if prettyPrint: + s.append(" " * (indentLevel-1)) + s.append(text) + if prettyPrint: + s.append("\n") + return ''.join(s) + + #Soup methods + + def find(self, name=None, attrs={}, recursive=True, text=None, + **kwargs): + """Return only the first child of this Tag matching the given + criteria.""" + r = None + l = self.findAll(name, attrs, recursive, text, 1, **kwargs) + if l: + r = l[0] + return r + findChild = find + + def findAll(self, name=None, attrs={}, recursive=True, text=None, + limit=None, **kwargs): + """Extracts a list of Tag objects that match the given + criteria. You can specify the name of the Tag and any + attributes you want the Tag to have. + + The value of a key-value pair in the 'attrs' map can be a + string, a list of strings, a regular expression object, or a + callable that takes a string and returns whether or not the + string matches for some custom definition of 'matches'. The + same is true of the tag name.""" + generator = self.recursiveChildGenerator + if not recursive: + generator = self.childGenerator + return self._findAll(name, attrs, text, limit, generator, **kwargs) + findChildren = findAll + + # Pre-3.x compatibility methods + first = find + fetch = findAll + + def fetchText(self, text=None, recursive=True, limit=None): + return self.findAll(text=text, recursive=recursive, limit=limit) + + def firstText(self, text=None, recursive=True): + return self.find(text=text, recursive=recursive) + + #Private methods + + def _getAttrMap(self): + """Initializes a map representation of this tag's attributes, + if not already initialized.""" + if not getattr(self, 'attrMap'): + self.attrMap = {} + for (key, value) in self.attrs: + self.attrMap[key] = value + return self.attrMap + + #Generator methods + def childGenerator(self): + # Just use the iterator from the contents + return iter(self.contents) + + def recursiveChildGenerator(self): + if not len(self.contents): + raise StopIteration + stopNode = self._lastRecursiveChild().next + current = self.contents[0] + while current is not stopNode: + yield current + current = current.next + + +# Next, a couple classes to represent queries and their results. +class SoupStrainer: + """Encapsulates a number of ways of matching a markup element (tag or + text).""" + + def __init__(self, name=None, attrs={}, text=None, **kwargs): + self.name = name + if isinstance(attrs, basestring): + kwargs['class'] = _match_css_class(attrs) + attrs = None + if kwargs: + if attrs: + attrs = attrs.copy() + attrs.update(kwargs) + else: + attrs = kwargs + self.attrs = attrs + self.text = text + + def __str__(self): + if self.text: + return self.text + else: + return "%s|%s" % (self.name, self.attrs) + + def searchTag(self, markupName=None, markupAttrs={}): + found = None + markup = None + if isinstance(markupName, Tag): + markup = markupName + markupAttrs = markup + callFunctionWithTagData = callable(self.name) \ + and not isinstance(markupName, Tag) + + if (not self.name) \ + or callFunctionWithTagData \ + or (markup and self._matches(markup, self.name)) \ + or (not markup and self._matches(markupName, self.name)): + if callFunctionWithTagData: + match = self.name(markupName, markupAttrs) + else: + match = True + markupAttrMap = None + for attr, matchAgainst in self.attrs.items(): + if not markupAttrMap: + if hasattr(markupAttrs, 'get'): + markupAttrMap = markupAttrs + else: + markupAttrMap = {} + for k,v in markupAttrs: + markupAttrMap[k] = v + attrValue = markupAttrMap.get(attr) + if not self._matches(attrValue, matchAgainst): + match = False + break + if match: + if markup: + found = markup + else: + found = markupName + return found + + def search(self, markup): + #print 'looking for %s in %s' % (self, markup) + found = None + # If given a list of items, scan it for a text element that + # matches. + if hasattr(markup, "__iter__") \ + and not isinstance(markup, Tag): + for element in markup: + if isinstance(element, NavigableString) \ + and self.search(element): + found = element + break + # If it's a Tag, make sure its name or attributes match. + # Don't bother with Tags if we're searching for text. + elif isinstance(markup, Tag): + if not self.text: + found = self.searchTag(markup) + # If it's text, make sure the text matches. + elif isinstance(markup, NavigableString) or \ + isinstance(markup, basestring): + if self._matches(markup, self.text): + found = markup + else: + raise Exception, "I don't know how to match against a %s" \ + % markup.__class__ + return found + + def _matches(self, markup, matchAgainst): + #print "Matching %s against %s" % (markup, matchAgainst) + result = False + if matchAgainst is True: + result = markup is not None + elif callable(matchAgainst): + result = matchAgainst(markup) + else: + #Custom match methods take the tag as an argument, but all + #other ways of matching match the tag name as a string. + if isinstance(markup, Tag): + markup = markup.name + if markup and not isinstance(markup, basestring): + markup = unicode(markup) + #Now we know that chunk is either a string, or None. + if hasattr(matchAgainst, 'match'): + # It's a regexp object. + result = markup and matchAgainst.search(markup) + elif hasattr(matchAgainst, '__iter__'): # list-like + result = markup in matchAgainst + elif hasattr(matchAgainst, 'items'): + result = markup.has_key(matchAgainst) + elif matchAgainst and isinstance(markup, basestring): + if isinstance(markup, unicode): + matchAgainst = unicode(matchAgainst) + else: + matchAgainst = str(matchAgainst) + + if not result: + result = matchAgainst == markup + return result + +class ResultSet(list): + """A ResultSet is just a list that keeps track of the SoupStrainer + that created it.""" + def __init__(self, source): + list.__init__([]) + self.source = source + +# Now, some helper functions. + +def buildTagMap(default, *args): + """Turns a list of maps, lists, or scalars into a single map. + Used to build the SELF_CLOSING_TAGS, NESTABLE_TAGS, and + NESTING_RESET_TAGS maps out of lists and partial maps.""" + built = {} + for portion in args: + if hasattr(portion, 'items'): + #It's a map. Merge it. + for k,v in portion.items(): + built[k] = v + elif hasattr(portion, '__iter__'): # is a list + #It's a list. Map each item to the default. + for k in portion: + built[k] = default + else: + #It's a scalar. Map it to the default. + built[portion] = default + return built + +# Now, the parser classes. + +class BeautifulStoneSoup(Tag, SGMLParser): + + """This class contains the basic parser and search code. It defines + a parser that knows nothing about tag behavior except for the + following: + + You can't close a tag without closing all the tags it encloses. + That is, "" actually means + "". + + [Another possible explanation is "", but since + this class defines no SELF_CLOSING_TAGS, it will never use that + explanation.] + + This class is useful for parsing XML or made-up markup languages, + or when BeautifulSoup makes an assumption counter to what you were + expecting.""" + + SELF_CLOSING_TAGS = {} + NESTABLE_TAGS = {} + RESET_NESTING_TAGS = {} + QUOTE_TAGS = {} + PRESERVE_WHITESPACE_TAGS = [] + + MARKUP_MASSAGE = [(re.compile('(<[^<>]*)/>'), + lambda x: x.group(1) + ' />'), + (re.compile(']*)>'), + lambda x: '') + ] + + ROOT_TAG_NAME = u'[document]' + + HTML_ENTITIES = "html" + XML_ENTITIES = "xml" + XHTML_ENTITIES = "xhtml" + # TODO: This only exists for backwards-compatibility + ALL_ENTITIES = XHTML_ENTITIES + + # Used when determining whether a text node is all whitespace and + # can be replaced with a single space. A text node that contains + # fancy Unicode spaces (usually non-breaking) should be left + # alone. + STRIP_ASCII_SPACES = { 9: None, 10: None, 12: None, 13: None, 32: None, } + + def __init__(self, markup="", parseOnlyThese=None, fromEncoding=None, + markupMassage=True, smartQuotesTo=XML_ENTITIES, + convertEntities=None, selfClosingTags=None, isHTML=False): + """The Soup object is initialized as the 'root tag', and the + provided markup (which can be a string or a file-like object) + is fed into the underlying parser. + + sgmllib will process most bad HTML, and the BeautifulSoup + class has some tricks for dealing with some HTML that kills + sgmllib, but Beautiful Soup can nonetheless choke or lose data + if your data uses self-closing tags or declarations + incorrectly. + + By default, Beautiful Soup uses regexes to sanitize input, + avoiding the vast majority of these problems. If the problems + don't apply to you, pass in False for markupMassage, and + you'll get better performance. + + The default parser massage techniques fix the two most common + instances of invalid HTML that choke sgmllib: + +
(No space between name of closing tag and tag close) + (Extraneous whitespace in declaration) + + You can pass in a custom list of (RE object, replace method) + tuples to get Beautiful Soup to scrub your input the way you + want.""" + + self.parseOnlyThese = parseOnlyThese + self.fromEncoding = fromEncoding + self.smartQuotesTo = smartQuotesTo + self.convertEntities = convertEntities + # Set the rules for how we'll deal with the entities we + # encounter + if self.convertEntities: + # It doesn't make sense to convert encoded characters to + # entities even while you're converting entities to Unicode. + # Just convert it all to Unicode. + self.smartQuotesTo = None + if convertEntities == self.HTML_ENTITIES: + self.convertXMLEntities = False + self.convertHTMLEntities = True + self.escapeUnrecognizedEntities = True + elif convertEntities == self.XHTML_ENTITIES: + self.convertXMLEntities = True + self.convertHTMLEntities = True + self.escapeUnrecognizedEntities = False + elif convertEntities == self.XML_ENTITIES: + self.convertXMLEntities = True + self.convertHTMLEntities = False + self.escapeUnrecognizedEntities = False + else: + self.convertXMLEntities = False + self.convertHTMLEntities = False + self.escapeUnrecognizedEntities = False + + self.instanceSelfClosingTags = buildTagMap(None, selfClosingTags) + SGMLParser.__init__(self) + + if hasattr(markup, 'read'): # It's a file-type object. + markup = markup.read() + self.markup = markup + self.markupMassage = markupMassage + try: + self._feed(isHTML=isHTML) + except StopParsing: + pass + self.markup = None # The markup can now be GCed + + def convert_charref(self, name): + """This method fixes a bug in Python's SGMLParser.""" + try: + n = int(name) + except ValueError: + return + if not 0 <= n <= 127 : # ASCII ends at 127, not 255 + return + return self.convert_codepoint(n) + + def _feed(self, inDocumentEncoding=None, isHTML=False): + # Convert the document to Unicode. + markup = self.markup + if isinstance(markup, unicode): + if not hasattr(self, 'originalEncoding'): + self.originalEncoding = None + else: + dammit = UnicodeDammit\ + (markup, [self.fromEncoding, inDocumentEncoding], + smartQuotesTo=self.smartQuotesTo, isHTML=isHTML) + markup = dammit.unicode + self.originalEncoding = dammit.originalEncoding + self.declaredHTMLEncoding = dammit.declaredHTMLEncoding + if markup: + if self.markupMassage: + if not hasattr(self.markupMassage, "__iter__"): + self.markupMassage = self.MARKUP_MASSAGE + for fix, m in self.markupMassage: + markup = fix.sub(m, markup) + # TODO: We get rid of markupMassage so that the + # soup object can be deepcopied later on. Some + # Python installations can't copy regexes. If anyone + # was relying on the existence of markupMassage, this + # might cause problems. + del(self.markupMassage) + self.reset() + + SGMLParser.feed(self, markup) + # Close out any unfinished strings and close all the open tags. + self.endData() + while self.currentTag.name != self.ROOT_TAG_NAME: + self.popTag() + + def __getattr__(self, methodName): + """This method routes method call requests to either the SGMLParser + superclass or the Tag superclass, depending on the method name.""" + #print "__getattr__ called on %s.%s" % (self.__class__, methodName) + + if methodName.startswith('start_') or methodName.startswith('end_') \ + or methodName.startswith('do_'): + return SGMLParser.__getattr__(self, methodName) + elif not methodName.startswith('__'): + return Tag.__getattr__(self, methodName) + else: + raise AttributeError + + def isSelfClosingTag(self, name): + """Returns true iff the given string is the name of a + self-closing tag according to this parser.""" + return self.SELF_CLOSING_TAGS.has_key(name) \ + or self.instanceSelfClosingTags.has_key(name) + + def reset(self): + Tag.__init__(self, self, self.ROOT_TAG_NAME) + self.hidden = 1 + SGMLParser.reset(self) + self.currentData = [] + self.currentTag = None + self.tagStack = [] + self.quoteStack = [] + self.pushTag(self) + + def popTag(self): + tag = self.tagStack.pop() + + #print "Pop", tag.name + if self.tagStack: + self.currentTag = self.tagStack[-1] + return self.currentTag + + def pushTag(self, tag): + #print "Push", tag.name + if self.currentTag: + self.currentTag.contents.append(tag) + self.tagStack.append(tag) + self.currentTag = self.tagStack[-1] + + def endData(self, containerClass=NavigableString): + if self.currentData: + currentData = u''.join(self.currentData) + if (currentData.translate(self.STRIP_ASCII_SPACES) == '' and + not set([tag.name for tag in self.tagStack]).intersection( + self.PRESERVE_WHITESPACE_TAGS)): + if '\n' in currentData: + currentData = '\n' + else: + currentData = ' ' + self.currentData = [] + if self.parseOnlyThese and len(self.tagStack) <= 1 and \ + (not self.parseOnlyThese.text or \ + not self.parseOnlyThese.search(currentData)): + return + o = containerClass(currentData) + o.setup(self.currentTag, self.previous) + if self.previous: + self.previous.next = o + self.previous = o + self.currentTag.contents.append(o) + + + def _popToTag(self, name, inclusivePop=True): + """Pops the tag stack up to and including the most recent + instance of the given tag. If inclusivePop is false, pops the tag + stack up to but *not* including the most recent instqance of + the given tag.""" + #print "Popping to %s" % name + if name == self.ROOT_TAG_NAME: + return + + numPops = 0 + mostRecentTag = None + for i in range(len(self.tagStack)-1, 0, -1): + if name == self.tagStack[i].name: + numPops = len(self.tagStack)-i + break + if not inclusivePop: + numPops = numPops - 1 + + for i in range(0, numPops): + mostRecentTag = self.popTag() + return mostRecentTag + + def _smartPop(self, name): + + """We need to pop up to the previous tag of this type, unless + one of this tag's nesting reset triggers comes between this + tag and the previous tag of this type, OR unless this tag is a + generic nesting trigger and another generic nesting trigger + comes between this tag and the previous tag of this type. + + Examples: +

FooBar *

* should pop to 'p', not 'b'. +

FooBar *

* should pop to 'table', not 'p'. +

Foo

Bar *

* should pop to 'tr', not 'p'. + +

    • *
    • * should pop to 'ul', not the first 'li'. +
  • ** should pop to 'table', not the first 'tr' + tag should + implicitly close the previous tag within the same
    ** should pop to 'tr', not the first 'td' + """ + + nestingResetTriggers = self.NESTABLE_TAGS.get(name) + isNestable = nestingResetTriggers != None + isResetNesting = self.RESET_NESTING_TAGS.has_key(name) + popTo = None + inclusive = True + for i in range(len(self.tagStack)-1, 0, -1): + p = self.tagStack[i] + if (not p or p.name == name) and not isNestable: + #Non-nestable tags get popped to the top or to their + #last occurance. + popTo = name + break + if (nestingResetTriggers is not None + and p.name in nestingResetTriggers) \ + or (nestingResetTriggers is None and isResetNesting + and self.RESET_NESTING_TAGS.has_key(p.name)): + + #If we encounter one of the nesting reset triggers + #peculiar to this tag, or we encounter another tag + #that causes nesting to reset, pop up to but not + #including that tag. + popTo = p.name + inclusive = False + break + p = p.parent + if popTo: + self._popToTag(popTo, inclusive) + + def unknown_starttag(self, name, attrs, selfClosing=0): + #print "Start tag %s: %s" % (name, attrs) + if self.quoteStack: + #This is not a real tag. + #print "<%s> is not real!" % name + attrs = ''.join([' %s="%s"' % (x, y) for x, y in attrs]) + self.handle_data('<%s%s>' % (name, attrs)) + return + self.endData() + + if not self.isSelfClosingTag(name) and not selfClosing: + self._smartPop(name) + + if self.parseOnlyThese and len(self.tagStack) <= 1 \ + and (self.parseOnlyThese.text or not self.parseOnlyThese.searchTag(name, attrs)): + return + + tag = Tag(self, name, attrs, self.currentTag, self.previous) + if self.previous: + self.previous.next = tag + self.previous = tag + self.pushTag(tag) + if selfClosing or self.isSelfClosingTag(name): + self.popTag() + if name in self.QUOTE_TAGS: + #print "Beginning quote (%s)" % name + self.quoteStack.append(name) + self.literal = 1 + return tag + + def unknown_endtag(self, name): + #print "End tag %s" % name + if self.quoteStack and self.quoteStack[-1] != name: + #This is not a real end tag. + #print " is not real!" % name + self.handle_data('' % name) + return + self.endData() + self._popToTag(name) + if self.quoteStack and self.quoteStack[-1] == name: + self.quoteStack.pop() + self.literal = (len(self.quoteStack) > 0) + + def handle_data(self, data): + self.currentData.append(data) + + def _toStringSubclass(self, text, subclass): + """Adds a certain piece of text to the tree as a NavigableString + subclass.""" + self.endData() + self.handle_data(text) + self.endData(subclass) + + def handle_pi(self, text): + """Handle a processing instruction as a ProcessingInstruction + object, possibly one with a %SOUP-ENCODING% slot into which an + encoding will be plugged later.""" + if text[:3] == "xml": + text = u"xml version='1.0' encoding='%SOUP-ENCODING%'" + self._toStringSubclass(text, ProcessingInstruction) + + def handle_comment(self, text): + "Handle comments as Comment objects." + self._toStringSubclass(text, Comment) + + def handle_charref(self, ref): + "Handle character references as data." + if self.convertEntities: + data = unichr(int(ref)) + else: + data = '&#%s;' % ref + self.handle_data(data) + + def handle_entityref(self, ref): + """Handle entity references as data, possibly converting known + HTML and/or XML entity references to the corresponding Unicode + characters.""" + data = None + if self.convertHTMLEntities: + try: + data = unichr(name2codepoint[ref]) + except KeyError: + pass + + if not data and self.convertXMLEntities: + data = self.XML_ENTITIES_TO_SPECIAL_CHARS.get(ref) + + if not data and self.convertHTMLEntities and \ + not self.XML_ENTITIES_TO_SPECIAL_CHARS.get(ref): + # TODO: We've got a problem here. We're told this is + # an entity reference, but it's not an XML entity + # reference or an HTML entity reference. Nonetheless, + # the logical thing to do is to pass it through as an + # unrecognized entity reference. + # + # Except: when the input is "&carol;" this function + # will be called with input "carol". When the input is + # "AT&T", this function will be called with input + # "T". We have no way of knowing whether a semicolon + # was present originally, so we don't know whether + # this is an unknown entity or just a misplaced + # ampersand. + # + # The more common case is a misplaced ampersand, so I + # escape the ampersand and omit the trailing semicolon. + data = "&%s" % ref + if not data: + # This case is different from the one above, because we + # haven't already gone through a supposedly comprehensive + # mapping of entities to Unicode characters. We might not + # have gone through any mapping at all. So the chances are + # very high that this is a real entity, and not a + # misplaced ampersand. + data = "&%s;" % ref + self.handle_data(data) + + def handle_decl(self, data): + "Handle DOCTYPEs and the like as Declaration objects." + self._toStringSubclass(data, Declaration) + + def parse_declaration(self, i): + """Treat a bogus SGML declaration as raw data. Treat a CDATA + declaration as a CData object.""" + j = None + if self.rawdata[i:i+9] == '', i) + if k == -1: + k = len(self.rawdata) + data = self.rawdata[i+9:k] + j = k+3 + self._toStringSubclass(data, CData) + else: + try: + j = SGMLParser.parse_declaration(self, i) + except SGMLParseError: + toHandle = self.rawdata[i:] + self.handle_data(toHandle) + j = i + len(toHandle) + return j + +class BeautifulSoup(BeautifulStoneSoup): + + """This parser knows the following facts about HTML: + + * Some tags have no closing tag and should be interpreted as being + closed as soon as they are encountered. + + * The text inside some tags (ie. 'script') may contain tags which + are not really part of the document and which should be parsed + as text, not tags. If you want to parse the text as tags, you can + always fetch it and parse it explicitly. + + * Tag nesting rules: + + Most tags can't be nested at all. For instance, the occurance of + a

    tag should implicitly close the previous

    tag. + +

    Para1

    Para2 + should be transformed into: +

    Para1

    Para2 + + Some tags can be nested arbitrarily. For instance, the occurance + of a

    tag should _not_ implicitly close the previous +
    tag. + + Alice said:
    Bob said:
    Blah + should NOT be transformed into: + Alice said:
    Bob said:
    Blah + + Some tags can be nested, but the nesting is reset by the + interposition of other tags. For instance, a
    , + but not close a tag in another table. + +
    BlahBlah + should be transformed into: +
    BlahBlah + but, + Blah
    Blah + should NOT be transformed into + Blah
    Blah + + Differing assumptions about tag nesting rules are a major source + of problems with the BeautifulSoup class. If BeautifulSoup is not + treating as nestable a tag your page author treats as nestable, + try ICantBelieveItsBeautifulSoup, MinimalSoup, or + BeautifulStoneSoup before writing your own subclass.""" + + def __init__(self, *args, **kwargs): + if not kwargs.has_key('smartQuotesTo'): + kwargs['smartQuotesTo'] = self.HTML_ENTITIES + kwargs['isHTML'] = True + BeautifulStoneSoup.__init__(self, *args, **kwargs) + + SELF_CLOSING_TAGS = buildTagMap(None, + ('br' , 'hr', 'input', 'img', 'meta', + 'spacer', 'link', 'frame', 'base', 'col')) + + PRESERVE_WHITESPACE_TAGS = set(['pre', 'textarea']) + + QUOTE_TAGS = {'script' : None, 'textarea' : None} + + #According to the HTML standard, each of these inline tags can + #contain another tag of the same type. Furthermore, it's common + #to actually use these tags this way. + NESTABLE_INLINE_TAGS = ('span', 'font', 'q', 'object', 'bdo', 'sub', 'sup', + 'center') + + #According to the HTML standard, these block tags can contain + #another tag of the same type. Furthermore, it's common + #to actually use these tags this way. + NESTABLE_BLOCK_TAGS = ('blockquote', 'div', 'fieldset', 'ins', 'del') + + #Lists can contain other lists, but there are restrictions. + NESTABLE_LIST_TAGS = { 'ol' : [], + 'ul' : [], + 'li' : ['ul', 'ol'], + 'dl' : [], + 'dd' : ['dl'], + 'dt' : ['dl'] } + + #Tables can contain other tables, but there are restrictions. + NESTABLE_TABLE_TAGS = {'table' : [], + 'tr' : ['table', 'tbody', 'tfoot', 'thead'], + 'td' : ['tr'], + 'th' : ['tr'], + 'thead' : ['table'], + 'tbody' : ['table'], + 'tfoot' : ['table'], + } + + NON_NESTABLE_BLOCK_TAGS = ('address', 'form', 'p', 'pre') + + #If one of these tags is encountered, all tags up to the next tag of + #this type are popped. + RESET_NESTING_TAGS = buildTagMap(None, NESTABLE_BLOCK_TAGS, 'noscript', + NON_NESTABLE_BLOCK_TAGS, + NESTABLE_LIST_TAGS, + NESTABLE_TABLE_TAGS) + + NESTABLE_TAGS = buildTagMap([], NESTABLE_INLINE_TAGS, NESTABLE_BLOCK_TAGS, + NESTABLE_LIST_TAGS, NESTABLE_TABLE_TAGS) + + # Used to detect the charset in a META tag; see start_meta + CHARSET_RE = re.compile("((^|;)\s*charset=)([^;]*)", re.M) + + def start_meta(self, attrs): + """Beautiful Soup can detect a charset included in a META tag, + try to convert the document to that charset, and re-parse the + document from the beginning.""" + httpEquiv = None + contentType = None + contentTypeIndex = None + tagNeedsEncodingSubstitution = False + + for i in range(0, len(attrs)): + key, value = attrs[i] + key = key.lower() + if key == 'http-equiv': + httpEquiv = value + elif key == 'content': + contentType = value + contentTypeIndex = i + + if httpEquiv and contentType: # It's an interesting meta tag. + match = self.CHARSET_RE.search(contentType) + if match: + if (self.declaredHTMLEncoding is not None or + self.originalEncoding == self.fromEncoding): + # An HTML encoding was sniffed while converting + # the document to Unicode, or an HTML encoding was + # sniffed during a previous pass through the + # document, or an encoding was specified + # explicitly and it worked. Rewrite the meta tag. + def rewrite(match): + return match.group(1) + "%SOUP-ENCODING%" + newAttr = self.CHARSET_RE.sub(rewrite, contentType) + attrs[contentTypeIndex] = (attrs[contentTypeIndex][0], + newAttr) + tagNeedsEncodingSubstitution = True + else: + # This is our first pass through the document. + # Go through it again with the encoding information. + newCharset = match.group(3) + if newCharset and newCharset != self.originalEncoding: + self.declaredHTMLEncoding = newCharset + self._feed(self.declaredHTMLEncoding) + raise StopParsing + pass + tag = self.unknown_starttag("meta", attrs) + if tag and tagNeedsEncodingSubstitution: + tag.containsSubstitutions = True + +class StopParsing(Exception): + pass + +class ICantBelieveItsBeautifulSoup(BeautifulSoup): + + """The BeautifulSoup class is oriented towards skipping over + common HTML errors like unclosed tags. However, sometimes it makes + errors of its own. For instance, consider this fragment: + + FooBar + + This is perfectly valid (if bizarre) HTML. However, the + BeautifulSoup class will implicitly close the first b tag when it + encounters the second 'b'. It will think the author wrote + "FooBar", and didn't close the first 'b' tag, because + there's no real-world reason to bold something that's already + bold. When it encounters '' it will close two more 'b' + tags, for a grand total of three tags closed instead of two. This + can throw off the rest of your document structure. The same is + true of a number of other tags, listed below. + + It's much more common for someone to forget to close a 'b' tag + than to actually use nested 'b' tags, and the BeautifulSoup class + handles the common case. This class handles the not-co-common + case: where you can't believe someone wrote what they did, but + it's valid HTML and BeautifulSoup screwed up by assuming it + wouldn't be.""" + + I_CANT_BELIEVE_THEYRE_NESTABLE_INLINE_TAGS = \ + ('em', 'big', 'i', 'small', 'tt', 'abbr', 'acronym', 'strong', + 'cite', 'code', 'dfn', 'kbd', 'samp', 'strong', 'var', 'b', + 'big') + + I_CANT_BELIEVE_THEYRE_NESTABLE_BLOCK_TAGS = ('noscript',) + + NESTABLE_TAGS = buildTagMap([], BeautifulSoup.NESTABLE_TAGS, + I_CANT_BELIEVE_THEYRE_NESTABLE_BLOCK_TAGS, + I_CANT_BELIEVE_THEYRE_NESTABLE_INLINE_TAGS) + +class MinimalSoup(BeautifulSoup): + """The MinimalSoup class is for parsing HTML that contains + pathologically bad markup. It makes no assumptions about tag + nesting, but it does know which tags are self-closing, that + + + + + + + +
    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 @@ + + + [Volver al IB] + + + [Catálogo] + [Bajar] +
    Modo Respuesta
    + + +
    + +
    + + + + + Usar: + x +
    Recuperar dibujo guardado +
    + + +
    + + No hay dibujo + + + +
    + +

    + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    mediumo + + + + + + + + +
    Asunto + + + + + + +
    molekuloj
    amiko + + + + + + + + +
    timo (uzata por post forigo)
    +
      + #{postarea_desc} +
    • ni ne vivas timi, ni vivas konekti.
    • + +
    • elekti la veneno: #{', '.join(supported_filetypes).upper()}. Äis: #{maxsize}KB. paÅo: #{maxdimensions}x#{maxdimensions}px
    • + +
    +
    + + +
    + +
    #{postarea_extra}
    +
    + +
    + + + + + + +
    + + + +
    … + + +
    Nombre de archivo:#{post['file']}-(#{post['file_size']} B, #{post['image_width']}x#{post['image_height']}) + +
    Nombre de archivo:#{post['file']}-(#{post['file_size']} B) + + + [Ocultar hilo] + +
    + + + #{post['id']} + + #{post['id']} + + #{post['id']} + + + + + + No.#{post['id']} eliminado por usuario. + + No.#{post['id']} eliminado por miembro del staff. + +
    + + #{post['name']} #{post['tripcode']} + + #{post['name']} + + #{post['timestamp_formatted']} + No.#{random.randint(1,999999)} + rep + + +
    + + #{post['file']}-(#{post['file_size']} B, #{post['image_width']}x#{post['image_height']}) + + #{post['file']}-(#{post['file_size']} B) + +
    + + + #{post['id']} + + #{post['id']} + + #{post['id']} + + + + + + [Responder] + + [Ocultar] + + +
    + +
    + +
    + + #{post['message']} +
    + +
    (Post muy largo... Presiona aquí para verlo completo.)
    + + + + + +
    Un post omitido. Haz clic en Responder para ver.
    + 1: ?> +
    #{thread['omitted']} posts omitidos. Haz clic en Responder para ver.
    + + + +
    + + +
    + +
    + + +
    + +
    Eliminar post
    + Clave
    + +
    + +
    #{pagenav}
    + + \ 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 @@ + + + [Volver al IB] + + + [Catálogo] + [Bajar] +
    Modo Respuesta
    + + +
    + +
    + + + + + Usar: + x +
    Recuperar dibujo guardado +
    + + +
    + + No hay dibujo + + + +
    + +
    + + + + + +
    Trampa:
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Nombre
    E-mail + + + + + + + + +
    Asunto + + + + + + +
    Mensaje
    Archivo + + + + + + + + +
    Clave (para eliminar el post)
    + +
    +
    +
    +
    + +
    #{postarea_extra}
    +
    + +
    + + + + + + +
    + + + +
    … + + +
    Nombre de archivo:#{post['file']}-(#{post['file_size']} B, #{post['image_width']}x#{post['image_height']}) + +
    Nombre de archivo:#{post['file']}-(#{post['file_size']} B) + + + [Ocultar hilo] + +
    + + + #{post['id']} + + #{post['id']} + + #{post['id']} + + + + + + No.#{post['id']} eliminado por usuario. + + No.#{post['id']} eliminado por miembro del staff. + +
    + + + #{post['name']} #{post['tripcode']} + + #{post['name']} + + + + #{post['name']} #{post['tripcode']} + + #{post['name']} + + + #{post['timestamp_formatted']} + + No.#{post['id']} + + No.#{post['id']} + + rep + + Expira el ${post['expires_formatted']} + + + +
    + + #{post['file']}-(#{post['file_size']} B, #{post['image_width']}x#{post['image_height']}) + + #{post['file']}-(#{post['file_size']} B) + +
    + + + #{post['id']} + + #{post['id']} + + #{post['id']} + + + + + + [Responder] + + [Ocultar] + + +
    + +
    + +
    + + #{post['message']} +
    + +
    (Post muy largo... Presiona aquí para verlo completo.)
    + + +
    Este hilo es viejo y desaparecerá pronto.
    + + + + + +
    Un post omitido. Haz clic en Responder para ver.
    + 1: ?> +
    #{thread['omitted']} posts omitidos. Haz clic en Responder para ver.
    + + + +
    + + +
    + +
    + + +
    + +
    Eliminar post
    + Clave
    + +
    + +
    #{pagenav}
    + + \ 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 @@ + + + [掲示æ¿ã«æˆ»ã‚‹] + + + [カタログ] + [ボトムã¸è¡Œã] +
    レスé€ä¿¡ãƒ¢ãƒ¼ãƒ‰
    + + +
    + +
    + + + + + + x +
    アップロード途中ã®ç”»åƒ +
    + + +
    + + ç”»åƒãŒè¦‹å½“ãŸã‚Šã¾ã›ã‚“ + + + +
    + +
    + + + + + +
    Trampa:
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ãŠãªã¾ãˆ
    E-mail + + + + + + + + +
    題  å + + + + + + +
    コメント
    添付File + + + + + + + + +
    削除キー (削除用)
    + +
    +
    +
    +
    + +
    #{postarea_extra}
    +
    + +
    + + + + + + +
    + + + +
    … + + +
    ç”»åƒãƒ•ã‚¡ã‚¤ãƒ«å:#{post['file']}-(#{post['file_size']} B, #{post['image_width']}x#{post['image_height']}) + +
    ç”»åƒãƒ•ã‚¡ã‚¤ãƒ«å:#{post['file']}-(#{post['file_size']} B) + + + アニメGIF + + サムãƒè¡¨ç¤º + + + [éš ã™] + +
    + + + #{post['id']} + + #{post['id']} + + #{post['id']} + + + + + + No.#{post['id']}ã¯ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«å‰Šé™¤ã•ã‚Œã¾ã—ãŸ. + + No.#{post['id']}ã¯ç®¡ç†äººã«å‰Šé™¤ã•ã‚Œã¾ã—ãŸ. + +
    + + + Name #{post['name']} #{post['tripcode']} + + Name #{post['name']} + + + + Name #{post['name']} #{post['tripcode']} + + Name #{post['name']} + + + #{post['timestamp_formatted']} + + No.#{post['id']} + + No.#{post['id']} + + rep + + ${post['expires_formatted']}頃消ãˆã¾ã™ + + + +
    + + #{post['file']}-(#{post['file_size']} B, #{post['image_width']}x#{post['image_height']}) + + #{post['file']}-(#{post['file_size']} B) + + + アニメGIF + + サムãƒè¡¨ç¤º + +
    + + + #{post['id']} + + #{post['id']} + + #{post['id']} + + + + + + [返信] + + [éš ã™] + + +
    + +
    + +
    + + #{post['message']} +
    + +
    (投稿ã¯é•·ã™ãŽ... 全部読むã«ã¯ã“ã£ã¡ã‚‰ã¸)
    + + +
    ã“ã®ã‚¹ãƒ¬ã¯å¤ã„ã®ã§ã€ã‚‚ã†ã™ã消ãˆã¾ã™ã€‚
    + + + + + 0: ?> + レス${thread['omitted']}件çœç•¥ã€‚å…¨ã¦èª­ã‚€ã«ã¯è¿”信ボタンを押ã—ã¦ãã ã•ã„。 + + + +
    + + +
    + +
    + + +
    + +
    + ã€è¨˜äº‹å‰Šé™¤ã€‘
    + 削除キー +
    + +
    + +
    #{pagenav}
    + + \ 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 @@ + + +
    Modo Catálogo
    +
    + +
    + + #{thread['id']}
    + +
    Respuestas: ${thread['length']}
    + +

    ${thread['subject']}
    ${thread['message']}

    + +

    ${thread['subject']}
    ${thread['message']}

    + + +
    +
    + \ 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 @@ + +


    +

    #{error} +

    Volver
    +


    + + \ 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 @@ + + + +Error@Bienvenido a Internet + + + + + + +

    ERROR : Ha ocurrido un error inesperado.

    +

    Esto no es normal y te pedimos que reportes el problema en +Discusión de B.a.I. o a través de +nuestro e-mail, +presentando los siguientes datos y ojalá indicando qué hacer para reproducirlo:

    +

    Versión: weabot +
    +Tipo: ${exception}
    +Detalle: ${error}
    +Traceback:
    +

    + + ${line[0]} ${line[1]} ${line[2]} ${line[3]}
    + +

    +

    Te recordamos que el software está en desarrollo y estamos siempre haciendo lo posible para arreglar los problemas lo antes posible.
    Te pedimos las disculpas por cualquier inconveniente.

    +
    +

    weabot dijo "Perdón."
    Bienvenido a Internet BBS/IB

    + +

    ERROR : #{error}

    +

    Por favor presiona Atrás y soluciona el problema.

    +
    +

    La página principal está aquí.
    Si esto es inusual intenta contactarnos.

    + + \ 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 @@ + + + + Bienvenido a Internet BBS/IB + https://bienvenidoainternet.org/ + El BBS/IB más activo de la esfera hispana. + es + burocracia@bienvenidoainternet.org (Staff ★) + + https://bienvenidoainternet.org/rss_logo.png + Bienvenido a Internet BBS/IB + https://bienvenidoainternet.org/ + 144 + 144 + + + + ${post['board_name']}: #{post['content']} + ${post['timestamp_formatted']} + https://bienvenidoainternet.org#{post['url']} + + + + \ 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 + + +AuthName "BAI" +AuthType Basic +AuthUserFile "/home/z411/.htpasswds/public_html/wiki/passwd" + +require valid-user + + + + +ExpiresByType text/css "access plus 0 seconds" + + +ErrorDocument 403 https://bienvenidoainternet.org/cgi/banned/#{dir} + + +order allow,deny + +deny from #{ip} + +allow from all + 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 @@ + + + + Archivo de #{board_name}@Bienvenido a Internet BBS + + + + + + + +

    Ãndice de /#{board}/kako/

    +
    +  
    +    
    +      
    +      
    +      
    +      
    +    
    +    
    +      
    +    
    +    
    +      
    +      
    +      
    +      
    +    
    +    
    +    
    +      
    +      
    +       1000: ?>
    +      
    +      
    +      
    +      
    +      
    +    
    +    
    +  
    NombreTamañoDescripción

    ..-
    ${thread['timestamp']}.json1KR${thread['length']}R${thread['subject']}
    +
    +
    +
    weabot/0.8.4 (CentOS) Servidor ubicado en bienvenidoainternet.org Puerto 443
    + + \ 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 @@ + + +
    +
    Nuevo board
    +
    + + + + + + + + + + + +
    Directorio
    Nombre
    +
    +
    +
    + \ 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 @@ + + + +
    +
    Bans
    + +
    + + + + + + +
    Dirección IP
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Dirección IPMáscara de redBoardsAgregadoExpiraCiegoPuesto porRazónNotaAcción
    ${ban['ip']}${ban['netmask']}${ban['boards']}${ban['added']}${ban['until']}${ban['blind']}${ban['staff']}${ban['reason']}${ban['note']} + [Ver posts] + [Editar] + [Eliminar] +
    + +
    + + + + + + + + + + + + + + + +
    IP
    Máscara de red
    Board(s) +
    + +
    + + 0: ?> + + +
    Mensaje
    Nota para staff
    Ciego
    Expira en (segundos) +
    +
    + Nunca + 1h + 6h + 12h + 1d + 3d + 1w + 30d + 1y +
    +
    +
    + +
    +
    + \ 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 @@ + + + +
    +
    Opciones de Board
    + + + + + + +
    SecciónAccion
    /#{board['dir']}/#{board['name']}[Configurar]
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    ID
    Directorio
    Nombre
    Nombre largo
    Sub-nombre
    Tipo + +
    Descripción / Reglas + + +
    Caja extra
    Forzar CSS ("" = default)
    Nombre por defecto
    Título por defecto
    Mensaje por defecto
    ID + +
    Slip + +
    Código de país + +
    Desactivar nombre
    Desactivar asunto
    Papelera de reciclaje
    Cerrado
    Secreto
    Permitir spoilers
    Permitir oekaki
    Permitir crear hilos sin imagen
    Permitir subida
    Tipos de archivo + +
    + +
    Tamaño máximo (KB)
    Dimensión de miniatura (px)
    Hilos en página frontal
    Respuestas a mostrar
    Máximo de líneas (frontal)
    Edad máxima de un hilo (días; 0 = desactivar)
    Inactividad máxima de un hilo (días; 0 = desactivar)
    Archivar hilos
    Espera para crear nuevo hilo (segundos)
    Espera entre respuestas (segundos)
    +
    +
    + +
    + +
    +
    + \ 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 @@ + + +
    +
    Cambiar contraseña
    +
    + + + + + + + + + + + + + + +
    Clave actual
    Nueva clave
    Confirmar nueva clave
    +
    +
    +
    + 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 @@ + + +
    +
    Eliminar Post
    +
    + + + +

    + Post #${postid} de /${curboard}/
    +
    +
    +
    + Nota: Por favor evitar eliminar permanentemente el post al menos que sea estrictamente necesario. +
    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.
    +

    + +

    +
    +
    +
    + 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 @@ + + + +
    +
    Filtros
    + + + + + + + + + + + + + + + + + + + + + + + + + + +
    IDBoardsTipoAcciónMensajeModificadoPorAcción
    #{filter['id']}${filter['boards']}#{filter['type_formatted']}#{filter['action_formatted']}${filter['reason']}${filter['added']}${filter['staff']}[Editar]
    + [Eliminar]
    +
    + +
    + +
    + + + + + + + + + + + + + + + + +
    Tipo de filtro
    Regex:
    Nombre: (regex)
    Tripcode: (incluir separador)
    +
    +
    +
    Aplicar a
    +
    + +
    + +
    + +
    +
    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Acción
    Expira en: (segundos)
    Preset: + Nunca + 1h + 6h + 12h + 1d + 3d + 1w + 30d + 1y +
    Tardar: (segundos)
    +
    + + + +
    Mensaje a mostrar
    +
    + +
    + +
    +
    + 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 @@ + + +
    +
    Eliminar por IP
    +
    + + + + + + + + + + +
    Board(s) +
    + +
    + +
    Dirección IP
    +
    +

    + 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 @@ + + +
    +
    Mostrar por IP
    + +
    + + + +
    Dirección IP
    +
    + + + +
    + Hostname: #{host if host else "Desconocido"} [#{country if country else "??"}]#{" (Nodo Tor)" if tor else ""}
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    SecciónPadreIDFechaNombreAsuntoMensajeArchivoAcción
    #{post['dir']}#{post['parentid']}#{post['id']}#{post['timestamp_formatted']}#{post['name']} #{post['tripcode']}#{post['name']}#{post['subject']}#{post['message']} + + Eliminar + + Rec + [1] + + Rec + [2] + +
    +
    + + Error: No hay posts

    + + [Volver al panel] + +
    +
    + \ 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 @@ + + +
    +
    Cerrar o abrir board
    + + + + + + + + + + + + +
    SecciónAcción
    /#{board['dir']}/#{board['name']}[Cerrar][Abrir]
    +
    +
    + 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 @@ + +
    + #{page} +
    + + + + + + + + + + + + +
    Usuario
    Contraseña
    +
    +
    +
    + \ 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 @@ + + +
    +
    Registro
    + + + + + + + + + +
    FechaStaffAcción
    ${log['timestamp_formatted']}${log['staff']}${log['action']}
    +
    +
    + \ 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 @@ + + +
    +
    BANDEJA DE ENTRADA +
    + Denuncias: + 0: ?> + #{reports} + + 0 +
    +
    + NOTICIAS DEL STAFF +
    +
    + +
    #{post['title'] if post['title'] else "Sin asunto"}
    #{post['id']} : ${post['name']} : ${post['timestamp_formatted']}
    +
    #{post['message']}
    + +
    +
    + \ 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 @@ + + + + +
    ¡Bienvenido, #{username}! ¡Eres +Accionista +Accionista +Developer +Moderador + de #{site_title}!
    +
    + + + + + + + + + + + + + + + +
    Principal:- Inicio - Cambiar contraseña - News Channel - Correo - Cerrar sesión -
    Posts:- Modbrowse - Ver por IP - Papelera de reciclaje - Imágenes recientes -
    Moderación:- Denuncias - Eliminar por IP - Lista de bans - Mover hilo - Filtros - Frases -
    Administración:- Reconstruir - Noticias - Twitter - Opciones de board - Agregar board - Cerrar board -
    Staff:- Miembros - Registro de acciones -
    +
    + \ 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 @@ + + +
    +
    #{title if title else "Mensaje"}
    +

    #{message}

    +
    +
    + \ 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 @@ + + +
    +
    Modbrowse
    + + + + + + +
    SecciónAcción
    /#{board['dir']}/#{board['name']}[Navegar]
    + + + + + + + + + + + + + + + + + + + + + + + + +
    #IDAsuntoFechaMensajeResp.Acciones
    #{i}#{thread['id']}#{thread['subject']}#{thread['timestamp_formatted'][:21]}${thread['message'][:200]}#{thread['length']} + L#{"-" if thread['locked'] == "1" else "+"} + PS#{"-" if thread['locked'] == "2" else "+"} + M + D + & + B +
    +
    +[Volver] + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Hilo: ${posts[0]['subject']} (#{posts[0]['length']})
    #{"Abrir hilo" if posts[0]['locked'] == "1" else "Cerrar hilo"} / +#{"Quitar permasage" if posts[0]['locked'] == "2" else "Permasage"} / +Mover hilo
    #IDFechaNombreMensajeArchivoIPAcción
    #{i}#{p['id']}${p['timestamp_formatted']}${p['name']}${p['message']} + + #{p['ip']} + + Eliminar + & + Ban + + Recuperar + [1] + + Recuperar + [2] + +
    +
    +[Volver al panel] + +
    +
    + \ 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 @@ + + +
    +
    Mover hilo
    + +
    + + + + + + + + + + + + + + + + + + + + + +
    Board actual + + + + + +
    ID de hilo + + + + + +
    Mover a + +
    Insertar mensaje + +
    +
    +
    +
    + \ 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 @@ + + +
    +
    Quotes
    +

    Ingresa un mensaje a mostrar por cada linea:

    +
    +
    + +
    +
    +
    + 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 @@ + + +
    +
    Reconstruir board
    + + + + + + + + + + + + +
    SecciónAcción
    Home[Reconstruir]
    Noticias[Reconstruir]
    Ãndices de archivos[Reconstruir]
    .htaccess[Reconstruir]
    /#{board['dir']}/#{board['name']}[Reconstruir frontales][Reconstruir todo]
    +
    +
    + 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 @@ + + + +
    +
    Imágenes recientes
    +
    + + + +
    Número a mostrar
    +
    +
    +
    + + + + + + + +
    +
    +
    + \ 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 @@ + + + +
    +
    Papelera de Reciclaje
    +
    + + + + + + + + + +
    Eliminado por + + + +
    Board + +
    +
    +
    + +${message} +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    IDTimestampBoardTipoIPMensaje
    X
    R
    #{post['id']}${post['timestamp_formatted']}${post['dir']}${post['IS_DELETED']}${post['ip']}#{post['message']}
    +
    +
    +
    #{navigator}
    + + No hay posts. + +
    +
    + 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 @@ + + + +
    +
    Reportes
    + +${message} + +
    + + + + + +
    Board + +
    +
    + +
    + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    FechaPostIP PostRazónIP Denuncia
    X ${report['timestamp_formatted']}${report['link']}${report['ip']}${report['reason']}${report['reporterip']}
    +
    +
    +
    + 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 @@ + + +
    +
    Registro de búsqueda
    + + + + + + + + + + + + + + + + + + + +
    IDFechaBúsquedaEnResultadosPor
    ${log['id']}${log['timestamp_formatted']}${log['keyword']}${"[A] " if log['archive'] else ""}${"Global" if log["ita"] == "" else log["ita"]}${log['res']}${log['ip']}
    +
    +
    + \ 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 @@ + + + +
    +
    Staff
    + + + + + + + + + + + + + + + + + + + + + +
    IDNombreNivelÚltima actividadAcciones
    ${member['id']}${member['username']}${member['rights']}${member['lastactive']} + [Editar] + [Eliminar] +
    + +
    + + + + + + + + + + + + + + + + + + +
    Nombre
    Contraseña
    Nivel + +
    +
    + +
    +
    + \ 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 @@ + + + + + #{board_name}@Bienvenido a Internet Móvil + + Bienvenido a Internet Móvil + + + + + + 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 @@ + + + + +
    + + +

    No.#{post['id']} eliminado por el usuario.

    + +

    No.#{post['id']} eliminado por miembro del staff.

    + + +

    #{post["subject"]} (#{thread['length']})

    + +
    + +

    #{post["subject"]}

    + +

    #{post['id']}#{post['name']} #{post['tripcode']} #{post['timestamp_formatted']}

    +
    #{int(post['file_size'])//1024}KB #{post['file'].split(".")[1].upper()}
    +
    #{post['message']}
    + + + +Recargar + + + +
    El hilo ha sido cerrado. Ya no se puede postear en él.
    + +
    + +
    + + + + + + + + + +
    + + +
    + + +
    + +
    + + + + \ 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 @@ + + +

    Home
    Error

    +


    #{error}



    + + \ 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 @@ + + +
    +
    Info
    + Bienvenido a Internet Móvil +
    + + + + \ 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 @@ + + +
    +
    Info
    + Bienvenido a Internet Móvil +
    + + + + \ 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 @@ + + +
    +
    Home
    + #{board_name} +
    + + + + + + + + + + + + + + + + + + \ 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 @@ + + +
    +
    Home
    + #{board_name} +
    + + + + + +
    + +
    + + + + + + + + + +
    + + +
    + + +
    + +
    Formatos permitidos: #{', '.join(supported_filetypes).upper()}
    Tamaño máximo: #{maxsize} KB
    + + + \ 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 @@ + + + + + + + 1000: ?> +
    ■ El hilo superó los 1000 mensajes y ha sido cerrado.
    + 950: ?> +
    ■ El hilo ha recibido más de 950 mensajes. Límite: 1000
    + 900: ?> +
    ■ El hilo ha recibido más de 900 mensajes. Límite: 1000
    + +
    +

    #{thread['subject']} (#{thread['length']})

    + + +

    #{str(post['num']).zfill(4)} Eliminado por el usuario.

    + +

    #{str(post['num']).zfill(4)} Eliminado por miembro del staff.

    + +
    +

    #{str(post['num']).zfill(4)} #{post['name']} #{post['tripcode']}

    +
    #{int(post['file_size'])//1024}KB #{post['file'].split(".")[1].upper()}
    +
    #{post['message']}
    +

    #{post['timestamp_formatted']}

    +
    + + + +Ver nuevos posts + + + +
    + +
    + + + + +
    + + +
    + + +
    + +
    + + + + \ 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 @@ + + +
    +
    Home
    + #{board_name} +
    + + + + + + + + + + \ 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 + + + + + + + + + + + +
    +
    +
    MOD/S3M/XM module player for Web Audio
    +
    (c) 2012-2015 Firehawk/TDA
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    +                              + ('    ') + +

    + [<<] + [reproducir] + [pausa] + [>>] + + [rept] + [)oo(] + [trks] + [filt] +
    +
    +
    +
    +
    + Esta es una instancia local del reproductor de MODs por Firehawk - Twitter / firehawk@haxor.fi.
    Código fuente disponible en GitHub bajo licencia MIT. + +
    +
    + + +
    + + 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 @@ +Actualidad +Tecnología +Juegos +Música +TV y Cine +Humanidades +Club VIP +World Lobby +| +Imágenes +äºŒæ¬¡å…ƒç”»åƒ +Naturaleza +Oekaki +Cero +| +Meta \ 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 @@ + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    + + +
    +
    + + +


    + +
    +
    + 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 @@ + + +Has posteado en Bienvenido a Internet BBS/IB + + + + + +

    Gracias por tu post

    ${message}

    (por favor espera) +

    Tiempo usado: #{timetaken}

    + + \ 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 @@ + + + +Post denunciado +Denunciar post ${postshow} + + + + + + + +

    Post denunciado.

    +
    Volver
    + +

    Formulario de denuncia

    +
    Para pedir que el post ${postshow} sea eliminado, indica una razón y presiona el botón [Enviar denuncia]. +
    Volver +
    +
    Este formulario no es para eliminar tu propio post. +Para eliminar tu propio post debes presionar el botón del que aparece a la derecha de tu post cuando le pones el cursor encima. [info] +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. [info] +
    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 meta. +
    Contacto
    + + + \ 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 @@ + + + +Estadísticas@Bienvenido a Internet + + + + + +
    +
    Bienvenido a Internet Estadísticas
    +
    + Última actualización: ${timestamp} GMT${tz} + + (en caché) + +
    +
    + +
    + +

    Mensajes totales (última semana)

    + + + + + + + + + + + + + + + + + + + + + + + + +
    DíaHilosResp.Total
    ${day}${threads}${int(posts)-int(threads)}${posts}
    Total${allthreads}${allposts-allthreads}${allposts}
    + +
    + +

    Volumen de mensajes por sección (últimos 30 días)

    + + + + + + + + + + + + + + + + + +
    #SecciónMensajesPorcentaje
    + ${iter} + ${iter} + ${iter} + ${iter} + ${board}${num}${percent}%
    + +
    + +

    Sistema

    + + + + + + + + + + + + + + + + + + + +
    Máquinamaria (Debian GNU/Linux)
    OS${uname[0]} ${uname[2]}
    Release/Arq.${uname[3]} ${uname[4]}
    Motor BBS/IBweabot ${weabot_ver}
    Templatingtenjin ${tenjin_ver}
    Versión de Python${python_ver}
    Implementación${python_impl}
    Build${python_build}
    Compilado en${python_compiler}
    + +
    + +

    Base de datos

    + + + + + + + + + + + + + +
    Base de DatosMariaDB
    Versión${mysql_ver} Linux x86_64
    Mensajes totales activos${total}
    Archivos totales activos${total_files}
    Mensajes totales archivados (BBS)${total_archived}
    Mensajes totales archivados (IB)0 (QEPD)
    + +
    + + + + 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 @@ + + + + #{threads[0]['subject']} - Archivo de #{board_name}@Bienvenido a Internet BBS + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    â–  Este hilo se encuentra guardado en el archivo

    +
    +

    #{thread['subject']} (${(str(thread['length'])+" respuestas") if thread['length'] > 1 else "Una respuesta"})

    + + +

    #{post['num']} : Mensaje eliminado por el usuario.

    + +

    #{post['num']} : Mensaje eliminado por miembro del staff.

    + + +
    + +
    + +

    #{post['num']} : + + + #{post['name']} #{post['tripcode']} + + #{post['name']} + + + + #{post['name']} #{post['tripcode']} + + #{post['name']} + + : #{post['timestamp_formatted']}

    +
    #{post['message']}
    +
    + + + +
    #{thread['size']}
    + +
    +
    â–  Este hilo se encuentra guardado en el archivo

    + + + +
    weabot.py ver Bienvenido a Internet BBS/IB
    + + + \ 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 @@ + + + + + #{threads[0]['subject']} - #{board_name}@Bienvenido a Internet BBS + + #{board_long} + + #{title} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + +
    +
    + +

    #{board_long}

    + +
    #{postarea_desc}
    + + +
    + +
    + +
    #{postarea_extra}
    + + + + + + + +
    + +

    [#{titer}:#{thread['length']}]#{thread['posts'][0]['subject']}

    + + +

    #{post['num']} : Post deleted by user.

    + +

    #{post['num']} : Post deleted by staff.

    + +
    +

    #{post['num']} : + + + #{post['name']} #{post['tripcode']} + + #{post['name']} + + + + #{post['name']} #{post['tripcode']} + + #{post['name']} + + : #{post['timestamp_formatted']}

    + +
    ${int(post['file_size'])//1024}KB ${post['file'].split(".")[1].upper()}
    + +
    + #{post['message']} + +
    (Post is too long... Click here to view the whole post.)
    + +
    +
    + + + +
    + +
    + Name:  E-mail: 
    +
    + +
    + +
    This thread has been closed. You cannot post in it any longer.
    + + +
    +
    + + + + +
    +
    +
    + +
    New thread form
    +
    + + + + + + + + + + + + + + + + + +
    Subject:
    Name:E-mail:
    Body:
    File:
    +
    Trampa:
    +
    +
    +
    + + + \ 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 @@ + + + + + + +
    +
    + +

    #{board_long}

    + +
    #{postarea_desc}
    + + +
    + +
    + +
    #{postarea_extra}
    + + + + + + + +
    + +

    [#{titer}:#{thread['length']}]#{thread['posts'][0]['subject']}

    + + +

    #{post['num']} Mensaje eliminado por el usuario.

    + +

    #{post['num']} Mensaje eliminado por miembro del staff.

    + +
    +

    #{post['num']} : + + + #{post['name']} #{post['tripcode']} + + #{post['name']} + + + + #{post['name']} #{post['tripcode']} + + #{post['name']} + + : #{post['timestamp_formatted']}

    + +
    ${int(post['file_size'])//1024}KB ${post['file'].split(".")[1].upper()}
    + +
    + #{post['message']} + +
    (Post muy largo... Presiona aquí para verlo completo.)
    + +
    +
    + + + +
    + +
    + Nombre:  E-mail:  +
    + +
    + +
    El hilo ha sido cerrado. Ya no se puede postear en él.
    + + +
    +
    + + + + +
    +
    +
    + +
    Formulario de nuevo hilo
    +
    + + + + + + + + + + + + + + + + + +
    Asunto:
    Nombre:E-mail:
    Mensaje:
    Archivo:
    +
    Trampa:
    +
    +
    +
    + + + \ 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 @@ + + +Error + + + + + +
    ERROR: #{error}
    +
    + Host ${info['host']}
    +
    + Nombre: ${info['name']}
    + E-mail: ${info['email']}
    + Mensaje:
    + ${info['message']} +
    +
    +
    + + + \ 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 @@ + + + + + +
    + 1000: ?> +
    The thread got over 1000 posts and has been closed.
    + 900: ?> +
    The thread has reached 900 posts. When it reaches 1000 posts it will be closed.
    + +
    +

    #{thread['subject']} (${(str(thread['length'])+" replies") if thread['length']>1 else "1 reply"})

    + + +

    #{post['num']} : Post deleted by user.

    + +

    #{post['num']} : Post deleted by staff.

    + + +
    + +
    + +

    #{post['num']} : + + + #{post['name']} #{post['tripcode']} + + #{post['name']} + + + + #{post['name']} #{post['tripcode']} + + #{post['name']} + + : #{post['timestamp_formatted']} + rep del

    + +
    ${int(post['file_size'])//1024}KB ${post['file'].split(".")[1].upper()}
    + +
    + #{post['message']} +
    +
    + + +
    #{thread['size']}
    +
    +
    + + +
    + + 1000: ?> +
    The thread got over 1000 posts and has been closed.
    + 950: ?> +
    The thread has reached 950 posts. When it reaches 1000 posts it will be closed.
    + 900: ?> +
    The thread has reached 900 posts. When it reaches 1000 posts it will be closed.
    + +
    + + + +
    + Name:  E-mail: 
    +
    + + + + + +
    + + +
    weabot.py ver Bienvenido a Internet BBS/IB
    + + + \ 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 @@ + + + + + +
    + 1000: ?> +
    El hilo superó los 1000 mensajes y ha sido cerrado. Ya no se puede postear en él.
    + 900: ?> +
    El hilo ha recibido más de 900 mensajes. Cuando llegue a 1000 será cerrado.
    + +
    +

    #{thread['subject']} (${(str(thread['length'])+" respuestas") if thread['length']>1 else "Una respuesta"})

    + + +

    #{post['num']} : Mensaje eliminado por el usuario.

    + +

    #{post['num']} : Mensaje eliminado por miembro del staff.

    + + +
    + +
    + +

    #{post['num']} : + + + #{post['name']} #{post['tripcode']} + + #{post['name']} + + + + #{post['name']} #{post['tripcode']} + + #{post['name']} + + : #{post['timestamp_formatted']} + rep del

    + +
    ${int(post['file_size'])//1024}KB ${post['file'].split(".")[1].upper()}
    + +
    #{post['message']}
    +
    + + +
    #{thread['size']}
    +
    +
    + + +
    + + 1000: ?> +
    El hilo superó los 1000 mensajes y ha sido cerrado. Ya no se puede postear en él.
    + 900: ?> +
    El hilo ha recibido más de 900 mensajes. Cuando llegue a 1000 será cerrado.
    + +
    + + + +
    + Nombre:  E-mail: 
    +
    + + + + + +
    + + +
    weabot.py ver Bienvenido a Internet BBS/IB
    + + + \ 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 @@ + + + + + + +
    +

    #{board_long}

    + +
    + + +
    + + + +
    +
    #{iter}:
    + +
    #{thread["length"]}
    +
    #{timestamps[iter-1][1]}
    +
    + + +
    + +
    +
    +
    +
    Formulario de nuevo hilo
    +
    + + + + + + + + + + + + + + + + + +
    Asunto:
    Nombre:E-mail:
    Mensaje:
    Archivo:
    +
    Trampa:
    +
    +
    +
    + + + \ No newline at end of file diff --git a/cgi/tenjin.py b/cgi/tenjin.py new file mode 100644 index 0000000..db8cdde --- /dev/null +++ b/cgi/tenjin.py @@ -0,0 +1,2118 @@ +## +## $Release: 1.1.1 $ +## $Copyright: copyright(c) 2007-2012 kuwata-lab.com all rights reserved. $ +## $License: MIT License $ +## +## Permission is hereby granted, free of charge, to any person obtaining +## a copy of this software and associated documentation files (the +## "Software"), to deal in the Software without restriction, including +## without limitation the rights to use, copy, modify, merge, publish, +## distribute, sublicense, and/or sell copies of the Software, and to +## permit persons to whom the Software is furnished to do so, subject to +## the following conditions: +## +## The above copyright notice and this permission notice shall be +## included in all copies or substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +## LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +## OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +## WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +## + +"""Very fast and light-weight template engine based embedded Python. + See User's Guide and examples for details. + http://www.kuwata-lab.com/tenjin/pytenjin-users-guide.html + http://www.kuwata-lab.com/tenjin/pytenjin-examples.html +""" + +__version__ = "$Release: 1.1.1 $"[10:-2] +__license__ = "$License: MIT License $"[10:-2] +__all__ = ('Template', 'Engine', ) + + +import sys, os, re, time, marshal +from time import time as _time +from os.path import getmtime as _getmtime +from os.path import isfile as _isfile +random = pickle = unquote = None # lazy import +python3 = sys.version_info[0] == 3 +python2 = sys.version_info[0] == 2 + +logger = None + + +## +## utilities +## + +def _write_binary_file(filename, content): + global random + if random is None: from random import random + tmpfile = filename + str(random())[1:] + f = open(tmpfile, 'w+b') # on windows, 'w+b' is preffered than 'wb' + try: + f.write(content) + finally: + f.close() + if os.path.exists(tmpfile): + try: + os.rename(tmpfile, filename) + except: + os.remove(filename) # on windows, existing file should be removed before renaming + os.rename(tmpfile, filename) + +def _read_binary_file(filename): + f = open(filename, 'rb') + try: + return f.read() + finally: + f.close() + +codecs = None # lazy import + +def _read_text_file(filename, encoding=None): + global codecs + if not codecs: import codecs + f = codecs.open(filename, encoding=(encoding or 'utf-8')) + try: + return f.read() + finally: + f.close() + +def _read_template_file(filename, encoding=None): + s = _read_binary_file(filename) ## binary(=str) + if encoding: s = s.decode(encoding) ## binary(=str) to unicode + return s + +_basestring = basestring +_unicode = unicode +_bytes = str + +def _ignore_not_found_error(f, default=None): + try: + return f() + except OSError, ex: + if ex.errno == 2: # error: No such file or directory + return default + raise + +def create_module(module_name, dummy_func=None, **kwargs): + """ex. mod = create_module('tenjin.util')""" + try: + mod = type(sys)(module_name) + except: + # The module creation above does not work for Jython 2.5.2 + import imp + mod = imp.new_module(module_name) + + mod.__file__ = __file__ + mod.__dict__.update(kwargs) + sys.modules[module_name] = mod + if dummy_func: + exec(dummy_func.func_code, mod.__dict__) + return mod + +def _raise(exception_class, *args): + raise exception_class(*args) + + +## +## helper method's module +## + +def _dummy(): + global unquote + unquote = None + global to_str, escape, echo, new_cycle, generate_tostrfunc + global start_capture, stop_capture, capture_as, captured_as, CaptureContext + global _p, _P, _decode_params + + def generate_tostrfunc(encode=None, decode=None): + """Generate 'to_str' function with encode or decode encoding. + ex. generate to_str() function which encodes unicode into binary(=str). + to_str = tenjin.generate_tostrfunc(encode='utf-8') + repr(to_str(u'hoge')) #=> 'hoge' (str) + ex. generate to_str() function which decodes binary(=str) into unicode. + to_str = tenjin.generate_tostrfunc(decode='utf-8') + repr(to_str('hoge')) #=> u'hoge' (unicode) + """ + if encode: + if decode: + raise ValueError("can't specify both encode and decode encoding.") + else: + def to_str(val, _str=str, _unicode=unicode, _isa=isinstance, _encode=encode): + """Convert val into string or return '' if None. Unicode will be encoded into binary(=str).""" + if _isa(val, _str): return val + if val is None: return '' + #if _isa(val, _unicode): return val.encode(_encode) # unicode to binary(=str) + if _isa(val, _unicode): + return val.encode(_encode) # unicode to binary(=str) + return _str(val) + else: + if decode: + def to_str(val, _str=str, _unicode=unicode, _isa=isinstance, _decode=decode): + """Convert val into string or return '' if None. Binary(=str) will be decoded into unicode.""" + #if _isa(val, _str): return val.decode(_decode) # binary(=str) to unicode + if _isa(val, _str): + return val.decode(_decode) + if val is None: return '' + if _isa(val, _unicode): return val + return _unicode(val) + else: + def to_str(val, _str=str, _unicode=unicode, _isa=isinstance): + """Convert val into string or return '' if None. Both binary(=str) and unicode will be retruned as-is.""" + if _isa(val, _str): return val + if val is None: return '' + if _isa(val, _unicode): return val + return _str(val) + return to_str + + to_str = generate_tostrfunc(encode='utf-8') # or encode=None? + + def echo(string): + """add string value into _buf. this is equivarent to '#{string}'.""" + lvars = sys._getframe(1).f_locals # local variables + lvars['_buf'].append(string) + + def new_cycle(*values): + """Generate cycle object. + ex. + cycle = new_cycle('odd', 'even') + print(cycle()) #=> 'odd' + print(cycle()) #=> 'even' + print(cycle()) #=> 'odd' + print(cycle()) #=> 'even' + """ + def gen(values): + i, n = 0, len(values) + while True: + yield values[i] + i = (i + 1) % n + return gen(values).next + + class CaptureContext(object): + + def __init__(self, name, store_to_context=True, lvars=None): + self.name = name + self.store_to_context = store_to_context + self.lvars = lvars or sys._getframe(1).f_locals + + def __enter__(self): + lvars = self.lvars + self._buf_orig = lvars['_buf'] + lvars['_buf'] = _buf = [] + lvars['_extend'] = _buf.extend + return self + + def __exit__(self, *args): + lvars = self.lvars + _buf = lvars['_buf'] + lvars['_buf'] = self._buf_orig + lvars['_extend'] = self._buf_orig.extend + lvars[self.name] = self.captured = ''.join(_buf) + if self.store_to_context and '_context' in lvars: + lvars['_context'][self.name] = self.captured + + def __iter__(self): + self.__enter__() + yield self + self.__exit__() + + def start_capture(varname=None, _depth=1): + """(obsolete) start capturing with name.""" + lvars = sys._getframe(_depth).f_locals + capture_context = CaptureContext(varname, None, lvars) + lvars['_capture_context'] = capture_context + capture_context.__enter__() + + def stop_capture(store_to_context=True, _depth=1): + """(obsolete) stop capturing and return the result of capturing. + if store_to_context is True then the result is stored into _context[varname]. + """ + lvars = sys._getframe(_depth).f_locals + capture_context = lvars.pop('_capture_context', None) + if not capture_context: + raise Exception('stop_capture(): start_capture() is not called before.') + capture_context.store_to_context = store_to_context + capture_context.__exit__() + return capture_context.captured + + def capture_as(name, store_to_context=True): + """capture partial of template.""" + return CaptureContext(name, store_to_context, sys._getframe(1).f_locals) + + def captured_as(name, _depth=1): + """helper method for layout template. + if captured string is found then append it to _buf and return True, + else return False. + """ + lvars = sys._getframe(_depth).f_locals # local variables + if name in lvars: + _buf = lvars['_buf'] + _buf.append(lvars[name]) + return True + return False + + def _p(arg): + """ex. '/show/'+_p("item['id']") => "/show/#{item['id']}" """ + return '<`#%s#`>' % arg # decoded into #{...} by preprocessor + + def _P(arg): + """ex. '%s' % _P("item['id']") => "${item['id']}" """ + return '<`$%s$`>' % arg # decoded into ${...} by preprocessor + + def _decode_params(s): + """decode <`#...#`> and <`$...$`> into #{...} and ${...}""" + global unquote + if unquote is None: + from urllib import unquote + dct = { 'lt':'<', 'gt':'>', 'amp':'&', 'quot':'"', '#039':"'", } + def unescape(s): + #return s.replace('<', '<').replace('>', '>').replace('"', '"').replace(''', "'").replace('&', '&') + return re.sub(r'&(lt|gt|quot|amp|#039);', lambda m: dct[m.group(1)], s) + s = to_str(s) + s = re.sub(r'%3C%60%23(.*?)%23%60%3E', lambda m: '#{%s}' % unquote(m.group(1)), s) + s = re.sub(r'%3C%60%24(.*?)%24%60%3E', lambda m: '${%s}' % unquote(m.group(1)), s) + s = re.sub(r'<`#(.*?)#`>', lambda m: '#{%s}' % unescape(m.group(1)), s) + s = re.sub(r'<`\$(.*?)\$`>', lambda m: '${%s}' % unescape(m.group(1)), s) + s = re.sub(r'<`#(.*?)#`>', r'#{\1}', s) + s = re.sub(r'<`\$(.*?)\$`>', r'${\1}', s) + return s + +helpers = create_module('tenjin.helpers', _dummy, sys=sys, re=re) +helpers.__all__ = ['to_str', 'escape', 'echo', 'new_cycle', 'generate_tostrfunc', + 'start_capture', 'stop_capture', 'capture_as', 'captured_as', + 'not_cached', 'echo_cached', 'cache_as', + '_p', '_P', '_decode_params', + ] +generate_tostrfunc = helpers.generate_tostrfunc + + +## +## escaped module +## +def _dummy(): + global is_escaped, as_escaped, to_escaped + global Escaped, EscapedStr, EscapedUnicode + global __all__ + __all__ = ('is_escaped', 'as_escaped', 'to_escaped', ) #'Escaped', 'EscapedStr', + + class Escaped(object): + """marking class that object is already escaped.""" + pass + + def is_escaped(value): + """return True if value is marked as escaped, else return False.""" + return isinstance(value, Escaped) + + class EscapedStr(str, Escaped): + """string class which is marked as escaped.""" + pass + + class EscapedUnicode(unicode, Escaped): + """unicode class which is marked as escaped.""" + pass + + def as_escaped(s): + """mark string as escaped, without escaping.""" + if isinstance(s, str): return EscapedStr(s) + if isinstance(s, unicode): return EscapedUnicode(s) + raise TypeError("as_escaped(%r): expected str or unicode." % (s, )) + + def to_escaped(value): + """convert any value into string and escape it. + if value is already marked as escaped, don't escape it.""" + if hasattr(value, '__html__'): + value = value.__html__() + if is_escaped(value): + #return value # EscapedUnicode should be convered into EscapedStr + return as_escaped(_helpers.to_str(value)) + #if isinstance(value, _basestring): + # return as_escaped(_helpers.escape(value)) + return as_escaped(_helpers.escape(_helpers.to_str(value))) + +escaped = create_module('tenjin.escaped', _dummy, _helpers=helpers) + + +## +## module for html +## +def _dummy(): + global escape_html, escape_xml, escape, tagattr, tagattrs, _normalize_attrs + global checked, selected, disabled, nl2br, text2html, nv, js_link + + #_escape_table = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' } + #_escape_pattern = re.compile(r'[&<>"]') + ##_escape_callable = lambda m: _escape_table[m.group(0)] + ##_escape_callable = lambda m: _escape_table.__get__(m.group(0)) + #_escape_get = _escape_table.__getitem__ + #_escape_callable = lambda m: _escape_get(m.group(0)) + #_escape_sub = _escape_pattern.sub + + #def escape_html(s): + # return s # 3.02 + + #def escape_html(s): + # return _escape_pattern.sub(_escape_callable, s) # 6.31 + + #def escape_html(s): + # return _escape_sub(_escape_callable, s) # 6.01 + + #def escape_html(s, _p=_escape_pattern, _f=_escape_callable): + # return _p.sub(_f, s) # 6.27 + + #def escape_html(s, _sub=_escape_pattern.sub, _callable=_escape_callable): + # return _sub(_callable, s) # 6.04 + + #def escape_html(s): + # s = s.replace('&', '&') + # s = s.replace('<', '<') + # s = s.replace('>', '>') + # s = s.replace('"', '"') + # return s # 5.83 + + def escape_html(s): + """Escape '&', '<', '>', '"' into '&', '<', '>', '"'.""" + return s.replace('&', '&').replace('<', '<').replace('>', '>').replace('"', '"').replace("'", ''') # 5.72 + + escape_xml = escape_html # for backward compatibility + + def tagattr(name, expr, value=None, escape=True): + """(experimental) Return ' name="value"' if expr is true value, else '' (empty string). + If value is not specified, expr is used as value instead.""" + if not expr and expr != 0: return _escaped.as_escaped('') + if value is None: value = expr + if escape: value = _escaped.to_escaped(value) + return _escaped.as_escaped(' %s="%s"' % (name, value)) + + def tagattrs(**kwargs): + """(experimental) built html tag attribtes. + ex. + >>> tagattrs(klass='main', size=20) + ' class="main" size="20"' + >>> tagattrs(klass='', size=0) + '' + """ + kwargs = _normalize_attrs(kwargs) + esc = _escaped.to_escaped + s = ''.join([ ' %s="%s"' % (k, esc(v)) for k, v in kwargs.iteritems() if v or v == 0 ]) + return _escaped.as_escaped(s) + + def _normalize_attrs(kwargs): + if 'klass' in kwargs: kwargs['class'] = kwargs.pop('klass') + if 'checked' in kwargs: kwargs['checked'] = kwargs.pop('checked') and 'checked' or None + if 'selected' in kwargs: kwargs['selected'] = kwargs.pop('selected') and 'selected' or None + if 'disabled' in kwargs: kwargs['disabled'] = kwargs.pop('disabled') and 'disabled' or None + return kwargs + + def checked(expr): + """return ' checked="checked"' if expr is true.""" + return _escaped.as_escaped(expr and ' checked="checked"' or '') + + def selected(expr): + """return ' selected="selected"' if expr is true.""" + return _escaped.as_escaped(expr and ' selected="selected"' or '') + + def disabled(expr): + """return ' disabled="disabled"' if expr is true.""" + return _escaped.as_escaped(expr and ' disabled="disabled"' or '') + + def nl2br(text): + """replace "\n" to "
    \n" and return it.""" + if not text: + return _escaped.as_escaped('') + return _escaped.as_escaped(text.replace('\n', '
    \n')) + + def text2html(text, use_nbsp=True): + """(experimental) escape xml characters, replace "\n" to "
    \n", and return it.""" + if not text: + return _escaped.as_escaped('') + s = _escaped.to_escaped(text) + if use_nbsp: s = s.replace(' ', '  ') + #return nl2br(s) + s = s.replace('\n', '
    \n') + return _escaped.as_escaped(s) + + def nv(name, value, sep=None, **kwargs): + """(experimental) Build name and value attributes. + ex. + >>> nv('rank', 'A') + 'name="rank" value="A"' + >>> nv('rank', 'A', '.') + 'name="rank" value="A" id="rank.A"' + >>> nv('rank', 'A', '.', checked=True) + 'name="rank" value="A" id="rank.A" checked="checked"' + >>> nv('rank', 'A', '.', klass='error', style='color:red') + 'name="rank" value="A" id="rank.A" class="error" style="color:red"' + """ + name = _escaped.to_escaped(name) + value = _escaped.to_escaped(value) + s = sep and 'name="%s" value="%s" id="%s"' % (name, value, name+sep+value) \ + or 'name="%s" value="%s"' % (name, value) + html = kwargs and s + tagattrs(**kwargs) or s + return _escaped.as_escaped(html) + + def js_link(label, onclick, **kwargs): + s = kwargs and tagattrs(**kwargs) or '' + html = '%s' % \ + (_escaped.to_escaped(onclick), s, _escaped.to_escaped(label)) + return _escaped.as_escaped(html) + +html = create_module('tenjin.html', _dummy, helpers=helpers, _escaped=escaped) +helpers.escape = html.escape_html +helpers.html = html # for backward compatibility +sys.modules['tenjin.helpers.html'] = html + + +## +## utility function to set default encoding of template files +## +_template_encoding = (None, 'utf-8') # encodings for decode and encode + +def set_template_encoding(decode=None, encode=None): + """Set default encoding of template files. + This should be called before importing helper functions. + ex. + ## I like template files to be unicode-base like Django. + import tenjin + tenjin.set_template_encoding('utf-8') # should be called before importing helpers + from tenjin.helpers import * + """ + global _template_encoding + if _template_encoding == (decode, encode): + return + if decode and encode: + raise ValueError("set_template_encoding(): cannot specify both decode and encode.") + if not decode and not encode: + raise ValueError("set_template_encoding(): decode or encode should be specified.") + if decode: + Template.encoding = decode # unicode base template + helpers.to_str = helpers.generate_tostrfunc(decode=decode) + else: + Template.encoding = None # binary base template + helpers.to_str = helpers.generate_tostrfunc(encode=encode) + _template_encoding = (decode, encode) + + +## +## Template class +## + +class TemplateSyntaxError(SyntaxError): + + def build_error_message(self): + ex = self + if not ex.text: + return self.args[0] + return ''.join([ + "%s:%s:%s: %s\n" % (ex.filename, ex.lineno, ex.offset, ex.msg, ), + "%4d: %s\n" % (ex.lineno, ex.text.rstrip(), ), + " %s^\n" % (' ' * ex.offset, ), + ]) + + +class Template(object): + """Convert and evaluate embedded python string. + See User's Guide and examples for details. + http://www.kuwata-lab.com/tenjin/pytenjin-users-guide.html + http://www.kuwata-lab.com/tenjin/pytenjin-examples.html + """ + + ## default value of attributes + filename = None + encoding = None + escapefunc = 'escape' + tostrfunc = 'to_str' + indent = 4 + preamble = None # "_buf = []; _expand = _buf.expand; _to_str = to_str; _escape = escape" + postamble = None # "print ''.join(_buf)" + smarttrim = None + args = None + timestamp = None + trace = False # if True then '' and '' are printed + + def __init__(self, filename=None, encoding=None, input=None, escapefunc=None, tostrfunc=None, + indent=None, preamble=None, postamble=None, smarttrim=None, trace=None): + """Initailizer of Template class. + + filename:str (=None) + Filename to convert (optional). If None, no convert. + encoding:str (=None) + Encoding name. If specified, template string is converted into + unicode object internally. + Template.render() returns str object if encoding is None, + else returns unicode object if encoding name is specified. + input:str (=None) + Input string. In other words, content of template file. + Template file will not be read if this argument is specified. + escapefunc:str (='escape') + Escape function name. + tostrfunc:str (='to_str') + 'to_str' function name. + indent:int (=4) + Indent width. + preamble:str or bool (=None) + Preamble string which is inserted into python code. + If true, '_buf = []; ' is used insated. + postamble:str or bool (=None) + Postamble string which is appended to python code. + If true, 'print("".join(_buf))' is used instead. + smarttrim:bool (=None) + If True then "
    \\n#{_context}\\n
    " is parsed as + "
    \\n#{_context}
    ". + """ + if encoding is not None: self.encoding = encoding + if escapefunc is not None: self.escapefunc = escapefunc + if tostrfunc is not None: self.tostrfunc = tostrfunc + if indent is not None: self.indent = indent + if preamble is not None: self.preamble = preamble + if postamble is not None: self.postamble = postamble + if smarttrim is not None: self.smarttrim = smarttrim + if trace is not None: self.trace = trace + # + if preamble is True: self.preamble = "_buf = []" + if postamble is True: self.postamble = "print(''.join(_buf))" + if input: + self.convert(input, filename) + self.timestamp = False # False means 'file not exist' (= Engine should not check timestamp of file) + elif filename: + self.convert_file(filename) + else: + self._reset() + + def _reset(self, input=None, filename=None): + self.script = None + self.bytecode = None + self.input = input + self.filename = filename + if input != None: + i = input.find("\n") + if i < 0: + self.newline = "\n" # or None + elif len(input) >= 2 and input[i-1] == "\r": + self.newline = "\r\n" + else: + self.newline = "\n" + self._localvars_assignments_added = False + + def _localvars_assignments(self): + return "_extend=_buf.extend;_to_str=%s;_escape=%s; " % (self.tostrfunc, self.escapefunc) + + def before_convert(self, buf): + if self.preamble: + eol = self.input.startswith('([ \t]*\r?\n)?', re.S) + + def stmt_pattern(self): + pat = self.STMT_PATTERN + if isinstance(pat, tuple): + pat = self.__class__.STMT_PATTERN = re.compile(*pat) + return pat + + def parse_stmts(self, buf, input): + if not input: return + rexp = self.stmt_pattern() + is_bol = True + index = 0 + for m in rexp.finditer(input): + mspace, code, rspace = m.groups() + #mspace, close, rspace = m.groups() + #code = input[m.start()+4+len(mspace):m.end()-len(close)-(rspace and len(rspace) or 0)] + text = input[index:m.start()] + index = m.end() + ## detect spaces at beginning of line + lspace = None + if text == '': + if is_bol: + lspace = '' + elif text[-1] == '\n': + lspace = '' + else: + rindex = text.rfind('\n') + if rindex < 0: + if is_bol and text.isspace(): + lspace, text = text, '' + else: + s = text[rindex+1:] + if s.isspace(): + lspace, text = s, text[:rindex+1] + #is_bol = rspace is not None + ## add text, spaces, and statement + self.parse_exprs(buf, text, is_bol) + is_bol = rspace is not None + #if mspace == "\n": + if mspace and mspace.endswith("\n"): + code = "\n" + (code or "") + #if rspace == "\n": + if rspace and rspace.endswith("\n"): + code = (code or "") + "\n" + if code: + code = self.statement_hook(code) + m = self._match_to_args_declaration(code) + if m: + self._add_args_declaration(buf, m) + else: + self.add_stmt(buf, code) + rest = input[index:] + if rest: + self.parse_exprs(buf, rest) + self._arrange_indent(buf) + + def statement_hook(self, stmt): + """expand macros and parse '#@ARGS' in a statement.""" + return stmt.replace("\r\n", "\n") # Python can't handle "\r\n" in code + + def _match_to_args_declaration(self, stmt): + if self.args is not None: + return None + args_pattern = r'^ *#@ARGS(?:[ \t]+(.*?))?$' + return re.match(args_pattern, stmt) + + def _add_args_declaration(self, buf, m): + arr = (m.group(1) or '').split(',') + args = []; declares = [] + for s in arr: + arg = s.strip() + if not s: continue + if not re.match('^[a-zA-Z_]\w*$', arg): + raise ValueError("%r: invalid template argument." % arg) + args.append(arg) + declares.append("%s = _context.get('%s'); " % (arg, arg)) + self.args = args + #nl = stmt[m.end():] + #if nl: declares.append(nl) + buf.append(''.join(declares) + "\n") + + s = '(?:\{.*?\}.*?)*' + EXPR_PATTERN = (r'#\{(.*?'+s+r')\}|\$\{(.*?'+s+r')\}|\{=(?:=(.*?)=|(.*?))=\}', re.S) + del s + + def expr_pattern(self): + pat = self.EXPR_PATTERN + if isinstance(pat, tuple): + self.__class__.EXPR_PATTERN = pat = re.compile(*pat) + return pat + + def get_expr_and_flags(self, match): + expr1, expr2, expr3, expr4 = match.groups() + if expr1 is not None: return expr1, (False, True) # not escape, call to_str + if expr2 is not None: return expr2, (True, True) # call escape, call to_str + if expr3 is not None: return expr3, (False, True) # not escape, call to_str + if expr4 is not None: return expr4, (True, True) # call escape, call to_str + + def parse_exprs(self, buf, input, is_bol=False): + buf2 = [] + self._parse_exprs(buf2, input, is_bol) + if buf2: + buf.append(''.join(buf2)) + + def _parse_exprs(self, buf, input, is_bol=False): + if not input: return + self.start_text_part(buf) + rexp = self.expr_pattern() + smarttrim = self.smarttrim + nl = self.newline + nl_len = len(nl) + pos = 0 + for m in rexp.finditer(input): + start = m.start() + text = input[pos:start] + pos = m.end() + expr, flags = self.get_expr_and_flags(m) + # + if text: + self.add_text(buf, text) + self.add_expr(buf, expr, *flags) + # + if smarttrim: + flag_bol = text.endswith(nl) or not text and (start > 0 or is_bol) + if flag_bol and not flags[0] and input[pos:pos+nl_len] == nl: + pos += nl_len + buf.append("\n") + if smarttrim: + if buf and buf[-1] == "\n": + buf.pop() + rest = input[pos:] + if rest: + self.add_text(buf, rest, True) + self.stop_text_part(buf) + if input[-1] == '\n': + buf.append("\n") + + def start_text_part(self, buf): + self._add_localvars_assignments_to_text(buf) + #buf.append("_buf.extend((") + buf.append("_extend((") + + def _add_localvars_assignments_to_text(self, buf): + if not self._localvars_assignments_added: + self._localvars_assignments_added = True + buf.append(self._localvars_assignments()) + + def stop_text_part(self, buf): + buf.append("));") + + def _quote_text(self, text): + text = re.sub(r"(['\\\\])", r"\\\1", text) + text = text.replace("\r\n", "\\r\n") + return text + + def add_text(self, buf, text, encode_newline=False): + if not text: return + use_unicode = self.encoding and python2 + buf.append(use_unicode and "u'''" or "'''") + text = self._quote_text(text) + if not encode_newline: buf.extend((text, "''', ")) + elif text.endswith("\r\n"): buf.extend((text[0:-2], "\\r\\n''', ")) + elif text.endswith("\n"): buf.extend((text[0:-1], "\\n''', ")) + else: buf.extend((text, "''', ")) + + _add_text = add_text + + def add_expr(self, buf, code, *flags): + if not code or code.isspace(): return + flag_escape, flag_tostr = flags + if not self.tostrfunc: flag_tostr = False + if not self.escapefunc: flag_escape = False + if flag_tostr and flag_escape: s1, s2 = "_escape(_to_str(", ")), " + elif flag_tostr: s1, s2 = "_to_str(", "), " + elif flag_escape: s1, s2 = "_escape(", "), " + else: s1, s2 = "(", "), " + buf.extend((s1, code, s2, )) + + def add_stmt(self, buf, code): + if not code: return + lines = code.splitlines(True) # keep "\n" + if lines[-1][-1] != "\n": + lines[-1] = lines[-1] + "\n" + buf.extend(lines) + self._add_localvars_assignments_to_stmts(buf) + + def _add_localvars_assignments_to_stmts(self, buf): + if self._localvars_assignments_added: + return + for index, stmt in enumerate(buf): + if not re.match(r'^[ \t]*(?:\#|_buf ?= ?\[\]|from __future__)', stmt): + break + else: + return + self._localvars_assignments_added = True + if re.match(r'^[ \t]*(if|for|while|def|with|class)\b', stmt): + buf.insert(index, self._localvars_assignments() + "\n") + else: + buf[index] = self._localvars_assignments() + buf[index] + + + _START_WORDS = dict.fromkeys(('for', 'if', 'while', 'def', 'try:', 'with', 'class'), True) + _END_WORDS = dict.fromkeys(('#end', '#endfor', '#endif', '#endwhile', '#enddef', '#endtry', '#endwith', '#endclass'), True) + _CONT_WORDS = dict.fromkeys(('elif', 'else:', 'except', 'except:', 'finally:'), True) + _WORD_REXP = re.compile(r'\S+') + + depth = -1 + + ## + ## ex. + ## input = r""" + ## if items: + ## _buf.extend(('
      \n', )) + ## i = 0 + ## for item in items: + ## i += 1 + ## _buf.extend(('
    • ', to_str(item), '
    • \n', )) + ## #endfor + ## _buf.extend(('
    \n', )) + ## #endif + ## """[1:] + ## lines = input.splitlines(True) + ## block = self.parse_lines(lines) + ## #=> [ "if items:\n", + ## [ "_buf.extend(('
      \n', ))\n", + ## "i = 0\n", + ## "for item in items:\n", + ## [ "i += 1\n", + ## "_buf.extend(('
    • ', to_str(item), '
    • \n', ))\n", + ## ], + ## "#endfor\n", + ## "_buf.extend(('
    \n', ))\n", + ## ], + ## "#endif\n", + ## ] + def parse_lines(self, lines): + block = [] + try: + self._parse_lines(lines.__iter__(), False, block, 0) + except StopIteration: + if self.depth > 0: + fname, linenum, colnum, linetext = self.filename, len(lines), None, None + raise TemplateSyntaxError("unexpected EOF.", (fname, linenum, colnum, linetext)) + else: + pass + return block + + def _parse_lines(self, lines_iter, end_block, block, linenum): + if block is None: block = [] + _START_WORDS = self._START_WORDS + _END_WORDS = self._END_WORDS + _CONT_WORDS = self._CONT_WORDS + _WORD_REXP = self._WORD_REXP + get_line = lines_iter.next + while True: + line = get_line() + linenum += line.count("\n") + m = _WORD_REXP.search(line) + if not m: + block.append(line) + continue + word = m.group(0) + if word in _END_WORDS: + if word != end_block and word != '#end': + if end_block is False: + msg = "'%s' found but corresponding statement is missing." % (word, ) + else: + msg = "'%s' expected but got '%s'." % (end_block, word) + colnum = m.start() + 1 + raise TemplateSyntaxError(msg, (self.filename, linenum, colnum, line)) + return block, line, None, linenum + elif line.endswith(':\n') or line.endswith(':\r\n'): + if word in _CONT_WORDS: + return block, line, word, linenum + elif word in _START_WORDS: + block.append(line) + self.depth += 1 + cont_word = None + try: + child_block, line, cont_word, linenum = \ + self._parse_lines(lines_iter, '#end'+word, [], linenum) + block.extend((child_block, line, )) + while cont_word: # 'elif' or 'else:' + child_block, line, cont_word, linenum = \ + self._parse_lines(lines_iter, '#end'+word, [], linenum) + block.extend((child_block, line, )) + except StopIteration: + msg = "'%s' is not closed." % (cont_word or word) + colnum = m.start() + 1 + raise TemplateSyntaxError(msg, (self.filename, linenum, colnum, line)) + self.depth -= 1 + else: + block.append(line) + else: + block.append(line) + assert "unreachable" + + def _join_block(self, block, buf, depth): + indent = ' ' * (self.indent * depth) + for line in block: + if isinstance(line, list): + self._join_block(line, buf, depth+1) + elif line.isspace(): + buf.append(line) + else: + buf.append(indent + line.lstrip()) + + def _arrange_indent(self, buf): + """arrange indentation of statements in buf""" + block = self.parse_lines(buf) + buf[:] = [] + self._join_block(block, buf, 0) + + + def render(self, context=None, globals=None, _buf=None): + """Evaluate python code with context dictionary. + If _buf is None then return the result of evaluation as str, + else return None. + + context:dict (=None) + Context object to evaluate. If None then new dict is created. + globals:dict (=None) + Global object. If None then globals() is used. + _buf:list (=None) + If None then new list is created. + """ + if context is None: + locals = context = {} + elif self.args is None: + locals = context.copy() + else: + locals = {} + if '_engine' in context: + context.get('_engine').hook_context(locals) + locals['_context'] = context + if globals is None: + globals = sys._getframe(1).f_globals + bufarg = _buf + if _buf is None: + _buf = [] + locals['_buf'] = _buf + if not self.bytecode: + self.compile() + if self.trace: + _buf.append("\n" % self.filename) + exec(self.bytecode, globals, locals) + _buf.append("\n" % self.filename) + else: + exec(self.bytecode, globals, locals) + if bufarg is not None: + return bufarg + elif not logger: + return ''.join(_buf) + else: + try: + return ''.join(_buf) + except UnicodeDecodeError, ex: + logger.error("[tenjin.Template] " + str(ex)) + logger.error("[tenjin.Template] (_buf=%r)" % (_buf, )) + raise + + def compile(self): + """compile self.script into self.bytecode""" + self.bytecode = compile(self.script, self.filename or '(tenjin)', 'exec') + + +## +## preprocessor class +## + +class Preprocessor(Template): + """Template class for preprocessing.""" + + STMT_PATTERN = (r'<\?PY( |\t|\r?\n)(.*?) ?\?>([ \t]*\r?\n)?', re.S) + + EXPR_PATTERN = (r'#\{\{(.*?)\}\}|\$\{\{(.*?)\}\}|\{#=(?:=(.*?)=|(.*?))=#\}', re.S) + + def add_expr(self, buf, code, *flags): + if not code or code.isspace(): + return + code = "_decode_params(%s)" % code + Template.add_expr(self, buf, code, *flags) + + +class TemplatePreprocessor(object): + factory = Preprocessor + + def __init__(self, factory=None): + if factory is not None: self.factory = factory + self.globals = sys._getframe(1).f_globals + + def __call__(self, input, **kwargs): + filename = kwargs.get('filename') + context = kwargs.get('context') or {} + globals = kwargs.get('globals') or self.globals + template = self.factory() + template.convert(input, filename) + return template.render(context, globals=globals) + + +class TrimPreprocessor(object): + + _rexp = re.compile(r'^[ \t]+<', re.M) + _rexp_all = re.compile(r'^[ \t]+', re.M) + + def __init__(self, all=False): + self.all = all + + def __call__(self, input, **kwargs): + if self.all: + return self._rexp_all.sub('', input) + else: + return self._rexp.sub('<', input) + + +class PrefixedLinePreprocessor(object): + + def __init__(self, prefix='::(?=[ \t]|$)'): + self.prefix = prefix + self.regexp = re.compile(r'^([ \t]*)' + prefix + r'(.*)', re.M) + + def convert_prefixed_lines(self, text): + fn = lambda m: "%s" % (m.group(1), m.group(2)) + return self.regexp.sub(fn, text) + + STMT_REXP = re.compile(r'<\?py\s.*?\?>', re.S) + + def __call__(self, input, **kwargs): + buf = []; append = buf.append + pos = 0 + for m in self.STMT_REXP.finditer(input): + text = input[pos:m.start()] + stmt = m.group(0) + pos = m.end() + if text: append(self.convert_prefixed_lines(text)) + append(stmt) + rest = input[pos:] + if rest: append(self.convert_prefixed_lines(rest)) + return "".join(buf) + + +class ParseError(Exception): + pass + + +class JavaScriptPreprocessor(object): + + def __init__(self, **attrs): + self._attrs = attrs + + def __call__(self, input, **kwargs): + return self.parse(input, kwargs.get('filename')) + + def parse(self, input, filename=None): + buf = [] + self._parse_chunks(input, buf, filename) + return ''.join(buf) + + CHUNK_REXP = re.compile(r'(?:^( *)<|<)!-- *#(?:JS: (\$?\w+(?:\.\w+)*\(.*?\))|/JS:?) *-->([ \t]*\r?\n)?', re.M) + + def _scan_chunks(self, input, filename): + rexp = self.CHUNK_REXP + pos = 0 + curr_funcdecl = None + for m in rexp.finditer(input): + lspace, funcdecl, rspace = m.groups() + text = input[pos:m.start()] + pos = m.end() + if funcdecl: + if curr_funcdecl: + raise ParseError("%s is nested in %s. (file: %s, line: %s)" % \ + (funcdecl, curr_funcdecl, filename, _linenum(input, m.start()), )) + curr_funcdecl = funcdecl + else: + if not curr_funcdecl: + raise ParseError("unexpected ''. (file: %s, line: %s)" % \ + (filename, _linenum(input, m.start()), )) + curr_funcdecl = None + yield text, lspace, funcdecl, rspace, False + if curr_funcdecl: + raise ParseError("%s is not closed by ''. (file: %s, line: %s)" % \ + (curr_funcdecl, filename, _linenum(input, m.start()), )) + rest = input[pos:] + yield rest, None, None, None, True + + def _parse_chunks(self, input, buf, filename=None): + if not input: return + stag = '([ \t]*\r?\n)?', re.M | re.S) + + def _scan_stmts(self, input): + rexp = self.STMT_REXP + pos = 0 + for m in rexp.finditer(input): + lspace, code, rspace = m.groups() + text = input[pos:m.start()] + pos = m.end() + yield text, lspace, code, rspace, False + rest = input[pos:] + yield rest, None, None, None, True + + def _parse_stmts(self, input, buf): + if not input: return + for text, lspace, code, rspace, end_p in self._scan_stmts(input): + if end_p: break + if lspace is not None and rspace is not None: + self._parse_exprs(text, buf) + buf.extend((lspace, code, rspace)) + else: + if lspace: + text += lspace + self._parse_exprs(text, buf) + buf.append(code) + if rspace: + self._parse_exprs(rspace, buf) + if text: + self._parse_exprs(text, buf) + + s = r'(?:\{[^{}]*?\}[^{}]*?)*' + EXPR_REXP = re.compile(r'\{=(.*?)=\}|([$#])\{(.*?' + s + r')\}', re.S) + del s + + def _get_expr(self, m): + code1, ch, code2 = m.groups() + if ch: + code = code2 + escape_p = ch == '$' + elif code1[0] == code1[-1] == '=': + code = code1[1:-1] + escape_p = False + else: + code = code1 + escape_p = True + return code, escape_p + + def _scan_exprs(self, input): + rexp = self.EXPR_REXP + pos = 0 + for m in rexp.finditer(input): + text = input[pos:m.start()] + pos = m.end() + code, escape_p = self._get_expr(m) + yield text, code, escape_p, False + rest = input[pos:] + yield rest, None, None, True + + def _parse_exprs(self, input, buf): + if not input: return + buf.append("_buf+=") + extend = buf.extend + op = '' + for text, code, escape_p, end_p in self._scan_exprs(input): + if end_p: + break + if text: + extend((op, self._escape_text(text))) + op = '+' + if code: + extend((op, escape_p and '_E(' or '_S(', code, ')')) + op = '+' + rest = text + if rest: + extend((op, self._escape_text(rest))) + if input.endswith("\n"): + buf.append(";\n") + else: + buf.append(";") + + def _escape_text(self, text): + lines = text.splitlines(True) + fn = self._escape_str + s = "\\\n".join( fn(line) for line in lines ) + return "".join(("'", s, "'")) + + def _escape_str(self, string): + return string.replace("\\", "\\\\").replace("'", "\\'").replace("\n", r"\n") + + +def _linenum(input, pos): + return input[0:pos].count("\n") + 1 + + +JS_FUNC = r""" +function _S(x){return x==null?'':x;} +function _E(x){return x==null?'':typeof(x)!=='string'?x:x.replace(/[&<>"']/g,_EF);} +var _ET={'&':"&",'<':"<",'>':">",'"':""","'":"'"}; +function _EF(c){return _ET[c];}; +"""[1:-1] +JS_FUNC = escaped.EscapedStr(JS_FUNC) + + + +## +## cache storages +## + +class CacheStorage(object): + """[abstract] Template object cache class (in memory and/or file)""" + + def __init__(self): + self.items = {} # key: full path, value: template object + + def get(self, cachepath, create_template): + """get template object. if not found, load attributes from cache file and restore template object.""" + template = self.items.get(cachepath) + if not template: + dct = self._load(cachepath) + if dct: + template = create_template() + for k in dct: + setattr(template, k, dct[k]) + self.items[cachepath] = template + return template + + def set(self, cachepath, template): + """set template object and save template attributes into cache file.""" + self.items[cachepath] = template + dct = self._save_data_of(template) + return self._store(cachepath, dct) + + def _save_data_of(self, template): + return { 'args' : template.args, 'bytecode' : template.bytecode, + 'script': template.script, 'timestamp': template.timestamp } + + def unset(self, cachepath): + """remove template object from dict and cache file.""" + self.items.pop(cachepath, None) + return self._delete(cachepath) + + def clear(self): + """remove all template objects and attributes from dict and cache file.""" + d, self.items = self.items, {} + for k in d.iterkeys(): + self._delete(k) + d.clear() + + def _load(self, cachepath): + """(abstract) load dict object which represents template object attributes from cache file.""" + raise NotImplementedError.new("%s#_load(): not implemented yet." % self.__class__.__name__) + + def _store(self, cachepath, template): + """(abstract) load dict object which represents template object attributes from cache file.""" + raise NotImplementedError.new("%s#_store(): not implemented yet." % self.__class__.__name__) + + def _delete(self, cachepath): + """(abstract) remove template object from cache file.""" + raise NotImplementedError.new("%s#_delete(): not implemented yet." % self.__class__.__name__) + + +class MemoryCacheStorage(CacheStorage): + + def _load(self, cachepath): + return None + + def _store(self, cachepath, template): + pass + + def _delete(self, cachepath): + pass + + +class FileCacheStorage(CacheStorage): + + def _load(self, cachepath): + if not _isfile(cachepath): return None + if logger: logger.info("[tenjin.%s] load cache (file=%r)" % (self.__class__.__name__, cachepath)) + data = _read_binary_file(cachepath) + return self._restore(data) + + def _store(self, cachepath, dct): + if logger: logger.info("[tenjin.%s] store cache (file=%r)" % (self.__class__.__name__, cachepath)) + data = self._dump(dct) + _write_binary_file(cachepath, data) + + def _restore(self, data): + raise NotImplementedError("%s._restore(): not implemented yet." % self.__class__.__name__) + + def _dump(self, dct): + raise NotImplementedError("%s._dump(): not implemented yet." % self.__class__.__name__) + + def _delete(self, cachepath): + _ignore_not_found_error(lambda: os.unlink(cachepath)) + + +class MarshalCacheStorage(FileCacheStorage): + + def _restore(self, data): + return marshal.loads(data) + + def _dump(self, dct): + return marshal.dumps(dct) + + +class PickleCacheStorage(FileCacheStorage): + + def __init__(self, *args, **kwargs): + global pickle + if pickle is None: + import cPickle as pickle + FileCacheStorage.__init__(self, *args, **kwargs) + + def _restore(self, data): + return pickle.loads(data) + + def _dump(self, dct): + dct.pop('bytecode', None) + return pickle.dumps(dct) + + +class TextCacheStorage(FileCacheStorage): + + def _restore(self, data): + header, script = data.split("\n\n", 1) + timestamp = encoding = args = None + for line in header.split("\n"): + key, val = line.split(": ", 1) + if key == 'timestamp': timestamp = float(val) + elif key == 'encoding': encoding = val + elif key == 'args': args = val.split(', ') + if encoding: script = script.decode(encoding) ## binary(=str) to unicode + return {'args': args, 'script': script, 'timestamp': timestamp} + + def _dump(self, dct): + s = dct['script'] + if dct.get('encoding') and isinstance(s, unicode): + s = s.encode(dct['encoding']) ## unicode to binary(=str) + sb = [] + sb.append("timestamp: %s\n" % dct['timestamp']) + if dct.get('encoding'): + sb.append("encoding: %s\n" % dct['encoding']) + if dct.get('args') is not None: + sb.append("args: %s\n" % ', '.join(dct['args'])) + sb.append("\n") + sb.append(s) + s = ''.join(sb) + if python3: + if isinstance(s, str): + s = s.encode(dct.get('encoding') or 'utf-8') ## unicode(=str) to binary + return s + + def _save_data_of(self, template): + dct = FileCacheStorage._save_data_of(self, template) + dct['encoding'] = template.encoding + return dct + + + +## +## abstract class for data cache +## +class KeyValueStore(object): + + def get(self, key, *options): + raise NotImplementedError("%s.get(): not implemented yet." % self.__class__.__name__) + + def set(self, key, value, *options): + raise NotImplementedError("%s.set(): not implemented yet." % self.__class__.__name__) + + def delete(self, key, *options): + raise NotImplementedError("%s.del(): not implemented yet." % self.__class__.__name__) + + def has(self, key, *options): + raise NotImplementedError("%s.has(): not implemented yet." % self.__class__.__name__) + + +## +## memory base data cache +## +class MemoryBaseStore(KeyValueStore): + + def __init__(self): + self.values = {} + + def get(self, key, original_timestamp=None): + tupl = self.values.get(key) + if not tupl: + return None + value, created_at, expires_at = tupl + if original_timestamp is not None and created_at < original_timestamp: + self.delete(key) + return None + if expires_at < _time(): + self.delete(key) + return None + return value + + def set(self, key, value, lifetime=0): + created_at = _time() + expires_at = lifetime and created_at + lifetime or 0 + self.values[key] = (value, created_at, expires_at) + return True + + def delete(self, key): + try: + del self.values[key] + return True + except KeyError: + return False + + def has(self, key): + pair = self.values.get(key) + if not pair: + return False + value, created_at, expires_at = pair + if expires_at and expires_at < _time(): + self.delete(key) + return False + return True + + +## +## file base data cache +## +class FileBaseStore(KeyValueStore): + + lifetime = 604800 # = 60*60*24*7 + + def __init__(self, root_path, encoding=None): + if not os.path.isdir(root_path): + raise ValueError("%r: directory not found." % (root_path, )) + self.root_path = root_path + if encoding is None and python3: + encoding = 'utf-8' + self.encoding = encoding + + _pat = re.compile(r'[^-.\/\w]') + + def filepath(self, key, _pat1=_pat): + return os.path.join(self.root_path, _pat1.sub('_', key)) + + def get(self, key, original_timestamp=None): + fpath = self.filepath(key) + #if not _isfile(fpath): return None + stat = _ignore_not_found_error(lambda: os.stat(fpath), None) + if stat is None: + return None + created_at = stat.st_ctime + expires_at = stat.st_mtime + if original_timestamp is not None and created_at < original_timestamp: + self.delete(key) + return None + if expires_at < _time(): + self.delete(key) + return None + if self.encoding: + f = lambda: _read_text_file(fpath, self.encoding) + else: + f = lambda: _read_binary_file(fpath) + return _ignore_not_found_error(f, None) + + def set(self, key, value, lifetime=0): + fpath = self.filepath(key) + dirname = os.path.dirname(fpath) + if not os.path.isdir(dirname): + os.makedirs(dirname) + now = _time() + if isinstance(value, _unicode): + value = value.encode(self.encoding or 'utf-8') + _write_binary_file(fpath, value) + expires_at = now + (lifetime or self.lifetime) # timestamp + os.utime(fpath, (expires_at, expires_at)) + return True + + def delete(self, key): + fpath = self.filepath(key) + ret = _ignore_not_found_error(lambda: os.unlink(fpath), False) + return ret != False + + def has(self, key): + fpath = self.filepath(key) + if not _isfile(fpath): + return False + if _getmtime(fpath) < _time(): + self.delete(key) + return False + return True + + + +## +## html fragment cache helper class +## +class FragmentCacheHelper(object): + """html fragment cache helper class.""" + + lifetime = 60 # 1 minute + prefix = None + + def __init__(self, store, lifetime=None, prefix=None): + self.store = store + if lifetime is not None: self.lifetime = lifetime + if prefix is not None: self.prefix = prefix + + def not_cached(self, cache_key, lifetime=None): + """(obsolete. use cache_as() instead of this.) + html fragment cache helper. see document of FragmentCacheHelper class.""" + context = sys._getframe(1).f_locals['_context'] + context['_cache_key'] = cache_key + key = self.prefix and self.prefix + cache_key or cache_key + value = self.store.get(key) + if value: ## cached + if logger: logger.debug('[tenjin.not_cached] %r: cached.' % (cache_key, )) + context[key] = value + return False + else: ## not cached + if logger: logger.debug('[tenjin.not_cached]: %r: not cached.' % (cache_key, )) + if key in context: del context[key] + if lifetime is None: lifetime = self.lifetime + context['_cache_lifetime'] = lifetime + helpers.start_capture(cache_key, _depth=2) + return True + + def echo_cached(self): + """(obsolete. use cache_as() instead of this.) + html fragment cache helper. see document of FragmentCacheHelper class.""" + f_locals = sys._getframe(1).f_locals + context = f_locals['_context'] + cache_key = context.pop('_cache_key') + key = self.prefix and self.prefix + cache_key or cache_key + if key in context: ## cached + value = context.pop(key) + else: ## not cached + value = helpers.stop_capture(False, _depth=2) + lifetime = context.pop('_cache_lifetime') + self.store.set(key, value, lifetime) + f_locals['_buf'].append(value) + + def functions(self): + """(obsolete. use cache_as() instead of this.)""" + return (self.not_cached, self.echo_cached) + + def cache_as(self, cache_key, lifetime=None): + key = self.prefix and self.prefix + cache_key or cache_key + _buf = sys._getframe(1).f_locals['_buf'] + value = self.store.get(key) + if value: + if logger: logger.debug('[tenjin.cache_as] %r: cache found.' % (cache_key, )) + _buf.append(value) + else: + if logger: logger.debug('[tenjin.cache_as] %r: expired or not cached yet.' % (cache_key, )) + _buf_len = len(_buf) + yield None + value = ''.join(_buf[_buf_len:]) + self.store.set(key, value, lifetime) + +## you can change default store by 'tenjin.helpers.fragment_cache.store = ...' +helpers.fragment_cache = FragmentCacheHelper(MemoryBaseStore()) +helpers.not_cached = helpers.fragment_cache.not_cached +helpers.echo_cached = helpers.fragment_cache.echo_cached +helpers.cache_as = helpers.fragment_cache.cache_as +helpers.__all__.extend(('not_cached', 'echo_cached', 'cache_as')) + + + +## +## helper class to find and read template +## +class Loader(object): + + def exists(self, filepath): + raise NotImplementedError("%s.exists(): not implemented yet." % self.__class__.__name__) + + def find(self, filename, dirs=None): + #: if dirs provided then search template file from it. + if dirs: + for dirname in dirs: + filepath = os.path.join(dirname, filename) + if self.exists(filepath): + return filepath + #: if dirs not provided then just return filename if file exists. + else: + if self.exists(filename): + return filename + #: if file not found then return None. + return None + + def abspath(self, filename): + raise NotImplementedError("%s.abspath(): not implemented yet." % self.__class__.__name__) + + def timestamp(self, filepath): + raise NotImplementedError("%s.timestamp(): not implemented yet." % self.__class__.__name__) + + def load(self, filepath): + raise NotImplementedError("%s.timestamp(): not implemented yet." % self.__class__.__name__) + + + +## +## helper class to find and read files +## +class FileSystemLoader(Loader): + + def exists(self, filepath): + #: return True if filepath exists as a file. + return os.path.isfile(filepath) + + def abspath(self, filepath): + #: return full-path of filepath + return os.path.abspath(filepath) + + def timestamp(self, filepath): + #: return mtime of file + return _getmtime(filepath) + + def load(self, filepath): + #: if file exists, return file content and mtime + def f(): + mtime = _getmtime(filepath) + input = _read_template_file(filepath) + mtime2 = _getmtime(filepath) + if mtime != mtime2: + mtime = mtime2 + input = _read_template_file(filepath) + mtime2 = _getmtime(filepath) + if mtime != mtime2: + if logger: + logger.warn("[tenjin] %s.load(): timestamp is changed while reading file." % self.__class__.__name__) + return input, mtime + #: if file not exist, return None + return _ignore_not_found_error(f) + + +## +## +## +class TemplateNotFoundError(Exception): + pass + + + +## +## template engine class +## + +class Engine(object): + """Template Engine class. + See User's Guide and examples for details. + http://www.kuwata-lab.com/tenjin/pytenjin-users-guide.html + http://www.kuwata-lab.com/tenjin/pytenjin-examples.html + """ + + ## default value of attributes + prefix = '' + postfix = '' + layout = None + templateclass = Template + path = None + cache = TextCacheStorage() # save converted Python code into text file + lang = None + loader = FileSystemLoader() + preprocess = False + preprocessorclass = Preprocessor + timestamp_interval = 1 # seconds + + def __init__(self, prefix=None, postfix=None, layout=None, path=None, cache=True, preprocess=None, templateclass=None, preprocessorclass=None, lang=None, loader=None, pp=None, **kwargs): + """Initializer of Engine class. + + prefix:str (='') + Prefix string used to convert template short name to template filename. + postfix:str (='') + Postfix string used to convert template short name to template filename. + layout:str (=None) + Default layout template name. + path:list of str(=None) + List of directory names which contain template files. + cache:bool or CacheStorage instance (=True) + Cache storage object to store converted python code. + If True, default cache storage (=Engine.cache) is used (if it is None + then create MarshalCacheStorage object for each engine object). + If False, no cache storage is used nor no cache files are created. + preprocess:bool(=False) + Activate preprocessing or not. + templateclass:class (=Template) + Template class which engine creates automatically. + lang:str (=None) + Language name such as 'en', 'fr', 'ja', and so on. If you specify + this, cache file path will be 'inex.html.en.cache' for example. + pp:list (=None) + List of preprocessor object which is callable and manipulates template content. + kwargs:dict + Options for Template class constructor. + See document of Template.__init__() for details. + """ + if prefix: self.prefix = prefix + if postfix: self.postfix = postfix + if layout: self.layout = layout + if templateclass: self.templateclass = templateclass + if preprocessorclass: self.preprocessorclass = preprocessorclass + if path is not None: self.path = path + if lang is not None: self.lang = lang + if loader is not None: self.loader = loader + if preprocess is not None: self.preprocess = preprocess + if pp is None: pp = [] + elif isinstance(pp, list): pass + elif isinstance(pp, tuple): pp = list(pp) + else: + raise TypeError("'pp' expected to be a list but got %r." % (pp,)) + self.pp = pp + if preprocess: + self.pp.append(TemplatePreprocessor(self.preprocessorclass)) + self.kwargs = kwargs + self.encoding = kwargs.get('encoding') + self._filepaths = {} # template_name => relative path and absolute path + self._added_templates = {} # templates added by add_template() + #self.cache = cache + self._set_cache_storage(cache) + + def _set_cache_storage(self, cache): + if cache is True: + if not self.cache: + self.cache = MarshalCacheStorage() + elif cache is None: + pass + elif cache is False: + self.cache = None + elif isinstance(cache, CacheStorage): + self.cache = cache + else: + raise ValueError("%r: invalid cache object." % (cache, )) + + def cachename(self, filepath): + #: if lang is provided then add it to cache filename. + if self.lang: + return '%s.%s.cache' % (filepath, self.lang) + #: return cache file name. + else: + return filepath + '.cache' + + def to_filename(self, template_name): + """Convert template short name into filename. + ex. + >>> engine = tenjin.Engine(prefix='user_', postfix='.pyhtml') + >>> engine.to_filename(':list') + 'user_list.pyhtml' + >>> engine.to_filename('list') + 'list' + """ + #: if template_name starts with ':', add prefix and postfix to it. + if template_name[0] == ':' : + return self.prefix + template_name[1:] + self.postfix + #: if template_name doesn't start with ':', just return it. + return template_name + + def _create_template(self, input=None, filepath=None, _context=None, _globals=None): + #: if input is not specified then just create empty template object. + template = self.templateclass(None, **self.kwargs) + #: if input is specified then create template object and return it. + if input: + template.convert(input, filepath) + return template + + def _preprocess(self, input, filepath, _context, _globals): + #if _context is None: _context = {} + #if _globals is None: _globals = sys._getframe(3).f_globals + #: preprocess template and return result + #preprocessor = self.preprocessorclass(filepath, input=input) + #return preprocessor.render(_context, globals=_globals) + #: preprocesses input with _context and returns result. + if '_engine' not in _context: + self.hook_context(_context) + for pp in self.pp: + input = pp.__call__(input, filename=filepath, context=_context, globals=_globals) + return input + + def add_template(self, template): + self._added_templates[template.filename] = template + + def _get_template_from_cache(self, cachepath, filepath): + #: if template not found in cache, return None + template = self.cache.get(cachepath, self.templateclass) + if not template: + return None + assert template.timestamp is not None + #: if checked within a sec, skip timestamp check. + now = _time() + last_checked = getattr(template, '_last_checked_at', None) + if last_checked and now < last_checked + self.timestamp_interval: + #if logger: logger.trace('[tenjin.%s] timestamp check skipped (%f < %f + %f)' % \ + # (self.__class__.__name__, now, template._last_checked_at, self.timestamp_interval)) + return template + #: if timestamp of template objectis same as file, return it. + if template.timestamp == self.loader.timestamp(filepath): + template._last_checked_at = now + return template + #: if timestamp of template object is different from file, clear it + #cache._delete(cachepath) + if logger: logger.info("[tenjin.%s] cache expired (filepath=%r)" % \ + (self.__class__.__name__, filepath)) + return None + + def get_template(self, template_name, _context=None, _globals=None): + """Return template object. + If template object has not registered, template engine creates + and registers template object automatically. + """ + #: accept template_name such as ':index'. + filename = self.to_filename(template_name) + #: if template object is added by add_template(), return it. + if filename in self._added_templates: + return self._added_templates[filename] + #: get filepath and fullpath of template + pair = self._filepaths.get(filename) + if pair: + filepath, fullpath = pair + else: + #: if template file is not found then raise TemplateNotFoundError. + filepath = self.loader.find(filename, self.path) + if not filepath: + raise TemplateNotFoundError('%s: filename not found (path=%r).' % (filename, self.path)) + # + fullpath = self.loader.abspath(filepath) + self._filepaths[filename] = (filepath, fullpath) + #: use full path as base of cache file path + cachepath = self.cachename(fullpath) + #: get template object from cache + cache = self.cache + template = cache and self._get_template_from_cache(cachepath, filepath) or None + #: if template object is not found in cache or is expired... + if not template: + ret = self.loader.load(filepath) + if not ret: + raise TemplateNotFoundError("%r: template not found." % filepath) + input, timestamp = ret + if self.pp: ## required for preprocessing + if _context is None: _context = {} + if _globals is None: _globals = sys._getframe(1).f_globals + input = self._preprocess(input, filepath, _context, _globals) + #: create template object. + template = self._create_template(input, filepath, _context, _globals) + #: set timestamp and filename of template object. + template.timestamp = timestamp + template._last_checked_at = _time() + #: save template object into cache. + if cache: + if not template.bytecode: + #: ignores syntax error when compiling. + try: template.compile() + except SyntaxError: pass + cache.set(cachepath, template) + #else: + # template.compile() + #: + template.filename = filepath + return template + + def include(self, template_name, append_to_buf=True, **kwargs): + """Evaluate template using current local variables as context. + + template_name:str + Filename (ex. 'user_list.pyhtml') or short name (ex. ':list') of template. + append_to_buf:boolean (=True) + If True then append output into _buf and return None, + else return stirng output. + + ex. + + #{include('file.pyhtml', False)} + + """ + #: get local and global vars of caller. + frame = sys._getframe(1) + locals = frame.f_locals + globals = frame.f_globals + #: get _context from caller's local vars. + assert '_context' in locals + context = locals['_context'] + #: if kwargs specified then add them into context. + if kwargs: + context.update(kwargs) + #: get template object with context data and global vars. + ## (context and globals are passed to get_template() only for preprocessing.) + template = self.get_template(template_name, context, globals) + #: if append_to_buf is true then add output to _buf. + #: if append_to_buf is false then don't add output to _buf. + if append_to_buf: _buf = locals['_buf'] + else: _buf = None + #: render template and return output. + s = template.render(context, globals, _buf=_buf) + #: kwargs are removed from context data. + if kwargs: + for k in kwargs: + del context[k] + return s + + def render(self, template_name, context=None, globals=None, layout=True): + """Evaluate template with layout file and return result of evaluation. + + template_name:str + Filename (ex. 'user_list.pyhtml') or short name (ex. ':list') of template. + context:dict (=None) + Context object to evaluate. If None then new dict is used. + globals:dict (=None) + Global context to evaluate. If None then globals() is used. + layout:str or Bool(=True) + If True, the default layout name specified in constructor is used. + If False, no layout template is used. + If str, it is regarded as layout template name. + + If temlate object related with the 'template_name' argument is not exist, + engine generates a template object and register it automatically. + """ + if context is None: + context = {} + if globals is None: + globals = sys._getframe(1).f_globals + self.hook_context(context) + while True: + ## context and globals are passed to get_template() only for preprocessing + template = self.get_template(template_name, context, globals) + content = template.render(context, globals) + layout = context.pop('_layout', layout) + if layout is True or layout is None: + layout = self.layout + if not layout: + break + template_name = layout + layout = False + context['_content'] = content + context.pop('_content', None) + return content + + def hook_context(self, context): + #: add engine itself into context data. + context['_engine'] = self + #context['render'] = self.render + #: add include() method into context data. + context['include'] = self.include + + +## +## safe template and engine +## + +class SafeTemplate(Template): + """Uses 'to_escaped()' instead of 'escape()'. + '#{...}' is not allowed with this class. Use '[==...==]' instead. + """ + + tostrfunc = 'to_str' + escapefunc = 'to_escaped' + + def get_expr_and_flags(self, match): + return _get_expr_and_flags(match, "#{%s}: '#{}' is not allowed with SafeTemplate.") + + +class SafePreprocessor(Preprocessor): + + tostrfunc = 'to_str' + escapefunc = 'to_escaped' + + def get_expr_and_flags(self, match): + return _get_expr_and_flags(match, "#{{%s}}: '#{{}}' is not allowed with SafePreprocessor.") + + +def _get_expr_and_flags(match, errmsg): + expr1, expr2, expr3, expr4 = match.groups() + if expr1 is not None: + raise TemplateSyntaxError(errmsg % match.group(1)) + if expr2 is not None: return expr2, (True, False) # #{...} : call escape, not to_str + if expr3 is not None: return expr3, (False, True) # [==...==] : not escape, call to_str + if expr4 is not None: return expr4, (True, False) # [=...=] : call escape, not to_str + + +class SafeEngine(Engine): + + templateclass = SafeTemplate + preprocessorclass = SafePreprocessor + + +## +## for Google App Engine +## (should separate into individual file or module?) +## + +def _dummy(): + global memcache, _tenjin + memcache = _tenjin = None # lazy import of google.appengine.api.memcache + global GaeMemcacheCacheStorage, GaeMemcacheStore, init + + class GaeMemcacheCacheStorage(CacheStorage): + + lifetime = 0 # 0 means unlimited + + def __init__(self, lifetime=None, namespace=None): + CacheStorage.__init__(self) + if lifetime is not None: self.lifetime = lifetime + self.namespace = namespace + + def _load(self, cachepath): + key = cachepath + if _tenjin.logger: _tenjin.logger.info("[tenjin.gae.GaeMemcacheCacheStorage] load cache (key=%r)" % (key, )) + return memcache.get(key, namespace=self.namespace) + + def _store(self, cachepath, dct): + dct.pop('bytecode', None) + key = cachepath + if _tenjin.logger: _tenjin.logger.info("[tenjin.gae.GaeMemcacheCacheStorage] store cache (key=%r)" % (key, )) + ret = memcache.set(key, dct, self.lifetime, namespace=self.namespace) + if not ret: + if _tenjin.logger: _tenjin.logger.info("[tenjin.gae.GaeMemcacheCacheStorage] failed to store cache (key=%r)" % (key, )) + + def _delete(self, cachepath): + key = cachepath + memcache.delete(key, namespace=self.namespace) + + + class GaeMemcacheStore(KeyValueStore): + + lifetime = 0 + + def __init__(self, lifetime=None, namespace=None): + if lifetime is not None: self.lifetime = lifetime + self.namespace = namespace + + def get(self, key): + return memcache.get(key, namespace=self.namespace) + + def set(self, key, value, lifetime=None): + if lifetime is None: lifetime = self.lifetime + if memcache.set(key, value, lifetime, namespace=self.namespace): + return True + else: + if _tenjin.logger: _tenjin.logger.info("[tenjin.gae.GaeMemcacheStore] failed to set (key=%r)" % (key, )) + return False + + def delete(self, key): + return memcache.delete(key, namespace=self.namespace) + + def has(self, key): + if memcache.add(key, 'dummy', namespace=self.namespace): + memcache.delete(key, namespace=self.namespace) + return False + else: + return True + + + def init(): + global memcache, _tenjin + if not memcache: + from google.appengine.api import memcache + if not _tenjin: import tenjin as _tenjin + ## avoid cache confliction between versions + ver = os.environ.get('CURRENT_VERSION_ID', '1.1')#.split('.')[0] + Engine.cache = GaeMemcacheCacheStorage(namespace=ver) + ## set fragment cache store + helpers.fragment_cache.store = GaeMemcacheStore(namespace=ver) + helpers.fragment_cache.lifetime = 60 # 1 minute + helpers.fragment_cache.prefix = 'fragment.' + + +gae = create_module('tenjin.gae', _dummy, + os=os, helpers=helpers, Engine=Engine, + CacheStorage=CacheStorage, KeyValueStore=KeyValueStore) + + +del _dummy diff --git a/cgi/tor.txt b/cgi/tor.txt new file mode 100644 index 0000000..f748b96 --- /dev/null +++ b/cgi/tor.txt @@ -0,0 +1,1140 @@ +102.165.54.56 +103.194.170.223 +103.208.220.122 +103.208.220.226 +103.234.220.195 +103.234.220.197 +103.236.201.110 +103.236.201.27 +103.28.52.93 +103.28.53.138 +103.3.61.114 +103.75.190.11 +103.76.180.54 +104.131.206.23 +104.192.3.226 +104.194.228.240 +104.196.43.128 +104.200.20.46 +104.218.63.72 +104.218.63.73 +104.218.63.74 +104.218.63.75 +104.218.63.76 +104.244.73.126 +104.244.74.165 +104.244.74.78 +104.244.76.13 +104.244.77.49 +104.244.77.66 +104.40.73.53 +107.155.49.126 +107.173.58.166 +107.181.161.182 +107.181.174.66 +108.85.99.10 +109.169.33.163 +109.201.133.100 +109.236.90.209 +109.69.66.98 +109.69.67.17 +109.70.100.10 +109.70.100.2 +109.70.100.3 +109.70.100.4 +109.70.100.5 +109.70.100.6 +109.70.100.7 +109.70.100.8 +109.70.100.9 +111.69.49.124 +114.32.35.232 +115.64.95.48 +118.163.74.160 +122.147.141.130 +124.109.1.207 +125.212.241.182 +128.14.136.158 +128.31.0.13 +130.149.80.199 +130.204.161.3 +136.243.102.134 +137.74.167.96 +137.74.169.241 +138.197.177.62 +139.162.10.72 +139.162.100.194 +139.162.138.14 +139.28.36.234 +139.99.96.114 +139.99.98.191 +142.93.168.48 +143.106.60.70 +143.202.161.75 +144.217.161.119 +144.217.164.104 +144.217.165.223 +144.217.166.19 +144.217.166.26 +144.217.166.59 +144.217.166.65 +144.217.60.211 +144.217.60.239 +144.217.64.46 +144.217.7.154 +144.217.7.33 +144.217.80.80 +144.217.90.68 +145.239.82.204 +145.239.91.37 +145.239.93.33 +145.249.106.102 +145.249.107.135 +149.202.170.60 +149.202.238.204 +151.73.206.187 +153.207.207.191 +154.127.60.92 +156.54.213.67 +157.157.87.22 +158.174.122.199 +158.255.7.61 +158.69.192.200 +158.69.192.239 +158.69.193.32 +158.69.201.47 +158.69.217.87 +158.69.218.78 +158.69.37.14 +160.119.249.239 +160.119.249.24 +160.119.249.240 +160.119.253.114 +160.202.162.186 +162.213.0.243 +162.213.3.221 +162.244.80.228 +162.247.74.199 +162.247.74.200 +162.247.74.201 +162.247.74.202 +162.247.74.204 +162.247.74.206 +162.247.74.213 +162.247.74.217 +162.247.74.27 +162.247.74.7 +162.247.74.74 +163.172.12.160 +163.172.151.47 +163.172.160.182 +163.172.221.204 +163.172.41.228 +163.172.66.247 +164.132.51.91 +164.132.9.199 +164.77.133.220 +166.70.15.14 +166.70.207.2 +167.114.108.152 +167.114.34.150 +167.99.42.89 +169.197.112.26 +171.233.208.235 +171.25.193.20 +171.25.193.235 +171.25.193.25 +171.25.193.77 +171.25.193.78 +172.96.118.14 +172.98.193.43 +173.14.173.227 +173.212.244.116 +173.244.209.5 +173.255.226.142 +174.18.153.201 +176.10.104.240 +176.10.107.180 +176.10.99.200 +176.10.99.201 +176.10.99.202 +176.10.99.203 +176.10.99.204 +176.10.99.205 +176.10.99.206 +176.10.99.207 +176.10.99.208 +176.10.99.209 +176.10.99.210 +176.107.179.147 +176.121.81.51 +176.126.83.211 +176.31.208.193 +176.31.45.3 +176.53.90.26 +176.58.100.98 +176.58.89.182 +176.67.168.210 +178.165.72.177 +178.17.166.146 +178.17.166.147 +178.17.166.148 +178.17.166.149 +178.17.166.150 +178.17.170.105 +178.17.170.112 +178.17.170.13 +178.17.170.135 +178.17.170.149 +178.17.170.164 +178.17.170.194 +178.17.170.196 +178.17.170.23 +178.17.170.81 +178.17.171.102 +178.17.171.114 +178.17.171.197 +178.17.171.39 +178.17.171.78 +178.17.174.10 +178.17.174.14 +178.17.174.196 +178.17.174.198 +178.17.174.229 +178.17.174.232 +178.17.174.68 +178.175.131.194 +178.175.132.209 +178.175.132.210 +178.175.132.211 +178.175.132.212 +178.175.132.213 +178.175.132.214 +178.175.132.225 +178.175.132.226 +178.175.132.227 +178.175.132.228 +178.175.132.229 +178.175.132.230 +178.175.135.100 +178.175.135.101 +178.175.135.102 +178.175.135.99 +178.175.143.155 +178.175.143.156 +178.175.143.157 +178.175.143.158 +178.175.143.163 +178.175.143.164 +178.175.143.165 +178.175.143.166 +178.175.143.234 +178.175.143.242 +178.175.148.11 +178.175.148.165 +178.175.148.224 +178.175.148.227 +178.175.148.34 +178.175.148.45 +178.20.55.16 +178.20.55.18 +178.211.45.18 +178.239.176.73 +178.32.147.150 +178.32.181.96 +178.32.181.97 +178.32.181.98 +178.32.181.99 +178.43.184.11 +178.63.97.34 +179.176.55.216 +179.43.134.154 +179.43.134.155 +179.43.134.156 +179.43.134.157 +179.43.146.230 +179.43.148.214 +179.43.151.146 +179.48.248.17 +179.48.251.188 +18.18.248.17 +18.85.192.253 +180.150.226.99 +185.10.68.123 +185.10.68.148 +185.10.68.180 +185.10.68.217 +185.10.68.225 +185.10.68.52 +185.10.68.76 +185.100.85.101 +185.100.85.132 +185.100.85.147 +185.100.85.190 +185.100.85.61 +185.100.86.100 +185.100.86.128 +185.100.86.154 +185.100.86.182 +185.100.87.206 +185.100.87.207 +185.104.120.2 +185.104.120.3 +185.104.120.4 +185.104.120.5 +185.104.120.60 +185.104.120.7 +185.106.122.188 +185.107.47.171 +185.107.47.215 +185.107.70.202 +185.107.83.71 +185.112.146.138 +185.112.254.195 +185.121.168.254 +185.125.33.114 +185.125.33.242 +185.127.25.192 +185.127.25.68 +185.129.62.62 +185.129.62.63 +185.130.104.241 +185.14.29.189 +185.147.237.8 +185.147.80.155 +185.163.45.38 +185.165.168.168 +185.165.168.229 +185.165.168.77 +185.165.169.165 +185.165.169.62 +185.165.169.71 +185.169.42.141 +185.175.208.179 +185.175.208.180 +185.177.151.34 +185.180.221.225 +185.191.204.254 +185.193.125.42 +185.198.58.198 +185.205.210.245 +185.220.100.252 +185.220.100.253 +185.220.100.254 +185.220.100.255 +185.220.101.0 +185.220.101.1 +185.220.101.12 +185.220.101.13 +185.220.101.15 +185.220.101.20 +185.220.101.21 +185.220.101.22 +185.220.101.24 +185.220.101.25 +185.220.101.26 +185.220.101.27 +185.220.101.28 +185.220.101.29 +185.220.101.3 +185.220.101.30 +185.220.101.31 +185.220.101.32 +185.220.101.33 +185.220.101.34 +185.220.101.35 +185.220.101.44 +185.220.101.45 +185.220.101.46 +185.220.101.48 +185.220.101.49 +185.220.101.5 +185.220.101.50 +185.220.101.52 +185.220.101.53 +185.220.101.54 +185.220.101.56 +185.220.101.57 +185.220.101.58 +185.220.101.6 +185.220.101.60 +185.220.101.62 +185.220.101.65 +185.220.101.66 +185.220.101.67 +185.220.101.68 +185.220.101.69 +185.220.101.7 +185.220.101.70 +185.220.102.4 +185.220.102.6 +185.220.102.7 +185.220.102.8 +185.222.202.104 +185.222.202.12 +185.222.202.125 +185.222.202.133 +185.222.202.153 +185.222.202.221 +185.222.209.87 +185.227.68.78 +185.227.82.9 +185.233.100.23 +185.234.219.111 +185.234.219.112 +185.234.219.113 +185.234.219.114 +185.234.219.115 +185.234.219.116 +185.234.219.117 +185.234.219.118 +185.234.219.119 +185.234.219.120 +185.242.113.224 +185.244.151.149 +185.248.160.21 +185.248.160.231 +185.248.160.65 +185.255.112.137 +185.31.136.244 +185.34.33.2 +185.35.138.92 +185.4.132.135 +185.4.132.183 +185.56.171.94 +185.61.149.193 +185.65.205.10 +185.65.206.154 +185.66.200.10 +185.72.244.24 +185.86.148.109 +185.86.148.90 +185.86.149.254 +185.86.151.21 +187.178.75.109 +188.127.251.63 +188.165.59.43 +188.166.56.121 +188.166.9.235 +188.214.104.146 +188.68.45.180 +189.84.21.44 +190.10.8.50 +190.105.226.81 +190.164.230.184 +190.210.98.90 +190.216.2.136 +191.114.118.98 +192.155.95.222 +192.160.102.164 +192.160.102.165 +192.160.102.166 +192.160.102.168 +192.160.102.169 +192.160.102.170 +192.195.80.10 +192.34.80.176 +192.42.116.13 +192.42.116.14 +192.42.116.15 +192.42.116.16 +192.42.116.17 +192.42.116.18 +192.42.116.19 +192.42.116.20 +192.42.116.22 +192.42.116.23 +192.42.116.24 +192.42.116.25 +192.42.116.26 +192.42.116.27 +192.42.116.28 +193.110.157.151 +193.150.121.66 +193.169.145.194 +193.169.145.202 +193.169.145.66 +193.19.118.171 +193.201.225.45 +193.29.15.223 +193.36.119.17 +193.56.29.101 +193.9.114.139 +193.9.115.24 +193.90.12.115 +193.90.12.116 +193.90.12.117 +193.90.12.118 +193.90.12.119 +194.88.143.66 +195.123.209.67 +195.123.212.75 +195.123.213.211 +195.123.216.32 +195.123.217.153 +195.123.222.135 +195.123.224.108 +195.123.227.87 +195.123.228.161 +195.123.237.251 +195.123.245.96 +195.170.63.164 +195.176.3.19 +195.176.3.20 +195.176.3.23 +195.176.3.24 +195.189.96.147 +195.206.105.217 +195.228.45.176 +195.254.134.194 +195.254.134.242 +195.254.135.76 +196.41.123.180 +197.231.221.211 +198.167.223.111 +198.167.223.133 +198.167.223.38 +198.167.223.44 +198.233.204.165 +198.46.135.18 +198.50.191.95 +198.50.200.129 +198.50.200.131 +198.71.81.66 +198.73.51.73 +198.96.155.3 +198.98.50.112 +198.98.50.201 +198.98.52.93 +198.98.54.28 +198.98.54.34 +198.98.56.149 +198.98.57.155 +198.98.57.178 +198.98.58.135 +198.98.59.240 +198.98.62.49 +199.127.226.150 +199.195.248.177 +199.195.250.77 +199.195.252.246 +199.249.230.64 +199.249.230.65 +199.249.230.66 +199.249.230.67 +199.249.230.68 +199.249.230.69 +199.249.230.70 +199.249.230.71 +199.249.230.72 +199.249.230.73 +199.249.230.74 +199.249.230.75 +199.249.230.76 +199.249.230.77 +199.249.230.78 +199.249.230.79 +199.249.230.80 +199.249.230.81 +199.249.230.82 +199.249.230.83 +199.249.230.84 +199.249.230.85 +199.249.230.86 +199.249.230.87 +199.249.230.88 +199.249.230.89 +199.87.154.255 +200.98.137.240 +200.98.146.219 +200.98.161.148 +2001:0470:000d:06dd:0011:0000:0000:beef +2001:0470:1f04:0d9a:0000:0000:0000:0002 +2001:0470:b304:0002:0000:0000:0051:0001 +2001:0620:20d0:0000:0000:0000:0000:0019 +2001:0620:20d0:0000:0000:0000:0000:0020 +2001:0620:20d0:0000:0000:0000:0000:0023 +2001:0620:20d0:0000:0000:0000:0000:0024 +2001:067c:2608:0000:0000:0000:0000:0001 +2001:067c:289c:0000:0000:0000:0000:0020 +2001:067c:289c:0000:0000:0000:0000:0025 +2001:067c:289c:0003:0000:0000:0000:0077 +2001:067c:289c:0003:0000:0000:0000:0078 +2001:0780:0107:000b:0000:0000:0000:0085 +2001:0981:5b21:000c:0000:0000:0000:0034 +2001:0985:7aa4:0000:0000:0000:0000:0002 +2001:0bc8:272a:0000:0000:0000:0000:0001 +2001:0bc8:3c96:0100:0000:0000:0000:0082 +2001:0bc8:4700:2000:0000:0000:0000:2317 +2001:0bc8:4700:2300:0000:0000:0004:021b +2001:0bc8:4728:1203:0000:0000:0000:0001 +2001:0bc8:472c:7507:0000:0000:0000:0001 +2001:0bc8:472c:d10c:0000:0000:0000:0001 +2001:0bf0:0666:0000:0000:0000:0000:0666 +2001:0bf7:b201:0000:0000:0000:0000:0006 +2001:0bf7:b301:0000:0000:0000:0000:0006 +2001:1af8:4700:a012:0001:0000:0000:0001 +2001:1b60:0003:0221:3132:0102:0000:0001 +2001:1b60:0003:0221:4134:0101:0000:0001 +2001:1b60:0003:0239:1003:0103:0000:0001 +2001:1b60:0003:0239:1003:0106:0000:0001 +2001:41d0:0052:0100:0000:0000:0000:112a +2001:41d0:0052:0500:0000:0000:0000:051a +2001:41d0:0052:0cff:0000:0000:0000:01fb +2001:41d0:0401:3100:0000:0000:0000:7d36 +2001:41d0:0404:0200:0000:0000:0000:1124 +2001:41d0:0601:1100:0000:0000:0000:06b0 +2001:41d0:0601:1100:0000:0000:0000:09eb +2001:41d0:0601:1100:0000:0000:0000:0eb0 +2001:41d0:0701:1100:0000:0000:0000:0761 +2001:41d0:0701:1100:0000:0000:0000:1a12 +2001:41d0:0801:2000:0000:0000:0000:0270 +2001:41d0:1008:26d8:0000:0000:0000:0150 +2001:4b78:2006:ffc3:0000:0000:0000:0001 +2001:4ba0:fff9:0160:dead:beef:ca1f:1337 +2001:b011:4010:3264:0000:0000:0000:0006 +2002:ce3f:e590:0001:0001:0000:0000:0015 +201.80.164.203 +201.80.181.11 +204.11.50.131 +204.17.56.42 +204.194.29.4 +204.209.81.3 +204.27.60.147 +204.8.156.142 +204.85.191.30 +204.85.191.9 +205.168.84.133 +205.185.126.56 +205.185.127.219 +206.248.184.127 +206.55.74.0 +207.180.224.17 +207.192.70.250 +207.244.70.35 +209.126.101.29 +209.141.33.25 +209.141.37.237 +209.141.40.86 +209.141.41.41 +209.141.45.212 +209.141.51.150 +209.141.58.114 +209.141.61.45 +209.95.51.11 +210.140.10.24 +210.3.102.152 +212.16.104.33 +212.21.66.6 +212.47.226.52 +212.47.229.60 +212.47.248.66 +212.81.199.159 +213.108.105.71 +213.136.92.52 +213.252.140.118 +213.252.244.99 +213.61.215.53 +213.95.149.22 +216.158.98.38 +216.19.178.143 +216.218.134.12 +216.239.90.19 +216.244.85.211 +217.115.10.131 +217.115.10.132 +217.12.221.196 +217.12.223.56 +217.170.197.83 +217.170.197.89 +217.182.78.177 +220.135.203.167 +223.26.48.248 +23.129.64.101 +23.129.64.104 +23.129.64.105 +23.129.64.106 +23.239.23.104 +23.94.113.11 +24.20.43.120 +24.3.111.78 +2400:8902:0000:0000:f03c:91ff:fe6b:3903 +2600:3c00:0000:0000:f03c:91ff:fee2:4963 +2600:3c01:0000:0000:f03c:91ff:fe30:ec17 +2600:3c03:0000:0000:f03c:91ff:fefa:755c +2601:01c2:1900:f202:0c2b:7370:df29:2ffe +2604:9a00:2010:a08d:0010:0000:0000:0023 +2605:2700:0000:0002:a800:00ff:fe20:0db3 +2605:2700:0000:0002:a800:00ff:fe39:0574 +2605:2700:0000:0002:a800:00ff:fe64:64ea +2605:4d00:0000:0002:0000:0000:0000:006e +2605:6400:0010:020b:226d:70ab:4c95:029b +2605:6400:0010:0549:0000:0000:0000:0001 +2605:6400:0010:0655:a871:c796:0015:f519 +2605:6400:0020:0693:279d:170f:8868:bc3e +2605:6400:0020:09ce:0000:0000:0000:0001 +2605:6400:0020:0e9d:2309:1a4d:8bd7:ea1c +2605:6400:0030:fa4e:aa41:e6cb:ec4d:230a +2605:6400:0030:fa6b:0000:0000:0000:0001 +2605:e200:d111:0001:0225:90ff:fe24:3f9e +2605:f700:00c0:0001:0000:0000:0de9:142a +2607:5300:0120:0e93:0000:0000:0000:0110 +2607:5300:0201:3100:0000:0000:0000:0c20 +2607:ff68:0100:0089:0000:0000:0000:0005 +2620:0007:6001:0000:0000:ffff:c759:e640 +2620:0007:6001:0000:0000:ffff:c759:e641 +2620:0007:6001:0000:0000:ffff:c759:e642 +2620:0007:6001:0000:0000:ffff:c759:e643 +2620:0007:6001:0000:0000:ffff:c759:e644 +2620:0007:6001:0000:0000:ffff:c759:e645 +2620:0007:6001:0000:0000:ffff:c759:e646 +2620:0007:6001:0000:0000:ffff:c759:e647 +2620:0007:6001:0000:0000:ffff:c759:e648 +2620:0007:6001:0000:0000:ffff:c759:e649 +2620:0007:6001:0000:0000:ffff:c759:e64a +2620:0007:6001:0000:0000:ffff:c759:e64b +2620:0007:6001:0000:0000:ffff:c759:e64c +2620:0007:6001:0000:0000:ffff:c759:e64d +2620:0007:6001:0000:0000:ffff:c759:e64e +2620:0007:6001:0000:0000:ffff:c759:e64f +2620:0007:6001:0000:0000:ffff:c759:e650 +2620:0007:6001:0000:0000:ffff:c759:e651 +2620:0007:6001:0000:0000:ffff:c759:e652 +2620:0007:6001:0000:0000:ffff:c759:e653 +2620:0007:6001:0000:0000:ffff:c759:e654 +2620:0007:6001:0000:0000:ffff:c759:e655 +2620:0007:6001:0000:0000:ffff:c759:e656 +2620:0007:6001:0000:0000:ffff:c759:e657 +2620:0007:6001:0000:0000:ffff:c759:e658 +2620:0007:6001:0000:0000:ffff:c759:e659 +2620:0132:300c:c01d:0000:0000:0000:0004 +2620:0132:300c:c01d:0000:0000:0000:0005 +2620:0132:300c:c01d:0000:0000:0000:0006 +2620:0132:300c:c01d:0000:0000:0000:0008 +2620:0132:300c:c01d:0000:0000:0000:0009 +2620:0132:300c:c01d:0000:0000:0000:000a +2620:018c:0000:1001:0000:0000:0000:0101 +2620:018c:0000:1001:0000:0000:0000:0104 +2620:018c:0000:1001:0000:0000:0000:0105 +2620:018c:0000:1001:0000:0000:0000:0106 +27.102.128.26 +2a00:0c98:2030:a03e:0002:0000:0000:0a10 +2a00:1298:8011:0212:0000:0000:0000:0163 +2a00:1298:8011:0212:0000:0000:0000:0164 +2a00:1298:8011:0212:0000:0000:0000:0165 +2a00:1328:e102:8000:0000:0000:0000:0131 +2a00:1768:1001:0021:0000:0000:32a3:201a +2a00:1768:2001:0023:1000:0000:0000:0200 +2a00:1768:6001:0016:0000:0000:0000:0071 +2a00:1dc0:2048:0000:0000:0000:0000:0002 +2a00:1dc0:cafe:0000:0000:0000:d6a2:ae67 +2a00:1dc0:cafe:0000:0000:0000:f290:7489 +2a00:1dc0:caff:0029:0000:0000:0000:6d8e +2a00:1dc0:caff:003a:0000:0000:0000:dcbe +2a00:1dc0:caff:0054:0000:0000:0000:a46d +2a00:1dc0:caff:0071:0000:0000:0000:e4da +2a00:1dc0:caff:0072:0000:0000:0000:2cb4 +2a00:1dc0:caff:007d:0000:0000:0000:8254 +2a00:1dc0:caff:008b:0000:0000:0000:5b9a +2a00:1dc0:caff:009e:0000:0000:0000:8e67 +2a00:1dc0:caff:00b0:0000:0000:0000:93c4 +2a00:1dc0:caff:00f6:0000:0000:0000:28ad +2a00:1dc0:caff:00f8:0000:0000:0001:c46a +2a00:1dc0:caff:010d:0000:0000:0000:234b +2a00:1dc0:caff:0111:0000:0000:0000:785b +2a00:1dc0:caff:0127:0000:0000:0000:e359 +2a00:1dc0:caff:0129:0000:0000:0000:4938 +2a00:1dc0:caff:0138:0000:0000:0000:94d2 +2a00:1dc0:caff:014e:0000:0000:0000:9ecd +2a00:1dc0:caff:0153:0000:0000:0000:d2c7 +2a00:1dc0:caff:0159:0000:0000:0000:4d79 +2a00:1dc0:caff:015c:0000:0000:0000:5627 +2a00:1dc0:caff:0168:0000:0000:0000:6b79 +2a00:5880:1801:0000:2891:33ff:fe93:d6a0 +2a01:04f9:c010:08fb:0000:0000:0000:0bee +2a01:0e35:8be7:65f0:0043:07ff:fe82:ac61 +2a01:7e00:0000:0000:f03c:91ff:fe56:2656 +2a01:7e01:0000:0000:f03c:91ff:fe6b:575b +2a02:0418:6017:0000:0000:0000:0000:0147 +2a02:0418:6017:0000:0000:0000:0000:0148 +2a02:0a00:2000:0034:0000:0000:0000:0195 +2a02:0ec0:0209:0010:0000:0000:0000:0004 +2a02:2970:1002:0000:5054:11ff:fe21:fb21 +2a02:2970:1002:0000:5054:45ff:fe4b:5a29 +2a02:2970:1002:0000:5054:a2ff:fed6:4d6c +2a02:2970:1002:0000:5054:a8ff:fe63:b164 +2a02:29e0:0002:0006:0001:0001:1156:b142 +2a02:29e0:0002:0006:0001:0001:1628:58bb +2a02:7aa0:0043:0000:0000:0000:1d04:1c97 +2a03:4000:0002:0a11:3a58:da1f:cffa:01bc +2a03:4000:0021:047a:0de1:0ea7:dead:beef +2a03:4000:0032:0488:08a9:72ff:fef6:07aa +2a03:b0c0:0000:1010:0000:0000:024c:1001 +2a03:b0c0:0002:00d0:0000:0000:0db1:4001 +2a03:b0c0:0003:00d0:0000:0000:0d9a:3001 +2a03:e600:0100:0000:0000:0000:0000:0002 +2a03:e600:0100:0000:0000:0000:0000:0003 +2a03:e600:0100:0000:0000:0000:0000:0004 +2a03:e600:0100:0000:0000:0000:0000:0005 +2a03:e600:0100:0000:0000:0000:0000:0006 +2a03:e600:0100:0000:0000:0000:0000:0007 +2a03:e600:0100:0000:0000:0000:0000:0008 +2a03:e600:0100:0000:0000:0000:0000:0009 +2a03:e600:0100:0000:0000:0000:0000:000a +2a04:9dc0:00c1:0007:0216:3eff:fe5c:3d83 +2a06:1700:0000:000b:0000:0000:44cb:00d9 +2a06:1700:0000:001f:0000:0000:0000:0031 +2a06:1700:0001:0000:0000:0000:0000:0007 +2a06:1700:0001:0000:0000:0000:0000:0011 +2a06:3000:0000:0000:0000:0000:0120:0002 +2a06:3000:0000:0000:0000:0000:0120:0003 +2a06:3000:0000:0000:0000:0000:0120:0004 +2a06:3000:0000:0000:0000:0000:0120:0005 +2a06:3000:0000:0000:0000:0000:0120:0007 +2a06:3000:0000:0000:0000:0000:0120:0060 +2a06:d380:0000:3700:0000:0000:0000:0062 +2a06:d380:0000:3700:0000:0000:0000:0063 +2a0b:f4c0:016c:0001:0000:0000:0000:0001 +2a0b:f4c0:016c:0002:0000:0000:0000:0001 +2a0b:f4c0:016c:0003:0000:0000:0000:0001 +2a0b:f4c0:016c:0004:0000:0000:0000:0001 +2a0b:f4c1:0000:0000:0000:0000:0000:0004 +2a0b:f4c1:0000:0000:0000:0000:0000:0006 +2a0b:f4c1:0000:0000:0000:0000:0000:0007 +2a0b:f4c1:0000:0000:0000:0000:0000:0008 +2a0c:b807:8000:c93a:ff51:90ac:0000:13fc +2a0c:b807:8000:c93a:ff51:90ac:0000:1b88 +2a0c:b807:8000:c93a:ff51:90ac:0000:1bae +2c0f:f930:0000:0003:0000:0000:0000:0221 +2c0f:f930:0000:0005:0000:0000:0000:0038 +31.131.2.19 +31.131.4.171 +31.148.220.211 +31.185.104.19 +31.185.104.20 +31.185.104.21 +31.185.27.203 +31.220.0.225 +31.220.40.54 +31.220.42.86 +31.31.72.24 +31.31.74.131 +31.31.74.47 +35.0.127.52 +37.128.222.30 +37.134.164.64 +37.139.8.104 +37.187.105.104 +37.187.180.18 +37.187.239.8 +37.200.98.117 +37.220.36.240 +37.228.129.2 +37.235.48.36 +37.28.154.68 +37.48.120.196 +37.9.231.195 +38.117.96.154 +40.124.44.53 +41.215.241.146 +45.125.65.45 +45.33.43.215 +45.35.72.85 +45.56.103.80 +45.62.250.175 +45.62.250.179 +45.64.186.102 +45.66.32.220 +45.76.115.159 +45.79.144.222 +45.79.73.22 +46.101.61.36 +46.105.52.65 +46.165.230.5 +46.165.245.154 +46.165.254.166 +46.166.139.35 +46.167.245.51 +46.17.46.199 +46.173.214.3 +46.182.106.190 +46.182.18.29 +46.182.18.40 +46.182.19.15 +46.182.19.219 +46.246.49.139 +46.250.220.166 +46.29.248.238 +46.36.36.184 +46.38.235.14 +46.4.144.81 +46.98.199.52 +46.98.200.43 +47.89.178.105 +49.50.107.221 +49.50.66.209 +5.135.158.101 +5.135.65.145 +5.150.254.67 +5.189.143.169 +5.189.146.133 +5.196.1.129 +5.196.66.162 +5.199.130.188 +5.2.64.194 +5.2.77.146 +5.200.52.112 +5.252.176.20 +5.254.146.7 +5.3.163.124 +5.34.181.34 +5.34.181.35 +5.34.183.105 +5.39.217.14 +5.45.76.56 +5.61.37.133 +5.79.68.161 +5.79.86.15 +5.79.86.16 +50.247.195.124 +50.7.151.127 +50.7.176.2 +51.15.0.226 +51.15.106.67 +51.15.117.50 +51.15.123.230 +51.15.125.181 +51.15.128.3 +51.15.187.209 +51.15.209.128 +51.15.224.0 +51.15.233.253 +51.15.235.211 +51.15.252.1 +51.15.3.40 +51.15.34.214 +51.15.36.100 +51.15.37.97 +51.15.43.205 +51.15.48.204 +51.15.49.134 +51.15.53.83 +51.15.56.18 +51.15.59.175 +51.15.59.9 +51.15.68.66 +51.15.75.133 +51.15.80.14 +51.15.92.212 +51.159.1.114 +51.254.208.245 +51.254.48.93 +51.255.106.85 +51.38.113.64 +51.38.134.189 +51.38.162.232 +51.38.64.136 +51.68.174.112 +51.68.214.45 +51.75.253.147 +51.75.71.123 +51.77.177.194 +51.77.193.218 +51.77.201.37 +51.77.62.52 +52.15.194.28 +52.167.231.173 +54.36.189.105 +54.36.222.37 +54.37.16.241 +54.37.234.66 +54.39.148.232 +54.39.148.233 +54.39.148.234 +54.39.151.167 +58.153.198.85 +59.115.159.251 +59.127.163.155 +62.102.148.67 +62.102.148.68 +62.102.148.69 +62.210.105.86 +62.210.116.201 +62.210.37.82 +64.113.32.29 +64.137.162.34 +64.27.17.140 +65.181.122.48 +65.181.123.254 +65.181.124.115 +65.19.167.130 +65.19.167.131 +65.19.167.132 +66.110.216.10 +66.146.193.33 +66.155.4.213 +66.175.208.248 +66.222.153.25 +66.42.224.235 +67.163.131.76 +67.215.255.140 +68.46.79.221 +69.162.107.5 +69.164.207.234 +70.168.93.214 +71.19.144.106 +71.19.144.148 +71.19.148.20 +72.14.179.10 +72.210.252.137 +74.82.47.194 +77.247.181.162 +77.247.181.163 +77.247.181.164 +77.247.181.165 +77.247.181.166 +77.250.227.202 +77.55.212.215 +77.68.42.132 +77.73.69.90 +77.81.104.124 +77.81.247.72 +78.109.23.2 +78.130.128.106 +78.142.175.70 +78.142.19.43 +78.21.17.242 +78.92.23.245 +79.134.234.247 +79.134.235.243 +79.134.235.253 +79.143.186.17 +79.172.193.32 +79.232.118.2 +80.127.116.96 +80.169.241.76 +80.241.60.207 +80.67.172.162 +80.68.92.225 +80.79.23.7 +81.169.136.206 +81.17.27.134 +81.17.27.135 +81.17.27.136 +81.17.27.137 +81.171.29.146 +81.49.51.12 +82.118.242.113 +82.118.242.128 +82.161.210.87 +82.221.128.191 +82.221.131.102 +82.221.131.5 +82.221.131.71 +82.221.139.190 +82.221.141.96 +82.223.14.245 +82.223.27.82 +82.228.252.20 +82.66.140.131 +82.94.132.34 +82.94.251.227 +83.136.106.136 +83.136.106.153 +84.19.182.33 +84.200.12.61 +84.200.50.18 +84.209.51.186 +84.53.192.243 +84.53.225.118 +85.119.82.142 +85.159.237.210 +85.214.243.115 +85.235.65.198 +85.248.227.163 +85.248.227.164 +85.248.227.165 +85.25.44.141 +86.104.15.15 +87.118.110.27 +87.118.112.63 +87.118.116.103 +87.118.116.12 +87.118.116.90 +87.118.122.30 +87.118.122.51 +87.118.92.43 +87.120.254.204 +87.120.254.223 +87.120.36.157 +87.122.229.240 +87.222.199.132 +87.64.102.248 +88.190.118.95 +88.77.181.199 +88.99.35.242 +89.14.189.217 +89.144.12.17 +89.187.143.31 +89.187.143.81 +89.203.249.251 +89.234.157.254 +89.234.190.157 +89.236.112.100 +89.31.57.58 +91.121.192.154 +91.121.251.65 +91.146.121.3 +91.153.76.138 +91.203.145.116 +91.203.146.126 +91.203.5.146 +91.203.5.165 +91.207.174.75 +91.219.236.171 +91.219.237.244 +91.219.238.95 +91.219.28.60 +91.221.57.179 +91.234.99.83 +91.250.241.241 +91.92.109.43 +91.92.109.53 +92.222.115.28 +92.222.180.10 +92.222.22.113 +92.222.38.67 +92.63.173.28 +93.115.241.194 +93.174.93.133 +93.174.93.6 +94.100.6.27 +94.100.6.72 +94.102.49.152 +94.102.51.78 +94.156.77.134 +94.230.208.147 +94.230.208.148 +94.242.57.161 +94.242.59.89 +94.32.66.15 +95.103.57.132 +95.128.43.164 +95.130.10.69 +95.130.11.170 +95.130.12.33 +95.130.9.90 +95.141.35.15 +95.142.161.63 +95.143.193.125 +95.165.133.22 +95.179.150.158 +95.211.118.194 +95.216.107.148 +95.216.145.1 +95.216.2.172 +95.42.126.41 +96.66.15.147 +96.70.31.155 +97.74.237.196 +98.174.90.43 \ No newline at end of file diff --git a/cgi/weabot.py b/cgi/weabot.py new file mode 100755 index 0000000..2e11252 --- /dev/null +++ b/cgi/weabot.py @@ -0,0 +1,1021 @@ +#!/usr/bin/python +# coding=utf-8 + +# Remove the first line to use the env command to locate python + +import os +import time +import datetime +import random +import cgi +import _mysql +from Cookie import SimpleCookie + +import tenjin +import manage +import oekaki +import gettext +from database import * +from settings import Settings +from framework import * +from formatting import * +from post import * +from img import * + +__version__ = "0.8.7" + +# Set to True to disable weabot's exception routing and enable profiling +_DEBUG = False + +# Set to True to save performance data to weabot.txt +_LOG = False + +class weabot(object): + def __init__(self, environ, start_response): + global _DEBUG + self.environ = environ + if self.environ["PATH_INFO"].startswith("/weabot.py/"): + self.environ["PATH_INFO"] = self.environ["PATH_INFO"][11:] + + self.start = start_response + self.formdata = getFormData(self) + + self.output = "" + + self.handleRequest() + + # Localization Code + lang = gettext.translation('weabot', './locale', languages=[Settings.LANG]) + lang.install() + + logTime("**Start**") + if _DEBUG: + import cProfile + + prof = cProfile.Profile() + prof.runcall(self.run) + prof.dump_stats('stats.prof') + else: + try: + self.run() + except UserError, message: + self.error(message) + except Exception, inst: + import sys, traceback + exc_type, exc_value, exc_traceback = sys.exc_info() + detail = ((os.path.basename(o[0]),o[1],o[2],o[3]) for o in traceback.extract_tb(exc_traceback)) + self.exception(type(inst), inst, detail) + + # close database and finish + CloseDb() + logTime("**End**") + + if _LOG: + logfile = open(Settings.ROOT_DIR + "weabot.txt", "w") + logfile.write(logTimes()) + logfile.close() + + def __iter__(self): + self.handleResponse() + self.start("200 OK", self.headers) + yield self.output + + def error(self, message): + board = Settings._.BOARD + if board: + if board['board_type'] == '1': + info = {} + info['host'] = self.environ["REMOTE_ADDR"] + info['name'] = self.formdata.get('fielda', '') + info['email'] = self.formdata.get('fieldb', '') + info['message'] = self.formdata.get('message', '') + + self.output += renderTemplate("txt_error.html", {"info": info, "error": message}) + else: + mobile = self.formdata.get('mobile', '') + if mobile: + self.output += renderTemplate("mobile/error.html", {"error": message}) + else: + self.output += renderTemplate("error.html", {"error": message, "boards_url": Settings.BOARDS_URL, "board": board["dir"]}) + else: + self.output += renderTemplate("exception.html", {"exception": None, "error": message}) + + def exception(self, type, message, detail): + self.output += renderTemplate("exception.html", {"exception": type, "error": message, "detail": detail}) + + def handleRequest(self): + self.headers = [("Content-Type", "text/html")] + self.handleCookies() + + def handleResponse(self): + if self._cookies is not None: + for cookie in self._cookies.values(): + self.headers.append(("Set-Cookie", cookie.output(header=""))) + + def handleCookies(self): + self._cookies = SimpleCookie() + self._cookies.load(self.environ.get("HTTP_COOKIE", "")) + + def run(self): + path_split = self.environ["PATH_INFO"].split("/") + caught = False + + if Settings.FULL_MAINTENANCE: + raise UserError, _("%s is currently under maintenance. We'll be back.") % Settings.SITE_TITLE + + if len(path_split) > 1: + if path_split[1] == "post": + # Making a post + caught = True + + if 'password' not in self.formdata: + raise UserError, "El request está incompleto." + + # let's get all the POST data we need + ip = self.environ["REMOTE_ADDR"] + boarddir = self.formdata.get('board') + parent = self.formdata.get('parent') + trap1 = self.formdata.get('name', '') + trap2 = self.formdata.get('email', '') + name = self.formdata.get('fielda', '') + email = self.formdata.get('fieldb', '') + subject = self.formdata.get('subject', '') + message = self.formdata.get('message', '') + file = self.formdata.get('file') + file_original = self.formdata.get('file_original') + spoil = self.formdata.get('spoil') + oek_file = self.formdata.get('oek_file') + password = self.formdata.get('password', '') + noimage = self.formdata.get('noimage') + mobile = ("mobile" in self.formdata.keys()) + + # call post function + (post_url, ttaken) = self.make_post(ip, boarddir, parent, trap1, trap2, name, email, subject, message, file, file_original, spoil, oek_file, password, noimage, mobile) + + # make redirect + self.output += make_redirect(post_url, ttaken) + elif path_split[1] == "environ": + caught = True + + self.output += repr(self.environ) + elif path_split[1] == "delete": + # Deleting a post + caught = True + + boarddir = self.formdata.get('board') + postid = self.formdata.get('delete') + imageonly = self.formdata.get('imageonly') + password = self.formdata.get('password') + mobile = self.formdata.get('mobile') + + # call delete function + self.delete_post(boarddir, postid, imageonly, password, mobile) + elif path_split[1] == "anarkia": + import anarkia + caught = True + OpenDb() + anarkia.anarkia(self, path_split) + elif path_split[1] == "manage": + caught = True + OpenDb() + manage.manage(self, path_split) + elif path_split[1] == "api": + import api + caught = True + self.headers = [("Content-Type", "application/json")] + OpenDb() + api.api(self, path_split) + elif path_split[1] == "threadlist": + OpenDb() + board = setBoard(path_split[2]) + caught = True + if board['board_type'] != '1': + raise UserError, "No disponible para esta sección." + self.output = threadList(0) + elif path_split[1] == "mobile": + OpenDb() + board = setBoard(path_split[2]) + caught = True + self.output = threadList(1) + elif path_split[1] == "mobilelist": + OpenDb() + board = setBoard(path_split[2]) + caught = True + self.output = threadList(2) + elif path_split[1] == "mobilecat": + OpenDb() + board = setBoard(path_split[2]) + caught = True + self.output = threadList(3) + elif path_split[1] == "mobilenew": + OpenDb() + board = setBoard(path_split[2]) + caught = True + self.output = renderTemplate('txt_newthread.html', {}, True) + elif path_split[1] == "mobilehome": + OpenDb() + latest_age = getLastAge(Settings.HOME_LASTPOSTS) + for threads in latest_age: + content = threads['url'] + content = content.replace('/read/', '/') + content = content.replace('/res/', '/') + content = content.replace('.html', '') + threads['url'] = content + caught = True + self.output = renderTemplate('latest.html', {'latest_age': latest_age}, True) + elif path_split[1] == "mobilenewest": + OpenDb() + newthreads = getNewThreads(Settings.HOME_LASTPOSTS) + for threads in newthreads: + content = threads['url'] + content = content.replace('/read/', '/') + content = content.replace('/res/', '/') + content = content.replace('.html', '') + threads['url'] = content + caught = True + self.output = renderTemplate('newest.html', {'newthreads': newthreads}, True) + elif path_split[1] == "mobileread": + OpenDb() + board = setBoard(path_split[2]) + caught = True + if len(path_split) > 4 and path_split[4] and board['board_type'] == '1': + #try: + self.output = dynamicRead(int(path_split[3]), path_split[4], True) + #except: + # self.output = threadPage(path_split[3], True) + elif board['board_type'] == '1': + self.output = threadPage(0, True, path_split[3]) + else: + self.output = threadPage(path_split[3], True) + elif path_split[1] == "catalog": + OpenDb() + board = setBoard(path_split[2]) + caught = True + sort = self.formdata.get('sort', '') + self.output = catalog(sort) + elif path_split[1] == "oekaki": + caught = True + OpenDb() + oekaki.oekaki(self, path_split) + elif path_split[1] == "play": + # Module player + caught = True + boarddir = path_split[2] + modfile = path_split[3] + self.output = renderTemplate('mod.html', {'board': boarddir, 'modfile': modfile}) + elif path_split[1] == "report": + # Report post, check if they are enabled + # Can't report if banned + caught = True + ip = self.environ["REMOTE_ADDR"] + boarddir = path_split[2] + postid = int(path_split[3]) + reason = self.formdata.get('reason') + try: + txt = True + postshow = int(path_split[4]) + except: + txt = False + postshow = postid + + self.report(ip, boarddir, postid, reason, txt, postshow) + elif path_split[1] == "stats": + caught = True + self.stats() + elif path_split[1] == "random": + caught = True + OpenDb() + board = FetchOne("SELECT `id`, `dir`, `board_type` FROM `boards` WHERE `secret` = 0 AND `id` <> 1 AND `id` <> 13 AND `id` <> 34 ORDER BY RAND() LIMIT 1") + thread = FetchOne("SELECT `id`, `timestamp` FROM `posts` WHERE `parentid` = 0 AND `boardid` = %s ORDER BY RAND() LIMIT 1" % board['id']) + if board['board_type'] == '1': + url = Settings.HOME_URL + board['dir'] + '/read/' + thread['timestamp'] + '/' + else: + url = Settings.HOME_URL + board['dir'] + '/res/' + thread['id'] + '.html' + self.output += '

    ...

    ' % url + elif path_split[1] == "nostalgia": + caught = True + OpenDb() + thread = FetchOne("SELECT `timestamp` FROM `archive` WHERE `boardid` = 9 AND `timestamp` < 1462937230 ORDER BY RAND() LIMIT 1") + url = Settings.HOME_URL + '/zonavip/read/' + thread['timestamp'] + '/' + self.output += '

    ...

    ' % url + elif path_split[1] == "banned": + OpenDb() + packed_ip = inet_aton(self.environ["REMOTE_ADDR"]) + bans = FetchAll("SELECT * FROM `bans` WHERE (`netmask` IS NULL AND `ip` = '"+str(packed_ip)+"') OR (`netmask` IS NOT NULL AND '"+str(packed_ip)+"' & `netmask` = `ip`)") + if bans: + for ban in bans: + if ban["boards"] != "": + boards = pickle.loads(ban["boards"]) + if ban["boards"] == "" or path_split[2] in boards: + caught = True + if ban["boards"]: + boards_str = '/' + '/, /'.join(boards) + '/' + else: + boards_str = _("all boards") + if ban["until"] != "0": + expire = formatTimestamp(ban["until"]) + else: + expire = "" + + template_values = { + 'cgi_url': Settings.CGI_URL, + 'return_board': path_split[2], + 'boards_str': boards_str, + 'reason': ban['reason'], + 'added': formatTimestamp(ban["added"]), + 'expire': expire, + 'ip': self.environ["REMOTE_ADDR"], + } + self.output = renderTemplate('banned.html', template_values) + else: + if len(path_split) > 2: + caught = True + self.output += '

    %s

    ' % (Settings.HOME_URL + path_split[2], _("Your ban has expired. Redirecting...")) + elif path_split[1] == "read": + # Textboard read: + if len(path_split) > 4: + caught = True + # 2: board + # 3: thread + # 4: post(s) + OpenDb() + board = setBoard(path_split[2]) + self.output = dynamicRead(int(path_split[3]), path_split[4]) + elif path_split[1] == "preview": + caught = True + OpenDb() + try: + board = setBoard(self.formdata["board"]) + message = format_post(self.formdata["message"], self.environ["REMOTE_ADDR"], self.formdata["parentid"]) + self.output = message + except Exception, messagez: + self.output = "Error: " + str(messagez) + " : " + str(self.formdata) + if not caught: + # Redirect the user back to the front page + self.output += '

    --> --> -->

    ' % Settings.HOME_URL + + def make_post(self, ip, boarddir, parent, trap1, trap2, name, email, subject, message, file, file_original, spoil, oek_file, password, noimage, mobile): + _STARTTIME = time.clock() # Comment if not debug + + # open database + OpenDb() + + # set the board + board = setBoard(boarddir) + + if board["dir"] != ["anarkia"]: + if addressIsProxy(ip): + raise UserError, "Proxy prohibido en esta sección." + + # check length of fields + if len(name) > 50: + raise UserError, "El campo de nombre es muy largo." + if len(email) > 50: + raise UserError, "El campo de e-mail es muy largo." + if len(subject) > 100: + raise UserError, "El campo de asunto es muy largo." + if len(message) > 8000: + raise UserError, "El campo de mensaje es muy largo." + if message.count('\n') > 50: + raise UserError, "El mensaje tiene muchos saltos de línea." + + # anti-spam trap + if trap1 or trap2: + raise UserError, "Te quedan tres días de vida." + + # Create a single datetime now so everything syncs up + t = time.time() + + # Delete expired bans + deletedBans = UpdateDb("DELETE FROM `bans` WHERE `until` != 0 AND `until` < " + str(timestamp())) + if deletedBans > 0: + regenerateAccess() + + # Redirect to ban page if user is banned + if addressIsBanned(ip, board["dir"]): + #raise UserError, 'Tu host está en la lista negra.' + raise UserError, '' % board["dir"] + + # Disallow posting if the site OR board is in maintenance + if Settings.MAINTENANCE: + raise UserError, _("%s is currently under maintenance. We'll be back.") % Settings.SITE_TITLE + if board["locked"] == '1': + raise UserError, _("This board is closed. You can't post in it.") + + # create post object + post = Post(board["id"]) + post["ip"] = inet_aton(ip) + post["timestamp"] = post["bumped"] = int(t) + post["timestamp_formatted"] = formatTimestamp(t) + + # load parent info if we are replying + parent_post = None + parent_timestamp = post["timestamp"] + if parent: + parent_post = get_parent_post(parent, board["id"]) + parent_timestamp = parent_post['timestamp'] + post["parentid"] = parent_post['id'] + post["bumped"] = parent_post['bumped'] + if parent_post['locked'] == '1': + raise UserError, _("The thread is closed. You can't post in it.") + + # check if the user is flooding + flood_check(t, post, board["id"]) + + # use fields only if enabled + if board["disable_name"] != '1': + post["name"] = cleanString(name) + post["email"] = cleanString(email, quote=True) + if board["disable_subject"] != '1': + post["subject"] = cleanString(subject) + + # process tripcodes + post["name"], post["tripcode"] = tripcode(post["name"]) + + # Remove carriage return, they're useless + message = message.replace("\r", "") + + # check ! functions before + extend = extend_str = dice = ball = None + + if not post["parentid"] and board["dir"] not in ['bai', 'world']: + # creating thread + __extend = re.compile(r"^!extend(:\w+)(:\w+)?\n") + res = __extend.match(message) + if res: + extend = res.groups() + # truncate extend + extend_str = res.group(0) + message = message[res.end(0):] + + if board["dir"] in ['juegos', '0', 'polka']: + __dice = re.compile(r"^!dado(:\w+)(:\w+)?\n") + res = __dice.match(message) + if res: + dice = res.groups() + message = message[res.end(0):] + + if board["dir"] in ['zonavip', '0', 'polka']: + __ball = re.compile(r"^!bola8\n") + res = __ball.match(message) + if res: + ball = True + message = message[res.end(0):] + + # use and format message + if message.strip(): + post["message"] = format_post(message, ip, post["parentid"], parent_timestamp) + + # add function messages + if extend_str: + extend_str = extend_str.replace('!extend', 'EXTEND') + post["message"] += '
    ' + extend_str + ' configurado.' + if dice: + post["message"] += '
    ' + throw_dice(dice) + if ball: + post["message"] += '
    ' + magic_ball() + + # remove sage from wrong fields + if post["name"].lower() == 'sage': + post["name"] = random.choice(board["anonymous"].split('|')) + if post["subject"].lower() == 'sage': + post["subject"] = board["subject"] + + if not post["parentid"] and post["email"].lower() == 'sage': + post["email"] = "" + + # disallow illegal characters + if post["name"]: + post["name"] = post["name"].replace('★', '☆') + post["name"] = post["name"].replace('◆', '◇') + + # process capcodes + cap_id = hide_end = None + if post["name"] in Settings.CAPCODES: + capcode = Settings.CAPCODES[post["name"]] + if post["tripcode"] == (Settings.TRIP_CHAR + capcode[0]): + post["name"], post["tripcode"] = capcode[1], capcode[2] + #if board['board_type'] == '1': + # post["name"], post["tripcode"] = capcode[1], '' + #else: + # post["name"] = post["tripcode"] = '' + # post["message"] = ('[%s]
    ' % capcode[2]) + post["message"] + + cap_id, hide_end = capcode[3], capcode[4] + + # hide ip if necessary + if hide_end: + post["ip"] = 0 + + # use password + post["password"] = password + + # EXTEND feature + if post["parentid"] and board["dir"] not in ['bai', 'world']: + # replying + __extend = re.compile(r"
    EXTEND(:\w+)(:\w+)?\b") + res = __extend.search(parent_post["message"]) + if res: + extend = res.groups() + + # compatibility : old id function + if 'id' in parent_post["email"]: + board["useid"] = '3' + + if 'id' in post["email"]: + board["useid"] = '3' + + if extend: + try: + # 1: ID + if extend[0] == ':no': + board["useid"] = '0' + elif extend[0] == ':yes': + board["useid"] = '1' + elif extend[0] == ':force': + board["useid"] = '2' + elif extend[0] == ':extra': + board["useid"] = '3' + + # 2: Slip + if extend[1] == ':no': + board["slip"] = '0' + elif extend[1] == ':yes': + board["slip"] = '1' + elif extend[1] == ':domain': + board["slip"] = '2' + elif extend[1] == ':verbose': + board["slip"] = '3' + elif extend[1] == ':country': + board["countrycode"] = '1' + elif extend[1] == ':all': + board["slip"] = '3' + board["countrycode"] = '1' + except IndexError: + pass + + # if we are replying, use first post's time + if post["parentid"]: + tim = parent_post["timestamp"] + else: + tim = post["timestamp"] + + # make ID hash + if board["useid"] != '0': + post["timestamp_formatted"] += ' ID:' + iphash(ip, post, tim, board["useid"], mobile, self.environ["HTTP_USER_AGENT"], cap_id, hide_end, (board["countrycode"] in ['1', '2'])) + + # use for future file checks + xfile = (file or oek_file) + + # textboard inforcements (change it to settings maybe?) + if board['board_type'] == '1': + if not post["parentid"] and not post["subject"]: + raise UserError, _("You must enter a title to create a thread.") + if not post["message"]: + raise UserError, _("Please enter a message.") + else: + if not post["parentid"] and not xfile and not noimage: + raise UserError, _("You must upload an image first to create a thread.") + if not xfile and not post["message"]: + raise UserError, _("Please enter a message or upload an image to reply.") + + # check if this post is allowed + if post["parentid"]: + if file and board['allow_image_replies'] == '0': + raise UserError, _("Image replies not allowed.") + else: + if file and board['allow_images'] == '0': + raise UserError, _("No images allowed.") + + # use default values when missing + if not post["name"] and not post["tripcode"]: + post["name"] = random.choice(board["anonymous"].split('|')) + if not post["subject"] and not post["parentid"]: + post["subject"] = board["subject"] + if not post["message"]: + post["message"] = board["message"] + + # process files + if oek_file: + try: + fname = "%s/oek_temp/%s.png" % (Settings.HOME_DIR, oek_file) + with open(fname) as f: + file = f.read() + os.remove(fname) + except: + raise UserError, "Imposible leer la imagen oekaki." + + if file and not noimage: + post = processImage(post, file, t, file_original, (spoil and board['allow_spoilers'] == '1')) + + # slip + if board["slip"] != '0': + slips = [] + + # name + if board["slip"] in ['1', '3']: + if time.strftime("%H") in ['00', '24'] and time.strftime("%M") == '00' and time.strftime("%S") == '00': + host_nick = '000000' + else: + host_nick = 'sarin' + + if hide_end: + host_nick = '★' + elif addressIsTor(ip): + host_nick = 'onion' + else: + isps = {'cablevision': 'easy', + 'cantv': 'warrior', + 'claro': 'america', + 'cnet': 'nova', + 'copelnet': 'cisneros', + 'cps.com': 'silver', + 'cybercable': 'bricklayer', + 'entel': 'matte', + 'eternet': 'stream', + 'fibertel': 'roughage', + 'geonet': 'thunder', + 'gtdinternet': 'casanueva', + 'ifxnw': 'effect', + 'infinitum': 'telegraph', + 'intercable': 'easy', + 'intercity': 'cordoba', + 'iplannet': 'conquest', + 'itcsa.net': 'sarmiento', + 'megared': 'clear', + 'movistar': 'bell', + 'nextel': 'fleet', + 'speedy': 'oxygen', + 'telecom': 'license', + 'telmex': 'slender', + 'telnor': 'compass', + 'tie.cl': 'bell', + 'vtr.net': 'liberty', + 'utfsm': 'virgin', + } + host = getHost(ip) + + if host: + for k, v in isps.iteritems(): + if k in host: + host_nick = v + break + + slips.append(host_nick) + + # hash + if board["slip"] in ['1', '3']: + if hide_end: + slips.append('-'.join(('****', '****'))) + elif addressIsTor(ip): + slips.append('-'.join(('****', getMD5(os.environ["HTTP_USER_AGENT"])[:4]))) + else: + slips.append('-'.join((getMD5(ip)[:4], getMD5(os.environ["HTTP_USER_AGENT"])[:4]))) + + # host + if board["slip"] == '2': + if hide_end: + host = '★' + elif addressIsTor(ip): + host = 'onion' + else: + host = getHost(ip) + if host: + hosts = host.split('.') + if len(hosts) > 2: + if hosts[-2] in ['ne', 'net', 'com', 'co']: + host = '.'.join((hosts[-3], hosts[-2], hosts[-1])) + else: + host = '.'.join((hosts[-2], hosts[-1])) + host = '*.' + host + else: + iprs = ip.split('.') + host = '%s.%s.*.*' % (iprs[0], iprs[1]) + slips.append(host) + + # IP + if board["slip"] == '3': + if hide_end: + host = '[*.*.*.*]' + else: + iprs = ip.split('.') + host = '[%s.%s.*.*]' % (iprs[0], iprs[1]) + slips.append(host) + + if slips: + post["tripcode"] += " (%s)" % ' '.join(slips) + + # country code + if board["countrycode"] == '1': + if hide_end or addressIsTor(ip): + country = '??' + else: + country = getCountry(ip) + post["name"] += " [%s]" % country + + # set expiration date if necessary + if board["maxage"] != '0' and not post["parentid"]: + if board["dir"] == '2d': + date_format = '%m月%d日' + date_format_y = '%Y年%m月' + else: + date_format = '%d/%m' + date_format_y = '%m/%Y' + post["expires"] = int(t) + (int(board["maxage"]) * 86400) + if int(board["maxage"]) >= 365: + date_format = date_format_y + post["expires_formatted"] = datetime.datetime.fromtimestamp(post["expires"]).strftime(date_format) + + if not post["parentid"]: + # fill with default values if creating a new thread + post["length"] = 1 + post["last"] = post["timestamp"] + + if board["dir"] == 'noticias': + # check if there's at least one link + if "' + '
    '.join(msgs) + + # redirect + if imageonly: + self.output += '

    %s

    ' % (("/cgi/mobile/" if mobile else Settings.BOARDS_URL) + board["dir"], _("File deleted successfully.")) + else: + self.output += '

    %s

    ' % (("/cgi/mobile/" if mobile else Settings.BOARDS_URL) + board["dir"], _("Post deleted successfully.")) + + def report(self, ip, boarddir, postid, reason, txt, postshow): + # don't allow if the report system is off + if not Settings.REPORTS_ENABLE: + raise UserError, _('Report system is deactivated.') + + # if there's not a reason, show the report page + if reason is None: + self.output += renderTemplate("report.html", {'finished': False, 'postshow': postshow, 'txt': txt}) + return + + # check reason + if not reason: + raise UserError, _("Enter a reason.") + if len(reason) > 100: + raise UserError, _("Text too long.") + + # open database + OpenDb() + + # set the board we're in + board = setBoard(boarddir) + + # check if he's banned + if addressIsBanned(ip, board["dir"]): + raise UserError, _("You're banned.") + + # check if post exists + post = FetchOne("SELECT `id`, `parentid`, `ip` FROM `posts` WHERE `id` = '%s' AND `boardid` = '%s'" % (_mysql.escape_string(str(postid)), _mysql.escape_string(board['id']))) + if not post: + raise UserError, _("Post doesn't exist.") + + # generate link + if board["board_type"] == '1': + parent_post = get_parent_post(post["parentid"], board["id"]) + link = "/%s/read/%s/%s" % (board["dir"], parent_post["timestamp"], postshow) + else: + link = "/%s/res/%s.html#%s" % (board["dir"], post["parentid"], post["id"]) + + # insert report + t = time.time() + message = cgi.escape(self.formdata["reason"]).strip()[0:8000] + message = message.replace("\n", "
    ") + + UpdateDb("INSERT INTO `reports` (board, postid, parentid, link, ip, reason, reporterip, timestamp, timestamp_formatted) VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')" % (board["dir"], post['id'], post['parentid'], link, post['ip'], _mysql.escape_string(message), _mysql.escape_string(self.environ["REMOTE_ADDR"]), str(t), formatTimestamp(t))) + self.output = renderTemplate("report.html", {'finished': True}) + + def stats(self): + import json, math, platform + try: + with open('stats.json', 'r') as f: + out = json.load(f) + except ValueError: + out = {'t': 0} + + regenerated = False + if (time.time() - out['t']) > 3600: + regenerated = True + + # open database + OpenDb() + + # 1 week = 604800 + query_day = FetchAll("SELECT DATE_FORMAT(FROM_UNIXTIME(FLOOR((timestamp-10800)/86400)*86400+86400), \"%Y-%m-%d\"), COUNT(1), COUNT(IF(parentid=0, 1, NULL)) " + "FROM posts " + "WHERE (timestamp-10800) > (UNIX_TIMESTAMP()-604800) AND (IS_DELETED = 0 OR IS_DELETED = 3) " + "GROUP BY FLOOR((timestamp-10800)/86400) " + "ORDER BY FLOOR((timestamp-10800)/86400)", 0) + + query_count = FetchOne("SELECT COUNT(1), COUNT(NULLIF(file, '')), VERSION() FROM posts", 0) + total = int(query_count[0]) + total_files = int(query_count[1]) + mysql_ver = query_count[2] + + archive_count = FetchOne("SELECT SUM(length) FROM archive", 0) + total_archived = int(archive_count[0]) + + days = [] + for date, count, threads in query_day[1:]: + days.append( (date, count, threads) ) + + query_b = FetchAll("SELECT id, dir, name FROM boards WHERE boards.secret = 0", 0) + + boards = [] + totalp = 0 + for id, dir, longname in query_b: + bposts = FetchOne("SELECT COUNT(1) FROM posts " + "WHERE '"+str(id)+"' = posts.boardid AND timestamp > ( UNIX_TIMESTAMP(DATE(NOW())) - 2419200 )", 0) + boards.append( (dir, longname, int(bposts[0])) ) + totalp += int(bposts[0]) + + boards = sorted(boards, key=lambda boards: boards[2], reverse=True) + + boards_percent = [] + for dir, longname, bposts in boards: + if bposts > 0: + boards_percent.append( (dir, longname, '{0:.2f}'.format( float(bposts)*100/totalp ), int(bposts) ) ) + else: + boards_percent.append( (dir, longname, '0.00', '0' ) ) + + #posts = FetchAll("SELECT `parentid`, `boardid` FROM `posts` INNER JOIN `boards` ON posts.boardid = boards.id WHERE posts.parentid<>0 AND posts.timestamp>(UNIX_TIMESTAMP()-86400) AND boards.secret=0 ORDER BY `parentid`") + #threads = {} + #for post in posts: + # if post["parentid"] in threads: + # threads[post["parentid"]] += 1 + # else: + # threads[post["parentid"]] = 1 + + python_version = platform.python_version() + if self.environ.get('FCGI_FORCE_CGI', 'N').upper().startswith('Y'): + python_version += " (CGI)" + else: + python_version += " (FastCGI)" + + out = { + "uname": platform.uname(), + "python_ver": python_version, + "python_impl": platform.python_implementation(), + "python_build": platform.python_build()[1], + "python_compiler": platform.python_compiler(), + "mysql_ver": mysql_ver, + "tenjin_ver": tenjin.__version__, + "weabot_ver": __version__, + "days": days, + "boards": boards, + "boards_percent": boards_percent, + "total": total, + "total_files": total_files, + "total_archived": total_archived, + "t": timestamp(), + "tz": Settings.TIME_ZONE, + } + with open('stats.json', 'w') as f: + json.dump(out, f) + + out['timestamp'] = re.sub(r"\(...\)", " ", formatTimestamp(out['t'])) + out['regenerated'] = regenerated + self.output = renderTemplate("stats.html", out) + #self.headers = [("Content-Type", "application/json")] + +if __name__ == "__main__": + from fcgi import WSGIServer + + # Psyco is not required, however it will be used if available + try: + import psyco + logTime("Psyco se ha instalado") + psyco.bind(tenjin.helpers.to_str) + psyco.bind(weabot.run, 2) + psyco.bind(getFormData) + psyco.bind(setCookie) + psyco.bind(threadUpdated) + psyco.bind(processImage) + except: + pass + + WSGIServer(weabot).run() + diff --git a/static/css/buri.css b/static/css/buri.css new file mode 100644 index 0000000..b8c1eb5 --- /dev/null +++ b/static/css/buri.css @@ -0,0 +1,23 @@ +html,body{background:#EEF2FF;color:#000;font-family:Arial,Helvetica,"Nimbus Sans L",sans-serif} +a,a .name,a .name b,.nav label:hover{color:#34345C} +a.rep{color:#000;text-decoration:underline} +a:visited{color:#34345C} +a:hover,a:hover .name,a:hover .name b,.nav label:hover{color:#DD0000} +.replymode,.extramode{color:#FFF} +.replymode{background:#0010E0} +.extramode{background:#0040E0} +.postblock{background:#9988EE;color:#000} +.q{color:#789922} +.fs{text-decoration:none} +.subj{color:#0F0C5D;font-weight:bold} +.name{color:#228854} +.name b{color:#117743} +.reply,#q-p{background:#D6DAF0;color:#000} +.omitted,.abbrev{color:#707070} +.highlight{background:#c1c6e2} +.managertable td{background:#9AD2F6;color:#000} +.managertable th{background:#0F8FE1;color:#000} +#catalog .thread:hover{background:#D6DAF0;box-shadow:0 0 5px 5px #D6DAF0} +#catalog .replies{color:#555555;font-weight:bold} +.yt{background:#E3E6F5;border:1px solid #C1C6E7} +.quoted{border-color:#EEF2FF;color:#707070} \ No newline at end of file diff --git a/static/css/cyber.css b/static/css/cyber.css new file mode 100644 index 0000000..e9732bc --- /dev/null +++ b/static/css/cyber.css @@ -0,0 +1,39 @@ +html,body{background:#000 url('img/cyb.png');color:#61CE3C;font-family:monospace} +a,a .name,a .name b,.nav label{color:#C80B63} +.reflink a,.rep,.hsbn,#main_nav a{color:#FFF} +a:hover,a:hover .name,a:hover .name b,.nav label:hover,#main_nav a:hover{color:#F00} +.reflink a:hover{text-decoration:underline} +hr{display:none} +.thread hr{border:0;border-top:1px solid #61CE3C;display:block} +input,input[type="text"],input[type="password"],textarea{background:#1A1A1A;border:0;color:#61CE3C} +input[type="submit"]{border:1px outset #999} +input[type="submit"]:active{border-style:inset} +#main_nav{background:#1A1A1A;border-bottom:double 3px #989898;color:#989898;margin:-10px -10px 0;padding:10px} +.logo{color:#C00} +.replymode,.extramode{color:#FFF;text-shadow:1px 1px #000} +.replymode{background:#C00;box-shadow:5px 5px #989898;margin-bottom:1em} +.extramode{background:#001eff;} +.postform,.oekform{background:#2b2b2b;border:1px solid #989898;box-shadow:5px 5px #989898;padding:1px} +.postblock{background:#2e8b57;color:#FFF} +.q{color:#93e0e3} +.quoted{color:#707070} +.fs,.info{color:#989898;text-decoration:none} +.subj{color:#7b68ee;font-weight:bold} +.name{color:#FBDE2D} +.name b{color:#989898} +.omitted,.abbrev{color:#428C29} +.thread{border:solid 1px #7b68ee;background:#1A1A1A;box-shadow:5px 5px #7b68ee;margin-top:1em;margin-bottom:1em;padding:5px} +.reply,#q-p{background:#2b2b2b;border:1px solid #2e8b57 !important;box-shadow:5px 5px #2e8b57} +.thread table{margin:0;margin-bottom:10px;margin-right:10px} +.thumb{border:1px solid #4D4D4D;box-shadow:3px 3px #4D4D4D;margin-bottom:5px} +.reply.highlight{border-color:#93e0e3 !important;box-shadow:5px 5px #93e0e3} +.pg,.userdelete,.nav{background:#2b2b2b;border:1px solid #2e8b57;box-shadow:5px 5px #2e8b57;color:#89A} +.nav{padding:4px} +#adminmenu table{margin-bottom:10px} +.managertable td{background:#2B2B2B;color:#FFF} +.managertable th{background:#1A1A1A;color:#FFF} +#catalog .thread{border:1px solid #61CE3C;border-radius:0;box-shadow:none} +#catalog .thread:hover{background:#383838} +#catalog .replies{color:#428C29;font-weight:bold} +.yt{background:#222;border:1px solid;box-shadow:2px 2px} +.quoted{border-color:#2e8b57;color:#989898} \ No newline at end of file diff --git a/static/css/dickgirl.css b/static/css/dickgirl.css new file mode 100644 index 0000000..ba0bcc4 --- /dev/null +++ b/static/css/dickgirl.css @@ -0,0 +1,23 @@ +html,body{background:#1B3345;color:#FFF;font-family:initial} +a,a .name,.nav label{color:#EFD279} +a.rep{color:#FFF} +a:hover,a:hover .name,.nav label:hover{color:#D00} +.logo{color:#CCFFCC} +.replymode,.extramode{color:#FFF} +.replymode{background:#1D7548} +.extramode{background:#0040E0} +.postblock{background:#95CBE9;color:#2C5700} +.q{color:#BDF46C} +.fs{text-decoration:none} +.subj{color:#DE9D7F;font-weight:bold} +.name{color:#AFD775} +.omitted{color:#909090} +.reply,#q-p{background:#3B6B94;color:#fff} +.abbrev{color:#BBB} +.highlight{background:#5B8BB4} +.managertable td{background:#3B6B94;color:#FFF} +.managertable th{background:#AAF;color:#FFF} +#catalog .thread:hover{background:#3B6B94;box-shadow:0 0 5px 5px #3B6B94} +#catalog .replies{color:#AAA;font-weight:bold} +.yt{background:#2F587A;border:1px solid #1B2933} +.quoted{border-color:#1B3345} \ No newline at end of file diff --git a/static/css/easymodo.css b/static/css/easymodo.css new file mode 100644 index 0000000..eaa88a8 --- /dev/null +++ b/static/css/easymodo.css @@ -0,0 +1,25 @@ +html,body{background:#EEFFF2;color:#000;font-family:Arial,Helvetica,"Nimbus Sans L",sans-serif} +.rep{color:#000} +a,a .name,a .name b,.nav label{color:#34345c} +a:hover,a:hover .name,a:hover .name b,.nav label:hover{color:#D00} +.reflink a:hover{text-decoration:underline} +.replymode,.extramode{color:#FFF} +.replymode{background:#E04000} +.extramode{background:#0040E0} +.postform,.oekform{background:#cce1cf;border:1px solid #CCE1CF;padding:1px} +.postblock{background:#98c1a9} +.q{color:#789922} +.quoted{color:#707070} +.fs{text-decoration:none} +.subj{color:#0f0c5d;font-weight:bold} +.name{color:#228854} +.name b{color:#117743} +.omitted,.abbrev{color:#707070} +.reply,#q-p,.pg{background:#d6f0da} +.highlight{background:#d6bad0} +.managertable td{background:#cce1cf} +.managertable th{background:#b8caba} +#catalog .thread:hover{background:#d6f0da;box-shadow:0 0 5px 5px #d6f0da} +#catalog .replies{color:#707070;font-weight:bold} +.yt{background:#c2d6c5;border:1px solid #7a877c;color:#000} +.quoted{border-color:#EEFFF2} \ No newline at end of file diff --git a/static/css/futaba.css b/static/css/futaba.css new file mode 100644 index 0000000..f90af88 --- /dev/null +++ b/static/css/futaba.css @@ -0,0 +1,22 @@ +html,body{background:#FFE;color:#800000;font-family:Arial,Helvetica,"Nimbus Sans L",sans-serif} +a,a .name,a .name b,.nav label{color:#0000EE} +a.rep{color:#800000;text-decoration:underline} +a:hover,a:hover .name,a:hover .name b,.nav label:hover{color:#D00} +.replymode,.extramode{color:#FFF} +.replymode{background:#E04000} +.extramode{background:#0040E0} +.postblock{background:#EEAA88} +.q{color:#789922} +.subj{color:#CC1105;font-weight:bold} +.name{color:#228854} +.name b{color:#117743} +.omitted{color:#707070} +.reply,#q-p{background:#F0E0D6} +.abbrev{color:#707070} +.highlight{background:#F0C0B0} +.managertable td{background:#EEEECC;color:#800000} +.managertable th{background:#AAAA66;color:#400000} +#catalog .thread:hover{background:#F0E0D6;box-shadow:0 0 5px 5px #F0E0D6} +#catalog .replies{color:#909090;font-weight:bold} +.yt{background:#F2E5DD;border:1px solid #E7CFC1;color:#500000} +.quoted{border-color:#FFE} \ No newline at end of file diff --git a/static/css/guro.css b/static/css/guro.css new file mode 100644 index 0000000..c938675 --- /dev/null +++ b/static/css/guro.css @@ -0,0 +1,24 @@ +html,body{background:#eddad2;color:#000;font-family:arial,helvetica,"nimbus sans l",sans-serif} +.rep{color:#000} +a,a .name,a .name b,.nav label{color:#af0a0f} +a:hover,a:hover .name,a:hover .name b,.nav label:hover{color:#d00} +.logo{color:#af0a0f} +.replymode,.extramode{background:#57463f;color:#fff} +.postblock,.reply{background:#d9af9e;border:1px solid #ca927b} +input,input[type="text"],input[type="password"],textarea{background:#e6cbc0;border:1px solid #ca927b} +input[type="submit"],input[type="button"]{border-style:outset;padding:3px 10px} +input[type="submit"]:active,input[type="button"]:active{border-style:inset} +.q{color:#707070} +.subj{color:#0f0c5d;font-weight:bold} +.name{color:#117743} +.name b{color:#228854} +.omitted,.abbrev{color:#444} +#q-p{background:#d9af9e;border:0} +.highlight{background:#5b5f69} +.managertable td{background:#e6cbc0} +.managertable th{background:#d9af9e} +hr{border:none;border-top:1px solid #d9af9e;height:0} +#catalog .thread:hover{background:#d9af9e;box-shadow:0 0 5px 5px #d9af9e} +#catalog .replies{color:#555;font-weight:bold} +.yt{background:#c39e8e;border:1px solid #8d6656} +.quoted{border-color:#ca927b} \ No newline at end of file diff --git a/static/css/ib.css b/static/css/ib.css new file mode 100644 index 0000000..1609e4d --- /dev/null +++ b/static/css/ib.css @@ -0,0 +1,72 @@ +*{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;word-wrap:break-word} +html,body{font-family:arial,helvetica,"nimbus sans l",sans-serif} +html{margin:0;padding:0} +body{margin:0;padding:10px;font-size:16px} +blockquote{line-height:20px} +.spoil{background:#000;color:#000}.spoil:hover{color:#fff} +.postarea table{margin:0 auto;text-align:left} +#main_nav{font-size:14px;line-height:1.3em;margin-bottom:.5em;text-align:center} +#main_nav span{display:inline-block} +#main_nav #sel,#main_nav .cur_brd,#main_nav #cur_stl{font-weight:bold} +.logo{font-size:160%;font-weight:bold;margin:8px 0;text-align:center} +input[type="text"],input[type="password"],textarea{background:#FFF;border:1px inset gray;padding:3px} +.postform input{max-width:250px} +.postform input[name="subject"]{max-width:300px} +.postform textarea{width:400px;height:125px} +.postblock{font-weight:bold;padding:3px} +.oekform{display:inline-block;margin-bottom:.5em} +.rules{width:468px;font-size:13px} +.rules ul{margin:4px 0 0;padding:0} +.rules li{margin-left:1em} +.thread{margin-right:170px} +.thread table{border-collapse:collapse;margin:4px 0} +.reply .info{padding-right:50px} +.hsbn{font-size:120%} +.thumb{border:none;float:left;margin:0 20px} +.ell{font-family:Mona,IPAMonaPGothic,Monapo,'MS PGothic',YOzFontAA97;vertical-align:top;width:20px} +.deleted{color:#777} +.reflink a{color:inherit;text-decoration:none} +.reply .fs,#q-p .fs{margin-left:20px} +.pg{border:1px solid;border-spacing:2px;display:table} +.pg span{border:1px inset;display:table-cell} +.pg span input{padding:.4em 1em} +.replymode,.extramode{font-weight:bold;text-align:center;padding:2px;margin:3px 0} +.name em{color:#009;font-style:normal} +.quoted{border-top:1px solid;clear:both;font-size:12px;line-height:1;margin:0 -1px;padding:4px} +.thumbpreview{display:inline-block;max-height:50px;height:auto;max-width:75px;width:auto;vertical-align:middle} +#catalog{text-align:center} +#cat_search{border:1px inset gray;padding:0;width:125px} +#catalog .thread{border-radius:4px;display:inline-block;font-size:14px;margin:5px;overflow:hidden;padding:2px;position:relative;vertical-align:top;max-height:275px;width:175px} +#catalog.enlarged .thread{margin:10px 5px;max-height:375px;width:275px} +#catalog .thread a img{border-radius:3px;margin-bottom:2px} +#catalog.enlarged .thread a img{min-width:150px;min-height:150px;max-width:250px;max-height:250px} +#catalog .subj{font-size:16px} +#catalog p{margin:0} +.yt{font-size:12px;display:inline-block;line-height:13px;margin:2px 0;padding:5px;text-decoration:none} +.yt b{font-size:14px} +.yt .pvw{width:100px;height:60px;overflow:hidden;float:left;margin-right:5px} +.yt .pvw img{margin-top:-15px;margin-left:-10px} +.cut{clear:both} +.nav label{text-decoration:underline} +.userdel{float:right;text-align:center;white-space:nowrap} +.footer{clear:both;margin-top:8px;text-align:center} +.managertable th,.managertable td{padding:3px} +#q-p{position:absolute;border:1px dotted gray} +@media(max-width:900px){.thread{margin-right:0}} +@media(max-width:720px){ + body{font-size:15px;padding:4px} + .postblock{font-size:14px;white-space:nowrap} + .pass,.ell,.thumbmsg{display:none} + .thread table,#postform input[type="text"],#postform input[type="submit"],#postform textarea,#postform input[type="file"],.rules{max-width:100%;width:100%} + .info,.fs .tt,.omitted{font-size:14px} + .date{font-size:13px} + .reply .info{padding-right:0} + .fs,.rules{font-size:12px} + .fs span{display:none} + .reply .fs{margin-left:4px} + .thumb{margin:0 8px 0 4px;max-width:100px;max-height:100px;width:auto;height:auto} + blockquote{margin:8px!important} + .userdel{float:none} + .pg{margin-top:0.5em;text-align:center;width:100%} + .pg span,.pg input{display:block;width:100%} +} \ No newline at end of file diff --git a/static/css/img/0back.png b/static/css/img/0back.png new file mode 100644 index 0000000..231a44d Binary files /dev/null and b/static/css/img/0back.png differ diff --git a/static/css/img/0info.png b/static/css/img/0info.png new file mode 100644 index 0000000..31ce6be Binary files /dev/null and b/static/css/img/0info.png differ diff --git a/static/css/img/0pc.png b/static/css/img/0pc.png new file mode 100644 index 0000000..f894f66 Binary files /dev/null and b/static/css/img/0pc.png differ diff --git a/static/css/img/ba.gif b/static/css/img/ba.gif new file mode 100644 index 0000000..fa1d375 Binary files /dev/null and b/static/css/img/ba.gif differ diff --git a/static/css/img/barra_dulce.png b/static/css/img/barra_dulce.png new file mode 100644 index 0000000..c872a7e Binary files /dev/null and b/static/css/img/barra_dulce.png differ diff --git a/static/css/img/bg_deportes.gif b/static/css/img/bg_deportes.gif new file mode 100644 index 0000000..1d107e5 Binary files /dev/null and b/static/css/img/bg_deportes.gif differ diff --git a/static/css/img/bg_madera.png b/static/css/img/bg_madera.png new file mode 100644 index 0000000..1e98769 Binary files /dev/null and b/static/css/img/bg_madera.png differ diff --git a/static/css/img/bg_oculto.gif b/static/css/img/bg_oculto.gif new file mode 100644 index 0000000..65a3744 Binary files /dev/null and b/static/css/img/bg_oculto.gif differ diff --git a/static/css/img/bgtb.gif b/static/css/img/bgtb.gif new file mode 100644 index 0000000..c9f675c Binary files /dev/null and b/static/css/img/bgtb.gif differ diff --git a/static/css/img/checked.png b/static/css/img/checked.png new file mode 100644 index 0000000..67332b0 Binary files /dev/null and b/static/css/img/checked.png differ diff --git a/static/css/img/cyb.png b/static/css/img/cyb.png new file mode 100644 index 0000000..a75a55f Binary files /dev/null and b/static/css/img/cyb.png differ diff --git a/static/css/img/cyba.png b/static/css/img/cyba.png new file mode 100644 index 0000000..c79e9b2 Binary files /dev/null and b/static/css/img/cyba.png differ diff --git a/static/css/img/fondo2012.gif b/static/css/img/fondo2012.gif new file mode 100644 index 0000000..d31e6a3 Binary files /dev/null and b/static/css/img/fondo2012.gif differ diff --git a/static/css/img/green.gif b/static/css/img/green.gif new file mode 100644 index 0000000..9d4963c Binary files /dev/null and b/static/css/img/green.gif differ diff --git a/static/css/img/hand.png b/static/css/img/hand.png new file mode 100644 index 0000000..291411c Binary files /dev/null and b/static/css/img/hand.png differ diff --git a/static/css/img/luz.gif b/static/css/img/luz.gif new file mode 100644 index 0000000..f8667cf Binary files /dev/null and b/static/css/img/luz.gif differ diff --git a/static/css/img/muro.jpg b/static/css/img/muro.jpg new file mode 100644 index 0000000..54dd86b Binary files /dev/null and b/static/css/img/muro.jpg differ diff --git a/static/css/img/nieve.png b/static/css/img/nieve.png new file mode 100644 index 0000000..ba8fc25 Binary files /dev/null and b/static/css/img/nieve.png differ diff --git a/static/css/img/picnicbdy.gif b/static/css/img/picnicbdy.gif new file mode 100644 index 0000000..f0c30bc Binary files /dev/null and b/static/css/img/picnicbdy.gif differ diff --git a/static/css/img/picnicbg.gif b/static/css/img/picnicbg.gif new file mode 100644 index 0000000..4c6aa64 Binary files /dev/null and b/static/css/img/picnicbg.gif differ diff --git a/static/css/img/picnicbtm.gif b/static/css/img/picnicbtm.gif new file mode 100644 index 0000000..a380890 Binary files /dev/null and b/static/css/img/picnicbtm.gif differ diff --git a/static/css/img/picnicbtn.gif b/static/css/img/picnicbtn.gif new file mode 100644 index 0000000..b7fd7fe Binary files /dev/null and b/static/css/img/picnicbtn.gif differ diff --git a/static/css/img/picnicfg.gif b/static/css/img/picnicfg.gif new file mode 100644 index 0000000..435ab0f Binary files /dev/null and b/static/css/img/picnicfg.gif differ diff --git a/static/css/img/picnichr.gif b/static/css/img/picnichr.gif new file mode 100644 index 0000000..b50ccb1 Binary files /dev/null and b/static/css/img/picnichr.gif differ diff --git a/static/css/img/picnicmid.gif b/static/css/img/picnicmid.gif new file mode 100644 index 0000000..de2beb4 Binary files /dev/null and b/static/css/img/picnicmid.gif differ diff --git a/static/css/img/picnicthr1.gif b/static/css/img/picnicthr1.gif new file mode 100644 index 0000000..c9a967f Binary files /dev/null and b/static/css/img/picnicthr1.gif differ diff --git a/static/css/img/picnicthr2.gif b/static/css/img/picnicthr2.gif new file mode 100644 index 0000000..cbe13fb Binary files /dev/null and b/static/css/img/picnicthr2.gif differ diff --git a/static/css/img/picnicthr3.gif b/static/css/img/picnicthr3.gif new file mode 100644 index 0000000..55c22c1 Binary files /dev/null and b/static/css/img/picnicthr3.gif differ diff --git a/static/css/img/picnictop.gif b/static/css/img/picnictop.gif new file mode 100644 index 0000000..91ccc5e Binary files /dev/null and b/static/css/img/picnictop.gif differ diff --git a/static/css/img/scan.png b/static/css/img/scan.png new file mode 100644 index 0000000..6632095 Binary files /dev/null and b/static/css/img/scan.png differ diff --git a/static/css/img/scroller1.gif b/static/css/img/scroller1.gif new file mode 100644 index 0000000..633d7c1 Binary files /dev/null and b/static/css/img/scroller1.gif differ diff --git a/static/css/img/tanasinn.gif b/static/css/img/tanasinn.gif new file mode 100644 index 0000000..466614b Binary files /dev/null and b/static/css/img/tanasinn.gif differ diff --git a/static/css/img/vndb1.jpg b/static/css/img/vndb1.jpg new file mode 100644 index 0000000..f91e414 Binary files /dev/null and b/static/css/img/vndb1.jpg differ diff --git a/static/css/img/vndb2.jpg b/static/css/img/vndb2.jpg new file mode 100644 index 0000000..e1dff0c Binary files /dev/null and b/static/css/img/vndb2.jpg differ diff --git a/static/css/img/vndb3.png b/static/css/img/vndb3.png new file mode 100644 index 0000000..d31bc8f Binary files /dev/null and b/static/css/img/vndb3.png differ diff --git a/static/css/kraut.css b/static/css/kraut.css new file mode 100644 index 0000000..a9e82da --- /dev/null +++ b/static/css/kraut.css @@ -0,0 +1,24 @@ +html,body{background:#eee;color:#000;font-family:arial,helvetica,"nimbus sans l",sans-serif} +.rep{background:#313370;border:1px solid #6569e5;border-radius:3px;color:#bdbee4;display:inline-block;font-size:14px;font-weight:bold;padding:1px;text-decoration:none} +a,a .name,.nav label{color:#229} +a:hover,a:hover .name,.nav label:hover{color:#922} +#main_nav{background:#bbd;margin:-10px -10px 0;padding:10px} +.replymode,.extramode{background:#313370;color:#fff} +.postblock{background:#313370;color:#fff} +.q{color:#077} +.reply .fs{font-style:italic} +.fs a{font-style:normal} +.subj{color:#c33;font-weight:bold} +.name{color:#33c} +.omitted,.abbrev{color:#666} +.reply,#q-p{background:#aac} +.thumb{background:#ddd;border:1px solid #aaa} +.reply .thumb{background:#99b;border:1px solid #aaf} +#q-p{border:1px solid #003099;box-shadow:5px 5px #333} +.highlight{background:#aac;/*border:2px dashed #448*/} +.managertable td{background:#ddd} +.managertable th{background:#313370;color:#fff} +#catalog .thread:hover{background:#aac;box-shadow:0 0 5px 5px #aac} +#catalog .replies{color:#888;font-weight:bold} +.yt{background:#99b;border:1px solid #313370;color:#000} +.quoted{border-color:#eee;color:#077} \ No newline at end of file diff --git a/static/css/mobile.css b/static/css/mobile.css new file mode 100644 index 0000000..9921d3a --- /dev/null +++ b/static/css/mobile.css @@ -0,0 +1,129 @@ +*{box-sizing:border-box;word-wrap:break-word} +body,input,textarea{color:#000;margin:0 auto;max-width:700px;padding:0} +body,textarea{font-family:arial,sans-serif;font-size:16px} +.txt{background:#efefef} +.img{background:#1a1d22;color:#e0e0e0} +br{line-height:0.5em} +a{text-decoration:none} +.txt a{color:#00c} +.txt a:active{color:#f00} +.img a{color:#b0ccde} +.img a:hover{color:#5c6a74} +.txt a.num{color:#222} +.img .num{color:#a3a3a3;float:right} +h1{font-size:18px} +.txt h1{margin-left:2px} +.img h1{color:#a6b8d8;margin:0 0 5px} +h1 span{font-weight:400} +h2{color:#a6b8d8;font-size:14px;margin:0;} +h3,h4{clear:both;font-size:12px;font-weight:400;line-height:1;margin:10px 0} +h3 em{font-weight:700;font-style:normal} +h4{text-align:right} +.txt h3,h4{color:#777} +.txt h3.del,.txt h3.del a.num{color:#afafaf} +.img h3{color:#a3a3a3;margin:0 0 5px} +.img h3.del{color:#606060;margin-bottom:0} +.prev h3{clear:none;margin:0} +hr{margin:.25em 0}m +.img hr{border:none;border-top:1px solid #333;height:0} +.top{background:#444;color:#fff;font-size:32px;font-weight:700;line-height:1;min-height:30px;padding:10px 2px} +.top a{color:#fff!important;float:right;font-size:14px;margin-top:-10px;padding-top:10px;text-align:center;height:50px;width:50px} +.top a img{height:18px;width:18px} +.bar{font-weight:bold;overflow-y:hidden;overflow-x:auto;white-space:nowrap;width:100%} +.txt .bar{background:#ccc} +.img .bar{background:#050607} +.bar a{padding:8px;display:inline-block} +.txt .bar a{color:#000} +.img .bar a{color:#e0e0e0} +.txt .bar a.sel{background:#efefef} +.img .bar a.sel{background:#1a1d22} +.ord{overflow-y:hidden;overflow-x:auto;white-space:nowrap;width:100%} +.txt .ord{border-top:1px solid #f8f8f8;border-bottom:1px solid #ddd;color:#000} +.img .ord{border-top:1px solid #444;border-bottom:1px solid #111;color:#e0e0e0} +.ord span{display:inline-block;font-weight:bold;padding:7px 10px} +.ord a{display:inline-block;padding:7px 10px} +.ord a.sel:before{content:'✓ '} +.txt .ord a{border-left:1px solid #f8f8f8;border-right:1px solid #ddd;color:#000} +.img .ord a{border-left:1px solid #444;border-right:1px solid #111;color:#e0e0e0} +.txt .ord a:hover{background:#dcdcdc} +.img .ord a:hover{background:#14161a} +.nav{text-align:center} +.list a{display:block;padding:10px 5px} +.txt .list a{border-top:1px solid #f8f8f8;border-bottom:1px solid #ddd;color:#000} +.txt .list a:hover{background:#dcdcdc;color:#000} +.img .list a{border-top:1px solid #444;border-bottom:1px solid #111;color:#e0e0e0;overflow:hidden} +.img .list a:hover{background:#14161a} +.list div{font-size:90%;font-weight:700;margin-top:3px;text-align:right} +.list div span{font-weight:400} +.list div span span{font-weight:700;color:red} +.list .info{display:block;font-size:75%;margin-top:3px} +.txt .list .info{color:#777} +.img .list .info{color:#a3a3a3} +.list .info span{float:right} +.txt .nav{border-top:1px solid #c6c7c8} +.img .nav{border-top:1px solid #333} +.nav div{display:table;width:100%} +.txt .nav div{border-bottom:1px solid #c6c7c8} +.img .nav div{border-bottom:1px solid #333} +.nav div a{display:table-cell;padding:6px 0;width:33%} +.txt .nav div a,#nav2 a{border-right:1px solid #c6c7c8;color:#000} +.img .nav div a{border-right:1px solid #333;color:#e0e0e0} +.txt .nav div a:last-child,.img .nav div a:last-child{border-right:0} +#nav2{overflow-y:auto;padding:3px;text-align:center;white-space:nowrap;width:100%} +#nav2 a{border:1px solid #c6c7c8;border-radius:5px;display:inline-block;padding:4px} +.msg{line-height:1.2em} +.msg a{border:1px solid;border-radius:10px;display:inline-block;font-size:12px;margin:2px 0;padding:4px} +.msg a[href^="/"]{border-radius:5px;font-size:inherit;padding:2px 4px} +.thm{color:grey!important;font-size:12px;float:left;line-height:12px;margin-right:5px;text-align:center} +.thm img{margin-bottom:2px} +.mnu{transform:rotate(90deg);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);float:left;font-weight:bold;line-height:1} +.txt a.mnu{color:#777;position:relative;left:2px} +.img .mnu{color:#a3a3a3;margin-right:3px} +#mnu-list{border:1px solid #111;border-bottom:0;box-shadow:1px 1px #000;display:inline-block;position:absolute} +.txt #mnu-list{background:#E6E6E6} +.img #mnu-list{background:#2A2D37} +#mnu-list a{border-bottom:1px solid #111;color:inherit;display:block;padding:5px} +.txt #mnu-list a:hover{background:#DDD} +.img #mnu-list a:hover{background:#1E212B} +.search input{background:#fff;border-top:1px solid #f8f8f8;border-right:0;border-bottom:1px solid #ddd;border-left:0;padding:8px;width:100%} +.fld,#post,textarea{background:#fff;border:none;width:100%} +.img .fld,.img textarea{border-bottom:1px solid #1a1d22} +.txt .fld,.txt textarea{border-bottom:1px solid #efefef} +input[type="text"].fld{font-size:12px;padding:4px 0} +input[type="file"].fld{color:#000;padding:2px 0;width:100%} +input[type="text"].imp{font-size:16px;font-weight:700} +.file{display:table;width:100%}.file .fld{display:table-cell} +.file label{color:#000;padding-left:5px;vertical-align:middle;white-space:nowrap;width:auto} +#post{background:#fefefe;background:-webkit-linear-gradient(#fefefe,#e7e8e9);background:-o-linear-gradient(#fefefe,#e7e8e9);background:-moz-linear-gradient(#fefefe,#e7e8e9);background:linear-gradient(#fefefe,#e7e8e9);border-top:1px solid #c6c7c8;border-bottom:1px solid #c6c7c8;box-shadow:0 1px #fff,0 -1px #fff;display:block;padding:12px 0} +#post:active{background:#e7e8e9;background:-webkit-linear-gradient(#e7e8e9,#fefefe);background:-o-linear-gradient(#e7e8e9,#fefefe);background:-moz-linear-gradient(#e7e8e9,#fefefe);background:linear-gradient(#e7e8e9,#fefefe)} +#post:disabled{background:#fefefe;background:-webkit-linear-gradient(#fefefe,#e7e8e9);background:-o-linear-gradient(#fefefe,#e7e8e9);background:-moz-linear-gradient(#fefefe,#e7e8e9);background:linear-gradient(#fefefe,#e7e8e9);color:gray;text-shadow:1px 1px #fff} +.img form{margin:5px 0}.img #post{margin-top:5px} +.txt form{margin:10px 0}.txt #post{margin-top:10px} +.img .cat{border:1px solid #373a44;color:#e0e0e0;display:inline-block;font-size:12px;height:150px;margin:3px;overflow:hidden;position:relative;padding:2px;text-align:center;vertical-align:top;width:130px} +.img .cat:hover{color:#fff;background:#373a44} +.img .cat img{margin-bottom:2px} +.img .prev{border-bottom:1px solid #333;font-size:14px;margin:8px 0;overflow:hidden;padding:0 5px 8px} +.img .prev .pst{margin-top:5px;margin-bottom:0} +.img .first,.img .pst{display:block;padding:5px;overflow:hidden} +.img .pst{background:#373a44;margin-bottom:5px} +.img .q{color:#789922} +.img .yt{background:#292c33;border:1px solid #5e6b7d;color:#e0e0e0} +#n{display:block;padding:6px 0;text-align:center} +.txt #n{border-top:1px solid #c6c7c8;color:#000} +.img #n{border-top:1px solid #333;color:#e0e0e0} +.txt #thread{margin-top:8px} +.txt .msg a{background:#e9e9e9;border-color:#ccc} +.txt .msg a:active{border-color:red} +.txt .pst{border-top:1px solid #c6c7c8;padding:0 2px} +.txt .q{color:#666} +.txt .yt{background:#ddd;border:1px solid gray!important} +.rules{font-size:12px;text-align:center} +.txt .rules{margin:10px}.img .rules{margin:5px} +.stop{font-size:75%;line-height:3em;padding:2px} +.warn{font-size:75%;padding:5px 2px} +.yellow{background:#ff0;color:#000} +.red{background:red;color:#fff} +.yt{border-radius:0!important;line-height:1.2em!important;margin:2px 0;padding:4px!important} +.yt .pvw{float:left;height:60px;margin-right:4px;overflow:hidden;width:100px} +.yt .pvw img{margin-top:-15px;margin-left:-10px} +.yt b{font-size:115%} \ No newline at end of file diff --git a/static/css/night.css b/static/css/night.css new file mode 100644 index 0000000..ba3ee7b --- /dev/null +++ b/static/css/night.css @@ -0,0 +1,22 @@ +html,body{background:#171e24;color:#979ea3;font-family:Arial,Helvetica,"Nimbus Sans L",sans-serif} +a,a .name,.nav label{color:#c0c4c8} +a.rep{color:#979ea3;text-decoration:underline} +a:hover,a:hover .name,.nav label:hover{color:#888c90} +.replymode,.extramode{color:#DDD} +.replymode{background:#B40D00} +.extramode{background:#001f6e} +.postblock{background:#2b3843} +.q{color:#789922} +.subj{background:inherit;color:#962e5f;font-weight:bold} +.name{color:#5f962e} +.name a{color:#2e5f96} +.name a:hover{color:#426fa0} +.reply{background:#2F3D48;border:1px solid #1c242b} +.abbrev{color:#707070} +.highlight{background:#1D1D21;border:1px solid #111} +hr{border:none;border-top:1px solid #979ea3;height:0} +#catalog .thread:hover{background:#2F3D48;box-shadow:0 0 5px 5px #2F3D48} +#catalog .replies{color:#909090;font-weight:bold} +.yt{background:#52626D;border:1px solid #131D25} +#q-p{background:#2F3D48} +.quoted{border-color:#171e24} \ No newline at end of file diff --git a/static/css/photon.css b/static/css/photon.css new file mode 100644 index 0000000..7be906a --- /dev/null +++ b/static/css/photon.css @@ -0,0 +1,22 @@ +html,body{background:#EEE;color:#333;font-family:Arial,Helvetica,"Nimbus Sans L",sans-serif} +.rep{color:#333} +a,a .name,a .name b,.logo,.nav label{color:#F60} +a:hover,a:hover .name,a:hover .name b,.nav label:hover{color:#0066FF} +.replymode,.extramode{color:#2266AA;border:solid 1px #CCC;background:#DDD} +.postblock{background:#DDD;color:#024;border:1px solid #CCC;} +.q{color:#789922} +.fs,.abbrev{color:#666;text-decoration:none} +.subj{color:#111;font-weight:bold} +.name{color:#F30} +.name b{color:#004A99} +.omitted{color:#707070} +.reply{background:#DDD;border:1px solid #CCC} +.highlight{background:#CCC} +.managertable td{background:#DDD;color:#024} +.managertable th{background:#CCC;color:#024} +hr{border:none;border-top:1px solid #BBB;height:0} +#catalog .thread:hover{background:#DDD;box-shadow:0 0 5px 5px #DDD} +#catalog .replies{color:#888;font-weight:bold} +.yt{background:#E9E9E9;border:1px solid #BBB;color:#333} +#q-p{background:#DDD} +.quoted{border-color:#CCC} \ No newline at end of file diff --git a/static/css/putaba.css b/static/css/putaba.css new file mode 100644 index 0000000..840d5fd --- /dev/null +++ b/static/css/putaba.css @@ -0,0 +1,46 @@ +html,body{background:#fff url('img/fondo2012.gif');font-family:"courier new",courier,monospace;color:#000} +a,.reflink a,.nav label{color:#fff;text-decoration:none;background:#f60} +a.rep{text-decoration:underline} +a:hover,.reflink a:hover,.nav label:hover{background:#f00} +a .name,a .name b{background:#0cf;color:#903} +a:hover .name,a:hover .name b{background:#f33;color:#fff} +input[type="button"],input[type="submit"]{background:#eff931;background:-moz-linear-gradient(top, #eff931 0%, #c9e800 100%);border:1px solid #d3de27;color:#333;padding:3px 10px} +input,input[type="text"],input[type="password"],textarea,.searchbar input{background:#cf0;border:1px solid #000} +#main_nav a{color:#000;background:#0cf} +#main_nav a:hover{color:#fff;background:#90f} +#main_nav span a{color:#fff;background:#f03} +#main_nav span a:hover{background:#cf0} +.replymode,.extramode{background:url('img/bgtb.gif');color:#000} +hr,.ell{display:none} +.thread hr{display:block} +.thread,.userdelete,.postform,.oekform{background:#fff;box-shadow:1px 1px 1px rgba(50, 50, 50, 0.5);margin:0 10px 10px;padding:10px;overflow:auto} +.postarea table{margin:0 auto 10px} +.info,.fs{text-transform:uppercase} +.thread label{background:#ff0} +.thread label a,.thread label a:hover{background:#00ccff;color:#990033} +.rules{letter-spacing:-0.5px} +.rules li{margin-left:0.5em} +.rules a{background:#f06;color:#fff} +.rules a:hover{color:#cf0} +.postblock{background:#ff0} +.q{color:#789922} +.subj{font-weight:bold;color:#909;background:#cf0;letter-spacing:-1px} +.name{color:black;background:white} +.name b{color:white;background:black} +.date{background:#ff0} +.omitted,.hsbn,.hsbn:hover{color:#ff3fff;background:#5500aa;display:inline-block} +.reply,#q-p{background:#e6e6e6} +.abbrev{color:#707070} +.highlight{background:#ccc} +.userdelete{padding:5px} +input[type="submit"].psei{background:#ff6600;color:white;border:none;padding:0.4em 1em} +.nav{float:left} +.managertable td,.pg{background:#fff} +.managertable th{background:#ddd} +#catalog .thread:hover{background:#e6e6e6} +#catalog .replies{background:#00ffff;color:#909090;font-weight:bold} +.yt{background:#f7f7f7;border:1px solid #999;color:#000} +.yt:hover{background:#efefef} +.footer{background:#000;color:#fff} +.footer a,.footer a:hover{background:#000} +.quoted{border-color:#fff} \ No newline at end of file diff --git a/static/css/red.css b/static/css/red.css new file mode 100644 index 0000000..ad3159a --- /dev/null +++ b/static/css/red.css @@ -0,0 +1,21 @@ +html,body{font-family:Georgia,"URW Bookman L",serif;background:#FFF2F2;color:#800000} +a,a .name,.nav label{color:#00E} +a:hover,a:hover .name,.nav label:hover{color:#D00} +.rep{color:#800000} +.replymode,.extramode{color:#FFF} +.replymode{background:#E04000} +.extramode{background:#0040E0} +.postblock{background:#F99} +.q{color:#789922} +.name{color:#036} +.omitted,.abbrev{color:#707070} +.reply,#q-p{background:#FBB} +.subj{color:#CC1105;font-weight:bold} +.highlight{background:#F0E0D6} +.managertable td{background:#FED0D0} +.managertable th{background:#FA4A4A;color:#400000} +#catalog .thread:hover{background:#FBB} +#catalog .thread:hover{background:#FBB;box-shadow:0 0 5px 5px #FBB} +#catalog .replies{color:#909090;font-weight:bold} +.yt{background:#FED8D8;border:1px solid #FE9B9B;color:#500000} +.quoted{border-color:#FFF2F2} \ No newline at end of file diff --git a/static/css/rene.css b/static/css/rene.css new file mode 100644 index 0000000..7126099 --- /dev/null +++ b/static/css/rene.css @@ -0,0 +1,22 @@ +html,body{background:#1a1d22;color:#e0e0e0;font-family:arial,helvetica,"nimbus sans l",sans-serif} +.rep{color:#e0e0e0} +a,a .name,.nav label{color:#b0ccde} +a:hover,a:hover .name,.nav label:hover{color:#5c6a74} +.replymode,.extramode{color:#fff} +.replymode{background:#2b2b2b} +.extramode{background:#333} +.postblock{background:#28282d;border:1px solid #333;color:#ddd} +.q{color:#789922} +.fs{text-decoration:none} +.subj{color:#a6b8d8;font-weight:bold} +.name,.omitted{color:#a3a3a3} +.reply,#q-p{background:#373a44} +.abbrev{color:#777} +.highlight{background:#5b5f69} +.managertable td{background:#64697b} +.managertable th{background:#252830;color:#f8f8f8} +hr{border:none;border-top:1px dotted #696969;height:0} +#catalog .thread:hover{background:#373a44;box-shadow:0 0 5px 5px #373a44} +#catalog .replies{color:#909090;font-weight:bold} +.yt{background:#292c33;border:1px solid #5e6b7d;color:#e0e0e0} +.quoted{border-color:#1a1d22;color:#aaa} \ No newline at end of file diff --git a/static/css/spc/base.css b/static/css/spc/base.css new file mode 100644 index 0000000..bb30a24 --- /dev/null +++ b/static/css/spc/base.css @@ -0,0 +1,269 @@ +/* +* Skeleton V1.2 +* Copyright 2011, Dave Gamache +* www.getskeleton.com +* Free to use under the MIT license. +* http://www.opensource.org/licenses/mit-license.php +* 6/20/2012 +*/ + + +/* Table of Content +================================================== + #Reset & Basics + #Basic Styles + #Site Styles + #Typography + #Links + #Lists + #Images + #Buttons + #Forms + #Misc */ + + +/* #Reset & Basics (Inspired by E. Meyers) +================================================== */ + html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; } + article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { + display: block; } + body { + line-height: 1; } + ol, ul { + list-style: none; } + blockquote, q { + quotes: none; } + blockquote:before, blockquote:after, + q:before, q:after { + content: ''; + content: none; } + table { + border-collapse: collapse; + border-spacing: 0; } + + +/* #Basic Styles +================================================== */ + body { + background: #fff; + font: 14px/21px "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #444; + -webkit-font-smoothing: antialiased; /* Fix for webkit rendering */ + -webkit-text-size-adjust: 100%; + } + + +/* #Typography +================================================== */ + h1, h2, h3, h4, h5, h6 { + color: #181818; + font-family: "Georgia", "Times New Roman", serif; + font-weight: normal; } + h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { font-weight: inherit; } + h1 { font-size: 46px; line-height: 50px; margin-bottom: 14px;} + h2 { font-size: 35px; line-height: 40px; margin-bottom: 10px; } + h3 { font-size: 28px; line-height: 34px; margin-bottom: 8px; } + h4 { font-size: 21px; line-height: 30px; margin-bottom: 4px; } + h5 { font-size: 17px; line-height: 24px; } + h6 { font-size: 14px; line-height: 21px; } + .subheader { color: #777; } + + p { margin: 0 0 20px 0; } + p img { margin: 0; } + p.lead { font-size: 21px; line-height: 27px; color: #777; } + + em { font-style: italic; } + strong { font-weight: bold; color: #333; } + small { font-size: 60%; } + +/* Blockquotes */ + blockquote, blockquote p { font-size: 17px; line-height: 24px; color: #777; font-style: italic; } + blockquote { margin: 0 0 20px; padding: 9px 20px 0 19px; border-left: 1px solid #ddd; } + blockquote cite { display: block; font-size: 12px; color: #555; } + blockquote cite:before { content: "\2014 \0020"; } + blockquote cite a, blockquote cite a:visited, blockquote cite a:visited { color: #555; } + + hr { border: solid #ccc; border-width: 1px 0 0; clear: both; margin: 30px 0 30px; height: 0; } + + +/* #Links +================================================== */ + a, a:visited { color: #333; text-decoration: underline; outline: 0; } + a:hover, a:focus { color: #000; } + p a, p a:visited { line-height: inherit; } + + +/* #Lists +================================================== */ + ul, ol { margin-bottom: 20px; } + ul { list-style: none outside; } + ol { list-style: decimal; } + ol, ul.square, ul.circle, ul.disc { margin-left: 30px; } + ul.square { list-style: square outside; } + ul.circle { list-style: circle outside; } + ul.disc { list-style: disc outside; } + ul ul, ul ol, + ol ol, ol ul { margin: 4px 0 5px 30px; font-size: 90%; } + ul ul li, ul ol li, + ol ol li, ol ul li { margin-bottom: 6px; } + li { line-height: 18px; margin-bottom: 12px; } + ul.large li { line-height: 21px; } + li p { line-height: 21px; } + +/* #Images +================================================== */ + + img.scale-with-grid { + max-width: 100%; + height: auto; } + + +/* #Buttons +================================================== */ + + .button, + button, + input[type="submit"], + input[type="reset"], + input[type="button"] { + background: #eee; /* Old browsers */ + background: #eee -moz-linear-gradient(top, rgba(255,255,255,.2) 0%, rgba(0,0,0,.2) 100%); /* FF3.6+ */ + background: #eee -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.2)), color-stop(100%,rgba(0,0,0,.2))); /* Chrome,Safari4+ */ + background: #eee -webkit-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* Chrome10+,Safari5.1+ */ + background: #eee -o-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* Opera11.10+ */ + background: #eee -ms-linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* IE10+ */ + background: #eee linear-gradient(top, rgba(255,255,255,.2) 0%,rgba(0,0,0,.2) 100%); /* W3C */ + border: 1px solid #aaa; + border-top: 1px solid #ccc; + border-left: 1px solid #ccc; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; + color: #444; + display: inline-block; + font-size: 11px; + font-weight: bold; + text-decoration: none; + text-shadow: 0 1px rgba(255, 255, 255, .75); + cursor: pointer; + margin-bottom: 20px; + line-height: normal; + padding: 8px 10px; + font-family: "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; } + + .button:hover, + button:hover, + input[type="submit"]:hover, + input[type="reset"]:hover, + input[type="button"]:hover { + color: #222; + background: #ddd; /* Old browsers */ + background: #ddd -moz-linear-gradient(top, rgba(255,255,255,.3) 0%, rgba(0,0,0,.3) 100%); /* FF3.6+ */ + background: #ddd -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.3)), color-stop(100%,rgba(0,0,0,.3))); /* Chrome,Safari4+ */ + background: #ddd -webkit-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* Chrome10+,Safari5.1+ */ + background: #ddd -o-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* Opera11.10+ */ + background: #ddd -ms-linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* IE10+ */ + background: #ddd linear-gradient(top, rgba(255,255,255,.3) 0%,rgba(0,0,0,.3) 100%); /* W3C */ + border: 1px solid #888; + border-top: 1px solid #aaa; + border-left: 1px solid #aaa; } + + .button:active, + button:active, + input[type="submit"]:active, + input[type="reset"]:active, + input[type="button"]:active { + border: 1px solid #666; + background: #ccc; /* Old browsers */ + background: #ccc -moz-linear-gradient(top, rgba(255,255,255,.35) 0%, rgba(10,10,10,.4) 100%); /* FF3.6+ */ + background: #ccc -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,.35)), color-stop(100%,rgba(10,10,10,.4))); /* Chrome,Safari4+ */ + background: #ccc -webkit-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* Chrome10+,Safari5.1+ */ + background: #ccc -o-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* Opera11.10+ */ + background: #ccc -ms-linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* IE10+ */ + background: #ccc linear-gradient(top, rgba(255,255,255,.35) 0%,rgba(10,10,10,.4) 100%); /* W3C */ } + + .button.full-width, + button.full-width, + input[type="submit"].full-width, + input[type="reset"].full-width, + input[type="button"].full-width { + width: 100%; + padding-left: 0 !important; + padding-right: 0 !important; + text-align: center; } + + /* Fix for odd Mozilla border & padding issues */ + button::-moz-focus-inner, + input::-moz-focus-inner { + border: 0; + padding: 0; + } + + +/* #Forms +================================================== */ + + form { + margin-bottom: 20px; } + fieldset { + margin-bottom: 20px; } + input[type="text"], + input[type="password"], + input[type="email"], + textarea, + select { + border: 1px solid #ccc; + padding: 6px 4px; + outline: none; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + border-radius: 2px; + font: 13px "HelveticaNeue", "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #777; + margin: 0; + width: 210px; + max-width: 100%; + display: block; + margin-bottom: 20px; + background: #fff; } + select { + padding: 0; } + input[type="text"]:focus, + input[type="password"]:focus, + input[type="email"]:focus, + textarea:focus { + border: 1px solid #aaa; + color: #444; + -moz-box-shadow: 0 0 3px rgba(0,0,0,.2); + -webkit-box-shadow: 0 0 3px rgba(0,0,0,.2); + box-shadow: 0 0 3px rgba(0,0,0,.2); } + textarea { + min-height: 60px; } + label, + legend { + display: block; + font-weight: bold; + font-size: 13px; } + select { + width: 220px; } + input[type="checkbox"] { + display: inline; } + label span, + legend span { + font-weight: normal; + font-size: 13px; + color: #444; } + +/* #Misc +================================================== */ + .remove-bottom { margin-bottom: 0 !important; } + .half-bottom { margin-bottom: 10px !important; } + .add-bottom { margin-bottom: 20px !important; } + + diff --git a/static/css/spc/halloween.css b/static/css/spc/halloween.css new file mode 100644 index 0000000..6870152 --- /dev/null +++ b/static/css/spc/halloween.css @@ -0,0 +1,47 @@ +body,textarea,h2 small,.del a{color:#FA5923} +body.mainpage,body.threads{background:#000 url('../img/bg_madera.png');} +body.threadpage{background:#111} +a,#n2{color:#F00} +a:active,a:active .name,#n2:active{color:#f60} +hr{border:0;border-top:1px solid #900;border-bottom: 1px solid #500000} +input[type=submit]:active,input[type=button]:active,a:active{filter:blur(2px)} +h1{text-shadow:0 4px 1px #300000,0 6px 1px #400000,0 8px 1px #500000,0 10px 1px #600000,0 12px 1px #700000,0 14px 1px #800000,0 16px 1px #900000,0 18px 1px #A00000,0 20px 1px #B00000,0 22px 1px #C00000,0 24px 1px #D00000,0 26px 1px #E00000,0 28px 1px #F00000,0 30px 1px #FA0000,0 32px 1px #FB0000,0 34px 1px #FC0000,0 36px 1px #FD0000,0 38px 1px #FE0000,0 40px 2px #F00} +.threads h1{margin-bottom:35px} +h2{margin-bottom:3px} +h2 a{color:#32cd32} +h3{color:#F00} +h3 span{color:#900} +#main_nav{background:#000} +.outerbox{background:#000;border:1px outset #FF4500;color:#FFA500} +.innerbox{border:1px inset #FF4500} +#threadlist{background:#330e00;border:1px inset #FF4500} +.mainpage .thread,#content{background:#111;border:1px outset #914400} +.name,a .name,.abbrev{color:#f90} +.name em{color:#111e6c} +.msg{color:#fa6a39;margin:4px 40px 24px} +a.thumb{margin-top:4px} +.q{color:#875384} +.yt{background:#240000;border:1px solid #FF4500} +.deleted{color:#592a56;margin-bottom:24px} +.outerbox input,.outerbox textarea{background:#222;color:#FFA500;border:1px solid #FF4500} +.outerbox input:focus,.outerbox textarea:focus{background:#401100} +.outerbox input[type=submit],.outerbox input[type=button]{background:#000;box-shadow:0 0 5px #FF4500} +.threadpage input,.threadpage textarea,.thread input,.thread textarea{background:#0C050D;border:1px solid #FA5923;color:#FA5923} +.threadpage input:focus,.threadpage textarea:focus,.thread input:focus,.thread textarea:focus{background:#290c0a} +.threadpage input[type=submit],.threadpage input[type=button],.thread input[type=submit],.thread input[type=button]{background:#0C050D} +#q-p{background:#160901;border:1px solid #521;box-shadow:0 0 5px #521} +#q-p .msg,#q-p a.thumb{margin-bottom:8px} +#createbox{display:flex} +#createbox .extrabox{border:1px inset grey;margin:7px 0 7px 7px;float:left;width:40px;height:auto;flex:0 1 40px;-webkit-flex:0 1 40px} +#createbox .innerbox{flex:0 1 100%;-webkit-flex:0 1 100%} +form .msg{border:1px dotted #FA5923;background:#000} +#footer{text-shadow:0 0 2px} +#content.list{padding:7px} +#content.list #header div{background:#2d0000;border-top:1px inset #914400} +#content.list .row:nth-child(odd),#content.grid .row:hover{background:#000} +#content.list .row div:first-child{border-left:1px inset #914400} +#content.list .row div:last-child{border-right:1px inset #914400} +#content.list .row:last-child div{border-bottom:1px inset #914400} +#content.grid{border:1px outset #914400;padding:1px} +#content.grid .row{border:1px inset #914400;margin:1px} +@media screen and (max-width:480px){.msg{margin:4px 20px 12px}} \ No newline at end of file diff --git a/static/css/spc/layout.css b/static/css/spc/layout.css new file mode 100644 index 0000000..b99f451 --- /dev/null +++ b/static/css/spc/layout.css @@ -0,0 +1,58 @@ +/* +* Skeleton V1.2 +* Copyright 2011, Dave Gamache +* www.getskeleton.com +* Free to use under the MIT license. +* http://www.opensource.org/licenses/mit-license.php +* 6/20/2012 +*/ + +/* Table of Content +================================================== + #Site Styles + #Page Styles + #Media Queries + #Font-Face */ + +/* #Site Styles +================================================== */ + +/* #Page Styles +================================================== */ + +/* #Media Queries +================================================== */ + + /* Smaller than standard 960 (devices and browsers) */ + @media only screen and (max-width: 959px) {} + + /* Tablet Portrait size to standard 960 (devices and browsers) */ + @media only screen and (min-width: 768px) and (max-width: 959px) {} + + /* All Mobile Sizes (devices and browser) */ + @media only screen and (max-width: 767px) {} + + /* Mobile Landscape Size to Tablet Portrait (devices and browsers) */ + @media only screen and (min-width: 480px) and (max-width: 767px) {} + + /* Mobile Portrait Size to Mobile Landscape Size (devices and browsers) */ + @media only screen and (max-width: 479px) {} + + +/* #Font-Face +================================================== */ +/* This is the proper syntax for an @font-face file + Just create a "fonts" folder at the root, + copy your FontName into code below and remove + comment brackets */ + +/* @font-face { + font-family: 'FontName'; + src: url('../fonts/FontName.eot'); + src: url('../fonts/FontName.eot?iefix') format('eot'), + url('../fonts/FontName.woff') format('woff'), + url('../fonts/FontName.ttf') format('truetype'), + url('../fonts/FontName.svg#webfontZam02nTh') format('svg'); + font-weight: normal; + font-style: normal; } +*/ \ No newline at end of file diff --git a/static/css/spc/navidad.css b/static/css/spc/navidad.css new file mode 100644 index 0000000..4d90c6a --- /dev/null +++ b/static/css/spc/navidad.css @@ -0,0 +1,161 @@ +html, body { + background:#004608; + color:#fff; +} +a { + color:#EFD279; +} +a.rep { + color:#fff; +} +a:hover { + color:#DD0000; +} +.reflink a:hover{ + font-weight: bold; +} +.adminbar { + text-align:right; + clear:both; + float:right; +} +.logo { + clear:both; + text-align:center; + font-size:2em; + color:#CCFFCC; + width:100%; +} +.replymode { + background:#078B26; + text-align:center; + padding:2px; + color:#FFFFFF; + width:100%; +} +.catalogmode { + background:#0040E0; + text-align:center; + padding:2px; + color:#FFFFFF; + width:100%; +} +.rules { + /*font-size:0.7em;*/ + width: 468px; + font-size: 10px; + font-family: sans-serif; +} +.rules li { + margin-left: 1em; + /*text-indent: 0em;*/ +} +.postblock { + background:#B00000; + color:#FFF; + font-weight:800; +} +.footer { + text-align:center; + font-size:12px; + font-family:serif; +} +.passvalid { + background:#EEAA88; + text-align:center; + width:100%; + color:#ffffff; +} +.dellist { + font-weight: bold; + text-align:center; +} +.delbuttons { + text-align:center; + padding-bottom:4px; + +} +.managehead { + background:#AAAA66; + color:#400000; + padding:0px; +} +.postlists { + background:#FFFFFF; + width:100%; + padding:0px; + color:#800000; +} +.row1 { + background:#EEEECC; + color:#800000; +} +.row2 { + background:#DDDDAA; + color:#800000; +} +.q { + background:inherit; + color:#BDF46C; +} +.filesize { + text-decoration:none; +} +.filetitle { + background:inherit; + font-size:1.3em; + color:#E91F1F; + font-weight:800; +} +.postername { + color:#AFD775; + font-weight:bold; +} +.postertrip { + color:#AFD775; +} +.oldpost { + color:#CC1105; + font-weight:800; +} +.omittedposts { + color:#909090; +} +.reply { + background: #078B26; + color: #fff; +} +.replyhl { + background: #F0C0B0; + color: #800000; +} +.replytitle { + font-size: 1.2em; + color:#CC1105; + font-weight:800; +} +.commentpostername { + color:#117743; + font-weight:800; +} +.thumbnailmsg { + font-size: small; + color:#800000; +} + +.abbrev { + color:#707070; +} +.highlight { + /*background:#95CBE9;*/ + background: #5B8BB4; + /*color:#2C5700;*/ + /*border: 2px dashed #070;*/ + border: 2px dashed #AFD775; +} +.banned { + color:#F99C64; +} +.administrator { + color:#C00 !important; +} diff --git a/static/css/spc/skeleton.css b/static/css/spc/skeleton.css new file mode 100644 index 0000000..049db08 --- /dev/null +++ b/static/css/spc/skeleton.css @@ -0,0 +1,242 @@ +/* +* Skeleton V1.2 +* Copyright 2011, Dave Gamache +* www.getskeleton.com +* Free to use under the MIT license. +* http://www.opensource.org/licenses/mit-license.php +* 6/20/2012 +*/ + + +/* Table of Contents +================================================== + #Base 960 Grid + #Tablet (Portrait) + #Mobile (Portrait) + #Mobile (Landscape) + #Clearing */ + + + +/* #Base 960 Grid +================================================== */ + + .container { position: relative; width: 960px; margin: 0 auto; padding: 0; } + .container .column, + .container .columns { float: left; display: inline; margin-left: 10px; margin-right: 10px; } + .row { margin-bottom: 20px; } + + /* Nested Column Classes */ + .column.alpha, .columns.alpha { margin-left: 0; } + .column.omega, .columns.omega { margin-right: 0; } + + /* Base Grid */ + .container .one.column, + .container .one.columns { width: 40px; } + .container .two.columns { width: 100px; } + .container .three.columns { width: 160px; } + .container .four.columns { width: 220px; } + .container .five.columns { width: 280px; } + .container .six.columns { width: 340px; } + .container .seven.columns { width: 400px; } + .container .eight.columns { width: 460px; } + .container .nine.columns { width: 520px; } + .container .ten.columns { width: 580px; } + .container .eleven.columns { width: 640px; } + .container .twelve.columns { width: 700px; } + .container .thirteen.columns { width: 760px; } + .container .fourteen.columns { width: 820px; } + .container .fifteen.columns { width: 880px; } + .container .sixteen.columns { width: 940px; } + + .container .one-third.column { width: 300px; } + .container .two-thirds.column { width: 620px; } + + /* Offsets */ + .container .offset-by-one { padding-left: 60px; } + .container .offset-by-two { padding-left: 120px; } + .container .offset-by-three { padding-left: 180px; } + .container .offset-by-four { padding-left: 240px; } + .container .offset-by-five { padding-left: 300px; } + .container .offset-by-six { padding-left: 360px; } + .container .offset-by-seven { padding-left: 420px; } + .container .offset-by-eight { padding-left: 480px; } + .container .offset-by-nine { padding-left: 540px; } + .container .offset-by-ten { padding-left: 600px; } + .container .offset-by-eleven { padding-left: 660px; } + .container .offset-by-twelve { padding-left: 720px; } + .container .offset-by-thirteen { padding-left: 780px; } + .container .offset-by-fourteen { padding-left: 840px; } + .container .offset-by-fifteen { padding-left: 900px; } + + + +/* #Tablet (Portrait) +================================================== */ + + /* Note: Design for a width of 768px */ + + @media only screen and (min-width: 768px) and (max-width: 959px) { + .container { width: 768px; } + .container .column, + .container .columns { margin-left: 10px; margin-right: 10px; } + .column.alpha, .columns.alpha { margin-left: 0; margin-right: 10px; } + .column.omega, .columns.omega { margin-right: 0; margin-left: 10px; } + .alpha.omega { margin-left: 0; margin-right: 0; } + + .container .one.column, + .container .one.columns { width: 28px; } + .container .two.columns { width: 76px; } + .container .three.columns { width: 124px; } + .container .four.columns { width: 172px; } + .container .five.columns { width: 220px; } + .container .six.columns { width: 268px; } + .container .seven.columns { width: 316px; } + .container .eight.columns { width: 364px; } + .container .nine.columns { width: 412px; } + .container .ten.columns { width: 460px; } + .container .eleven.columns { width: 508px; } + .container .twelve.columns { width: 556px; } + .container .thirteen.columns { width: 604px; } + .container .fourteen.columns { width: 652px; } + .container .fifteen.columns { width: 700px; } + .container .sixteen.columns { width: 748px; } + + .container .one-third.column { width: 236px; } + .container .two-thirds.column { width: 492px; } + + /* Offsets */ + .container .offset-by-one { padding-left: 48px; } + .container .offset-by-two { padding-left: 96px; } + .container .offset-by-three { padding-left: 144px; } + .container .offset-by-four { padding-left: 192px; } + .container .offset-by-five { padding-left: 240px; } + .container .offset-by-six { padding-left: 288px; } + .container .offset-by-seven { padding-left: 336px; } + .container .offset-by-eight { padding-left: 384px; } + .container .offset-by-nine { padding-left: 432px; } + .container .offset-by-ten { padding-left: 480px; } + .container .offset-by-eleven { padding-left: 528px; } + .container .offset-by-twelve { padding-left: 576px; } + .container .offset-by-thirteen { padding-left: 624px; } + .container .offset-by-fourteen { padding-left: 672px; } + .container .offset-by-fifteen { padding-left: 720px; } + } + + +/* #Mobile (Portrait) +================================================== */ + + /* Note: Design for a width of 320px */ + + @media only screen and (max-width: 767px) { + .container { width: 300px; } + .container .columns, + .container .column { margin: 0; } + + .container .one.column, + .container .one.columns, + .container .two.columns, + .container .three.columns, + .container .four.columns, + .container .five.columns, + .container .six.columns, + .container .seven.columns, + .container .eight.columns, + .container .nine.columns, + .container .ten.columns, + .container .eleven.columns, + .container .twelve.columns, + .container .thirteen.columns, + .container .fourteen.columns, + .container .fifteen.columns, + .container .sixteen.columns, + .container .one-third.column, + .container .two-thirds.column { width: 300px; } + + /* Offsets */ + .container .offset-by-one, + .container .offset-by-two, + .container .offset-by-three, + .container .offset-by-four, + .container .offset-by-five, + .container .offset-by-six, + .container .offset-by-seven, + .container .offset-by-eight, + .container .offset-by-nine, + .container .offset-by-ten, + .container .offset-by-eleven, + .container .offset-by-twelve, + .container .offset-by-thirteen, + .container .offset-by-fourteen, + .container .offset-by-fifteen { padding-left: 0; } + + } + + +/* #Mobile (Landscape) +================================================== */ + + /* Note: Design for a width of 480px */ + + @media only screen and (min-width: 480px) and (max-width: 767px) { + .container { width: 420px; } + .container .columns, + .container .column { margin: 0; } + + .container .one.column, + .container .one.columns, + .container .two.columns, + .container .three.columns, + .container .four.columns, + .container .five.columns, + .container .six.columns, + .container .seven.columns, + .container .eight.columns, + .container .nine.columns, + .container .ten.columns, + .container .eleven.columns, + .container .twelve.columns, + .container .thirteen.columns, + .container .fourteen.columns, + .container .fifteen.columns, + .container .sixteen.columns, + .container .one-third.column, + .container .two-thirds.column { width: 420px; } + } + + +/* #Clearing +================================================== */ + + /* Self Clearing Goodness */ + .container:after { content: "\0020"; display: block; height: 0; clear: both; visibility: hidden; } + + /* Use clearfix class on parent to clear nested columns, + or wrap each row of columns in a
    */ + .clearfix:before, + .clearfix:after, + .row:before, + .row:after { + content: '\0020'; + display: block; + overflow: hidden; + visibility: hidden; + width: 0; + height: 0; } + .row:after, + .clearfix:after { + clear: both; } + .row, + .clearfix { + zoom: 1; } + + /* You can also use a
    to clear columns */ + .clear { + clear: both; + display: block; + overflow: hidden; + visibility: hidden; + width: 0; + height: 0; + } \ No newline at end of file diff --git a/static/css/spc/valentin.css b/static/css/spc/valentin.css new file mode 100644 index 0000000..bbbc6c1 --- /dev/null +++ b/static/css/spc/valentin.css @@ -0,0 +1,170 @@ +html, body { + /*background:#940BFE;*/ + background: url('img/corazoncitos.gif'); + color:#fff; +} +a { + color:#EFD279; +} +a.rep { + color:#fff; +} +a:hover { + color:#DD0000; +} +.reflink a:hover{ + font-weight: bold; +} +.adminbar { + text-align:right; + clear:both; + float:right; +} +.logo { + clear:both; + text-align:center; + font-size:2em; + color:#CCFFCC; + width:100%; +} +.replymode { + background:#0BBEB8; + text-align:center; + padding:2px; + color:#FFFFFF; + width:100%; +} +.extramode { + background:#0040E0; + text-align:center; + padding:2px; + color:#FFFFFF; + width:100%; +} +.rules { + /*font-size:0.7em;*/ + width: 468px; + font-size: 11px; + font-family: sans-serif; +} +.rules li { + margin-left: 1em; + /*text-indent: 0em;*/ +} +.postblock { + background:#95CBE9; + color:#2C5700; + font-weight:800; +} +.footer { + text-align:center; + font-size:12px; + font-family:serif; +} +.passvalid { + background:#EEAA88; + text-align:center; + width:100%; + color:#ffffff; +} +.dellist { + font-weight: bold; + text-align:center; +} +.delbuttons { + text-align:center; + padding-bottom:4px; + +} +.managehead { + background:#AAAA66; + color:#400000; + padding:0px; +} +.postlists { + background:#FFFFFF; + width:100%; + padding:0px; + color:#800000; +} +.row1 { + background:#EEEECC; + color:#800000; +} +.row2 { + background:#DDDDAA; + color:#800000; +} +.q { + background:inherit; + color:#BDF46C; +} +.filesize { + text-decoration:none; +} +.filetitle { + background:inherit; + font-size:1.3em; + color:#DE9D7F; + font-weight:800; +} +.postername { + color:#AFD775; + font-weight:bold; +} +.postertrip { + color:#AFD775; +} +.oldpost { + color:#CC1105; + font-weight:800; +} +.omittedposts { + color:#909090; +} +.reply { + background: #FE0BDF; + color: #fff; +} +.replyhl { + background: #F0C0B0; + color: #800000; +} +.replytitle { + font-size: 1.2em; + color:#CC1105; + font-weight:800; +} +.commentpostername { + color:#117743; + font-weight:800; +} +.thumbnailmsg { + font-size: small; + color:#800000; +} + +.abbrev { + color:#707070; +} +.highlight { + /*background:#95CBE9;*/ + background: #5B8BB4; + /*color:#2C5700;*/ + /*border: 2px dashed #070;*/ + border: 2px dashed #AFD775; +} +.banned { + color:#F99C64; +} +.administrator { + color:#C00 !important; +} +.managertable td { + background:#3B6B94; + color:#FFF; +} +.managertable th { + background:#AAF; + color:#FFF; +} \ No newline at end of file diff --git a/static/css/spc/valentin2.css b/static/css/spc/valentin2.css new file mode 100644 index 0000000..189611c --- /dev/null +++ b/static/css/spc/valentin2.css @@ -0,0 +1,177 @@ +html, body { + background:url('img/hearts1.gif'); + color:#000; +} +a { + color:#2D89D0; +} +a.rep { + color:#000; +} +a:hover { + color:#DD0000; +} +.reflink a:hover{ + font-weight: bold; +} +.adminbar { + text-align:right; + clear:both; + float:right; +} +.logo { + clear:both; + text-align:center; + font-size:2em; + color:#B35692; + width:100%; +} +.replymode { + background:#1D7548; + text-align:center; + font-weight: bold; + padding:2px; + color:#FFFFFF; + width:100%; +} +.extramode { + background:#0040E0; + text-align:center; + font-weight: bold; + padding:2px; + color:#FFFFFF; + width:100%; +} +.rules { + /*font-size:0.7em;*/ + width: 468px; + font-size: 11px; + font-family: sans-serif; +} +.rules li { + margin-left: 1em; + /*text-indent: 0em;*/ +} +.postblock { + background:#FF7BD1; + color:#666; + font-weight:800; +} +.footer { + text-align:center; + font-size:12px; + font-family:serif; +} +.passvalid { + background:#EEAA88; + text-align:center; + width:100%; + color:#ffffff; +} +.dellist { + font-weight: bold; + text-align:center; +} +.delbuttons { + text-align:center; + padding-bottom:4px; + +} +.managehead { + background:#AAAA66; + color:#400000; + padding:0px; +} +.postlists { + background:#FFFFFF; + width:100%; + padding:0px; + color:#800000; +} +.row1 { + background:#EEEECC; + color:#800000; +} +.row2 { + background:#DDDDAA; + color:#800000; +} +.q { + background:inherit; + color:#3D343C; +} +blockquote blockquote { + background:inherit; + color:#6D940C; +} +.filesize { + text-decoration:none; +} +.filetitle { + background:inherit; + font-size:1.3em; + color:#DC3D90; + font-weight:800; +} +.postername { + color:#C000D6; + font-weight:bold; +} +.postertrip { + color:#C000D; +} +.oldpost { + color:#CC1105; + font-weight:800; +} +.omittedposts { + color:#909090; +} +.reply { + background: url('img/hearts2.jpg'); + border: 1px solid #BBF; + color: #333; +} +.replyhl { + background: #F0C0B0; + color: #800000; +} +.replytitle { + font-size: 1.2em; + color:#DE9D7F; + font-weight:800; +} +.commentpostername { + color:#117743; + font-weight:800; +} +.thumbnailmsg { + font-size: small; + color:#000; + margin: 0; +} + +.abbrev { + color:#707070; +} +.highlight { + /*background:#95CBE9;*/ + background: #5B8BB4; + /*color:#2C5700;*/ + /*border: 2px dashed #070;*/ + border: 2px dashed #AFD775; +} +.banned { + color:#F99C64; +} +.administrator { + color:#C00 !important; +} +.managertable td { + background:#3B6B94; + color:#FFF; +} +.managertable th { + background:#AAF; + color:#FFF; +} diff --git a/static/css/txt/4am.css b/static/css/txt/4am.css new file mode 100644 index 0000000..c3f06b4 --- /dev/null +++ b/static/css/txt/4am.css @@ -0,0 +1,42 @@ +body{background:#222 url('/bg2.gif');color:#CED1CF} +body.threadpage{background-image:none} +a,a .name,#n2{color:#81A2BE;text-decoration:none} +a:hover,a:focus,#n2:active{text-decoration:underline} +hr{border:1px inset #111} +input[type="text"],input[type="submit"],input[type="button"],textarea,button{background:#383838;border:1px solid #4B4E55;color:#e8e8e8} +input[type="submit"],input[type="button"],button{background:#333;padding:2px 10px} +input[type="submit"]:active,input[type="button"]:active,button:active{background:#232323} +h1{color:#dc9656;font-size:26px;margin-top:-5px;text-align:center} +h2 a{color:#C66} +h2 span{color:#999} +h3{color:#ab4642} +h3 span{color:#999} +h4{color:#c1c5c2} +#main_nav{background:#000;color:#7cafc2;z-index:9} +.banner{-webkit-filter:grayscale(60%);filter:grayscale(60%)} +.outerbox{background:#111213;border:1px solid #4B4E55;color:#777879} +#titlebox .threadnav{margin:-6px} +#threadlist{background:#0e0e0e;border:1px solid #4B4E55} +.mainpage .thread,#content{background:#1D1F21;border:3px double #4B4E55;color:#CED1CF;opacity:.9} +.threadpage .thread{color:#CED1CF} +.name,.abbrev{color:#B5BD68} +.name em{color:#88f} +.del a{color:#ab4642} +h4 .date,.quoted{color:#4e4e4e} +.msg{margin:4px 40px 24px} +a.thumb{margin-top:4px} +.q{color:#666} +.yt{background:#383838;border:1px solid gray;color:#e8e8e8} +.yt:hover{text-decoration:none} +.deleted{color:#999;margin-bottom:12px} +#q-p{background:#222;border:1px solid #999} +#q-p .msg,#q-p a.thumb{margin-bottom:8px} +.lastposts #n2{text-decoration:none} +.size{color:#ab4642} +form .msg{background:#383838;border:1px dotted #000} +#footer{color:#f7ca88} +.threads h1{text-align:left} +#content.list #header div{background:#111213} +#content.list .row:nth-child(odd),#content.grid .row:hover{background:#191B1D} +#content.grid{border:1px solid #4B4E55;padding:1px} +#content.grid .row{border:1px solid #4B4E55;margin:1px} \ No newline at end of file diff --git a/static/css/txt/amber.css b/static/css/txt/amber.css new file mode 100644 index 0000000..3de2dd5 --- /dev/null +++ b/static/css/txt/amber.css @@ -0,0 +1,44 @@ +body{background:#000;text-shadow:1px 1px #000,0 0 10px} +body,a,h2 a,h3,#n2{color:#f9690e} +a:active,#n2:active{color:#FF9F3F} +h4{background:#f9690e;color:#000;padding:0 7px;text-shadow:none} +.threadpage h4{padding:0 3px} +h4 a,.name,.name a{color:#000} +h1:after,h2 a:after,h3:after{content:"_";animation:blink 1s infinite}@keyframes blink{from,to{opacity:0}50%{opacity:1}} +h2,.thread .threadnav{margin:7px} +h3{margin:8px 0} +h3 span,.size,.abbrev{color:#f00} +hr{background:#f9690e;border:0;height:1px;box-shadow:0 0 10px #f9690e} +.spoil{background:#f9690e;color:#f9690e;text-shadow:none}.spoil:hover{color:#000} +input[type=submit],input[type=button],button{padding:2px 10px} +input,button{font-family:monospace} +input,input[type="text"],textarea,button{background:#000;border:1px solid #f9690e;color:#f9690e;text-shadow:1px 1px #000} +input[type="text"]:focus,textarea:focus{background:#3a1903} +input[type=submit]:active,input[type=button]:active,button:active{background:#f9690e;color#000} +#main_nav{background:#000;box-shadow: 0 0 10px} +.outerbox,.innerbox{border:1px solid #f9690e} +#threadlist{border:3px double #f9690e} +.mainpage .thread,.thread .innerbox{border:1px solid #f9690e} +.thread .innerbox,.threadpage,#q-p{background:#000 url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gkRBxEEIxazLgAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAGklEQVQI12NkYGD4z4AEmBjQAAsvK6oAhgoAQ6UBGwQB8rcAAAAASUVORK5CYII=')} +.thread .innerbox{padding:0} +.name em{color:#ff0} +.q{color:#d4b300} +.deleted{background:none;border-color:#f9690e;border-style:solid;border-width:1px 0;color:inherit} +.yt{background:#000;border:1px solid #f9690e} +.mainpage .postform{border-top:1px solid #f9690e;padding:1em 0 1em 40px} +.formpad{padding:0} +form .msg{border:1px dotted #f9690e;background:#000;color:#f9690e} +#q-p{border:1px solid #000;padding:0} +#q-p .reply{border:3px double #f9690e} +#q-p .reply h4{padding:1px} +#footer a{color:#f9690e} +#content{border:3px double #f9690e} +#content.list #header{background:#451d04} +#content.list .row:nth-child(odd){background:#251002} +#content.grid{border:1px solid #f9690e} +#content.grid .row{border:1px solid #f9690e} +#content.grid .row:hover{background:#251002;border-color:#f9690e} +@media(max-width:720px){ + div.msg{margin:.5em} + .mainpage .postform{padding:.5em} +} \ No newline at end of file diff --git a/static/css/txt/ayashii.css b/static/css/txt/ayashii.css new file mode 100644 index 0000000..b7e5fc0 --- /dev/null +++ b/static/css/txt/ayashii.css @@ -0,0 +1,52 @@ +body{background:#004040;color:#FFF} +a,a .name,#n2:active{color:#EFE} +a:active,a:active .name,#n2:active{color:#F00} +h2:before{content:"◆ "} +h2{display:inline-block;margin:0;margin-bottom:.5em} +h2 span{font-weight:initial;font-size:24px;margin-left:4px;display:inline-block;float:right} +h3{margin-bottom:.5em;padding-bottom:.5em} +h4:before{content:">";color:#FFFFFE;display:inline-block;font-size:16px;width:40px} +.first h4:before{content:none} +input[type=submit],input[type=button],button{border:1px outset #FFF;background:#DDD;color:#000;padding:2px 10px} +input[type=submit]:active,input[type=button]:active,button:active{border-style:inset} +#main_nav,.banner{background:inherit;text-align:left;padding-left:2.5%} +#titlebox{margin-bottom:1em;margin-top:5px} +.threadnav a{margin-left:4px} +.innerbox{margin:0;padding:0} +.innerbox,.mainpage .thread,.deleted,#content{margin-bottom:1em;padding-bottom:1em} +.innerbox,.mainpage .thread,.reply,.deleted,h3,#content{border-bottom:2px groove gray} +.links,#listmenu{text-align:left} +#threadbox{margin-bottom:1em} +#threadlinks{text-align:left;margin-bottom:.5em} +#threadlist{background:#003535;border:1px inset gray} +.reply{clear:both;margin-bottom:1em;overflow:hidden} +.name em{color:#009} +.quoted{font-size:9pt} +.del a{color:#FFF} +.first .msg{margin:1em 40px} +.msg{margin:1em 60px} +.q{color:#99b3b3} +.yt{border:1px solid #FFF} +.abbrev{margin-top:1em} +.deleted{text-decoration:line-through} +#q-p{background:#004040;border:1px solid #DDD} +#q-p h4:before{display:none} +#q-p .reply:last-child{border:0;margin-bottom:0} +.postform,.formpad{padding-left:0} +.size{color:#FFF;margin-top:-6px} +form .msg{border:1px dotted #FFF} +#footer{margin-bottom:1em;margin-top:1em;text-align:right} +.threads .outerbox{margin-top:1em} +#content.list #header div{background:#001e1e} +#content.list .row:nth-child(odd){background:#003535} +#content.grid{border-width:2px 2px 0 0} +#content.grid .row{border-width:0 0 2px 2px} +#content.grid,#content.grid .row{border-style:groove;border-color:gray} +.threads #footer{text-align:center} +@media(max-width:720px){ + body.mainpage,body.threads{margin:8px} + h2 span{margin-left:0;float:none} + .reply{margin-bottom:.5em} + h4:before{font-size:12px;width:20px} + div.msg{margin:.5em 0 .5em 20px} +} \ No newline at end of file diff --git a/static/css/txt/baisano.css b/static/css/txt/baisano.css new file mode 100644 index 0000000..82043dd --- /dev/null +++ b/static/css/txt/baisano.css @@ -0,0 +1,43 @@ +body,textarea{color:#000} +body.mainpage,body.threads{background:#c5ad99 url(../img/muro.jpg)} +body.threadpage{background:#EFEFEF} +a,a .name,#n2{color:#00F} +a:active,a:active .name,#n2:active{color:#f00} +h2{margin-bottom:3px} +h2 a{color:#F00} +h3{color:#F00} +h3 span{color:#000} +.mainpage h4:hover{background:#FFEFEF} +h4.hidden{background:#CCC} +.mainpage h4.hidden:hover{background:#DCC} +#main_nav{background:#FFF} +.outerbox{background:#CFC;border:1px outset #FFF} +.innerbox{border:1px inset #FFF} +#threadlist{background:#BEB;border:1px inset #FFF} +.mainpage .thread,#content{background:#EFEFEF;border:1px outset #FFF} +.name,.abbrev{color:green} +.name em{color:#009} +.del a{color:#000} +.msg{margin:4px 40px 24px} +a.thumb{margin-top:4px} +.q{color:#666} +.yt{background:#DDD;border:1px solid #AAA} +.deleted{color:#AFAFAF;margin-bottom:24px} +#q-p{background:#EFEFEF;border:1px solid #999} +#q-p .msg,#q-p a.thumb{margin-bottom:8px} +#createbox{display:flex} +#createbox .extrabox{border:1px inset #FFF;margin:7px 0 7px 7px;float:left;width:40px;height:auto;flex:0 1 40px;-webkit-flex:0 1 40px} +#createbox .innerbox{flex:0 1 100%;-webkit-flex:0 1 100%} +form .msg{border:1px dotted #000;background:#EFEFEF} +#footer{color:#333} +#content.list{padding:7px} +#content.list #header div{background:#CCC;border-top:1px inset #FFF} +#content.list .row:nth-child(odd),#content.grid .row:hover{background:#FFF} +#content.list .row div:first-child{border-left:1px inset #FFF} +#content.list .row div:last-child{border-right:1px inset #FFF} +#content.list .row:last-child div{border-bottom:1px inset #FFF} +#content.grid{border:1px outset #FFF;padding:1px} +#content.grid .row{border:1px inset #FFF;margin:1px} +@media(max-width:720px){ + .extrabox{display:none} +} \ No newline at end of file diff --git a/static/css/txt/bbs.css b/static/css/txt/bbs.css new file mode 100644 index 0000000..0ae6041 --- /dev/null +++ b/static/css/txt/bbs.css @@ -0,0 +1,95 @@ +*{box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;word-wrap:break-word} +body,textarea{font-family:arial,helvetica,sans-serif;font-size:16px} +body.mainpage,body.threads{margin:0} +body.threadpage{margin:8px} +h1,h5{font-size:18px;margin:0} +h2{font-size:16px;margin:0 0 7px} +h2 span{margin-right:2px} +h2 a{font-size:24px;text-decoration:none} +h3{font-size:19px;font-weight:normal;margin:8px 0} +h4{clear:both;font-weight:normal;margin:0} +h5{margin-bottom:8px} +input[type="text"],textarea{background:#FFF;border:1px inset #DDD;color:#000} +.banner{display:block;margin:0 auto} +#rules{line-height:1.25em;margin:8px 0} +.spoil{background:#000;color:#000}.spoil:hover{color:#fff} +code{font-size:14px} +pre{line-height:125%;margin:8px 0;white-space:pre-wrap} +#main_nav .cur_brd,#cur_stl,.locked{font-weight:bold} +#main_nav{font-size:14px;padding:4px 0;text-align:center;width:100%} +#main_nav a,#thread_nav a,#threadlinks a,.threadlinks a,label{display:inline-block} +.outerbox,.mainpage .thread,#footer,#content{margin-bottom:1em;margin-left:2.5%;margin-right:2.5%} +.innerbox{padding:7px;margin:7px} +.threadnav{float:right;font-family:mona,monapo,ipamonapgothic,monapo,'ms pgothic',yozfontaa97} +#search input{margin-right:2px} +#search input[type="text"]{padding:4px;max-width:500px;width:100%} +.links{font-size:14px;text-align:center} +#threadlinks{margin-bottom:7px;text-align:center} +#threadlinks a{margin:0 4px} +#threadlist{font-size:14px;line-height:1;max-height:11em;padding:7px;overflow-y:scroll} +#threadlist a{text-decoration:none} +#thread_nav{padding-left:6px} +.mainpage .postform,.formpad{padding-left:40px} +.reply{clear:both;line-height:1.25em;overflow:hidden} +.num{color:inherit!important;font-weight:bold;text-decoration:none} +.name em{font-style:normal} +.del{visibility:hidden} +.reply:hover .del{visibility:visible} +.quoted{font-size:12px;line-height:1} +.msg{margin:1em 40px} +.msg hr{margin-left:0;max-width:500px} +a.thumb{cursor:zoom-in;font-size:14px;float:left;margin:1em 20px;text-align:center;text-decoration:none;color:gray!important} +a.yt{margin:2px 0;display:inline-block;font-size:12px;line-height:1.2em;padding:5px;text-decoration:none} +a.yt .pvw{width:100px;height:60px;overflow:hidden;float:left;margin-right:5px} +a.yt .pvw img{margin-top:-15px;margin-left:-10px} +a.yt b{font-size:115%} +.deleted{margin-bottom:1em} +#q-p{margin-right:1em;padding:8px 8px 0;position:absolute} +#q-p .del,#q-p .quoted,#q-p .thumb div{display:none} +.size{color:#f00;font-family:arial,sans-serif;font-weight:bold;margin-bottom:8px} +.lastposts{text-align:center;line-height:1} +.lastposts #n2{text-decoration:underline} +.threadpage .threadlinks{margin:8px 0} +#createbox input,#createbox textarea{width:100%} +.pblock{text-align:right;white-space:nowrap} +form .msg{margin:0;padding:8px 2px;text-align:left} +.end,#search{margin-top:8px} +.warn{padding:1px} +.stop{padding:1em 1px} +.yellow{background:#ff0;color:#000} +.red{background:#f00;color:#fff} +#listmenu{margin-top:7px;text-align:center} +#content a{text-decoration:none} +#content a:hover{text-decoration:underline} +#content.list a{display:block;line-height:1} +#content.list .row{display:table-row} +#content.list .row div{display:table-cell;padding:5px} +#content.list .row div.thread{padding:0}#content.list .row div.thread a{padding:5px} +#content.list .pos,#content.list .com{text-align:right} +#content.list #header div{font-weight:bold;text-align:center;white-space:nowrap} +#content.grid{display:flex;flex-flow:row wrap;justify-content:space-around} +#content.grid .row{flex:1 1 auto;padding:5px} +#content.grid .row div{display:inline} +@media(min-height:999px){#threadlist{max-height:16em}} +@media(max-width:720px){ + body{font-size:15px} + .banner{width:100%!important;height:auto!important;margin-top:1em} + .outerbox,.mainpage .thread,#footer,#content{margin:1em 0} + br{line-height:.5em} + h2 a{font-size:19px} + h4,h2 span,#rules{font-size:12px} + .pblock,#footer,.end{font-size:14px} + #threadlist{overflow-x:auto;white-space:nowrap} + .size,.postform br{display:none} + .num{margin:-10px;padding:10px;position:relative} + .del{visibility:visible} + div.msg{margin:.5em 0} + .mainpage .postform,.formpad,#thread_nav{padding-left:0} + .postform>span{display:table;width:100%} + .postform span>*{display:table-cell;font-size:14px;margin-bottom:2px;white-space:nowrap} + .postform input,textarea{width:100%} + .postform textarea{height:100px} + form,#thread_nav,#footer,.end,.locked{text-align:center} + #footer a{display:block} + #content.list .row div{padding:0 2px} +} \ No newline at end of file diff --git a/static/css/txt/bios.css b/static/css/txt/bios.css new file mode 100644 index 0000000..41e7f38 --- /dev/null +++ b/static/css/txt/bios.css @@ -0,0 +1,51 @@ +body,textarea,.lastposts #counter{background:#00a;color:#fff} +a,a .name,.lastposts #n2{color:#ff0;text-decoration:none} +a:focus,a:active,a:active .name,#n2:active{background:#f00;color:#fff} +.mainpage .threadlinks a:before,#threadlinks a:before,.lastposts a:before,.lastposts label:before{content:'▶ '} +input[type="text"],textarea{background:#00a;border:1px solid #fff;color:#fff} +input[type="submit"],input[type="button"],button{background:#fff;border:0;color:#000;padding:3px 11px} +input[type="submit"]:active,input[type="button"]:active,button:active{background:#000;color:#fff} +::selection{background:#fff;color:#000} +::-moz-selection{background:#fff;color:#000} +hr{display:none} +h2,.thread .threadnav{margin:.75em} +h3{background:#fff;color:#00a;margin:0;padding:2px 8px} +h3 span{background:#00a;color:#fff;padding:2px} +#main_nav,#thread_nav{background:linear-gradient(270deg, #0000ff, #000000, #0000ff);background-position:0% 50%;-webkit-animation:bios 6s linear infinite;-moz-animation:bios 6s linear infinite;animation:bios 6s linear infinite;background-size:500% 500%} +@-webkit-keyframes bios{0%{background-position:0% 0%}50%{background-position:250% 0%}100%{background-position:500% 0%}} +@-moz-keyframes bios{0%{background-position:0% 0%}50%{background-position:250% 0%}100%{background-position:500% 0%}} +@keyframes bios{0%{background-position:0% 0%}50%{background-position:250% 0%}100%{background-position:500% 0%}} +#main_nav a,#thread_nav a,.threadpage .threadlinks a{color:#fff;text-decoration:underline} +#main_nav .cur_brd{background:#fff;color:#00a;padding:1px;text-decoration:none} +#thread_nav{margin:-8px -8px 8px;padding:6px 16px} +.innerbox{border:1px solid #fff;margin:3px;padding:.75em} +.innerbox.links{border-top:0;margin-top:-3px} +#cur_stl{background:#ff0;color:#00a} +.outerbox,.mainpage .thread,#threadlist,#content{border:1px solid #fff} +.thread .innerbox{padding:0} +.threadpage .thread{border-color:#fff;border-style:double;border-width:4px 4px 1px} +.reply{border-top:1px solid #FFF;padding:.5em .75em 0} +.threadpage .reply{padding:.5em .5em 0} +.name em{background:#fff;color:#00f} +.q,.deleted,.abbrev{color:#5cf;margin-bottom:24px} +.size{margin-left:.5em} +.yt{border:1px solid #ff0} +.yt:active{background:#f00;border:1px solid #f00;color:#fff} +#q-p{background:#00a;border:1px solid #fff} +#q-p .msg,#q-p a.thumb{margin-bottom:8px} +.lastposts{border-color:#fff;border-style:double;border-width:0 4px;color:#00a;padding:.5em} +.mainpage .threadlinks{margin-top:.75em} +.threadpage .threadlinks{margin-top:0} +.threadpage .postform{border-color:#fff;border-style:double;border-width:1px 4px 4px;padding:.5em} +.formpad{padding-left:0} +.mainpage .postform{border-top:1px solid #fff;padding:.75em} +form .msg{border:3px double #fff} +#content.list{border:4px double #fff} +#content.list #header div{border-bottom:1px solid #fff} +#content.grid{border:1px solid #fff;padding:2px} +#content.grid .row{border:1px solid #fff;margin:2px} +@media(max-width:720px){ + body.threadpage{margin:8px 0} + h2{margin-bottom:.5em} + #thread_nav{margin:-8px 0px 8px} +} \ No newline at end of file diff --git a/static/css/txt/blue moon.css b/static/css/txt/blue moon.css new file mode 100644 index 0000000..271fe9a --- /dev/null +++ b/static/css/txt/blue moon.css @@ -0,0 +1,61 @@ +body.threadpage{margin-top:0} +body{background:#6B7B8D;color:#FFF} +a,#n2:active,h3 span{color:#AFB9C5} +a:active,form a:active,#n2:active{color:#EEE} +#main_nav a,.reply a,form a,#q-p a,.row a{color:#49525D} +#main_nav a:active,.reply a:active,#q-p a:active,a:active .name,.row a:active{color:#8C9FB4} +h2{color:#EEE;line-height:1;margin:0 0 10px} +h2 a{color:#EEE} +h3{color:#EEE;margin:0.7em 0} +h4{background:#DDD;padding-bottom:5px} +hr{display:none} +input[type=text],textarea{background:#EEE;border:1px inset #444} +input[type=submit],input[type=button],button{background:#000;color:#FFF;border:1px outset #444;padding:2px 10px} +input[type=submit]:active,input[type=button]:active,button:active{border-style:inset} +#main_nav{background:#FFF;color:#6B7B8D} +#titlebox .innerbox:first-child{margin-bottom:5px} +.outerbox{background:#49525D;padding:5px} +.innerbox{margin:0;padding:10px} +.links{padding-top:5px} +#threadbox{margin-bottom:19px;margin-top:19px} +#threadlist{background:#3e4247;border:1px inset #B6C2CF} +.mainpage .thread{background:#49525D} +.threadpage .thread{background:#49525D;padding:1px 10px} +#thread_nav{background:#49525D;margin-bottom:2px;padding:7px 10px} +.postform,#createbox form,h5{background:#8C9FB4;color:#49525D;padding:10px} +h5{margin:0;padding-bottom:0} +.mainpage .postform{margin-top:10px} +.reply{background:#FFF;border-top:3px solid #DDD;border-right:10px solid #DDD;border-bottom:3px solid #DDD;border-left:10px solid #DDD;color:#000} +.first{border-top:6px solid #DDD} +.name,a .name{color:#2B3037} +.name em{color:#009} +.del a{color:#000} +.msg,a.thumb{background:#FFF;color:#000080;margin:10px} +.msg hr{display:block} +.abbrev a{color:#000080} +.abbrev,.q{color:#697685} +.threadpage .postform{margin-top:2px;border:10px solid #49525D} +.yt{background:#EEE;border:1px solid gray} +.deleted{background:#DDD;color:#AFAFAF;margin-bottom:0;padding:3px 10px} +#q-p{background:#FFF;color:#000;border:1px solid #49525D;padding:0} +form .msg{border:1px inset #DDD;margin:0;padding:.5em 0.15em} +.size{color:#8C9FB4;margin:5px 0} +.lastposts{background:#49525D;color:#AFB9C5;margin-top:2px;padding:.5em} +.threadpage .threadlinks{margin:0} +.warn,.stop{padding-left:10px;margin:2px 0} +#footer a{color:#FFF} +#content{background:#FFF;border:10px solid #49525D;color:#000080} +#content.list #header div{background:#2c2c32;color:#EEE} +#content.list .row:nth-child(odd),#content.grid .row:hover{background:#E7E7FF} +#content.grid .row{border:1px solid #DDD} +@media(max-width:720px){ + body.threadpage{margin:0 0 8px} + .innerbox,.postform,#createbox form,h5{padding:6px;padding-left:6px} + h2{margin-bottom:6px} + .threadpage .thread{padding:1px 6px 6px} + .mainpage .postform{margin-top:6px;padding-left:6px} + .reply{border-left-width:6px;border-right-width:6px} + .threadpage .postform{border-width:6px} + .msg,a.thumb{margin:6px} + .thread form{margin-top:6px} +} \ No newline at end of file diff --git a/static/css/txt/ciber.css b/static/css/txt/ciber.css new file mode 100644 index 0000000..45fce17 --- /dev/null +++ b/static/css/txt/ciber.css @@ -0,0 +1,55 @@ +body{background:#000 url('../img/cyb.png');text-shadow:1px 1px #000} +body,h3{color:#BA55D3} +a,h2 a,#n2{color:#DB43B5} +a:active,#n2:active{color:#F0F} +h4{background:#2A4A75;padding:0 7px;text-shadow:0 2px #000} +.threadpage h4{padding:0 3px} +h4,h4 a,.name,.name a{color:#9370DB} +h1,h2 a,h3,h5{text-shadow:1px 1px #000,0 0 10px} +h1:after,h2 a:after,h3:after{content:"_";animation:blink 1s infinite}@keyframes blink{from,to{opacity:0}50%{opacity:1}} +h2,.thread .threadnav{margin:7px} +h3{margin:8px 0} +h3 span,.size,.abbrev{color:#639} +hr{background:#2A4A75;border:0;height:1px;box-shadow:0 0 10px #2A4A75} +.spoil{background:#2A4A75;color:#2A4A75;text-shadow:none}.spoil:hover{color:#000} +input[type=submit],input[type=button],button{padding:2px 10px} +input:active,input:focus,textarea:active,textarea:focus,button:active,button:active{box-shadow:0 0 15px} +.outerbox input,.outerbox textarea{background:#002f00;border:1px solid #68F855;color:#68F855} +.outerbox input[type=submit],.outerbox input[type=button],.outerbox button{background:#0F0;border:3px outset #0F0;color:#000} +.outerbox input[type=submit]:active,.outerbox input[type=button]:active,.outerbox button:active{background:#0C0;border-style:inset} +.threadpage input,.threadpage textarea,.thread input,.thread textarea{background:#000;border:1px solid #2A4A75;color:#2A4A75;text-shadow:1px 1px #000} +.threadpage input[type=submit]:active,.threadpage input[type=button]:active,.thread input[type=submit]:active,.thread input[type=button]:active{border-color:#d21cea;color:#d21cea} +#main_nav{background:#000;box-shadow:0 0 10px #68F855} +.outerbox{background:#111;color:#5FE44E;border:3px outset #0F0;background:#0C0} +.outerbox a,#main_nav a,#footer a{color:#68F855} +.outerbox a:active,#main_nav a:active,#footer a:active{color:#ef6177} +#threadlist{background:rgba(26,26,26,.5);border:3px solid #0C0} +.innerbox{border:3px inset #0F0} +.outerbox .innerbox{background:#000 url('../img/green.gif')} +.mainpage .thread,.thread .innerbox{border:1px solid #2A4A75} +.mainpage .thread{background:#2A4A75;box-shadow:0 0 5px 5px #2A4A75} +.thread .innerbox,.threadpage,#q-p,form .msg{background:#000 url(' data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAIAAAAW4yFwAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAAWSURBVHjaYrDk0GLm/88FAAAA//8DAATaAYeGqOFRAAAAAElFTkSuQmCC')} +.thread .innerbox{padding:0} +.name em{color:#4B0082} +.q{color:#9932CC} +.deleted{background:none;border-color:#2A4A75;border-style:solid;border-width:1px 0;color:inherit} +.yt{background:#000;border:1px solid #2A4A75} +.mainpage .postform{border-top:1px solid #2A4A75;padding:1em 0 1em 40px} +.formpad{padding:0} +form .msg{border:1px dotted #2A4A75;color:#2A4A75} +#q-p{border:1px solid #000;padding:0} +#q-p .reply{border:3px double #2A4A75} +#q-p .reply h4{padding:1px} +#footer{color:#0C0;text-shadow:0 0 5px #0F0} +#footer a{color:#989898} +#content{background:#000;border:3px double #d500fb;color:#39c8df}#content a{color:#d500fb} +#content.list #header{text-shadow:0 0 5px} +#content.list .row:nth-child(odd){background:#200020} +#content.grid{border:2px solid #141937} +#content.grid .row{border:2px solid #141937} +#content.grid .row:hover{background:#27151D;border-color:#9B1937} +#content .row:hover a{text-shadow:0 0 5px} +@media(max-width:720px){ + div.msg{margin:.5em} + .mainpage .postform{padding:.5em} +} \ No newline at end of file diff --git a/static/css/txt/futanari.css b/static/css/txt/futanari.css new file mode 100644 index 0000000..2606f03 --- /dev/null +++ b/static/css/txt/futanari.css @@ -0,0 +1,49 @@ +body{background:#13334c;color:#edf9fc} +body.threadpage,body.threads{margin-top:0} +a,a .name,#n2{color:#efd279} +a:active,a:active .name,#n2:active{color:#d00} +h1{background:#5b8bb4;margin:-10px -10px 10px;padding:10px} +h2 span{color:#aaa;margin-right:2px} +h2 a,h2 a:active{color:#de9d7f;text-decoration:none} +h3{color:#de9d7f;margin:0.7em 0} +h3 span{color:#909090} +hr{display:none} +input,input[type="text"],textarea,button{border:1px solid #3b6b94} +input[type=submit],input[type=button],button{background:#aaf;color:#2c5700;padding:2px 10px} +input[type="submit"]:active,input[type="button"]:active,button:active{background:#88c} +#main_nav{background:#1d7548} +#titlebox{margin-bottom:0} +.outerbox{background:#3b6b94} +.innerbox{margin:0;padding:10px} +.links{background:#5b8bb4} +#threadlist{background:#154a72;border:1px inset #1b3345} +.mainpage .thread{padding:5px} +#thread_nav{background:#1d7548;padding:6px} +.name{color:#afd775} +.name em{color:#009} +.del a{color:#fff} +.msg{margin:4px 40px 24px} +.q{color:#aac} +.yt{background:#2f587a;border:1px solid #1b2933} +.msg hr{display:block} +.deleted{color:#afafaf;margin-bottom:24px} +.abbrev{color:#bbb} +.size{color:#de9d7f} +.postform,#createbox,.threads .outerbox,#content{border-right:2px solid #5b8bb4;border-bottom:2px solid #5b8bb4;background:#3b6b94} +.postform{padding:10px} +.threadpage .threadlinks{margin:0 0 3px} +form .msg{border:1px dashed #000;background:#1b3345} +#q-p{background:#1b3345;border:1px solid #3b6b94} +#q-p .msg,#q-p a.thumb{margin-bottom:8px} +.lastposts{background:#5b8bb4;padding:8px} +#content{padding:0 10px 10px} +#content.list #header div{background:#3b6b94} +#content.list .row:nth-child(odd){background:#1b3345} +#content.list .row:nth-child(even){background:#294b68} +#content.grid{border:0;padding:0} +#content.grid .row{border-width:0 2px 2px 0;border-style:solid;border-color:#5b8bb4} +#content.grid .row:hover{background:#154a72} +@media(max-width:720px){ + .mainpage .thread{padding:0} + .innerbox,.postform,.mainpage .postform{padding:8px;padding-left:8px} +} \ No newline at end of file diff --git a/static/css/txt/headline.css b/static/css/txt/headline.css new file mode 100644 index 0000000..8fb085b --- /dev/null +++ b/static/css/txt/headline.css @@ -0,0 +1,41 @@ +body,#main_nav{background:#FFF} +body,textarea{color:#000} +a,#n2,h3 span{color:#D60} +a:active .name,h2 a:active,h4 a:active,a:active,#n2:active{color:#FA4} +h2 a,.del a,.name,h4 a,h4{color:#000} +h1{border-bottom:2px solid #F70;padding:0 10px;margin:0 -10px 10px} +h2,h3{background:#EEE;border-bottom:2px solid #F70;display:inline-block;padding:2px 3px} +h3{margin:0.7em 0} +h4{background:#EEE;border-bottom:1px solid #BBB;padding:0 3px} +hr{display:none} +input,input[type="text"],textarea,button{border:1px solid #000} +input[type="submit"],input[type="button"],button{background:#DDD;padding:2px 10px} +input[type="submit"]:active,input[type="button"]:active,button:active{background:#CCC} +.outerbox,#titlebox .innerbox:first-child,.postform,.lastposts,#content{background:#EEE;border-bottom:2px solid #BBB} +.innerbox{margin:0;padding:10px} +#threadlist{background:#fff;border:1px inset #bbb} +.mainpage .thread{padding:5px} +#thread_nav{border-bottom:2px solid #F70;padding:0 0 6px 6px} +.mainpage .first div.msg::first-letter{font-size:1.5em;text-transform:uppercase} +.name em{color:#009;font-style:normal} +.q,.abbrev{color:#7f7f7f} +.yt{background:#f2f2f2;border:1px solid #bbb} +.msg hr{display:block;max-width:500px;margin-left:0} +.deleted{color:#AFAFAF} +#q-p{background:#FFF;border:1px solid #BBB;border-bottom:2px solid #BBB} +.lastposts{padding:8px} +.size{color:#D60} +.threadpage .threadlinks{margin:0 0 3px} +.postform{padding:10px} +form .msg{border:1px dashed #000;background:#FFF;margin:0;padding:.5em 0.15em} +#content{padding:0 10px 10px} +#content.list #header div{background:#EEE} +#content.list .row:nth-child(odd){background:#FFF} +#content.list .row:nth-child(even){background:#DDD} +#content.grid{border:1px solid #BBB;padding:0} +#content.grid .row{border:1px solid #BBB} +#content.grid .row:hover{background:#DDD} +@media(max-width:720px){ + .mainpage .thread{padding:0} + .innerbox,.postform,.mainpage .postform{padding:8px;padding-left:8px} +} \ No newline at end of file diff --git a/static/css/txt/postal.css b/static/css/txt/postal.css new file mode 100644 index 0000000..d91b523 --- /dev/null +++ b/static/css/txt/postal.css @@ -0,0 +1,47 @@ +body,textarea{color:#000} +body{background:#E5B98D} +a,a .name,#n2{color:#3683C2} +a:active,a:active .name,#n2:active{color:#E9976B} +input[type="text"],textarea{border:1px solid #CCC} +input[type="submit"],input[type="button"],button{background:#CBCBCB;border:0;padding:3px 10px} +input[type="submit"]:active,input[type="button"]:active,button:active{background:#B1B1B1} +body>hr{position:absolute;top:0;left:8px;right:8px;border:0;background-image:repeating-linear-gradient(125deg,#EE4C47 0px,#EE4C47 30px,#FFF 30px,#FFF 50px,#5CACEB 50px,#5CACEB 80px,#FFF 80px,#FFF 100px);height:1em} +hr,.threadpage .thread{background-image:repeating-linear-gradient(125deg,#EE4C47 0px,#EE4C47 30px,#FFF 30px,#FFF 50px,#5CACEB 50px,#5CACEB 80px,#FFF 80px,#FFF 100px)} +h2 span{color:#686868} +h2 a,h2 a:active,h3{color:#3E3020} +h2 a:active{text-decoration:underline} +h3{margin-top:0} +h3 span{color:dimgrey} +h4{background:#F0E7CE;color:#686868;padding-left:3px} +#main_nav,.outerbox{background:#FFF} +.outerbox{border:1px solid #FFF} +#threadlist{background:#EFEFEF;border:1px inset #EFEFEF} +.thread .innerbox{background:#FFF;box-shadow:1px 1px 0 rgba(0,0,0,0.1),3px 3px 0 rgba(255,255,255,1),4px 4px 0 rgba(0,0,0,0.125),6px 6px 0 rgba(255,255,255,1),7px 7px 0 rgba(0,0,0,0.15),9px 9px 0 rgba(255,255,255,1),10px 10px 0 rgba(0,0,0,0.175),12px 12px 0 rgba(255,255,255,1),13px 13px 0 rgba(0,0,0,0.175);margin:8px 12px 8px 0;padding:8px} +#thread_nav{background:#FFF;font-style:italic;padding:1.5em 8px .5em} +.threadpage .thread{background-color:#FFF;background-position:bottom;background-repeat:repeat-x;background-size:100% 1em;overflow:hidden;padding:0 10px 1.5em} +.innerbox.links {border-top:2px solid #E5B98D;margin:-1px;padding:12px} +.name,.abbrev{color:#416D91} +.name em{color:#009} +.del a{color:#000} +.q{color:#666;display:inline-block} +.q:hover{background:#F0F0E0} +.yt{background:#EEE;border:1px solid #CCC} +.deleted{background:##F7F3E6;color:#AAA} +#q-p{background:#FFF;border:1px solid #CCC} +#createbox{background:#F0E7CE;border-color:#F0E7CE;color:#353535} +.lastposts,.threadpage .postform{margin-top:.5em;padding:.5em} +.lastposts,.threadpage .postform,.threads .outerbox,#content.list,#content.grid .row{background:#FFF;-webkit-box-shadow:0 0 10px rgba(0,0,0,0.3);-moz-box-shadow:0 0 10px rgba(0,0,0,0.3);box-shadow:0 0 10px rgba(0,0,0,0.3)} +.threadpage .threadlinks{margin-top:0} +.size{margin-bottom:0} +form .msg{border:1px dotted #CCC;background:#FFF} +#footer{color:#333} +#content.list{padding:8px} +#content.list #header div{background:#6AA9D7} +#content.list .row:hover,#content.grid .row:hover{background:#B7D2E8} +#content.list .row a:hover,#content.grid .row:hover a{color:#0801BF} +#content.grid .row{margin:4px} +@media(max-width:720px){ + body.threadpage{margin:0 0 8px} + body>hr{top:-8px;left:0;right:0} + #createbox .innerbox{padding:0} +} \ No newline at end of file diff --git a/static/css/txt/sjis.css b/static/css/txt/sjis.css new file mode 100644 index 0000000..018c6db --- /dev/null +++ b/static/css/txt/sjis.css @@ -0,0 +1 @@ +body,textarea{font-family:Mona,Monapo,IPAMonaPGothic,'MS PGothic',YOzFontAA97}textarea{font-size:16px} diff --git a/static/css/txt/ventanas.css b/static/css/txt/ventanas.css new file mode 100644 index 0000000..cddee34 --- /dev/null +++ b/static/css/txt/ventanas.css @@ -0,0 +1,48 @@ +body,textarea{color:#000} +body.mainpage,body.threads{background:#008081} +body.threadpage,.outerbox,.mainpage .thread,#q-p{background:#C0C0C0} +::selection{background:blue;color:white}::-moz-selection{background:blue;color:white} +a,a .name,#n2{color:#00F} +a:active,a:active .name,#n2:active{color:#f00} +input[type=submit],input[type=button],button{border-width:2px;border-color:#FFF #000 #000 #FFF;border-style:ridge;background:#C0C0C0;color:#000;padding:2px 10px} +h1,h2,#threadlinks:before,h5{background:#010081;color:#FFF;font-size:21px;font-weight:bold;margin:-11px -11px 11px;padding:2px} +h2 a,h2 a:active{color:#FFF} +h3 span{color:#555;text-decoration:underline} +hr{border:0} +hr,.reply,.deleted{border-bottom:2px groove white} +#main_nav{background:#C0C0C0;border-bottom:2px ridge white;line-height:1;padding:2px 0} +.threadnav{line-height:1;margin:-11px} +#main_nav a,.threadnav a{background:#C0C0C0;border-width:2px;border-color:#FFF #000 #000 #FFF;border-style:ridge;color:#000;display:inline-block;margin:0 -1px;padding:2px;text-decoration:none;outline-offset:-4px} +.threadnav a{margin:2px;padding:0} +#main_nav a:first-child{font-weight:bold} +#main_nav .cur_brd{background:#BBB url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAHUlEQVQImQESAO3/AMG/wv////7/AP///v++vr7/gXcOcY36q6gAAAAASUVORK5CYII=');font-weight:bold} +#main_nav .cur_brd,#main_nav a:active,.threadnav a:active,input[type=submit]:active,input[type=button]:active,button:active{border-color:#000 #FFF #FFF #000} +.outerbox,.mainpage .thread,#q-p{border-width:2px;border-color:#FFF #000 #000 #FFF;border-style:groove} +input[type=text],textarea,.innerbox,#content,#threadlist{border-width:2px;border-color:#000 #FFF #FFF #000;border-style:groove} +#threadlinks:before{content:"";display:block;height:15px;margin-bottom:5px} +.innerbox{padding:10px;margin:2px} +.links{border:1px solid;border-color:#888 #dadada #dadada #888;padding:2px} +#threadlist{background:#FFF} +#threadlist a{color:#000} +#thread_nav a{color:#000;display:inline-block;margin:-3px -2px;padding:3px}#thread_nav a:hover{background:#DDD} +.reply,.deleted{margin-bottom:.5em} +.name,.abbrev{color:#444} +.name em{color:#009} +.del a{color:#000} +.q{color:#666} +.yt{background:#FFF;border:1px inset #aaa;color:#000} +.deleted{color:gray;padding-bottom:.5em} +#q-p{box-shadow:5px 5px #000;padding:0} +#q-p .reply{padding:.5em;margin-bottom:0} +#q-p a.thumb,#q-p .msg{margin-bottom:.5em} +.postform,.formpad{padding:0} +form .msg{background:#FFFFE0;border:1px solid #000} +#footer{color:#FFF} +#listmenu h1{background:none;color:#000;margin:0;padding:0} +#content{background:#FFF} +#content.list #header div{background:#CCC} +#content.list .row div,#content.grid .row{border-width:0 1px 1px 0;border-style:solid;border-color:#000} +#content .row:hover{background:#EEE} +@media(max-width:720px){ + #createbox form{margin:-10px} +} \ No newline at end of file diff --git a/static/css/vndb.css b/static/css/vndb.css new file mode 100644 index 0000000..43a9c7c --- /dev/null +++ b/static/css/vndb.css @@ -0,0 +1,30 @@ +html,body{background-attachment:scroll,fixed;background-color:#000;background-image:url('img/vndb1.jpg'),url('img/vndb2.jpg');background-position:left top,right top;background-repeat:no-repeat,no-repeat;color:#DDD;font-family:Arial,Helvetica,"Nimbus Sans L",sans-serif} +.rep{color:#DDD} +a,a .name,.nav label{color:#77BBDD} +a:hover,a:hover .name,.nav label:hover{border-bottom:1px dotted #DDD;text-decoration:none} +#catalog .thread > a:hover{border-bottom:none;text-decoration:underline} +.logo{color:#135;font-style:italic} +.replymode,.extramode{color:#FFF} +.replymode{background:#258} +.extramode{background:#247} +.postblock{border:1px solid #258;background:rgba(7,28,47,0.75)} +input,input[type="text"],input[type="password"],textarea{background:#0d2741;border:1px solid #35A;color:#DDD} +input[type="submit"]{background:rgba(7,28,47,0.9);padding:3px 10px} +input[type="submit"]:active{background:#0d2741} +.fs{text-decoration:none} +.subj{color:#7bd;font-weight:bold} +.ell,.name,.omitted{color:#258} +.q{border-left:1px dotted #258;color:#336da7} +.reply,#q-p{background:rgba(7,28,47,0.8);border:1px solid #258} +.abbrev{color:#707070} +.highlight{background:rgb(10,35,60)} +.managertable{border:1px solid #258} +.managertable td{background:rgba(7,28,47,0.5)} +.managertable th{background:rgba(7,28,47,0.9)} +hr{border:none;border-top:1px solid #258;height:0} +#catalog .thread:hover{background:rgba(7,28,47,0.92);box-shadow:0 0 5px 5px rgba(7,28,47,0.9)} +#catalog .replies{color:#258;font-weight:bold} +.yt,.yt:hover{background:#0d2741;border:1px solid #258;color:#DDD} +.pg,.pg td{background:rgba(7,28,47,0.8);border:1px solid #258} +.footer,.footer a{color:#247} +.quoted{border-color:#35A;color:#247} \ No newline at end of file diff --git a/static/ico/1372836.gif b/static/ico/1372836.gif new file mode 100644 index 0000000..9ebe25b Binary files /dev/null and b/static/ico/1372836.gif differ diff --git a/static/ico/1k.gif b/static/ico/1k.gif new file mode 100644 index 0000000..95847ec Binary files /dev/null and b/static/ico/1k.gif differ diff --git a/static/ico/2-1.gif b/static/ico/2-1.gif new file mode 100644 index 0000000..a7f2b98 Binary files /dev/null and b/static/ico/2-1.gif differ diff --git a/static/ico/2ppa.gif b/static/ico/2ppa.gif new file mode 100644 index 0000000..23088ea Binary files /dev/null and b/static/ico/2ppa.gif differ diff --git a/static/ico/2syobo_2.gif b/static/ico/2syobo_2.gif new file mode 100644 index 0000000..d54d613 Binary files /dev/null and b/static/ico/2syobo_2.gif differ diff --git a/static/ico/3-2.gif b/static/ico/3-2.gif new file mode 100644 index 0000000..c0aff5a Binary files /dev/null and b/static/ico/3-2.gif differ diff --git a/static/ico/3.gif b/static/ico/3.gif new file mode 100644 index 0000000..fb65b6d Binary files /dev/null and b/static/ico/3.gif differ diff --git a/static/ico/3na.gif b/static/ico/3na.gif new file mode 100644 index 0000000..2c30e0c Binary files /dev/null and b/static/ico/3na.gif differ diff --git a/static/ico/4-2.gif b/static/ico/4-2.gif new file mode 100644 index 0000000..0d43898 Binary files /dev/null and b/static/ico/4-2.gif differ diff --git a/static/ico/4248688.gif b/static/ico/4248688.gif new file mode 100644 index 0000000..ef629f0 Binary files /dev/null and b/static/ico/4248688.gif differ diff --git a/static/ico/5007629.gif b/static/ico/5007629.gif new file mode 100644 index 0000000..9fa6a22 Binary files /dev/null and b/static/ico/5007629.gif differ diff --git a/static/ico/5296219.gif b/static/ico/5296219.gif new file mode 100644 index 0000000..a77351d Binary files /dev/null and b/static/ico/5296219.gif differ diff --git a/static/ico/5ta.gif b/static/ico/5ta.gif new file mode 100644 index 0000000..04800b1 Binary files /dev/null and b/static/ico/5ta.gif differ diff --git a/static/ico/6396408.gif b/static/ico/6396408.gif new file mode 100644 index 0000000..ba33fc2 Binary files /dev/null and b/static/ico/6396408.gif differ diff --git a/static/ico/6za.gif b/static/ico/6za.gif new file mode 100644 index 0000000..bd4a945 Binary files /dev/null and b/static/ico/6za.gif differ diff --git a/static/ico/8028885.gif b/static/ico/8028885.gif new file mode 100644 index 0000000..cca1680 Binary files /dev/null and b/static/ico/8028885.gif differ diff --git a/static/ico/8toushinnomonar16.gif b/static/ico/8toushinnomonar16.gif new file mode 100644 index 0000000..e4ac044 Binary files /dev/null and b/static/ico/8toushinnomonar16.gif differ diff --git a/static/ico/8toushinnomonar32.gif b/static/ico/8toushinnomonar32.gif new file mode 100644 index 0000000..4c31836 Binary files /dev/null and b/static/ico/8toushinnomonar32.gif differ diff --git a/static/ico/ace.gif b/static/ico/ace.gif new file mode 100644 index 0000000..f521c7e Binary files /dev/null and b/static/ico/ace.gif differ diff --git a/static/ico/af1.gif b/static/ico/af1.gif new file mode 100644 index 0000000..e88e02b Binary files /dev/null and b/static/ico/af1.gif differ diff --git a/static/ico/af2.gif b/static/ico/af2.gif new file mode 100644 index 0000000..fe46aa6 Binary files /dev/null and b/static/ico/af2.gif differ diff --git a/static/ico/ahya_xmas_2.gif b/static/ico/ahya_xmas_2.gif new file mode 100644 index 0000000..6c0aebc Binary files /dev/null and b/static/ico/ahya_xmas_2.gif differ diff --git a/static/ico/aka.gif b/static/ico/aka.gif new file mode 100644 index 0000000..c22596b Binary files /dev/null and b/static/ico/aka.gif differ diff --git a/static/ico/ame.gif b/static/ico/ame.gif new file mode 100644 index 0000000..08dca67 Binary files /dev/null and b/static/ico/ame.gif differ diff --git a/static/ico/anime_buun02.gif b/static/ico/anime_buun02.gif new file mode 100644 index 0000000..c3422f2 Binary files /dev/null and b/static/ico/anime_buun02.gif differ diff --git a/static/ico/anime_charhan01.gif b/static/ico/anime_charhan01.gif new file mode 100644 index 0000000..cb04d65 Binary files /dev/null and b/static/ico/anime_charhan01.gif differ diff --git a/static/ico/anime_charhan02.gif b/static/ico/anime_charhan02.gif new file mode 100644 index 0000000..92eb054 Binary files /dev/null and b/static/ico/anime_charhan02.gif differ diff --git a/static/ico/anime_giko01.gif b/static/ico/anime_giko01.gif new file mode 100644 index 0000000..d4a6f84 Binary files /dev/null and b/static/ico/anime_giko01.gif differ diff --git a/static/ico/anime_giko04.gif b/static/ico/anime_giko04.gif new file mode 100644 index 0000000..bab9e77 Binary files /dev/null and b/static/ico/anime_giko04.gif differ diff --git a/static/ico/anime_giko10.gif b/static/ico/anime_giko10.gif new file mode 100644 index 0000000..c9db6cc Binary files /dev/null and b/static/ico/anime_giko10.gif differ diff --git a/static/ico/anime_giko11.gif b/static/ico/anime_giko11.gif new file mode 100644 index 0000000..80af838 Binary files /dev/null and b/static/ico/anime_giko11.gif differ diff --git a/static/ico/anime_giko12.gif b/static/ico/anime_giko12.gif new file mode 100644 index 0000000..201d60c Binary files /dev/null and b/static/ico/anime_giko12.gif differ diff --git a/static/ico/anime_giko13.gif b/static/ico/anime_giko13.gif new file mode 100644 index 0000000..446bed8 Binary files /dev/null and b/static/ico/anime_giko13.gif differ diff --git a/static/ico/anime_hossyu01.gif b/static/ico/anime_hossyu01.gif new file mode 100644 index 0000000..66be979 Binary files /dev/null and b/static/ico/anime_hossyu01.gif differ diff --git a/static/ico/anime_imanouchi01.gif b/static/ico/anime_imanouchi01.gif new file mode 100644 index 0000000..d3eacf5 Binary files /dev/null and b/static/ico/anime_imanouchi01.gif differ diff --git a/static/ico/anime_iyou02.gif b/static/ico/anime_iyou02.gif new file mode 100644 index 0000000..1f3216c Binary files /dev/null and b/static/ico/anime_iyou02.gif differ diff --git a/static/ico/anime_jien01.gif b/static/ico/anime_jien01.gif new file mode 100644 index 0000000..bd2d8ed Binary files /dev/null and b/static/ico/anime_jien01.gif differ diff --git a/static/ico/anime_jien02.gif b/static/ico/anime_jien02.gif new file mode 100644 index 0000000..51d5393 Binary files /dev/null and b/static/ico/anime_jien02.gif differ diff --git a/static/ico/anime_jien03.gif b/static/ico/anime_jien03.gif new file mode 100644 index 0000000..2e59a55 Binary files /dev/null and b/static/ico/anime_jien03.gif differ diff --git a/static/ico/anime_jyorujyu01.gif b/static/ico/anime_jyorujyu01.gif new file mode 100644 index 0000000..6e3bca8 Binary files /dev/null and b/static/ico/anime_jyorujyu01.gif differ diff --git a/static/ico/anime_jyorujyu02.gif b/static/ico/anime_jyorujyu02.gif new file mode 100644 index 0000000..5d13a89 Binary files /dev/null and b/static/ico/anime_jyorujyu02.gif differ diff --git a/static/ico/anime_jyorujyu03.gif b/static/ico/anime_jyorujyu03.gif new file mode 100644 index 0000000..5034286 Binary files /dev/null and b/static/ico/anime_jyorujyu03.gif differ diff --git a/static/ico/anime_kukkuru01.gif b/static/ico/anime_kukkuru01.gif new file mode 100644 index 0000000..7a817cd Binary files /dev/null and b/static/ico/anime_kukkuru01.gif differ diff --git a/static/ico/anime_kuma01.gif b/static/ico/anime_kuma01.gif new file mode 100644 index 0000000..5c1cbae Binary files /dev/null and b/static/ico/anime_kuma01.gif differ diff --git a/static/ico/anime_kumaface01.gif b/static/ico/anime_kumaface01.gif new file mode 100644 index 0000000..e6027fc Binary files /dev/null and b/static/ico/anime_kumaface01.gif differ diff --git a/static/ico/anime_loop.gif b/static/ico/anime_loop.gif new file mode 100644 index 0000000..19f2e9b Binary files /dev/null and b/static/ico/anime_loop.gif differ diff --git a/static/ico/anime_marara02.gif b/static/ico/anime_marara02.gif new file mode 100644 index 0000000..7d3fb7f Binary files /dev/null and b/static/ico/anime_marara02.gif differ diff --git a/static/ico/anime_matanki01.gif b/static/ico/anime_matanki01.gif new file mode 100644 index 0000000..7ab5b77 Binary files /dev/null and b/static/ico/anime_matanki01.gif differ diff --git a/static/ico/anime_matanki02.gif b/static/ico/anime_matanki02.gif new file mode 100644 index 0000000..342eca3 Binary files /dev/null and b/static/ico/anime_matanki02.gif differ diff --git a/static/ico/anime_miruna01.gif b/static/ico/anime_miruna01.gif new file mode 100644 index 0000000..85e1c5d Binary files /dev/null and b/static/ico/anime_miruna01.gif differ diff --git a/static/ico/anime_monar02.gif b/static/ico/anime_monar02.gif new file mode 100644 index 0000000..c8bfdfc Binary files /dev/null and b/static/ico/anime_monar02.gif differ diff --git a/static/ico/anime_monar03.gif b/static/ico/anime_monar03.gif new file mode 100644 index 0000000..b3e061c Binary files /dev/null and b/static/ico/anime_monar03.gif differ diff --git a/static/ico/anime_monar05.gif b/static/ico/anime_monar05.gif new file mode 100644 index 0000000..4d934fb Binary files /dev/null and b/static/ico/anime_monar05.gif differ diff --git a/static/ico/anime_morara01.gif b/static/ico/anime_morara01.gif new file mode 100644 index 0000000..e9d4808 Binary files /dev/null and b/static/ico/anime_morara01.gif differ diff --git a/static/ico/anime_morara02.gif b/static/ico/anime_morara02.gif new file mode 100644 index 0000000..0cf4f97 Binary files /dev/null and b/static/ico/anime_morara02.gif differ diff --git a/static/ico/anime_morara04.gif b/static/ico/anime_morara04.gif new file mode 100644 index 0000000..846d642 Binary files /dev/null and b/static/ico/anime_morara04.gif differ diff --git a/static/ico/anime_nokar01.gif b/static/ico/anime_nokar01.gif new file mode 100644 index 0000000..89ea5bb Binary files /dev/null and b/static/ico/anime_nokar01.gif differ diff --git a/static/ico/anime_okashi01.gif b/static/ico/anime_okashi01.gif new file mode 100644 index 0000000..5e4e518 Binary files /dev/null and b/static/ico/anime_okashi01.gif differ diff --git a/static/ico/anime_okashi02.gif b/static/ico/anime_okashi02.gif new file mode 100644 index 0000000..6ba6ec3 Binary files /dev/null and b/static/ico/anime_okashi02.gif differ diff --git a/static/ico/anime_onigiri04.gif b/static/ico/anime_onigiri04.gif new file mode 100644 index 0000000..78f3f66 Binary files /dev/null and b/static/ico/anime_onigiri04.gif differ diff --git a/static/ico/anime_saitama01.gif b/static/ico/anime_saitama01.gif new file mode 100644 index 0000000..b36dcb5 Binary files /dev/null and b/static/ico/anime_saitama01.gif differ diff --git a/static/ico/anime_saitama02.gif b/static/ico/anime_saitama02.gif new file mode 100644 index 0000000..0a81ff2 Binary files /dev/null and b/static/ico/anime_saitama02.gif differ diff --git a/static/ico/anime_saitama03.gif b/static/ico/anime_saitama03.gif new file mode 100644 index 0000000..5cf168b Binary files /dev/null and b/static/ico/anime_saitama03.gif differ diff --git a/static/ico/anime_sasuga01.gif b/static/ico/anime_sasuga01.gif new file mode 100644 index 0000000..279d97a Binary files /dev/null and b/static/ico/anime_sasuga01.gif differ diff --git a/static/ico/anime_sasuga03.gif b/static/ico/anime_sasuga03.gif new file mode 100644 index 0000000..047e2b9 Binary files /dev/null and b/static/ico/anime_sasuga03.gif differ diff --git a/static/ico/anime_sasuga04.gif b/static/ico/anime_sasuga04.gif new file mode 100644 index 0000000..0e9f839 Binary files /dev/null and b/static/ico/anime_sasuga04.gif differ diff --git a/static/ico/anime_shii01.gif b/static/ico/anime_shii01.gif new file mode 100644 index 0000000..99cf151 Binary files /dev/null and b/static/ico/anime_shii01.gif differ diff --git a/static/ico/anime_shii02.gif b/static/ico/anime_shii02.gif new file mode 100644 index 0000000..233869b Binary files /dev/null and b/static/ico/anime_shii02.gif differ diff --git a/static/ico/anime_shii03.gif b/static/ico/anime_shii03.gif new file mode 100644 index 0000000..51f3723 Binary files /dev/null and b/static/ico/anime_shii03.gif differ diff --git a/static/ico/anime_syobon01.gif b/static/ico/anime_syobon01.gif new file mode 100644 index 0000000..bcbd7eb Binary files /dev/null and b/static/ico/anime_syobon01.gif differ diff --git a/static/ico/anime_syobon03.gif b/static/ico/anime_syobon03.gif new file mode 100644 index 0000000..02bc032 Binary files /dev/null and b/static/ico/anime_syobon03.gif differ diff --git a/static/ico/anime_tarn01.gif b/static/ico/anime_tarn01.gif new file mode 100644 index 0000000..0de9031 Binary files /dev/null and b/static/ico/anime_tarn01.gif differ diff --git a/static/ico/anime_uwan01.gif b/static/ico/anime_uwan01.gif new file mode 100644 index 0000000..8945d5a Binary files /dev/null and b/static/ico/anime_uwan01.gif differ diff --git a/static/ico/anime_uwan02.gif b/static/ico/anime_uwan02.gif new file mode 100644 index 0000000..c4e5c2d Binary files /dev/null and b/static/ico/anime_uwan02.gif differ diff --git a/static/ico/anime_uwan03.gif b/static/ico/anime_uwan03.gif new file mode 100644 index 0000000..7ec0b3e Binary files /dev/null and b/static/ico/anime_uwan03.gif differ diff --git a/static/ico/anime_youkanman01.gif b/static/ico/anime_youkanman01.gif new file mode 100644 index 0000000..8706427 Binary files /dev/null and b/static/ico/anime_youkanman01.gif differ diff --git a/static/ico/anime_youkanman02.gif b/static/ico/anime_youkanman02.gif new file mode 100644 index 0000000..6c3862a Binary files /dev/null and b/static/ico/anime_youkanman02.gif differ diff --git a/static/ico/anime_youkanman03.gif b/static/ico/anime_youkanman03.gif new file mode 100644 index 0000000..a5973f6 Binary files /dev/null and b/static/ico/anime_youkanman03.gif differ diff --git a/static/ico/anime_zonu01.gif b/static/ico/anime_zonu01.gif new file mode 100644 index 0000000..964ed8c Binary files /dev/null and b/static/ico/anime_zonu01.gif differ diff --git a/static/ico/anime_zonu02.gif b/static/ico/anime_zonu02.gif new file mode 100644 index 0000000..70d4572 Binary files /dev/null and b/static/ico/anime_zonu02.gif differ diff --git a/static/ico/aramaki.gif b/static/ico/aramaki.gif new file mode 100644 index 0000000..b3f6420 Binary files /dev/null and b/static/ico/aramaki.gif differ diff --git a/static/ico/aroeri-na32.gif b/static/ico/aroeri-na32.gif new file mode 100644 index 0000000..e6cf7d6 Binary files /dev/null and b/static/ico/aroeri-na32.gif differ diff --git a/static/ico/asopasomaso.gif b/static/ico/asopasomaso.gif new file mode 100644 index 0000000..2b153e4 Binary files /dev/null and b/static/ico/asopasomaso.gif differ diff --git a/static/ico/bikyakusan32.gif b/static/ico/bikyakusan32.gif new file mode 100644 index 0000000..62f8483 Binary files /dev/null and b/static/ico/bikyakusan32.gif differ diff --git a/static/ico/bs.gif b/static/ico/bs.gif new file mode 100644 index 0000000..25c1f0f Binary files /dev/null and b/static/ico/bs.gif differ diff --git a/static/ico/button1_03.gif b/static/ico/button1_03.gif new file mode 100644 index 0000000..1e29394 Binary files /dev/null and b/static/ico/button1_03.gif differ diff --git a/static/ico/buun.gif b/static/ico/buun.gif new file mode 100644 index 0000000..81f9b62 Binary files /dev/null and b/static/ico/buun.gif differ diff --git a/static/ico/chahan.gif b/static/ico/chahan.gif new file mode 100644 index 0000000..d10116c Binary files /dev/null and b/static/ico/chahan.gif differ diff --git a/static/ico/dokuo1.gif b/static/ico/dokuo1.gif new file mode 100644 index 0000000..70e9a1f Binary files /dev/null and b/static/ico/dokuo1.gif differ diff --git a/static/ico/file2_01.gif b/static/ico/file2_01.gif new file mode 100644 index 0000000..9c88ab0 Binary files /dev/null and b/static/ico/file2_01.gif differ diff --git a/static/ico/fujisan.gif b/static/ico/fujisan.gif new file mode 100644 index 0000000..9e33757 Binary files /dev/null and b/static/ico/fujisan.gif differ diff --git a/static/ico/fuun.gif b/static/ico/fuun.gif new file mode 100644 index 0000000..7576689 Binary files /dev/null and b/static/ico/fuun.gif differ diff --git a/static/ico/gaku.gif b/static/ico/gaku.gif new file mode 100644 index 0000000..667c680 Binary files /dev/null and b/static/ico/gaku.gif differ diff --git a/static/ico/gaku2.gif b/static/ico/gaku2.gif new file mode 100644 index 0000000..6f30a26 Binary files /dev/null and b/static/ico/gaku2.gif differ diff --git a/static/ico/gaku3.gif b/static/ico/gaku3.gif new file mode 100644 index 0000000..685a0fc Binary files /dev/null and b/static/ico/gaku3.gif differ diff --git a/static/ico/gekisya1.gif b/static/ico/gekisya1.gif new file mode 100644 index 0000000..7b2238f Binary files /dev/null and b/static/ico/gekisya1.gif differ diff --git a/static/ico/giko1.gif b/static/ico/giko1.gif new file mode 100644 index 0000000..330a682 Binary files /dev/null and b/static/ico/giko1.gif differ diff --git a/static/ico/gikog_gomibako.gif b/static/ico/gikog_gomibako.gif new file mode 100644 index 0000000..cfdd338 Binary files /dev/null and b/static/ico/gikog_gomibako.gif differ diff --git a/static/ico/gikog_gyunyupack.gif b/static/ico/gikog_gyunyupack.gif new file mode 100644 index 0000000..8e2de6b Binary files /dev/null and b/static/ico/gikog_gyunyupack.gif differ diff --git a/static/ico/gikog_pimiento.gif b/static/ico/gikog_pimiento.gif new file mode 100644 index 0000000..21e5eca Binary files /dev/null and b/static/ico/gikog_pimiento.gif differ diff --git a/static/ico/gikoinu.gif b/static/ico/gikoinu.gif new file mode 100644 index 0000000..d923982 Binary files /dev/null and b/static/ico/gikoinu.gif differ diff --git a/static/ico/gikoneko.gif b/static/ico/gikoneko.gif new file mode 100644 index 0000000..f9e4999 Binary files /dev/null and b/static/ico/gikoneko.gif differ diff --git a/static/ico/gikoneko2.gif b/static/ico/gikoneko2.gif new file mode 100644 index 0000000..54d4647 Binary files /dev/null and b/static/ico/gikoneko2.gif differ diff --git a/static/ico/gikoneko_1.gif b/static/ico/gikoneko_1.gif new file mode 100644 index 0000000..a168dbf Binary files /dev/null and b/static/ico/gikoneko_1.gif differ diff --git a/static/ico/gocchin_face.gif b/static/ico/gocchin_face.gif new file mode 100644 index 0000000..cfde101 Binary files /dev/null and b/static/ico/gocchin_face.gif differ diff --git a/static/ico/gomiopen.gif b/static/ico/gomiopen.gif new file mode 100644 index 0000000..56d9ada Binary files /dev/null and b/static/ico/gomiopen.gif differ diff --git a/static/ico/goo_1.gif b/static/ico/goo_1.gif new file mode 100644 index 0000000..e3c2d93 Binary files /dev/null and b/static/ico/goo_1.gif differ diff --git a/static/ico/goo_3.gif b/static/ico/goo_3.gif new file mode 100644 index 0000000..b47825b Binary files /dev/null and b/static/ico/goo_3.gif differ diff --git a/static/ico/gya-.gif b/static/ico/gya-.gif new file mode 100644 index 0000000..dfb2bd1 Binary files /dev/null and b/static/ico/gya-.gif differ diff --git a/static/ico/hagenin-shuriken.gif b/static/ico/hagenin-shuriken.gif new file mode 100644 index 0000000..51e3f8e Binary files /dev/null and b/static/ico/hagenin-shuriken.gif differ diff --git a/static/ico/hagurumaou.gif b/static/ico/hagurumaou.gif new file mode 100644 index 0000000..06a1969 Binary files /dev/null and b/static/ico/hagurumaou.gif differ diff --git a/static/ico/hikky.gif b/static/ico/hikky.gif new file mode 100644 index 0000000..87e90e7 Binary files /dev/null and b/static/ico/hikky.gif differ diff --git a/static/ico/hikky_xmas_2.gif b/static/ico/hikky_xmas_2.gif new file mode 100644 index 0000000..162b96f Binary files /dev/null and b/static/ico/hikky_xmas_2.gif differ diff --git a/static/ico/hyou.gif b/static/ico/hyou.gif new file mode 100644 index 0000000..0574ff5 Binary files /dev/null and b/static/ico/hyou.gif differ diff --git a/static/ico/iirasan_face.gif b/static/ico/iirasan_face.gif new file mode 100644 index 0000000..83b2462 Binary files /dev/null and b/static/ico/iirasan_face.gif differ diff --git a/static/ico/imanouchi_1.gif b/static/ico/imanouchi_1.gif new file mode 100644 index 0000000..9e242a0 Binary files /dev/null and b/static/ico/imanouchi_1.gif differ diff --git a/static/ico/iyahoo.gif b/static/ico/iyahoo.gif new file mode 100644 index 0000000..3387787 Binary files /dev/null and b/static/ico/iyahoo.gif differ diff --git a/static/ico/iyou.gif b/static/ico/iyou.gif new file mode 100644 index 0000000..bc94072 Binary files /dev/null and b/static/ico/iyou.gif differ diff --git a/static/ico/jisakujien_2.gif b/static/ico/jisakujien_2.gif new file mode 100644 index 0000000..0cc759a Binary files /dev/null and b/static/ico/jisakujien_2.gif differ diff --git a/static/ico/jisakujien_xmas.gif b/static/ico/jisakujien_xmas.gif new file mode 100644 index 0000000..9c1c8c8 Binary files /dev/null and b/static/ico/jisakujien_xmas.gif differ diff --git a/static/ico/kantoku1.gif b/static/ico/kantoku1.gif new file mode 100644 index 0000000..6459dc4 Binary files /dev/null and b/static/ico/kantoku1.gif differ diff --git a/static/ico/kappappa1.gif b/static/ico/kappappa1.gif new file mode 100644 index 0000000..e182e84 Binary files /dev/null and b/static/ico/kappappa1.gif differ diff --git a/static/ico/kasa-ri.gif b/static/ico/kasa-ri.gif new file mode 100644 index 0000000..26fde75 Binary files /dev/null and b/static/ico/kasa-ri.gif differ diff --git a/static/ico/kashiwamo-chi32.gif b/static/ico/kashiwamo-chi32.gif new file mode 100644 index 0000000..5d99a57 Binary files /dev/null and b/static/ico/kashiwamo-chi32.gif differ diff --git a/static/ico/kinokorusensei32.gif b/static/ico/kinokorusensei32.gif new file mode 100644 index 0000000..e315517 Binary files /dev/null and b/static/ico/kinokorusensei32.gif differ diff --git a/static/ico/kita_.gif b/static/ico/kita_.gif new file mode 100644 index 0000000..b953217 Binary files /dev/null and b/static/ico/kita_.gif differ diff --git a/static/ico/kodomona.gif b/static/ico/kodomona.gif new file mode 100644 index 0000000..9998fb8 Binary files /dev/null and b/static/ico/kodomona.gif differ diff --git a/static/ico/konkon_folder.gif b/static/ico/konkon_folder.gif new file mode 100644 index 0000000..7a1f3c6 Binary files /dev/null and b/static/ico/konkon_folder.gif differ diff --git a/static/ico/kossorisan.gif b/static/ico/kossorisan.gif new file mode 100644 index 0000000..96e177c Binary files /dev/null and b/static/ico/kossorisan.gif differ diff --git a/static/ico/kotatu.gif b/static/ico/kotatu.gif new file mode 100644 index 0000000..2b0fa89 Binary files /dev/null and b/static/ico/kotatu.gif differ diff --git a/static/ico/kuma.gif b/static/ico/kuma.gif new file mode 100644 index 0000000..453e2c3 Binary files /dev/null and b/static/ico/kuma.gif differ diff --git a/static/ico/kuma2.gif b/static/ico/kuma2.gif new file mode 100644 index 0000000..a3e7109 Binary files /dev/null and b/static/ico/kuma2.gif differ diff --git a/static/ico/maimai.gif b/static/ico/maimai.gif new file mode 100644 index 0000000..0a37a4f Binary files /dev/null and b/static/ico/maimai.gif differ diff --git a/static/ico/makotan2_folder.gif b/static/ico/makotan2_folder.gif new file mode 100644 index 0000000..ea6996c Binary files /dev/null and b/static/ico/makotan2_folder.gif differ diff --git a/static/ico/mona.gif b/static/ico/mona.gif new file mode 100644 index 0000000..2163e99 Binary files /dev/null and b/static/ico/mona.gif differ diff --git a/static/ico/mona_shiri.gif b/static/ico/mona_shiri.gif new file mode 100644 index 0000000..f1c209a Binary files /dev/null and b/static/ico/mona_shiri.gif differ diff --git a/static/ico/mona_tya.gif b/static/ico/mona_tya.gif new file mode 100644 index 0000000..ae5feb6 Binary files /dev/null and b/static/ico/mona_tya.gif differ diff --git a/static/ico/monaazarashi_1.gif b/static/ico/monaazarashi_1.gif new file mode 100644 index 0000000..b6c09ca Binary files /dev/null and b/static/ico/monaazarashi_1.gif differ diff --git a/static/ico/namaetukenai.gif b/static/ico/namaetukenai.gif new file mode 100644 index 0000000..a381eba Binary files /dev/null and b/static/ico/namaetukenai.gif differ diff --git a/static/ico/naoruyo.gif b/static/ico/naoruyo.gif new file mode 100644 index 0000000..0dc9c83 Binary files /dev/null and b/static/ico/naoruyo.gif differ diff --git a/static/ico/nida.gif b/static/ico/nida.gif new file mode 100644 index 0000000..8c383b6 Binary files /dev/null and b/static/ico/nida.gif differ diff --git a/static/ico/nigete.gif b/static/ico/nigete.gif new file mode 100644 index 0000000..271dfb1 Binary files /dev/null and b/static/ico/nigete.gif differ diff --git a/static/ico/nono_ie.gif b/static/ico/nono_ie.gif new file mode 100644 index 0000000..302971b Binary files /dev/null and b/static/ico/nono_ie.gif differ diff --git a/static/ico/nurupo_ga_2.gif b/static/ico/nurupo_ga_2.gif new file mode 100644 index 0000000..4cc8611 Binary files /dev/null and b/static/ico/nurupo_ga_2.gif differ diff --git a/static/ico/onigiri_seito.gif b/static/ico/onigiri_seito.gif new file mode 100644 index 0000000..9be7160 Binary files /dev/null and b/static/ico/onigiri_seito.gif differ diff --git a/static/ico/otiketu48.gif b/static/ico/otiketu48.gif new file mode 100644 index 0000000..3787378 Binary files /dev/null and b/static/ico/otiketu48.gif differ diff --git a/static/ico/pc3.gif b/static/ico/pc3.gif new file mode 100644 index 0000000..a4ddc7d Binary files /dev/null and b/static/ico/pc3.gif differ diff --git a/static/ico/pgya.gif b/static/ico/pgya.gif new file mode 100644 index 0000000..edfad21 Binary files /dev/null and b/static/ico/pgya.gif differ diff --git a/static/ico/sasuga1.gif b/static/ico/sasuga1.gif new file mode 100644 index 0000000..1f8bfd9 Binary files /dev/null and b/static/ico/sasuga1.gif differ diff --git a/static/ico/seito_2.gif b/static/ico/seito_2.gif new file mode 100644 index 0000000..3ff3e3c Binary files /dev/null and b/static/ico/seito_2.gif differ diff --git a/static/ico/soon.gif b/static/ico/soon.gif new file mode 100644 index 0000000..95e4d74 Binary files /dev/null and b/static/ico/soon.gif differ diff --git a/static/ico/tasukete.gif b/static/ico/tasukete.gif new file mode 100644 index 0000000..9e4fe3a Binary files /dev/null and b/static/ico/tasukete.gif differ diff --git a/static/ico/torimasu1.gif b/static/ico/torimasu1.gif new file mode 100644 index 0000000..64fd5fe Binary files /dev/null and b/static/ico/torimasu1.gif differ diff --git a/static/ico/torimasu2.gif b/static/ico/torimasu2.gif new file mode 100644 index 0000000..e3ec154 Binary files /dev/null and b/static/ico/torimasu2.gif differ diff --git a/static/ico/u_ame.gif b/static/ico/u_ame.gif new file mode 100644 index 0000000..1369356 Binary files /dev/null and b/static/ico/u_ame.gif differ diff --git a/static/ico/u_hoshi.gif b/static/ico/u_hoshi.gif new file mode 100644 index 0000000..6b8adbd Binary files /dev/null and b/static/ico/u_hoshi.gif differ diff --git a/static/ico/u_naoruyo_bath.gif b/static/ico/u_naoruyo_bath.gif new file mode 100644 index 0000000..def8ca6 Binary files /dev/null and b/static/ico/u_naoruyo_bath.gif differ diff --git a/static/ico/u_okotowari_a.gif b/static/ico/u_okotowari_a.gif new file mode 100644 index 0000000..ed43164 Binary files /dev/null and b/static/ico/u_okotowari_a.gif differ diff --git a/static/ico/u_sofa.gif b/static/ico/u_sofa.gif new file mode 100644 index 0000000..783aa98 Binary files /dev/null and b/static/ico/u_sofa.gif differ diff --git a/static/ico/wakannai1.gif b/static/ico/wakannai1.gif new file mode 100644 index 0000000..eeecb33 Binary files /dev/null and b/static/ico/wakannai1.gif differ diff --git a/static/ico/yakimochi.gif b/static/ico/yakimochi.gif new file mode 100644 index 0000000..8652360 Binary files /dev/null and b/static/ico/yakimochi.gif differ diff --git a/static/ico/youkan.gif b/static/ico/youkan.gif new file mode 100644 index 0000000..d1c386e Binary files /dev/null and b/static/ico/youkan.gif differ diff --git a/static/ico/zonu_1.gif b/static/ico/zonu_1.gif new file mode 100644 index 0000000..816c451 Binary files /dev/null and b/static/ico/zonu_1.gif differ diff --git a/static/ico/zuzagiko48.gif b/static/ico/zuzagiko48.gif new file mode 100644 index 0000000..c4dd620 Binary files /dev/null and b/static/ico/zuzagiko48.gif differ diff --git a/static/img/anarkia.jpg b/static/img/anarkia.jpg new file mode 100644 index 0000000..43db329 Binary files /dev/null and b/static/img/anarkia.jpg differ diff --git a/static/img/bai.jpg b/static/img/bai.jpg new file mode 100644 index 0000000..ac41b4d Binary files /dev/null and b/static/img/bai.jpg differ diff --git a/static/img/cero.gif b/static/img/cero.gif new file mode 100644 index 0000000..9ab0f0f Binary files /dev/null and b/static/img/cero.gif differ diff --git a/static/img/default.png b/static/img/default.png new file mode 100644 index 0000000..9cd9b93 Binary files /dev/null and b/static/img/default.png differ diff --git a/static/img/juegos1.jpg b/static/img/juegos1.jpg new file mode 100644 index 0000000..b908128 Binary files /dev/null and b/static/img/juegos1.jpg differ diff --git a/static/img/juegos2.jpg b/static/img/juegos2.jpg new file mode 100644 index 0000000..0cc9cc5 Binary files /dev/null and b/static/img/juegos2.jpg differ diff --git a/static/img/juegos3.png b/static/img/juegos3.png new file mode 100644 index 0000000..685a3d0 Binary files /dev/null and b/static/img/juegos3.png differ diff --git a/static/img/juegos4.gif b/static/img/juegos4.gif new file mode 100644 index 0000000..40aca15 Binary files /dev/null and b/static/img/juegos4.gif differ diff --git a/static/img/letras1.png b/static/img/letras1.png new file mode 100644 index 0000000..719de0d Binary files /dev/null and b/static/img/letras1.png differ diff --git a/static/img/letras2.png b/static/img/letras2.png new file mode 100644 index 0000000..61affa4 Binary files /dev/null and b/static/img/letras2.png differ diff --git a/static/img/letras3.png b/static/img/letras3.png new file mode 100644 index 0000000..78183be Binary files /dev/null and b/static/img/letras3.png differ diff --git a/static/img/letras4.jpg b/static/img/letras4.jpg new file mode 100644 index 0000000..32c5ff6 Binary files /dev/null and b/static/img/letras4.jpg differ diff --git a/static/img/letras5.jpg b/static/img/letras5.jpg new file mode 100644 index 0000000..61128bc Binary files /dev/null and b/static/img/letras5.jpg differ diff --git a/static/img/musica1.jpg b/static/img/musica1.jpg new file mode 100644 index 0000000..3cd141d Binary files /dev/null and b/static/img/musica1.jpg differ diff --git a/static/img/noticias.png b/static/img/noticias.png new file mode 100644 index 0000000..1ee2187 Binary files /dev/null and b/static/img/noticias.png differ diff --git a/static/img/old/2d_1.jpg b/static/img/old/2d_1.jpg new file mode 100644 index 0000000..01216b3 Binary files /dev/null and b/static/img/old/2d_1.jpg differ diff --git a/static/img/old/2d_2.jpg b/static/img/old/2d_2.jpg new file mode 100644 index 0000000..dd9c234 Binary files /dev/null and b/static/img/old/2d_2.jpg differ diff --git a/static/img/old/2d_3.png b/static/img/old/2d_3.png new file mode 100644 index 0000000..034cf1e Binary files /dev/null and b/static/img/old/2d_3.png differ diff --git a/static/img/old/2d_4.jpg b/static/img/old/2d_4.jpg new file mode 100644 index 0000000..7f5c7fe Binary files /dev/null and b/static/img/old/2d_4.jpg differ diff --git a/static/img/old/argentina1.png b/static/img/old/argentina1.png new file mode 100644 index 0000000..4dc22b6 Binary files /dev/null and b/static/img/old/argentina1.png differ diff --git a/static/img/old/chile1.png b/static/img/old/chile1.png new file mode 100644 index 0000000..37bda0b Binary files /dev/null and b/static/img/old/chile1.png differ diff --git a/static/img/old/chile2.jpg b/static/img/old/chile2.jpg new file mode 100644 index 0000000..558212a Binary files /dev/null and b/static/img/old/chile2.jpg differ diff --git a/static/img/old/g0.jpg b/static/img/old/g0.jpg new file mode 100644 index 0000000..b70c449 Binary files /dev/null and b/static/img/old/g0.jpg differ diff --git a/static/img/old/g1.jpg b/static/img/old/g1.jpg new file mode 100644 index 0000000..30315c9 Binary files /dev/null and b/static/img/old/g1.jpg differ diff --git a/static/img/old/g2.jpg b/static/img/old/g2.jpg new file mode 100644 index 0000000..c073028 Binary files /dev/null and b/static/img/old/g2.jpg differ diff --git a/static/img/old/g3.jpg b/static/img/old/g3.jpg new file mode 100644 index 0000000..9686553 Binary files /dev/null and b/static/img/old/g3.jpg differ diff --git a/static/img/old/g4.jpg b/static/img/old/g4.jpg new file mode 100644 index 0000000..f49404b Binary files /dev/null and b/static/img/old/g4.jpg differ diff --git a/static/img/old/g5.jpg b/static/img/old/g5.jpg new file mode 100644 index 0000000..959aaaf Binary files /dev/null and b/static/img/old/g5.jpg differ diff --git a/static/img/old/peli.jpg b/static/img/old/peli.jpg new file mode 100644 index 0000000..0b953b9 Binary files /dev/null and b/static/img/old/peli.jpg differ diff --git a/static/img/old/salon2d_3.jpg b/static/img/old/salon2d_3.jpg new file mode 100644 index 0000000..592b04f Binary files /dev/null and b/static/img/old/salon2d_3.jpg differ diff --git a/static/img/old/salon2d_4.png b/static/img/old/salon2d_4.png new file mode 100644 index 0000000..bbcd904 Binary files /dev/null and b/static/img/old/salon2d_4.png differ diff --git a/static/img/old/salon2d_5.jpg b/static/img/old/salon2d_5.jpg new file mode 100644 index 0000000..35151b1 Binary files /dev/null and b/static/img/old/salon2d_5.jpg differ diff --git a/static/img/old/zine.png b/static/img/old/zine.png new file mode 100644 index 0000000..2812b34 Binary files /dev/null and b/static/img/old/zine.png differ diff --git a/static/img/salon2d_1.png b/static/img/salon2d_1.png new file mode 100644 index 0000000..7295a44 Binary files /dev/null and b/static/img/salon2d_1.png differ diff --git a/static/img/salon2d_3.jpg b/static/img/salon2d_3.jpg new file mode 100644 index 0000000..592b04f Binary files /dev/null and b/static/img/salon2d_3.jpg differ diff --git a/static/img/salon2d_4.png b/static/img/salon2d_4.png new file mode 100644 index 0000000..bbcd904 Binary files /dev/null and b/static/img/salon2d_4.png differ diff --git a/static/img/salon2d_5.jpg b/static/img/salon2d_5.jpg new file mode 100644 index 0000000..35151b1 Binary files /dev/null and b/static/img/salon2d_5.jpg differ diff --git a/static/img/tech1.png b/static/img/tech1.png new file mode 100644 index 0000000..3e851c2 Binary files /dev/null and b/static/img/tech1.png differ diff --git a/static/img/tech2.jpg b/static/img/tech2.jpg new file mode 100644 index 0000000..cd982ff Binary files /dev/null and b/static/img/tech2.jpg differ diff --git a/static/img/tech3.png b/static/img/tech3.png new file mode 100644 index 0000000..b7ad99d Binary files /dev/null and b/static/img/tech3.png differ diff --git a/static/img/tech4.jpg b/static/img/tech4.jpg new file mode 100644 index 0000000..d9d959d Binary files /dev/null and b/static/img/tech4.jpg differ diff --git a/static/img/tech5.jpg b/static/img/tech5.jpg new file mode 100644 index 0000000..b19df49 Binary files /dev/null and b/static/img/tech5.jpg differ diff --git a/static/img/tech6.png b/static/img/tech6.png new file mode 100644 index 0000000..32faa9b Binary files /dev/null and b/static/img/tech6.png differ diff --git a/static/img/tv1.png b/static/img/tv1.png new file mode 100644 index 0000000..17ab84b Binary files /dev/null and b/static/img/tv1.png differ diff --git a/static/img/weird-al.jpg b/static/img/weird-al.jpg new file mode 100644 index 0000000..10de1c6 Binary files /dev/null and b/static/img/weird-al.jpg differ diff --git a/static/img/world.gif b/static/img/world.gif new file mode 100644 index 0000000..f6a8d80 Binary files /dev/null and b/static/img/world.gif differ diff --git a/static/img/zonavip1.jpg b/static/img/zonavip1.jpg new file mode 100644 index 0000000..2d8d98f Binary files /dev/null and b/static/img/zonavip1.jpg differ diff --git a/static/img/zonavip2.gif b/static/img/zonavip2.gif new file mode 100644 index 0000000..0e37bae Binary files /dev/null and b/static/img/zonavip2.gif differ diff --git a/static/img/zonavip3.png b/static/img/zonavip3.png new file mode 100644 index 0000000..323e346 Binary files /dev/null and b/static/img/zonavip3.png differ diff --git a/static/img/zonavip4.jpg b/static/img/zonavip4.jpg new file mode 100644 index 0000000..98d0ef4 Binary files /dev/null and b/static/img/zonavip4.jpg differ diff --git a/static/img/zonavip5.gif b/static/img/zonavip5.gif new file mode 100644 index 0000000..dc69964 Binary files /dev/null and b/static/img/zonavip5.gif differ diff --git a/static/img/zonavip6.png b/static/img/zonavip6.png new file mode 100644 index 0000000..aa3443b Binary files /dev/null and b/static/img/zonavip6.png differ diff --git a/static/img/zonavip7.gif b/static/img/zonavip7.gif new file mode 100644 index 0000000..ff96166 Binary files /dev/null and b/static/img/zonavip7.gif differ diff --git a/static/img/zonavip8.png b/static/img/zonavip8.png new file mode 100644 index 0000000..847ad9a Binary files /dev/null and b/static/img/zonavip8.png differ diff --git a/static/img/zonavip9.gif b/static/img/zonavip9.gif new file mode 100644 index 0000000..ba636df Binary files /dev/null and b/static/img/zonavip9.gif differ diff --git a/static/img/zonavip9.jpg b/static/img/zonavip9.jpg new file mode 100644 index 0000000..9590b48 Binary files /dev/null and b/static/img/zonavip9.jpg differ diff --git a/static/img/zonavip_halloween.jpg b/static/img/zonavip_halloween.jpg new file mode 100644 index 0000000..674792f Binary files /dev/null and b/static/img/zonavip_halloween.jpg differ diff --git a/static/img/zonavip_nav.jpg b/static/img/zonavip_nav.jpg new file mode 100644 index 0000000..506abf9 Binary files /dev/null and b/static/img/zonavip_nav.jpg differ diff --git a/static/js/aquiencitas.js b/static/js/aquiencitas.js new file mode 100644 index 0000000..0cf860f --- /dev/null +++ b/static/js/aquiencitas.js @@ -0,0 +1,168 @@ +var cur_url; +var linklist; +var linki; +var is_bbs; +var plimit = 5; +function getPostRange(t, n) { + var posts, replies, s, ss, ee, rev = false; + posts = []; + replies = t.getElementsByClassName("reply"); + s = n.split('-'); + ss = parseInt(s[0]); + ee = ss; + if(s.length == 2) ee = parseInt(s[1]); + if(ee ee) break; + if(num >= ss && num <= ee) { + if(rev) posts.unshift(replies[j]); + else posts.push(replies[j]); + } + } + return posts; +} +function findAncestor (el) { + while ((el = el.parentElement) && !el.className.startsWith("thread") && !el.className.startsWith("cont")); + return el; +} +function getPostDivs(e) { + if(is_bbs) { + divs = []; + t = findAncestor(e); + s = e.getAttribute('href').split('/'); + r = s[s.length-1]; + rs = r.split(','); + linki = 0; + for(i=0;i maxWidth) { + width = maxWidth; + } + + for(i=0;i>")) continue; + + if(localStorage.getItem("shobon_preview") != "false") { + q.addEventListener('mouseover', who_are_you_quoting, false); + q.addEventListener('mouseout', remove_quote_preview, false); + } + + if(localStorage.getItem("shobon_backlink") != "false") { + fill_links(q); + } + } + } +/* if (document.body.className === "threadpage") { + for (x = 0; x < replies.length; x++) { + var q = replies[x].getElementsByTagName("a"); + for(var j=0;j>")) q[j].addEventListener("click", goTo, false); + } + } + }*/ +} +document.addEventListener('DOMContentLoaded', quotePreview, false); \ No newline at end of file diff --git a/static/js/autorefresh.js b/static/js/autorefresh.js new file mode 100644 index 0000000..0ed3e06 --- /dev/null +++ b/static/js/autorefresh.js @@ -0,0 +1,275 @@ +var lastTime = 0; +var refreshInterval; +var refreshMaxTime = 30; +var refreshTime; +var manual = 0; +var serviceType = 0; // 2 = BBS, 3 = IB +var thread_length = 0; +var thread_lastreply = 0; +var thread_title = ""; +var thread_first_length = 0; +var http_request = new XMLHttpRequest(); + +function checkNew(e) { + e.preventDefault(); + manual = 1; + loadJSON(); + if (chk.checked) refreshMaxTime = 25; +} + +function loadJSON() { + if (chk.checked) + stopCounter("..."); + if (manual) + document.getElementById("counter").innerText = "..."; + var data_file; + if (serviceType == 2 || serviceType == 3) { + board = document.getElementsByName("board")[0].value; + parent = document.getElementsByName("parent")[0].value; + data_file = "/cgi/api/thread?dir=" + board + "&id=" + parent + "&offset=" + thread_length + "&time=" + lastTime; + } else { + return false; + } + http_request.open("GET", data_file, true); + http_request.send(); +} + +function updateThread(posts, total_replies, serverTime) { + thread_div = document.getElementsByClassName("thread")[0]; + if (serviceType == 2) + last_elem = document.getElementsByClassName("size")[0]; + else + last_elem = document.getElementsByClassName("cut")[0]; + + for (var i = 0; i < posts.length; i++) { + post = posts[i]; + var div = document.createElement('div'); + if (serviceType == 2) div.className = "reply"; + else div.className = "replycont"; + if (post.email) { + if (post.tripcode) s_name = '
    ' + post.name + ' ' + post.tripcode + ''; + else s_name = '' + post.name + ''; + } else { + if (post.tripcode) s_name = '' + post.name + ' ' + post.tripcode + ''; + else s_name = '' + post.name + ''; + } + if (serviceType == 2) { + if (post.file) { + s_img = '
    ' + Math.round(post.file_size/1024) + 'KB ' + post.file.substring(post.file.lastIndexOf(".")+1, post.file.length).toUpperCase() + '
    '; + } else s_img = ''; + if (post.IS_DELETED == 1) div.innerHTML = '

    ' + (thread_length + i + 1) + ' : Mensaje eliminado por el usuario.

    '; + else if (post.IS_DELETED == 2) div.innerHTML = '

    ' + (thread_length + i + 1) + ' : Mensaje eliminado por miembro del staff.

    '; + else + div.innerHTML = '

    ' + (thread_length + i + 1) + ' : ' + s_name + ' : ' + post.timestamp_formatted + ' rep del

    ' + s_img + '
    ' + post.message + '
    '; + } else { + if (post.file) { + if (post.image_width != 0) { + s_img = '
    ' + post.file + '-(' + post.file_size+ ' B, ' + post.image_width + 'x' + post.image_height + ')
    '; + } else { + s_img = '
    ' + post.file + '-(' + post.file_size+ ' B)
    '; + } + s_img += '' + post.id + ''; + s_msg = '
    ' + post.message + '
    '; + } else { + s_img = ''; + s_msg = '
    ' + post.message + '
    '; + } + if (post.IS_DELETED == 0) { + div.innerHTML = '
    …
    ' + (post.subject ? (' ' + post.subject + '') : '') + ' ' + s_name + ' ' + '' + post.timestamp_formatted + ' No.' + post.id + ' rep
    ' + s_img + s_msg + '
    '; + } + } + + thread_div.insertBefore(div, last_elem); + thread_div.setAttribute("data-length",(thread_length + i + 1)); + if (serviceType == 2) + document.getElementsByTagName("h3")[0].getElementsByTagName("span")[0].innerText = "(" + (thread_length + i + 1) + " respuestas)"; + } + + if (posts.length > 0) { + if (!manual) + refreshMaxTime = 10; + if (!document.hasFocus()) + if (posts.length > 1) + notif(thread_title, posts.length + ' nuevos mensajes'); + else + notif(thread_title, 'Un nuevo mensaje'); + } else { + if (refreshMaxTime <= 60) + refreshMaxTime += 5; + } + + thread_length = parseInt(total_replies) + 1; + //document.getElementsByClassName("thread")[0].firstChild.children[0].innerHTML = "("+thread_length+")"; + new_unread = thread_length - thread_first_length; + + if (new_unread) + document.title = "(" + new_unread + ") " + thread_title; + else + document.title = thread_title; +} + +function notif(title, msg) { + var n = new Notification(title, { + body: msg + }); + setTimeout(n.close.bind(n), 10000); +} + +function counter() { + if (refreshTime < 1) { + loadJSON(); + } else { + refreshTime--; + document.getElementById("counter").innerHTML = (refreshTime + 1); + } +} + +function detectService() { + if (document.body.className === "threadpage") { + if (!document.getElementById("n")) return; + thread_title = document.title; + thread_length = parseInt(document.getElementsByClassName("thread")[0].dataset.length); + thread_first_length = thread_length; + replylist = document.getElementsByClassName("reply"); + lastr = replylist[replylist.length - 1].textContent; + thread_lastreply = parseInt(lastr.substr(0, lastr.indexOf(" :"))); + if (thread_length == thread_lastreply) { + serviceType = 2; + document.getElementById("n").addEventListener("click", checkNew); + var footer = document.getElementsByClassName("lastposts")[0]; + var in1 = document.createElement("input"); + in1.id = "autorefresh"; + in1.setAttribute("type", "checkbox"); + in1.addEventListener("click", autoRefresh); + in1.style.display = "none"; + var in2 = document.createElement("label"); + in2.id = "n2"; + in2.setAttribute("for", "autorefresh"); + in2.style.marginRight = "4px"; + in2.style.cursor = "pointer"; + in2.textContent = "Auto refresh"; + var in3 = document.createElement("span"); + in3.id = "counter"; + in3.style.position = "absolute"; + in3.textContent = "OFF"; + footer.appendChild(document.createTextNode(" | ")); + footer.appendChild(in1); + footer.appendChild(in2); + footer.appendChild(in3); + return true; + } else { + return false; + } + } else if (document.body.className === "res") { + serviceType = 3; + thread_title = document.title; + thread_length = parseInt(document.getElementsByClassName("thread")[0].dataset.length); + thread_first_length = thread_length; + replylist = document.getElementsByClassName("thread"); + replylist += document.getElementsByClassName("reply"); + var footer = document.getElementsByClassName("nav")[0]; + var mnl = document.createElement("a"); + mnl.id = "shownew"; + mnl.href = "#"; + mnl.textContent = "Ver nuevos posts"; + var in1 = document.createElement("input"); + in1.id = "autorefresh"; + in1.setAttribute("type", "checkbox"); + in1.addEventListener("click", autoRefresh); + in1.style.display = "none"; + var in2 = document.createElement("label"); + in2.setAttribute("for", "autorefresh"); + in2.style.cursor = "pointer"; + in2.title = "Ver nuevos posts automáticamente"; + in2.textContent = "Auto"; + var in4 = document.createElement("span"); + in4.id = "counter"; + in4.textContent = "OFF"; + footer.appendChild(document.createTextNode(" [")); + footer.appendChild(mnl); + document.getElementById("shownew").addEventListener("click", checkNew); + footer.appendChild(document.createTextNode("] [")); + footer.appendChild(in1); + footer.appendChild(in2); + footer.appendChild(document.createTextNode("] ")); + footer.appendChild(in4); + return true; + } else { + return false; + } +} + +function startCounter() { + refreshTime = refreshMaxTime; + counter(); + refreshInterval = setInterval(counter, 1000); +} + +function stopCounter(str) { + clearInterval(refreshInterval); + document.getElementById("counter").innerHTML = str; +} + +function autoRefresh(e) { + chk_snd = document.getElementById("autosound"); + if (document.getElementById("autorefresh").checked) { + if (chk_snd) + chk_snd.disabled = false; + Notification.requestPermission(); + lastTime = Math.floor(Date.now() / 1000); + refreshTime = refreshMaxTime; + startCounter(); + } else { + if (chk_snd) + document.getElementById("autosound").disabled = true; + stopCounter("OFF"); + } +} + +http_request.onreadystatechange = function() { + if (http_request.readyState == 4) { + var jsonObj = JSON.parse(http_request.responseText); + if (jsonObj.state == "success") { + if (serviceType == 2 || serviceType == 3) + updateThread(jsonObj.posts, jsonObj.total_replies, jsonObj.time); + lastTime = jsonObj.time; + if (chk.checked) + startCounter(); + } + if (!chk.checked) { + document.getElementById("counter").innerText = "OFF"; + } + manual = 0; + } +} +document.addEventListener("DOMContentLoaded", function() { + if (!detectService()) return; + + chk = document.getElementById("autorefresh"); + chk_snd = document.getElementById("autosound"); + + if (localStorage.getItem("autorefresh")) { + document.getElementById("autorefresh").checked = true; + autoRefresh(); + } + if (!chk_snd) return; + if (localStorage.getItem("mainpage_nosound")) + document.getElementById("autosound").checked = false; +}); + +window.addEventListener("unload", function() { + if (!serviceType) return; + + chk = document.getElementById("autorefresh"); + chk_snd = document.getElementById("autosound"); + + if (chk.checked) + localStorage.setItem("autorefresh", true); + else + localStorage.removeItem("autorefresh"); + if (!chk_snd) return; + if (!document.getElementById("autosound").checked) + localStorage.setItem("mainpage_nosound", true); + else + localStorage.removeItem("mainpage_nosound"); +}); \ No newline at end of file diff --git a/static/js/home.js b/static/js/home.js new file mode 100644 index 0000000..0c921ec --- /dev/null +++ b/static/js/home.js @@ -0,0 +1,173 @@ +console.log("%c¡Es calidad BaI!", "font-size: 50px; font-weight: bold;"); + +function set_stylesheet(styletitle) { + opcs.style = styletitle; + parse(); + var links=document.getElementsByTagName("link"); + var found=false; + for(var i=0;i last_t) { + items[i].className += ' urgent'; + dates[i].innerHTML = '
    ' + dates[i].innerHTML; + } + opcs.last = Date.now() / 1000 | 0; + parse(); +} + +var lastTime = 0; +var refreshInterval; +var refreshMaxTime = 30; +var refreshTime; +var unread = {}; +var last_threads = 0; +var last_serverTime = 0; +var http_request = new XMLHttpRequest(); + +function loadJSON() { + stopCounter("..."); + var data_file = "/cgi/api/lastage?time=" + lastTime + "&limit=" + document.getElementById("limit").value; + http_request.open("GET", data_file, true); + http_request.send(); +} + +function setRead(threadId) { + if (threadId in unread) { + unread[threadId] = false; + updatePostList(last_threads, last_serverTime); + } +} + +function updatePostList(threads, serverTime) { + if (refreshMaxTime <= 120) refreshMaxTime += 5; + var arrayLength = threads.length; + if (!arrayLength) return; + + html = ""; + last_threads = threads; + last_serverTime = serverTime; + + var newposts = 0; + var newTitle = "Bienvenido a Internet BBS/IB"; + var new_unread = false; + var news = []; + + for (var i = 0; i < arrayLength; i++) { + thread = threads[i]; + if (thread.bumped >= lastTime) { + unread[thread.id] = true; + news.push('- ' + thread.board_fulln + ': ' + thread.content); + new_unread = true; + } + if (unread[thread.id]) html += ''; + html += '[' + thread.board_name + '] ' + thread.content + ' (' + thread.length + ')'; + if (unread[thread.id]) { + html += ''; + newposts++; + } + } + if (newposts) newTitle = '(' + newposts + ') ' + newTitle; + if (new_unread) { + document.getElementById("newposts").style = "color:red"; + notif('Bienvenido a Internet BBS/IB', 'Hay nuevos mensajes:\n' + news.join('\n')); + refreshMaxTime = 10; + if (document.getElementById('autosound').checked) { + document.getElementById("machina").volume = 0.6; + document.getElementById("machina").play(); + } + } + window.parent.document.title = newTitle; + document.title = newTitle; + document.getElementById("postlist").innerHTML = html; +} + +function notif(title, msg) { + var n = new Notification(title, { body: msg }); + setTimeout(n.close.bind(n), 10000); +} + +function counter() { + if (refreshTime < 1) loadJSON(); + else { + refreshTime--; + document.getElementById("counter").innerHTML = "– " + (refreshTime + 1); + } +} + +function startCounter() { + refreshTime = refreshMaxTime; + counter(); + refreshInterval = setInterval(counter, 1000); +} + +function stopCounter(str) { + clearInterval(refreshInterval); + document.getElementById("counter").innerHTML = str; +} + +function autoRefresh(e) { + if (chk.checked) { + if (chk_snd) chk_snd.disabled = false; + Notification.requestPermission(); + lastTime = Math.floor(Date.now() / 1000); + refreshTime = refreshMaxTime; + startCounter(); + } else { + if (chk_snd) chk_snd.disabled = true; + stopCounter(""); + } +} + +http_request.onreadystatechange = function() { + if (http_request.readyState == 4) { + var jsonObj = JSON.parse(http_request.responseText); + if (jsonObj.state == "success") { + updatePostList(jsonObj.threads, jsonObj.time); + lastTime = jsonObj.time; + if (chk.checked) startCounter(); + } + } +} + +function parse() { localStorage.setItem("home", JSON.stringify(opcs)); } + +document.addEventListener("DOMContentLoaded", function() { + if (localStorage.hasOwnProperty("home")) opcs=JSON.parse(localStorage.getItem("home")); + else { opcs={"style":"IB","auto":false,"sound":false,"last":0}; parse(); } + set_stylesheet(opcs.style); + + var css = document.getElementById("change_style").getElementsByTagName("a"); + for(var j=0;j)[^>]*|#([\w-]*))$/,rsingleTag=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,rmsPrefix=/^-ms-/,rdashAlpha=/-([\da-z])/gi,fcamelCase=function(all,letter){return letter.toUpperCase();},completed=function(){document.removeEventListener("DOMContentLoaded",completed,false);window.removeEventListener("load",completed,false);jQuery.ready();};jQuery.fn=jQuery.prototype={jquery:core_version,constructor:jQuery,init:function(selector,context,rootjQuery){var match,elem;if(!selector){return this;} +if(typeof selector==="string"){if(selector.charAt(0)==="<"&&selector.charAt(selector.length-1)===">"&&selector.length>=3){match=[null,selector,null];}else{match=rquickExpr.exec(selector);} +if(match&&(match[1]||!context)){if(match[1]){context=context instanceof jQuery?context[0]:context;jQuery.merge(this,jQuery.parseHTML(match[1],context&&context.nodeType?context.ownerDocument||context:document,true));if(rsingleTag.test(match[1])&&jQuery.isPlainObject(context)){for(match in context){if(jQuery.isFunction(this[match])){this[match](context[match]);}else{this.attr(match,context[match]);}}} +return this;}else{elem=document.getElementById(match[2]);if(elem&&elem.parentNode){this.length=1;this[0]=elem;} +this.context=document;this.selector=selector;return this;}}else{if(!context||context.jquery){return(context||rootjQuery).find(selector);}else{return this.constructor(context).find(selector);}}}else{if(selector.nodeType){this.context=this[0]=selector;this.length=1;return this;}else{if(jQuery.isFunction(selector)){return rootjQuery.ready(selector);}}} +if(selector.selector!==undefined){this.selector=selector.selector;this.context=selector.context;} +return jQuery.makeArray(selector,this);},selector:"",length:0,toArray:function(){return core_slice.call(this);},get:function(num){return num==null?this.toArray():num<0?this[this.length+num]:this[num];},pushStack:function(elems){var ret=jQuery.merge(this.constructor(),elems);ret.prevObject=this;ret.context=this.context;return ret;},each:function(callback,args){return jQuery.each(this,callback,args);},ready:function(fn){jQuery.ready.promise().done(fn);return this;},slice:function(){return this.pushStack(core_slice.apply(this,arguments));},first:function(){return this.eq(0);},last:function(){return this.eq(-1);},eq:function(i){var len=this.length,j=+i+(i<0?len:0);return this.pushStack(j>=0&&j0){return;} +readyList.resolveWith(document,[jQuery]);if(jQuery.fn.trigger){jQuery(document).trigger("ready").off("ready");}},isFunction:function(obj){return jQuery.type(obj)==="function";},isArray:Array.isArray,isWindow:function(obj){return obj!=null&&obj===obj.window;},isNumeric:function(obj){return!isNaN(parseFloat(obj))&&isFinite(obj);},type:function(obj){if(obj==null){return String(obj);} +return typeof obj==="object"||typeof obj==="function"?class2type[core_toString.call(obj)]||"object":typeof obj;},isPlainObject:function(obj){if(jQuery.type(obj)!=="object"||obj.nodeType||jQuery.isWindow(obj)){return false;} +try{if(obj.constructor&&!core_hasOwn.call(obj.constructor.prototype,"isPrototypeOf")){return false;}}catch(e){return false;} +return true;},isEmptyObject:function(obj){var name;for(name in obj){return false;} +return true;},error:function(msg){throw new Error(msg);},parseHTML:function(data,context,keepScripts){if(!data||typeof data!=="string"){return null;} +if(typeof context==="boolean"){keepScripts=context;context=false;} +context=context||document;var parsed=rsingleTag.exec(data),scripts=!keepScripts&&[];if(parsed){return[context.createElement(parsed[1])];} +parsed=jQuery.buildFragment([data],context,scripts);if(scripts){jQuery(scripts).remove();} +return jQuery.merge([],parsed.childNodes);},parseJSON:JSON.parse,parseXML:function(data){var xml,tmp;if(!data||typeof data!=="string"){return null;} +try{tmp=new DOMParser;xml=tmp.parseFromString(data,"text/xml");}catch(e){xml=undefined;} +if(!xml||xml.getElementsByTagName("parsererror").length){jQuery.error("Invalid XML: "+data);} +return xml;},noop:function(){},globalEval:function(code){var script,indirect=eval;code=jQuery.trim(code);if(code){if(code.indexOf("use strict")===1){script=document.createElement("script");script.text=code;document.head.appendChild(script).parentNode.removeChild(script);}else{indirect(code);}}},camelCase:function(string){return string.replace(rmsPrefix,"ms-").replace(rdashAlpha,fcamelCase);},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toLowerCase()===name.toLowerCase();},each:function(obj,callback,args){var value,i=0,length=obj.length,isArray=isArraylike(obj);if(args){if(isArray){for(;i0&&length-1 in obj);} +rootjQuery=jQuery(document);(function(window,undefined){var i,support,cachedruns,Expr,getText,isXML,compile,outermostContext,sortInput,setDocument,document,docElem,documentIsHTML,rbuggyQSA,rbuggyMatches,matches,contains,expando="sizzle"+ -new Date,preferredDoc=window.document,dirruns=0,done=0,classCache=createCache(),tokenCache=createCache(),compilerCache=createCache(),hasDuplicate=false,sortOrder=function(){return 0;},strundefined=typeof undefined,MAX_NEGATIVE=1<<31,hasOwn={}.hasOwnProperty,arr=[],pop=arr.pop,push_native=arr.push,push=arr.push,slice=arr.slice,indexOf=arr.indexOf||function(elem){var i=0,len=this.length;for(;i+~]|"+whitespace+")"+whitespace+"*"),rsibling=new RegExp(whitespace+"*[+~]"),rattributeQuotes=new RegExp("="+whitespace+"*([^\\]'\"]*)"+ +whitespace+"*\\]","g"),rpseudo=new RegExp(pseudos),ridentifier=new RegExp("^"+identifier+"$"),matchExpr={"ID":new RegExp("^#("+characterEncoding+")"),"CLASS":new RegExp("^\\.("+characterEncoding+")"),"TAG":new RegExp("^("+characterEncoding.replace("w","w*")+")"),"ATTR":new RegExp("^"+attributes),"PSEUDO":new RegExp("^"+pseudos),"CHILD":new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+whitespace+"*(even|odd|(([+-]|)(\\d*)n|)"+whitespace+"*(?:([+-]|)"+whitespace+"*(\\d+)|))"+whitespace+"*\\)|)","i"),"bool":new RegExp("^(?:"+booleans+")$","i"),"needsContext":new RegExp("^"+whitespace+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+whitespace+"*((?:-\\d)?\\d*)"+whitespace+"*\\)|)(?=[^-]|$)","i")},rnative=/^[^{]+\{\s*\[native \w/,rquickExpr=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,rinputs=/^(?:input|select|textarea|button)$/i,rheader=/^h\d$/i,rescape=/'|\\/g,runescape=new RegExp("\\\\([\\da-f]{1,6}"+ +whitespace+"?|("+whitespace+")|.)","ig"),funescape=function(_,escaped,escapedWhitespace){var high="0x"+escaped-65536;return high!==high||escapedWhitespace?escaped:high<0?String.fromCharCode(high+65536):String.fromCharCode(high>>10|55296,high&1023|56320);};try{push.apply(arr=slice.call(preferredDoc.childNodes),preferredDoc.childNodes);arr[preferredDoc.childNodes.length].nodeType;}catch(e){push={apply:arr.length?function(target,els){push_native.apply(target,slice.call(els));}:function(target,els){var j=target.length,i=0;while(target[j++]=els[i++]){} +target.length=j-1;}};} +function Sizzle(selector,context,results,seed){var match,elem,m,nodeType,i,groups,old,nid,newContext,newSelector;if((context?context.ownerDocument||context:preferredDoc)!==document){setDocument(context);} +context=context||document;results=results||[];if(!selector||typeof selector!=="string"){return results;} +if((nodeType=context.nodeType)!==1&&nodeType!==9){return[];} +if(documentIsHTML&&!seed){if(match=rquickExpr.exec(selector)){if(m=match[1]){if(nodeType===9){elem=context.getElementById(m);if(elem&&elem.parentNode){if(elem.id===m){results.push(elem);return results;}}else{return results;}}else{if(context.ownerDocument&&(elem=context.ownerDocument.getElementById(m))&&contains(context,elem)&&elem.id===m){results.push(elem);return results;}}}else{if(match[2]){push.apply(results,context.getElementsByTagName(selector));return results;}else{if((m=match[3])&&support.getElementsByClassName&&context.getElementsByClassName){push.apply(results,context.getElementsByClassName(m));return results;}}}} +if(support.qsa&&(!rbuggyQSA||!rbuggyQSA.test(selector))){nid=old=expando;newContext=context;newSelector=nodeType===9&&selector;if(nodeType===1&&context.nodeName.toLowerCase()!=="object"){groups=tokenize(selector);if(old=context.getAttribute("id")){nid=old.replace(rescape,"\\$&");}else{context.setAttribute("id",nid);} +nid="[id='"+nid+"'] ";i=groups.length;while(i--){groups[i]=nid+toSelector(groups[i]);} +newContext=rsibling.test(selector)&&context.parentNode||context;newSelector=groups.join(",");} +if(newSelector){try{push.apply(results,newContext.querySelectorAll(newSelector));return results;}catch(qsaError){}finally{if(!old){context.removeAttribute("id");}}}}} +return select(selector.replace(rtrim,"$1"),context,results,seed);} +function isNative(fn){return rnative.test(fn+"");} +function createCache(){var keys=[];function cache(key,value){if(keys.push(key+=" ")>Expr.cacheLength){delete cache[keys.shift()];} +return cache[key]=value;} +return cache;} +function markFunction(fn){fn[expando]=true;return fn;} +function assert(fn){var div=document.createElement("div");try{return!!fn(div);}catch(e$0){return false;}finally{if(div.parentNode){div.parentNode.removeChild(div);} +div=null;}} +function addHandle(attrs,handler,test){attrs=attrs.split("|");var current,i=attrs.length,setHandle=test?null:handler;while(i--){if(!(current=Expr.attrHandle[attrs[i]])||current===handler){Expr.attrHandle[attrs[i]]=setHandle;}}} +function boolHandler(elem,name){var val=elem.getAttributeNode(name);return val&&val.specified?val.value:elem[name]===true?name.toLowerCase():null;} +function interpolationHandler(elem,name){return elem.getAttribute(name,name.toLowerCase()==="type"?1:2);} +function valueHandler(elem){if(elem.nodeName.toLowerCase()==="input"){return elem.defaultValue;}} +function siblingCheck(a,b){var cur=b&&a,diff=cur&&a.nodeType===1&&b.nodeType===1&&(~b.sourceIndex||MAX_NEGATIVE)-(~a.sourceIndex||MAX_NEGATIVE);if(diff){return diff;} +if(cur){while(cur=cur.nextSibling){if(cur===b){return-1;}}} +return a?1:-1;} +function createInputPseudo(type){return function(elem){var name=elem.nodeName.toLowerCase();return name==="input"&&elem.type===type;};} +function createButtonPseudo(type){return function(elem){var name=elem.nodeName.toLowerCase();return(name==="input"||name==="button")&&elem.type===type;};} +function createPositionalPseudo(fn){return markFunction(function(argument){argument=+argument;return markFunction(function(seed,matches){var j,matchIndexes=fn([],seed.length,argument),i=matchIndexes.length;while(i--){if(seed[j=matchIndexes[i]]){seed[j]=!(matches[j]=seed[j]);}}});});} +isXML=Sizzle.isXML=function(elem){var documentElement=elem&&(elem.ownerDocument||elem).documentElement;return documentElement?documentElement.nodeName!=="HTML":false;};support=Sizzle.support={};setDocument=Sizzle.setDocument=function(node){var doc=node?node.ownerDocument||node:preferredDoc,parent=doc.parentWindow;if(doc===document||doc.nodeType!==9||!doc.documentElement){return document;} +document=doc;docElem=doc.documentElement;documentIsHTML=!isXML(doc);if(parent&&parent.frameElement){parent.attachEvent("onbeforeunload",function(){setDocument();});} +support.attributes=assert(function(div){div.innerHTML="";addHandle("type|href|height|width",interpolationHandler,div.firstChild.getAttribute("href")==="#");addHandle(booleans,boolHandler,div.getAttribute("disabled")==null);div.className="i";return!div.getAttribute("className");});support.input=assert(function(div){div.innerHTML="";div.firstChild.setAttribute("value","");return div.firstChild.getAttribute("value")==="";});addHandle("value",valueHandler,support.attributes&&support.input);support.getElementsByTagName=assert(function(div){div.appendChild(doc.createComment(""));return!div.getElementsByTagName("*").length;});support.getElementsByClassName=assert(function(div){div.innerHTML="
    ";div.firstChild.className="i";return div.getElementsByClassName("i").length===2;});support.getById=assert(function(div){docElem.appendChild(div).id=expando;return!doc.getElementsByName||!doc.getElementsByName(expando).length;});if(support.getById){Expr.find["ID"]=function(id,context){if(typeof context.getElementById!==strundefined&&documentIsHTML){var m=context.getElementById(id);return m&&m.parentNode?[m]:[];}};Expr.filter["ID"]=function(id){var attrId=id.replace(runescape,funescape);return function(elem){return elem.getAttribute("id")===attrId;};};}else{delete Expr.find["ID"];Expr.filter["ID"]=function(id){var attrId=id.replace(runescape,funescape);return function(elem){var node=typeof elem.getAttributeNode!==strundefined&&elem.getAttributeNode("id");return node&&node.value===attrId;};};} +Expr.find["TAG"]=support.getElementsByTagName?function(tag,context){if(typeof context.getElementsByTagName!==strundefined){return context.getElementsByTagName(tag);}}:function(tag,context){var elem,tmp=[],i=0,results=context.getElementsByTagName(tag);if(tag==="*"){while(elem=results[i++]){if(elem.nodeType===1){tmp.push(elem);}} +return tmp;} +return results;};Expr.find["CLASS"]=support.getElementsByClassName&&function(className,context){if(typeof context.getElementsByClassName!==strundefined&&documentIsHTML){return context.getElementsByClassName(className);}};rbuggyMatches=[];rbuggyQSA=[];if(support.qsa=isNative(doc.querySelectorAll)){assert(function(div){div.innerHTML="";if(!div.querySelectorAll("[selected]").length){rbuggyQSA.push("\\["+whitespace+"*(?:value|"+booleans+")");} +if(!div.querySelectorAll(":checked").length){rbuggyQSA.push(":checked");}});assert(function(div){var input=doc.createElement("input");input.setAttribute("type","hidden");div.appendChild(input).setAttribute("t","");if(div.querySelectorAll("[t^='']").length){rbuggyQSA.push("[*^$]="+whitespace+"*(?:''|\"\")");} +if(!div.querySelectorAll(":enabled").length){rbuggyQSA.push(":enabled",":disabled");} +div.querySelectorAll("*,:x");rbuggyQSA.push(",.*:");});} +if(support.matchesSelector=isNative(matches=docElem.webkitMatchesSelector||docElem.mozMatchesSelector||docElem.oMatchesSelector||docElem.msMatchesSelector)){assert(function(div){support.disconnectedMatch=matches.call(div,"div");matches.call(div,"[s!='']:x");rbuggyMatches.push("!=",pseudos);});} +rbuggyQSA=rbuggyQSA.length&&new RegExp(rbuggyQSA.join("|"));rbuggyMatches=rbuggyMatches.length&&new RegExp(rbuggyMatches.join("|"));contains=isNative(docElem.contains)||docElem.compareDocumentPosition?function(a,b){var adown=a.nodeType===9?a.documentElement:a,bup=b&&b.parentNode;return a===bup||!!(bup&&bup.nodeType===1&&(adown.contains?adown.contains(bup):a.compareDocumentPosition&&a.compareDocumentPosition(bup)&16));}:function(a,b){if(b){while(b=b.parentNode){if(b===a){return true;}}} +return false;};support.sortDetached=assert(function(div1){return div1.compareDocumentPosition(doc.createElement("div"))&1;});sortOrder=docElem.compareDocumentPosition?function(a,b){if(a===b){hasDuplicate=true;return 0;} +var compare=b.compareDocumentPosition&&a.compareDocumentPosition&&a.compareDocumentPosition(b);if(compare){if(compare&1||!support.sortDetached&&b.compareDocumentPosition(a)===compare){if(a===doc||contains(preferredDoc,a)){return-1;} +if(b===doc||contains(preferredDoc,b)){return 1;} +return sortInput?indexOf.call(sortInput,a)-indexOf.call(sortInput,b):0;} +return compare&4?-1:1;} +return a.compareDocumentPosition?-1:1;}:function(a,b){var cur,i=0,aup=a.parentNode,bup=b.parentNode,ap=[a],bp=[b];if(a===b){hasDuplicate=true;return 0;}else{if(!aup||!bup){return a===doc?-1:b===doc?1:aup?-1:bup?1:sortInput?indexOf.call(sortInput,a)-indexOf.call(sortInput,b):0;}else{if(aup===bup){return siblingCheck(a,b);}}} +cur=a;while(cur=cur.parentNode){ap.unshift(cur);} +cur=b;while(cur=cur.parentNode){bp.unshift(cur);} +while(ap[i]===bp[i]){i++;} +return i?siblingCheck(ap[i],bp[i]):ap[i]===preferredDoc?-1:bp[i]===preferredDoc?1:0;};return doc;};Sizzle.matches=function(expr,elements){return Sizzle(expr,null,null,elements);};Sizzle.matchesSelector=function(elem,expr){if((elem.ownerDocument||elem)!==document){setDocument(elem);} +expr=expr.replace(rattributeQuotes,"='$1']");if(support.matchesSelector&&documentIsHTML&&(!rbuggyMatches||!rbuggyMatches.test(expr))&&(!rbuggyQSA||!rbuggyQSA.test(expr))){try{var ret=matches.call(elem,expr);if(ret||support.disconnectedMatch||elem.document&&elem.document.nodeType!==11){return ret;}}catch(e$1){}} +return Sizzle(expr,document,null,[elem]).length>0;};Sizzle.contains=function(context,elem){if((context.ownerDocument||context)!==document){setDocument(context);} +return contains(context,elem);};Sizzle.attr=function(elem,name){if((elem.ownerDocument||elem)!==document){setDocument(elem);} +var fn=Expr.attrHandle[name.toLowerCase()],val=fn&&hasOwn.call(Expr.attrHandle,name.toLowerCase())?fn(elem,name,!documentIsHTML):undefined;return val===undefined?support.attributes||!documentIsHTML?elem.getAttribute(name):(val=elem.getAttributeNode(name))&&val.specified?val.value:null:val;};Sizzle.error=function(msg){throw new Error("Syntax error, unrecognized expression: "+msg);};Sizzle.uniqueSort=function(results){var elem,duplicates=[],j=0,i=0;hasDuplicate=!support.detectDuplicates;sortInput=!support.sortStable&&results.slice(0);results.sort(sortOrder);if(hasDuplicate){while(elem=results[i++]){if(elem===results[i]){j=duplicates.push(i);}} +while(j--){results.splice(duplicates[j],1);}} +return results;};getText=Sizzle.getText=function(elem){var node,ret="",i=0,nodeType=elem.nodeType;if(!nodeType){for(;node=elem[i];i++){ret+=getText(node);}}else{if(nodeType===1||nodeType===9||nodeType===11){if(typeof elem.textContent==="string"){return elem.textContent;}else{for(elem=elem.firstChild;elem;elem=elem.nextSibling){ret+=getText(elem);}}}else{if(nodeType===3||nodeType===4){return elem.nodeValue;}}} +return ret;};Expr=Sizzle.selectors={cacheLength:50,createPseudo:markFunction,match:matchExpr,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:true}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:true},"~":{dir:"previousSibling"}},preFilter:{"ATTR":function(match){match[1]=match[1].replace(runescape,funescape);match[3]=(match[4]||match[5]||"").replace(runescape,funescape);if(match[2]==="~="){match[3]=" "+match[3]+" ";} +return match.slice(0,4);},"CHILD":function(match){match[1]=match[1].toLowerCase();if(match[1].slice(0,3)==="nth"){if(!match[3]){Sizzle.error(match[0]);} +match[4]=+(match[4]?match[5]+(match[6]||1):2*(match[3]==="even"||match[3]==="odd"));match[5]=+(match[7]+match[8]||match[3]==="odd");}else{if(match[3]){Sizzle.error(match[0]);}} +return match;},"PSEUDO":function(match){var excess,unquoted=!match[5]&&match[2];if(matchExpr["CHILD"].test(match[0])){return null;} +if(match[3]&&match[4]!==undefined){match[2]=match[4];}else{if(unquoted&&rpseudo.test(unquoted)&&(excess=tokenize(unquoted,true))&&(excess=unquoted.indexOf(")",unquoted.length-excess)-unquoted.length)){match[0]=match[0].slice(0,excess);match[2]=unquoted.slice(0,excess);}} +return match.slice(0,3);}},filter:{"TAG":function(nodeNameSelector){var nodeName=nodeNameSelector.replace(runescape,funescape).toLowerCase();return nodeNameSelector==="*"?function(){return true;}:function(elem){return elem.nodeName&&elem.nodeName.toLowerCase()===nodeName;};},"CLASS":function(className){var pattern=classCache[className+" "];return pattern||(pattern=new RegExp("(^|"+whitespace+")"+className+"("+whitespace+"|$)"))&&classCache(className,function(elem){return pattern.test(typeof elem.className==="string"&&elem.className||typeof elem.getAttribute!==strundefined&&elem.getAttribute("class")||"");});},"ATTR":function(name,operator,check){return function(elem){var result=Sizzle.attr(elem,name);if(result==null){return operator==="!=";} +if(!operator){return true;} +result+="";return operator==="="?result===check:operator==="!="?result!==check:operator==="^="?check&&result.indexOf(check)===0:operator==="*="?check&&result.indexOf(check)>-1:operator==="$="?check&&result.slice(-check.length)===check:operator==="~="?(" "+result+" ").indexOf(check)>-1:operator==="|="?result===check||result.slice(0,check.length+1)===check+"-":false;};},"CHILD":function(type,what,argument,first,last){var simple=type.slice(0,3)!=="nth",forward=type.slice(-4)!=="last",ofType=what==="of-type";return first===1&&last===0?function(elem){return!!elem.parentNode;}:function(elem,context,xml){var cache,outerCache,node,diff,nodeIndex,start,dir=simple!==forward?"nextSibling":"previousSibling",parent=elem.parentNode,name=ofType&&elem.nodeName.toLowerCase(),useCache=!xml&&!ofType;if(parent){if(simple){while(dir){node=elem;while(node=node[dir]){if(ofType?node.nodeName.toLowerCase()===name:node.nodeType===1){return false;}} +start=dir=type==="only"&&!start&&"nextSibling";} +return true;} +start=[forward?parent.firstChild:parent.lastChild];if(forward&&useCache){outerCache=parent[expando]||(parent[expando]={});cache=outerCache[type]||[];nodeIndex=cache[0]===dirruns&&cache[1];diff=cache[0]===dirruns&&cache[2];node=nodeIndex&&parent.childNodes[nodeIndex];while(node=++nodeIndex&&node&&node[dir]||(diff=nodeIndex=0)||start.pop()){if(node.nodeType===1&&++diff&&node===elem){outerCache[type]=[dirruns,nodeIndex,diff];break;}}}else{if(useCache&&(cache=(elem[expando]||(elem[expando]={}))[type])&&cache[0]===dirruns){diff=cache[1];}else{while(node=++nodeIndex&&node&&node[dir]||(diff=nodeIndex=0)||start.pop()){if((ofType?node.nodeName.toLowerCase()===name:node.nodeType===1)&&++diff){if(useCache){(node[expando]||(node[expando]={}))[type]=[dirruns,diff];} +if(node===elem){break;}}}}} +diff-=last;return diff===first||diff%first===0&&diff / first>=0;}};},"PSEUDO":function(pseudo,argument){var args,fn=Expr.pseudos[pseudo]||Expr.setFilters[pseudo.toLowerCase()]||Sizzle.error("unsupported pseudo: "+pseudo);if(fn[expando]){return fn(argument);} +if(fn.length>1){args=[pseudo,pseudo,"",argument];return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase())?markFunction(function(seed,matches){var idx,matched=fn(seed,argument),i=matched.length;while(i--){idx=indexOf.call(seed,matched[i]);seed[idx]=!(matches[idx]=matched[i]);}}):function(elem){return fn(elem,0,args);};} +return fn;}},pseudos:{"not":markFunction(function(selector){var input=[],results=[],matcher=compile(selector.replace(rtrim,"$1"));return matcher[expando]?markFunction(function(seed,matches,context,xml){var elem,unmatched=matcher(seed,null,xml,[]),i=seed.length;while(i--){if(elem=unmatched[i]){seed[i]=!(matches[i]=elem);}}}):function(elem,context,xml){input[0]=elem;matcher(input,null,xml,results);return!results.pop();};}),"has":markFunction(function(selector){return function(elem){return Sizzle(selector,elem).length>0;};}),"contains":markFunction(function(text){return function(elem){return(elem.textContent||elem.innerText||getText(elem)).indexOf(text)>-1;};}),"lang":markFunction(function(lang){if(!ridentifier.test(lang||"")){Sizzle.error("unsupported lang: "+lang);} +lang=lang.replace(runescape,funescape).toLowerCase();return function(elem){var elemLang;do{if(elemLang=documentIsHTML?elem.lang:elem.getAttribute("xml:lang")||elem.getAttribute("lang")){elemLang=elemLang.toLowerCase();return elemLang===lang||elemLang.indexOf(lang+"-")===0;}}while((elem=elem.parentNode)&&elem.nodeType===1);return false;};}),"target":function(elem){var hash=window.location&&window.location.hash;return hash&&hash.slice(1)===elem.id;},"root":function(elem){return elem===docElem;},"focus":function(elem){return elem===document.activeElement&&(!document.hasFocus||document.hasFocus())&&!!(elem.type||elem.href||~elem.tabIndex);},"enabled":function(elem){return elem.disabled===false;},"disabled":function(elem){return elem.disabled===true;},"checked":function(elem){var nodeName=elem.nodeName.toLowerCase();return nodeName==="input"&&!!elem.checked||nodeName==="option"&&!!elem.selected;},"selected":function(elem){if(elem.parentNode){elem.parentNode.selectedIndex;} +return elem.selected===true;},"empty":function(elem){for(elem=elem.firstChild;elem;elem=elem.nextSibling){if(elem.nodeName>"@"||elem.nodeType===3||elem.nodeType===4){return false;}} +return true;},"parent":function(elem){return!Expr.pseudos["empty"](elem);},"header":function(elem){return rheader.test(elem.nodeName);},"input":function(elem){return rinputs.test(elem.nodeName);},"button":function(elem){var name=elem.nodeName.toLowerCase();return name==="input"&&elem.type==="button"||name==="button";},"text":function(elem){var attr;return elem.nodeName.toLowerCase()==="input"&&elem.type==="text"&&((attr=elem.getAttribute("type"))==null||attr.toLowerCase()===elem.type);},"first":createPositionalPseudo(function(){return[0];}),"last":createPositionalPseudo(function(matchIndexes,length){return[length-1];}),"eq":createPositionalPseudo(function(matchIndexes,length,argument){return[argument<0?argument+length:argument];}),"even":createPositionalPseudo(function(matchIndexes,length){var i=0;for(;i=0;){matchIndexes.push(i);} +return matchIndexes;}),"gt":createPositionalPseudo(function(matchIndexes,length,argument){var i=argument<0?argument+length:argument;for(;++i1?function(elem,context,xml){var i=matchers.length;while(i--){if(!matchers[i](elem,context,xml)){return false;}} +return true;}:matchers[0];} +function condense(unmatched,map,filter,context,xml){var elem,newUnmatched=[],i=0,len=unmatched.length,mapped=map!=null;for(;i-1){seed[temp]=!(results[temp]=elem);}}}}else{matcherOut=condense(matcherOut===results?matcherOut.splice(preexisting,matcherOut.length):matcherOut);if(postFinder){postFinder(null,results,matcherOut,xml);}else{push.apply(results,matcherOut);}}});} +function matcherFromTokens(tokens){var checkContext,matcher,j,len=tokens.length,leadingRelative=Expr.relative[tokens[0].type],implicitRelative=leadingRelative||Expr.relative[" "],i=leadingRelative?1:0,matchContext=addCombinator(function(elem){return elem===checkContext;},implicitRelative,true),matchAnyContext=addCombinator(function(elem){return indexOf.call(checkContext,elem)>-1;},implicitRelative,true),matchers=[function(elem,context,xml){return!leadingRelative&&(xml||context!==outermostContext)||((checkContext=context).nodeType?matchContext(elem,context,xml):matchAnyContext(elem,context,xml));}];for(;i1&&elementMatcher(matchers),i>1&&toSelector(tokens.slice(0,i-1).concat({value:tokens[i-2].type===" "?"*":""})).replace(rtrim,"$1"),matcher,i0,byElement=elementMatchers.length>0,superMatcher=function(seed,context,xml,results,expandContext){var elem,j,matcher,setMatched=[],matchedCount=0,i="0",unmatched=seed&&[],outermost=expandContext!=null,contextBackup=outermostContext,elems=seed||byElement&&Expr.find["TAG"]("*",expandContext&&context.parentNode||context),dirrunsUnique=dirruns+=contextBackup==null?1:Math.random()||.1;if(outermost){outermostContext=context!==document&&context;cachedruns=matcherCachedRuns;} +for(;(elem=elems[i])!=null;i++){if(byElement&&elem){j=0;while(matcher=elementMatchers[j++]){if(matcher(elem,context,xml)){results.push(elem);break;}} +if(outermost){dirruns=dirrunsUnique;cachedruns=++matcherCachedRuns;}} +if(bySet){if(elem=!matcher&&elem){matchedCount--;} +if(seed){unmatched.push(elem);}}} +matchedCount+=i;if(bySet&&i!==matchedCount){j=0;while(matcher=setMatchers[j++]){matcher(unmatched,setMatched,context,xml);} +if(seed){if(matchedCount>0){while(i--){if(!(unmatched[i]||setMatched[i])){setMatched[i]=pop.call(results);}}} +setMatched=condense(setMatched);} +push.apply(results,setMatched);if(outermost&&!seed&&setMatched.length>0&&matchedCount+setMatchers.length>1){Sizzle.uniqueSort(results);}} +if(outermost){dirruns=dirrunsUnique;outermostContext=contextBackup;} +return unmatched;};return bySet?markFunction(superMatcher):superMatcher;} +compile=Sizzle.compile=function(selector,group){var i,setMatchers=[],elementMatchers=[],cached=compilerCache[selector+" "];if(!cached){if(!group){group=tokenize(selector);} +i=group.length;while(i--){cached=matcherFromTokens(group[i]);if(cached[expando]){setMatchers.push(cached);}else{elementMatchers.push(cached);}} +cached=compilerCache(selector,matcherFromGroupMatchers(elementMatchers,setMatchers));} +return cached;};function multipleContexts(selector,contexts,results){var i=0,len=contexts.length;for(;i2&&(token=tokens[0]).type==="ID"&&support.getById&&context.nodeType===9&&documentIsHTML&&Expr.relative[tokens[1].type]){context=(Expr.find["ID"](token.matches[0].replace(runescape,funescape),context)||[])[0];if(!context){return results;} +selector=selector.slice(tokens.shift().value.length);} +i=matchExpr["needsContext"].test(selector)?0:tokens.length;while(i--){token=tokens[i];if(Expr.relative[type=token.type]){break;} +if(find=Expr.find[type]){if(seed=find(token.matches[0].replace(runescape,funescape),rsibling.test(tokens[0].type)&&context.parentNode||context)){tokens.splice(i,1);selector=seed.length&&toSelector(tokens);if(!selector){push.apply(results,seed);return results;} +break;}}}}} +compile(selector,match)(seed,context,!documentIsHTML,results,rsibling.test(selector));return results;} +Expr.pseudos["nth"]=Expr.pseudos["eq"];function setFilters(){} +setFilters.prototype=Expr.filters=Expr.pseudos;Expr.setFilters=new setFilters;support.sortStable=expando.split("").sort(sortOrder).join("")===expando;setDocument();[0,0].sort(sortOrder);support.detectDuplicates=hasDuplicate;jQuery.find=Sizzle;jQuery.expr=Sizzle.selectors;jQuery.expr[":"]=jQuery.expr.pseudos;jQuery.unique=Sizzle.uniqueSort;jQuery.text=Sizzle.getText;jQuery.isXMLDoc=Sizzle.isXML;jQuery.contains=Sizzle.contains;})(window);var optionsCache={};function createOptions(options){var object=optionsCache[options]={};jQuery.each(options.match(core_rnotwhite)||[],function(_,flag){object[flag]=true;});return object;} +jQuery.Callbacks=function(options){options=typeof options==="string"?optionsCache[options]||createOptions(options):jQuery.extend({},options);var memory,fired,firing,firingStart,firingLength,firingIndex,list=[],stack=!options.once&&[],fire=function(data){memory=options.memory&&data;fired=true;firingIndex=firingStart||0;firingStart=0;firingLength=list.length;firing=true;for(;list&&firingIndex-1){list.splice(index,1);if(firing){if(index<=firingLength){firingLength--;} +if(index<=firingIndex){firingIndex--;}}}});} +return this;},has:function(fn){return fn?jQuery.inArray(fn,list)>-1:!!(list&&list.length);},empty:function(){list=[];firingLength=0;return this;},disable:function(){list=stack=memory=undefined;return this;},disabled:function(){return!list;},lock:function(){stack=undefined;if(!memory){self.disable();} +return this;},locked:function(){return!stack;},fireWith:function(context,args){args=args||[];args=[context,args.slice?args.slice():args];if(list&&(!fired||stack)){if(firing){stack.push(args);}else{fire(args);}} +return this;},fire:function(){self.fireWith(this,arguments);return this;},fired:function(){return!!fired;}};return self;};jQuery.extend({Deferred:function(func){var tuples=[["resolve","done",jQuery.Callbacks("once memory"),"resolved"],["reject","fail",jQuery.Callbacks("once memory"),"rejected"],["notify","progress",jQuery.Callbacks("memory")]],state="pending",promise={state:function(){return state;},always:function(){deferred.done(arguments).fail(arguments);return this;},then:function(){var fns=arguments;return jQuery.Deferred(function(newDefer){jQuery.each(tuples,function(i,tuple){var action=tuple[0],fn=jQuery.isFunction(fns[i])&&fns[i];deferred[tuple[1]](function(){var returned=fn&&fn.apply(this,arguments);if(returned&&jQuery.isFunction(returned.promise)){returned.promise().done(newDefer.resolve).fail(newDefer.reject).progress(newDefer.notify);}else{newDefer[action+"With"](this===promise?newDefer.promise():this,fn?[returned]:arguments);}});});fns=null;}).promise();},promise:function(obj){return obj!=null?jQuery.extend(obj,promise):promise;}},deferred={};promise.pipe=promise.then;jQuery.each(tuples,function(i,tuple){var list=tuple[2],stateString=tuple[3];promise[tuple[1]]=list.add;if(stateString){list.add(function(){state=stateString;},tuples[i^1][2].disable,tuples[2][2].lock);} +deferred[tuple[0]]=function(){deferred[tuple[0]+"With"](this===deferred?promise:this,arguments);return this;};deferred[tuple[0]+"With"]=list.fireWith;});promise.promise(deferred);if(func){func.call(deferred,deferred);} +return deferred;},when:function(subordinate){var i=0,resolveValues=core_slice.call(arguments),length=resolveValues.length,remaining=length!==1||subordinate&&jQuery.isFunction(subordinate.promise)?length:0,deferred=remaining===1?subordinate:jQuery.Deferred(),updateFunc=function(i,contexts,values){return function(value){contexts[i]=this;values[i]=arguments.length>1?core_slice.call(arguments):value;if(values===progressValues){deferred.notifyWith(contexts,values);}else{if(!--remaining){deferred.resolveWith(contexts,values);}}};},progressValues,progressContexts,resolveContexts;if(length>1){progressValues=new Array(length);progressContexts=new Array(length);resolveContexts=new Array(length);for(;i1,null,true);},removeData:function(key){return this.each(function(){data_user.remove(this,key);});}});function dataAttr(elem,key,data){var name;if(data===undefined&&elem.nodeType===1){name="data-"+key.replace(rmultiDash,"-$1").toLowerCase();data=elem.getAttribute(name);if(typeof data==="string"){try{data=data==="true"?true:data==="false"?false:data==="null"?null:+data+""===data?+data:rbrace.test(data)?JSON.parse(data):data;}catch(e){} +data_user.set(elem,key,data);}else{data=undefined;}} +return data;} +jQuery.extend({queue:function(elem,type,data){var queue;if(elem){type=(type||"fx")+"queue";queue=data_priv.get(elem,type);if(data){if(!queue||jQuery.isArray(data)){queue=data_priv.access(elem,type,jQuery.makeArray(data));}else{queue.push(data);}} +return queue||[];}},dequeue:function(elem,type){type=type||"fx";var queue=jQuery.queue(elem,type),startLength=queue.length,fn=queue.shift(),hooks=jQuery._queueHooks(elem,type),next=function(){jQuery.dequeue(elem,type);};if(fn==="inprogress"){fn=queue.shift();startLength--;} +if(fn){if(type==="fx"){queue.unshift("inprogress");} +delete hooks.stop;fn.call(elem,next,hooks);} +if(!startLength&&hooks){hooks.empty.fire();}},_queueHooks:function(elem,type){var key=type+"queueHooks";return data_priv.get(elem,key)||data_priv.access(elem,key,{empty:jQuery.Callbacks("once memory").add(function(){data_priv.remove(elem,[type+"queue",key]);})});}});jQuery.fn.extend({queue:function(type,data){var setter=2;if(typeof type!=="string"){data=type;type="fx";setter--;} +if(arguments.length1);},removeAttr:function(name){return this.each(function(){jQuery.removeAttr(this,name);});},prop:function(name,value){return jQuery.access(this,jQuery.prop,name,value,arguments.length>1);},removeProp:function(name){return this.each(function(){delete this[jQuery.propFix[name]||name];});},addClass:function(value){var classes,elem,cur,clazz,j,i=0,len=this.length,proceed=typeof value==="string"&&value;if(jQuery.isFunction(value)){return this.each(function(j){jQuery(this).addClass(value.call(this,j,this.className));});} +if(proceed){classes=(value||"").match(core_rnotwhite)||[];for(;i=0){cur=cur.replace(" "+clazz+" "," ");}} +elem.className=value?jQuery.trim(cur):"";}}} +return this;},toggleClass:function(value,stateVal){var type=typeof value,isBool=typeof stateVal==="boolean";if(jQuery.isFunction(value)){return this.each(function(i){jQuery(this).toggleClass(value.call(this,i,this.className,stateVal),stateVal);});} +return this.each(function(){if(type==="string"){var className,i=0,self=jQuery(this),state=stateVal,classNames=value.match(core_rnotwhite)||[];while(className=classNames[i++]){state=isBool?state:!self.hasClass(className);self[state?"addClass":"removeClass"](className);}}else{if(type===core_strundefined||type==="boolean"){if(this.className){data_priv.set(this,"__className__",this.className);} +this.className=this.className||value===false?"":data_priv.get(this,"__className__")||"";}}});},hasClass:function(selector){var className=" "+selector+" ",i=0,l=this.length;for(;i=0){return true;}} +return false;},val:function(value){var hooks,ret,isFunction,elem=this[0];if(!arguments.length){if(elem){hooks=jQuery.valHooks[elem.type]||jQuery.valHooks[elem.nodeName.toLowerCase()];if(hooks&&"get"in hooks&&(ret=hooks.get(elem,"value"))!==undefined){return ret;} +ret=elem.value;return typeof ret==="string"?ret.replace(rreturn,""):ret==null?"":ret;} +return;} +isFunction=jQuery.isFunction(value);return this.each(function(i){var val;if(this.nodeType!==1){return;} +if(isFunction){val=value.call(this,i,jQuery(this).val());}else{val=value;} +if(val==null){val="";}else{if(typeof val==="number"){val+="";}else{if(jQuery.isArray(val)){val=jQuery.map(val,function(value){return value==null?"":value+"";});}}} +hooks=jQuery.valHooks[this.type]||jQuery.valHooks[this.nodeName.toLowerCase()];if(!hooks||!("set"in hooks)||hooks.set(this,val,"value")===undefined){this.value=val;}});}});jQuery.extend({valHooks:{option:{get:function(elem){var val=elem.attributes.value;return!val||val.specified?elem.value:elem.text;}},select:{get:function(elem){var value,option,options=elem.options,index=elem.selectedIndex,one=elem.type==="select-one"||index<0,values=one?null:[],max=one?index+1:options.length,i=index<0?max:one?index:0;for(;i=0){optionSet=true;}} +if(!optionSet){elem.selectedIndex=-1;} +return values;}}},attr:function(elem,name,value){var hooks,ret,nType=elem.nodeType;if(!elem||nType===3||nType===8||nType===2){return;} +if(typeof elem.getAttribute===core_strundefined){return jQuery.prop(elem,name,value);} +if(nType!==1||!jQuery.isXMLDoc(elem)){name=name.toLowerCase();hooks=jQuery.attrHooks[name]||(jQuery.expr.match.bool.test(name)?boolHook:nodeHook);} +if(value!==undefined){if(value===null){jQuery.removeAttr(elem,name);}else{if(hooks&&"set"in hooks&&(ret=hooks.set(elem,value,name))!==undefined){return ret;}else{elem.setAttribute(name,value+"");return value;}}}else{if(hooks&&"get"in hooks&&(ret=hooks.get(elem,name))!==null){return ret;}else{ret=jQuery.find.attr(elem,name);return ret==null?undefined:ret;}}},removeAttr:function(elem,value){var name,propName,i=0,attrNames=value&&value.match(core_rnotwhite);if(attrNames&&elem.nodeType===1){while(name=attrNames[i++]){propName=jQuery.propFix[name]||name;if(jQuery.expr.match.bool.test(name)){elem[propName]=false;} +elem.removeAttribute(name);}}},attrHooks:{type:{set:function(elem,value){if(!jQuery.support.radioValue&&value==="radio"&&jQuery.nodeName(elem,"input")){var val=elem.value;elem.setAttribute("type",value);if(val){elem.value=val;} +return value;}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(elem,name,value){var ret,hooks,notxml,nType=elem.nodeType;if(!elem||nType===3||nType===8||nType===2){return;} +notxml=nType!==1||!jQuery.isXMLDoc(elem);if(notxml){name=jQuery.propFix[name]||name;hooks=jQuery.propHooks[name];} +if(value!==undefined){return hooks&&"set"in hooks&&(ret=hooks.set(elem,value,name))!==undefined?ret:elem[name]=value;}else{return hooks&&"get"in hooks&&(ret=hooks.get(elem,name))!==null?ret:elem[name];}},propHooks:{tabIndex:{get:function(elem){return elem.hasAttribute("tabindex")||rfocusable.test(elem.nodeName)||elem.href?elem.tabIndex:-1;}}}});boolHook={set:function(elem,value,name){if(value===false){jQuery.removeAttr(elem,name);}else{elem.setAttribute(name,name);} +return name;}};jQuery.each(jQuery.expr.match.bool.source.match(/\w+/g),function(i,name){var getter=jQuery.expr.attrHandle[name]||jQuery.find.attr;jQuery.expr.attrHandle[name]=function(elem,name,isXML){var fn=jQuery.expr.attrHandle[name],ret=isXML?undefined:(jQuery.expr.attrHandle[name]=undefined)!=getter(elem,name,isXML)?name.toLowerCase():null;jQuery.expr.attrHandle[name]=fn;return ret;};});if(!jQuery.support.optSelected){jQuery.propHooks.selected={get:function(elem){var parent=elem.parentNode;if(parent&&parent.parentNode){parent.parentNode.selectedIndex;} +return null;}};} +jQuery.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){jQuery.propFix[this.toLowerCase()]=this;});jQuery.each(["radio","checkbox"],function(){jQuery.valHooks[this]={set:function(elem,value){if(jQuery.isArray(value)){return elem.checked=jQuery.inArray(jQuery(elem).val(),value)>=0;}}};if(!jQuery.support.checkOn){jQuery.valHooks[this].get=function(elem){return elem.getAttribute("value")===null?"on":elem.value;};}});var rkeyEvent=/^key/,rmouseEvent=/^(?:mouse|contextmenu)|click/,rfocusMorph=/^(?:focusinfocus|focusoutblur)$/,rtypenamespace=/^([^.]*)(?:\.(.+)|)$/;function returnTrue(){return true;} +function returnFalse(){return false;} +function safeActiveElement(){try{return document.activeElement;}catch(err){}} +jQuery.event={global:{},add:function(elem,types,handler,data,selector){var handleObjIn,eventHandle,tmp,events,t,handleObj,special,handlers,type,namespaces,origType,elemData=data_priv.get(elem);if(!elemData){return;} +if(handler.handler){handleObjIn=handler;handler=handleObjIn.handler;selector=handleObjIn.selector;} +if(!handler.guid){handler.guid=jQuery.guid++;} +if(!(events=elemData.events)){events=elemData.events={};} +if(!(eventHandle=elemData.handle)){eventHandle=elemData.handle=function(e){return typeof jQuery!==core_strundefined&&(!e||jQuery.event.triggered!==e.type)?jQuery.event.dispatch.apply(eventHandle.elem,arguments):undefined;};eventHandle.elem=elem;} +types=(types||"").match(core_rnotwhite)||[""];t=types.length;while(t--){tmp=rtypenamespace.exec(types[t])||[];type=origType=tmp[1];namespaces=(tmp[2]||"").split(".").sort();if(!type){continue;} +special=jQuery.event.special[type]||{};type=(selector?special.delegateType:special.bindType)||type;special=jQuery.event.special[type]||{};handleObj=jQuery.extend({type:type,origType:origType,data:data,handler:handler,guid:handler.guid,selector:selector,needsContext:selector&&jQuery.expr.match.needsContext.test(selector),namespace:namespaces.join(".")},handleObjIn);if(!(handlers=events[type])){handlers=events[type]=[];handlers.delegateCount=0;if(!special.setup||special.setup.call(elem,data,namespaces,eventHandle)===false){if(elem.addEventListener){elem.addEventListener(type,eventHandle,false);}}} +if(special.add){special.add.call(elem,handleObj);if(!handleObj.handler.guid){handleObj.handler.guid=handler.guid;}} +if(selector){handlers.splice(handlers.delegateCount++,0,handleObj);}else{handlers.push(handleObj);} +jQuery.event.global[type]=true;} +elem=null;},remove:function(elem,types,handler,selector,mappedTypes){var j,origCount,tmp,events,t,handleObj,special,handlers,type,namespaces,origType,elemData=data_priv.hasData(elem)&&data_priv.get(elem);if(!elemData||!(events=elemData.events)){return;} +types=(types||"").match(core_rnotwhite)||[""];t=types.length;while(t--){tmp=rtypenamespace.exec(types[t])||[];type=origType=tmp[1];namespaces=(tmp[2]||"").split(".").sort();if(!type){for(type in events){jQuery.event.remove(elem,type+types[t],handler,selector,true);} +continue;} +special=jQuery.event.special[type]||{};type=(selector?special.delegateType:special.bindType)||type;handlers=events[type]||[];tmp=tmp[2]&&new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.|)")+"(\\.|$)");origCount=j=handlers.length;while(j--){handleObj=handlers[j];if((mappedTypes||origType===handleObj.origType)&&(!handler||handler.guid===handleObj.guid)&&(!tmp||tmp.test(handleObj.namespace))&&(!selector||selector===handleObj.selector||selector==="**"&&handleObj.selector)){handlers.splice(j,1);if(handleObj.selector){handlers.delegateCount--;} +if(special.remove){special.remove.call(elem,handleObj);}}} +if(origCount&&!handlers.length){if(!special.teardown||special.teardown.call(elem,namespaces,elemData.handle)===false){jQuery.removeEvent(elem,type,elemData.handle);} +delete events[type];}} +if(jQuery.isEmptyObject(events)){delete elemData.handle;data_priv.remove(elem,"events");}},trigger:function(event,data,elem,onlyHandlers){var i,cur,tmp,bubbleType,ontype,handle,special,eventPath=[elem||document],type=core_hasOwn.call(event,"type")?event.type:event,namespaces=core_hasOwn.call(event,"namespace")?event.namespace.split("."):[];cur=tmp=elem=elem||document;if(elem.nodeType===3||elem.nodeType===8){return;} +if(rfocusMorph.test(type+jQuery.event.triggered)){return;} +if(type.indexOf(".")>=0){namespaces=type.split(".");type=namespaces.shift();namespaces.sort();} +ontype=type.indexOf(":")<0&&"on"+type;event=event[jQuery.expando]?event:new jQuery.Event(type,typeof event==="object"&&event);event.isTrigger=onlyHandlers?2:3;event.namespace=namespaces.join(".");event.namespace_re=event.namespace?new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.|)")+"(\\.|$)"):null;event.result=undefined;if(!event.target){event.target=elem;} +data=data==null?[event]:jQuery.makeArray(data,[event]);special=jQuery.event.special[type]||{};if(!onlyHandlers&&special.trigger&&special.trigger.apply(elem,data)===false){return;} +if(!onlyHandlers&&!special.noBubble&&!jQuery.isWindow(elem)){bubbleType=special.delegateType||type;if(!rfocusMorph.test(bubbleType+type)){cur=cur.parentNode;} +for(;cur;cur=cur.parentNode){eventPath.push(cur);tmp=cur;} +if(tmp===(elem.ownerDocument||document)){eventPath.push(tmp.defaultView||tmp.parentWindow||window);}} +i=0;while((cur=eventPath[i++])&&!event.isPropagationStopped()){event.type=i>1?bubbleType:special.bindType||type;handle=(data_priv.get(cur,"events")||{})[event.type]&&data_priv.get(cur,"handle");if(handle){handle.apply(cur,data);} +handle=ontype&&cur[ontype];if(handle&&jQuery.acceptData(cur)&&handle.apply&&handle.apply(cur,data)===false){event.preventDefault();}} +event.type=type;if(!onlyHandlers&&!event.isDefaultPrevented()){if((!special._default||special._default.apply(eventPath.pop(),data)===false)&&jQuery.acceptData(elem)){if(ontype&&jQuery.isFunction(elem[type])&&!jQuery.isWindow(elem)){tmp=elem[ontype];if(tmp){elem[ontype]=null;} +jQuery.event.triggered=type;elem[type]();jQuery.event.triggered=undefined;if(tmp){elem[ontype]=tmp;}}}} +return event.result;},dispatch:function(event){event=jQuery.event.fix(event);var i,j,ret,matched,handleObj,handlerQueue=[],args=core_slice.call(arguments),handlers=(data_priv.get(this,"events")||{})[event.type]||[],special=jQuery.event.special[event.type]||{};args[0]=event;event.delegateTarget=this;if(special.preDispatch&&special.preDispatch.call(this,event)===false){return;} +handlerQueue=jQuery.event.handlers.call(this,event,handlers);i=0;while((matched=handlerQueue[i++])&&!event.isPropagationStopped()){event.currentTarget=matched.elem;j=0;while((handleObj=matched.handlers[j++])&&!event.isImmediatePropagationStopped()){if(!event.namespace_re||event.namespace_re.test(handleObj.namespace)){event.handleObj=handleObj;event.data=handleObj.data;ret=((jQuery.event.special[handleObj.origType]||{}).handle||handleObj.handler).apply(matched.elem,args);if(ret!==undefined){if((event.result=ret)===false){event.preventDefault();event.stopPropagation();}}}}} +if(special.postDispatch){special.postDispatch.call(this,event);} +return event.result;},handlers:function(event,handlers){var i,matches,sel,handleObj,handlerQueue=[],delegateCount=handlers.delegateCount,cur=event.target;if(delegateCount&&cur.nodeType&&(!event.button||event.type!=="click")){for(;cur!==this;cur=cur.parentNode||this){if(cur.disabled!==true||event.type!=="click"){matches=[];for(i=0;i=0:jQuery.find(sel,this,null,[cur]).length;} +if(matches[sel]){matches.push(handleObj);}} +if(matches.length){handlerQueue.push({elem:cur,handlers:matches});}}}} +if(delegateCount1?jQuery.unique(ret):ret);ret.selector=this.selector?this.selector+" "+selector:selector;return ret;},has:function(target){var targets=jQuery(target,this),l=targets.length;return this.filter(function(){var i=0;for(;i-1:cur.nodeType===1&&jQuery.find.matchesSelector(cur,selectors))){cur=matched.push(cur);break;}}} +return this.pushStack(matched.length>1?jQuery.unique(matched):matched);},index:function(elem){if(!elem){return this[0]&&this[0].parentNode?this.first().prevAll().length:-1;} +if(typeof elem==="string"){return core_indexOf.call(jQuery(elem),this[0]);} +return core_indexOf.call(this,elem.jquery?elem[0]:elem);},add:function(selector,context){var set=typeof selector==="string"?jQuery(selector,context):jQuery.makeArray(selector&&selector.nodeType?[selector]:selector),all=jQuery.merge(this.get(),set);return this.pushStack(jQuery.unique(all));},addBack:function(selector){return this.add(selector==null?this.prevObject:this.prevObject.filter(selector));}});function sibling(cur,dir){while((cur=cur[dir])&&cur.nodeType!==1){} +return cur;} +jQuery.each({parent:function(elem){var parent=elem.parentNode;return parent&&parent.nodeType!==11?parent:null;},parents:function(elem){return jQuery.dir(elem,"parentNode");},parentsUntil:function(elem,i,until){return jQuery.dir(elem,"parentNode",until);},next:function(elem){return sibling(elem,"nextSibling");},prev:function(elem){return sibling(elem,"previousSibling");},nextAll:function(elem){return jQuery.dir(elem,"nextSibling");},prevAll:function(elem){return jQuery.dir(elem,"previousSibling");},nextUntil:function(elem,i,until){return jQuery.dir(elem,"nextSibling",until);},prevUntil:function(elem,i,until){return jQuery.dir(elem,"previousSibling",until);},siblings:function(elem){return jQuery.sibling((elem.parentNode||{}).firstChild,elem);},children:function(elem){return jQuery.sibling(elem.firstChild);},contents:function(elem){return elem.contentDocument||jQuery.merge([],elem.childNodes);}},function(name,fn){jQuery.fn[name]=function(until,selector){var matched=jQuery.map(this,fn,until);if(name.slice(-5)!=="Until"){selector=until;} +if(selector&&typeof selector==="string"){matched=jQuery.filter(selector,matched);} +if(this.length>1){if(!guaranteedUnique[name]){jQuery.unique(matched);} +if(rparentsprev.test(name)){matched.reverse();}} +return this.pushStack(matched);};});jQuery.extend({filter:function(expr,elems,not){var elem=elems[0];if(not){expr=":not("+expr+")";} +return elems.length===1&&elem.nodeType===1?jQuery.find.matchesSelector(elem,expr)?[elem]:[]:jQuery.find.matches(expr,jQuery.grep(elems,function(elem){return elem.nodeType===1;}));},dir:function(elem,dir,until){var matched=[],truncate=until!==undefined;while((elem=elem[dir])&&elem.nodeType!==9){if(elem.nodeType===1){if(truncate&&jQuery(elem).is(until)){break;} +matched.push(elem);}} +return matched;},sibling:function(n,elem){var matched=[];for(;n;n=n.nextSibling){if(n.nodeType===1&&n!==elem){matched.push(n);}} +return matched;}});function winnow(elements,qualifier,not){if(jQuery.isFunction(qualifier)){return jQuery.grep(elements,function(elem,i){return!!qualifier.call(elem,i,elem)!==not;});} +if(qualifier.nodeType){return jQuery.grep(elements,function(elem){return elem===qualifier!==not;});} +if(typeof qualifier==="string"){if(isSimple.test(qualifier)){return jQuery.filter(qualifier,elements,not);} +qualifier=jQuery.filter(qualifier,elements);} +return jQuery.grep(elements,function(elem){return core_indexOf.call(qualifier,elem)>=0!==not;});} +var rxhtmlTag=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,rtagName=/<([\w:]+)/,rhtml=/<|&#?\w+;/,rnoInnerhtml=/<(?:script|style|link)/i,manipulation_rcheckableType=/^(?:checkbox|radio)$/i,rchecked=/checked\s*(?:[^=]|=\s*.checked.)/i,rscriptType=/^$|\/(?:java|ecma)script/i,rscriptTypeMasked=/^true\/(.*)/,rcleanScript=/^\s*\s*$/g,wrapMap={option:[1,""],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};wrapMap.optgroup=wrapMap.option;wrapMap.tbody=wrapMap.tfoot=wrapMap.colgroup=wrapMap.caption=wrapMap.thead;wrapMap.th=wrapMap.td;jQuery.fn.extend({text:function(value){return jQuery.access(this,function(value){return value===undefined?jQuery.text(this):this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(value));},null,value,arguments.length);},append:function(){return this.domManip(arguments,function(elem){if(this.nodeType===1||this.nodeType===11||this.nodeType===9){var target=manipulationTarget(this,elem);target.appendChild(elem);}});},prepend:function(){return this.domManip(arguments,function(elem){if(this.nodeType===1||this.nodeType===11||this.nodeType===9){var target=manipulationTarget(this,elem);target.insertBefore(elem,target.firstChild);}});},before:function(){return this.domManip(arguments,function(elem){if(this.parentNode){this.parentNode.insertBefore(elem,this);}});},after:function(){return this.domManip(arguments,function(elem){if(this.parentNode){this.parentNode.insertBefore(elem,this.nextSibling);}});},remove:function(selector,keepData){var elem,elems=selector?jQuery.filter(selector,this):this,i=0;for(;(elem=elems[i])!=null;i++){if(!keepData&&elem.nodeType===1){jQuery.cleanData(getAll(elem));} +if(elem.parentNode){if(keepData&&jQuery.contains(elem.ownerDocument,elem)){setGlobalEval(getAll(elem,"script"));} +elem.parentNode.removeChild(elem);}} +return this;},empty:function(){var elem,i=0;for(;(elem=this[i])!=null;i++){if(elem.nodeType===1){jQuery.cleanData(getAll(elem,false));elem.textContent="";}} +return this;},clone:function(dataAndEvents,deepDataAndEvents){dataAndEvents=dataAndEvents==null?false:dataAndEvents;deepDataAndEvents=deepDataAndEvents==null?dataAndEvents:deepDataAndEvents;return this.map(function(){return jQuery.clone(this,dataAndEvents,deepDataAndEvents);});},html:function(value){return jQuery.access(this,function(value){var elem=this[0]||{},i=0,l=this.length;if(value===undefined&&elem.nodeType===1){return elem.innerHTML;} +if(typeof value==="string"&&!rnoInnerhtml.test(value)&&!wrapMap[(rtagName.exec(value)||["",""])[1].toLowerCase()]){value=value.replace(rxhtmlTag,"<$1>");try{for(;i0){setGlobalEval(destElements,!inPage&&getAll(elem,"script"));} +return clone;},buildFragment:function(elems,context,scripts,selection){var elem,tmp,tag,wrap,contains,j,i=0,l=elems.length,fragment=context.createDocumentFragment(),nodes=[];for(;i")+wrap[2];j=wrap[0];while(j--){tmp=tmp.firstChild;} +jQuery.merge(nodes,tmp.childNodes);tmp=fragment.firstChild;tmp.textContent="";}}}} +fragment.textContent="";i=0;while(elem=nodes[i++]){if(selection&&jQuery.inArray(elem,selection)!==-1){continue;} +contains=jQuery.contains(elem.ownerDocument,elem);tmp=getAll(fragment.appendChild(elem),"script");if(contains){setGlobalEval(tmp);} +if(scripts){j=0;while(elem=tmp[j++]){if(rscriptType.test(elem.type||"")){scripts.push(elem);}}}} +return fragment;},cleanData:function(elems){var data,elem,events,type,key,j,special=jQuery.event.special,i=0;for(;(elem=elems[i])!==undefined;i++){if(Data.accepts(elem)){key=elem[data_priv.expando];if(key&&(data=data_priv.cache[key])){events=Object.keys(data.events||{});if(events.length){for(j=0;(type=events[j])!==undefined;j++){if(special[type]){jQuery.event.remove(elem,type);}else{jQuery.removeEvent(elem,type,data.handle);}}} +if(data_priv.cache[key]){delete data_priv.cache[key];}}} +delete data_user.cache[elem[data_user.expando]];}},_evalUrl:function(url){return jQuery.ajax({url:url,type:"GET",dataType:"script",async:false,global:false,"throws":true});}});function manipulationTarget(elem,content){return jQuery.nodeName(elem,"table")&&jQuery.nodeName(content.nodeType===1?content:content.firstChild,"tr")?elem.getElementsByTagName("tbody")[0]||elem.appendChild(elem.ownerDocument.createElement("tbody")):elem;} +function disableScript(elem){elem.type=(elem.getAttribute("type")!==null)+"/"+elem.type;return elem;} +function restoreScript(elem){var match=rscriptTypeMasked.exec(elem.type);if(match){elem.type=match[1];}else{elem.removeAttribute("type");} +return elem;} +function setGlobalEval(elems,refElements){var l=elems.length,i=0;for(;i1);},show:function(){return showHide(this,true);},hide:function(){return showHide(this);},toggle:function(state){var bool=typeof state==="boolean";return this.each(function(){if(bool?state:isHidden(this)){jQuery(this).show();}else{jQuery(this).hide();}});}});jQuery.extend({cssHooks:{opacity:{get:function(elem,computed){if(computed){var ret=curCSS(elem,"opacity");return ret===""?"1":ret;}}}},cssNumber:{"columnCount":true,"fillOpacity":true,"fontWeight":true,"lineHeight":true,"opacity":true,"orphans":true,"widows":true,"zIndex":true,"zoom":true},cssProps:{"float":"cssFloat"},style:function(elem,name,value,extra){if(!elem||elem.nodeType===3||elem.nodeType===8||!elem.style){return;} +var ret,type,hooks,origName=jQuery.camelCase(name),style=elem.style;name=jQuery.cssProps[origName]||(jQuery.cssProps[origName]=vendorPropName(style,origName));hooks=jQuery.cssHooks[name]||jQuery.cssHooks[origName];if(value!==undefined){type=typeof value;if(type==="string"&&(ret=rrelNum.exec(value))){value=(ret[1]+1)*ret[2]+parseFloat(jQuery.css(elem,name));type="number";} +if(value==null||type==="number"&&isNaN(value)){return;} +if(type==="number"&&!jQuery.cssNumber[origName]){value+="px";} +if(!jQuery.support.clearCloneStyle&&value===""&&name.indexOf("background")===0){style[name]="inherit";} +if(!hooks||!("set"in hooks)||(value=hooks.set(elem,value,extra))!==undefined){style[name]=value;}}else{if(hooks&&"get"in hooks&&(ret=hooks.get(elem,false,extra))!==undefined){return ret;} +return style[name];}},css:function(elem,name,extra,styles){var val,num,hooks,origName=jQuery.camelCase(name);name=jQuery.cssProps[origName]||(jQuery.cssProps[origName]=vendorPropName(elem.style,origName));hooks=jQuery.cssHooks[name]||jQuery.cssHooks[origName];if(hooks&&"get"in hooks){val=hooks.get(elem,true,extra);} +if(val===undefined){val=curCSS(elem,name,styles);} +if(val==="normal"&&name in cssNormalTransform){val=cssNormalTransform[name];} +if(extra===""||extra){num=parseFloat(val);return extra===true||jQuery.isNumeric(num)?num||0:val;} +return val;}});curCSS=function(elem,name,_computed){var width,minWidth,maxWidth,computed=_computed||getStyles(elem),ret=computed?computed.getPropertyValue(name)||computed[name]:undefined,style=elem.style;if(computed){if(ret===""&&!jQuery.contains(elem.ownerDocument,elem)){ret=jQuery.style(elem,name);} +if(rnumnonpx.test(ret)&&rmargin.test(name)){width=style.width;minWidth=style.minWidth;maxWidth=style.maxWidth;style.minWidth=style.maxWidth=style.width=ret;ret=computed.width;style.width=width;style.minWidth=minWidth;style.maxWidth=maxWidth;}} +return ret;};function setPositiveNumber(elem,value,subtract){var matches=rnumsplit.exec(value);return matches?Math.max(0,matches[1]-(subtract||0))+(matches[2]||"px"):value;} +function augmentWidthOrHeight(elem,name,extra,isBorderBox,styles){var i=extra===(isBorderBox?"border":"content")?4:name==="width"?1:0,val=0;for(;i<4;i+=2){if(extra==="margin"){val+=jQuery.css(elem,extra+cssExpand[i],true,styles);} +if(isBorderBox){if(extra==="content"){val-=jQuery.css(elem,"padding"+cssExpand[i],true,styles);} +if(extra!=="margin"){val-=jQuery.css(elem,"border"+cssExpand[i]+"Width",true,styles);}}else{val+=jQuery.css(elem,"padding"+cssExpand[i],true,styles);if(extra!=="padding"){val+=jQuery.css(elem,"border"+cssExpand[i]+"Width",true,styles);}}} +return val;} +function getWidthOrHeight(elem,name,extra){var valueIsBorderBox=true,val=name==="width"?elem.offsetWidth:elem.offsetHeight,styles=getStyles(elem),isBorderBox=jQuery.support.boxSizing&&jQuery.css(elem,"boxSizing",false,styles)==="border-box";if(val<=0||val==null){val=curCSS(elem,name,styles);if(val<0||val==null){val=elem.style[name];} +if(rnumnonpx.test(val)){return val;} +valueIsBorderBox=isBorderBox&&(jQuery.support.boxSizingReliable||val===elem.style[name]);val=parseFloat(val)||0;} +return val+augmentWidthOrHeight(elem,name,extra||(isBorderBox?"border":"content"),valueIsBorderBox,styles)+"px";} +function css_defaultDisplay(nodeName){var doc=document,display=elemdisplay[nodeName];if(!display){display=actualDisplay(nodeName,doc);if(display==="none"||!display){iframe=(iframe||jQuery("