2015-07-13 08:46:50 +02:00
|
|
|
|
# Copyright (C) 2004–2015 Alex Schroeder <alex@gnu.org>
|
2015-09-23 20:58:50 +03:00
|
|
|
|
# Copyright (C) 2015 Alex-Daniel Jakimenko <alex.jakimenko@gmail.com>
|
2006-09-18 00:06:31 +00:00
|
|
|
|
#
|
2012-05-25 00:57:40 +02:00
|
|
|
|
# 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.
|
2006-09-18 00:06:31 +00:00
|
|
|
|
#
|
2012-05-25 00:57:40 +02:00
|
|
|
|
# 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.
|
2006-09-18 00:06:31 +00:00
|
|
|
|
#
|
2012-05-25 00:57:40 +02:00
|
|
|
|
# You should have received a copy of the GNU General Public License along with
|
|
|
|
|
|
# this program. If not, see <http://www.gnu.org/licenses/>.
|
2006-09-18 00:06:31 +00:00
|
|
|
|
|
2006-09-18 21:14:01 +00:00
|
|
|
|
package OddMuse;
|
|
|
|
|
|
use lib '.';
|
2006-09-18 00:06:31 +00:00
|
|
|
|
use XML::LibXML;
|
2012-05-24 12:25:01 +02:00
|
|
|
|
use utf8;
|
2016-06-22 14:54:52 +02:00
|
|
|
|
use Encode qw(encode_utf8 decode_utf8);
|
2012-07-30 23:30:27 +02:00
|
|
|
|
use vars qw($raw);
|
2006-09-18 00:06:31 +00:00
|
|
|
|
|
2013-01-12 23:55:08 +01:00
|
|
|
|
# Test::More explains how to fix wide character in print issues
|
|
|
|
|
|
my $builder = Test::More->builder;
|
2015-05-02 05:00:02 +03:00
|
|
|
|
binmode $builder->output, ":encoding(UTF-8)";
|
|
|
|
|
|
binmode $builder->failure_output, ":encoding(UTF-8)";
|
|
|
|
|
|
binmode $builder->todo_output, ":encoding(UTF-8)";
|
2013-01-12 23:55:08 +01:00
|
|
|
|
|
2006-09-18 00:06:31 +00:00
|
|
|
|
# Import the functions
|
|
|
|
|
|
|
2012-07-30 23:30:27 +02:00
|
|
|
|
$raw = 0; # capture utf8 is the default
|
2006-09-18 00:06:31 +00:00
|
|
|
|
$RunCGI = 0; # don't print HTML on stdout
|
|
|
|
|
|
$UseConfig = 0; # don't read module files
|
2008-05-26 22:58:39 +00:00
|
|
|
|
$DataDir = 'test-data';
|
2015-10-12 15:13:22 +02:00
|
|
|
|
while (not mkdir($DataDir)) {
|
|
|
|
|
|
$DataDir = sprintf("test-data-%03d", int(rand(1000)));
|
|
|
|
|
|
}
|
2008-05-26 22:58:39 +00:00
|
|
|
|
$ENV{WikiDataDir} = $DataDir;
|
2006-09-18 21:14:01 +00:00
|
|
|
|
require 'wiki.pl';
|
2013-08-21 10:41:51 +02:00
|
|
|
|
|
|
|
|
|
|
# Try to guess which Perl we should be using. Since we loaded wiki.pl,
|
|
|
|
|
|
# our $ENV{PATH} is set to /bin:/usr/bin in order to find diff and
|
|
|
|
|
|
# grep.
|
|
|
|
|
|
if ($ENV{PERLBREW_PATH}) {
|
|
|
|
|
|
$ENV{PATH} = $ENV{PERLBREW_PATH} . ':' . $ENV{PATH};
|
|
|
|
|
|
} elsif (-f '/usr/local/bin/perl') {
|
|
|
|
|
|
$ENV{PATH} = '/usr/local/bin:' . $ENV{PATH};
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-07-05 03:56:17 +03:00
|
|
|
|
clear_pages();
|
2006-09-18 00:06:31 +00:00
|
|
|
|
Init();
|
2006-09-19 18:27:20 +00:00
|
|
|
|
use vars qw($redirect);
|
|
|
|
|
|
|
2006-09-18 00:06:31 +00:00
|
|
|
|
undef $/;
|
|
|
|
|
|
$| = 1; # no output buffering
|
|
|
|
|
|
|
|
|
|
|
|
sub url_encode {
|
|
|
|
|
|
my $str = shift;
|
|
|
|
|
|
return '' unless $str;
|
2016-06-22 14:54:52 +02:00
|
|
|
|
my @letters = split(//, encode_utf8($str));
|
2006-09-18 00:06:31 +00:00
|
|
|
|
my @safe = ('a' .. 'z', 'A' .. 'Z', '0' .. '9', '-', '_', '.'); # shell metachars are unsafe
|
|
|
|
|
|
foreach my $letter (@letters) {
|
|
|
|
|
|
my $pattern = quotemeta($letter);
|
|
|
|
|
|
if (not grep(/$pattern/, @safe)) {
|
|
|
|
|
|
$letter = sprintf("%%%02x", ord($letter));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return join('', @letters);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-07-30 23:30:27 +02:00
|
|
|
|
# Run perl in a subprocess and make sure it prints UTF-8 and not Latin-1
|
|
|
|
|
|
# If you use the download action, the output will be raw bytes. Use
|
|
|
|
|
|
# something like the following:
|
|
|
|
|
|
# {
|
|
|
|
|
|
# local $raw = 1;
|
|
|
|
|
|
# $page = get_page('action=download id=Trogs');
|
|
|
|
|
|
# }
|
2012-05-22 11:45:00 +02:00
|
|
|
|
sub capture {
|
|
|
|
|
|
my $command = shift;
|
2012-07-30 23:30:27 +02:00
|
|
|
|
if ($raw) {
|
|
|
|
|
|
open (CL, '-|', $command) or die "Can't run $command: $!";
|
|
|
|
|
|
} else {
|
|
|
|
|
|
open (CL, '-|:encoding(utf-8)', $command) or die "Can't run $command: $!";
|
|
|
|
|
|
}
|
2012-05-22 11:45:00 +02:00
|
|
|
|
my $result = <CL>;
|
|
|
|
|
|
close CL;
|
|
|
|
|
|
return $result;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-18 00:06:31 +00:00
|
|
|
|
sub update_page {
|
|
|
|
|
|
my ($id, $text, $summary, $minor, $admin, @rest) = @_;
|
2015-09-12 00:05:30 +02:00
|
|
|
|
$id = FreeToNormal($id);
|
2006-09-18 00:06:31 +00:00
|
|
|
|
my $pwd = $admin ? 'foo' : 'wrong';
|
2010-11-06 16:19:19 +00:00
|
|
|
|
my $page = url_encode($id);
|
2006-09-18 00:06:31 +00:00
|
|
|
|
$text = url_encode($text);
|
|
|
|
|
|
$summary = url_encode($summary);
|
|
|
|
|
|
$minor = $minor ? 'on' : 'off';
|
|
|
|
|
|
my $rest = join(' ', @rest);
|
2012-05-22 11:45:00 +02:00
|
|
|
|
$redirect = capture("perl wiki.pl 'Save=1' 'title=$page' 'summary=$summary' 'recent_edit=$minor' 'text=$text' 'pwd=$pwd' $rest");
|
|
|
|
|
|
$output = capture("perl wiki.pl action=browse id=$page $rest");
|
2006-10-10 01:37:01 +00:00
|
|
|
|
if ($redirect =~ /^Status: 302 /) {
|
2006-10-10 01:28:17 +00:00
|
|
|
|
# just in case a new page got created or NearMap or InterMap
|
|
|
|
|
|
$IndexHash{$id} = 1;
|
|
|
|
|
|
@IndexList = sort(keys %IndexHash);
|
|
|
|
|
|
ReInit($id); # if $id eq $InterMap, we need it to be in the $IndexHash before running ReInit()
|
|
|
|
|
|
}
|
2006-09-18 00:06:31 +00:00
|
|
|
|
return $output;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub get_page {
|
2012-05-22 11:45:00 +02:00
|
|
|
|
return capture("perl wiki.pl @_");
|
2006-09-18 00:06:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-19 15:00:18 +00:00
|
|
|
|
sub name {
|
|
|
|
|
|
$_ = shift;
|
|
|
|
|
|
s/\n/\\n/g;
|
2014-06-06 17:32:44 +02:00
|
|
|
|
$_ = '...' . substr($_, -67) if length > 70;
|
2006-09-19 15:00:18 +00:00
|
|
|
|
return $_;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub newlines {
|
2014-01-25 18:16:06 +01:00
|
|
|
|
my @strings = @_;
|
|
|
|
|
|
return map { s/\\n/\n/g; $_; } @strings;
|
2006-09-19 15:00:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# alternating input and output strings for applying rules
|
|
|
|
|
|
sub run_tests {
|
|
|
|
|
|
# translate embedded newlines (other backslashes remain untouched)
|
2014-01-25 18:16:06 +01:00
|
|
|
|
my @tests = newlines(@_);
|
2006-09-19 15:00:18 +00:00
|
|
|
|
my ($input, $output);
|
|
|
|
|
|
while (($input, $output, @tests) = @tests) {
|
|
|
|
|
|
my $result = apply_rules($input);
|
|
|
|
|
|
is($result, $output, name($input));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-07-13 08:46:50 +02:00
|
|
|
|
# alternating input and output strings for applying rules
|
|
|
|
|
|
sub run_tests_negative {
|
|
|
|
|
|
# translate embedded newlines (other backslashes remain untouched)
|
|
|
|
|
|
my @tests = newlines(@_);
|
|
|
|
|
|
my ($input, $output);
|
|
|
|
|
|
while (($input, $output, @tests) = @tests) {
|
|
|
|
|
|
my $result = apply_rules($input);
|
|
|
|
|
|
isnt($result, $output, name($input));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-19 15:00:18 +00:00
|
|
|
|
sub apply_rules {
|
|
|
|
|
|
my $input = shift;
|
|
|
|
|
|
local *STDOUT;
|
|
|
|
|
|
$output = '';
|
|
|
|
|
|
open(STDOUT, '>', \$output) or die "Can't open memory file: $!";
|
|
|
|
|
|
$FootnoteNumber = 0;
|
|
|
|
|
|
ApplyRules(QuoteHtml($input), 1);
|
|
|
|
|
|
return $output;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# alternating input and output strings for applying macros instead of rules
|
|
|
|
|
|
sub run_macro_tests {
|
|
|
|
|
|
# translate embedded newlines (other backslashes remain untouched)
|
|
|
|
|
|
my %test = map { s/\\n/\n/g; $_; } @_;
|
|
|
|
|
|
# Note that the order of tests is not specified!
|
|
|
|
|
|
foreach my $input (keys %test) {
|
|
|
|
|
|
$_ = $input;
|
|
|
|
|
|
foreach my $macro (@MyMacros) { &$macro; }
|
|
|
|
|
|
is($_, $test{$input}, $input);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
# one string, many tests
|
2006-09-18 00:06:31 +00:00
|
|
|
|
sub test_page {
|
2013-01-12 23:55:08 +01:00
|
|
|
|
my ($page, @tests) = @_;
|
|
|
|
|
|
foreach my $test (@tests) {
|
2012-05-22 11:45:00 +02:00
|
|
|
|
like($page, qr($test), name($test));
|
2006-09-18 00:06:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2014-03-18 10:32:22 +01:00
|
|
|
|
# one file, many tests
|
|
|
|
|
|
sub test_file {
|
|
|
|
|
|
my ($file, @tests) = @_;
|
2015-05-02 05:00:02 +03:00
|
|
|
|
if (open(F, '< :encoding(UTF-8)', $file)) {
|
2014-03-18 10:32:22 +01:00
|
|
|
|
local $/ = undef;
|
|
|
|
|
|
test_page(<F>, @tests);
|
|
|
|
|
|
close(F);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
warn "cannot open $file\n";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-19 15:00:18 +00:00
|
|
|
|
# one string, many negative tests
|
2006-09-18 00:06:31 +00:00
|
|
|
|
sub test_page_negative {
|
|
|
|
|
|
my $page = shift;
|
|
|
|
|
|
foreach my $str (@_) {
|
2006-10-06 12:13:18 +00:00
|
|
|
|
unlike($page, qr($str), name("not $str"));
|
2006-09-18 00:06:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-19 14:19:57 +00:00
|
|
|
|
sub xpath_do {
|
|
|
|
|
|
my ($check, $message, $page, @tests) = @_;
|
2007-11-13 20:21:10 +00:00
|
|
|
|
$page =~ s/^.*?(<html)/$1/s; # strip headers
|
2008-10-12 21:21:12 +00:00
|
|
|
|
$page =~ s/^.*?<\?xml.*?>\s*//s; # strip xml processing
|
2007-10-10 14:37:04 +00:00
|
|
|
|
my $page_shown = 0;
|
2006-09-18 00:06:31 +00:00
|
|
|
|
my $parser = XML::LibXML->new();
|
|
|
|
|
|
my $doc;
|
2015-04-02 21:46:49 +02:00
|
|
|
|
my @result;
|
2006-09-19 00:04:23 +00:00
|
|
|
|
SKIP: {
|
|
|
|
|
|
eval { $doc = $parser->parse_html_string($page) };
|
2008-10-12 21:21:12 +00:00
|
|
|
|
eval { $doc = $parser->parse_string($page) } if $@;
|
2006-09-19 10:18:06 +00:00
|
|
|
|
skip("Cannot parse ".name($page).": $@", $#tests + 1) if $@;
|
2006-09-19 00:04:23 +00:00
|
|
|
|
foreach my $test (@tests) {
|
|
|
|
|
|
my $nodelist;
|
2016-06-22 14:54:52 +02:00
|
|
|
|
# libxml2 is not aware of UTF8 flag
|
|
|
|
|
|
eval { $nodelist = $doc->findnodes(encode_utf8($test)) };
|
2006-09-19 00:04:23 +00:00
|
|
|
|
if ($@) {
|
2006-10-06 12:13:18 +00:00
|
|
|
|
fail(&$check(1) ? "$test: $@" : "not $test: $@");
|
2012-05-24 12:25:01 +02:00
|
|
|
|
} elsif (ok(&$check($nodelist->size()),
|
|
|
|
|
|
name(&$check(1) ? $test : "not $test"))) {
|
2015-04-02 21:46:49 +02:00
|
|
|
|
push(@result, $nodelist->string_value());
|
2006-09-19 16:07:39 +00:00
|
|
|
|
} else {
|
2008-06-13 14:41:13 +00:00
|
|
|
|
$page =~ s/^.*?<html/<html/s;
|
2007-10-10 14:37:04 +00:00
|
|
|
|
diag($message, substr($page,0,30000)) unless $page_shown;
|
|
|
|
|
|
$page_shown = 1;
|
2006-09-18 00:06:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2015-04-02 21:46:49 +02:00
|
|
|
|
return wantarray ? @result : $result[0]; # list or string of first result
|
2006-09-18 00:06:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-19 14:19:57 +00:00
|
|
|
|
sub xpath_test {
|
|
|
|
|
|
xpath_do(sub { shift > 0; }, "No Matches\n", @_);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2014-03-18 10:32:22 +01:00
|
|
|
|
sub xpath_test_file {
|
|
|
|
|
|
my ($file, @tests) = @_;
|
2015-05-02 05:00:02 +03:00
|
|
|
|
if (open(F, '< :encoding(UTF-8)', $file)) {
|
2014-03-18 10:32:22 +01:00
|
|
|
|
local $/ = undef;
|
|
|
|
|
|
xpath_test(<F>, @tests);
|
|
|
|
|
|
close(F);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
warn "cannot open $file\n";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-18 00:06:31 +00:00
|
|
|
|
sub negative_xpath_test {
|
2006-09-19 14:19:57 +00:00
|
|
|
|
xpath_do(sub { shift == 0; }, "Unexpected Matches\n", @_);
|
2006-09-18 00:06:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
2009-08-31 08:33:12 +00:00
|
|
|
|
# alias
|
|
|
|
|
|
sub xpath_test_negative {
|
|
|
|
|
|
return negative_xpath_test(@_);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-18 00:06:31 +00:00
|
|
|
|
sub xpath_run_tests {
|
|
|
|
|
|
# translate embedded newlines (other backslashes remain untouched)
|
2014-01-25 18:16:06 +01:00
|
|
|
|
my @tests = newlines(@_);
|
2006-09-19 11:27:36 +00:00
|
|
|
|
my ($input, $output);
|
|
|
|
|
|
while (($input, $output, @tests) = @tests) {
|
2014-01-25 18:16:06 +01:00
|
|
|
|
my $result = apply_rules($input);
|
2006-09-19 11:27:36 +00:00
|
|
|
|
xpath_test("<div>$result</div>", $output);
|
2006-09-18 00:06:31 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-07-13 08:46:50 +02:00
|
|
|
|
sub xpath_run_tests_negative {
|
|
|
|
|
|
# translate embedded newlines (other backslashes remain untouched)
|
|
|
|
|
|
my @tests = newlines(@_);
|
|
|
|
|
|
my ($input, $output);
|
|
|
|
|
|
while (($input, $output, @tests) = @tests) {
|
|
|
|
|
|
my $result = apply_rules($input);
|
|
|
|
|
|
xpath_test_negative("<div>$result</div>", $output);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-18 00:06:31 +00:00
|
|
|
|
sub remove_rule {
|
|
|
|
|
|
my $rule = shift;
|
|
|
|
|
|
my @list = ();
|
|
|
|
|
|
my $found = 0;
|
|
|
|
|
|
foreach my $item (@MyRules) {
|
|
|
|
|
|
if ($item ne $rule) {
|
|
|
|
|
|
push @list, $item;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$found = 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
die "Rule not found" unless $found;
|
|
|
|
|
|
@MyRules = @list;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub add_module {
|
2012-05-24 12:25:01 +02:00
|
|
|
|
my ($mod, $subdir) = @_;
|
|
|
|
|
|
$subdir .= '/' if $subdir and substr($subdir, -1) ne '/';
|
2006-09-18 00:06:31 +00:00
|
|
|
|
mkdir $ModuleDir unless -d $ModuleDir;
|
|
|
|
|
|
my $dir = `/bin/pwd`;
|
|
|
|
|
|
chop($dir);
|
2008-12-17 12:36:52 +00:00
|
|
|
|
if (-l "$ModuleDir/$mod") {
|
|
|
|
|
|
# do nothing
|
2012-05-24 12:25:01 +02:00
|
|
|
|
} elsif (eval{ symlink("$dir/modules/$subdir$mod", "$ModuleDir/$mod"); 1; }) {
|
2008-12-17 12:36:52 +00:00
|
|
|
|
# do nothing
|
|
|
|
|
|
} else {
|
2015-06-27 14:45:48 +03:00
|
|
|
|
system('copy', "$dir/modules/$subdir$mod", "$ModuleDir/$mod");
|
2008-12-17 12:36:52 +00:00
|
|
|
|
}
|
|
|
|
|
|
die "Cannot symlink $mod: $!" unless -e "$ModuleDir/$mod";
|
2006-09-18 00:06:31 +00:00
|
|
|
|
do "$ModuleDir/$mod";
|
|
|
|
|
|
@MyRules = sort {$RuleOrder{$a} <=> $RuleOrder{$b}} @MyRules;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub remove_module {
|
|
|
|
|
|
my $mod = shift;
|
|
|
|
|
|
mkdir $ModuleDir unless -d $ModuleDir;
|
|
|
|
|
|
unlink("$ModuleDir/$mod") or die "Cannot unlink: $!";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2014-07-31 13:17:02 +02:00
|
|
|
|
sub write_config_file {
|
2012-05-24 12:25:01 +02:00
|
|
|
|
open(F, '>:encoding(utf-8)', "$DataDir/config");
|
2006-09-18 00:06:31 +00:00
|
|
|
|
print F "\$AdminPass = 'foo';\n";
|
|
|
|
|
|
# this used to be the default in earlier CGI.pm versions
|
|
|
|
|
|
print F "\$ScriptName = 'http://localhost/wiki.pl';\n";
|
|
|
|
|
|
print F "\$SurgeProtection = 0;\n";
|
|
|
|
|
|
close(F);
|
|
|
|
|
|
$ScriptName = 'http://localhost/test.pl'; # different!
|
|
|
|
|
|
$IndexInit = 0;
|
|
|
|
|
|
%IndexHash = ();
|
2012-08-05 02:28:39 +02:00
|
|
|
|
@IndexList = ();
|
2006-09-18 00:06:31 +00:00
|
|
|
|
$InterSiteInit = 0;
|
|
|
|
|
|
%InterSite = ();
|
|
|
|
|
|
$NearSiteInit = 0;
|
|
|
|
|
|
%NearSite = ();
|
|
|
|
|
|
%NearSearch = ();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2014-07-31 13:17:02 +02:00
|
|
|
|
sub clear_pages {
|
|
|
|
|
|
if (-f "/bin/rm") {
|
2015-06-27 14:45:48 +03:00
|
|
|
|
system('/bin/rm', '-rf', $DataDir);
|
2014-07-31 13:17:02 +02:00
|
|
|
|
} else {
|
2015-06-27 14:45:48 +03:00
|
|
|
|
system('c:/cygwin/bin/rm.exe', '-rf', $DataDir);
|
2014-07-31 13:17:02 +02:00
|
|
|
|
}
|
2015-06-26 20:12:40 +02:00
|
|
|
|
die "Cannot remove '$DataDir'!\n" if -e $DataDir;
|
2014-07-31 13:17:02 +02:00
|
|
|
|
mkdir $DataDir;
|
2015-07-05 08:42:10 +02:00
|
|
|
|
if ($^O eq 'darwin') {
|
|
|
|
|
|
# On a Mac we are probably using the HFS filesystem which uses NFD instead
|
|
|
|
|
|
# of NFC for filenames. Since clear_pages runs as the very first thing, the
|
|
|
|
|
|
# modules directory doesn't exist, yet. And as Init() hasn't run, $ModuleDir
|
|
|
|
|
|
# is not set either. All we have is $DataDir.
|
|
|
|
|
|
$ModuleDir = "$DataDir/modules";
|
|
|
|
|
|
add_module('mac.pl');
|
|
|
|
|
|
}
|
2014-07-31 13:17:02 +02:00
|
|
|
|
write_config_file();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-06-11 20:08:04 +02:00
|
|
|
|
# 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;
|
|
|
|
|
|
|
2016-06-12 17:32:20 +02:00
|
|
|
|
# Fork a simple test server
|
2016-06-11 20:08:04 +02:00
|
|
|
|
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: $!";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-06-12 17:32:20 +02:00
|
|
|
|
# Fork a Mojolicious server
|
|
|
|
|
|
sub start_mojolicious_server {
|
|
|
|
|
|
die "A server already exists: $pid\n" if $pid;
|
|
|
|
|
|
my $port = random_port();
|
2016-06-12 22:29:49 +02:00
|
|
|
|
my $listen = "http://127.0.0.1:$port";
|
|
|
|
|
|
$ScriptName = "http://127.0.0.1:$port/wiki";
|
2016-06-12 17:32:20 +02:00
|
|
|
|
AppendStringToFile($ConfigFile, "\$ScriptName = '$ScriptName';\n");
|
|
|
|
|
|
$pid = fork();
|
|
|
|
|
|
if (!defined $pid) {
|
|
|
|
|
|
die "Cannot fork: $!";
|
|
|
|
|
|
} elsif ($pid == 0) {
|
|
|
|
|
|
use Config;
|
|
|
|
|
|
my $secure_perl_path = $Config{perlpath};
|
2016-06-12 21:26:18 +02:00
|
|
|
|
exec($secure_perl_path, "server.pl", "daemon", "-l", $listen)
|
|
|
|
|
|
or die "Cannot exec: $!";
|
2016-06-12 17:32:20 +02:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2016-06-11 20:08:04 +02:00
|
|
|
|
END {
|
|
|
|
|
|
# kill server
|
|
|
|
|
|
if ($pid) {
|
|
|
|
|
|
kill 'KILL', $pid or warn "Could not kill server $pid";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-09-23 20:58:50 +03:00
|
|
|
|
sub RunAndTerminate { # runs a command for 1 second and then sends SIGTERM
|
|
|
|
|
|
my $pid = fork();
|
|
|
|
|
|
if (not $pid) { # child
|
|
|
|
|
|
open(STDOUT, '>', '/dev/null'); # we don't want to see the output
|
|
|
|
|
|
open(STDERR, '>', '/dev/null');
|
|
|
|
|
|
exec(@_) or die "Cannot start a new process: $!";
|
|
|
|
|
|
}
|
|
|
|
|
|
# parent
|
|
|
|
|
|
sleep 1;
|
|
|
|
|
|
kill 'TERM', $pid;
|
|
|
|
|
|
wait; # let it finish
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sub AppendToConfig {
|
|
|
|
|
|
my @data = @_; # one or more strings
|
|
|
|
|
|
open(my $fh, '>>', "$DataDir/config") or die "Could not append to config file: $!";
|
|
|
|
|
|
print $fh join("\n", @data);
|
|
|
|
|
|
close $fh;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2006-09-18 00:06:31 +00:00
|
|
|
|
1;
|
2016-06-11 20:08:04 +02:00
|
|
|
|
|