Merge branch 'ready/more-magic'
authorSimon McVittie <smcv@debian.org>
Mon, 15 Sep 2014 20:08:40 +0000 (21:08 +0100)
committerSimon McVittie <smcv@debian.org>
Mon, 15 Sep 2014 20:08:40 +0000 (21:08 +0100)
57 files changed:
IkiWiki.pm
IkiWiki/CGI.pm
IkiWiki/Plugin/comments.pm
IkiWiki/Plugin/conditional.pm
IkiWiki/Plugin/edittemplate.pm
IkiWiki/Plugin/img.pm
IkiWiki/Plugin/inline.pm
IkiWiki/Plugin/linkmap.pm
IkiWiki/Plugin/trail.pm
IkiWiki/Wrapper.pm
debian/changelog
doc/bugs/CGI_wrapper_doesn__39__t_store_PERL5LIB_environment_variable.mdwn
doc/bugs/Inlining_adds_newlines_which_can_break_markdown.mdwn [new file with mode: 0644]
doc/bugs/__91____91____33__inline_postform__61__no__93____93___doesn__39__t_disable_it.mdwn
doc/bugs/can__39__t_upload_a_simple_png_image:_prohibited_by_allowed__95__attachments___40__file_MIME_type_is_application__47__octet-stream....mdwn
doc/bugs/debwiki_shortcut_creates_buggy_URLs_to_subpages.mdwn [new file with mode: 0644]
doc/bugs/editing_gitbranch_template_is_really_slow.mdwn
doc/bugs/garbled_non-ascii_characters_in_body_in_web_interface.mdwn [new file with mode: 0644]
doc/bugs/image_rescaling_distorts_with_small_pictures.mdwn
doc/bugs/linkmap_displays_underscore_escapes.mdwn
doc/bugs/listdirectives_doesn__39__t_register_a_link.mdwn
doc/bugs/openid_login_fails_wirth_Could_not_determine_ID_provider_from_URL.mdwn
doc/bugs/possible_to_post_comments_that_will_not_be_displayed.mdwn
doc/bugs/pythonproxy-utf8_again.mdwn
doc/bugs/redirect.mdwn [deleted file]
doc/bugs/rst_fails_on_file_containing_only_a_number.mdwn
doc/bugs/rst_plugin_hangs_when_used_with_Python_3.mdwn
doc/bugs/svg_and_pdf_conversion_fails.mdwn
doc/bugs/trails_depend_on_everything.mdwn
doc/forum/Using_reverse_proxy__59___base_URL_is_http_instead_of_https/comment_5_674f56100c0682eba36cc5327fbdae4a._comment [new file with mode: 0644]
doc/forum/__34__Error:_cannot_decode_string_with_wide_characters__34___on_Mageia_Linux_x86-64_Cauldron.mdwn
doc/forum/__34__Error:_cannot_decode_string_with_wide_characters__34___on_Mageia_Linux_x86-64_Cauldron/comment_1_abf7ec7c378ab0908685d72d159e9fd2._comment [new file with mode: 0644]
doc/git.mdwn
doc/ikiwiki/directive/edittemplate.mdwn
doc/ikiwiki/directive/img.mdwn
doc/news/openid/discussion.mdwn
doc/plugins/openid.mdwn
doc/plugins/openid/troubleshooting.mdwn [new file with mode: 0644]
doc/sandbox.mdwn
doc/shortcuts.mdwn
doc/tips/Hosting_Ikiwiki_and_master_git_repository_on_different_machines.mdwn
doc/tips/Hosting_Ikiwiki_and_master_git_repository_on_different_machines/separate-web-git-servers.svg [new file with mode: 0644]
doc/tips/distributed_wikis.mdwn
doc/todo/Option_linktext_for_pagestats_directive.mdwn
doc/todo/calendar_autocreate.mdwn
doc/todo/do_not_make_links_backwards.mdwn
doc/todo/edittemplate_should_support_uuid__44___date_variables.mdwn
doc/todo/pick_a_new_canonical_name_for_equivalent_of_SQL_limit.mdwn
doc/todo/redirect.mdwn [new file with mode: 0644]
doc/todo/should_use_a_standard_encoding_for_utf_chars_in_filenames.mdwn
doc/todo/upload__95__figure.mdwn
plugins/proxy.py
t/img.t [new file with mode: 0755]
t/img/redsquare.png [new file with mode: 0644]
t/img/twopages.pdf [new file with mode: 0644]
t/inline.t [new file with mode: 0755]
t/rst.t

index cd4ac815dbba6beec9a4debc9d0410de01a342e4..49ac9719658496953dc5f32c920e27ee5ba9d20c 100644 (file)
@@ -2460,6 +2460,19 @@ sub pagespec_match ($$;@) {
        return $sub->($page, @params);
 }
 
+# e.g. @pages = sort_pages("title", \@pages, reverse => "yes")
+#
+# Not exported yet, but could be in future if it is generally useful.
+# Note that this signature is not the same as IkiWiki::SortSpec::sort_pages,
+# which is "more internal".
+sub sort_pages ($$;@) {
+       my $sort = shift;
+       my $list = shift;
+       my %params = @_;
+       $sort = sortspec_translate($sort, $params{reverse});
+       return IkiWiki::SortSpec::sort_pages($sort, @$list);
+}
+
 sub pagespec_match_list ($$;@) {
        my $page=shift;
        my $pagespec=shift;
index c0d8f598b5f882b27bd2d5671d476aa5164a812b..cb83319e62ee893d92fd1d5f64695c23144d2614 100644 (file)
@@ -110,11 +110,23 @@ sub decode_cgi_utf8 ($) {
        }
 }
 
+sub safe_decode_utf8 ($) {
+    my $octets = shift;
+    # call decode_utf8 on >= 5.20 only if it's not already decoded,
+    # otherwise it balks, on < 5.20, always call it
+    if ($] < 5.02 || !Encode::is_utf8($octets)) {
+        return decode_utf8($octets);
+    }
+    else {
+        return $octets;
+    }
+}
+
 sub decode_form_utf8 ($) {
        if ($] >= 5.01) {
                my $form = shift;
                foreach my $f ($form->field) {
-                       my @value=map { decode_utf8($_) } $form->field($f);
+                       my @value=map { safe_decode_utf8($_) } $form->field($f);
                        $form->field(name  => $f,
                                     value => \@value,
                                     force => 1,
index a0ca9f32e484090969fbfa605875268cd112e9d8..98ae13810200269a34fbfb8b24093e26dc5ad4bb 100644 (file)
@@ -438,6 +438,16 @@ sub editcomment ($$) {
                        $page));
        }
 
+       # There's no UI to get here, but someone might construct the URL,
+       # leading to a comment that exists in the repository but isn't
+       # shown
+       if (!pagespec_match($page, $config{comments_pagespec},
+               location => $page)) {
+               error(sprintf(gettext(
+                       "comments on page '%s' are not allowed"),
+                       $page));
+       }
+
        if (pagespec_match($page, $config{comments_closed_pagespec},
                location => $page)) {
                error(sprintf(gettext(
index 0a3d7fb4cd18ef14261eb6896722c0991d8405dd..b450f1a0a1cea267e3e2791376142c67438f03b9 100644 (file)
@@ -33,11 +33,15 @@ sub preprocess_if (@) {
            # An optimisation to avoid needless looping over every page
            # for simple uses of some of the tests.
            $params{test} =~ /^([\s\!()]*((enabled|sourcepage|destpage|included)\([^)]*\)|(and|or))[\s\!()]*)+$/) {
-               add_depends($params{page}, "($params{test}) and $params{page}");
                $result=pagespec_match($params{page}, $params{test},
                                location => $params{page},
                                sourcepage => $params{page},
                                destpage => $params{destpage});
+               my $i = $result->influences;
+               foreach my $k (keys %$i) {
+                       # minor optimization: influences are always simple dependencies
+                       $IkiWiki::depends_simple{$params{page}}{lc $k} |= $i->{$k};
+               }
        }
        else {
                $result=pagespec_match_list($params{page}, $params{test},
index e3ce5e3d97437392c681f20f6c3a23b0b9690790..c2a8da29f853ec5f13e8fab959773751cc86ada9 100644 (file)
@@ -139,6 +139,25 @@ sub filltemplate ($$) {
 
        $template->param(name => $page);
 
+       if ($template->query(name => 'uuid')) {
+               my $uuid;
+               if (open(my $fh, "<", "/proc/sys/kernel/random/uuid")) {
+                       $uuid = <$fh>;
+                       chomp $uuid;
+                       close $fh;
+               }
+               else {
+                       eval {
+                               require UUID::Tiny;
+                               $uuid = UUID::Tiny::create_uuid_as_string(UUID::Tiny::UUID_V4());
+                       };
+               }
+               $template->param(uuid => $uuid);
+       }
+
+       my $time = time();
+       $template->param(time => IkiWiki::date_3339($time));
+
        return $template->output;
 }
 
index b92e24cc06fb93d8d88adcf1517903e46e49dc25..54c13d06919e0858442758d8fec09eb34bf0f0c3 100644 (file)
@@ -65,82 +65,85 @@ sub preprocess (@) {
        my $dir = $params{page};
        my $base = IkiWiki::basename($file);
        my $issvg = $base=~s/\.svg$/.png/i;
+       my $ispdf = $base=~s/\.pdf$/.png/i;
+       my $pagenumber = exists($params{pagenumber}) ? int($params{pagenumber}) : 0;
+       if ($pagenumber != 0) {
+               $base = "p$pagenumber-$base";
+       }
 
        eval q{use Image::Magick};
        error gettext("Image::Magick is not installed") if $@;
-       my $im = Image::Magick->new($issvg ? (magick => "png") : ());
+       my $im = Image::Magick->new();
        my $imglink;
-       my $r = $im->Read($srcfile);
+       my $imgdatalink;
+       my $r = $im->Read("$srcfile\[$pagenumber]");
        error sprintf(gettext("failed to read %s: %s"), $file, $r) if $r;
        
        my ($dwidth, $dheight);
 
-       if ($params{size} ne 'full') {
+       if ($params{size} eq 'full') {
+               $dwidth = $im->Get("width");
+               $dheight = $im->Get("height");
+       } else {
                my ($w, $h) = ($params{size} =~ /^(\d*)x(\d*)$/);
                error sprintf(gettext('wrong size format "%s" (should be WxH)'), $params{size})
                        unless (defined $w && defined $h &&
                                (length $w || length $h));
-               
-               if ((length $w && $w > $im->Get("width")) ||
-                   (length $h && $h > $im->Get("height"))) {
-                       # resizing larger
-                       $imglink = $file;
-
-                       # don't generate larger image, just set display size
-                       if (length $w && length $h) {
-                               ($dwidth, $dheight)=($w, $h);
-                       }
-                       # avoid division by zero on 0x0 image
-                       elsif ($im->Get("width") == 0 || $im->Get("height") == 0) {
-                               ($dwidth, $dheight)=(0, 0);
-                       }
-                       # calculate unspecified size from the other one, preserving
-                       # aspect ratio
-                       elsif (length $w) {
-                               $dwidth=$w;
-                               $dheight=$w / $im->Get("width") * $im->Get("height");
-                       }
-                       elsif (length $h) {
-                               $dheight=$h;
-                               $dwidth=$h / $im->Get("height") * $im->Get("width");
-                       }
+
+               if ($im->Get("width") == 0 || $im->Get("height") == 0) {
+                       ($dwidth, $dheight)=(0, 0);
+               } elsif (! length $w || (length $h && $im->Get("height")*$w > $h * $im->Get("width"))) {
+                       # using height because only height is given or ...
+                       # because original image is more portrait than $w/$h
+                       # ... slimness of $im > $h/w
+                       # ... $im->Get("height")/$im->Get("width") > $h/$w
+                       # ... $im->Get("height")*$w > $h * $im->Get("width")
+
+                       $dheight=$h;
+                       $dwidth=$h / $im->Get("height") * $im->Get("width");
+               } else { # (! length $h) or $w is what determines the resized size
+                       $dwidth=$w;
+                       $dheight=$w / $im->Get("width") * $im->Get("height");
+               }
+       }
+
+       if ($dwidth < $im->Get("width") || $ispdf) {
+               # resize down, or resize to pixels at all
+
+               my $outfile = "$config{destdir}/$dir/$params{size}-$base";
+               $imglink = "$dir/$params{size}-$base";
+
+               will_render($params{page}, $imglink);
+
+               if (-e $outfile && (-M $srcfile >= -M $outfile)) {
+                       $im = Image::Magick->new;
+                       $r = $im->Read($outfile);
+                       error sprintf(gettext("failed to read %s: %s"), $outfile, $r) if $r;
                }
                else {
-                       # resizing smaller
-                       my $outfile = "$config{destdir}/$dir/${w}x${h}-$base";
-                       $imglink = "$dir/${w}x${h}-$base";
-               
-                       will_render($params{page}, $imglink);
-
-                       if (-e $outfile && (-M $srcfile >= -M $outfile)) {
-                               $im = Image::Magick->new;
-                               $r = $im->Read($outfile);
-                               error sprintf(gettext("failed to read %s: %s"), $outfile, $r) if $r;
+                       $r = $im->Resize(geometry => "${dwidth}x${dheight}");
+                       error sprintf(gettext("failed to resize: %s"), $r) if $r;
+
+                       $im->set(($issvg || $ispdf) ? (magick => 'png') : ());
+                       my @blob = $im->ImageToBlob();
+                       # don't actually write resized file in preview mode;
+                       # rely on width and height settings
+                       if (! $params{preview}) {
+                               writefile($imglink, $config{destdir}, $blob[0], 1);
                        }
                        else {
-                               $r = $im->Resize(geometry => "${w}x${h}");
-                               error sprintf(gettext("failed to resize: %s"), $r) if $r;
-
-                               # don't actually write resized file in preview mode;
-                               # rely on width and height settings
-                               if (! $params{preview}) {
-                                       my @blob = $im->ImageToBlob();
-                                       writefile($imglink, $config{destdir}, $blob[0], 1);
-                               }
-                               else {
-                                       $imglink = $file;
-                               }
+                               eval q{use MIME::Base64};
+                               error($@) if $@;
+                               $imgdatalink = "data:image/".$im->Get("magick").";base64,".encode_base64($blob[0]);
                        }
-
-                       # always get the true size of the resized image
-                       $dwidth  = $im->Get("width"); 
-                       $dheight = $im->Get("height");
                }
-       }
-       else {
-               $imglink = $file;
-               $dwidth = $im->Get("width");
+
+               # always get the true size of the resized image (it could be
+               # that imagemagick did its calculations differently)
+               $dwidth  = $im->Get("width");
                $dheight = $im->Get("height");
+       } else {
+               $imglink = $file;
        }
        
        if (! defined($dwidth) || ! defined($dheight)) {
@@ -148,14 +151,9 @@ sub preprocess (@) {
        }
 
        my ($fileurl, $imgurl);
-       if (! $params{preview}) {
-               $fileurl=urlto($file, $params{destpage});
-               $imgurl=urlto($imglink, $params{destpage});
-       }
-       else {
-               $fileurl=urlto($file);
-               $imgurl=urlto($imglink);
-       }
+       my $urltobase = $params{preview} ? undef : $params{destpage};
+       $fileurl=urlto($file, $urltobase);
+       $imgurl=$imgdatalink ? $imgdatalink : urlto($imglink, $urltobase);
 
        if (! exists $params{class}) {
                $params{class}="img";
index 123dfd36489c8536450971c95267ef30261abcc9..f578526cc0da9fe1c369c5d1e709fe21f5154341 100644 (file)
@@ -329,8 +329,12 @@ sub preprocess_inline (@) {
 
        my $ret="";
 
-       if (length $config{cgiurl} && ! $params{preview} && (exists $params{rootpage} ||
-           (exists $params{postform} && yesno($params{postform}))) &&
+       my $postform = (exists $params{rootpage});
+       if (exists $params{postform}) {
+               $postform = yesno($params{postform});
+       }
+
+       if (length $config{cgiurl} && ! $params{preview} && $postform &&
            IkiWiki->can("cgi_editpage")) {
                # Add a blog post form, with feed buttons.
                my $formtemplate=template_depends("blogpost.tmpl", $params{page}, blind_cache => 1);
index ac26e072e9dc7afa18ad33d5fa2049d347f291bb..b5ef1a137beb26e3e66aee89f468c33fd6e1865a 100644 (file)
@@ -5,6 +5,7 @@ use warnings;
 use strict;
 use IkiWiki 3.00;
 use IPC::Open2;
+use HTML::Entities;
 
 sub import {
        hook(type => "getsetup", id => "linkmap", call => \&getsetup);
@@ -22,6 +23,18 @@ sub getsetup () {
 
 my $mapnum=0;
 
+sub pageescape {
+       my $item = shift;
+       # encoding explicitly in case ikiwiki is configured to accept <> or &
+       # in file names
+       my $title = pagetitle($item, 1);
+       # it would not be necessary to encode *all* the html entities (<> would
+       # be sufficient, &" probably a good idea), as dot accepts utf8, but it
+       # isn't bad either
+       $title = encode_entities($title);
+       return("<$title>");
+}
+
 sub preprocess (@) {
        my %params=@_;
 
@@ -63,7 +76,7 @@ sub preprocess (@) {
        my $show=sub {
                my $item=shift;
                if (! $shown{$item}) {
-                       print OUT "\"$item\" [shape=box,href=\"$mapitems{$item}\"];\n";
+                       print OUT pageescape($item)." [shape=box,href=\"$mapitems{$item}\"];\n";
                        $shown{$item}=1;
                }
        };
@@ -74,7 +87,7 @@ sub preprocess (@) {
                        foreach my $endpoint ($item, $link) {
                                $show->($endpoint);
                        }
-                       print OUT "\"$item\" -> \"$link\";\n";
+                       print OUT pageescape($item)." -> ".pageescape($link).";\n";
                }
        }
        print OUT "}\n";
index d5fb2b5d624c1b21cf0fa9163b5b223a090e917e..476db4dcb90130ce895c9480300ac84e12c482b1 100644 (file)
@@ -319,10 +319,9 @@ sub prerender {
                }
 
                if (defined $pagestate{$trail}{trail}{sort}) {
-                       # re-sort
-                       @$members = pagespec_match_list($trail, 'internal(*)',
-                               list => $members,
-                               sort => $pagestate{$trail}{trail}{sort});
+                       @$members = IkiWiki::sort_pages(
+                               $pagestate{$trail}{trail}{sort},
+                               $members);
                }
 
                if (IkiWiki::yesno $pagestate{$trail}{trail}{reverse}) {
index b46bc6aa9794abdca46f68c8dc753e88daf7019b..4c99cdaa0b670080ac8548e8d95de91b7b74de07 100644 (file)
@@ -52,6 +52,7 @@ sub gen_wrapper () {
                       HTTP_COOKIE REMOTE_USER HTTPS REDIRECT_STATUS
                       HTTP_HOST SERVER_PORT HTTPS HTTP_ACCEPT
                       REDIRECT_URL} if $config{cgi};
+       my $envsize=$#envsave;
        my $envsave="";
        foreach my $var (@envsave) {
                $envsave.=<<"EOF";
@@ -59,6 +60,18 @@ sub gen_wrapper () {
                addenv("$var", s);
 EOF
        }
+       if (ref $config{ENV} eq 'HASH') {
+               foreach my $key (keys %{$config{ENV}}) {
+                       my $val=$config{ENV}{$key};
+                       utf8::encode($val) if utf8::is_utf8($val);
+                       $val =~ s/([^A-Za-z0-9])/sprintf '""\\x%02x""', ord($1)/ge;
+                       $envsize += 1;
+                       $envsave.=<<"EOF";
+       addenv("$key", "$val");
+EOF
+               }
+               delete $config{ENV};
+       }
        
        my @wrapper_hooks;
        run_hooks(genwrapper => sub { push @wrapper_hooks, shift->() });
@@ -171,7 +184,7 @@ EOF
 #include <sys/file.h>
 
 extern char **environ;
-char *newenviron[$#envsave+7];
+char *newenviron[$envsize+7];
 int i=0;
 
 void addenv(char *var, char *val) {
index 022fc7d05c47cdae3f64e71728a95500726cfd8a..b50b515b0d0fc3cc83f1694d83695d8a423febe7 100644 (file)
@@ -1,3 +1,30 @@
+ikiwiki (3.20140912) UNRELEASED; urgency=medium
+
+  * Don't double-decode CGI submissions with Encode.pm >= 2.53,
+    fixing "Error: Cannot decode string with wide characters".
+    Thanks, Antoine Beaupré
+  * Avoid making trails depend on everything in the wiki by giving them
+    a better way to sort the pages
+  * Don't let users post comments that won't be displayed
+  * Fix encoding of Unicode strings in Python plugins.
+    Thanks, chrysn
+  * Improve performance and correctness of the [[!if]] directive
+  * Let [[!inline rootpage=foo postform=no]] disable the posting form
+  * Switch default [[!man]] shortcut to manpages.debian.org. Closes: #700322
+  * Add UUID and TIME variables to edittemplate. Closes: #752827
+    Thanks, Jonathon Anderson
+  * Display pages in linkmaps as their pagetitle (no underscore escapes).
+    Thanks, chrysn
+  * Fix aspect ratio when scaling small images, and add support for
+    converting SVG and PDF graphics to PNG.
+    Thanks, chrysn
+  * In the CGI wrapper, incorporate $config{ENV} into the environment
+    before executing Perl code, so that PERL5LIB can point to a
+    non-system-wide installation of IkiWiki.
+    Thanks, Lafayette Chamber Singers Webmaster
+
+ -- Simon McVittie <smcv@debian.org>  Fri, 12 Sep 2014 21:23:58 +0100
+
 ikiwiki (3.20140831) unstable; urgency=medium
 
   * Make --no-gettime work in initial build. Closes: #755075
index 81a5abf2862e0430ff566c758e0fe5ebc6ce3fff..140b487d140d5ed2c814775bc1849c1962d4594b 100644 (file)
@@ -26,3 +26,46 @@ This brutal patch implement your solution as a temporary fix.
 As I am not sure that remembering `PERL5LIB` is a good idea, I think that a prettier solution will be to add a config variable (let's say `cgi_wrapper_perllib`) which, if fixed, contains the `PERL5LIB` value to include in the wrapper, or another (let's say `cgi_wrapper_remember_libdir`), which, if fixed, remember the current `PERL5LIB`.
 
 -- Bruno
+
+**Update:** I had not seen this bug earlier, but I ran into the same issue and made a more general solution. You can already add stuff to `%config{ENV}` in the setup file, but it was being processed too late for `PERL5LIB` to do any good.
+[This change](https://github.com/jcflack/ikiwiki/compare/early-env) moves the `%config{ENV}` handling earlier in the wrapper, so anything specified there is placed back in the actual environment before Perl gets control. Problem solved!
+
+-- Chap
+
+> Thanks, this looks like a nicer solution than the above. Some review:
+>
+>     + $val =~ s/([\\"])/\\$1/g;
+>
+> This is *probably* OK, because the configuration is unlikely to include
+> non-ASCII, but I'd prefer something that covers all possibilities,
+> like this:
+>
+>     my $tmp = $val;
+>     utf8::encode($tmp) if utf8::is_utf8($tmp);
+>     $tmp =~ s/([^A-Za-z0-9])/sprintf "\\x%02x", $1/ge;
+>
+> and then passing $tmp to addenv.
+>
+>     + delete $config{ENV};
+>
+> I don't think this is particularly necessary: there doesn't seem any harm
+> in having it in the storable too?
+>
+> --[[smcv]]
+
+Happy to make the escaping change, thanks for the sharp eye.
+
+> [[Merged|done]] with that change. --[[smcv]]
+
+My thinking on `delete` is once it's handled, it's handled. The C code
+is going to put this straight into the real environment and then do
+a simple `exec` ... is there any way this hasn't been handled?
+
+It just takes up space twice in the generated wrapper otherwise.
+Admittedly it's not much space, but seems to be even less point ... ?
+
+-- Chap
+
+> That makes sense, as long as nothing else is going to read
+> `$config{ENV}` for purposes other than copying it into the actual
+> environment. --[[smcv]]
diff --git a/doc/bugs/Inlining_adds_newlines_which_can_break_markdown.mdwn b/doc/bugs/Inlining_adds_newlines_which_can_break_markdown.mdwn
new file mode 100644 (file)
index 0000000..eb71994
--- /dev/null
@@ -0,0 +1,43 @@
+I'm trying to put a list of tags in a table, so I carefully make a newline-free taglist.tmpl and then do:
+
+    | \[[!inline pages="link(/category/env)" feeds=no archive=yes sort=title template=taglist]] |
+
+but there's a line in `inline.pm` that does:
+
+    return "&lt;div class=\"inline\" id=\"$#inline\"&gt;&lt;/div&gt;\n\n";
+
+And the extra newlines break the table.  Can they be safely removed?
+
+> If you want an HTML table, I would suggest using an HTML table, which
+> should pass through Markdown without being interpreted further:
+>
+>     <table><tr>
+>     \[[!inline pages="link(/category/env)" feeds=no archive=yes sort=title template=tagtd]]
+>     </tr></table>
+>
+> where tagtd.tmpl is of the form `<td>your markup here</td>`; or even just
+>
+>     \[[!inline pages="link(/category/env)" feeds=no archive=yes sort=title template=tagtable]]
+>
+> where tagtable.tmpl looks like
+>
+>     <TMPL_IF FIRST>
+>     <table><tr>
+>     </TMPL_IF>
+>
+>     <td>your tag here</td>
+>
+>     <TMPL_IF LAST>
+>     </tr></table>
+>     </TMPL_IF>
+>
+> I don't think you're deriving much benefit from Markdown's table syntax
+> if you have to mix it with HTML::Template and ikiwiki directives,
+> and be pathologically careful with whitespace. "Right tool for the job"
+> and all that :-)
+>
+> When I edited this page I was amused to find that you used HTML,
+> not Markdown, as its format. It seems oddly appropriate to my answer, but
+> I've converted it to Markdown and adjusted the formatting, for easier
+> commenting.
+> --[[smcv]]
index 7e7548657812fdac4b3d18dd48478a6b9259483c..7b97b40b3be9260386d8cefd8a4436d7a8c59f45 100644 (file)
@@ -21,3 +21,4 @@ not the actual inlining of pages, but it's a start.
 --[[smcv]]
 
 >> this looks simple, straightforward and good to me --[[chrysn]]
+>>> [[merged|done]] --[[smcv]]
index 4e3332748db2cb25c13dc1c53793ee2bf0a91870..627b2c82764de62be9f2609e686a58665645fffc 100644 (file)
@@ -56,16 +56,22 @@ Weird... --[[anarcat]]
 > > 
 > > --[[anarcat]]
 
+> > > [[!template  id=gitbranch branch=ready/more-magic author="[[smcv]]" browse=http://git.pseudorandom.co.uk/smcv/ikiwiki.git/commitdiff/ready/more-magic]]
 > > > If the regex match isn't necessary and it's just about deleting the
-> > > parameters, I think I'd prefer something like
+> > > parameters, I think I'd prefer
 > > >
 > > >     if (! defined $mimetype) {
 > > >         ...
 > > >     }
 > > >     $mimetype =~ s/;.*//;
 > > >
-> > > but I'd be hesitant to do that without knowing why Joey implemented it
-> > > the way it is. If it's about catching a result from file(1) that
+> > > as done in my `ready/more-magic` branch.
+> > >
+> > > I'm a little hesitant to do that without knowing why Joey implemented it
+> > > the way it is, but as far as I can tell it's just an oversight.
+> > >
+> > > Or, if the result of the s/// is checked for a reason, and it's
+> > > about catching a result from file(1) that
 > > > is not, in fact, a MIME type at all (empty string or error message
 > > > or something), maybe something more like this?
 > > >
@@ -74,3 +80,12 @@ Weird... --[[anarcat]]
 > > > (or whatever the allowed characters in MIME types are). --[[smcv]]
 
 > > > > I don't mind either way, but i feel this should be fixed for the next release, as I need to reapply this patch at every upgrade now. -- [[anarcat]]
+
+> > > > > This is still a problem in 3.20140831. -- [[anarcat]]
+
+> > > > > > I still don't think appending a semicolon is the right answer:
+> > > > > > at best it's equivalent to what I suggested, and at worst it's
+> > > > > > disabling a check that does have some reason behind it.
+> > > > > > I've turned the version I suggested above into a proper branch.
+> > > > > > Review by someone who can commit to ikiwiki.git would be appreciated.
+> > > > > > --[[smcv]]
diff --git a/doc/bugs/debwiki_shortcut_creates_buggy_URLs_to_subpages.mdwn b/doc/bugs/debwiki_shortcut_creates_buggy_URLs_to_subpages.mdwn
new file mode 100644 (file)
index 0000000..f83f960
--- /dev/null
@@ -0,0 +1,5 @@
+E.g. [[!debwiki Derivatives/Guidelines]].
+
+Maybe we should use `%S` instead of `%s` in the shortcut definition?
+
+> seems reasonable, [[done]] --[[smcv]]
index c7d0ffbe2ef20e92cfb607f0c06204b4235cb16c..22733e6fee541487a49e7fdc8185db2949c1acc2 100644 (file)
@@ -63,3 +63,5 @@ browse=http://git.pseudorandom.co.uk/smcv/ikiwiki.git/shortlog/refs/heads/ready/
 > `bestlink` is still the single most expensive function in this refresh
 > at ~ 9.5s, with `match_glob` at ~ 5.2s as the runner-up.
 > --[[smcv]]
+
+>> [[merged|done]] --[[smcv]]
diff --git a/doc/bugs/garbled_non-ascii_characters_in_body_in_web_interface.mdwn b/doc/bugs/garbled_non-ascii_characters_in_body_in_web_interface.mdwn
new file mode 100644 (file)
index 0000000..657b86b
--- /dev/null
@@ -0,0 +1,126 @@
+since my latest jessie upgrade here, charsets are all broken when editing a page. the page i'm trying to edit is [this wishlist](http://anarc.at/wishlist/), and it used to work fine. now, instead of:
+
+`Voici des choses que vous pouvez m'acheter si vous êtes le Père Nowel (yeah right):`
+
+... as we see in the rendered body right now, when i edit the page i see:
+
+`Voici des choses que vous pouvez m'acheter si vous �tes le P�re Nowel (yeah right):`
+
+... a typical double-encoding nightmare. The actual binary data is this for the word "Père" according to `hd`:
+
+~~~~
+anarcat@marcos:ikiwiki$ echo "Père" | hd
+00000000  50 c3 a8 72 65 0a                                 |P..re.|
+00000006
+anarcat@marcos:ikiwiki$ echo "P�re" | hd
+00000000  50 ef bf bd 72 65 0a                              |P...re.|
+00000007
+~~~~
+
+> I don't know what that is, but it isn't the usual double-UTF-8 encoding:
+>
+>     >>> u'è'.encode('utf-8')
+>     '\xc3\xa8'
+>     >>> u'è'.encode('utf-8').decode('latin-1').encode('utf-8')
+>     '\xc3\x83\xc2\xa8'
+>
+> A packet capture of the incorrect HTTP request/response headers and body
+> might be enlightening? --[[smcv]]
+>
+> > Here are the headers according to chromium:
+> > 
+> > ~~~~
+> > GET /ikiwiki.cgi?do=edit&page=wishlist HTTP/1.1
+> > Host: anarc.at
+> > Connection: keep-alive
+> > Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
+> > User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36
+> > Referer: http://anarc.at/wishlist/
+> > Accept-Encoding: gzip,deflate,sdch
+> > Accept-Language: fr,en-US;q=0.8,en;q=0.6
+> > Cookie: openid_provider=openid; ikiwiki_session_anarcat=XXXXXXXXXXXXXXXXXXXXXXX
+> > 
+> > HTTP/1.1 200 OK
+> > Date: Mon, 08 Sep 2014 21:22:24 GMT
+> > Server: Apache/2.4.10 (Debian)
+> > Set-Cookie: ikiwiki_session_anarcat=XXXXXXXXXXXXXXXXXXXXXXX; path=/; HttpOnly
+> > Vary: Accept-Encoding
+> > Content-Encoding: gzip
+> > Content-Length: 4093
+> > Keep-Alive: timeout=5, max=100
+> > Connection: Keep-Alive
+> > Content-Type: text/html; charset=utf-8
+> > ~~~~
+> > 
+> > ... which seem fairly normal... getting more data than this is a little inconvenient since the data is gzip-encoded and i'm kind of lazy extracting that from the stream. Chromium does seem to auto-detect it as utf8 according to the menus however... not sure what's going on here. I would focus on the following error however, since it's clearly emanating from the CGI... --[[anarcat]]
+
+Clicking on the Cancel button yields the following warning:
+
+~~~~
+Error: Cannot decode string with wide characters at /usr/lib/x86_64-linux-gnu/perl/5.20/Encode.pm line 215.
+~~~~
+
+> Looks as though you might be able to get a Python-style backtrace for this
+> by setting `$Carp::Verbose = 1`.
+>
+> The error is that we're taking some string (which string? only a backtrace
+> would tell you) that is already flagged as Unicode, and trying to decode
+> it from byte-blob to Unicode again, analogous to this Python:
+>
+>     some_bytes.decode('utf-8').decode('utf-8')
+>
+> --[[smcv]]
+> > 
+> > I couldn't figure out where to set that Carp thing - it doesn't work simply by setting it in /usr/bin/ikiwiki - so i am not sure how to use this. However, with some debugging code in Encode.pm, i was able to find a case of double-encoding - in the left menu, for example, which is the source of the Encode.pm crash.
+> > 
+> > It seems that some unicode semantics changed in Perl 5.20, or more precisely, in Encode.pm 2.53, according to [this](https://code.activestate.com/lists/perl-unicode/3314/). 5.20 does have significant Unicode changes, but I am not sure they are related (see [perldelta](https://metacpan.org/pod/distribution/perl/pod/perldelta.pod)). Doing more archeology, it seems that Encode.pm is indeed where the problem started, all the way back in [commit 8005a82](https://github.com/dankogai/p5-encode/commit/8005a82d8aa83024d72b14e66d9eb97d82029eeb#diff-f3330aa405ffb7e3fec2395c1fc953ac) (august 2013), taken from [pull request #11](https://github.com/dankogai/p5-encode/pull/11) which expressively forbids double-decoding, in effect failing like python does in the above example you gave (Perl used to silently succeed instead, a rather big change if you ask me).
+> > 
+> > So stepping back, it seems that this would be a bug in Ikiwiki. It could be in any of those places:
+> > 
+> > ~~~~
+> > anarcat@marcos:ikiwiki$ grep -r decode_utf8 IkiWiki* | wc -l
+> > 31
+> > ~~~~
+> > 
+> > Now the fun part is to determine which one should be turned off... or should we duplicate the logic that was removed in decode_utf8, or make a safe_decode_utf8 for ourselves? --[[anarcat]]
+
+The apache logs yield:
+
+~~~~
+[Mon Sep 08 16:17:43.995827 2014] [cgi:error] [pid 2609] [client 192.168.0.3:47445] AH01215: Died at /usr/share/perl5/IkiWiki/CGI.pm line 467., referer: http://anarc.at/ikiwiki.cgi?do=edit&page=wishlist
+~~~~
+
+Interestingly enough, I can't reproduce the bug here (at least in this page). Also, editing the page through git works fine.
+
+I had put ikiwiki on hold during the last upgrade, so it was upgraded separately. The bug happens both with 3.20140613 and 3.20140831. The major thing that happened today is the upgrade from perl 5.18 to 5.20. Here's the output of `egrep '[0-9] (remove|purge|install|upgrade)' /var/log/dpkg.log | pastebinit -b paste.debian.net` to give an idea of what was upgraded today:
+
+http://paste.debian.net/plain/119944
+
+This is a major bug which should probably be fixed before jessie, yet i can't seem to find a severity statement in reportbug that would justify blocking the release based on this - unless we consider non-english speakers as "most" users (i don't know the demographics well enough). It certainly makes ikiwiki completely unusable for my users that operate on the web interface in french... --[[anarcat]]
+
+Note that on this one page, i can't even get the textarea to display and i immediately get `Error: Cannot decode string with wide characters at /usr/lib/x86_64-linux-gnu/perl/5.20/Encode.pm line 215`: http://anarc.at/ikiwiki.cgi?do=edit&page=hardware%2Fserver%2Fmarcos.
+
+Also note that this is the same as [[forum/"Error: cannot decode string with wide characters" on Mageia Linux x86-64 Cauldron]], I believe. The backtrace I get here is:
+
+~~~~
+Error: Cannot decode string with wide characters at /usr/lib/x86_64-linux-gnu/perl/5.20/Encode.pm line 215. Encode::decode_utf8("**Menu**\x{d}\x{a}\x{d}\x{a} * [[\x{fffd} propos|index]]\x{d}\x{a} * [[Logiciels|software]]"...)
+called at /usr/share/perl5/IkiWiki/CGI.pm line 117 IkiWiki::decode_form_utf8(CGI::FormBuilder=HASH(0x2ad63b8))
+called at /usr/share/perl5/IkiWiki/Plugin/editpage.pm line 90 IkiWiki::cgi_editpage(CGI=HASH(0xd514f8), CGI::Session=HASH(0x27797e0))
+called at /usr/share/perl5/IkiWiki/CGI.pm line 443 IkiWiki::__ANON__(CODE(0xfaa460))
+called at /usr/share/perl5/IkiWiki.pm line 2101 IkiWiki::run_hooks("sessioncgi", CODE(0x2520138))
+called at /usr/share/perl5/IkiWiki/CGI.pm line 443 IkiWiki::cgi()
+called at /usr/bin/ikiwiki line 192 eval {...}
+called at /usr/bin/ikiwiki line 192 IkiWiki::main()
+called at /usr/bin/ikiwiki line 231
+~~~~
+
+so this would explain the error on cancel, but doesn't explain the weird encoding i get when editing the page... <sigh>...
+
+... and that leads me to this crazy patch which fixes all the above issue, by avoiding double-decoding... go figure that shit out...
+
+[[!template  id=gitbranch branch=anarcat/dev/safe_unicode author="[[anarcat]]"]] 
+
+> [[Looks good to me|users/smcv/ready]] although I'm not sure how valuable
+> the `$] < 5.02 || ` test is - I'd be tempted to just call `is_utf8`. --[[smcv]]
+
+>> [[merged|done]] --[[smcv]]
index 6425c1ece829146eec6bfe76027532383b5a3a87..9ce091e15993437b78dc12364895fda8b3a8111d 100644 (file)
@@ -47,3 +47,5 @@ If you use the rescaling feature of the directive [[ikiwiki/directive/img/]] wit
 >>> in my copy of the branch.
 >>>
 >>> --[[smcv]]
+
+>>>> [[merged|done]] --[[smcv]]
index 14164d0761edecfa6a55c048e882869fb1918493..16080358b1a01b0a8c9bd5a7c91add8bdb06bf30 100644 (file)
@@ -33,3 +33,5 @@ the patch is stored in [[the patch.pl]] as created by git-format-patch, and can
 be pulled from the abovementioned branch.
 
 > update 2014-06-29: branch still merges cleanly and works. --[[chrysn]]
+
+>> [[merged|done]] --[[smcv]]
index ad52d780ace742399d46a2c4fe43d7d1d7db6e92..bae331f6493afeaf1b291d969bc2fb1420bc2e88 100644 (file)
@@ -112,3 +112,34 @@ The [[ikiwiki/directive/listdirectives]]` directive doesn't register a link betw
 >>>>> it doesn't inline. That's never going to end well :-) --[[smcv]]
 >>>>>> We have to differentiate between what users of ikiwiki consider first class links and what internally is happening. For the user any link contributing to the structured access tree is first class. The code on the other hand has to differentiate between the static links, then generated links, then orphan links. Three "passes", even your proposed solution could be seen as adding another pass since the orphan plugin has to run after all the plugins generating (first class user) links.   -- [[holger]]
 
+>>>>>>> I think the difference between your point of view, and what ikiwiki
+>>>>>>> currently implements / what its design is geared towards, is this:
+>>>>>>> ikiwiki says A links to B if the *source code* of A contains an
+>>>>>>> explicit link to B. You say A links to B if the *compiled HTML*
+>>>>>>> of A contains a link to B.
+>>>>>>>
+>>>>>>> Would you agree with that characterization?
+>>>>>>>
+>>>>>>> I suspect that "link in the source code" may be the more useful concept
+>>>>>>> when using links for backlinks (I think the original implementation is
+>>>>>>> <http://c2.com/cgi/wiki?BackLink>) and as pseudo-tags
+>>>>>>> (<http://c2.com/cgi/wiki?WikiCategories>). The fact that this is what
+>>>>>>> `link()` and `backlink()` mean could be better-documented: it's
+>>>>>>> entirely possible that the author of their documentation (Joey?)
+>>>>>>> thought it was obvious that that's what they mean, because they
+>>>>>>> were coming from a compiler/source-code mindset.
+>>>>>>>
+>>>>>>> Also, backlinks become rather all-engulfing if their presence in
+>>>>>>> the compiled output counts as a link, since after a render pass, they
+>>>>>>> would all become bidirectional; and as I noted previously, if pagespecs
+>>>>>>> can match by linkedness (which we want) and plugins can generate lists
+>>>>>>> of links according to pagespecs (which we also want), then links in the
+>>>>>>> compiled output can certainly get into [[!wikipedia Russell's paradox]]-like
+>>>>>>> situations, such as the page that links to every page to which it
+>>>>>>> does not link.
+>>>>>>>
+>>>>>>> For the special case of deciding what is orphaned, sure, it's the
+>>>>>>> compiled HTML that is the more relevant thing;
+>>>>>>> that's why I talked about "reachability" rather than "links".
+>>>>>>>
+>>>>>>> --[[smcv]]
index ec22f0c78e6a732190c3f08c4ee8237783939067..073c10d14bb492089d8aa62c19d191acddd5010e 100644 (file)
@@ -4,6 +4,37 @@ On some ikiwikis that I run, I get the following error on OpenID logins:
 
 > Is this fixed now that [[!debbug 738493]] has been fixed? --[[smcv]]
 
+> > No, it isn't. I still get: `no_identity_server: Could not determine ID provider from URL.` from the latest ikiwiki in jessie (3.20140831), with liblwpx-paranoidagent-perl 1.10-3. Debugging tells me it's still related to the `500 Can't verify SSL peers without knowing which Certificate Authorities to trust` error, so probably because `Mozilla::CA` is not packaged ([[!debbug 702124]]). I still had to apply the patch to disable SSL verification at the end of this file. However, setting `$ENV{PERL_LWP_SSL_CA_PATH} = '/etc/ssl/certs';` seems to work now, so the following dumb patch works:
+> > 
+> > ~~~~
+> > --- /usr/bin/ikiwiki.orig       2014-09-08 15:48:35.715868902 -0400
+> > +++ /usr/bin/ikiwiki    2014-09-08 15:50:29.666779878 -0400
+> > @@ -225,4 +225,5 @@
+> >         }
+> >  }
+> > 
+> > +$ENV{PERL_LWP_SSL_CA_PATH} = '/etc/ssl/certs';
+> >  main;
+> > ~~~~
+> > 
+> > may not be the best place to fiddle around with this, but then again it makes sense that it applies to the whole program. it should probably be reported upstream as well. also in my git repo. -- [[anarcat]]
+> >
+> > > This seems Debian-specific. I would be inclined to consider this to be
+> > > a packaging/system-integration (i.e. non-upstream) bug in
+> > > `liblwpx-paranoidagent-perl` rather than an upstream bug in IkiWiki;
+> > > it certainly seems inappropriate to put this Debian-specific path
+> > > in upstream IkiWiki. If it can't be fixed in LWPX::ParanoidAgent for
+> > > whatever reason, applying it via some sort of sed in ikiwiki's
+> > > `debian/rules` might be more reasonable? --[[smcv]]
+> > >
+> > > > by "upstream", i did mean `liblwpx-paranoidagent-perl`. so yeah, maybe this should be punted back into that package's court again. :( --[[anarcat]]
+> > > > 
+> > > > done, by bumping the severity of [[!debbug 744404]] to release-criticial. --[[anarcat]]
+> > > > 
+> > > > > ooh cool, the bug was fixed already with an upload, so this should probably be considered [[done]] at this point, even without the patch below! great! -- [[anarcat]]
+
+[[!template  id=gitbranch branch=anarcat/dev/ssl_ca_path author="[[anarcat]]"]] 
+
 I seem recall having that error before, and fixing it, but it always seems to come back and I forget how to fix it. So I'll just open this bug and document it if i can figure it out... -- [[users/anarcat]]
 
 The Perl module manual says:
@@ -157,18 +188,13 @@ Workaround - disable error checking:
 > My only workaround for now was to fix `PERL_LWP_SSL_VERIFY_HOSTNAME` to 0 directly in `ikiwiki` :-(  -- [[users/bbb]]
 
 ~~~~
-*** /home/bruno/opt/ikiwiki/bin/ikiwiki.bad     2014-04-17 15:41:38.868972152 +0200
---- /home/bruno/opt/ikiwiki/bin/ikiwiki 2014-04-17 15:04:56.524996905 +0200
-*************** sub main () {
-*** 226,229 ****
-        }
-  }
-  
-! main;
---- 226,229 ----
+--- /usr/bin/ikiwiki.orig       2014-09-08 15:48:35.715868902 -0400
++++ /usr/bin/ikiwiki    2014-09-08 15:48:38.895947911 -0400
+@@ -225,4 +225,5 @@
         }
-  }
-  
-! $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0 ; main;
+ }
+
++$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0;
+ main;
 ~~~~
 
index bb6cd17d3f28404eb489bb670172665cd0015d8f..83d662cbf59a117b7fff0586102dc2f574e4697d 100644 (file)
@@ -30,3 +30,5 @@ to
     comments_pagespec && !comments_closed_pagespec && check_canedit
 
 --[[smcv]]
+
+> [[merged|done]] --[[smcv]]
index cc6d11de7a6c08eacda2625a5ef3bdbd05f740d9..f068782b416e4abda5b4257ff59c34e497995d5f 100644 (file)
@@ -66,3 +66,5 @@ patch.
 >>>> Joey, I think this is [[ready for merge|users/smcv/ready]] even if it
 >>>> doesn't fix chrysn's bug - it does fix Python 3 support
 >>>> in general. --[[smcv]]
+
+>>>>> [[merged|done]] --[[smcv]]
diff --git a/doc/bugs/redirect.mdwn b/doc/bugs/redirect.mdwn
deleted file mode 100644 (file)
index 6296c3d..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-I suppose this isn't technically a bug, but whetever.
-
-I want symbolic links to be rendered as HTTP redirects. For example,
-if we do this,
-
-    touch foo.mkdwn
-    ln -s foo.mkdwn bar.mkdwn
-    git push baz.branchable.com
-
-then the following command should print 302
-
-    curl -o /dev/null -s -w "%{http_code}" http://baz.thomaslevine.com/bar/
-
-> An interesting idea, but it conflicts somewhat with wanting symlinks to be
-> treated as the referenced file when it's safe to do so, which would be
-> great for [[todo/git-annex support]], and also good to avoid duplication
-> for files in system-wide underlays.
->
-> Also, I don't think this is possible without help from the web server
-> configuration: for instance, under Apache, I believe the only way to get
-> an HTTP 302 redirect is via Apache-specific `.htaccess` files or
-> system-level Apache configuration.
->
-> In current ikiwiki, you can get a broadly similar effect by either
-> using \[[!meta redir=foo]] (which does a HTML `<meta>` redirect)
-> or reconfiguring the web server. --[[smcv]]
index 99e46aac9c4018f67366152ec1c135ca51f84776..57e0cf6aafeaab8bb7113dfbf09de7a8c9a98fc7 100644 (file)
@@ -27,3 +27,5 @@ throwing code..):
 
 > On second thought, this was a bug in ikiwiki, it should be transmitting
 > that as a string. Fixed in external.pm --[[Joey]] 
+
+>> [[done]] a while ago, then. I've added a regression test now. --[[smcv]]
index ca0738ad580957f29ecd45003a5ef50b92d7ee71..001d990ca5cbc6965460a3934bbf650ec2069405 100644 (file)
@@ -33,3 +33,5 @@ without decode('utf8') is working
 > [[this related bug|bugs/pythonproxy-utf8_again]]. [[!tag patch]] --smcv
 
 tested and fixed with patch [http://git.pseudorandom.co.uk/smcv/ikiwiki.git/commitdiff/38bd51bc1bab0cabd97dfe3cb598220a2c02550a](http://git.pseudorandom.co.uk/smcv/ikiwiki.git/commitdiff/38bd51bc1bab0cabd97dfe3cb598220a2c02550a) and patch [http://git.pseudorandom.co.uk/smcv/ikiwiki.git/commitdiff/81506fae8a6d5360f6d830b0e07190e60a7efd1c](http://git.pseudorandom.co.uk/smcv/ikiwiki.git/commitdiff/81506fae8a6d5360f6d830b0e07190e60a7efd1c)
+
+> [[done]], pending release --[[smcv]]
index ac18fe8aa31c42cae33218b97d187d685d10a6f9..9910959f907580cce8d1fe18dd18321a1a5356eb 100644 (file)
@@ -56,3 +56,5 @@ should be safe for inclusion.
 >>> which works, so my biggest fear about the all-to-png change is unwarranted.
 >>> i'll have a look at that some time, but i think as things are, this is
 >>> ready now, please review again. --[[chrysn]]
+
+>>>> [[merged|done]] --[[smcv]]
index babb1e3612a1e9c56170e6d981c5c690bff9605a..8e9edcf431e99ddb4893747c5a18740d0a50e64b 100644 (file)
@@ -12,3 +12,5 @@ list of pages.
 They should just sort the pages instead; they'll already have all the
 dependencies they need. My branch adds `IkiWiki::sort_pages` but does not
 make it plugin API just yet. --[[smcv]]
+
+> [[merged|done]] --[[smcv]]
diff --git a/doc/forum/Using_reverse_proxy__59___base_URL_is_http_instead_of_https/comment_5_674f56100c0682eba36cc5327fbdae4a._comment b/doc/forum/Using_reverse_proxy__59___base_URL_is_http_instead_of_https/comment_5_674f56100c0682eba36cc5327fbdae4a._comment
new file mode 100644 (file)
index 0000000..1546c67
--- /dev/null
@@ -0,0 +1,61 @@
+[[!comment format=mdwn
+ username="https://www.google.com/accounts/o8/id?id=AItOawk6z7Jsfi_XWfzFJNZIjYUcjgrthg4aPUU"
+ nickname="Alejandro"
+ subject="Same Trick in Apache"
+ date="2014-09-10T18:58:24Z"
+ content="""
+I got it working with Apache 2.4 and Virtual Hosts on both HTTP 1.1 and HTTPS (SNI). The procedure is somewhat analogous to the nginx procedure above. So here is my set-up in the hopes will help other avoid this pain.
+
+## Set-up
+
+    CLIENT <---- HTTPS ----> REVERSE PROXY <---- HTTP ----> IKIWIKI
+
+
+## The HTTP to HTTPS Redirect
+
+To assure that all your HTTP requests are being redirected to HTTPS I chose to use mod_rewrite because simple Redirect does not pass query parameters. You will want an HTTP VHost that will redirect with something like the one below (notice the subtle ? before query string). **Note: This will NOT re-write ikiwiki's http:// URLs (base tag, etc.)**. For that I use a content filter like you will see below. This HTTP to HTTPS redirect is required though for both security and for the /foo/?updated URI form in this set-up.
+
+<pre>
+
+&lt;VirtualHost *:80&gt;
+    ServerName imass.name
+    RewriteEngine On
+    RewriteCond %{HTTPS} off
+    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}?%{QUERY_STRING}
+    ErrorLog /var/log/imass.name-error.log
+    LogLevel warn
+    CustomLog /var/log/imass.name-access.log combined
+&lt;/VirtualHost&gt;
+
+</pre>
+
+## The SSL Virtual Host
+
+This part is a bit more tricky. First I am using SNI as I don't care for non-SNI user agents. Second, you need to use a filter that replaces all http:// to https:// before the response is set. Note that this alone won't deal with ?update so you will need the HTTP to HTTPS set-up above anyway. Third, I use HTTP Auth so I don't know if this will work with your particular Auth set-up (although it should IMHO), YMMV:
+
+<pre>
+
+&lt;VirtualHost *:443&gt;
+    ServerName imass.name
+    ProxyHTMLEnable On
+    ProxyHTMLExtended On
+    SSLEngine on
+    SSLCertificateFile XXX
+    SSLCertificateKeyFile XXX
+    SSLCertificateChainFile XXX
+    SSLOptions +StdEnvVars
+    ProxyPreserveHost On
+    ProxyHTMLURLMap http:// https://
+    ProxyPass / http://192.168.101.101/
+    ProxyPassReverse / http://192.168.101.101/
+    LogLevel warn
+    ErrorLog /var/log/imass.name-ssl-error.log
+    TransferLog \"/var/log/imass.name-ssl-access.log\"
+    CustomLog \"/var/log/imass.name-ssl-request.log\" \"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \\"%r\\" %b\"
+&lt;/VirtualHost&gt;
+
+</pre>
+
+
+
+"""]]
index 8f922596822edd1183e814f1c7a35318079ebe80..c5a91be06c7403fdec2393478034e5d2fb48b0cd 100644 (file)
@@ -18,3 +18,6 @@ Can anyone shed any light on this problem and guide me what I need to do to fix
 Regards,
 
 -- [Shlomi Fish](http://www.shlomifish.org/)
+
+> [[Merged anarcat's fix for
+this|bugs/garbled non-ascii characters in body in web interface]] --[[smcv]]
diff --git a/doc/forum/__34__Error:_cannot_decode_string_with_wide_characters__34___on_Mageia_Linux_x86-64_Cauldron/comment_1_abf7ec7c378ab0908685d72d159e9fd2._comment b/doc/forum/__34__Error:_cannot_decode_string_with_wide_characters__34___on_Mageia_Linux_x86-64_Cauldron/comment_1_abf7ec7c378ab0908685d72d159e9fd2._comment
new file mode 100644 (file)
index 0000000..8b066b3
--- /dev/null
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="https://id.koumbit.net/anarcat"
+ ip="72.0.72.144"
+ subject="comment 1"
+ date="2014-09-10T03:00:22Z"
+ content="""
+i had a similar issue, reported in [[bugs/garbled_non-ascii_characters_in_body_in_web_interface]]. 
+"""]]
index e71fa57d72cb223721100bddddebfade598ae811..55cc9c16eba4c73d4cb5cad97671966ac05dadf2 100644 (file)
@@ -81,6 +81,7 @@ think about merging them. This is recommended. :-)
 * [[cbaines]] `git://git.cbaines.net/ikiwiki`
 * [[mhameed]] `git://github.com/mhameed/ikiwiki.git`
 * [[spalax]] `git://github.com/paternal/ikiwiki.git` ([[browse|https://github.com/paternal/ikiwiki]])
+* [[jcflack]] `git://github.com/jcflack/ikiwiki.git`
 
 ## branches
 
index a6f301dd3c5906548fcdfd3853dd33937abe96d7..6269f5dd8a23935f1970fe62b998ecc15f569885 100644 (file)
@@ -27,8 +27,20 @@ something like:
        Details:
 
 The template page can also contain [[!cpan HTML::Template]] directives,
-like other ikiwiki [[templates]]. Currently only one variable is
-set: `<TMPL_VAR name>` is replaced with the name of the page being
-created.
+like other ikiwiki [[templates]].
+
+These variables might be set:
+
+* `<TMPL_VAR name>` is replaced with the name of the page being
+  created.
+  
+* `<TMPL_VAR uuid>` is replaced with a version 4 (random) UUID
+  suitable for use in `\[[!meta guid="urn:uuid:<TMPL_VAR uuid>"]]`.
+  (Requires the `UUID::Tiny` Perl module if not running on Linux.)
+
+* `<TMPL_VAR time>` is replaced with the current (template generation)
+  time using a fixed format (RFC 3339, `%Y-%m-%dT%H:%M:%SZ`),
+  suitable for use in `\[[!meta date="<TMPL_VAR time>"]]`
+  (see [[meta]]) or `\[[!date "<TMPL_VAR time>"]]` (see [[date]]).
 
 [[!meta robots="noindex, follow"]]
index cda62b58f04cdad190f2b9a72b28546416185652..08d15898702ca800c825cc33cb610c34bec50f23 100644 (file)
@@ -28,6 +28,9 @@ to the full size version. By default it does; set "link=somepage" to link
 to another page instead, or "link=no" to disable the link, or
 "link=http://url" to link to a given url.
 
+The `pagenumber` parameter selects which of multiple images should be rendered;
+this is relevant mainly for GIF and PDF source images.
+
 You can also set default values that will be applied to all later images on
 the page, unless overridden. Useful when including many images on a page.
 
index d8c83f022ff422429c192466b40aed2674a15bc9..e1a7ef07554bf02eb20265fec8e62211e2fdee8a 100644 (file)
@@ -121,3 +121,8 @@ I'm worried, at least until the issue is cleared.
 
 This poll is now 8 years old. Do we have enough data to make a decision?
 Can we consider adding `open=no` to the poll? -- [[Jon]]
+
+----
+
+I vote against disabling password logins until my OpenID will work on [ikiwiki.info](/)!
+See [[/plugins/openid/troubleshooting]]. -- Chap
index d56d1a396b8b505e424d272d8d93bae4dd3eb455..82c23fc4f6a0d6d3d4a4a8eab848c9d4f755463c 100644 (file)
@@ -30,3 +30,8 @@ certain setups.
   to be used when doing openid authentication. The `openid_cgiurl` must
   point to an ikiwiki [[CGI]], and it will need to match the `openid_realm`
   to work.
+
+## troubleshooting
+
+See [[plugins/openid/troubleshooting]] for a number of issues that may
+need to be addressed when setting up ikiwiki to accept OpenID logins reliably.
diff --git a/doc/plugins/openid/troubleshooting.mdwn b/doc/plugins/openid/troubleshooting.mdwn
new file mode 100644 (file)
index 0000000..c59f734
--- /dev/null
@@ -0,0 +1,197 @@
+**TL;DR**
+
+[[!toc levels=3]]
+
+# An odyssey through lots of things that have to be right before OpenID works
+
+Having just (at last) made an ikiwiki installation accept my
+OpenID, I have learned many of the things that may have to be checked
+when getting the [[plugins/openid]] plugin to work. (These are probably
+the reasons why [ikiwiki.info](/) itself won't accept my OpenID!)
+
+Just to describe my OpenID setup a bit (and why it makes a good stress-test
+for the OpenID plugin :).
+
+I'm using my personal home page URL as my OpenID. My page lives at
+a shared-hosting service I have hired. It contains links that delegate
+my OpenID processing to [indieauth.com](https://indieauth.com).
+
+IndieAuth, in turn, uses
+[rel-me authentication](http://microformats.org/wiki/RelMeAuth) to find
+an [OAuth](http://microformats.org/wiki/OAuth) provider that can authenticate
+me. (At present, I am using [github](http://github.com) for that, which
+is an OAuth provider but not an OpenID provider, so the gatewaying provided
+by IndieAuth solves that problem.) As far as ikiwiki is concerned,
+IndieAuth is my OpenID provider; the details beyond that are transparent.
+
+So, what were the various issues I had to sort out before my first successful
+login with the [[plugins/openid]] plugin?
+
+## no_identity_server: Could not determine ID provider from URL.
+
+This is the message [ikiwiki.info](/) shows as soon as I enter my home URL
+as an OpenID. It is also the first one I got on my own ikiwiki installation.
+
+### various possible causes ...
+
+There could be lots of causes. Maybe:
+
+* the offered OpenID is an `https:` URL and there is an issue in checking
+    the certificate, so the page can't be retrieved?
+* the page can be retrieved, but it isn't well-formed HTML and the library
+    can't parse it for the needed OpenID links?
+* ...?
+
+### make a luckier setting of useragent ?!
+
+In my case, it was none of the above. It turns out my shared-hosting provider
+has a rule that refuses requests with `User-Agent: libwww-perl/6.03` (!!).
+This is the sort of problem that's really hard to anticipate or plan around.
+I could fix it (_for this case!_) by changing `useragent:` in `ikiwiki.setup`
+to a different string that my goofy provider lets through.
+
+__Recommendation:__ set `useragent:` in `ikiwiki.setup` to some
+unlikely-to-be-blacklisted value. I can't guess what the best
+unlikely-to-be-blacklisted value is; if there is one, it's probably the
+next one all the rude bots will be using anyway, and some goofy provider
+like mine will blacklist it.
+
+## Error: OpenID failure: naive_verify_failed_network: Could not contact ID provider to verify response.
+
+Again, this could have various causes. It was helpful to bump the debug level
+and get some logging, to see:
+
+    500 Can't connect to indieauth.com:443 (Net::SSL from Crypt-SSLeay can't
+    verify hostnames; either install IO::Socket::SSL or turn off verification
+    by setting the PERL_LWP_SSL_VERIFY_HOSTNAME environment variable to 0)
+
+I don't belong to the camp that solves every verification problem by turning
+verification off, so this meant finding out how to get verification to be done.
+It turns out there are two different Perl modules that can be used for SSL:
+
+* `IO::Socket::SSL` (verifies hostnames)
+* `Net::SSL` (_does not_ verify hostnames)
+
+Both were installed on my hosted server. How was Perl deciding which one
+to use?
+
+### set `PERL_NET_HTTPS_SSL_SOCKET_CLASS` appropriately
+
+It turns out
+[there's an environment variable](https://rt.cpan.org/Public/Bug/Display.html?id=71599).
+So just set `PERL_NET_HTTPS_SSL_SOCKET_CLASS` to `IO::Socket::SSL` and the
+right module gets used, right?
+
+[Wrong](https://github.com/csirtgadgets/LWPx-ParanoidAgent/commit/fed6f7d7df8619df0754e8883cfad2ac15703a38#diff-2).
+That change was made to `ParanoidAgent.pm` back in November 2013 because of an
+unrelated [bug](https://github.com/csirtgadgets/LWPx-ParanoidAgent/issues/4)
+in `IO::Socket::SSL`. Essentially, _hmm, something goes wrong in
+`IO::Socket::SSL` when reading certain large documents, so we'll fix it by
+forcing the use of `Net::SSL` instead (the one that never verifies hostnames!),
+no matter what the admin has set `PERL_NET_HTTPS_SSL_SOCKET_CLASS` to!_
+
+### undo change that broke `PERL_NET_HTTPS_SSL_SOCKET_CLASS`
+
+Plenty of [comments](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=738493)
+quickly appeared about how good an idea that wasn't, and it was corrected in
+June 2014 with [one commit](https://github.com/csirtgadgets/LWPx-ParanoidAgent/commit/a92ed8f45834a6167ff62d3e7330bb066b307a35)
+to fix the original reading-long-documents issue in `IO::Socket::SSL` and
+[another commit](https://github.com/csirtgadgets/LWPx-ParanoidAgent/commit/815c691ad5554a219769a90ca5f4001ae22a4019)
+that reverts the forcing of `Net::SSL` no matter how the environment is set.
+
+Unfortunately, there isn't a release in CPAN yet that includes those two
+commits, but they are only a few lines to edit into your own locally-installed
+module.
+
+## Still naive_verify_failed_network, new improved reason
+
+    500 Can't connect to indieauth.com:443 (SSL connect attempt failed
+    with unknown error error:14090086:SSL
+    routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed)
+
+Yay, at least it's trying to verify! Now why can't it verify IndieAuth's
+certificate?
+
+[Here's why](https://tools.ietf.org/html/rfc6066#section-3). As it turns out,
+[indieauth.com](https://indieauth.com/) is itself a virtual host on a shared
+server. If you naively try
+
+    openssl s_client -connect indieauth.com:443
+
+you get back a certificate for [indieweb.org](https://indieweb.org/)
+instead, so the hostname won't verify. If you explicitly indicate what server
+name you're connecting to:
+
+    openssl s_client -connect indieauth.com:443 -servername indieauth.com
+
+then, magically, the correct certificate comes back.
+
+### ensure `OpenSSL`, `Net::SSLeay`, `IO::Socket::SSL` new enough for SNI
+
+If your `openssl` doesn't recognize the `-servername` option, it is too old
+to do SNI, and a newer version needs to be built and installed. In fact,
+even though SNI support was reportedly backported into OpenSSL 0.9.8f, it will
+not be used by `IO::Socket::SSL` unless it is
+[1.0 or higher](http://search.cpan.org/~sullr/IO-Socket-SSL-1.998/lib/IO/Socket/SSL.pod#SNI_Support).
+
+Then a recent `Net::SSLeay` perl module needs to be built and linked against it.
+
+### Local OpenSSL installation will need certs to trust
+
+Bear in mind that the OpenSSL distribution doesn't come with a collection
+of trusted issuer certs. If a newer version is built and installed locally
+(say, on a shared server where the system locations can't be written), it will
+need to be given a directory of trusted issuer certs, say by linking to the
+system-provided ones. However, a change to the certificate hash algorithm used
+for the symlinks in that directory was [reportedly](http://www.cilogon.org/openssl1)
+made with OpenSSL 1.0.0. So if the system-provided trusted certificate directory
+was set up for an earlier OpenSSL version, all the certificates in it will be
+fine but the hash symlinks will be wrong. That can be fixed by linking only the
+named certificate files from the system directory into the newly-installed one,
+and then running the new version of `c_rehash` there.
+
+## Still certificate verify failed
+
+Using [SNI](https://tools.ietf.org/html/rfc6066#section-3)-supporting versions
+of `IO::Socket::SSL`, `Net::SSLeay`, and `OpenSSL` doesn't do any good if an
+upper layer hasn't passed down the name of the host being connected to so the
+SSL layer can SNI for it.
+
+### ensure that `LWPx::ParanoidAgent` passes server name to SSL layer for SNI
+
+That was fixed in `LWPx::ParanoidAgent` with
+[this commit](https://github.com/csirtgadgets/LWPx-ParanoidAgent/commit/df6df19ccdeeb717c709cccb011af35d3713f546),
+which needs to be backported by hand if it hasn't made it into a CPAN release
+yet.
+
+Only that still doesn't end the story, because that hand didn't know what
+[this hand](https://github.com/noxxi/p5-io-socket-ssl/commit/4f83a3cd85458bd2141f0a9f22f787174d51d587#diff-1)
+was doing. What good is passing the name in
+`PeerHost` if the SSL code looks in `PeerAddr` first ... and then, if that
+doesn't match a regex for a hostname, decides you didn't supply one at all,
+without even looking at `PeerHost`?
+
+Happily, is is possible to assign a key that _explicitly_ supplies the
+server name for SNI:
+
+    --- LWPx/Protocol/http_paranoid.pm    2014-09-08 03:33:00.000000000 -0400
+    +++ LWPx/Protocol/http_paranoid.pm    2014-09-08 03:33:27.000000000 -0400
+    @@ -73,6 +73,7 @@
+            close($el);
+             $sock = $self->socket_class->new(PeerAddr => $addr,
+                                              PeerHost => $host,
+    +                                         SSL_hostname => $host,
+                                              PeerPort => $port,
+                                              Proto    => 'tcp',
+                                              Timeout  => $conn_timeout,
+
+... not submitted upstream yet, so needs to be applied by hand.
+
+# Success!!
+
+And with that, ladies and gents, I got my first successful OpenID login!
+I'm pretty sure that if the same fixes can be applied to
+[ikiwiki.info](/) itself, a wider range of OpenID logins (like mine, for
+example :) will work here too.
+
+-- Chap
index 047fb38497e9e86676e9a4fb15aed79927a09b6b..f9fa321b3b96baa49c0b79ce32ce03a8553d38c6 100644 (file)
@@ -1,3 +1,4 @@
+
 This is the [[SandBox]], a page anyone can edit to try out ikiwiki
 (version [[!version  ]]).
 
index b4f6d8ef47b4fb0ec1a067743c8732c6eb6f7d24..ca529c296b64e9eb34f884c5a1595365ea41cca6 100644 (file)
@@ -27,7 +27,7 @@ This page controls what shortcut links the wiki supports.
 * [[!shortcut name=debrt url="https://rt.debian.org/Ticket/Display.html?id=%s"]]
 * [[!shortcut name=debss url="http://snapshot.debian.org/package/%s/"]]
   * Usage: `\[[!debss package]]` or `\[[!debss package/version]]`.  See <http://snapshot.debian.org/> for details.
-* [[!shortcut name=debwiki url="https://wiki.debian.org/%s"]]
+* [[!shortcut name=debwiki url="https://wiki.debian.org/%S"]]
 * [[!shortcut name=fdobug url="https://bugs.freedesktop.org/show_bug.cgi?id=%s" desc="freedesktop.org bug #%s"]]
 * [[!shortcut name=fdolist url="http://lists.freedesktop.org/mailman/listinfo/%s" desc="%s@lists.freedesktop.org"]]
 * [[!shortcut name=gnomebug url="https://bugzilla.gnome.org/show_bug.cgi?id=%s" desc="GNOME bug #%s"]]
@@ -55,7 +55,7 @@ This page controls what shortcut links the wiki supports.
 * [[!shortcut name=whois url="http://reports.internic.net/cgi/whois?whois_nic=%s&type=domain"]]
 * [[!shortcut name=cve url="https://cve.mitre.org/cgi-bin/cvename.cgi?name=%s"]]
 * [[!shortcut name=flickr url="https://secure.flickr.com/photos/%s"]]
-* [[!shortcut name=man url="http://linux.die.net/man/%s"]]
+* [[!shortcut name=man url="http://manpages.debian.org/%s"]]
 * [[!shortcut name=ohloh url="https://www.ohloh.net/p/%s"]]
 * [[!shortcut name=cpanrt url="https://rt.cpan.org/Ticket/Display.html?id=%s" desc="CPAN RT#%s"]]
 * [[!shortcut name=novellbug url="https://bugzilla.novell.com/show_bug.cgi?id=%s" desc="bug %s"]]
index 6bbaf3e6e818e2e286c0cf9d357c9b03f649e146..e6277d3384861a9bda93ed09b1c67399a1ea60e2 100644 (file)
@@ -38,6 +38,8 @@ it on a remote machine, and tell Ikiwiki to use it instead of its local one. We
 will also ensure that the wiki is rendered whenever a commit is done to the git
 repository.
 
+[[!img separate-web-git-servers.svg size=400x]]
+
 # Conventions
 
 - We are building a wiki called *SITE*.
diff --git a/doc/tips/Hosting_Ikiwiki_and_master_git_repository_on_different_machines/separate-web-git-servers.svg b/doc/tips/Hosting_Ikiwiki_and_master_git_repository_on_different_machines/separate-web-git-servers.svg
new file mode 100644 (file)
index 0000000..b6095a2
--- /dev/null
@@ -0,0 +1,783 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   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://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="493.26132"
+   height="546.48431"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="separate-web-git-servers.svg">
+  <defs
+     id="defs4">
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Lend"
+       style="overflow:visible">
+      <path
+         id="path3914"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lend"
+       style="overflow:visible">
+      <path
+         id="path3896"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+         transform="matrix(-0.8,0,0,-0.8,-10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow1Lstart"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow1Lstart"
+       style="overflow:visible">
+      <path
+         id="path3893"
+         d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+         style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+         transform="matrix(0.8,0,0,0.8,10,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <linearGradient
+       id="linearGradient3767">
+      <stop
+         style="stop-color:#efbc00;stop-opacity:1;"
+         offset="0"
+         id="stop3769" />
+      <stop
+         id="stop3775"
+         offset="0.93150687"
+         style="stop-color:#ffcb10;stop-opacity:1;" />
+      <stop
+         style="stop-color:#ffffff;stop-opacity:1;"
+         offset="1"
+         id="stop3771" />
+    </linearGradient>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Lend-4"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3914-9"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker5456"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path5458"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Lend-3"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3914-6"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker5456-4"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path5458-7"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Lend-5"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3914-92"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker5456-3"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path5458-78"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Lend-36"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path3914-5"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker5532"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path5534"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="Arrow2Lend-9"
+       style="overflow:visible">
+      <path
+         id="path3914-62"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker3131"
+       style="overflow:visible">
+      <path
+         id="path3133"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-1.1,0,0,-1.1,-1.1,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker5532-3"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path5534-1"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+    </marker>
+    <marker
+       inkscape:stockid="Arrow2Lend"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="marker5532-1"
+       style="overflow:visible">
+      <path
+         inkscape:connector-curvature="0"
+         id="path5534-12"
+         style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+         d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+         transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1.0885159"
+     inkscape:cx="285.18022"
+     inkscape:cy="314.69374"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     inkscape:snap-global="true"
+     inkscape:window-width="1440"
+     inkscape:window-height="834"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1"
+     fit-margin-top="25"
+     fit-margin-left="25"
+     fit-margin-right="25"
+     fit-margin-bottom="25">
+    <inkscape:grid
+       type="xygrid"
+       id="grid2985"
+       empspacing="5"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true"
+       originx="0.24219388px"
+       originy="26px" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-159.41406,-135.03802)">
+    <rect
+       style="fill:none;stroke:#000000;stroke-width:0.44862616;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       id="rect3866"
+       width="442.58115"
+       height="91.284172"
+       x="184.86992"
+       y="415.3576"
+       ry="4.005312"
+       rx="10.005878" />
+    <path
+       style="fill:#ffcb14;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 355,222.36218 55,0 0,-45 -25,0 -5,-5 -20,0 -5,5 z"
+       id="path2989"
+       inkscape:connector-curvature="0" />
+    <text
+       xml:space="preserve"
+       style="font-size:40px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="368.57144"
+       y="251.21931"
+       id="text2995"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan2997"
+         x="368.57144"
+         y="251.21931" /></text>
+    <path
+       style="fill:#ffcb14;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 355,348.36218 55,0 0,-45 -25,0 -5,-5 -20,0 -5,5 z"
+       id="path2989-4"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:#ffcb14;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 355,483.36218 55,0 0,-45 -25,0 -5,-5 -20,0 -5,5 z"
+       id="path2989-1"
+       inkscape:connector-curvature="0" />
+    <path
+       style="fill:#ffcb14;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 355,623.36218 55,0 0,-45 -25,0 -5,-5 -20,0 -5,5 z"
+       id="path2989-5"
+       inkscape:connector-curvature="0" />
+    <path
+       style="opacity:0.48800001;fill:#ffcb14;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 475,623.36218 55,0 0,-45 -25,0 -5,-5 -20,0 -5,5 z"
+       id="path2989-2"
+       inkscape:connector-curvature="0" />
+    <path
+       style="opacity:0.5;fill:#ffcb14;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="m 235,623.36218 55,0 0,-45 -25,0 -5,-5 -20,0 -5,5 z"
+       id="path2989-8"
+       inkscape:connector-curvature="0" />
+    <text
+       xml:space="preserve"
+       style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="386.06738"
+       y="652.36218"
+       id="text3868"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3870"
+         x="386.06738"
+         y="652.36218"
+         style="font-size:20px;text-align:center;text-anchor:middle">working clones</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:18px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="524.37988"
+       y="463.36218"
+       id="text3874"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3876"
+         x="524.37988"
+         y="463.36218"
+         style="font-size:20px;text-align:center;text-anchor:middle">repository</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="525.35156"
+       y="330.36218"
+       id="text3878"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3880"
+         x="525.35156"
+         y="330.36218"
+         style="font-size:20px;text-align:center;text-anchor:middle">srcdir</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="525.1543"
+       y="201.36218"
+       id="text3882"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan3884"
+         x="525.1543"
+         y="201.36218"
+         style="font-size:20px;text-align:center;text-anchor:middle">destdir</tspan></text>
+    <g
+       id="g5440"
+       transform="translate(5,51.000003)">
+      <path
+         sodipodi:nodetypes="cc"
+         inkscape:connector-curvature="0"
+         id="path3886"
+         d="m 370,512.36218 c -5,-24.99999 -5,-44.99999 0,-70"
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none;marker-mid:none;marker-end:url(#Arrow2Lend)" />
+      <path
+         sodipodi:nodetypes="cc"
+         inkscape:connector-curvature="0"
+         id="path3888"
+         d="m 390,442.36218 c 5,25 5,45 0,70"
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)" />
+    </g>
+    <g
+       transform="translate(5,-84)"
+       id="g5440-4" />
+    <g
+       transform="matrix(0.71872744,0.69529193,-0.69529193,0.71872744,353.78964,-78.94206)"
+       id="g5440-47">
+      <path
+         sodipodi:nodetypes="cc"
+         inkscape:connector-curvature="0"
+         id="path3886-3"
+         d="m 370,512.36218 c -5,-24.99999 -0.0778,-66.9912 7.34379,-88.08431"
+         style="opacity:0.5;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none;marker-mid:none;marker-end:url(#Arrow2Lend)" />
+      <path
+         sodipodi:nodetypes="cc"
+         inkscape:connector-curvature="0"
+         id="path3888-6"
+         d="m 391.48399,424.51223 c 5,25 6.0155,63.74804 -1.48399,87.84995"
+         style="opacity:0.5;fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)" />
+    </g>
+    <g
+       transform="matrix(-0.71872744,0.69529193,0.69529193,0.71872744,421.21036,-78.94206)"
+       id="g5440-47-9"
+       style="opacity:0.5">
+      <path
+         sodipodi:nodetypes="cc"
+         inkscape:connector-curvature="0"
+         id="path3886-3-3"
+         d="m 370,512.36218 c -5,-24.99999 -0.0778,-66.9912 7.34379,-88.08431"
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:none;marker-mid:none;marker-end:url(#Arrow2Lend)" />
+      <path
+         sodipodi:nodetypes="cc"
+         inkscape:connector-curvature="0"
+         id="path3888-6-3"
+         d="m 391.48399,424.51223 c 5,25 6.0155,63.74804 -1.48399,87.84995"
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#Arrow2Lend)" />
+    </g>
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker5532)"
+       d="m 380,288.36218 0,-60"
+       id="path5558"
+       inkscape:connector-curvature="0" />
+    <g
+       id="g5810"
+       transform="translate(0,17)">
+      <g
+         transform="translate(-230,-4.9999974)"
+         id="g3784-7">
+        <g
+           id="g3779-37">
+          <path
+             inkscape:connector-curvature="0"
+             id="path2993-5"
+             d="m 440,177.36218 10,0 0,-10"
+             style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+          <path
+             sodipodi:nodetypes="cccccc"
+             inkscape:connector-curvature="0"
+             id="path2991-3"
+             d="m 440,177.36218 0,40 35,0 0,-50 -25,0 z"
+             style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+          <path
+             inkscape:connector-curvature="0"
+             id="path3777-8"
+             d="m 440,177.36218 10,0 0,-10"
+             style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+        </g>
+      </g>
+      <g
+         transform="translate(-235,-9.9999974)"
+         id="g3784">
+        <g
+           id="g3779">
+          <path
+             inkscape:connector-curvature="0"
+             id="path2993"
+             d="m 440,177.36218 10,0 0,-10"
+             style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+          <path
+             sodipodi:nodetypes="cccccc"
+             inkscape:connector-curvature="0"
+             id="path2991"
+             d="m 440,177.36218 0,40 35,0 0,-50 -25,0 z"
+             style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+          <path
+             inkscape:connector-curvature="0"
+             id="path3777"
+             d="m 440,177.36218 10,0 0,-10"
+             style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+        </g>
+      </g>
+      <text
+         sodipodi:linespacing="125%"
+         id="text5762"
+         y="176.55017"
+         x="206.62401"
+         style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+         xml:space="preserve"><tspan
+           style="font-size:8px"
+           y="176.55017"
+           x="206.62401"
+           id="tspan5764"
+           sodipodi:role="line">&lt;html&gt;</tspan></text>
+    </g>
+    <g
+       id="g5824"
+       transform="translate(0,17)">
+      <g
+         transform="translate(-165,-9.9999974)"
+         id="g3784-0">
+        <g
+           id="g3779-3">
+          <path
+             inkscape:connector-curvature="0"
+             id="path2993-2"
+             d="m 440,177.36218 10,0 0,-10"
+             style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+          <path
+             sodipodi:nodetypes="cccccc"
+             inkscape:connector-curvature="0"
+             id="path2991-8"
+             d="m 440,177.36218 0,40 35,0 0,-50 -25,0 z"
+             style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+          <path
+             inkscape:connector-curvature="0"
+             id="path3777-7"
+             d="m 440,177.36218 10,0 0,-10"
+             style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+        </g>
+      </g>
+      <g
+         transform="matrix(0.74161576,0,0,0.74161576,75.250882,53.354937)"
+         id="g5772">
+        <path
+           sodipodi:type="star"
+           style="fill:#939393;fill-opacity:1;stroke:#939393;stroke-width:0.70866144;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+           id="path5768"
+           sodipodi:sides="13"
+           sodipodi:cx="295"
+           sodipodi:cy="187.36218"
+           sodipodi:r1="10.889445"
+           sodipodi:r2="14.142136"
+           sodipodi:arg1="-2.3561945"
+           sodipodi:arg2="-2.1145335"
+           inkscape:flatsided="false"
+           inkscape:rounded="0.36"
+           inkscape:randomized="0"
+           d="m 287.3,179.66218 c 1.12496,-1.12496 -0.97775,-3.57952 0.38374,-4.40257 1.36149,-0.82305 2.55772,2.1795 4.07662,1.70619 1.5189,-0.47331 0.79773,-3.62389 2.38576,-3.71995 1.58803,-0.0961 1.25188,3.11848 2.81676,3.40526 1.56487,0.28677 2.39046,-2.83808 3.84123,-2.18514 1.45078,0.65294 -0.34074,3.34306 0.91162,4.32422 1.25235,0.98116 3.43557,-1.40209 4.41673,-0.14973 0.98116,1.25236 -1.85532,2.80178 -1.20238,4.25255 0.65294,1.45078 3.69363,0.35511 3.98041,1.91998 0.28677,1.56488 -2.94485,1.61865 -3.04091,3.20668 -0.0961,1.58803 3.10552,2.03094 2.63221,3.54984 -0.47331,1.5189 -3.35976,0.0647 -4.18281,1.42619 -0.82305,1.3615 1.80598,3.24152 0.68102,4.36648 -1.12496,1.12496 -3.00498,-1.50407 -4.36648,-0.68101 -1.36149,0.82305 0.0927,3.7095 -1.42619,4.1828 -1.5189,0.47331 -1.96181,-2.72827 -3.54984,-2.63221 -1.58803,0.0961 -1.64181,3.32768 -3.20668,3.04091 -1.56488,-0.28678 -0.4692,-3.32746 -1.91998,-3.9804 -1.45077,-0.65294 -3.00019,2.18353 -4.25255,1.20237 -1.25236,-0.98116 1.13089,-3.16437 0.14973,-4.41673 -0.98116,-1.25236 -3.67128,0.53916 -4.32422,-0.91161 -0.65294,-1.45078 2.47191,-2.27636 2.18513,-3.84124 -0.28677,-1.56488 -3.50131,-1.22873 -3.40525,-2.81676 0.096,-1.58803 3.24664,-0.86686 3.71995,-2.38576 0.47331,-1.5189 -2.52925,-2.71513 -1.70619,-4.07662 0.82305,-1.36149 3.27761,0.74122 4.40257,-0.38374 z"
+           inkscape:transform-center-x="-0.68364368"
+           inkscape:transform-center-y="0.68364368"
+           transform="translate(-2,0)" />
+        <path
+           sodipodi:type="arc"
+           style="fill:#ffffff;fill-opacity:1;stroke:#939393;stroke-width:0.70866144;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+           id="path5770"
+           sodipodi:cx="295"
+           sodipodi:cy="187.36218"
+           sodipodi:rx="5"
+           sodipodi:ry="5"
+           d="m 300,187.36218 c 0,2.76143 -2.23858,5 -5,5 -2.76142,0 -5,-2.23857 -5,-5 0,-2.76142 2.23858,-5 5,-5 2.76142,0 5,2.23858 5,5 z"
+           transform="matrix(1.4,0,0,1.4,-120,-74.944873)" />
+      </g>
+    </g>
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="265"
+       y="237.36218"
+       id="text5806"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan5808"
+         x="265"
+         y="237.36218"
+         style="font-size:12px">ikiwiki.cgi</tspan></text>
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker5532)"
+       d="m 295,243.36218 c -33.17806,71.23519 20.40659,76.94287 53.16264,84.08132"
+       id="path5834"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="303.54837"
+       y="447.15784"
+       id="text6240"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan6242"
+         x="303.54837"
+         y="447.15784"
+         style="font-size:14px;text-align:end;writing-mode:lr-tb;text-anchor:end">post-update</tspan><tspan
+         sodipodi:role="line"
+         x="303.54837"
+         y="464.65784"
+         style="font-size:14px;text-align:end;writing-mode:lr-tb;text-anchor:end"
+         id="tspan6244">hook</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="400.70767"
+       y="387.44351"
+       id="text6246"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan6248"
+         x="400.70767"
+         y="387.44351"
+         style="font-size:14px">ikiwiki.cgi</tspan><tspan
+         sodipodi:role="line"
+         x="400.70767"
+         y="404.94351"
+         id="tspan6250"
+         style="font-size:14px">push</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="382"
+       y="342.36218"
+       id="text6252"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan6254"
+         x="382"
+         y="342.36218">.git</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="383"
+       y="618.36218"
+       id="text6252-3"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan6254-1"
+         x="383"
+         y="618.36218">.git</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;opacity:0.3;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="502"
+       y="617.36218"
+       id="text6252-3-1"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan6254-1-0"
+         x="502"
+         y="617.36218">.git</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;opacity:0.3;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="263"
+       y="618.36218"
+       id="text6252-3-6"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan6254-1-1"
+         x="263"
+         y="618.36218">.git</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="411"
+       y="482.36218"
+       id="text6252-3-0"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan6254-1-2"
+         x="411"
+         y="482.36218">.git</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="353.28357"
+       y="277.33801"
+       id="text6372"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan6374"
+         x="353.28357"
+         y="277.33801"
+         style="font-size:14px">web-side</tspan><tspan
+         sodipodi:role="line"
+         x="353.28357"
+         y="294.83801"
+         id="tspan6376"
+         style="font-size:14px">edit</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="410"
+       y="258.36218"
+       id="text6378"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan6380"
+         x="410"
+         y="258.36218"
+         style="font-size:14px">automatic</tspan><tspan
+         sodipodi:role="line"
+         x="410"
+         y="275.86218"
+         id="tspan6382"
+         style="font-size:14px">rebuild</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="406.75635"
+       y="527.15295"
+       id="text6384"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan6386"
+         x="406.75635"
+         y="527.15295"
+         style="font-size:14px">git</tspan><tspan
+         sodipodi:role="line"
+         x="406.75635"
+         y="544.65295"
+         id="tspan6388"
+         style="font-size:14px">pull</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="363.62955"
+       y="530.39691"
+       id="text6390"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan6392"
+         x="363.62955"
+         y="530.39691"
+         style="font-size:14px;text-align:end;text-anchor:end">git</tspan><tspan
+         sodipodi:role="line"
+         x="363.62955"
+         y="547.89691"
+         id="tspan6394"
+         style="font-size:14px;text-align:end;text-anchor:end">push</tspan></text>
+    <rect
+       style="fill:none;stroke:#000000;stroke-width:1.11616147;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       id="rect3866-3"
+       width="441.9136"
+       height="210.04529"
+       x="184.97214"
+       y="160.5961"
+       ry="24.83"
+       rx="9.9907875" />
+    <text
+       xml:space="preserve"
+       style="font-size:16px;font-style:normal;font-weight:normal;text-align:end;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:end;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+       x="246.14922"
+       y="257.2352"
+       id="text6240-9"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         x="246.14922"
+         y="257.2352"
+         style="font-size:14px;text-align:end;writing-mode:lr-tb;text-anchor:end"
+         id="tspan6244-2">pingee</tspan></text>
+    <path
+       style="fill:none;stroke:#000000;stroke-width:0.96974897px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker5532)"
+       d="m 381.75266,355.47259 0,66.86071"
+       id="path5558-7"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-end:url(#marker5532)"
+       d="M 342.2494,449.19328 C 188.8295,356.40638 236.60096,296.40639 265.99879,248.63492"
+       id="path5558-1"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cc" />
+  </g>
+</svg>
index 1d8a8f5a91bddb9167f5495ca148cac64a9b483b..2547a2e9fe510bdbb8ab22a06f847d1a47aaac47 100644 (file)
@@ -37,6 +37,8 @@ the git server.
 
 ### Separate webserver and git repository, the git srcdir being hosted on the webserver
 
+[[!img Hosting_Ikiwiki_and_master_git_repository_on_different_machines/separate-web-git-servers.svg size=400x]]
+
 This is the configuration described in
 [[tips/Hosting_Ikiwiki_and_master_git_repository_on_different_machines]]. One server hosts the web server (and the [[Ikiwiki cgi|cgi]]) and the git source dir; a second server hosts the git bare repository. This can be used when you have very limited access to the git server.
 
index 8bbb7c2cf912bbb7cd26d0dc0ed9eef747fbbe72..ab5eb229b0eae766826b9ac50c2c1a5034c5a0c9 100644 (file)
@@ -194,3 +194,10 @@ Regards,
 > like `limit` (by analogy with SQL) or `max` as the canonical name for the
 > "number of things to match" parameter, at which point a non-numeric
 > `show` could mean this thing. --[[smcv]]
+
+>> [[!template id=gitbranch branch=smcv/pagestats-show
+author="[[Louis|spalax]], [[smcv]]"
+browse=http://git.pseudorandom.co.uk/smcv/ikiwiki.git/shortlog/refs/heads/pagestats-show]]
+>> Here's a branch. It depends on my `ready/limit` branch
+>> from [[todo/pick a new canonical name for equivalent of SQL limit]].
+>> --[[smcv]]
index 02659d0d1825d618a530da88f1f4f967e1bda97e..2a7350b79ef3656ac4f334d3415f6a8fdf4d378b 100644 (file)
@@ -181,3 +181,45 @@ sub gencalendaryear {
 ---
 
 [[smcv]], can you please go on reviewing this?
+
+> I don't think I'm really the reviewer you want, since I don't have commit
+> access (as you might be able to tell from the number of pending branches
+> I have)... but nobody with commit access seems to be available to do
+> reviews at the moment, so I'm probably the best you're going to get.
+>
+>     +    0 0 * * * ikiwiki ~/ikiwiki.setup --refresh
+>
+> I think that should be `ikiwiki --setup ~/ikiwiki.setup --refresh`
+>
+> The indentation of some of the new code in `IkiWiki/Plugin/calendar.pm`
+> is weird. Please use one hard tab (U+0009) per indent step: you seem
+> to have used a mixture of one hard tab per indent or two spaces
+> per indent, which looks bizarre for anyone whose tab size is not
+> 2 spaces.
+>
+>     +        return unless $config{calendar_autocreate};
+>
+> This is checked in `gencalendaryear` but not in `gencalendarmonth`.
+> Shouldn't `gencalendarmonth` do it too? Alternatively, do the check
+> in `scan`, which calls `gencalendarmonth` directly.
+>
+>     +                my $year  = $date[5] + 1900;
+>
+> You calculate this, but you don't seem to do anything with it?
+>
+>     +  if (not exists $changed{$params{year}}) {
+>     +    $changed{$params{year}} = ();
+>     +  }
+>     +  $changed{$params{year}}{$params{month}} = 1;
+>
+> `$changed{$params{year}}` is a scalar (you can tell because it starts with the
+> `$` sigil) but `()` is a list. I think you want `{}`
+> (a scalar that is a reference to an empty anonymous hash).
+>
+> However, that whole `if` block can be omitted, and you can just use
+> `$changed{$params{year}}{$params{month}} = 1;`, because Perl will automatically
+> create `$changed{$params{year}}` as a reference to an empty hash if necessary,
+> in order to put the pair `$params{month} => 1` in it (the term to look
+> up if you're curious is "autovivification").
+>
+> --[[smcv]]
index 4059d8e2ac83d092bb5210549159082a581ef0f3..50720fed04d06cd69a260323d373cea2852526b6 100644 (file)
@@ -30,6 +30,35 @@ Discussion
 > > 
 > > Originally, I named that parameter `backwards_links`, but then it wouldn't make sense in the long term, and isn't exactly neutral: it assume the current way is backwards! Your suggestion is interesting however, but I don't think the rtl/ltr nomenclature is problematic, with proper documentation of course... --[[anarcat]]
 
+> > > I still don't think `rtl`/`ltr` is the right terminology here. I think
+> > > the "API" should say what you mean: the distinction being made is
+> > > "text first" vs. "link first", so, say that.
+> > >
+> > > As far as I understand it, RTL languages like Arabic typically write
+> > > text files "in logical order" (i.e. reading/writing order - first
+> > > letter is first in the bytestream) and only apply RTL rendering on
+> > > display. IkiWiki is UTF-8-only, and Unicode specifies that all
+> > > Unicode text should be in logical order. The opposite of logical
+> > > order is is "display order", which is how you would have to mangle
+> > > the file for it to appear correctly on a naive terminal that expects
+> > > LTR; that can only work correctly for hard-wrapped text, I think.
+> > >
+> > > IkiWiki will parse files
+> > > in logical order too; so if a link's text and destination are both
+> > > written in Arabic, in text-before-link order in the source code, an
+> > > Arabic reader starting from the right would still see the text
+> > > before the link. Similarly, in your proposed link-before-text
+> > > order, an Arabic reader would still see the link before the text
+> > > (which in their case means further to the right). So I don't think
+> > > it would make sense to suggest that
+> > > one order was more appropriate for RTL languages than the other: if
+> > > it's "more correct" (for whatever opinion of "correct") in English, then
+> > > it's "more correct" in Arabic too.
+> > >
+> > > (If the destination is written in Latin then it gets
+> > > more complicated, because the destination will be rendered LTR within an
+> > > otherwise RTL document. I think the order still works though.) --[[smcv]]
+
 There's a caveat: we can't have a per-wiki backwards_links option, because of the underlay, common to all wikis, which needs to be converted. So the option doesn't make much sense. Not sure how to deal with this... Maybe this needs to be at the package level? --[[anarcat]]
 
 > I've thought about adding a direction-neutral `\[[!link]]` directive -
@@ -80,6 +109,7 @@ I think we can approach this rationnally:
 
  1. left to right (text then link) can be considered more natural, and should therefore be supported
  2. it is supported in markdown using regular markdown links. in the proposed branch, the underlay wikilinks are converted to use regular markdown links
+    > Joey explicitly rejected this for a valid reason (it breaks inlining). See above. --[[smcv]]
  3. ikiwiki links break other markup plugins, like mediawiki and creole, as those work right to left.
  4. those are recognized "standards" used by other popular sites, like Wikipedia, or any wiki supporting the Creole markup, which is [most wikis](http://www.wikicreole.org/wiki/Engines)
 
index e5a8d0ab9eaf8a480a0aa35eeac856d8732a6e25..6d702fedf1032c9398f80cc526237307e6ee2149 100644 (file)
@@ -83,3 +83,5 @@ Changes to the structure of `$pagestate{$registering_page}{edittemplate}{$pagesp
 >>>>> almost 5 years ago. Branch replaced by `smcv/ready/edittemplate2`
 >>>>> which drops `formatted_time` and `html_time`, and adds a suggestion
 >>>>> to use `\[[!date]]`. --[[smcv]]
+
+>>>>>> [[merged|done]] --[[smcv]]
index daa520d71042112e39452152a5b2d408f85c5cfe..4e70f81798d6e810d02131a358d0530bdacdfe02 100644 (file)
@@ -35,4 +35,10 @@ Which of those do Joey/other contributors prefer?
 Or if keeping `show=10` is preferred, what should be the conventional name
 for functionality like `\[[!map show=title]]`?
 
-I personally like the idea of `\[[!inline limit=10]]`. --[[smcv]]
+> [[!template id=gitbranch branch=smcv/ready/limit
+author="[[Simon McVittie|smcv]]"
+browse=http://git.pseudorandom.co.uk/smcv/ikiwiki.git/shortlog/refs/heads/ready/limit]]
+> [[!tag patch users/smcv/ready]]
+
+I personally prefer `\[[!inline limit=10]]` so I have put that in a branch.
+Agreement/objections/better ideas welcome. --[[smcv]]
diff --git a/doc/todo/redirect.mdwn b/doc/todo/redirect.mdwn
new file mode 100644 (file)
index 0000000..87f6a67
--- /dev/null
@@ -0,0 +1,53 @@
+I suppose this isn't technically a bug, but whetever.
+
+I want symbolic links to be rendered as HTTP redirects. For example,
+if we do this,
+
+    touch foo.mkdwn
+    ln -s foo.mkdwn bar.mkdwn
+    git push baz.branchable.com
+
+then the following command should print 302
+
+    curl -o /dev/null -s -w "%{http_code}" http://baz.thomaslevine.com/bar/
+
+> An interesting idea, but it conflicts somewhat with wanting symlinks to be
+> treated as the referenced file when it's safe to do so, which would be
+> great for [[todo/git-annex support]], and also good to avoid duplication
+> for files in system-wide underlays.
+>
+> Also, I don't think this is possible without help from the web server
+> configuration: for instance, under Apache, I believe the only way to get
+> an HTTP 302 redirect is via Apache-specific `.htaccess` files or
+> system-level Apache configuration.
+>
+> In current ikiwiki, you can get a broadly similar effect by either
+> using \[[!meta redir=foo]] (which does a HTML `<meta>` redirect)
+> or reconfiguring the web server. --[[smcv]]
+
+>> The CGI spec (http://www.ietf.org/rfc/rfc3875) says that a CGI can cause a redirect by returning a Location: header.
+>> So it's possible; desirable (due to your point about conflicting with git-annex support) is a different matter.
+
+>>> One of the major things that separates ikiwiki from other wiki software
+>>> is that ikiwiki is a wiki compiler: ordinary page-views are purely
+>>> static HTML, and the CGI only gets involved when you do something
+>>> that really has to be dynamic (like an edit).
+>>>
+>>> However, there is no server-independent static content that ikiwiki
+>>> could write out to the destdir that would result in that redirect.
+>>>
+>>> If you're OK with requiring the [[plugins/404]] plugin (and a
+>>> web server where it works, which I think still means Apache) then
+>>> it would be possible to write a plugin that detected symlinks,
+>>> stored them in the `%wikistate`, and used them to make the
+>>> [[plugins/404]] plugin (or its own hook similar to the one
+>>> in that plugin) do a 302 redirect instead of a 404.
+>>> Similarly, a plugin that assumed a suitable Apache
+>>> configuration with fairly broad `AllowOverrides`,
+>>> and wrote out `.htaccess` files, would be a feasible thing
+>>> for someone to write.
+>>>
+>>> I don't think this is a bug; I think it's a request for a
+>>> feature that not everyone will want. The solution to those
+>>> is for someone who wants the feature to
+>>> [[write a plugin|plugins/write]]. --[[smcv]]
index a454d7da5d6565fa4e475fca5cef8af1ff5e0c49..5a55fcce5b8977612b3e3f360cf6a59dbc8179ba 100644 (file)
@@ -5,7 +5,7 @@ I hope it's a bug, not a feature and you fix it soon :) --[[Paweł|ptecza]]
 
 > ikiwiki only allows a very limited set of characters raw in page names,
 > this is done as a deny-by-default security thing. All other characters
-> need to be encoded in __code__ format, where "code" is the character
+> need to be encoded in `__code__` format, where "code" is the character
 > number. This is normally done for you, but if you're adding a page
 > manually, you need to handle it yourself. --[[Joey]]
 
@@ -48,6 +48,11 @@ I hope it's a bug, not a feature and you fix it soon :) --[[Paweł|ptecza]]
 >>>>>> What's your locale? I have both pl\_PL (ISO-8859-2) and pl\_PL.UTF-8,
 >>>>>> but I use pl\_PL. Is it wrong? --[[Paweł|ptecza]]
 
+>>>>>>> IkiWiki assumes UTF-8 throughout, so escaped filename characters
+>>>>>>> should be `__x____y____z__` where x, y, z are the bytes of the
+>>>>>>> UTF-8 encoding of the character. I don't know how to achieve that
+>>>>>>> from a non-UTF-8 locale. --[[smcv]]
+
 >>>> Now, as to UTF7, in retrospect, using a standard encoding might be a
 >>>> better idea than coming up with my own encoding for filenames. Can 
 >>>> you provide a pointer to a description to modified-UTF7? --[[Joey]]
@@ -58,4 +63,38 @@ I hope it's a bug, not a feature and you fix it soon :) --[[Paweł|ptecza]]
 >>>>> There is a Perl [Unicode::IMAPUtf7](http://search.cpan.org/~fabpot/Unicode-IMAPUtf7-2.01/lib/Unicode/IMAPUtf7.pm)
 >>>>> module at the CPAN, but probably it hasn't been debianized yet :( --[[Paweł|ptecza]]
 
+> Note: [libencode-imaputf7-perl][1] has made it into debian.
+>
+>> "IMAP UTF-7" uses & as an escape character, which seems like a recipe
+>> for shell injection vulnerabilities... so I would not recommend it
+>> for this particular use. --[[smcv]]
+
+> I would value some clarification, in the ikiwiki setup file I have
+>
+>     wiki_file_chars: -[:alnum:][\p{Arabic}()]+/.:_
+>
+> Ikiwiki doesn't seem to produce any errors on the commandline for this, but
+> when I attempt to create a new post with Arabic characters from the web I get the following error :
+>
+>     Error: Cannot decode string with wide characters at /usr/lib/x86_64-linux-gnu/perl/5.20/Encode.pm line 215. 
+>
+> Should the modified regexp not be sufficient?
+> Ikiwiki 3.20140815.
+> --[[mhameed]]
+
+>> This seems like a bug: in principle non-ASCII in `wiki_file_chars` should work,
+>> in practice it does not. I would suggest either using the default
+>> `wiki_file_chars`, or digging into the code to find what is wrong.
+>> Solving this sort of bug usually requires having a clear picture of
+>> which "strings" are bytestrings, and which "strings" are Unicode. --[[smcv]]
+
+>>> mhameed confirmed on IRC that anarcat's [[patch]] from
+>>> [[bugs/garbled_non-ascii_characters_in_body_in_web_interface]] fixes this.
+>>> --[[smcv]]
+
+>>>> Merged that patch. Not marking this page as done, because the todo
+>>>> about using a standard encoding still stands (although I'm not at
+>>>> all sure there's an encoding that would be better). --[[smcv]]
+
 [[wishlist]]
+[1]: https://packages.debian.org/search?suite=all&section=all&arch=any&searchon=names&keywords=libencode-imaputf7-perl
index d8dd65921505b63a8f06f358a7de3e6110c7a410..a63e183e8523447165529ca587fd750641b9115c 100644 (file)
@@ -18,3 +18,5 @@ Unfortunately, Github shows [[raw code|https://github.com/paternal/ikiwiki/blob/
 >
 > This particular SVG [[looks good to me|users/smcv/ready]] and I've
 > mirrored it in my own git repo. --[[smcv]]
+
+>> [[merged|done]] --[[smcv]]
index d70a967a5b706845202121b0be77352c47924036..b61eb466c8d47ef839fc24e5d0ba54be3a9b23fa 100755 (executable)
@@ -158,15 +158,24 @@ class _IkiWikiExtPluginXMLRPCHandler(object):
     def send_rpc(self, cmd, in_fd, out_fd, *args, **kwargs):
         xml = _xmlrpc_client.dumps(sum(kwargs.items(), args), cmd)
         self._debug_fn(
-            "calling ikiwiki procedure `{0}': [{1}]".format(cmd, xml))
-        _IkiWikiExtPluginXMLRPCHandler._write(out_fd, xml.encode('utf8'))
+            "calling ikiwiki procedure `{0}': [{1}]".format(cmd, repr(xml)))
+        # ensure that encoded is a str (bytestring in Python 2, Unicode in 3)
+        if str is bytes and not isinstance(xml, str):
+            encoded = xml.encode('utf8')
+        else:
+            encoded = xml
+        _IkiWikiExtPluginXMLRPCHandler._write(out_fd, encoded)
 
         self._debug_fn('reading response from ikiwiki...')
 
-        xml = _IkiWikiExtPluginXMLRPCHandler._read(in_fd).decode('utf8')
+        response = _IkiWikiExtPluginXMLRPCHandler._read(in_fd)
+        if str is bytes and not isinstance(response, str):
+            xml = response.encode('utf8')
+        else:
+            xml = response
         self._debug_fn(
             'read response to procedure {0} from ikiwiki: [{1}]'.format(
-                cmd, xml))
+                cmd, repr(xml)))
         if xml is None:
             # ikiwiki is going down
             self._debug_fn('ikiwiki is going down, and so are we...')
diff --git a/t/img.t b/t/img.t
new file mode 100755 (executable)
index 0000000..9a48cb1
--- /dev/null
+++ b/t/img.t
@@ -0,0 +1,82 @@
+#!/usr/bin/perl
+#
+# unit test that creates test images (png, svg, multi-page pdf), runs ikiwiki
+# on them, checks the resulting images for plausibility based on their image
+# sizes, and checks if they vanish when not required in the build process any
+# more
+#
+# if you have trouble here, be aware that there are three debian packages that
+# can provide Image::Magick: perlmagick, libimage-magick-perl and
+# graphicsmagick-libmagick-dev-compat
+#
+package IkiWiki;
+
+use warnings;
+use strict;
+use Test::More;
+
+BEGIN { use_ok("IkiWiki"); }
+BEGIN { use_ok("Image::Magick"); }
+
+ok(! system("rm -rf t/tmp; mkdir -p t/tmp/in"));
+
+ok(! system("cp t/img/redsquare.png t/tmp/in/redsquare.png"));
+writefile("emptysquare.svg", "t/tmp/in", '<svg width="30" height="30"/>');
+# using different image sizes for different pages, so the pagenumber selection can be tested easily
+ok(! system("cp t/img/twopages.pdf t/tmp/in/twopages.pdf"));
+
+writefile("imgconversions.mdwn", "t/tmp/in", <<EOF
+[[!img redsquare.png]]
+[[!img redsquare.png size=10x]]
+[[!img redsquare.png size=30x50]] expecting 30x30
+[[!img emptysquare.svg size=10x]]
+[[!img twopages.pdf size=12x]]
+[[!img twopages.pdf size=16x pagenumber=1]]
+EOF
+);
+
+ok(! system("make -s ikiwiki.out"));
+
+my $command = "perl -I. ./ikiwiki.out -set usedirs=0 -plugin img t/tmp/in t/tmp/out -verbose";
+
+ok(! system($command));
+
+sub size($) {
+       my $filename = shift;
+       my $im = Image::Magick->new();
+       my $r = $im->Read($filename);
+       return "no image" if $r;
+       my $w = $im->Get("width");
+       my $h = $im->Get("height");
+       return "${w}x${h}";
+}
+
+my $outpath = "t/tmp/out/imgconversions";
+my $outhtml = readfile("$outpath.html");
+
+is(size("$outpath/10x-redsquare.png"), "10x10");
+ok(! -e "$outpath/30x-redsquare.png");
+ok($outhtml =~ /width="30" height="30".*expecting 30x30/);
+# if this fails, you need libmagickcore-6.q16-2-extra installed
+is(size("$outpath/10x-emptysquare.png"), "10x10");
+is(size("$outpath/12x-twopages.png"), "12x12");
+is(size("$outpath/16x-p1-twopages.png"), "16x2");
+
+# now let's remove them again
+
+if (1) { # for easier testing
+       writefile("imgconversions.mdwn", "t/tmp/in", "nothing to see here");
+
+       ok(! system("$command --refresh"));
+
+       ok(! -e "$outpath/10x-simple.png");
+       ok(! -e "$outpath/10x-simple-svg.png");
+       ok(! -e "$outpath/10x-simple-pdf.png");
+       ok(! -e "$outpath/10x-p1-simple-pdf.png");
+
+       # cleanup
+       ok(! system("rm -rf t/tmp"));
+}
+done_testing;
+
+1;
diff --git a/t/img/redsquare.png b/t/img/redsquare.png
new file mode 100644 (file)
index 0000000..0033932
Binary files /dev/null and b/t/img/redsquare.png differ
diff --git a/t/img/twopages.pdf b/t/img/twopages.pdf
new file mode 100644 (file)
index 0000000..8be9b65
Binary files /dev/null and b/t/img/twopages.pdf differ
diff --git a/t/inline.t b/t/inline.t
new file mode 100755 (executable)
index 0000000..726227b
--- /dev/null
@@ -0,0 +1,68 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More;
+use IkiWiki;
+
+my $blob;
+
+ok(! system("rm -rf t/tmp"));
+ok(! system("mkdir t/tmp"));
+
+sub write_old_file {
+       my $name = shift;
+       my $content = shift;
+
+       writefile($name, "t/tmp/in", $content);
+       ok(utime(333333333, 333333333, "t/tmp/in/$name"));
+}
+
+write_old_file("protagonists.mdwn",
+       '[[!inline pages="protagonists/*" rootpage="protagonists/new"]]');
+write_old_file("friends.mdwn",
+       '[[!inline pages="friends/*" postform=yes sort=title show=2]]');
+write_old_file("antagonists.mdwn",
+       '[[!inline pages="antagonists/*"]]');
+write_old_file("enemies.mdwn",
+       '[[!inline pages="enemies/*" postform=no rootpage=enemies sort=title reverse=yes show=2]]');
+foreach my $page (qw(protagonists/shepard protagonists/link
+               antagonists/saren antagonists/ganondorf
+               friends/garrus friends/liara friends/midna friends/telma
+               enemies/benezia enemies/geth enemies/rachni
+               enemies/zant)) {
+       write_old_file("$page.mdwn", "this page is {$page}");
+}
+
+ok(! system("make -s ikiwiki.out"));
+
+my $command = "perl -I. ./ikiwiki.out -set usedirs=0 -plugin inline -url=http://example.com -cgiurl=http://example.com/ikiwiki.cgi -rss -atom -underlaydir=underlays/basewiki -set underlaydirbase=underlays -templatedir=templates t/tmp/in t/tmp/out -verbose";
+
+ok(! system($command));
+
+ok(! system("$command -refresh"));
+
+$blob = readfile("t/tmp/out/protagonists.html");
+like($blob, qr{Add a new post}, 'rootpage=yes gives postform');
+like($blob, qr{<input type="hidden" name="from" value="protagonists/new"},
+       'explicit rootpage is /protagonists/new');
+
+$blob = readfile("t/tmp/out/friends.html");
+like($blob, qr{Add a new post}, 'postform=yes forces postform');
+like($blob, qr{<input type="hidden" name="from" value="friends"},
+       'implicit rootpage is /friends');
+like($blob, qr[this page is {friends/garrus}.*this page is {friends/liara}]s,
+       'first two pages in desired sort order are present');
+unlike($blob, qr{friends/(?:midna|telma)},
+       'pages excluded by show should not be present');
+
+$blob = readfile("t/tmp/out/antagonists.html");
+unlike($blob, qr{Add a new post}, 'default is no postform');
+
+$blob = readfile("t/tmp/out/enemies.html");
+unlike($blob, qr{Add a new post}, 'postform=no forces no postform');
+like($blob, qr[this page is {enemies/zant}.*this page is {enemies/rachni}]s,
+       'first two pages in reversed sort order are present');
+unlike($blob, qr{enemies/(?:benezia|geth)},
+       'pages excluded by show should not be present');
+
+done_testing;
diff --git a/t/rst.t b/t/rst.t
index 4e0c4b74775842cc930aca7c63dd501a34993e64..a72c4681cbf3bd0e13817c730338761a5537e7b8 100755 (executable)
--- a/t/rst.t
+++ b/t/rst.t
@@ -8,7 +8,7 @@ BEGIN {
        }
 }
 
-use Test::More tests => 2;
+use Test::More tests => 3;
 
 BEGIN { use_ok("IkiWiki"); }
 
@@ -19,4 +19,8 @@ $config{add_plugins}=[qw(rst)];
 IkiWiki::loadplugins();
 IkiWiki::checkconfig();
 
-ok(IkiWiki::htmlize("foo", "foo", "rst", "foo\n") =~ m{\s*<p>foo</p>\s*});
+like(IkiWiki::htmlize("foo", "foo", "rst", "foo\n"), qr{\s*<p>foo</p>\s*});
+# regression test for [[bugs/rst fails on file containing only a number]]
+my $html = IkiWiki::htmlize("foo", "foo", "rst", "11");
+$html =~ s/<[^>]*>//g;
+like($html, qr{\s*11\s*});