Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec4987e817 | ||
|
|
655d3b47c6 | ||
|
|
8b85c6e9dd | ||
|
|
ef35e4eda6 | ||
|
|
7bb1ca239b | ||
|
|
a7625b35f4 | ||
|
|
1d239aa9a6 | ||
|
|
3f1e5caaad | ||
|
|
bdbd6c8ba7 | ||
|
|
1a898ee589 | ||
|
|
9609adb575 | ||
|
|
34c10202b0 | ||
|
|
1457fad242 | ||
|
|
ce355499c7 | ||
|
|
2bb3d2f967 | ||
|
|
a301ab5e1c | ||
|
|
d74d29fa13 | ||
|
|
96c54d9d66 | ||
|
|
9a0700cac1 | ||
|
|
864890c168 | ||
|
|
a93873d1d4 | ||
|
|
b0a8fa2141 |
@@ -156,8 +156,11 @@ WikiDataDir=$HOME/oddmuse perl server.pl daemon
|
||||
}}}
|
||||
|
||||
This makes the server available on {{{http://localhost:3000/wiki}}}.
|
||||
Make sure you create the directory before starting the server!
|
||||
If you don't, you'll get a strange error:
|
||||
`STDERR: : No such file or directory at ... perl5/Mojolicious/Plugin/CGI.pm`.
|
||||
|
||||
If it works for you, feel free to upgrade to Hypnotoad.
|
||||
If it works, feel free to upgrade to Hypnotoad.
|
||||
|
||||
{{{
|
||||
WikiDataDir=$HOME/oddmuse hypnotoad server.pl
|
||||
|
||||
93
contrib/emacswiki/bootstrap.js
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
// Public Domain
|
||||
// initial version by Alex Schroeder <alex@gnu.org>
|
||||
// with many improvements by Evgkeni Sampelnikof
|
||||
|
||||
$(function(){
|
||||
|
||||
// add fancy classes
|
||||
$('div.header' ).addClass('container');
|
||||
$('div.wrapper').addClass('container');
|
||||
$('div.footer' ).addClass('container');
|
||||
$('div.footer > .navbar' ).remove();
|
||||
$('.message > p' ).addClass('alert');
|
||||
$('img.portrait').addClass('img-polaroid');
|
||||
|
||||
$('input:text').addClass('input-medium search-query');
|
||||
$('textarea').addClass('span12');
|
||||
$('input:submit').addClass('btn');
|
||||
$('.download a').addClass('btn btn-success');
|
||||
|
||||
$('.footer .gotobar').remove();
|
||||
$('.footer br').first().remove();
|
||||
var $gotobar = $('.gotobar')
|
||||
.after($('<div>').attr('class','navbar')
|
||||
.append($('<div>').attr('class','navbar-inner')
|
||||
.append($('<ul>').attr('class', 'nav'))));
|
||||
var $id = $('h1 a').first().text();
|
||||
var $list = $('.nav')
|
||||
.append($('<li>')
|
||||
.append($('<a>').attr('class', 'brand').attr('href', 'http://www.emacswiki.org/')
|
||||
.append('Emacs Wiki')));
|
||||
$('.gotobar a').each(function() {
|
||||
var $item = $('<li>');
|
||||
$(this).appendTo($item);
|
||||
$item.appendTo($list);
|
||||
if ($(this).text() == $id) {
|
||||
$item.addClass('active');
|
||||
}
|
||||
});
|
||||
$gotobar.remove();
|
||||
|
||||
// search without labels, without button, without language field
|
||||
$('form.search input[type=submit]').remove();
|
||||
$('form.search label').remove();
|
||||
$('form.search input#searchlang').remove();
|
||||
$('form.search')
|
||||
.css({'float': 'right',
|
||||
'margin-top': '10px'});
|
||||
$('.navbar').append($('form.search'));
|
||||
|
||||
// add button style to some links
|
||||
$('.edit.bar a').addClass('btn');
|
||||
|
||||
// add color to Talk button for a non-existing page
|
||||
$('a.btn.comment.edit').addClass('btn-warning');
|
||||
|
||||
// move article link and talk link below title
|
||||
var $link = $('a.original').add('a.comment');
|
||||
if ($link) {
|
||||
$('.header h1').after($('<p>').append($link));
|
||||
}
|
||||
|
||||
// toc
|
||||
if ($('title').text() == "EmacsWiki: Wikified Emacs Lisp List") {
|
||||
$('.content').addClass('ell');
|
||||
}
|
||||
|
||||
// tables
|
||||
$('table').addClass('table');
|
||||
|
||||
// minor edit checkbox
|
||||
$('input[type=checkbox]').addClass('checkbox');
|
||||
$('input[type=checkbox]').parent().addClass('checkbox');
|
||||
|
||||
// clean up admin page
|
||||
$('li a.clear').parent().remove();
|
||||
$('li a.index').parent().remove();
|
||||
|
||||
$('a[href="http://creativecommons.org/licenses/GPL/2.0/"]')
|
||||
.parent()
|
||||
.css({'margin-right': '120px',
|
||||
'opacity': 0.3,
|
||||
'padding-top': '1em'});
|
||||
$('.footer .bar')
|
||||
.after('<hr />');
|
||||
var footer_wrapper = $('<div/>')
|
||||
.addClass('footer_wrapper');
|
||||
var footer = $('.footer.container');
|
||||
footer.after(footer_wrapper);
|
||||
footer_wrapper.append(footer);
|
||||
var logo_image = $('<img />')
|
||||
.attr('src', 'http://emacswiki.org/ew_logo.png');
|
||||
$('.header .navbar .brand').html(logo_image);
|
||||
});
|
||||
44
css/wiki.css
@@ -172,6 +172,50 @@ span.bar a {
|
||||
padding: 1ex 0;
|
||||
}
|
||||
|
||||
.red {
|
||||
background: red;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.orange {
|
||||
background: orange;
|
||||
color: orange;
|
||||
}
|
||||
|
||||
.yellow {
|
||||
background: yellow;
|
||||
color: yellow;
|
||||
}
|
||||
|
||||
.green {
|
||||
background: green;
|
||||
color: green;
|
||||
}
|
||||
|
||||
.blue {
|
||||
background: blue;
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.indigo {
|
||||
background: indigo;
|
||||
color: indigo;
|
||||
}
|
||||
|
||||
.violet {
|
||||
background: violet;
|
||||
color: violet;
|
||||
}
|
||||
|
||||
.white {
|
||||
background: white;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.ip-code {
|
||||
border: 1px solid #666;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
color: black;
|
||||
|
||||
BIN
logo/falky/Neris/Neris-Black.otf
Normal file
BIN
logo/falky/Neris/Neris-BlackItalic.otf
Normal file
BIN
logo/falky/Neris/Neris-Light.otf
Normal file
BIN
logo/falky/Neris/Neris-LightItalic.otf
Normal file
BIN
logo/falky/Neris/Neris-SemiBold.otf
Normal file
BIN
logo/falky/Neris/Neris-SemiBoldItalic.otf
Normal file
BIN
logo/falky/Neris/Neris-Thin.otf
Normal file
BIN
logo/falky/Neris/Neris-ThinItalic.otf
Normal file
15
logo/falky/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
Falky schreibt:
|
||||
|
||||
Zum Thema Rechte am Logo möchte ich erstmal sagen, dass es mir primär
|
||||
darum ging den Auftritt von oddmuse.org aufzuhübschen. Also du/ihr
|
||||
sollt durch das Logo unterstützt werden, nicht eingeschränkt.
|
||||
|
||||
Welche Lizenz das ab besten leisten, da hab ich keinen Schimmer.
|
||||
|
||||
Schön wäre, wenn irgendwo ein verweis auf "Falky [falky.de]"
|
||||
auftaucht, der soll aber nicht bei jeder Verwendung auftauchen,
|
||||
sondern irgendwo 'auffindbar' an 'zentraler' Stelle - halt irgendwo
|
||||
auf der Homepage, dass ich darauf verweisen kann und dass niemand was
|
||||
anderes behaupten kann. Das wäre es schon. Und ja, falls jemand das
|
||||
logo für ein anderes Projekt verwenden möchte, kann man ja höflich
|
||||
nochmal fragen oder so.
|
||||
BIN
logo/falky/oddmuse.banner.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
25
logo/falky/oddmuse.banner.svg
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-61 -1 177 62">
|
||||
|
||||
<rect fill="#FFF" x="-60" y="0" width="175" height="60"/>
|
||||
|
||||
<text style="font:400 6px Neris Black" fill="#000" x="2" y="18">powered by</text>
|
||||
<text style="font:400 16px Neris Thin" fill="#000" x="2" y="34">Oddmuse<tspan style="font-family:Neris Black">.org</tspan></text>
|
||||
|
||||
<g id="new" transform="translate(-30,30) scale(.18,.18)" >
|
||||
<circle fill="#FFF" stroke="#000" stroke-width="3" cx="0" cy="0" r="160.5"/>
|
||||
<g id="new" transform="rotate(207.2)" >
|
||||
|
||||
<path fill="#000" d="m42 -77 q24 0 38 20 c14 -1 42 -18 52 -29 c-1 50 -26 68 -44 70 c0 90 -44 141 -88 141 c-44 0 -88 -51 -88 -141 c-18 -2 -43 -20 -44 -70 c10 11 38 28 52 29 q14 -20 38 -20z"/>
|
||||
<path fill="#000" transform="translate(0,60) rotate(-14)" d="m -22 46q1 50 22 50q21 0 22 -50z"/>
|
||||
|
||||
<path stroke="#FFF" stroke-width="4" fill="#000" d="m0 17 c 30 0 36 -2 46 -2 c 18 0 32 16 32 51 c 0 34 -12 50 -32 50 c-16 0 -26 -5 -46 -5 c-20 0 -30 5 -46 5 c-20 0 -33 -18 -32 -50 c0 -36 16 -52 32 -51 c10 0 16 2 46 2z"/>
|
||||
<circle fill="#FFF" cx="44" cy="49" r="12"/> <circle fill="#FFF" cx="-44" cy="49" r="12"/>
|
||||
|
||||
<circle fill="#FFF" cx="42" cy="-31" r="40"/> <circle fill="#000" cx="42" cy="-31" r="20.5"/>
|
||||
<circle fill="#FFF" cx="-42" cy="-31" r="40"/> <path fill="#000" transform="translate(-42,-31) rotate(55)" d="m-7 7 v20 q7 2 14 0 v-20 h20 q2 -7 0 -14 h-20 v-20 q -7 -2 -14 0 v20 h-20 q-2 7 0 14z"/>
|
||||
|
||||
</g></g>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
BIN
logo/falky/oddmuse.icon.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
19
logo/falky/oddmuse.icon.svg
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-100 -100 200 200" >
|
||||
|
||||
<rect fill="#D88" x="-100" y="-100" width="200" height="200"/>
|
||||
|
||||
<g id="new" transform="rotate(180) translate(0,-19)" >
|
||||
|
||||
<path fill="#A00" d="m42 -77 q18 0 33 14 q 12 -6 23 -16 q-2 25 -10 43 c0 110 -44 155 -88 155 c-44 0 -88 -44 -88 -155 q-8 -18 -10 -43 q11 10 23 16 q15 -14 33 -14z"/>
|
||||
|
||||
<path stroke="#FFF" stroke-width="6" fill="#A00" d="m0 16 c30 0 38 -2 48 -2 c17 0 33 16 33 52 c0 34 -12 52 -31 52 c-15 0 -30 -7 -50 -7 c-20 0 -35 7 -50 7 c-19 0 -31 -18 -31 -52 c0 -36 16 -52 33 -52 c10 0 18 2 48 2z"/>
|
||||
<circle fill="#FFF" cx="45" cy="49" r="12"/> <circle fill="#FFF" cx="-45" cy="49" r="12"/>
|
||||
|
||||
<circle fill="#FFF" cx="42" cy="-31" r="40"/> <circle fill="#000" cx="42" cy="-31" r="20.5"/>
|
||||
<circle fill="#FFF" cx="-42" cy="-31" r="40"/> <path fill="#666" transform="translate(-42,-31) rotate(55)" d="m-7 7 v20 q7 2 14 0 v-20 h20 q2 -7 0 -14 h-20 v-20 q -7 -2 -14 0 v20 h-20 q-2 7 0 14z"/>
|
||||
|
||||
</g>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
BIN
logo/falky/oddmuse.logo.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
22
logo/falky/oddmuse.logo.svg
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-162 -162 324 324">
|
||||
|
||||
<circle fill="#FEE" stroke="#000" stroke-width="3" cx="0" cy="0" r="160.5"/>
|
||||
|
||||
<g id="new" transform="rotate(210)" >
|
||||
|
||||
<path fill="#A00" d="m42 -77 q24 0 38 20 c14 -1 42 -18 52 -29 c-1 50 -26 68 -44 70 c0 90 -44 141 -88 141 c-44 0 -88 -51 -88 -141 c-18 -2 -43 -20 -44 -70 c10 11 38 28 52 29 q14 -20 38 -20z"/>
|
||||
<path fill="#A00" transform="translate(0,60) rotate(-14)" d="m -22 46q1 50 22 50q21 0 22 -50z"/>
|
||||
|
||||
<path stroke="#FFF" stroke-width="4" fill="#D88" d="m0 17 c 30 0 36 -2 46 -2 c 18 0 32 16 32 51 c 0 34 -12 50 -32 50 c-16 0 -26 -5 -46 -5 c-20 0 -30 5 -46 5 c-20 0 -33 -18 -32 -50 c0 -36 16 -52 32 -51 c10 0 16 2 46 2z"/>
|
||||
<circle fill="#FFF" cx="44" cy="49" r="12"/> <circle fill="#FFF" cx="-44" cy="49" r="12"/>
|
||||
|
||||
<circle fill="#FFF" cx="42" cy="-31" r="40"/> <circle fill="#000" cx="42" cy="-31" r="20.5"/>
|
||||
<circle fill="#FFF" cx="-42" cy="-31" r="40"/> <path fill="#666" transform="translate(-42,-31) rotate(55)" d="m-7 7 v20 q7 2 14 0 v-20 h20 q2 -7 0 -14 h-20 v-20 q -7 -2 -14 0 v20 h-20 q-2 7 0 14z"/>
|
||||
|
||||
</g>
|
||||
|
||||
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
24
logo/falky/oddmuse.siegel.svg
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="-162 -162 324 324">
|
||||
|
||||
<circle fill="#FFF" stroke="#000" stroke-width="3" cx="0" cy="0" r="160.5"/>
|
||||
|
||||
<text style="font:400 27px Neris Black" fill="#000" text-anchor="middle" x="-5" y="137">Oddmuse</text>
|
||||
|
||||
<g id="new" transform="rotate(210)" >
|
||||
|
||||
<path fill="#000" d="m42 -77 q24 0 38 20 c14 -1 42 -18 52 -29 c-1 50 -26 68 -44 70 c0 90 -44 141 -88 141 c-44 0 -88 -51 -88 -141 c-18 -2 -43 -20 -44 -70 c10 11 38 28 52 29 q14 -20 38 -20z"/>
|
||||
<path fill="#000" transform="translate(0,60) rotate(-14)" d="m -22 46q1 50 22 50q21 0 22 -50z"/>
|
||||
|
||||
<path stroke="#FFF" stroke-width="4" fill="#000" d="m0 17 c 30 0 36 -2 46 -2 c 18 0 32 16 32 51 c 0 34 -12 50 -32 50 c-16 0 -26 -5 -46 -5 c-20 0 -30 5 -46 5 c-20 0 -33 -18 -32 -50 c0 -36 16 -52 32 -51 c10 0 16 2 46 2z"/>
|
||||
<circle fill="#FFF" cx="44" cy="49" r="12"/> <circle fill="#FFF" cx="-44" cy="49" r="12"/>
|
||||
|
||||
<circle fill="#FFF" cx="42" cy="-31" r="40"/> <circle fill="#000" cx="42" cy="-31" r="20.5"/>
|
||||
<circle fill="#FFF" cx="-42" cy="-31" r="40"/> <path fill="#000" transform="translate(-42,-31) rotate(55)" d="m-7 7 v20 q7 2 14 0 v-20 h20 q2 -7 0 -14 h-20 v-20 q -7 -2 -14 0 v20 h-20 q-2 7 0 14z"/>
|
||||
|
||||
</g>
|
||||
|
||||
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
BIN
logo/falky/preview/oddmuse-preview.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
logo/falky/preview/oddmuse.icon-preview.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
logo/falky/preview/oddmuse.org-preview.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
logo/falky/testmonial.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
4
logo/murray/README.md
Normal file
@@ -0,0 +1,4 @@
|
||||
The logo is licensed under the [GNU Free Documentation
|
||||
License](http://www.emacswiki.org/FDL) as well as the [CC BY
|
||||
2.0](http://creativecommons.org/licenses/by/2.0/) license. The author
|
||||
is [Murray Altheim](http://www.altheim.com/murray/).
|
||||
BIN
logo/murray/oddmuse-logo.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
100
logo/murray/oddmuse-logo.svg
Normal file
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Sodipodi ("http://www.sodipodi.com/") -->
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://web.resource.org/cc/"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
inkscape:version="0.41"
|
||||
sodipodi:docname="oddmuse-logo.svg"
|
||||
sodipodi:docbase="/Users/alex/Pictures/Oddmuse"
|
||||
height="1000pt"
|
||||
width="1000pt"
|
||||
sodipodi:version="0.32"
|
||||
id="svg1">
|
||||
<metadata
|
||||
id="metadata32">
|
||||
<rdf:RDF
|
||||
id="RDF34">
|
||||
<cc:Work
|
||||
id="Work36"
|
||||
rdf:about="">
|
||||
<dc:format
|
||||
id="format38">image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage"
|
||||
id="type40" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs3" />
|
||||
<sodipodi:namedview
|
||||
inkscape:current-layer="svg1"
|
||||
inkscape:window-y="22"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-height="535"
|
||||
inkscape:window-width="640"
|
||||
inkscape:cy="625.00000"
|
||||
inkscape:cx="625.00000"
|
||||
inkscape:zoom="0.28960000"
|
||||
id="base" />
|
||||
<g
|
||||
transform="translate(-155.7935,22.13440)"
|
||||
id="g176">
|
||||
<path
|
||||
transform="matrix(1.021740,0.000000,0.000000,1.021740,-299.4160,85.75640)"
|
||||
sodipodi:ry="148.93437"
|
||||
sodipodi:rx="142.30524"
|
||||
sodipodi:cy="475.27606"
|
||||
sodipodi:cx="1066.8474"
|
||||
d="M 1209.1526 475.27606 A 142.30524 148.93437 0 1 1 924.54218,475.27606 A 142.30524 148.93437 0 1 1 1209.1526 475.27606 z"
|
||||
id="path166"
|
||||
style="fill:#ffde00;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:22.021299;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="matrix(0.591973,0.000000,0.000000,0.523224,159.0800,309.0390)"
|
||||
sodipodi:ry="148.93437"
|
||||
sodipodi:rx="142.30524"
|
||||
sodipodi:cy="475.27606"
|
||||
sodipodi:cx="1066.8474"
|
||||
d="M 1209.1526 475.27606 A 142.30524 148.93437 0 1 1 924.54218,475.27606 A 142.30524 148.93437 0 1 1 1209.1526 475.27606 z"
|
||||
id="path168"
|
||||
style="fill:#ffde00;fill-opacity:1.0000000;fill-rule:evenodd;stroke:#000000;stroke-width:38.609402;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
sodipodi:type="arc" />
|
||||
<rect
|
||||
transform="translate(-1.416020,0.000000)"
|
||||
y="561.16870"
|
||||
x="694.39026"
|
||||
height="88.691116"
|
||||
width="195.30150"
|
||||
id="rect170"
|
||||
style="font-size:12.000000;fill:#ffde00;fill-opacity:1.0000000;fill-rule:evenodd;stroke-width:1.0000000pt" />
|
||||
<g
|
||||
id="g173">
|
||||
<path
|
||||
transform="translate(185.0000,-158.7500)"
|
||||
sodipodi:ry="31.250000"
|
||||
sodipodi:rx="25.000000"
|
||||
sodipodi:cy="783.75000"
|
||||
sodipodi:cx="565.00000"
|
||||
d="M 590.00000 783.75000 A 25.000000 31.250000 0 1 1 540.00000,783.75000 A 25.000000 31.250000 0 1 1 590.00000 783.75000 z"
|
||||
id="path171"
|
||||
style="fill:#000000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="translate(266.2500,-158.7500)"
|
||||
sodipodi:ry="31.250000"
|
||||
sodipodi:rx="25.000000"
|
||||
sodipodi:cy="783.75000"
|
||||
sodipodi:cx="565.00000"
|
||||
d="M 590.00000 783.75000 A 25.000000 31.250000 0 1 1 540.00000,783.75000 A 25.000000 31.250000 0 1 1 590.00000 783.75000 z"
|
||||
id="path172"
|
||||
style="fill:#000000;fill-opacity:1.0000000;fill-rule:evenodd;stroke:none;stroke-width:1.0000000pt;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000"
|
||||
sodipodi:type="arc" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
@@ -198,8 +198,7 @@ sub MakeLaTeX {
|
||||
}
|
||||
|
||||
if (not $error and IsFile('srender1.png') and not ZeroSize('srender1.png')) {
|
||||
my $png = ReadFileOrDie("srender1.png");
|
||||
WriteStringToFile ("$LatexDir/$hash.png", $png);
|
||||
Rename("srender1.png", "$LatexDir/$hash.png");
|
||||
} else {
|
||||
$error = "[Error retrieving image for $latex]";
|
||||
}
|
||||
|
||||
@@ -206,10 +206,12 @@ sub send_mail {
|
||||
|
||||
sub main {
|
||||
my $rss = get_rss();
|
||||
return unless @{$rss->{items}};
|
||||
my $subscribers = get_subscribers();
|
||||
return unless %{$subscribers};
|
||||
send_files($rss, $subscribers);
|
||||
if (@{$rss->{items}}) {
|
||||
my $subscribers = get_subscribers();
|
||||
if (%{$subscribers}) {
|
||||
send_files($rss, $subscribers);
|
||||
}
|
||||
}
|
||||
update_timestamp();
|
||||
}
|
||||
|
||||
|
||||
87
scripts/strip-host.pl
Executable file
@@ -0,0 +1,87 @@
|
||||
#! /usr/bin/perl -w
|
||||
|
||||
# Copyright (C) 2018 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/>.
|
||||
|
||||
sub ParseData {
|
||||
my $data = shift;
|
||||
my %result;
|
||||
while ($data =~ /(\S+?): (.*?)(?=\n[^ \t]|\Z)/sg) {
|
||||
my ($key, $value) = ($1, $2);
|
||||
$value =~ s/\n\t/\n/g;
|
||||
$result{$key} = $value;
|
||||
}
|
||||
return %result;
|
||||
}
|
||||
|
||||
sub EncodePage {
|
||||
my @data = @_;
|
||||
my $result = '';
|
||||
$result .= (shift @data) . ': ' . EscapeNewlines(shift @data) . "\n" while (@data);
|
||||
return $result;
|
||||
}
|
||||
|
||||
sub EscapeNewlines {
|
||||
$_[0] =~ s/\n/\n\t/g; # modify original instead of copying
|
||||
return $_[0];
|
||||
}
|
||||
|
||||
sub main {
|
||||
die "There is no temp directory, here.\n"
|
||||
. "Perhaps this isn't an Oddmuse data directory?\n"
|
||||
unless -d 'temp';
|
||||
die "The main lock already exists in the temp directory.\n"
|
||||
if -d "temp/lockmain";
|
||||
mkdir "temp/lockmain" or die "Cannot create main lock in temp: $!\n";
|
||||
local $/ = undef; # Read complete files
|
||||
foreach my $dir (qw/keep page/) {
|
||||
warn "Did not find the $dir directory.\n" unless -d $dir;
|
||||
}
|
||||
# include dotfiles!
|
||||
my $t = 0;
|
||||
my $n = 0;
|
||||
foreach my $file (glob("page/*.pg page/.*.pg"),
|
||||
glob("keep/*/*.kp keep/.*.kp")) {
|
||||
$t++;
|
||||
open(my $fh, '<', $file) or die "Cannot read $file file: $!\n";
|
||||
my $data = <$fh>;
|
||||
close($fh);
|
||||
next unless $data;
|
||||
my %result = ParseData($data);
|
||||
if (exists($result{host}) or exists($result{ip})) {
|
||||
delete($result{host});
|
||||
delete($result{ip});
|
||||
open($fh,'>', "$file~") or die "Cannot $file~: $!\n";
|
||||
print $fh EncodePage(%result);
|
||||
close($fh);
|
||||
rename("$file~", $file) or die "Cannot rename $file~ to $file: $!\n";
|
||||
$n++;
|
||||
}
|
||||
}
|
||||
rmdir "temp/lockmain" or die "Cannot remove main lock: $!\n";
|
||||
print "I looked at $t files and found $n host or ip keys which I removed.\n";
|
||||
}
|
||||
|
||||
if (@ARGV) {
|
||||
print qq{
|
||||
Usage: $0 [--page DIR]
|
||||
|
||||
Goes through the wiki and removes the hostname or IP number from page and
|
||||
keep files. Make a backup before running this script! Run this script in
|
||||
your data directory.
|
||||
}
|
||||
} else {
|
||||
main ();
|
||||
}
|
||||
@@ -177,6 +177,12 @@ sub NewGopherFiltered {
|
||||
return @pages;
|
||||
}
|
||||
|
||||
sub normal_to_free {
|
||||
my $title = shift;
|
||||
$title =~ s/_/ /g;
|
||||
return $title;
|
||||
}
|
||||
|
||||
sub print_text {
|
||||
my $self = shift;
|
||||
my $text = shift;
|
||||
@@ -222,17 +228,17 @@ sub serve_main_menu {
|
||||
$self->print_info("Phlog:");
|
||||
my @pages = sort { $b cmp $a } grep(/^\d\d\d\d-\d\d-\d\d/, @IndexList);
|
||||
for my $id (@pages[0..9]) {
|
||||
$self->print_menu("1" . NormalToFree($id), "$id/menu");
|
||||
$self->print_menu("1" . normal_to_free($id), "$id/menu");
|
||||
}
|
||||
$self->print_menu("1" . "More...", "do/more");
|
||||
$self->print_info("");
|
||||
|
||||
for my $id (@{$self->{server}->{wiki_pages}}) {
|
||||
$self->print_menu("1" . NormalToFree($id), "$id/menu");
|
||||
$self->print_menu("1" . normal_to_free($id), "$id/menu");
|
||||
}
|
||||
|
||||
for my $id (@{$self->{server}->{menu}}) {
|
||||
$self->print_menu("1" . NormalToFree($id), "map/$id");
|
||||
$self->print_menu("1" . normal_to_free($id), "map/$id");
|
||||
}
|
||||
|
||||
$self->print_menu("1" . "Recent Changes", "do/rc");
|
||||
@@ -255,7 +261,7 @@ sub serve_phlog_archive {
|
||||
$self->log(3, "Serving phlog archive");
|
||||
my @pages = sort { $b cmp $a } grep(/^\d\d\d\d-\d\d-\d\d/, @IndexList);
|
||||
for my $id (@pages) {
|
||||
$self->print_menu("1" . NormalToFree($id), "$id/menu");
|
||||
$self->print_menu("1" . normal_to_free($id), "$id/menu");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +269,7 @@ sub serve_index {
|
||||
my $self = shift;
|
||||
$self->log(3, "Serving index of all pages");
|
||||
for my $id (sort newest_first @IndexList) {
|
||||
$self->print_menu("1" . NormalToFree($id), "$id/menu");
|
||||
$self->print_menu("1" . normal_to_free($id), "$id/menu");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,7 +280,7 @@ sub serve_match {
|
||||
$self->print_info("Use a regular expression to match page titles.");
|
||||
$self->print_info("Spaces in page titles are underlines, '_'.");
|
||||
for my $id (sort newest_first grep(/$match/i, @IndexList)) {
|
||||
$self->print_menu( "1" . NormalToFree($id), "$id/menu");
|
||||
$self->print_menu( "1" . normal_to_free($id), "$id/menu");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,7 +291,7 @@ sub serve_search {
|
||||
$self->print_info("Use regular expressions separated by spaces.");
|
||||
SearchTitleAndBody($str, sub {
|
||||
my $id = shift;
|
||||
$self->print_menu("1" . NormalToFree($id), "$id/menu");
|
||||
$self->print_menu("1" . normal_to_free($id), "$id/menu");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -299,7 +305,7 @@ sub serve_tags {
|
||||
$count{$tag} = @{$h{$tag}};
|
||||
}
|
||||
foreach my $id (sort { $count{$b} <=> $count{$a} } keys %count) {
|
||||
$self->print_menu("1" . NormalToFree($id), "$id/tag");
|
||||
$self->print_menu("1" . normal_to_free($id), "$id/tag");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,7 +332,7 @@ sub serve_rc {
|
||||
sub {
|
||||
my($id, $ts, $author_host, $username, $summary, $minor, $revision,
|
||||
$languages, $cluster, $last) = @_;
|
||||
$self->print_menu("1" . NormalToFree($id), "$id/menu");
|
||||
$self->print_menu("1" . normal_to_free($id), "$id/menu");
|
||||
for my $line (split(/\n/, wrap(' ', ' ', $summary))) {
|
||||
$self->print_info($line);
|
||||
}
|
||||
@@ -403,7 +409,7 @@ sub serve_file_page_menu {
|
||||
my $revision = shift;
|
||||
my $code = substr($type, 0, 6) eq 'image/' ? 'I' : '9';
|
||||
$self->log(3, "Serving file page menu for " . UrlEncode($id));
|
||||
$self->print_menu($code . NormalToFree($id)
|
||||
$self->print_menu($code . normal_to_free($id)
|
||||
. ($revision ? "/$revision" : ""), $id);
|
||||
$self->serve_page_comment_link($id, $revision);
|
||||
$self->serve_page_history_link($id, $revision);
|
||||
@@ -418,11 +424,11 @@ sub serve_text_page_menu {
|
||||
. ($revision ? "/$revision" : ""));
|
||||
|
||||
$self->print_info("The text of this page:");
|
||||
$self->print_menu("0" . NormalToFree($id),
|
||||
$self->print_menu("0" . normal_to_free($id),
|
||||
$id . ($revision ? "/$revision" : ""));
|
||||
$self->print_menu("h" . NormalToFree($id),
|
||||
$self->print_menu("h" . normal_to_free($id),
|
||||
$id . ($revision ? "/$revision" : "") . "/html");
|
||||
$self->print_menu("w" . "Replace " . NormalToFree($id),
|
||||
$self->print_menu("w" . "Replace " . normal_to_free($id),
|
||||
$id . "/write/text");
|
||||
|
||||
$self->serve_page_comment_link($id, $revision);
|
||||
@@ -434,7 +440,7 @@ sub serve_text_page_menu {
|
||||
= ($1, $2||$4||$9, $3, $5, $6||70, $7||1, $8);
|
||||
if ($first) {
|
||||
$self->print_info("");
|
||||
$self->print_info("Links leaving " . NormalToFree($id) . ":");
|
||||
$self->print_info("Links leaving " . normal_to_free($id) . ":");
|
||||
$first = 0;
|
||||
}
|
||||
if ($hostname) {
|
||||
@@ -447,8 +453,8 @@ sub serve_text_page_menu {
|
||||
} elsif ($title =~ s!^image[/a-z]* external:!pics/!) {
|
||||
$self->print_menu("I" . $text||$title, $title);
|
||||
} elsif ($title) {
|
||||
$title =~ s!^image[/[a-z]]*:!!;
|
||||
$self->print_menu("1" . $text||$title, $title . "/menu");
|
||||
$title =~ s!^image[/a-z]*:!!i;
|
||||
$self->print_menu("1" . ($text||$title), $title . "/menu");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -478,18 +484,18 @@ sub serve_page_history {
|
||||
$self->log(3, "Serving history of " . UrlEncode($id));
|
||||
OpenPage($id);
|
||||
|
||||
$self->print_menu("1" . NormalToFree($id) . " (current)", "$id/menu");
|
||||
$self->print_menu("1" . normal_to_free($id) . " (current)", "$id/menu");
|
||||
$self->print_info(CalcTime($Page{ts})
|
||||
. " by " . GetAuthor($Page{host}, $Page{username})
|
||||
. " by " . GetAuthor($Page{username})
|
||||
. ($Page{summary} ? ": $Page{summary}" : "")
|
||||
. ($Page{minor} ? " (minor)" : ""));
|
||||
|
||||
foreach my $revision (GetKeepRevisions($OpenPageName)) {
|
||||
my $keep = GetKeptRevision($revision);
|
||||
$self->print_menu("1" . NormalToFree($id) . " ($keep->{revision})",
|
||||
$self->print_menu("1" . normal_to_free($id) . " ($keep->{revision})",
|
||||
"$id/$keep->{revision}/menu");
|
||||
$self->print_info(CalcTime($keep->{ts})
|
||||
. " by " . GetAuthor($keep->{host}, $keep->{username})
|
||||
. " by " . GetAuthor($keep->{username})
|
||||
. ($keep->{summary} ? ": $keep->{summary}" : "")
|
||||
. ($keep->{minor} ? " (minor)" : ""));
|
||||
}
|
||||
@@ -570,7 +576,7 @@ sub serve_page_html {
|
||||
|
||||
$self->log(3, "Serving " . UrlEncode($id) . " as HTML");
|
||||
|
||||
my $title = NormalToFree($id);
|
||||
my $title = normal_to_free($id);
|
||||
print GetHtmlHeader(Ts('%s:', $SiteName) . ' ' . UnWiki($title), $id);
|
||||
print GetHeaderDiv($id, $title);
|
||||
print $q->start_div({-class=>'wrapper'});
|
||||
@@ -631,7 +637,7 @@ sub serve_tag_list {
|
||||
my $tag = shift;
|
||||
$self->print_info("Search result for tag $tag:");
|
||||
for my $id (sort newest_first TagFind($tag)) {
|
||||
$self->print_menu("1" . NormalToFree($id), "$id/menu");
|
||||
$self->print_menu("1" . normal_to_free($id), "$id/menu");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -641,7 +647,7 @@ sub serve_tag {
|
||||
$self->log(3, "Serving tag " . UrlEncode($tag));
|
||||
if ($IndexHash{$tag}) {
|
||||
$self->print_info("This page is about the tag $tag.");
|
||||
$self->print_menu("1" . NormalToFree($tag), "$tag/menu");
|
||||
$self->print_menu("1" . normal_to_free($tag), "$tag/menu");
|
||||
$self->print_info("");
|
||||
}
|
||||
$self->serve_tag_list($tag);
|
||||
@@ -679,7 +685,7 @@ sub write_page_ok {
|
||||
my $self = shift;
|
||||
my $id = shift;
|
||||
$self->print_info("Page was saved.");
|
||||
$self->print_menu("1" . NormalToFree($id), "$id/menu");
|
||||
$self->print_menu("1" . normal_to_free($id), "$id/menu");
|
||||
}
|
||||
|
||||
sub write_page_error {
|
||||
|
||||
@@ -41,7 +41,7 @@ while ($arg =~ /^-l/) {
|
||||
die $help unless -f $file;
|
||||
my %backup = %Translate;
|
||||
header_info_extract($file); # keep the header information of the translation files
|
||||
do $file or die "Cannot do $file";
|
||||
do "./$file" or die "Cannot do $file";
|
||||
foreach my $key (keys %Translate) {
|
||||
$backup{$key} = $Translate{$key};
|
||||
}
|
||||
|
||||
40
t/checkbox.t
Normal file
@@ -0,0 +1,40 @@
|
||||
# Copyright (C) 2018 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 => 5;
|
||||
|
||||
add_module('checkbox.pl');
|
||||
|
||||
my $text = q{
|
||||
There's some stuff I want to work on:
|
||||
|
||||
[[ :something to do]]
|
||||
[[x:something done]]
|
||||
[[save:update the list]]
|
||||
|
||||
Let's do this!
|
||||
};
|
||||
|
||||
$page = update_page('TODO', $text, 'saving it');
|
||||
|
||||
xpath_test(
|
||||
$page,
|
||||
'//p[text()="There\'s some stuff I want to work on:"]',
|
||||
'//form[@class="checkboxes"]/p/label/input[@type="checkbox"][@name="something_to_do"]/following-sibling::text()[string()="something to do"]',
|
||||
'//form[@class="checkboxes"]/p/label/input[@type="checkbox"][@name="something_done"][@checked="checked"]/following-sibling::text()[string()="something done"]',
|
||||
'//form[@class="checkboxes"]/p/input[@type="submit"][@name="update the list"]',
|
||||
'//p[text()="Let\'s do this!"]',);
|
||||
@@ -226,7 +226,7 @@ like($page, qr/^$haiku_re/, "Haiku updated");
|
||||
|
||||
$page = query_gopher("Haiku/history");
|
||||
like($page, qr/^1Haiku \(current\)\tHaiku\/menu\t/m, "Haiku (current)");
|
||||
like($page, qr/^i\d\d:\d\d UTC by Alex from \S+: typos \(minor\)/m,
|
||||
like($page, qr/^i\d\d:\d\d UTC by Alex: typos \(minor\)/m,
|
||||
"Metadata recorded");
|
||||
like($page, qr/^1Haiku \(1\)\tHaiku\/1\/menu\t/m, "Haiku (1)");
|
||||
|
||||
|
||||
73
t/maintain.t
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2009–2015 Alex Schroeder <alex@gnu.org>
|
||||
# Copyright (C) 2009–2018 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
|
||||
@@ -15,18 +15,66 @@
|
||||
|
||||
require './t/test.pl';
|
||||
package OddMuse;
|
||||
use Test::More tests => 10;
|
||||
use Test::More tests => 20;
|
||||
|
||||
my $hundred_days_ago = $Now - 100 * 24 * 60 * 60;
|
||||
my $ten_days_ago = $Now - 10 * 24 * 60 * 60;
|
||||
my $two_days_ago = $Now - 2 * 24 * 60 * 60;
|
||||
my $ip = '127.0.0.1';
|
||||
# $ts, $id, $minor, $summary, $host, @rest
|
||||
|
||||
# First, make sure that moving all the entries from rc.log leaves no newline in
|
||||
# the file.
|
||||
|
||||
my $log = join("\n",
|
||||
join($FS, $hundred_days_ago, 'Two_Hundred_Days_Ago', '',
|
||||
'Boring', $ip,
|
||||
'Alex', '1', '', ''),
|
||||
'');
|
||||
WriteStringToFile($RcFile, $log);
|
||||
|
||||
# old log entry to be moved
|
||||
my $log = join($FS, '1235079422', 'Ganz_und_Gar', '',
|
||||
'Ladenbeschreibung und Preisliste', '62.12.165.34',
|
||||
'Alex', '1', '', '');
|
||||
WriteStringToFile($RcFile, $log . "\n");
|
||||
test_page(get_page('action=maintain pwd=foo'),
|
||||
'Moving 1 log entries');
|
||||
test_page(ReadFileOrDie($RcOldFile),
|
||||
"^1235079422$FS");
|
||||
is(ReadFileOrDie($RcFile), '', 'empty rc.log');
|
||||
'Moving 1 log entries',
|
||||
'Removing IP numbers from 0 log entries');
|
||||
$log = ReadFileOrDie($RcOldFile);
|
||||
test_page($log, "Hundred_Days_Ago.*Anonymous");
|
||||
test_page_negative($log, $ip);
|
||||
$log = ReadFileOrDie($RcFile);
|
||||
is($log, '', 'rc.log is empty');
|
||||
|
||||
# Now let's make sure that an old entry get anonymized and moved (like the
|
||||
# previous test), and that those that are not moved care anonymized if they are
|
||||
# old enough.
|
||||
|
||||
$log = join("\n",
|
||||
join($FS, $hundred_days_ago, 'One_Hundred_Days_Ago', '',
|
||||
'Boring', $ip,
|
||||
'Alex', '1', '', ''),
|
||||
join($FS, $ten_days_ago, 'Ten_Days_Ago', '',
|
||||
'Boring', $ip,
|
||||
'Alex', '1', '', ''),
|
||||
join($FS, $two_days_ago, 'Two_Days_Ago', '',
|
||||
'Boring', $ip,
|
||||
'Alex', '1', '', ''),
|
||||
'');
|
||||
WriteStringToFile($RcFile, $log);
|
||||
|
||||
test_page(get_page('action=maintain pwd=foo'),
|
||||
'Moving 1 log entries',
|
||||
'Removing IP numbers from 1 log entries');
|
||||
$log = ReadFileOrDie($RcOldFile);
|
||||
test_page($log,
|
||||
"Two_Hundred_Days_Ago.*Anonymous",
|
||||
"One_Hundred_Days_Ago.*Anonymous");
|
||||
test_page_negative($log, $ip);
|
||||
$log = ReadFileOrDie($RcFile);
|
||||
test_page($log,
|
||||
"Ten_Days_Ago.*Anonymous",
|
||||
"Two_Days_Ago.*$ip");
|
||||
test_page_negative($log, "Hundred_Days_Ago");
|
||||
|
||||
# Let's make sure that updating pages write the right rc lines.
|
||||
|
||||
update_page('test', 'this is a test');
|
||||
my $log = ReadFileOrDie($RcFile);
|
||||
test_page($log,
|
||||
@@ -34,7 +82,8 @@ test_page($log,
|
||||
"${FS}this is a test${FS}");
|
||||
test_page_negative($log, "^\n");
|
||||
|
||||
# old page to be deleted
|
||||
# Make sure that pages to be deleted are in fact deleted.
|
||||
|
||||
OpenPage('test');
|
||||
$Page{ts} = 1;
|
||||
$Page{revision} = 1;
|
||||
|
||||
4
t/rc.t
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2006–20015 Alex Schroeder <alex@gnu.org>
|
||||
# Copyright (C) 2006–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
|
||||
@@ -51,7 +51,7 @@ test_page(get_page('action=rc raw=1'), 'title: Wiki');
|
||||
WriteStringToFile($RcFile, "1${FS}test${FS}${FS}test${FS}127.0.0.1${FS}${FS}1${FS}${FS}\n");
|
||||
test_page_negative(get_page('action=rc raw=1'), 'title: test');
|
||||
test_page(get_page('action=rc raw=1 from=1'), 'title: Wiki', 'title: test',
|
||||
'description: test', 'generator: 127.0.0.1',
|
||||
'description: test', 'generator: Anonymous',
|
||||
'link: http://localhost/wiki.pl/test',
|
||||
'last-modified: 1970-01-01T00:00Z', 'revision: 1');
|
||||
|
||||
|
||||
23
t/search-inclusion.t
Normal file
@@ -0,0 +1,23 @@
|
||||
# Copyright (C) 2018 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;
|
||||
|
||||
test_page(update_page("Omega", "last page"), "last page");
|
||||
test_page(update_page("Alpha", "first page\n<search page>"),
|
||||
"Omega");
|
||||
test_page(get_page('Omega'), 'last page');
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (C) 2006–2015 Alex Schroeder <alex@gnu.org>
|
||||
# Copyright (C) 2006–2018 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
|
||||
@@ -156,7 +156,7 @@ xpath_test(update_page('IncludeSearch',
|
||||
'//p[text()="first line "]', # note the NL -> SPC
|
||||
'//div[@class="search"]/p/span[@class="result"]/a[@class="local"][@href="http://localhost/wiki.pl/NegativeSearchTest"][text()="NegativeSearchTest"]',
|
||||
'//div[@class="search"]/p/span[@class="result"]/a[@class="local"][@href="http://localhost/wiki.pl/NegativeSearchTestTwo"][text()="NegativeSearchTestTwo"]',
|
||||
'//p[text()=" last line"]'); # note the NL -> SPC
|
||||
'//p[text()=" last line"]'); # note the NL -> SPC
|
||||
|
||||
xpath_test(get_page('search=Schröder'),
|
||||
'//input[@name="search"][@value="Schröder"]');
|
||||
|
||||
100
wiki.pl
@@ -1,5 +1,5 @@
|
||||
#! /usr/bin/perl
|
||||
# Copyright (C) 2001-2015
|
||||
# Copyright (C) 2001-2018
|
||||
# Alex Schroeder <alex@gnu.org>
|
||||
# Copyright (C) 2014-2015
|
||||
# Alex Jakimenko <alex.jakimenko@gmail.com>
|
||||
@@ -35,6 +35,7 @@ use warnings;
|
||||
no warnings 'numeric';
|
||||
no warnings 'uninitialized';
|
||||
use utf8; # in case anybody ever adds UTF8 characters to the source
|
||||
use B;
|
||||
use CGI qw/-utf8/;
|
||||
use CGI::Carp qw(fatalsToBrowser);
|
||||
use File::Glob ':glob';
|
||||
@@ -124,6 +125,7 @@ our $DeletedPage = 'DeletedPage'; # Pages starting with this can be deleted
|
||||
our $RCName = 'RecentChanges'; # Name of changes page
|
||||
our @RcDays = qw(1 3 7 30 90); # Days for links on RecentChanges
|
||||
our $RcDefault = 30; # Default number of RecentChanges days
|
||||
our $KeepHostDays = 4; # Days to keep IP numbers for
|
||||
our $KeepDays = 0; # Days to keep old revisions (0 means keep forever)
|
||||
our $KeepMajor = 1; # 1 = keep at least one major rev when expiring pages
|
||||
our $SummaryHours = 4; # Hours to offer the old subject when editing a page
|
||||
@@ -1324,12 +1326,12 @@ sub DoBrowseRequest {
|
||||
eval { local $SIG{__DIE__}; MyActions(); };
|
||||
} elsif ($action) {
|
||||
ReportError(Ts('Invalid action parameter %s', $action), '501 NOT IMPLEMENTED');
|
||||
} elsif (GetParam('match', '') ne '') {
|
||||
SetParam('action', 'index'); # make sure this gets a NOINDEX
|
||||
DoIndex();
|
||||
} elsif (GetParam('search', '') ne '') { # allow search for "0"
|
||||
SetParam('action', 'search'); # make sure this gets a NOINDEX
|
||||
DoSearch();
|
||||
} elsif (GetParam('match', '') ne '') {
|
||||
SetParam('action', 'index'); # make sure this gets a NOINDEX
|
||||
DoIndex();
|
||||
} elsif (GetParam('title', '') and not GetParam('Cancel', '')) {
|
||||
DoPost(GetParam('title', ''));
|
||||
} else {
|
||||
@@ -1757,7 +1759,7 @@ sub RcHtml {
|
||||
$languages, $cluster, $last) = @_;
|
||||
my $all_revision = $last ? undef : $revision; # no revision for the last one
|
||||
$host = QuoteHtml($host);
|
||||
my $author = GetAuthorLink($host, $username);
|
||||
my $author = GetAuthorLink($username, $host);
|
||||
my $sum = $summary ? $q->span({class=>'dash'}, ' – ')
|
||||
. $q->strong(QuoteHtml($summary)) : '';
|
||||
my $edit = $minor ? $q->em({class=>'type'}, T('(minor)')) : '';
|
||||
@@ -1840,7 +1842,7 @@ sub RcTextRevision {
|
||||
: ($UsePathInfo ? '/' : '?') . UrlEncode($id));
|
||||
print "\n", RcTextItem('title', NormalToFree($id)),
|
||||
RcTextItem('description', $summary),
|
||||
RcTextItem('generator', GetAuthor($host, $username)),
|
||||
RcTextItem('generator', GetAuthor($username)),
|
||||
RcTextItem('language', join(', ', @{$languages})), RcTextItem('link', $link),
|
||||
RcTextItem('last-modified', TimeToW3($ts)),
|
||||
RcTextItem('revision', $revision),
|
||||
@@ -1925,7 +1927,6 @@ sub RssItem {
|
||||
}
|
||||
my $date = TimeToRFC822($ts);
|
||||
$username = QuoteHtml($username);
|
||||
$username ||= $host;
|
||||
my $rss = "<item>\n";
|
||||
$rss .= "<title>$name</title>\n";
|
||||
my $link = ScriptUrl(GetParam('all', $cluster)
|
||||
@@ -2034,8 +2035,7 @@ sub GetHistoryLine {
|
||||
$html .= ' ' . GetOldPageLink('browse', $id, $revision,
|
||||
Ts('Revision %s', $revision));
|
||||
}
|
||||
my $host = $data{host} || $data{ip};
|
||||
$html .= T(' . . . .') . ' ' . GetAuthorLink($host, $data{username});
|
||||
$html .= T(' . . . .') . ' ' . GetAuthorLink($data{username});
|
||||
$html .= $q->span({class=>'dash'}, ' – ')
|
||||
. $q->strong(QuoteHtml($data{summary})) if $data{summary};
|
||||
$html .= ' ' . $q->em({class=>'type'}, T('(minor)')) . ' ' if $data{minor};
|
||||
@@ -2197,26 +2197,37 @@ sub ScriptLinkDiff {
|
||||
return ScriptLink($action, $text, 'diff');
|
||||
}
|
||||
|
||||
sub ColorCode {
|
||||
my ($str) = @_;
|
||||
my $num = unpack("L",B::hash($str)); # 32-bit integer
|
||||
my $code = sprintf("%o", $num); # octal is 0-7
|
||||
my @indexes = split(//, substr($code, 0, 4)); # four numbers
|
||||
my @colors = qw/red orange yellow green blue indigo violet white/;
|
||||
return $q->span({-class => 'ip-code', -title => T('Anonymous')},
|
||||
join('', map { $q->span({-class => $colors[$_]}, $_) }
|
||||
@indexes));
|
||||
}
|
||||
|
||||
sub GetAuthor {
|
||||
my ($host, $username) = @_;
|
||||
return $username . ' ' . Ts('from %s', $host) if $username and $host;
|
||||
my ($username) = @_;
|
||||
return $username if $username;
|
||||
return T($host); # could be 'Anonymous'
|
||||
return T('Anonymous');
|
||||
}
|
||||
|
||||
sub GetAuthorLink {
|
||||
my ($host, $username) = @_;
|
||||
my ($username, $host) = @_;
|
||||
$username = FreeToNormal($username);
|
||||
my $name = NormalToFree($username);
|
||||
if (ValidId($username) ne '') { # ValidId() returns error string
|
||||
$username = ''; # Just pretend it isn't there.
|
||||
}
|
||||
if ($username and $RecentLink) {
|
||||
return ScriptLink(UrlEncode($username), $name, 'author', undef, $host);
|
||||
return ScriptLink(UrlEncode($username), $name, 'author');
|
||||
} elsif ($username) {
|
||||
return $q->span({-class=>'author'}, $name);
|
||||
}
|
||||
return T($host); # could be 'Anonymous'
|
||||
return T('Anonymous') if $host eq 'Anonymous';
|
||||
return ColorCode($host);
|
||||
}
|
||||
|
||||
sub GetHistoryLink {
|
||||
@@ -2437,7 +2448,7 @@ sub GetFooterTimestamp {
|
||||
$page //= \%Page;
|
||||
if ($id and $rev ne 'history' and $rev ne 'edit' and $page->{revision}) {
|
||||
my @elements = (($rev eq '' ? T('Last edited') : T('Edited')), TimeToText($page->{ts}),
|
||||
Ts('by %s', GetAuthorLink($page->{host}, $page->{username})));
|
||||
Ts('by %s', GetAuthorLink($page->{username})));
|
||||
push(@elements, ScriptLinkDiff(2, $id, T('(diff)'), $rev)) if $UseDiff and $page->{revision} > 1;
|
||||
return $q->div({-class=>'time'}, @elements);
|
||||
}
|
||||
@@ -3473,8 +3484,8 @@ sub SearchTitleAndBody {
|
||||
foreach my $id (Filtered($regex, AllPagesList())) {
|
||||
my $name = NormalToFree($id);
|
||||
my ($text) = PageIsUploadedFile($id); # set to mime-type if this is an uploaded file
|
||||
local ($OpenPageName, %Page); # this is local!
|
||||
if (not $text) { # not uploaded file, therefore allow searching of page body
|
||||
local ($OpenPageName, %Page); # this is local!
|
||||
OpenPage($id); # this opens a page twice if it is not uploaded, but that's ok
|
||||
if ($lang) {
|
||||
my @languages = split(/,/, $Page{languages});
|
||||
@@ -3490,8 +3501,11 @@ sub SearchTitleAndBody {
|
||||
return @found;
|
||||
}
|
||||
|
||||
sub Filtered { # this is overwriten in extensions such as tags.pl
|
||||
return @_[1 .. $#_]; # ignores $regex and returns all pages
|
||||
sub Filtered { # this is overwriten in extensions such as tags.pl
|
||||
my ($string, @pages) = @_;
|
||||
my $match = GetParam('match', '');
|
||||
@pages = grep /$match/i, @pages if $match;
|
||||
return @pages;
|
||||
}
|
||||
|
||||
sub SearchString {
|
||||
@@ -3526,20 +3540,19 @@ sub PrintSearchResult {
|
||||
$entry{size} = int((length($text) / 1024) + 1) . 'K';
|
||||
$entry{'last-modified'} = TimeToText($Page{ts});
|
||||
$entry{username} = $Page{username};
|
||||
$entry{host} = $Page{host};
|
||||
PrintSearchResultEntry(\%entry);
|
||||
}
|
||||
|
||||
sub PrintSearchResultEntry {
|
||||
my %entry = %{(shift)}; # get value from reference
|
||||
if (GetParam('raw', 0)) {
|
||||
$entry{generator} = GetAuthor($entry{host}, $entry{username});
|
||||
foreach my $key (qw(title description size last-modified generator username host)) {
|
||||
$entry{generator} = GetAuthor($entry{username});
|
||||
foreach my $key (qw(title description size last-modified generator username)) {
|
||||
print RcTextItem($key, $entry{$key});
|
||||
}
|
||||
print RcTextItem('link', "$ScriptName?$entry{title}"), "\n";
|
||||
} else {
|
||||
my $author = GetAuthorLink($entry{host}, $entry{username});
|
||||
my $author = GetAuthorLink($entry{username});
|
||||
$author ||= $entry{generator};
|
||||
my $id = $entry{title};
|
||||
my ($class, $resolved, $title, $exists) = ResolveId($id);
|
||||
@@ -3593,8 +3606,8 @@ sub ReplaceAndSave {
|
||||
RequestLockOrError(); # fatal
|
||||
my @result = Replace($from, $to, 1, sub {
|
||||
my ($id, $new) = @_;
|
||||
Save($id, $new, $from . ' → ' . $to, 1, ($Page{host} ne $q->remote_addr()));
|
||||
});
|
||||
Save($id, $new, $from . ' → ' . $to, 1);
|
||||
});
|
||||
ReleaseLock();
|
||||
return @result;
|
||||
}
|
||||
@@ -3713,9 +3726,7 @@ sub DoPost {
|
||||
}
|
||||
my $newAuthor = 0;
|
||||
if ($oldrev) { # the first author (no old revision) is not considered to be "new"
|
||||
# prefer usernames for potential new author detection
|
||||
$newAuthor = 1 if not $Page{username} or $Page{username} ne GetParam('username', '');
|
||||
$newAuthor = 1 if not $q->remote_addr() or not $Page{host} or $q->remote_addr() ne $Page{host};
|
||||
}
|
||||
my $oldtime = $Page{ts};
|
||||
my $myoldtime = GetParam('oldtime', ''); # maybe empty!
|
||||
@@ -3789,7 +3800,6 @@ sub AddComment {
|
||||
sub Save { # call within lock, with opened page
|
||||
my ($id, $new, $summary, $minor, $upload) = @_;
|
||||
my $user = GetParam('username', '');
|
||||
my $host = $q->remote_addr();
|
||||
my $revision = $Page{revision} + 1;
|
||||
my $old = $Page{text};
|
||||
my $olddiff = $Page{'diff-major'} == '1' ? $Page{'diff-minor'} : $Page{'diff-major'};
|
||||
@@ -3805,8 +3815,8 @@ sub Save { # call within lock, with opened page
|
||||
ExpireKeepFiles();
|
||||
$Page{lastmajor} = $revision unless $minor;
|
||||
$Page{lastmajorsummary} = $summary unless $minor;
|
||||
@Page{qw(ts revision summary username host minor text)} =
|
||||
($Now, $revision, $summary, $user, $host, $minor, $new);
|
||||
@Page{qw(ts revision summary username minor text)} =
|
||||
($Now, $revision, $summary, $user, $minor, $new);
|
||||
if ($UseDiff and $UseCache > 1 and $revision > 1 and not $upload and not TextIsFile($old)) {
|
||||
UpdateDiffs($old, $new, $olddiff); # sets diff-major and diff-minor
|
||||
}
|
||||
@@ -3817,6 +3827,7 @@ sub Save { # call within lock, with opened page
|
||||
if ($revision == 1 and $LockOnCreation{$id}) {
|
||||
WriteStringToFile(GetLockedPageFile($id), 'LockOnCreation');
|
||||
}
|
||||
my $host = $q->remote_addr();
|
||||
WriteRcLog($id, $summary, $minor, $revision, $user, $host, $languages, GetCluster($new));
|
||||
AddToIndex($id) if ($revision == 1);
|
||||
}
|
||||
@@ -3890,7 +3901,7 @@ sub DoMaintain {
|
||||
RequestLockOrError();
|
||||
print $q->p(T('Main lock obtained.'));
|
||||
print $q->p(Ts('Moving part of the %s log file.', $RCName));
|
||||
# Determine the number of days to go back
|
||||
# Determine the number of days to go back, default is largest of @RcDays
|
||||
my $days = 0;
|
||||
foreach (@RcDays) {
|
||||
$days = $_ if $_ > $days;
|
||||
@@ -3901,23 +3912,36 @@ sub DoMaintain {
|
||||
if (not $status) {
|
||||
print $q->p($q->strong(Ts('Could not open %s log file', $RCName) . ':') . ' ' . $RcFile),
|
||||
$q->p(T('Error was') . ':'), $q->pre($!), $q->p(T('Note: This error is normal if no changes have been made.'));
|
||||
} else {
|
||||
WriteStringToFile($RcFile . '.old', $data);
|
||||
}
|
||||
# Move the old stuff from rc to temp
|
||||
my @rc = split(/\n/, $data);
|
||||
my @tmp = ();
|
||||
for my $line (@rc) {
|
||||
my $line;
|
||||
my $changed = 0;
|
||||
while ($line = shift(@rc)) {
|
||||
my ($ts, $id, $minor, $summary, $host, @rest) = split(/$FS/, $line);
|
||||
last if $ts >= $starttime;
|
||||
push(@tmp, join($FS, $ts, $id, $minor, $summary, 'Anonymous', @rest));
|
||||
$changed = 1;
|
||||
}
|
||||
unshift(@rc, $line) if $line; # this one ended the loop
|
||||
print $q->p(Ts('Moving %s log entries.', scalar(@tmp)));
|
||||
if (@tmp) {
|
||||
# Write new files, and backups
|
||||
AppendStringToFile($RcOldFile, join("\n", @tmp) . "\n");
|
||||
WriteStringToFile($RcFile . '.old', $data);
|
||||
splice(@rc, 0, scalar(@tmp)); # strip
|
||||
WriteStringToFile($RcFile, @rc ? join("\n", @rc) . "\n" : '');
|
||||
AppendStringToFile($RcOldFile, join("\n", @tmp) . "\n") if @tmp;
|
||||
# remove IP numbers from all but the last few days
|
||||
$starttime = $Now - $KeepHostDays * 86400; # 24*60*60
|
||||
@tmp = ();
|
||||
while ($line = shift(@rc)) {
|
||||
my ($ts, $id, $minor, $summary, $host, @rest) = split(/$FS/, $line);
|
||||
last if $ts >= $starttime;
|
||||
push(@tmp, join($FS, $ts, $id, $minor, $summary, 'Anonymous', @rest));
|
||||
$changed = 1;
|
||||
}
|
||||
unshift(@rc, $line) if $line; # this one ended the loop
|
||||
unshift(@rc, @tmp) if @tmp;
|
||||
print $q->p(Ts('Removing IP numbers from %s log entries.', scalar(@tmp)));
|
||||
WriteStringToFile($RcFile, @rc ? join("\n", @rc) . "\n" : '') if $changed;
|
||||
if (opendir(DIR, $RssDir)) { # cleanup if they should expire anyway
|
||||
foreach (readdir(DIR)) {
|
||||
Unlink("$RssDir/$_") if $Now - Modified($_) > $RssCacheHours * 3600;
|
||||
|
||||