#!/usr/bin/perl $SiteName = 'Campaign Wiki'; $AdminPass = "*secret*"; # not the real password $ScriptName = 'http://campaignwiki.org/wiki'; $WikiLinks = 0; @UserGotoBarPages = ($HomePage, $RCName, 'About'); $CommentsPrefix = 'Comments_on_'; $ENV{PATH} = '/usr/bin:/bin'; $NewComment = ''; $HoneyPotOk = 'ts'; # $KeepDays = 1/100000; # HTML Headers push(@MyInitVariables, \&MyExtraHeaders); sub MyExtraHeaders { $HtmlHeaders .= < var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-2101513-3']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); EOT my $id = GetId(); if ($q and $id) { my $text; if (GetParam('Preview', '')) { $text = GetParam('text', ''); } elsif (GetParam('action', 'browse') eq 'browse') { OpenPage($id); $text = $Page{text}; } my @fonts; while ($text =~ /\[font=([A-Z][^]]*)\]/g) { push(@fonts, $1); } foreach my $font (@fonts) { $font =~ s/ +/+/g; $HtmlHeaders .= qq{}; } } } # Images $MaxPost = 1024 * 500; $UploadAllowed = 1; $StaticAlways = 1; %StaticMimeTypes = ('image/svg+xml' => 'svg', 'image/svg+xml-compressed' => 'svg', 'application/pdf' => 'pdf', 'image/jpeg' => 'jpg', 'image/pjpeg' => 'jpg', 'image/png' => 'png', 'image/x-png' => 'png'); @UploadTypes = keys %StaticMimeTypes; $StaticMimeTypes{"image/svg+xml gzip"} = 'svgz'; $StaticMimeTypes{"image/svg+xml-compressed gzip"} = 'svgz'; push(@MyInitVariables, sub { $StaticDir = "/home/alex/websites/campaignwiki.org/pics"; $StaticDir .= '/' . $NamespaceCurrent if $NamespaceCurrent; $StaticUrl = 'http://campaignwiki.org/pics'; $StaticUrl .= '/' . $NamespaceCurrent if $NamespaceCurrent; $StaticUrl .= '/'; }); # Languages # push(@Debugging, sub {print $q->p($CurrentLanguage)}); push(@MyInitVariables, sub { if ($CurrentLanguage eq 'de') { $Translate{Calendar} = 'Kalender'; $Translate{'Read Comments'} = 'Kommentare lesen'; $EditNote = $q->p(Ts('Mehr Information zur Formatierung gibt es auf der %s Seite.', $q->a({-href=>"$NamespaceRoot/Info_(Deutsch)"}, 'Info'))); if ($NamespaceCurrent eq '') { $HomePage = 'Hauptseite'; $RCName = 'Änderungen'; $UserGotoBar = join('', map {GetPageLink($_)} $HomePage, $RCName, 'Übersicht', 'Impressum'); } } elsif ($CurrentLanguage eq 'fr') { $Translate{Calendar} = 'Calendrier'; $Translate{'Read Comments'} = 'Commentaires'; $EditNote = $q->p(Ts('Pour plus d’information sur la mise en forme, voiez la page d’%s.', $q->a({-href=>"$NamespaceRoot/Info_(Français)"}, 'Information'))); $FooterNote = $q->p('(Aidez-moi à améliorer la traduction du logiciel et envoyez-moi un émail' . ' si vous avez des suggestions. ☺ – ' . $q->a({-href=>'mailto:kensanata@gmail.com'}, 'Alex') . ')'); if ($NamespaceCurrent eq '') { $HomePage = 'Acceuil'; $RCName = 'Modifications Récentes'; $UserGotoBar = join('', map {GetPageLink($_)} $HomePage, $RCName, 'Status', 'About'); } } elsif ($CurrentLanguage eq 'it') { $Translate{Calendar} = 'Calendario'; $Translate{'Read Comments'} = 'Commenti'; $EditNote = $q->p(Ts('Vedere la pagina %s per le regole di marcatura.', $q->a({-href=>"$NamespaceRoot/Info_(Italiano)"}, 'Informazioni'))); $FooterNote = $q->p('(Aiutami a tradurre il software e mandarmi una email con suggerimenti. ☺ – ' . $q->a({-href=>'mailto:kensanata@gmail.com'}, 'Alex') . ')'); if ($NamespaceCurrent eq '') { $HomePage = 'Pagina principale'; $RCName = 'Recenti_cambiamenti'; $UserGotoBar = join('', map {GetPageLink($_)} $HomePage, $RCName, 'Stato', 'A proposito'); } } else { $EditNote = $q->p(Ts('See %s for markup rules.', $q->a({-href=>"$NamespaceRoot/Info"}, 'Info'))); if ($CurrentLanguage and $CurrentLanguage ne 'en') { $FooterNote = $q->p('(Help me translate the software and send me an email with suggestions. ☺ – ' . $q->a({-href=>'mailto:kensanata@gmail.com'}, 'Alex') . ')'); } } if (not $UserGotoBar) { # The GotoBar page was no used $UserGotoBar .= ' ' . ScriptLink('action=new', T('New'), 'new'); $UserGotoBar .= ' ' . ScriptLink('action=calendar', T('Calendar'), 'cal'); } }); # CSS $StyleSheet = 'http://www.campaignwiki.org/beige.css'; $StyleSheetPage = 'CSS'; push(@MyInitVariables, sub { # anybody can change the CSS page delete($LockOnCreation{$StyleSheetPage}); # if it exists, ignore the default CSS $StyleSheet = undef if $IndexHash{$StyleSheetPage} and GetPageContent($StyleSheetPage) !~ /^\s*$/; }); # Spam @QuestionaskerQuestions = (['Please say HELLO.' => sub { shift =~ /^\s*hello!*\s*$/i }], ); use vars qw($QuestionaskerRememberAnswer $QuestionaskerSecretKey); $QuestionaskerRememberAnswer = 1; $QuestionaskerSecretKey = 'frodo'; # Markup push(@MyRules, \&MyTabRule); $RuleOrder{\&MyTabRule} = -20; # be the first! sub MyTabRule { if ($bol and /\G\t/cgs) { # TAB: linebreak return $q->br(); } return undef; } push(@MyRules, \&MyRules); $RuleOrder{\&MyRules} = 20; # be after SearchListRule sub MyRules { if (m/\G\<html\>(.*?)\<\/html\>/cgs and -f GetLockedPageFile($OpenPageName)) { return UnquoteHtml($1); } elsif (pos == 0 and m/\G#!/gc || m/\G<.*>/gc) { pos = length($_); # fake matching entire file return $q->pre({-class=>source}, $_); } elsif (/\G:([-a-z]+|0|\+):/cg) { # :smile: return $q->img({-class=>'smiley', -alt=>$1, -src=>"http://www.emacswiki.org/pics/$1.png"}); } elsif (m/\G\<(div class="[^\"]+")\>/cgi or m/\G\<(\/div)\>/cgi) { #
return CloseHtmlEnvironments() . '<' . UrlDecode($1) . '>'; } elsif ($bol and /\G: /cg) { # : indented return CloseHtmlEnvironments() . AddHtmlEnvironment('blockquote'); } elsif (m/\G\[print\]/cgi) { return 'Print'; } return undef; } $MarkupPairs{'_'} = $MarkupForcedPairs{'__'} = ['em', {'class' => 'underline', 'style'=>'text-decoration: underline; ' . 'font-style: normal;'}]; $MarkupSingles{'\times'} = '×'; $MarkupSingles{'\star'} = '★'; $MarkupSingles{'\box'} = '☐'; $MarkupSingles{'\check'} = '✓'; $MarkupSingles{'<-'} = '←'; $MarkupSingles{'<--'} = '←'; $MarkupSingles{'-->'} = '→'; $MarkupSingles{'=>'} = '⇒'; $MarkupSingles{'==>'} = '⇒'; $MarkupSingles{'<=>'} = '⇔'; $MarkupSingles{'+/-'} = '±'; $MarkupSingles{'^0'} = '⁰'; $MarkupSingles{'^1'} = '¹'; $MarkupSingles{'^2'} = '²'; $MarkupSingles{'^3'} = '³'; $MarkupSingles{'^4'} = '⁴'; $MarkupSingles{'^5'} = '⁵'; $MarkupSingles{'^6'} = '⁶'; $MarkupSingles{'^7'} = '⁷'; $MarkupSingles{'^8'} = '⁸'; $MarkupSingles{'^9'} = '⁹'; $MarkupSingles{'1/2'} = '½'; $MarkupSingles{'1/4'} = '¼'; $MarkupSingles{'3/4'} = '¾'; $MarkupSingles{'1/3'} = '⅓'; $MarkupSingles{'2/3'} = '⅔'; $MarkupSingles{'1/5'} = '⅕'; $MarkupSingles{'2/5'} = '⅖'; $MarkupSingles{'3/5'} = '⅗'; $MarkupSingles{'4/5'} = '⅘'; $MarkupSingles{'1/6'} = '⅙'; $MarkupSingles{'5/6'} = '⅚'; $MarkupSingles{'1/8'} = '⅛'; $MarkupSingles{'3/8'} = '⅜'; $MarkupSingles{'5/8'} = '⅝'; $MarkupSingles{'7/8'} = '⅞'; $CreoleDashStyleUnorderedLists = 1; # New Action $Action{new} = \&DoNew; sub DoNew { my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime($Now); $today = sprintf("%d-%02d-%02d", $year + 1900, $mon + 1, $mday); print GetHeader(undef, T('New Page')); print GetFormStart(undef, undef, 'new'); print $q->p(GetHiddenValue('action', 'edit'), T('Pagename:'), ' ', $q->textfield(-name => 'id', -value => $today . ' ', -size => 40, -maxlength => 120), $q->submit(-name => 'Edit', -accesskey => T('e'), -value => T('Edit'))); print $q->endform; PrintJournal(); PrintFooter(); } # Configurable Logo and Footer push @MyInitVariables, \&InitPageVariables; sub InitPageVariables { $AdminPages{LogoUrl} = 1; if ($IndexHash{LogoUrl}) { my $logo = GetPageContent('LogoUrl'); if ($logo =~ /^$FullUrlPattern$/) { $LogoUrl = $logo; } } $AdminPages{FooterNote} = 1; if ($IndexHash{FooterNote}) { # ApplyRules will print to STDOUT but we want to store the HTML in # $FooterNote! local *STDOUT; open(STDOUT, '>', \$FooterNote) or die "Can't open memory file: $!"; ApplyRules(GetPageContent('FooterNote'), 1, undef, undef, 'p'); } } *MyOldGetPageLink = *GetPageLink; *GetPageLink = *MyNewGetPageLink; sub MyNewGetPageLink { my ($id, $name, $class) = @_; return MyOldGetPageLink(@_) if $class ne 'comment'; if ($IndexHash{$id}) { $name = T('Read Comments'); $name .= ' (' . scalar(split(/----+/, GetPageContent($id))) . ')'; } else { $name = T('Add Comment'); } return MyOldGetPageLink($id, $name, $class); } # crypto banning some stuff -- no override by admins sub text_match { my $re = shift; return (GetParam('text') =~ /$re/i or GetParam('aftertext') =~ /$re/i); } push(@MyInitVariables, sub { # crypto banning usernames like tbattlet7, # cyrillic spammers using the word порно (porn) if (GetParam('title') and (GetParam('username') =~ /\d$/ or GetParam('username') =~ /^(buy|seo)/ or text_match('порно') or text_match('<a\s+href='))) { SetParam('action', 'browse'); SetParam('id', GetParam('title')); }}); $MonitorUser = 'oddmuse.wiki'; $MonitorPassword = $AdminPass; $MonitorHost = 'smtp.gmail.com'; $MonitorFrom = 'oddmuse.wiki@gmail.com'; $MonitorTo = 'kensanata@gmail.com'; $MonitorRegexp = '.'; # tags push(@MyInitVariables, sub { $TagUrl = $ScriptName . "/%s"; }); # a separate tag cloud implementation that doesn't do a search sub TagCloud { print GetHeader('', T('Tag Cloud'), ''), $q->start_div({-class=>'content cloud'}) . '

'; # open the DB file require DB_File; tie %h, "DB_File", $TagFile; my $max = 0; my $min = 0; my %count = (); foreach my $tag (grep !/^_/, keys %h) { $count{$tag} = split(/$FS/, $h{$tag}); $max = $count{$tag} if $count{$tag} > $max; $min = $count{$tag} if not $min or $count{$tag} < $min; } untie %h; foreach my $tag (sort keys %count) { my $n = $count{$tag}; my $url = "$ScriptName?search=tag:" . UrlEncode($tag); foreach my $id (AllPagesList()) { if (lc($id) eq $tag) { $url = ScriptUrl($id); last; } } print $q->a({-href => $url, -title => $n, -style => 'font-size: ' . int(80+120*($max == $min ? 1 : ($n-$min)/($max-$min))) . '%;', }, NormalToFree($tag)), T(' ... '); } print '

'; PrintFooter(); } $Action{tagcloud} = \&TagCloud; # Debug # push(@Debugging, sub { # my %ids = map { my ($ts, $id) = @$_; $id => 1; } # make unique via hash # GetRcLines($Now - $KeepDays * 86400); # 24*60*60 # @ids = keys %ids; # my $to = GetParam('to', 0); # RequestLockOrError(); # foreach my $id (@ids) { # OpenPage($id); # my ($text, $minor, $ts) = GetTextAtTime($to); # if ($Page{text} eq $text) { # print T("The two revisions are the same."), $q->br(); # } elsif (!UserCanEdit($id, 1)) { # print Ts('Editing not allowed for %s.', $id), $q->br(); # } elsif (not UserIsEditor() and my $rule = BannedContent($text)) { # print Ts('Rollback of %s would restore banned content.', $id), $rule, $q->br(); # } else { # Save($id, $text, Ts('Rollback to %s', TimeToText($to)), $minor, ($Page{ip} ne $ENV{REMOTE_ADDR})); # print Ts('%s rolled back', GetPageLink($id)), ($ts ? ' ' . Ts('to %s', TimeToText($to)) : ''), $q->br(); # } # } # WriteRcLog('[[rollback]]', '', $to); # leave marker # ReleaseLock(); # }); # 1319660883