forked from github/kensanata.oddmuse
Compare commits
33 Commits
2.3.6
...
as/looking
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7db436f00 | ||
|
|
14c33c5a9a | ||
|
|
0bd2afe4e1 | ||
|
|
0a9ff1b723 | ||
|
|
2dab06f905 | ||
|
|
8c143393e3 | ||
|
|
8255303d95 | ||
|
|
cb00e7e969 | ||
|
|
1b2fe0d713 | ||
|
|
8e73f6f0dd | ||
|
|
d3c7b45ad9 | ||
|
|
fee15fd880 | ||
|
|
196b960b47 | ||
|
|
241a88ef48 | ||
|
|
fdf0c2711b | ||
|
|
239a95e683 | ||
|
|
d3205d2425 | ||
|
|
681ba8068c | ||
|
|
d5429d276f | ||
|
|
746b10be81 | ||
|
|
b9aa27e406 | ||
|
|
00cf277156 | ||
|
|
75ce7d745e | ||
|
|
ee1bbca5c9 | ||
|
|
0effc86620 | ||
|
|
8a36970b24 | ||
|
|
8be87ede99 | ||
|
|
d61dd71627 | ||
|
|
755f742088 | ||
|
|
0107e41123 | ||
|
|
e58c8c2192 | ||
|
|
ee4518da9e | ||
|
|
64e7183896 |
4
Makefile
4
Makefile
@@ -19,6 +19,10 @@ build:
|
||||
|
||||
clean:
|
||||
rm -rf build
|
||||
prove t/setup.pl
|
||||
|
||||
release:
|
||||
perl stuff/release ~/oddmuse.org
|
||||
|
||||
build/wiki.pl: wiki.pl
|
||||
perl -lne "s/(\\\$$q->a\({-href=>'http:\/\/www.oddmuse.org\/'}, 'Oddmuse'\))/\\\$$q->a({-href=>'http:\/\/git.savannah.gnu.org\/cgit\/oddmuse.git\/tag\/?id=$(VERSION_NO)'}, 'wiki.pl') . ' ($(VERSION_NO)), see ' . \$$1/; print" < $< > $@
|
||||
|
||||
14
contrib/campaignwiki/delete.sh
Executable file
14
contrib/campaignwiki/delete.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
if test -z "$2" -o ! -z "$3"; then
|
||||
echo "Usage: delete.sh USERNAME WIKI"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
username=$1
|
||||
wiki=$2
|
||||
|
||||
for p in $(curl "https://campaignwiki.org/wiki/$wiki?action=index;raw=1"); do
|
||||
echo "Deleting: $p"
|
||||
curl -F frodo=1 -F "title=$p" -F text=DeletedPage -F summary=Deleted -F username="$username" "https://campaignwiki.org/wiki/$wiki"
|
||||
sleep 5
|
||||
done
|
||||
131
contrib/no-flickr.pl
Normal file
131
contrib/no-flickr.pl
Normal file
@@ -0,0 +1,131 @@
|
||||
#! /usr/bin/perl -w
|
||||
|
||||
# Copyright (C) 2005-2016 Alex Schroeder <alex@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use Modern::Perl;
|
||||
use LWP::UserAgent;
|
||||
use utf8;
|
||||
binmode(STDOUT, ":utf8");
|
||||
|
||||
my $ua = LWP::UserAgent->new;
|
||||
|
||||
sub url_encode {
|
||||
my $str = shift;
|
||||
return '' unless $str;
|
||||
utf8::encode($str); # turn to byte string
|
||||
my @letters = split(//, $str);
|
||||
my %safe = map {$_ => 1} ('a' .. 'z', 'A' .. 'Z', '0' .. '9', '-', '_', '.', '!', '~', '*', "'", '(', ')', '#');
|
||||
foreach my $letter (@letters) {
|
||||
$letter = sprintf("%%%02x", ord($letter)) unless $safe{$letter};
|
||||
}
|
||||
return join('', @letters);
|
||||
}
|
||||
|
||||
sub get_raw {
|
||||
my $uri = shift;
|
||||
my $response = $ua->get($uri);
|
||||
return $response->content if $response->is_success;
|
||||
}
|
||||
|
||||
sub get_wiki_page {
|
||||
my ($wiki, $id, $password) = @_;
|
||||
my $parameters = [
|
||||
pwd => $password,
|
||||
action => 'browse',
|
||||
id => $id,
|
||||
raw => 1,
|
||||
];
|
||||
my $response = $ua->post($wiki, $parameters);
|
||||
return $response->decoded_content if $response->is_success;
|
||||
die "Getting $id returned " . $response->status_line;
|
||||
}
|
||||
|
||||
sub get_wiki_index {
|
||||
my $wiki = shift;
|
||||
my $parameters = [
|
||||
search => "flickr.com",
|
||||
context => 0,
|
||||
raw => 1,
|
||||
];
|
||||
my $response = $ua->post($wiki, $parameters);
|
||||
return $response->decoded_content if $response->is_success;
|
||||
die "Getting the index returned " . $response->status_line;
|
||||
}
|
||||
|
||||
sub post_wiki_page {
|
||||
my ($wiki, $id, $username, $password, $text) = @_;
|
||||
my $parameters = [
|
||||
username => $username,
|
||||
pwd => $password,
|
||||
recent_edit => 'on',
|
||||
text => $text,
|
||||
title => $id,
|
||||
];
|
||||
my $response = $ua->post($wiki, $parameters);
|
||||
die "Posting to $id returned " . $response->status_line unless $response->code == 302;
|
||||
}
|
||||
|
||||
my %seen = ();
|
||||
|
||||
sub write_flickr {
|
||||
my ($id, $flickr, $dir, $file) = @_;
|
||||
say "Found $flickr";
|
||||
warn "$file was seen before: " . $seen{$file} if $seen{$file};
|
||||
die "$file contains unknown characters" if $file =~ /[^a-z0-9_.]/;
|
||||
$seen{$file} = "$id used $flickr";
|
||||
my $bytes = get_raw($flickr) or die("No data for $id");
|
||||
open(my $fh, '>', "$dir/$file") or die "Cannot write $dir/$file";
|
||||
binmode($fh);
|
||||
print $fh $bytes;
|
||||
close($fh);
|
||||
}
|
||||
|
||||
sub convert_page {
|
||||
my ($wiki, $pics, $dir, $username, $password, $id) = @_;
|
||||
say $id;
|
||||
my $text = get_wiki_page($wiki, $id, $password);
|
||||
my $is_changed = 0;
|
||||
while ($text =~ m!(https://[a-z0-9.]+.flickr.com/(?:[a-z0-9.]+/)?([a-z0-9_]+\.(?:jpg|png)))!) {
|
||||
my $flickr = $1;
|
||||
my $file = $2;
|
||||
write_flickr($id, $flickr, $dir, $file);
|
||||
$is_changed = 1;
|
||||
my $re = quotemeta($flickr);
|
||||
$text =~ s!$flickr!$pics/$file!g;
|
||||
}
|
||||
if ($is_changed) {
|
||||
post_wiki_page($wiki, $id, $username, $password, $text);
|
||||
} else {
|
||||
# die "$id has no flickr matches?\n$text";
|
||||
}
|
||||
sleep(5);
|
||||
}
|
||||
|
||||
sub convert_site {
|
||||
my ($wiki, $pics, $dir, $username, $password) = @_;
|
||||
my @ids = split(/\n/, get_wiki_index($wiki));
|
||||
for my $id (@ids) {
|
||||
convert_page($wiki, $pics, $dir, $username, $password, $id);
|
||||
}
|
||||
}
|
||||
|
||||
our $AdminPass;
|
||||
do "/home/alex/password.pl";
|
||||
convert_site('https://alexschroeder.ch/wiki',
|
||||
'https://alexschroeder.ch/pics',
|
||||
'/home/alex/alexschroeder.ch/pics',
|
||||
'Alex Schroeder',
|
||||
$AdminPass);
|
||||
@@ -38,9 +38,10 @@
|
||||
;;; Code:
|
||||
|
||||
(eval-when-compile
|
||||
(require 'cl)
|
||||
(require 'sgml-mode)
|
||||
(require 'skeleton))
|
||||
'(progn
|
||||
(require 'cl)
|
||||
(require 'sgml-mode)
|
||||
(require 'skeleton)))
|
||||
|
||||
(require 'goto-addr); URL regexp
|
||||
(require 'info); link face
|
||||
@@ -257,24 +258,6 @@ Example:
|
||||
(defvar oddmuse-revision nil
|
||||
"A variable to bind dynamically when calling `oddmuse-format-command'.")
|
||||
|
||||
(defun oddmuse-revision-put (wiki page rev)
|
||||
"Store REV for WIKI and PAGE in `oddmuse-revisions'."
|
||||
(let ((w (assoc wiki oddmuse-revisions)))
|
||||
(unless w
|
||||
(setq w (list wiki)
|
||||
oddmuse-revisions (cons w oddmuse-revisions)))
|
||||
(let ((p (assoc page w)))
|
||||
(unless p
|
||||
(setq p (list page))
|
||||
(setcdr w (cons p (cdr w))))
|
||||
(setcdr p rev))))
|
||||
|
||||
(defun oddmuse-revision-get (wiki page)
|
||||
"Get revision for WIKI and PAGE in `oddmuse-revisions'."
|
||||
(let ((w (assoc wiki oddmuse-revisions)))
|
||||
(when w
|
||||
(cdr (assoc page w)))))
|
||||
|
||||
;;; Helpers
|
||||
|
||||
(defsubst oddmuse-page-name (file)
|
||||
@@ -300,7 +283,7 @@ Example:
|
||||
(defun oddmuse-url (wiki pagename)
|
||||
"Get the URL of oddmuse wiki."
|
||||
(condition-case v
|
||||
(concat (or (cadr (assoc wiki oddmuse-wikis)) (error)) "/"
|
||||
(concat (or (cadr (assoc wiki oddmuse-wikis)) (error "Wiki not found in `oddmuse-wikis'")) "/"
|
||||
(url-hexify-string pagename))
|
||||
(error nil)))
|
||||
|
||||
@@ -534,7 +517,7 @@ as well."
|
||||
((string-match "<title>Error</title>" status)
|
||||
(if (string-match "<h1>\\(.*\\)</h1>" status)
|
||||
(error "Error %s: %s" mesg (match-string 1 status))
|
||||
(error "Error %s: Cause unknown")))
|
||||
(error "Error %s: Cause unknown" status)))
|
||||
(t
|
||||
(message "%s...done" mesg))))))
|
||||
|
||||
@@ -736,7 +719,7 @@ Font-locking is controlled by `oddmuse-markup-functions'.
|
||||
(set (make-local-variable 'sgml-tag-alist)
|
||||
`(("b") ("code") ("em") ("i") ("strong") ("nowiki")
|
||||
("pre" \n) ("tt") ("u")))
|
||||
(set (make-local-variable 'skeleton-transformation) 'identity)
|
||||
(set (make-local-variable 'skeleton-transformation-function) 'identity)
|
||||
|
||||
(make-local-variable 'oddmuse-wiki)
|
||||
(make-local-variable 'oddmuse-page-name)
|
||||
@@ -854,11 +837,8 @@ people have been editing the wiki in the mean time."
|
||||
(set-buffer (get-buffer-create name))
|
||||
(erase-buffer); in case of current-prefix-arg
|
||||
(oddmuse-run "Loading" oddmuse-get-command wiki pagename)
|
||||
(oddmuse-revision-put wiki pagename (oddmuse-get-latest-revision wiki pagename))
|
||||
;; fix mode-line for VC in the new buffer because this is not a vc-checkout
|
||||
(setq buffer-file-name (concat oddmuse-directory "/" wiki "/" pagename))
|
||||
(vc-mode-line buffer-file-name 'oddmuse)
|
||||
(pop-to-buffer (current-buffer))
|
||||
(vc-working-revision buffer-file-name 'oddmuse)
|
||||
;; check for a diff (this ends with display-buffer) and bury the
|
||||
;; buffer if there are no hunks
|
||||
(when (file-exists-p buffer-file-name)
|
||||
@@ -869,7 +849,9 @@ people have been editing the wiki in the mean time."
|
||||
;; this also changes the buffer name
|
||||
(basic-save-buffer)
|
||||
;; this makes sure that the buffer name is set correctly
|
||||
(oddmuse-mode))))
|
||||
(oddmuse-mode)
|
||||
;; fix mode-line for VC in the new buffer because this is not a vc-checkout
|
||||
(vc-mode-line buffer-file-name 'oddmuse))))
|
||||
|
||||
(defalias 'oddmuse-go 'oddmuse-edit)
|
||||
|
||||
@@ -909,8 +891,11 @@ Use a prefix argument to override this."
|
||||
(and buffer-file-name (basic-save-buffer))
|
||||
(oddmuse-run "Posting" oddmuse-post-command nil nil
|
||||
(get-buffer-create " *oddmuse-response*") t 302)
|
||||
(oddmuse-revision-put oddmuse-wiki oddmuse-page-name
|
||||
(oddmuse-get-latest-revision oddmuse-wiki oddmuse-page-name)))
|
||||
;; force reload
|
||||
(vc-file-setprop buffer-file-name 'vc-working-revision
|
||||
(oddmuse-get-latest-revision oddmuse-wiki oddmuse-page-name))
|
||||
;; fix mode-line for VC in the new buffer because this is not a vc-checkout
|
||||
(vc-mode-line buffer-file-name 'oddmuse))
|
||||
|
||||
;;;###autoload
|
||||
(defun oddmuse-preview (&optional arg)
|
||||
|
||||
@@ -47,7 +47,8 @@ For a list of possible values, see `vc-state'."
|
||||
|
||||
(defun vc-oddmuse-working-revision (file)
|
||||
"The current revision based on `oddmuse-revisions'."
|
||||
(oddmuse-revision-get oddmuse-wiki oddmuse-page-name))
|
||||
(with-oddmuse-file
|
||||
(oddmuse-get-latest-revision wiki pagename)))
|
||||
|
||||
(defun vc-oddmuse-checkout-model (files)
|
||||
"No locking."
|
||||
@@ -59,10 +60,6 @@ For a list of possible values, see `vc-state'."
|
||||
(defun vc-oddmuse-register (files &optional rev comment)
|
||||
"This always works.")
|
||||
|
||||
(defun vc-oddmuse-revert (file &optional contents-done)
|
||||
"No idea"
|
||||
nil)
|
||||
|
||||
(defvar vc-oddmuse-log-command
|
||||
(concat "curl --silent %w"
|
||||
" --form action=rc"
|
||||
@@ -149,7 +146,7 @@ a version backup."
|
||||
(with-oddmuse-file file
|
||||
(let ((command (oddmuse-format-command vc-oddmuse-get-revision-command)))
|
||||
(with-temp-buffer
|
||||
(oddmuse-run "Loading" command)
|
||||
(oddmuse-run "Loading" command wiki pagename)
|
||||
(write-file file))))))
|
||||
|
||||
(defun vc-oddmuse-checkin (files rev comment)
|
||||
|
||||
536
css/alex-2016.css
Normal file
536
css/alex-2016.css
Normal file
@@ -0,0 +1,536 @@
|
||||
/* This file is in the public domain. */
|
||||
html{ text-align: center; }
|
||||
|
||||
body, rss {
|
||||
font-family: "Palatino Linotype", "Book Antiqua", Palatino, serif;
|
||||
font-style: normal;
|
||||
font-size: 14pt;
|
||||
padding: 1em 3em;
|
||||
max-width: 72ex;
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
color: #000;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
@media print {
|
||||
body {
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
/* hide all the crap */
|
||||
div.diff, div.diff+hr, div.refer, div.near, div.definition, div.sister,
|
||||
div.cal, div.footer, span.specialdays, span.gotobar, a.edit, a.number span,
|
||||
div.rc form, form.tiny, p.comment, p#plus1, div.g-plusone, div.content a.feed {
|
||||
display:none;
|
||||
}
|
||||
div.content a.book,
|
||||
div.content a.movie {
|
||||
text-decoration: none;
|
||||
}
|
||||
a cite {
|
||||
font-style: italic;
|
||||
}
|
||||
img[alt="RSS"] { display: none }
|
||||
a.rss { font-size: 8pt }
|
||||
}
|
||||
|
||||
/* headings: we can use larger sizes if we use a lighter color.
|
||||
we cannot inherit the font-family because header and footer use a narrow font. */
|
||||
|
||||
h1, h2, h3, title {
|
||||
font-family: inherit;
|
||||
font-weight: normal;
|
||||
}
|
||||
h1, channel title {
|
||||
font-size: 32pt;
|
||||
margin: 1em 0 0.5em 0;
|
||||
padding: 0.4em 0;
|
||||
}
|
||||
h2 {
|
||||
font-size: 18pt;
|
||||
margin: 2em 0 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
h3 {
|
||||
font-size: inherit;
|
||||
font-weight: bold;
|
||||
padding: 0;
|
||||
margin: 1em 0 0 0;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* headers in the journal are smaller */
|
||||
|
||||
div.journal h1, item title {
|
||||
font-size: inherit;
|
||||
padding: 0;
|
||||
clear: both;
|
||||
border-bottom: 1px solid #000;
|
||||
}
|
||||
div.journal h2 {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
div.journal h3 {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
font-style: italic;
|
||||
}
|
||||
div.journal hr {
|
||||
visibility: hidden;
|
||||
}
|
||||
p.more {
|
||||
margin-top: 3em;
|
||||
}
|
||||
/* Links in headings appear on journal pages. */
|
||||
|
||||
h1 a, h2 a, h3 a {
|
||||
color:inherit;
|
||||
text-decoration:none;
|
||||
font-weight: normal;
|
||||
}
|
||||
h1 a:visited, h2 a:visited, h3 a:visited {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
/* for download buttons and the like */
|
||||
|
||||
.button {
|
||||
display: inline-block;
|
||||
font-size: 120%;
|
||||
cursor: pointer;
|
||||
padding: 0.4em 0.6em;
|
||||
text-shadow: 0px -1px 0px #ccc;
|
||||
background-color: #cfa;
|
||||
border: 1px solid #9d8;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0px 1px 3px white inset, 0px 1px 3px black;
|
||||
}
|
||||
|
||||
.button .icon {
|
||||
color: #363;
|
||||
text-shadow: 0px -1px 1px white, 0px 1px 3px #666;
|
||||
}
|
||||
|
||||
.button a {
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
/* links */
|
||||
|
||||
a.pencil {
|
||||
padding-left: 1ex;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
visibility: hidden;
|
||||
transition: visibility 0s 1s, opacity 1s linear;
|
||||
opacity: 0;
|
||||
}
|
||||
*:hover > a.pencil {
|
||||
visibility: visible;
|
||||
transition: opacity .5s linear;
|
||||
opacity: 1;
|
||||
}
|
||||
@media print {
|
||||
a.pencil {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
a.number {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* stop floating content from flowing over the footer */
|
||||
|
||||
hr {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* the distance between links in the navigation bars */
|
||||
|
||||
span.bar a {
|
||||
margin-right: 1ex;
|
||||
}
|
||||
|
||||
a img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* search box in the top bar */
|
||||
|
||||
.header form, .header p {
|
||||
display: inline;
|
||||
white-space: nowrap;
|
||||
}
|
||||
label[for="searchlang"], #searchlang, .header input[type="submit"] {
|
||||
/* don't use display: none! http://stackoverflow.com/questions/5665203/getting-iphone-go-button-to-submit-form */
|
||||
visibility: hidden; position: absolute;
|
||||
}
|
||||
/* wrap on the iphone */
|
||||
@media only screen and (max-device-width: 480px) {
|
||||
}
|
||||
|
||||
.header input {
|
||||
width: 10ex;
|
||||
}
|
||||
|
||||
/* other form fields */
|
||||
|
||||
input[type="text"] {
|
||||
padding: 0;
|
||||
font-size: 80%;
|
||||
line-height: 125%;
|
||||
}
|
||||
|
||||
/* code */
|
||||
|
||||
textarea, pre, code, tt {
|
||||
font-family: "Andale Mono", Monaco, "Courier New", Courier, monospace, "Symbola";
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow:hidden;
|
||||
white-space: pre-wrap; /* CSS 3 */
|
||||
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
|
||||
white-space: -pre-wrap; /* Opera 4-6 */
|
||||
white-space: -o-pre-wrap; /* Opera 7 */
|
||||
word-wrap: break-word; /* Internet Explorer 5.5+ */
|
||||
}
|
||||
|
||||
/* styling for divs that will be invisible when printing
|
||||
when printing. */
|
||||
|
||||
div.header, div.footer, div.near, div.definition, p.comment, a.tag {
|
||||
|
||||
font-size: 14pt;
|
||||
}
|
||||
@media print {
|
||||
div.header, div.footer, div.near, div.definition, p.comment, a.tag {
|
||||
font-size: 8pt;
|
||||
}
|
||||
}
|
||||
|
||||
div.footer form.search {
|
||||
display: none;
|
||||
}
|
||||
div.rc li + li {
|
||||
margin-top: 1em;
|
||||
}
|
||||
div.rc li strong, table.history strong, strong.description {
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
}
|
||||
div.diff {
|
||||
padding-left: 5%;
|
||||
padding-right: 5%;
|
||||
font-size: 12pt;
|
||||
color: #000;
|
||||
|
||||
}
|
||||
div.old {
|
||||
background-color: #ffffaf;
|
||||
}
|
||||
div.new {
|
||||
background-color: #cfffcf;
|
||||
}
|
||||
|
||||
div.refer {
|
||||
padding-left: 5%;
|
||||
padding-right: 5%;
|
||||
font-size: 12pt;
|
||||
}
|
||||
|
||||
div.message {
|
||||
background-color:#fee;
|
||||
color:#000;
|
||||
}
|
||||
|
||||
img.xml {
|
||||
border:none;
|
||||
padding:1px;
|
||||
}
|
||||
a.small img {
|
||||
max-width:300px;
|
||||
}
|
||||
a.large img {
|
||||
max-width:600px;
|
||||
}
|
||||
div.sister {
|
||||
margin-right:1ex;
|
||||
background-color:inherit;
|
||||
}
|
||||
div.sister p {
|
||||
margin-top:0;
|
||||
}
|
||||
div.sister hr {
|
||||
display:none;
|
||||
}
|
||||
div.sister img {
|
||||
border:none;
|
||||
}
|
||||
|
||||
div.near, div.definition {
|
||||
background-color:#efe;
|
||||
}
|
||||
|
||||
div.sidebar {
|
||||
float:right;
|
||||
border:1px dotted #000;
|
||||
padding:0 1em;
|
||||
}
|
||||
div.sidebar ul {
|
||||
padding-left:1em;
|
||||
}
|
||||
|
||||
/* replacements, features */
|
||||
|
||||
ins {
|
||||
font-style: italic;
|
||||
text-decoration: none;
|
||||
}
|
||||
acronym, abbr {
|
||||
letter-spacing:0.1em;
|
||||
font-variant:small-caps;
|
||||
}
|
||||
|
||||
/* Interlink prefix not shown */
|
||||
a .site, a .separator {
|
||||
display: none;
|
||||
}
|
||||
a cite { font:inherit; }
|
||||
/* browser borkage */
|
||||
textarea[name="text"] { width:97%; height:80%; }
|
||||
textarea[name="summary"] { width:97%; height:3em; }
|
||||
/* comments */
|
||||
textarea[name="aftertext"] { width:97%; height:10em; }
|
||||
div.commentshown {
|
||||
font-size: 12pt;
|
||||
padding: 2em 0;
|
||||
}
|
||||
div.commenthidden {
|
||||
display:none;
|
||||
}
|
||||
div.commentshown {
|
||||
display:block;
|
||||
}
|
||||
p.comment {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
div.comment {
|
||||
font-size: 14pt;
|
||||
}
|
||||
div.comment h2 {
|
||||
margin-top: 5em;
|
||||
}
|
||||
/* comment pages with username, homepage, and email subscription */
|
||||
.comment form span { display: block; }
|
||||
.comment form span label { display: inline-block; width: 10em; }
|
||||
/* IE sucks */
|
||||
.comment input#username,
|
||||
.comment input#homepage,
|
||||
.comment input#mail { width: 20em; }
|
||||
|
||||
/* cal */
|
||||
div.month { padding:0; margin:0 2ex; }
|
||||
body > div.month {
|
||||
float:right;
|
||||
background-color: inherit;
|
||||
border:solid thin;
|
||||
padding:0 1ex;
|
||||
}
|
||||
.year > .month {
|
||||
float:left;
|
||||
}
|
||||
.footer {
|
||||
clear:both;
|
||||
}
|
||||
.month .title a.local {
|
||||
background-color: inherit;
|
||||
}
|
||||
.month a.local {
|
||||
background-color: #ddf;
|
||||
}
|
||||
.month a.today {
|
||||
background-color: #fdd;
|
||||
}
|
||||
.month a {
|
||||
color:inherit;
|
||||
font-weight:inherit;
|
||||
text-decoration: none;
|
||||
background-color: #eee;
|
||||
}
|
||||
/* history tables and other tables */
|
||||
table.history {
|
||||
border: none;
|
||||
}
|
||||
td.history {
|
||||
border: none;
|
||||
}
|
||||
|
||||
table.user {
|
||||
border: none;
|
||||
border-top: 1px solid #ccc;
|
||||
border-bottom: 1px solid #ccc;
|
||||
padding: 1em;
|
||||
margin: 1em 2em;
|
||||
}
|
||||
table.user tr td, table.user tr th {
|
||||
border: none;
|
||||
padding: 0.2em 0.5em;
|
||||
vertical-align: top;
|
||||
}
|
||||
table.arab tr th {
|
||||
font-weight:normal;
|
||||
text-align:left;
|
||||
vertical-align:top;
|
||||
}
|
||||
table.arab, table.arab tr th, table.arab tr td {
|
||||
border:none;
|
||||
}
|
||||
th.nobreak {
|
||||
white-space:nowrap;
|
||||
}
|
||||
table.full { width:99%; margin-left:1px; }
|
||||
table.j td, table.j th, table tr td.j, table tr th.j, .j { text-align:justify; }
|
||||
table.l td, table.l th, table tr td.l, table tr th.l, .l { text-align:left; }
|
||||
table.r td, table.r th, table tr td.r, table tr th.r, .r { text-align:right; }
|
||||
table.c td, table.c th, table tr td.c, table tr th.c, .c { text-align:center; }
|
||||
table.t td { vertical-align: top; }
|
||||
td.half { width:50%; }
|
||||
td.third { width:33%; }
|
||||
|
||||
form table td { padding:5px; }
|
||||
|
||||
/* lists */
|
||||
dd { padding-bottom:0.5ex; }
|
||||
dl.inside dt { float:left; }
|
||||
/* search */
|
||||
div.search span.result { font-size:larger; }
|
||||
div.search span.info { font-size:smaller; font-style:italic; }
|
||||
div.search p.result { display:none; }
|
||||
|
||||
img.logo {
|
||||
float: right;
|
||||
margin: 0 0 0 1ex;
|
||||
padding: 0;
|
||||
border: 1px solid #000;
|
||||
opacity: 0.3;
|
||||
background-color:#ffe;
|
||||
}
|
||||
|
||||
/* images */
|
||||
|
||||
div.content a.feed img, div.journal a.feed img,
|
||||
div.content a img.smiley, div.journal a img.smiley, img.smiley,
|
||||
div.content a.inline img, div.journal a.inline img,
|
||||
div.content li a.image img, div.journal li a.image img {
|
||||
margin: 0; padding: 0; border: none;
|
||||
}
|
||||
div.image a img {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
div.image span.caption {
|
||||
margin: 0 1em;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.left { float:left; margin-right: 1em; }
|
||||
.right { float:right; margin-left: 1em; }
|
||||
.half img { height: 50%; width: 50%; }
|
||||
.face img { width: 200px; }
|
||||
div.left .left, div.right .right {
|
||||
float:none;
|
||||
}
|
||||
.center { text-align:center; }
|
||||
table.aside {
|
||||
float:right;
|
||||
width:40%;
|
||||
margin-left: 1em;
|
||||
padding: 1ex;
|
||||
border: 1px dotted #666;
|
||||
}
|
||||
table.aside td {
|
||||
text-align:left;
|
||||
}
|
||||
div.sidebar {
|
||||
float:right; width: 250px;
|
||||
text-align: right;
|
||||
border: none;
|
||||
margin: 1ex;
|
||||
}
|
||||
|
||||
.bigsidebar {
|
||||
float:right;
|
||||
width: 500px;
|
||||
border: none;
|
||||
margin-left: 1ex;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
dl.irc dt { width:20ex; float:left; text-align:right; clear:left; }
|
||||
dl.irc dt span.time { float:left; }
|
||||
dl.irc dd { margin-left:22ex; }
|
||||
|
||||
/* portrait */
|
||||
|
||||
div.footer, div.comment, hr { clear: both; }
|
||||
.portrait { float: left; font-size: small; margin-right: 1em; }
|
||||
.portrait a { color: #999; }
|
||||
|
||||
div.left { float:left; margin:1em; padding: 0.5em; }
|
||||
div.left p { display:table-cell; }
|
||||
div.left p + p { display:table-caption; caption-side:bottom; }
|
||||
|
||||
p.table a { float:left; width:20ex; }
|
||||
p.table + p { clear:both; }
|
||||
|
||||
/* rss */
|
||||
|
||||
channel * { display: block; }
|
||||
|
||||
channel title {
|
||||
margin-top: 30pt;
|
||||
}
|
||||
copyright {
|
||||
font-size: 14pt;
|
||||
margin-top: 1em;
|
||||
}
|
||||
channel > link:before {
|
||||
font-size: 18pt;
|
||||
display: block;
|
||||
margin: 1em;
|
||||
padding: 0.5em;
|
||||
content: "This is an RSS feed, designed to be read in a feed reader.";
|
||||
color: red;
|
||||
border: 1px solid red;
|
||||
}
|
||||
link, license {
|
||||
font-size: 11pt;
|
||||
margin-bottom: 9pt;
|
||||
}
|
||||
username:before { content: "Last edited by "; }
|
||||
username:after { content: "."; }
|
||||
generator:before { content: "Feed generated by "; }
|
||||
generator:after { content: "."; }
|
||||
channel description {
|
||||
font-weight: bold;
|
||||
}
|
||||
item description {
|
||||
font-style: italic;
|
||||
font-weight: normal;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
docs, language,
|
||||
pubDate, lastBuildDate, ttl, guid, category, comments,
|
||||
docs, image title, image link,
|
||||
status, version, diff, history, importance {
|
||||
display: none;
|
||||
}
|
||||
@@ -201,6 +201,7 @@ div.message {
|
||||
}
|
||||
table.history { border-style:none; }
|
||||
td.history { border-style:none; }
|
||||
div.history span.dash + strong { font-weight: normal; }
|
||||
span.result { font-size:larger; }
|
||||
span.info { font-size:smaller; font-style:italic; }
|
||||
div.rc hr { display: none; }
|
||||
|
||||
@@ -29,6 +29,7 @@ our %TranslationsLibrary = (
|
||||
'bg' => 'bulgarian-utf8.pl',
|
||||
'ca' => 'catalan-utf8.pl',
|
||||
'de' => 'german-utf8.pl',
|
||||
'et' => 'estonian-utf8.pl',
|
||||
'es' => 'spanish-utf8.pl',
|
||||
'fi' => 'finnish-utf8.pl',
|
||||
'fr' => 'french-utf8.pl',
|
||||
@@ -72,6 +73,7 @@ sub LoadLanguage {
|
||||
foreach (@prefs) {
|
||||
last if $Lang{$_} eq 'en'; # the default
|
||||
my $file = $TranslationsLibrary{$Lang{$_}};
|
||||
next unless $file; # file is not listed, eg. there is no file for "de-ch"
|
||||
$file = "$LoadLanguageDir/$file" if defined $LoadLanguageDir;
|
||||
if (-r $file) {
|
||||
do $file;
|
||||
|
||||
@@ -137,13 +137,8 @@ sub NamespacesInitVariables {
|
||||
$StaticUrl .= UrlEncode($NamespaceCurrent) . '/'
|
||||
if substr($StaticUrl,-1) eq '/'; # from static-copy.pl
|
||||
$WikiDescription .= "<p>Current namespace: $NamespaceCurrent</p>";
|
||||
# override LastUpdate
|
||||
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks)
|
||||
= stat($IndexFile);
|
||||
$LastUpdate = $mtime;
|
||||
CreateDir($DataDir); # Create directory if it doesn't exist
|
||||
ReportError(Ts('Cannot create %s', $DataDir) . ": $!", '500 INTERNAL SERVER ERROR')
|
||||
unless -d $DataDir;
|
||||
$LastUpdate = (stat($IndexFile))[9];
|
||||
CreateDir($DataDir);
|
||||
}
|
||||
$Namespaces{$NamespacesSelf} = $ScriptName . '?';
|
||||
# reinitialize
|
||||
|
||||
@@ -154,7 +154,7 @@ sub PageContentToTitle {
|
||||
$title =~ s!\s+! !g;
|
||||
$title =~ s!^ !!;
|
||||
$title =~ s! $!!;
|
||||
$title = substring($title, 0, $RefererTitleLimit) . "..."
|
||||
$title = substr($title, 0, $RefererTitleLimit) . "..."
|
||||
if length($title) > $RefererTitleLimit;
|
||||
return $title;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ sub StaticScriptLink {
|
||||
my %params;
|
||||
if ($action !~ /=/) {
|
||||
# the page might not exist, eg. if called via GetAuthorLink
|
||||
$params{-href} = StaticFileName($action) if $IndexHash{$action};
|
||||
$params{'-href'} = StaticFileName($action) if $IndexHash{UrlDecode($action)};
|
||||
}
|
||||
$params{'-class'} = $class if $class;
|
||||
$params{'-name'} = UrlEncode($name) if $name;
|
||||
|
||||
1669
modules/translations/estonian-utf8.pl
Normal file
1669
modules/translations/estonian-utf8.pl
Normal file
File diff suppressed because it is too large
Load Diff
162
modules/translations/national-days-es.pl
Normal file
162
modules/translations/national-days-es.pl
Normal file
@@ -0,0 +1,162 @@
|
||||
# Copyright (C) 2016 Alex Schroeder <alex@gnu.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# The source for the data is unknown.
|
||||
|
||||
use utf8;
|
||||
use strict;
|
||||
|
||||
AddModuleDescription('national-days-de.pl', 'Special Days') if defined &AddModuleDescription;
|
||||
|
||||
our %SpecialDays = (
|
||||
'1-1' => 'Sudán, Día Nacional, Haití, Día de Independencia, Cuba, Día de Liberación',
|
||||
'1-4' => 'Myanmar, Día de Independencia',
|
||||
'1-9' => 'Islas de Mariana del Norte, Día Nacional',
|
||||
'1-26' => 'Australia, Día de Australia',
|
||||
'1-31' => 'Nauru, Día Nacional',
|
||||
'2-4' => 'Sri Lanka, Día de Conmemoración de la Independencia',
|
||||
'2-6' => 'Nueva Zelanda, Día de Waitangi',
|
||||
'2-7' => 'Grenada, Día de Independencia',
|
||||
'2-11' => 'Irán, Victoria de la Revolución Islámica en Irán',
|
||||
'2-16' => 'Lituania, Día de Independencia',
|
||||
'2-18' => 'Gambia, Día Nacional',
|
||||
'2-22' => 'Santa Lucía, Día Nacional',
|
||||
'2-23' => 'Guyana, Día Nacional, Brunei Darussalam, Día Nacional',
|
||||
'2-24' => 'Estonia, Día de Independencia',
|
||||
'2-25' => 'Kuwait, Día Nacional',
|
||||
'2-27' => 'República Dominicana, Día de Independencia',
|
||||
'3-3' => 'Bulgaria, Día Nacional',
|
||||
'3-6' => 'Ghana, Día de Independencia',
|
||||
'3-12' => 'Mauritius, Día Nacional',
|
||||
'3-17' => 'Irlanda, Día de San Patricio',
|
||||
'3-20' => 'Tunisia, Aniversario de la Independencia de la República de Tunisia',
|
||||
'3-21' => 'Namibia, Día de Independencia',
|
||||
'3-23' => 'Pakistán, Día Nacional',
|
||||
'3-25' => 'Grecia, Día de Independencia',
|
||||
'3-26' => 'Bangladesh, Día de Independencia',
|
||||
'4-4' => 'Senegal, Día de Independencia',
|
||||
'4-16' => 'Dinamarca, Cumpleaños de la Reina',
|
||||
'4-17' => 'Syria, Día Nacional',
|
||||
'4-18' => 'Zimbabwe, Día Nacional',
|
||||
'4-19' => 'Sierra Leona, Día de la República',
|
||||
'4-26' => 'Tanzania, Día de la Unión, Israel, Día de Independencia',
|
||||
'4-27' => 'República Federal de Yugoslavia, Día Nacional, Togo, Togolais Día Nacional, Suráfrica, Día de la Libertad',
|
||||
'4-30' => 'Los Países Bajos, Cumpleaños Oficial de Su Majestad la Reina Beatriz',
|
||||
'5-1' => 'Islas Marshall, Día Nacional',
|
||||
'5-3' => 'Polonia, Día Nacional',
|
||||
'5-9' => 'Unión Europea, Día de Europa',
|
||||
'5-14' => 'Paraguay, Día Nacional',
|
||||
'5-17' => 'Noruega, Día de la Constitución',
|
||||
'5-20' => 'Camerún, Día Nacional',
|
||||
'5-22' => 'Yemen, Día Nacional',
|
||||
'5-24' => 'Eritrea, Día de Independencia',
|
||||
'5-25' => 'Jordania, Día de Independencia, Argentina, Día Nacional',
|
||||
'5-26' => 'Georgia, Día Nacional',
|
||||
'5-28' => 'Etiopía, Día Nacional, Azerbaijan, Día Nacional',
|
||||
'6-1' => 'Samoa, Día de Independencia',
|
||||
'6-2' => 'Italia, Fundación de la República',
|
||||
'6-4' => 'Tonga, Día de Emancipación',
|
||||
'6-6' => 'Suecia, Día Nacional',
|
||||
'6-10' => 'Portugal, Día de Portugal, Día de Camões y Día de las Comunidades Portuguesas',
|
||||
'6-12' => 'Filipinas, Día de Independencia, Rusia, Día Nacional',
|
||||
'6-17' => 'Islandia, Día Nacional',
|
||||
'6-18' => 'Seychelles, Día Nacional',
|
||||
'6-23' => 'Luxemburgo, Día Nacional y Cumpleaños Oficial de H.R.H. el Gran Duque',
|
||||
'6-25' => 'Croacia, Día Nacional, Eslovenia, Día Nacional, Mozambique, Día de Independencia',
|
||||
'6-26' => 'Madagascar, Día Nacional',
|
||||
'6-27' => 'Djibouti, Día de Independencia',
|
||||
'6-30' => 'República Democrática del Congo, Día de Independencia',
|
||||
'7-1' => 'Burundi, Día Nacional, Canadá, Día de Canadá',
|
||||
'7-3' => 'Belarus, Día Nacional',
|
||||
'7-4' => 'Estados Unidos de América, Día de Independencia',
|
||||
'7-5' => 'Rwanda, Día de Liberación, Cape Verde, Día Nacional, Venezuela, Día Nacional',
|
||||
'7-6' => 'Malawi, Día Nacional, Comoros, Día Nacional',
|
||||
'7-7' => 'Nepal, Cumpleaños del Rey y Día Nacional, Islas Solomon, Día Nacional',
|
||||
'7-10' => 'Bahamas, Día de Independencia',
|
||||
'7-11' => 'Mongolia, Aniversario de la Revolución de las Gentes de Mongolia',
|
||||
'7-12' => 'Sao Tome & Principe, Día Nacional, Kiribati, Día Nacional',
|
||||
'7-14' => 'Francia, Día de Bastillas',
|
||||
'7-17' => 'Irak, Día Nacional',
|
||||
'7-20' => 'Colombia, Día Nacional',
|
||||
'7-21' => 'Bélgica, Ascenso del Rey Leopoldo I (1831)',
|
||||
'7-23' => 'Egipto, Aniversario de la Revolución',
|
||||
'7-26' => 'Liberia, Día Nacional, Maldives, Día Nacional',
|
||||
'7-28' => 'Perú, Día de Independencia',
|
||||
'7-30' => 'Vanuatu, Día de Independencia, Marruecos, Festival del Trono',
|
||||
'8-1' => 'Benin, Día Nacional, Suiza, Fundación de la Confederación Suiza',
|
||||
'8-4' => 'Islas Cook, Día Nacional',
|
||||
'8-5' => 'Jamaica, Día Nacional',
|
||||
'8-6' => 'Bolivia, Día de Independencia',
|
||||
'8-7' => 'Cote D\'Ivoire, Día Nacional',
|
||||
'8-9' => 'Singapur, Día Nacional',
|
||||
'8-10' => 'Ecuador, Día Nacional',
|
||||
'8-11' => 'Chad, Día Nacional',
|
||||
'8-15' => 'República de Korea, Día Nacional, Liechtenstein, Día Nacional, India, Día Nacional, República del Congo, Día de Independencia',
|
||||
'8-17' => 'Indonesia, Proclamación de Independencia, Gabon, Día Nacional',
|
||||
'8-19' => 'Afganistán, Día de Independencia',
|
||||
'8-20' => 'Hungaria, Día Nacional',
|
||||
'8-24' => 'Ucrania, Día Nacional',
|
||||
'8-25' => 'Uruguay, Día de Independencia',
|
||||
'8-27' => 'Moldova, Día Nacional',
|
||||
'8-31' => 'Kyrgyzstan, Día Nacional, Trinidad y Tobago, Día Nacional, Malasia, Día Nacional',
|
||||
'9-1' => 'Uzbekistán, Día Nacional, Eslovakia, Día de la Constitución',
|
||||
'9-2' => 'Vietnam, Día Nacional, Libyan Arab Jamahiriya, Día Nacional',
|
||||
'9-3' => 'Qatar, Día Nacional, San Marino, Día de Fundación Nacional',
|
||||
'9-6' => 'Swaziland, Día Nacional',
|
||||
'9-7' => 'Brazil, Día de Independencia',
|
||||
'9-8' => 'Andorra, Día Nacional, Antigua República de Macedonia Yugoslava, Día de Independencia',
|
||||
'9-9' => 'República Democrática de Korea, Día Nacional, Tajikistán, Día Nacional',
|
||||
'9-15' => 'Guatemala, Día de Independencia, Honduras, Día de Independencia, El Salvador, Día de Independencia, Costa Rica, Día de Independencia, Nicaragua, Día de Independencia',
|
||||
'9-16' => 'Papua Nueva Guinea, Día de Independencia, Méjico, Proclamación de Independencia',
|
||||
'9-18' => 'Chile, Día Nacional',
|
||||
'9-19' => 'St Kitts Nevis, Día de Independencia',
|
||||
'9-21' => 'Belize, Día Nacional, Malta, Día de Independencia, Armenia, Día Nacional',
|
||||
'9-22' => 'República de Mali, Proclamación de Independencia',
|
||||
'9-23' => 'Arabia Saudita, Día Nacional',
|
||||
'9-24' => 'Guinea Bissau, Día de Independencia',
|
||||
'9-30' => 'Botswana, Día Nacional',
|
||||
'10-1' => 'Guinea, Día de Independencia, China, Día Nacional, Palau, Día Nacional, Tuvalu, Día de Independencia, Cyprus, Día Nacional, Nigeria, Día Nacional',
|
||||
'10-3' => 'Alemania, Día Nacional',
|
||||
'10-4' => 'Lesotho, Día Nacional',
|
||||
'10-9' => 'Uganda, Día de Independencia',
|
||||
'10-10' => 'Fiji, Día Nacional',
|
||||
'10-12' => 'Guinea Ecuatorial, Día de Independencia, España, Día Nacional',
|
||||
'10-19' => 'Niue, Día Nacional',
|
||||
'10-22' => 'Holy See, Aniversario, Ministerio Pontífice de Su Santidad el Papa Juan Pablo II',
|
||||
'10-24' => 'Zambia, Día de Independencia',
|
||||
'10-26' => 'Austria, Día Nacional',
|
||||
'10-27' => 'Turkmenistán, Día Nacional, San Vincente y las Granadinas, Día Nacional',
|
||||
'10-28' => 'República Checa, Día Nacional',
|
||||
'10-29' => 'Turquía, Día de la República',
|
||||
'11-1' => 'Antigua y Barbuda, Día Nacional, Algeria, Aniversario de la Revolución',
|
||||
'11-3' => 'Panamá, Día Nacional, Dominica, Día Nacional, Estados Federados de Micronesia, Día Nacional',
|
||||
'11-9' => 'Cambodia, Día de Independencia',
|
||||
'11-11' => 'Angola, Día Nacional',
|
||||
'11-18' => 'Omán, Día Nacional, Latvia, Proclamación de Independencia',
|
||||
'11-19' => 'Mónaco, Día Nacional',
|
||||
'11-22' => 'Lebanon, Día de Independencia',
|
||||
'11-25' => 'Bosnia y Herzegovina, Día del Estado, Surinam, Día Nacional',
|
||||
'11-28' => 'Mauritania, Día Nacional, Albania, Día Nacional',
|
||||
'11-30' => 'Barbados, Día de Independencia',
|
||||
'12-1' => 'Rumania, Día Nacional, República de África Central, Día Nacional',
|
||||
'12-2' => 'Emiratos Árabes Unidos, Día Nacional, Laos, Día Nacional',
|
||||
'12-5' => 'Tailandia, Cumpleaños del Rey',
|
||||
'12-6' => 'Finlandia, Día de Independencia',
|
||||
'12-11' => 'Burkina Faso, Día Nacional',
|
||||
'12-12' => 'Kenya, Día de Jamhuri',
|
||||
'12-16' => 'Bahrain, Día Nacional, Kazakhstán, Día Nacional',
|
||||
'12-17' => 'Bután, Día Nacional',
|
||||
'12-18' => 'Nigeria, Día Nacional',
|
||||
'12-23' => 'Japón, Cumpleaños del Emperador',
|
||||
);
|
||||
37
server.pl
37
server.pl
@@ -1,36 +1,49 @@
|
||||
#! /usr/bin/env perl
|
||||
#!/usr/bin/env perl
|
||||
|
||||
# This script only works with a version of Mojolicious::Plugin::CGI better than
|
||||
# the official 0.23. One version would be my fork:
|
||||
# https://github.com/kensanata/mojolicious-plugin-cgi
|
||||
# Copyright (C) 2015-2016 Alex Schroeder <alex@gnu.org>
|
||||
|
||||
# If you use the fork, you might want to simply add its lib directory to your
|
||||
# libraries instead of installing it?
|
||||
|
||||
# use lib '/Users/alex/src/mojolicious-plugin-cgi/lib';
|
||||
# This program is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use Mojolicious::Lite;
|
||||
|
||||
# This needs to be in a different section, sometimes?
|
||||
plugin CGI => {
|
||||
support_semicolon_in_query_string => 1,
|
||||
};
|
||||
|
||||
|
||||
plugin CGI => {
|
||||
route => '/wiki',
|
||||
# We need this for older versions of Mojolicious::Plugin::CGI
|
||||
script => 'wiki.pl',
|
||||
run => \&OddMuse::DoWikiRequest,
|
||||
before => sub {
|
||||
no warnings;
|
||||
$OddMuse::RunCGI = 0;
|
||||
$OddMuse::DataDir = '/tmp/oddmuse';
|
||||
# The default data directory is determined by the environment variable
|
||||
# WikiDataDir and falls back to the following
|
||||
# $OddMuse::DataDir = '/tmp/oddmuse';
|
||||
use warnings;
|
||||
require 'wiki.pl' unless defined &OddMuse::DoWikiRequest;
|
||||
},
|
||||
env => {},
|
||||
errlog => 'wiki.log', # path to where STDERR from cgi script goes
|
||||
# path to where STDERR from cgi script goes
|
||||
errlog => ($ENV{WikiDataDir} || '/tmp/oddmuse')
|
||||
. "/wiki.log",
|
||||
};
|
||||
|
||||
get '/' => sub {
|
||||
my $self = shift;
|
||||
$self->redirect_to('/wiki');
|
||||
};
|
||||
|
||||
|
||||
app->start;
|
||||
|
||||
63
stuff/expire-bans.pl
Executable file
63
stuff/expire-bans.pl
Executable file
@@ -0,0 +1,63 @@
|
||||
#! /usr/bin/perl
|
||||
my $usage = q{expire-pans.pl
|
||||
Usage: this script expects to be run in a directory with a spammer.log file as
|
||||
produced by the LogBannedContent module.
|
||||
<https://oddmuse.org/wiki/LogBannedContent_Module>
|
||||
|
||||
In the same directory, it expects at least one of BannedContent, BannedHosts or
|
||||
BannedRegexps. It will work on all three, though. These must be the raw text
|
||||
files of the wiki.
|
||||
|
||||
Here's how you might get them from Emacs Wiki, for example.
|
||||
|
||||
wget https://www.emacswiki.org/spammer.log
|
||||
wget https://www.emacswiki.org/emacs/raw/BannedContent
|
||||
wget https://www.emacswiki.org/emacs/raw/BannedHosts
|
||||
wget https://www.emacswiki.org/emacs/raw/BannedRegexps
|
||||
|
||||
};
|
||||
|
||||
die $usage if ! -f 'spammer.log'
|
||||
|| !(-f 'BannedContent' || -f 'BannedHosts' || -f 'BannedRegexps');
|
||||
|
||||
my $fh;
|
||||
my @bans;
|
||||
|
||||
warn "Reading spammer.log...\n";
|
||||
open($fh, '<:utf8', 'spammer.log') or die "Cannot read spammer.log: $!";
|
||||
for my $line (<$fh>) {
|
||||
push(@bans, $line);
|
||||
}
|
||||
close($fh);
|
||||
|
||||
for my $file (qw(BannedContent BannedHosts BannedRegexps)) {
|
||||
warn "Reading $file...\n";
|
||||
if (open($fh, '<:utf8', $file)) {
|
||||
my $count = 0;
|
||||
my $used = 0;
|
||||
my @out;
|
||||
for my $line (<$fh>) {
|
||||
if ($line =~ m/^\s*([^#]+?)\s*(#\s*(\d\d\d\d-\d\d-\d\d\s*)?(.*))?$/) {
|
||||
$count++;
|
||||
my ($regexp, $comment) = ($1, $4);
|
||||
foreach my $ban (@bans) {
|
||||
if (index($ban, $regexp) > -1) {
|
||||
$used++;
|
||||
push(@out, $line);
|
||||
last;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
push(@out, $line);
|
||||
}
|
||||
}
|
||||
close ($fh);
|
||||
warn "$count regular expressions checked\n";
|
||||
warn "$used regular expressions were used\n";
|
||||
warn "Writing $file-new...\n";
|
||||
open ($fh, '>:utf8', "$file-new")
|
||||
or die "Cannot write $file-new: $!";
|
||||
print $fh join("", @out);
|
||||
close $fh;
|
||||
}
|
||||
}
|
||||
63
stuff/release
Normal file
63
stuff/release
Normal file
@@ -0,0 +1,63 @@
|
||||
#!/bin/env perl
|
||||
# Copyright (C) 2015 Alex Schroeder <alex@gnu.org>
|
||||
|
||||
# This program is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use version;
|
||||
|
||||
my $dir = shift;
|
||||
|
||||
unless (-d $dir) {
|
||||
die <<"EOT";
|
||||
Usage: $0 DIR [RELEASE]
|
||||
|
||||
DIR is the directory where the tarballs for each tag are created.
|
||||
It must already exist.
|
||||
|
||||
If an optional RELEASE such as 2.3.0 is provided, then only tags
|
||||
equal or greater than 2.3.0 will be considered. The default is 2.3.0.
|
||||
EOT
|
||||
}
|
||||
|
||||
my $min = version->parse(shift || "2.3.0");
|
||||
|
||||
my @tags = grep { /\d+\.\d+\.\d+/ and version->parse($_) > $min }
|
||||
split(/\n/, qx{git tag --list});
|
||||
|
||||
unless (@tags) {
|
||||
die "git tag --list produced no list of tags\n";
|
||||
}
|
||||
|
||||
for my $tag (@tags) {
|
||||
my $fname = "$dir/oddmuse-$tag.tar.gz";
|
||||
unless (-f $fname) {
|
||||
|
||||
system("git", "checkout", $tag) == 0
|
||||
or die "Failed to git checkout $tag\n";
|
||||
system("make", "prepare") == 0
|
||||
or die "Failed to run make prepare for tag $tag\n";
|
||||
system("mv", "build", "oddmuse-$tag") == 0
|
||||
or die "Failed to rename the build directory to oddmuse-$tag\n";
|
||||
system("tar", "czf", "oddmuse-$tag.tar.gz", "oddmuse-$tag") == 0
|
||||
or die "Failed to build tarball oddmuse-$tag.tar.gz\n";
|
||||
system("mv", "oddmuse-$tag.tar.gz", $fname) == 0
|
||||
or die "Failed to move the tarball oddmuse-$tag.tar.gz\n";
|
||||
system("rm", "-rf", "oddmuse-$tag") == 0
|
||||
or die "Failed to remove the directory oddmuse-$tag\n";
|
||||
}
|
||||
}
|
||||
|
||||
system("git", "checkout", "master") == 0
|
||||
or die "Failed to git checkout master\n";
|
||||
45
t/atom.t
45
t/atom.t
@@ -22,45 +22,9 @@ use XML::Atom::Client;
|
||||
use XML::Atom::Entry;
|
||||
use XML::Atom::Person;
|
||||
|
||||
sub random_port {
|
||||
use Errno qw( EADDRINUSE );
|
||||
use Socket qw( PF_INET SOCK_STREAM INADDR_ANY sockaddr_in );
|
||||
|
||||
my $family = PF_INET;
|
||||
my $type = SOCK_STREAM;
|
||||
my $proto = getprotobyname('tcp') or die "getprotobyname: $!";
|
||||
my $host = INADDR_ANY; # Use inet_aton for a specific interface
|
||||
|
||||
for my $i (1..3) {
|
||||
my $port = 1024 + int(rand(65535 - 1024));
|
||||
socket(my $sock, $family, $type, $proto) or die "socket: $!";
|
||||
my $name = sockaddr_in($port, $host) or die "sockaddr_in: $!";
|
||||
setsockopt($sock, SOL_SOCKET, SO_REUSEADDR, 1);
|
||||
bind($sock, $name)
|
||||
and close($sock)
|
||||
and return $port;
|
||||
die "bind: $!" if $! != EADDRINUSE;
|
||||
print "Port $port in use, retrying...\n";
|
||||
}
|
||||
die "Tried 3 random ports and failed.\n"
|
||||
}
|
||||
|
||||
my $port = random_port();
|
||||
$ScriptName = "http://localhost:$port";
|
||||
|
||||
AppendStringToFile($ConfigFile, "\$ScriptName = '$ScriptName';\n");
|
||||
|
||||
add_module('atom.pl');
|
||||
|
||||
# Fork a test server with the new config file and the module
|
||||
my $pid = fork();
|
||||
if (!defined $pid) {
|
||||
die "Cannot fork: $!";
|
||||
} elsif ($pid == 0) {
|
||||
use Config;
|
||||
my $secure_perl_path = $Config{perlpath};
|
||||
exec($secure_perl_path, "stuff/server.pl", "wiki.pl", $port) or die "Cannot exec: $!";
|
||||
}
|
||||
start_server();
|
||||
|
||||
# Give the child time to start
|
||||
sleep 1;
|
||||
@@ -69,7 +33,7 @@ sleep 1;
|
||||
my $ua = LWP::UserAgent->new;
|
||||
my $response = $ua->get("$ScriptName?action=version");
|
||||
ok($response->is_success, "There is a wiki running at $ScriptName");
|
||||
like($response->content, qr/\batom\.pl/, "The has the atom extension installed");
|
||||
like($response->content, qr/\batom\.pl/, "The server has the atom extension installed");
|
||||
|
||||
# Testing the Atom API
|
||||
my $api = XML::Atom::Client->new;
|
||||
@@ -179,8 +143,3 @@ sub trim {
|
||||
}
|
||||
ok(trim($result->content->body) eq ("<p>" . trim($content) . '</p>'), 'verify content');
|
||||
ok($result->author->name eq $username, 'verify author');
|
||||
|
||||
END {
|
||||
# kill server
|
||||
kill 'KILL', $pid;
|
||||
}
|
||||
|
||||
25
t/basic.t
Normal file
25
t/basic.t
Normal file
@@ -0,0 +1,25 @@
|
||||
# Copyright (C) 2016 Alex Schroeder <alex@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
require 't/test.pl';
|
||||
package OddMuse;
|
||||
use Test::More tests => 3;
|
||||
|
||||
# editing pages
|
||||
test_page(get_page('Test'),
|
||||
'<title>Wiki: Test</title>',
|
||||
'Status: 404 NOT FOUND');
|
||||
test_page(update_page('Test', 'Muuu!', 'first edit', undef, undef,
|
||||
'username=Alex'),
|
||||
'<p>Muuu!</p>');
|
||||
2
t/git.t
2
t/git.t
@@ -23,6 +23,8 @@ SKIP: {
|
||||
|
||||
add_module('git.pl');
|
||||
|
||||
$ENV{LANG} = "en_US.UTF-8"; # test relies on English output
|
||||
|
||||
if (qx($GitBinary --version) !~ /git version/) {
|
||||
skip "$GitBinary not found", 16;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# Copyright (C) 2015 Alex-Daniel Jakimenko <alex.jakimenko@gmail.com>
|
||||
# Copyright (C) 2016 Alex Schroeder <alex@gnu.org>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
@@ -14,7 +15,7 @@
|
||||
|
||||
require 't/test.pl';
|
||||
package OddMuse;
|
||||
use Test::More tests => 1;
|
||||
use Test::More tests => 6;
|
||||
|
||||
use File::Basename;
|
||||
|
||||
@@ -23,9 +24,10 @@ require("$ModuleDir/load-lang.pl");
|
||||
|
||||
my %choosable_translations = reverse %TranslationsLibrary;
|
||||
my @missing = (); # missing in load-lang.pl
|
||||
|
||||
my $count = 0;
|
||||
foreach (bsd_glob("modules/translations/*.p[ml]")) {
|
||||
my $filename = fileparse($_);
|
||||
$count++;
|
||||
next if exists $choosable_translations{$filename};
|
||||
next if $filename eq 'new-utf8.pl'; # placeholder
|
||||
next if $filename =~ /^month-names/; # month names are located in translations/ for whatever reason
|
||||
@@ -37,4 +39,20 @@ unless (ok(@missing == 0, 'All translations are listed')) {
|
||||
diag("$_ is not listed in load-lang.pl") for @missing;
|
||||
}
|
||||
|
||||
# TODO test the module itself
|
||||
unless (ok($count > 0, "$count translations were found")) {
|
||||
diag("if 0 then the \$LoadLanguageDir was not set correctly");
|
||||
}
|
||||
|
||||
test_page(get_page('Test'), 'Edit this page');
|
||||
|
||||
CreateDir($LoadLanguageDir);
|
||||
WriteStringToFile("$LoadLanguageDir/german-utf8.pl", ReadFileOrDie("modules/translations/german-utf8.pl"));
|
||||
# AppendStringToFile("$LoadLanguageDir/german-utf8.pl", "warn 'reading german-utf8.pl';\n");
|
||||
|
||||
$ENV{'HTTP_ACCEPT_LANGUAGE'} = 'de-ch,de;q=0.7,en;q=0.3';
|
||||
|
||||
test_page(get_page('action=version'), 'load-lang.pl');
|
||||
|
||||
my $page = get_page('Test');
|
||||
test_page($page, 'Diese Seite bearbeiten');
|
||||
test_page_negative($page, 'Edit this page');
|
||||
|
||||
69
t/mojolicious-namespaces.t
Normal file
69
t/mojolicious-namespaces.t
Normal file
@@ -0,0 +1,69 @@
|
||||
# Copyright (C) 2016 Alex Schroeder <alex@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package OddMuse;
|
||||
use Test::More;
|
||||
use Test::Mojo;
|
||||
|
||||
require 't/test.pl';
|
||||
|
||||
add_module('namespaces.pl');
|
||||
|
||||
start_mojolicious_server();
|
||||
sleep(1);
|
||||
|
||||
my $t = Test::Mojo->new;
|
||||
|
||||
# Installation worked
|
||||
$t->get_ok("$ScriptName?action=version")
|
||||
->content_like(qr/namespaces\.pl/);
|
||||
|
||||
# Edit a page in the Main namespace
|
||||
$t->post_ok("$ScriptName"
|
||||
=> form => {title => 'Some_Page',
|
||||
text => 'This is the Main namespace.'})
|
||||
->status_is(302);
|
||||
$t->get_ok("$ScriptName/Some_Page")
|
||||
->status_is(200)
|
||||
->content_like(qr/This is the Main namespace/);
|
||||
|
||||
# Edit a page in the Five Winds namespace
|
||||
$t->post_ok("$ScriptName/FiveWinds"
|
||||
=> form => {title => 'Some_Page',
|
||||
text => 'This is the Five Winds namespace.'})
|
||||
->status_is(302);
|
||||
$t->get_ok("$ScriptName/FiveWinds/Some_Page")
|
||||
->status_is(200)
|
||||
->content_like(qr/This is the Five Winds namespace/);
|
||||
|
||||
# This didn't overwrite the Main namespace.
|
||||
$t->get_ok("$ScriptName/Some_Page")
|
||||
->content_like(qr/This is the Main namespace/);
|
||||
|
||||
TODO: {
|
||||
local $TODO = "Some bug in namespaces.pl remains";
|
||||
diag "Waiting for the lock dir in RefreshIndex...";
|
||||
|
||||
# Umlauts
|
||||
$t->post_ok("$ScriptName/F%C3%BCnfWinde"
|
||||
=> form => {title => 'Some_Page',
|
||||
text => 'Wir sind im Namensraum Fünf Winde.'})
|
||||
->status_is(302);
|
||||
$t->get_ok("$ScriptName/F%C3%BCnfWinde/Some_Page")
|
||||
->status_is(200)
|
||||
->content_like(qr/Wir sind im Namensraum Fünf Winde/);
|
||||
}
|
||||
|
||||
done_testing();
|
||||
35
t/mojolicious.t
Normal file
35
t/mojolicious.t
Normal file
@@ -0,0 +1,35 @@
|
||||
# Copyright (C) 2016 Alex Schroeder <alex@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package OddMuse;
|
||||
use Test::More;
|
||||
use Test::Mojo;
|
||||
|
||||
require 't/test.pl';
|
||||
|
||||
start_mojolicious_server();
|
||||
sleep(1);
|
||||
|
||||
my $t = Test::Mojo->new;
|
||||
|
||||
$t->get_ok("$ScriptName")->status_is(404)->content_like(qr/Welcome!/);
|
||||
$t->get_ok("$ScriptName?action=admin")->status_is(200);
|
||||
|
||||
$t->post_ok("$ScriptName"
|
||||
=> form => {title => 'HomePage', text => 'This is a test.'})
|
||||
->status_is(302);
|
||||
$t->get_ok("$ScriptName")->status_is(200)->content_like(qr/This is a test/);
|
||||
|
||||
done_testing();
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2015 Alex Schroeder <alex@gnu.org>
|
||||
# Copyright (C) 2015-2016 Alex Schroeder <alex@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
@@ -18,8 +18,14 @@ use Test::More tests => 2;
|
||||
|
||||
add_module('pygmentize.pl');
|
||||
|
||||
$ENV{PATH} = '.'; # pygmentize is not installed in the current directory
|
||||
$page = apply_rules(newlines('{{{\ntest\n}}}\n'));
|
||||
test_page($page,
|
||||
'\bsh\b.*\bpygmentize\b.*\bnot found\b',
|
||||
'<pre>test</pre>');
|
||||
SKIP: {
|
||||
if (qx(pygmentize -V) !~ /Pygments version/) {
|
||||
skip "pygmentize not found", 2;
|
||||
}
|
||||
|
||||
$ENV{PATH} = '.'; # pygmentize is not installed in the current directory
|
||||
$page = apply_rules(newlines('{{{\ntest\n}}}\n'));
|
||||
test_page($page,
|
||||
'\bsh\b.*\bpygmentize\b.*\bnot found\b',
|
||||
'<pre>test</pre>');
|
||||
}
|
||||
|
||||
33
t/server.t
Normal file
33
t/server.t
Normal file
@@ -0,0 +1,33 @@
|
||||
# Copyright (C) 2016 Alex Schroeder <alex@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
require 't/test.pl';
|
||||
package OddMuse;
|
||||
|
||||
use Test::More tests => 4;
|
||||
use LWP::UserAgent;
|
||||
|
||||
start_server();
|
||||
|
||||
# Give the child time to start
|
||||
sleep 1;
|
||||
|
||||
# Check whether the child is up and running
|
||||
my $ua = LWP::UserAgent->new;
|
||||
my $response = $ua->get("$ScriptName?action=version");
|
||||
ok($response->is_success, "There is a wiki running at $ScriptName");
|
||||
like($response->content, qr/Oddmuse/, "It self-identifies as Oddmuse");
|
||||
ok($ua->get("$ScriptName?title=Test;text=Testing")->is_success, "Page saved");
|
||||
like($ua->get("$ScriptName/Test")->content, qr/Testing/, "Content verified");
|
||||
89
t/sidebar.t
89
t/sidebar.t
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env perl
|
||||
# Copyright (C) 2006, 2007 Alex Schroeder <alex@emacswiki.org>
|
||||
# Copyright (C) 2006–2016 Alex Schroeder <alex@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
@@ -16,19 +16,71 @@
|
||||
|
||||
require 't/test.pl';
|
||||
package OddMuse;
|
||||
use Test::More tests => 6;
|
||||
use Test::More tests => 9;
|
||||
|
||||
# basic test
|
||||
|
||||
add_module('sidebar.pl');
|
||||
|
||||
test_page(update_page($SidebarName, 'mu'), '<div class="sidebar"><p>mu</p></div>');
|
||||
test_page(get_page('HomePage'), '<div class="sidebar"><p>mu</p></div>');
|
||||
|
||||
#FIXME: Due to the recent refactoring of the Table of Contents module, the
|
||||
#Sidebar module is now known **not** to work as expected with that module.
|
||||
#This would appear to be an unavoidable consequence of that refactoring... The
|
||||
#Sidebar module, as currently implemented, **cannot** be made to work with the
|
||||
#Table of Contents module. As such, we disable all prior tests against the
|
||||
#Table of Contents module. It's hardly ideal. (But then, what is?)
|
||||
# with images
|
||||
|
||||
add_module('image.pl');
|
||||
# enable uploads
|
||||
AppendStringToFile($ConfigFile, "\$UploadAllowed = 1;\n");
|
||||
update_page('pic', "#FILE image/png\niVBORw0KGgoAAAA");
|
||||
xpath_test(update_page($SidebarName, '[[image:pic|picture|Target]]'),
|
||||
'//div[@class="sidebar"]/p/a[@class="image"][@href="http://localhost/wiki.pl/Target"]/img[@class="upload"][@src="http://localhost/wiki.pl/download/pic"][@alt="picture"]');
|
||||
|
||||
# with static-copy
|
||||
|
||||
add_module('static-copy.pl');
|
||||
|
||||
AppendStringToFile($ConfigFile, q{
|
||||
$StaticAlways = 1;
|
||||
$StaticDir = $DataDir . '/static';
|
||||
$StaticUrl = '/static/';
|
||||
%StaticMimeTypes = ('image/png' => 'png', );
|
||||
@UploadTypes = ('image/png', );
|
||||
});
|
||||
|
||||
update_page('pic', "DeletedPage");
|
||||
update_page('pic', "#FILE image/png\niVBORw0KGgoAAAA", undef, 0, 1);
|
||||
ok(-f "$DataDir/static/pic.png", "$DataDir/static/pic.png exists");
|
||||
|
||||
xpath_test(update_page($SidebarName, '[[image:pic|a picture|Target]]'),
|
||||
'//div[@class="sidebar"]/p/a[@class="image"][@href="http://localhost/wiki.pl/Target"]/img[@class="upload"][@src="/static/pic.png"][@alt="a picture"]');
|
||||
|
||||
# with forms
|
||||
|
||||
add_module('forms.pl');
|
||||
|
||||
# Markup the sidebar page prior to locking the sidebar page. This should ensure
|
||||
# that forms on that page are not interpreted.
|
||||
test_page(update_page($SidebarName, '<form><h1>mu</h1></form>'),
|
||||
'<div class="sidebar"><p><form><h1>mu</h1></form></p></div>');
|
||||
|
||||
# Lock the sidebar page, mark it up again, and ensure that forms on that page
|
||||
# are now interpreted.
|
||||
xpath_test(get_page("action=pagelock id=$SidebarName set=1 pwd=foo"),
|
||||
'//p/text()[string()="Lock for "]/following-sibling::a[@href="http://localhost/wiki.pl/SideBar"][@class="local"][text()="SideBar"]/following-sibling::text()[string()=" created."]');
|
||||
test_page(get_page("action=browse id=$SidebarName cache=0"), #update_page($SidebarName, '<form><h1>mu</h1></form>'),
|
||||
'<div class="sidebar"><form><h1>mu</h1></form></div>');
|
||||
# While rendering the SideBar as part of the HomePage, it should still
|
||||
# be considered "locked", and therefore the form should render
|
||||
# correctly.
|
||||
test_page(get_page('HomePage'),
|
||||
'<div class="sidebar"><form><h1>mu</h1></form></div>');
|
||||
|
||||
|
||||
# FIXME: Due to the recent refactoring of the Table of Contents module, the
|
||||
# Sidebar module is now known **not** to work as expected with that module.
|
||||
# This would appear to be an unavoidable consequence of that refactoring... The
|
||||
# Sidebar module, as currently implemented, **cannot** be made to work with the
|
||||
# Table of Contents module. As such, we disable all prior tests against the
|
||||
# Table of Contents module. It's hardly ideal. (But then, what is?)
|
||||
|
||||
# with toc
|
||||
|
||||
@@ -72,24 +124,3 @@ test_page(get_page('HomePage'), '<div class="sidebar"><p>mu</p></div>');
|
||||
|
||||
# remove_rule(\&TocRule);
|
||||
# remove_rule(\&UsemodRule);
|
||||
|
||||
# with forms
|
||||
|
||||
add_module('forms.pl');
|
||||
|
||||
# Markup the sidebar page prior to locking the sidebar page. This should ensure
|
||||
# that forms on that page are not interpreted.
|
||||
test_page(update_page($SidebarName, '<form><h1>mu</h1></form>'),
|
||||
'<div class="sidebar"><p><form><h1>mu</h1></form></p></div>');
|
||||
|
||||
# Lock the sidebar page, mark it up again, and ensure that forms on that page
|
||||
# are now interpreted.
|
||||
xpath_test(get_page("action=pagelock id=$SidebarName set=1 pwd=foo"),
|
||||
'//p/text()[string()="Lock for "]/following-sibling::a[@href="http://localhost/wiki.pl/SideBar"][@class="local"][text()="SideBar"]/following-sibling::text()[string()=" created."]');
|
||||
test_page(get_page("action=browse id=$SidebarName cache=0"), #update_page($SidebarName, '<form><h1>mu</h1></form>'),
|
||||
'<div class="sidebar"><form><h1>mu</h1></form></div>');
|
||||
# While rendering the SideBar as part of the HomePage, it should still
|
||||
# be considered "locked", and therefore the form should render
|
||||
# correctly.
|
||||
test_page(get_page('HomePage'),
|
||||
'<div class="sidebar"><form><h1>mu</h1></form></div>');
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
require 't/test.pl';
|
||||
package OddMuse;
|
||||
use utf8;
|
||||
use Test::More tests => 36;
|
||||
use Test::More tests => 38;
|
||||
|
||||
add_module('static-copy.pl');
|
||||
|
||||
@@ -167,3 +167,17 @@ xpath_test(update_page('test_image', '[[image/right:bar baz]]'),
|
||||
# Next, using a real page. The image type is used appropriately.
|
||||
xpath_test(update_page('test_image', '[[image/right:Logo]]'),
|
||||
'//a[@class="image right"][@href="http://localhost/wiki.pl/Logo"]/img[@class="upload"][@src="/static/Logo.png"][@alt="Logo"]');
|
||||
|
||||
|
||||
my $weirdPage = 'Ï_lövé_¥ǫµnĩçȯḑë';
|
||||
update_page($weirdPage, 'Some text');
|
||||
update_page('Unicode', '[[' . $weirdPage . ']]');
|
||||
|
||||
get_page('action=static raw=1 pwd=foo html=1'); # generate static files
|
||||
|
||||
my ($status, $data) = ReadFile("$DataDir/static/Unicode.html");
|
||||
|
||||
xpath_test(get_page('Unicode'),
|
||||
'//a[@class="local"]' . '[@href="http://localhost/wiki.pl/' . UrlEncode($weirdPage) . '"]');
|
||||
xpath_test($data,
|
||||
'//a[@class="local"]' . '[@href="' . UrlEncode($weirdPage) . '.html"]');
|
||||
|
||||
68
t/test.pl
68
t/test.pl
@@ -353,6 +353,73 @@ sub clear_pages {
|
||||
write_config_file();
|
||||
}
|
||||
|
||||
# Find an unused port
|
||||
sub random_port {
|
||||
use Errno qw( EADDRINUSE );
|
||||
use Socket qw( PF_INET SOCK_STREAM INADDR_ANY sockaddr_in );
|
||||
|
||||
my $family = PF_INET;
|
||||
my $type = SOCK_STREAM;
|
||||
my $proto = getprotobyname('tcp') or die "getprotobyname: $!";
|
||||
my $host = INADDR_ANY; # Use inet_aton for a specific interface
|
||||
|
||||
for my $i (1..3) {
|
||||
my $port = 1024 + int(rand(65535 - 1024));
|
||||
socket(my $sock, $family, $type, $proto) or die "socket: $!";
|
||||
my $name = sockaddr_in($port, $host) or die "sockaddr_in: $!";
|
||||
setsockopt($sock, SOL_SOCKET, SO_REUSEADDR, 1);
|
||||
bind($sock, $name)
|
||||
and close($sock)
|
||||
and return $port;
|
||||
die "bind: $!" if $! != EADDRINUSE;
|
||||
print "Port $port in use, retrying...\n";
|
||||
}
|
||||
die "Tried 3 random ports and failed.\n"
|
||||
}
|
||||
|
||||
my $pid;
|
||||
|
||||
# Fork a simple test server
|
||||
sub start_server {
|
||||
die "A server already exists: $pid\n" if $pid;
|
||||
my $port = random_port();
|
||||
$ScriptName = "http://localhost:$port";
|
||||
AppendStringToFile($ConfigFile, "\$ScriptName = '$ScriptName';\n");
|
||||
$pid = fork();
|
||||
if (!defined $pid) {
|
||||
die "Cannot fork: $!";
|
||||
} elsif ($pid == 0) {
|
||||
use Config;
|
||||
my $secure_perl_path = $Config{perlpath};
|
||||
exec($secure_perl_path, "stuff/server.pl", "wiki.pl", $port) or die "Cannot exec: $!";
|
||||
}
|
||||
}
|
||||
|
||||
# Fork a Mojolicious server
|
||||
sub start_mojolicious_server {
|
||||
die "A server already exists: $pid\n" if $pid;
|
||||
my $port = random_port();
|
||||
my $listen = "http://127.0.0.1:$port";
|
||||
$ScriptName = "http://127.0.0.1:$port/wiki";
|
||||
AppendStringToFile($ConfigFile, "\$ScriptName = '$ScriptName';\n");
|
||||
$pid = fork();
|
||||
if (!defined $pid) {
|
||||
die "Cannot fork: $!";
|
||||
} elsif ($pid == 0) {
|
||||
use Config;
|
||||
my $secure_perl_path = $Config{perlpath};
|
||||
exec($secure_perl_path, "server.pl", "daemon", "-l", $listen)
|
||||
or die "Cannot exec: $!";
|
||||
}
|
||||
}
|
||||
|
||||
END {
|
||||
# kill server
|
||||
if ($pid) {
|
||||
kill 'KILL', $pid or warn "Could not kill server $pid";
|
||||
}
|
||||
}
|
||||
|
||||
sub RunAndTerminate { # runs a command for 1 second and then sends SIGTERM
|
||||
my $pid = fork();
|
||||
if (not $pid) { # child
|
||||
@@ -374,3 +441,4 @@ sub AppendToConfig {
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
31
t/umlaut.t
Normal file
31
t/umlaut.t
Normal file
@@ -0,0 +1,31 @@
|
||||
# Copyright (C) 2016 Alex Schroeder <alex@gnu.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation; either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
require 't/test.pl';
|
||||
package OddMuse;
|
||||
use Test::More tests => 3;
|
||||
use utf8;
|
||||
|
||||
my $dir = $ENV{WikiDataDir};
|
||||
$dir .= "-ä";
|
||||
utf8::encode($dir); # bytes
|
||||
$ENV{WikiDataDir} = $dir;
|
||||
|
||||
# editing pages
|
||||
test_page(get_page('Test'),
|
||||
'<title>Wiki: Test</title>',
|
||||
'Status: 404 NOT FOUND');
|
||||
test_page(update_page('Test', 'Muuu!', 'first edit', undef, undef,
|
||||
'username=Alex'),
|
||||
'<p>Muuu!</p>');
|
||||
1
wiki.pl
1
wiki.pl
@@ -305,7 +305,6 @@ sub InitVariables { # Init global session variables for mod_perl!
|
||||
$LastUpdate = $ts;
|
||||
unshift(@MyRules, \&MyRules) if defined(&MyRules) && (not @MyRules or $MyRules[0] != \&MyRules);
|
||||
@MyRules = sort {$RuleOrder{$a} <=> $RuleOrder{$b}} @MyRules; # default is 0
|
||||
ReportError(Ts('Cannot create %s', $DataDir) . ": $!", '500 INTERNAL SERVER ERROR') unless -d $DataDir;
|
||||
@IndexOptions = (['pages', T('Include normal pages'), 1, \&AllPagesList]);
|
||||
foreach my $sub (@MyInitVariables) {
|
||||
my $result = $sub->();
|
||||
|
||||
Reference in New Issue
Block a user