diff options
author | Yorhel <git@yorhel.nl> | 2008-10-26 13:23:15 +0100 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2008-10-26 13:23:15 +0100 |
commit | 45802c119b3f3a36ffae3296b37d51dd3a454f29 (patch) | |
tree | dde77096c1d248596c0c1d9b25f546db881ffd11 | |
parent | 3fb8a1ca280184cbe9b9873b2c736cab446414ac (diff) |
Removing all files we're not going to use with the rewrite
...this is basically everything we're going to rewrite
64 files changed, 0 insertions, 9781 deletions
@@ -1,6 +1,5 @@ /data/config.pl /data/log/ -/data/tplcompiled.pm /static/cv/ /static/rg/ /static/sf/ diff --git a/data/tpl/defs.pl b/data/tpl/defs.pl deleted file mode 100644 index 9135adb1..00000000 --- a/data/tpl/defs.pl +++ /dev/null @@ -1,562 +0,0 @@ -[[! - -use Time::CTime (); -use Algorithm::Diff 'sdiff'; -use POSIX ('ceil', 'floor'); - -my %p; # $X->{page} global page data -my %d; # $X->{page}->{$p} local page data - -# redefine _hchar - usually a bad idea, but who cares -sub _hchar {local$_=shift||return'';s/&/&/g;s/</</g;s/>/>/g;s/"/"/g;s/\r?\n/ <br \/>\n/g;return$_;} - -sub formatdate {return _hchar(Time::CTime::strftime($_[0],gmtime($_[1]||0)))||'';} -sub txt {local$_=shift||return'';s/&/&/g;s/</</g;s/>/>/g;return$_;} -sub art2str {my$r='';$r.=($r?' & ':'').$_->{name}foreach (@{$_[0]->{artists}});return $_[1]?$r:_hchar($r);} -sub calctime {my$r=shift;return'0:00:00'if!$r;my$x=sprintf'%d:%02d:%02d',int($r/3600),int(($r%3600)/60),($r%3600)%60;return $x;} -sub shorten {local$_=shift||return'';return length>$_[0]?substr($_,0,$_[0]-3).'...':$_}; - -# Date string format: yyyy-mm-dd -# y = 0 -> Unknown -# y = 9999 -> TBA (To Be Announced) -# m = 99 -> Month + day unknown, year known -# d = 99 -> Day unknown, month + year known -sub datestr { - my $d = sprintf '%08d', $_[0]||0; - my $b = $d > Time::CTime::strftime("%Y%m%d", gmtime()); - my @d = map int, $1, $2, $3 if $d =~ /^([0-9]{4})([0-9]{2})([0-9]{2})$/; - return 'unknown' if $d[0] == 0; - my $r = sprintf $d[1] == 99 ? '%04d' : $d[2] == 99 ? '%04d-%02d' : '%04d-%02d-%02d', @d; - $r = 'TBA' if $d[0] == 9999; - $r =~ s/^[0-9]{4}-// if $_[1]; - return ($b&&!$_[1]?'<b class="future">':'').$r.($b?'</b>':''); -} -sub mediastr { - return join(', ', map { - $_->{medium} =~ /^(cd|dvd|gdr|blr)$/ - ? sprintf('%d %s%s', $_->{qty}, $VNDB::MED->{$_->{medium}}, $_->{qty}>1?'s':'') - : $VNDB::MED->{$_->{medium}} - } @{$_[0]}); -} -sub sortbut { # url, col - my $r=' '; my $u = _hchar($_[0]); - $u .= $u =~ /\?/ ? ';' : '?'; - for ('a', 'd') { - my $chr = $_ eq 'd' ? "\x{25BE}" : "\x{25B4}"; - $r .= $d{order}[0] eq $_[1] && $d{order}[1] eq $_ ? $chr : - sprintf '<a href="%ss=%s;o=%s">%s</a>', $u, $_[1], $_, $chr; - } - return $r; -} -sub pagebut { # url - my @br; my $ng = $_[0] =~ /\?/ ? ';' : '?'; - push @br, sprintf '<a href="%s"><- previous</a>', $_[0].($d{page}-2 ? $ng.'p='.($d{page}-1) : '') if $d{page} > 1; - push @br, sprintf '<a href="%s">next -></a>', $_[0].$ng.'p='.($d{page}+1) if $d{npage}; - return $#br >= 0 ? ('<p class="browse">( '.join(' | ', @br).' )</p>') : ''; -} -sub wraplong { # text, margin - local $_ = $_[0]; - my $m = $_[1]/2; - s/([^\s\r\n]{$m})([^\s\r\n])/$1 $2/g; - return $_; -} -sub age { - my $a = time-$_[0]; - return sprintf '%d %s%s', - $a > 60*60*24*365*2 ? ( $a/60/60/24/365, 'years' ) : - $a > 60*60*24*(365/12)*2 ? ( $a/60/60/24/(365/12), 'months' ) : - $a > 60*60*24*7*2 ? ( $a/60/60/24/7, 'weeks' ) : - $a > 60*60*24*2 ? ( $a/60/60/24, 'days' ) : - $a > 60*60*2 ? ( $a/60/60, 'hours' ) : - $a > 60*2 ? ( $a/60, 'min' ) : - ( $a, 'sec' ), - $_[1]?'':' ago'; -} -sub userstr { # [ uid, username ] or a hashref containing those keys - my($id,$n) = ref($_[0])eq'HASH'?($_[0]{uid}||$_[0]{requester}, $_[0]{username}):@_; - return !$id ? '[deleted]' : '<a href="/u'.$id.'">'.$n.'</a>'; -} - - -sub wordsplit { # split a string into an array of words, but make sure to not split HTML tags -# return [ split //, $_[0] ]; - my @a; - my $in=''; - for (split /\s+/, $_[0]) { - my $gt = () = />/g; - my $lt = () = /</g; - if($in && $gt > $lt) { - push @a, $in.$_; - $in=''; - } elsif($lt > $gt || $in) { - $in .= $_.' '; - } else { - push @a, $_; - }; - } - push @a, $in if $in; - return \@a; -} - -sub cdiff { # obj1, obj2, @items->[ short, name, serialise, diff, [parsed_x, parsed_y] ] - my($x, $y, @items, @c) = @_; - # serialise = 0 -> integer, 1 -> string, CODEref -> code - - my $type = defined $$y{minage} ? 'r' : defined $$y{length} ? 'v' : 'p'; - my $pre = '<div id="revbrowse">'. - ($$y{next} ? qq|<a href="/$type$$y{id}.$$y{next}" id="revnext">later revision -></a>| : ''). - ($x ? qq|<a href="/$type$$y{id}.$$x{rev}" id="revprev"><- earlier revision</a>| : ''). - qq|<a href="/$type$$y{id}" id="revmain">$type$$y{id}</a> </div>|; - - if(!$x) { # just show info about the revision if there is no previous edit - return $pre.qq|<div id="tmc"><b>Revision $$y{rev}</b> (<a href="/$type$$y{id}/edit?rev=$$y{rev}">edit</a>)<br />By |.userstr($y).q| on |. - formatdate('%Y-%m-%d at %R', $$y{added}).'<br /><b>Edit summary:</b><br /><br />'. - summary($$y{comments}, 0, '[no summary]').'</div>'; - } - for (@items) { - $_->[4] = !$_->[2] ? $x->{$_->[0]}||'0' : !ref($_->[2]) ? _hchar(wraplong($x->{$_->[0]}||'[empty]',60)) : &{$_->[2]}($x->{$_->[0]})||'[empty]'; - $_->[5] = !$_->[2] ? $y->{$_->[0]}||'0' : !ref($_->[2]) ? _hchar(wraplong($y->{$_->[0]}||'[empty]',60)) : &{$_->[2]}($y->{$_->[0]})||'[empty]'; - push(@c, $_) if $_->[4] ne $_->[5]; - if($_->[3] && $_->[4] ne $_->[5]) { - my($rx,$ry,$ch) = ('','','u'); - for (sdiff(wordsplit($_->[4]), wordsplit($_->[5]))) { - if($ch ne $_->[0]) { - if($ch ne 'u') { - $rx .= '</b>'; - $ry .= '</b>'; - } - $rx .= '<b class="diff_del">' if $_->[0] eq '-' || $_->[0] eq 'c'; - $ry .= '<b class="diff_add">' if $_->[0] eq '+' || $_->[0] eq 'c'; - } - $ch = $_->[0]; - $rx .= $_->[1].' ' if $ch ne '+'; - $ry .= $_->[2].' ' if $ch ne '-'; - } - $_->[4] = $rx; - $_->[5] = $ry; - } - } - return $pre.'<table id="tmc"><thead><tr><td class="tc1"> </td>'. - qq|<td class="tc2"><b>Revision $$x{rev}</b> (<a href="/$type$$y{id}/edit?rev=$$x{rev}">edit</a>)<br />By |.userstr($x).' on '.formatdate('%Y-%m-%d at %R', $$x{added}).'</td>'. - qq|<td class="tc3"><b>Revision $$y{rev}</b> (<a href="/$type$$y{id}/edit?rev=$$y{rev}">edit</a>)<br />By |.userstr($y).' on '.formatdate('%Y-%m-%d at %R', $$y{added}).'</td>'. - '</tr><tr></tr><tr><td> </td><td colspan="2"><b>Edit summary of revision '.$$y{rev}.'</b><br /><br />'.summary($$y{comments}, 0, '[no summary]').'<br /><br /></td></tr></thead>'. - join('',map{ - '<tr><td class="tc1">'.$_->[1].'</td><td class="tc2">'.$_->[4].'</td><td class="tc3">'.$_->[5].'</td></tr>' - } @c).'</table>'; -} - - -sub summary { # cmd, len, def - return $_[2]||'' if !$_[0]; - my $res = ''; - my $len = 0; - my $as = 0; - my $raw = 0; - (my $txt = $_[0]) =~ s/\r?\n/\n /g; - for (split / /, $txt) { - next if !defined $_ || $_ eq ''; - my $l = length; - s/\&/&/g; - s/>/>/g; - s/</</g; - if(!$raw && s/^\[raw\]//) { - $l -= 5; - $raw++; - } - if(!$raw) { - $l -= 9 while(s/\[spoiler\]/<b class="spoiler">/i); - $l -= 10 while(s/\[\/spoiler\]/<\/b>/i); - while(s/\[url=((https?:\/\/|\/)[^\]>]+)\]/<a href="$1" rel="nofollow">/i) { - $l -= length($1)+6; - $as++; - } - if(!$as && s/(http|https):\/\/(.+[0-9a-zA-Z=\/])/<a href="$1:\/\/$2" rel="nofollow">link<\/a>/) { - $l = 4; - } elsif(!$as) { - s/^(.*[^\w]|)([tdvpr][1-9][0-9]*)\.([1-9][0-9]*)([^\w].*|)$/$1<a href="\/$2.$3">$2.$3<\/a>$4/ || - s/^(.*[^\w]|)([tduvpr][1-9][0-9]*)([^\w].*|)$/$1<a href="\/$2">$2<\/a>$3/; - } - while(s/\[\/url\]/<\/a>/i) { - $l -= 6; - $as--; - } - } - if(s/\[\/raw\]//) { - $l -= 6; - $raw=0; - } - $len += $l + 1; - last if $_[1] && $len > $_[1]; - $res .= "$_ "; - } - $res =~ y/\n/ / if $_[1]; - $res =~ s/\n/<br \/>/g if !$_[1]; - $res =~ s/ +$//; - $res .= '</a>' x $as if $as; - $res .= '...' if $_[1] && $len > $_[1]; - return $res; -} - - -sub ttabs { # [vrpu], obj, sel - my($t, $o, $s) = @_; - $s||=''; - my @act = ( - !$s?'%s':'<a href="/%s">%1$s</a>', - $$o{locked} ? - '<b>locked for editing</b>' : (), - $p{Authlock} && $t ne 'u' ? - sprintf('<a href="/%%s/lock">%s</a>', $$o{locked} ? 'unlock' : 'lock') : (), - $p{Authdel} && $t ne 'u' ? ( - sprintf('<a href="/%%s/hide"%s>%s</a>', $t eq 'v' ? ' id="vhide"' : '', $$o{hidden} ? 'unhide' : 'hide') ) : (), - $t eq 'u' && $p{Authusermod} ? ( - '<a href="/%s/del" id="userdel">del</a>' ) : (), - ($t eq 'u' && $p{Authusermod}) || ($t ne 'u' && (!$$o{locked} && !$$o{hidden}) || ($p{Authedit} && $p{Authlock})) ? - ($s eq 'edit' ? 'edit' : '<a href="'.($p{Authedit}?'/%s/edit':'/u/register?n=1').'" '.($t eq 'v' || $t eq 'r' ? 'class="dropdown" rel="nofollow editDD"':'').'>edit</a>') : (), - - $t eq 'u' ? ( - $o->{flags} & $VNDB::UFLAGS->{list} ? ( $s eq 'list' ? 'list' : '<a href="/%s/list">list</a>', ) : (), - $o->{flags} & $VNDB::UFLAGS->{list} ? ( $s eq 'wish' ? 'wishlist' : '<a href="/%s/wish">wishlist</a>', ) : (), - ) : (), - - $t ne 'r' ? ( - $s eq 'disc' ? 'discussions' : '<a href="/t/%s">discussions</a>', ) : (), - - $p{Authhist} ? - ($s eq 'hist' ? 'history' : '<a href="/%s/hist">history</a>') : (), - ); - return '<p class="mod">< '.join(' - ', map { sprintf $_, $t.$$o{id} } @act).' ></p>'.( - !$p{Authedit} ? qq| -<div id="editDD" class="dropdown"> - <ul> - <li><b>Not logged in</b></li> - <li><a href="/u/login">Login</a></li> - <li><a href="/u/register">Register</a></li> - </ul> -</div> - | : $t eq 'v' ? qq| -<div id="editDD" class="dropdown"> - <ul> - <li><a href="/v$$o{id}/edit" rel="nofollow">Edit all</a></li> - <li><a href="/v$$o{id}/edit?fh=info" rel="nofollow">General info</a></li> - <li><a href="/v$$o{id}/edit?fh=cat" rel="nofollow">Categories</a></li> - <li><a href="/v$$o{id}/edit?fh=rel" rel="nofollow">Relations</a></li> - <li><a href="/v$$o{id}/edit?fh=img" rel="nofollow">Image</a></li> - <li><a href="/v$$o{id}/edit?fh=scr" rel="nofollow">Screenshots</a></li> - <li><a href="/v$$o{id}/add" rel="nofollow">Add release</a></li> - </ul> -</div>| : $t eq 'r' ? qq| -<div id="editDD" class="dropdown"> - <ul> - <li><a href="/r$$o{id}/edit" rel="nofollow">Edit all</a></li> - <li><a href="/r$$o{id}/edit?fh=info" rel="nofollow">General info</a></li> - <li><a href="/r$$o{id}/edit?fh=pnm" rel="nofollow">Platforms & media</a></li> - <li><a href="/r$$o{id}/edit?fh=prod" rel="nofollow">Producers</a></li> - <li><a href="/r$$o{id}/edit?fh=rel" rel="nofollow">Relations</a></li> - </ul> -</div>| : '' - ); -} - - -# Uwaaaa~ ugly function! -sub rlist_dd { - my $r = shift; - return - qq|<div class="dropdown rlistdd" id="rlistDD$$r{id}"><ul><li><b>Release status</b></li>|. - join('', map { - $r->{rlist} && $_ == $r->{rlist}{rstat} ? qq|<li><b><acronym class="uicons r$_"> </acronym> $$VNDB::RSTAT[$_]</b></li>| - : qq|<li><a href="/r$$r{id}/list?r=$_"><acronym class="uicons r$_"> </acronym> $$VNDB::RSTAT[$_]</a></li>| - } 0..$#$VNDB::RSTAT). - qq|</ul><ul><li><b>Play status</b></li>|. - join('', map { - $r->{rlist} && $_ == $r->{rlist}{vstat} ? qq|<li><b><acronym class="uicons v$_"> </acronym> $$VNDB::VSTAT[$_]</b></li>| - : qq|<li><a href="/r$$r{id}/list?v=$_"><acronym class="uicons v$_"> </acronym> $$VNDB::VSTAT[$_]</a></li>| - } 0..$#$VNDB::VSTAT). - qq|</ul><ul class="full">|. - ($r->{rlist} ? qq|<li class="center"><a href="/r$$r{id}/list?d=1">remove from my list</a></li>| - : qq|<li class="center"><b>not in your list</b></li>|). - qq|</ul></div>|; -} - - -my %pagetitles = ( - faq => 'Frequently Asked Questions', - userlogin => 'Login', - userreg => 'Register a new account', - userpass => 'Forgot your password?', - home => 'Visual Novel Database', - pbrowse => 'Browse producers', - userlist => 'Browse users', - tindex => 'Discussion board index', - ttag => sub { - return ($p{ttag}{obj} ? 'Related discussions for ' : '').$p{ttag}{title} }, - tthread => sub { - return $p{tthread}{t}{title} }, - tedit => sub { - return $p{tedit}{p} ? 'Edit post' : - $p{tedit}{t} ? 'Reply to thread' : 'Start a new thread' }, - userpage => sub { - return 'User: '.$p{userpage}{user}{username} }, - vnlist => 'My visual novel list (old)', - wlist => sub { - return $p{wlist}{user}{username} eq $p{AuthUsername} ? 'My wishlist' : ($p{wlist}{user}{username}.'\'s wishlist'); }, - rlist => sub { - return $p{rlist}{user}{username} eq $p{AuthUsername} ? 'My visual novel list' : ($p{rlist}{user}{username}.'\'s visual novel list'); }, - useredit => sub { - return !$p{useredit}{adm} ? 'My account' : 'Edit '.$p{useredit}{form}{username}.'\'s account'; }, - ppage => sub { - return $p{ppage}{prod}{name} }, - pedit => sub { - return $p{pedit}{id} ? sprintf('Edit %s', $p{pedit}{form}{name}) : 'Add a new producer'; }, - vnedit => sub { - return $p{vnedit}{id} ? sprintf('Edit %s', $p{vnedit}{form}{title}) : 'Add a new visual novel'; }, - redit => sub { - return $p{redit}{id} ? sprintf('Edit %s', $p{redit}{rel}{title}) : sprintf('Add release to %s', $p{redit}{vn}{title}); }, - vnpage => sub { return $p{vnpage}{vn}{title}; }, - vnrg => sub { return 'Relations for '.$p{vnrg}{vn}{title} }, - vnstats => sub { return 'User statistics for '.$p{vnstats}{vn}{title} }, - vnbrowse => sub { - return $p{vnbrowse}{chr} eq 'search' ? 'Visual novel search' : - $p{vnbrowse}{chr} eq 'mod' ? 'Visual Novels awaiting moderation' : - $p{vnbrowse}{chr} eq 'all' ? 'Browse all visual novels' : - $p{vnbrowse}{chr} eq '0' ? 'Browse by char: Other' : - sprintf 'Browse by char: %s', uc $p{vnbrowse}{chr}; }, - rpage => sub { - return $p{rpage}{rel}{romaji} || $p{rpage}{rel}{title} }, - hist => sub { - return !$p{hist}{id} || !$p{hist}{type} ? 'Recent changes' : - $p{hist}{type} eq 'u' ? 'Recent changes by '.$p{hist}{title} : 'Edit history of '.$p{hist}{title}; }, - docs => sub { $p{docs}{title} }, - error => sub { - $p{error}{err} eq 'notfound' ? '404 Page Not Found' : 'Error Parsing Form' }, -); -sub gettitle{$p{$_}&&($p{PageTitle}=ref($pagetitles{$_}) eq 'CODE' ? &{$pagetitles{$_}} : $pagetitles{$_}) for (keys%pagetitles);} - - -# -# F O R M E R R O R H A N D L I N G -# -my %formerr_names = ( - # this list is rather incomplete... - mail => 'Email', - username => 'Username', - userpass => 'Password', - pass1 => 'Password', - pass2 => 'Password (second)', - title => 'Title', - desc => 'Description', - rel => 'Relation', - romaji => 'Romanized title', - lang => 'Language', - web => 'Website', - released => 'Release date', - platforms => 'Platforms', - media => 'Media', - name => 'Name', - vn => 'Visual novel relations', - l_vnn => 'Visual-novels.net link', - comm => 'Edit summary', - msg => 'Message', -); -my @formerr_msgs = ( - sub { return sprintf 'Field "%s" is required.', @_ }, - sub { return sprintf '%s should have at least %d characters.', @_ }, - sub { return sprintf '%s is too large! Only %d characters allowed.', @_ }, - sub { return - $_[1] eq 'mail' ? 'Invalid email address' : - $_[1] eq 'url' ? 'Invalid URL' : - $_[1] eq 'pname' ? sprintf('%s can only contain alfanumeric characters!', $_[0]) : - $_[1] eq 'asciiprint' ? sprintf('Only ASCII characters are allowed at %s', $_[0]) : - $_[1] eq 'int' ? sprintf('%s should be a number!', $_[0]) : - $_[1] eq 'gtin' ? 'Not a valid JAN, UPC or EAN code!' : ''; - }, - sub { return sprintf '%s: invalid item selected', @_ }, - sub { return 'Invalid unicode, are you sure your browser works fine?' }, -); -my %formerr_exeptions = ( - loginerr => 'Invalid username or password', - badpass => 'Passwords do not match', - usrexists => 'Username already exists, please choose an other one', - mailexists => 'There already is a user with that email address, please request a new password if you forgot it', - nomail => 'No user found with that email address', - nojpeg => 'Image is not in JPEG or PNG format!', - toolarge => 'Image is too large (in filesize), try to compress it a little', - wrongtag => 'Wrong tag selected!', -); -sub formerr { - my @err = ref $_[0] eq 'ARRAY' ? @{$_[0]} : (); - return '' if $#err < 0; - my @msgs; - my $ret = '<span class="warning"> - Error:<ul>'; - $ret .= sprintf " <li>%s</li>\n", - /^([a-z0-9_]+)-([0-9]+)(?:-(.+))?$/ ? &{$formerr_msgs[$2-1]}($formerr_names{$1}||$1, $3||'') : $formerr_exeptions{$_} - foreach (@err); - $ret .= "</ul>\n</span>\n"; -} - -# -# F O R M C R E A T I N G -# - -# args = [ -# { -# type => $type, -# %options -# }, ... -# ], $formobj -# -# $type $formobj %options ( required, [ optional ] ) -# error X ( ) -# startform ( action, [ upload ] ) -# endform ( ) -# input X ( short, name, [ class, default ] ) -# pass ( short, name ) -# upload ( short, name, [ class ] ) -# hidden X ( short, [ value ] ) -# textarea X ( short, name, [ rows, cols, class ] ) -# select X ( short, name, options, [ class ] ) # options = arrayref of hashes with keys: short, name -# as X ( name ) -# trans X ( ) -# submit ( [ text, short ] ) -# sub ( title ) -# check X ( short, name, [ value ] ) -# static ( text, raw [ name, class ] ) -# date X ( short, name ) -# -sub cform { - my $obj = shift; - my $frm = shift; - my $ret = ''; - my $csub = ''; - for (@$obj) { - $_->{class} ||= ''; - $_->{class} .= ' sf_'.$csub if $csub && $_->{class} !~ /nohid/; - $_->{class} .= ' formhid' if $csub && $frm->{_hid} && !$frm->{_hid}{$csub} && $_->{class} !~ /nohid/; - $_->{name} = '<i>*</i> '.$_->{name} if $_->{r}; - - # error - if($_->{type} eq 'error') { - $ret .= formerr($frm->{_err}); - # startform - } elsif($_->{type} eq 'startform') { - $ret .= sprintf qq|<form action="/nospam?%s" method="post" accept-charset="utf-8"%s>\n|, - $_->{action}, $_->{upload} ? ' enctype="multipart/form-data"' : ''; - $ret .= sprintf qq| <input type="hidden" class="hidden" name="fh" id="_hid" value="%s" />\n|, - $frm->{_hid} ? _hchar(join(',', keys %{$frm->{_hid}})) : '' if $_->{fh}; - $ret .= qq|<p class="formnotice">Items denoted by a red asterisk (<i>*</i>) are required.</p>\n| - if scalar grep { $_->{r} } @$obj; - $ret .= "<ul>\n"; - # endform - } elsif($_->{type} eq 'endform') { - $ret .= qq|</ul></form>\n|; - # input - } elsif($_->{type} eq 'input') { - $ret .= sprintf qq|<li%s>\n <label for="%s">%s</label>\n %s<input type="text" class="text" name="%2\$s" id="%2\$s" value="%s" />%s\n</li>\n|, - $_->{class} ? ' class="'.$_->{class}.'"' : '', $_->{short}, $_->{name}, $_->{pre} ? '<i>'.$_->{pre}.'</i>' : '', - _hchar($frm->{$_->{short}}?$frm->{$_->{short}}:$_->{default}), $_->{post} ? '<i>'.$_->{post}.'</i>' : ''; - # pass - } elsif($_->{type} eq 'pass') { - $ret .= sprintf qq|<li%s>\n <label for="%s">%s</label>\n <input type="password" class="text" name="%2\$s" id="%2\$s" />\n</li>\n|, - $_->{class} ? ' class="'.$_->{class}.'"' : '', $_->{short}, $_->{name}; - # upload - } elsif($_->{type} eq 'upload') { - $ret .= sprintf qq|<li%s>\n <label for="%s">%s</label>\n <input type="file" class="text" name="%2\$s" id="%2\$s" />\n</li>\n|, - $_->{class} ? ' class="'.$_->{class}.'"' : '', $_->{short}, $_->{name}; - # hidden - } elsif($_->{type} eq 'hidden') { - $ret .= sprintf qq| <input type="hidden" class="hidden" name="%s" id="%1\$s" value="%s" />\n|, - $_->{short}, _hchar($_->{value} || $frm->{$_->{short}}); - # textarea - } elsif($_->{type} eq 'textarea') { - $ret .= sprintf qq|<li%s>\n <label for="%s">%s</label>\n <textarea name="%2\$s" id="%2\$s" rows="%s" cols="%s">%s</textarea>\n</li>\n|, - $_->{class} ? ' class="'.$_->{class}.'"' : '', $_->{short}, $_->{name}, $_->{rows}||15, $_->{cols}||70, txt($frm->{$_->{short}}); - # select - } elsif($_->{type} eq 'select') { - $ret .= sprintf qq|<li%s>\n <label for="%s">%s</label>\n <select name="%2\$s" id="%2\$s">\n%s</select>\n</li>\n|, - $_->{class} ? ' class="'.$_->{class}.'"' : '', $_->{short}, $_->{name}, eval { - my $r=''; - for my $s (@{$_->{options}}) { - $r .= sprintf qq| <option value="%s"%s>%s</option>\n|, - $s->{short}, defined $frm->{$_->{short}} && $frm->{$_->{short}} eq $s->{short} ? ' selected="selected"' : '', $s->{name}; - } - return $r; - }; - # jssel - } elsif($_->{type} eq 'jssel') { - (my $oname = $_->{name}) =~ s/^<i>\*<\/i>//; - $ret .= sprintf - qq|<li%s>\n| - .qq| <label for="%s_select">%s</label>\n| - .qq| <select name="%s_select" id="%s_select" multiple="multiple" size="5" class="multiple">\n| - .qq| <option value="0_new" style="font-style: italic">Add %s...</option>\n| - .qq| </select>\n| - .qq| <div id="%s_conts">\n| - .qq| Loading...\n| - .qq| </div>\n| - .qq| <input type="hidden" name="%s" id="%s" class="hidden" value="%s" />\n| - .qq|</li>\n|, - $_->{class} ? ' class="'.$_->{class}.'"' : '', - $_->{sh}, $_->{name}, $_->{sh}, $_->{sh}, $oname, $_->{sh}, $_->{short}, $_->{short}, _hchar($frm->{$_->{short}}); - # submit - } elsif($_->{type} eq 'submit') { - $ret .= sprintf qq|<li class="nolabel">\n <br /><input type="submit" class="submit" value="%s"%s />\n </li>\n|, - $_->{text} || 'Verstuur', $_->{short} ? sprintf(' name="%s" id="%1$s"', $_->{short}) : ''; - # sub - } elsif($_->{type} eq 'sub') { - $ret .= sprintf qq|<li class="subform">\n <a href="#" class="s_%s">%s %s</a>\n</li>\n|, - $_->{short}, $frm->{_hid} && !$frm->{_hid}{$_->{short}} ? '▸' : '▾', $_->{title}; - $csub = $_->{short}; - # check - } elsif($_->{type} eq 'check') { - $ret .= sprintf qq|<li class="nolabel%s">\n <input type="checkbox" name="%s" id="%2\$s" value="%s"%s />\n <label for="%2\$s" class="checkbox">%s</label>\n</li>\n|, - $_->{class} ? ' '.$_->{class} : '', - $_->{short}, $_->{value} || 'true', $frm->{$_->{short}} ? ' checked="checked"' : '', $_->{name}; - # static - } elsif($_->{type} eq 'static') { - $ret .= $_->{name} - ? sprintf qq|<li%s>\n <label>%s</label>\n <p>%s</p>\n</li>|, $_->{class} ? ' class="'.$_->{class}.'"' : '', $_->{name}, $_->{text} - : $_->{raw} - ? sprintf qq|<li%s>\n %s\n</li>|, $_->{class} ? ' class="'.$_->{class}.'"' : '', $_->{text} - : sprintf qq|<li class="nolabel%s">\n %s\n</li>|, $_->{class} ? ' '.$_->{class} : '', $_->{text}; - # date - } elsif($_->{type} eq 'date') { - $ret .= sprintf qq|<li class="date%s">\n <label for="%s">%s</label>\n|, - $_->{class} ? ' '.$_->{class} : '', $_->{short}, $_->{name}; - $ret .= sprintf qq| <select name="%s" id="%s">\n%s</select>\n|, - $_->{short}, $_->{short}, eval { - my $r=''; - for my $s (0, 1980..((localtime())[5]+1905), 9999) { - $r .= sprintf qq| <option value="%s"%s>%s</option>\n|, - $s, $frm->{$_->{short}} && ($frm->{$_->{short}}[0]||0) == $s ? ' selected="selected"' : '', - !$s ? '-year-' : $s < 9999 ? $s : 'TBA'; - } - return $r; - }; - $ret .= sprintf qq| <select name="%s" id="%s_m">\n%s</select>\n|, - $_->{short}, $_->{short}, eval { - my $r=''; - for my $s (0..12) { - $r .= sprintf qq| <option value="%s"%s>%s</option>\n|, - $s, $frm->{$_->{short}} && ($frm->{$_->{short}}[1]||0) == $s ? ' selected="selected"' : '', - $s ? $Time::CTime::MonthOfYear[$s-1] : '-month-'; - } - return $r; - }; - $ret .= sprintf qq| <select name="%s" id="%s_d">\n%s</select>\n</li>\n|, - $_->{short}, $_->{short}, eval { - my $r=''; - for my $s (0..31) { - $r .= sprintf qq| <option value="%s"%s>%s</option>\n|, - $s, $frm->{$_->{short}} && ($frm->{$_->{short}}[2]||0) == $s ? ' selected="selected"' : '', - $s ? $s : '-day-'; - } - return $r; - }; - } - } - return $ret; -} - -]] diff --git a/data/tpl/docs b/data/tpl/docs deleted file mode 100644 index 6aeefe81..00000000 --- a/data/tpl/docs +++ /dev/null @@ -1,4 +0,0 @@ -<h2>[[: $p{PageTitle} ]]</h2> -<div id="dpage"> -[[= $d{content} ]] -</div> diff --git a/data/tpl/error b/data/tpl/error deleted file mode 100644 index 995293d1..00000000 --- a/data/tpl/error +++ /dev/null @@ -1,10 +0,0 @@ -<h2>[[: $p{PageTitle} ]]</h2> -[[ if($d{err} eq 'notfound') { ]] - The page you were looking for could not be found! - -[[ } elsif($d{err} eq 'formerr') { ]] -<span class="warning"> - <b>Error:</b> The form could not be sent, please make sure you have Javascript - enabled in your browser! -</span> -[[ } ]] diff --git a/data/tpl/hist b/data/tpl/hist deleted file mode 100644 index fd8863b4..00000000 --- a/data/tpl/hist +++ /dev/null @@ -1,102 +0,0 @@ -[[= $d{type} ? ttabs($d{type}, $d{obj}, 'hist') : '' ]]- -<h2 class="rss">[[: $p{PageTitle} ]]</h2> -[[ if($d{type} eq 'u' && $#{$d{hist}} < 0) { ]] -<p> - You haven't made any changes yet. -</p> -[[ } ]] -<br /><br /> - -[[ - my $url = !$d{type} ? '/hist' : '/'.$d{type}.$d{id}.'/hist'; - my $furl = $url.'?e='.$d{sele}.';t='; - my $eurl = $url.'?t='.$d{selt}.';e='; - my $purl = !$d{type}?$eurl.$d{sele}:$d{type} eq 'v' && $d{seli} ? $url.'?i=1' : $url; - my $rurl = $url.'/rss.xml'.(!$d{type}?'?t='.$d{selt}.';e='.$d{sele}:$d{type} eq 'v' && $d{seli} ? '?i=1' : ''); - local $_ = $d{selt}; - my @fil = ( - /a/ ? 'all items' : '<a href="%sa">all items</a>', - /v/ ? 'visual novels' : '<a href="%sv">visual novels</a>', - /r/ ? 'releases' : '<a href="%sr">releases</a>', - /p/ ? 'producers' : '<a href="%sp">producers</a>', - ); - local $_ = $d{sele}; - my @edi = ( - /0/ ? 'all changes' : '<a href="%s0">all changes</a>', - /2/ ? 'edits only' : '<a href="%s2">edits only</a>', - /1/ ? 'newly created pages only' : '<a href="%s1">newly created pages only</a>', - ); - local $_ = $d{seli}; - my @inc = ( - /0/ ? 'exclude' : '<a href="'.$url.'">exclude</a>', - /1/ ? 'include' : '<a href="'.$url.'?i=1">include</a>', - ); -]] - -[[ if(!$d{type}) { ]]- -<p class="browse"> - [[= join(' | ', map { sprintf $_, $furl } @fil) ]]<br /> - [[= join(' | ', map { sprintf $_, $eurl } @edi) ]]<br /><br /><br /> -</p> -[[ } if($d{type} eq 'v') { ]]- -<p class="browse"> - ([[= join(' | ', @inc) ]]) edits of releases. -</p> -[[ } ]] - -[[ if($d{act} eq 'r') { ]] -<span class="msg"> - Performed the mass-revert, please see the following list for details. -</span> -[[ } elsif($d{act} eq 'd') { ]] -<span class="msg"> - The following edits have been completely deleted. -</span> -[[ } ]]- - - -<a class="rss" href="[[= $rurl ]]">RSS</a> -[[= pagebut($purl) ]] -[[ if(0 and $p{Authmod} || $p{Authdel}) { ]] -<form method="post" action="[[= $purl ]]" class="tblf"> -[[ } ]] -<table id="thi"> - <thead><tr> - <td class="tc1" colspan="2">Rev.</td> - <td class="tc2">Date</td> - [[ if($d{type} ne 'u' || $d{act}) { ]]- - <td class="tc3">User</td>[[ } ]]- - [[ if(!$d{type} || $d{type} eq 'u' || $d{act}) { ]]- - <td class="tc4">Page</td>[[ } ]]- - [[ if($d{type} && !$d{act}) { ]]- - <td class="tc5">Summary</td>[[ } ]]- - [[ if($d{act} eq 'r') { ]]- - <td class="tc5">Action</td>[[ } ]]- - [[ if(0 and $p{Authmod}) { ]]- - <td class="tc6"><input type="checkbox" id="checkall" name="sel" value="all" /></td>[[ } ]]- - </tr></thead> - - [[ for (@{$d{hist}}) { my $t = (qw|v r p|)[$_->{type}]; ]]- - <tr> - <td class="tc1_1"><a href="/[[= $t.$_->{iid}.'.'.$_->{rev} ]]">[[= $_->{rev} == 1 ? "<b>$t$_->{iid}</b>" : $t.$_->{iid} ]]</a></td> - <td class="tc1_2"><a href="/[[= $t.$_->{iid}.'.'.$_->{rev} ]]">.[[= $_->{rev} == 1 ? '<b>'.$_->{rev}.'</b>' : $_->{rev} ]]</a></td> - <td class="tc2">[[= formatdate('%Y-%m-%d %R', $_->{added}, 'dh') ]]</td> - [[ if($d{type} ne 'u' || $d{act}) { ]]- - <td class="tc3">[[= userstr $_ ]]</td>[[ } ]]- - [[ if(!$d{type} || $d{type} eq 'u' || $d{act}) { ]]- - <td class="tc4"><a href="/[[= $t.$_->{iid} ]].[[= $_->{rev} ]]" title="[[: $_->{ioriginal}||$_->{ititle} ]]">[[: shorten $_->{ititle}, 30 ]]</a></td>[[ } ]]- - [[ if($d{type} && !$d{act}) { ]]- - <td class="tc5">[[= summary($_->{comments}, $d{type} eq 'u' ? 40 : 60)||'[empty]' ]]</td>[[ } ]]- - [[ if($d{act} eq 'r') { ]]- - <td class="tc5">[[: $_->{_status} ]]</td>[[ } ]]- - [[ if(0 and $p{Authmod} && !$d{act}) { ]]- - <td class="tc6"><input type="checkbox" name="sel" value="[[= $_->{id} ]]" /></td>[[ } ]]- - </tr> - [[ } ]] - -</table> -[[ if(0 and $p{Authmod}) { ]]<input type="submit" class="right" name="post" value="Mass revert" />[[ } ]] -[[ if(0 and $p{Authdel}) { ]]<input type="submit" class="right" name="post" value="Mass delete" id="massdel" />[[ } ]] -[[ if(0 and $p{Authmod} || $p{Authdel}) { ]]</form>[[ } ]] -[[= pagebut($purl) ]] - diff --git a/data/tpl/home b/data/tpl/home deleted file mode 100644 index 3b36246d..00000000 --- a/data/tpl/home +++ /dev/null @@ -1,66 +0,0 @@ -<h2>Welcome to VNDB - The Visual Novel Database!</h2> -<p class="desc"> - <br /> - VNDB.org strives to be a comprehensive database for information about visual novels and - eroge.<br /> - This website is built as a wiki, meaning that anyone can freely add and contribute information - to the database, allowing us to create the largest, most accurate and most up-to-date visual novel - database on the web.<br /> - Registered users are also able to keep track of a personal list of games they want to play or have finished - and they can vote on all visual novels.<br /><br /> - - Feel free to <a href="/v">browse around</a>, <a href="/u/register">register an account</a> - or to participate in the discussions about visual novels or VNDB on our <a href="/t">discussion board</a>. -</p> - -[[ if($d{an}{title}) { ]]- -<h3 class="home">[[: $d{an}{title} ]]- - <p class="actions">[[= age $d{anpost}{date} ]]</p></h3> -<p class="desc"> - [[= summary $d{anpost}{msg}, 200 ]] - <br /> - <a href="/t[[= $d{an}{id} ]]">Read more...</a> - <a href="/t/an">news archive</a>. -</p> -[[ } ]]- - -<ul class="home"> - <li><b>Recent changes</b></li> - [[ for (@{$d{recentedits}}) { my $t = (qw|v r p|)[$_->{type}]; ]]- - <li>[[= $t ]]:<a href="/[[= $t.$_->{iid}.'.'.$_->{rev} ]]" title="[[: $_->{ioriginal}||$_->{ititle} ]]">[[: shorten $_->{ititle}, 30 ]]</a></li> - [[ } ]]- -</ul> - -<ul class="home"> - <li><b>Recent posts</b></li> - [[ for (@{$d{recentposts}}) { ]]- - <li><a href="/t[[= $_->{id}.'.'.$_->{count} ]]" title="[[: $_->{original}||$_->{title} ]]">[[: shorten $_->{title}, 25 ]]</a> <i>[[= age $_->{ldate}, 1 ]]</i></li> - [[ } ]]- -</ul> - -<ul class="home"> - <li><b>Upcoming releases</b></li> - [[ for (@{$d{upcomingrel}}) { ]]- - <li>[[= datestr $_->{released}, 1 ]]- <a href="/r[[= $_->{id} ]]" title="[[: $_->{original}||$_->{title} ]]">[[: shorten $_->{title}, 25 ]]</a></i></li> - [[ } ]]- -</ul> - -<ul class="home break"> - <li><b>Recently added visual novels</b></li> - [[ for (@{$d{recentvns}}) { ]]- - <li><a href="/v[[= $_->{iid} ]]" title="[[: $_->{ioriginal}||$_->{ititle} ]]">[[: shorten $_->{ititle}, 30 ]]</a></li> - [[ } ]]- -</ul> - -<ul class="home"> - <li><b>Random visual novels</b></li> - [[ for (@{$d{randomvns}}) { ]]- - <li><a href="/v[[= $_->{id} ]]" title="[[: $_->{original}||$_->{title} ]]">[[: shorten $_->{title}, 30 ]]</a></li> -[[ } ]]- -</ul> - -<ul class="home"> - <li><b>Just released</b></li> - [[ for (@{$d{justrel}}) { ]]- - <li>[[= datestr $_->{released}, 1 ]]- <a href="/r[[= $_->{id} ]]" title="[[: $_->{original}||$_->{title} ]]">[[: shorten $_->{title}, 25 ]]</a></i></li> - [[ } ]]- -</ul> diff --git a/data/tpl/main b/data/tpl/main deleted file mode 100644 index a9c4a69d..00000000 --- a/data/tpl/main +++ /dev/null @@ -1,161 +0,0 @@ -[[+ defs.pl ]] -[[ %p = %{$X->{page}}; gettitle(); ]] - -<!DOCTYPE html - PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> - -<head> - <title>[[: $p{PageTitle} ]]- :: VNDB</title> - <link href="[[: $p{st} ]]/files/style.css?[[= $VNDB::VERSION ]]" rel="stylesheet" type="text/css" media="screen" /> - <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" /> -[[ if($p{redit} || $p{vnedit}) { ]]- - <script src="[[: $p{st} ]]/files/dyna.js?[[= $VNDB::VERSION ]]" type="text/javascript"></script> -[[ } ]]- - <script src="[[: $p{st} ]]/files/def.js?[[= $VNDB::VERSION ]]" type="text/javascript"></script> -[[ if(0 && $p{devshit}) { ]]- - <link rel="icon" href="/favicon.gif" type="image/gif" /> - <meta name="robots" content="noindex, nofollow" /> -[[ } elsif( - grep($p{$_}, qw| userlist userpage userlogin userreg userpass vnlist rlist wlist hist |) - || ($p{ttag} && $p{ttag}{iid}) - || ($p{vnpage} && $p{vnpage}{page} eq 'stats') - || grep { $p{$_} && $p{$_}{change} } qw|vnpage ppage rpage| - ) { ]]- - <meta name="robots" content="noindex, follow" /> -[[ }]]- - -[[if($p{hist}){ ]] - <link rel="alternate" type="application/rss+xml" title="Recent changes" href=" - [[= (!$p{hist}{type}?'/hist':'/'.$p{hist}{type}.$p{hist}{id}.'/hist').'/rss.xml'.(!$p{hist}{type}?'?t='.$p{hist}{selt}.';e='.$p{hist}{sele}:$p{hist}{type} eq 'v' && $p{hist}{seli} ? '?i=1':'') ]]" /> -[[ } ]]- -</head> - -<body> -<div id="header"> - <form id="search" method="get" action="/v/search"> - <fieldset> - <legend>Search</legend> - <input id="searchfield" type="text" name="sq" value="search" style="color: #999" /> - <input id="searchsubmit" type="submit" value="Search" /> - </fieldset> - </form> - <h1><a href="http://vndb.org/">vndb.org</a> / #vndb @ irc.synirc.net <a href="/"> - [[ if($p{devshit}) { ]]<b style="color: red">The VNDB.org Testing Grounds</b>[[ } else { ]]<b>The Visual Novel Database</b>[[ } ]]</a></h1> -</div> - - -<div id="page"> - -<div id="content"> -[[ # = noindex-tag (see above) ]] -[[ if($p{home}) { %d = %{$p{home}}; ]] [[+ home ]][[ } ]] -[[ if($p{userlogin}) { %d = %{$p{userlogin}}; ]] [[+ userlogin ]][[ } ]] -[[ if($p{userreg}) { %d = %{$p{userreg}}; ]] [[+ userreg ]][[ } ]] -[[ if($p{userpass}) { %d = %{$p{userpass}}; ]] [[+ userpass ]][[ } ]] -[[ if($p{useredit}) { %d = %{$p{useredit}}; ]] [[+ useredit ]][[ } ]] -[[ if($p{userlist}) { %d = %{$p{userlist}}; ]] [[+ userlist ]][[ }# ]] -[[ if($p{userpage}) { %d = %{$p{userpage}}; ]] [[+ userpage ]][[ }# ]] -[[ if($p{vnpage}) { %d = %{$p{vnpage}}; ]] [[+ vnpage ]][[ } ]] -[[ if($p{vnedit}) { %d = %{$p{vnedit}}; ]] [[+ vnedit ]][[ } ]] -[[ if($p{redit}) { %d = %{$p{redit}}; ]] [[+ redit ]][[ } ]] -[[ if($p{vnbrowse}) { %d = %{$p{vnbrowse}}; ]] [[+ vnbrowse ]][[ } ]] -[[ if($p{pbrowse}) { %d = %{$p{pbrowse}}; ]] [[+ pbrowse ]][[ } ]] -[[ if($p{pedit}) { %d = %{$p{pedit}}; ]] [[+ pedit ]][[ } ]] -[[ if($p{ppage}) { %d = %{$p{ppage}}; ]] [[+ ppage ]][[ } ]] -[[ if($p{vnlist}) { %d = %{$p{vnlist}}; ]] [[+ vnlist ]][[ }# ]] -[[ if($p{rlist}) { %d = %{$p{rlist}}; ]] [[+ rlist ]][[ }# ]] -[[ if($p{wlist}) { %d = %{$p{wlist}}; ]] [[+ wlist ]][[ }# ]] -[[ if($p{hist}) { %d = %{$p{hist}}; ]] [[+ hist ]][[ }# ]] -[[ if($p{rpage}) { %d = %{$p{rpage}}; ]] [[+ rpage ]][[ } ]] -[[ if($p{docs}) { %d = %{$p{docs}}; ]] [[+ docs ]][[ } ]] -[[ if($p{tindex}) { %d = %{$p{tindex}}; ]] [[+ tindex ]][[ } ]] -[[ if($p{ttag}) { %d = %{$p{ttag}}; ]] [[+ ttag ]][[ }# ]] -[[ if($p{tthread}) { %d = %{$p{tthread}}; ]] [[+ tthread ]][[ } ]] -[[ if($p{tedit}) { %d = %{$p{tedit}}; ]] [[+ tedit ]][[ } ]] -[[ if($p{error}) { %d = %{$p{error}}; ]] [[+ error ]][[ } ]] -</div> - - -<div id="side"><div><div> - - <h2>Menu</h2> - <ul> - <li><a href="/">Home</a></li> - <li><a href="/v">Browse</a> | <a href="/v/search">Search</a></li> - <li><a href="/p">Producers</a></li> - <li><a href="/u/list">Users</a></li> - <li><a href="/hist">Recent changes</a></li> - <li><a href="/t">Discussion board</a></li> - <li><a href="/d6">FAQ</a></li> - </ul> - --[[ if(!$p{AuthLoggedin}) { ]]- - <h2>Login</h2> - <form method="post" action="/nospam?/u/login" id="loginform"> - <fieldset> - <legend>Login</legend> - <input type="text" id="usrname" name="username" /> - <input type="password" id="usrpass" name="userpass" /> - <input type="submit" value="Login" /> - </fieldset> - </form> - <p> - <a href="/u/register">register</a> or <a href="/u/newpass">forgot password?</a> - </p> -[[ } else { ]]- - <h2>User menu</h2> - <ul> - <li><a href="/u[[= $p{AuthId} ]]">[[: $p{AuthUsername} ]]</a> ([[: $p{AuthRankname} ]])</li> - <li><a href="/u[[= $p{AuthId} ]]/edit">My profile</a></li> - <li><a href="/u[[= $p{AuthId} ]]/list">My visual novel list</a></li> - [[ if($p{AuthOldList}) { ]]- - <li><a href="/u[[= $p{AuthId} ]]/vlist">My visual novel list (old)</a></li>[[ } ]]- - <li><a href="/u[[= $p{AuthId} ]]/wish">My wishlist</a></li> - <li><a href="/t/u[[= $p{AuthId} ]]">My messages</a></li> - <li><a href="/u[[= $p{AuthId} ]]/hist">My recent changes</a></li> - [[ if($p{Authedit}) { ]]- - <li> </li> - <li><a href="/v/new">Add visual novel</a></li> - <li><a href="/p/add">Add producer</a></li> - [[ } ]] - <li> </li> - <li><a href="/u/logout">Logout</a></li> - </ul> -[[ } ]]- - --[[ #</div></div><div><div> ]] - <h2>Statistics</h2> - <ul> - <li><b>[[= $p{Statvn}||0 ]]</b> visual novels</li> - <li><b>[[= $p{Statproducers}||0 ]]</b> producers</li> - <li><b>[[= $p{Statreleases}||0 ]]</b> releases</li> - <li><b>[[= $p{Statusers}||0 ]]</b> users</li> - </ul> -[[ if(0) { ]] <h2>Most popular</h2> - <ul>[[ for (@{$p{popular}}) { ]]- - <li><a href="/v[[: $_->{id} ]]" title="[[: $_->{title} ]]">[[: length($_->{title})>30 ? (substr($_->{title}, 0, 27).'...') : $_->{title} ]]</a></li>[[ } ]]- - <li class="more"><a href="/v/all?s=votes&o=d">More...</a></li> - </ul>[[ } ]]- -</div></div></div> - -</div> - -<div id="footer"> - <p> - vndb v[[: $VNDB::VERSION ]]- | - <a href="/d7">about us</a> | - <a href="mailto:contact@vndb.org">contact@vndb.org</a> (english only) | - designed by <a href="http://www.freecsstemplates.org/">free css templates</a>. - </p> -</div> - --[[ if(0 && $p{devshit}) { ]]- - <pre id="debug">SQL Queries used:<br /> -[[= $p{devshit} ]] -</pre> -[[ } ]]- - -</body> -</html> diff --git a/data/tpl/pbrowse b/data/tpl/pbrowse deleted file mode 100644 index 8d2604c3..00000000 --- a/data/tpl/pbrowse +++ /dev/null @@ -1,45 +0,0 @@ -<h2>[[: $p{PageTitle} ]]</h2> -<p class="chr"> - -[[= $d{chr} ne 'all' ? '<a href="/p/all">all</a>' : 'all' ]]- | - [[ for('a'..'z', 0) { ]]- - -[[ if($d{chr} eq $_) { ]][[= $_?$_:'#' ]][[ } else { ]]<a href="/p/[[= $_ ]]">[[= $_?$_:'#' ]]</a>[[ } ]] - [[ } ]]- - <form id="psearch" method="get" action="/p" accept-charset="UTF-8"> - <fieldset> - <input type="text" name="q" id="q" value="[[: $d{query} ]]" class="text" - /><input type="submit" value="Search!" /> - </fieldset> - </form> -</p> - --[[ if($#{$d{prods}} < 0) { ]] -<p> - No results again, life sucks... :'( -</p> -[[ } else { - my $url = sprintf '/p/%s', $d{chr}; - $url .= '?q='.$d{query} if $d{query}; -]] -[[= pagebut($url) ]] -<table id="tpd"> - <thead><tr> - <td class="tc1">Name</td> - <td class="tc2">Type</td> - <td class="tc3">Website</td> - </tr></thead> -[[ for (@{$d{prods}}) { ]]- - <tr> - <td class="tc1"> - <acronym class="icons lang -[[= $_->{lang} ]]" title="[[: $VNDB::LANG->{$_->{lang}} ]]"> </acronym><a - href="/p[[= $_->{id} ]]" title="[[: $_->{original}||$_->{name} ]]">[[: $_->{name} ]]</a></td> - <td class="tc2">[[: $VNDB::PROT->{$_->{type}} ]]</td> - <td class="tc3"> - [[ if($_->{website}) { ]] - <a href="[[: $_->{website} ]]">[[: shorten $_->{website}, 50 ]] - [[ } else { ]]---[[ } ]] - </td> - </tr> -[[ } ]]- -</table> -[[= pagebut($url) ]] -[[ } ]] diff --git a/data/tpl/pedit b/data/tpl/pedit deleted file mode 100644 index 56c06b92..00000000 --- a/data/tpl/pedit +++ /dev/null @@ -1,44 +0,0 @@ -[[= $d{id} ? ttabs('p', $d{prod}, 'edit') : '' ]] -<h2>[[: $p{PageTitle} ]]</h2> --[[ if(!$d{id}) { ]] - <span class="msg"> - Please search the database before adding a new producer in order to prevent duplicate entries. - </span> -[[ } else { ]] - <span class="msg"> - Please check the <a href="/t/p[[= $d{id} ]]">discussion board</a> <b>before</b> making - any changes! - </span> -[[ } if($d{id} && $d{prod}{cid} != $d{prod}{latest}) { ]] - <span class="warning"> - You are editing an old revision of this producer. If you save it, all changes made after - -[[= formatdate('%Y-%m-%d %R', $d{prod}{added}) ]]- will be removed! - </span> -[[ } ]] - --[[= cform([ - { type => 'error' }, - { type => 'startform', action => $d{id} ? '/p'.$d{id}.'/edit' : '/p/add' }, - - { type => 'sub', title => 'General info', short => 'info' }, - { type => 'select', name => 'Type', short => 'type', r=>1, options => [ map { - { short => $_, name => $VNDB::PROT->{$_} } } sort keys %$VNDB::PROT ] }, - { type => 'input', name => 'Name (romaji)', short => 'name', r=>1 }, - { type => 'input', name => 'Original name', short => 'original' }, - { type => 'static', text => q| - The original name of the producer, leave blank if it is already in the Latin alphabet.<br /><br />| }, - - { type => 'select', name => 'Primary language', short => 'lang', r=>1, options => [ map { - ({ short => $_, name => sprintf '%s (%s)', $_, $VNDB::LANG->{$_} }) } sort keys %{$VNDB::LANG} ] }, - - { type => 'input', name => 'Website', short => 'website' }, - { type => 'textarea', name => 'Description', short => 'desc', rows => 7, cols => 60 }, - - { type => 'sub', title => 'Edit summary', short => 'com' }, - { type => 'textarea', name => 'Edit summary', short => 'comm', rows => 3, cols => 60 }, - { type => 'static', text => 'Please explain your modifications and cite all sources.' }, - - { type => 'submit', text => $d{id} ? 'Edit' : 'Add' }, - { type => 'endform' }, - -], $d{form}) ]] diff --git a/data/tpl/ppage b/data/tpl/ppage deleted file mode 100644 index e0a1fa08..00000000 --- a/data/tpl/ppage +++ /dev/null @@ -1,55 +0,0 @@ -[[= ttabs('p', $d{prod}) ]] -<h2>[[: $p{PageTitle} ]]</h2> -[[ if($d{prod}{original}) { ]]<h3 class="alttitle">[[: $d{prod}{original} ]]</h3>[[ } ]] - -[[ if($d{prod}{hidden}) { ]]- - <span class="warning"> - This item has been deleted from the database. File a request on the - <a href="/t/p[[= $d{prod}{id} ]]">discussion board</a> to undelete this page. - </span> -[[ } ]] -[[ if(!$d{prod}{hidden} || $p{Authdel}) { ]]- - - - -[[ if($d{change}) { ]] -[[= cdiff($d{prev}, $d{prod}, - [ type => 'Type', sub { $VNDB::PROT->{$_[0]} } ], - [ name => 'Name (romaji)', 1 ], - [ original => 'Original name', 1 ], - [ lang => 'Language', sub { $VNDB::LANG->{$_[0]} } ], - [ website => 'Website', 1 ], - [ desc => 'Description', 1, 1 ], - ) ]] -[[ } ]] - -<dl> - <dt>Type</dt><dd>[[: $VNDB::PROT->{$d{prod}{type}} ]]</dd> - <dt>Primary lang.</dt><dd>[[: $VNDB::LANG->{$d{prod}{lang}} ]]</dd> -[[ if($d{prod}{website}) { ]]- - <dt>Links</dt><dd><a href="[[: $d{prod}{website} ]]">Official homepage</a></dd>[[ } ]]- -</dl> - --[[ if($d{prod}{desc}) { ]] -<p>[[= summary($d{prod}{desc}) ]]<br /><br /></p> -[[ } ]] - - -<h3>Visual novel relations</h3> -[[ if($#{$d{vn}} < 0) { ]]- -<p> - We have currently no visual novels related to this producer. -</p> -[[ } else { ]]- -<ul> - [[ for (@{$d{vn}}) { ]]- - <li><a href="/v[[= $_->{id} ]]">[[: $_->{title} ]]</a> - [[ if($_->{date} ne "0000-00-00") { ]]- ([[= datestr($_->{date}) ]])[[ } ]] - </li> - [[ } ]]- -</ul> -[[ } ]] - - - -[[ } ]] diff --git a/data/tpl/redit b/data/tpl/redit deleted file mode 100644 index 32d618e3..00000000 --- a/data/tpl/redit +++ /dev/null @@ -1,69 +0,0 @@ -[[= $d{id} ? ttabs('r', $d{rel}, 'edit') : ttabs('v', $d{vn}, 'edit') ]]- -<h2>[[: $p{PageTitle} ]]</h2> - -[[ if($d{id}) { ]] - <span class="msg"> - Please check the <a href="/t/v[[= $d{rel}{vn}[0]{vid} ]]">discussion board</a> <b>before</b> making - any changes! - </span> -[[ } if($d{id} && $d{rel}{cid} != $d{rel}{latest}) { ]] - <span class="warning"> - You are editing an old revision of this producer. If you save it, all changes made after - -[[= formatdate('%Y-%m-%d %R', $d{rel}{added}) ]]- will be removed! - </span> -[[ } ]] - -[[= cform( [ - { type => 'error' }, - { type => 'startform', action => $d{id} ? sprintf('/r%d/edit', $d{rel}{id}) : '/v'.$d{vn}{id}.'/add', fh => 1 }, - - { type => 'sub', title => 'General info', short => 'info' }, - { type => 'select', name => 'Type', short => 'type', r=>1, options => [ map { - ({ short => $_, name => $VNDB::RTYP->[$_] }) } 0..$#{$VNDB::RTYP} ] }, - - { type => 'input', name => 'Title (romaji)', short => 'title', r=>1 }, - { type => 'input', name => 'Original title', short => 'original' }, - { type => 'static', text => q| - The original title of this release, leave blank if it already is in the Latin alphabet.<br /><br />| }, - - { type => 'select', name => 'Language', short => 'language', r=>1, options => [ map { - ({ short => $_, name => sprintf '%s (%s)', $_, $VNDB::LANG->{$_} }) } sort keys %{$VNDB::LANG} ] }, - - { type => 'input', name => 'JAN/UPC/EAN', short => 'gtin' }, - { type => 'input', name => 'Official website', short => 'website' }, - { type => 'date', name => 'Release date', short => 'released' }, - { type => 'static', text => 'Leave month or day blank if they are unknown<br /><br />' }, - { type => 'select', name => 'Age rating', short => 'minage', options => [ map - { { name => $VNDB::VRAGES->{$_}, short => $_ } } sort { $a <=> $b } keys %$VNDB::VRAGES ] }, - { type => 'textarea', name => 'Notes', short => 'notes', rows => 3, cols => 50 }, - { type => 'static', text => 'Miscellaneous notes/comments, information that does not fit in the above fields. E.g.: Censored/uncensored or for which releases this patch applies. Max. 250 characters.' }, - - { type => 'sub', title => 'Platforms & Media', short => 'pnm' }, - { type => 'static', raw => 1, text => '<label>Platforms</label><ul class="platforms">'.join('', map { my $p = $_; - '<li><input type="checkbox" name="platforms" value="'.$_.'" id="'.$_.'" '. - (($d{form}{platforms} && grep { $p eq $_ } @{$d{form}{platforms}}) ? 'checked="checked" ':'').'/>'. - '<label for="'.$_.'"><acronym class="icons '.$_.'" title="'.$VNDB::PLAT->{$_}.'"> </acronym>'.$VNDB::PLAT->{$_}.'</label></li>' - } sort { $VNDB::PLAT->{$a} cmp $VNDB::PLAT->{$b} } keys %$VNDB::PLAT).'</ul>' }, - - { type => 'static', text => '<br />' }, - { type => 'jssel', name => 'Media', sh => 'md', short => 'media' }, - - { type => 'sub', title => 'Producers', short => 'prod' }, - { type => 'jssel', name => 'Producers', sh => 'pd', short => 'producers' }, - - { type => 'sub', title => 'Visual novel relations', short => 'rel'}, - { type => 'jssel', name => 'Relations', sh => 'vn', short => 'vn', r=>1 }, - { type => 'static', text => q| - Although a release usually contains only one visual novel, it is also possible - for one release to include several games. Use this field to specify which - visual novels are included in this release.| }, - - - { type => 'sub', title => 'Edit summary', short => 'com' }, - { type => 'textarea', name => 'Edit summary', short => 'comm', rows => 3, cols => 60 }, - { type => 'static', text => 'Please explain your modifications and cite all sources.' }, - - { type => 'submit', text => $d{id} ? 'Edit' : 'Add' }, - { type => 'endform' }, - -], $d{form}) ]] diff --git a/data/tpl/rlist b/data/tpl/rlist deleted file mode 100644 index f76eb65d..00000000 --- a/data/tpl/rlist +++ /dev/null @@ -1,90 +0,0 @@ -[[= ttabs('u', $d{user}, 'list') ]] -<h2>[[: $p{PageTitle} ]]</h2> - -[[ - my $url = '/u'.$d{user}{id}.'/list'; - my $surl = sprintf '%s?s=%s;o=%s', $url, $d{order}[0], $d{order}[1]; # main URL + order - my $purl = "$surl;c=$d{char}"; # full URL - page - my $sourl = "$url?c=$d{char}"; # full URL - page & order - my $curl = $surl; # full URL - character & page - my $furl = "$surl;c=$d{char};p=$d{page}"; # full URL - - my $i=0;my $j=0; - -]]- - -<p class="chr"> - -[[= $d{char} ne 'all' ? '<a href="'.$curl.';c=all">all</a>' : 'all' ]]- | - [[ for('a'..'z', 0) { ]]- - -[[ if($d{char} eq $_) { ]][[= $_?$_:'#' ]][[ } else { ]]<a href="[[= $curl.';c='.$_ ]]">[[= $_?$_:'#' ]]</a>[[ } ]] - [[ } ]]- - <br /><br /> -</p> - - --[[ if(@{$d{list}}) { ]] -[[= pagebut($surl) ]] -[[ if($d{user}{username} eq $p{AuthUsername}) { ]] -<form method="post" action="[[= $furl ]]" class="tblf"> -[[ } ]]- -<table id="rli"> - <thead><tr> - <td colspan="3" class="tc1">Title -[[= sortbut($sourl, 'title') ]]</td> - <td class="tc2" id="relhidpar"><b id="relhidparb">▸</b>Releases*</td> - <td class="tc3">Vote -[[= sortbut($sourl, 'vote') ]]</td> - </tr></thead> -[[ for (@{$d{list}}) { $j=0; my $c = ' style="background-color: #'.($i++%2?'fff':'f5f5f5').'"'; ]]- - <tr[[=$c]]> - <td colspan="3" class="tc1"><a href="/v[[= $_->{vid} ]]" title="[[: $_->{original}||$_->{title} ]]">[[= shorten $_->{title}, 50 ]]</a></td> - <td class="tc2[[= @{$_->{rels}} ? ' relhid" id="rh'.$_->{vid}.'"' : ' relnone"' ]]><b[[= @{$_->{rels}} ? ' id="rhd'.$_->{vid}.'"' : '' ]]>▸</b> - [[= grep $_->{rstat}==2, @{$_->{rels}} ]]/[[= grep $_->{vstat}==2, @{$_->{rels}} ]]/[[= @{$_->{rels}} ]] - </td> - <td class="tc3">[[= $_->{vote} || '-' ]]</td> - </tr> - [[ for (@{$_->{rels}}) { ]]- - <tr class="relhid" id="rr[[= $_->{vid}.'-'.++$j ]]"> - <td class="tc1_1">[[= datestr $_->{released} ]]</td> - <td class="tc1_2"> - <acronym class="icons lang -[[= $_->{language} ]]" title="[[: $$VNDB::LANG{$_->{language}} ]]"> </acronym><acronym - title="[[= $VNDB::RTYP->[$_->{type}] ]]- release" class="icons -[[= lc substr($VNDB::RTYP->[$_->{type}],0,3) ]]"> </acronym> - </td> - <td class="tc1_3"><a href="/r[[= $_->{rid} ]]" title="[[: $_->{original}||$_->{title} ]]">[[= shorten $_->{title}, 60 ]]</a></td> - <td class="tc1_4"> - <acronym title="[[: $VNDB::RSTAT->[$_->{rstat}] ]]" class="uicons r[[= $_->{rstat} ]]"> </acronym><acronym - title="[[: $VNDB::VSTAT->[$_->{vstat}] ]]" class="uicons v[[= $_->{vstat} ]]"> </acronym> - </td> - <td class="tc1_5">[[ if($d{user}{username} eq $p{AuthUsername}) { ]]<input type="checkbox" name="rsel" value="[[= $_->{rid} ]]" />[[ } else { ]] [[ } ]]</td> - </tr> - [[ } ]] -[[ } ]]- -</table> -[[ if($d{user}{username} eq $p{AuthUsername}) { ]] -<select id="vnlistchange" name="vnlistchange" class="right"> - <option value="n">- with selected -</option> - <option value="d">Delete</option> - <optgroup label="Update release status:"> - [[ for (0..$#$VNDB::RSTAT) { ]]- - <option value="r[[= $_ ]]">[[: $VNDB::RSTAT->[$_] ]]</option> - [[ } ]] - </optgroup> - <optgroup label="Update play status:"> - [[ for (0..$#$VNDB::VSTAT) { ]]- - <option value="v[[= $_ ]]">[[: $VNDB::VSTAT->[$_] ]]</option> - [[ } ]] - </optgroup> -</select> -</form> -[[ } ]] -[[= pagebut($surl) ]] -<p> - <br /> - <b>*</b> Obtained/finished/total. -</p> - - - -[[ } else { ]]- -<p> - No results found. -</p> -[[ } ]] diff --git a/data/tpl/rpage b/data/tpl/rpage deleted file mode 100644 index d31ffe24..00000000 --- a/data/tpl/rpage +++ /dev/null @@ -1,68 +0,0 @@ -[[= ttabs('r', $d{rel}) ]] -<h2>[[: $p{PageTitle} ]]</h2> -[[ if($d{rel}{original}) { ]]<h3 class="alttitle">[[: $d{rel}{original} ]]</h3>[[ } ]] - -[[ if($d{rel}{hidden}) { ]]- - <span class="warning"> - This item has been deleted from the database. File a request on the - <a href="/t/v[[= $d{rel}{vn}[0]{vid} ]]">discussion board</a> to undelete this page. - </span> -[[ } ]] -[[ if(!$d{rel}{hidden} || $p{Authdel}) { ]]- - --[[ if($p{AuthLoggedin}) { ]] -<p class="mod">< -<a href="/u[[= $p{AuthId} ]]/list" rel="rlistDD[[= $d{rel}{id} ]]" class="dropdown"> -[[= !$d{rel}{rlist} ? 'not in your list' : "$$VNDB::RSTAT[$d{rel}{rlist}{rstat}] / $$VNDB::VSTAT[$d{rel}{rlist}{vstat}]" ]] -</a> ></p> -[[= rlist_dd($d{rel}) ]] -[[ } ]]- - - --[[ if($d{change}) { ]] -[[= cdiff($d{prev}, $d{rel}, - [ vn => 'Relations', sub { join("<br />\n", map { $_->{title} } @{$_[0]}) } ], - [ type => 'Type', sub { $VNDB::RTYP->[$_[0] ] } ], - [ title => 'Title', 1 ], - [ original => 'Orig. title', 1 ], - [ gtin => 'JAN/UPC/EAN', 1 ], - [ language => 'Language', sub { $VNDB::LANG->{$_[0]} } ], - [ website => 'Website', \&summary ], - [ released => 'Release date', \&datestr ], - [ minage => 'Age rating', sub { $VNDB::VRAGES->{$_[0]} } ], - [ notes => 'Notes', 1, 1 ], - [ platforms => 'Platforms', sub { join(', ', sort @{$_[0]}) } ], - [ media => 'Media', \&mediastr ], - [ producers => 'Producers', sub { join(', ', map { _hchar($_->{name}) } sort { $a->{name} cmp $b->{name} } @{$_[0]}) } ], - ) ]] -[[ } ]] - -<dl> - <dt>Relation</dt><dd>[[= join('<br />', map { '<a href="/v'.$_->{vid}.'" title="'._hchar($_->{original}||$_->{title}).'">'._hchar($_->{title}).'</a>' } @{$d{rel}{vn}}) ]]</dd> - <dt>Type</dt><dd>[[: $VNDB::RTYP->[$d{rel}{type}] ]]</dd> - <dt>Language</dt><dd>[[: $VNDB::LANG->{$d{rel}{language}} ]]</dd> - <dt>Release date</dt><dd>[[= datestr($d{rel}{released}) ]]</dd> -[[ if($d{rel}{gtin}) { ]]- - <dt>[[: VNDB::GTINType($d{rel}{gtin}) ]]- code</dt><dd>[[= $d{rel}{gtin} ]]</dd>[[ } ]]- -[[ if($d{rel}{minage} >= 0) { ]]- - <dt>Age rating</dt><dd>[[: $VNDB::VRAGES->{$d{rel}{minage}} ]]</dd>[[ } ]]- -[[ if($#{$d{rel}{producers}} >= 0) { ]]- - <dt>Producer[[: $#{$d{rel}{producers}} > 0 ? 's' : '' ]]</dt><dd>[[= join(', ', map { - sprintf('<a href="/p%d" title="'._hchar($_->{original}||$_->{name}).'">%s</a>', $_->{id}, _hchar($_->{name})) } @{$d{rel}{producers}}) - ]]</dd>[[ } ]]- -[[ if($#{$d{rel}{platforms}} >= 0) { ]]- - <dt>Platform[[: $#{$d{rel}{platforms}} > 0 ? 's' : '' ]]</dt><dd>[[: join(', ', map { - $VNDB::PLAT->{$_} } @{$d{rel}{platforms}}) ]]</dd>[[ } ]]- -[[ if($#{$d{rel}{media}} >= 0) { ]]- - <dt>Medi[[: $#{$d{rel}{media}} > 0 ? 'a' : 'um' ]]</dt><dd>[[: mediastr($d{rel}{media}) ]]</dd>[[ } ]]- -[[ if($d{rel}{website}) { ]]- - <dt>Links</dt><dd><a href="[[: $d{rel}{website} ]]">Official website</a></dd>[[ } ]]- -</dl> - -[[ if($d{rel}{notes}) { ]]- -<p>[[= summary($d{rel}{notes}) ]]<br /><br /></p> -[[ } ]]- - - - -[[ } ]] diff --git a/data/tpl/tedit b/data/tpl/tedit deleted file mode 100644 index 5953ead0..00000000 --- a/data/tpl/tedit +++ /dev/null @@ -1,33 +0,0 @@ -<h2>[[: $p{PageTitle} ]]</h2> -[[ if($d{tag}) { my($type, $iid) = ($1, $2||0) if $d{tag} =~ /^([a-z]{1,2})([0-9]*)$/; ]]- -<p> - <a href="/t">Discussion board</a> - > <a href="/t/[[= $type ]]">[[: $VNDB::DTAGS->{$type} ]]</a> - [[ if($iid) { ]]- - > <a href="/t/[[= $d{tag} ]]">[[: $d{tag} ]]</a>[[ } ]]- -</p> -[[ } ]] - --[[= cform( [ - { type => 'error' }, - { type => 'startform', action => $d{p} ? '/t'.$d{t}{id}.'.'.$d{p}{num}.'/edit' : $d{t} ? '/t'.$d{t}{id}.'/reply' : '/t/'.$d{tag}.'/new' }, - { type => 'static', name => 'Username', text => '<a href="/u'.($d{p}?$d{p}{uid}:$p{AuthId}).'">'.($d{p}?$d{p}{username}:$p{AuthUsername}).'</a>' }, - $d{t} && !($d{p} && $d{p}{num} == 1) ? ( - { type => 'static', name => 'Topic', text => '<a href="/t'.$d{t}{id}.'">'.$d{t}{title}.'</a>.' } - ) : ( - { type => 'input', short => 'title', name => 'Thread title' }, - { type => 'input', short => 'tags', name => 'Tags' }, - { type => 'static', text => 'Read <a href="/d9.2">d9.2</a> for information about how to use tags' }, - $p{Authboardmod} ? ( - { type => 'check', short => 'lock', name => 'Locked' }, - ) : (), - ), - $p{Authboardmod} ? ( - { type => 'check', short => 'hide', name => 'Hidden' }, - ) : (), - { type => 'textarea', short => 'msg', name => 'Message', rows => 10, cols => 60 }, - { type => 'static', text => 'It is possible to include formatting and ID codes, see <a href="/d9.3">d9.3</a> for more information.' }, - { type => 'submit', text => 'Submit' }, - { type => 'endform' }, -], $d{form}) ]]- - diff --git a/data/tpl/tindex b/data/tpl/tindex deleted file mode 100644 index cb9cd154..00000000 --- a/data/tpl/tindex +++ /dev/null @@ -1,49 +0,0 @@ -<h2>[[: $p{PageTitle} ]]</h2> - -[[ - my %desc = ( - an => 'Yorhel\'s place to make useless announcements...', - db => 'General discussions about VNDB.org. This is the place to be for feature requests and bug reports.', - v => 'Discussions about the visual novels in the database', - p => '...Producers', - r => '...Releases', - u => 'Messages to or discussions about other users on this site.' - ); -]] - - -[[ for my $tag (qw|an db v p u|) { ]]- - -<br /> -<h3>[[: $VNDB::DTAGS->{$tag} ]]</h3> -[[ if(@{$d{$tag}}) { ]]- -<table id="tin"> -[[ for (@{$d{$tag}}) { ]]- - <tr> - <td class="tc1"> - <a href="/t[[= $_->{id} ]]" title="[[= join ', ', sort map $$_[1]?$$_[0].$$_[1]:$$_[0], @{$_->{tags}} ]]">[[: $_->{title} ]]</a> - [[ if($_->{locked}) { ]]- <b>[locked]</b>[[ } ]] - </td> - <td class="tc2">[[= $_->{count}-1 ]]</td> - <td class="tc3">[[= userstr $_ ]]</td> - <td class="tc4">[[= userstr $_->{luid}, $_->{lusername} ]]- @ - <a href="/t[[= $_->{id}.($_->{count}>$d{ppp}?'/'.ceil($_->{count}/$d{ppp}):'').'#'.$_->{count} ]]"> - [[= age $_->{ldate} ]]</a></td> - </tr> -[[ } ]] -</table> -<a class="right" href="/t/[[= $tag ]]">more...</a> -[[ if($tag eq 'db') { ]]- - <a class="right" href="/t/[[= $tag ]]/new" style="padding-right: 10px">start new thread</a> -[[ } ]] - -[[ } else { ]]- - <p>No threads yet. - -[[ if($tag eq 'db') { ]] - <a href="/t/[[= $tag ]]/new">Start a new thread.</a> - [[ } ]] - </p> -[[ } ]] -<br /> - -[[ } ]] diff --git a/data/tpl/ttag b/data/tpl/ttag deleted file mode 100644 index 0d46ddf1..00000000 --- a/data/tpl/ttag +++ /dev/null @@ -1,60 +0,0 @@ -[[= $d{obj} ? ttabs($d{type}, $d{obj}, 'disc') : '' ]]- -<h2>[[: $p{PageTitle} ]]</h2> -<p> - <a href="/t">Discussion board</a> - > <a href="/t/[[= $d{type} ]]">[[: $VNDB::DTAGS->{$d{type}} ]]</a> - [[ if($d{obj}) { ]]- - > <b>[[= $d{tag} ]]</b>:<a href="/t/[[= $d{tag} ]]" title="[[: $d{original}||$d{title} ]]">[[: $d{title} ]]</a>[[ } ]]- -</p> - -[[ if(@{$d{t}}) { ]]- - -[[ if(!$d{obj} && $d{tag} !~ /(an|db)/) { - my @tags = grep $$_[0] eq $d{type}, map @{$_->{tags}}, @{$d{t}}; my %tags; my $i=0; ]]- -<dl> - <dt>Recent tags</dt> - <dd> - [[ for (@tags) { next if $tags{$$_[1]}++; last if $i++ == 5; ]]- - <b>[[= $$_[0].$$_[1] ]]</b>:<a href="/t/[[= $$_[0].$$_[1] ]]">[[: $$_[2] ]]</a><br />[[ } ]] - </dd> -</dl> -[[ } else { ]] -<br /> -[[ } ]] - - -[[= pagebut('/t/'.$d{tag}) ]] -<table id="tin"> - <thead><tr> - <td class="tc1">Topic</td> - <td class="tc2">#</td> - <td class="tc3">Starter</td> - <td class="tc4">Last post</td> - </tr></thead> -[[ for (@{$d{t}}) { ]]- - <tr> - <td class="tc1"> - <a href="/t[[= $_->{id} ]]" title="[[= join ', ', sort map $$_[1]?$$_[0].$$_[1]:$$_[0], @{$_->{tags}} ]]">[[: $_->{title} ]]</a> - [[ if($_->{locked}) { ]]- <b>[locked]</b>[[ } ]] - </td> - <td class="tc2">[[= $_->{count}-1 ]]</td> - <td class="tc3">[[= userstr $_ ]]</td> - <td class="tc4">[[= userstr $_->{luid}, $_->{lusername} ]]- @ - <a href="/t[[= $_->{id}.($_->{count}>$d{ppp}?'/'.ceil($_->{count}/$d{ppp}):'').'#'.$_->{count} ]]"> - [[= age $_->{ldate} ]]</a></td> - </tr> -[[ } ]] -</table> -[[= pagebut('/t/'.$d{tag}) ]] - -[[ } else { ]] -<p><br /> - <b>No related threads found.</b> -</p> -[[ } ]]- - --[[ if($p{Authboard} && $d{tag} =~ /^(?:db|[vpru][0-9]+)$/) { ]]- -<br /> -<a class="right" href="/t/[[= $d{tag} ]]/new">create a new thread</a> -[[ } ]] - diff --git a/data/tpl/tthread b/data/tpl/tthread deleted file mode 100644 index 0b67345c..00000000 --- a/data/tpl/tthread +++ /dev/null @@ -1,81 +0,0 @@ -<h2>[[: $p{PageTitle} ]]</h2> -[[ if($d{t}{hidden}) { ]] -<span class="warning">This thread has been deleted!</span> -[[ } ]] - -<dl> - <dt>Posted in</dt> - <dd> - [[ for (sort { $$a[0].$$a[1] cmp $$b[0].$$b[1] } @{$d{t}{tags}}) { ]]- - <a href="/t/[[= $$_[0] ]]">[[: $VNDB::DTAGS->{$$_[0]} ]]</a> - [[ if($$_[1]) { ]]- - > <b>[[= $$_[0].$$_[1] ]]</b>:<a href="/t/[[= $$_[0].$$_[1] ]]" title="[[: $$_[3]||$$_[2] ]]">[[: $$_[2] ]]</a>[[ } ]]- - <br /> - [[ } ]] - </dd> -</dl> - -<br /> - -[[ - my $pages=''; - my $lp = ceil($d{t}{count}/$d{ppp}); - if($d{t}{count} > $d{ppp}) { - my @pages = ( - $d{page} == 1 ? '<<' : '<a href="/t%d"><<</a>', - $lp > 2 ? (map - $d{page} == $_ ? $_ : '<a href="/t%d/'.$_.'">'.$_.'</a>', - 2..($lp-1) ) : (), - $d{page} == $lp ? '>>' : '<a href="/t%d/'.$lp.'">>></a>' - ); - $pages = '<p class="browse">'.join(' ', map sprintf($_,$d{t}{id}), @pages).'</p>'; - } -]] - -[[= $pages ]] -<table id="tth"> - [[ for (@{$d{p}}) { ]]- - <tr> - <td class="tc1"> - <a href="/t[[= $d{t}{id} ]].[[= $_->{num} ]]" name="[[= $_->{num} ]]">#[[= $_->{num} ]]</a> - [[ if(!$_->{hidden}) { ]]- - by -[[= userstr $_ ]]<br /> - <i>[[= formatdate('%Y-%m-%d %R', $_->{date}) ]]</i> - [[ } ]] - </td> - <td class="tc2"> - [[ if($p{AuthId} == $_->{uid} && !$_->{hidden} || $p{Authboardmod}) { ]]- - <p class="mod">< <a href="/t[[= $d{t}{id}.'.'.$_->{num} ]]/edit">edit</a> ></p> - [[ } ]] - [[ if(!$_->{hidden}) { ]]- - [[= summary $_->{msg} ]] - [[ if($_->{edited}) { ]]<br /> - <i>last modified -[[= formatdate('%Y-%m-%d %R', $_->{edited}) ]]</i> - [[ } ]] - [[ } else { ]] - <b class="hidden">Post deleted.</b> - [[ } ]] - </td> - </tr> - [[ } ]]- -</table> -[[= $pages ]] - -<br /> -[[ if($lp == $d{page}) { ]] - [[ if($d{t}{locked}) { ]]- - <p> - This thread has been locked, you can't reply anymore. - </p> - [[ } elsif(!$p{AuthLoggedin}) { ]]- - <p> - You need to be <a href="/u/login">logged in</a> to reply to this thread. - </p> - [[ } elsif($p{Authboard} && $lp == $d{page}) { ]]- - <form action="/nospam?/t[[= $d{t}{id} ]]/reply" method="post" accept-charset="utf-8" id="qreply"> - <h3>Quick reply</h3> - <textarea name="msg" id="msg" rows="5" cols="70"></textarea> - <input type="submit" value="Post reply" /> - </form> - [[ } ]] -[[ } ]] diff --git a/data/tpl/useredit b/data/tpl/useredit deleted file mode 100644 index e6243fb5..00000000 --- a/data/tpl/useredit +++ /dev/null @@ -1,36 +0,0 @@ -[[= ttabs('u', $d{u}, 'edit') ]] -<h2>[[: $p{PageTitle} ]]</h2> - --[[ if($d{done}) { ]] -<span class="msg"> - Settings succesfully saved. -</span> -[[ } ]] --[[= cform( [ - { type => 'error' }, - { type => 'startform', action => '/u'.$d{user}.'/edit' }, - - { type => 'sub', title => 'General info', short => 'info' }, - { type => 'static', name => 'Username', text => _hchar($d{form}{username}) }, - { type => 'input', name => 'Email', short => 'mail' }, - - { type => 'sub', title => 'Change password', short => 'pass' }, - { type => 'static', text => 'Leave blank to keep your current password.' }, - { type => 'pass', name => 'Password', short => 'pass1' }, - { type => 'pass', name => 'Confirm', short => 'pass2' }, - - { type => 'sub', title => 'Miscellaneous options', short => 'misc' }, - { type => 'check', short => 'plist', name => sprintf - 'Allow other people to see my visual novel list (<a href="/u%d/list">/u%1$d/list</a>) and wishlist (<a href="/u%1$d/wish">/u%1$d/wish</a>)', $d{user} }, - { type => 'check', short => 'pign_nsfw', name => 'Disable warnings for images that are not safe for work.' }, - - $d{adm} ? ( - { type => 'sub', title => 'Admin', short => 'adm' }, - { type => 'input', name => 'Username', short => 'username' }, - { type => 'select', name => 'Rank', short => 'rank', options => [ - map { { name => $VNDB::VNDBopts{ranks}[0][0][$_], short => $_ } } 1..($#{$VNDB::VNDBopts{ranks}}-1) ] }, - ) : (), - - { type => 'submit', text => 'Save' }, - { type => 'endform' }, -], $d{form}) ]] diff --git a/data/tpl/userlist b/data/tpl/userlist deleted file mode 100644 index 578d320e..00000000 --- a/data/tpl/userlist +++ /dev/null @@ -1,50 +0,0 @@ -<h2>[[: $p{PageTitle} ]]</h2> -<p class="chr"> - -[[= $d{chr} ne 'all' ? '<a href="/u/list/all">all</a>' : 'all' ]]- | - [[ for('a'..'z', 0) { ]]- - -[[ if($d{chr} eq $_) { ]][[= $_?$_:'#' ]][[ } else { ]]<a href="/u/list/[[= $_ ]]">[[= $_?$_:'#' ]]</a>[[ } ]] - [[ } ]]- - <br /><br /> -</p> - -[[ if($#{$d{users}} < 0) { ]]- -<p> - No users found... -</p> -[[ } else { - my $url = sprintf '/u/list/%s', $d{chr}; - my $surl = sprintf '%s?s=%s&o=%s', $url, $d{order}[0], $d{order}[1]; -]] -[[= pagebut($surl) ]]- -<table id="tul"> - <thead><tr> - <td class="tc1">Username [[= sortbut($url, 'username') ]]</td> -[[ if($p{Authusermod}) { ]]- - <td class="tc2">Mail [[= sortbut($url, 'mail') ]]</td> - <td class="tc3">Rank [[= sortbut($url, 'rank') ]]</td>[[ } ]]- - <td class="tc4">Registered [[= sortbut($url, 'registered') ]]</td> - <td class="tc6">Votes</td> - <td class="tc7">Changes</td> -[[ if($p{Authusermod}) { ]]- - <td class="tc8"> </td>[[ } ]]- - </tr></thead> - [[ for (@{$d{users}}) { ]]- - <tr> - <td class="tc1"><a href="/u[[= $_->{id} ]]">[[: $_->{username} ]]</a></td> -[[ if($p{Authusermod}) { ]]- - <td class="tc2">[[: $_->{mail} ]]</td> - <td class="tc3">[[: $VNDB::VNDBopts{ranks}[0][0][$_->{rank}] ]]</td>[[ } ]]- - <td class="tc4">[[= formatdate('%Y-%m-%d', $_->{registered}, 'wd') ]]</td> - <td class="tc6">[[ if($_->{flags} & $VNDB::UFLAGS->{list} && $_->{votes}) { ]] - <a href="/u[[= $_->{id} ]]/list" title="[[: $_->{username} ]]'s votes">[[= $_->{votes} ]]</a> - [[ } else { ]][[= $_->{flags} & $VNDB::UFLAGS->{list} ? 0 : '-' ]][[ } ]]</td> - <td class="tc7">[[ if($_->{changes}) { ]] - <a href="/u[[= $_->{id} ]]/hist" title="Recent changes by -[[: $_->{username} ]]">[[= $_->{changes} ]]</a> - [[ } else { ]]0[[ } ]]</td> -[[ if($p{Authusermod}) { ]]- - <td class="tc8">( <a href="/u[[= $_->{id} ]]/edit">edit</a> )</td>[[ } ]]- - </tr> - [[ } ]]- -</table> --[[= pagebut($surl) ]]- -[[ } ]] diff --git a/data/tpl/userlogin b/data/tpl/userlogin deleted file mode 100644 index b4af29d2..00000000 --- a/data/tpl/userlogin +++ /dev/null @@ -1,14 +0,0 @@ -<h2>[[: $p{PageTitle} ]]</h2> --[[= cform( [ - { type => 'error' }, - { type => 'startform', action => '/u/login' }, - { type => 'input', short => 'username', name => 'Username' }, - { type => 'pass', short => 'userpass', name => 'Password' }, - { type => 'submit', text => 'Login!' }, - { type => 'endform' }, -], $d{log}) ]]- - -<p> - <br /><br /> - <a href="/u/register">No account yet</a>, or <a href="/u/newpass">forgot your username or password?</a> -</p> diff --git a/data/tpl/userpage b/data/tpl/userpage deleted file mode 100644 index aa02062e..00000000 --- a/data/tpl/userpage +++ /dev/null @@ -1,13 +0,0 @@ -[[= ttabs('u', $d{user}) ]] -[[ - $d{pl} = $d{user}{flags} & $VNDB::UFLAGS->{list}; -]] -<h2>[[: $p{PageTitle} ]]</h2> -<dl> - <dt>Username</dt><dd>[[: $d{user}{username} ]]- (<a href="/u[[= $d{user}{id} ]]">u[[= $d{user}{id} ]]</a>)</dd> - <dt>Registered</dt><dd>[[= formatdate('%Y-%m-%d', $d{user}{registered}) ]]</dd> - <dt>Votes</dt><dd>[[= $d{pl} ? $d{user}{votes}.' (<a href="/u'.$d{user}{id}.'/list">view all</a>)' : '(hidden)' ]]</dd> - <dt>Changes</dt><dd>[[= $d{user}{changes}.($d{user}{changes}>0?' (<a href="/u'.$d{user}{id}.'/hist">recent changes</a>)':'') ]]</dd> -</dl> - -[[= T_vnpage_stats($X) ]] diff --git a/data/tpl/userpass b/data/tpl/userpass deleted file mode 100644 index c3b04840..00000000 --- a/data/tpl/userpass +++ /dev/null @@ -1,21 +0,0 @@ -<h2>[[: $p{PageTitle} ]]</h2> -<p> - You're lucky that vndb has a very advanced password recovery tool! Just - type your email address (the same one you used for your account), and - wait for an email! -</p> - --[[ if(!$d{done}) { ]] -[[= cform( [ - { type => 'error', }, - { type => 'startform', action => '/u/newpass' }, - { type => 'input', short => 'mail', name => 'Email' }, - { type => 'submit', text => 'Gimme my password!' }, - { type => 'endform' }, -], $d{pas} ) ]] - -[[ } else { ]] -<span class="msg"> - Your password succesfully been reset. Check your mail for instructions. -</span> -[[ } ]] diff --git a/data/tpl/userreg b/data/tpl/userreg deleted file mode 100644 index 31b2b622..00000000 --- a/data/tpl/userreg +++ /dev/null @@ -1,38 +0,0 @@ -<h2>[[: $p{PageTitle} ]]</h2> - --[[ if($d{denied}) { ]] -[[ } ]]- - -<br /><br /> -<h3>Why should I register?</h3> -<p> - Registered users have access to special features on this site: -</p> -<ul> - <li>You can keep track of the visual novels you'd like to play or have - finished playing,</li> - <li>Vote on visual novels,</li> - <li>And more importantly: you can add and edit all information on the - website!</li> -</ul> -<p> - <br /> - And of course, registering an account is (and will always remain) - completely free! - <br /><br /> -</p> - --[[= cform( [ - { type => 'error' }, - { type => 'startform', action => '/u/register' }, - { type => 'input', short => 'username', name => 'Username' }, - { type => 'input', short => 'mail', name => 'Email' }, - { type => 'static', text => q| - Your email address will only be used in case you lose your password, at least for now. - We will never send spam or newsletters unless you explicitly ask us for it. - | }, - { type => 'pass', short => 'pass1', name => 'Password' }, - { type => 'pass', short => 'pass2', name => 'Confirm pass.' }, - { type => 'submit', text => 'Register!' }, - { type => 'endform' }, -], $d{reg}) ]] diff --git a/data/tpl/vnbrowse b/data/tpl/vnbrowse deleted file mode 100644 index fa4ba1ac..00000000 --- a/data/tpl/vnbrowse +++ /dev/null @@ -1,108 +0,0 @@ -<h2>[[: $p{PageTitle} ]]</h2> - - -[[ if($d{chr} eq 'search') { ]] - <form id="vsearch" method="get" action="/v/search" accept-charset="UTF-8"> - <fieldset> - <input type="text" name="q" id="q" value="[[: $p{searchquery} ]]" class="text" - /><input type="submit" value="Search!" /> - <br /> - <b id="adsearchclick">[[= !$p{searchquery} ? '▾' : '▸' ]]- advanced options</b> - </fieldset> - </form> - - <div id="adsearch" [[= !$p{searchquery} ? '' : ' style="display: none"' ]]> - <b>Categories</b> (boolean and, selecting more gives less results. The categories are explained on <a href="/d1">this page</a>) - <ul id="cat"> - [[ for my $c (qw| e g t p h l s |) { ]]- - -[[= $c !~ /[thl]/ ? '<li>' : '<br />' ]][[: $VNDB::CAT->{$c}[0] ]]- - <ul> - [[ for (sort keys %{$VNDB::CAT->{$c}[1]}) { my $ca = $c.$_; ]]- - <li id="cat_[[= $ca ]]"> - [[: $VNDB::CAT->{$c}[1]{$_} ]]- ([[= $d{cat}{$ca} || 0 ]])</li> - [[ } ]] - </ul>[[= $c !~ /[gph]/ ? '</li>' : '' ]]- - [[ } ]]- - </ul> - <br style="clear: both" /> - <br /> - - <b>Languages</b> (boolean or, selecting more gives more results)<br /> - <ul class="filter" id="lfilter"> - [[ for (sort keys %{$d{langc}}) { next if !$d{langc}{$_}; my $l=$_; ]]- - <li><input type="checkbox" name="lang_[[= $l ]]" id="lang_[[= $l ]]" value="[[: $VNDB::LANG->{$l} ]]" /> - <label for="lang_[[= $l ]]"><acronym class="icons lang -[[= $l ]]" title="[[: $VNDB::LANG->{$l} ]]"> </acronym>([[= $d{langc}{$l} ]])</label></li> - [[ } ]]- - </ul> - <br style="clear: both" /> - <br /> - - <b>Platforms</b> (boolean or, selecting more gives more results)<br /> - <ul class="filter" id="pfilter"> - [[ for (sort keys %$VNDB::PLAT) { next if /oth/; my $l=$_; ]]- - <li><input type="checkbox" name="plat_[[= $l ]]" id="plat_[[= $l ]]" value="[[: $VNDB::PLAT->{$l} ]]" /> - <label for="plat_[[= $l ]]"><acronym class="icons -[[= $l ]]" title="[[: $VNDB::PLAT->{$l} ]]"> </acronym></label></li> - [[ } ]]- - </ul> - <br style="clear: both" /> - <input type="button" class="right" id="vsearch_sub" name="vsearch_sub" value="Search!" /> - <br style="clear: left" /> - <br /><br /> - </div> - -[[ } else { ]]- -<p class="chr"> - -[[= $d{chr} ne 'all' ? '<a href="/v/all">all</a>' : 'all' ]]- | - [[ for('a'..'z', 0) { ]]- - -[[ if($d{chr} eq $_) { ]][[= $_?$_:'#' ]][[ } else { ]]<a href="/v/[[= $_ ]]">[[= $_?$_:'#' ]]</a>[[ } ]] - [[ } ]]- - <br /><br /> -</p> -[[ } ]]- - - --[[ if($#{$d{vn}} < 0) { ]] - -[[ if($d{chr} eq 'search' && $p{searchquery} || $d{chr} ne 'search') { ]] -<p> - No results again, life sucks... :'( -</p> - [[ } ]] -[[ } else { - my %url = ( - $p{searchquery} ? ( q => $p{searchquery} ) : (), - ); - my %urls = ( %url, - $d{order}[0] ne 'title' ? ( s => $d{order}[0] ) : (), - $d{order}[1] ne 'a' ? ( o => $d{order}[1] ) : (), - ); - my $url = sprintf '/v/%s', $d{chr}; - my $urls = $url; - $urls .= '?'.join(';', map { $_.'='.$urls{$_} } keys %urls) if keys %urls; - $url .= '?'.join(';', map { $_.'='.$url{$_} } keys %url) if keys %url; -]] - -[[= pagebut($urls) ]] -<table id="tbv"> - <thead><tr> - <td class="tc1">Title [[= sortbut($url, 'title') ]]</td> - <td class="tc2"> </td> - <td class="tc3"> </td> - <td class="tc4">Released [[= sortbut($url, 'released') ]]</td> - </tr></thead> - [[ for (@{$d{vn}}) { - $_->{c_released} =~ s#^([0-9]{4})([0-9]{2}).+#$1==0?'N/A':$1==9999?'TBA':(($2&&$2<13?($Time::CTime::MoY[$2-1].' '):'').$1)#e; - $_->{c_platforms} = join '', map { - $_ ne 'oth' ? '<acronym class="icons '.$_.'" title="'._hchar($VNDB::PLAT->{$_}).'"> </acronym>' : () - } split /\//, $_->{c_platforms}; - $_->{c_languages} = join '', map qq|<acronym class="icons lang $_" title="$$VNDB::LANG{$_}"> </acronym>|, reverse sort split /\//, $_->{c_languages}; - ]]- - <tr> - <td class="tc1"><a href="/v[[= $_->{id} ]]" title="[[: $_->{original}||$_->{title} ]]">[[: shorten $_->{title}, 50 ]]</a></td> - <td class="tc2">[[= $_->{c_platforms} ]]</td> - <td class="tc3">[[= $_->{c_languages} ]]</td> - <td class="tc4">[[: $_->{c_released} ]]</td> - </tr> - [[ } ]]- -</table> -[[= pagebut($urls) ]] -[[ } ]] diff --git a/data/tpl/vnedit b/data/tpl/vnedit deleted file mode 100644 index a9801674..00000000 --- a/data/tpl/vnedit +++ /dev/null @@ -1,120 +0,0 @@ -[[= $d{id} ? ttabs('v', $d{vn}, 'edit') : '' ]]- -<h2>[[: $p{PageTitle} ]]</h2> - -[[ if(!$d{id}) { ]] - <span class="msg">Please search the database before adding a new visual novel - in order to prevent duplicate entries.</span> -[[ } else { ]] - <span class="msg"> - Please check the <a href="/t/v[[= $d{id} ]]">discussion board</a> <b>before</b> making - any changes! - </span> -[[ } if($d{id} && $d{vn}{cid} != $d{vn}{latest}) { ]] - <span class="warning"> - You are editing an old revision of this visual novel. If you save it, all changes made after - -[[= formatdate('%Y-%m-%d %R', $d{vn}{added}) ]]- will be removed! - </span> -[[ } ]] - - --[[= cform([ - { type => 'error' }, - { type => 'startform', action => $d{id} ?( '/v'.$d{id}.'/edit') : '/v/new', upload => 1, fh => 1 }, - - { type => 'sub', title => 'General info', short => 'info' }, - { type => 'input', name => 'Title (romaji)', short => 'title', r=>1 }, - { type => 'input', name => 'Original title', short => 'original' }, - { type => 'static', text => q| - The original title of this visual novel, leave blank if it already is in the Latin alphabet.<br /><br />| }, - - { type => 'textarea', name => 'Aliases', short => 'alias', rows => 2, cols => 60 }, - { type => 'static', text => q| - Comma seperated list of alternative titles or abbreviations. Can include both official - (japanese/english) titles and unofficial titles used around net. <b>Titles that are listed in the releases do not have to be added here.</b><br /><br />| }, - - { type => 'textarea', name => 'Description', short => 'desc', rows => 7, cols => 70, r=>1 }, - { type => 'static', text => q| - Short description of the main story. Please do not include spoilers, and don't forget to list the source - in case you didn't write the description yourself. ([url] BBCode tag is allowed)<br /><br />| }, - - { type => 'select', name => 'Length', short => 'length', class => 'longopts', options => [ map { - { short => $_, - name => !$_?$VNDB::VNLEN->[$_][0]:($VNDB::VNLEN->[$_][0].', '.$VNDB::VNLEN->[$_][1].' ('.$VNDB::VNLEN->[$_][2].')') } } 0..$#$VNDB::VNLEN - ] }, - { type => 'static', text => '<br />' }, - { type => 'input', name => 'External links', short => 'l_wp', pre => 'http://en.wikipedia.org/wiki/' }, - { type => 'input', name => ' ', short => 'l_encubed', pre => 'http://novelnews.net/tag/', post => '/' }, - { type => 'input', name => ' ', short => 'l_renai', pre => 'http://renai.us/game/', post => '.shtml' }, - { type => 'input', name => ' ', short => 'l_vnn', pre => 'http://visual-novels.net/vn/index.php?option=com_content&task=view&id=', class => 'shortopts' }, - - { type => 'static', text => '<br />' }, - { type => 'input', name => 'Related anime', short => 'anime' }, - { type => 'static', text => q| - Whitespace seperated list of <a href="http://anidb.net/">AniDB</a> anime IDs. - E.g. "1015 3348" will add <a href="http://anidb.net/a1015">Shingetsutan Tsukihime</a> - and <a href="http://anidb.net/a3348">Fate/stay night</a> as related anime.<br /> - <b>Note:</b> It can take a few minutes for the anime titles to appear on the VN page.| }, - - { type => 'sub', title => 'Categories', short => 'cat' }, - { type => 'hidden', short => 'categories' }, - { type => 'static', raw => 1, text => eval { - my $r = 'Please read the <a href="/d1">category descriptions</a> before modifying categories!<br /><br />' - .'<ul id="cat">'; - for my $c (qw| e g t p h l s |) { - $r .= ($c !~ /[thl]/ ? '<li>' : '<br />').$VNDB::CAT->{$c}[0].'<a href="/d1#'.$VNDB::CAT->{$c}[2].'" class="help">?</a><ul>'; - for (sort keys %{$VNDB::CAT->{$c}[1]}) { - $r .= sprintf '<li><a href="#" id="cat_%1$s"><b id="b_%1$s">-</b> %2$s</a></li>', - $c.$_, $VNDB::CAT->{$c}[1]{$_}; - } - $r .= '</ul>'.($c !~ /[gph]/ ? '</li>' : ''); - } - $r.'</ul>'; - } }, - - { type => 'sub', title => 'Image', short => 'img' }, - $d{id} ? ( - { type => 'static', text => $d{vn}{image} > 0 ? - sprintf '<img src="%s/cv/%02d/%d.jpg" style="float: right" />', $p{st}, $d{vn}{image}%100, $d{vn}{image} : - $d{vn}{image} < 0 ? '[processing]' : 'No image uploaded yet...' }, - ) : (), - { type => 'upload', name => $d{vn}{image} ? 'Change' : 'Upload', short => 'img' }, - { type => 'static', text => q| - Preferably the cover of the CD/DVD/package. Image must be in JPEG or PNG format and at most 500kB. Images larger than 256x400 will automatically be resized.<br /><br />| }, - { type => 'check', short => 'img_nsfw', name => '<b>NSFW.</b> Please check this option if the image contains nudity, gore, or is otherwise not safe in a work-friendly environment.' }, - - { type => 'sub', title => 'Visual novel relations', short => 'rel' }, - { type => 'jssel', name => 'Relations', short => 'relations', sh => 'rl' }, - { type => 'static', text => q| - <b>Direct relations:</b> Please only add direct relations. E.g. the sequel of a sequel does not have to be listed - here because it's already listed on an other visual novel that is in turn listed here. VNDB will handle these - relations automatically.<br /> - <b>Reverse relations:</b> If you add a relation with an other visual novel here, the same (or "reverse") relation - will automatically be added to the other visual novel. For example: if you add Tsukihime as a prequel of Kagetsu Tohya, - Kagetsu Tohya will automatically be added as a sequel for Tsukihime. - |}, - - { type => 'sub', title => 'Screenshots', short => 'scr' }, - { type => 'hidden', short => 'screenshots' }, - { type => 'static', raw => 1, text => qq| - <span class="warning"> - <b style="float: none; display: inline; font-weight: bold">Please keep the following in mind when uploading screenshots:</b><br /> - * Screenshots have to be in the native resolution of the game,<br /> - * Remove any window borders and make sure the image is unmarked,<br /> - * Don't only upload event CGs.<br /> - Please read the <a href="/d2#6">guidelines</a> for more information.<br /> - <b style="float: none; display: inline; font-weight: bold">Make sure to submit the form after the upload has finished!</b> - </span><br /> - <div id="scrfrm" class="$p{st}">...make sure to enable Javascript...</div> - <script type="text/javascript"> - var scrRel = [|.join(', ', map { ($$_{title} = _hchar($$_{title})) =~ s/\\/\\\\/g; $$_{title}=~s/'/\\'/g; "[ $$_{id}, '$$_{language}', '$$_{title}' ]" } @{$d{rel}}).q|]; - </script> - |}, - - { type => 'sub', title => 'Edit summary', short => 'com' }, - { type => 'textarea', name => 'Edit summary', short => 'comm', rows => 3, cols => 60 }, - { type => 'static', text => 'Please explain your modifications and cite all sources.' }, - - { type => 'submit', text => $d{id} ? 'Edit' : 'Add' }, - { type => 'endform' }, - -], $d{form}) ]] diff --git a/data/tpl/vnlist b/data/tpl/vnlist deleted file mode 100644 index d2763b39..00000000 --- a/data/tpl/vnlist +++ /dev/null @@ -1,63 +0,0 @@ -[[= ttabs('u', $d{user}) ]] -<h2>[[: $p{PageTitle} ]]</h2> -[[ - my $url = sprintf '/u%d/vlist', $d{user}{id}; - my $surl = sprintf '%s?s=%s;o=%s', $url, $d{order}[0], $d{order}[1]; - my $purl = $surl . ';t='.$d{status}; - my $sourl = $url . '?t='.$d{status}; - my $furl = $purl . ';p='.$d{page}; -]] - -<span class="warning"> - This visual novel list is read-only, only visible to you, and may be - deleted in future versions of the site. You are highly encouraged to - move everything in this list to the new <a href="/u[[= $d{user}{id} ]]/list">visual novel list</a>. -</span> - -<p class="chr"> - status: -[[ for (-1..$#$VNDB::LSTAT) { if($_ >= 0) { ]]- | -[[ } - if($d{status} == $_) { ]]<b>[[= $_ eq -1 ? 'all' : lc $VNDB::LSTAT->[$_] ]]</b>[[ } - else { ]]<a href="[[= $surl ]]&t=[[= $_ ]]">[[= $_ eq -1 ? 'all' : lc $VNDB::LSTAT->[$_] ]]</a>[[ } } ]] - <br /><br /> -</p> - - -[[ if($#{$d{list}} < 0) { ]]- -<p> -[[ if($d{status} >= 0) { ]] - No results found... -[[ } elsif($d{user}{username} eq $p{AuthUsername}) { ]] - Your visual novel list is empty. You can keep track of all the visual novels - you'd like to play, you're currently playing, or you've finished. Just go to - a visual novel page and add it to your VN list! -[[ } else { ]] - [[: $d{user}{username} ]]'s visual novel list is empty... -[[ } ]] -</p> - -[[ } else { ]] -[[= pagebut($purl) ]]- -<form method="post" action="[[= $furl ]]" class="tblf"> -<table id="tvl"> - <thead><tr> - <td class="tc1">Title [[= sortbut($sourl, 'title') ]]</td> - <td class="tc2">Status</td> - <td class="tc3">Added [[= sortbut($sourl, 'date') ]]</td> - <td class="tc4">Personal note</td> - <td class="tc5"> </td> - </tr></thead> - [[ for (@{$d{list}}) { ]]- - <tr> - <td class="tc1"><a href="/v[[= $_->{vid} ]]" title="[[: $_->{title} ]]">[[: length($_->{title})>40 ? substr($_->{title},0, 37).'...' : $_->{title} ]]</a></td> - <td class="tc2">[[= $VNDB::LSTAT->[$_->{status}] ]]</td> - <td class="tc3">[[= formatdate('%Y-%m-%d', $_->{date}, 'dh') ]]</td> - <td class="tc4">[[: $_->{comments}||'-' ]]</td> - <td class="tc5"><input type="checkbox" name="sel" value="[[= $_->{vid} ]]" /></td> - </tr> - [[ } ]]- -</table> -<input type="submit" value="Delete selected items" class="right" /> -</form> --[[= pagebut($purl) ]] -[[ } ]]- - diff --git a/data/tpl/vnpage b/data/tpl/vnpage deleted file mode 100644 index bca1bf35..00000000 --- a/data/tpl/vnpage +++ /dev/null @@ -1,204 +0,0 @@ -[[= ttabs('v', $d{vn}) ]] - -<h2>[[: $d{vn}{title} ]]</h2> -[[ if($d{vn}{original}) { ]]<h3 class="alttitle">[[: $d{vn}{original} ]]</h3>[[ } ]] - - -[[ if($d{vn}{hidden}) { ]]- - <span class="warning"> - This item has been deleted from the database. File a request on the - <a href="/t/v[[= $d{vn}{id} ]]">discussion board</a> to undelete this page. - </span> -[[ } ]] -[[ if(!$d{vn}{hidden} || $p{Authdel}) { ]]- - --[[ if($p{AuthLoggedin}) { ]] -<p class="mod">< - user options - - <a href="/u[[= $p{AuthId} ]]/list" rel="voteDD" class="dropdown">[[= $d{vote}{vid} ? 'your vote: '.$d{vote}{vote} : 'vote' ]]</a> - - <a href="/u[[= $p{AuthId} ]]/wish" rel="wishDD" class="dropdown">[[= $d{wlist}{vid} ? 'wishlist: '.lc($$VNDB::WSTAT[$d{wlist}{wstat}]) : 'wishlist' ]]</a> -></p> -[[ } ]]- - - - -[[ if($d{change}) { ]] -[[= cdiff($d{prev}, $d{vn}, - [ title => 'Title (romaji)', 1 ], - [ original => 'Original title', 1 ], - [ alias => 'Alias', 1, 1 ], - [ desc => 'Description', 1, 1 ], - [ length => 'Length', sub { $VNDB::VNLEN->[$_[0] ][0] } ], - [ l_wp => 'Wikipedia link', sub { $_[0] ? '<a href="http://en.wikipedia.org/wiki/'.$_[0].'">'.$_[0].'</a>' : 'No link' } ], - [ l_encubed => 'Encubed tag', sub { $_[0] ? '<a href="http://novelnews.net/tag/'._huri($_[0]).'/">'.$_[0].'</a>' : 'No link' } ], - [ l_renai => 'Renai.us link', sub { $_[0] ? '<a href="http://renai.us/game/'._huri($_[0]).'.shtml">'.$_[0].'</a>' : 'No link' } ], - [ l_vnn => 'V-N.net link', sub { $_[0] ? '<a href="http://visual-novels.net/vn/index.php?option=com_content&task=view&id='.$_[0].'">'.$_[0].'</a>' : 'No link' } ], - [ anime => 'Related anime', sub { join(' ', map qq|<a href="http://anidb.net/a$$_{id}">$$_{id}</a>|, sort { $a->{id} <=> $b->{id} } @{$_[0]}) } ], - [ categories => 'Categories', sub { join(' ', map { my $l=$VNDB::CAT->{substr($_->[0],0,1)}[1]{substr($_->[0],1,2)}; $l?$l.'('.$_->[1].')':() } sort { $a->[0] cmp $b->[0] } @{$_[0]}) || 'No categories selected' }, 1 ], - [ relations => 'Relations', sub { join("<br />\n", map { $VNDB::VREL->[$_->{relation}].': '._hchar($_->{title}) } sort { $a->{id} <=> $b->{id} } @{$_[0]}) } ], - [ image => 'Image', sub { $_[0] > 0 ? sprintf '<img src="%s/cv/%02d/%d.jpg" />', $p{st}, $_[0]%100, $_[0] : $_[0] < 0 ? '[processing]' : 'No image'; } ], - [ screenshots => 'Screenshots', sub { join "<br />\n", map sprintf('[%s] <a href="%s/sf/%02d/%d.jpg">%4$d</a> (%s)',$$_{rid}?qq|<a href="/r$$_{rid}">r$$_{rid}</a>|:'no release',$p{st},$$_{id}%100,$$_{id},$$_{nsfw}?'NSFW':'Safe'), @{$_[0]} } ], - [ img_nsfw => 'NSFW', sub { $_[0] ? 'Not safe' : 'Safe' } ] - ) ]] -[[ } ]]- - -[[ - my @lang; - for (@{$d{rel}}) { - my $l = $_->{language}; - next if grep { $_ eq $l } @lang; - push @lang, $l; - } - -]] - - -<div id="vnheader"> -<div> -[[ if($d{vn}{image} > 0) { ]] - [[ if($d{vn}{img_nsfw} && !$p{AuthNsfw}) { ]] - <img src="[[: $p{st} ]]/cv/nsfw.png" id="nsfw" class="[[: $p{st} ]]/cv/[[= sprintf '%02d/%d', $d{vn}{image}%100, $d{vn}{image} ]].jpg" /> - [[ } else { ]] - <img src="[[: $p{st} ]]/cv/[[= sprintf '%02d/%d', $d{vn}{image}%100, $d{vn}{image} ]].jpg" alt="[[: $p{PageTitle} ]]" /> - [[ if($d{vn}{img_nsfw}) { ]] - <p class="nsfw">[ flagged as NSFW ]</p> - [[ } ]] - [[ } ]] -[[ } elsif($d{vn}{image} < 0) { ]]- - [processing image, please return in a few minutes] -[[ } else { ]]- - No image uploaded yet... -[[ } ]]- -</div> - --[[ - my @links = ( - $d{vn}{l_wp} ? [ 'Wikipedia', 'http://en.wikipedia.org/wiki/%s', $d{vn}{l_wp} ] : (), - $d{vn}{l_encubed} ? [ 'Encubed', 'http://novelnews.net/tag/%s/', _huri $d{vn}{l_encubed} ] : (), - $d{vn}{l_renai} ? [ 'Renai.us', 'http://renai.us/game/%s.shtml', _huri $d{vn}{l_renai} ] : (), - $d{vn}{l_vnn} ? [ 'V-N.net', 'http://visual-novels.net/vn/index.php?option=com_content&task=view&id=%d', $d{vn}{l_vnn} ] : (), - ); - - my $prod = @lang && grep { @{$_->{producers}} } @{$d{rel}}; - -if($d{vn}{length} || $d{vn}{alias} || @links || $prod) { ]] - <h3>General info</h3> - <dl> - [[ if($d{vn}{length}) { ]]- - <dt>Length</dt><dd>[[: $VNDB::VNLEN->[$d{vn}{length}][0] ]]- ([[: $VNDB::VNLEN->[$d{vn}{length}][1] ]])</dd>[[ } ]]- - [[ if($d{vn}{alias}) { ]]- - <dt>Aliases</dt><dd>[[: $d{vn}{alias} ]]</dd>[[ } ]]- - [[ if(@links > 0) { ]]- - <dt>Links</dt><dd>[[= join(', ', map { '<a href="'.sprintf($_->[1],$_->[2]).'">'.$_->[0].'</a>' } @links) ]]</dd>[[ } ]]- - [[ if($prod) { ]]- - <dt>Producers</dt><dd> - [[ for my $l (@lang) { my %l; - $_->{language} eq $l && (%l = ( %l, map { - sprintf('<a href="/p%d" title="%s">%s</a>', - $_->{id}, _hchar($_->{original}||$_->{name}), _hchar shorten $_->{name}, 30) => 1 - } @{$_->{producers}} )) for (@{$d{rel}}); - if(keys %l) { ]]- - <acronym class="icons lang -[[= $l ]]" title="[[: $VNDB::LANG->{$l} ]]"> </acronym>[[= join(' & ', keys %l) ]]<br /> - [[ } } ]] - </dd>[[ } ]]- - </dl> -[[ } ]]- - - [[ if(@{$d{vn}{categories}}) { my %nolvl = (map {$_=>1} qw| pli pbr gaa gab hfa hfe lea lfa lsp tfu tpa tpr |); ]]- - <h3>Categories</h3> - <dl class="vnrel"> - [[ for (qw|e s g p h|) { - my $c = $_; - my @c = map { my $s=$_; - my ($cs) = grep { $_->[0] eq $c.$s } @{$d{vn}{categories}}; - $cs ? sprintf('<i class="crgn%d">%s</i>', $nolvl{$c.$_}?0:$cs->[1], $VNDB::CAT->{$c}[1]{$s}) - : () - } sort keys %{$VNDB::CAT->{$c}[1]}; - if(@c) { ]]- - <dt>[[: $VNDB::CAT->{$c}[0] ]]</dt><dd>[[= join(', ', @c) ]]</dd> - [[ } } ]] - [[ if(grep $_->[0] =~ /^[tl]/, @{$d{vn}{categories}}) { ]]- - <dt>Place/Time</dt><dd>[[= join ', ', map $VNDB::CAT->{substr($_->[0],0,1)}[1]{substr($_->[0],1,2)}, - sort { $a->[0] cmp $b->[0] } grep $_->[0] =~ /^[tl]/, @{$d{vn}{categories}} ]]</dd> - [[ } ]]- - </dl> - [[ } ]]- - - [[ if($#{$d{vn}{relations}} >= 0) { ]]- - <h3>[[= $d{page} eq 'rg' ? 'Relations' : '<a href="/v'.$d{vn}{id}.'/rg">Relations</a>' ]]</h3> - <dl class="vnrel"> - [[ my $lrel = -1; my $i=0; for (sort { $a->{relation} <=> $b->{relation} } @{$d{vn}{relations}}) { - if($_->{relation} != $lrel) { $lrel=$_->{relation}; if($i) { ]]</dd>[[ } ]]- - <dt>[[: $VNDB::VREL->[$lrel] ]]</dt><dd>[[ } else { ]]<br />[[ } ]] - <a href="/v[[= $_->{id} ]]" title="[[: $_->{original}||$_->{title} ]]">[[: shorten $_->{title}, 40 ]]</a> - [[ ++$i;} ]]</dd> - </dl> - [[ } ]]- - - [[ if(@{$d{vn}{anime}}) { ]]- - <h3>Related anime</h3> - <ul class="vnani"> - [[ for (sort { $a->{year} < 1 ? 1 : $b->{year} < 1 ? -1 : $a->{year} <=> $b->{year} } @{$d{vn}{anime}}) { ]]- - <li> - -[[ if($_->{lastfetch} < 1) { ]] - <b>[[= $_->{lastfetch} < 0 ? '[unknown anidb id: ' : '[no information available at this time: ' ]]<a href="http://anidb.net/a[[= $_->{id} ]]">[[= $_->{id} ]]</a>]</b> - [[ } else { - my $l = join '-', qq|<a href="http://anidb.net/a$_->{id}" title="AniDB">DB</a>|, - $_->{nfo_id} ? qq|<a href="http://animenfo.com/animetitle,$_->{nfo_id},vndb.html" title="AnimeNFO">NFO</a>| : (), - $_->{ann_id} ? qq|<a href="http://www.animenewsnetwork.com/encyclopedia/anime.php?id=$_->{ann_id}" title="Anime News Network">ANN</a>| : (); - ]] - <b>[-[[= $l ]]-]</b> <acronym title="[[: $_->{title_kanji} ]]">[[: shorten $_->{title_romaji}, 40 ]]</acronym> - <b>([[: $VNDB::ANITYPE->[$_->{type}][0] eq 'unknown' ? '' : $VNDB::ANITYPE->[$_->{type}][0].', ' ]][[= $_->{year} ]])</b> - [[ } ]] - </li> - [[ } ]] - </ul> - [[ } ]]- -</div> - --[[ - my @lnks = ( - !$d{page} ? '<b>description & releases</b>' : '<a href="/v'.$d{vn}{id}.'">description & releases</a>', - $d{page} eq 'stats' ? '<b>stats</b>' : '<a href="/v'.$d{vn}{id}.'/stats">stats</a>', - @{$d{vn}{screenshots}} ? ( - $d{page} eq 'scr' ? '<b>screenshots</b>' : '<a href="/v'.$d{vn}{id}.'/scr">screenshots</a>', - ) : (), - @{$d{vn}{relations}} ? ( - $d{page} eq 'rg' ? '<b>relations</b>' : '<a href="/v'.$d{vn}{id}.'/rg">relations</a>', - ) : (), - ); -]] -<p class="opts">- -[[= join(' - ', @lnks) ]]- -</p> - -[[ if(!$d{page}) { ]][[+ vnpage_rel ]][[ } ]] -[[ if($d{page} eq 'stats') { ]][[+ vnpage_stats ]][[ } ]] -[[ if($d{page} eq 'rg') { ]][[+ vnpage_rg ]][[ } ]] -[[ if($d{page} eq 'scr') { ]][[+ vnpage_scr ]][[ } ]] - -[[ if($p{AuthLoggedin}) { ]]- -<div class="dropdown" id="voteDD"> - <ul> - [[ if($d{vote}{vid}) { ]]- - <li><a href="/v[[= $d{vn}{id} ]]/vote?v=-1">revoke</a></li> - [[ } for (reverse 1..10) { ]]- - <li class="center"><a href="/v[[= $d{vn}{id} ]]/vote?v=[[= $_ ]]" id="dovote_[[= $_ ]]">[[= $_ ]]</a></li> - [[ } ]] - </ul> -</div> - -<div class="dropdown" id="wishDD"> - <ul> - [[ for (0..$#$VNDB::WSTAT) { - if($d{wlist}{vid} && $d{wlist}{wstat} == $_) { ]]- - <li><b>[[: $$VNDB::WSTAT[$_] ]]</b></li> - [[ } else { ]]- - <li><a href="/v[[= $d{vn}{id} ]]/wish?w=[[= $_ ]]">[[: $$VNDB::WSTAT[$_] ]]</a></li> - [[ } } if($d{wlist}{vid}) { ]]- - <li><a href="/v[[= $d{vn}{id} ]]/wish?w=-1">remove</a></li> - [[ } ]] - </ul> -</div> -[[ } ]] - - -[[ } ]] diff --git a/data/tpl/vnpage_rel b/data/tpl/vnpage_rel deleted file mode 100644 index 4e5d29b2..00000000 --- a/data/tpl/vnpage_rel +++ /dev/null @@ -1,59 +0,0 @@ -<h3>Description</h3> -<p class="desc"> - [[= summary($d{vn}{desc}) ]] - <br /><br /><br /> -</p> - - - -[[ - my @lang; - for (@{$d{rel}}) { - my $l = $_->{language}; - next if grep { $_ eq $l } @lang; - push @lang, $l; - } - -]] - - -<h3>Releases -[[ if((!$d{vn}{locked} && $p{Authedit}) || $p{Authlock}) { ]]- <p class="actions">(<a href="/v[[= $d{vn}{id} ]]/add">add release</a>)</p>[[ } ]]</h3> -[[ if(@{$d{rel}}) { ]]- -<table id="tre"> -[[ for(@lang) { my $l = $_; ]]- -<tr class="lang"> - <td colspan="6">[[: $VNDB::LANG->{$l} ]]</td> -</tr> -[[ for (@{$d{rel}}) { next if $l ne $_->{language}; ]]- - <tr> - <td class="tc1">[[= datestr($_->{released}) ]]</td> - <td class="tc2">[[= $_->{minage}<0 ? '' : $VNDB::VRAGES->{$_->{minage}} ]]</td> - <td class="tc3"> - [[= join('', map { $_ ne 'oth' ? '<acronym class="icons '.$_.'" title="'._hchar($VNDB::PLAT->{$_}).'"> </acronym>' : () } sort @{$_->{platforms}}) ]] - <acronym title="[[= $VNDB::RTYP->[$_->{type}] ]]- release" class="icons -[[= lc substr($VNDB::RTYP->[$_->{type}],0,3) ]]"> </acronym> - </td> - <td class="tc4"><a href="/r[[= $_->{id} ]]" title="[[: $_->{original} || $_->{title} ]]">[[: shorten $_->{title},60 ]]</a></td> - <td class="tc5">[[ if($p{AuthId}) { ]] - [[= sprintf '<a href="/r%d" class="dropdown above" rel="rlistDD%1$d">%s</a>', $_->{id}, $_->{rlist} ? - ('<acronym title="'.$VNDB::RSTAT->[$_->{rlist}{rstat}].'" class="uicons r'.$_->{rlist}{rstat}.'"> </acronym>'. - '<acronym title="'.$VNDB::VSTAT->[$_->{rlist}{vstat}].'" class="uicons v'.$_->{rlist}{vstat}.'"> </acronym>') - : '<acronym title="Add to your visual novel list" class="uicons no"> </acronym>' ]] - [[ } else { ]] [[ } ]]</td> - <td class="tc6">[[ if($_->{website}) { ]]<a href="[[: $_->{website} ]]" class="icons ext" title="WWW"> </a>[[ } ]]</td> - </tr> -[[ } ]]- -[[ } ]]- -</table> -[[ } else { ]]- -<p> - This game has either not been released yet, or we just don't have information about - any releases. -</p> -[[ } ]] - - -[[ if($p{AuthId}) { ]] -[[ for my $r (@{$d{rel}}) { ]]- --[[= rlist_dd($r) ]] -[[ } } ]] diff --git a/data/tpl/vnpage_rg b/data/tpl/vnpage_rg deleted file mode 100644 index deae6124..00000000 --- a/data/tpl/vnpage_rg +++ /dev/null @@ -1,11 +0,0 @@ -<h3>Relations</h3> -[[ if(!$d{vn}{rgraph}) { ]] - <p> - Relation graph has not been generated yet... - </p> -[[ } else { ]] - [[= $d{vn}{cmap} ]] - <p id="relations"> - <img src="[[= sprintf "%s/rg/%02d/%d.png", $p{st}, $d{vn}{rgraph}%100, $d{vn}{rgraph} ]]" usemap="#rgraph" alt="Relation graph for -[[: $d{vn}{title} ]]" /> - </p> -[[ } ]] diff --git a/data/tpl/vnpage_scr b/data/tpl/vnpage_scr deleted file mode 100644 index f0c4ae9f..00000000 --- a/data/tpl/vnpage_scr +++ /dev/null @@ -1,37 +0,0 @@ -<h3>Screenshots -[[ if((!$d{vn}{locked} && $p{Authedit}) || $p{Authlock}) { ]]- <p class="actions">(<a href="/v[[= $d{vn}{id} ]]/edit?fh=scr">manage screenshots</a>)</p>[[ } ]]</h3> - -[[ if(@{$d{vn}{screenshots}}) { - my $tot = @{$d{vn}{screenshots}}; - my $nsfw = grep $$_{nsfw}, @{$d{vn}{screenshots}}; -]]- - -<div id="screenshots"> -[[ for my $r (undef, @{$d{rel}}) { - my @s = grep { !$r && !$_->{rid} || $r && $_->{rid} && $_->{rid} == $r->{id} } @{$d{vn}{screenshots}}; - next if !@s; -]]- -[[ if($r) { ]] -<b><acronym class="icons lang -[[= $r->{language} ]]" title="[[: $VNDB::LANG->{$r->{language}} ]]"> </acronym> -[[: $r->{title} ]]</b> -[[ } ]] -[[ for(@s) { ]] - <a href="[[= sprintf '%s/sf/%02d/%d.jpg', $p{st}, $$_{id}%100, $$_{id} ]]" - class="shot [[= $$_{nsfw} ? ' scr_nsfw':'' ]]" [[= !$p{AuthNsfw}&&$$_{nsfw}?' style="display: none"':'' ]]- - rel="[[= $$_{width}.'x'.$$_{height} ]]"><img src="[[= sprintf '%s/st/%02d/%d.jpg', $p{st}, $$_{id}%100, $$_{id} ]]" - /><b>[[= $$_{nsfw} ? 'x' : ' ' ]]</b></a> -[[ } ]]- -<br style="clear: left" /><br /> -[[ } ]] - -</div> -[[ if($nsfw) { ]]- -<p id="scrNsfwHid"> </p> -<i style="font-size: 10px;">Items marked with a red X are flagged as NSFW.</i> -[[ } ]]- - -[[ } else { ]]- -<p> - No screenshots have been uploaded yet for this visual novel. -</p> -[[ } ]] diff --git a/data/tpl/vnpage_stats b/data/tpl/vnpage_stats deleted file mode 100644 index ab159f14..00000000 --- a/data/tpl/vnpage_stats +++ /dev/null @@ -1,39 +0,0 @@ -<ul id="stats"> - -[[ - my $max = 1; my $total = 0; my $sum = 0; - for (0..$#{$d{votes}{graph}}) { - $total += $d{votes}{graph}[$_]; - $max = $d{votes}{graph}[$_] if $d{votes}{graph}[$_] > $max; - $sum += ($_+1) * $d{votes}{graph}[$_]; - } -]] -[[ if(!$d{user} || ($d{pl} && $d{user}{votes})) { ]]- -<li><h3>Vote graph <p class="actions">[[= $total ]]- vote[[= $total==1?'':'s' ]]- total - [[= $total && $d{user} ? sprintf(', average: %.1f.', $sum/$total) : '' ]]</p></h3> -<table id="tvg"> -[[ for (reverse 0..$#{$d{votes}{graph}}) { ]]- - <tr> - <td class="tc1">[[= $_+1 ]]</td> - <td class="tc2"><div style="width: -[[= ($d{votes}{graph}[$_]/$max)*270 + 5 ]]px"> </div>[[= $d{votes}{graph}[$_] ]]</td> - </tr> -[[ } ]]- -</table></li> - -[[ if($#{$d{votes}{latest}} >= 0) { ]] -<li><h3>Recent votes</h3> -<table id="tvr"> -[[ for (@{$d{votes}{latest}}) { ]]- - <tr> - [[ if(!$d{user}) { ]]- - <td class="tc1">[[= userstr $_ ]]</td> - [[ } else { ]]- - <td class="tc1"><a href="/v[[= $_->{vid} ]]" title="[[: $_->{original}||$_->{title} ]]">[[: shorten $_->{title}, 30 ]]</a></td> - [[ } ]]- - <td class="tc2">[[= $_->{vote} ]]</td> - <td class="tc3">[[= formatdate('%Y-%m-%d %R', $_->{date}, 'dh') ]]</td> - </tr> -[[ } ]]- -</table></li> -[[ } } ]]- -</ul> diff --git a/data/tpl/wlist b/data/tpl/wlist deleted file mode 100644 index 049d28ca..00000000 --- a/data/tpl/wlist +++ /dev/null @@ -1,55 +0,0 @@ -[[= ttabs('u', $d{user}, 'wish') ]] -<h2>[[: $p{PageTitle} ]]</h2> -[[ - my $url = sprintf '/u%d/wish', $d{user}{id}; - my $surl = sprintf '%s?s=%s;o=%s', $url, $d{order}[0], $d{order}[1]; - my $furl = $surl . ';p='.$d{page}; -]] - - -[[ if($#{$d{list}} < 0) { ]]- -<p> -[[ if($d{user}{username} eq $p{AuthUsername}) { ]] - Your wishlist is empty. You can keep track of all the visual novels - you'd like to play. Just go to a visual novel page and add it to your wishlist! -[[ } else { ]] - [[: $d{user}{username} ]]'s wishlist is empty... -[[ } ]] -</p> - -[[ } else { ]] -[[= pagebut($surl) ]]- -[[ if($d{user}{username} eq $p{AuthUsername}) { ]] -<form method="post" action="[[= $furl ]]" class="tblf"> -[[ } ]] -<table id="twl"> - <thead><tr> - <td class="tc1">Title [[= sortbut($url, 'title') ]]</td> - <td class="tc2">Priority [[= sortbut($url, 'wstat') ]]</td> - <td class="tc3">Added [[= sortbut($url, 'added') ]]</td> - <td class="tc4"> </td> - </tr></thead> - [[ for (@{$d{list}}) { ]]- - <tr> - <td class="tc1"><a href="/v[[= $_->{vid} ]]" title="[[: $_->{original}||$_->{title} ]]">[[: shorten $_->{title}, 40 ]]</a></td> - <td class="tc2">[[= $VNDB::WSTAT->[$_->{wstat}] ]]</td> - <td class="tc3">[[= formatdate('%Y-%m-%d', $_->{added}) ]]</td> - <td class="tc4">[[ if($d{user}{username} eq $p{AuthUsername}) { ]]<input type="checkbox" name="sel" value="[[= $_->{vid} ]]" />[[ } else { ]] [[ } ]]</td> - </tr> - [[ } ]]- -</table> -[[ if($d{user}{username} eq $p{AuthUsername}) { ]] -<select id="vnlistchange" name="vnlistchange" class="right"> - <option value="n">- with selected -</option> - <option value="d">Delete</option> - <optgroup label="Update priority:"> - [[ for (0..$#$VNDB::WSTAT) { ]]- - <option value="[[= $_ ]]">[[: $VNDB::WSTAT->[$_] ]]</option> - [[ } ]] - </optgroup> -</select> -</form> -[[ } ]] --[[= pagebut($surl) ]] -[[ } ]]- - diff --git a/lib/VNDB.pm b/lib/VNDB.pm deleted file mode 100644 index 94edf82e..00000000 --- a/lib/VNDB.pm +++ /dev/null @@ -1,247 +0,0 @@ -package VNDB; - -use strict; -use warnings; - -BEGIN { require 'global.pl'; } -our $DEBUG; - -require Time::HiRes if $DEBUG; -require Data::Dumper if $DEBUG; -use VNDB::Util::Template; -use VNDB::Util::Request; -use VNDB::Util::Response; -use VNDB::Util::DB; -use VNDB::Util::Tools; -use VNDB::Util::Auth; -use VNDB::Discussions; -use VNDB::HomePages; -use VNDB::Producers; -use VNDB::Releases; -use VNDB::VNLists; -use VNDB::Users; -use VNDB::VN; - - -my %VNDBuris = ( # wildcards: * -> (.+), + -> ([0-9]+) - '/' => sub { shift->HomePage }, - 'd+' => sub { shift->DocPage(shift) }, - 'd+.+' => sub { shift->ResRedirect('/d'.$_[0][0].'#'.$_[0][1]) }, - nospam => sub { shift->ResAddTpl(error => { err => 'formerr' }) }, - hist => {'*'=> sub { shift->History(undef, undef, $_[1]) } }, - # users - u => { - login => sub { shift->UsrLogin }, - logout => sub { shift->UsrLogout }, - register => sub { shift->UsrReg }, - newpass => sub { shift->UsrPass }, - list => { - '/' => sub { shift->UsrList }, - '*' => sub { $_[3] =~ /^([a-z0]|all)$/ ? shift->UsrList($_[2]) : shift->ResNotFound }, - }, - }, - 'u+' => { - '/' => sub { shift->UsrPage(shift) }, - edit => sub { shift->UsrEdit(shift) }, - del => sub { shift->UsrDel(shift) }, - list => sub { shift->RList(shift) }, - vlist => sub { shift->VNMyList(shift) }, - wish => sub { shift->WList(shift) }, - hist => {'*'=> sub { shift->History('u', shift, $_[1]) } }, - }, - # visual novels - v => { - '/' => sub { shift->VNBrowse }, - new => sub { shift->VNEdit(0); }, - '*' => sub { $_[2] =~ /^([a-z0]|all|search)$/ ? shift->VNBrowse($_[1]) : shift->ResNotFound; }, - }, - 'v+' => { - '/' => sub { shift->VNPage(shift) }, - stats => sub { shift->VNPage(shift, shift) }, - rg => sub { shift->VNPage(shift, shift) }, - scr => sub { shift->VNPage(shift, shift) }, - edit => sub { shift->VNEdit(shift) }, - vote => sub { shift->VNVote(shift) }, - wish => sub { shift->WListMod(shift) }, - add => sub { shift->REdit('v', shift) }, - lock => sub { shift->VNLock(shift) }, - hide => sub { shift->VNHide(shift) }, - hist => {'*'=> sub { shift->History('v', shift, $_[1]) } }, - }, - 'v+.+' => sub { shift->VNPage($_[0][0], '', $_[0][1]) }, - # releases - 'r+' => { - '/' => sub { shift->RPage(shift) }, - edit => sub { shift->REdit('r', shift) }, - lock => sub { shift->RLock(shift) }, - hide => sub { shift->RHide(shift) }, - list => sub { shift->RListMod(shift) }, - hist => {'*'=> sub { shift->History('r', shift, $_[1]) } }, - }, - 'r+.+' => sub { shift->RPage($_[0][0], $_[0][1]) }, - # producers - p => { - '/' => sub { shift->PBrowse }, - add => sub { shift->PEdit(0) }, - '*' => sub { $_[2] =~ /^([a-z0]|all)$/ ? shift->PBrowse($_[1]) : shift->ResNotFound; } - }, - 'p+' => { - '/' => sub { shift->PPage(shift) }, - edit => sub { shift->PEdit(shift) }, - lock => sub { shift->PLock(shift) }, - hide => sub { shift->PHide(shift) }, - hist => {'*'=> sub { shift->History('p', shift, $_[1]) } }, - }, - 'p+.+' => sub { shift->PPage($_[0][0], $_[0][1]) }, - # discussions - t => { - '/' => sub { shift->TIndex }, - '*' => { - '/' => sub { shift->TTag($_[1]) }, - new => sub { shift->TEdit(0, 0, $_[1]) }, - }, - }, - 't+' => { - '/' => sub { shift->TThread(shift) }, - reply => sub { shift->TEdit(shift) }, - '+' => sub { shift->TThread(shift, shift) }, - }, - 't+.+' => { - edit => sub { shift->TEdit($_[0][0], $_[0][1]) }, - '/' => sub { $_[0]->ResRedirect('/t'.$_[1][0].($_[1][1]>$_[0]->{postsperpage}?'/'.ceil($_[1][1]/$_[0]->{postsperpagee}):'').'#'.$_[1][1], 'perm') }, - }, - # stuff (.xml extension to make sure they aren't counted as pageviews) - xml => { - 'producers.xml' => sub { shift->PXML }, - 'vn.xml' => sub { shift->VNXML }, - 'screenshots.xml' => sub { shift->VNScrXML }, - }, -); - - -# provide redirects for old URIs -my %OLDuris = ( - faq => sub { shift->ResRedirect('/d6', 'perm') }, - notes => sub { shift->ResRedirect('/d8', 'perm') }, - vn => { - rss => sub { shift->ResRedirect('/hist/rss?t=v&e=1', 'perm') }, - '*' => sub { shift->ResRedirect('/v/'.$_[1], 'perm') }, - }, - v => { - cat => sub { - my $f = $_[0]->FormCheck({name=>'i',required=>0},{name=>'e',required=>0},{name=>'l',required=>0}, - {name=>'p',required=>0},{name=>'o',required=>0},{name=>'s',required=>0}); - my %f; - $f{$_} = $f->{$_} for (qw|p o s|); - $f{q} = join ' ', (map $VNDB::CAT->{substr($_,0,1)}[1]{substr($_,1,2)}, split /,/, $f->{i}), - (map '-'.$VNDB::CAT->{substr($_,0,1)}[1]{substr($_,1,2)}, split /,/, $f->{e}), - (map $VNDB::LANG->{$_}, split /,/, $f->{l}); - !$f{$_}&&delete $f{$_} for keys %f; - $_[0]->ResRedirect('/v/search'.(!(keys %f)?'':'?'.join(';', map $_.'='.$f{$_}, keys %f) ), 'perm'); - }, - }, - 'v+' => { - votes => sub { shift->ResRedirect('/v'.(shift).'/stats', 'perm') }, - hist=>{rss => sub { shift->ResRedirect('/v'.(shift).'/hist/rss.xml', 'perm') } }, - }, - u => { - '*' => { - '*' => sub { - if($_[2] =~ /^_(login|logout|register|newpass|list)$/) { - $_[3] eq '/' ? $_[0]->ResRedirect('/u/'.$1, 'perm') : $_[0]->ResRedirect('/u/'.$1.'/'.$_[3], 'perm'); - } else { - my $id = $_[0]->DBGetUser(username => $_[2])->[0]{id}; - $id ? $_[0]->ResRedirect('/u'.$id.'/'.$_[3], 'perm') : $_[0]->ResNotFound; - } - }, - } - }, - 'u+' => { - votes => sub { shift->ResRedirect('/u'.(shift).'/list', 'perm') }, - hist=>{rss => sub { shift->ResRedirect('/u'.(shift).'/hist/rss.xml', 'perm') } }, - }, - 'p+' => { - hist=>{rss => sub { shift->ResRedirect('/p'.(shift).'/hist/rss.xml', 'perm') } }, - }, - 'r+' => { - hist=>{rss => sub { shift->ResRedirect('/r'.(shift).'/hist/rss.xml', 'perm') } }, - }, - hist=>{rss => sub { shift->ResRedirect('/hist/rss.xml', 'perm') } }, -); - - - -sub new { - my $self = shift; - my $type = ref($self) || $self; - my %args = @_; - - my $me = bless { - debug => $VNDB::DEBUG, - %args, - _DB => VNDB::Util::DB->new(@VNDB::DBLOGIN), - _TPL => VNDB::Util::Template->new(%{$args{tplopts}}), - cmds => [], - }, $type; - - return $me; -} - - -sub get_page { - my $self = shift; - my $r = shift; - - $self->{_Req} = VNDB::Util::Request->new($r); - $self->{_Res} = VNDB::Util::Response->new($self->{_TPL}); - - $self->AuthCheckCookie(); - $self->checkuri(); - - my $res = $self->ResSetModPerl($r); - $self->DBCommit(); - - # commands have to be executed _after_ the call to DBCommit, - # otherwise Multi can't see the new additions - $self->RunCmd(); - - return($self, $res); -} - - -sub checkuri { - my $self = shift; - (my $uri = lc($self->ReqUri)) =~ s/^\/+//; - $uri =~ s/\?.*$//; - return $self->ResRedirect("/$uri", 'perm') if $uri =~ s/\/+$//; - $uri =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; # ugly hack, but we only accept ASCII anyway - return $self->ResNotFound() if $uri !~ /^[a-z0-9\-\._~\/]*$/; # rfc3986 section 2.3, "Unreserved Characters" - my @uri; - defined $_ and push(@uri, $_) for (split(/\/+/, $uri)); - my @ouri = @uri; # items in @uri can be modified by uri2page - $self->uri2page(\%VNDBuris, \@uri, 0); - $self->uri2page(\%OLDuris, \@ouri, 0) # provide redirects for old uris - if $self->{_Res}->{code} == 404; -} - - -sub uri2page { - my($s, $o, $u, $i) = @_; - $u->[$i] = '/' if !defined $u->[$i]; - my $n = $o->{$u->[$i]} ? $u->[$i] : ((map { - if(/[\*\+]/) { - (my $t = "^$_\$") =~ s/\./\\./g; - /\*/ ? ($t =~ s/\*/(.+)/g) : ($t =~ s/\+/([1-9][0-9]*)/g); - $u->[$i] =~ /$t/ ? ($u->[$i] = $2?[$1,$2]:$1) && $_ : (); - } else { () } } - sort { length($b) <=> length($a) } keys %$o)[0] || '*'); - ref($o->{$n}) eq 'HASH' && $n ne '/' ? - $s->uri2page($o->{$n}, $u, ++$i) : - ref($o->{$n}) eq 'CODE' && $i == $#$u ? - &{$o->{$n}}($s, @$u) : - $s->ResNotFound(); -} - - -1; - diff --git a/lib/VNDB/Discussions.pm b/lib/VNDB/Discussions.pm deleted file mode 100644 index 9f80b0b0..00000000 --- a/lib/VNDB/Discussions.pm +++ /dev/null @@ -1,193 +0,0 @@ - -package VNDB::Discussions; - -use strict; -use warnings; -use Exporter 'import'; -use POSIX 'ceil'; - -use vars ('$VERSION', '@EXPORT'); -$VERSION = $VNDB::VERSION; -@EXPORT = qw| TThread TEdit TIndex TTag |; - - -sub TThread { - my $self = shift; - my $id = shift; - my $page = shift||1; - - my $t = $self->DBGetThreads(id => $id, what => 'tagtitles')->[0]; - return $self->ResNotFound if !$t || $t->{hidden} && !$self->AuthCan('boardmod'); - - my $p = $self->DBGetPosts(tid => $id, results => $self->{postsperpage}, page => $page); - return $self->ResNotFound if !$p->[0]; - - $self->ResAddTpl(tthread => { - t => $t, - ppp => $self->{postsperpage}, - page => $page, - p => $p, - }); -} - - -# tid num action -# 0 0 Start a new thread -# x 0 Reply to a thread -# x 1 Edit thread (and first post) -# x x Edit post -sub TEdit { - my $self = shift; - my $tid = shift||0; - my $num = shift||0; - my $tag = shift||''; - - my $t = $tid && $self->DBGetThreads(id => $tid, what => 'tags')->[0]; - return $self->ResNotFound if $tid && !$t; - - my $p = $num && $self->DBGetPosts(tid => $tid, num => $num)->[0]; - - my $frm = {}; - if($self->ReqMethod eq 'POST') { - $frm = $self->FormCheck( - { name => 'msg', required => 1, maxlength => 5000 }, - !$tid || $num == 1 ? ( - { name => 'title', required => 1, maxlength => 50 }, - { name => 'tags', required => 1, maxlength => 50 }, - ) : (), - $self->AuthCan('boardmod') ? ( - { name => 'hide', required => 0 }, - { name => 'lock', required => 0 } - ) : (), - ); - $frm->{msg} =~ s/[\r\s\n]$//g; - - my %tags = !$frm->{tags} || $frm->{_err} ? () : map { - $frm->{_err} = [ 'wrongtag' ] if - !/^([a-z]{1,2})([0-9]*)$/ || !$VNDB::DTAGS->{$1} - || $1 eq 'v' && (!$2 || !$self->DBGetVN(id => $2)->[0]) - #|| $1 eq 'r' && (!$2 || !$self->DBGetRelease(id => $2)->[0]) - || $1 eq 'p' && (!$2 || !$self->DBGetProducer(id => $2)->[0]) - || $1 eq 'u' && (!$2 || !$self->DBGetUser(id => $2)->[0]) - || $1 eq 'an' && !$self->AuthCan('boardmod'); - $1.($2||0) => [ $1, $2||0 ] - } split / /, $frm->{tags}; - my @tags = values %tags; - - if(!$frm->{_err}) { - my $otid = $tid; - if(!$tid || $num == 1) { - my @tags = - my %thread = ( - id => $tid, - title => $frm->{title}, - tags => \@tags, - hidden => $frm->{hide}, - locked => $frm->{lock}, - ); - $self->DBEditThread(%thread) if $tid; # edit thread - $tid = $self->DBAddThread(%thread) if !$tid; # create thread - } - - my $onum = $num; - my %post = ( - tid => $tid, - num => !$otid ? 1 : $num, - msg => $frm->{msg}, - hidden => $num != 1 && $frm->{hide}, - ); - $self->DBEditPost(%post) if $num; # edit post - $num = $self->DBAddPost(%post) if !$num; # add post - - $self->RunCmd('ircnotify t'.$tid.'.'.$num) if !$onum && !$frm->{hide}; - - my $pagenum = ceil($num/$self->{postsperpage}); - $pagenum = $pagenum > 1 ? '/'.$pagenum : ''; - $self->ResRedirect('/t'.$tid.$pagenum.'#'.$num, 'POST'); - } - } - - if($p) { - $frm->{msg} ||= $p->{msg}; - $frm->{hide} = $p->{hidden}; - if($num == 1) { - $frm->{tags} ||= join ' ', sort map $_->[1]?$_->[0].$_->[1]:$_->[0], @{$t->{tags}}; - $frm->{title} ||= $t->{title}; - $frm->{lock} = $t->{locked}; - $frm->{hide} = $t->{hidden}; - } - } - $frm->{tags} ||= $tag; - - $self->ResAddTpl(tedit => { - t => $t, - p => $p, - tag => $tag, - form => $frm, - }); -} - - -sub TIndex { - my $self = shift; - - my %opts = ( - results => 6, - what => 'firstpost lastpost tags', - order => 'tp2.date DESC', - ); - - $self->ResAddTpl(tindex => { - ppp => $self->{postsperpage}, - map +($_, scalar $self->DBGetThreads(%opts, type => $_)), qw| an db v p u| - }); -} - - -sub TTag { - my $self = shift; - my $tag = shift; - my($type, $iid) = ($1, $2||0) if $tag =~ /^([a-z]{1,2})([0-9]*)$/; - return $self->ResNotFound if !$type; - - my $f = $self->FormCheck( - { name => 'p', required => 0, default => 1, template => 'int' }, - ); - return $self->ResNotFound if $f->{_err}; - - my $o = !$iid ? undef : - $type eq 'u' ? $self->DBGetUser(uid => $iid)->[0] : - $type eq 'v' ? $self->DBGetVN(id => $iid)->[0] : - #$type eq 'r' ? $self->DBGetRelease(id => $iid)->[0] : - $self->DBGetProducer(id => $iid)->[0]; - return $self->ResNotFound if $iid && !$o || !$VNDB::DTAGS->{$type}; - my $title = $o ? $o->{username} || $o->{romaji} || $o->{title} || $o->{name} : $VNDB::DTAGS->{$type}; - my $original = $o ? $o->{username} || $o->{original} : $VNDB::DTAGS->{$type}; - - my($t, $np) = $self->DBGetThreads( - type => $type, - iid => $iid, - results => 50, - page => $f->{p}, - what => 'firstpost lastpost tagtitles', - order => $tag eq 'an' ? 't.id DESC' : 'tp2.date DESC', - ); - - $self->ResAddTpl(ttag => { - page => $f->{p}, - npage => $np, - obj => $o, - type => $type, - iid => $iid, - title => $title, - original => $original, - tag => $tag, - t => $t, - ppp => $self->{postsperpage}, - }); -} - - - -1; - diff --git a/lib/VNDB/HomePages.pm b/lib/VNDB/HomePages.pm deleted file mode 100644 index 63adcab7..00000000 --- a/lib/VNDB/HomePages.pm +++ /dev/null @@ -1,306 +0,0 @@ - -package VNDB::HomePages; - -use strict; -use warnings; -use Exporter 'import'; - -use vars ('$VERSION', '@EXPORT'); -$VERSION = $VNDB::VERSION; -@EXPORT = qw| HomePage DocPage History HistRevert HistDelete |; - - -sub HomePage { - my $self = shift; - - my $an = $self->DBGetThreads(type => 'an', order => 't.id DESC', results => 1)->[0]; - $self->ResAddTpl(home => { - an => $an, - anpost => $self->DBGetPosts(tid => $an->{id}, num => 1)->[0], - recentedits => scalar $self->DBGetHist( results => 10, what => 'iid ititle'), - recentvns => scalar $self->DBGetHist( results => 10, what => 'iid ititle', edits => 0, type => 'v'), - randomvns => scalar $self->DBGetVN( results => 10, order => 'RANDOM()'), - recentposts => scalar $self->DBGetThreads(results => 10, what => 'lastpost', order => 'tp2.date DESC'), - # cache this shit when performance is going to be problematic - upcomingrel => scalar $self->DBGetRelease(results => 10, unreleased => 1), - justrel => scalar $self->DBGetRelease(results => 10, order => 'rr.released DESC', unreleased => 0), - }); -} - - -sub DocPage { - my($s,$p) = @_; - - open my $F, '<', sprintf('%s/%d', $s->{docpath}, $p) or return $s->ResNotFound(); - my @c = <$F>; - close $F; - - (my $title = shift @c) =~ s/^:TITLE://; - chomp $title; - - my $sec = 0; - for (@c) { - s{^:SUB:(.+)\r?\n$}{ - $sec++; - qq|<h3><a href="#$sec" name="$sec">$sec. $1</a></h3>\n| - }eg; - s{^:INC:(.+)\r?\n$}{ - open $F, '<', sprintf('%s/%s', $s->{docpath}, $1) or die $!; - my $ii = join('', <$F>); - close $F; - $ii; - }eg; - } - - $s->ResAddTpl(docs => { - title => $title, - content => join('', @c), - }); -} - - -sub History { # type(p,v,r,u), id, [rss.xml|/] - my($self, $type, $id, $fmt) = @_; - $type ||= ''; - $id ||= 0; - - $fmt = undef if !$fmt || $fmt eq '/'; - return $self->ResNotFound if $fmt && $fmt ne 'rss.xml'; - - my $f = $self->FormCheck( - { name => 'p', required => 0, default => 1, template => 'int' }, - { name => 'ip', required => 0, default => 0 }, # hidden option - { name => 't', required => 0, default => 'a', enum => [ qw| v r p a | ] }, - { name => 'e', required => 0, default => 0, enum => [ 0..2 ] }, - { name => 'r', required => 0, default => $fmt ? 10 : 50, template => 'int' }, - { name => 'i', required => 0, default => 0, enum => [ 0..1 ] }, - { name => 'h', required => 0, default => 0, enum => [ 0..2 ] }, # hidden option - ); - return $self->ResNotFound if $f->{_err}; - - my $o = - $type eq 'u' ? $self->DBGetUser(uid => $id)->[0] : - $type eq 'v' ? $self->DBGetVN(id => $id)->[0] : - $type eq 'r' ? $self->DBGetRelease(id => $id)->[0] : - $type eq 'p' ? $self->DBGetProducer(id => $id)->[0] : - undef; - return $self->ResNotFound if $type && !$o; - my $t = - $type eq 'u' ? $o->{username} : - $type eq 'v' ? $o->{title} : - $type eq 'r' ? $o->{romaji} || $o->{title} : - $type eq 'p' ? $o->{name} : - undef; - - my($h, $np, $act); - - if($self->ReqMethod ne 'POST' || $fmt) { - ($h, $np) = $self->DBGetHist( - what => 'iid ititle user', - type => $type, - !$type && $f->{t} ne 'a' ? ( - type => $f->{t} ) : (), - $f->{e} ? ( - edits => $f->{e} == 1 ? 0 : 1 ) : (), - id => $id, - page => $fmt ? 0 : $f->{p}, - results => $f->{r}, - releases => $type eq 'v' ? $f->{i} : 0, - showhid => $f->{h}, - $f->{ip} ? ( - ip => $f->{ip} ) : (), - ); - } - else { - my $frm = $self->FormCheck( - { name => 'sel', required => 1, multi => 1 }, - { name => 'post', required => 1, default => 'Mass revert', enum => [ 'Mass revert', 'Mass delete' ] }, - ); - my @s = grep /^[0-9]+$/, @{$frm->{sel}}; - if(!$frm->{_err} && @s) { - $np = 0; - $h = $frm->{post} =~ /revert/ ? $self->HistRevert(\@s) : $self->HistDelete(\@s); - $act = $frm->{post} =~ /revert/ ? 'r' : 'd'; - } - } - - if(!$fmt) { - $self->ResAddTpl(hist => { - title => $t, - selt => $f->{t}, - sele => $f->{e}, - seli => $f->{i}, - type => $type, - id => $id, - hist => $h, - page => $f->{p}, - npage => $np, - obj => $o, - act => $act || '', - }); - } else { - my $x = $self->ResStartXML; - $x->startTag('rss', version => '2.0'); - $x->startTag('channel'); - $x->dataElement('language', 'en'); - $x->dataElement('title', !$type ? 'Recent changes at VNDB.org' : $type eq 'u' ? 'Recent changes by '.$t : 'Edit history of '.$t); - $x->dataElement('link', $self->{root_url}.(!$type ? '/hist' : '/'.$type.$id.'/hist')); - - for (@$h) { - my $t = (qw| v r p |)[$_->{type}]; - my $url = $self->{root_url}.'/'.$t.$_->{iid}.'?rev='.$_->{id}; - $_->{comments} = VNDB::Util::Template::tpl::summary($_->{comments})||'[no summary]'; - $x->startTag('item'); - $x->dataElement(title => $_->{ititle}); - $x->dataElement(link => $url); - $x->dataElement(pubDate => NTL::time2str($_->{requested})); - $x->dataElement(guid => $url); - $x->dataElement(description => $_->{comments}); - $x->endTag('item'); - } - - $x->endTag('channel'); - $x->endTag('rss'); - } -} - - - - -1; - -__END__ - - -############################################################# -# E X P E R I M E N T A L S T U F F # -# # - -# !WARNING!: this code has not been updated to reflect the recent database changes! - - -# !WARNING!: this code uses rather many large SQL queries, use with care... -sub HistRevert { # \@ids - my($self, $l) = @_; - my $comm = 'Mass revert to revision %d by %s'; - - # first, get objects, remove newly created items and causedby edits and add original edits - $l = $self->DBGetHist(cid => $l, results => 1000, what => 'iid'); - my @todo; - for (@$l) { - next if !$_->{prev}; # remove newly created items - if($_->{causedby}) { # remove causedby edits - push @todo, $self->DBGetHist(cid => [ $_->{causedby} ], what => 'iid')->[0]; # add original edit - } else { - push @todo, $_; - } - } - - # second, group all items and remove duplicate edits - my %todo; # key=type.iid, value = [objects] - for my $t (@todo) { - my $k = $t->{type}.$t->{iid}; - $todo{$k} = [ $t ] and next - if !$todo{$k}; - push @{$todo{$k}}, $t - if !grep { $_->{id} == $t->{id} } @{$todo{$k}}; - } - - # third, make sure we don't revert edits we don't want to revert - #TODO - - # fourth, get the lowest revision of each item to revert to (ignoring intermetiate edits) - @todo = map { (sort { $a->{id} <=> $b->{id} } @{$todo{$_}})[0] } keys %todo; - - # fifth, actually revert the edits - my @relupd; - for (@todo) { - - if($_->{type} == 0) { # visual novel - my $v = $self->DBGetVN(id => $_->{iid}, rev => $_->{prev}, what => 'extended changes relations')->[0]; - my $old = $self->DBGetVN(id => $_->{iid}, rev => $_->{id}, what => 'relations')->[0]; - my $cid = $self->DBEditVN($_->{iid}, - (map { $_ => $v->{$_} } qw| title desc alias categories comm length l_wp l_cisv l_vnn img_nsfw image|), - relations => [ map { [ $_->{relation}, $_->{id} ] } @{$v->{relations}} ], - comm => sprintf($comm, $v->{cid}, $v->{username}), - ); - my %old = map { $_->{id} => $_->{relation} } @{$old->{relations}}; - my %new = map { $_->{id} => $_->{relation} } @{$v->{relations}}; - push @relupd, $self->VNUpdReverse(\%old, \%new, $_->{iid}, $cid); - } - - if($_->{type} == 1) { # release - my $r = $self->DBGetRelease(id => $_->{iid}, rev => $_->{prev}, what => 'producers platforms media vn changes')->[0]; - $self->DBEditRelease($_->{iid}, - (map { $_ => $r->{$_} } qw| title original language website notes minage type released platforms |), - media => [ map { [ $_->{medium}, $_->{qty} ] } @{$r->{media}} ], - producers => [ map { $_->{id} } @{$r->{producers}} ], - comm => sprintf($comm, $r->{cid}, $r->{username}), - vn => [ map { $_->{vid} } @{$r->{vn}} ], - ); - } - - if($_->{type} == 2) { # producer - my $p = $self->DBGetProducer(id => $_->{iid}, rev => $_->{prev}, what => 'changes')->[0]; - $self->DBEditProducer($_->{iid}, - (map { $_ => $p->{$_} } qw| name original website type lang desc |), - comm => sprintf($comm, $p->{cid}, $p->{username}), - ); - } - } - # update relation graphs - $self->VNRecreateRel(@relupd) if @relupd; - - # sixth, create report of what happened - my @done; - for my $t (@todo, @$l) { - next if $t->{_status}; - $t->{_status} = - (scalar grep { $t->{id} == $_->{id} } @todo) ? 'reverted' : - $t->{causedby} ? 'automated' : - 'skipped'; - push @done, $t; - } - return \@done; -} - - -# ONLY DELETES NEWLY CREATED PAGES (for now...) -sub HistDelete { # \@ids - my ($self, $l) = @_; - - # get objects and add causedby edits - $l = $self->DBGetHist(cid => $l, results => 1000, what => 'iid'); - my @todo = @$l; -# for (@$l) { -# if($_->{causedby}) { # remove causedby edits -# my $n = $self->DBGetHist(cid => [ $_->{causedby} ])->[0]; # add original edit -# push @todo, $n, $self->DBGetHist(causedby => $n->{id} ])->[0]; # add causedby edits -# } else { -# push @todo, $_; -# } -# } - - # remove duplicate edit - # (not necessary now) - - # completely delete newly created items (sort on type to make sure we delete vn's before releases, which is faster) - my @vns; - for my $t (sort { $a->{type} <=> $b->{type} } @todo) { - next if $t->{prev}; - $self->DBDelVN($t->{iid}) if $t->{type} == 0; - $self->DBDelProducer($t->{iid}) if $t->{type} == 2; - if($t->{type} == 1) { # we need to know the vn's to remove a release - my $r = $self->DBGetRelease(id => $t->{iid}, what => 'vn')->[0]; - next if !$r; # we could have deleted this release by deleting the related vn - $self->DBDelRelease([ map { $_->{vid} } @{$r->{vn}} ], $t->{iid}); - } - } - - # delete individual edits - #TODO - - return \@todo; -} - - diff --git a/lib/VNDB/Producers.pm b/lib/VNDB/Producers.pm deleted file mode 100644 index 9756855d..00000000 --- a/lib/VNDB/Producers.pm +++ /dev/null @@ -1,176 +0,0 @@ - -package VNDB::Producers; - -use strict; -use warnings; -use Exporter 'import'; -use Digest::MD5; - -use vars ('$VERSION', '@EXPORT'); -$VERSION = $VNDB::VERSION; -@EXPORT = qw| PPage PBrowse PEdit PLock PHide PXML |; - - -sub PPage { - my $self = shift; - my $id = shift; - my $rev = shift||0; - - return $self->ResNotFound if $self->ReqParam('rev'); - - my $p = $self->DBGetProducer( - id => $id, - $rev ? ( what => 'changes', rev => $rev ) : (), - )->[0]; - return $self->ResNotFound if !$p->{id}; - - my $c = $rev && $rev > 1 && $self->DBGetProducer(id => $id, rev => $rev-1, what => 'changes')->[0]; - $p->{next} = $rev && $p->{latest} > $p->{cid} ? $rev+1 : 0; - - return $self->ResAddTpl(ppage => { - prod => $p, - prev => $c, - change => $rev, - vn => $self->DBGetProducerVN($id), - }); -} - - -sub PBrowse { - my $self = shift; - my $chr = shift; - $chr = 'all' if !defined $chr; - - my $p = $self->FormCheck( - { name => 'p', required => 0, default => 1, template => 'int' }, - { name => 'q', required => 0, default => '' } - ); - return $self->ResNotFound if $p->{_err}; - - my($r, $np) = $self->DBGetProducer( - $chr ne 'all' ? ( - char => $chr ) : (), - $p->{q} ? ( - search => $p->{q} ) : (), - page => $p->{p}, - results => 50, - ); - - $self->ResAddTpl(pbrowse => { - prods => $r, - page => $p->{p}, - npage => $np, - query => $p->{q}, - chr => $chr, - }); -} - - -sub PEdit { - my $self = shift; - my $id = shift || 0; # 0 = new - - my $rev = $self->FormCheck({ name => 'rev', required => 0, default => 0, template => 'int' }); - return $self->ResNotFound if $rev->{_err}; - $rev = $rev->{rev}; - - my $p = $self->DBGetProducer(id => $id, what => 'changes', $rev ? ( rev => $rev ) : ())->[0] if $id; - return $self->ResNotFound() if $id && !$p; - - return $self->ResDenied if !$self->AuthCan('edit') || ($p->{locked} && !$self->AuthCan('lock')); - - - my %b4 = $id ? ( - map { $_ => $p->{$_} } qw|name original website type lang desc| - ) : (); - - my $frm = {}; - if($self->ReqMethod() eq 'POST') { - $frm = $self->FormCheck( - { name => 'type', required => 1, enum => [ keys %$VNDB::PROT ] }, - { name => 'name', required => 1, maxlength => 200 }, - { name => 'original', required => 0, maxlength => 200, default => '' }, - { name => 'lang', required => 1, enum => [ keys %$VNDB::LANG ] }, - { name => 'website', required => 0, maxlength => 200, template => 'url', default => '' }, - { name => 'desc', required => 0, maxlength => 10240, default => '' }, - { name => 'comm', required => 0, default => '' }, - ); - - return $self->ResRedirect('/p'.$id, 'post') - if $id && 6 == scalar grep { $_ ne 'comm' && $b4{$_} eq $frm->{$_} } keys %b4; - - if(!$frm->{_err}) { - my $nrev = 1; - ($nrev) = $self->DBEditProducer($id, %$frm) if $id; # edit - ($id) = $self->DBAddProducer(%$frm) if !$id; # add - - $self->RunCmd('ircnotify p'.$id.'.'.$nrev); - return $self->ResRedirect('/p'.$id.'.'.$nrev, 'post'); - } - } - - if($id) { - $frm->{$_} ||= $b4{$_} for (keys %b4); - $frm->{comm} = sprintf 'Reverted to revision p%d.%d', $p->{id}, $p->{rev} if $p->{cid} != $p->{latest}; - } else { - $frm->{lang} ||= 'ja'; - } - - $self->ResAddTpl(pedit => { - form => $frm, - id => $id, - prod => $p, - }); -} - - -sub PLock { - my $self = shift; - my $id = shift; - - my $p = $self->DBGetProducer(id => $id)->[0]; - return $self->ResNotFound() if !$p; - return $self->ResDenied if !$self->AuthCan('lock'); - $self->DBLockItem('producers', $id, $p->{locked}?0:1); - return $self->ResRedirect('/p'.$id, 'perm'); -} - - -sub PHide { - my $self = shift; - my $id = shift; - - my $p = $self->DBGetProducer(id => $id)->[0]; - return $self->ResNotFound() if !$p; - return $self->ResDenied if !$self->AuthCan('del'); - $self->DBHideProducer($id, $p->{hidden}?0:1); - return $self->ResRedirect('/p'.$id, 'perm'); -} - -sub PXML { - my $self = shift; - - my $q = $self->FormCheck( - { name => 'q', required => 0, maxlength => 100 } - )->{q}; - - my $r = []; - if($q) { - $r = $self->DBGetProducer(results => 10, - $q =~ /^p([0-9]+)$/ ? (id => $1) : (search => $q)); - } - - my $x = $self->ResStartXML; - $x->startTag('producers', results => $#$r+1, query => $q); - for (@$r) { - $x->startTag('item'); - $x->dataElement(id => $_->{id}); - $x->dataElement(name => $_->{name}); - $x->dataElement(original => $_->{original}) if $_->{original}; - $x->dataElement(website => $_->{website}) if $_->{website}; - $x->endTag('item'); - } - $x->endTag('producers'); -} - - diff --git a/lib/VNDB/Releases.pm b/lib/VNDB/Releases.pm deleted file mode 100644 index 0f36c4fe..00000000 --- a/lib/VNDB/Releases.pm +++ /dev/null @@ -1,188 +0,0 @@ - -package VNDB::Releases; - -use strict; -use warnings; -use Exporter 'import'; -use Digest::MD5; - -use vars ('$VERSION', '@EXPORT'); -$VERSION = $VNDB::VERSION; -@EXPORT = qw| RPage REdit RLock RHide RVNCache |; - - -sub RPage { - my $self = shift; - my $id = shift; - my $rev = shift||0; - - return $self->ResNotFound if $self->ReqParam('rev'); - - my $v = $self->DBGetRelease( - id => $id, - what => 'producers platforms media vn'.($rev ? ' changes':''), - $rev ? ( rev => $rev ) : () - )->[0]; - return $self->ResNotFound if !$v->{id}; - - my $c = $rev && $rev > 1 && $self->DBGetRelease(id => $id, rev => $rev-1, what => 'changes producers platforms media vn')->[0]; - $v->{next} = $rev && $v->{latest} > $v->{cid} ? $rev+1 : 0; - - $self->ResRedirect('/v'.$v->{vn}[0]{vid}) - if ($self->ReqHeader('Referer')||'') =~ m{^http://[^/]*(yahoo|google)} && @{$v->{vn}} == 1; - - $v->{rlist} = $self->DBGetRList(rids => [ $id ], uid => $self->AuthInfo->{id})->[0] - if $self->AuthInfo->{id}; - - return $self->ResAddTpl(rpage => { - rel => $v, - prev => $c, - change => $rev, - }); -} - - -sub REdit { - my $self = shift; - my $act = shift||'v'; - my $id = shift || 0; - - my $rid = $act eq 'r' ? $id : 0; - - my $rev = $self->FormCheck({ name => 'rev', required => 0, default => 0, template => 'int' }); - return $self->ResNotFound if $rev->{_err}; - $rev = $rev->{rev}; - - my $r = $self->DBGetRelease(id => $rid, what => 'changes producers platforms media vn', $rev ? ( rev => $rev ) : ())->[0] if $rid; - my $ivn = $self->DBGetVN(id => $id)->[0] if !$rid; - return $self->ResNotFound() if ($rid && !$r) || (!$rid && !$ivn); - - my $vn = $rid ? $r->{vn} : [ { vid => $id, title => $ivn->{title} } ]; - - return $self->ResDenied if !$self->AuthCan('edit') || ($r->{locked} && !$self->AuthCan('lock')); - - my %b4 = $rid ? ( - (map { $_ => $r->{$_} } qw|title original gtin language website notes minage type platforms|), - released => $r->{released} =~ /^([0-9]{4})([0-9]{2})([0-9]{2})$/ ? [ $1, $2, $3 ] : [ 0, 0, 0 ], - media => join(',', map { $_->{medium} =~ /^(cd|dvd|gdr|blr)$/ ? ($_->{medium}.'_'.$_->{qty}) : $_->{medium} } @{$r->{media}}), - producers => join('|||', map { $_->{id}.','.$_->{name} } @{$r->{producers}}), - ) : (); - $b4{vn} = join('|||', map { $_->{vid}.','.$_->{title} } @$vn); - - my $frm = {}; - if($self->ReqMethod() eq 'POST') { - $frm = $self->FormCheck( - { name => 'type', required => 1, enum => [ 0..$#{$VNDB::RTYP} ] }, - { name => 'title', required => 1, maxlength => 250 }, - { name => 'original', required => 0, maxlength => 250, default => '' }, - { name => 'gtin', required => 0, template => 'gtin', default => '0' }, - { name => 'language', required => 1, enum => [ keys %{$VNDB::LANG} ] }, - { name => 'website', required => 0, template => 'url', default => '' }, - { name => 'released', required => 0, multi => 1, template => 'int', default => 0 }, - { name => 'minage' , required => 0, enum => [ keys %{$VNDB::VRAGES} ], default => -1 }, - { name => 'notes', required => 0, maxlength => 10240, default => '' }, - { name => 'platforms', required => 0, multi => 1, enum => [ keys %$VNDB::PLAT ], default => '' }, - { name => 'media', required => 0, default => '' }, - { name => 'producers', required => 0, default => '' }, - { name => 'vn', required => 1, maxlength => 10240 }, - { name => 'comm', required => 0, default => '' }, - ); - - my $released = !$frm->{released}[0] ? 0 : - $frm->{released}[0] == 9999 ? 99999999 : - sprintf '%04d%02d%02d', $frm->{released}[0], $frm->{released}[1]||99, $frm->{released}[2]||99; - my $media = [ map { /_/ ? [ split /_/ ] : [ $_, 0 ] } split /,/, $frm->{media} ]; - my $producers = [ map { /^([0-9]+)/ ? $1 : () } split /\|\|\|/, $frm->{producers} ]; - my $new_vn = [ map { /^([0-9]+)/ ? $1 : () } split /\|\|\|/, $frm->{vn} ]; - - $frm->{_err} = $frm->{_err} ? [ @{$frm->{_err}}, 'vn_1' ] : [ 'vn_1' ] - if !@$new_vn; - - # weed out empty string - $frm->{platforms} = [ map { $_ ? $_ : () } @{$frm->{platforms}} ]; - - return $self->ResRedirect('/r'.$rid, 'post') - if $rid && $released == $r->{released} && - (join(',', sort @{$b4{platforms}}) eq join(',', sort @{$frm->{platforms}})) && - 11 == scalar grep { $_ ne 'comm' && $_ ne 'released' && $_ ne 'platforms' && $frm->{$_} eq $b4{$_} } keys %b4; - - if(!$frm->{_err}) { - my %opts = ( - vn => $new_vn, - (map { $_ => $frm->{$_} } qw|title original gtin language website notes minage type comm platforms|), - released => $released, - media => $media, - producers => $producers, - ); - my $nrev = 1; - ($nrev) = $self->DBEditRelease($rid, %opts) if $rid; # edit - ($rid) = $self->DBAddRelease(%opts) if !$rid; # add - - $self->RVNCache(@$new_vn, (map { $_->{vid} } @$vn)); - - $self->RunCmd('ircnotify r'.$rid.'.'.$nrev); - return $self->ResRedirect('/r'.$rid.'.'.$nrev, 'post'); - } - } - - if($rid) { - $frm->{$_} ||= $b4{$_} for (keys %b4); - $frm->{comm} = sprintf 'Reverted to revision r%d.%d', $r->{id}, $r->{rev} if $r->{cid} != $r->{latest}; - } else { - $frm->{language} = 'ja'; - $frm->{vn} = $b4{vn}; - } - - $self->AddHid($frm); - $frm->{_hid} = {map{$_=>1} qw| info pnm prod com |} - if !$frm->{_hid} && !$rid; - $self->ResAddTpl(redit => { - form => $frm, - id => $rid, - rel => $r, - vn => !$rid ? $ivn : $vn, - }); -} - - -sub RLock { - my $self = shift; - my $id = shift; - - my $r = $self->DBGetRelease(id => $id)->[0]; - return $self->ResNotFound() if !$r; - return $self->ResDenied if !$self->AuthCan('lock'); - $self->DBLockItem('releases', $id, $r->{locked}?0:1); - return $self->ResRedirect('/r'.$id, 'perm'); -} - - -sub RHide { - my $self = shift; - my $id = shift; - - return $self->ResDenied if !$self->AuthCan('del'); - my $r = $self->DBGetRelease(id => $id, what => 'vn')->[0]; - return $self->ResNotFound if !$r; - $self->DBHideRelease($id, $r->{hidden}?0:1); - $self->RVNCache(map { $_->{vid} } @{$r->{vn}}); - return $self->ResRedirect('/r'.$id, 'perm'); -} - - -sub RVNCache { # @vids - calls update_vncache and regenerates relation graphs if needed - my($self, @vns) = @_; - my $before = $self->DBGetVN(id => \@vns, order => 'v.id', what => 'relations'); - $self->DBVNCache(@vns); - my $after = $self->DBGetVN(id => \@vns, order => 'v.id'); - my @upd = map { - @{$before->[$_]{relations}} && ( - $before->[$_]{c_released} != $after->[$_]{c_released} - || $before->[$_]{c_languages} ne $after->[$_]{c_languages} - ) ? $before->[$_]{id} : (); - } 0..$#$before; - $self->RunCmd('relgraph '.join(' ', @upd)) if @upd; -} - -1; - diff --git a/lib/VNDB/Users.pm b/lib/VNDB/Users.pm deleted file mode 100644 index e2021627..00000000 --- a/lib/VNDB/Users.pm +++ /dev/null @@ -1,238 +0,0 @@ - -package VNDB::Users; - -use strict; -use warnings; -use Exporter 'import'; -use Digest::MD5 'md5_hex'; - -our $VERSION = $VNDB::VERSION; -our @EXPORT = qw| UsrLogin UsrLogout UsrReg UsrPass UsrEdit UsrList UsrPage UsrDel |; - - -sub UsrLogin { - my $self = shift; - - (return $self->ResRedirect('/', 'temp')) if $self->AuthInfo()->{id}; - - my $frm = {}; - if($self->ReqMethod() eq 'POST') { - $frm = $self->FormCheck( - { name => 'username', required => 1, minlength => 2, maxlength => 15, template => 'pname' }, - { name => 'userpass', required => 1, minlength => 4, maxlength => 15, template => 'asciiprint' }, - ); - if(!$frm->{_err}) { - (my $ref = $self->ReqHeader('Referer')||'/') =~ s/^$self->{root_url}//; - my $r = $self->AuthLogin($frm->{username}, $frm->{userpass}, 1, $ref); - $r == 1 ? (return) : ($frm->{_err} = [ 'loginerr' ]); - } - } - - $self->ResAddTpl(userlogin => { - log => $frm, - } ); -} - - -sub UsrLogout { - shift->AuthLogout(); -} - - -sub UsrReg { - my $self = shift; - - (return $self->ResRedirect('/', 'temp')) if $self->AuthInfo()->{id}; - - my $frm = {}; - if($self->ReqMethod() eq 'POST') { - $frm = $self->FormCheck( - { name => 'username', required => 1, minlength => 2, maxlength => 15, template => 'pname' }, - { name => 'mail', required => 1, template => 'mail' }, - { name => 'pass1', required => 1, minlength => 4, maxlength => 15, template => 'asciiprint' }, - { name => 'pass2', required => 1, minlength => 4, maxlength => 15, template => 'asciiprint' }, - ); - $frm->{_err} = $frm->{_err} ? [ @{$frm->{_err}}, 'badpass' ] : [ 'badpass' ] - if $frm->{pass1} ne $frm->{pass2}; - $frm->{_err} = $frm->{_err} ? [ @{$frm->{_err}}, 'usrexists' ] : [ 'usrexists' ] - if $frm->{username} eq 'anonymous' || $self->DBGetUser(username => $frm->{username})->[0]; - $frm->{_err} = $frm->{_err} ? [ @{$frm->{_err}}, 'mailexists' ] : [ 'mailexists' ] - if $frm->{mail} && $self->DBGetUser(mail => $frm->{mail})->[0]; - - if(!$frm->{_err}) { - $self->DBAddUser($frm->{username}, md5_hex($frm->{pass1}), $frm->{mail}, 2); - return $self->AuthLogin($frm->{username}, $frm->{pass1}, 1, '/'); - } - } - $self->ResAddTpl(userreg => { - reg => $frm, - }); -} - - -sub UsrPass { - my $self = shift; - - (return $self->ResRedirect('/', 'temp')) if $self->AuthInfo()->{id}; - - my $d = $self->ReqParam('d'); - - my $frm = {}; - if(!$d && $self->ReqMethod() eq 'POST') { - $frm = $self->FormCheck({ name => 'mail', required => 1, template => 'mail' }); - my $unfo; - if(!$frm->{_err}) { - $frm->{mail} =~ s/%//g; - $unfo = $self->DBGetUser(mail => $frm->{mail})->[0]; - $frm->{_err} = $frm->{_err} ? [ @{$frm->{_err}}, 'nomail' ] : [ 'nomail' ] - if !$unfo; - } - if(!$frm->{_err}) { - my @chars = ( 'A'..'Z', 'a'..'z', 0..9 ); - my $pass = join('', map $chars[int rand $#chars+1], 0..8); - $self->DBUpdateUser($unfo->{id}, passwd => md5_hex($pass)); - $self->SendMail(sprintf(<<__, $unfo->{username}, $unfo->{username}, $pass), -Hello %s, - -Your password has been reset, you can now login at http://vndb.org/ with the -following information: - -Username: %s -Password: %s - -Now don't forget your password again! :-) - -vndb.org -__ - To => $frm->{mail}, - Subject => sprintf('Password request for %s', $unfo->{username}), - ); - return $self->ResRedirect('/u/newpass?d=1', 'post'); - } - } - - $self->ResAddTpl(userpass => { - pas => $frm, - done => $d, - }); -} - - -sub UsrEdit { - my $self = shift; - my $user = shift; - - my $u = $self->AuthInfo(); - return $self->ResDenied if !$u->{id}; - my $adm = $u->{id} != $user; - return $self->ResDenied if $adm && !$self->AuthCan('usermod'); - $u = $self->DBGetUser(uid => $user)->[0] if $adm; - return $self->ResNotFound if !$u->{id}; - - my $d = $self->ReqParam('d'); - - my $frm = {}; - if(!$d && $self->ReqMethod() eq 'POST') { - $frm = $self->FormCheck( - { name => 'mail', required => 1, template => 'mail' }, - { name => 'pass1', required => 0, template => 'asciiprint' }, - { name => 'pass2', required => 0, template => 'asciiprint' }, - $adm ? ( - { name => 'username',required => 1, template => 'pname', minlength => 2, maxlength => 15 }, - { name => 'rank', required => 1, enum => [ '1'..($#{$self->{ranks}}-1) ] }, - ) : (), - { name => 'plist', required => 0 }, - { name => 'pign_nsfw', required => 0 }, - ); - if(($frm->{pass1} || $frm->{pass2}) && $frm->{pass1} ne $frm->{pass2}) { - $frm->{_err} = [] if !$frm->{_err}; - push(@{$frm->{_err}}, 'badpass'); - } - if(!$frm->{_err}) { - my $pass = $frm->{pass1} ? md5_hex($frm->{pass1}) : ''; - my %opts = ( - username => $frm->{username}||undef, - rank => $frm->{rank}||undef, - mail => $frm->{mail}, - ); - $opts{passwd} = $pass if $pass; - $opts{flags} = $frm->{plist} ? $VNDB::UFLAGS->{list} : 0; - $opts{flags} += $VNDB::UFLAGS->{nsfw} if $frm->{pign_nsfw}; - $self->DBUpdateUser($u->{id}, %opts); - return $adm ? $self->ResRedirect('/u'.$user.'/edit?d=1', 'post') : - $pass ? $self->AuthLogin($u->{username}, $frm->{pass1}, 1, '/u'.$user.'/edit?d=1') : - $self->ResRedirect('/u'.$user.'/edit?d=1', 'post'); - } - } - - $frm->{$_} ||= $u->{$_} - for (qw| username mail rank |); - $frm->{plist} ||= $u->{flags} & $VNDB::UFLAGS->{list}; - $frm->{pign_nsfw} ||= $u->{flags} & $VNDB::UFLAGS->{nsfw}; - $self->ResAddTpl(useredit => { - form => $frm, - done => $d, - adm => $adm, - user => $user, - u => $u - }); -} - - -sub UsrList { - my $self = shift; - my $chr = shift; - $chr = 'all' if !defined $chr; - - my $f = $self->FormCheck( - { name => 's', required => 0, default => 'username', enum => [ qw|username mail rank registered| ] }, - { name => 'o', required => 0, default => 'a', enum => [ 'a','d' ] }, - { name => 'p', required => 0, default => 1, template => 'int' }, - ); - return $self->ResNotFound if $f->{_err}; - - my($unfo, $np) = $self->DBGetUser( - order => $f->{s}.($f->{o} eq 'a' ? ' ASC' : ' DESC'), - $chr ne 'all' ? ( - firstchar => $chr ) : (), - results => 50, - page => $f->{p}, - what => 'list', - ); - - $self->ResAddTpl(userlist => { - users => $unfo, - chr => $chr, - page => $f->{p}, - npage => $np, - order => [ $f->{s}, $f->{o} ], - } ); -} - - -sub UsrPage { - my($self, $id) = @_; - - my $u = $self->DBGetUser(uid => $id, what => 'list')->[0]; - return $self->ResNotFound if !$u; - - $self->ResAddTpl(userpage => { - user => $u, - votes => { - latest => scalar $self->DBGetVotes(uid => $id, results => 10), - graph => $self->DBVoteStats(uid => $id), - }, - }); -} - - -sub UsrDel { - my($s, $id) = @_; - return $s->ResDenied if !$s->AuthCan('usermod'); - $s->DBDelUser($id); - $s->ResRedirect('/u/list', 'temp'); -} - - -1; - diff --git a/lib/VNDB/Util/Auth.pm b/lib/VNDB/Util/Auth.pm deleted file mode 100644 index 6f265253..00000000 --- a/lib/VNDB/Util/Auth.pm +++ /dev/null @@ -1,133 +0,0 @@ - - - - - -# N E E D S M O A R S A L T ! - - -package VNDB::Util::Auth; - -use strict; -use warnings; -use Exporter 'import'; -use Digest::MD5 'md5_hex'; -use Crypt::Lite; # simple, small and easy encryption for cookies - -use vars ('$VERSION', '@EXPORT'); -$VERSION = $VNDB::VERSION; -@EXPORT = qw| AuthCheckCookie AuthLogin AuthLogout AuthInfo AuthCan AuthAddTpl |; - - -{ # local data for these 2 methods only - my $crl = Crypt::Lite->new(debug => 0); - my $scrt = md5_hex($VNDB::COOKEY); - -sub AuthCheckCookie { - my $self = shift; - my $info = $self->{_Req} || $self; - $info->{_auth} = {} if !exists $info->{_auth}; - - my $cookie = $self->ReqCookie('vndb_auth'); - return 0 if !$cookie; - my $str = $crl->decrypt($cookie, $scrt); - return 0 if length($str) < 36; - my $pass = substr($str, 4, 32); - my $user = substr($str, 36); - return _AuthCheck($self, $user, $pass); -} - -sub AuthLogin { - my $self = shift; - my $user = lc(scalar shift); - my $psbk = shift; - my $pass = md5_hex($psbk); - my $keep = shift; - my $to = shift; - my $status = _AuthCheck($self, $user, $pass); - if($status == 1) { - (my $cookie = $crl->encrypt("VNDB$pass$user", $scrt)) =~ s/\r?\n//g; - $self->ResRedirect($to, "post"); - $self->ResAddHeader('Set-Cookie', "vndb_auth=$cookie; " . ($keep ? 'expires=Sat, 01-Jan-2030 00:00:00 GMT; ' : ' ') . "path=/; domain=$self->{CookieDomain}"); - return 1; - } - return $status; -} -} # end of local data - -sub AuthLogout { - my $self = shift; - $self->ResRedirect('/', 'temp'); - $self->ResAddHeader('Set-Cookie', "vndb_auth= ; expires=Sat, 01-Jan-2000 00:00:00 GMT; path=/; domain=$self->{CookieDomain}"); -} - -sub AuthInfo { - my $self = shift; - my $info = $self->{_Req} || shift; - return $info->{_auth} || {}; -} - -sub AuthCan { - my $self = shift; - my $act = shift; - my $info = $self->{_Req} || shift; - return $self->{ranks}[($info->{_auth}{rank}||0)+1]{$act}; -} - -sub _AuthCheck { - my $self = shift; - my $user = shift; - my $pass = shift; - my $info = $self->{_Req} || shift; - - $info->{_auth} = undef; - - return 2 if !$user || length($user) > 15 || length($user) < 2; - return 3 if !$pass || length($pass) != 32; - - my $d = $self->DBGetUser(username => $user, passwd => $pass)->[0]; - return 4 if !defined $d->{id}; - return 5 if !$d->{rank}; - - $d->{oldvnlist} = $self->DBGetVNList(uid => $d->{id}, results => 1)->[0] ? 1 : 0; - $info->{_auth} = $d; - - return 1; -} - - -# adds the keys AuthLoggedin, AuthRank, AuthUsername, AuthMail, AuthId -sub AuthAddTpl { - my $self = shift; - my $info = $self->{_Req} || shift; - my %tpl; - - if($info->{_auth}{id}) { - %tpl = ( - AuthLoggedin => 1, - AuthRank => $info->{_auth}{rank}, - AuthRankname => $self->{ranks}[0][0][$info->{_auth}{rank}], - AuthUsername => $info->{_auth}{username}, - AuthMail => $info->{_auth}{mail}, - AuthId => $info->{_auth}{id}, - AuthNsfw => $info->{_auth}{flags} & $VNDB::UFLAGS->{nsfw}, - AuthOldList => $info->{_auth}{oldvnlist}, - ); - } else { - %tpl = ( - AuthLoggedin => 0, - AuthRank => '', - AuthRankname => '', - AuthUsername => '', - AuthMail => '', - AuthId => 0, - AuthNsfw => 0, - ); - } - $tpl{'Auth'.$_} = $self->{ranks}[($info->{_auth}{rank}||0)+1]{$_} - for (keys %{$self->{ranks}[0][1]}); - $self->ResAddTpl(%tpl); -} - -1; - diff --git a/lib/VNDB/Util/DB.pm b/lib/VNDB/Util/DB.pm deleted file mode 100644 index dac01a52..00000000 --- a/lib/VNDB/Util/DB.pm +++ /dev/null @@ -1,1582 +0,0 @@ - -package VNDB::Util::DB; - -use strict; -use warnings; -use DBI; -use Exporter 'import'; - -use vars ('$VERSION', '@EXPORT'); -$VERSION = $VNDB::VERSION; - -@EXPORT = qw| - DBInit DBCheck DBCommit DBRollBack DBExit - DBLanguageCount DBCategoryCount DBTableCount DBGetHist DBLockItem DBIncId DBAddScreenshot DBGetScreenshot - DBGetUser DBAddUser DBUpdateUser DBDelUser - DBGetVotes DBVoteStats DBAddVote DBDelVote - DBGetVNList DBDelVNList - DBGetWishList DBEditWishList DBDelWishList - DBGetRList DBGetRLists DBEditRList DBDelRList - DBGetVN DBAddVN DBEditVN DBHideVN DBVNCache - DBGetRelease DBAddRelease DBEditRelease DBHideRelease - DBGetProducer DBGetProducerVN DBAddProducer DBEditProducer DBHideProducer - DBGetThreads DBGetPosts DBAddPost DBEditPost DBEditThread DBAddThread - DBExec DBRow DBAll -|; - - - - - -#-----------------------------------------------------------------------------# -# I M P O R T A N T S T U F F # -#-----------------------------------------------------------------------------# - - -sub new { - my $me = shift; - - my $type = ref($me) || $me; - $me = bless { o => \@_ }, $type; - - $me->DBInit(); - - return $me; -} - - -sub DBInit { - my $self = shift; - my $info = $self->{_DB} || $self; - - $info->{sql} = DBI->connect(@{$self->{o}}, { - PrintError => 0, RaiseError => 1, - AutoCommit => 0, pg_enable_utf8 => 1, - } - ); -} - - -sub DBCheck { - my $self = shift; - my $info = $self->{_DB} || $self; - - require Time::HiRes - if $self->{debug} && !$Time::Hires::VERSION; - $info->{Queries} = [] if $self->{debug}; - my $start = [Time::HiRes::gettimeofday()] if $self->{debug}; - - if(!$info->{sql}->ping) { - warn "Ping failed, reconnecting"; - $self->DBInit; - } - $info->{sql}->rollback(); - push(@{$info->{Queries}}, - [ 'ping/rollback', Time::HiRes::tv_interval($start) ]) - if $self->{debug}; -} - - -sub DBCommit { - my $self = shift; - my $info = $self->{_DB} || $self; - my $start = [Time::HiRes::gettimeofday()] if $self->{debug}; - $info->{sql}->commit(); - push(@{$info->{Queries}}, - [ 'commit', Time::HiRes::tv_interval($start) ]) - if $self->{debug}; -} - - -sub DBRollBack { - my $self = shift; - my $info = $self->{_DB} || $self; - $info->{sql}->rollback(); -} - - -sub DBExit { - my $self = shift; - my $info = $self->{_DB} || $self; - $info->{sql}->disconnect(); -} - - -# XXX: this function should be disabled when performance is going to be a problem -sub DBCategoryCount { - return { - (map { map { $_, 0 } keys %{$VNDB::CAT->{$_}[1]} } keys %{$VNDB::CAT}), - map { $_->{cat}, $_->{cnt} } @{shift->DBAll(q| - SELECT cat, COUNT(vid) AS cnt - FROM vn_categories vc - JOIN vn v ON v.latest = vc.vid - WHERE v.hidden = FALSE - GROUP BY cat - ORDER BY cnt| - )} - }; -} - - -# XXX: Above comment also applies to this function -sub DBLanguageCount { - return { (map { $_ => 0 } keys %$VNDB::LANG ), - map { $_->{language} => $_->{count} } @{shift->DBAll(q| - SELECT rr.language, COUNT(DISTINCT v.id) AS count - FROM releases_rev rr - JOIN releases r ON r.latest = rr.id - JOIN releases_vn rv ON rv.rid = rr.id - JOIN vn v ON v.id = rv.vid - WHERE r.hidden = FALSE - AND v.hidden = FALSE - AND rr.type <> 2 - AND rr.released <= TO_CHAR('today'::timestamp, 'YYYYMMDD')::integer - GROUP BY rr.language|)} }; -} - - -sub DBTableCount { # table (users, producers, vn, releases, votes) - return $_[0]->DBRow(q| - SELECT COUNT(*) as cnt - FROM !s - !W|, - $_[1], - $_[1] =~ /producers|vn|releases/ ? { 'hidden = ?' => 0 } : {}, - )->{cnt} - ($_[1] eq 'users' ? 1 : 0); -} - - - -# XXX: iid, ititle and hidden columns should be cached if performance will be a problem -sub DBGetHist { # %options->{ type, id, cid, caused, next, page, results, ip, edits, showhid, what } (Item hist) - my($s, %o) = @_; - - $o{results} ||= $o{next} ? 1 : 50; - $o{page} ||= 1; - $o{type} ||= ''; - $o{what} ||= ''; #flags: user iid ititle - $o{showhid} ||= $o{type} && $o{type} ne 'u' && $o{id} || $o{cid} ? 1 : 0; - - my %where = ( - $o{cid} ? ( - 'c.id IN(!l)' => [$o{cid}] ) : (), - $o{type} eq 'u' ? ( - 'c.requester = ?' => $o{id} ) : (), - - $o{type} eq 'v' && !$o{releases} ? ( 'c.type = ?' => 0, - $o{id} ? ( 'vr.vid = ?' => $o{id} ) : () ) : (), - $o{type} eq 'v' && $o{releases} ? ( - '((c.type = ? AND vr.vid = ?) OR (c.type = ? AND rv.vid = ?))' => [0,$o{id},1,$o{id}] ) : (), - - $o{type} eq 'r' ? ( 'c.type = ?' => 1, - $o{id} ? ( 'rr.rid = ?' => $o{id} ) : () ) : (), - $o{type} eq 'p' ? ( 'c.type = ?' => 2, - $o{id} ? ( 'pr.pid = ?' => $o{id} ) : () ) : (), - - $o{caused} ? ( - 'c.causedby = ?' => $o{caused} ) : (), - $o{ip} ? ( - 'c.ip = ?' => $o{ip} ) : (), - defined $o{edits} && !$o{edits} ? ( - 'c.rev = ?' => 1 ) : (), - $o{edits} ? ( - 'c.rev > ?' => 1 ) : (), - - # get rid of 'hidden' items - !$o{showhid} ? ( - '(v.hidden IS NOT NULL AND v.hidden = FALSE OR r.hidden IS NOT NULL AND r.hidden = FALSE OR p.hidden IS NOT NULL AND p.hidden = FALSE)' => 1, - ) : $o{showhid} == 2 ? ( - '(v.hidden IS NOT NULL AND v.hidden = TRUE OR r.hidden IS NOT NULL AND r.hidden = TRUE OR p.hidden IS NOT NULL AND p.hidden = TRUE)' => 1, - ) : (), - ); - - my $select = 'c.id, c.type, c.added, c.requester, c.comments, c.rev, c.causedby'; - $select .= ', u.username' if $o{what} =~ /user/; - $select .= ', COALESCE(vr.vid, rr.rid, pr.pid) AS iid' if $o{what} =~ /iid/; - $select .= ', COALESCE(vr2.title, rr2.title, pr2.name) AS ititle, COALESCE(vr2.original, rr2.original, pr2.original) AS ioriginal' if $o{what} =~ /ititle/; - - my $join = ''; - $join .= ' JOIN users u ON u.id = c.requester' if $o{what} =~ /user/; - $join .= ' LEFT JOIN vn_rev vr ON c.type = 0 AND c.id = vr.id'. - ' LEFT JOIN releases_rev rr ON c.type = 1 AND c.id = rr.id'. - ' LEFT JOIN producers_rev pr ON c.type = 2 AND c.id = pr.id' if $o{what} =~ /(iid|ititle)/ || $o{releases} || $o{id} || !$o{showhid}; - # these joins should be optimised away at some point (cache the required columns in changes as mentioned above) - $join .= ' LEFT JOIN vn v ON v.id = vr.vid'. - ' LEFT JOIN vn_rev vr2 ON vr2.id = v.latest'. - ' LEFT JOIN releases r ON r.id = rr.rid'. - ' LEFT JOIN releases_rev rr2 ON rr2.id = r.latest'. - ' LEFT JOIN producers p ON p.id = pr.pid'. - ' LEFT JOIN producers_rev pr2 ON pr2.id = p.latest' if $o{what} =~ /ititle/ || $o{releases} || !$o{showhid}; - $join .= ' LEFT JOIN releases_vn rv ON c.id = rv.rid' if $o{type} eq 'v' && $o{releases}; - - my $r = $s->DBAll(qq| - SELECT $select - FROM changes c - $join - !W - ORDER BY c.id !s - LIMIT ? OFFSET ?|, - \%where, - $o{next} ? 'ASC' : 'DESC', - $o{results}+(wantarray?1:0), $o{results}*($o{page}-1) - ); - return $r if !wantarray; - return ($r, 0) if $#$r != $o{results}; - pop @$r; - return ($r, 1); -} - - -sub DBLockItem { # table, id, locked - my($s, $tbl, $id, $l) = @_; - $s->DBExec(q| - UPDATE !s - SET locked = ? - WHERE id = ?|, - $tbl, $l?1:0, $id); -} - - -sub DBIncId { # sequence (this is a rather low-level function... aww heck...) - return $_[0]->DBRow(q|SELECT nextval(?) AS ni|, $_[1])->{ni}; -} - - -sub DBAddScreenshot { # just returns an ID - return $_[0]->DBRow(q|INSERT INTO screenshots (status) VALUES(0) RETURNING id|)->{id}; -} - - -sub DBGetScreenshot { # ids - return $_[0]->DBAll(q|SELECT * FROM screenshots WHERE id IN(!l)|, $_[1]); -} - - - -#-----------------------------------------------------------------------------# -# A U T H / U S E R S T U F F # -#-----------------------------------------------------------------------------# - - -sub DBGetUser { # %options->{ username mail passwd order firstchar uid results page what } - my $s = shift; - my %o = ( - order => 'username ASC', - page => 1, - results => 10, - what => '', - @_ - ); - - my %where = ( - 'id > 0' => 1, - $o{username} ? ( - 'username = ?' => $o{username} ) : (), - $o{mail} ? ( - 'mail = ?' => $o{mail} ) : (), - $o{passwd} ? ( - 'passwd = decode(?, \'hex\')' => $o{passwd} ) : (), - $o{firstchar} ? ( - 'SUBSTRING(username from 1 for 1) = ?' => $o{firstchar} ) : (), - !$o{firstchar} && defined $o{firstchar} ? ( - 'ASCII(username) < 97 OR ASCII(username) > 122' => 1 ) : (), - $o{uid} ? ( - 'id = ?' => $o{uid} ) : (), - !$o{uid} && !$o{username} ? ( - 'id > 0' => 1 ) : (), - ); - - my $r = $s->DBAll(q| - SELECT * - FROM users u - !W - ORDER BY !s - LIMIT ? OFFSET ?|, - \%where, - $o{order}, - $o{results}+(wantarray?1:0), $o{results}*($o{page}-1) - ); - - # XXX: easy to cache, good performance win - if($o{what} =~ /list/ && $#$r >= 0) { - my %r = map { - $r->[$_]{votes} = 0; - $r->[$_]{changes} = 0; - ($r->[$_]{id}, $_) - } 0..$#$r; - - $r->[$r{$_->{uid}}]{votes} = $_->{cnt} for (@{$s->DBAll(q| - SELECT uid, COUNT(vid) AS cnt - FROM votes - WHERE uid IN(!l) - GROUP BY uid|, - [ keys %r ] - )}); - - $r->[$r{$_->{requester}}]{changes} = $_->{cnt} for (@{$s->DBAll(q| - SELECT requester, COUNT(id) AS cnt - FROM changes - WHERE requester IN(!l) - GROUP BY requester|, - [ keys %r ] - )}); - } - - return $r if !wantarray; - return ($r, 0) if $#$r != $o{results}; - pop @$r; - return ($r, 1); -} - - -sub DBAddUser { # username, passwd, mail, rank - return $_[0]->DBExec(q| - INSERT INTO users - (username, passwd, mail, rank, registered) - VALUES (?, decode(?, 'hex'), ?, ?, ?)|, - lc($_[1]), $_[2], $_[3], $_[4], time - ); -} - - -sub DBUpdateUser { # uid, %options->{ columns in users table } - my $s = shift; - my $user = shift; - my %opt = @_; - my %h; - - defined $opt{$_} && ($h{$_.' = ?'} = $opt{$_}) - for (qw| username mail rank flags |); - $h{'passwd = decode(?, \'hex\')'} = $opt{passwd} - if defined $opt{passwd}; - - return 0 if scalar keys %h <= 0; - return $s->DBExec(q| - UPDATE users - !H - WHERE id = ?|, - \%h, $user); -} - - -sub DBDelUser { # uid - my($s, $id) = @_; - $s->DBExec($_, $id) for ( - q|DELETE FROM vnlists WHERE uid = ?|, - q|DELETE FROM rlists WHERE uid = ?|, - q|DELETE FROM wlists WHERE uid = ?|, - q|DELETE FROM votes WHERE uid = ?|, - q|UPDATE changes SET requester = 0 WHERE requester = ?|, - q|UPDATE threads_posts SET uid = 0 WHERE uid = ?|, - q|DELETE FROM users WHERE id = ?| - ); -} - - - - - - -#-----------------------------------------------------------------------------# -# V O T E S # -#-----------------------------------------------------------------------------# - - -sub DBGetVotes { # %options->{ uid vid hide order results page } - my($s, %o) = @_; - $o{order} ||= 'n.date DESC'; - $o{results} ||= 50; - $o{page} ||= 1; - - my %where = ( - $o{uid} ? ( 'n.uid = ?' => $o{uid} ) : (), - $o{vid} ? ( 'n.vid = ?' => $o{vid} ) : (), - $o{hide} ? ( 'u.flags & ? = ?' => [ $VNDB::UFLAGS->{list}, $VNDB::UFLAGS->{list} ] ) : (), - ); - - my $r = $s->DBAll(q| - SELECT n.vid, vr.title, vr.original, n.vote, n.date, n.uid, u.username - FROM votes n - JOIN vn v ON v.id = n.vid - JOIN vn_rev vr ON vr.id = v.latest - JOIN users u ON u.id = n.uid - !W - ORDER BY !s - LIMIT ? OFFSET ?|, - \%where, - $o{order}, - $o{results}+(wantarray?1:0), $o{results}*($o{page}-1) - ); - return $r if !wantarray; - return ($r, 0) if $#$r < $o{results}; - pop @$r; - return ($r, 1); -} - - -sub DBVoteStats { # uid|vid => id - my($s, $col, $id) = @_; - my $r = [ qw| 0 0 0 0 0 0 0 0 0 0 | ]; - $r->[$_->{vote}-1] = $_->{votes} for (@{$s->DBAll(q| - SELECT vote, COUNT(vote) as votes - FROM votes - !W - GROUP BY vote|, - $col ? { '!s = ?' => [ $col, $id ] } : {}, - )}); - return $r; -} - - -sub DBAddVote { # vid, uid, vote - $_[0]->DBExec(q| - UPDATE votes - SET vote = ? - WHERE vid = ? - AND uid = ?|, - $_[3], $_[1], $_[2] - ) || $_[0]->DBExec(q| - INSERT INTO votes - (vid, uid, vote, date) - VALUES (!l)|, - [ @_[1..3], time ] - ); -} - - -sub DBDelVote { # uid, vid # uid = 0 to delete all - $_[0]->DBExec(q| - DELETE FROM votes - !W|, - { 'vid = ?' => $_[2], - $_[1] ? ('uid = ?' => $_[1]) : () - } - ); -} - - - - - -#-----------------------------------------------------------------------------# -# U S E R V I S U A L N O V E L L I S T S # -#-----------------------------------------------------------------------------# - - -sub DBGetVNList { # %options->{ uid vid hide order results page status } - my($s, %o) = @_; - $o{results} ||= 10; - $o{page} ||= 1; - $o{order} ||= 'l.date DESC'; - - my %where = ( - $o{uid} ? ( - 'l.uid = ?' => $o{uid} ) : (), - $o{vid} ? ( - 'l.vid = ?' => $o{vid} ) : (), - defined $o{status} ? ( - 'l.status = ?' => $o{status} ) : (), - $o{hide} ? ( 'u.flags & ? = ?' => [ $VNDB::UFLAGS->{list}, $VNDB::UFLAGS->{list} ] ) : (), - ); - - return wantarray ? ([], 0) : [] if !keys %where; - - my $r = $s->DBAll(q| - SELECT l.vid, vr.title, l.status, l.comments, l.date, l.uid, u.username - FROM vnlists l - JOIN vn v ON l.vid = v.id - JOIN vn_rev vr ON vr.id = v.latest - JOIN users u ON l.uid = u.id - !W - ORDER BY !s - LIMIT ? OFFSET ?|, - \%where, - $o{order}, - $o{results}+(wantarray?1:0), $o{results}*($o{page}-1) - ); - return $r if !wantarray; - return ($r, 0) if $#$r < $o{results}; - pop @$r; - return ($r, 1); -} - - -sub DBDelVNList { # uid, @vid # uid = 0 to delete all - my($s, $uid, @vid) = @_; - $s->DBExec(q| - DELETE FROM vnlists - !W|, - { 'vid IN (!l)' => [\@vid], - $uid ? ('uid = ?' => $uid) : () - } - ); -} - - - - - -#-----------------------------------------------------------------------------# -# U S E R W I S H L I S T S # -#-----------------------------------------------------------------------------# - - -sub DBGetWishList { # %options->{ uid vid what order page results } - my($s, %o) = @_; - - $o{order} ||= 'wl.wstat ASC'; - $o{page} ||= 1; - $o{results} ||= 50; - $o{what} ||= ''; - - my %where = ( - 'wl.uid = ?' => $o{uid}, - $o{vid} ? ( 'wl.vid = ?' => $o{vid} ) : (), - ); - - my $select = 'wl.vid, wl.wstat, wl.added'; - my @join; - if($o{what} =~ /vn/) { - $select .= ', vr.title, vr.original'; - push @join, 'JOIN vn v ON v.id = wl.vid', - 'JOIN vn_rev vr ON vr.id = v.latest'; - } - - my $r = $s->DBAll(qq| - SELECT $select - FROM wlists wl - @join - !W - ORDER BY !s - LIMIT ? OFFSET ?|, - \%where, - $o{order}, - $o{results}+(wantarray?1:0), $o{results}*($o{page}-1) - ); - return $r if !wantarray; - return ($r, 0) if $#$r < $o{results}; - pop @$r; - return ($r, 1); -} - - -sub DBEditWishList { # %options->{ uid vid wstat } - my($s, %o) = @_; - $s->DBExec(q|UPDATE wlists SET wstat = ? WHERE uid = ? AND vid IN(!l)|, - $o{wstat}, $o{uid}, ref($o{vid}) eq 'ARRAY' ? $o{vid} : [ $o{vid} ]) - || - $s->DBExec(q|INSERT INTO wlists (uid, vid, wstat) - VALUES(!l)|, - [@o{qw| uid vid wstat |}]); -} - - -sub DBDelWishList { # uid, vids - my($s, $uid, $vid) = @_; - $s->DBExec(q|DELETE FROM wlists WHERE uid = ? AND vid IN(!l)|, $uid, $vid); -} - - - - - - -#-----------------------------------------------------------------------------# -# U S E R R E L E A S E L I S T S # -#-----------------------------------------------------------------------------# - - -sub DBGetRList { # %options->{ uid rids } - my($s, %o) = @_; - - my %where = ( - 'uid = ?' => $o{uid}, - $o{rids} ? ( - 'rid IN(!l)' => [$o{rids}] ) : (), - ); - - return $s->DBAll(q| - SELECT uid, rid, rstat, vstat - FROM rlists - !W|, - \%where); -} - - -# separate function, which also fetches VN info and votes -sub DBGetRLists { # %options->{ uid order char rstat vstat voted page results } - my($s, %o) = @_; - - $o{results} ||= 50; - $o{page} ||= 1; - - # bit ugly... - my $where = !$o{rstat} && !$o{vstat} ? 'vo.vote IS NOT NULL' : ''; - $where .= ($where?' OR ':'').q|v.id IN( - SELECT irv.vid - FROM rlists irl - JOIN releases ir ON ir.id = irl.rid - JOIN releases_vn irv ON irv.rid = ir.latest - !W - )| if !$o{voted}; - $where = '('.$where.') AND LOWER(SUBSTR(vr.title, 1, 1)) = \''.$o{char}.'\'' if $o{char}; - $where = '('.$where.') AND (ASCII(vr.title) < 97 OR ASCII(vr.title) > 122) AND (ASCII(vr.title) < 65 OR ASCII(vr.title) > 90)' if defined $o{char} && !$o{char}; - - # WHERE clause for the rlists subquery - my %where = ( - 'uid = ?' => $o{uid}, - defined $o{rstat} ? ( 'rstat = ?' => $o{rstat} ) : (), - defined $o{vstat} ? ( 'vstat = ?' => $o{vstat} ) : (), - ); - - my $r = $s->DBAll(qq| - SELECT vr.vid, vr.title, vr.original, v.c_released, v.c_languages, v.c_platforms, COALESCE(vo.vote, 0) AS vote - FROM vn v - JOIN vn_rev vr ON vr.id = v.latest - !s JOIN votes vo ON vo.vid = v.id AND vo.uid = ? - WHERE $where - ORDER BY !s - LIMIT ? OFFSET ?|, - $o{voted} ? '' : 'LEFT', $o{uid}, # JOIN if we only want votes, LEFT JOIN if we also want rlist items - $o{voted} ? () : \%where, - $o{order}, - $o{results}+(wantarray?1:0), $o{results}*($o{page}-1) - ); - - # now fetch the releases and link them to VNs - if(@$r) { - my %vns = map { $_->{rels}=[]; $_->{vid}, $_->{rels} } @$r; - push @{$vns{$_->{vid}}}, $_ for (@{$s->DBAll(q| - SELECT rv.vid, rr.rid, rr.title, rr.original, rr.released, rr.type, rr.language, rr.minage, rl.rstat, rl.vstat - FROM rlists rl - JOIN releases r ON rl.rid = r.id - JOIN releases_rev rr ON rr.id = r.latest - JOIN releases_vn rv ON rv.rid = r.latest - WHERE rl.uid = ? - AND rv.vid IN(!l) - ORDER BY rr.released ASC|, - $o{uid}, [ keys %vns ] - )}); - } - - return $r if !wantarray; - return ($r, 0) if $#$r < $o{results}; - pop @$r; - return ($r, 1); -} - - -sub DBEditRList { # %options->{ uid rid rstat vstat } - # rid can only be a arrayref with UPDATE - my($s, %o) = @_; - my %s = ( - defined $o{rstat} ? ( 'rstat = ?', $o{rstat} ) : (), - defined $o{vstat} ? ( 'vstat = ?', $o{vstat} ) : (), - ); - $o{rstat}||=0; - $o{vstat}||=0; - - $s->DBExec(q|UPDATE rlists !H WHERE uid = ? AND rid IN(!l)|, - \%s, $o{uid}, ref($o{rid}) eq 'ARRAY' ? $o{rid} : [ $o{rid} ]) - || - $s->DBExec(q|INSERT INTO rlists (uid, rid, rstat, vstat) - VALUES(!l)|, - [@o{qw| uid rid rstat vstat |}]); -} - - -sub DBDelRList { # uid, \@rids - my($s, $uid, $rid) = @_; - $s->DBExec(q|DELETE FROM rlists WHERE uid = ? AND rid IN(!l)|, $uid, ref($rid) eq 'ARRAY' ? $rid : [ $rid ]); -} - - - - - -#-----------------------------------------------------------------------------# -# V I S U A L N O V E L S # -#-----------------------------------------------------------------------------# - - -sub DBGetVN { # %options->{ id rev char search order results page what cati cate lang platform } - my $s = shift; - my %o = ( - page => 1, - results => 50, - order => 'vr.title ASC', - what => '', - @_ ); - - my %where = ( - !$o{id} && !$o{rev} ? ( # don't fetch hidden items unless we ask for an ID - 'v.hidden = ?' => 0 ) : (), - $o{id} && !ref($o{id}) ? ( - 'v.id = ?' => $o{id} ) : (), - $o{id} && ref($o{id}) ? ( - 'v.id IN(!l)' => [$o{id}] ) : (), - $o{rev} ? ( - 'c.rev = ?' => $o{rev} ) : (), - $o{char} ? ( - 'LOWER(SUBSTR(vr.title, 1, 1)) = ?' => $o{char} ) : (), - defined $o{char} && !$o{char} ? ( - '(ASCII(vr.title) < 97 OR ASCII(vr.title) > 122) AND (ASCII(vr.title) < 65 OR ASCII(vr.title) > 90)' => 1 ) : (), - $o{cati} && @{$o{cati}} ? ( q| - v.id IN(SELECT iv.id - FROM vn_categories ivc - JOIN vn iv ON iv.latest = ivc.vid - WHERE cat IN(!l) - GROUP BY iv.id - HAVING COUNT(cat) = ?)| => [ $o{cati}, $#{$o{cati}}+1 ] ) : (), - $o{cate} && @{$o{cate}} ? ( q| - v.id NOT IN(SELECT iv.id - FROM vn_categories ivc - JOIN vn iv ON iv.latest = ivc.vid - WHERE cat IN(!l) - GROUP BY iv.id)| => [ $o{cate} ] ) : (), - # this needs some proper handling... - $o{lang} && @{$o{lang}} ? ( - '('.join(' OR ', map "v.c_languages ILIKE '%%$_%%'", @{$o{lang}}).')' => 1 ) : (), - $o{platform} && @{$o{platform}} ? ( - '('.join(' OR ', map "v.c_platforms ILIKE '%%$_%%'", @{$o{platform}}).')' => 1 ) : (), - ); - - if($o{search}) { - my @w; - for (split /[ -,]/, $o{search}) { - s/%//g; - next if length($_) < 2; - if(VNDB::GTINType($_)) { - push @w, 'irr.gtin = ?', $_; - } else { - $_ = "%$_%"; - push @w, '(ivr.title ILIKE ? OR ivr.alias ILIKE ? OR irr.title ILIKE ? OR irr.original ILIKE ?)', - [ $_, $_, $_, $_ ]; - } - } - $where{ q| - v.id IN(SELECT iv.id - FROM vn iv - JOIN vn_rev ivr ON iv.latest = ivr.id - LEFT JOIN releases_vn irv ON irv.vid = iv.id - LEFT JOIN releases_rev irr ON irr.id = irv.rid - LEFT JOIN releases ir ON ir.latest = irr.id - !W - GROUP BY iv.id)| } = [ \@w ] if @w; - } - - my @join = ( - $o{rev} ? - 'JOIN vn v ON v.id = vr.vid' : - 'JOIN vn v ON vr.id = v.latest', - $o{what} =~ /changes/ || $o{rev} ? ( - 'JOIN changes c ON c.id = vr.id', - 'JOIN users u ON u.id = c.requester' ) : (), - $o{what} =~ /relgraph/ ? ( - 'LEFT JOIN relgraph rg ON rg.id = v.rgraph' ) : (), - ); - - my $sel = 'v.id, v.locked, v.hidden, v.c_released, v.c_languages, v.c_platforms, vr.title, vr.original, vr.id AS cid'; - $sel .= ', vr.alias, vr.image AS image, vr.img_nsfw, vr.length, vr.desc, vr.l_wp, vr.l_encubed, vr.l_renai, vr.l_vnn' if $o{what} =~ /extended/; - $sel .= ', c.added, c.requester, c.comments, v.latest, u.username, c.rev, c.causedby' if $o{what} =~ /changes/; - $sel .= ', v.rgraph, rg.cmap' if $o{what} =~ /relgraph/; - - my $r = $s->DBAll(qq| - SELECT $sel - FROM vn_rev vr - @join - !W - ORDER BY !s - LIMIT ? OFFSET ?|, - \%where, - $o{order}, - $o{results}+(wantarray?1:0), $o{results}*($o{page}-1) - ); - $_->{c_released} = sprintf '%08d', $_->{c_released} for @$r; - - if($o{what} =~ /(?:relations|categories|anime|screenshots)/ && $#$r >= 0) { - my %r = map { - $r->[$_]{relations} = []; - $r->[$_]{categories} = []; - $r->[$_]{anime} = []; - $r->[$_]{screenshots} = []; - ($r->[$_]{cid}, $_) - } 0..$#$r; - - if($o{what} =~ /categories/) { - push(@{$r->[$r{$_->{vid}}]{categories}}, [ $_->{cat}, $_->{lvl} ]) for (@{$s->DBAll(q| - SELECT vid, cat, lvl - FROM vn_categories - WHERE vid IN(!l)|, - [ keys %r ] - )}); - } - - if($o{what} =~ /anime/) { - push(@{$r->[$r{$_->{vid}}]{anime}}, $_) && delete $_->{vid} for (@{$s->DBAll(q| - SELECT va.vid, a.* - FROM vn_anime va - JOIN anime a ON va.aid = a.id - WHERE va.vid IN(!l)|, - [ keys %r ] - )}); - } - - if($o{what} =~ /screenshots/) { - push(@{$r->[$r{$_->{vid}}]{screenshots}}, $_) && delete $_->{vid} for (@{$s->DBAll(q| - SELECT vs.vid, s.id, vs.nsfw, vs.rid, s.width, s.height - FROM vn_screenshots vs - JOIN screenshots s ON vs.scr = s.id - WHERE vs.vid IN(!l) - ORDER BY vs.scr|, - [ keys %r ] - )}); - } - - if($o{what} =~ /relations/) { - my $rel = $s->DBAll(q| - SELECT rel.vid1, rel.vid2, rel.relation, vr.title, vr.original - FROM vn_relations rel - JOIN vn v ON rel.vid2 = v.id - JOIN vn_rev vr ON v.latest = vr.id - WHERE rel.vid1 IN(!l)|, - [ keys %r ]); - push(@{$r->[$r{$_->{vid1}}]{relations}}, { - relation => $_->{relation}, - id => $_->{vid2}, - title => $_->{title}, - original => $_->{original} - }) for (@$rel); - } - } - - return $r if !wantarray; - return ($r, 0) if $#$r != $o{results}; - pop @$r; - return ($r, 1); -} - - -sub DBAddVN { # %options->{ comm + _insert_vn_rev } - my($s, %o) = @_; - - my $id = $s->DBRow(q| - INSERT INTO changes (type, requester, ip, comments) - VALUES (!l) - RETURNING id|, - [ 0, $s->AuthInfo->{id}, $s->ReqIP, $o{comm} ] - )->{id}; - - my $vid = $s->DBRow(q| - INSERT INTO vn (latest) - VALUES (?) - RETURNING id|, $id - )->{id}; - - _insert_vn_rev($s, $id, $vid, \%o); - - return ($vid, $id); # item id, global revision -} - - -sub DBEditVN { # id, %options->( comm + _insert_vn_rev + uid + causedby } - my($s, $vid, %o) = @_; - - my $c = $s->DBRow(q| - INSERT INTO changes (type, requester, ip, comments, rev, causedby) - VALUES (?, ?, ?, ?, ( - SELECT c.rev+1 - FROM changes c - JOIN vn_rev vr ON vr.id = c.id - WHERE vr.vid = ? - ORDER BY c.id DESC - LIMIT 1 - ), ?) - RETURNING id, rev|, - 0, $o{uid}||$s->AuthInfo->{id}, $s->ReqIP, $o{comm}, $vid, $o{causedby}||undef); - - _insert_vn_rev($s, $c->{id}, $vid, \%o); - - $s->DBExec(q|UPDATE vn SET latest = ? WHERE id = ?|, $c->{id}, $vid); - return ($c->{rev}, $c->{id}); # local revision, global revision -} - - -sub _insert_vn_rev { # columns in vn_rev + categories + screenshots + relations - my($s, $cid, $vid, $o) = @_; - - $$o{img_nsfw} = $$o{img_nsfw}?1:0; - $s->DBExec(q| - INSERT INTO vn_rev (id, vid, title, original, "desc", alias, image, img_nsfw, length, l_wp, l_encubed, l_renai, l_vnn) - VALUES (!l)|, - [ $cid, $vid, @$o{qw|title original desc alias image img_nsfw length l_wp l_encubed l_renai l_vnn|} ]); - - $s->DBExec(q| - INSERT INTO vn_categories (vid, cat, lvl) - VALUES (?, ?, ?)|, - $cid, $_->[0], $_->[1] - ) for (@{$o->{categories}}); - - $s->DBExec(q| - INSERT INTO vn_screenshots (vid, scr, nsfw, rid) - VALUES (?, ?, ?, ?)|, - $cid, $_->[0], $_->[1]?1:0, $_->[2] - ) for (@{$o->{screenshots}}); - - $s->DBExec(q| - INSERT INTO vn_relations (vid1, vid2, relation) - VALUES (?, ?, ?)|, - $cid, $_->[1], $_->[0] - ) for (@{$o->{relations}}); - - if(@{$o->{anime}}) { - $s->DBExec(q| - INSERT INTO vn_anime (vid, aid) - VALUES (?, ?)|, - $cid, $_ - ) for (@{$o->{anime}}); - - # insert unknown anime - my $a = $s->DBAll(q| - SELECT id FROM anime WHERE id IN(!l)|, - $o->{anime}); - $s->DBExec(q| - INSERT INTO anime (id) VALUES (?)|, $_ - ) for (grep { - my $ia = $_; - !(scalar grep $ia == $_->{id}, @$a) - } @{$o->{anime}}); - } -} - - -sub DBHideVN { # id, hidden - my($s, $id, $h) = @_; - $s->DBExec(q| - UPDATE vn - SET hidden = ? - WHERE id = ?|, - $h?1:0, $id); -} - - -sub DBVNCache { # @vids - my($s,@vn) = @_; - $s->DBExec('SELECT update_vncache(?)', $_) for (@vn); -} - - - - - -#-----------------------------------------------------------------------------# -# R E L E A S E S # -#-----------------------------------------------------------------------------# - - -sub DBGetRelease { # %options->{ id vid results page rev } - my($s, %o) = @_; - - $o{results} ||= 50; - $o{page} ||= 1; - $o{what} ||= ''; - $o{order} ||= 'rr.released ASC'; - my %where = ( - !$o{id} && !$o{rev} ? ( - 'r.hidden = ?' => 0 ) : (), - $o{id} ? ( - 'r.id = ?' => $o{id} ) : (), - $o{rev} ? ( - 'c.rev = ?' => $o{rev} ) : (), - $o{vid} ? ( - 'rv.vid = ?' => $o{vid} ) : (), - defined $o{unreleased} ? ( - q|rr.released !s TO_CHAR('today'::timestamp, 'YYYYMMDD')::integer| => $o{unreleased} ? '>' : '<=' ) : (), - ); - - my @join; - push @join, $o{rev} ? 'JOIN releases r ON r.id = rr.rid' : 'JOIN releases r ON rr.id = r.latest'; - push @join, 'JOIN changes c ON c.id = rr.id' if $o{what} =~ /changes/ || $o{rev}; - push @join, 'JOIN users u ON u.id = c.requester' if $o{what} =~ /changes/; - push @join, 'JOIN releases_vn rv ON rv.rid = rr.id' if $o{vid}; - - my $select = 'r.id, r.locked, r.hidden, rr.id AS cid, rr.title, rr.original, rr.gtin, rr.language, rr.website, rr.released, rr.notes, rr.minage, rr.type'; - $select .= ', c.added, c.requester, c.comments, r.latest, u.username, c.rev' if $o{what} =~ /changes/; - - my $r = $s->DBAll(qq| - SELECT $select - FROM releases_rev rr - @join - !W - ORDER BY !s - LIMIT ? OFFSET ?|, - \%where, - $o{order}, - $o{results}+(wantarray?1:0), $o{results}*($o{page}-1) - ); - $_->{released} = sprintf '%08d', $_->{released} for @$r; - - if($#$r >= 0 && $o{what} =~ /(vn|producers|platforms|media)/) { - my %r = map { - $r->[$_]{producers} = []; - $r->[$_]{platforms} = []; - $r->[$_]{media} = []; - $r->[$_]{vn} = []; - ($r->[$_]{cid}, $_) - } 0..$#$r; - - if($o{what} =~ /vn/) { - push(@{$r->[$r{$_->{rid}}]{vn}}, $_) for (@{$s->DBAll(q| - SELECT rv.rid, vr.vid, vr.title, vr.original - FROM releases_vn rv - JOIN vn v ON v.id = rv.vid - JOIN vn_rev vr ON vr.id = v.latest - WHERE rv.rid IN(!l)|, - [ keys %r ] - )}); - } - - if($o{what} =~ /producers/) { - push(@{$r->[$r{$_->{rid}}]{producers}}, $_) for (@{$s->DBAll(q| - SELECT rp.rid, p.id, pr.name, pr.original, pr.type - FROM releases_producers rp - JOIN producers p ON rp.pid = p.id - JOIN producers_rev pr ON pr.id = p.latest - WHERE rp.rid IN(!l)|, - [ keys %r ] - )}); - } - if($o{what} =~ /platforms/) { - push(@{$r->[$r{$_->{rid}}]{platforms}}, $_->{platform}) for (@{$s->DBAll(q| - SELECT rid, platform - FROM releases_platforms - WHERE rid IN(!l)|, - [ keys %r ] - )}); - } - if($o{what} =~ /media/) { - ($_->{medium}=~s/\s+//||1)&&push(@{$r->[$r{$_->{rid}}]{media}}, $_) for (@{$s->DBAll(q| - SELECT rid, medium, qty - FROM releases_media - WHERE rid IN(!l)|, - [ keys %r ] - )}); - } - } - - return $r if !wantarray; - return ($r, 0) if $#$r < $o{results}; - pop @$r; - return ($r, 1); -} - - -sub DBAddRelease { # options -> { comm + _insert_release_rev } - my($s, %o) = @_; - - my $id = $s->DBRow(q| - INSERT INTO changes (type, requester, ip, comments) - VALUES (!l) - RETURNING id|, - [ 1, $s->AuthInfo->{id}, $s->ReqIP, $o{comm} ] - )->{id}; - - my $rid = $s->DBRow(q| - INSERT INTO releases (latest) - VALUES (?) - RETURNING id|, $id)->{id}; - - _insert_release_rev($s, $id, $rid, \%o); - return ($rid, $id); # item id, global revision -} - - -sub DBEditRelease { # id, %opts->{ comm + _insert_release_rev } - my($s, $rid, %o) = @_; - - my $c = $s->DBRow(q| - INSERT INTO changes (type, requester, ip, comments, rev) - VALUES (?, ?, ?, ?, ( - SELECT c.rev+1 - FROM changes c - JOIN releases_rev rr ON rr.id = c.id - WHERE rr.rid = ? - ORDER BY c.id DESC - LIMIT 1 - )) - RETURNING id, rev|, - 1, $s->AuthInfo->{id}, $s->ReqIP, $o{comm}, $rid); - - _insert_release_rev($s, $c->{id}, $rid, \%o); - - $s->DBExec(q|UPDATE releases SET latest = ? WHERE id = ?|, $c->{id}, $rid); - return ($c->{rev}, $c->{id}); # local revision, global revision -} - - -sub _insert_release_rev { # %option->{ columns in releases_rev + producers + platforms + vn + media } - my($s, $cid, $rid, $o) = @_; - - $s->DBExec(q| - INSERT INTO releases_rev (id, rid, title, original, gtin, language, website, released, notes, minage, type) - VALUES (!l)|, - [ $cid, $rid, @$o{qw| title original gtin language website released notes minage type|} ]); - - $s->DBExec(q| - INSERT INTO releases_producers (rid, pid) - VALUES (?, ?)|, - $cid, $_ - ) for (@{$o->{producers}}); - - $s->DBExec(q| - INSERT INTO releases_platforms (rid, platform) - VALUES (?, ?)|, - $cid, $_ - ) for (@{$o->{platforms}}); - - $s->DBExec(q| - INSERT INTO releases_vn (rid, vid) - VALUES (?, ?)|, - $cid, $_ - ) for (@{$o->{vn}}); - - $s->DBExec(q| - INSERT INTO releases_media (rid, medium, qty) - VALUES (?, ?, ?)|, - $cid, $_->[0], $_->[1] - ) for (@{$o->{media}}); -} - - -sub DBHideRelease { # id, hidden - my($s, $id, $h) = @_; - $s->DBExec(q| - UPDATE releases - SET hidden = ? - WHERE id = ?|, - $h?1:0, $id); -} - - - -#-----------------------------------------------------------------------------# -# P R O D U C E R S # -#-----------------------------------------------------------------------------# - - -sub DBGetProducer { # %options->{ id search char results page rev } - my($s, %o) = @_; - - $o{results} ||= 50; - $o{page} ||= 1; - $o{search} =~ s/%//g if $o{search}; - $o{what} ||= ''; - my %where = ( - !$o{id} && !$o{rev} ? ( - 'p.hidden = ?' => 0 ) : (), - $o{id} ? ( - 'p.id = ?' => $o{id} ) : (), - $o{search} ? ( - '(pr.name ILIKE ? OR pr.original ILIKE ?)', [ '%%'.$o{search}.'%%', '%%'.$o{search}.'%%' ] ) : (), - $o{char} ? ( - 'LOWER(SUBSTR(pr.name, 1, 1)) = ?' => $o{char} ) : (), - defined $o{char} && !$o{char} ? ( - '(ASCII(pr.name) < 97 OR ASCII(pr.name) > 122) AND (ASCII(pr.name) < 65 OR ASCII(pr.name) > 90)' => 1 ) : (), - $o{rev} ? ( - 'c.rev = ?' => $o{rev} ) : (), - ); - - my @join; - push @join, $o{rev} ? 'JOIN producers p ON p.id = pr.pid' : 'JOIN producers p ON pr.id = p.latest'; - push @join, 'JOIN changes c ON c.id = pr.id' if $o{what} =~ /changes/ || $o{rev}; - push @join, 'JOIN users u ON u.id = c.requester' if $o{what} =~ /changes/; - - my $select = 'p.id, p.locked, p.hidden, pr.type, pr.name, pr.original, pr.website, pr.lang, pr.desc'; - $select .= ', c.added, c.requester, c.comments, p.latest, pr.id AS cid, u.username, c.rev' if $o{what} =~ /changes/; - - my $r = $s->DBAll(qq| - SELECT $select - FROM producers_rev pr - @join - !W - ORDER BY pr.name ASC - LIMIT ? OFFSET ?|, - \%where, - $o{results}+(wantarray?1:0), $o{results}*($o{page}-1) - ); - - return $r if !wantarray; - return ($r, 0) if $#$r < $o{results}; - pop @$r; - return ($r, 1); -} - - -sub DBGetProducerVN { # pid - return $_[0]->DBAll(q| - SELECT v.id, MAX(vr.title) AS title, MAX(vr.original) AS original, MIN(rr.released) AS date - FROM releases_producers vp - JOIN releases_rev rr ON rr.id = vp.rid - JOIN releases r ON r.latest = rr.id - JOIN releases_vn rv ON rv.rid = rr.id - JOIN vn v ON v.id = rv.vid - JOIN vn_rev vr ON vr.id = v.latest - WHERE vp.pid = ? - AND v.hidden = ? - GROUP BY v.id - ORDER BY date|, - $_[1], 0); -} - - -sub DBAddProducer { # %opts->{ comm + _insert_producer_rev } - my($s, %o) = @_; - - my $id = $s->DBRow(q| - INSERT INTO changes (type, requester, ip, comments) - VALUES (!l) - RETURNING id|, - [ 2, $s->AuthInfo->{id}, $s->ReqIP, $o{comm} ] - )->{id}; - - my $pid = $s->DBRow(q| - INSERT INTO producers (latest) - VALUES (?) - RETURNING id|, $id - )->{id}; - - _insert_producer_rev($s, $id, $pid, \%o); - - return ($pid, $id); # item id, global revision -} - - -sub DBEditProducer { # id, %opts->{ comm + _insert_producer_rev } - my($s, $pid, %o) = @_; - - my $c = $s->DBRow(q| - INSERT INTO changes (type, requester, ip, comments, rev) - VALUES (?, ?, ?, ?, ( - SELECT c.rev+1 - FROM changes c - JOIN producers_rev pr ON pr.id = c.id - WHERE pr.pid = ? - ORDER BY c.id DESC - LIMIT 1 - )) - RETURNING id, rev|, - 2, $s->AuthInfo->{id}, $s->ReqIP, $o{comm}, $pid); - - _insert_producer_rev($s, $c->{id}, $pid, \%o); - - $s->DBExec(q|UPDATE producers SET latest = ? WHERE id = ?|, $c->{id}, $pid); - return ($c->{rev}, $c->{id}); # local revision, global revision -} - - -sub _insert_producer_rev { # %opts->{ columns in produces_rev } - my($s, $cid, $pid, $o) = @_; - $s->DBExec(q| - INSERT INTO producers_rev (id, pid, name, original, website, type, lang, "desc") - VALUES (!l)|, - [ $cid, $pid, @$o{qw| name original website type lang desc|} ]); -} - - -sub DBHideProducer { # id, hidden - my($s, $id, $h) = @_; - $s->DBExec(q| - UPDATE producers - SET hidden = ? - WHERE id = ?|, - $h?1:0, $id); -} - - - - - -#-----------------------------------------------------------------------------# -# D I S C U S S I O N S # -#-----------------------------------------------------------------------------# - - -sub DBGetThreads { # %options->{ id type iid results page what } - my($s, %o) = @_; - - $o{results} ||= 50; - $o{page} ||= 1; - $o{what} ||= ''; - $o{order} ||= 't.id DESC'; - - my %where = ( - $o{id} ? ( - 't.id = ?' => $o{id} ) : (), - !$o{id} ? ( - 't.hidden = ?' => 0 ) : (), - $o{type} && !$o{iid} ? ( - 't.id IN(SELECT tid FROM threads_tags WHERE type = ?)' => $o{type} ) : (), - $o{type} && $o{iid} ? ( - 'tt.type = ?' => $o{type}, 'tt.iid = ?' => $o{iid} ) : (), - ); - - my $select = 't.id, t.title, t.count, t.locked, t.hidden'; - $select .= ', tp.uid, tp.date, u.username' if $o{what} =~ /firstpost/; - $select .= ', tp2.uid AS luid, tp2.date AS ldate, u2.username AS lusername' if $o{what} =~ /lastpost/; - - my @join; - push @join, 'JOIN threads_posts tp ON tp.tid = t.id AND tp.num = 1' if $o{what} =~ /firstpost/; - push @join, 'JOIN users u ON u.id = tp.uid' if $o{what} =~ /firstpost/; - push @join, 'JOIN threads_posts tp2 ON tp2.tid = t.id AND tp2.num = t.count' if $o{what} =~ /lastpost/; - push @join, 'JOIN users u2 ON u2.id = tp2.uid' if $o{what} =~ /lastpost/; - push @join, 'JOIN threads_tags tt ON tt.tid = t.id' if $o{type} && $o{iid}; - - my $r = $s->DBAll(qq| - SELECT $select - FROM threads t - @join - !W - ORDER BY !s - LIMIT ? OFFSET ?|, - \%where, - $o{order}, - $o{results}+(wantarray?1:0), $o{results}*($o{page}-1) - ); - - if($o{what} =~ /(tags|tagtitles)/ && $#$r >= 0) { - my %r = map { - $r->[$_]{tags} = []; - ($r->[$_]{id}, $_) - } 0..$#$r; - - if($o{what} =~ /tags/) { - ($_->{type}=~s/ +//||1) && push(@{$r->[$r{$_->{tid}}]{tags}}, [ $_->{type}, $_->{iid} ]) for (@{$s->DBAll(q| - SELECT tid, type, iid - FROM threads_tags - WHERE tid IN(!l)|, - [ keys %r ] - )}); - } - if($o{what} =~ /tagtitles/) { - ($_->{type}=~s/ +//||1) && push(@{$r->[$r{$_->{tid}}]{tags}}, [ $_->{type}, $_->{iid}, $_->{title}, $_->{original} ]) for (@{$s->DBAll(q| - SELECT tt.tid, tt.type, tt.iid, COALESCE(u.username, vr.title, pr.name) AS title, COALESCE(u.username, vr.original, pr.original) AS original - FROM threads_tags tt - LEFT JOIN vn v ON tt.type = 'v' AND v.id = tt.iid - LEFT JOIN vn_rev vr ON vr.id = v.latest - LEFT JOIN producers p ON tt.type = 'p' AND p.id = tt.iid - LEFT JOIN producers_rev pr ON pr.id = p.latest - LEFT JOIN users u ON tt.type = 'u' AND u.id = tt.iid - WHERE tt.tid IN(!l)|, - [ keys %r ] - )}); - } - } - - return $r if !wantarray; - return ($r, 0) if $#$r < $o{results}; - pop @$r; - return ($r, 1); -} - - -sub DBGetPosts { # %options->{ tid num page results } - my($s, %o) = @_; - - $o{results} ||= 50; - $o{page} ||= 1; - - my %where = ( - 'tp.tid = ?' => $o{tid}, - $o{num} ? ( - 'tp.num = ?' => $o{num} ) : (), - ); - - my $r = $s->DBAll(q| - SELECT tp.num, tp.date, tp.edited, tp.msg, tp.hidden, tp.uid, u.username - FROM threads_posts tp - JOIN users u ON u.id = tp.uid - !W - ORDER BY tp.num ASC - LIMIT ? OFFSET ?|, - \%where, - $o{results}, $o{results}*($o{page}-1) - ); - - return $r if !wantarray; -} - - -sub DBAddPost { # %options->{ tid uid msg num } - my($s, %o) = @_; - - $o{num} ||= $s->DBRow('SELECT num FROM threads_posts WHERE tid = ? ORDER BY num DESC LIMIT 1', $o{tid})->{num}+1; - $o{uid} ||= $s->AuthInfo->{id}; - - $s->DBExec(q| - INSERT INTO threads_posts (tid, num, uid, msg) - VALUES(?, ?, ?, ?)|, - @o{qw| tid num uid msg |} - ); - $s->DBExec(q| - UPDATE threads - SET count = count+1 - WHERE id = ?|, - $o{tid}); - - return $o{num}; -} - - -sub DBEditPost { # %options->{ tid num msg hidden } - my($s, %o) = @_; - - my %set = ( - 'msg = ?' => $o{msg}, - 'edited = ?' => time, - 'hidden = ?' => $o{hidden}?1:0, - ); - - $s->DBExec(q| - UPDATE threads_posts - !H - WHERE tid = ? - AND num = ?|, - \%set, $o{tid}, $o{num} - ); -} - - -sub DBEditThread { # %options->{ id title locked hidden tags } - my($s, %o) = @_; - - my %set = ( - 'title = ?' => $o{title}, - 'locked = ?' => $o{locked}?1:0, - 'hidden = ?' => $o{hidden}?1:0, - ); - - $s->DBExec(q| - UPDATE threads - !H - WHERE id = ?|, - \%set, $o{id}); - - if($o{tags}) { - $s->DBExec('DELETE FROM threads_tags WHERE tid = ?', $o{id}); - $s->DBExec(q| - INSERT INTO threads_tags (tid, type, iid) - VALUES (?, ?, ?)|, - $o{id}, $_->[0], $_->[1]||0 - ) for (@{$o{tags}}); - } -} - - -sub DBAddThread { # %options->{ title hidden locked tags } - my($s, %o) = @_; - - my $id = $s->DBRow(q| - INSERT INTO threads (title, hidden, locked) - VALUES (?, ?, ?) - RETURNING id|, - $o{title}, $o{hidden}?1:0, $o{locked}?1:0 - )->{id}; - - $s->DBExec(q| - INSERT INTO threads_tags (tid, type, iid) - VALUES (?, ?, ?)|, - $id, $_->[0], $_->[1] - ) for (@{$o{tags}}); - - return $id; -} - - - - - -#-----------------------------------------------------------------------------# -# U T I L I T I E S # -#-----------------------------------------------------------------------------# - - -sub DBExec { return sqlhelper(shift, 0, @_); } -sub DBRow { return sqlhelper(shift, 1, @_); } -sub DBAll { return sqlhelper(shift, 2, @_); } - -sub sqlhelper { # type, query, @list - my $self = shift; - my $type = shift; - my $sqlq = shift; - my $s = $self->{_DB}->{sql}; - - my $start = [Time::HiRes::gettimeofday()] if $self->{debug}; - - $sqlq =~ s/\r?\n/ /g; - $sqlq =~ s/ +/ /g; - my(@q) = @_ ? sqlprint(0, $sqlq, @_) : ($sqlq); - #warn join(', ', map "'$_'", @q)."\n"; - - my $q = $s->prepare($q[0]); - $q->execute($#q ? @q[1..$#q] : ()); - my $r = $type == 1 ? $q->fetchrow_hashref : - $type == 2 ? $q->fetchall_arrayref({}) : - $q->rows; - $q->finish(); - - push(@{$self->{_DB}->{Queries}}, [ $q[0], Time::HiRes::tv_interval($start), @q[1..$#q] ]) if $self->{debug}; - - $r = 0 if $type == 0 && !$r; - $r = {} if $type == 1 && (!$r || ref($r) ne 'HASH'); - $r = [] if $type == 2 && (!$r || ref($r) ne 'ARRAY'); - - return $r; -} - - -# sqlprint: -# ? normal placeholder -# !l list of placeholders, expects arrayref -# !H list of SET-items, expects hashref or arrayref: format => (bind_value || \@bind_values) -# !W same as !H, but for WHERE clauses (AND'ed together) -# !s the classic sprintf %s, use with care -# This isn't sprintf, so all other things won't work, -# Only the ? placeholder is supported, so no dollar sign numbers or named placeholders -# Indeed, this also means you can't use PgSQL operators containing a question mark - -sub sqlprint { # start, query, bind values. Returns new query + bind values - my @a; - my $q=''; - my $s = shift; - for my $p (split /(\?|![lHWs])/, shift) { - next if !defined $p; - if($p eq '?') { - push @a, shift; - $q .= '$'.(@a+$s); - } elsif($p eq '!s') { - $q .= shift; - } elsif($p eq '!l') { - my $l = shift; - $q .= join ', ', map '$'.(@a+$s+$_+1), 0..$#$l; - push @a, @$l; - } elsif($p eq '!H' || $p eq '!W') { - my $h=shift; - my @h=ref $h eq 'HASH' ? %$h : @$h; - my @r; - while(my($k,$v) = (shift(@h), shift(@h))) { - last if !defined $k; - my($n,@l) = sqlprint($#a+1, $k, ref $v eq 'ARRAY' ? @$v : $v); - push @r, $n; - push @a, @l; - } - $q .= ($p eq '!W' ? 'WHERE ' : 'SET ').join $p eq '!W' ? ' AND ' : ', ', @r - if @r; - } else { - $q .= $p; - } - } - return($q, @a); -} - -1; - diff --git a/lib/VNDB/Util/Request.pm b/lib/VNDB/Util/Request.pm deleted file mode 100644 index 5cffec99..00000000 --- a/lib/VNDB/Util/Request.pm +++ /dev/null @@ -1,46 +0,0 @@ - -package VNDB::Util::Request; - -use strict; -use warnings; -use Encode; -use Exporter 'import'; - -our @EXPORT; -@EXPORT = qw| ReqParam ReqSaveUpload ReqCookie - ReqMethod ReqHeader ReqUri ReqIP |; - -sub new { - return bless {}, ref($_[0]) || $_[0]; -} -sub ReqParam { - my($s,$n) = @_; - return wantarray - ? map { decode 'UTF-8', defined $_ ? $_ : '' } $FCGI::Handler::c->param($n) - : decode 'UTF-8', defined $FCGI::Handler::c->param($n) ? $FCGI::Handler::c->param($n) : ''; -} -sub ReqSaveUpload { - my($s,$n,$f) = @_; - open my $F, '>', $f or die "Unable to write to $f: $!"; - print $F $FCGI::Handler::c->param($n); - close $F; -} -sub ReqCookie { - my $c = CGI::Cookie::XS->fetch; - return $c && ref($c) eq 'HASH' && $c->{$_[1]} ? $c->{$_[1]}[0] : ''; -} -sub ReqMethod { - return ($ENV{REQUEST_METHOD}||'') =~ /post/i ? 'POST' : 'GET'; -} -sub ReqHeader { - (my $v = uc $_[1]) =~ tr/-/_/; - return $ENV{"HTTP_$v"}||''; -} -sub ReqUri { - return $ENV{REQUEST_URI}; -} -sub ReqIP { - return $ENV{REMOTE_ADDR}; -} - -1; diff --git a/lib/VNDB/Util/Response.pm b/lib/VNDB/Util/Response.pm deleted file mode 100644 index c5e9a704..00000000 --- a/lib/VNDB/Util/Response.pm +++ /dev/null @@ -1,220 +0,0 @@ - -package VNDB::Util::Response; - - -use strict; -use warnings; -use POSIX (); -use Encode; -use XML::Writer; -use Compress::Zlib; -use Exporter 'import'; -require bytes; - -use vars ('$VERSION', '@EXPORT'); -$VERSION = $VNDB::VERSION; -@EXPORT = qw| ResRedirect ResNotFound ResDenied ResFile - ResForceBody ResSetContentType ResAddHeader ResAddTpl ResAddDefaultStuff - ResStartXML ResGetXML ResGetBody ResGet ResGetCGI ResSetModPerl |; - -sub new { - my $self = shift; - my $tplo = shift; - my $type = ref($self) || $self; - my $me = bless { - headers => [ ], - contenttype => 'text/html; charset=UTF-8', - code => 200, - tplo => $tplo, - tpl => { }, - body => undef, - xmlobj => undef, - xmldata => undef, - whattouse => 1, - }, $type; - - return $me; -} - - -## Some ready-to-use methods -sub ResRedirect { - my $self = shift; - my $url = shift; # should start with '/', if no URL specified, use referer or '/' - my $type = shift; - my $info = $self->{_Res} || $self; - - if(!$url) { - $url = "/"; - my $ref = $self->ReqHeader('Referer'); - ($url = $ref) =~ s/^$self->{root_url}// if $ref; - } - - my $code = !$type ? 301 : - $type eq 'temp' ? 307 : - $type eq 'post' ? 303 : 301; - $info->{body} = 'Redirecting...'; - $info->{code} = $code; - $info->{headers} = [ 'Location', "$self->{root_url}$url" ]; - $info->{contenttype} = 'text/html; charset=UTF-8'; - $info->{whattouse} = 1; -} - -sub ResNotFound { - my $s = shift; - my $i = $s->{_Res}; - $i->{code} = 404; - $i->{whattouse} = 2; - $i->{tpl} = { - page => { error => { - err => 'notfound' - }}, - }; -} - -sub ResDenied { - my $self = shift; - $self->ResRedirect('/u/register?n=1', 'temp'); -} - -sub ResFile { - my($s,$f,@h) = @_; - my $i = $s->{_Res}; - $i->{whattouse} = 4; - $i->{code} = 200; - $i->{contenttype} = ''; - push @{$i->{headers}}, - 'X-Sendfile' => $f, - 'Cache-Control' => sprintf('max-age=%d, public', 7*24*3600), - @h; -} - -## And some often-used methods -sub ResForceBody { - my $self = shift; - my $body = shift; - my $info = $self->{_Res} || $self; - $info->{whattouse} = 1; - $info->{body} = $body; -} - -sub ResSetContentType { - my $self = shift; - my $ctype = shift; - my $info = $self->{_Res} || $self; - $info->{contenttype} = $ctype; - return 1; -} - -sub ResAddHeader { - my $self = shift; - die("Odd number in parameters, must be in key => value format!") unless ((@_ % 2) == 0); - my $info = $self->{_Res} || $self; - $info->{headers} = [ @{$info->{headers}}, @_ ]; - return 1; -} - -sub ResAddTpl { - my $self = shift; - die("Odd number in parameters, must be in key=>value format") unless ((@_ % 2) == 0); - my $info = $self->{_Res} || $self; - $info->{tpl} = { page => { } } if !$info->{tpl}->{page}; - $info->{tpl}->{page} = { %{$info->{tpl}->{page}}, @_ }; - $info->{whattouse} = 2; - return 1; -} - -sub ResStartXML { - my $self = shift; - my $info = $self->{_Res} || $self; - $info->{xmldata} = undef; - $info->{xmlobj} = XML::Writer->new( - OUTPUT => \$info->{xmldata}, - NEWLINES => 0, - ENCODING => 'UTF-8', - DATA_MODE => 1, - DATA_INDENT => 2, - ); - $info->{xmlobj}->xmlDecl(); - $info->{contenttype} = "text/xml; charset=UTF-8"; - # disable caching on XML content, IE < 7 has "some" bugs... - $self->ResAddHeader('Cache-Control' => 'must-revalidate, post-check=0, pre-check=0', - 'Pragma' => 'public'); - $info->{whattouse} = 3; - return $info->{xmlobj}; -} - -## And of course some methods to get the information -sub ResGetXML { - my $self = shift; - my $info = $self->{_Res} || $self; - return undef if !$info->{xmlobj} || !$info->{xmldata}; - $info->{xmlobj}->end(); - my $tmpvar = $info->{xmldata}; - undef $info->{xmldata}; - return $tmpvar; -} - -sub ResGetBody { - my $self = shift; - my $info = $self->{_Res} || $self; - my $whattouse = shift || $info->{whattouse}; - if($whattouse == 1) { return $info->{body}; } - if($whattouse == 2) { - $self->AddDefaultStuff() if exists $info->{tpl}->{page}; - my $start = [Time::HiRes::gettimeofday()] if $self->{debug} && $Time::HiRes::VERSION; - my $output = $info->{tplo}->compile($info->{tpl}); - $info->{_tpltime} = Time::HiRes::tv_interval($start) if $self->{debug} && $Time::HiRes::VERSION; - return $output; - } - if($whattouse == 3) { return $self->ResGetXML; } -} - -sub ResGet { - my $self = shift; - my $info = $self->{_Res} || $self; - my $whattouse = shift || $info->{whattouse}; - - return ($info->{code}, $info->{headers}, $info->{contenttype}, $self->ResGetBody($whattouse)); -} - - -my %scodes = ( - # just a few useful codes - 200 => 'OK', - 301 => 'Moved Permanently', - 302 => 'Found', - 303 => 'See Other', - 304 => 'Not Modified', - 307 => 'Temporary Redirect', - 403 => 'Forbidden', - 404 => 'Not Found', - 500 => 'Internal Server Error' -); - -# don't rename! -sub ResSetModPerl { - my $s = shift; - my $i = $s->{_Res}; - printf "Status: %d %s\r\n", $i->{code}, $scodes{$i->{code}}; - print "X-Powered-By: Perl\r\n"; - printf "Content-Type: %s\r\n", $i->{contenttype} if $i->{contenttype}; - my $c=0; - printf "%s: %s\r\n", $i->{headers}[$c++], $i->{headers}[$c++] - while ($c<$#{$i->{headers}}); - - my $b = $s->ResGetBody||''; - if($b && $s->ReqHeader('Accept-Encoding') =~ /gzip/ && $i->{contenttype} =~ /^text/) { - my $ol = bytes::length($b) if $s->{debug}; - $b = Compress::Zlib::memGzip(Encode::encode_utf8($b)); - $i->{_gzip} = [ $ol, bytes::length($b) ]; - print "Content-Encoding: gzip\n"; - } - my $l = bytes::length($b); - printf "Content-Length: %d\r\n", $l if $l; - print "\r\n"; - print $b; - $FCGI::Handler::outputted = 1; -} - -1; diff --git a/lib/VNDB/Util/Template.pm b/lib/VNDB/Util/Template.pm deleted file mode 100644 index f9c63998..00000000 --- a/lib/VNDB/Util/Template.pm +++ /dev/null @@ -1,235 +0,0 @@ -# VNDB::Util::Template - A direct copy of NTL::Util::Template - -# This file has not been edited for at least a year, -# and there's probably no need to do so in the near future - -# template specific stuff: -# [[ perl code to execute at the specified place ]] -# [[= perl code, append return value to the template at the specified place ]] -# [[: same as above, but escape special HTML chars (<, >, &, " and \n) ]] -# [[% same as above, but also escape as an URL (expects UTF-8 strings) ]] -# [[! perl code, append at the top of the script (useful for subroutine-declarations etc) ]] -# [[+ path to a file to include, relative to $searchdir ]] - -package VNDB::Util::Template; - -use strict; -use warnings; - -use vars ('$VERSION', '@EXPORT'); -$VERSION = $VNDB::VERSION; - - -sub new { - my $pack = shift; - my %ops = @_; - my $me = bless { - namespace => __PACKAGE__ . '::tpl', - pre_chomp => 0, - post_chomp => 0, - rm_newlines => 0, - %ops, - lastreload => 0 - }, ref($pack) || $pack; - - $me->{mainfile} = sprintf '%s/%s', $me->{searchdir}, $me->{filename}; - - die "No filename specified!" if !$me->{filename}; - die "No searchdir specified!" if !$me->{searchdir}; - die "Filename does not exist!" if !-e $me->{mainfile}; - die "No place for the compiled script specified!" if !$me->{compiled}; - - $me->includescript(); - - return $me; -} - -sub includescript { - my $self = shift; - - my $dt = 0; - my $dc = (stat($self->{compiled}))[9] || 0; - - if(-s $self->{compiled} && !exists $INC{$self->{compiled}}) { - eval { require $self->{compiled}; }; - if(!$@) { - $self->{lastreload} = $dc; - } else { - # make sure we can fix the problem and try again - $INC{$self->{compiled}} = $self->{compiled}; - die $@; - } - } - - my $T_version = eval(sprintf '$%s::VERSION;', $self->{namespace}); - - if($dc > $self->{lastreload} || !$T_version) { - $dt = 1; - } - elsif($self->{deep_reload} && $T_version >= 0.1) { - my @T_files = @{ eval(sprintf '\@%s::T_FILES;', $self->{namespace}) }; - if($#T_files >= 0) { - foreach (@T_files) { - if((stat(sprintf('%s/%s', $self->{searchdir}, $_)))[9] > $dc) { - $dt = 2; - last; - } - } - } - } elsif((stat($self->{mainfile}))[9] > $dc) { - $dt = 2; - } - if($dt) { - $self->compiletpl() if $dt == 2 || $dc <= $self->{lastreload}; - delete $INC{$self->{compiled}}; - eval { require $self->{compiled}; }; - if(!$@) { - warn "Reloaded template\n"; - } else { - $INC{$self->{compiled}} = $self->{compiled}; - warn "Template contains errors, not reloading\n"; - } - $self->{lastreload} = (stat($self->{compiled}))[9]; - } -} - -sub compile { - my $self = shift; - my $X = shift; - $self->includescript(); - - return $self->{namespace}->compile($X); -} - -sub compiletpl { - my $self = shift; - open(my $T, '>', $self->{compiled}) || die sprintf '%s: %s', $self->{compiled}, $!; - printf $T <<__, __PACKAGE__, $self->{namespace}, ($self->compilefile()); -# Compiled from a template by %s -package %s; - -use strict; -use warnings; -no warnings qw(redefine); -use URI::Escape \'uri_escape_utf8\'; - -our \$VERSION = 0.1; -our \@T_FILES = qw| %s |; - -sub _hchar { local\$_=shift||return\'\';s/&/&/g;s/</</g;s/>/>/g;s/"/"/g;s/\\r?\\n/<br \\/>/g;return\$_; } -sub _huri { _hchar(uri_escape_utf8((scalar shift)||return \'\')) } -%s -%s -%s -1; -__ - close($T); - warn "Recompiled template\n"; -} - -sub compilefile { - my $self = shift; - my $file = shift||$self->{filename}; - my $func = shift||'compile'; - - my $files = $file; - $file = sprintf('%s/%s', $self->{searchdir}, $file); - open(my $F, '<', $file) || die "$file: $!"; - my $tpl = ''; - $tpl .= $_ while(<$F>); - close($F); - my @t = split(//, $tpl); - $tpl = undef; - - my $inperl = 0; - my $top = ''; - my $R = ''; - my $bottom = ''; - my $dat = ''; - my $perl = ''; - - for(my $i=0; $i<=$#t; $i++) { - # [[= (2), [[: (3) and [[% (4) - if(!$inperl && $t[$i] eq '[' && $t[$i+1] eq '[' && $t[$i+2] =~ /[=:%]/) { - $i+=2; - if($t[$i] eq '=') { - $inperl=2; - $perl = '\' . ( scalar '; - } elsif($t[$i] eq ':') { - $inperl=3; - $perl = '\' . _hchar( scalar '; - } else { - $inperl=4; - $perl = '\' . _huri( scalar '; - } - $R .= $self->_pd($dat); - } elsif($inperl >= 2 && $inperl <= 4 && $t[$i] eq ']' && $t[$i+1] eq ']') { - $inperl=0; $i++; - $R .= $perl . "\n) . '"; - $dat = ''; - # [[! (5) - } elsif(!$inperl && $t[$i] eq '[' && $t[$i+1] eq '[' && $t[$i+2] eq '!') { - $inperl=5; $i+=2; - $perl = ''; - $R .= $self->_pd($dat); - } elsif($inperl == 5 && $t[$i] eq ']' && $t[$i+1] eq ']') { - $inperl=0; $i++; - $top .= $perl . "\n"; - $dat = ''; - # [[+ (6) - } elsif(!$inperl && $t[$i] eq '[' && $t[$i+1] eq '[' && $t[$i+2] eq '+') { - $inperl=6; $i+=2; - $R .= $self->_pd($dat); - $perl = ''; - } elsif($inperl == 6 && $t[$i] eq ']' && $t[$i+1] eq ']') { - $inperl=0;$i++; - $perl =~ s/[\r\n\s]//g; - die "Invalid file specified: $perl\n" if $perl !~ /^[a-zA-Z0-9-_\.\/]+$/; - (my $func = $perl) =~ s/[^a-zA-Z0-9_]/_/g; - my($ifiles, $itop, $imid, $ibot) = $self->compilefile($perl, "T_$func"); - $files .= ' ' . $ifiles; - $top .= $itop; - $bottom .= "\n\n$imid\n$ibot\n"; - $R .= "' . T_$func(\$X) . '"; - $dat = ''; - # [[ (1) - } elsif(!$inperl && $t[$i] eq '[' && $t[$i+1] eq '[') { - $inperl = 1; $i++; - $R .= $self->_pd($dat); - $perl = "';\n"; - } elsif($inperl == 1 && $t[$i] eq ']' && $t[$i+1] eq ']') { - $inperl=0; $i++; - $R .= $perl . "\n \$R .= '"; - $dat = ''; - # data - } elsif(!$inperl) { - (my $l = $t[$i]) =~ s/'/\\'/; - $dat .= $l; - } else { - $perl .= $t[$i]; - } - } - if(!$inperl) { - $R .= $self->_pd($dat) . "';\n"; - } else { - die "Error, no ']]' found at $file!\n"; - } - $R = "sub $func { - my \$X = \$_[". ($func eq 'compile' ? 1 : 0) . "]; - my \$R = '".$R." - return \$R; - }"; - return($files, $top, $R, $bottom); -} - -sub _pd { # Parse Dat - my $self = shift; - local $_ = shift; - - s/[\r\n\s]+$//g if $_ !~ s/-$// && $self->{pre_chomp}; - s/^[\r\n\s]+//g if $_ !~ s/^-// && $self->{post_chomp}; - s/([\s\t]*)[\r\n]+([\s\t]*)/{ $1||$2?' ':'' }/eg if $self->{rm_newlines}; - return $_; -} - -1; diff --git a/lib/VNDB/Util/Tools.pm b/lib/VNDB/Util/Tools.pm deleted file mode 100644 index ee295a67..00000000 --- a/lib/VNDB/Util/Tools.pm +++ /dev/null @@ -1,172 +0,0 @@ - -package VNDB::Util::Tools; - -use strict; -use warnings; -use Encode; -use Tie::ShareLite ':lock'; -use Exporter 'import'; - -our $VERSION = $VNDB::VERSION; -our @EXPORT = qw| FormCheck AddHid GTINType SendMail AddDefaultStuff RunCmd |; - - -# ...this function could use some serious rewriting -sub FormCheck { - my $self = shift; - my @ps = @_; - my %hash; my @err; - - foreach my $i (0..$#ps) { - next if !$ps[$i] || ref($ps[$i]) ne 'HASH'; - my $k = $ps[$i]{name}; - $hash{$k} = [ ( $self->ReqParam($k) ) ]; - $hash{$k}[0] = '' if !defined $hash{$k}[0]; - foreach my $j (0..$#{$hash{$k}}) { - my $val = \$hash{$k}[$j]; my $e = 0; - $e = 1 if !$e && $ps[$i]{required} && !$$val && length($$val) < 1 && $$val ne '0'; - $e = 2 if !$e && $ps[$i]{minlength} && length($$val) < $ps[$i]{minlength}; - $e = 3 if !$e && $ps[$i]{maxlength} && length($$val) > $ps[$i]{maxlength}; - if(!$e && $ps[$i]{template}) { - my $t = $ps[$i]{template}; - $hash{$k}[$j] = lc $hash{$k}[$j] if $t eq 'pname'; - $e = 4 if ($t eq 'mail' && $$val !~ # From regexlib.com, author: Gavin Sharp - /^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+\@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,6}$/) - || ($t eq 'url' && $$val !~ # From regexlib.com, author: M H - /^(http|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:\/~\+#]*[\w\-\@?^=%&\/~\+#])?$/) - || ($t eq 'pname' && $$val !~ /^[a-z0-9][a-z0-9\-]*$/) - || ($t eq 'asciiprint' && $$val !~ /^[\x20-\x7E]*$/) - || ($t eq 'int' && $$val !~ /^\-?[0-9]+$/) - || ($t eq 'date' && $$val !~ /^[0-9]{4}(-[0-9]{2}(-[0-9]{2})?)?$/) - || ($t eq 'gtin' && !GTINType($$val)); - } - $e = 5 if !$e && $ps[$i]{enum} && ref($ps[$i]{enum}) eq "ARRAY" && !_inarray($$val, $ps[$i]{enum}); - if($e) { - if(!$ps[$i]{required} && !$$val && length($$val) < 1 && $$val ne '0') { - $hash{$k}[$j] = exists $ps[$i]{default} ? $ps[$i]{default} : undef; - } else { - my $errc = $ps[$i]{name}.'-'.$e; - $errc .= '-'.$ps[$i]{minlength} if $e == 2; - $errc .= '-'.$ps[$i]{maxlength} if $e == 3; - $errc .= '-'.$ps[$i]{template} if $e == 4; - push(@err, $errc); - last; - } - } - last if !$ps[$i]{multi}; - } - $hash{$k} = $hash{$k}[0] if !$ps[$i]{multi}; - } - $hash{_err} = $#err >= 0 ? \@err : 0; - - return \%hash; -} - - -sub AddHid { - my $fh = $_[0]->FormCheck({ name => 'fh', required => 0, maxlength => 30 })->{fh}; - $_[1]->{_hid} = { map { $_ => 1 } 'com', 'mod', split /,/, $fh } - if $fh; -} - - -sub GTINType { # returns 'JAN', 'EAN', 'UPC' or undef - (my $c = $_[0]) =~ s/^0+//; - return undef if $c !~ /^[0-9]{12,13}$/; # only gtin-12 and 13 - $c = ('0'x(13-length $c)) . $c; # pad with zeros - - # calculate check digit according to - # http://www.gs1.org/productssolutions/barcodes/support/check_digit_calculator.html#how - my @n = reverse split //, $c; - my $n = shift @n; - $n += $n[$_] * ($_ % 2 != 0 ? 1 : 3) for (0..$#n); - return undef if $n % 10 != 0; - - # Do some rough guesses based on: - # http://www.gs1.org/productssolutions/barcodes/support/prefix_list.html - # and http://en.wikipedia.org/wiki/List_of_GS1_country_codes - local $_ = $c; - return 'JAN' if /^4[59]/; # prefix code 450-459 & 490-499 - return 'UPC' if /^(?:0[01]|0[6-9]|13|75[45])/; # prefix code 000-019 & 060-139 & 754-755 - return undef if /(?:0[2-5]|2|97[789]|9[6-9])/; # some codes we don't want: 020–059 & 200-299 & 977-999 - return 'EAN'; # let's just call everything else EAN :) -} - - -sub _inarray { # errr... this is from when I didn't know about grep - foreach (@{$_[1]}) { - (return 1) if $_[0] eq $_; - } - return 0; -} - - -sub SendMail { - my $self = shift; - my $body = shift; - my %hs = @_; - - die "No To: specified!\n" if !$hs{To}; - die "No Subject specified!\n" if !$hs{Subject}; - $hs{'Content-Type'} ||= 'text/plain; charset=\'UTF-8\''; - $hs{From} ||= 'vndb <noreply@vndb.org>'; - $hs{'X-mailer'} ||= "VNDB $VERSION"; - $body =~ s/\r?\n/\n/g; # force a '\n'-linebreak - - my $mail = ''; - foreach (keys %hs) { - $hs{$_} =~ s/[\r\n]//g; - $mail .= sprintf "%s: %s\n", $_, $hs{$_}; - } - $mail .= sprintf "\n%s", $body; - - if(open(my $mailer, "|/usr/sbin/sendmail -t -f '$hs{From}'")) { - print $mailer encode('UTF-8', $mail); - die "Error running sendmail ($!)" - if !close($mailer); - } else { - die "Error opening sendail: $!"; - } -} - - -sub AddDefaultStuff { - my $self = shift; - - $self->AuthAddTpl; - $self->ResAddTpl(st => $self->{static_url}); - - $self->ResAddTpl('Stat'.$_, $self->DBTableCount($_)) - for (qw|users producers vn releases|); - - # development shit - if($self->{debug}) { - my $sqls; - for (@{$self->{_DB}->{Queries}}) { - $_->[0] =~ s/^\s//g; - $sqls .= sprintf("[%6.2fms] %s\n", $_->[1]*1000, $_->[0] || '[undef]'); - $sqls .= " ".join(', ', map "'$_'", @{$_}[2..$#$_])."\n" if exists $$_[2]; - } - $self->ResAddTpl(devshit => $sqls); - } -} - - -# commands aren't actually sent until the function is called without cmd parameter -sub RunCmd { # cmd - my($self, $c) = @_; - if($c) { - push @{$self->{cmds}}, $c; - } elsif(@{$self->{cmds}}) { - my $s = tie my %s, 'Tie::ShareLite', @VNDB::SHMOPTS; - $s->lock(LOCK_EX); - my @q = ( ($s{queue} ? @{$s{queue}} : ()), @{$self->{cmds}} ); - $s{queue} = \@q; - $s->unlock(); - $self->{cmds} = []; - } -} - - -1; - diff --git a/lib/VNDB/VN.pm b/lib/VNDB/VN.pm deleted file mode 100644 index c25f97dd..00000000 --- a/lib/VNDB/VN.pm +++ /dev/null @@ -1,419 +0,0 @@ - -package VNDB::VN; - -use strict; -use warnings; -use Exporter 'import'; -use Digest::MD5; -require bytes; - -use vars ('$VERSION', '@EXPORT'); -$VERSION = $VNDB::VERSION; -@EXPORT = qw| VNPage VNEdit VNLock VNHide VNBrowse VNXML VNScrXML VNUpdReverse |; - - -sub VNPage { - my $self = shift; - my $id = shift; - my $page = shift || ''; - my $rev = shift || 0; - - return $self->ResNotFound if $self->ReqParam('rev'); - - my $what = 'extended relations categories anime screenshots'; - $what .= ' changes' if $rev; - $what .= ' relgraph' if $page eq 'rg'; - - my $v = $self->DBGetVN( - id => $id, - what => $what, - $rev ? ( rev => $rev ) : () - )->[0]; - return $self->ResNotFound if !$v->{id}; - - my $c = $rev && $rev > 1 && $self->DBGetVN(id => $id, rev => $rev-1, what => $what)->[0]; - $v->{next} = $rev && $v->{latest} > $v->{cid} ? $rev+1 : 0; - - my $rel = $self->DBGetRelease(vid => $id, what => 'producers platforms'); - - if(!$page && @$rel && $self->AuthInfo->{id}) { - my $rl = $self->DBGetRList( - rids => [ map $_->{id}, @$rel ], - uid => $self->AuthInfo->{id} - ); - for my $i (@$rl) { - my $r = (grep $i->{rid} == $_->{id}, @$rel)[0]; - $r->{rlist} = $i; - } - } - - $self->ResAddTpl(vnpage => { - vote => $self->AuthInfo->{id} ? $self->DBGetVotes(uid => $self->AuthInfo->{id}, vid => $id)->[0] : {}, - wlist => $self->AuthInfo->{id} ? $self->DBGetWishList(uid => $self->AuthInfo->{id}, vid => $id)->[0] : {}, - vn => $v, - rel => $rel, - prev => $c, - page => $page, - change => $rev, - $page eq 'stats' ? ( - votes => { - latest => scalar $self->DBGetVotes(vid => $id, results => 10, hide => 1), - graph => $self->DBVoteStats(vid => $id), - }, - ) : (), - }); -} - - -sub VNEdit { - my $self = shift; - my $id = shift; # 0 = new - - my $rev = $self->FormCheck({ name => 'rev', required => 0, default => 0, template => 'int' }); - return $self->ResNotFound if $rev->{_err}; - $rev = $rev->{rev}; - - my $v = $self->DBGetVN(id => $id, what => 'extended changes relations categories anime screenshots', $rev ? ( rev => $rev ) : ())->[0] if $id; - return $self->ResNotFound() if $id && !$v; - - return $self->ResDenied if !$self->AuthCan('edit') || ($v->{locked} && !$self->AuthCan('lock')); - - my %b4 = $id ? ( - ( map { $_ => $v->{$_} } qw| title original desc alias img_nsfw length l_wp l_encubed l_renai l_vnn | ), - relations => join('|||', map { $_->{relation}.','.$_->{id}.','.$_->{title} } @{$v->{relations}}), - categories => join(',', map { $_->[0].$_->[1] } sort { $a->[0] cmp $b->[0] } @{$v->{categories}}), - anime => join(' ', sort { $a <=> $b } map $_->{id}, @{$v->{anime}}), - screenshots => join(' ', map sprintf('%d,%d,%d', $$_{id}, $$_{nsfw}?1:0, $$_{rid}||0), @{$v->{screenshots}}), - ) : (); - - my $frm = {}; - if($self->ReqMethod() eq 'POST') { - $frm = $self->FormCheck( - { name => 'title', required => 1, maxlength => 250 }, - { name => 'original', required => 0, maxlength => 250 }, - { name => 'alias', required => 0, maxlength => 500, default => '' }, - { name => 'desc', required => 1, maxlength => 10240 }, - { name => 'length', required => 0, enum => [ 0..($#$VNDB::VNLEN+1) ], default => 0 }, - { name => 'l_wp', required => 0, default => '', maxlength => 150 }, - { name => 'l_encubed', required => 0, default => '', maxlength => 100 }, - { name => 'l_renai', required => 0, default => '', maxlength => 100 }, - { name => 'l_vnn', required => 0, default => 0, template => 'int' }, - { name => 'anime', required => 0, default => '' }, - { name => 'img_nsfw', required => 0 }, - { name => 'categories', required => 0, default => '' }, - { name => 'relations', required => 0, default => '' }, - { name => 'screenshots', required => 0, default => '' }, - { name => 'comm', required => 0, default => '' }, - ); - my $relations = [ map { /^([0-9]+),([0-9]+)/ && $2 != $id ? ( [ $1, $2 ] ) : () } split /\|\|\|/, $frm->{relations} ]; - my $cat = [ map { [ substr($_,0,3), substr($_,3,1) ] } split /,/, $frm->{categories} ]; - my $anime = [ grep /^[0-9]+$/, split / +/, $frm->{anime} ]; - my $screenshots = [ map { local $_=[split /,/];$$_[2]||=undef; $_ } grep /^[0-9]+,[01],[0-9]+$/, split / +/, $frm->{screenshots} ]; - - $frm->{img_nsfw} = $frm->{img_nsfw} ? 1 : 0; - $frm->{anime} = join ' ', sort { $a <=> $b } @$anime; # re-sort - $frm->{screenshots} = join ' ', map sprintf('%d,%d,%d', $$_[0], $$_[1]?1:0, $$_[2]||0), sort { $$a[0] <=> $$b[0] } @$screenshots; - - return $self->ResRedirect('/v'.$id, 'post') - if $id && !$self->ReqParam('img') && 14 == scalar grep { $b4{$_} eq $frm->{$_} } keys %b4; - - # upload image - my $imgid = 0; - if($self->ReqParam('img')) { - my $tmp = sprintf '%s/00/tmp.%d.jpg', $self->{imgpath}, $$*int(rand(1000)+1); - $self->ReqSaveUpload('img', $tmp); - - my $l; - open(my $T, '<:raw:bytes', $tmp) || die $1; - read $T, $l, 2; - close($T); - - $frm->{_err} = $frm->{_err} ? [ @{$frm->{_err}}, 'nojpeg' ] : [ 'nojpeg' ] - if $l ne pack('H*', 'ffd8') && $l ne pack('H*', '8950'); - $frm->{_err} = $frm->{_err} ? [ @{$frm->{_err}}, 'toolarge' ] : [ 'toolarge' ] - if !$frm->{_err} && -s $tmp > 512*1024; # 500 KB max. - - if($frm->{_err}) { - unlink $tmp; - } else { - $imgid = $self->DBIncId('covers_seq'); - my $new = sprintf '%s/%02d/%d.jpg', $self->{imgpath}, $imgid%100, $imgid; - rename $tmp, $new or die $!; - chmod 0666, $new; - $self->RunCmd(sprintf 'coverimage %d', $imgid); - $imgid = -1*$imgid; - } - } elsif($id) { - $imgid = $v->{image}; - } - - my %args = ( - ( map { $_ => $frm->{$_} } qw| title original desc alias comm length l_wp l_encubed l_renai l_vnn img_nsfw| ), - image => $imgid, - anime => $anime, - relations => $relations, - categories => $cat, - screenshots => $screenshots, - ); - - if(!$frm->{_err}) { - my($oid, $nrev, $cid) = ($id, 1, 0); - ($nrev, $cid) = $self->DBEditVN($id, %args) if $id; # edit - ($id, $cid) = $self->DBAddVN(%args) if !$id; # add - - # update reverse relations and relation graph - if((!$oid && $#$relations >= 0) || ($oid && $frm->{relations} ne $b4{relations})) { - my %old = $oid ? (map { $_->{id} => $_->{relation} } @{$v->{relations}}) : (); - my %new = map { $_->[1] => $_->[0] } @$relations; - $self->VNUpdReverse(\%old, \%new, $id, $cid, $nrev); - } - # also regenerate relation graph if the title changes - elsif(@$relations && $frm->{title} ne $b4{title}) { - $self->RunCmd('relgraph '.$id); - } - - # check for new anime data - $self->RunCmd('anime') if $oid && $frm->{anime} ne $b4{anime} || !$oid && $frm->{anime}; - - $self->RunCmd('ircnotify v'.$id.'.'.$nrev); - return $self->ResRedirect('/v'.$id.'.'.$nrev, 'post'); - } - } - - if($id) { - $frm->{$_} ||= $b4{$_} for (keys %b4); - $frm->{comm} = sprintf 'Reverted to revision v%d.%d', $v->{id}, $v->{rev} if $v->{cid} != $v->{latest}; - } - - $self->AddHid($frm); - $frm->{_hid} = {map{$_=>1} qw| info cat img com |} - if !$frm->{_hid} && !$id; - $self->ResAddTpl(vnedit => { - form => $frm, - id => $id, - vn => $v, - rel => scalar $self->DBGetRelease(vid => $id), - }); -} - - -sub VNLock { - my $self = shift; - my $id = shift; - - my $v = $self->DBGetVN(id => $id)->[0]; - return $self->ResNotFound() if !$v; - return $self->ResDenied if !$self->AuthCan('lock'); - $self->DBLockItem('vn', $id, $v->{locked}?0:1); - $self->DBLockItem('releases', $_->{id}, $v->{locked}?0:1) - for (@{$self->DBGetRelease(vid => $id)}); - return $self->ResRedirect('/v'.$id, 'perm'); -} - - -sub VNHide { - my $self = shift; - my $id = shift; - - my $v = $self->DBGetVN(id => $id, what => 'relations')->[0]; - return $self->ResNotFound() if !$v; - return $self->ResDenied if !$self->AuthCan('del'); - $self->DBHideVN($id, $v->{hidden}?0:1); - return $self->ResRedirect('/v'.$id, 'perm'); -} - - -sub VNBrowse { - my $self = shift; - my $chr = shift; - $chr = 'all' if !defined $chr; - - my $f = $self->FormCheck( - { name => 's', required => 0, default => 'title', enum => [ qw|title released votes| ] }, - { name => 'o', required => 0, default => 'a', enum => [ 'a','d' ] }, - { name => 'q', required => 0, default => '' }, - { name => 'sq', required => 0, default => '' }, - { name => 'p', required => 0, template => 'int', default => 1}, - ); - return $self->ResNotFound if $f->{_err}; - $f->{s} = 'title' if $f->{s} eq 'votes'; - - $f->{q} ||= $f->{sq}; - - my(@cati, @cate, @plat, @lang); - my $q = $f->{q}; - if($chr eq 'search') { - # VNDBID - return $self->ResRedirect('/'.$1.$2.(!$3 ? '' : $1 eq 'd' ? '#'.$3 : '.'.$3), 'temp') - if $q =~ /^([vrptud])([0-9]+)(?:\.([0-9]+))?$/; - - if(!($q =~ s/^title://)) { - # categories - my %catl = map { - my $ic = $_; - map { $ic.$_ => $VNDB::CAT->{$ic}[1]{$_} } keys %{$VNDB::CAT->{$ic}[1]} - } keys %$VNDB::CAT; - - $q =~ s/-(?:$catl{$_}|c:$_)//ig && push @cate, $_ for keys %catl; - $q =~ s/(?:$catl{$_}|c:$_)//ig && push @cati, $_ for keys %catl; - - # platforms - $_ ne 'oth' && $q =~ s/(?:$VNDB::PLAT->{$_}|p:$_)//ig && push @plat, $_ for keys %$VNDB::PLAT; - - # languages - $q =~ s/($VNDB::LANG->{$_}|l:$_)//ig && push @lang, $_ for keys %$VNDB::LANG; - } - } - $q =~ s/ +$//; - $q =~ s/^ +//; - - my($r, $np) = $chr ne 'search' || $q || @lang || @plat || @cati || @cate ? ($self->DBGetVN( - $chr =~ /^[a-z0]$/ ? ( char => $chr ) : (), - $q ? ( search => $q ) : (), - @cati ? ( cati => \@cati ) : (), - @cate ? ( cate => \@cate ) : (), - @lang ? ( lang => \@lang ) : (), - @plat ? ( platform => \@plat ) : (), - results => 50, - page => $f->{p}, - order => {title => 'vr.title', released => 'v.c_released', - }->{$f->{s}}.{a=>' ASC',d=>' DESC'}->{$f->{o}}, - )) : ([], 0); - - $self->ResRedirect('/v'.$r->[0]{id}, 'temp') - if $chr eq 'search' && $#$r == 0; - - $self->ResAddTpl(vnbrowse => { - vn => $r, - npage => $np, - page => $f->{p}, - chr => $chr, - $chr eq 'search' ? ( - cat => $self->DBCategoryCount, - langc => $self->DBLanguageCount, - ) : (), - order => [ $f->{s}, $f->{o} ], - }, - searchquery => $f->{q}); -} - - -sub VNXML { - my $self = shift; - - my $q = $self->FormCheck( - { name => 'q', required => 0, maxlength => 100 } - )->{q}; - - my $r = []; - if($q) { - ($r,undef) = $self->DBGetVN(results => 10, - $q =~ /^v([0-9]+)$/ ? (id => $1) : (search => $q)); - } - - my $x = $self->ResStartXML; - $x->startTag('vn', results => $#$r+1, query => $q); - for (@$r) { - $x->startTag('item'); - $x->dataElement(id => $_->{id}); - $x->dataElement(title => $_->{title}); - $x->endTag('item'); - } - $x->endTag('vn'); -} - - -sub VNScrXML { - my $self = shift; - return $self->ResDenied if !$self->AuthCan('edit'); - - # check the status of recently uploaded screenshots - if($self->ReqMethod ne 'POST') { - my $ids = $self->FormCheck( - { name => 'id', required => 1, template => 'int', multi => 1 } - ); - return $self->ResNotFound if $ids->{_err}; - my $r = $self->DBGetScreenshot($ids->{id}); - return $self->ResNotFound if !@$r; - my $x = $self->ResStartXML; - $x->startTag('images'); - $x->emptyTag('image', id => $_->{id}, status => $_->{status}, width => $_->{width}, height => $_->{height}) - for (@$r); - $x->endTag('images'); - return; - } - - # upload new screenshot - my $i = $self->FormCheck( - { name => 'itemnumber', required => 1, template => 'int' } - ); - return $self->ResNotFound if $i->{_err}; - $i = $i->{itemnumber}; - - my $tmp = sprintf '%s/00/tmp.%d.jpg', $self->{sfpath}, $$*int(rand(1000)+1); - $self->ReqSaveUpload('scrAddFile'.$i, $tmp); - - my $id = 0; - $id = -2 if !-s $tmp; - if(!$id) { - my $l; - open(my $T, '<:raw:bytes', $tmp) || die $1; - read $T, $l, 2; - close($T); - $id = -1 if $l ne pack('H*', 'ffd8') && $l ne pack('H*', '8950'); - } - - if($id) { - unlink $tmp; - } else { - $id = $self->DBAddScreenshot; - my $new = sprintf '%s/%02d/%d.jpg', $self->{sfpath}, $id%100, $id; - rename $tmp, $new or die $!; - chmod 0666, $new; - $self->RunCmd('screenshot'); - } - - my $x = $self->ResStartXML; - $x->pi('xml-stylesheet', 'href="'.$self->{static_url}.'/files/blank.css" type="text/css"'); - $x->emptyTag('image', id => $id); -} - - -# Update reverse relations -sub VNUpdReverse { # old, new, id, cid, rev - my($self, $old, $new, $id, $cid, $rev) = @_; - my %upd; - for (keys %$old, keys %$new) { - if(exists $$old{$_} and !exists $$new{$_}) { - $upd{$_} = -1; - } elsif((!exists $$old{$_} and exists $$new{$_}) || ($$old{$_} != $$new{$_})) { - $upd{$_} = $$new{$_}; - if($VNDB::VRELW->{$upd{$_}}) { $upd{$_}-- } - elsif($VNDB::VRELW->{$upd{$_}+1}) { $upd{$_}++ } - } - } - - for my $i (keys %upd) { - my $r = $self->DBGetVN(id => $i, what => 'extended relations categories anime screenshots')->[0]; - my @newrel; - $_->{id} != $id && push @newrel, [ $_->{relation}, $_->{id} ] - for (@{$r->{relations}}); - push @newrel, [ $upd{$i}, $id ] if $upd{$i} != -1; - $self->DBEditVN($i, - relations => \@newrel, - comm => 'Reverse relation update caused by revision v'.$id.'.'.$rev, - causedby => $cid, - uid => 1, # Multi - hardcoded - anime => [ map $_->{id}, @{$r->{anime}} ], - screenshots => [ map [ $_->{id}, $_->{nsfw}, $_->{rid} ], @{$r->{screenshots}} ], - ( map { $_ => $r->{$_} } qw| title original desc alias categories img_nsfw length l_wp l_encubed l_renai l_vnn image | ) - ); - } - - $self->RunCmd('relgraph '.join(' ', $id, keys %upd)); -} - - - -1; - diff --git a/lib/VNDB/VNLists.pm b/lib/VNDB/VNLists.pm deleted file mode 100644 index 0b7a5207..00000000 --- a/lib/VNDB/VNLists.pm +++ /dev/null @@ -1,230 +0,0 @@ - -package VNDB::VNLists; - -use strict; -use warnings; -use Exporter 'import'; - -use vars ('$VERSION', '@EXPORT'); -$VERSION = $VNDB::VERSION; -@EXPORT = qw| VNMyList VNVote RListMod RList WListMod WList |; - - -sub VNMyList { - my $self = shift; - my $user = shift; - - my $u = $self->DBGetUser(uid => $user)->[0]; - return $self->ResNotFound if !$user || !$u || !$self->AuthInfo->{id} || $self->AuthInfo->{id} != $user; - - my $f = $self->FormCheck( - { name => 's', required => 0, default => 'title', enum => [ qw|title date| ] }, - { name => 'o', required => 0, default => 'a', enum => [ 'a','d' ] }, - { name => 'p', required => 0, template => 'int', default => 1 }, - { name => 't', required => 0, enum => [ -1..$#$VNDB::LSTAT ], default => -1 }, - ); - return $self->ResNotFound if $f->{_err}; - - if($self->ReqMethod eq 'POST') { - my $f = $self->FormCheck({ name => 'sel', required => 1, multi => 1, template => 'int' }); - $self->DBDelVNList($user, @{$f->{sel}}) if !$f->{_err}; - } - - my $order = $f->{s} . ($f->{o} eq 'a' ? ' ASC' : ' DESC'); - my($list, $np) = $self->DBGetVNList( - uid => $u->{id}, - order => $order, - results => 50, - page => $f->{p}, - $f->{t} >= 0 ? ( - status => $f->{t} ) : () - ); - - $self->ResAddTpl(vnlist => { - npage => $np, - page => $f->{p}, - list => $list, - order => [ $f->{s}, $f->{o} ], - user => $u, - status => $f->{t}, - }); -} - - -sub VNVote { - my $self = shift; - my $id = shift; - - my $uid = $self->AuthInfo()->{id}; - return $self->ResDenied() if !$uid; - - my $f = $self->FormCheck( - { name => 'v', required => 0, default => 0, enum => [ '-1','1'..'10'] } - ); - return $self->ResNotFound() if !$f->{v}; - - - $self->DBDelVote($uid, $id) if $f->{v} == -1 || $self->DBGetVotes(uid => $uid, vid => $id)->[0]{vid}; - $self->DBAddVote($id, $uid, $f->{v}) if $f->{v} > 0; - - $self->ResRedirect('/v'.$id, 'temp'); -} - - -sub RListMod { - my $self = shift; - my $rid = shift; - - my $f = $self->FormCheck( - { name => 'd', required => 0 }, - { name => 'r', required => 0, enum => [ 0..$#$VNDB::RSTAT ] }, - { name => 'v', required => 0, enum => [ 0..$#$VNDB::VSTAT ] }, - ); - - return $self->ResNotFound if $f->{_err}; - return $self->ResDenied if !$self->AuthInfo->{id}; - - if($f->{d}) { - $self->DBDelRList($self->AuthInfo->{id}, $rid); - } else { - $self->DBEditRList( - uid => $self->AuthInfo->{id}, - rid => $rid, - rstat => $f->{r}, - vstat => $f->{v}, - ); - } - - my $r = $self->ReqHeader('Referer'); - $r = $r && $r =~ /([vr][0-9]+)$/ ? $1 : 'r'.$rid; - return $self->ResRedirect('/'.$r, 'temp'); -} - - -sub RList { - my $self = shift; - my $uid = shift; - - my $u = $self->DBGetUser(uid => $uid)->[0]; - return $self->ResNotFound if !$uid || !$u || (($self->AuthInfo->{id}||0) != $uid && !($u->{flags} & $VNDB::UFLAGS->{list})); - - my $f = $self->FormCheck( - { name => 's', required => 0, default => 'title', enum => [ qw|title vote| ] }, - { name => 'o', required => 0, default => 'a', enum => [ 'a','d' ] }, - { name => 'p', required => 0, template => 'int', default => 1 }, - { name => 'c', required => 0, default => 'all', enum => [ 'a'..'z', '0', 'all' ] }, - ); - return $self->ResNotFound if $f->{_err}; - - if($self->ReqMethod eq 'POST') { - return $self->ResDenied if $uid != $self->AuthInfo->{id}; - my $frm = $self->FormCheck( - { name => 'vnlistchange', required => 1, enum => [ 'd', 'r0'..('r'.$#$VNDB::RSTAT), 'v0'..('v'.$#$VNDB::VSTAT) ] }, - { name => 'rsel', required => 1, multi => 1, template => 'int' }, - ); - if(!$frm->{_err} && @{$frm->{rsel}}) { - $self->DBDelRList($uid, $frm->{rsel}) if $frm->{vnlistchange} eq 'd'; - $self->DBEditRList( - uid => $uid, - rid => $frm->{rsel}, - substr($frm->{vnlistchange},0,1).'stat', substr($frm->{vnlistchange},1) - ) if $frm->{vnlistchange} ne 'd'; - } - } - - my $order = $f->{s} . ($f->{o} eq 'a' ? ' ASC' : ' DESC'); - my($list, $np) = $self->DBGetRLists( - uid => $uid, - results => 50, - page => $f->{p}, - order => $order, - char => $f->{c} eq 'all' ? undef : $f->{c}, - ); - - $self->ResAddTpl(rlist => { - user => $u, - list => $list, - char => $f->{c}, - order => [ $f->{s}, $f->{o} ], - page => $f->{p}, - npage => $np, - }); -} - - -sub WListMod { - my $self = shift; - my $vid = shift; - - my $f = $self->FormCheck( - { name => 'w', required => 1, enum => [ -1..$#$VNDB::RSTAT ] }, - ); - - return $self->ResNotFound if $f->{_err}; - return $self->ResDenied if !$self->AuthInfo->{id}; - - if($f->{w} == -1) { - $self->DBDelWishList($self->AuthInfo->{id}, [ $vid ]); - } else { - $self->DBEditWishList( - uid => $self->AuthInfo->{id}, - vid => $vid, - wstat => $f->{w} - ); - } - - return $self->ResRedirect('/v'.$vid, 'temp'); -} - - -sub WList { - my $self = shift; - my $uid = shift; - - my $u = $self->DBGetUser(uid => $uid)->[0]; - return $self->ResNotFound if !$uid || !$u || (($self->AuthInfo->{id}||0) != $uid && !($u->{flags} & $VNDB::UFLAGS->{list})); - - my $f = $self->FormCheck( - { name => 's', required => 0, default => 'title', enum => [ qw|title wstat added| ] }, - { name => 'o', required => 0, default => 'a', enum => [ 'a','d' ] }, - { name => 'p', required => 0, template => 'int', default => 1 }, - ); - return $self->ResNotFound if $f->{_err}; - - if($self->ReqMethod eq 'POST') { - return $self->ResDenied if $uid != $self->AuthInfo->{id}; - my $frm = $self->FormCheck( - { name => 'sel', required => 1, multi => 1, template => 'int' }, - { name => 'vnlistchange', required => 1, enum => [ 'd', '0'.."$#$VNDB::WLIST" ] }, - ); - if(!$frm->{_err} && @{$frm->{sel}}) { - $self->DBDelWishList($uid, $frm->{sel}) if $frm->{vnlistchange} eq 'd'; - $self->DBEditWishList( - uid => $uid, - vid => $frm->{sel}, - wstat => $frm->{vnlistchange} - ) if $frm->{vnlistchange} ne 'd'; - } - } - - my $order = $f->{s} . ($f->{o} eq 'a' ? ' ASC' : ' DESC'); - $order .= ', title' . ($f->{o} eq 'a' ? ' ASC' : ' DESC') if $f->{s} eq 'wstat'; - my($list, $np) = $self->DBGetWishList( - uid => $u->{id}, - order => $order, - results => 50, - what => 'vn', - page => $f->{p}, - ); - - $self->ResAddTpl(wlist => { - npage => $np, - page => $f->{p}, - list => $list, - order => [ $f->{s}, $f->{o} ], - user => $u, - }); -} - - -1; diff --git a/lib/global.pl b/lib/global.pl deleted file mode 100644 index dea30098..00000000 --- a/lib/global.pl +++ /dev/null @@ -1,687 +0,0 @@ -package VNDB; - -our @DBLOGIN = ( 'dbi:Pg:dbname=vndb', 'vndb', 'passwd' ); -our @SHMOPTS = ( -key => 'VNDB', -create => 'yes', -destroy => 'no', -mode => 0666); -our $DEBUG = 1; -our $VERSION = 'svn'; -our $COOKEY = '73jkS39Sal2)'; # encryption key for cookies (not to worry, this one is fake) - -our $MULTI = [ - RG => {}, - Image => {}, - Sitemap => {}, - #Anime => { user => '', pass => '' }, - Maintenance => {}, - #IRC => { user => 'Multi'}, -]; - -our %VNDBopts = ( - CookieDomain => '.vndb.org', - root_url => 'http://vndb.org', - static_url => 'http://static.vndb.org', - tplopts => { - filename => 'main', - searchdir => '/www/vndb/data/tpl', - compiled => '/www/vndb/data/tplcompiled.pm', - namespace => 'VNDB::Util::Template::tpl', - pre_chomp => 1, - post_chomp => 1, - rm_newlines => 0, - deep_reload => 1, - }, - ranks => [ - [ [ qw| visitor loser user mod admin | ], [] ], - {map{$_,1}qw| hist |}, # 0 - visitor (not logged in) - {map{$_,1}qw| hist |}, # 1 - loser - {map{$_,1}qw| hist board edit |}, # 2 - user - {map{$_,1}qw| hist board boardmod edit mod lock del |}, # 3 - mod - {map{$_,1}qw| hist board boardmod edit mod lock del usermod |}, # 4 - admin - ], - postsperpage => 25, - imgpath => '/www/vndb/static/cv', # cover images - sfpath => '/www/vndb/static/sf', # full-size screenshots - stpath => '/www/vndb/static/st', # screenshot thumbnails - docpath => '/www/vndb/data/docs', -); -$VNDBopts{ranks}[0][1] = { (map{$_,1} map { keys %{$VNDBopts{ranks}[$_]} } 1..5) }; - - -# I wonder why I even made this hash, almost everything is still hardcoded anyway... -our $DTAGS = { - an => 'Announcements', # 0 - usage restricted to boardmods - db => 'VNDB Discussions', # 0 - v => 'Visual novels', # vid - p => 'Producers', # pid - u => 'Users', # uid -}; - - -our $PLAT = { - win => 'Windows', - lin => 'Linux', - mac => 'Mac OS', - dvd => 'DVD Player', - gba => 'Game Boy Advance', - msx => 'MSX', - nds => 'Nintendo DS', - nes => 'Famicom', - psp => 'Playstation Portable', - ps1 => 'Playstation 1', - ps2 => 'Playstation 2', - ps3 => 'Playstation 3', - drc => 'Dreamcast', - sfc => 'Super Nintendo', - wii => 'Nintendo Wii', - xb3 => 'Xbox 360', - oth => 'Other' -}; - - -# NOTE: don't forget to update dyna.js -our $MED = { - cd => 'CD', - dvd => 'DVD', - gdr => 'GD-ROM', - blr => 'Blu-Ray disk', - in => 'Internet download', - pa => 'Patch', - otc => 'Other (console)', -}; - - -our $PROT = { - co => 'Company', - in => 'Individual', - ng => 'Amateur group', -}; - - -our $RTYP = [ - 'Complete', - 'Partial', - 'Trial' -]; - - -# Yes, this is the category list. No, changing something here may -# not change it on the entire site - many things are still hardcoded -our $CAT = { - g => [ 'Gameplay', { - aa => 'NVL', # 0..1 - ab => 'ADV', # 0..1 - ac => "Act\x{200B}ion", # Ugliest. Hack. Ever. - rp => 'RPG', - st => 'Strategy', - si => 'Simulation', - }, 2 ], - p => [ 'Plot', { # 0..1 - li => 'Linear', - br => 'Branching', - }, 3 ], - e => [ 'Elements', { - ac => 'Action', - co => 'Comedy', - dr => 'Drama', - fa => 'Fantasy', - ho => 'Horror', - my => 'Mystery', - ro => 'Romance', - sc => 'School Life', - sf => 'SciFi', - sj => 'Shoujo Ai', - sn => 'Shounen Ai', - }, 1 ], - t => [ 'Time', { # 0..1 - fu => 'Future', - pa => 'Past', - pr => 'Present', - }, 4 ], - l => [ 'Place', { # 0..1 - ea => 'Earth', - fa => "Fant\x{200B}asy world", - sp => 'Space', - }, 5 ], - h => [ 'Protagonist', { # 0..1 - fa => 'Male', - fe => "Fem\x{200B}ale", - }, 6 ], - s => [ 'Sexual content', { - aa => 'Sexual content', - be => 'Bestiality', - in => 'Incest', - lo => 'Lolicon', - sh => 'Shotacon', - ya => 'Yaoi', - yu => 'Yuri', - ra => 'Rape', - }, 7 ], -}; - - -our $RSTAT = [ - 'Unknown', - 'Pending', - 'Obtained', # hardcoded - 'On loan', - 'Deleted', -]; -our $VSTAT = [ - 'Unknown', - 'Playing', - 'Finished', # hardcoded - 'Stalled', - 'Dropped', -]; - -our $WSTAT = [ - 'High', - 'Medium', - 'Low', - 'Blacklist', -]; - - -# OLD -our $LSTAT = [ - 'Wishlist', - 'Blacklist', - 'Playing', - 'Finished', - 'Stalled', - 'Dropped', - 'Other', # XXX: hardcoded at 6 -]; - - -our $VREL = [ - 'Sequel', - 'Prequel', # 1 - 'Same setting', - 'Alternative setting', - 'Alternative version', - 'Same characters', - 'Side story', - 'Parent story',# 7 - 'Summary', - 'Full story', # 9 - 'Other', -]; -# these reverse relations need a [relation]-1 -our $VRELW = {map{$_=>1}qw| 1 7 9 |}; - - -# users.flags -our $UFLAGS = { - list => 4, - nsfw => 8, -}; - - -our $VNLEN = [ - [ 'Unkown', '', '' ], - [ 'Very short', '< 2 hours', 'OMGWTFOTL, A Dream of Summer' ], - [ 'Short', '2 - 10 hours', 'Narcissu, Planetarian' ], - [ 'Medium', '10 - 30 hours', 'Kana: Little Sister' ], - [ 'Long', '30 - 50 hours', 'Tsukihime' ], - [ 'Very long', '> 50 hours', 'Clannad' ], -]; - - -our $VRAGES = { - -1 => 'Unknown', - 0 => 'All ages', - map { $_ => $_.'+' } 6..18 -}; - - -our $ANITYPE = [ - # VNDB AniDB - [ 'unknown', 'unknown', ], - [ 'TV', 'TV Series' ], - [ 'OVA', 'OVA' ], - [ 'Movie', 'Movie' ], - [ 'unknown', 'Other' ], - [ 'unknown', 'Web' ], - [ 'TV Special', 'TV Special' ], - [ 'unknown', 'Music Video' ], -]; -# AniDB defines: -# id="1", name="unknown -# id="2", name="TV Series -# id="3", name="OVA -# id="4", name="Movie -# id="5", name="Other -# id="6", name="Web -# id="7", name="TV Special -# id="8", name="Music Video - - - - - -our $LANG = { -# 'aa' => q|Afar|, -# 'ab' => q|Abkhazian|, -# 'ace' => q|Achinese|, -# 'ach' => q|Acoli|, -# 'ada' => q|Adangme|, -# 'ady' => q|Adyghe|, -# 'ae' => q|Avestan|, -# 'af' => q|Afrikaans|, -# 'afh' => q|Afrihili|, -# 'ak' => q|Akan|, -# 'akk' => q|Akkadian|, -# 'ale' => q|Aleut|, -# 'alg' => q|Algonquian languages|, -# 'am' => q|Amharic|, -# 'an' => q|Aragonese|, -# 'apa' => q|Apache languages|, -# 'ar' => q|Arabic|, -# 'arc' => q|Aramaic|, -# 'arn' => q|Araucanian|, -# 'arp' => q|Arapaho|, -# 'arw' => q|Arawak|, -# 'as' => q|Assamese|, -# 'ast' => q|Asturian|, -# 'ath' => q|Athapascan languages|, -# 'aus' => q|Australian languages|, -# 'av' => q|Avaric|, -# 'awa' => q|Awadhi|, -# 'ay' => q|Aymara|, -# 'az' => q|Azerbaijani|, -# 'ba' => q|Bashkir|, -# 'bad' => q|Banda|, -# 'bai' => q|Bamileke languages|, -# 'bal' => q|Baluchi|, -# 'ban' => q|Balinese|, -# 'bas' => q|Basa|, -# 'be' => q|Belarusian|, -# 'bej' => q|Beja|, -# 'bem' => q|Bemba|, -# 'bg' => q|Bulgarian|, -# 'bh' => q|Bihari|, -# 'bho' => q|Bhojpuri|, -# 'bi' => q|Bislama|, -# 'bik' => q|Bikol|, -# 'bin' => q|Bini|, -# 'bla' => q|Siksika|, -# 'bm' => q|Bambara|, -# 'bn' => q|Bengali|, -# 'bo' => q|Tibetan|, -# 'br' => q|Breton|, -# 'bra' => q|Braj|, -# 'bs' => q|Bosnian|, -# 'btk' => q|Batak (Indonesia)|, -# 'bua' => q|Buriat|, -# 'bug' => q|Buginese|, -# 'ca' => q|Catalan|, -# 'cad' => q|Caddo|, -# 'car' => q|Carib|, -# 'ce' => q|Chechen|, -# 'ceb' => q|Cebuano|, -# 'ch' => q|Chamorro|, -# 'chb' => q|Chibcha|, -# 'chg' => q|Chagatai|, -# 'chk' => q|Chuukese|, -# 'chm' => q|Mari|, -# 'chn' => q|Chinook Jargon|, -# 'cho' => q|Choctaw|, -# 'chp' => q|Chipewyan|, -# 'chr' => q|Cherokee|, -# 'chy' => q|Cheyenne|, -# 'cmc' => q|Chamic languages|, -# 'co' => q|Corsican|, -# 'cop' => q|Coptic|, -# 'cr' => q|Cree|, -# 'crh' => q|Crimean Turkish|, - 'cs' => q|Czech|, -# 'csb' => q|Kashubian|, -# 'cu' => q|Church Slavic|, -# 'cv' => q|Chuvash|, -# 'cy' => q|Welsh|, - 'da' => q|Danish|, -# 'dak' => q|Dakota|, -# 'dar' => q|Dargwa|, -# 'day' => q|Dayak|, - 'de' => q|German|, -# 'del' => q|Delaware|, -# 'dgr' => q|Dogrib|, -# 'din' => q|Dinka|, -# 'doi' => q|Dogri|, -# 'dua' => q|Duala|, -# 'dv' => q|Divehi|, -# 'dyu' => q|Dyula|, -# 'dz' => q|Dzongkha|, -# 'ee' => q|Ewe|, -# 'efi' => q|Efik|, -# 'eka' => q|Ekajuk|, -# 'el' => q|Modern Greek|, -# 'elx' => q|Elamite|, - 'en' => q|English|, -# 'eo' => q|Esperanto|, - 'es' => q|Spanish|, -# 'et' => q|Estonian|, -# 'eu' => q|Basque|, -# 'ewo' => q|Ewondo|, -# 'fa' => q|Persian|, -# 'fan' => q|Fang|, -# 'fat' => q|Fanti|, -# 'ff' => q|Fulah|, - 'fi' => q|Finnish|, -# 'fj' => q|Fijian|, -# 'fo' => q|Faroese|, -# 'fon' => q|Fon|, - 'fr' => q|French|, -# 'fur' => q|Friulian|, -# 'fy' => q|Frisian|, -# 'ga' => q|Irish|, -# 'gaa' => q|Ga|, -# 'gay' => q|Gayo|, -# 'gba' => q|Gbaya|, -# 'gd' => q|Scots Gaelic|, -# 'gez' => q|Geez|, -# 'gil' => q|Gilbertese|, -# 'gl' => q|Gallegan|, -# 'gn' => q|Guarani|, -# 'gon' => q|Gondi|, -# 'gor' => q|Gorontalo|, -# 'got' => q|Gothic|, -# 'grb' => q|Grebo|, -# 'grc' => q|Ancient Greek|, -# 'gu' => q|Gujarati|, -# 'gv' => q|Manx|, -# 'gwi' => q|Gwich'in|, -# 'ha' => q|Hausa|, -# 'hai' => q|Haida|, -# 'haw' => q|Hawaiian|, -# 'he' => q|Hebrew|, -# 'hi' => q|Hindi|, -# 'hil' => q|Hiligaynon|, -# 'him' => q|Himachali|, -# 'hit' => q|Hittite|, -# 'hmn' => q|Hmong|, -# 'ho' => q|Hiri Motu|, -# 'hr' => q|Croatian|, -# 'ht' => q|Haitian|, -# 'hu' => q|Hungarian|, -# 'hup' => q|Hupa|, -# 'hy' => q|Armenian|, -# 'hz' => q|Herero|, -# 'i-ami' => q|Ami|, -# 'i-bnn' => q|Bunun|, -# 'i-klingon' => q|Klingon|, -# 'i-mingo' => q|Mingo|, -# 'i-pwn' => q|Paiwan|, -# 'i-tao' => q|Tao|, -# 'i-tay' => q|Tayal|, -# 'i-tsu' => q|Tsou|, -# 'iba' => q|Iban|, -# 'id' => q|Indonesian|, -# 'ie' => q|Interlingue|, -# 'ig' => q|Igbo|, -# 'ii' => q|Sichuan Yi|, -# 'ijo' => q|Ijo|, -# 'ik' => q|Inupiaq|, -# 'ilo' => q|Iloko|, -# 'inh' => q|Ingush|, -# 'io' => q|Ido|, -# 'iro' => q|Iroquoian languages|, -# 'is' => q|Icelandic|, - 'it' => q|Italian|, -# 'iu' => q|Inuktitut|, - 'ja' => q|Japanese|, -# 'jpr' => q|Judeo-Persian|, -# 'jrb' => q|Judeo-Arabic|, -# 'jv' => q|Javanese|, -# 'ka' => q|Georgian|, -# 'kaa' => q|Kara-Kalpak|, -# 'kab' => q|Kabyle|, -# 'kac' => q|Kachin|, -# 'kam' => q|Kamba|, -# 'kar' => q|Karen|, -# 'kaw' => q|Kawi|, -# 'kbd' => q|Kabardian|, -# 'kg' => q|Kongo|, -# 'kha' => q|Khasi|, -# 'kho' => q|Khotanese|, -# 'ki' => q|Kikuyu|, -# 'kj' => q|Kuanyama|, -# 'kk' => q|Kazakh|, -# 'kl' => q|Kalaallisut|, -# 'km' => q|Khmer|, -# 'kmb' => q|Kimbundu|, -# 'kn' => q|Kannada|, - 'ko' => q|Korean|, -# 'kok' => q|Konkani|, -# 'kos' => q|Kosraean|, -# 'kpe' => q|Kpelle|, -# 'kr' => q|Kanuri|, -# 'krc' => q|Karachay-Balkar|, -# 'kro' => q|Kru|, -# 'kru' => q|Kurukh|, -# 'ks' => q|Kashmiri|, -# 'ku' => q|Kurdish|, -# 'kum' => q|Kumyk|, -# 'kut' => q|Kutenai|, -# 'kv' => q|Komi|, -# 'kw' => q|Cornish|, -# 'ky' => q|Kirghiz|, -# 'la' => q|Latin|, -# 'lad' => q|Ladino|, -# 'lah' => q|Lahnda|, -# 'lam' => q|Lamba|, -# '#lb' => q|Letzeburgesch|, -# 'lez' => q|Lezghian|, -# 'lg' => q|Ganda|, -# 'li' => q|Limburgish|, -# 'ln' => q|Lingala|, -# 'lo' => q|Lao|, -# 'lol' => q|Mongo|, -# 'loz' => q|Lozi|, -# 'lt' => q|Lithuanian|, -# 'lu' => q|Luba-Katanga|, -# 'lua' => q|Luba-Lulua|, -# 'lui' => q|Luiseno|, -# 'lun' => q|Lunda|, -# 'luo' => q|Luo (Kenya and Tanzania)|, -# 'lus' => q|Lushai|, -# 'lv' => q|Latvian|, -# 'mad' => q|Madurese|, -# 'mag' => q|Magahi|, -# 'mai' => q|Maithili|, -# 'mak' => q|Makasar|, -# 'man' => q|Mandingo|, -# 'mas' => q|Masai|, -# 'mdf' => q|Moksha|, -# 'mdr' => q|Mandar|, -# 'men' => q|Mende|, -# 'mg' => q|Malagasy|, -# 'mh' => q|Marshall|, -# 'mi' => q|Maori|, -# 'mic' => q|Micmac|, -# 'min' => q|Minangkabau|, -# 'mk' => q|Macedonian|, -# 'ml' => q|Malayalam|, -# 'mn' => q|Mongolian|, -# 'mnc' => q|Manchu|, -# 'mni' => q|Manipuri|, -# 'mno' => q|Manobo languages|, -# 'mo' => q|Moldavian|, -# 'moh' => q|Mohawk|, -# 'mos' => q|Mossi|, -# 'mr' => q|Marathi|, -# 'ms' => q|Malay|, -# 'mt' => q|Maltese|, -# 'mul' => q|Multiple languages|, -# 'mun' => q|Munda languages|, -# 'mus' => q|Creek|, -# 'mwr' => q|Marwari|, -# 'my' => q|Burmese|, -# 'myn' => q|Mayan languages|, -# 'myv' => q|Erzya|, -# 'na' => q|Nauru|, -# 'nah' => q|Nahuatl|, -# 'nap' => q|Neapolitan|, -# 'nb' => q|Norwegian Bokmal|, -# 'nd' => q|North Ndebele|, -# 'ne' => q|Nepali|, -# 'new' => q|Newari|, -# 'ng' => q|Ndonga|, -# 'nia' => q|Nias|, -# 'niu' => q|Niuean|, - 'nl' => q|Dutch|, - 'no' => q|Norwegian|, -# 'nog' => q|Nogai|, -# 'non' => q|Old Norse|, -# 'nr' => q|South Ndebele|, -# 'nso' => q|Northern Sotho|, -# 'nub' => q|Nubian languages|, -# 'nv' => q|Navajo|, -# 'ny' => q|Chichewa|, -# 'nym' => q|Nyamwezi|, -# 'nyn' => q|Nyankole|, -# 'nyo' => q|Nyoro|, -# 'nzi' => q|Nzima|, -# 'oj' => q|Ojibwa|, -# 'om' => q|Oromo|, -# 'or' => q|Oriya|, -# 'os' => q|Ossetian; Ossetic|, -# 'osa' => q|Osage|, -# 'oto' => q|Otomian languages|, -# 'pa' => q|Panjabi|, -# 'pag' => q|Pangasinan|, -# 'pal' => q|Pahlavi|, -# 'pam' => q|Pampanga|, -# 'pap' => q|Papiamento|, -# 'pau' => q|Palauan|, -# 'phn' => q|Phoenician|, -# 'pi' => q|Pali|, - 'pl' => q|Polish|, -# 'pon' => q|Pohnpeian|, -# 'pra' => q|Prakrit languages|, -# 'ps' => q|Pushto|, - 'pt' => q|Portuguese|, -# 'pt-br' => q|Brazilian Portuguese|, -# 'pt-pt' => q|Portugal Portuguese|, -# 'qu' => q|Quechua|, -# 'raj' => q|Rajasthani|, -# 'rap' => q|Rapanui|, -# 'rar' => q|Rarotongan|, -# 'rm' => q|Raeto-Romance|, -# 'rn' => q|Rundi|, -# 'ro' => q|Romanian|, -# 'rom' => q|Romany|, - 'ru' => q|Russian|, -# 'rw' => q|Kinyarwanda|, -# 'sa' => q|Sanskrit|, -# 'sad' => q|Sandawe|, -# 'sah' => q|Yakut|, -# 'sal' => q|Salishan languages|, -# 'sam' => q|Samaritan Aramaic|, -# 'sas' => q|Sasak|, -# 'sat' => q|Santali|, -# 'sc' => q|Sardinian|, -# 'sco' => q|Scots|, -# 'sd' => q|Sindhi|, -# 'se' => q|Northern Sami|, -# 'sel' => q|Selkup|, -# 'sg' => q|Sango|, -# 'shn' => q|Shan|, -# 'si' => q|Sinhalese|, -# 'sid' => q|Sidamo|, -# 'sio' => q|Siouan languages|, -# 'sk' => q|Slovak|, -# 'sl' => q|Slovenian|, -# 'sm' => q|Samoan|, -# 'sma' => q|Southern Sami|, -# 'smj' => q|Lule Sami|, -# 'smn' => q|Inari Sami|, -# 'sms' => q|Skolt Sami|, -# 'sn' => q|Shona|, -# 'snk' => q|Soninke|, -# 'so' => q|Somali|, -# 'sog' => q|Sogdian|, -# 'son' => q|Songhai|, -# 'sq' => q|Albanian|, -# 'sr' => q|Serbian|, -# 'srr' => q|Serer|, -# 'ss' => q|Swati|, -# 'st' => q|Southern Sotho|, -# 'su' => q|Sundanese|, -# 'suk' => q|Sukuma|, -# 'sus' => q|Susu|, -# 'sux' => q|Sumerian|, - 'sv' => q|Swedish|, -# 'sw' => q|Swahili|, -# 'syr' => q|Syriac|, -# 'ta' => q|Tamil|, -# 'te' => q|Telugu|, -# 'tem' => q|Timne|, -# 'ter' => q|Tereno|, -# 'tet' => q|Tetum|, -# 'tg' => q|Tajik|, -# 'th' => q|Thai|, -# 'ti' => q|Tigrinya|, -# 'tig' => q|Tigre|, -# 'tiv' => q|Tiv|, -# 'tk' => q|Turkmen|, -# 'tkl' => q|Tokelau|, -# 'tl' => q|Tagalog|, -# 'tli' => q|Tlingit|, -# 'tmh' => q|Tamashek|, -# 'tn' => q|Tswana|, -# 'to' => q|Tonga (Tonga Islands)|, -# 'tog' => q|Tonga (Nyasa)|, -# 'tpi' => q|Tok Pisin|, - 'tr' => q|Turkish|, -# 'ts' => q|Tsonga|, -# 'tsi' => q|Tsimshian|, -# 'tt' => q|Tatar|, -# 'tum' => q|Tumbuka|, -# 'tup' => q|Tupi languages|, -# 'tvl' => q|Tuvalu|, -# 'tw' => q|Twi|, -# 'ty' => q|Tahitian|, -# 'tyv' => q|Tuvinian|, -# 'udm' => q|Udmurt|, -# 'ug' => q|Uighur|, -# 'uga' => q|Ugaritic|, -# 'uk' => q|Ukrainian|, -# 'umb' => q|Umbundu|, -# 'ur' => q|Urdu|, -# 'uz' => q|Uzbek|, -# 'vai' => q|Vai|, -# 've' => q|Venda|, -# 'vi' => q|Vietnamese|, -# 'vo' => q|Volapuk|, -# 'vot' => q|Votic|, -# 'wa' => q|Walloon|, -# 'wak' => q|Wakashan languages|, -# 'wal' => q|Walamo|, -# 'war' => q|Waray|, -# 'was' => q|Washo|, -# 'wen' => q|Sorbian languages|, -# 'wo' => q|Wolof|, -# 'xal' => q|Kalmyk|, -# 'xh' => q|Xhosa|, -# 'yao' => q|Yao|, -# 'yap' => q|Yapese|, -# 'yi' => q|Yiddish|, -# 'yo' => q|Yoruba|, -# 'ypk' => q|Yupik languages|, -# 'za' => q|Zhuang|, -# 'zap' => q|Zapotec|, -# 'zen' => q|Zenaga|, - 'zh' => q|Chinese|, -# 'znd' => q|Zande|, -# 'zu' => q|Zulu|, -# 'zun' => q|Zuni|, -}; - - -# override config vars -require '/www/vndb/data/config.pl' if -e '/www/vndb/data/config.pl'; - - -1; - diff --git a/static/files/blank.css b/static/files/blank.css deleted file mode 100644 index e69de29b..00000000 --- a/static/files/blank.css +++ /dev/null diff --git a/static/files/def.js b/static/files/def.js deleted file mode 100644 index 4928cb84..00000000 --- a/static/files/def.js +++ /dev/null @@ -1,479 +0,0 @@ - - -/* G L O B A L S T U F F */ - -function x(y){return document.getElementById(y)} -function cl(o,f){if(x(o))x(o).onclick=f} -function DOMLoad(y){var d=0;var f=function(){if(d++)return;y()}; -if(document.addEventListener)document.addEventListener("DOMCont" -+"entLoaded",f,false);document.write("<script id=_ie defer src=" -+"javascript:void(0)><\/script>");document.getElementById('_ie') -.onreadystatechange=function(){if(this.readyState=="complete")f() -};if(/WebKit/i.test(navigator.userAgent))var t=setInterval( -function(){if(/loaded|complete/.test(document.readyState)){ -clearInterval(t);f()}},10);window.onload=f;} - - - - -/* F O R M S U B S */ - -var formsubs = []; -function formhid() { - var i; - var j; - var l = document.forms[1].getElementsByTagName('a'); - for(i=0; i<l.length; i++) - if(l[i].className.indexOf('s_') != -1) { - formsubs[ l[i].className.substr(l[i].className.indexOf('s_')+2) ] = 0; - l[i].onclick = function() { - formtoggle(this.className.substr(this.className.indexOf('s_')+2)); - return false; - }; - } - - if(x('_hid') && x('_hid').value.length > 1) { - l = x('_hid').value.split(/,/); - for(i in formsubs) { - var inz=0; - for(j=0; j<l.length; j++) - if(l[j] == i) - inz = 1; - if(!inz) - formsubs[i] = !formsubs[i]; - } - } - if(x('screenshots') && !formsubs['scr']) - scrLoad(); -} -function formtoggle(n) { - formsubs[n] = !formsubs[n]; - if(x('screenshots') && !formsubs['scr'] && !x('scrTbl')) - scrLoad(); - - var i; - var l = document.forms[1].getElementsByTagName('a'); - for(i=0; i<l.length; i++) - if(l[i].className.indexOf('s_'+n) != -1) - l[i].innerHTML = (formsubs[n] ? '▸' : '▾') + l[i].innerHTML.substr(1); - - l = document.forms[1].getElementsByTagName('li'); - for(i=0; i<l.length; i++) - if(l[i].className.indexOf('sf_'+n) != -1) { - if(formsubs[n]) - l[i].className += ' formhid'; - else - l[i].className = l[i].className.replace(/formhid/g, ''); - } - - if(x('_hid')) { - l = []; - for(i in formsubs) - if(!formsubs[i]) - l[l.length] = i; - x('_hid').value = l.toString(); - } -} - - - - -/* D R O P D O W N M E N U S */ - -var ddx;var ddy;var dds=null; -function dropDown(e) { - e = e || window.event; - var tg = e.target || e.srcElement; - while(tg && (tg.nodeType == 3 || tg.nodeName.toLowerCase() != 'a')) - tg = tg.parentNode; - - if(tg && tg.rel) - tg.rel = tg.rel.replace(/ *nofollow */,""); - if(!dds && (!tg || !tg.rel || tg.className.indexOf('dropdown') < 0)) - return; - - if(!dds) { - var obj=tg; - ddx = ddy = 0; - do { - ddx += obj.offsetLeft; - ddy += obj.offsetTop; - } while(obj = obj.offsetParent); - if(tg.className.indexOf('above') >= 0) { - ddx += 30; - ddy -= x(tg.rel).offsetHeight - 20; - } - else - ddy += 16; - obj = x(tg.rel); - obj.style.left = ddx+'px'; - obj.style.top = ddy+'px'; - dds = tg; - } - - if(dds) { - var mouseX = e.pageX || (e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft); - var mouseY = e.pageY || (e.clientY + document.body.scrollTop + document.documentElement.scrollTop); - var obj = x(dds.rel); - if((mouseX < ddx-25 || mouseX > ddx+obj.offsetWidth+5 || mouseY < ddy-20 || mouseY > ddy + obj.offsetHeight) - || (tg && tg.className.indexOf('dropdown') >= 0 && tg != dds)) { - obj.style.left = '-500px'; - dds = null; - } - } -} - - - - -/* A D V A N C E D S E A R C H */ - -var ad_cats = {}; -var ad_lang = {}; -var ad_plat = {}; - -function adsearch() { - x('vsearch').onsubmit = ad_dosearch; - x('vsearch_sub').onclick = ad_dosearch; - x('q').onkeyup = ad_update; - - x('adsearchclick').onclick = function() { - if(x('adsearch').style.display == 'none') { - x('adsearch').style.display = 'block'; - x('adsearchclick').innerHTML = '▾ advanced options'; - } else { - x('adsearch').style.display = 'none'; - x('adsearchclick').innerHTML = '▸ advanced options'; - } - }; - - var l = x('cat').getElementsByTagName('li'); - for(i=0;i<l.length;i++) - if(l[i].id.indexOf('cat_') != -1) { - ad_cats[ l[i].id.substr(l[i].id.indexOf('cat_')+4, 3) ] = l[i].innerHTML.substring(0, l[i].innerHTML.indexOf('(')-1).toLowerCase(); - l[i].onclick = function () { - try { document.selection.empty() } catch(e) { try { window.getSelection().collapse(this, 0) } catch(e) {} }; - ad_update(1, this.innerHTML.substring(0, this.innerHTML.indexOf('(')-1)); - }; - } - - l = x('lfilter').getElementsByTagName('input'); - for(i=0;i<l.length;i++) { - ad_lang[ l[i].name.substring(5) ] = l[i].value.toLowerCase(); - l[i].onclick = function() { ad_update(0, this.value) }; - } - - l = x('pfilter').getElementsByTagName('input'); - for(i=0;i<l.length;i++) { - ad_plat[ l[i].name.substring(5) ] = l[i].value.toLowerCase(); - l[i].onclick = function() { ad_update(0, this.value) }; - } - - ad_update(); -} - -function ad_update(add, term) { - var q = x('q').value; - var i; - - if(add == 0 || add === 1) { - var qn = q; - if(!add) - eval('qn = qn.replace(/'+term+'/gi, "")'); - else { - eval('qn = qn.replace(/(^|[^-])'+term+'/gi, "$1-'+term+'")'); - if(qn == q) - eval('qn = qn.replace(/-'+term+'/gi, "")'); - } - if(qn == q) - q += ' '+term; - else - q = qn; - - q = q.replace(/^ +/, ""); - q = q.replace(/ +$/, ""); - q = q.replace(/ +/g, " "); - - x('q').value = q; - } - - q = q.toLowerCase(); - for (i in ad_lang) - x('lang_'+i).checked = q.indexOf(ad_lang[i]) >= 0 || q.indexOf('l:'+i) >= 0 ? true : false; - for (i in ad_plat) - x('plat_'+i).checked = q.indexOf(ad_plat[i]) >= 0 || q.indexOf('p:'+i) >= 0 ? true : false; - for (i in ad_cats) - x('cat_'+i).className = q.indexOf('-'+ad_cats[i]) >= 0 || q.indexOf('-c:'+i) >= 0 ? 'exc' : q.indexOf(ad_cats[i]) >= 0 || q.indexOf('c:'+i) >= 0 ? 'inc' : ''; -} - -function ad_dosearch() { - location.href = '?q='+x('q').value; - return false; -} - - - -/* S C R E E N S H O T S */ - -var scrNsfwEnabled = null; -function scrNsfwHid() { - var l=x('screenshots').getElementsByTagName('a'); - var i; - if(scrNsfwEnabled == null) - scrNsfwEnabled = 0; - else { - for(i=0;i<l.length;i++) - if(l[i].className.indexOf('scr_nsfw')>=0) - l[i].style.display = scrNsfwEnabled ? 'block' : 'none'; - scrNsfwEnabled = scrNsfwEnabled ? 0 : 1; - } - - var t=0;var n=0; - for(i=0;i<l.length;i++) { - if(l[i].className.indexOf('shot')<0) - continue; - t++; - if(l[i].className.indexOf('scr_nsfw')>=0) - n++; - if(l[i].style.display == 'none') - scrNsfwEnabled = 1; - } - x('scrNsfwHid').innerHTML = 'Showing '+(t-(scrNsfwEnabled?n:0))+' out of '+t+' items. ' - +(scrNsfwEnabled ? '<a href="javascript:scrNsfwHid()">Show</a> / hide' : 'Show / <a href="javascript:scrNsfwHid()">hide</a>') - +' nsfw.'; -} -function scrView(what) { - what = what && what.rel ? what : this; - var u=what.href; - var r=what.rel; - d = x('scrView'); - - // fix prev/next links (if any) - var ol=x('screenshots').getElementsByTagName('a'); - if(ol.length > 0) { - var l=[]; - for(i=0;i<ol.length;i++) - if(ol[i].className.indexOf('shot')>=0 && (!scrNsfwEnabled || ol[i].className.indexOf('scr_nsfw')<0)) - l[l.length] = ol[i]; - - ol=0; - for(i=0;i<l.length;i++) - if(l[i].href == u) { - ol=1; - x('scrnext').style.visibility = l[i+1] ? 'visible' : 'hidden'; - x('scrnext').href = l[i+1] ? l[i+1].href : '#'; - x('scrnext').rel = l[i+1] ? l[i+1].rel : ''; - x('scrprev').style.visibility = l[i-1] ? 'visible' : 'hidden'; - x('scrprev').href = l[i-1] ? l[i-1].href : '#'; - x('scrprev').rel = l[i-1] ? l[i-1].rel : ''; - } - } else - ol=0; - if(!ol) - x('scrnext').style.visibility = x('scrprev').style.visibility = 'hidden'; - - // calculate dimensions - var w = Math.floor(r.split('x')[0]); - var h = Math.floor(r.split('x')[1]); - var ww = typeof(window.innerWidth) == 'number' ? window.innerWidth : document.documentElement.clientWidth; - var wh = typeof(window.innerHeight) == 'number' ? window.innerHeight : document.documentElement.clientHeight; - var st = typeof(window.pageYOffset) == 'number' ? window.pageYOffset : document.body && document.body.scrollTop ? document.body.scrollTop : document.documentElement.scrollTop; - if(w+100 > ww || h+70 > wh) { - x('scrfull').href = u; - x('scrfull').innerHTML = w+'x'+h; - x('scrfull').style.visibility = 'visible'; - if(w/h > ww/wh) { // width++ - h *= (ww-100)/w; - w = ww-100; - } else { // height++ - w *= (wh-70)/h; - h = wh-70; - } - } else - x('scrfull').style.visibility = 'hidden'; - var dw = w; - var dh = h+20; - dw = dw < 200 ? 200 : dw; - - // update document - d.style.display = 'block'; - x('scrimg').innerHTML = '<img src="'+u+'" onclick="scrClose()" onload="document.getElementById(\'scrimgload\').style.top=\'-400px\'" style="width: '+w+'px; height: '+h+'px" />'; - d.style.width = dw+'px'; - d.style.height = dh+'px'; - d.style.left = ((ww - dw) / 2 - 10)+'px'; - d.style.top = ((wh - dh) / 2 + st - 20)+'px'; - x('scrimgload').style.left = ((ww - 100) / 2 - 10)+'px'; - x('scrimgload').style.top = ((wh - 20) / 2 + st)+'px'; - return false; -} -function scrClose() { - x('scrView').style.display = 'none'; - x('scrView').style.top = '-5000px'; - x('scrimg').innerHTML = ''; - return false; -} - - - - -/* O N L O A D */ - -DOMLoad(function() { - var i; - - // search box - i = x('searchfield'); - i.onfocus = function () { - if(this.value == 'search') { - this.value = ''; - this.style.color = '#000'; } }; - i.onblur = function () { - if(this.value.length < 1) { - this.value = 'search'; - this.style.color = '#999';} }; - - // advanced search - if(x('adsearch')) - adsearch(); - - // userdel - cl('userdel', function() { return confirm("Completely remove this account from the site?") }); - - // vote warnings - cl('dovote_10', function() { return confirm( - "You are about to give this visual novel a 10 out of 10. This is a rather extreme rating, " - +"meaning this is one of the best visual novels you've ever played and it's unlikely " - +"that any other game could ever be better than this one.\n" - +"It is generally a bad idea to have more than three games in your vote list with this rating, choose carefully!") }); - cl('dovote_1', function() { return confirm( - "You are about to give this visual novel a 1 out of 10. This is a rather extreme rating, " - +"meaning this game has absolutely nothing to offer, and that it's the worst game you have ever played.\n" - +"Are you really sure this visual novel matches that description?") }); - - // NSFW - cl('nsfw', function () { - this.src = this.className; - this.id = ''; - }); - - // rlists - i = x('rli'); - if(i) { - var l=i.getElementsByTagName('td'); - for(i=0;i<l.length;i++) - if(l[i].className.indexOf('relhid')>=0) - l[i].onclick = function() { - var id=this.id.substr(2); - var j=0;var o; - var op=x('rr'+id+'-1').style.display == 'none' ? 1 : 0; - while((o=x('rr'+id+'-'+(++j))) != null) - o.style.display = op ? '' : 'none'; - x('rhd'+id).innerHTML = op ? '▾' : '▸'; - }; - var l=x('rli').getElementsByTagName('tr'); - for(i=0;i<l.length;i++) - if(l[i].className.indexOf('relhid')>=0) - l[i].style.display = 'none'; - var allhid=1; - cl('relhidpar', function() { - allhid=!allhid; - l=x('rli').getElementsByTagName('tr'); - for(i=0;i<l.length;i++) - if(l[i].className.indexOf('relhid')>=0) - l[i].style.display = allhid ? 'none' : ''; - l=x('rli').getElementsByTagName('b'); - for(i=0;i<l.length;i++) - if(l[i].id.substr(0,3) == 'rhd') - l[i].innerHTML = !allhid ? '▾' : '▸'; - x('relhidparb').innerHTML = !allhid ? '▾' : '▸'; - }); - } - - // mass-change rlist or wlist status - if(x('vnlistchange')) { - x('vnlistchange').onchange = function() { - var val = this.options[this.selectedIndex].value; - if(val == 'n') - return; - var l = (x('rli')||x('twl')).getElementsByTagName('input'); - var y; var ch=0; - for(y=0;y<l.length;y++) - if(l[y].type == 'checkbox' && l[y].checked) - ch++; - if(!ch) - return alert('Nothing selected...'); - if(val == 'd' && !confirm('Are you sure you want to remove the selected items from your list?')) - return; - document.forms[1].submit(); - } - } - - // screenshots - if(x('scrNsfwHid')) - scrNsfwHid(); - if(x('screenshots')) { - l=x('screenshots').getElementsByTagName('a'); - for(i=0;i<l.length;i++) - l[i].onclick=scrView; - var d = document.createElement('div'); - d.id = 'scrView'; - d.innerHTML = '<b id="scrimg"></b><br />' - +'<a href="#" id="scrfull"> </a>' - +'<a href="#" onclick="return scrClose()" id="scrclose">close</a>' - +'<a href="#" onclick="return scrView(this)" id="scrprev"><- previous</a>' - +'<a href="#" onclick="return scrView(this)" id="scrnext">next -></a>'; - document.body.appendChild(d); - d = document.createElement('b'); - d.id = 'scrimgload'; - d.innerHTML = 'Loading...'; - document.body.appendChild(d); - } - - // spam protection on all forms - if(document.forms.length > 1) - for(i=1; i<document.forms.length; i++) - document.forms[i].action = document.forms[i].action.replace(/\/nospam\?/,''); - - // dropdown menus - var z = document.getElementsByTagName('a'); - for(i=0;i<z.length;i++) - if(z[i].rel && z[i].className.indexOf('dropdown') >= 0) { - document.onmousemove = dropDown; - break; - } - - // form-stuff - if(document.forms.length > 1) { - formhid(); - // edit summary warning - if(x('comm')) - document.forms[1].onsubmit = function () { - var z = x('comm'); - if(z.value.length > 5) return true; - var y = prompt("Edit summary field is empty,\nPlease explain your edits and cite all sources!", z.value); - if(y == null) return false; - z.value = y; - return true; - }; - } - - // init dyna - if(window.dInit) - dInit(); - - // zebra-striped tables (client side!? yes... client side :3) - var sub = document.getElementsByTagName('tr'); - for(i=1; i<sub.length; i+=2) - if(!sub[i].style.backgroundColor) - sub[i].style.backgroundColor = '#f5f5f5'; -}); - - - - -// small hack because the mozilla -moz-inline-stack display hack sucks -// (so we're counter-hacking a CSS hack using JS... right) -if(navigator.userAgent.indexOf('Gecko') >= 0 && navigator.userAgent.indexOf('like Gecko') < 0 && navigator.userAgent.indexOf('3.0') < 0) - document.write('<style type="text/css">.icons.lang { width: 15px; height: 13px; }</style>'); - - diff --git a/static/files/dyna.js b/static/files/dyna.js deleted file mode 100644 index fd0411d2..00000000 --- a/static/files/dyna.js +++ /dev/null @@ -1,815 +0,0 @@ -var med = { - cd: 'CD', - dvd: 'DVD', - gdr: 'GD-ROM', - blr: 'Blu-Ray disk', - 'in':'Internet download', - pa: 'Patch', - otc: 'Other (console)' -}; -var vrel = [ - 'Sequel', - 'Prequel', - 'Same setting', - 'Alternative setting', - 'Alternative version', - 'Same characters', - 'Side story', - 'Parent story', - 'Summary', - 'Full story', - 'Other' -]; - -var md;var pd;var rl;var vn;var ct; - -function dInit() { - md = x('md_select'); - if(md) { - md.onclick = mdChangeSel; - mdLoad(); - md.selectedIndex = 0; - mdChangeSel(); - } - - pd = x('pd_select'); - if(pd) { - pd.onclick = pdChangeSel; - pdLoad(); - pd.selectedIndex = 0; - pdChangeSel(); - } - - rl = x('rl_select'); - if(rl) { - rl.onclick = rlChangeSel; - rlLoad(); - rl.selectedIndex = 0; - rlChangeSel(); - } - - vn = x('vn_select'); - if(vn) { - vn.onclick = vnChangeSel; - vnLoad(); - vn.selectedIndex = 0; - vnChangeSel(); - } - - ct = x('categories'); - if(ct) - catLoad(); - -/* scrLoad() is called by the form sub functions in def.js - if(x('scrfrm')) - scrLoad();*/ -} - -function qq(v) { - return v.replace(/&/g,"&").replace(/</,"<").replace(/>/,">").replace(/'/g,/*'*/ "\\'").replace(/"/g,/*"*/'"'); -} - -// small AJAX wapper -var hr = false; -function ajax(url, func) { - if(hr) - hr.abort(); - hr = (window.ActiveXObject) ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest(); - if(hr == null) { - alert("Your browse does not support the functionality this website requires."); - return; - } - hr.onreadystatechange = func; - hr.open('GET', url, true); - hr.send(null); -} - - - - - /************************\ - * M E D I A * - \************************/ - - -function mdChangeSel() { - var sel = md.options[md.selectedIndex || 0]; - var o = x('md_conts'); - var i; - if(sel.value == '0_new') { - var l = ''; var q = '<option value="0">Qty</option>'; - for(i in med) - l += '<option value="'+i+'">'+med[i]+'</option>'; - for(i=1;i<10;i++) - q += '<option value="'+i+'">'+i+'</option>'; - o.innerHTML = '<select id="md_Q" name="md_Q" style="width: 50px;">'+q+'</select>' - + '<select id="md_S" name="md_S" style="width: 150px;">'+l+'</select>' - + '<br style="clear: both" />' - + '<button type="button" onclick="mdAddRem()">add/remove</button>' - + '<br />Qty is only required for CD & DVD'; - } else { - o.innerHTML = 'Selected "' + sel.text + '"<br />' - + '<button type="button" onclick="mdAddRem(\'' + sel.value + '\')">remove</button>'; - } -} - -function mdAddRem(id) { - var i; - var d = 0; - var o = id ? null : x('md_S').options[x('md_S').selectedIndex]; - var qty = id ? null : x('md_Q').options[x('md_Q').selectedIndex].value; - var v = id ? id : (o.value != 'cd' && o.value != 'dvd' && o.value != 'gdr' && o.value != 'blr' ? o.value : (o.value + '_' + qty)); - for(i=0;i<md.options.length;i++) - if(md.options[i].value == v) { - md.options[i] = null; - d = 1; - } - if(!d && !id) { - if(v.indexOf('_') >= 0 && qty == 0) { - alert('Please specify the quantity'); - return; - } - md.options[md.options.length] = new Option(mdString(qty, o.value), v); - } - else if(id) { - md.options[0].selected = true; - mdChangeSel(); - } - mdSerialize(); -} - -function mdSerialize() { - var dest = x('media'); - var str = ''; - var i; - for(i=0;i<md.options.length;i++) - md.options[i].value != '0_new' && (str += (str.length>0 ? ',' : '') + md.options[i].value); - dest.value = str; -} - -function mdLoad() { - var me = x('media').value.split(','); - var i, j; - for(i=0;i<me.length;i++) { - var m = me[i].split('_'); - if(med[m[0]]) - md.options[md.options.length] = new Option(mdString(m[1], m[0]), me[i]); - } -} - -function mdString(qty, medium) { - if(medium != 'cd' && medium != 'dvd' && medium != 'gdr' && medium != 'blr') - return med[medium]; - else - return qty + ' ' + med[medium] + (qty > 1 ? 's' : ''); -} - - - - - - - /************************\ - * P R O D U C E R S * - \************************/ - - -function pdChangeSel() { - var sel = pd.options[pd.selectedIndex || 0]; - var o = x('pd_conts'); - var i; - if(sel.value == '0_new') { - o.innerHTML = '<input type="text" name="pd_S" id="pd_S" onkeyup="pdDoSearch(0)" onkeydown="return pdEnter(event)" style="width: 150px;" />' - + '<button type="button" onclick="pdDoSearch(1)" style="width: 55px;">Search!</button><br style="clear: both" />' - + '<span id="pd_R" style="display: block; width: 220px; height: 70px; overflow: auto"></span>' - + '<a href="/p/add" target="_blank">Add new producer</a>'; - pdDoSearch(''); - } else { - o.innerHTML = 'Selected "' + sel.text + '"<br />' - + '<button type="button" onclick="pdAddRem(\'' + qq(sel.value) + '\')">remove</button>'; - } -} - -function pdEnter(ev) { - var c = document.layers ? ev.which : document.all ? event.keyCode : ev.keyCode; - if(c == 13) { - pdDoSearch(0); - return false; - } - return true; -} - -function pdDoSearch(f) { - var v = x('pd_S').value; - var d = x('pd_R'); - if(v.length < 1) - d.innerHTML = 'Hint: type pX if you know the producer id.'; - else { - if(f) - d.innerHTML = '...searching...'; - ajax('/xml/producers.xml?q='+encodeURIComponent(v)+'&r='+(Math.floor(Math.random()*999)+1), function () { - if(!hr || hr.readyState != 4 || !hr.responseText) - return; - if(hr.status != 200) - return alert('Whoops, error! :('); - var items = hr.responseXML.getElementsByTagName('item'); - if(!items || items.length < 1) { - d.innerHTML = 'No results'; - return false; - } - var res = ''; - var i,j; - for(i=0; i<items.length; i++) { - var id = items[i].getElementsByTagName('id')[0].firstChild.nodeValue; - var name = items[i].getElementsByTagName('name')[0].firstChild.nodeValue; - var cid = id + ',' + name; - var s = ''; - for(j=0; j<pd.options.length; j++) - if(pd.options[j].value == cid) - s = ' checked="checked"'; - res += '<input type="checkbox" id="pd_I'+id+'"'+s+' onclick="pdAddRem(\''+qq(cid)+'\', \''+qq(name)+'\')" />' - + '<label style="width: auto" for="pd_I'+id+'">'+name+'</label><br style="clear: left" />'; - } - d.innerHTML = res; - }); - } -} - -function pdAddRem(id, name) { - var i; - var d = 0; - for(i=0;i<pd.options.length;i++) - if(pd.options[i].value == id) { - pd.options[i] = null; - d = 1; - } - if(!d && name) - pd.options[pd.options.length] = new Option(name, id); - else if(!name) { - pd.options[0].selected = true; - pdChangeSel(); - } - pdSerialize(); -} - -// id,name|||id,name -function pdSerialize() { - var dest = x('producers'); - var str = ''; - var i; - for(i=0;i<pd.options.length;i++) - pd.options[i].value != '0_new' && (str += (str.length>0 ? '|||' : '') + pd.options[i].value); - dest.value = str; -} - -function pdLoad() { - var pds = x('producers').value.split('|||'); - if(!pds[0]) - return; - var i; - for(i=0;i<pds.length;i++) - pd.options[pd.options.length] = new Option(pds[i].split(',',2)[1], pds[i]); -} - - - - - - - - - /************************\ - * R E L A T I O N S * - \************************/ - - -var rlsel = ''; var rlname = ''; -function rlChangeSel() { - var sel = rl.options[rl.selectedIndex || 0]; - var o = x('rl_conts'); - var i; - rlsel = ''; - var ops=''; - for(i=0;i<vrel.length;i++) - ops += '<option value="'+i+'">'+vrel[i]+'</option>'; - if(sel.value == '0_new') { - o.innerHTML = '<input type="text" name="rl_S" id="rl_S" onkeyup="rlDoSearch(0)" onkeydown="return rlEnter(event)" style="width: 150px;" />' - + '<button type="button" onclick="rlDoSearch(1)" style="width: 60px;">Search!</button><br style="clear: both" />' - + '<span id="rl_R" style="display: block; width: 250px; height: 70px; overflow: auto"></span>' - + '<select id="rl_L" name="rl_L" onchange="rlAddRem(0)"><option value="-1">...is a [..] of this visual novel</option>'+ops+'</select>'; - rlDoSearch(''); - } else { - o.innerHTML = sel.value.split(',', 3)[2] + '<br />' - + '<select id="rl_L" name="rl_L" onchange="rlAddRem(\''+qq(sel.value)+'\')">' - + '<option value="-1"> - change - </option>'+ops+'<option value="-2"> - remove relation - </option></select>'; - } -} - -function rlEnter(ev) { - var c = document.layers ? ev.which : document.all ? event.keyCode : ev.keyCode; - if(c == 13) { - rlDoSearch(0); - return false; - } - return true; -} - -function rlDoSearch(f) { - var v = x('rl_S').value; - var d = x('rl_R'); - if(v.length < 1) - d.innerHTML = 'Search for a visual novel to add a relation.<br /><br />' - + 'Hint: type vX if you know the VN id.'; - else { - if(f) - d.innerHTML = '...searching...'; - ajax('/xml/vn.xml?q='+encodeURIComponent(v)+'&r='+(Math.floor(Math.random()*999)+1), function () { - if(!hr || hr.readyState != 4 || !hr.responseText) - return; - if(hr.status != 200) - return alert('Whoops, error! :('); - rlsel = ''; - var items = hr.responseXML.getElementsByTagName('item'); - if(!items || items.length < 1) { - d.innerHTML = 'No results'; - return false; - } - var res = ''; - var i,j; - for(i=0; i<items.length; i++) { - var id = items[i].getElementsByTagName('id')[0].firstChild.nodeValue; - var title = items[i].getElementsByTagName('title')[0].firstChild.nodeValue; - var cid = id + ',' + title; - res += '<input type="radio" name="rl_rad" id="pd_I'+id+'" value="rl_I'+id+'" onclick="rlAddRem(\''+qq(cid)+'\', \''+qq(title)+'\')" />' - + '<label style="width: auto" for="rl_I'+id+'">'+title+'</label><br style="clear: left" />'; - } - d.innerHTML = res; - }); - } -} - -function rlAddRem(id, name) { - var i; - var rs = x('rl_L').selectedIndex; - if(id && name) { - rlsel = id; - rlname = name; - } else if(id) { - if(!rs) - return; - if(rs == x('rl_L').options.length-1) { // remove - for(i=0;i<rl.options.length;i++) - if(rl.options[i].value == id) - rl.options[i] = null; - rl.options[0].selected = true; - } else { - var cur = id.split(',', 3); - i = rl.selectedIndex; - rs--; - rl.options[i] = new Option(vrel[rs]+': '+cur[2], (rs)+','+cur[1]+','+cur[2]); - rl.options[i].selected = true; - } - rlChangeSel(); - rlSerialize(); - return; - } else if(!rlsel) { - alert('No visual novel selected'); - return; - } - - if(!id && rlsel && !rs) { // remove - for(i=0;i<rl.options.length;i++) - if(rl.options[i].value.indexOf(rlsel) != -1) - rl.options[i] = null; - rlSerialize(); - return; - } - if(!rs) - return; - - // add/edit - var mod = rl.options.length; - rs--; - for(i=0;i<rl.options.length;i++) - if(rl.options[i].value.indexOf(rlsel) != -1) - mod = i; - rl.options[mod] = new Option(vrel[rs]+': '+rlname, rs+','+rlsel); - - rlSerialize(); -} - -// rel,id,name|||rel,id,name -function rlSerialize() { - var dest = x('relations'); - var str = ''; - var i; - for(i=0;i<rl.options.length;i++) - rl.options[i].value != '0_new' && (str += (str.length>0 ? '|||' : '') + rl.options[i].value); - dest.value = str; -} - -function rlLoad() { - var rls = x('relations').value.split('|||'); - if(!rls[0]) - return; - var i; - for(i=0;i<rls.length;i++) - rl.options[rl.options.length] = new Option(vrel[rls[i].split(',',3)[0]]+': '+rls[i].split(',',3)[2], rls[i]); -} - - - - - - - - - /************************\ - * VISUAL NOVELS * - \************************/ - - -function vnChangeSel() { - var sel = vn.options[vn.selectedIndex || 0]; - var o = x('vn_conts'); - var i; - var ops=''; - for(i=0;i<vrel.length;i++) - ops += '<option value="'+i+'">'+vrel[i]+'</option>'; - if(sel.value == '0_new') { - o.innerHTML = '<input type="text" name="vn_S" id="vn_S" onkeyup="vnDoSearch(0)" onkeydown="return vnEnter(event)" style="width: 150px;" />' - + '<button type="button" onclick="vnDoSearch(1)" style="width: 60px;">Search!</button><br style="clear: both" />' - + '<span id="vn_R" style="display: block; width: 250px; height: 90px; overflow: auto"></span>'; - vnDoSearch(''); - } else { - o.innerHTML = 'Selected "' + sel.text + '"<br />' - + '<button type="button" onclick="vnAddRem(\'' + sel.value + '\')">remove</button>'; - } -} - -function vnEnter(ev) { - var c = document.layers ? ev.which : document.all ? event.keyCode : ev.keyCode; - if(c == 13) { - vnDoSearch(0); - return false; - } - return true; -} - -function vnDoSearch(f) { - var v = x('vn_S').value; - var d = x('vn_R'); - if(v.length < 1) - d.innerHTML = 'Hint: type vX if you know the visual novel id.'; - else { - if(f) - d.innerHTML = '...searching...'; - ajax('/xml/vn.xml?q='+encodeURIComponent(v)+'&r='+(Math.floor(Math.random()*999)+1), function () { - if(!hr || hr.readyState != 4 || !hr.responseText) - return; - if(hr.status != 200) - return alert('Whoops, error! :('); - var items = hr.responseXML.getElementsByTagName('item'); - if(!items || items.length < 1) { - d.innerHTML = 'No results'; - return false; - } - var res = ''; - var i,j; - for(i=0; i<items.length; i++) { - var id = items[i].getElementsByTagName('id')[0].firstChild.nodeValue; - var title = items[i].getElementsByTagName('title')[0].firstChild.nodeValue; - var s = ''; - for(j=0; j<vn.options.length; j++) - if(vn.options[j].value == id) - s = ' checked="checked"'; - res += '<input type="checkbox" id="vn_I'+id+'"'+s+' onclick="vnAddRem(\''+qq(id)+'\', \''+qq(title)+'\')" />' - + '<label style="width: auto" for="vn_I'+id+'">'+title+'</label><br style="clear: left" />'; - } - d.innerHTML = res; - }); - } -} - -function vnAddRem(id, title) { - var i; - var d = 0; - for(i=0;i<vn.options.length;i++) - if(vn.options[i].value == id) { - vn.options[i] = null; - d = 1; - } - if(!d && title) - vn.options[vn.options.length] = new Option(title, id); - else if(!title) { - vn.options[0].selected = true; - vnChangeSel(); - } - vnSerialize(); -} - -// id,title|||id,title -function vnSerialize() { - var dest = x('vn'); - var str = ''; - var i; - for(i=0;i<vn.options.length;i++) - vn.options[i].value != '0_new' && (str += (str.length>0 ? '|||' : '') + vn.options[i].value + ',' + vn.options[i].text); - dest.value = str; -} - -function vnLoad() { - var vns = x('vn').value.split('|||'); - if(!vns[0]) - return; - var i; - for(i=0;i<vns.length;i++) - vn.options[vn.options.length] = new Option(vns[i].split(',',2)[1], vns[i].split(',',2)[0]); -} - - - - - - - /************************\ - * C A T E G O R I E S * - \************************/ - - -function catLoad() { - var i;var cats=[]; - var l = ct.value.split(','); - for(i=0;i<l.length;i++) - cats[l[i].substr(0,3)] = Math.floor(l[i].substr(3,1)); - - var l=x('cat').getElementsByTagName('a'); - for(i=0;i<l.length;i++) { - if(l[i].id.substr(0, 4) != 'cat_') - continue; - catSet(l[i].id.substr(4), cats[l[i].id.substr(4)]||0); - l[i].onclick = function() { - var c = this.id.substr(4); - if(!cats[c]) cats[c] = 0; - if(c.substr(0,1) == 'p' || c == 'gaa' || c == 'gab' || c.substr(0,1) == 'h' || c.substr(0,1) == 'l' || c.substr(0,1) == 't') { - if(cats[c]++) - cats[c] = 0; - } else if(++cats[c] == 4) - cats[c] = 0; - catSet(c, cats[c]); - - // has to be ordered before serializing! - var r;l=[];i=0; - for(r in cats) - l[i++] = r; - l = l.sort(); - r=''; - for(i=0;i<l.length;i++) - if(cats[l[i]] > 0) - r+=(r?',':'')+l[i]+cats[l[i]]; - ct.value = r; - return false; - }; - } -} - -function catSet(id, rnk) { - var c = rnk == 0 ? '#000' : - rnk == 1 ? '#090' : - rnk == 2 ? '#990' : '#900'; - x('b_'+id).style.color = c; - x('cat_'+id).style.color = c; - x('b_'+id).innerHTML = rnk; -} - - - - - - - - /***************************\ - * S C R E E N S H O T S * - \***************************/ - - -var scrL = []; // id, load, nsfw, obj, rid -function scrLoad() { - // 'screenshots' format: id,nsfw id,nsfw .. - var l=x('screenshots').value.split(' '); - for(var i=0;i<l.length;i++) - if(l[i].length > 2) - scrL[i] = { load: 2, id: l[i].split(',')[0], nsfw: l[i].split(',')[1]>0?1:0, rid: l[i].split(',')[2] }; - - // <tbody> because IE can't operate on <table> - x('scrfrm').innerHTML = '<table><tbody id="scrTbl"></tbody></table>'; - for(i=0;i<scrL.length;i++) - scrGenerateTR(i); - scrGenerateTR(i); - - setTimeout(scrSetSubmit, 1000); - scrCheckStatus(); -} - -// give an error when submitting the form while still uploading an image -function scrSetSubmit() { - var o=document.forms[1].onsubmit; - document.forms[1].onsubmit = function() { - var c=0;var r=0; - for(var i=0;i<scrL.length;i++) { - if(scrL[i] && scrL[i].load) - c=1; - if(scrL[i] && scrL[i].rid == 0) - r=1; - } - if(c) { - alert('Please wait for the screenshots to be uploaded before submitting the form.'); - return false; - } else if(r) { - alert('Please select the appropriate release for every screenshot'); - return false; - } else - return o(); - }; -} - -function scrURL(id, t) { - return x('scrfrm').className+'/s'+t+'/'+(id%100<10?'0':'')+(id%100)+'/'+id+'.jpg'; -} - -function scrGenerateTR(i) { - if(!scrL[i]) - scrL[i] = { id: 0, load: 0 }; - var r = '<b style="width: auto; float: none;margin: 0; padding: 0; font-weight: bold">'; - if(!scrL[i].id && !scrL[i].load) { - var c=0; - for(var j=0,c=0; j<scrL.length; j++) - if(scrL[j] && (scrL[j].load || scrL[j].id)) - c++; - if(c >= 10) - r += 'Enough screenshots</b>' - +'The limit of 10 screenshots per visual novel has been reached. ' - +'If you want to add a new screenshot, please remove an existing one first.'; - else - r += 'Add screenshot</b>' - +'<input type="file" name="scrAddFile'+i+'" id="scrAddFile'+i+'" style="float: none; height: auto; width: auto;" />' - +'<input type="button" value="Upload!" style="float: none; height: auto; width: auto; display: inline;" onclick="scrUpload('+i+')" /><br />' - +'Image must be smaller than 5MB and in PNG or JPEG format.'; - } - if(scrL[i].load && scrL[i].load == 1) - r += 'Uploading...</b>This could take a while, depending on the file size and your upload speed.<br />' - +'<a href="javascript:scrDel('+i+')">cancel</a>'; - if(scrL[i].load && scrL[i].load == 2) - r += 'Generating thumbnail...</b>Note: if this takes longer than 30 seconds, there\'s probably something wrong on our side.' - +'Please try again later or report a bug if that is the case.'; - if(scrL[i].id && !scrL[i].load) - r += 'Screenshot #'+scrL[i].id+'</b>' - +'<input type="checkbox" name="scrNSFW'+i+'" id="scrNSFW'+i+'"'+(scrL[i].nsfw?' checked="checked"':'')+' style="float: left" onclick="scrSer()" /> ' - +'<label for="scrNSFW'+i+'" class="checkbox"> This screenshot is NSFW.</label>' - +'<input type="button" value="remove" onclick="scrDel('+i+')" style="float: right; width: auto; height: auto" />' - +'<br /><b style="float: left; width: auto; margin-right: 5px">Release:</b>' - +'<select style="width: 350px; float: none; height: auto;" onchange="scrSer()" id="scrRel'+i+'">'+scrRelList(scrL[i].rid)+'</select>' - +'<br />Full size: '+scrL[i].width+'x'+scrL[i].height+'px'; - - if(scrL[i].obj) { - x('scrTr'+i).getElementsByTagName('td')[1].innerHTML = r; - return; - } - - // the slow and tedious way, because we need to use DOM functions to manipulate the table contents... - var o = document.createElement('tr'); - o.setAttribute('id', 'scrTr'+i); - o.style.cssText = 'border-top: 1px solid #ccc'; - var d = document.createElement('td'); - d.style.cssText = 'width: 141px; height: 102px; padding: 0;'; - d.innerHTML = scrL[i].id && !scrL[i].load ? '<img src="'+scrURL(scrL[i].id, 't')+'" style="margin: 0; padding: 0; border: 0" />' : ' '; - var e = document.createElement('td'); - e.innerHTML = r; - o.appendChild(d); - o.appendChild(e); - x('scrTbl').appendChild(o); - scrL[i].obj = o; - scrStripe(); -} - -function scrUpload(i) { - scrL[i].load = 1; - // move the file selection box into a temporary form and post it into a temporary iframe - var d = document.createElement('div'); - d.id = 'scrUpl'+i; - d.style.cssText = 'visibility: hidden; overflow: hidden; width: 1px; height: 1px; position: absolute; left: -500px; top: -500px'; - d.innerHTML = '<iframe name="scrIframe'+i+'" id="scrIframe'+i+'" style="height: 0px; width: 0px; visibility: hidden"' - +' src="about:blank" onload="scrUploadComplete('+i+')"></iframe>' - +'<form method="post" action="/xml/screenshots.xml" target="scrIframe'+i+'" enctype="multipart/form-data" id="scrUplFrm'+i+'" name="scrUplFrm'+i+'">' - +'<input type="hidden" name="itemnumber" value="'+i+'" />' - +'</form>'; - document.body.appendChild(d); - x('scrUplFrm'+i).appendChild(x('scrAddFile'+i)); - x('scrUplFrm'+i).submit(); - scrGenerateTR(i); - scrGenerateTR(i+1); - return false; -} - -function scrStripe() { - var l = x('scrTbl').getElementsByTagName('tr'); - for(var j=0; j<l.length; j++) - l[j].style.backgroundColor = j%2==0 ? '#fff' : '#f5f5f5'; -} - -function scrRelLine(rid, sel) { - var r; - for(var i=0;i<scrRel.length;i++) - if(scrRel[i][0] == rid) - r = scrRel[i]; - return '<option value="'+r[0]+'"'+(sel?' selected="selected"':'')+'>['+r[1]+'] '+r[2]+'</option>'; -} - -function scrRelList(rid) { - var r='<option value="0">-- select release --</option>'; - for(var i=0;i<scrRel.length;i++) - r += scrRelLine(scrRel[i][0], rid == scrRel[i][0] ? 1 : 0); - return r; -} - -function scrUploadComplete(i) { - if(window.frames['scrIframe'+i].location.href.indexOf('screenshots') > 0) { - try { - scrL[i].id = window.frames['scrIframe'+i].window.document.getElementsByTagName('image')[0].getAttribute('id'); - } catch(e) { - scrL[i].id = -10; - } - if(scrL[i].id < 0) { - alert( - scrL[i].id == -10 ? - 'Oops! Seems like something went wrong...\n' - +'Make sure the file you\'re uploading doesn\'t exceed 5MB in size.\n' - +'If that isn\'t the problem, then please report a bug.' : - scrL[i].id == -1 ? - 'Upload failed!\nOnly JPEG or PNG images are accepted.' : - 'Upload failed!\nNo file selected, or an empty file?'); - return scrDel(i); - } - scrL[i].load = 2; - scrGenerateTR(i); - scrImageFail(i); - } -} - -function scrCheckStatus() { - var ids=''; - for(var i=0;i<scrL.length;i++) - if(scrL[i] && scrL[i].load == 2) - ids+=(ids?';':'')+'id='+scrL[i].id; - if(!ids) - return setTimeout(scrCheckStatus, 1000); - var ti = setTimeout(scrCheckStatus, 10000); - ajax('/xml/screenshots.xml?'+ids+';r='+(Math.floor(Math.random()*999)+1), function () { - if(!hr || hr.readyState != 4 || !hr.responseText) - return; - if(hr.status != 200) - return alert('Whoops, error! :('); - var l = hr.responseXML.getElementsByTagName('image'); - for(var s=0;s<l.length;s++) { - for(i=0;i<scrL.length;i++) - if(scrL[i] && scrL[i].id == l[s].getAttribute('id') && l[s].getAttribute('status') > 0) { - scrL[i].load = 0; - scrL[i].width = l[s].getAttribute('width'); - scrL[i].height = l[s].getAttribute('height'); - x('scrTr'+i).getElementsByTagName('td')[0].innerHTML = - '<a href="'+scrURL(scrL[i].id, 'f')+'" rel="'+scrL[i].width+'x'+scrL[i].height+'" onclick="return scrView(this)">' - +'<img src="'+scrURL(scrL[i].id, 't')+'" style="margin: 0; padding: 0; border: 0" /></a>'; - scrGenerateTR(i); - scrSer(); - } - } - clearTimeout(ti); - setTimeout(scrCheckStatus, 1000); - }); -} - -function scrDel(i) { - x('scrTbl').removeChild(x('scrTr'+i)); - if(scrL[i].load) - document.body.removeChild(x('scrUpl'+i)); - scrL[i]=null; - scrGenerateTR(scrL.length-1); - scrSer(); - scrStripe(); -} - -function scrSer() { - var r=''; - for(var i=0;i<scrL.length;i++) { - if(scrL[i] && scrL[i].id && !scrL[i].load) { - scrL[i].nsfw = x('scrNSFW'+i).checked ? '1' : '0'; - scrL[i].rid = x('scrRel'+i).options[x('scrRel'+i).selectedIndex].value; - r += ' '+scrL[i].id+','+scrL[i].nsfw+','+scrL[i].rid; - } - } - x('screenshots').value = r; -} - - - - diff --git a/static/files/footer.gif b/static/files/footer.gif Binary files differdeleted file mode 100644 index c87fb121..00000000 --- a/static/files/footer.gif +++ /dev/null diff --git a/static/files/graph.png b/static/files/graph.png Binary files differdeleted file mode 100644 index bb56f758..00000000 --- a/static/files/graph.png +++ /dev/null diff --git a/static/files/headerbg.jpg b/static/files/headerbg.jpg Binary files differdeleted file mode 100644 index 81f4dd75..00000000 --- a/static/files/headerbg.jpg +++ /dev/null diff --git a/static/files/headerbot.png b/static/files/headerbot.png Binary files differdeleted file mode 100644 index 6e04ab05..00000000 --- a/static/files/headerbot.png +++ /dev/null diff --git a/static/files/icons.png b/static/files/icons.png Binary files differdeleted file mode 100644 index 4cb1a180..00000000 --- a/static/files/icons.png +++ /dev/null diff --git a/static/files/rss.png b/static/files/rss.png Binary files differdeleted file mode 100644 index 923c3822..00000000 --- a/static/files/rss.png +++ /dev/null diff --git a/static/files/select.png b/static/files/select.png Binary files differdeleted file mode 100644 index ac219e05..00000000 --- a/static/files/select.png +++ /dev/null diff --git a/static/files/sidebarbg.jpg b/static/files/sidebarbg.jpg Binary files differdeleted file mode 100644 index 00eb5697..00000000 --- a/static/files/sidebarbg.jpg +++ /dev/null diff --git a/static/files/sidebarbot.jpg b/static/files/sidebarbot.jpg Binary files differdeleted file mode 100644 index 49884ded..00000000 --- a/static/files/sidebarbot.jpg +++ /dev/null diff --git a/static/files/sidebg.jpg b/static/files/sidebg.jpg Binary files differdeleted file mode 100644 index 65fd3306..00000000 --- a/static/files/sidebg.jpg +++ /dev/null diff --git a/static/files/style.css b/static/files/style.css deleted file mode 100644 index 6c51bacf..00000000 --- a/static/files/style.css +++ /dev/null @@ -1,923 +0,0 @@ - -body { - margin: 15px 0 0 0; - padding: 0 0 60px 0; - background: #fff; - font-family: Arial, Helvetica, sans-serif; - font-size: 13px; - color: #203C36; -} - -form { - margin: 0; - padding: 0; -} - -fieldset { - margin: 0; - padding: 0; - border: none; -} - -legend { - display: none; -} - -input, textarea { - padding: 2px 5px; - border: 1px solid #B8E0D7; - font: normal 1em Arial, Helvetica, sans-serif; - color: #203C36; -} - -h1, h2 { - color: #203C36; - margin: 0; -} - -h1 { - text-transform: lowercase; - letter-spacing: -1px; - font-size: 3em; -} - -h2 { - font-size: 1.7em; - clear: right; -} - -h3 { - font-size: 1.1em; - margin: 0; -} -h3.alttitle { - margin: 0 0 0 20px; -} - -p, ul, ol { - margin: 0; -} -a { - color: #69A89A; -} -a:hover { - text-decoration: none; -} - -img { - border: none; -} - -/* Header */ - -#header { - width: 960px; - height: 80px; - margin: 0 auto; - background: url(/files/headerbg.jpg); -} - -#header h1 { - margin: 0; - padding: 15px 0 0 20px; - letter-spacing: normal; - font-size: 1em; - color: #FFFFFF; -} - -#header h1 a { - text-decoration: none; - color: #FFFFFF; -} - -#header h1 a:hover { - text-decoration: underline; -} - -#header b { - display: block; - letter-spacing: -2px; - font-size: 2.4em; -} - -/* Search */ - -#search { - float: right; - width: 180px; - padding-top: 30px; -} - -#searchfield { - width: 150px; -} - -#searchsubmit { - display: none; -} - -/* Login */ - -#loginform { - padding: 0; - margin: 0 0 0 20px; -} -#loginform input { - width: 40px; - margin: 0; - padding: 1px; - position: relative; -} -#loginform #usrname, #loginform #usrpass { - width: 70px; - border: 0; -} - -/* Page */ - -#page { - width: 960px; - margin: 0 auto; - padding: 40px 0; - background: url(/files/headerbot.png) no-repeat; -} - -#content { - float: left; - width: 700px; -} - -/* Side */ - -#side { - float: right; - padding: 0; - background: url(/files/sidebg.jpg); - color: #fff; -} -#side div { - background: url(/files/sidebarbg.jpg) no-repeat; -} -#side div div { - width: 240px; - padding: 0 0 60px 0; - background: url(/files/sidebarbot.jpg) no-repeat left bottom; -} - -#side a { - color: #fff; -} - -#side h2 { - padding: 20px 20px 0 15px; - text-transform: uppercase; - font-family: "Arial Black", Arial, Helvetica, sans-serif; - font-size: .8em; - color: #fff; -} - -#side ul { - margin: 0; - padding: 0 20px 0 20px; - list-style: none; -} - -#side li { - padding: 0; -} - -#side p { - margin: 0; - padding: 0 0 0 20px; -} -#side li.more { - font-style: italic; -} - -/* Footer */ - -#footer { - clear: both; - padding: 10px 0; -} - -#footer p { - margin: 0; - text-align: center; - color: #999999; - font-size: 0.8em; -} - -#footer a { - color: #999999; -} - -/* Forms */ -#content form { - display: block; - margin: 20px 0 10px 0; - padding: 0; -} -#content form.tblf { - margin: 0; -} -form ul { - margin: 0; - padding: 0; -} -form li { - display: block; - clear: left; - list-style-type: none; - margin: 0; - padding: 0; -} -form ul ul { - margin: 0; padding: 0; - clear: left; -} -form li.nolabel, form ul ul { - padding: 0 0 0 110px; -} -form li.nextpart { - padding: 10px 0 0 0; -} -#content label, #content input, #content textarea, #content select, form li b, form li p { - display: block; - float: left; -} -form li label i, form p.formnotice i { - display: inline; - color: #f00; -} -input.text, select { - width: 200px; -} -select, input.text, textarea { - border: 1px solid #B8E0D7; - font: normal 1em Arial, Helvetica, sans-serif; - color: #203C36; -} -form label.checkbox { - width: auto; -} -select.multiple { - height: 120px; - width: 230px; -} -#md_conts, #pd_conts, #rl_conts, #vn_conts { - display: block; - float: left; - background-color: #e3ecff; - border: 1px dashed #b4b4ff; - padding: 2px; -} -#rl_select { - width: 280px; -} -form li.longopts select { - width: 350px; -} -form li.shortopts input { - width: 50px; -} -form li i { - float: left; -} -input.hidden { - display: none; - position: absolute; - top: -30px; -} -label, form li b { - width: 110px; - font-weight: normal; -} -form li.nolabel b { - display: inline; - width: auto; - font-weight: bold; - float: none; -} -form li.subform { - padding: 10px 0 0 0; - clear: both; -} -form li.subform a { - display: block; - margin: 0; - padding: 0; - width: 100%; - background-color: #f0f0f0; - text-decoration: none; - font-weight: bold; - color: #7AB9AB; -} -li.formhid { - float: none; - position: absolute; - top: -2000px; - left: -2000px; - width: 10px; -} -form li.date select { - width: 100px; -} - -/* Platform selecter */ -form ul.platforms { - clear: none; - padding: 0; - margin: 0 0 0 110px; -} -form ul.platforms li { - float: left; - clear: none; -} -form ul.platforms li label { - width: 150px; -} -form ul.platforms input { - padding: 0; - margin: 0 2px 0 2px; - border: 0; - height: 14px; -} - -/* Warning & msg box */ -span.warning { - display: block; - margin: 5px 10% 5px 10%; - padding: 3px 5px 3px 60px; - background: #ffece3 url('/files/warning.png') no-repeat; - border: 1px dashed #ffb4b4; - min-height: 57px; -} -* html span.warning { height: 57px; } -span.msg { - display: block; - margin: 5px 10% 5px 10%; - padding: 3px 5px 3px 5px; - border: 1px dashed #3cb700; - background: #bfffb5; -} -span.warning ul, span.msg ul { - padding: 0 0 0 15px; -} -a.help { - vertical-align: super; - font-size: 10px; - text-decoration: none; - font-weight: bold; - padding-left: 1px; - /*background: #eee;*/ -} - - -/* VN page header, general dl and list markup */ -p.nsfw { color: #999; font-size: 10px; font-style: italic; } -dt { - float: left; - font-style: italic; -} -dd { - padding: 0 0 0 50px; -} -dl.vnrel dd, dl.vncat dd { - padding: 0 0 0 75px; -} -ul.vnani i { color: #999 } -ul.vnani b { color: #999; font-weight: normal; font-size: 10px; } -ul.vnani acronym { border: 0 } -ul { - padding: 0 0 0 17px; -} -p.actions { - display: inline; - margin: 0 0 0 5px; - font-weight: normal; - font-size: 12px; - color: #999; -} -#vnheader div { - width: 256px; - float: left; - text-align: center; -} -#vnheader div img { - margin: 0 auto 0 auto; -} -#vnheader #nsfw { - cursor: pointer; -} -#vnheader dl, #vnheader ul { - margin: 0 0 0 270px; - padding: 0; -} -#vnheader li { list-style-type: none; margin: 0; padding: 0; } -#vnheader h3 { - margin: 10px 0 0 260px; - font-size: 13px; -} -#vnheader p.mod { - margin: 0; -} - - -/* producer search */ - -form#psearch fieldset { - display: block; - width: 700px; - text-align: center; -} -form#psearch input { margin: 0 auto; float: none; position: relative; display: inline } - - -ul.home { - float: left; - list-style-type: none; - width: 210px; - margin-top: 30px; -} -ul.home li { padding: 0; } -ul.home.break { clear: left; } -h3.home { - clear: left; - padding-top: 30px; -} - - -/* edit links and stuff */ - -p.mod { - float: right; - color: #999; -} -div.dropdown { - width: 100px; - position: absolute; - left: -500px; - top: 0; - border: 1px solid #d0d0d0; - border-bottom: none; -} -div.dropdown ul, div.dropdown ul li { - list-style-type: none; - margin: 0; - padding: 0; - width: 100px; - background-color: #f0f0f0; - border-bottom: 1px solid #d0d0d0; -} -div.dropdown a, div.dropdown b { - display: block; - width: 90px; - margin: 0; - padding: 2px 5px; - text-decoration: none; -} -div.dropdown b { - font-weight: normal; - font-style: italic; - color: #666; -} -div.dropdown li.center a, div.dropdown li.center b { - text-align: center; -} -div.dropdown a:hover { - background-color: #e0e0e0; -} -div.rlistdd { - width: 200px; -} -div.rlistdd ul, div.rlistdd ul li { - float: left; -} -div.rlistdd a, div.rlistdd b { - padding: 0px 5px; -} -div.dropdown ul.full a, div.dropdown ul.full b { - width: 190px; - padding: 1px 5px; -} -div.dropdown ul.full, div.dropdown ul.full li { - clear: left; - width: 200px; -} - - -/* paragraph markups... */ - -p#relations { - margin: 20px 0 0 0; - width: 100%; - text-align: center; -} -p.desc { - padding: 0 10px 0 10px; -} -p.chr { - width: 100%; - text-align: center; - font-size: 1.1em; -} -p.browse { - width: 100%; - text-align: center; -} -b.mod, a.mod { - color: #f00; -} - - -/* vn search */ - -form#vsearch fieldset { - display: block; - width: 700px; - text-align: center; -} -form#vsearch input { margin: 0 auto; float: none; position: relative; display: inline } -form#vsearch input.text { width: 400px; } -b#adsearchclick { cursor: pointer } - -ul.filter { margin: 0 0 0 15px; padding: 0; list-style-type: none } -ul.filter li { float: left; padding: 4px 10px 0 0; } -ul.filter label { width: auto; color: #666; font-size: 11px; margin: 0; padding: 0 0 0 1px;} -ul.filter input { border: 0; margin: 0; } - - - -/* categories */ - -ul#cat { - margin: 0 0 0 15px; - padding: 0; -} -ul#cat ul { - list-style-type: none; - padding: 0; -} -ul#cat input { - padding: 0; - margin: 0 2px 0 2px; - border: 0; - height: 14px; -} -ul#cat li, form ul#cat li { - display: block; - width: 170px; - float: left; - clear: none; - font-weight: bold; -} -ul#cat li li { - display: list-item; - width: auto; - float: none; - clear: left; - font-weight: normal; - padding: 0 0 0 20px; - margin: 0; - cursor: pointer; - list-style-type: none; - background: url(/files/select.png) no-repeat; -} -form ul#cat li li { - padding: 0; - background: none; -} -form ul#cat li li b { width: 13px; font-weight: bold; } -form ul#cat li li a { color: #000; text-decoration: none; display: block; width: 160px; } -ul#cat li li.inc { background-position: 0px -16px; color: #090; } -ul#cat li li.exc { background-position: 0px -33px; color: #900; } -i.crgn0 { font-style: normal; } -i.crgn1 { font-style: normal; color: #bbb; } -i.crgn2 { font-style: normal; } -i.crgn3 { font-style: normal; font-weight: bold; } - - - -/* DOCUMENTATION PAGES */ -#dpage h3 { margin-top: 25px; } -#dpage h3 a { color: #203C36; text-decoration: none; } -#dpage dd { padding-bottom: 5px; margin-left: 70px; } -#dpage ul.index { display: block; float: right; width: 150px; padding: 2px; margin: 0 0 10px 5px; background-color: #f1f1f1; border: 1px solid #ccc; } -#dpage ul.index li { list-style-type: none; } -#dpage ul.index li a { margin: 0 0 0 10px; } -#dpage .retired { text-decoration: line-through; } -#dpage dt b { color: #999; font-weight: normal; font-style: normal; font-size: 12px; } - -/* Screenshots */ -div#screenshots { - display: block; - width: 700px; - margin: 0; - padding: 0; -} -div#screenshots b { - display: block; - margin: 0; - padding: 0; - width: 100%; - background-color: #f5f5f5; - font-weight: normal; -} -div#screenshots a.shot { - display: block; - float: left; - width: 136px; - height: 102px; - margin: 0; - padding: 2px; - text-decoration: none; - text-align: center; -} -div#screenshots a.shot:hover { - background-color: #ccc; -} -div#screenshots a.shot b { - display: block; - margin: -16px 0 0 0; - padding: 0; - height: 14px; - width: 136px; - text-align: right; - font-size: 12px; - color: #f00; -} -div#screenshots img { border: 0; padding: 0; } -div#scrView { - position: absolute; - display: none; - top: -5000px; - left: -5000px; - background-color: #fff; - border: 2px solid #ccc; - padding: 10px; - text-align: center; -} -#scrView img { cursor: pointer } -#scrclose { float: right; padding-left: 10px; } -#scrnext { padding-left: 5px; } -#scrprev { padding-right: 5px; } -#scrfull { float: left; padding-right: 10px; } -#scrimgload { - display: block; - position: absolute; - left: -500px; - top: -50px; - width: 100px; - padding: 3px; - background-color: #f5f5f5; - text-align: center; - border: 1px solid #ccc; - color: #000; -} - - - -#content input.right, #content select.right { - float: right; -} -#vnlistchange { width: 130px; } -p.opts { - clear: left; - text-align: center; - width: 100%; - background-color: #f0f0f0; - margin-bottom: 10px; - margin-top: 10px; - padding: 1px 0; -} -ul#stats { - clear: left; - list-style-type: none; - padding: 0px 0 0 5px; -} -ul#stats li { - padding: 0; - display: block; - width: 345px; - float: left; - margin: 0 0 20px 0; -} -ul#stats li.break { - clear: left; -} - -acronym { - border-bottom: 1px dotted #999; -} -acronym.date { - border: 0; -} -b.future { font-weight: normal; color: #900; } - - -/* icon image sprites */ - -a.rss { - display: block; - height: 16px; - width: 16px; - background: url(/files/rss.png) no-repeat; - text-indent: -9999px; - overflow: hidden; - float: right; -} -.icons, .uicons { - background: url(/files/icons.png) no-repeat; - width: 16px; - height: 14px; - margin: 0 2px 0 0; - overflow: hidden; - display:-moz-inline-stack; - display: inline-block; - padding: 0; - border: 0; - text-decoration: none; -} -.uicons { - width: 14px; - margin: 0; - background: url(/files/uicons.png) no-repeat; -} -.icons.lang { - width: 13px; - height: 11px; - border: 1px solid #999; - /* see def.js for an ugly FF hack */ -} -.icons.par, .icons.tri, .icons.com { width: 11px; } -acronym.icons, acronym.uicons { cursor: default; } -.icons.oth { background: none; } -.icons.drc { background-position: 0px 0px; } -.icons.lin { background-position: 0px -14px; } -.icons.nds { background-position: 0px -28px; } -.icons.ps2 { background-position: 0px -42px; } -.icons.sfc { background-position: 0px -56px; } -.icons.gba { background-position: 0px -70px; } -.icons.ps3 { background-position: 0px -84px; } - -.icons.dvd { background-position: -16px 0px; } -.icons.mac { background-position: -16px -14px; } -.icons.ps1 { background-position: -16px -28px; } -.icons.psp { background-position: -16px -42px; } -.icons.win { background-position: -16px -56px; } -.icons.wii { background-position: -16px -70px; } -.icons.xb3 { background-position: -16px -84px; } - -.icons.com { background-position: -32px 0px; } -.icons.par { background-position: -32px -14px; } -.icons.tri { background-position: -32px -28px; } -.icons.ext { background-position: -32px -42px; } -.icons.msx { background-position: -32px -56px; } -.icons.nes { background-position: -32px -70px; } - -.icons.cs { background-position: -48px 0px; } -.icons.da { background-position: -48px -11px; } -.icons.de { background-position: -48px -22px; } -.icons.en { background-position: -48px -33px; } -.icons.es { background-position: -48px -44px; } -.icons.fi { background-position: -48px -55px; } -.icons.fr { background-position: -48px -66px; } -.icons.it { background-position: -48px -77px; } -.icons.ja { background-position: -48px -88px; } - -.icons.nl { background-position: -61px 0px; } -.icons.no { background-position: -61px -11px; } -.icons.pl { background-position: -61px -22px; } -.icons.pt { background-position: -61px -33px; } -.icons.ru { background-position: -61px -44px; } -.icons.sv { background-position: -61px -55px; } -.icons.tr { background-position: -61px -66px; } -.icons.zh { background-position: -61px -77px; } -.icons.ko { background-position: -61px -88px; } - -.uicons.no { background-position: 0px 0px; } -.uicons.r0 { background-position: 0px -14px; } -.uicons.v0 { background-position: 0px -14px; } -.uicons.r1 { background-position: 0px -28px; } -.uicons.r2 { background-position: 0px -42px; } -.uicons.r3 { background-position: 0px -56px; } - -.uicons.r4 { background-position: -14px 0px; } -.uicons.v1 { background-position: -14px -14px; } -.uicons.v2 { background-position: -14px -28px; } -.uicons.v3 { background-position: -14px -42px; } -.uicons.v4 { background-position: -14px -56px; } - - -/* tables */ - -table td { vertical-align: top; } -table { width: 100%; border-collapse: collapse; } -thead tr td { font-weight: bold; } -thead tr td a { text-decoration: none; } -#content table input { - width: 13px; - height: 13px; - margin: 0; - float: right; -} - -/* revisions */ -#tmc { width: 650px; margin: 0 0 30px 30px; border: 1px solid #ddd; background-color: #fbfbfb; clear: both; } -#tmc thead tr td { font-weight: normal; text-align: center; } -#tmc .tc1, #tmc .tc2 { border-right: 1px solid #ddd; } -#tmc .tc1 { font-weight: bold; padding-right: 10px; } -#tmc .tc1 { width: 100px; } -#tmc .tc2, #tmc .tc3 { width: 275px; } -div#tmc { text-align: center; } -div#revbrowse { margin: 20px 0 0 30px; width: 650px; text-align: center; } /* position: relative; top: 17px; left: 30px; */ -a#revnext { float: right } -a#revprev { float: left; } -b.diff_add { font-weight: normal; background-color: #cfc; } -b.diff_del { font-weight: normal; background-color: #fcc; } - -#tvg tr, #tus tr { background-color: #fff!important } -#tvg .tc1, #tus .tc1 { width: 25px; text-align: right; padding-right: 3px; } -#tvg .tc2 div, #tus .tc2 div { margin: 0 5px 0 0; padding: 0; float: left; background: url(/files/graph.png); height: 13px; } -#tus .tc1 { width: 60px } - -#tvr .tc3, #tvl .tc5, #tur .tc3, #tul .tc8, #thi .tc6 { text-align: right } - -#tvl .tc1, #tvl .tc2, #tvl .tc3 { white-space: nowrap; padding-right: 10px; } - -#thi { clear: both } -#thi .tc1_1 { text-align: right; padding-right: 0; width: 10px; } -#thi .tc1_2 { padding-left: 0; padding-right: 10px; } -#thi .tc1_1 a, #thi .tc1_2 a { text-decoration: none } -#thi .tc1 { width: 10px } -#thi .tc2 { width: 110px; } - -#rli tr.relhid { background-color: #fff!important; } -#rli td.relhid, #relhidpar { cursor: pointer; } -#rli td.relnone { color: #aaa } -#rli .tc1 { width: 560px; } -#rli .tc2 { width: 80px; } -#rli .tc3 { width: 50px; } -#rli .tc1_1 { width: 70px; padding-left: 20px } -#rli .tc1_2 { width: 40px; padding:0; text-align: right; } -#rli .tc1_3 { width: 430px; } -#rli .tc1_3 a { color: #203c36; } -#rli .tc1_5 { text-align: right } - -#tre tr { background-color: #fff!important; } -#tre tr.lang { background-color: #f5f5f5!important; font-style: italic; } - -#tre .tc1 { width: 75px; padding-left: 10px; } -#tre .tc2 { width: 50px; text-align: center; white-space: nowrap; } -#tre .tc3, #tre .tc6 { width: 16px; margin: 0; padding: 0; white-space: nowrap; text-align: right } -#tre .tc3 { width: 70px; } -#tre .tc5 { width: 30px; text-align: right; padding: 0 10px 0 0; } -#tre .tc5 a { display: block; width: 30px; text-align: right;text-decoration: none; } - -#tbv .tc2 acronym, #tbv .tc3 acronym { - zoom: 1; - opacity: 0.7; - filter:alpha(opacity=70); - -moz-opacity: 0.7; -} -#tbv .tc2, #tbv .tc3 { margin: 0; padding: 0; white-space: nowrap } -#tbv .tc2 { text-align: right; padding-right: 3px; } - -#tpd .tc1 { margin: 0; padding: 0; } - - -/* message board */ - -#tth tr { border-top: 1px solid #999 } -#tth .tc1 { width: 150px; border-right: 1px solid #999; padding: 5px; } -#tth .tc2 { padding: 5px } -#tth p.mod { margin: -5px; font-size: 10px; } -#tth .tc2 i { font-size: 10px; float: right; } -#tth .tc2 b.hidden { font-size: 10px; color: #888; font-weight: normal; } -#tin .tc1 { width: 400px; } -#tin .tc2 { width: 25px; } -#tin .tc4 { text-align: right } -#tin .tc1 b { font-weight: normal; color: #888; } -#qreply { display: block; width: 100%; text-align: center } -#qreply textarea, #qreply input { float: none; margin: auto; } -a.right { float: right } -b.spoiler { font-weight: normal; color: #ccc; background-color: #ccc } -b.spoiler:hover { color: #000; background-color: #eee } - - - -#debug { - border-top: 1px solid #ffb4b4; - background-color: #ffece3; - height: 70px; - overflow: auto; - position: fixed; - left: 0; - bottom: 0; - width: 100%; - font-size: 10px; - margin: 0; - padding: 0; -} - diff --git a/static/files/uicons.png b/static/files/uicons.png Binary files differdeleted file mode 100644 index 09f8da17..00000000 --- a/static/files/uicons.png +++ /dev/null diff --git a/static/files/warning.png b/static/files/warning.png Binary files differdeleted file mode 100644 index b8af1a53..00000000 --- a/static/files/warning.png +++ /dev/null diff --git a/util/fcgi.pl b/util/fcgi.pl deleted file mode 100644 index 6a391386..00000000 --- a/util/fcgi.pl +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/perl - -package FCGI::Handler; - -use strict; -use warnings; -use lib '/www/vndb/lib'; - -use strict; -use warnings; -use FCGI; -use CGI::Minimal (); -use CGI::Cookie::XS; -use Time::HiRes; -use VNDB; - -my $elog = "/www/err.log"; - -our $req = FCGI::Request(); -our $c; -our $outputted = 0; - -my $VNDB = VNDB->new(%VNDB::VNDBopts); - -our @WRN; -$SIG{__WARN__} = sub { push @FCGI::Handler::WRN, @_; }; - -while($req->Accept() >= 0) { - # lighty doesn't always split the query string from REQUEST_URI - ($ENV{REQUEST_URI}, $ENV{QUERY_STRING}) = split /\?/, $ENV{REQUEST_URI} - if ($ENV{REQUEST_URI}||'') =~ /\?/; - - # re-init CGI::Minimal (can die()) - eval { - CGI::Minimal::reset_globals; - CGI::Minimal::allow_hybrid_post_get(1); - CGI::Minimal::max_read_size(5*1024*1024); # allow 5MB of POST data - $c = CGI::Minimal->new(); - }; - if($@) { - send500(); - $req->Finish(); - next; - } - - # figure out some required variables - my $o = $VNDB; - my $start = [ Time::HiRes::gettimeofday ] if $o->{debug}; - - # call appropriate functions in VNDB.pm - my $e = eval { - if($c->truncated) { - send500(); - warn "Truncated post request!\n"; - } else { - $o->DBCheck; - $o->get_page; # automatically calls DBCommit on success - } - 1; - }; - - # Error handling - if(@WRN && $e && !$@ && open(my $F, '>>', $elog)) { - for (@WRN) { - chomp; - printf $F "[%s] %s: %s\n", scalar localtime(), $ENV{HTTP_HOST}.$ENV{REQUEST_URI}.'?'.$ENV{QUERY_STRING}, $_; - } - close $F; - } - if(!defined $e && $@ && open(my $F, '>>', $elog)) { - printf $F "[%s] %s: FATAL ERROR!\n", scalar localtime(), $ENV{HTTP_HOST}.$ENV{REQUEST_URI}.'?'.$ENV{QUERY_STRING}; - print $F " ENV-dump:\n"; - printf $F " %s: %s\n", $_, $ENV{$_} for (sort keys %ENV); - print $F " PARAM-dump:\n"; - printf $F " %s: %s\n", $_, $c->param($_) for (sort $c->param()); - my $err = $@; chomp($err); - printf $F " ERROR:\n %s\n", $err; - if(@WRN) { - print $F " WARNINGS:\n"; - for (@WRN) { - chomp; - printf $F " %s\n", $_; - } - } - print $F "\n"; - close $F; - eval { $o->DBRollBack; }; - send500() if !$outputted; - } - - # Debug info - if($o->{debug} && open(my $F, '>>', $elog)) { - my($sqlt, $sqlc) = (0, 0); - for (@{$o->{_DB}->{Queries}}) { - if($_->[0]) { - $sqlc++; - $sqlt += $_->[1]; - } - } - my $time = Time::HiRes::tv_interval($start); - my $tpl = $o->{_Res}->{_tpltime} ? $o->{_Res}->{_tpltime}/$time*100 : 0; - my $gzip = 0; - $gzip = 100 - $o->{_Res}->{_gzip}->[1]/$o->{_Res}->{_gzip}->[0]*100 - if($o->{_Res}->{_gzip} && ref($o->{_Res}->{_gzip}) eq 'ARRAY' && $o->{_Res}->{_gzip}->[0] > 0); - printf $F "Took %3dms (SQL/TPL/perl: %4.1f%% %4.1f%% %4.1f%%) (GZIP: %4.1f%%) to parse %s\n", - $time*1000, $sqlt/$time*100, $tpl, 100-($sqlt/$time*100)-$tpl, $gzip, $ENV{REQUEST_URI}; - close $F; - } - - # reset vars - @WRN = (); - $outputted = 0; - undef $o->{_Res}; - undef $o->{_Req}; - - $req->Finish(); -} - -sub send500 { - print "Status: 500 Internal Server Error\n"; - print "Content-Type: text/html\n"; - print "X-Sendfile: /www/vndb/www/files/err.html\n\n"; -} - |