tagging version 1.33.2 etch
authorjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>
Wed, 21 Mar 2007 06:55:41 +0000 (06:55 +0000)
committerjoey <joey@0fa5a96a-9a0e-0410-b3b2-a0fd24251071>
Wed, 21 Mar 2007 06:55:41 +0000 (06:55 +0000)
346 files changed:
1.33.2/CHANGELOG [new symlink]
1.33.2/IkiWiki.pm [new file with mode: 0644]
1.33.2/IkiWiki/CGI.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/aggregate.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/brokenlinks.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/camelcase.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/ddate.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/favicon.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/fortune.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/googlecalendar.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/haiku.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/html.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/htmlscrubber.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/htmltidy.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/img.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/inline.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/linkmap.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/map.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/mdwn.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/meta.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/orphans.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/otl.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/pagecount.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/pagestats.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/polygen.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/rst.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/search.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/shortcut.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/sidebar.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/skeleton.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/smiley.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/tag.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/template.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/toc.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/typography.pm [new file with mode: 0644]
1.33.2/IkiWiki/Plugin/wikitext.pm [new file with mode: 0644]
1.33.2/IkiWiki/Rcs/Stub.pm [new file with mode: 0644]
1.33.2/IkiWiki/Rcs/git.pm [new file with mode: 0644]
1.33.2/IkiWiki/Rcs/mercurial.pm [new file with mode: 0644]
1.33.2/IkiWiki/Rcs/svn.pm [new file with mode: 0644]
1.33.2/IkiWiki/Rcs/tla.pm [new file with mode: 0644]
1.33.2/IkiWiki/Render.pm [new file with mode: 0644]
1.33.2/IkiWiki/Setup.pm [new file with mode: 0644]
1.33.2/IkiWiki/Setup/Standard.pm [new file with mode: 0644]
1.33.2/IkiWiki/UserInfo.pm [new file with mode: 0644]
1.33.2/IkiWiki/Wrapper.pm [new file with mode: 0644]
1.33.2/Makefile.PL [new file with mode: 0755]
1.33.2/NEWS [new symlink]
1.33.2/README [new file with mode: 0644]
1.33.2/basewiki/blog.mdwn [new file with mode: 0644]
1.33.2/basewiki/favicon.ico [new file with mode: 0644]
1.33.2/basewiki/helponformatting.mdwn [new file with mode: 0644]
1.33.2/basewiki/index.mdwn [new file with mode: 0644]
1.33.2/basewiki/local.css [new file with mode: 0644]
1.33.2/basewiki/markdown.mdwn [new file with mode: 0644]
1.33.2/basewiki/pagespec.mdwn [new file with mode: 0644]
1.33.2/basewiki/preprocessordirective.mdwn [new file with mode: 0644]
1.33.2/basewiki/sandbox.mdwn [new file with mode: 0644]
1.33.2/basewiki/shortcuts.mdwn [new file with mode: 0644]
1.33.2/basewiki/smileys.mdwn [new file with mode: 0644]
1.33.2/basewiki/smileys/alert.png [new file with mode: 0644]
1.33.2/basewiki/smileys/angry.png [new file with mode: 0644]
1.33.2/basewiki/smileys/attention.png [new file with mode: 0644]
1.33.2/basewiki/smileys/biggrin.png [new file with mode: 0644]
1.33.2/basewiki/smileys/checkmark.png [new file with mode: 0644]
1.33.2/basewiki/smileys/devil.png [new file with mode: 0644]
1.33.2/basewiki/smileys/frown.png [new file with mode: 0644]
1.33.2/basewiki/smileys/icon-error.png [new file with mode: 0644]
1.33.2/basewiki/smileys/icon-info.png [new file with mode: 0644]
1.33.2/basewiki/smileys/idea.png [new file with mode: 0644]
1.33.2/basewiki/smileys/ohwell.png [new file with mode: 0644]
1.33.2/basewiki/smileys/redface.png [new file with mode: 0644]
1.33.2/basewiki/smileys/sad.png [new file with mode: 0644]
1.33.2/basewiki/smileys/smile.png [new file with mode: 0644]
1.33.2/basewiki/smileys/smile2.png [new file with mode: 0644]
1.33.2/basewiki/smileys/smile3.png [new file with mode: 0644]
1.33.2/basewiki/smileys/smile4.png [new file with mode: 0644]
1.33.2/basewiki/smileys/star_off.png [new file with mode: 0644]
1.33.2/basewiki/smileys/star_on.png [new file with mode: 0644]
1.33.2/basewiki/smileys/thumbs-up.png [new file with mode: 0644]
1.33.2/basewiki/smileys/tired.png [new file with mode: 0644]
1.33.2/basewiki/smileys/tongue.png [new file with mode: 0644]
1.33.2/basewiki/style.css [new file with mode: 0644]
1.33.2/basewiki/subpage.mdwn [new file with mode: 0644]
1.33.2/basewiki/subpage/linkingrules.mdwn [new file with mode: 0644]
1.33.2/basewiki/wikiicons/diff.png [new file with mode: 0644]
1.33.2/basewiki/wikilink.mdwn [new file with mode: 0644]
1.33.2/debian/NEWS [new file with mode: 0644]
1.33.2/debian/README.Debian [new file with mode: 0644]
1.33.2/debian/changelog [new file with mode: 0644]
1.33.2/debian/compat [new file with mode: 0644]
1.33.2/debian/control [new file with mode: 0644]
1.33.2/debian/copyright [new file with mode: 0644]
1.33.2/debian/postinst [new file with mode: 0755]
1.33.2/debian/preinst [new file with mode: 0755]
1.33.2/debian/rules [new file with mode: 0755]
1.33.2/doc/BSD [new file with mode: 0644]
1.33.2/doc/GPL [new file with mode: 0644]
1.33.2/doc/about_rcs_backends.mdwn [new file with mode: 0644]
1.33.2/doc/backlinks.mdwn [new file with mode: 0644]
1.33.2/doc/bugs.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/404_when_cancel_create_page.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/Disappearing_Pages.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/PREFIX_not_honoured_for_underlaydir.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/Problems_using_cygwin.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/bestlink_change_update_issue.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/broken_parentlinks.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/diff_links_to_backtrace.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/done.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/formbuilder_3.0401_broken.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/helponformatting_link_disappears.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/html_errors.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/inline_page_not_updated_on_removal.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/markdown_module_location.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/meta_inline.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/pruning_is_too_strict.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/rss_feed_cleanup_on_delete.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/rss_output_relative_links.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/svn+ssh_commit_fail.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/svn_post-commit_wrapper_can__39__t_find_IkiWiki.pm_if_not_installed.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/tags_base_dir_not_used_when_creating_new_tags.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/underlaydir_file_expose.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/utf8_html_templates.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/utf8_svn_log.mdwn [new file with mode: 0644]
1.33.2/doc/bugs/word_wrap.mdwn [new file with mode: 0644]
1.33.2/doc/cgi.mdwn [new file with mode: 0644]
1.33.2/doc/commit-internals.mdwn [new file with mode: 0644]
1.33.2/doc/css.mdwn [new file with mode: 0644]
1.33.2/doc/css_market.mdwn [new file with mode: 0644]
1.33.2/doc/css_market/kirkambar.css [new file with mode: 0644]
1.33.2/doc/css_market/zack.css [new file with mode: 0644]
1.33.2/doc/download.mdwn [new file with mode: 0644]
1.33.2/doc/examples.mdwn [new file with mode: 0644]
1.33.2/doc/examples/blog.mdwn [new file with mode: 0644]
1.33.2/doc/examples/blog/index.mdwn [new file with mode: 0644]
1.33.2/doc/examples/blog/posts.mdwn [new file with mode: 0644]
1.33.2/doc/examples/blog/posts/first_post.mdwn [new file with mode: 0644]
1.33.2/doc/examples/blog/sidebar.mdwn [new file with mode: 0644]
1.33.2/doc/examples/blog/tags.mdwn [new file with mode: 0644]
1.33.2/doc/examples/blog/tags/life.mdwn [new file with mode: 0644]
1.33.2/doc/examples/blog/tags/tech.mdwn [new file with mode: 0644]
1.33.2/doc/features.mdwn [new file with mode: 0644]
1.33.2/doc/freesoftware.mdwn [new file with mode: 0644]
1.33.2/doc/git.mdwn [new file with mode: 0644]
1.33.2/doc/hyperestraier.mdwn [new file with mode: 0644]
1.33.2/doc/ikiwiki-mass-rebuild.mdwn [new file with mode: 0644]
1.33.2/doc/ikiwiki.setup [new file with mode: 0644]
1.33.2/doc/ikiwikiusers.mdwn [new file with mode: 0644]
1.33.2/doc/index.mdwn [new file with mode: 0644]
1.33.2/doc/index/discussion.mdwn [new file with mode: 0644]
1.33.2/doc/install.mdwn [new file with mode: 0644]
1.33.2/doc/joey.mdwn [new file with mode: 0644]
1.33.2/doc/jonassmedegaard.mdwn [new file with mode: 0644]
1.33.2/doc/logo.mdwn [new file with mode: 0644]
1.33.2/doc/logo/discussion.mdwn [new file with mode: 0644]
1.33.2/doc/logo/ikiwiki.png [new file with mode: 0644]
1.33.2/doc/logo/ikiwiki.svgz [new file with mode: 0644]
1.33.2/doc/logo/ikiwiki_button.png [new file with mode: 0644]
1.33.2/doc/logo/ikiwiki_large.png [new file with mode: 0644]
1.33.2/doc/logo/ikiwiki_old.png [new file with mode: 0644]
1.33.2/doc/logo/ikiwiki_old2.png [new file with mode: 0644]
1.33.2/doc/logo/ikiwiki_old2.svgz [new file with mode: 0644]
1.33.2/doc/mercurial.mdwn [new file with mode: 0644]
1.33.2/doc/news.mdwn [new file with mode: 0644]
1.33.2/doc/news/seeking_article_writer.mdwn [new file with mode: 0644]
1.33.2/doc/news/seeking_article_writer/discussion.mdwn [new file with mode: 0644]
1.33.2/doc/news/stylesheets.mdwn [new file with mode: 0644]
1.33.2/doc/news/svn_move.mdwn [new file with mode: 0644]
1.33.2/doc/news/version_1.30.mdwn [new file with mode: 0644]
1.33.2/doc/news/version_1.31.mdwn [new file with mode: 0644]
1.33.2/doc/news/version_1.32.mdwn [new file with mode: 0644]
1.33.2/doc/pagehistory.mdwn [new file with mode: 0644]
1.33.2/doc/patchqueue.mdwn [new file with mode: 0644]
1.33.2/doc/patchqueue/index.html_allowed.mdwn [new file with mode: 0644]
1.33.2/doc/patchqueue/index.html_allowed/discussion.mdwn [new file with mode: 0644]
1.33.2/doc/patchqueue/l10n.mdwn [new file with mode: 0644]
1.33.2/doc/patchqueue/pruning_is_too_strict.mdwn [new file with mode: 0644]
1.33.2/doc/patchqueue/various_fixes.mdwn [new file with mode: 0644]
1.33.2/doc/plugins.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/aggregate.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/brokenlinks.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/camelcase.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/contrib.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/contrib/googlemaps.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/contrib/googlemaps/discussion.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/contrib/img.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/contrib/img/discussion.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/contrib/linguas.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/contrib/syntax.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/contrib/syntax/discussion.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/ddate.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/favicon.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/fortune.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/googlecalendar.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/haiku.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/html.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/htmlscrubber.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/htmltidy.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/img.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/inline.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/linkmap.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/map.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/mdwn.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/meta.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/orphans.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/otl.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/pagecount.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/pagestats.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/polygen.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/rst.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/search.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/shortcut.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/sidebar.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/smiley.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/tag.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/template.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/toc.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/type/chrome.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/type/core.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/type/format.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/type/fun.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/type/html.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/type/link.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/type/meta.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/type/slow.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/type/special-purpose.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/type/tags.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/type/useful.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/typography.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/wikitext.mdwn [new file with mode: 0644]
1.33.2/doc/plugins/write.mdwn [new file with mode: 0644]
1.33.2/doc/post-commit.mdwn [new file with mode: 0644]
1.33.2/doc/recentchanges.mdwn [new file with mode: 0644]
1.33.2/doc/roadmap.mdwn [new file with mode: 0644]
1.33.2/doc/sandbox.mdwn [new file with mode: 0644]
1.33.2/doc/sandbox/foo.wiki [new file with mode: 0644]
1.33.2/doc/sandbox/just_another_test.mdwn [new file with mode: 0644]
1.33.2/doc/sandbox/my_blog_entry.mdwn [new file with mode: 0644]
1.33.2/doc/sandbox/test.mdwn [new file with mode: 0644]
1.33.2/doc/sandbox/testtest.mdwn [new file with mode: 0644]
1.33.2/doc/sandbox/yes.mdwn [new file with mode: 0644]
1.33.2/doc/security.mdwn [new file with mode: 0644]
1.33.2/doc/setup.mdwn [new file with mode: 0644]
1.33.2/doc/smileys.mdwn [new file with mode: 0644]
1.33.2/doc/subversion.mdwn [new file with mode: 0644]
1.33.2/doc/tags.mdwn [new file with mode: 0644]
1.33.2/doc/templates.mdwn [new file with mode: 0644]
1.33.2/doc/templates/note.mdwn [new file with mode: 0644]
1.33.2/doc/templates/plugin.mdwn [new file with mode: 0644]
1.33.2/doc/tla.mdwn [new file with mode: 0644]
1.33.2/doc/todo.mdwn [new file with mode: 0644]
1.33.2/doc/todo/Case.mdwn [new file with mode: 0644]
1.33.2/doc/todo/Moving_Pages.mdwn [new file with mode: 0644]
1.33.2/doc/todo/Option_to_make_title_an_h1__63__.mdwn [new file with mode: 0644]
1.33.2/doc/todo/RSS_links.mdwn [new file with mode: 0644]
1.33.2/doc/todo/adding_new_pages_by_using_the_web_interface.mdwn [new file with mode: 0644]
1.33.2/doc/todo/aggregation.mdwn [new file with mode: 0644]
1.33.2/doc/todo/automatic_rebuilding_of_html_pages.mdwn [new file with mode: 0644]
1.33.2/doc/todo/automatic_use_of_syntax_plugin_on_source_code_files.mdwn [new file with mode: 0644]
1.33.2/doc/todo/blogging.mdwn [new file with mode: 0644]
1.33.2/doc/todo/blogs.mdwn [new file with mode: 0644]
1.33.2/doc/todo/discussion_page_as_blog.mdwn [new file with mode: 0644]
1.33.2/doc/todo/done.mdwn [new file with mode: 0644]
1.33.2/doc/todo/firm_up_plugin_interface.mdwn [new file with mode: 0644]
1.33.2/doc/todo/html.mdwn [new file with mode: 0644]
1.33.2/doc/todo/htmlvalidation.mdwn [new file with mode: 0644]
1.33.2/doc/todo/improve_globlists.mdwn [new file with mode: 0644]
1.33.2/doc/todo/link_map.mdwn [new file with mode: 0644]
1.33.2/doc/todo/linkify_and_preprocessor_ordering.mdwn [new file with mode: 0644]
1.33.2/doc/todo/lists.mdwn [new file with mode: 0644]
1.33.2/doc/todo/logo.mdwn [new file with mode: 0644]
1.33.2/doc/todo/mailnotification.mdwn [new file with mode: 0644]
1.33.2/doc/todo/mercurial.mdwn [new file with mode: 0644]
1.33.2/doc/todo/metadata.mdwn [new file with mode: 0644]
1.33.2/doc/todo/multiple_templates.mdwn [new file with mode: 0644]
1.33.2/doc/todo/onlinepageediting.mdwn [new file with mode: 0644]
1.33.2/doc/todo/onlinepageediting/discussion.mdwn [new file with mode: 0644]
1.33.2/doc/todo/optimisations.mdwn [new file with mode: 0644]
1.33.2/doc/todo/pageindexes.mdwn [new file with mode: 0644]
1.33.2/doc/todo/pluggablerenderers.mdwn [new file with mode: 0644]
1.33.2/doc/todo/plugin.mdwn [new file with mode: 0644]
1.33.2/doc/todo/plugin_data_storage.mdwn [new file with mode: 0644]
1.33.2/doc/todo/plugin_dependency_calulation.mdwn [new file with mode: 0644]
1.33.2/doc/todo/recentchanges.mdwn [new file with mode: 0644]
1.33.2/doc/todo/rss_title_description.mdwn [new file with mode: 0644]
1.33.2/doc/todo/search.mdwn [new file with mode: 0644]
1.33.2/doc/todo/sigs.mdwn [new file with mode: 0644]
1.33.2/doc/todo/skip_option_for_inline_plugin.mdwn [new file with mode: 0644]
1.33.2/doc/todo/spam_fighting.mdwn [new file with mode: 0644]
1.33.2/doc/todo/spell_check_plug-in.mdwn [new file with mode: 0644]
1.33.2/doc/todo/strftime.mdwn [new file with mode: 0644]
1.33.2/doc/todo/tagging_with_a_publication_date.mdwn [new file with mode: 0644]
1.33.2/doc/todo/tags.mdwn [new file with mode: 0644]
1.33.2/doc/todo/terminalclient.mdwn [new file with mode: 0644]
1.33.2/doc/todo/tla.mdwn [new file with mode: 0644]
1.33.2/doc/todo/toplevel_index.mdwn [new file with mode: 0644]
1.33.2/doc/todo/underlay.mdwn [new file with mode: 0644]
1.33.2/doc/todo/upgradehooks.mdwn [new file with mode: 0644]
1.33.2/doc/todo/utf8.mdwn [new file with mode: 0644]
1.33.2/doc/todo/wiki-formatted_comments_with_syntax_plugin.mdwn [new file with mode: 0644]
1.33.2/doc/todo/wikilinkfeatures.mdwn [new file with mode: 0644]
1.33.2/doc/usage.mdwn [new file with mode: 0644]
1.33.2/doc/w3mmode.mdwn [new file with mode: 0644]
1.33.2/doc/w3mmode/ikiwiki.setup [new file with mode: 0644]
1.33.2/doc/whyikiwiki.mdwn [new file with mode: 0644]
1.33.2/ikiwiki-mass-rebuild [new file with mode: 0755]
1.33.2/ikiwiki-w3m.cgi [new file with mode: 0755]
1.33.2/ikiwiki.pl [new file with mode: 0755]
1.33.2/mdwn2man [new file with mode: 0755]
1.33.2/pm_filter [new file with mode: 0755]
1.33.2/t/basename.t [new file with mode: 0755]
1.33.2/t/bestlink.t [new file with mode: 0755]
1.33.2/t/crazy-badass-perl-bug.t [new file with mode: 0755]
1.33.2/t/dirname.t [new file with mode: 0755]
1.33.2/t/html.t [new file with mode: 0755]
1.33.2/t/htmlize.t [new file with mode: 0755]
1.33.2/t/linkify.t [new file with mode: 0755]
1.33.2/t/pagename.t [new file with mode: 0755]
1.33.2/t/pagespec_match.t [new file with mode: 0755]
1.33.2/t/pagespec_merge.t [new file with mode: 0755]
1.33.2/t/pagetitle.t [new file with mode: 0755]
1.33.2/t/pagetype.mdwn [new file with mode: 0755]
1.33.2/t/readfile.t [new file with mode: 0755]
1.33.2/t/syntax.t [new file with mode: 0755]
1.33.2/t/test1.mdwn [new file with mode: 0644]
1.33.2/t/test2.mdwn [new file with mode: 0644]
1.33.2/t/test3.mdwn [new file with mode: 0644]
1.33.2/t/titlepage.t [new file with mode: 0755]
1.33.2/templates/aggregatepost.tmpl [new file with mode: 0644]
1.33.2/templates/atomitem.tmpl [new file with mode: 0644]
1.33.2/templates/atompage.tmpl [new file with mode: 0644]
1.33.2/templates/blogpost.tmpl [new file with mode: 0644]
1.33.2/templates/editpage.tmpl [new file with mode: 0644]
1.33.2/templates/estseek.conf [new file with mode: 0644]
1.33.2/templates/feedlink.tmpl [new file with mode: 0644]
1.33.2/templates/inlinepage.tmpl [new file with mode: 0644]
1.33.2/templates/inlinepagetitle.tmpl [new file with mode: 0644]
1.33.2/templates/misc.tmpl [new file with mode: 0644]
1.33.2/templates/notifymail.tmpl [new file with mode: 0644]
1.33.2/templates/page.tmpl [new file with mode: 0644]
1.33.2/templates/passwordmail.tmpl [new file with mode: 0644]
1.33.2/templates/recentchanges.tmpl [new file with mode: 0644]
1.33.2/templates/rssitem.tmpl [new file with mode: 0644]
1.33.2/templates/rsspage.tmpl [new file with mode: 0644]
1.33.2/templates/searchform.tmpl [new file with mode: 0644]
1.33.2/wikilist [new file with mode: 0644]

diff --git a/1.33.2/CHANGELOG b/1.33.2/CHANGELOG
new file mode 120000 (symlink)
index 0000000..d526672
--- /dev/null
@@ -0,0 +1 @@
+debian/changelog
\ No newline at end of file
diff --git a/1.33.2/IkiWiki.pm b/1.33.2/IkiWiki.pm
new file mode 100644 (file)
index 0000000..efacb20
--- /dev/null
@@ -0,0 +1,841 @@
+#!/usr/bin/perl
+
+package IkiWiki;
+use warnings;
+use strict;
+use Encode;
+use HTML::Entities;
+use open qw{:utf8 :std};
+
+use vars qw{%config %links %oldlinks %oldpagemtime %pagectime %pagecase
+            %renderedfiles %oldrenderedfiles %pagesources %depends %hooks
+           %forcerebuild};
+
+use Exporter q{import};
+our @EXPORT = qw(hook debug error template htmlpage add_depends pagespec_match
+                 bestlink htmllink readfile writefile pagetype srcfile pagename
+                 displaytime will_render
+                 %config %links %renderedfiles %pagesources);
+our $VERSION = 1.01; # plugin interface version
+
+# Optimisation.
+use Memoize;
+memoize("abs2rel");
+memoize("pagespec_translate");
+
+my $installdir=''; # INSTALLDIR_AUTOREPLACE done by Makefile, DNE
+our $version='unknown'; # VERSION_AUTOREPLACE done by Makefile, DNE
+
+sub defaultconfig () { #{{{
+       wiki_file_prune_regexp => qr{((^|/).svn/|\.\.|^\.|\/\.|\.x?html?$|\.rss$|\.atom$|.arch-ids/|{arch}/)},
+       wiki_link_regexp => qr/\[\[(?:([^\]\|]+)\|)?([^\s\]]+)\]\]/,
+       wiki_file_regexp => qr/(^[-[:alnum:]_.:\/+]+$)/,
+       verbose => 0,
+       syslog => 0,
+       wikiname => "wiki",
+       default_pageext => "mdwn",
+       cgi => 0,
+       rcs => 'svn',
+       notify => 0,
+       url => '',
+       cgiurl => '',
+       historyurl => '',
+       diffurl => '',
+       anonok => 0,
+       rss => 0,
+       atom => 0,
+       discussion => 1,
+       rebuild => 0,
+       refresh => 0,
+       getctime => 0,
+       w3mmode => 0,
+       wrapper => undef,
+       wrappermode => undef,
+       svnrepo => undef,
+       svnpath => "trunk",
+       srcdir => undef,
+       destdir => undef,
+       pingurl => [],
+       templatedir => "$installdir/share/ikiwiki/templates",
+       underlaydir => "$installdir/share/ikiwiki/basewiki",
+       setup => undef,
+       adminuser => undef,
+       adminemail => undef,
+       plugin => [qw{mdwn inline htmlscrubber}],
+       timeformat => '%c',
+       locale => undef,
+       sslcookie => 0,
+       httpauth => 0,
+} #}}}
+   
+sub checkconfig () { #{{{
+       # locale stuff; avoid LC_ALL since it overrides everything
+       if (defined $ENV{LC_ALL}) {
+               $ENV{LANG} = $ENV{LC_ALL};
+               delete $ENV{LC_ALL};
+       }
+       if (defined $config{locale}) {
+               eval q{use POSIX};
+               error($@) if $@;
+               $ENV{LANG} = $config{locale}
+                       if POSIX::setlocale(&POSIX::LC_TIME, $config{locale});
+       }
+
+       if ($config{w3mmode}) {
+               eval q{use Cwd q{abs_path}};
+               error($@) if $@;
+               $config{srcdir}=possibly_foolish_untaint(abs_path($config{srcdir}));
+               $config{destdir}=possibly_foolish_untaint(abs_path($config{destdir}));
+               $config{cgiurl}="file:///\$LIB/ikiwiki-w3m.cgi/".$config{cgiurl}
+                       unless $config{cgiurl} =~ m!file:///!;
+               $config{url}="file://".$config{destdir};
+       }
+
+       if ($config{cgi} && ! length $config{url}) {
+               error("Must specify url to wiki with --url when using --cgi\n");
+       }
+       if (($config{rss} || $config{atom}) && ! length $config{url}) {
+               error("Must specify url to wiki with --url when using --rss or --atom\n");
+       }
+       
+       $config{wikistatedir}="$config{srcdir}/.ikiwiki"
+               unless exists $config{wikistatedir};
+       
+       if ($config{rcs}) {
+               eval qq{require IkiWiki::Rcs::$config{rcs}};
+               if ($@) {
+                       error("Failed to load RCS module IkiWiki::Rcs::$config{rcs}: $@");
+               }
+       }
+       else {
+               require IkiWiki::Rcs::Stub;
+       }
+
+       run_hooks(checkconfig => sub { shift->() });
+} #}}}
+
+sub loadplugins () { #{{{
+       foreach my $plugin (@{$config{plugin}}) {
+               my $mod="IkiWiki::Plugin::".possibly_foolish_untaint($plugin);
+               eval qq{use $mod};
+               if ($@) {
+                       error("Failed to load plugin $mod: $@");
+               }
+       }
+       run_hooks(getopt => sub { shift->() });
+       if (grep /^-/, @ARGV) {
+               print STDERR "Unknown option: $_\n"
+                       foreach grep /^-/, @ARGV;
+               usage();
+       }
+} #}}}
+
+sub error ($) { #{{{
+       if ($config{cgi}) {
+               print "Content-type: text/html\n\n";
+               print misctemplate("Error", "<p>Error: @_</p>");
+       }
+       log_message(error => @_);
+       exit(1);
+} #}}}
+
+sub debug ($) { #{{{
+       return unless $config{verbose};
+       log_message(debug => @_);
+} #}}}
+
+my $log_open=0;
+sub log_message ($$) { #{{{
+       my $type=shift;
+
+       if ($config{syslog}) {
+               require Sys::Syslog;
+               unless ($log_open) {
+                       Sys::Syslog::setlogsock('unix');
+                       Sys::Syslog::openlog('ikiwiki', '', 'user');
+                       $log_open=1;
+               }
+               eval {
+                       Sys::Syslog::syslog($type, join(" ", @_));
+               }
+       }
+       elsif (! $config{cgi}) {
+               print "@_\n";
+       }
+       else {
+               print STDERR "@_\n";
+       }
+} #}}}
+
+sub possibly_foolish_untaint ($) { #{{{
+       my $tainted=shift;
+       my ($untainted)=$tainted=~/(.*)/;
+       return $untainted;
+} #}}}
+
+sub basename ($) { #{{{
+       my $file=shift;
+
+       $file=~s!.*/+!!;
+       return $file;
+} #}}}
+
+sub dirname ($) { #{{{
+       my $file=shift;
+
+       $file=~s!/*[^/]+$!!;
+       return $file;
+} #}}}
+
+sub pagetype ($) { #{{{
+       my $page=shift;
+       
+       if ($page =~ /\.([^.]+)$/) {
+               return $1 if exists $hooks{htmlize}{$1};
+       }
+       return undef;
+} #}}}
+
+sub pagename ($) { #{{{
+       my $file=shift;
+
+       my $type=pagetype($file);
+       my $page=$file;
+       $page=~s/\Q.$type\E*$// if defined $type;
+       return $page;
+} #}}}
+
+sub htmlpage ($) { #{{{
+       my $page=shift;
+
+       return $page.".html";
+} #}}}
+
+sub srcfile ($) { #{{{
+       my $file=shift;
+
+       return "$config{srcdir}/$file" if -e "$config{srcdir}/$file";
+       return "$config{underlaydir}/$file" if -e "$config{underlaydir}/$file";
+       error("internal error: $file cannot be found");
+} #}}}
+
+sub readfile ($;$) { #{{{
+       my $file=shift;
+       my $binary=shift;
+
+       if (-l $file) {
+               error("cannot read a symlink ($file)");
+       }
+       
+       local $/=undef;
+       open (IN, $file) || error("failed to read $file: $!");
+       binmode(IN) if ($binary);
+       my $ret=<IN>;
+       close IN;
+       return $ret;
+} #}}}
+
+sub writefile ($$$;$) { #{{{
+       my $file=shift; # can include subdirs
+       my $destdir=shift; # directory to put file in
+       my $content=shift;
+       my $binary=shift;
+       
+       my $test=$file;
+       while (length $test) {
+               if (-l "$destdir/$test") {
+                       error("cannot write to a symlink ($test)");
+               }
+               $test=dirname($test);
+       }
+
+       my $dir=dirname("$destdir/$file");
+       if (! -d $dir) {
+               my $d="";
+               foreach my $s (split(m!/+!, $dir)) {
+                       $d.="$s/";
+                       if (! -d $d) {
+                               mkdir($d) || error("failed to create directory $d: $!");
+                       }
+               }
+       }
+       
+       open (OUT, ">$destdir/$file") || error("failed to write $destdir/$file: $!");
+       binmode(OUT) if ($binary);
+       print OUT $content;
+       close OUT;
+} #}}}
+
+my %cleared;
+sub will_render ($$;$) { #{{{
+       my $page=shift;
+       my $dest=shift;
+       my $clear=shift;
+
+       # Important security check.
+       if (-e "$config{destdir}/$dest" && ! $config{rebuild} &&
+           ! grep { $_ eq $dest } (@{$renderedfiles{$page}}, @{$oldrenderedfiles{$page}})) {
+               error("$config{destdir}/$dest independently created, not overwriting with version from $page");
+       }
+
+       if (! $clear || $cleared{$page}) {
+               $renderedfiles{$page}=[$dest, grep { $_ ne $dest } @{$renderedfiles{$page}}];
+       }
+       else {
+               $renderedfiles{$page}=[$dest];
+               $cleared{$page}=1;
+       }
+} #}}}
+
+sub bestlink ($$) { #{{{
+       my $page=shift;
+       my $link=shift;
+       
+       my $cwd=$page;
+       do {
+               my $l=$cwd;
+               $l.="/" if length $l;
+               $l.=$link;
+
+               if (exists $links{$l}) {
+                       return $l;
+               }
+               elsif (exists $pagecase{lc $l}) {
+                       return $pagecase{lc $l};
+               }
+       } while $cwd=~s!/?[^/]+$!!;
+
+       #print STDERR "warning: page $page, broken link: $link\n";
+       return "";
+} #}}}
+
+sub isinlinableimage ($) { #{{{
+       my $file=shift;
+       
+       $file=~/\.(png|gif|jpg|jpeg)$/i;
+} #}}}
+
+sub pagetitle ($) { #{{{
+       my $page=shift;
+       $page=~s/__(\d+)__/&#$1;/g;
+       $page=~y/_/ /;
+       return $page;
+} #}}}
+
+sub titlepage ($) { #{{{
+       my $title=shift;
+       $title=~y/ /_/;
+       $title=~s/([^-[:alnum:]_:+\/.])/"__".ord($1)."__"/eg;
+       return $title;
+} #}}}
+
+sub cgiurl (@) { #{{{
+       my %params=@_;
+
+       return $config{cgiurl}."?".join("&amp;", map "$_=$params{$_}", keys %params);
+} #}}}
+
+sub baseurl (;$) { #{{{
+       my $page=shift;
+
+       return "$config{url}/" if ! defined $page;
+       
+       $page=~s/[^\/]+$//;
+       $page=~s/[^\/]+\//..\//g;
+       return $page;
+} #}}}
+
+sub abs2rel ($$) { #{{{
+       # Work around very innefficient behavior in File::Spec if abs2rel
+       # is passed two relative paths. It's much faster if paths are
+       # absolute! (Debian bug #376658)
+       my $path="/".shift;
+       my $base="/".shift;
+
+       require File::Spec;
+       my $ret=File::Spec->abs2rel($path, $base);
+       $ret=~s/^// if defined $ret;
+       return $ret;
+} #}}}
+
+sub displaytime ($) { #{{{
+       my $time=shift;
+
+       eval q{use POSIX};
+       error($@) if $@;
+       # strftime doesn't know about encodings, so make sure
+       # its output is properly treated as utf8
+       return decode_utf8(POSIX::strftime(
+                       $config{timeformat}, localtime($time)));
+} #}}}
+
+sub htmllink ($$$;$$$) { #{{{
+       my $lpage=shift; # the page doing the linking
+       my $page=shift; # the page that will contain the link (different for inline)
+       my $link=shift;
+       my $noimageinline=shift; # don't turn links into inline html images
+       my $forcesubpage=shift; # force a link to a subpage
+       my $linktext=shift; # set to force the link text to something
+
+       my $bestlink;
+       if (! $forcesubpage) {
+               $bestlink=bestlink($lpage, $link);
+       }
+       else {
+               $bestlink="$lpage/".lc($link);
+       }
+
+       $linktext=pagetitle(basename($link)) unless defined $linktext;
+       
+       return "<span class=\"selflink\">$linktext</span>"
+               if length $bestlink && $page eq $bestlink;
+       
+       # TODO BUG: %renderedfiles may not have it, if the linked to page
+       # was also added and isn't yet rendered! Note that this bug is
+       # masked by the bug that makes all new files be rendered twice.
+       if (! grep { $_ eq $bestlink } map { @{$_} } values %renderedfiles) {
+               $bestlink=htmlpage($bestlink);
+       }
+       if (! grep { $_ eq $bestlink } map { @{$_} } values %renderedfiles) {
+               return "<span><a href=\"".
+                       cgiurl(do => "create", page => lc($link), from => $page).
+                       "\">?</a>$linktext</span>"
+       }
+       
+       $bestlink=abs2rel($bestlink, dirname($page));
+       
+       if (! $noimageinline && isinlinableimage($bestlink)) {
+               return "<img src=\"$bestlink\" alt=\"$linktext\" />";
+       }
+       return "<a href=\"$bestlink\">$linktext</a>";
+} #}}}
+
+sub htmlize ($$$) { #{{{
+       my $page=shift;
+       my $type=shift;
+       my $content=shift;
+
+       if (exists $hooks{htmlize}{$type}) {
+               $content=$hooks{htmlize}{$type}{call}->(
+                       page => $page,
+                       content => $content,
+               );
+       }
+       else {
+               error("htmlization of $type not supported");
+       }
+
+       run_hooks(sanitize => sub {
+               $content=shift->(
+                       page => $page,
+                       content => $content,
+               );
+       });
+
+       return $content;
+} #}}}
+
+sub linkify ($$$) { #{{{
+       my $lpage=shift; # the page containing the links
+       my $page=shift; # the page the link will end up on (different for inline)
+       my $content=shift;
+
+       $content =~ s{(\\?)$config{wiki_link_regexp}}{
+               $2 ? ( $1 ? "[[$2|$3]]" : htmllink($lpage, $page, titlepage($3), 0, 0, pagetitle($2)))
+                  : ( $1 ? "[[$3]]" :    htmllink($lpage, $page, titlepage($3)))
+       }eg;
+       
+       return $content;
+} #}}}
+
+my %preprocessing;
+sub preprocess ($$$;$) { #{{{
+       my $page=shift; # the page the data comes from
+       my $destpage=shift; # the page the data will appear in (different for inline)
+       my $content=shift;
+       my $scan=shift;
+
+       my $handle=sub {
+               my $escape=shift;
+               my $command=shift;
+               my $params=shift;
+               if (length $escape) {
+                       return "[[$command $params]]";
+               }
+               elsif (exists $hooks{preprocess}{$command}) {
+                       return "" if $scan && ! $hooks{preprocess}{$command}{scan};
+                       # Note: preserve order of params, some plugins may
+                       # consider it significant.
+                       my @params;
+                       while ($params =~ /(?:(\w+)=)?(?:"""(.*?)"""|"([^"]+)"|(\S+))(?:\s+|$)/sg) {
+                               my $key=$1;
+                               my $val;
+                               if (defined $2) {
+                                       $val=$2;
+                                       $val=~s/\r\n/\n/mg;
+                                       $val=~s/^\n+//g;
+                                       $val=~s/\n+$//g;
+                               }
+                               elsif (defined $3) {
+                                       $val=$3;
+                               }
+                               elsif (defined $4) {
+                                       $val=$4;
+                               }
+
+                               if (defined $key) {
+                                       push @params, $key, $val;
+                               }
+                               else {
+                                       push @params, $val, '';
+                               }
+                       }
+                       if ($preprocessing{$page}++ > 3) {
+                               # Avoid loops of preprocessed pages preprocessing
+                               # other pages that preprocess them, etc.
+                               return "[[$command preprocessing loop detected on $page at depth $preprocessing{$page}]]";
+                       }
+                       my $ret=$hooks{preprocess}{$command}{call}->(
+                               @params,
+                               page => $page,
+                               destpage => $destpage,
+                       );
+                       $preprocessing{$page}--;
+                       return $ret;
+               }
+               else {
+                       return "[[$command $params]]";
+               }
+       };
+       
+       $content =~ s{(\\?)\[\[(\w+)\s+((?:(?:\w+=)?(?:""".*?"""|"[^"]+"|[^\s\]]+)\s*)*)\]\]}{$handle->($1, $2, $3)}seg;
+       return $content;
+} #}}}
+
+sub filter ($$) { #{{{
+       my $page=shift;
+       my $content=shift;
+
+       run_hooks(filter => sub {
+               $content=shift->(page => $page, content => $content);
+       });
+
+       return $content;
+} #}}}
+
+sub indexlink () { #{{{
+       return "<a href=\"$config{url}\">$config{wikiname}</a>";
+} #}}}
+
+sub lockwiki () { #{{{
+       # Take an exclusive lock on the wiki to prevent multiple concurrent
+       # run issues. The lock will be dropped on program exit.
+       if (! -d $config{wikistatedir}) {
+               mkdir($config{wikistatedir});
+       }
+       open(WIKILOCK, ">$config{wikistatedir}/lockfile") ||
+               error ("cannot write to $config{wikistatedir}/lockfile: $!");
+       if (! flock(WIKILOCK, 2 | 4)) {
+               debug("wiki seems to be locked, waiting for lock");
+               my $wait=600; # arbitrary, but don't hang forever to 
+                             # prevent process pileup
+               for (1..600) {
+                       return if flock(WIKILOCK, 2 | 4);
+                       sleep 1;
+               }
+               error("wiki is locked; waited $wait seconds without lock being freed (possible stuck process or stale lock?)");
+       }
+} #}}}
+
+sub unlockwiki () { #{{{
+       close WIKILOCK;
+} #}}}
+
+sub loadindex () { #{{{
+       open (IN, "$config{wikistatedir}/index") || return;
+       while (<IN>) {
+               $_=possibly_foolish_untaint($_);
+               chomp;
+               my %items;
+               $items{link}=[];
+               $items{dest}=[];
+               foreach my $i (split(/ /, $_)) {
+                       my ($item, $val)=split(/=/, $i, 2);
+                       push @{$items{$item}}, decode_entities($val);
+               }
+
+               next unless exists $items{src}; # skip bad lines for now
+
+               my $page=pagename($items{src}[0]);
+               if (! $config{rebuild}) {
+                       $pagesources{$page}=$items{src}[0];
+                       $oldpagemtime{$page}=$items{mtime}[0];
+                       $oldlinks{$page}=[@{$items{link}}];
+                       $links{$page}=[@{$items{link}}];
+                       $depends{$page}=$items{depends}[0] if exists $items{depends};
+                       $renderedfiles{$page}=[@{$items{dest}}];
+                       $oldrenderedfiles{$page}=[@{$items{dest}}];
+                       $pagecase{lc $page}=$page;
+               }
+               $pagectime{$page}=$items{ctime}[0];
+       }
+       close IN;
+} #}}}
+
+sub saveindex () { #{{{
+       run_hooks(savestate => sub { shift->() });
+
+       if (! -d $config{wikistatedir}) {
+               mkdir($config{wikistatedir});
+       }
+       open (OUT, ">$config{wikistatedir}/index") || 
+               error("cannot write to $config{wikistatedir}/index: $!");
+       foreach my $page (keys %oldpagemtime) {
+               next unless $oldpagemtime{$page};
+               my $line="mtime=$oldpagemtime{$page} ".
+                       "ctime=$pagectime{$page} ".
+                       "src=$pagesources{$page}";
+               $line.=" dest=$_" foreach @{$renderedfiles{$page}};
+               my %count;
+               $line.=" link=$_" foreach grep { ++$count{$_} == 1 } @{$links{$page}};
+               if (exists $depends{$page}) {
+                       $line.=" depends=".encode_entities($depends{$page}, " \t\n");
+               }
+               print OUT $line."\n";
+       }
+       close OUT;
+} #}}}
+
+sub template_params (@) { #{{{
+       my $filename=shift;
+       
+       require HTML::Template;
+       return filter => sub {
+                       my $text_ref = shift;
+                       $$text_ref=&Encode::decode_utf8($$text_ref);
+               },
+               filename => "$config{templatedir}/$filename",
+               loop_context_vars => 1,
+               die_on_bad_params => 0,
+               @_;
+} #}}}
+
+sub template ($;@) { #{{{
+       HTML::Template->new(template_params(@_));
+} #}}}
+
+sub misctemplate ($$;@) { #{{{
+       my $title=shift;
+       my $pagebody=shift;
+       
+       my $template=template("misc.tmpl");
+       $template->param(
+               title => $title,
+               indexlink => indexlink(),
+               wikiname => $config{wikiname},
+               pagebody => $pagebody,
+               baseurl => baseurl(),
+               @_,
+       );
+       run_hooks(pagetemplate => sub {
+               shift->(page => "", destpage => "", template => $template);
+       });
+       return $template->output;
+}#}}}
+
+sub hook (@) { # {{{
+       my %param=@_;
+       
+       if (! exists $param{type} || ! ref $param{call} || ! exists $param{id}) {
+               error "hook requires type, call, and id parameters";
+       }
+
+       return if $param{no_override} && exists $hooks{$param{type}}{$param{id}};
+       
+       $hooks{$param{type}}{$param{id}}=\%param;
+} # }}}
+
+sub run_hooks ($$) { # {{{
+       # Calls the given sub for each hook of the given type,
+       # passing it the hook function to call.
+       my $type=shift;
+       my $sub=shift;
+
+       if (exists $hooks{$type}) {
+               foreach my $id (keys %{$hooks{$type}}) {
+                       $sub->($hooks{$type}{$id}{call});
+               }
+       }
+} #}}}
+
+sub globlist_to_pagespec ($) { #{{{
+       my @globlist=split(' ', shift);
+
+       my (@spec, @skip);
+       foreach my $glob (@globlist) {
+               if ($glob=~/^!(.*)/) {
+                       push @skip, $glob;
+               }
+               else {
+                       push @spec, $glob;
+               }
+       }
+
+       my $spec=join(" or ", @spec);
+       if (@skip) {
+               my $skip=join(" and ", @skip);
+               if (length $spec) {
+                       $spec="$skip and ($spec)";
+               }
+               else {
+                       $spec=$skip;
+               }
+       }
+       return $spec;
+} #}}}
+
+sub is_globlist ($) { #{{{
+       my $s=shift;
+       $s=~/[^\s]+\s+([^\s]+)/ && $1 ne "and" && $1 ne "or";
+} #}}}
+
+sub safequote ($) { #{{{
+       my $s=shift;
+       $s=~s/[{}]//g;
+       return "q{$s}";
+} #}}}
+
+sub pagespec_merge ($$) { #{{{
+       my $a=shift;
+       my $b=shift;
+
+       return $a if $a eq $b;
+
+        # Support for old-style GlobLists.
+        if (is_globlist($a)) {
+                $a=globlist_to_pagespec($a);
+        }
+        if (is_globlist($b)) {
+                $b=globlist_to_pagespec($b);
+        }
+
+       return "($a) or ($b)";
+} #}}}
+
+sub pagespec_translate ($) { #{{{
+       # This assumes that $page is in scope in the function
+       # that evalulates the translated pagespec code.
+       my $spec=shift;
+
+       # Support for old-style GlobLists.
+       if (is_globlist($spec)) {
+               $spec=globlist_to_pagespec($spec);
+       }
+
+       # Convert spec to perl code.
+       my $code="";
+       while ($spec=~m/\s*(\!|\(|\)|\w+\([^\)]+\)|[^\s()]+)\s*/ig) {
+               my $word=$1;
+               if (lc $word eq "and") {
+                       $code.=" &&";
+               }
+               elsif (lc $word eq "or") {
+                       $code.=" ||";
+               }
+               elsif ($word eq "(" || $word eq ")" || $word eq "!") {
+                       $code.=" ".$word;
+               }
+               elsif ($word =~ /^(link|backlink|created_before|created_after|creation_month|creation_year|creation_day)\((.+)\)$/) {
+                       $code.=" match_$1(\$page, ".safequote($2).")";
+               }
+               else {
+                       $code.=" match_glob(\$page, ".safequote($word).")";
+               }
+       }
+
+       return $code;
+} #}}}
+
+sub add_depends ($$) { #{{{
+       my $page=shift;
+       my $pagespec=shift;
+       
+       if (! exists $depends{$page}) {
+               $depends{$page}=$pagespec;
+       }
+       else {
+               $depends{$page}=pagespec_merge($depends{$page}, $pagespec);
+       }
+} # }}}
+
+sub pagespec_match ($$) { #{{{
+       my $page=shift;
+       my $spec=shift;
+
+       return eval pagespec_translate($spec);
+} #}}}
+
+sub match_glob ($$) { #{{{
+       my $page=shift;
+       my $glob=shift;
+
+       # turn glob into safe regexp
+       $glob=quotemeta($glob);
+       $glob=~s/\\\*/.*/g;
+       $glob=~s/\\\?/./g;
+
+       return $page=~/^$glob$/i;
+} #}}}
+
+sub match_link ($$) { #{{{
+       my $page=shift;
+       my $link=lc(shift);
+
+       my $links = $links{$page} or return undef;
+       foreach my $p (@$links) {
+               return 1 if lc $p eq $link;
+       }
+       return 0;
+} #}}}
+
+sub match_backlink ($$) { #{{{
+       match_link(pop, pop);
+} #}}}
+
+sub match_created_before ($$) { #{{{
+       my $page=shift;
+       my $testpage=shift;
+
+       if (exists $pagectime{$testpage}) {
+               return $pagectime{$page} < $pagectime{$testpage};
+       }
+       else {
+               return 0;
+       }
+} #}}}
+
+sub match_created_after ($$) { #{{{
+       my $page=shift;
+       my $testpage=shift;
+
+       if (exists $pagectime{$testpage}) {
+               return $pagectime{$page} > $pagectime{$testpage};
+       }
+       else {
+               return 0;
+       }
+} #}}}
+
+sub match_creation_day ($$) { #{{{
+       return ((gmtime($pagectime{shift()}))[3] == shift);
+} #}}}
+
+sub match_creation_month ($$) { #{{{
+       return ((gmtime($pagectime{shift()}))[4] + 1 == shift);
+} #}}}
+
+sub match_creation_year ($$) { #{{{
+       return ((gmtime($pagectime{shift()}))[5] + 1900 == shift);
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/CGI.pm b/1.33.2/IkiWiki/CGI.pm
new file mode 100644 (file)
index 0000000..1e0ee01
--- /dev/null
@@ -0,0 +1,749 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+use IkiWiki;
+use IkiWiki::UserInfo;
+use open qw{:utf8 :std};
+use Encode;
+
+package IkiWiki;
+
+sub printheader ($) { #{{{
+       my $session=shift;
+       
+       if ($config{sslcookie}) {
+               print $session->header(-charset => 'utf-8',
+                       -cookie => $session->cookie(-secure => 1));
+       } else {
+               print $session->header(-charset => 'utf-8');
+       }
+
+} #}}}
+
+sub redirect ($$) { #{{{
+       my $q=shift;
+       my $url=shift;
+       if (! $config{w3mmode}) {
+               print $q->redirect($url);
+       }
+       else {
+               print "Content-type: text/plain\n";
+               print "W3m-control: GOTO $url\n\n";
+       }
+} #}}}
+
+sub page_locked ($$;$) { #{{{
+       my $page=shift;
+       my $session=shift;
+       my $nonfatal=shift;
+       
+       my $user=$session->param("name");
+       return if defined $user && is_admin($user);
+
+       foreach my $admin (@{$config{adminuser}}) {
+               my $locked_pages=userinfo_get($admin, "locked_pages");
+               if (pagespec_match($page, userinfo_get($admin, "locked_pages"))) {
+                       return 1 if $nonfatal;
+                       error(htmllink("", "", $page, 1)." is locked by ".
+                             htmllink("", "", $admin, 1)." and cannot be edited.");
+               }
+       }
+
+       return 0;
+} #}}}
+
+sub decode_form_utf8 ($) { #{{{
+       my $form = shift;
+       foreach my $f ($form->field) {
+               next if Encode::is_utf8(scalar $form->field($f));
+               $form->field(name  => $f,
+                            value => decode_utf8($form->field($f)),
+                            force => 1,
+                           );
+       }
+} #}}}
+
+sub cgi_recentchanges ($) { #{{{
+       my $q=shift;
+       
+       unlockwiki();
+
+       # Optimisation: building recentchanges means calculating lots of
+       # links. Memoizing htmllink speeds it up a lot (can't be memoized
+       # during page builds as the return values may change, but they
+       # won't here.)
+       eval q{use Memoize};
+       error($@) if $@;
+       memoize("htmllink");
+
+       eval q{use Time::Duration};
+       error($@) if $@;
+       eval q{use CGI 'escapeHTML'};
+       error($@) if $@;
+
+       my $changelog=[rcs_recentchanges(100)];
+       foreach my $change (@$changelog) {
+               $change->{when} = concise(ago($change->{when}));
+               $change->{user} = htmllink("", "", escapeHTML($change->{user}), 1);
+
+               my $is_excess = exists $change->{pages}[10]; # limit pages to first 10
+               delete @{$change->{pages}}[10 .. @{$change->{pages}}] if $is_excess;
+               $change->{pages} = [
+                       map {
+                               $_->{link} = htmllink("", "", $_->{page}, 1);
+                               $_;
+                       } @{$change->{pages}}
+               ];
+               push @{$change->{pages}}, { link => '...' } if $is_excess;
+       }
+
+       my $template=template("recentchanges.tmpl"); 
+       $template->param(
+               title => "RecentChanges",
+               indexlink => indexlink(),
+               wikiname => $config{wikiname},
+               changelog => $changelog,
+               baseurl => baseurl(),
+       );
+       run_hooks(pagetemplate => sub {
+               shift->(page => "", destpage => "", template => $template);
+       });
+       print $q->header(-charset => 'utf-8'), $template->output;
+} #}}}
+
+sub cgi_signin ($$) { #{{{
+       my $q=shift;
+       my $session=shift;
+
+       eval q{use CGI::FormBuilder};
+       error($@) if $@;
+       my $form = CGI::FormBuilder->new(
+               title => "signin",
+               fields => [qw(do title page subpage from name password)],
+               header => 1,
+               charset => "utf-8",
+               method => 'POST',
+               validate => {
+                       confirm_password => {
+                               perl => q{eq $form->field("password")},
+                       },
+                       email => 'EMAIL',
+               },
+               required => 'NONE',
+               javascript => 0,
+               params => $q,
+               action => $config{cgiurl},
+               header => 0,
+               template => (-e "$config{templatedir}/signin.tmpl" ?
+                            {template_params("signin.tmpl")} : ""),
+               stylesheet => baseurl()."style.css",
+       );
+               
+       decode_form_utf8($form);
+       
+       $form->field(name => "name", required => 0);
+       $form->field(name => "do", type => "hidden");
+       $form->field(name => "page", type => "hidden");
+       $form->field(name => "title", type => "hidden");
+       $form->field(name => "from", type => "hidden");
+       $form->field(name => "subpage", type => "hidden");
+       $form->field(name => "password", type => "password", required => 0);
+       if ($form->submitted eq "Register" || $form->submitted eq "Create Account") {
+               $form->title("register");
+               $form->text("");
+               $form->fields(qw(do title page subpage from name password confirm_password email));
+               $form->field(name => "confirm_password", type => "password");
+               $form->field(name => "email", type => "text");
+       }
+       if ($q->param("do") ne "signin" && !$form->submitted) {
+               $form->text("You need to log in first.");
+       }
+       
+       if ($form->submitted) {
+               # Set required fields based on how form was submitted.
+               my %required=(
+                       "Login" => [qw(name password)],
+                       "Register" => [],
+                       "Create Account" => [qw(name password confirm_password email)],
+                       "Mail Password" => [qw(name)],
+               );
+               foreach my $opt (@{$required{$form->submitted}}) {
+                       $form->field(name => $opt, required => 1);
+               }
+       
+               # Validate password differently depending on how
+               # form was submitted.
+               if ($form->submitted eq 'Login') {
+                       $form->field(
+                               name => "password",
+                               validate => sub {
+                                       length $form->field("name") &&
+                                       shift eq userinfo_get($form->field("name"), 'password');
+                               },
+                       );
+                       $form->field(name => "name", validate => '/^\w+$/');
+               }
+               else {
+                       $form->field(name => "password", validate => 'VALUE');
+               }
+               # And make sure the entered name exists when logging
+               # in or sending email, and does not when registering.
+               if ($form->submitted eq 'Create Account' ||
+                   $form->submitted eq 'Register') {
+                       $form->field(
+                               name => "name",
+                               validate => sub {
+                                       my $name=shift;
+                                       length $name &&
+                                       $name=~/$config{wiki_file_regexp}/ &&
+                                       ! userinfo_get($name, "regdate");
+                               },
+                       );
+               }
+               else {
+                       $form->field(
+                               name => "name",
+                               validate => sub {
+                                       my $name=shift;
+                                       length $name &&
+                                       userinfo_get($name, "regdate");
+                               },
+                       );
+               }
+       }
+       else {
+               # First time settings.
+               $form->field(name => "name", comment => "use FirstnameLastName");
+               if ($session->param("name")) {
+                       $form->field(name => "name", value => $session->param("name"));
+               }
+       }
+
+       if ($form->submitted && $form->validate) {
+               if ($form->submitted eq 'Login') {
+                       $session->param("name", $form->field("name"));
+                       if (defined $form->field("do") && 
+                           $form->field("do") ne 'signin') {
+                               redirect($q, cgiurl(
+                                       do => $form->field("do"),
+                                       page => $form->field("page"),
+                                       title => $form->field("title"),
+                                       subpage => $form->field("subpage"),
+                                       from => $form->field("from"),
+                               ));
+                       }
+                       else {
+                               redirect($q, $config{url});
+                       }
+               }
+               elsif ($form->submitted eq 'Create Account') {
+                       my $user_name=$form->field('name');
+                       if (userinfo_setall($user_name, {
+                                          'email' => $form->field('email'),
+                                          'password' => $form->field('password'),
+                                          'regdate' => time
+                                        })) {
+                               $form->field(name => "confirm_password", type => "hidden");
+                               $form->field(name => "email", type => "hidden");
+                               $form->text("Account creation successful. Now you can Login.");
+                               printheader($session);
+                               print misctemplate($form->title, $form->render(submit => ["Login"]));
+                       }
+                       else {
+                               error("Error creating account.");
+                       }
+               }
+               elsif ($form->submitted eq 'Mail Password') {
+                       my $user_name=$form->field("name");
+                       my $template=template("passwordmail.tmpl");
+                       $template->param(
+                               user_name => $user_name,
+                               user_password => userinfo_get($user_name, "password"),
+                               wikiurl => $config{url},
+                               wikiname => $config{wikiname},
+                               REMOTE_ADDR => $ENV{REMOTE_ADDR},
+                       );
+                       
+                       eval q{use Mail::Sendmail};
+                       error($@) if $@;
+                       sendmail(
+                               To => userinfo_get($user_name, "email"),
+                               From => "$config{wikiname} admin <$config{adminemail}>",
+                               Subject => "$config{wikiname} information",
+                               Message => $template->output,
+                       ) or error("Failed to send mail");
+                       
+                       $form->text("Your password has been emailed to you.");
+                       $form->field(name => "name", required => 0);
+                       printheader($session);
+                       print misctemplate($form->title, $form->render(submit => ["Login", "Mail Password"]));
+               }
+               elsif ($form->submitted eq "Register") {
+                       printheader($session);
+                       print misctemplate($form->title, $form->render(submit => ["Create Account"]));
+               }
+       }
+       elsif ($form->submitted eq "Create Account") {
+               printheader($session);
+               print misctemplate($form->title, $form->render(submit => ["Create Account"]));
+       }
+       else {
+               printheader($session);
+               print misctemplate($form->title, $form->render(submit => ["Login", "Register", "Mail Password"]));
+       }
+} #}}}
+
+sub cgi_prefs ($$) { #{{{
+       my $q=shift;
+       my $session=shift;
+
+       eval q{use CGI::FormBuilder};
+       error($@) if $@;
+       my $form = CGI::FormBuilder->new(
+               title => "preferences",
+               fields => [qw(do name password confirm_password email 
+                             subscriptions locked_pages)],
+               header => 0,
+               charset => "utf-8",
+               method => 'POST',
+               validate => {
+                       confirm_password => {
+                               perl => q{eq $form->field("password")},
+                       },
+                       email => 'EMAIL',
+               },
+               required => 'NONE',
+               javascript => 0,
+               params => $q,
+               action => $config{cgiurl},
+               template => (-e "$config{templatedir}/prefs.tmpl" ?
+                            {template_params("prefs.tmpl")} : ""),
+               stylesheet => baseurl()."style.css",
+       );
+       my @buttons=("Save Preferences", "Logout", "Cancel");
+       
+       my $user_name=$session->param("name");
+       $form->field(name => "do", type => "hidden");
+       $form->field(name => "name", disabled => 1,
+               value => $user_name, force => 1);
+       $form->field(name => "password", type => "password");
+       $form->field(name => "confirm_password", type => "password");
+       $form->field(name => "subscriptions", size => 50,
+               comment => "(".htmllink("", "", "PageSpec", 1).")");
+       $form->field(name => "locked_pages", size => 50,
+               comment => "(".htmllink("", "", "PageSpec", 1).")");
+       $form->field(name => "banned_users", size => 50);
+       
+       if (! is_admin($user_name)) {
+               $form->field(name => "locked_pages", type => "hidden");
+               $form->field(name => "banned_users", type => "hidden");
+       }
+
+       if ($config{httpauth}) {
+               $form->field(name => "password", type => "hidden");
+               $form->field(name => "confirm_password", type => "hidden");
+       }
+       
+       if (! $form->submitted) {
+               $form->field(name => "email", force => 1,
+                       value => userinfo_get($user_name, "email"));
+               $form->field(name => "subscriptions", force => 1,
+                       value => userinfo_get($user_name, "subscriptions"));
+               $form->field(name => "locked_pages", force => 1,
+                       value => userinfo_get($user_name, "locked_pages"));
+               if (is_admin($user_name)) {
+                       $form->field(name => "banned_users", force => 1,
+                               value => join(" ", get_banned_users()));
+               }
+       }
+       
+       decode_form_utf8($form);
+       
+       if ($form->submitted eq 'Logout') {
+               $session->delete();
+               redirect($q, $config{url});
+               return;
+       }
+       elsif ($form->submitted eq 'Cancel') {
+               redirect($q, $config{url});
+               return;
+       }
+       elsif ($form->submitted eq "Save Preferences" && $form->validate) {
+               foreach my $field (qw(password email subscriptions locked_pages)) {
+                       if (length $form->field($field)) {
+                               userinfo_set($user_name, $field, $form->field($field)) || error("failed to set $field");
+                       }
+               }
+               if (is_admin($user_name)) {
+                       set_banned_users(grep { ! is_admin($_) }
+                                       split(' ', $form->field("banned_users")));
+               }
+               $form->text("Preferences saved.");
+       }
+       
+       printheader($session);
+       print misctemplate($form->title, $form->render(submit => \@buttons));
+} #}}}
+
+sub cgi_editpage ($$) { #{{{
+       my $q=shift;
+       my $session=shift;
+
+       my @fields=qw(do rcsinfo subpage from page type editcontent comments);
+       my @buttons=("Save Page", "Preview", "Cancel");
+       
+       eval q{use CGI::FormBuilder; use CGI::FormBuilder::Template::HTML};
+       error($@) if $@;
+       my $renderer=CGI::FormBuilder::Template::HTML->new(
+               fields => \@fields,
+               template_params("editpage.tmpl"),
+       );
+       run_hooks(pagetemplate => sub {
+               shift->(page => "", destpage => "", template => $renderer->engine);
+       });
+       my $form = CGI::FormBuilder->new(
+               fields => \@fields,
+               header => 1,
+               charset => "utf-8",
+               method => 'POST',
+               validate => {
+                       editcontent => '/.+/',
+               },
+               required => [qw{editcontent}],
+               javascript => 0,
+               params => $q,
+               action => $config{cgiurl},
+               table => 0,
+               template => $renderer,
+       );
+       
+       decode_form_utf8($form);
+       
+       # This untaint is safe because titlepage removes any problematic
+       # characters.
+       my ($page)=$form->field('page');
+       $page=titlepage(possibly_foolish_untaint($page));
+       if (! defined $page || ! length $page ||
+           $page=~/$config{wiki_file_prune_regexp}/ || $page=~/^\//) {
+               error("bad page name");
+       }
+       
+       my $from;
+       if (defined $form->field('from')) {
+               ($from)=$form->field('from')=~/$config{wiki_file_regexp}/;
+       }
+       
+       my $file;
+       my $type;
+       if (exists $pagesources{$page}) {
+               $file=$pagesources{$page};
+               $type=pagetype($file);
+               if (! defined $type) {
+                       error("$page is not an editable page");
+               }
+       }
+       else {
+               $type=$form->param('type');
+               if (defined $type && length $type && $hooks{htmlize}{$type}) {
+                       $type=possibly_foolish_untaint($type);
+               }
+               elsif (defined $from) {
+                       # favor the type of linking page
+                       $type=pagetype($pagesources{$from});
+               }
+               $type=$config{default_pageext} unless defined $type;
+               $file=$page.".".$type;
+       }
+
+       my $newfile=0;
+       if (! -e "$config{srcdir}/$file") {
+               $newfile=1;
+       }
+
+       $form->field(name => "do", type => 'hidden');
+       $form->field(name => "from", type => 'hidden');
+       $form->field(name => "rcsinfo", type => 'hidden');
+       $form->field(name => "subpage", type => 'hidden');
+       $form->field(name => "page", value => $page, force => 1);
+       $form->field(name => "type", value => $type, force => 1);
+       $form->field(name => "comments", type => "text", size => 80);
+       $form->field(name => "editcontent", type => "textarea", rows => 20,
+               cols => 80);
+       $form->tmpl_param("can_commit", $config{rcs});
+       $form->tmpl_param("indexlink", indexlink());
+       $form->tmpl_param("helponformattinglink",
+               htmllink("", "", "HelpOnFormatting", 1));
+       $form->tmpl_param("baseurl", baseurl());
+       if (! $form->submitted) {
+               $form->field(name => "rcsinfo", value => rcs_prepedit($file),
+                       force => 1);
+       }
+       
+       if ($form->submitted eq "Cancel") {
+               if ($newfile && defined $from) {
+                       redirect($q, "$config{url}/".htmlpage($from));
+               }
+               elsif ($newfile) {
+                       redirect($q, $config{url});
+               }
+               else {
+                       redirect($q, "$config{url}/".htmlpage($page));
+               }
+               return;
+       }
+       elsif ($form->submitted eq "Preview") {
+               my $content=$form->field('editcontent');
+               my $comments=$form->field('comments');
+               $form->field(name => "editcontent",
+                               value => $content, force => 1);
+               $form->field(name => "comments",
+                               value => $comments, force => 1);
+               $config{rss}=$config{atom}=0; # avoid preview writing a feed!
+               $form->tmpl_param("page_preview",
+                       htmlize($page, $type,
+                       linkify($page, "",
+                       preprocess($page, $page,
+                       filter($page, $content)))));
+       }
+       else {
+               $form->tmpl_param("page_preview", "");
+       }
+       $form->tmpl_param("page_conflict", "");
+       
+       if (! $form->submitted || $form->submitted eq "Preview" || 
+           ! $form->validate) {
+               if ($form->field("do") eq "create") {
+                       my @page_locs;
+                       my $best_loc;
+                       if (! defined $from || ! length $from ||
+                           $from ne $form->field('from') ||
+                           $from=~/$config{wiki_file_prune_regexp}/ ||
+                           $from=~/^\// ||
+                           $form->submitted eq "Preview") {
+                               @page_locs=$best_loc=$page;
+                       }
+                       else {
+                               my $dir=$from."/";
+                               $dir=~s![^/]+/+$!!;
+                               
+                               if ((defined $form->field('subpage') && length $form->field('subpage')) ||
+                                   $page eq 'discussion') {
+                                       $best_loc="$from/$page";
+                               }
+                               else {
+                                       $best_loc=$dir.$page;
+                               }
+                               
+                               push @page_locs, $dir.$page;
+                               push @page_locs, "$from/$page";
+                               while (length $dir) {
+                                       $dir=~s![^/]+/+$!!;
+                                       push @page_locs, $dir.$page;
+                               }
+                       }
+
+                       @page_locs = grep {
+                               ! exists $pagecase{lc $_} &&
+                               ! page_locked($_, $session, 1)
+                       } @page_locs;
+                       
+                       if (! @page_locs) {
+                               # hmm, someone else made the page in the
+                               # meantime?
+                               redirect($q, "$config{url}/".htmlpage($page));
+                               return;
+                       }
+                       
+                       my @page_types;
+                       if (exists $hooks{htmlize}) {
+                               @page_types=keys %{$hooks{htmlize}};
+                       }
+                       
+                       $form->tmpl_param("page_select", 1);
+                       $form->field(name => "page", type => 'select',
+                               options => \@page_locs, value => $best_loc);
+                       $form->field(name => "type", type => 'select',
+                               options => \@page_types);
+                       $form->title("creating ".pagetitle($page));
+               }
+               elsif ($form->field("do") eq "edit") {
+                       page_locked($page, $session);
+                       if (! defined $form->field('editcontent') || 
+                           ! length $form->field('editcontent')) {
+                               my $content="";
+                               if (exists $pagesources{$page}) {
+                                       $content=readfile(srcfile($pagesources{$page}));
+                                       $content=~s/\n/\r\n/g;
+                               }
+                               $form->field(name => "editcontent", value => $content,
+                                       force => 1);
+                       }
+                       $form->tmpl_param("page_select", 0);
+                       $form->field(name => "page", type => 'hidden');
+                       $form->field(name => "type", type => 'hidden');
+                       $form->title("editing ".pagetitle($page));
+               }
+               
+               print $form->render(submit => \@buttons);
+       }
+       else {
+               # save page
+               page_locked($page, $session);
+               
+               my $content=$form->field('editcontent');
+
+               $content=~s/\r\n/\n/g;
+               $content=~s/\r/\n/g;
+               writefile($file, $config{srcdir}, $content);
+               
+               my $message="web commit ";
+               if (defined $session->param("name") && 
+                   length $session->param("name")) {
+                       $message.="by ".$session->param("name");
+               }
+               else {
+                       $message.="from $ENV{REMOTE_ADDR}";
+               }
+               if (defined $form->field('comments') &&
+                   length $form->field('comments')) {
+                       $message.=": ".$form->field('comments');
+               }
+               
+               if ($config{rcs}) {
+                       if ($newfile) {
+                               rcs_add($file);
+                       }
+                       # prevent deadlock with post-commit hook
+                       unlockwiki();
+                       # presumably the commit will trigger an update
+                       # of the wiki
+                       my $conflict=rcs_commit($file, $message,
+                               $form->field("rcsinfo"));
+               
+                       if (defined $conflict) {
+                               $form->field(name => "rcsinfo", value => rcs_prepedit($file),
+                                       force => 1);
+                               $form->tmpl_param("page_conflict", 1);
+                               $form->field("editcontent", value => $conflict, force => 1);
+                               $form->field(name => "comments", value => $form->field('comments'), force => 1);
+                               $form->field("do", "edit)");
+                               $form->tmpl_param("page_select", 0);
+                               $form->field(name => "page", type => 'hidden');
+                               $form->field(name => "type", type => 'hidden');
+                               $form->title("editing $page");
+                               print $form->render(submit => \@buttons);
+                               return;
+                       }
+               }
+               else {
+                       require IkiWiki::Render;
+                       refresh();
+                       saveindex();
+               }
+               
+               # The trailing question mark tries to avoid broken
+               # caches and get the most recent version of the page.
+               redirect($q, "$config{url}/".htmlpage($page)."?updated");
+       }
+} #}}}
+
+sub cgi () { #{{{
+       eval q{use CGI; use CGI::Session};
+       error($@) if $@;
+       
+       my $q=CGI->new;
+       
+       run_hooks(cgi => sub { shift->($q) });
+       
+       my $do=$q->param('do');
+       if (! defined $do || ! length $do) {
+               my $error = $q->cgi_error;
+               if ($error) {
+                       error("Request not processed: $error");
+               }
+               else {
+                       error("\"do\" parameter missing");
+               }
+       }
+       
+       # Things that do not need a session.
+       if ($do eq 'recentchanges') {
+               cgi_recentchanges($q);
+               return;
+       }
+       elsif ($do eq 'hyperestraier') {
+               cgi_hyperestraier();
+       }
+       
+       CGI::Session->name("ikiwiki_session_".encode_utf8($config{wikiname}));
+       
+       my $oldmask=umask(077);
+       my $session = CGI::Session->new("driver:DB_File", $q,
+               { FileName => "$config{wikistatedir}/sessions.db" });
+       umask($oldmask);
+       
+       # Everything below this point needs the user to be signed in.
+       if (((! $config{anonok} || $do eq 'prefs') &&
+            (! $config{httpauth}) &&
+            (! defined $session->param("name") ||
+            ! userinfo_get($session->param("name"), "regdate"))) || $do eq 'signin') {
+               cgi_signin($q, $session);
+       
+               # Force session flush with safe umask.
+               my $oldmask=umask(077);
+               $session->flush;
+               umask($oldmask);
+               
+               return;
+       }
+
+       if ($config{httpauth} && (! defined $session->param("name"))) {
+               if (! defined $q->remote_user()) {
+                       error("Could not determine authenticated username.");
+               }
+               else {
+                       $session->param("name", $q->remote_user());
+                       if (! userinfo_get($session->param("name"), "regdate")) {
+                               userinfo_setall($session->param("name"), {
+                                       email => "",
+                                       password => "",
+                                       regdate=>time,
+                               });
+                       }
+               }
+       }
+
+       if (defined $session->param("name") && userinfo_get($session->param("name"), "banned")) {
+               print $q->header(-status => "403 Forbidden");
+               $session->delete();
+               print "You are banned.";
+               exit;
+       }
+       
+       if ($do eq 'create' || $do eq 'edit') {
+               cgi_editpage($q, $session);
+       }
+       elsif ($do eq 'prefs') {
+               cgi_prefs($q, $session);
+       }
+       elsif ($do eq 'blog') {
+               my $page=titlepage(decode_utf8($q->param('title')));
+               # if the page already exists, munge it to be unique
+               my $from=$q->param('from');
+               my $add="";
+               while (exists $pagecase{lc "$from/$page$add"}) {
+                       $add=1 unless length $add;
+                       $add++;
+               }
+               $q->param('page', $page.$add);
+               # now run same as create
+               $q->param('do', 'create');
+               cgi_editpage($q, $session);
+       }
+       else {
+               error("unknown do parameter");
+       }
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/aggregate.pm b/1.33.2/IkiWiki/Plugin/aggregate.pm
new file mode 100644 (file)
index 0000000..2a3f36f
--- /dev/null
@@ -0,0 +1,416 @@
+#!/usr/bin/perl
+# Blog aggregation plugin.
+package IkiWiki::Plugin::aggregate;
+
+use warnings;
+use strict;
+use IkiWiki;
+use HTML::Entities;
+use HTML::Parser;
+use HTML::Tagset;
+use URI;
+use open qw{:utf8 :std};
+
+my %feeds;
+my %guids;
+
+sub import { #{{{
+       hook(type => "getopt", id => "aggregate", call => \&getopt);
+       hook(type => "checkconfig", id => "aggregate", call => \&checkconfig);
+       hook(type => "filter", id => "aggregate", call => \&filter);
+       hook(type => "preprocess", id => "aggregate", call => \&preprocess);
+        hook(type => "delete", id => "aggregate", call => \&delete);
+       hook(type => "savestate", id => "aggregate", call => \&savestate);
+} # }}}
+
+sub getopt () { #{{{
+        eval q{use Getopt::Long};
+       error($@) if $@;
+        Getopt::Long::Configure('pass_through');
+        GetOptions("aggregate" => \$config{aggregate});
+} #}}}
+
+sub checkconfig () { #{{{
+       IkiWiki::lockwiki();
+       loadstate();
+       if ($config{aggregate}) {
+               IkiWiki::loadindex();
+               aggregate();
+               expire();
+               savestate();
+       }
+       IkiWiki::unlockwiki();
+} #}}}
+
+sub filter (@) { #{{{
+       my %params=@_;
+       my $page=$params{page};
+
+       # Mark all feeds originating on this page as removable;
+       # preprocess will unmark those that still exist.
+       remove_feeds($page);
+
+       return $params{content};
+} # }}}
+
+sub preprocess (@) { #{{{
+       my %params=@_;
+
+       foreach my $required (qw{name url}) {
+               if (! exists $params{$required}) {
+                       return "[[aggregate plugin missing $required parameter]]";
+               }
+       }
+
+       my $feed={};
+       my $name=$params{name};
+       if (exists $feeds{$name}) {
+               $feed=$feeds{$name};
+       }
+       else {
+               $feeds{$name}=$feed;
+       }
+       $feed->{name}=$name;
+       $feed->{sourcepage}=$params{page};
+       $feed->{url}=$params{url};
+       my $dir=exists $params{dir} ? $params{dir} : $params{page}."/".IkiWiki::titlepage($params{name});
+       $dir=~s/^\/+//;
+       ($dir)=$dir=~/$config{wiki_file_regexp}/;
+       $feed->{dir}=$dir;
+       $feed->{feedurl}=defined $params{feedurl} ? $params{feedurl} : "";
+       $feed->{updateinterval}=defined $params{updateinterval} ? $params{updateinterval} * 60 : 15 * 60;
+       $feed->{expireage}=defined $params{expireage} ? $params{expireage} : 0;
+       $feed->{expirecount}=defined $params{expirecount} ? $params{expirecount} : 0;
+       delete $feed->{remove};
+       delete $feed->{expired};
+       $feed->{lastupdate}=0 unless defined $feed->{lastupdate};
+       $feed->{numposts}=0 unless defined $feed->{numposts};
+       $feed->{newposts}=0 unless defined $feed->{newposts};
+       $feed->{message}="new feed" unless defined $feed->{message};
+       $feed->{error}=0 unless defined $feed->{error};
+       $feed->{tags}=[];
+       while (@_) {
+               my $key=shift;
+               my $value=shift;
+               if ($key eq 'tag') {
+                       push @{$feed->{tags}}, $value;
+               }
+       }
+
+       return "<a href=\"".$feed->{url}."\">".$feed->{name}."</a>: ".
+              ($feed->{error} ? "<em>" : "").$feed->{message}.
+              ($feed->{error} ? "</em>" : "").
+              " (".$feed->{numposts}." posts".
+              ($feed->{newposts} ? "; ".$feed->{newposts}." new" : "").
+              ")";
+} # }}}
+
+sub delete (@) { #{{{
+       my @files=@_;
+
+       # Remove feed data for removed pages.
+       foreach my $file (@files) {
+               my $page=pagename($file);
+               remove_feeds($page);
+       }
+} #}}}
+
+sub loadstate () { #{{{
+       if (-e "$config{wikistatedir}/aggregate") {
+               open (IN, "$config{wikistatedir}/aggregate" ||
+                       die "$config{wikistatedir}/aggregate: $!");
+               while (<IN>) {
+                       $_=IkiWiki::possibly_foolish_untaint($_);
+                       chomp;
+                       my $data={};
+                       foreach my $i (split(/ /, $_)) {
+                               my ($field, $val)=split(/=/, $i, 2);
+                               if ($field eq "name" || $field eq "feed" ||
+                                   $field eq "guid" || $field eq "message") {
+                                       $data->{$field}=decode_entities($val, " \t\n");
+                               }
+                               elsif ($field eq "tag") {
+                                       push @{$data->{tags}}, $val;
+                               }
+                               else {
+                                       $data->{$field}=$val;
+                               }
+                       }
+                       
+                       if (exists $data->{name}) {
+                               $feeds{$data->{name}}=$data;
+                       }
+                       elsif (exists $data->{guid}) {
+                               $guids{$data->{guid}}=$data;
+                       }
+               }
+
+               close IN;
+       }
+} #}}}
+
+sub savestate () { #{{{
+       eval q{use HTML::Entities};
+       error($@) if $@;
+       open (OUT, ">$config{wikistatedir}/aggregate" ||
+               die "$config{wikistatedir}/aggregate: $!");
+       foreach my $data (values %feeds, values %guids) {
+               if ($data->{remove}) {
+                       if ($data->{name}) {
+                               foreach my $guid (values %guids) {
+                                       if ($guid->{feed} eq $data->{name}) {
+                                               $guid->{remove}=1;
+                                       }
+                               }
+                       }
+                       else {
+                               unlink pagefile($data->{page});
+                       }
+                       next;
+               }
+               elsif ($data->{expired} && exists $data->{page}) {
+                       unlink pagefile($data->{page});
+                       delete $data->{page};
+                       delete $data->{md5};
+               }
+
+               my @line;
+               foreach my $field (keys %$data) {
+                       if ($field eq "name" || $field eq "feed" ||
+                           $field eq "guid" || $field eq "message") {
+                               push @line, "$field=".encode_entities($data->{$field}, " \t\n");
+                       }
+                       elsif ($field eq "tags") {
+                               push @line, "tag=$_" foreach @{$data->{tags}};
+                       }
+                       else {
+                               push @line, "$field=".$data->{$field};
+                       }
+               }
+               print OUT join(" ", @line)."\n";
+       }
+       close OUT;
+} #}}}
+
+sub expire () { #{{{
+       foreach my $feed (values %feeds) {
+               next unless $feed->{expireage} || $feed->{expirecount};
+               my $count=0;
+               foreach my $item (sort { $IkiWiki::pagectime{$b->{page}} <=> $IkiWiki::pagectime{$a->{page}} }
+                                 grep { exists $_->{page} && $_->{feed} eq $feed->{name} && $IkiWiki::pagectime{$_->{page}} }
+                                 values %guids) {
+                       if ($feed->{expireage}) {
+                               my $days_old = (time - $IkiWiki::pagectime{$item->{page}}) / 60 / 60 / 24;
+                               if ($days_old > $feed->{expireage}) {
+                                       debug("expiring ".$item->{page}." ($days_old days old)");
+                                       $item->{expired}=1;
+                               }
+                       }
+                       elsif ($feed->{expirecount} &&
+                              $count >= $feed->{expirecount}) {
+                               debug("expiring ".$item->{page});
+                               $item->{expired}=1;
+                       }
+                       else {
+                               $count++;
+                       }
+               }
+       }
+} #}}}
+
+sub aggregate () { #{{{
+       eval q{use XML::Feed};
+       error($@) if $@;
+       eval q{use HTML::Entities};
+       error($@) if $@;
+
+       foreach my $feed (values %feeds) {
+               next unless $config{rebuild} || 
+                       time - $feed->{lastupdate} >= $feed->{updateinterval};
+               $feed->{lastupdate}=time;
+               $feed->{newposts}=0;
+               $IkiWiki::forcerebuild{$feed->{sourcepage}}=1;
+
+               debug("checking feed ".$feed->{name}." ...");
+
+               if (! length $feed->{feedurl}) {
+                       my @urls=XML::Feed->find_feeds($feed->{url});
+                       if (! @urls) {
+                               $feed->{message}="could not find feed at ".$feed->{feedurl};
+                               $feed->{error}=1;
+                               debug($feed->{message});
+                               next;
+                       }
+                       $feed->{feedurl}=pop @urls;
+               }
+               my $f=eval{XML::Feed->parse(URI->new($feed->{feedurl}))};
+               if ($@) {
+                       $feed->{message}="feed crashed XML::Feed! $@";
+                       $feed->{error}=1;
+                       debug($feed->{message});
+                       next;
+               }
+               if (! $f) {
+                       $feed->{message}=XML::Feed->errstr;
+                       $feed->{error}=1;
+                       debug($feed->{message});
+                       next;
+               }
+
+               foreach my $entry ($f->entries) {
+                       add_page(
+                               feed => $feed,
+                               title => defined $entry->title ? decode_entities($entry->title) : "untitled",
+                               link => $entry->link,
+                               content => $entry->content->body,
+                               guid => defined $entry->id ? $entry->id : time."_".$feed->name,
+                               ctime => $entry->issued ? ($entry->issued->epoch || time) : time,
+                       );
+               }
+
+               $feed->{message}="processed ok at ".
+                       displaytime($feed->{lastupdate});
+               $feed->{error}=0;
+       }
+} #}}}
+
+sub add_page (@) { #{{{
+       my %params=@_;
+       
+       my $feed=$params{feed};
+       my $guid={};
+       my $mtime;
+       if (exists $guids{$params{guid}}) {
+               # updating an existing post
+               $guid=$guids{$params{guid}};
+               return if $guid->{expired};
+       }
+       else {
+               # new post
+               $guid->{guid}=$params{guid};
+               $guids{$params{guid}}=$guid;
+               $mtime=$params{ctime};
+               $feed->{numposts}++;
+               $feed->{newposts}++;
+
+               # assign it an unused page
+               my $page=IkiWiki::titlepage($params{title});
+               # escape slashes and periods in title so it doesn't specify
+               # directory name or trigger ".." disallowing code.
+               $page=~s!([/.])!"__".ord($1)."__"!eg;
+               $page=$feed->{dir}."/".$page;
+               ($page)=$page=~/$config{wiki_file_regexp}/;
+               if (! defined $page || ! length $page) {
+                       $page=$feed->{dir}."/item";
+               }
+               my $c="";
+               while (exists $IkiWiki::pagecase{lc $page.$c} ||
+                      -e pagefile($page.$c)) {
+                       $c++
+               }
+               $guid->{page}=$page;
+               debug("creating new page $page");
+       }
+       $guid->{feed}=$feed->{name};
+       
+       # To write or not to write? Need to avoid writing unchanged pages
+       # to avoid unneccessary rebuilding. The mtime from rss cannot be
+       # trusted; let's use a digest.
+       eval q{use Digest::MD5 'md5_hex'};
+       error($@) if $@;
+       require Encode;
+       my $digest=md5_hex(Encode::encode_utf8($params{content}));
+       return unless ! exists $guid->{md5} || $guid->{md5} ne $digest || $config{rebuild};
+       $guid->{md5}=$digest;
+
+       # Create the page.
+       my $template=template("aggregatepost.tmpl", blind_cache => 1);
+       $template->param(title => $params{title})
+               if defined $params{title} && length($params{title});
+       $template->param(content => htmlescape(htmlabs($params{content}, $feed->{feedurl})));
+       $template->param(name => $feed->{name});
+       $template->param(url => $feed->{url});
+       $template->param(permalink => urlabs($params{link}, $feed->{feedurl}))
+               if defined $params{link};
+       if (ref $feed->{tags}) {
+               $template->param(tags => [map { tag => $_ }, @{$feed->{tags}}]);
+       }
+       writefile(htmlpage($guid->{page}), $config{srcdir},
+               $template->output);
+
+       # Set the mtime, this lets the build process get the right creation
+       # time on record for the new page.
+       utime $mtime, $mtime, pagefile($guid->{page}) if defined $mtime;
+} #}}}
+
+sub htmlescape ($) { #{{{
+       # escape accidental wikilinks and preprocessor stuff
+       my $html=shift;
+       $html=~s/(?<!\\)\[\[/\\\[\[/g;
+       return $html;
+} #}}}
+
+sub urlabs ($$) { #{{{
+       my $url=shift;
+       my $urlbase=shift;
+
+       URI->new_abs($url, $urlbase)->as_string;
+} #}}}
+
+sub htmlabs ($$) { #{{{
+       # Convert links in html from relative to absolute.
+       # Note that this is a heuristic, which is not specified by the rss
+       # spec and may not be right for all feeds. Also, see Debian
+       # bug #381359.
+       my $html=shift;
+       my $urlbase=shift;
+
+       my $ret="";
+       my $p = HTML::Parser->new(api_version => 3);
+       $p->handler(default => sub { $ret.=join("", @_) }, "text");
+       $p->handler(start => sub {
+               my ($tagname, $pos, $text) = @_;
+               if (ref $HTML::Tagset::linkElements{$tagname}) {
+                       while (4 <= @$pos) {
+                               # use attribute sets from right to left
+                               # to avoid invalidating the offsets
+                               # when replacing the values
+                               my($k_offset, $k_len, $v_offset, $v_len) =
+                                       splice(@$pos, -4);
+                               my $attrname = lc(substr($text, $k_offset, $k_len));
+                               next unless grep { $_ eq $attrname } @{$HTML::Tagset::linkElements{$tagname}};
+                               next unless $v_offset; # 0 v_offset means no value
+                               my $v = substr($text, $v_offset, $v_len);
+                               $v =~ s/^([\'\"])(.*)\1$/$2/;
+                               my $new_v=urlabs($v, $urlbase);
+                               $new_v =~ s/\"/&quot;/g; # since we quote with ""
+                               substr($text, $v_offset, $v_len) = qq("$new_v");
+                       }
+               }
+               $ret.=$text;
+       }, "tagname, tokenpos, text");
+       $p->parse($html);
+       $p->eof;
+
+       return $ret;
+} #}}}
+
+sub remove_feeds () { #{{{
+       my $page=shift;
+
+       my %removed;
+       foreach my $id (keys %feeds) {
+               if ($feeds{$id}->{sourcepage} eq $page) {
+                       $feeds{$id}->{remove}=1;
+                       $removed{$id}=1;
+               }
+       }
+} #}}}
+
+sub pagefile ($) { #{{{
+       my $page=shift;
+
+       return "$config{srcdir}/".htmlpage($page);
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/brokenlinks.pm b/1.33.2/IkiWiki/Plugin/brokenlinks.pm
new file mode 100644 (file)
index 0000000..6741f90
--- /dev/null
@@ -0,0 +1,41 @@
+#!/usr/bin/perl
+# Provides a list of broken links.
+package IkiWiki::Plugin::brokenlinks;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import { #{{{
+       hook(type => "preprocess", id => "brokenlinks", call => \&preprocess);
+} # }}}
+
+sub preprocess (@) { #{{{
+       my %params=@_;
+       $params{pages}="*" unless defined $params{pages};
+       
+       # Needs to update whenever a page is added or removed, so
+       # register a dependency.
+       add_depends($params{page}, $params{pages});
+       
+       my @broken;
+       foreach my $page (keys %links) {
+               if (pagespec_match($page, $params{pages})) {
+                       foreach my $link (@{$links{$page}}) {
+                               next if $link =~ /.*\/discussion/i && $config{discussion};
+                               my $bestlink=bestlink($page, $link);
+                               next if length $bestlink;
+                               push @broken,
+                                       htmllink($page, $params{destpage}, $link, 1).
+                                       " from ".
+                                       htmllink($params{page}, $params{destpage}, $page, 1);
+                       }
+               }
+       }
+       
+       return "There are no broken links!" unless @broken;
+       my %seen;
+       return "<ul>\n".join("\n", map { "<li>$_</li>" } grep { ! $seen{$_}++ } sort @broken)."</ul>\n";
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/camelcase.pm b/1.33.2/IkiWiki/Plugin/camelcase.pm
new file mode 100644 (file)
index 0000000..0bb35b6
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+# CamelCase links
+package IkiWiki::Plugin::camelcase;
+
+use IkiWiki;
+use warnings;
+use strict;
+
+sub import { #{{{
+       hook(type => "filter", id => "camelcase", call => \&filter);
+} # }}}
+
+sub filter (@) { #{{{
+       my %params=@_;
+
+       # Make CamelCase links work by promoting them to fullfledged
+       # WikiLinks. This regexp is based on the one in Text::WikiFormat.
+       $params{content}=~s#(?<![[|"/>=])\b((?:[A-Z][a-z0-9]\w*){2,})#[[$1]]#g;
+
+       return $params{content};
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/ddate.pm b/1.33.2/IkiWiki/Plugin/ddate.pm
new file mode 100644 (file)
index 0000000..862d4da
--- /dev/null
@@ -0,0 +1,32 @@
+#!/usr/bin/perl
+# Discordian date support fnord ikiwiki.
+package IkiWiki::Plugin::ddate;
+use IkiWiki;
+no warnings;
+
+sub import { #{{{
+       hook(type => "checkconfig", id => "skeleton", call => \&checkconfig);
+} # }}}
+
+sub checkconfig () { #{{{
+       if (! defined $config{timeformat} ||
+           $config{timeformat} eq '%c') {
+               $config{timeformat}='on %A, the %e of %B, %Y. %N%nCelebrate %H';
+       }
+} #}}}
+
+sub IkiWiki::displaytime ($) { #{{{
+       my $time=shift;
+       eval q{
+               use DateTime;
+               use DateTime::Calendar::Discordian;
+       };
+       if ($@) {
+                return "some time or other ($@ -- hail Eris!)";
+       }
+       my $dt = DateTime->from_epoch(epoch => $time);
+       my $dd = DateTime::Calendar::Discordian->from_object(object => $dt);
+       return $dd->strftime($IkiWiki::config{timeformat});
+} #}}}
+
+5
diff --git a/1.33.2/IkiWiki/Plugin/favicon.pm b/1.33.2/IkiWiki/Plugin/favicon.pm
new file mode 100644 (file)
index 0000000..864131d
--- /dev/null
@@ -0,0 +1,24 @@
+#!/usr/bin/perl
+# favicon plugin.
+
+package IkiWiki::Plugin::favicon;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import { #{{{
+       hook(type => "pagetemplate", id => "favicon", call => \&pagetemplate);
+} # }}}
+
+sub pagetemplate (@) { #{{{
+       my %params=@_;
+
+       my $template=$params{template};
+       
+       if ($template->query(name => "favicon")) {
+               $template->param(favicon => "favicon.ico");
+       }
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/fortune.pm b/1.33.2/IkiWiki/Plugin/fortune.pm
new file mode 100644 (file)
index 0000000..43f4526
--- /dev/null
@@ -0,0 +1,25 @@
+#!/usr/bin/perl
+# Include a fortune in a page
+package IkiWiki::Plugin::fortune;
+
+use IkiWiki;
+use warnings;
+use strict;
+
+sub import { #{{{
+       hook(type => "preprocess", id => "fortune", call => \&preprocess);
+} # }}}
+
+sub preprocess (@) { #{{{
+       $ENV{PATH}="$ENV{PATH}:/usr/games:/usr/local/games";
+       my $f = `fortune`;
+
+       if ($?) {
+               return "[[fortune failed]]";
+       }
+       else {
+               return "<pre>$f</pre>\n";
+       }
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/googlecalendar.pm b/1.33.2/IkiWiki/Plugin/googlecalendar.pm
new file mode 100644 (file)
index 0000000..dc0df0a
--- /dev/null
@@ -0,0 +1,45 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::googlecalendar;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import { #{{{
+       hook(type => "preprocess", id => "googlecalendar",
+               call => \&preprocess);
+       hook(type => "format", id => "googlecalendar",
+               call => \&format);
+} # }}}
+
+sub preprocess (@) { #{{{
+       my %params=@_;
+
+       # Parse the html, looking for the url to embed for the calendar.
+       # Avoid XSS attacks..
+       my ($url)=$params{html}=~m#iframe\s+src="http://www\.google\.com/calendar/embed\?([^"<>]+)"#;
+       if (! defined $url || ! length $url) {
+               return "[[googlecalendar failed to find url in html]]";
+       }
+       my ($height)=$params{html}=~m#height="(\d+)"#;
+       my ($width)=$params{html}=~m#width="(\d+)"#;
+
+       return "<div class=\"googlecalendar\" src=\"$url\" height=\"$height\" width=\"$width\"></div>";
+} # }}}
+
+sub format (@) { #{{{
+        my %params=@_;
+
+       $params{content}=~s/<div class=\"googlecalendar" src="([^"]+)" height="([^"]+)" width="([^"]+)"><\/div>/gencal($1,$2,$3)/eg;
+
+        return $params{content};
+} # }}}
+
+sub gencal ($$$) { #{{{
+       my $url=shift;
+       my $height=shift;
+       my $width=shift;
+       return qq{<iframe src="http://www.google.com/calendar/embed?$url" style=" border-width:0 " width="$width" frameborder="0" height="$height"></iframe>};
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/haiku.pm b/1.33.2/IkiWiki/Plugin/haiku.pm
new file mode 100644 (file)
index 0000000..fe8a782
--- /dev/null
@@ -0,0 +1,50 @@
+#!/usr/bin/perl
+# haiku generator plugin
+package IkiWiki::Plugin::haiku;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import { #{{{
+       hook(type => "preprocess", id => "haiku", call => \&preprocess);
+} # }}}
+
+sub preprocess (@) { #{{{
+       my %params=@_;
+
+       my $haiku;
+       eval q{use Coy};
+       if ($@ || ! Coy->can("Coy::with_haiku")) {
+               my @canned=(
+                       "The lack of a Coy:
+                        No darting, subtle haiku.
+                        Instead, canned tuna.
+                       ",
+                       "apt-get install Coy
+                        no, wait, that's not quite it
+                        instead: libcoy-perl
+                       ",
+                       "Coyly I'll do it,
+                        no code, count Five-Seven-Five
+                        to make a haiku.
+                       ",
+               );
+                                        
+               $haiku=$canned[rand @canned];
+       }
+       else {
+               $haiku=Coy::with_haiku($params{hint} ? $params{hint} : $params{page});
+               
+               # trim off other text
+               $haiku=~s/\s+-----\n//s;
+               $haiku=~s/\s+-----.*//s;
+       }
+               
+       $haiku=~s/^\s+//mg;
+       $haiku=~s/\n/<br>\n/mg;
+       
+       return "\n\n<blockquote>$haiku</blockquote>\n\n";
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/html.pm b/1.33.2/IkiWiki/Plugin/html.pm
new file mode 100644 (file)
index 0000000..4270a7e
--- /dev/null
@@ -0,0 +1,23 @@
+#!/usr/bin/perl
+# Raw html as a wiki page type.
+package IkiWiki::Plugin::html;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import { #{{{
+       hook(type => "htmlize", id => "html", call => \&htmlize);
+       hook(type => "htmlize", id => "htm", call => \&htmlize);
+
+       # ikiwiki defaults to skipping .html files as a security measure;
+       # make it process them so this plugin can take effect
+       $config{wiki_file_prune_regexp} =~ s/\|\\\.x\?html\?\$//;
+} # }}}
+
+sub htmlize (@) { #{{{
+       my %params=@_;
+       return $params{content};
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/htmlscrubber.pm b/1.33.2/IkiWiki/Plugin/htmlscrubber.pm
new file mode 100644 (file)
index 0000000..ae3ec44
--- /dev/null
@@ -0,0 +1,53 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::htmlscrubber;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import { #{{{
+       hook(type => "sanitize", id => "htmlscrubber", call => \&sanitize);
+} # }}}
+
+sub sanitize (@) { #{{{
+       my %params=@_;
+       return scrubber()->scrub($params{content});
+} # }}}
+
+my $_scrubber;
+sub scrubber { #{{{
+       return $_scrubber if defined $_scrubber;
+       
+       eval q{use HTML::Scrubber};
+       error($@) if $@;
+       # Lists based on http://feedparser.org/docs/html-sanitization.html
+       $_scrubber = HTML::Scrubber->new(
+               allow => [qw{
+                       a abbr acronym address area b big blockquote br
+                       button caption center cite code col colgroup dd del
+                       dfn dir div dl dt em fieldset font form h1 h2 h3 h4
+                       h5 h6 hr i img input ins kbd label legend li map
+                       menu ol optgroup option p pre q s samp select small
+                       span strike strong sub sup table tbody td textarea
+                       tfoot th thead tr tt u ul var
+               }],
+               default => [undef, { map { $_ => 1 } qw{
+                       abbr accept accept-charset accesskey action
+                       align alt axis border cellpadding cellspacing
+                       char charoff charset checked cite class
+                       clear cols colspan color compact coords
+                       datetime dir disabled enctype for frame
+                       headers height href hreflang hspace id ismap
+                       label lang longdesc maxlength media method
+                       multiple name nohref noshade nowrap prompt
+                       readonly rel rev rows rowspan rules scope
+                       selected shape size span src start summary
+                       tabindex target title type usemap valign
+                       value vspace width
+               }, "/" => 1, # emit proper <hr /> XHTML
+               }],
+       );
+       return $_scrubber;
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/htmltidy.pm b/1.33.2/IkiWiki/Plugin/htmltidy.pm
new file mode 100644 (file)
index 0000000..0609e72
--- /dev/null
@@ -0,0 +1,45 @@
+#!/usr/bin/perl
+# HTML Tidy plugin
+# requires 'tidy' binary, found in Debian or http://tidy.sf.net/
+# mostly a proof-of-concept on how to use external filters.
+# It is particularly useful when the html plugin is used.
+#
+# by Faidon Liambotis
+package IkiWiki::Plugin::htmltidy;
+
+use warnings;
+use strict;
+use IkiWiki;
+use IPC::Open2;
+
+sub import { #{{{
+       hook(type => "sanitize", id => "tidy", call => \&sanitize);
+} # }}}
+
+sub sanitize (@) { #{{{
+       my %params=@_;
+
+       my $pid;
+       my $sigpipe=0;
+       $SIG{PIPE}=sub { $sigpipe=1 };
+       $pid=open2(*IN, *OUT, 'tidy -quiet -asxhtml -utf8 --show-body-only yes --show-warnings no --tidy-mark no');
+       
+       # open2 doesn't respect "use open ':utf8'"
+       binmode (IN, ':utf8');
+       binmode (OUT, ':utf8'); 
+       
+       print OUT $params{content};
+       close OUT;
+
+       local $/ = undef;
+       my $ret=<IN>;
+       close IN;
+       waitpid $pid, 0;
+
+       return $params{content} if $sigpipe;
+       $SIG{PIPE}="DEFAULT";
+
+       return $ret;
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/img.pm b/1.33.2/IkiWiki/Plugin/img.pm
new file mode 100644 (file)
index 0000000..20893f5
--- /dev/null
@@ -0,0 +1,85 @@
+#!/usr/bin/perl
+# Ikiwiki enhanced image handling plugin
+# Christian Mock cm@tahina.priv.at 20061002
+package IkiWiki::Plugin::img;
+
+use warnings;
+use strict;
+use IkiWiki;
+use Image::Magick;
+
+my $convert = 'convert';
+
+my %imgdefaults;
+
+sub import { #{{{
+       hook(type => "preprocess", id => "img", call => \&preprocess);
+} #}}}
+
+sub preprocess (@) { #{{{
+       my ($image) = $_[0] =~ /$config{wiki_file_regexp}/; # untaint
+       my %params=@_;
+
+       if (! exists $imgdefaults{$params{page}}) {
+               $imgdefaults{$params{page}} = {};
+       }
+       my $size = $params{size} || $imgdefaults{$params{page}}->{size} || 'full';
+       my $alt = $params{alt} || $imgdefaults{$params{page}}->{alt} || '';
+
+       if ($image eq 'defaults') {
+               $imgdefaults{$params{page}} = {
+                       size => $size,
+                       alt => $alt,
+               };
+               return '';
+       }
+
+       add_depends($params{page}, $image);
+       my $file = bestlink($params{page}, $image) || return "[[img $image not found]]";
+
+       my $dir = IkiWiki::dirname($file);
+       my $base = IkiWiki::basename($file);
+       my $im = Image::Magick->new;
+       my $imglink;
+       my $r;
+
+       if ($size ne 'full') {
+               my ($w, $h) = ($size =~ /^(\d+)x(\d+)$/);
+               return "[[img bad size \"$size\"]]" unless (defined $w && defined $h);
+
+               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($file) >= -M $outfile)) {
+                       $r = $im->Read($outfile);
+                       return "[[img failed to read $outfile: $r]]" if $r;
+               }
+               else {
+                       $r = $im->Read(srcfile($file));
+                       return "[[img failed to read $file: $r]]" if $r;
+
+                       $r = $im->Resize(geometry => "${w}x${h}");
+                       return "[[img failed to resize: $r]]" if $r;
+
+                       my @blob = $im->ImageToBlob();
+                       writefile($imglink, $config{destdir}, $blob[0], 1);
+               }
+       }
+       else {
+               $r = $im->Read(srcfile($file));
+               return "[[img failed to read $file: $r]]" if $r;
+               $imglink = $file;
+       }
+
+       add_depends($imglink, $params{page});
+
+       return '<a href="'.
+               IkiWiki::abs2rel($file, IkiWiki::dirname($params{destpage})).
+               '"><img src="'.
+               IkiWiki::abs2rel($imglink, IkiWiki::dirname($params{destpage})).
+               '" alt="'.$alt.'" width="'.$im->Get("width").
+               '" height="'.$im->Get("height").'" /></a>';
+} #}}}
+
+1;
diff --git a/1.33.2/IkiWiki/Plugin/inline.pm b/1.33.2/IkiWiki/Plugin/inline.pm
new file mode 100644 (file)
index 0000000..c6c6c6a
--- /dev/null
@@ -0,0 +1,372 @@
+#!/usr/bin/perl
+# Page inlining and blogging.
+package IkiWiki::Plugin::inline;
+
+use warnings;
+use strict;
+use IkiWiki 1.00;
+use IkiWiki::Render; # for displaytime
+use URI;
+
+sub import { #{{{
+       hook(type => "preprocess", id => "inline", 
+               call => \&IkiWiki::preprocess_inline);
+       hook(type => "pagetemplate", id => "inline",
+               call => \&IkiWiki::pagetemplate_inline);
+       # Hook to change to do pinging since it's called late.
+       # This ensures each page only pings once and prevents slow
+       # pings interrupting page builds.
+       hook(type => "change", id => "inline", 
+               call => \&IkiWiki::pingurl);
+} # }}}
+
+# Back to ikiwiki namespace for the rest, this code is very much
+# internal to ikiwiki even though it's separated into a plugin.
+package IkiWiki;
+
+my %toping;
+my %feedlinks;
+
+sub yesno ($) { #{{{
+       my $val=shift;
+       return (defined $val && lc($val) eq "yes");
+} #}}}
+
+sub preprocess_inline (@) { #{{{
+       my %params=@_;
+       
+       if (! exists $params{pages}) {
+               return "";
+       }
+       my $raw=yesno($params{raw});
+       my $archive=yesno($params{archive});
+       my $rss=($config{rss} && exists $params{rss}) ? yesno($params{rss}) : $config{rss};
+       my $atom=($config{atom} && exists $params{atom}) ? yesno($params{atom}) : $config{atom};
+       my $feeds=exists $params{feeds} ? yesno($params{feeds}) : 1;
+       if (! exists $params{show} && ! $archive) {
+               $params{show}=10;
+       }
+       my $desc;
+       if (exists $params{description}) {
+               $desc = $params{description} 
+       } else {
+               $desc = $config{wikiname};
+       }
+       my $actions=yesno($params{actions});
+
+       my @list;
+       foreach my $page (keys %pagesources) {
+               next if $page eq $params{page};
+               if (pagespec_match($page, $params{pages})) {
+                       push @list, $page;
+               }
+       }
+
+       if (exists $params{sort} && $params{sort} eq 'title') {
+               @list=sort @list;
+       }
+       elsif (! exists $params{sort} || $params{sort} eq 'age') {
+               @list=sort { $pagectime{$b} <=> $pagectime{$a} } @list;
+       }
+       else {
+               return "unknown sort type $params{sort}";
+       }
+
+       if (exists $params{skip}) {
+               @list=@list[$params{skip} .. scalar @list - 1];
+       }
+       
+       if ($params{show} && @list > $params{show}) {
+               @list=@list[0..$params{show} - 1];
+       }
+
+       add_depends($params{page}, $params{pages});
+
+       my $rssurl=rsspage(basename($params{page}));
+       my $atomurl=atompage(basename($params{page}));
+       my $ret="";
+
+       if (exists $params{rootpage} && $config{cgiurl}) {
+               # Add a blog post form, with feed buttons.
+               my $formtemplate=template("blogpost.tmpl", blind_cache => 1);
+               $formtemplate->param(cgiurl => $config{cgiurl});
+               $formtemplate->param(rootpage => $params{rootpage});
+               $formtemplate->param(rssurl => $rssurl) if $feeds && $rss;
+               $formtemplate->param(atomurl => $atomurl) if $feeds && $atom;
+               $ret.=$formtemplate->output;
+       }
+       elsif ($feeds) {
+               # Add feed buttons.
+               my $linktemplate=template("feedlink.tmpl", blind_cache => 1);
+               $linktemplate->param(rssurl => $rssurl) if $rss;
+               $linktemplate->param(atomurl => $atomurl) if $atom;
+               $ret.=$linktemplate->output;
+       }
+       
+       my $template=template(
+               ($archive ? "inlinepagetitle.tmpl" : "inlinepage.tmpl"),
+               blind_cache => 1,
+       ) unless $raw;
+       
+       foreach my $page (@list) {
+               my $file = $pagesources{$page};
+               my $type = pagetype($file);
+               if (! $raw || ($raw && ! defined $type)) {
+                       # Get the content before populating the template,
+                       # since getting the content uses the same template
+                       # if inlines are nested.
+                       # TODO: if $archive=1, the only reason to do this
+                       # is to let the meta plugin get page title info; so stop
+                       # calling this next line then once the meta plugin can
+                       # store that accross runs (also tags plugin).
+                       my $content=get_inline_content($page, $params{destpage});
+                       # Don't use htmllink because this way the title is separate
+                       # and can be overridden by other plugins.
+                       my $link=bestlink($params{page}, $page);
+                       $link=htmlpage($link) if defined $type;
+                       $link=abs2rel($link, dirname($params{destpage}));
+                       $template->param(pageurl => $link);
+                       $template->param(title => pagetitle(basename($page)));
+                       $template->param(content => $content);
+                       $template->param(ctime => displaytime($pagectime{$page}));
+
+                       if ($actions) {
+                               my $file = $pagesources{$page};
+                               my $type = pagetype($file);
+                               if ($config{discussion}) {
+                                       $template->param(have_actions => 1);
+                                       $template->param(discussionlink => htmllink($page, $page, "Discussion", 1, 1));
+                               }
+                               if (length $config{cgiurl} && defined $type) {
+                                       $template->param(have_actions => 1);
+                                       $template->param(editurl => cgiurl(do => "edit", page => $page));
+                               }
+                       }
+
+                       run_hooks(pagetemplate => sub {
+                               shift->(page => $page, destpage => $params{page},
+                                       template => $template,);
+                       });
+
+                       $ret.=$template->output;
+                       $template->clear_params;
+               }
+               else {
+                       if (defined $type) {
+                               $ret.="\n".
+                                     linkify($page, $params{page},
+                                     preprocess($page, $params{page},
+                                     filter($page,
+                                     readfile(srcfile($file)))));
+                       }
+               }
+       }
+       
+       if ($feeds && $rss) {
+               will_render($params{page}, rsspage($params{page}));
+               writefile(rsspage($params{page}), $config{destdir},
+                       genfeed("rss", $rssurl, $desc, $params{page}, @list));
+               $toping{$params{page}}=1 unless $config{rebuild};
+               $feedlinks{$params{destpage}}=qq{<link rel="alternate" type="application/rss+xml" title="RSS" href="$rssurl" />};
+       }
+       if ($feeds && $atom) {
+               will_render($params{page}, atompage($params{page}));
+               writefile(atompage($params{page}), $config{destdir},
+                       genfeed("atom", $atomurl, $desc, $params{page}, @list));
+               $toping{$params{page}}=1 unless $config{rebuild};
+               $feedlinks{$params{destpage}}=qq{<link rel="alternate" type="application/atom+xml" title="Atom" href="$atomurl" />};
+       }
+       
+       return $ret;
+} #}}}
+
+sub pagetemplate_inline (@) { #{{{
+       my %params=@_;
+       my $page=$params{page};
+       my $template=$params{template};
+
+       $template->param(feedlinks => $feedlinks{$page})
+               if exists $feedlinks{$page} && $template->query(name => "feedlinks");
+} #}}}
+
+sub get_inline_content ($$) { #{{{
+       my $page=shift;
+       my $destpage=shift;
+       
+       my $file=$pagesources{$page};
+       my $type=pagetype($file);
+       if (defined $type) {
+               return htmlize($page, $type,
+                      linkify($page, $destpage,
+                      preprocess($page, $destpage,
+                      filter($page,
+                      readfile(srcfile($file))))));
+       }
+       else {
+               return "";
+       }
+} #}}}
+
+sub date_822 ($) { #{{{
+       my $time=shift;
+
+       eval q{use POSIX};
+       error($@) if $@;
+       my $lc_time= POSIX::setlocale(&POSIX::LC_TIME);
+       POSIX::setlocale(&POSIX::LC_TIME, "C");
+       my $ret=POSIX::strftime("%a, %d %b %Y %H:%M:%S %z", localtime($time));
+       POSIX::setlocale(&POSIX::LC_TIME, $lc_time);
+       return $ret;
+} #}}}
+
+sub date_3339 ($) { #{{{
+       my $time=shift;
+
+       eval q{use POSIX};
+       error($@) if $@;
+       my $lc_time= POSIX::setlocale(&POSIX::LC_TIME);
+       POSIX::setlocale(&POSIX::LC_TIME, "C");
+       my $ret=POSIX::strftime("%Y-%m-%dT%H:%M:%SZ", localtime($time));
+       POSIX::setlocale(&POSIX::LC_TIME, $lc_time);
+       return $ret;
+} #}}}
+
+sub absolute_urls ($$) { #{{{
+       # sucky sub because rss sucks
+       my $content=shift;
+       my $url=shift;
+
+       $url=~s/[^\/]+$//;
+       
+       $content=~s/<a\s+href="(?![^:]+:\/\/)([^"]+)"/<a href="$url$1"/ig;
+       $content=~s/<img\s+src="(?![^:]+:\/\/)([^"]+)"/<img src="$url$1"/ig;
+       return $content;
+} #}}}
+
+sub rsspage ($) { #{{{
+       my $page=shift;
+
+       return $page.".rss";
+} #}}}
+
+sub atompage ($) { #{{{
+       my $page=shift;
+
+       return $page.".atom";
+} #}}}
+
+sub genfeed ($$$$@) { #{{{
+       my $feedtype=shift;
+       my $feedurl=shift;
+       my $feeddesc=shift;
+       my $page=shift;
+       my @pages=@_;
+       
+       my $url=URI->new(encode_utf8($config{url}."/".htmlpage($page)));
+       
+       my $itemtemplate=template($feedtype."item.tmpl", blind_cache => 1);
+       my $content="";
+       my $lasttime = 0;
+       foreach my $p (@pages) {
+               my $u=URI->new(encode_utf8($config{url}."/".htmlpage($p)));
+
+               $itemtemplate->param(
+                       title => pagetitle(basename($p)),
+                       url => $u,
+                       permalink => $u,
+                       date_822 => date_822($pagectime{$p}),
+                       date_3339 => date_3339($pagectime{$p}),
+               );
+
+               my $pcontent = absolute_urls(get_inline_content($p, $page), $url);
+               if ($itemtemplate->query(name => "enclosure")) {
+                       my $file=$pagesources{$p};
+                       my $type=pagetype($file);
+                       if (defined $type) {
+                               $itemtemplate->param(content => $pcontent);
+                       }
+                       else {
+                               my ($a, $b, $c, $d, $e, $f, $g, $size) = stat(srcfile($file));
+                               my $mime="unknown";
+                               eval q{use File::MimeInfo};
+                               if (! $@) {
+                                       $mime = mimetype($file);
+                               }
+                               $itemtemplate->param(
+                                       enclosure => $u,
+                                       type => $mime,
+                                       length => $size,
+                               );
+                       }
+               }
+               else {
+                       $itemtemplate->param(content => $pcontent);
+               }
+
+               run_hooks(pagetemplate => sub {
+                       shift->(page => $p, destpage => $page,
+                               template => $itemtemplate);
+               });
+
+               $content.=$itemtemplate->output;
+               $itemtemplate->clear_params;
+
+               $lasttime = $pagectime{$p} if $pagectime{$p} > $lasttime;
+       }
+
+       my $template=template($feedtype."page.tmpl", blind_cache => 1);
+       $template->param(
+               title => $page ne "index" ? pagetitle($page) : $config{wikiname},
+               wikiname => $config{wikiname},
+               pageurl => $url,
+               content => $content,
+               feeddesc => $feeddesc,
+               feeddate => date_3339($lasttime),
+               feedurl => $feedurl,
+               version => $IkiWiki::version,
+       );
+       run_hooks(pagetemplate => sub {
+               shift->(page => $page, destpage => $page,
+                       template => $template);
+       });
+       
+       return $template->output;
+} #}}}
+
+sub pingurl (@) { #{{{
+       return unless $config{pingurl} && %toping;
+
+       eval q{require RPC::XML::Client};
+       if ($@) {
+               debug("RPC::XML::Client not found, not pinging");
+               return;
+       }
+
+       # TODO: daemonize here so slow pings don't slow down wiki updates
+
+       foreach my $page (keys %toping) {
+               my $title=pagetitle(basename($page));
+               my $url="$config{url}/".htmlpage($page);
+               foreach my $pingurl (@{$config{pingurl}}) {
+                       debug("Pinging $pingurl for $page");
+                       eval {
+                               my $client = RPC::XML::Client->new($pingurl);
+                               my $req = RPC::XML::request->new('weblogUpdates.ping',
+                               $title, $url);
+                               my $res = $client->send_request($req);
+                               if (! ref $res) {
+                                       debug("Did not receive response to ping");
+                               }
+                               my $r=$res->value;
+                               if (! exists $r->{flerror} || $r->{flerror}) {
+                                       debug("Ping rejected: ".(exists $r->{message} ? $r->{message} : "[unknown reason]"));
+                               }
+                       };
+                       if ($@) {
+                               debug "Ping failed: $@";
+                       }
+               }
+       }
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/linkmap.pm b/1.33.2/IkiWiki/Plugin/linkmap.pm
new file mode 100644 (file)
index 0000000..d7dffc9
--- /dev/null
@@ -0,0 +1,105 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::linkmap;
+
+use warnings;
+use strict;
+use IkiWiki;
+use IPC::Open2;
+
+sub import { #{{{
+       hook(type => "preprocess", id => "linkmap", call => \&preprocess);
+       hook(type => "format", id => "linkmap", call => \&format);
+} # }}}
+
+my $mapnum=0;
+my %maps;
+
+sub preprocess (@) { #{{{
+       my %params=@_;
+
+       $params{pages}="*" unless defined $params{pages};
+       
+       # Needs to update whenever a page is added or removed, so
+       # register a dependency.
+       add_depends($params{page}, $params{pages});
+       
+       # Can't just return the linkmap here, since the htmlscrubber
+       # scrubs out all <object> tags (with good reason!)
+       # Instead, insert a placeholder tag, which will be expanded during
+       # formatting.
+       $mapnum++;
+       $maps{$mapnum}=\%params;
+       return "<div class=\"linkmap$mapnum\"></div>";
+} # }}}
+
+sub format (@) { #{{{
+        my %params=@_;
+
+       $params{content}=~s/<div class=\"linkmap(\d+)"><\/div>/genmap($1)/eg;
+
+        return $params{content};
+} # }}}
+
+sub genmap ($) { #{{{
+       my $mapnum=shift;
+       return "" unless exists $maps{$mapnum};
+       my %params=%{$maps{$mapnum}};
+
+       # Get all the items to map.
+       my %mapitems = ();
+       foreach my $item (keys %links) {
+               if (pagespec_match($item, $params{pages})) {
+                       my $link=htmlpage($item);
+                       $link=IkiWiki::abs2rel($link, IkiWiki::dirname($params{page}));
+                       $mapitems{$item}=$link;
+               }
+       }
+
+       # Use ikiwiki's function to create the file, this makes sure needed
+       # subdirs are there and does some sanity checking.
+       will_render($params{page}, $params{page}.".png");
+       writefile($params{page}.".png", $config{destdir}, "");
+
+       # Run dot to create the graphic and get the map data.
+       my $pid;
+       my $sigpipe=0;;
+       $SIG{PIPE}=sub { $sigpipe=1 };
+       $pid=open2(*IN, *OUT, "dot -Tpng -o '$config{destdir}/$params{page}.png' -Tcmapx");
+       
+       # open2 doesn't respect "use open ':utf8'"
+       binmode (IN, ':utf8'); 
+       binmode (OUT, ':utf8'); 
+
+       print OUT "digraph linkmap$mapnum {\n";
+       print OUT "concentrate=true;\n";
+       print OUT "charset=\"utf-8\";\n";
+       print OUT "ratio=compress;\nsize=\"".($params{width}+0).", ".($params{height}+0)."\";\n"
+               if defined $params{width} and defined $params{height};
+       foreach my $item (keys %mapitems) {
+               print OUT "\"$item\" [shape=box,href=\"$mapitems{$item}\"];\n";
+               foreach my $link (map { bestlink($item, $_) } @{$links{$item}}) {
+                       print OUT "\"$item\" -> \"$link\";\n"
+                               if $mapitems{$link};
+               }
+       }
+       print OUT "}\n";
+       close OUT;
+
+       local $/=undef;
+       my $ret="<object data=\"".
+              IkiWiki::abs2rel("$params{page}.png", IkiWiki::dirname($params{page})).
+              "\" type=\"image/png\" usemap=\"#linkmap$mapnum\">\n".
+               <IN>.
+               "</object>";
+       close IN;
+       
+       waitpid $pid, 0;
+       $SIG{PIPE}="DEFAULT";
+       if ($sigpipe) {
+               return  "[[linkmap failed to run dot]]";
+       }
+
+       return $ret;
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/map.pm b/1.33.2/IkiWiki/Plugin/map.pm
new file mode 100644 (file)
index 0000000..96daf39
--- /dev/null
@@ -0,0 +1,64 @@
+#!/usr/bin/perl
+#
+# Produce a hierarchical map of links.
+#
+# by Alessandro Dotti Contra <alessandro@hyboria.org>
+#
+# Revision: 0.2
+package IkiWiki::Plugin::map;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import { #{{{
+       hook(type => "preprocess", id => "map", call => \&preprocess);
+} # }}}
+
+sub preprocess (@) { #{{{
+       my %params=@_;
+       $params{pages}="*" unless defined $params{pages};
+       
+       # Needs to update whenever a page is added or removed, so
+       # register a dependency.
+       add_depends($params{page}, $params{pages});
+       
+       # Get all the items to map.
+       my @mapitems = ();
+       foreach my $page (keys %links) {
+               if (pagespec_match($page, $params{pages})) {
+                       push @mapitems, $page;
+               }
+       }
+
+       # Create the map.
+       my $indent=0;
+       my $openli=0;
+       my $map = "<div class='map'>\n";
+       $map .= "<ul>\n";
+       foreach my $item (sort @mapitems) {
+               my $depth = ($item =~ tr/\//\//);
+               while ($depth < $indent) {
+                       $indent--;
+                       $map.="</li></ul>\n";
+               }
+               while ($depth > $indent) {
+                       $indent++;
+                       $map.="<ul>\n";
+                       $openli=0;
+               }
+               $map .= "</li>\n" if $openli;
+               $map .= "<li>"
+                       .htmllink($params{page}, $params{destpage}, $item) ."\n";
+               $openli=1;
+       }
+       while ($indent > 0) {
+               $indent--;
+               $map.="</li></ul>\n";
+       }
+       $map .= "</li></ul>\n";
+       $map .= "</div>\n";
+       return $map;
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/mdwn.pm b/1.33.2/IkiWiki/Plugin/mdwn.pm
new file mode 100644 (file)
index 0000000..625f77f
--- /dev/null
@@ -0,0 +1,54 @@
+#!/usr/bin/perl
+# Markdown markup language
+package IkiWiki::Plugin::mdwn;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import { #{{{
+       hook(type => "htmlize", id => "mdwn", call => \&htmlize);
+} # }}}
+
+my $markdown_sub;
+sub htmlize (@) { #{{{
+       my %params=@_;
+       my $content = $params{content};
+
+       if (! defined $markdown_sub) {
+               # Markdown is forked and splintered upstream and can be
+               # available in a variety of incompatible forms. Support
+               # them all.
+               no warnings 'once';
+               $blosxom::version="is a proper perl module too much to ask?";
+               use warnings 'all';
+
+               eval q{use Markdown};
+               if (! $@) {
+                       $markdown_sub=\&Markdown::Markdown;
+               }
+               else {
+                       eval q{use Text::Markdown};
+                       if (! $@) {
+                               $markdown_sub=\&Text::Markdown::Markdown;
+                       }
+                       else {
+                               do "/usr/bin/markdown" ||
+                                       error("failed to load Markdown.pm perl module ($@) or /usr/bin/markdown ($!)");
+                               $markdown_sub=\&Markdown::Markdown;
+                       }
+               }
+               require Encode;
+       }
+       
+       # Workaround for perl bug (#376329)
+       $content=Encode::encode_utf8($content);
+       $content=Encode::encode_utf8($content);
+       $content=&$markdown_sub($content);
+       $content=Encode::decode_utf8($content);
+       $content=Encode::decode_utf8($content);
+
+       return $content;
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/meta.pm b/1.33.2/IkiWiki/Plugin/meta.pm
new file mode 100644 (file)
index 0000000..f53fdb6
--- /dev/null
@@ -0,0 +1,98 @@
+#!/usr/bin/perl
+# Ikiwiki metadata plugin.
+package IkiWiki::Plugin::meta;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+my %meta;
+my %title;
+my %permalink;
+my %author;
+my %authorurl;
+
+sub import { #{{{
+       hook(type => "preprocess", id => "meta", call => \&preprocess, scan => 1);
+       hook(type => "filter", id => "meta", call => \&filter);
+       hook(type => "pagetemplate", id => "meta", call => \&pagetemplate);
+} # }}}
+
+sub filter (@) { #{{{
+       my %params=@_;
+       
+       $meta{$params{page}}='';
+
+       return $params{content};
+} # }}}
+
+sub preprocess (@) { #{{{
+       if (! @_) {
+               return "";
+       }
+       my %params=@_;
+       my $key=shift;
+       my $value=$params{$key};
+       delete $params{$key};
+       my $page=$params{page};
+       delete $params{page};
+       delete $params{destpage};
+
+       eval q{use HTML::Entities};
+       # Always dencode, even if encoding later, since it might not be
+       # fully encoded.
+       $value=decode_entities($value);
+
+       if ($key eq 'link') {
+               if (%params) {
+                       $meta{$page}.="<link href=\"".encode_entities($value)."\" ".
+                               join(" ", map { encode_entities($_)."=\"".encode_entities(decode_entities($params{$_}))."\"" } keys %params).
+                               " />\n";
+               }
+               else {
+                       # hidden WikiLink
+                       push @{$links{$page}}, $value;
+               }
+       }
+       elsif ($key eq 'title') {
+               $title{$page}=encode_entities($value);
+       }
+       elsif ($key eq 'permalink') {
+               $permalink{$page}=$value;
+               $meta{$page}.="<link rel=\"bookmark\" href=\"".encode_entities($value)."\" />\n";
+       }
+       else {
+               $meta{$page}.="<meta name=\"".encode_entities($key).
+                       "\" content=\"".encode_entities($value)."\" />\n";
+               if ($key eq 'author') {
+                       $author{$page}=$value;
+               }
+               elsif ($key eq 'authorurl') {
+                       $authorurl{$page}=$value;
+               }
+       }
+
+       return "";
+} # }}}
+
+sub pagetemplate (@) { #{{{
+       my %params=@_;
+        my $page=$params{page};
+        my $template=$params{template};
+
+       $template->param(meta => $meta{$page})
+               if exists $meta{$page} && $template->query(name => "meta");
+       if (exists $title{$page} && $template->query(name => "title")) {
+               $template->param(title => $title{$page});
+               $template->param(title_overridden => 1);
+       }
+       $template->param(permalink => $permalink{$page})
+               if exists $permalink{$page} && $template->query(name => "permalink");
+       $template->param(author => $author{$page})
+               if exists $author{$page} && $template->query(name => "author");
+       $template->param(authorurl => $authorurl{$page})
+               if exists $authorurl{$page} && $template->query(name => "authorurl");
+       
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/orphans.pm b/1.33.2/IkiWiki/Plugin/orphans.pm
new file mode 100644 (file)
index 0000000..3a8a795
--- /dev/null
@@ -0,0 +1,45 @@
+#!/usr/bin/perl
+# Provides a list of pages no other page links to.
+package IkiWiki::Plugin::orphans;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import { #{{{
+       hook(type => "preprocess", id => "orphans", call => \&preprocess);
+} # }}}
+
+sub preprocess (@) { #{{{
+       my %params=@_;
+       $params{pages}="*" unless defined $params{pages};
+       
+       # Needs to update whenever a page is added or removed, so
+       # register a dependency.
+       add_depends($params{page}, $params{pages});
+       
+       my %linkedto;
+       foreach my $p (keys %links) {
+               map { $linkedto{bestlink($p, $_)}=1 if length $_ }
+                       @{$links{$p}};
+       }
+       
+       my @orphans;
+       foreach my $page (keys %renderedfiles) {
+               next if $linkedto{$page};
+               next unless pagespec_match($page, $params{pages});
+               # If the page has a link to some other page, it's
+               # indirectly linked to a page via that page's backlinks.
+               next if grep { 
+                       length $_ &&
+                       ($_ !~ /\/Discussion$/i || ! $config{discussion}) &&
+                       bestlink($page, $_) !~ /^($page|)$/ 
+               } @{$links{$page}};
+               push @orphans, $page;
+       }
+       
+       return "All pages are linked to by other pages." unless @orphans;
+       return "<ul>\n".join("\n", map { "<li>".htmllink($params{page}, $params{destpage}, $_, 1)."</li>" } sort @orphans)."</ul>\n";
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/otl.pm b/1.33.2/IkiWiki/Plugin/otl.pm
new file mode 100644 (file)
index 0000000..3f34133
--- /dev/null
@@ -0,0 +1,90 @@
+#!/usr/bin/perl
+# outline markup
+package IkiWiki::Plugin::otl;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import { #{{{
+       hook(type => "filter", id => "otl", call => \&filter);
+       hook(type => "htmlize", id => "otl", call => \&htmlize);
+
+} # }}}
+
+sub filter (@) { #{{{
+       my %params=@_;
+        
+       # Munge up check boxes to look a little bit better. This is a hack.
+       my $checked=htmllink($params{page}, $params{page},
+               "smileys/star_on.png", 0, 0, "[X]");
+       my $unchecked=htmllink($params{page}, $params{page},
+               "smileys/star_off.png", 0, 0, "[_]");
+       $params{content}=~s/^(\s*)\[X\]\s/${1}$checked /mg;
+       $params{content}=~s/^(\s*)\[_\]\s/${1}$unchecked /mg;
+        
+       return $params{content};
+} # }}}
+
+sub htmlize (@) { #{{{
+       my %params=@_;
+
+       # Can't use open2 since otl2html doesn't play nice with buffering.
+       # Instead, fork off a child process that will run otl2html and feed
+       # it the content. Then read otl2html's response.
+
+       my $tries=10;
+       my $pid;
+       do {
+               $pid = open(KID_TO_READ, "-|");
+               unless (defined $pid) {
+                       $tries--;
+                       if ($tries < 1) {
+                               debug("failed to fork: $@");
+                               return $params{content};
+                       }
+               }
+       } until defined $pid;
+
+       if (! $pid) {
+               $tries=10;
+               $pid=undef;
+
+               do {
+                       $pid = open(KID_TO_WRITE, "|-");
+                       unless (defined $pid) {
+                               $tries--;
+                               if ($tries < 1) {
+                                       debug("failed to fork: $@");
+                                       print $params{content};
+                                       exit;
+                               }
+                       }
+               } until defined $pid;
+
+               if (! $pid) {
+                       if (! exec 'otl2html', '-S', '/dev/null', '-T', '/dev/stdin') {
+                               debug("failed to run otl2html: $@");
+                               print $params{content};
+                               exit;
+                       }
+               }
+
+               print KID_TO_WRITE $params{content};
+               close KID_TO_WRITE;
+               waitpid $pid, 0;
+               exit;
+       }
+       
+       local $/ = undef;
+       my $ret=<KID_TO_READ>;
+       close KID_TO_READ;
+       waitpid $pid, 0;
+
+       $ret=~s/.*<body>//s;
+       $ret=~s/<body>.*//s;
+       $ret=~s/<div class="Footer">.*//s;
+       return $ret;
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/pagecount.pm b/1.33.2/IkiWiki/Plugin/pagecount.pm
new file mode 100644 (file)
index 0000000..7ced159
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/perl
+# Provides [[pagecount ]] to count the number of pages.
+package IkiWiki::Plugin::pagecount;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import { #{{{
+       hook(type => "preprocess", id => "pagecount", call => \&preprocess);
+} # }}}
+
+sub preprocess (@) { #{{{
+       my %params=@_;
+       $params{pages}="*" unless defined $params{pages};
+       
+       # Needs to update count whenever a page is added or removed, so
+       # register a dependency.
+       add_depends($params{page}, $params{pages});
+       
+       my @pages=keys %pagesources;
+       return $#pages+1 if $params{pages} eq "*"; # optimisation
+       my $count=0;
+       foreach my $page (@pages) {
+               $count++ if pagespec_match($page, $params{pages});
+       }
+       return $count;
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/pagestats.pm b/1.33.2/IkiWiki/Plugin/pagestats.pm
new file mode 100644 (file)
index 0000000..0958f5a
--- /dev/null
@@ -0,0 +1,68 @@
+#!/usr/bin/perl
+#
+# Produce page statistics in various forms.
+#
+# Currently supported:
+#   cloud: produces statistics in the form of a del.icio.us-style tag cloud
+#          (default)
+#   table: produces a table with the number of backlinks for each page
+#
+# by Enrico Zini
+package IkiWiki::Plugin::pagestats;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+# Names of the HTML classes to use for the tag cloud
+our @classes = ('smallestPC', 'smallPC', 'normalPC', 'bigPC', 'biggestPC' );
+
+sub import { #{{{
+       hook(type => "preprocess", id => "pagestats", call => \&preprocess);
+} # }}}
+
+sub preprocess (@) { #{{{
+       my %params=@_;
+       $params{pages}="*" unless defined $params{pages};
+       my $style = ($params{style} or 'cloud');
+       
+       # Needs to update whenever a page is added or removed, so
+       # register a dependency.
+       add_depends($params{page}, $params{pages});
+       
+       my %counts;
+       my $max = 0;
+       foreach my $page (keys %links) {
+               if (pagespec_match($page, $params{pages})) {
+                       my @bl = IkiWiki::backlinks($page);
+                       $counts{$page} = scalar(@bl);
+                       $max = $counts{$page} if $counts{$page} > $max;
+               }
+       }
+
+       if ($style eq 'table') {
+               return "<table class='pageStats'>\n".
+                       join("\n", map {
+                               "<tr><td>".
+                               htmllink($params{page}, $params{destpage}, $_, 1).
+                               "</td><td>".$counts{$_}."</td></tr>"
+                       }
+                       sort { $counts{$b} <=> $counts{$a} } keys %counts).
+                       "\n</table>\n" ;
+       } else {
+               # In case of misspelling, default to a page cloud
+
+               my $res = "<div class='pagecloud'>\n";
+               foreach my $page (sort keys %counts) {
+                       my $class = $classes[$counts{$page} * scalar(@classes) / ($max + 1)];
+                       $res .= "<span class=\"$class\">".
+                               htmllink($params{page}, $params{destpage}, $page).
+                               "</span>\n";
+               }
+               $res .= "</div>\n";
+
+               return $res;
+       }
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/polygen.pm b/1.33.2/IkiWiki/Plugin/polygen.pm
new file mode 100644 (file)
index 0000000..966b6cb
--- /dev/null
@@ -0,0 +1,60 @@
+#!/usr/bin/perl
+#
+# Include polygen output in a page
+# 
+# by Enrico Zini
+package IkiWiki::Plugin::polygen;
+
+use warnings;
+use strict;
+use IkiWiki;
+use File::Find;
+
+sub import { #{{{
+       hook(type => "preprocess", id => "polygen", call => \&preprocess);
+} # }}}
+
+sub preprocess (@) { #{{{
+       my %params=@_;
+       my $grammar = ($params{grammar} or 'polygen');
+       my $symbol = ($params{symbol} or undef);
+
+       # Sanitize parameters
+       $grammar =~ IkiWiki::basename($grammar);
+       $grammar =~ s/[^A-Za-z0-9]//g;
+       $grammar =~ s/\.grm$//;
+       $grammar .= '.grm';
+       $symbol =~ s/[^A-Za-z0-9]//g if defined $symbol;
+       $symbol = IkiWiki::possibly_foolish_untaint($symbol) if defined $symbol;
+
+       my $grmfile = '/usr/share/polygen/ita/polygen.grm';
+       if (! -d '/usr/share/polygen') {
+               return "[[polygen not installed]]";
+       }
+       find({wanted => sub {
+                       if (substr($File::Find::name, -length($grammar)) eq $grammar) {
+                               $grmfile = IkiWiki::possibly_foolish_untaint($File::Find::name);
+                       }
+               },
+               no_chdir => 1,
+       }, '/usr/share/polygen');
+       
+       my $res;
+       if (defined $symbol) {
+               $res = `polygen -S $symbol $grmfile 2>/dev/null`;
+       }
+       else {
+               $res = `polygen $grmfile 2>/dev/null`;
+       }
+
+       if ($?) {
+               $res="[[polygen failed]]";
+       }
+
+       # Strip trainling spaces and newlines so that we flow well with the
+       # markdown text
+       $res =~ s/\s*$//;
+       return $res;
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/rst.pm b/1.33.2/IkiWiki/Plugin/rst.pm
new file mode 100644 (file)
index 0000000..afd60f6
--- /dev/null
@@ -0,0 +1,69 @@
+#!/usr/bin/perl
+# Very simple reStructuredText processor.
+#
+# This plugin calls python and requires python-docutils to transform the text
+# into html.
+#
+# Its main problem is that it does not support ikiwiki's WikiLinks nor
+# Preprocessor Directives.
+#
+# Probably Wikilinks and Preprocessor Directives should support a list of
+# extensions to process (i.e. the linkify function could be transformed into
+# reStructuredText instead of HTML using a hook on rst.py instead of the
+# current linkify function)
+#
+# by Sergio Talens-Oliag <sto@debian.org>
+
+package IkiWiki::Plugin::rst;
+
+use warnings;
+use strict;
+use IkiWiki;
+use IPC::Open2;
+
+# Simple python script, maybe it should be implemented using an external script.
+# The settings_overrides are given to avoid potential security risks when
+# reading external files or if raw html is included on rst pages.
+my $pyCmnd = "
+from docutils.core import publish_string;
+from sys import stdin;
+html = publish_string(stdin.read(), writer_name='html', 
+       settings_overrides = { 'halt_level': 6, 
+                              'file_insertion_enabled': 0,
+                              'raw_enabled': 0 }
+);
+print html[html.find('<body>')+6:html.find('</body>')].strip();
+";
+
+sub import { #{{{
+       hook(type => "htmlize", id => "rst", call => \&htmlize);
+} # }}}
+
+sub htmlize (@) { #{{{
+       my %params=@_;
+       my $content=$params{content};
+
+       my $pid;
+       my $sigpipe=0;
+       $SIG{PIPE}=sub { $sigpipe=1 };
+       $pid=open2(*IN, *OUT, "python", "-c",  $pyCmnd);
+       
+       # open2 doesn't respect "use open ':utf8'"
+       binmode (IN, ':utf8');
+       binmode (OUT, ':utf8');
+       
+       print OUT $content;
+       close OUT;
+
+       local $/ = undef;
+       my $ret=<IN>;
+       close IN;
+       waitpid $pid, 0;
+
+       return $content if $sigpipe;
+       $SIG{PIPE}="DEFAULT";
+
+       return $ret;
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/search.pm b/1.33.2/IkiWiki/Plugin/search.pm
new file mode 100644 (file)
index 0000000..3cfc301
--- /dev/null
@@ -0,0 +1,139 @@
+#!/usr/bin/perl
+# hyperestraier search engine plugin
+package IkiWiki::Plugin::search;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import { #{{{
+       hook(type => "getopt", id => "hyperestraier",
+               call => \&getopt);
+       hook(type => "checkconfig", id => "hyperestraier",
+               call => \&checkconfig);
+       hook(type => "pagetemplate", id => "hyperestraier",
+               call => \&pagetemplate);
+       hook(type => "delete", id => "hyperestraier",
+               call => \&delete);
+       hook(type => "change", id => "hyperestraier",
+               call => \&change);
+       hook(type => "cgi", id => "hyperestraier",
+               call => \&cgi);
+} # }}}
+
+sub getopt () { #{{{
+        eval q{use Getopt::Long};
+       error($@) if $@;
+        Getopt::Long::Configure('pass_through');
+        GetOptions("estseek=s" => \$config{estseek});
+} #}}}
+
+sub checkconfig () { #{{{
+       foreach my $required (qw(url cgiurl)) {
+               if (! length $config{$required}) {
+                       error("Must specify $required when using the search plugin\n");
+               }
+       }
+} #}}}
+
+my $form;
+sub pagetemplate (@) { #{{{
+       my %params=@_;
+       my $page=$params{page};
+       my $template=$params{template};
+
+       # Add search box to page header.
+       if ($template->query(name => "searchform")) {
+               if (! defined $form) {
+                       my $searchform = template("searchform.tmpl", blind_cache => 1);
+                       $searchform->param(searchaction => $config{cgiurl});
+                       $form=$searchform->output;
+               }
+
+               $template->param(searchform => $form);
+       }
+} #}}}
+
+sub delete (@) { #{{{
+       debug("cleaning hyperestraier search index");
+       estcmd("purge -cl");
+       estcfg();
+} #}}}
+
+sub change (@) { #{{{
+       debug("updating hyperestraier search index");
+       estcmd("gather -cm -bc -cl -sd",
+               map {
+                       Encode::encode_utf8($config{destdir}."/".$_)
+                               foreach @{$renderedfiles{pagename($_)}};
+               } @_
+       );
+       estcfg();
+} #}}}
+
+sub cgi ($) { #{{{
+       my $cgi=shift;
+
+       if (defined $cgi->param('phrase')) {
+               # only works for GET requests
+               chdir("$config{wikistatedir}/hyperestraier") || error("chdir: $!");
+               exec("./".IkiWiki::basename($config{cgiurl})) || error("estseek.cgi failed");
+       }
+} #}}}
+
+my $configured=0;
+sub estcfg () { #{{{
+       return if $configured;
+       $configured=1;
+       
+       my $estdir="$config{wikistatedir}/hyperestraier";
+       my $cgi=IkiWiki::basename($config{cgiurl});
+       $cgi=~s/\..*$//;
+       open(TEMPLATE, ">:utf8", "$estdir/$cgi.tmpl") ||
+               error("write $estdir/$cgi.tmpl: $!");
+       print TEMPLATE IkiWiki::misctemplate("search", 
+               "<!--ESTFORM-->\n\n<!--ESTRESULT-->\n\n<!--ESTINFO-->\n\n",
+               baseurl => IkiWiki::dirname($config{cgiurl})."/");
+       close TEMPLATE;
+       open(TEMPLATE, ">$estdir/$cgi.conf") ||
+               error("write $estdir/$cgi.conf: $!");
+       my $template=template("estseek.conf");
+       eval q{use Cwd 'abs_path'};
+       $template->param(
+               index => $estdir,
+               tmplfile => "$estdir/$cgi.tmpl",
+               destdir => abs_path($config{destdir}),
+               url => $config{url},
+       );
+       print TEMPLATE $template->output;
+       close TEMPLATE;
+       $cgi="$estdir/".IkiWiki::basename($config{cgiurl});
+       unlink($cgi);
+       my $estseek = defined $config{estseek} ? $config{estseek} : '/usr/lib/estraier/estseek.cgi';
+       symlink($estseek, $cgi) ||
+               error("symlink $estseek $cgi: $!");
+} # }}}
+
+sub estcmd ($;@) { #{{{
+       my @params=split(' ', shift);
+       push @params, "-cl", "$config{wikistatedir}/hyperestraier";
+       if (@_) {
+               push @params, "-";
+       }
+       
+       my $pid=open(CHILD, "|-");
+       if ($pid) {
+               # parent
+               foreach (@_) {
+                       print CHILD "$_\n";
+               }
+               close(CHILD) || error("estcmd @params exited nonzero: $?");
+       }
+       else {
+               # child
+               open(STDOUT, "/dev/null"); # shut it up (closing won't work)
+               exec("estcmd", @params) || error("can't run estcmd");
+       }
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/shortcut.pm b/1.33.2/IkiWiki/Plugin/shortcut.pm
new file mode 100644 (file)
index 0000000..d09d587
--- /dev/null
@@ -0,0 +1,58 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::shortcut;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import { #{{{
+       hook(type => "checkconfig", id => "shortcut", call => \&checkconfig);
+       hook(type => "preprocess", id => "shortcut", call => \&preprocess_shortcut);
+} #}}}
+
+sub checkconfig () { #{{{
+       # Preprocess the shortcuts page to get all the available shortcuts
+       # defined before other pages are rendered.
+       IkiWiki::preprocess("shortcuts", "shortcuts",
+               readfile(srcfile("shortcuts.mdwn")));
+} # }}}
+
+sub preprocess_shortcut (@) { #{{{
+       my %params=@_;
+
+       if (! defined $params{name} || ! defined $params{url}) {
+               return "[[shortcut missing name or url parameter]]";
+       }
+
+       hook(type => "preprocess", no_override => 1, id => $params{name},
+               call => sub { shortcut_expand($params{name}, $params{url}, @_) });
+
+       return "shortcut $params{name} points to $params{url}";
+} # }}}
+
+sub shortcut_expand ($$@) { #{{{
+       my $name=shift;
+       my $url=shift;
+       my %params=@_;
+
+       # Get params in original order.
+       my @params;
+       while (@_) {
+               my $key=shift;
+               my $value=shift;
+               push @params, $key if ! length $value;
+       }
+
+       # If the shortcuts page changes, all pages that use shortcuts will
+       # need to be updated.
+       add_depends($params{destpage}, "shortcuts");
+
+       my $text=join(" ", @params);
+       my $encoded_text=$text;
+       $encoded_text=~s/([^A-Za-z0-9])/sprintf("%%%02X", ord($1))/seg;
+       
+       $url=~s/\%s/$encoded_text/g;
+       return "<a href=\"$url\">$text</a>";
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/sidebar.pm b/1.33.2/IkiWiki/Plugin/sidebar.pm
new file mode 100644 (file)
index 0000000..da1f82b
--- /dev/null
@@ -0,0 +1,52 @@
+#!/usr/bin/perl
+# Sidebar plugin.
+# by Tuomo Valkonen <tuomov at iki dot fi>
+
+package IkiWiki::Plugin::sidebar;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import { #{{{
+       hook(type => "pagetemplate", id => "sidebar", call => \&pagetemplate);
+} # }}}
+
+sub sidebar_content ($) { #{{{
+       my $page=shift;
+       
+       my $sidebar_page=bestlink($page, "sidebar") || return;
+       my $sidebar_file=$pagesources{$sidebar_page} || return;
+       my $sidebar_type=pagetype($sidebar_file);
+       
+       if (defined $sidebar_type) {
+               # FIXME: This isn't quite right; it won't take into account
+               # adding a new sidebar page. So adding such a page
+               # currently requires a wiki rebuild.
+               add_depends($page, $sidebar_page);
+
+               my $content=readfile(srcfile($sidebar_file));
+               return unless length $content;
+               return IkiWiki::htmlize($page, $sidebar_type,
+                      IkiWiki::linkify($sidebar_page, $page,
+                      IkiWiki::preprocess($sidebar_page, $page,
+                      IkiWiki::filter($sidebar_page, $content))));
+       }
+
+} # }}}
+
+sub pagetemplate (@) { #{{{
+       my %params=@_;
+
+       my $page=$params{page};
+       my $template=$params{template};
+       
+       if ($template->query(name => "sidebar")) {
+               my $content=sidebar_content($page);
+               if (defined $content && length $content) {
+                       $template->param(sidebar => $content);
+               }
+       }
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/skeleton.pm b/1.33.2/IkiWiki/Plugin/skeleton.pm
new file mode 100644 (file)
index 0000000..acac16c
--- /dev/null
@@ -0,0 +1,102 @@
+#!/usr/bin/perl
+# Ikiwiki skeleton plugin. Replace "skeleton" with the name of your plugin
+# in the lines below, remove hooks you don't use, and flesh out the code to
+# make it do something.
+package IkiWiki::Plugin::skeleton;
+
+use warnings;
+use strict;
+use IkiWiki '1.00';
+
+sub import { #{{{
+       hook(type => "getopt", id => "skeleton",  call => \&getopt);
+       hook(type => "checkconfig", id => "skeleton", call => \&checkconfig);
+       hook(type => "preprocess", id => "skeleton", call => \&preprocess);
+       hook(type => "filter", id => "skeleton", call => \&filter);
+       hook(type => "htmlize", id => "skeleton", call => \&htmlize);
+       hook(type => "sanitize", id => "skeleton", call => \&sanitize);
+       hook(type => "format", id => "skeleton", call => \&format);
+       hook(type => "pagetemplate", id => "skeleton", call => \&pagetemplate);
+       hook(type => "delete", id => "skeleton", call => \&delete);
+       hook(type => "change", id => "skeleton", call => \&change);
+       hook(type => "cgi", id => "skeleton", call => \&cgi);
+       hook(type => "savestate", id => "savestate", call => \&savestate);
+} # }}}
+
+sub getopt () { #{{{
+       debug("skeleton plugin getopt");
+} #}}}
+
+sub checkconfig () { #{{{
+       debug("skeleton plugin checkconfig");
+} #}}}
+
+sub preprocess (@) { #{{{
+       my %params=@_;
+
+       return "skeleton plugin result";
+} # }}}
+
+sub filter (@) { #{{{
+       my %params=@_;
+       
+       debug("skeleton plugin running as filter");
+
+       return $params{content};
+} # }}}
+
+sub htmlize (@) { #{{{
+       my %params=@_;
+
+       debug("skeleton plugin running as htmlize");
+
+       return $params{content};
+} # }}}
+
+sub sanitize (@) { #{{{
+       my %params=@_;
+       
+       debug("skeleton plugin running as a sanitizer");
+
+       return $params{content};
+} # }}}
+
+sub format (@) { #{{{
+       my %params=@_;
+       
+       debug("skeleton plugin running as a formatter");
+
+       return $params{content};
+} # }}}
+
+sub pagetemplate (@) { #{{{
+       my %params=@_;
+       my $page=$params{page};
+       my $template=$params{template};
+       
+       debug("skeleton plugin running as a pagetemplate hook");
+} # }}}
+
+sub delete (@) { #{{{
+       my @files=@_;
+
+       debug("skeleton plugin told that files were deleted: @files");
+} #}}}
+
+sub change (@) { #{{{
+       my @files=@_;
+
+       debug("skeleton plugin told that changed files were rendered: @files");
+} #}}}
+
+sub cgi ($) { #{{{
+       my $cgi=shift;
+
+       debug("skeleton plugin running in cgi");
+} #}}}
+
+sub savestate () { #{{{
+       debug("skeleton plugin running in savestate");
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/smiley.pm b/1.33.2/IkiWiki/Plugin/smiley.pm
new file mode 100644 (file)
index 0000000..0c6f5d4
--- /dev/null
@@ -0,0 +1,44 @@
+#!/usr/bin/perl
+package IkiWiki::Plugin::smiley;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+my %smileys;
+my $smiley_regexp;
+
+sub import { #{{{
+       hook(type => "checkconfig", id => "smiley", call => \&setup);
+} # }}}
+
+sub setup () { #{{{
+       my $list=readfile(srcfile("smileys.mdwn"));
+       while ($list =~ m/^\s*\*\s+\\([^\s]+)\s+\[\[([^]]+)\]\]/mg) {
+               $smileys{$1}=$2;
+       }
+       
+       if (! %smileys) {
+               debug("failed to parse any smileys, disabling plugin");
+               return;
+       }
+       
+       hook(type => "filter", id => "smiley", call => \&filter);
+       # sort and reverse so that substrings come after longer strings
+       # that contain them, in most cases.
+       $smiley_regexp='('.join('|', map { quotemeta }
+               reverse sort keys %smileys).')';
+       #debug($smiley_regexp);
+} #}}}
+
+sub filter (@) { #{{{
+       my %params=@_;
+       
+       $params{content} =~ s{(?<=\s)(\\?)$smiley_regexp(?=\s)}{
+               $1 ? $2 : htmllink($params{page}, $params{page}, $smileys{$2}, 0, 0, $2)
+       }egs;
+       
+       return $params{content};
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/tag.pm b/1.33.2/IkiWiki/Plugin/tag.pm
new file mode 100644 (file)
index 0000000..ddb67c2
--- /dev/null
@@ -0,0 +1,74 @@
+#!/usr/bin/perl
+# Ikiwiki tag plugin.
+package IkiWiki::Plugin::tag;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+my %tags;
+
+sub import { #{{{
+       hook(type => "getopt", id => "tag", call => \&getopt);
+       hook(type => "preprocess", id => "tag", call => \&preprocess, scan => 1);
+       hook(type => "pagetemplate", id => "tag", call => \&pagetemplate);
+} # }}}
+
+sub getopt () { #{{{
+       eval q{use Getopt::Long};
+       error($@) if $@;
+       Getopt::Long::Configure('pass_through');
+       GetOptions("tagbase=s" => \$config{tagbase});
+} #}}}
+
+sub tagpage ($) { #{{{
+       my $tag=shift;
+                       
+       if (exists $config{tagbase} &&
+           defined $config{tagbase}) {
+               $tag=$config{tagbase}."/".$tag;
+       }
+
+       return $tag;
+} #}}}
+
+sub preprocess (@) { #{{{
+       if (! @_) {
+               return "";
+       }
+       my %params=@_;
+       my $page = $params{page};
+       delete $params{page};
+       delete $params{destpage};
+
+       $tags{$page} = [];
+       foreach my $tag (keys %params) {
+               push @{$tags{$page}}, $tag;
+               # hidden WikiLink
+               push @{$links{$page}}, tagpage($tag);
+       }
+               
+       return "";
+} # }}}
+
+sub pagetemplate (@) { #{{{
+       my %params=@_;
+       my $page=$params{page};
+       my $destpage=$params{destpage};
+       my $template=$params{template};
+
+       $template->param(tags => [
+               map { 
+                       link => htmllink($page, $destpage, tagpage($_))
+               }, @{$tags{$page}}
+       ]) if exists $tags{$page} && @{$tags{$page}} && $template->query(name => "tags");
+
+       if ($template->query(name => "pubdate")) {
+               # It's an rss template. Add any categories.
+               if (exists $tags{$page} && @{$tags{$page}}) {
+                       $template->param(categories => [map { category => $_ }, @{$tags{$page}}]);
+               }
+       }
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/template.pm b/1.33.2/IkiWiki/Plugin/template.pm
new file mode 100644 (file)
index 0000000..0957056
--- /dev/null
@@ -0,0 +1,57 @@
+#!/usr/bin/perl
+# Structured template plugin.
+package IkiWiki::Plugin::template;
+
+use warnings;
+use strict;
+use IkiWiki;
+use HTML::Template;
+use Encode;
+
+sub import { #{{{
+       hook(type => "preprocess", id => "template", call => \&preprocess);
+} # }}}
+
+sub preprocess (@) { #{{{
+       my %params=@_;
+
+       if (! exists $params{id}) {
+               return "[[template missing id parameter]]"
+       }
+
+       my $template_page="templates/$params{id}";
+       add_depends($params{page}, $template_page);
+
+       my $template_file=$pagesources{$template_page};
+       return "[[template ".
+              htmllink($params{page}, $params{destpage}, $template_page).
+              " not found]]"
+               unless defined $template_file;
+
+       my $template;
+       eval {
+               $template=HTML::Template->new(
+                       filter => sub {
+                               my $text_ref = shift;
+                               $$text_ref=&Encode::decode_utf8($$text_ref);
+                               chomp $$text_ref;
+                       },
+                       filename => srcfile($template_file),
+                               die_on_bad_params => 0,
+                       no_includes => 1,
+                       blind_cache => 1,
+               );
+       };
+       if ($@) {
+               return "[[template failed to process: $@]]";
+       }
+
+       foreach my $param (keys %params) {
+               $template->param($param => $params{$param});
+       }
+
+       return IkiWiki::preprocess($params{page}, $params{destpage},
+               $template->output);
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/toc.pm b/1.33.2/IkiWiki/Plugin/toc.pm
new file mode 100644 (file)
index 0000000..279eef0
--- /dev/null
@@ -0,0 +1,112 @@
+#!/usr/bin/perl
+# Table Of Contents generator
+package IkiWiki::Plugin::toc;
+
+use warnings;
+use strict;
+use IkiWiki;
+use HTML::Parser;
+
+sub import { #{{{
+       hook(type => "preprocess", id => "toc", call => \&preprocess);
+       hook(type => "format", id => "toc", call => \&format);
+} # }}}
+
+my %tocpages;
+
+sub preprocess (@) { #{{{
+       my %params=@_;
+
+       $params{levels}=1 unless exists $params{levels};
+
+       # It's too early to generate the toc here, so just record the
+       # info.
+       $tocpages{$params{destpage}}=\%params;
+
+       return "\n<div class=\"toc\"></div>\n";
+} # }}}
+
+sub format (@) { #{{{
+       my %params=@_;
+       my $content=$params{content};
+       
+       return $content unless exists $tocpages{$params{page}};
+       %params=%{$tocpages{$params{page}}};
+
+       my $p=HTML::Parser->new(api_version => 3);
+       my $page="";
+       my $index="";
+       my %anchors;
+       my $curlevel;
+       my $startlevel=0;
+       my $liststarted=0;
+       my $indent=sub { "\t" x $curlevel };
+       $p->handler(start => sub {
+               my $tagname=shift;
+               my $text=shift;
+               if ($tagname =~ /^h(\d+)$/i) {
+                       my $level=$1;
+                       my $anchor="index".++$anchors{$level}."h$level";
+                       $page.="$text<a name=\"$anchor\" />";
+       
+                       # Take the first header level seen as the topmost level,
+                       # even if there are higher levels seen later on.
+                       if (! $startlevel) {
+                               $startlevel=$level;
+                               $curlevel=$startlevel-1;
+                       }
+                       elsif ($level < $startlevel) {
+                               $level=$startlevel;
+                       }
+                       
+                       return if $level - $startlevel >= $params{levels};
+       
+                       if ($level > $curlevel) {
+                               while ($level > $curlevel + 1) {
+                                       $index.=&$indent."<ol>\n";
+                                       $curlevel++;
+                                       $index.=&$indent."<li class=\"L$curlevel\">\n";
+                               }
+                               $index.=&$indent."<ol>\n";
+                               $curlevel=$level;
+                               $liststarted=1;
+                       }
+                       elsif ($level < $curlevel) {
+                               while ($level < $curlevel) {
+                                       $index.=&$indent."</li>\n" if $curlevel;
+                                       $curlevel--;
+                                       $index.=&$indent."</ol>\n";
+                               }
+                               $liststarted=0;
+                       }
+       
+                       $p->handler(text => sub {
+                               $page.=join("", @_);
+                               $index.=&$indent."</li>\n" unless $liststarted;
+                               $liststarted=0;
+                               $index.=&$indent."<li class=\"L$curlevel\">".
+                                       "<a href=\"#$anchor\">".
+                                       join("", @_).
+                                       "</a>\n";
+                               $p->handler(text => undef);
+                       }, "dtext");
+               }
+               else {
+                       $page.=$text;
+               }
+       }, "tagname, text");
+       $p->handler(default => sub { $page.=join("", @_) }, "text");
+       $p->parse($content);
+       $p->eof;
+
+       while ($startlevel && $curlevel >= $startlevel) {
+               $index.=&$indent."</li>\n" if $curlevel;
+               $curlevel--;
+               $index.=&$indent."</ol>\n";
+       }
+
+       $page=~s/(<div class=\"toc\">)/$1\n$index/;
+       return $page;
+}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/typography.pm b/1.33.2/IkiWiki/Plugin/typography.pm
new file mode 100644 (file)
index 0000000..682dada
--- /dev/null
@@ -0,0 +1,22 @@
+#!/usr/bin/perl
+
+package IkiWiki::Plugin::typography;
+
+use warnings;
+use strict;
+use IkiWiki;
+
+sub import { #{{{
+       IkiWiki::hook(type => "sanitize", id => "typography", call => \&sanitize);
+} # }}}
+
+sub sanitize (@) { #{{{
+       my %params=@_;
+
+       eval q{use Text::Typography};
+       return $params{content} if $@;
+
+       return Text::Typography::typography($params{content});
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Plugin/wikitext.pm b/1.33.2/IkiWiki/Plugin/wikitext.pm
new file mode 100644 (file)
index 0000000..95182f8
--- /dev/null
@@ -0,0 +1,21 @@
+#!/usr/bin/perl
+# WikiText markup
+package IkiWiki::Plugin::wikitext;
+
+use warnings;
+use strict;
+use IkiWiki;
+use Text::WikiFormat;
+
+sub import { #{{{
+       hook(type => "htmlize", id => "wiki", call => \&htmlize);
+} # }}}
+
+sub htmlize (@) { #{{{
+       my %params=@_;
+       my $content = $params{content};
+
+       return Text::WikiFormat::format($content, undef, { implicit_links => 0 });
+} # }}}
+
+1
diff --git a/1.33.2/IkiWiki/Rcs/Stub.pm b/1.33.2/IkiWiki/Rcs/Stub.pm
new file mode 100644 (file)
index 0000000..e408d5a
--- /dev/null
@@ -0,0 +1,69 @@
+#!/usr/bin/perl
+# Stubs for no revision control.
+
+use warnings;
+use strict;
+use IkiWiki;
+
+package IkiWiki;
+
+sub rcs_update () {
+       # Update working directory to current version.
+       # (May be more complex for distributed RCS.)
+}
+
+sub rcs_prepedit ($) {
+       # Prepares to edit a file under revision control. Returns a token
+       # that must be passed into rcs_commit when the file is ready
+       # for committing.
+       # The file is relative to the srcdir.
+       return ""
+}
+
+sub rcs_commit ($$$) {
+       # Tries to commit the page; returns undef on _success_ and
+       # a version of the page with the rcs's conflict markers on failure.
+       # The file is relative to the srcdir.
+       return undef # success
+}
+
+sub rcs_add ($) {
+       # Add a file. The filename is relative to the root of the srcdir.
+}
+
+sub rcs_recentchanges ($) {
+       # Examine the RCS history and generate a list of recent changes.
+       # The data structure returned for each change is:
+       # {
+       #       user => # name of user who made the change,
+       #       committype => # either "web" or the name of the rcs,
+       #       when => # time when the change was made,
+       #       message => [
+       #               { line => "commit message line" },
+       #               { line => "commit message line" },
+       #               # etc,
+       #       ],
+       #       pages => [
+       #               {
+       #                       page => # name of page changed,
+       #                       diffurl => # optional url to a diff showing 
+       #                                  # the changes,
+       #               },
+       #               # repeat for each page changed in this commit,
+       #       ],
+       # }
+}
+
+sub rcs_notify () {
+       # This function is called when a change is committed to the wiki,
+       # and ikiwiki is running as a post-commit hook from the RCS.
+       # It should examine the repository to somehow determine what pages
+       # changed, and then send emails to users subscribed to those pages.
+}
+
+sub rcs_getctime ($) {
+       # Optional, used to get the page creation time from the RCS.
+       error "getctime not implemented";
+}
+
+1
diff --git a/1.33.2/IkiWiki/Rcs/git.pm b/1.33.2/IkiWiki/Rcs/git.pm
new file mode 100644 (file)
index 0000000..c8b5adc
--- /dev/null
@@ -0,0 +1,486 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+use IkiWiki;
+use Encode;
+use open qw{:utf8 :std};
+
+package IkiWiki;
+
+my $origin_branch    = 'origin';            # Git ref for main repository
+my $master_branch    = 'master';            # working branch
+my $sha1_pattern     = qr/[0-9a-fA-F]{40}/; # pattern to validate Git sha1sums
+my $dummy_commit_msg = 'dummy commit';      # message to skip in recent changes
+my $web_commit_msg   = qr/^web commit (by (\w+)|from (\d+\.\d+\.\d+\.\d+)):?(.*)/;
+
+sub _safe_git (&@) { #{{{
+       # Start a child process safely without resorting /bin/sh.
+       # Return command output or success state (in scalar context).
+
+       my ($error_handler, @cmdline) = @_;
+
+       my $pid = open my $OUT, "-|";
+
+       error("Cannot fork: $!") if !defined $pid;
+
+       if (!$pid) {
+               # In child.
+               open STDERR, ">&STDOUT"
+                   or error("Cannot dup STDOUT: $!");
+               # Git commands want to be in wc.
+               chdir $config{srcdir}
+                   or error("Cannot chdir to $config{srcdir}: $!");
+               exec @cmdline or error("Cannot exec '@cmdline': $!");
+       }
+       # In parent.
+
+       my @lines;
+       while (<$OUT>) {
+               chomp;
+               push @lines, $_;
+       }
+
+       close $OUT;
+
+       ($error_handler || sub { })->("'@cmdline' failed: $!") if $?;
+
+       return wantarray ? @lines : ($? == 0);
+}
+# Convenient wrappers.
+sub run_or_die ($@) { _safe_git(\&error, @_) }
+sub run_or_cry ($@) { _safe_git(sub { warn @_ },  @_) }
+sub run_or_non ($@) { _safe_git(undef,            @_) }
+#}}}
+
+sub _merge_past ($$$) { #{{{
+       # Unlike with Subversion, Git cannot make a 'svn merge -rN:M file'.
+       # Git merge commands work with the committed changes, except in the
+       # implicit case of '-m' of git-checkout(1).  So we should invent a
+       # kludge here.  In principle, we need to create a throw-away branch
+       # in preparing for the merge itself.  Since branches are cheap (and
+       # branching is fast), this shouldn't cost high.
+       #
+       # The main problem is the presence of _uncommitted_ local changes.  One
+       # possible approach to get rid of this situation could be that we first
+       # make a temporary commit in the master branch and later restore the
+       # initial state (this is possible since Git has the ability to undo a
+       # commit, i.e. 'git-reset --soft HEAD^').  The method can be summarized
+       # as follows:
+       #
+       #       - create a diff of HEAD:current-sha1
+       #       - dummy commit
+       #       - create a dummy branch and switch to it
+       #       - rewind to past (reset --hard to the current-sha1)
+       #       - apply the diff and commit
+       #       - switch to master and do the merge with the dummy branch
+       #       - make a soft reset (undo the last commit of master)
+       #
+       # The above method has some drawbacks: (1) it needs a redundant commit
+       # just to get rid of local changes, (2) somewhat slow because of the
+       # required system forks.  Until someone points a more straight method
+       # (which I would be grateful) I have implemented an alternative method.
+       # In this approach, we hide all the modified files from Git by renaming
+       # them (using the 'rename' builtin) and later restore those files in
+       # the throw-away branch (that is, we put the files themselves instead
+       # of applying a patch).
+
+       my ($sha1, $file, $message) = @_;
+
+       my @undo;      # undo stack for cleanup in case of an error
+       my $conflict;  # file content with conflict markers
+
+       eval {
+               # Hide local changes from Git by renaming the modified file.
+               # Relative paths must be converted to absolute for renaming.
+               my ($target, $hidden) = (
+                   "$config{srcdir}/${file}", "$config{srcdir}/${file}.${sha1}"
+               );
+               rename($target, $hidden)
+                   or error("rename '$target' to '$hidden' failed: $!");
+               # Ensure to restore the renamed file on error.
+               push @undo, sub {
+                       return if ! -e "$hidden"; # already renamed
+                       rename($hidden, $target)
+                           or warn "rename '$hidden' to '$target' failed: $!";
+               };
+
+               my $branch = "throw_away_${sha1}"; # supposed to be unique
+
+               # Create a throw-away branch and rewind backward.
+               push @undo, sub { run_or_cry('git-branch', '-D', $branch) };
+               run_or_die('git-branch', $branch, $sha1);
+
+               # Switch to throw-away branch for the merge operation.
+               push @undo, sub {
+                       if (!run_or_cry('git-checkout', $master_branch)) {
+                               run_or_cry('git-checkout','-f',$master_branch);
+                       }
+               };
+               run_or_die('git-checkout', $branch);
+
+               # Put the modified file in _this_ branch.
+               rename($hidden, $target)
+                   or error("rename '$hidden' to '$target' failed: $!");
+
+               # _Silently_ commit all modifications in the current branch.
+               run_or_non('git-commit', '-m', $message, '-a');
+               # ... and re-switch to master.
+               run_or_die('git-checkout', $master_branch);
+
+               # Attempt to merge without complaining.
+               if (!run_or_non('git-pull', '--no-commit', '.', $branch)) {
+                       $conflict = readfile($target);
+                       run_or_die('git-reset', '--hard');
+               }
+       };
+       my $failure = $@;
+
+       # Process undo stack (in reverse order).  By policy cleanup
+       # actions should normally print a warning on failure.
+       while (my $handle = pop @undo) {
+               $handle->();
+       }
+
+       error("Git merge failed!\n$failure\n") if $failure;
+
+       return $conflict;
+} #}}}
+
+sub _parse_diff_tree (@) { #{{{
+       # Parse the raw diff tree chunk and return the info hash.
+       # See git-diff-tree(1) for the syntax.
+
+       my ($dt_ref) = @_;
+
+       # End of stream?
+       return if !defined @{ $dt_ref } || !length @{ $dt_ref }[0];
+
+       my %ci;
+       # Header line.
+       HEADER: while (my $line = shift @{ $dt_ref }) {
+               return if $line !~ m/^(.+) ($sha1_pattern)/;
+
+               my $sha1 = $1;
+               $ci{'sha1'} = $sha1;
+               last HEADER;
+       }
+
+       # Identification lines for the commit.
+       IDENT: while (my $line = shift @{ $dt_ref }) {
+               # Regexps are semi-stolen from gitweb.cgi.
+               if ($line =~ m/^tree ([0-9a-fA-F]{40})$/) {
+                       $ci{'tree'} = $1;
+               } elsif ($line =~ m/^parent ([0-9a-fA-F]{40})$/) {
+                       # XXX: collecting in reverse order
+                       push @{ $ci{'parents'} }, $1;
+               } elsif ($line =~ m/^(author|committer) (.*) ([0-9]+) (.*)$/) {
+                       my ($who, $name, $epoch, $tz) =
+                          ($1,   $2,    $3,     $4 );
+
+                       $ci{  $who          } = $name;
+                       $ci{ "${who}_epoch" } = $epoch;
+                       $ci{ "${who}_tz"    } = $tz;
+
+                       if ($name =~ m/^([^<]+) <([^@]+)/) {
+                               my ($fullname, $username) = ($1, $2);
+                               $ci{"${who}_fullname"}    = $fullname;
+                               $ci{"${who}_username"}    = $username;
+                       } else {
+                               $ci{"${who}_fullname"} =
+                                       $ci{"${who}_username"} = $name;
+                       }
+               } elsif ($line =~ m/^$/) {
+                       # Trailing empty line signals next section.
+                       last IDENT;
+               }
+       }
+
+       error("No 'tree' or 'parents' seen in diff-tree output")
+           if !defined $ci{'tree'} || !defined $ci{'parents'};
+
+       $ci{'parent'} = @{ $ci{'parents'} }[0];
+
+       # Commit message.
+       COMMENT: while (my $line = shift @{ $dt_ref }) {
+               if ($line =~ m/^$/) {
+                       # Trailing empty line signals next section.
+                       last COMMENT;
+               };
+               $line =~ s/^    //;
+               push @{ $ci{'comment'} }, $line;
+       }
+
+       # Modified files.
+       FILE: while (my $line = shift @{ $dt_ref }) {
+               if ($line =~ m{^:
+                       ([0-7]{6})[ ]      # from mode
+                       ([0-7]{6})[ ]      # to mode
+                       ($sha1_pattern)[ ] # from sha1
+                       ($sha1_pattern)[ ] # to sha1
+                       (.)                # status
+                       ([0-9]{0,3})\t     # similarity
+                       (.*)               # file
+               $}xo) {
+                       my ($sha1_from, $sha1_to, $file) =
+                          ($3,         $4,       $7   );
+
+                       if ($file =~ m/^"(.*)"$/) {
+                               ($file=$1) =~ s/\\([0-7]{1,3})/chr(oct($1))/eg;
+                       }
+                       if (length $file) {
+                               push @{ $ci{'details'} }, {
+                                       'file'      => decode_utf8($file),
+                                       'sha1_from' => $sha1_from,
+                                       'sha1_to'   => $sha1_to,
+                               };
+                       }
+                       next FILE;
+               };
+               last FILE;
+       }
+
+       warn "No detail in diff-tree output" if !defined $ci{'details'};
+
+       return \%ci;
+} #}}}
+
+sub git_commit_info (;$$) { #{{{
+       # Return an array of commit info hashes of num commits (default: 1)
+       # starting from the given sha1sum (default: HEAD).
+
+       my ($sha1, $num) = @_;
+
+       $num ||= 1;
+
+       my @raw_lines =
+           run_or_die(qq{git-rev-list --max-count=$num $sha1 |
+                         git-diff-tree --stdin --pretty=raw -M -r});
+
+       my @ci;
+       while (my $parsed = _parse_diff_tree(\@raw_lines)) {
+               push @ci, $parsed;
+       }
+
+       warn "Cannot parse commit info for '$sha1' commit" if !@ci;
+
+       return wantarray ? @ci : $ci[0];
+} #}}}
+
+sub git_sha1 (;$) { #{{{
+       # Return head sha1sum (of given file).
+
+       my $file = shift || q{--};
+
+       # Ignore error since a non-existing file might be given.
+       my ($sha1) = run_or_non('git-rev-list', '--max-count=1', 'HEAD', $file);
+       if ($sha1) {
+               ($sha1) = $sha1 =~ m/($sha1_pattern)/; # sha1 is untainted now
+       } else { debug("Empty sha1sum for '$file'.") }
+       return defined $sha1 ? $sha1 : q{};
+} #}}}
+
+sub rcs_update () { #{{{
+       # Update working directory.
+
+       run_or_cry('git-pull', $origin_branch);
+} #}}}
+
+sub rcs_prepedit ($) { #{{{
+       # Return the commit sha1sum of the file when editing begins.
+       # This will be later used in rcs_commit if a merge is required.
+
+       my ($file) = @_;
+
+       return git_sha1($file);
+} #}}}
+
+sub rcs_commit ($$$) { #{{{
+       # Try to commit the page; returns undef on _success_ and
+       # a version of the page with the rcs's conflict markers on
+       # failure.
+
+       my ($file, $message, $rcstoken) = @_;
+
+       # XXX: Wiki directory is in the unlocked state when starting this
+       # action.  But it takes time for a Git process to finish its job
+       # (especially if a merge required), so we must re-lock to prevent
+       # race conditions.  Only when the time of the real commit action
+       # (i.e. git-push(1)) comes, we'll unlock the directory.
+       lockwiki();
+
+       # Check to see if the page has been changed by someone else since
+       # rcs_prepedit was called.
+       my $cur    = git_sha1($file);
+       my ($prev) = $rcstoken =~ /^($sha1_pattern)$/; # untaint
+
+       if (defined $cur && defined $prev && $cur ne $prev) {
+               my $conflict = _merge_past($prev, $file, $dummy_commit_msg);
+               return $conflict if defined $conflict;
+       }
+
+       # git-commit(1) returns non-zero if file has not been really changed.
+       # so we should ignore its exit status (hence run_or_non).
+       $message = possibly_foolish_untaint($message);
+       if (run_or_non('git-commit', '-m', $message, '-i', $file)) {
+               unlockwiki();
+               run_or_cry('git-push', $origin_branch);
+       }
+
+       return undef; # success
+} #}}}
+
+sub rcs_add ($) { # {{{
+       # Add file to archive.
+
+       my ($file) = @_;
+
+       run_or_cry('git-add', $file);
+} #}}}
+
+sub rcs_recentchanges ($) { #{{{
+       # List of recent changes.
+
+       my ($num) = @_;
+
+       eval q{use Date::Parse};
+       error($@) if $@;
+
+       my ($sha1, $type, $when, $diffurl, $user, @pages, @message, @rets);
+       INFO: foreach my $ci (git_commit_info('HEAD', $num)) {
+               my $title = @{ $ci->{'comment'} }[0];
+
+               # Skip redundant commits.
+               next INFO if ($title eq $dummy_commit_msg);
+
+               $sha1 = $ci->{'sha1'};
+               $type = "web";
+               $when = time - $ci->{'author_epoch'};
+
+               DETAIL: foreach my $detail (@{ $ci->{'details'} }) {
+                       my $diffurl = $config{'diffurl'};
+                       my $file    = $detail->{'file'};
+
+                       $diffurl =~ s/\[\[file\]\]/$file/go;
+                       $diffurl =~ s/\[\[sha1_parent\]\]/$ci->{'parent'}/go;
+                       $diffurl =~ s/\[\[sha1_from\]\]/$detail->{'sha1_from'}/go;
+                       $diffurl =~ s/\[\[sha1_to\]\]/$detail->{'sha1_to'}/go;
+
+                       push @pages, {
+                               page => pagename($file),
+                               diffurl => $diffurl,
+                       };
+               }
+
+               push @message, { line => $title };
+
+               if (defined $message[0] &&
+                   $message[0]->{line} =~ m/$web_commit_msg/) {
+                       $user=defined $2 ? "$2" : "$3";
+                       $message[0]->{line}=$4;
+               } else {
+                       $type ="git";
+                       $user = $ci->{'author_username'};
+               }
+
+               push @rets, {
+                       rev        => $sha1,
+                       user       => $user,
+                       committype => $type,
+                       when       => $when,
+                       message    => [@message],
+                       pages      => [@pages],
+               } if @pages;
+
+               $sha1 = $type = $when = $diffurl = $user = undef;
+               @pages = @message = ();
+       }
+
+       return @rets;
+} #}}}
+
+sub rcs_notify () { #{{{
+       # Send notification mail to subscribed users.
+       #
+       # In usual Git usage, hooks/update script is presumed to send
+       # notification mails (see git-receive-pack(1)).  But we prefer
+       # hooks/post-update to support IkiWiki commits coming from a
+       # cloned repository (through command line) because post-update
+       # is called _after_ each ref in repository is updated (update
+       # hook is called _before_ the repository is updated).  Since
+       # post-update hook does not accept command line arguments, we
+       # don't have an $ENV variable in this function.
+       #
+       # Here, we rely on a simple fact: we can extract all parts of the
+       # notification content by parsing the "HEAD" commit (which also
+       # triggers a refresh of IkiWiki pages) and we can obtain the diff
+       # by comparing HEAD and HEAD^ (the previous commit).
+
+       my $sha1 = 'HEAD'; # the commit which triggers this action
+
+       my $ci = git_commit_info($sha1);
+       return if !defined $ci;
+
+       my @changed_pages = map { $_->{'file'} } @{ $ci->{'details'} };
+
+       my ($user, $message);
+       if (@{ $ci->{'comment'} }[0] =~ m/$web_commit_msg/) {
+               $user    = defined $2 ? "$2" : "$3";
+               $message = $4;
+       } else {
+               $user    = $ci->{'author_username'};
+               $message = join "\n", @{ $ci->{'comment'} };
+       }
+
+       require IkiWiki::UserInfo;
+       my @email_recipients = commit_notify_list($user, @changed_pages);
+       return if !@email_recipients;
+
+       # TODO: if a commit spans multiple pages, this will send
+       # subscribers a diff that might contain pages they did not
+       # sign up for. Should separate the diff per page and
+       # reassemble into one mail with just the pages subscribed to.
+       my $diff = join "\n", run_or_die('git-diff', "${sha1}^", $sha1);
+
+       my $subject = "$config{wikiname} update of ";
+       if (@changed_pages > 2) {
+               $subject .= "$changed_pages[0] $changed_pages[1] etc";
+       } else {
+               $subject .= join " ", @changed_pages;
+       }
+       $subject .= " by $user";
+
+       my $template = template("notifymail.tmpl");
+       $template->param(
+               wikiname => $config{wikiname},
+               diff     => $diff,
+               user     => $user,
+               message  => $message,
+       );
+
+       eval q{use Mail::Sendmail};
+       error($@) if $@;
+       foreach my $email (@email_recipients) {
+               sendmail(
+                       To      => $email,
+                       From    => "$config{wikiname} <$config{adminemail}>",
+                       Subject => $subject,
+                       Message => $template->output,
+               ) or error("Failed to send update notification mail: $!");
+       }
+} #}}}
+
+sub rcs_getctime ($) { #{{{
+       # Get the ctime of file.
+
+       my ($file) = @_;
+
+       my $sha1  = git_sha1($file);
+       my $ci    = git_commit_info($sha1);
+       my $ctime = $ci->{'author_epoch'};
+       debug("ctime for '$file': ". localtime($ctime) . "\n");
+
+       return $ctime;
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/Rcs/mercurial.pm b/1.33.2/IkiWiki/Rcs/mercurial.pm
new file mode 100644 (file)
index 0000000..36972c5
--- /dev/null
@@ -0,0 +1,144 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+use IkiWiki;
+use Encode;
+use open qw{:utf8 :std};
+
+package IkiWiki;
+
+sub mercurial_log($) {
+       my $out = shift;
+       my @infos;
+
+       while (<$out>) {
+               my $line = $_;
+               my ($key, $value);
+
+               if (/^description:/) {
+                       $key = "description";
+                       $value = "";
+
+                       # slurp everything as the description text 
+                       # until the next changeset
+                       while (<$out>) {
+                               if (/^changeset: /) {
+                                       $line = $_;
+                                       last;
+                               }
+
+                               $value .= $_;
+                       }
+
+                       local $/ = "";
+                       chomp $value;
+                       $infos[$#infos]{$key} = $value;
+               }
+
+               chomp $line;
+               ($key, $value) = split /: +/, $line, 2;
+
+               if ($key eq "changeset") {
+                       push @infos, {};
+
+                       # remove the revision index, which is strictly 
+                       # local to the repository
+                       $value =~ s/^\d+://;
+               }
+
+               $infos[$#infos]{$key} = $value;
+       }
+       close $out;
+
+       return @infos;
+}
+
+sub rcs_update () { #{{{
+       my @cmdline = ("hg", "-R", "$config{srcdir}", "update");
+       if (system(@cmdline) != 0) {
+               warn "'@cmdline' failed: $!";
+       }
+} #}}}
+
+sub rcs_prepedit ($) { #{{{
+       return "";
+} #}}}
+
+sub rcs_commit ($$$) { #{{{
+       my ($file, $message, $rcstoken) = @_;
+
+       $message = possibly_foolish_untaint($message);
+
+       my @cmdline = ("hg", "-R", "$config{srcdir}", "commit", "-m", "$message");
+       if (system(@cmdline) != 0) {
+               warn "'@cmdline' failed: $!";
+       }
+
+       return undef; # success
+} #}}}
+
+sub rcs_add ($) { # {{{
+       my ($file) = @_;
+
+       my @cmdline = ("hg", "-R", "$config{srcdir}", "add", "$file");
+       if (system(@cmdline) != 0) {
+               warn "'@cmdline' failed: $!";
+       }
+} #}}}
+
+sub rcs_recentchanges ($) { #{{{
+       my ($num) = @_;
+
+       eval q{use CGI 'escapeHTML'};
+       error($@) if $@;
+
+       my @cmdline = ("hg", "-R", $config{srcdir}, "log", "-v", "-l", $num);
+       open (my $out, "@cmdline |");
+
+       my @ret;
+       foreach my $info (mercurial_log($out)) {
+               my @pages = ();
+               my @message = ();
+        
+               foreach my $msgline (split(/\n/, $info->{description})) {
+                       push @message, { line => $msgline };
+               }
+
+               foreach my $file (split / /,$info->{files}) {
+                       my $diffurl = $config{'diffurl'};
+                       $diffurl =~ s/\[\[file\]\]/$file/go;
+                       $diffurl =~ s/\[\[r2\]\]/$info->{changeset}/go;
+
+                       push @pages, {
+                               page => pagename($file),
+                               diffurl => $diffurl,
+                       };
+               }
+
+               my $user = $info->{"user"};
+               $user =~ s/\s*<.*>\s*$//;
+               $user =~ s/^\s*//;
+
+               push @ret, {
+                       rev        => $info->{"changeset"},
+                       user       => $user,
+                       committype => "mercurial",
+                       when       => $info->{"date"},
+                       message    => [@message],
+                       pages      => [@pages],
+               };
+       }
+
+       return @ret;
+} #}}}
+
+sub rcs_notify () { #{{{
+       # TODO
+} #}}}
+
+sub rcs_getctime ($) { #{{{
+       error "getctime not implemented";
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/Rcs/svn.pm b/1.33.2/IkiWiki/Rcs/svn.pm
new file mode 100644 (file)
index 0000000..2d3ad04
--- /dev/null
@@ -0,0 +1,289 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+use IkiWiki;
+use POSIX qw(setlocale LC_CTYPE);
+
+package IkiWiki;
+               
+my $svn_webcommit=qr/^web commit (by (\w+)|from (\d+\.\d+\.\d+\.\d+)):?(.*)/;
+
+# svn needs LC_CTYPE set to a UTF-8 locale, so try to find one. Any will do.
+sub find_lc_ctype() {
+       my $current = setlocale(LC_CTYPE());
+       return $current if $current =~ m/UTF-?8$/i;
+
+       # Make some obvious attempts to avoid calling `locale -a`
+       foreach my $locale ("$current.UTF-8", "en_US.UTF-8", "en_GB.UTF-8") {
+               return $locale if setlocale(LC_CTYPE(), $locale);
+       }
+
+       # Try to get all available locales and pick the first UTF-8 one found.
+       if (my @locale = grep(/UTF-?8$/i, `locale -a`)) {
+               chomp @locale;
+               return $locale[0] if setlocale(LC_CTYPE(), $locale[0]);
+       }
+
+       # fallback to the current locale
+       return $current;
+} # }}}
+$ENV{LC_CTYPE} = $ENV{LC_CTYPE} || find_lc_ctype();
+
+sub svn_info ($$) { #{{{
+       my $field=shift;
+       my $file=shift;
+
+       my $info=`LANG=C svn info $file`;
+       my ($ret)=$info=~/^$field: (.*)$/m;
+       return $ret;
+} #}}}
+
+sub rcs_update () { #{{{
+       if (-d "$config{srcdir}/.svn") {
+               if (system("svn", "update", "--quiet", $config{srcdir}) != 0) {
+                       warn("svn update failed\n");
+               }
+       }
+} #}}}
+
+sub rcs_prepedit ($) { #{{{
+       # Prepares to edit a file under revision control. Returns a token
+       # that must be passed into rcs_commit when the file is ready
+       # for committing.
+       # The file is relative to the srcdir.
+       my $file=shift;
+       
+       if (-d "$config{srcdir}/.svn") {
+               # For subversion, return the revision of the file when
+               # editing begins.
+               my $rev=svn_info("Revision", "$config{srcdir}/$file");
+               return defined $rev ? $rev : "";
+       }
+} #}}}
+
+sub rcs_commit ($$$) { #{{{
+       # Tries to commit the page; returns undef on _success_ and
+       # a version of the page with the rcs's conflict markers on failure.
+       # The file is relative to the srcdir.
+       my $file=shift;
+       my $message=shift;
+       my $rcstoken=shift;
+
+       if (-d "$config{srcdir}/.svn") {
+               # Check to see if the page has been changed by someone
+               # else since rcs_prepedit was called.
+               my ($oldrev)=$rcstoken=~/^([0-9]+)$/; # untaint
+               my $rev=svn_info("Revision", "$config{srcdir}/$file");
+               if (defined $rev && defined $oldrev && $rev != $oldrev) {
+                       # Merge their changes into the file that we've
+                       # changed.
+                       chdir($config{srcdir}); # svn merge wants to be here
+                       if (system("svn", "merge", "--quiet", "-r$oldrev:$rev",
+                                  "$config{srcdir}/$file") != 0) {
+                               warn("svn merge -r$oldrev:$rev failed\n");
+                       }
+               }
+
+               if (system("svn", "commit", "--quiet", 
+                          "--encoding", "UTF-8", "-m",
+                          possibly_foolish_untaint($message),
+                          "$config{srcdir}") != 0) {
+                       my $conflict=readfile("$config{srcdir}/$file");
+                       if (system("svn", "revert", "--quiet", "$config{srcdir}/$file") != 0) {
+                               warn("svn revert failed\n");
+                       }
+                       return $conflict;
+               }
+       }
+       return undef # success
+} #}}}
+
+sub rcs_add ($) { #{{{
+       # filename is relative to the root of the srcdir
+       my $file=shift;
+
+       if (-d "$config{srcdir}/.svn") {
+               my $parent=dirname($file);
+               while (! -d "$config{srcdir}/$parent/.svn") {
+                       $file=$parent;
+                       $parent=dirname($file);
+               }
+               
+               if (system("svn", "add", "--quiet", "$config{srcdir}/$file") != 0) {
+                       warn("svn add failed\n");
+               }
+       }
+} #}}}
+
+sub rcs_recentchanges ($) { #{{{
+       my $num=shift;
+       my @ret;
+       
+       return unless -d "$config{srcdir}/.svn";
+
+       eval q{
+               use Date::Parse;
+               use Time::Duration;
+               use XML::SAX;
+               use XML::Simple;
+       };
+       error($@) if $@;
+
+       # avoid using XML::SAX::PurePerl, it's buggy with UTF-8 data
+       my @parsers = map { ${$_}{Name} } @{XML::SAX->parsers()};
+       do {
+               $XML::Simple::PREFERRED_PARSER = pop @parsers;
+       } until $XML::Simple::PREFERRED_PARSER ne 'XML::SAX::PurePerl';
+
+       # --limit is only supported on Subversion 1.2.0+
+       my $svn_version=`svn --version -q`;
+       my $svn_limit='';
+       $svn_limit="--limit $num"
+               if $svn_version =~ /\d\.(\d)\.\d/ && $1 >= 2;
+
+       my $svn_url=svn_info("URL", $config{srcdir});
+       my $xml = XMLin(scalar `svn $svn_limit --xml -v log '$svn_url'`,
+               ForceArray => [ 'logentry', 'path' ],
+               GroupTags => { paths => 'path' },
+               KeyAttr => { path => 'content' },
+       );
+       foreach my $logentry (@{$xml->{logentry}}) {
+               my (@pages, @message);
+
+               my $rev = $logentry->{revision};
+               my $user = $logentry->{author};
+
+               my $when=time - str2time($logentry->{date}, 'UTC');
+
+               foreach my $msgline (split(/\n/, $logentry->{msg})) {
+                       push @message, { line => $msgline };
+               }
+
+               my $committype="web";
+               if (defined $message[0] &&
+                   $message[0]->{line}=~/$svn_webcommit/) {
+                       $user=defined $2 ? "$2" : "$3";
+                       $message[0]->{line}=$4;
+               }
+               else {
+                       $committype="svn";
+               }
+
+               foreach (keys %{$logentry->{paths}}) {
+                       next unless /^\/\Q$config{svnpath}\E\/([^ ]+)(?:$|\s)/;
+                       my $file=$1;
+                       my $diffurl=$config{diffurl};
+                       $diffurl=~s/\[\[file\]\]/$file/g;
+                       $diffurl=~s/\[\[r1\]\]/$rev - 1/eg;
+                       $diffurl=~s/\[\[r2\]\]/$rev/g;
+                       push @pages, {
+                               page => pagename($file),
+                               diffurl => $diffurl,
+                       } if length $file;
+               }
+               push @ret, { rev => $rev,
+                       user => $user,
+                       committype => $committype,
+                       when => $when,
+                       message => [@message],
+                       pages => [@pages],
+               } if @pages;
+               return @ret if @ret >= $num;
+       }
+
+       return @ret;
+} #}}}
+
+sub rcs_notify () { #{{{
+       if (! exists $ENV{REV}) {
+               error("REV is not set, not running from svn post-commit hook, cannot send notifications");
+       }
+       my $rev=int(possibly_foolish_untaint($ENV{REV}));
+       
+       my $user=`svnlook author $config{svnrepo} -r $rev`;
+       chomp $user;
+       my $message=`svnlook log $config{svnrepo} -r $rev`;
+       if ($message=~/$svn_webcommit/) {
+               $user=defined $2 ? "$2" : "$3";
+               $message=$4;
+       }
+
+       my @changed_pages;
+       foreach my $change (`svnlook changed $config{svnrepo} -r $rev`) {
+               chomp $change;
+               if ($change =~ /^[A-Z]+\s+\Q$config{svnpath}\E\/(.*)/) {
+                       push @changed_pages, $1;
+               }
+       }
+               
+       require IkiWiki::UserInfo;
+       my @email_recipients=commit_notify_list($user, @changed_pages);
+       if (@email_recipients) {
+               # TODO: if a commit spans multiple pages, this will send
+               # subscribers a diff that might contain pages they did not
+               # sign up for. Should separate the diff per page and
+               # reassemble into one mail with just the pages subscribed to.
+               my $diff=`svnlook diff $config{svnrepo} -r $rev --no-diff-deleted`;
+
+               my $subject="$config{wikiname} update of ";
+               if (@changed_pages > 2) {
+                       $subject.="$changed_pages[0] $changed_pages[1] etc";
+               }
+               else {
+                       $subject.=join(" ", @changed_pages);
+               }
+               $subject.=" by $user";
+
+               my $template=template("notifymail.tmpl");
+               $template->param(
+                       wikiname => $config{wikiname},
+                       diff => $diff,
+                       user => $user,
+                       message => $message,
+               );
+               
+               eval q{use Mail::Sendmail};
+               error($@) if $@;
+               foreach my $email (@email_recipients) {
+                       sendmail(
+                               To => $email,
+                               From => "$config{wikiname} <$config{adminemail}>",
+                               Subject => $subject,
+                               Message => $template->output,
+                       ) or error("Failed to send update notification mail");
+               }
+       }
+} #}}}
+
+sub rcs_getctime ($) { #{{{
+       my $file=shift;
+
+       my $svn_log_infoline=qr/^r\d+\s+\|\s+[^\s]+\s+\|\s+(\d+-\d+-\d+\s+\d+:\d+:\d+\s+[-+]?\d+).*/;
+               
+       my $child = open(SVNLOG, "-|");
+       if (! $child) {
+               exec("svn", "log", $file) || error("svn log $file failed to run");
+       }
+
+       my $date;
+       while (<SVNLOG>) {
+               if (/$svn_log_infoline/) {
+                       $date=$1;
+               }
+       }
+       close SVNLOG || warn "svn log $file exited $?";
+
+       if (! defined $date) {
+               warn "failed to parse svn log for $file\n";
+               return 0;
+       }
+               
+       eval q{use Date::Parse};
+       error($@) if $@;
+       $date=str2time($date);
+       debug("found ctime ".localtime($date)." for $file");
+       return $date;
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/Rcs/tla.pm b/1.33.2/IkiWiki/Rcs/tla.pm
new file mode 100644 (file)
index 0000000..c71c9e6
--- /dev/null
@@ -0,0 +1,262 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+use IkiWiki;
+use POSIX qw(setlocale LC_CTYPE);
+
+package IkiWiki;
+
+my $tla_webcommit=qr/^web commit (by (\w+)|from (\d+\.\d+\.\d+\.\d+)):?(.*)/;
+
+sub quiet_system (@) {
+       # See Debian bug #385939.
+       open (SAVEOUT, ">&STDOUT");
+       close STDOUT;
+       open (STDOUT, ">/dev/null");
+       my $ret=system(@_);
+       close STDOUT;
+       open (STDOUT, ">&SAVEOUT");
+       close SAVEOUT;
+       return $ret;
+}
+
+sub rcs_update () { #{{{
+       if (-d "$config{srcdir}/{arch}") {
+               if (quiet_system("tla", "replay", "-d", $config{srcdir}) != 0) {
+                       warn("tla replay failed\n");
+               }
+       }
+} #}}}
+
+sub rcs_prepedit ($) { #{{{
+       my $file=shift;
+
+       if (-d "$config{srcdir}/{arch}") {
+               # For Arch, return the tree-id of archive when
+               # editing begins.
+               my $rev=`tla tree-id $config{srcdir}`;
+               return defined $rev ? $rev : "";
+       }
+} #}}}
+
+sub rcs_commit ($$$) { #{{{
+       my $file=shift;
+       my $message=shift;
+       my $rcstoken=shift;
+
+       if (-d "$config{srcdir}/{arch}") {
+               # Check to see if the page has been changed by someone
+               # else since rcs_prepedit was called.
+               my ($oldrev)=$rcstoken=~/^([A-Za-z0-9@\/._-]+)$/; # untaint
+               my $rev=`tla tree-id $config{srcdir}`;
+               if (defined $rev && defined $oldrev && $rev ne $oldrev) {
+                       # Merge their changes into the file that we've
+                       # changed.
+                       if (quiet_system("tla", "update", "-d",
+                                  "$config{srcdir}") != 0) {
+                               warn("tla update failed\n");
+                       }
+               }
+
+               if (quiet_system("tla", "commit",
+                          "-L".possibly_foolish_untaint($message),
+                          '-d', $config{srcdir}) != 0) {
+                       my $conflict=readfile("$config{srcdir}/$file");
+                       if (system("tla", "undo", "-n", "--quiet", "-d", "$config{srcdir}") != 0) {
+                               warn("tla undo failed\n");
+                       }
+                       return $conflict;
+               }
+       }
+       return undef # success
+} #}}}
+
+sub rcs_add ($) { #{{{
+       my $file=shift;
+
+       if (-d "$config{srcdir}/{arch}") {
+               if (quiet_system("tla", "add", "$config{srcdir}/$file") != 0) {
+                       warn("tla add failed\n");
+               }
+       }
+} #}}}
+
+sub rcs_recentchanges ($) {
+       my $num=shift;
+       my @ret;
+
+       return unless -d "$config{srcdir}/{arch}";
+
+       eval q{use Date::Parse};
+       error($@) if $@;
+       eval q{use Mail::Header};
+       error($@) if $@;
+
+       my $logs = `tla logs -d $config{srcdir}`;
+       my @changesets = reverse split(/\n/, $logs);
+
+       for (my $i=0; $i<$num && $i<$#changesets; $i++) {
+               my ($change)=$changesets[$i]=~/^([A-Za-z0-9@\/._-]+)$/; # untaint
+
+               open(LOG, "tla cat-log -d $config{srcdir} $change|");
+               my $head = Mail::Header->new(\*LOG);
+               close(LOG);
+
+               my $rev = $head->get("Revision");
+               my $summ = $head->get("Summary");
+               my $newfiles = $head->get("New-files");
+               my $modfiles = $head->get("Modified-files");
+               my $remfiles = $head->get("Removed-files");
+               my $user = $head->get("Creator");
+
+               my @paths = grep { !/^(.*\/)?\.arch-ids\/.*\.id$/ }
+                       split(/ /, "$newfiles $modfiles .arch-ids/fake.id");
+
+               my $sdate = $head->get("Standard-date");
+               my $when = time - str2time($sdate, 'UTC');
+
+               my $committype = "web";
+               if (defined $summ && $summ =~ /$tla_webcommit/) {
+                       $user = defined $2 ? "$2" : "$3";
+                       $summ = $4;
+               }
+               else {
+                       $committype="tla";
+               }
+
+               my @message;
+               push @message, { line => escapeHTML($summ) };
+
+               my @pages;
+
+               foreach my $file (@paths) {
+                       my $diffurl=$config{diffurl};
+                       $diffurl=~s/\[\[file\]\]/$file/g;
+                       $diffurl=~s/\[\[rev\]\]/$change/g;
+                       push @pages, {
+                               page => pagename($file),
+                               diffurl => $diffurl,
+                       } if length $file;
+               }
+               push @ret, { rev => $change,
+                       user => $user,
+                       committype => $committype,
+                       when => $when,
+                       message => [@message],
+                       pages => [@pages],
+               } if @pages;
+
+               last if $i == $num;
+       }
+
+       return @ret;
+}
+
+sub rcs_notify () { #{{{
+       # FIXME: Not set
+       if (! exists $ENV{ARCH_VERSION}) {
+               error("ARCH_VERSION is not set, not running from tla post-commit hook, cannot send notifications");
+       }
+       my $rev=int(possibly_foolish_untaint($ENV{REV}));
+
+       eval q{use Mail::Header};
+       error($@) if $@;
+       open(LOG, $ENV{"ARCH_LOG"});
+       my $head = Mail::Header->new(\*LOG);
+       close(LOG);
+
+       my $message = $head->get("Summary");
+       my $user = $head->get("Creator");
+
+       my $newfiles = $head->get("New-files");
+       my $modfiles = $head->get("Modified-files");
+       my $remfiles = $head->get("Removed-files");
+
+       my @changed_pages = grep { !/(^.*\/)?\.arch-ids\/.*\.id$/ }
+               split(/ /, "$newfiles $modfiles $remfiles .arch-ids/fake.id");
+
+       if ($message =~ /$tla_webcommit/) {
+               $user=defined $2 ? "$2" : "$3";
+               $message=$4;
+       }
+
+       require IkiWiki::UserInfo;
+       my @email_recipients=commit_notify_list($user, @changed_pages);
+       if (@email_recipients) {
+               # TODO: if a commit spans multiple pages, this will send
+               # subscribers a diff that might contain pages they did not
+               # sign up for. Should separate the diff per page and
+               # reassemble into one mail with just the pages subscribed to.
+               my $logs = `tla logs -d $config{srcdir}`;
+               my @changesets = reverse split(/\n/, $logs);
+               my $i;
+
+               for($i=0;$i<$#changesets;$i++) {
+                       last if $changesets[$i] eq $rev;
+               }
+
+               my $revminusone = $changesets[$i+1];
+               my $diff=`tla diff -d $ENV{ARCH_TREE_ROOT} $revminusone`;
+
+               my $subject="$config{wikiname} update of ";
+               if (@changed_pages > 2) {
+                       $subject.="$changed_pages[0] $changed_pages[1] etc";
+               }
+               else {
+                       $subject.=join(" ", @changed_pages);
+               }
+               $subject.=" by $user";
+
+               my $template=template("notifymail.tmpl");
+               $template->param(
+                       wikiname => $config{wikiname},
+                       diff => $diff,
+                       user => $user,
+                       message => $message,
+               );
+
+               eval q{use Mail::Sendmail};
+               error($@) if $@;
+               foreach my $email (@email_recipients) {
+                       sendmail(
+                               To => $email,
+                               From => "$config{wikiname} <$config{adminemail}>",
+                               Subject => $subject,
+                               Message => $template->output,
+                       ) or error("Failed to send update notification mail");
+               }
+       }
+} #}}}
+
+sub rcs_getctime ($) { #{{{
+       my $file=shift;
+       eval q{use Date::Parse};
+       error($@) if $@;
+       eval q{use Mail::Header};
+       error($@) if $@;
+
+       my $logs = `tla logs -d $config{srcdir}`;
+       my @changesets = reverse split(/\n/, $logs);
+       my $sdate;
+
+       for (my $i=0; $i<$#changesets; $i++) {
+               my $change = $changesets[$i];
+
+               open(LOG, "tla cat-log -d $config{srcdir} $change|");
+               my $head = Mail::Header->new(\*LOG);
+               close(LOG);
+
+               $sdate = $head->get("Standard-date");
+               my $newfiles = $head->get("New-files");
+
+               my ($lastcreation) = grep {/^$file$/} split(/ /, "$newfiles");
+               last if defined($lastcreation);
+       }
+
+       my $date=str2time($sdate, 'UTC');
+       debug("found ctime ".localtime($date)." for $file");
+       return $date;
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/Render.pm b/1.33.2/IkiWiki/Render.pm
new file mode 100644 (file)
index 0000000..47fbe7a
--- /dev/null
@@ -0,0 +1,430 @@
+#!/usr/bin/perl
+
+package IkiWiki;
+
+use warnings;
+use strict;
+use IkiWiki;
+use Encode;
+
+my %backlinks;
+my $backlinks_calculated=0;
+
+sub calculate_backlinks () { #{{{
+       return if $backlinks_calculated;
+       %backlinks=();
+       foreach my $page (keys %links) {
+               foreach my $link (@{$links{$page}}) {
+                       my $bestlink=bestlink($page, $link);
+                       if (length $bestlink && $bestlink ne $page) {
+                               $backlinks{$bestlink}{$page}=1;
+                       }
+               }
+       }
+       $backlinks_calculated=1;
+} #}}}
+
+sub backlinks ($) { #{{{
+       my $page=shift;
+
+       calculate_backlinks();
+
+       my @links;
+       return unless $backlinks{$page};
+       foreach my $p (keys %{$backlinks{$page}}) {
+               my $href=abs2rel(htmlpage($p), dirname($page));
+                       
+               # Trim common dir prefixes from both pages.
+               my $p_trimmed=$p;
+               my $page_trimmed=$page;
+               my $dir;
+               1 while (($dir)=$page_trimmed=~m!^([^/]+/)!) &&
+                       defined $dir &&
+                       $p_trimmed=~s/^\Q$dir\E// &&
+                       $page_trimmed=~s/^\Q$dir\E//;
+                              
+               push @links, { url => $href, page => pagetitle($p_trimmed) };
+       }
+
+       return sort { $a->{page} cmp $b->{page} } @links;
+} #}}}
+
+sub parentlinks ($) { #{{{
+       my $page=shift;
+       
+       my @ret;
+       my $pagelink="";
+       my $path="";
+       my $skip=1;
+       return if $page eq 'index'; # toplevel
+       foreach my $dir (reverse split("/", $page)) {
+               if (! $skip) {
+                       $path.="../";
+                       unshift @ret, { url => $path.htmlpage($dir), page => pagetitle($dir) };
+               }
+               else {
+                       $skip=0;
+               }
+       }
+       unshift @ret, { url => length $path ? $path : ".", page => $config{wikiname} };
+       return @ret;
+} #}}}
+
+sub genpage ($$$) { #{{{
+       my $page=shift;
+       my $content=shift;
+       my $mtime=shift;
+
+       my $template=template("page.tmpl", blind_cache => 1);
+       my $actions=0;
+
+       if (length $config{cgiurl}) {
+               $template->param(editurl => cgiurl(do => "edit", page => $page));
+               $template->param(prefsurl => cgiurl(do => "prefs"));
+               if ($config{rcs}) {
+                       $template->param(recentchangesurl => cgiurl(do => "recentchanges"));
+               }
+               $actions++;
+       }
+
+       if (length $config{historyurl}) {
+               my $u=$config{historyurl};
+               $u=~s/\[\[file\]\]/$pagesources{$page}/g;
+               $template->param(historyurl => $u);
+               $actions++;
+       }
+       if ($config{discussion}) {
+               $template->param(discussionlink => htmllink($page, $page, "Discussion", 1, 1));
+               $actions++;
+       }
+
+       if ($actions) {
+               $template->param(have_actions => 1);
+       }
+
+       $template->param(
+               title => $page eq 'index' 
+                       ? $config{wikiname} 
+                       : pagetitle(basename($page)),
+               wikiname => $config{wikiname},
+               parentlinks => [parentlinks($page)],
+               content => $content,
+               backlinks => [backlinks($page)],
+               mtime => displaytime($mtime),
+               baseurl => baseurl($page),
+       );
+
+       run_hooks(pagetemplate => sub {
+               shift->(page => $page, destpage => $page, template => $template);
+       });
+       
+       $content=$template->output;
+
+       run_hooks(format => sub {
+               $content=shift->(
+                       page => $page,
+                       content => $content,
+               );
+       });
+
+       return $content;
+} #}}}
+
+sub mtime ($) { #{{{
+       my $file=shift;
+       
+       return (stat($file))[9];
+} #}}}
+
+sub scan ($) { #{{{
+       my $file=shift;
+
+       my $type=pagetype($file);
+       if (defined $type) {
+               my $srcfile=srcfile($file);
+               my $content=readfile($srcfile);
+               my $page=pagename($file);
+               will_render($page, htmlpage($page), 1);
+
+               # Always needs to be done, since filters might add links
+               # to the content.
+               $content=filter($page, $content);
+
+               my @links;
+               while ($content =~ /(?<!\\)$config{wiki_link_regexp}/g) {
+                       push @links, titlepage($2);
+               }
+               if ($config{discussion}) {
+                       # Discussion links are a special case since they're not in the
+                       # text of the page, but on its template.
+                       push @links, "$page/discussion";
+               }
+               $links{$page}=\@links;
+               
+               # Preprocess in scan-only mode.
+               preprocess($page, $page, $content, 1);
+       }
+       else {
+               will_render($file, $file, 1);
+       }
+} #}}}
+
+sub render ($) { #{{{
+       my $file=shift;
+       
+       my $type=pagetype($file);
+       my $srcfile=srcfile($file);
+       if (defined $type) {
+               my $content=readfile($srcfile);
+               my $page=pagename($file);
+               delete $depends{$page};
+               will_render($page, htmlpage($page), 1);
+               
+               $content=filter($page, $content);
+               $content=preprocess($page, $page, $content);
+               $content=linkify($page, $page, $content);
+               $content=htmlize($page, $type, $content);
+               
+               writefile(htmlpage($page), $config{destdir},
+                       genpage($page, $content, mtime($srcfile)));
+               $oldpagemtime{$page}=time;
+       }
+       else {
+               my $content=readfile($srcfile, 1);
+               delete $depends{$file};
+               will_render($file, $file, 1);
+               writefile($file, $config{destdir}, $content, 1);
+               $oldpagemtime{$file}=time;
+       }
+} #}}}
+
+sub prune ($) { #{{{
+       my $file=shift;
+
+       unlink($file);
+       my $dir=dirname($file);
+       while (rmdir($dir)) {
+               $dir=dirname($dir);
+       }
+} #}}}
+
+sub refresh () { #{{{
+       # find existing pages
+       my %exists;
+       my @files;
+       eval q{use File::Find};
+       error($@) if $@;
+       find({
+               no_chdir => 1,
+               wanted => sub {
+                       $_=decode_utf8($_);
+                       if (/$config{wiki_file_prune_regexp}/) {
+                               $File::Find::prune=1;
+                       }
+                       elsif (! -d $_ && ! -l $_) {
+                               my ($f)=/$config{wiki_file_regexp}/; # untaint
+                               if (! defined $f) {
+                                       warn("skipping bad filename $_\n");
+                               }
+                               else {
+                                       $f=~s/^\Q$config{srcdir}\E\/?//;
+                                       push @files, $f;
+                                       $exists{pagename($f)}=1;
+                               }
+                       }
+               },
+       }, $config{srcdir});
+       find({
+               no_chdir => 1,
+               wanted => sub {
+                       $_=decode_utf8($_);
+                       if (/$config{wiki_file_prune_regexp}/) {
+                               $File::Find::prune=1;
+                       }
+                       elsif (! -d $_ && ! -l $_) {
+                               my ($f)=/$config{wiki_file_regexp}/; # untaint
+                               if (! defined $f) {
+                                       warn("skipping bad filename $_\n");
+                               }
+                               else {
+                                       # Don't add files that are in the
+                                       # srcdir.
+                                       $f=~s/^\Q$config{underlaydir}\E\/?//;
+                                       if (! -e "$config{srcdir}/$f" && 
+                                           ! -l "$config{srcdir}/$f") {
+                                               push @files, $f;
+                                               $exists{pagename($f)}=1;
+                                       }
+                               }
+                       }
+               },
+       }, $config{underlaydir});
+
+       my %rendered;
+
+       # check for added or removed pages
+       my @add;
+       foreach my $file (@files) {
+               my $page=pagename($file);
+               if (! $oldpagemtime{$page}) {
+                       push @add, $file;
+                       $pagecase{lc $page}=$page;
+                       $pagesources{$page}=$file;
+                       if ($config{getctime} && -e "$config{srcdir}/$file") {
+                               $pagectime{$page}=rcs_getctime("$config{srcdir}/$file");
+                       }
+                       elsif (! exists $pagectime{$page}) {
+                               $pagectime{$page}=mtime(srcfile($file));
+                       }
+               }
+       }
+       my @del;
+       foreach my $page (keys %oldpagemtime) {
+               if (! $exists{$page}) {
+                       debug("removing old page $page");
+                       push @del, $pagesources{$page};
+                       $links{$page}=[];
+                       $renderedfiles{$page}=[];
+                       $oldpagemtime{$page}=0;
+                       prune($config{destdir}."/".$_)
+                               foreach @{$oldrenderedfiles{$page}};
+                       delete $pagesources{$page};
+               }
+       }
+
+       # scan changed and new files
+       my @changed;
+       foreach my $file (@files) {
+               my $page=pagename($file);
+               
+               if (! exists $oldpagemtime{$page} ||
+                   mtime(srcfile($file)) > $oldpagemtime{$page} ||
+                   $forcerebuild{$page}) {
+                       debug("scanning $file");
+                       push @changed, $file;
+                       scan($file);
+               }
+       }
+       calculate_backlinks();
+
+       # render changed and new pages
+       foreach my $file (@changed) {
+               debug("rendering $file");
+               render($file);
+               $rendered{$file}=1;
+       }
+       
+       # rebuild pages that link to added or removed pages
+       if (@add || @del) {
+               foreach my $f (@add, @del) {
+                       my $p=pagename($f);
+                       foreach my $page (keys %{$backlinks{$p}}) {
+                               my $file=$pagesources{$page};
+                               next if $rendered{$file};
+                               debug("rendering $file, which links to $p");
+                               render($file);
+                               $rendered{$file}=1;
+                       }
+               }
+       }
+
+       if (%rendered || @del) {
+               # rebuild dependant pages
+               foreach my $f (@files) {
+                       next if $rendered{$f};
+                       my $p=pagename($f);
+                       if (exists $depends{$p}) {
+                               foreach my $file (keys %rendered, @del) {
+                                       next if $f eq $file;
+                                       my $page=pagename($file);
+                                       if (pagespec_match($page, $depends{$p})) {
+                                               debug("rendering $f, which depends on $page");
+                                               render($f);
+                                               $rendered{$f}=1;
+                                               last;
+                                       }
+                               }
+                       }
+               }
+               
+               # handle backlinks; if a page has added/removed links,
+               # update the pages it links to
+               my %linkchanged;
+               foreach my $file (keys %rendered, @del) {
+                       my $page=pagename($file);
+                       
+                       if (exists $links{$page}) {
+                               foreach my $link (map { bestlink($page, $_) } @{$links{$page}}) {
+                                       if (length $link &&
+                                           (! exists $oldlinks{$page} ||
+                                            ! grep { bestlink($page, $_) eq $link } @{$oldlinks{$page}})) {
+                                               $linkchanged{$link}=1;
+                                       }
+                               }
+                       }
+                       if (exists $oldlinks{$page}) {
+                               foreach my $link (map { bestlink($page, $_) } @{$oldlinks{$page}}) {
+                                       if (length $link &&
+                                           (! exists $links{$page} || 
+                                            ! grep { bestlink($page, $_) eq $link } @{$links{$page}})) {
+                                               $linkchanged{$link}=1;
+                                       }
+                               }
+                       }
+               }
+               foreach my $link (keys %linkchanged) {
+                       my $linkfile=$pagesources{$link};
+                       if (defined $linkfile) {
+                               next if $rendered{$linkfile};
+                               debug("rendering $linkfile, to update its backlinks");
+                               render($linkfile);
+                               $rendered{$linkfile}=1;
+                       }
+               }
+       }
+
+       # remove no longer rendered files
+       foreach my $src (keys %rendered) {
+               my $page=pagename($src);
+               foreach my $file (@{$oldrenderedfiles{$page}}) {
+                       if (! grep { $_ eq $file } @{$renderedfiles{$page}}) {
+                               debug("removing $file, no longer rendered by $page");
+                               prune($config{destdir}."/".$file);
+                       }
+               }
+       }
+
+       if (@del) {
+               run_hooks(delete => sub { shift->(@del) });
+       }
+       if (%rendered) {
+               run_hooks(change => sub { shift->(keys %rendered) });
+       }
+} #}}}
+
+sub commandline_render () { #{{{
+       loadplugins();
+       checkconfig();
+       lockwiki();
+       loadindex();
+       unlockwiki();
+
+       my $srcfile=possibly_foolish_untaint($config{render});
+       my $file=$srcfile;
+       $file=~s/\Q$config{srcdir}\E\/?//;
+
+       my $type=pagetype($file);
+       die "ikiwiki: cannot render $srcfile\n" unless defined $type;
+       my $content=readfile($srcfile);
+       my $page=pagename($file);
+       $pagesources{$page}=$file;
+       $content=filter($page, $content);
+       $content=preprocess($page, $page, $content);
+       $content=linkify($page, $page, $content);
+       $content=htmlize($page, $type, $content);
+
+       print genpage($page, $content, mtime($srcfile));
+       exit 0;
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/Setup.pm b/1.33.2/IkiWiki/Setup.pm
new file mode 100644 (file)
index 0000000..2b4c76b
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+use IkiWiki;
+use open qw{:utf8 :std};
+
+package IkiWiki;
+
+sub setup () { # {{{
+       my $setup=possibly_foolish_untaint($config{setup});
+       delete $config{setup};
+       open (IN, $setup) || error("read $setup: $!\n");
+       my $code;
+       {
+               local $/=undef;
+               $code=<IN>;
+       }
+       ($code)=$code=~/(.*)/s;
+       close IN;
+
+       eval $code;
+       error($@) if $@;
+
+       exit;
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/Setup/Standard.pm b/1.33.2/IkiWiki/Setup/Standard.pm
new file mode 100644 (file)
index 0000000..7512c25
--- /dev/null
@@ -0,0 +1,90 @@
+#!/usr/bin/perl
+# Standard ikiwiki setup module.
+# Parameters to import should be all the standard ikiwiki config stuff,
+# plus an array of wrappers to set up.
+
+use warnings;
+use strict;
+use IkiWiki::Wrapper;
+use IkiWiki::Render;
+
+package IkiWiki::Setup::Standard;
+
+sub import {
+       IkiWiki::setup_standard(@_);
+}
+       
+package IkiWiki;
+
+sub setup_standard {
+       my %setup=%{$_[1]};
+
+       $setup{plugin}=$config{plugin};
+       if (exists $setup{add_plugins}) {
+               push @{$setup{plugin}}, @{$setup{add_plugins}};
+               delete $setup{add_plugins};
+       }
+       if (exists $setup{disable_plugins}) {
+               foreach my $plugin (@{$setup{disable_plugins}}) {
+                       $setup{plugin}=[grep { $_ ne $plugin } @{$setup{plugin}}];
+               }
+               delete $setup{disable_plugins};
+       }
+       if (exists $setup{exclude}) {
+               $config{wiki_file_prune_regexp}=qr/$config{wiki_file_prune_regexp}|$setup{exclude}/;
+       }
+
+       if (! $config{render} && (! $config{refresh} || $config{wrappers})) {
+               debug("generating wrappers..");
+               my @wrappers=@{$setup{wrappers}};
+               delete $setup{wrappers};
+               my %startconfig=(%config);
+               foreach my $wrapper (@wrappers) {
+                       %config=(%startconfig, verbose => 0, %setup, %{$wrapper});
+                       checkconfig();
+                       gen_wrapper();
+               }
+               %config=(%startconfig);
+       }
+       
+       foreach my $c (keys %setup) {
+               if (defined $setup{$c}) {
+                       if (! ref $setup{$c}) {
+                               $config{$c}=possibly_foolish_untaint($setup{$c});
+                       }
+                       elsif (ref $setup{$c} eq 'ARRAY') {
+                               $config{$c}=[map { possibly_foolish_untaint($_) } @{$setup{$c}}]
+                       }
+                       elsif (ref $setup{$c} eq 'HASH') {
+                               foreach my $key (keys %{$setup{$c}}) {
+                                       $config{$c}{$key}=possibly_foolish_untaint($setup{$c}{$key});
+                               }
+                       }
+               }
+               else {
+                       $config{$c}=undef;
+               }
+       }
+
+       if ($config{render}) {
+               commandline_render();
+       }
+       elsif (! $config{refresh}) {
+               $config{rebuild}=1;
+               debug("rebuilding wiki..");
+       }
+       else {
+               debug("refreshing wiki..");
+       }
+
+       loadplugins();
+       checkconfig();
+       lockwiki();
+       loadindex();
+       refresh();
+
+       debug("done");
+       saveindex();
+}
+
+1
diff --git a/1.33.2/IkiWiki/UserInfo.pm b/1.33.2/IkiWiki/UserInfo.pm
new file mode 100644 (file)
index 0000000..ae63d80
--- /dev/null
@@ -0,0 +1,111 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+use Storable;
+use IkiWiki;
+
+package IkiWiki;
+
+sub userinfo_retrieve () { #{{{
+       my $userinfo=eval{ Storable::lock_retrieve("$config{wikistatedir}/userdb") };
+       return $userinfo;
+} #}}}
+       
+sub userinfo_store ($) { #{{{
+       my $userinfo=shift;
+       
+       my $oldmask=umask(077);
+       my $ret=Storable::lock_store($userinfo, "$config{wikistatedir}/userdb");
+       umask($oldmask);
+       return $ret;
+} #}}}
+       
+sub userinfo_get ($$) { #{{{
+       my $user=shift;
+       my $field=shift;
+
+       my $userinfo=userinfo_retrieve();
+       if (! defined $userinfo ||
+           ! exists $userinfo->{$user} || ! ref $userinfo->{$user} ||
+            ! exists $userinfo->{$user}->{$field}) {
+               return "";
+       }
+       return $userinfo->{$user}->{$field};
+} #}}}
+
+sub userinfo_set ($$$) { #{{{
+       my $user=shift;
+       my $field=shift;
+       my $value=shift;
+       
+       my $userinfo=userinfo_retrieve();
+       if (! defined $userinfo ||
+           ! exists $userinfo->{$user} || ! ref $userinfo->{$user}) {
+               return "";
+       }
+       
+       $userinfo->{$user}->{$field}=$value;
+       return userinfo_store($userinfo);
+} #}}}
+
+sub userinfo_setall ($$) { #{{{
+       my $user=shift;
+       my $info=shift;
+       
+       my $userinfo=userinfo_retrieve();
+       if (! defined $userinfo) {
+               $userinfo={};
+       }
+       $userinfo->{$user}=$info;
+       return userinfo_store($userinfo);
+} #}}}
+
+sub is_admin ($) { #{{{
+       my $user_name=shift;
+
+       return grep { $_ eq $user_name } @{$config{adminuser}};
+} #}}}
+
+sub get_banned_users () { #{{{
+       my @ret;
+       my $userinfo=userinfo_retrieve();
+       foreach my $user (keys %{$userinfo}) {
+               push @ret, $user if $userinfo->{$user}->{banned};
+       }
+       return @ret;
+} #}}}
+
+sub set_banned_users (@) { #{{{
+       my %banned=map { $_ => 1 } @_;
+       my $userinfo=userinfo_retrieve();
+       foreach my $user (keys %{$userinfo}) {
+               $userinfo->{$user}->{banned} = $banned{$user};
+       }
+       return userinfo_store($userinfo);
+} #}}}
+
+sub commit_notify_list ($@) { #{{{
+       my $committer=shift;
+       
+       my @pages;
+       foreach my $file (@_) {
+               push @pages, grep { $pagesources{$_} eq $file } keys %pagesources;
+       }
+       
+       my @ret;
+       my $userinfo=userinfo_retrieve();
+       foreach my $user (keys %{$userinfo}) {
+               next if $user eq $committer;
+               if (exists $userinfo->{$user}->{subscriptions} &&
+                   length $userinfo->{$user}->{subscriptions} &&
+                   exists $userinfo->{$user}->{email} &&
+                   length $userinfo->{$user}->{email} &&
+                   grep { pagespec_match($_, $userinfo->{$user}->{subscriptions}) } @pages) {
+                       push @ret, $userinfo->{$user}->{email};
+               }
+       }
+       return @ret;
+} #}}}
+
+1
diff --git a/1.33.2/IkiWiki/Wrapper.pm b/1.33.2/IkiWiki/Wrapper.pm
new file mode 100644 (file)
index 0000000..a3ecccd
--- /dev/null
@@ -0,0 +1,107 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+use Cwd q{abs_path};
+use Data::Dumper;
+use IkiWiki;
+
+package IkiWiki;
+
+sub gen_wrapper () { #{{{
+       $config{srcdir}=abs_path($config{srcdir});
+       $config{destdir}=abs_path($config{destdir});
+       my $this=abs_path($0);
+       if (! -x $this) {
+               error("$this doesn't seem to be executable");
+       }
+
+       if ($config{setup}) {
+               error("cannot create a wrapper that uses a setup file");
+       }
+       my $wrapper=possibly_foolish_untaint($config{wrapper});
+       if (! defined $wrapper || ! length $wrapper) {
+               error("wrapper filename not specified");
+       }
+       delete $config{wrapper};
+       
+       my @envsave;
+       push @envsave, qw{REMOTE_ADDR QUERY_STRING REQUEST_METHOD REQUEST_URI
+                      CONTENT_TYPE CONTENT_LENGTH GATEWAY_INTERFACE
+                      HTTP_COOKIE REMOTE_USER} if $config{cgi};
+       my $envsave="";
+       foreach my $var (@envsave) {
+               $envsave.=<<"EOF"
+       if ((s=getenv("$var")))
+               asprintf(&newenviron[i++], "%s=%s", "$var", s);
+EOF
+       }
+       if ($config{rcs} eq "svn" && $config{notify}) {
+               # Support running directly as hooks/post-commit by passing
+               # $2 in REV in the environment.
+               $envsave.=<<"EOF"
+       if (argc == 3)
+               asprintf(&newenviron[i++], "REV=%s", argv[2]);
+       else if ((s=getenv("REV")))
+               asprintf(&newenviron[i++], "%s=%s", "REV", s);
+EOF
+       }
+       if ($config{rcs} eq "tla" && $config{notify}) {
+               $envsave.=<<"EOF"
+       if ((s=getenv("ARCH_VERSION")))
+               asprintf(&newenviron[i++], "%s=%s", "ARCH_VERSION", s);
+EOF
+       }
+       
+       $Data::Dumper::Indent=0; # no newlines
+       my $configstring=Data::Dumper->Dump([\%config], ['*config']);
+       $configstring=~s/\\/\\\\/g;
+       $configstring=~s/"/\\"/g;
+       $configstring=~s/\n/\\\n/g;
+       
+       open(OUT, ">$wrapper.c") || error("failed to write $wrapper.c: $!");;
+       print OUT <<"EOF";
+/* A wrapper for ikiwiki, can be safely made suid. */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern char **environ;
+
+int main (int argc, char **argv) {
+       /* Sanitize environment. */
+       char *s;
+       char *newenviron[$#envsave+5];
+       int i=0;
+$envsave
+       newenviron[i++]="HOME=$ENV{HOME}";
+       newenviron[i++]="WRAPPED_OPTIONS=$configstring";
+       newenviron[i]=NULL;
+       environ=newenviron;
+
+       if (setregid(getegid(), -1) != 0 || setreuid(geteuid(), -1) != 0) {
+               perror("failed to drop real uid/gid");
+               exit(1);
+       }
+
+       execl("$this", "$this", NULL);
+       perror("failed to run $this");
+       exit(1);
+}
+EOF
+       close OUT;
+       if (system("gcc", "$wrapper.c", "-o", $wrapper) != 0) {
+               error("failed to compile $wrapper.c");
+       }
+       unlink("$wrapper.c");
+       if (defined $config{wrappermode} &&
+           ! chmod(oct($config{wrappermode}), $wrapper)) {
+               error("chmod $wrapper: $!");
+       }
+       print "successfully generated $wrapper\n";
+} #}}}
+
+1
diff --git a/1.33.2/Makefile.PL b/1.33.2/Makefile.PL
new file mode 100755 (executable)
index 0000000..b27e6ce
--- /dev/null
@@ -0,0 +1,62 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use ExtUtils::MakeMaker;
+
+# Add a few more targets.
+sub MY::postamble {
+q{
+all:: extra_build
+clean:: extra_clean
+install:: extra_install
+pure_install:: extra_install
+
+VER=$(shell perl -e '$$_=<>;print m/\((.*?)\)/'<debian/changelog)
+
+extra_build:
+       ./ikiwiki.pl doc html --templatedir=templates --underlaydir=basewiki \
+               --wikiname="ikiwiki" --verbose --no-rcs \
+               --exclude=/discussion --no-discussion \
+               --plugin=brokenlinks --plugin=pagecount \
+               --plugin=orphans --plugin=haiku --plugin=meta \
+               --plugin=tag --plugin=polygen --plugin=pagestats \
+               --plugin=fortune --plugin=aggregate --plugin=map \
+               --plugin=template --plugin=toc
+       ./mdwn2man ikiwiki 1 doc/usage.mdwn > ikiwiki.man
+       ./mdwn2man ikiwiki-mass-rebuild 8 doc/ikiwiki-mass-rebuild.mdwn > ikiwiki-mass-rebuild.man
+       ./pm_filter $(PREFIX) $(VER) < ikiwiki.pl > ikiwiki.out
+               
+extra_clean:
+       rm -rf html doc/.ikiwiki
+       rm -f ikiwiki.man ikiwiki-mass-rebuild.man ikiwiki.out
+
+extra_install:
+       install -d $(DESTDIR)$(PREFIX)/share/ikiwiki/templates
+       $(CP) -a templates/* $(DESTDIR)$(PREFIX)/share/ikiwiki/templates
+
+       install -d $(DESTDIR)$(PREFIX)/share/ikiwiki/basewiki
+       $(CP) -a basewiki/* $(DESTDIR)$(PREFIX)/share/ikiwiki/basewiki
+
+       install -d $(DESTDIR)$(PREFIX)/share/man/man1
+       install ikiwiki.man $(DESTDIR)$(PREFIX)/share/man/man1/ikiwiki.1
+       
+       install -d $(DESTDIR)$(PREFIX)/share/man/man8
+       install ikiwiki-mass-rebuild.man $(DESTDIR)$(PREFIX)/share/man/man8/ikiwiki-mass-rebuild.8
+       
+       install -d $(DESTDIR)$(PREFIX)/sbin
+       install ikiwiki-mass-rebuild $(DESTDIR)$(PREFIX)/sbin
+
+       install -d $(DESTDIR)$(PREFIX)/lib/w3m/cgi-bin
+       install ikiwiki-w3m.cgi $(DESTDIR)$(PREFIX)/lib/w3m/cgi-bin
+
+       install -d $(DESTDIR)$(PREFIX)/bin
+       install ikiwiki.out $(DESTDIR)$(PREFIX)/bin/ikiwiki
+}
+}
+
+WriteMakefile(
+       NAME            => 'IkiWiki',
+       PREFIX          => "/usr/local",
+       PM_FILTER       => './pm_filter $(PREFIX) $(VER)',
+       MAN1PODS        => {},
+);
diff --git a/1.33.2/NEWS b/1.33.2/NEWS
new file mode 120000 (symlink)
index 0000000..798088b
--- /dev/null
@@ -0,0 +1 @@
+debian/NEWS
\ No newline at end of file
diff --git a/1.33.2/README b/1.33.2/README
new file mode 100644 (file)
index 0000000..f5b128d
--- /dev/null
@@ -0,0 +1,5 @@
+Use ./Makefile.PL to generate a Makefile, "make" will build the
+documentation wiki and a man page, and "make install" will install ikiwiki.
+
+All other documentation is in the ikiwiki documentation wiki, which is also
+available online at <http://ikiwiki.kitenet.net/>
diff --git a/1.33.2/basewiki/blog.mdwn b/1.33.2/basewiki/blog.mdwn
new file mode 100644 (file)
index 0000000..859fa6a
--- /dev/null
@@ -0,0 +1,35 @@
+You can turn any page on this wiki into a weblog by inserting a
+[[PreProcessorDirective]]. Like this:
+
+       \[[inline pages="blog/* and !*/Discussion" show="10" rootpage="blog"]]
+
+Any pages that match the specified [[PageSpec]] (in the example, any
+[[SubPage]] of "blog") will be part of the blog, and the newest 10
+of them will appear in the page. Note that if files that are not pages
+match the [[PageSpec]], they will be included in the feed using RSS
+enclosures, which is useful for podcasting.
+
+The optional `rootpage` parameter tells the wiki that new posts to this blog
+should default to being [[SubPage]]s of "blog", and enables a form at the
+top of the blog that can be used to add new items.
+
+If you want your blog to have an archive page listing every post ever made
+to it, you can accomplish that like this:
+
+       \[[inline pages="blog/* and !*/Discussion" archive="yes"]]
+
+You can even create an automatically generated list of all the pages on the
+wiki, with the most recently added at the top, like this:
+
+       \[[inline pages="* and !*/Discussion" archive="yes"]]
+
+If you want to be able to add pages to a given blog feed by tagging them,
+you can do that too. To tag a page, just make it link to a page or pages 
+that represent its tags. Then use the special link() [[PageSpec]] to match
+all pages that have a given tag:
+
+       \[[inline pages="link(life)"]]
+
+Or include some tags and exclude others:
+
+       \[[inline pages="link(debian) and !link(social)"]]
diff --git a/1.33.2/basewiki/favicon.ico b/1.33.2/basewiki/favicon.ico
new file mode 100644 (file)
index 0000000..354b627
Binary files /dev/null and b/1.33.2/basewiki/favicon.ico differ
diff --git a/1.33.2/basewiki/helponformatting.mdwn b/1.33.2/basewiki/helponformatting.mdwn
new file mode 100644 (file)
index 0000000..4e5661b
--- /dev/null
@@ -0,0 +1,60 @@
+# Help on formatting text
+
+Text on this wiki is, by default, written in a form very close to how you
+might write text for an email message. This style of text formatting is
+called [[MarkDown]], and it works like this:
+
+Leave blank lines between paragraphs.
+
+You can \**emphasise*\* or \*\***strongly emphasise**\*\* text by placing it
+in single or double asterisks.
+
+To create a list, start each line with an asterisk:
+
+* "* this is my list"
+* "* another item"
+
+To make a numbered list, start each line with a number (any number will
+do) followed by a period:
+
+1. "1. first line"
+2. "2. second line"
+2. "2. third line"
+
+To create a header, start a line with one or more `#` characters followed
+by a space and the header text. The number of `#` characters controls the
+size of the header:
+
+# # h1
+## ## h2
+### ### h3
+#### #### h4
+
+To create a horizontal rule, just write three or more dashes on their own
+line:
+
+----
+
+To quote someone, prefix the quote with ">":
+
+> To be or not to be,
+> that is the question.
+
+To write a code block, indent each line with a tab or 4 spaces:
+
+       10 PRINT "Hello, world!"
+       20 GOTO 10
+
+To link to another page on the wiki, place the page's name inside double
+square brackets, so you would use `\[[WikiLink]]` to link to [[WikiLink]].
+
+To link to any other web page, or to an email address, you can just put the url in angle brackets: <<http://ikiwiki.kitenet.net>>, or you can use the form
+\[link text\]\(url\)
+
+----
+
+Advanced users can use [[PreProcessorDirective]]s to do additional cool
+stuff.
+
+Also, if the smiley plugin is enabled in your wiki, you can insert
+[[smileys]] and some other useful symbols.
diff --git a/1.33.2/basewiki/index.mdwn b/1.33.2/basewiki/index.mdwn
new file mode 100644 (file)
index 0000000..d598c1f
--- /dev/null
@@ -0,0 +1,7 @@
+Welcome to your new wiki.
+
+All wikis are supposed to have a [[SandBox]], so this one does too.
+
+----
+
+This wiki is powered by [ikiwiki](http://ikiwiki.kitenet.net).
diff --git a/1.33.2/basewiki/local.css b/1.33.2/basewiki/local.css
new file mode 100644 (file)
index 0000000..a0dec8c
--- /dev/null
@@ -0,0 +1,3 @@
+/* ikiwiki local style sheet */
+
+/* Add local styling here, instead of modifying style.css. */
diff --git a/1.33.2/basewiki/markdown.mdwn b/1.33.2/basewiki/markdown.mdwn
new file mode 100644 (file)
index 0000000..317a17d
--- /dev/null
@@ -0,0 +1,10 @@
+[Markdown](http://daringfireball.net/projects/markdown/)
+is a minimal markup language that resembles plain text as used in
+email messages. It is the markup language used by this wiki by default.
+
+For documentation about the markdown syntax, see [[HelpOnFormatting]] and
+[Markdown: syntax](http://daringfireball.net/projects/markdown/syntax).
+
+Note that [[WikiLink]]s and [[PreProcessorDirective]]s are not part of the
+markdown syntax, and are the only bit of markup that this wiki handles
+internally.
diff --git a/1.33.2/basewiki/pagespec.mdwn b/1.33.2/basewiki/pagespec.mdwn
new file mode 100644 (file)
index 0000000..b2b9135
--- /dev/null
@@ -0,0 +1,65 @@
+To select a set of pages, such as pages that are locked, pages
+whose commit emails you want subscribe to, or pages to combine into a
+blog, the wiki uses a PageSpec. This is an expression that matches
+a set of pages.
+
+The simplest PageSpec is a simple list of pages. For example, this matches
+any of the three listed pages:
+
+       foo or bar or baz
+
+More often you will want to match any pages that have a particular thing in
+their name. You can do this using a glob pattern. "`*`" stands for any part
+of a page name, and "`?`" for any single letter of a page name. So this
+matches all pages about music, and any [[SubPage]]s of the SandBox, but does
+not match the SandBox itself:
+
+       *music* or SandBox/*
+
+You can also prefix an item with "`!`" to skip pages that match it. So to
+match all pages except for Discussion pages and the SandBox:
+
+       * and !SandBox and !*/Discussion
+
+Some more elaborate limits can be added to what matches using any of these
+functions:
+
+* "`link(page)`" - match only pages that link to a given page
+* "`backlink(page)`" - match only pages that a given page links to
+* "`creation_month(month)`" - match only pages created on the given month
+* "`creation_day(mday)`" - or day of the month
+* "`creation_year(year)`" - or year
+* "`created_after(page)`" - match only pages created after the given page
+  was created
+* "`created_before(page)`" - match only pages created before the given page
+  was created
+
+For example, to match all pages in a blog that link to the page about music
+and were written in 2005:
+
+       blog/* and link(music) and creation_year(2005)
+
+More complex expressions can also be created, by using parentheses for
+grouping. For example, to match pages in a blog that are tagged with either
+of two tags, use:
+
+       blog/* and (link(tag/foo) or link(tag/bar))
+
+## Old syntax
+
+The old PageSpec syntax was called a "GlobList", and worked differently in
+two ways:
+
+1. "and" and "or" were not used; any page matching any item from the list
+   matched.
+2. If an item was prefixed with "`!`", then no page matching that item
+   matched, even if it matched an earlier list item.
+
+For example, here is the old way to match all pages except for the SandBox
+and Discussion pages:
+
+       * !SandBox !*/Discussion
+
+Using this old syntax is still supported. However, the old syntax is
+deprecated and will be removed at some point, and using the new syntax is
+recommended.
diff --git a/1.33.2/basewiki/preprocessordirective.mdwn b/1.33.2/basewiki/preprocessordirective.mdwn
new file mode 100644 (file)
index 0000000..1e2332c
--- /dev/null
@@ -0,0 +1,33 @@
+Preprocessor directives are similar to a [[WikiLink]] in form, except they
+contain spaces and parameters. The general form is:
+
+       \[[directive param="value" param="value"]]
+
+This gets expanded before the rest of the page is processed, and can be used
+to transform the page in various ways.
+
+The quotes around values can be omitted if the value is a simple word.
+Also, some directives may use parameters without values, for example:
+
+       \[[tag foo]]
+
+Note that if a preprocessor directive has no parameters, a space still must
+be put after its name, to avoid confusion with a [[WikiLink]]. For example:
+
+       \[[pagecount ]]
+
+A preprocessor directive does not need to all be on one line, it can be
+wrapped to multiple lines if you like:
+       
+       \[[directive foo="baldersnatch"
+       bar="supercalifragalisticexpealadocious" baz=11]]
+
+Also, multiple lines of *quoted* text can be used for a value.
+To allow quote marks inside the quoted text, delimit the block
+of text with triple-quotes:
+
+       \[[directive text="""
+       1. "foo"
+       2. "bar"
+       3. "baz"
+       """]]
diff --git a/1.33.2/basewiki/sandbox.mdwn b/1.33.2/basewiki/sandbox.mdwn
new file mode 100644 (file)
index 0000000..c93c8f3
--- /dev/null
@@ -0,0 +1,32 @@
+This is the SandBox, a page anyone can edit to learn how to use the wiki.
+
+----
+
+Here's a paragraph.
+
+Here's another one with *emphasised* text.
+
+# Header
+
+## Subheader
+
+> This is a blockquote.
+>
+> This is the first level of quoting.
+>
+> > This is nested blockquote.
+>
+> Back to the first level.
+
+Numbered list 
+
+1. First item.
+1. Another.
+1. And another..
+
+Bulleted list
+
+* *item*
+* item
+
+[[WikiLink]]
diff --git a/1.33.2/basewiki/shortcuts.mdwn b/1.33.2/basewiki/shortcuts.mdwn
new file mode 100644 (file)
index 0000000..a941dbd
--- /dev/null
@@ -0,0 +1,9 @@
+This page is used to control what shortcut links are supported by the wiki.
+
+* [[shortcut name=google url="http://www.google.com/search?q=%s"]]
+* [[shortcut name=wikipedia url="http://en.wikipedia.org/wiki/%s"]]
+* [[shortcut name=debbug url="http://bugs.debian.org/%s"]]
+* [[shortcut name=cpan url="http://search.cpan.org/search?mode=dist&query=%s"]]
+
+To add a new shortcut, use the "shortcut" preprocessor directive. "%s" in
+the url is replaced by the text of the shortcut.
diff --git a/1.33.2/basewiki/smileys.mdwn b/1.33.2/basewiki/smileys.mdwn
new file mode 100644 (file)
index 0000000..2b23d2b
--- /dev/null
@@ -0,0 +1,42 @@
+This page is used to control what smileys are supported by the wiki.
+Just write the text of a smiley to display it.
+
+* \:)  [[smileys/smile.png]]
+* \:-) [[smileys/smile.png]]
+* \:D  [[smileys/biggrin.png]]
+* \B)  [[smileys/smile2.png]]
+* \:)) [[smileys/smile3.png]]
+* \:-))        [[smileys/smile3.png]]
+* \;)  [[smileys/smile4.png]]
+* \;-) [[smileys/smile4.png]]
+* \:\  [[smileys/ohwell.png]]
+* \:/  [[smileys/ohwell.png]]
+* \>:> [[smileys/devil.png]]
+* \X-( [[smileys/angry.png]]
+* \<:( [[smileys/frown.png]]
+* \:(  [[smileys/sad.png]]
+* \:-( [[smileys/sad.png]]
+* \:-? [[smileys/tongue.png]]
+* \:o  [[smileys/redface.png]]
+* \|)  [[smileys/tired.png]]
+* \|-) [[smileys/tired.png]]
+* \{OK}        [[smileys/thumbs-up.png]]
+* \{X} [[smileys/icon-error.png]]
+* \(./)        [[smileys/checkmark.png]]
+* \(!) [[smileys/idea.png]]
+* \[!] [[smileys/attention.png]]
+* \/!\ [[smileys/alert.png]]
+* \{*} [[smileys/star_on.png]]
+* \{o} [[smileys/star_off.png]]
+
+For example: {*} :-) {*}
+
+----
+
+To change the supported smileys, just edit the lists on this page.
+Note that the format is important; each list item should start with the
+text that is turned into the smiley, escaped so that users can see what
+produces it, followed by a [[WikiLink]] to the image to display.
+
+/!\ Bear in mind that the link to the imge needs to be written in a way that
+will work if it's copied to other pages on the wiki.
diff --git a/1.33.2/basewiki/smileys/alert.png b/1.33.2/basewiki/smileys/alert.png
new file mode 100644 (file)
index 0000000..5bb87e3
Binary files /dev/null and b/1.33.2/basewiki/smileys/alert.png differ
diff --git a/1.33.2/basewiki/smileys/angry.png b/1.33.2/basewiki/smileys/angry.png
new file mode 100644 (file)
index 0000000..05bc69f
Binary files /dev/null and b/1.33.2/basewiki/smileys/angry.png differ
diff --git a/1.33.2/basewiki/smileys/attention.png b/1.33.2/basewiki/smileys/attention.png
new file mode 100644 (file)
index 0000000..7e06456
Binary files /dev/null and b/1.33.2/basewiki/smileys/attention.png differ
diff --git a/1.33.2/basewiki/smileys/biggrin.png b/1.33.2/basewiki/smileys/biggrin.png
new file mode 100644 (file)
index 0000000..f71b42c
Binary files /dev/null and b/1.33.2/basewiki/smileys/biggrin.png differ
diff --git a/1.33.2/basewiki/smileys/checkmark.png b/1.33.2/basewiki/smileys/checkmark.png
new file mode 100644 (file)
index 0000000..8869caa
Binary files /dev/null and b/1.33.2/basewiki/smileys/checkmark.png differ
diff --git a/1.33.2/basewiki/smileys/devil.png b/1.33.2/basewiki/smileys/devil.png
new file mode 100644 (file)
index 0000000..8684c39
Binary files /dev/null and b/1.33.2/basewiki/smileys/devil.png differ
diff --git a/1.33.2/basewiki/smileys/frown.png b/1.33.2/basewiki/smileys/frown.png
new file mode 100644 (file)
index 0000000..2999b55
Binary files /dev/null and b/1.33.2/basewiki/smileys/frown.png differ
diff --git a/1.33.2/basewiki/smileys/icon-error.png b/1.33.2/basewiki/smileys/icon-error.png
new file mode 100644 (file)
index 0000000..53b1055
Binary files /dev/null and b/1.33.2/basewiki/smileys/icon-error.png differ
diff --git a/1.33.2/basewiki/smileys/icon-info.png b/1.33.2/basewiki/smileys/icon-info.png
new file mode 100644 (file)
index 0000000..c08b08d
Binary files /dev/null and b/1.33.2/basewiki/smileys/icon-info.png differ
diff --git a/1.33.2/basewiki/smileys/idea.png b/1.33.2/basewiki/smileys/idea.png
new file mode 100644 (file)
index 0000000..37bc02d
Binary files /dev/null and b/1.33.2/basewiki/smileys/idea.png differ
diff --git a/1.33.2/basewiki/smileys/ohwell.png b/1.33.2/basewiki/smileys/ohwell.png
new file mode 100644 (file)
index 0000000..a83adfb
Binary files /dev/null and b/1.33.2/basewiki/smileys/ohwell.png differ
diff --git a/1.33.2/basewiki/smileys/redface.png b/1.33.2/basewiki/smileys/redface.png
new file mode 100644 (file)
index 0000000..9a87392
Binary files /dev/null and b/1.33.2/basewiki/smileys/redface.png differ
diff --git a/1.33.2/basewiki/smileys/sad.png b/1.33.2/basewiki/smileys/sad.png
new file mode 100644 (file)
index 0000000..68d9966
Binary files /dev/null and b/1.33.2/basewiki/smileys/sad.png differ
diff --git a/1.33.2/basewiki/smileys/smile.png b/1.33.2/basewiki/smileys/smile.png
new file mode 100644 (file)
index 0000000..b51b3ff
Binary files /dev/null and b/1.33.2/basewiki/smileys/smile.png differ
diff --git a/1.33.2/basewiki/smileys/smile2.png b/1.33.2/basewiki/smileys/smile2.png
new file mode 100644 (file)
index 0000000..43ea05f
Binary files /dev/null and b/1.33.2/basewiki/smileys/smile2.png differ
diff --git a/1.33.2/basewiki/smileys/smile3.png b/1.33.2/basewiki/smileys/smile3.png
new file mode 100644 (file)
index 0000000..c690ccc
Binary files /dev/null and b/1.33.2/basewiki/smileys/smile3.png differ
diff --git a/1.33.2/basewiki/smileys/smile4.png b/1.33.2/basewiki/smileys/smile4.png
new file mode 100644 (file)
index 0000000..f8f5b52
Binary files /dev/null and b/1.33.2/basewiki/smileys/smile4.png differ
diff --git a/1.33.2/basewiki/smileys/star_off.png b/1.33.2/basewiki/smileys/star_off.png
new file mode 100644 (file)
index 0000000..c5535c3
Binary files /dev/null and b/1.33.2/basewiki/smileys/star_off.png differ
diff --git a/1.33.2/basewiki/smileys/star_on.png b/1.33.2/basewiki/smileys/star_on.png
new file mode 100644 (file)
index 0000000..ec5c030
Binary files /dev/null and b/1.33.2/basewiki/smileys/star_on.png differ
diff --git a/1.33.2/basewiki/smileys/thumbs-up.png b/1.33.2/basewiki/smileys/thumbs-up.png
new file mode 100644 (file)
index 0000000..1faabac
Binary files /dev/null and b/1.33.2/basewiki/smileys/thumbs-up.png differ
diff --git a/1.33.2/basewiki/smileys/tired.png b/1.33.2/basewiki/smileys/tired.png
new file mode 100644 (file)
index 0000000..a3d5c56
Binary files /dev/null and b/1.33.2/basewiki/smileys/tired.png differ
diff --git a/1.33.2/basewiki/smileys/tongue.png b/1.33.2/basewiki/smileys/tongue.png
new file mode 100644 (file)
index 0000000..6510540
Binary files /dev/null and b/1.33.2/basewiki/smileys/tongue.png differ
diff --git a/1.33.2/basewiki/style.css b/1.33.2/basewiki/style.css
new file mode 100644 (file)
index 0000000..0334670
--- /dev/null
@@ -0,0 +1,207 @@
+/* ikiwiki style sheet */
+
+/* Note that instead of modifying this style sheet, you can instead edit
+ * local.css and use it to override or change settings in this one.
+ */
+
+.header {
+       margin: 0;
+       font-size: 22px;
+       font-weight: bold;
+       line-height: 1em;
+       display: block;
+}
+
+.author {
+       margin: 0;
+       font-size: 18px;
+       font-weight: bold;
+       display: block;
+}
+
+.actions ul {
+       margin: 0;
+       padding: 6px;
+       list-style-type: none;
+       border-bottom: 1px solid #000;
+}
+
+.inlinepage .actions ul {
+       border-bottom: 0;
+}
+
+.actions li {
+       display: inline;
+       padding: .2em .4em;
+}
+
+#backlinks {
+       margin: 1em 0;
+}
+
+.tags {
+       clear: both;
+}
+
+div.tags {
+       border-top: 1px solid #000;
+}
+
+#footer {
+       margin: 1em 0;
+}
+
+#searchform {
+       display: inline;
+       float: right;
+}
+
+#editcontent {
+       width: 100%;
+}      
+
+/* Stuff for the RecentChanges table. */
+tr.changeheader {
+       background: #eee;
+       color: black !important;
+}
+tr.changeinfo {
+       background: #eee;
+       color: black !important;
+}
+th.changeheader {
+       padding: 1px .3em;
+}
+td.changeinfo { 
+       padding: 1px .3em;
+}
+td.changetime {
+       white-space: nowrap;
+       padding: 1px .3em;
+}
+td.changelog {
+       font-style: italic;
+}
+
+.pagecloud {
+       padding: 10px 10px;
+       border: 1px solid #aaa;
+       background: #eee;
+       color: black !important;
+}
+
+/* Used for adding a blog page. */
+#blogform {
+       padding: 10px 10px;
+       border: 1px solid #aaa;
+       background: #eee;
+       color: black !important;
+}
+
+.inlinepage {
+       padding: 10px 10px;
+       border: 1px solid #aaa;
+}
+
+.pageinfo {
+       clear: both;
+       font-style: italic;
+       display: block;
+}
+
+/* Used for invalid form fields. */
+.fb_invalid {
+       color: red;
+       background: white !important;
+}
+
+/* Used for required form fields. */
+.fb_required {
+       font-weight: bold;
+}
+
+/* Orange feed button. */
+.feedbutton {
+       background: #ff6600;
+       color: white !important;
+       border-left: 1px solid #cc9966;
+       border-top: 1px solid #ccaa99;
+       border-right: 1px solid #993300;
+       border-bottom: 1px solid #331100;
+       padding: 0px 0.5em 0px 0.5em;
+       font-family: helvetica, arial, sans-serif;
+       font-weight: bold;
+       font-size: small;
+       text-decoration: none;
+       margin-top: 1em;
+}
+.feedbutton:hover {
+       color: white !important;
+       background: #ff9900;
+}
+
+/* Tag cloud. */
+.pagecloud {
+       float: right;
+       width: 30%;
+       text-align: center;
+}
+.smallestPC { font-size: 70%; }
+.smallPC { font-size: 85%; }
+.normalPC { font-size: 100%; }
+.bigPC { font-size: 115%; }
+.biggestPC { font-size: 130%; }
+
+#sidebar {
+       line-height: 3ex;
+       width: 20ex;
+       float: right;
+       margin-left: 40px;
+       margin-bottom: 40px;
+       padding: 2ex 2ex;
+}
+
+.infobox {
+       float: right;
+       margin-left: 2ex;
+       margin-top: 1ex;
+       margin-bottom: 1ex;
+       padding: 1ex 1ex;
+       border: 1px solid #aaa;
+}
+
+.notebox {
+       float: right;
+       margin-left: 2ex;
+       margin-top: 1ex;
+       margin-bottom: 1ex;
+       padding: 1ex 1ex;
+       border: 1px solid #aaa;
+       width: 25%
+}
+
+/* outlines  */
+li.L1 {
+       list-style: upper-roman;
+}
+li.L2 {
+       list-style: decimal;
+}
+li.L3 {
+       list-style: lower-alpha;
+}
+li.L4 {
+       list-style: disc;
+}
+li.L5 {
+       list-style: square;
+}
+li.L6 {
+       list-style: circle;
+}
+li.L7 {
+       list-style: lower-roman;
+}
+li.L8 {
+       list-style: upper-alpha;
+}
diff --git a/1.33.2/basewiki/subpage.mdwn b/1.33.2/basewiki/subpage.mdwn
new file mode 100644 (file)
index 0000000..4366920
--- /dev/null
@@ -0,0 +1,11 @@
+ikiwiki supports placing pages in a directory hierarchy. For example,
+this page, [[SubPage]] has some related pages placed under it, like
+[[SubPage/LinkingRules]]. This is a useful way to add some order to your
+wiki rather than just having a great big directory full of pages.
+
+To add a SubPage, just make a subdirectory and put pages in it. For
+example, this page is SubPage.mdwn in this wiki's source, and there is also
+a SubPage subdirectory, which contains SubPage/LinkingRules.mdwn. Subpages
+can be nested as deeply as you'd like.
+
+Linking to and from a SubPage is explained in [[LinkingRules]].
diff --git a/1.33.2/basewiki/subpage/linkingrules.mdwn b/1.33.2/basewiki/subpage/linkingrules.mdwn
new file mode 100644 (file)
index 0000000..83625cc
--- /dev/null
@@ -0,0 +1,21 @@
+To link to or from a [[SubPage]], you can normally use a regular
+[[WikiLink]] that does not contain the name of the parent directory of
+the [[SubPage]]. Ikiwiki descends the directory hierarchy looking for a
+page that matches your link.
+
+For example, if FooBar/SubPage links to "OtherPage", ikiwiki will first 
+prefer pointing the link to FooBar/SubPage/OtherPage if it exists, next
+to FooBar/OtherPage and finally to OtherPage in the root of the wiki.
+
+Note that this means that if a link on FooBar/SomePage to "OtherPage"
+currently links to OtherPage, in the root of the wiki, and FooBar/OtherPage
+is created, the link will _change_ to point to FooBar/OtherPage. On the
+other hand, a link from BazBar to "OtherPage" would be unchanged by this
+creation of a [[SubPage]] of FooBar.
+
+You can also specify a link that contains a directory name, like
+"FooBar/OtherPage" to more exactly specify what page to link to. This is
+the only way to link to an unrelated [[SubPage]].
+
+You can use this to, for example, to link from BazBar to "FooBar/SubPage",
+or from BazBar/SubPage to "FooBar/SubPage".
diff --git a/1.33.2/basewiki/wikiicons/diff.png b/1.33.2/basewiki/wikiicons/diff.png
new file mode 100644 (file)
index 0000000..0b98d79
Binary files /dev/null and b/1.33.2/basewiki/wikiicons/diff.png differ
diff --git a/1.33.2/basewiki/wikilink.mdwn b/1.33.2/basewiki/wikilink.mdwn
new file mode 100644 (file)
index 0000000..ce9ae20
--- /dev/null
@@ -0,0 +1,20 @@
+WikiLinks provide easy linking between pages of the wiki. To create a
+[[WikiLink]], just put the name of the page to link to in double brackets.
+For example "\[[WikiLink]]".
+
+If you ever need to write something like "\[[WikiLink]] without creating a
+wikilink, just prefix it with a "\", like "\\\\[[WikiLink]]".
+
+There are some special [[SubPage/LinkingRules]] that come into play when
+linking between [[SubPages|SubPage]].
+
+Also, if the file linked to by a WikiLink looks like an image, it will
+be displayed inline on the page.
+
+WikiLinks are matched with page names in a case-insensative manner, so you
+don't need to worry about getting the case the same, and can capitalise
+links at the start of a sentence, and so on.
+
+It's also possible to write a WikiLink that uses something other than the
+page name as the link text. For example "\[[foo_bar|SandBox]]" links to the
+SandBox page, but the link will appear like this: [[foo_bar|SandBox]]
diff --git a/1.33.2/debian/NEWS b/1.33.2/debian/NEWS
new file mode 100644 (file)
index 0000000..781a32f
--- /dev/null
@@ -0,0 +1,127 @@
+ikiwiki (1.32) unstable; urgency=low
+
+  There is a change to the plugin interface in this version. Any plugins that
+  modify data in %links should pass scan => 1 when registering the hook that
+  does so.
+
+ -- Joey Hess <joeyh@debian.org>  Sat, 28 Oct 2006 00:13:12 -0400
+
+ikiwiki (1.29) unstable; urgency=low
+
+  Wikis need to be rebuilt on upgrade to this version. If you listed your wiki
+  in /etc/ikiwiki/wikilist this will be done automatically when the Debian
+  package is upgraded. Or use ikiwiki-mass-rebuild to force a rebuild.
+
+  There is a change to the plugin interface in this version. Plugins that use
+  %renderedfiles will need to be updated, as the hash's values are now arrays
+  of rendered files. Plugins that cause a page to render additional files
+  should use the new will_render function to register the files.
+
+ -- Joey Hess <joeyh@debian.org>  Sun,  8 Oct 2006 17:27:56 -0400
+
+ikiwiki (1.22) unstable; urgency=low
+  
+  Due to some changes in the CSS, wikis should be rebuilt on upgrade to this
+  version. If you listed your wiki in /etc/ikiwiki/wikilist this will be done
+  automatically when the Debian package is upgraded. Or use ikiwiki-mass-rebuild
+  to force a rebuild.
+
+  If you have modified versions of ikiwiki's html templates, you will need
+  to update your templates to link to the stylesheet file using
+  "<TMPL_VAR BASEURL>style.css" instead of the old method which used
+  STYLEURL.
+
+  There have also been some changes to the plugin interface:
+  Any plugins that use santize, htmlize, or format hooks will need to be
+  updated for this version of ikiwiki since these hooks have been changed
+  to use named parameters.
+
+ -- Joey Hess <joeyh@debian.org>  Tue, 22 Aug 2006 15:33:12 -0400
+
+ikiwiki (1.13) unstable; urgency=low
+
+  The GlobList format which was used for specifiying sets of pages, has been
+  replaced with a new, more expressive PageSpec format. While GlobLists will
+  continue to work, that format is deprecated, and you are encouraged to use
+  PageSpecs from now on, and also to change any GlobLists in your wiki to
+  PageSpecs. See the new PageSpec page for details.
+  
+  You will need to rebuild your wiki when upgrading to this version. If you
+  listed your wiki in /etc/ikiwiki/wikilist this will be done automatically
+  when the Debian package is upgraded. Or use ikiiki-mass-rebuild to force a
+  rebuild.
+
+ -- Joey Hess <joeyh@debian.org>  Tue,  1 Aug 2006 18:29:51 -0400
+
+ikiwiki (1.11) unstable; urgency=low
+
+  Some changes to tags in this release, due to a new tag plugin. If you have
+  been using the meta plugin to tag pages, you'll want to enable the tag
+  plugin too, and change things like this:
+
+  [[meta link="foobar"]]
+
+  To this:
+
+  [[tag foobar]]
+
+  The new tags will appear at page footers, and are also easier to type.
+
+  There have also been some changes to the plugin interface, particularly the
+  interface of pagetemplate hooks has changed. See the changelog for details.
+
+ -- Joey Hess <joeyh@debian.org>  Thu, 27 Jul 2006 17:03:09 -0400
+
+ikiwiki (1.8) unstable; urgency=low
+
+  If your wiki is configured with a setup file, you should modify it to
+  stop setting the "plugin" list directly, and instead add or remove plugins
+  via the add_plugins and disable_plugins lines. For example, if you had:
+
+       plugin => [qw{inline smiley search}],
+
+  Change it to these lines, which disables the default htmlscrubber plugin
+  and adds the two additional plugins:
+
+       add_plugins => [qw{smiley search}],
+       disable_plugins => [qw{htmlscrubber}],
+
+  Making this change makes your ikiwiki setup file more future-proof since
+  new default plugins will be automatically used.
+  
+  You will need to rebuild your ikiwiki wrappers when upgrading to this
+  version. If you listed your wiki in /etc/ikiwiki/wikilist this will be
+  done automatically when the Debian package is upgraded. Or use
+  ikiiki-mass-rebuild --refresh to force a refresh.
+
+ -- Joey Hess <joeyh@debian.org>  Mon,  3 Jul 2006 16:59:29 -0400
+
+ikiwiki (1.1) unstable; urgency=low
+
+  There have been several configuration changes in this release of ikiwiki:
+
+  The --svn and --no-svn switches are removed, instead you should use
+   --rcs=svn or --no-rcs. ikiwiki setup files that set svn => 1 should
+  be changed to set rcs => "svn"; if your setup file sets svn => 0
+  then change it to use rcs => "" to disable svn.
+
+  The --hyperestraier switch is gone too. To enable searching, turn on the
+  search plugin, by passing --plugin=search or through the plugin setting in
+  the setup file.
+
+  The --sanitize and --no-sanitize switches are also gone, replaced with the
+  htmlscrubber plugin. This plugin is enabled by default, to disable it,
+  use --disable-plugin=htmlscrubber, or modify the plugin setting in the
+  setup file.
+
+  Discussion pages are enabled by default, but if your wiki is configured
+  with a setup file, you need to edit it to keep them enabled on upgrade
+  to this version. Add a line reading:
+  discussion => 1,
+
+  You will need to rebuild your wiki when upgrading to this version.
+  If you listed your wiki in /etc/ikiwiki/wikilist this will be done
+  automatically when the Debian package is upgraded. Or use
+  ikiiki-mass-rebuild to force a rebuild.
+
+ -- Joey Hess <joeyh@debian.org>  Tue,  2 May 2006 14:13:59 -0400
diff --git a/1.33.2/debian/README.Debian b/1.33.2/debian/README.Debian
new file mode 100644 (file)
index 0000000..9301318
--- /dev/null
@@ -0,0 +1,13 @@
+It's a good idea, and in some cases a requirement, to rebuild your wiki
+when upgrading to a new version of ikiwiki. If you have a lot of different
+wikis on a system, this can be a pain to do by hand, and it's a good idea
+to automate it anyway.
+
+This Debian package of ikiwiki supports rebuilding wikis on upgrade. It
+will run ikiwiki-mass-rebuild if necessary when upgraded. The file
+/etc/ikiwiki/wikilist lists the setup files of wikis to rebuild, as well
+as the user who owns the wiki. Edit this file and add any wikis you 
+set up.
+
+
+The examples directory contains the source to some example wiki setups.
diff --git a/1.33.2/debian/changelog b/1.33.2/debian/changelog
new file mode 100644 (file)
index 0000000..2d7923e
--- /dev/null
@@ -0,0 +1,805 @@
+ikiwiki (1.33.2) testing-proposed-updates; urgency=medium
+
+  * Backport fix for a security hole that allowed a web user to insert
+    arbitrary html in the title of a page due to missing escaping of
+    titles in the meta plugin.
+  * Fix examples directory location.
+
+ -- Joey Hess <joeyh@debian.org>  Wed, 21 Mar 2007 01:55:02 -0400
+
+ikiwiki (1.33.1) testing-proposed-updates; urgency=medium
+
+  * Backport fix for a security hole that allowed a web user to edit images
+    and other non-page format files in the wiki. To exploit this, the file
+    already had to exist in the wiki, and the web user would need to somehow
+    use the web based editor to replace it with malicious content.
+
+ -- Joey Hess <joeyh@debian.org>  Sat, 10 Feb 2007 15:30:12 -0500
+
+ikiwiki (1.33) unstable; urgency=low
+
+  * Fix issue with aggregate plugin updating expired pages.
+  * Avoid syntax errors in templates used by the template plugin crashing
+    ikiwiki.
+  * Enable utf8 file IO in aggregate plugin.
+  * Fix some issues with the new registration form.
+  * Patch from Ethan Glasser Camp to add a skip option to the inline plugin.
+  * Make sure to check for errors from every eval.
+  * Fix img plugin's handling of adding dependencies for images that do not
+    yet exist.
+  * Work around a strange bug in CGI::FormBuilder 3.0401 that makes
+    FORM-SUBMIT unusable on customised formbuilder templates. For now,
+    hardcode the submit buttons in editpage.tmpl instead of using the
+    template variable, which is ok, since the buttons are static.
+  * Work with hyperestraier 1.4.9.
+
+ -- Joey Hess <joeyh@debian.org>  Wed, 15 Nov 2006 18:32:26 -0500
+
+ikiwiki (1.32) unstable; urgency=low
+
+  * Add a separate pass to find page links, and only render each page once,
+    instead of over and over. Typical speedup is ~4x. Max possible speedup:
+    8x.
+  * Add "scan" parameter to hook(), which is used to make the hook be called
+    during the scanning pass, as well as the render pass. The meta and tag
+    plugins need to use the new scan parameter, so will any others that modify
+    %links.
+  * Now that links are calculated in a separate pass, it can also
+    precalculate backlinks in one pass, which is O(N^2) instead of the
+    previous code that was O(N^3). A very nice speedup for wikis with lots
+    (thousands) of pages.
+  * Stylish update to the ikiwiki logo, thanks to Recai Oktaş and Selçuk
+    Erdem.
+  * Add a default stylesheet entry for the pagecloud.
+  * Add examples page with some examples of things that can be done using
+    ikiwiki, like a weblog. The examples can be copied into a user's wiki
+    for a quick start, without needing to learn everything about how to put
+    them together.
+  * Install the source of the examples into /usr/share/doc/ikiwiki/examples.
+  * Add perlmagick to build-depends so syntax check of img plugin works.
+    Closes: #396702
+  * Improve login/register process, the login dialog has only name and
+    password fields, which allows more web browsers to regognise it as a login
+    field, and is less confusing.
+  * Implemented expiry options for aggregate plugin.
+  * Use precalculated backlinks info when determining if files need an update
+    due to a page they link to being added/removed. Mostly significant if
+    there are lots of pages.
+  * Remove duplicate link info when saving index. In some cases it could
+    pile up rather badly. (Probably not the best way to deal with this
+    problem.)
+  * Patch from James Westby to support podcasting, photoblogging, vidcasting,
+    or what have you, by creating enclosures for non-page items that are
+    included in feeds.
+
+ -- Joey Hess <joeyh@debian.org>  Fri,  3 Nov 2006 14:46:37 -0500
+
+ikiwiki (1.31) unstable; urgency=low
+
+  * Patch from Pawel Tecza to cp -a the templates in the Makefile.
+  * Change the rss feed title from the wikiname to the page title, with
+    an exception for the wiki's toplevel index page, which will still use the
+    wikiname as the feed title.
+    Overriding the page title with meta title already overrode the rss feed
+    tittle.
+  * Add an img plugin, based on Christian Mock's img plugin, but stripped
+    down to the bare essentials. Useful for handling large images on websites.
+  * Sanitize possibly problimatic characters out of the polygen grammar names,
+    just in case. Should not be exploitable anyway, since it only tries to run
+    polygen after finding the specified grammar file.
+  * Add missing dependency on the URI perl module.
+  * Add basic spam fighting tool for admins: An admin's prefs page now allows
+    editing a list of banned users.
+
+ -- Joey Hess <joeyh@debian.org>  Fri, 27 Oct 2006 23:16:33 -0400
+
+ikiwiki (1.30) unstable; urgency=low
+
+  * Add no_override parameter to hook().
+  * Add a shortcut plugin, inspired by Victor Moral's contributed shortcuts
+    plugin, but featuring a more ikiwiki-ish syntax and with shortcuts that
+    can be configured using a page in wiki.
+  * Fix support for --pingurl at the command line.
+  * Fix a subtle bug in will_render that broke some builds, by only clearing
+    items from renderedfiles the first time per build.
+  * Wrap entire technortati ping operation in an eval to catch all possible
+    failure modes, after I observed a simple ->value crashing ikiwiki when
+    a ping failed.
+
+ -- Joey Hess <joeyh@debian.org>  Mon, 16 Oct 2006 15:17:38 -0400
+
+ikiwiki (1.29) unstable; urgency=low
+
+  * Patch from Paul Tötterman to use CP in the Makefile.
+  * Patch from Alec Berryman adding a http_auth config item that allows
+    using HTTP Authentication instead of ikiwiki's built in authentication.
+    Useful for eg, large sites with their own previously existing user auth
+    setup. Closes: #384534
+  * Change %renderedfiles to store an array of files rendered from a given
+    source file, to allow tracking of extra rendered files like rss feeds.
+  * Note that plugins that accessed this variable will need to be updated!
+    The plugin interface has been increased to version 1.01 for this change.
+    As few plugins use %renderedfiles I haven't done anything else to ensure
+    compatability of old plugins.
+  * Add will_render function to the plugin interface, used to register that a
+    page renders a destination file, and do some security checks. Previously
+    but no longer rendered files will be cleaned up.
+  * Use will_render in the inline and linkmap plugins.
+  * You will need to rebuild your wiki on upgrade to this version.
+  * Atom feed support based on a patch by Clint Adams.
+  * Add feeds=no option to inline preprocessor directive to turn off all types
+    of feeds.
+  * $IkiWiki::version now holds the program version, and is accessible to
+    plugins.
+  * Make the aggregate plugin emphasize error messages.
+  * Patch from Recai to limit recentchanges to displaying max 10 files for a
+    given changeset (to avoid large number of file changes excessively
+    bloating the page).
+
+ -- Joey Hess <joeyh@debian.org>  Fri, 13 Oct 2006 23:14:28 -0400
+
+ikiwiki (1.28) unstable; urgency=low
+
+  * inline: Add ability to sort by page name, based on a patch from
+    Benjamin A'Lee.
+  * Fix a forkbomb in various calls to IPC::Open2, which has a highly
+    braindead interface. Closes: #389383
+  * Don't rm -rf ikiwiki on distclean, since a) there's no such file
+    and b) those poor Mac OSX users and their case insensative files!
+  * Don't fail syntax check if Text::Typography isn't installed.
+    Closes: #389406
+
+ -- Joey Hess <joeyh@debian.org>  Tue, 26 Sep 2006 02:08:17 -0400
+
+ikiwiki (1.27) unstable; urgency=low
+
+  * Work on firming up the plugin interface:
+    - Plugins should not need to load IkiWiki::Render to get commonly
+      used functions, so moved some functions from there to IkiWiki.
+    - Picked out the set of functions and variables that most plugins
+      use, documented them, and made IkiWiki export them by default,
+      like a proper perl module should.
+    - Use the other functions at your own risk.
+    - This is not quite complete, I still have to decide whether to
+      export some other things.
+  * Changed all plugins included in ikiwiki to not use "IkiWiki::" when
+    referring to stuff now exported by the IkiWiki module.
+  * Add a module version number to IkiWiki, so you can "use IkiWiki '1.00'"
+    to declare which version of the interface your plugin needs.
+  * Anyone with a third-party ikiwiki plugin is strongly encouraged
+    to make like changes to it and avoid use of non-exported symbols from
+    "IkiWiki::".
+  * Link debian/changelog and debian/news to NEWS and CHANGELOG.
+  * Support hyperestradier version 1.4.2, which adds a new required phraseform
+    setting.
+  * If an inlined page has a permalink, link the page title to that.
+  * Patch from Recai to use utf8 when reading the setup file, so that
+    utf8 wikinames from there will be used properly.
+  * Patch from Recai to kill utf-8 on the wiki name when generating the
+    session cookie.
+  * Change ddate plugin to use the DateTime::Calendar::Discordian perl module.
+  * Fix a baseurl problem in hyperestradier search results.
+  * Add a stub local.css to avoid problems with 404's.
+  * Patch from Recai to fix a wide character warning from the search plugin
+    during setup if the wikiname contains utf8.
+  * Yet another fix for those poor case-insensative OS X users.
+  * pagetemplate hooks are now also called when generating cgi pages.
+  * Add a favicon plugin, which simply adds a link tag for an icon to each
+    page (and cgis).
+  * Patch from James Westby to deal with the case where you're editing a
+    new page, hit cancel, and need to be redirected to somewhere sane.
+  * Various documentation improvements by various wiki users.
+  * Support Text::Markdown from CPAN, which has a different interface from
+    the original markdown or the one in Debian.
+  * Version the libcgi-session-perl dependency, some features that need
+    the new version are used in some cases (sslcookie).
+  * Numerous tla fixes from Clint.
+  * Updated ikiwiki.svgz from Recai, includes an icon and is used to generate
+    a multi-resolution favicon.ico.
+  * README.Debian: typo Closes: #388110
+  * chomp trailing newline at the end of templates read in by the template
+    plugin, to allow use of the template preprocessor directive in
+    whitespace-sensative situations. Closes: #387073
+  * Patch from James Westby to make the location of the estseek.cgi script
+    configurable.
+  * Add typography (SmartyPants) plugin by Recai.
+  * Add --render mode, which can be used to preview an edit at the command
+    line by test rendering a single page.
+  * Add a googlecalendar plugin. A bit special-purpose, but it shows
+    one way to to deal with user-supplied content that could cause XSS
+    issues w/o the htmlscrubber, and won't survive the scrubber.
+
+ -- Joey Hess <joeyh@debian.org>  Sun, 24 Sep 2006 00:02:21 -0400
+
+ikiwiki (1.26) unstable; urgency=low
+
+  * Add a missing -n to tla undo call.
+  * otl2hmtl can't be safely used with IPC::Open2 since it sometimes
+    writes before consuming its whole stdin. Avoid this deadlock.
+  * Fix alt tags for outline checkboxes.
+
+ -- Joey Hess <joeyh@debian.org>  Fri,  8 Sep 2006 16:24:16 -0400
+
+ikiwiki (1.25) unstable; urgency=low
+
+  * Add proper waitpid calls for open2ed processes throughout to avoid
+    zombies; this hit htmltidy especially badly.
+  * Drop real uid/gid in the suid wrapper, thus allowing commits to remote
+    subversion repos and fixing some other issues.
+  * Add support for tla, contributed by Clint Adams. Closes: #385936
+  * Add support for mercurial, contributed by Emanuele Aina.
+  * Include <link rel> tag for RSS feeds, used by some aggregators and
+    firefox to find the feed.
+  * Add a linkmap plugin (requires graphviz).
+
+ -- Joey Hess <joeyh@debian.org>  Fri,  8 Sep 2006 01:54:14 -0400
+
+ikiwiki (1.24) unstable; urgency=low
+
+  * Simplify the data structure returned by rcs_recentchanges to avoid
+    each rcs plugin needing to form complex strings on its own.
+  * Fix another destpage issue in the inline directive. Closes: #385512
+    again.
+
+ -- Joey Hess <joeyh@debian.org>  Sun,  3 Sep 2006 15:46:45 -0400
+
+ikiwiki (1.23) unstable; urgency=low
+
+  * Allow inline directives to be nested inside eg, sidebars. Closes: #385512
+
+ -- Joey Hess <joeyh@debian.org>  Sun,  3 Sep 2006 12:14:45 -0400
+
+ikiwiki (1.22) unstable; urgency=low
+
+  * Change how the stylesheet url is determined in the templates: Remove
+    STYLEURL and add BASEURL to all templates (some already had it). This
+    new more general variable can be used to link to other things (eg, images)
+    from the template, as well as stylesheets.
+  * Fix a bug introduced last version to do with nested inlines.
+  * Allow preprocessor directives to span multiple lines, both to make
+    long ones with lots of values easier to write, and to allow for ones with
+    multi-line quoted values.
+  * Allow preprocessor directives to contain python-like triple-quoted
+    text blocks, for easy nesting of quotes inside.
+  * Add a template plugin.
+  * Make pagespec merge code smarter about merging duplicate pagespecs.
+  * Patch from Jordà Polo to make Setup::Standard support hashes in config
+    files.
+  * Change order of linkify and preprocess; first preprocess and then linkify.
+    This allows passing a wikilink inside a parameter to a preprocessor
+    directive without it being expanded to html, and leaking out of the
+    parameter, which had required some non-obvious use of triple-quoting
+    to avoid. Note that any preprocessor plugins that output something
+    that looks like a wikilink will now have it treated as such; AFAIK
+    this doesn't change any behavior though except for the template plugin.
+  * Enable preprocessor directives when previewing an edit.
+  * Make all pages pull in a local.css style sheet, if present. This won't
+    be included in ikiwiki, but can be created to make local styling changes
+    w/o needing to merge in every new change to the distributed style.css.
+  * Use DESTDIR and not PREFIX to specify installation prefix for packaging.
+  * Support running "perl Makefile.PL PREFIX=foo" to build ikiwiki to run
+    from a different directory.
+  * Generalised preprocesser loop protection code.
+  * Patch from James Westby to allow a description to be set for rss feeds.
+  * Patch from James Westby to add a template for the search form.
+  * Added a ddate plugin.
+  * Patch from James Westby to add a --sslcookie switch, which forces
+    cookies to only be sent over ssl connections to avoid interception.
+  * Fix preferences page on anonok wikis; still need to sign in to get
+    to the preferences page.
+  * Add toc (table of contents) plugin.
+  * Change htmlize, format, and sanitize hooks to use named parameters.
+  * Patch from James Westby to add an actions option to inline; this
+    adds Edit and Discussion links at the end of blog entries.
+  * Due to some css changes, you'll want to rebuild your wiki on upgrade
+    to this version. Will be handled automatically by the deb.
+  * Add processed date to aggregate preprocessor directive status output.
+
+ -- Joey Hess <joeyh@debian.org>  Fri,  1 Sep 2006 22:03:34 -0400
+
+ikiwiki (1.21) unstable; urgency=low
+
+  * Add a tail fin^W^Wsidebar plugin by Tuomo Valkonen.
+  * If a page links to itself, mark up the link text in a span with
+    class="selflink" so that it can be styled. I don't have a useful style
+    defined for that though.
+  * Call filter hooks on inlined page content.
+  * Support inlining pages raw, rather than creating a blog.
+  * Clean up yes/no parameter parsing in inline plugin.
+  * Implemented better cycle detection in the inline plugin; nested inlines
+    will now work.
+  * Add a map plugin contributed by Alessandro Dotti Contra.
+  * Add otl format plugin, which handles files as created by vimoutliner.
+  * Fix ikiwiki-mass-rebuild to work in the way the postinst uses it.
+  * Add first draft at a Restructured Text (rst) plugin, by Sergio
+    Talens-Oliag. Note that this has many known issues -- see the caveats on
+    the plugin's page.
+  * Credit everyone who wrote a plugin on the plugins' wiki pages.
+  * Fix utf-8 in blog post form.
+
+ -- Joey Hess <joeyh@debian.org>  Sun, 20 Aug 2006 16:42:54 -0400
+
+ikiwiki (1.20) unstable; urgency=low
+
+  * Relicense the templates and basewiki under the 2-clause BSD license.
+    Since these can easily become part of other people's websites, they
+    should be under as permissive a license as possible.
+  * Add --syslog config option, to log to the syslog.
+  * Catch failing IPC::Open2 in tidy plugin and retry in case this is a
+    transient failure to fork (which I've seen happen in the wild).
+  * Fix a bug in the aggregator introduced last version that caused all
+    aggregator state to be lost during a non-aggregating build.
+
+ -- Joey Hess <joeyh@debian.org>  Thu, 17 Aug 2006 19:05:56 -0400
+
+ikiwiki (1.19) unstable; urgency=low
+
+  * Fix several related bugs in page type determination during online editing.
+  * Add some locking to prevent 2 aggregators from running at once.
+  * Fix an infinite loop in the aggregator when finding a unique filename.
+
+ -- Joey Hess <joeyh@debian.org>  Wed, 16 Aug 2006 13:46:25 -0400
+
+ikiwiki (1.18) unstable; urgency=low
+
+  * The last release accidentially installed ikiwiki as ikiwiki.pl, now fixed.
+  * Add --version.
+  * Man page format fixups.
+  * If the meta plugin overides the page title, set a title_overridden
+    variable in the template to true. This allows doing things with the
+    templates conditional on the title being overriden.
+  * Add a %pagecase which maps lower-case page names to the actual case
+    used in the filename. Use this in bestlinks calculation instead of
+    forcing the link to lowercase.
+  * Also use %pagecase in various other places that want to check if a page
+    with a given name exists.
+  * This means that links to pages with mixed case names will now work,
+    even if the link is in some other case mixture, and mixed case pages
+    should be fully supported throughout ikiwiki.
+  * Recommend rebuilding wikis on upgrade to this version.
+
+ -- Joey Hess <joeyh@debian.org>  Sat, 12 Aug 2006 22:10:48 -0400
+
+ikiwiki (1.17) unstable; urgency=low
+
+  * Disable tidy generator tag.
+  * Move tidy back to sanitize hook, found out how to only show body.
+  * Turn off tidy indentation too.
+  * Turn on HTML::Template loop_context_vars; not actually used in stock
+    templates but can be useful for things like making comma-delimited lists
+    of tags or what have you.
+  * Remove <br> from end of aggregate preprocessor directive output.
+  * Ship ikiwiki executable as ikiwiki.pl in source to avoid issues on
+    case-sensative filesystems like OSX.
+  * Improve markdown loading. First, try to load it as a proper perl module,
+    in case it was installed as one. Then fall back to trying
+    /usr/bin/markdown.
+  * Document in install page how to install markdown, since it has no
+    installation procedure in the upstream tarball.
+  * Set die_on_bad_params => 0 for all templates, to allow users to modify
+    them without annoyances.
+  * Suck in the page content when generating an inline archive page, to work
+    around the meta plugin's lack of caching of title metadata across runs.
+
+ -- Joey Hess <joeyh@debian.org>  Sat, 12 Aug 2006 12:52:13 -0400
+
+ikiwiki (1.16) unstable; urgency=low
+
+  * Try to handle relative links in aggregated feeds. However,
+    the current support is a crude hack due to limitations of XML::Feed:
+    xml:base is not supported, neither is Content-Location. And of course,
+    relative links in RSS feeds are ill-undefined..
+  * Make aggregator save permalinks and author name to pages as metadata.
+  * Add permalink and author support to meta plugin, affecting RSS feeds
+    and blog pages.
+  * Various CSS and formatting changes.
+  * Encode link and guid urls in rss feeds to avoid illegal utf8 slipping in.
+  * Add xhtml files to the default prune regexp.
+  * Also generate rel=bookmark links for permalinks.
+  * Fix the htmltidy plugin, which wasn't working due my breaking it when
+    I added it..
+  * Don't run tidy with -xml as that fails if the input is not well-formed.
+    Run it with -asxhtml instead, so it will output well-formed xhtml no
+    matter what the input.
+  * Disable tidy warnings too.
+  * Add a new format hook, and make tidy use it, since tidy can really only
+    operate on and output complete html documents, not the body chunks
+    that sanitise gets.
+  * Fix dates in rss feeds if running localised, so they're still rfc 822.
+
+ -- Joey Hess <joeyh@debian.org>  Fri,  4 Aug 2006 20:48:36 -0400
+
+ikiwiki (1.15) unstable; urgency=low
+
+  * Remove CDPATH and other env vars perl taint checking doesn't like.
+    Closes: #381279
+  * Added created_before and created_after PageSpec limits.
+
+ -- Joey Hess <joeyh@debian.org>  Thu,  3 Aug 2006 13:00:57 -0400
+
+ikiwiki (1.14) unstable; urgency=low
+
+  * Memoize pagespec translation, this speeds up a build of the ikiwiki tree
+    by 10% or so.
+  * Fix stupid bug in date matching, patch from Roland Mas. Closes: #381132
+  * Added many unit tests for pagespec_match.
+
+ -- Joey Hess <joeyh@debian.org>  Wed,  2 Aug 2006 11:34:06 -0400
+
+ikiwiki (1.13) unstable; urgency=low
+
+  * ikiwiki can now download and aggregate feeds with its new aggregate
+    plugin, so it's possible to implement a Planet using ikiwiki!
+  * Add a run_hooks function for the common task of running all hooks of a
+    given type.
+  * Add a savestate hook.
+  * Don't put blog post forms on pages if there's no cgiurl set.
+  * --setup --refresh no longer rebuilds wrappers. Use --setup --refresh
+    --wrappers to do that.
+  * Add %IkiWiki::forcerebuild to provide a way for plugins like aggregate
+    to update pages that haven't changed on disk.
+  * Change meta tags to use html entity-escaped text for values, so that
+    quotes and such can be represented in title tags.
+  * Depend and build-depend on HTML::Parser for HTML::Entities which is used
+    for the above.
+  * Make --rebuild also cause --aggregate to re-download and write aggregated
+    pages.
+  * Avoid outputting duplicate meta info.
+  * Include title metadata on aggregated posts for capitalised and un-munged
+    titles.
+  * Title metadata of inlined pages now shows up in blogs and rss feeds.
+  * Fix issue with unicode filenames and updating the hyper estradier search
+    index. (Aka Please Please Please, let that be the last one.)
+  * Patch from Roland Mas to support an rss=no parameter to inline directives.
+    Closes: #380743
+  * Renamed GlobLists to PageSpecs.
+  * PageSpecs can now include nested parens, "and", and "or". This remains
+    backwards compatible to the old GlobList format. It's implemented by
+    treating the GlobList as a very limited microlanguage that is transformed
+    to perl code that does the matching.
+  * The old GlobList format is deprecated, and I encourage users to switch to
+    using the new PageSpec format. Compatability with the old format will be
+    removed at some point, possibly by 2.0.
+  * Wiki rebuild needed on upgrade to this version due to PageSpec change.
+  * Add support for creation_month and creation_year to PageSpec.
+    Closes: #380680
+  * Changes to index file encoding.
+
+ -- Joey Hess <joeyh@debian.org>  Tue,  1 Aug 2006 21:21:19 -0400
+
+ikiwiki (1.12) unstable; urgency=low
+
+  "Viva l'Italia!"
+  * New pagestats plugin from Enrico, which can generate a table counting
+    the backlinks for each page, or a del.icio.us style cloud.
+  * Build-depend on libtext-wikiformat-perl, so that the syntax check of
+    the wikiformat plugin works. Thanks, Emanuele Aina.
+  * Patch from Alessandro Dotti Contra to clean up backlinks and navbar
+    display, running them through pagetitle. This removes ugly underscores and
+    other gunk from the display, much nicer. You may want to rebuild your wiki
+    when upgrading to get the cleanup globally.
+  * Polygen plugin from Enrico.
+  * htmltidy plugin from Faidon.
+  * Locale patch from Faidon:
+    - Adds a locale setting to setup files.
+    - Proper local time, if the locale configuration option is used.
+    - Support for UTF-8 (or ISO-8859-X) filenames in SVN. Before this patch,
+      commiting (or even rcs_updating) on repositories with UTF-8 filenames was
+      impossible.
+  * Add getopt hook type, this allows plugins to add new command-line options.
+  * Add --tagbase option to tag plugin.
+  * Add exclude option in setup files, works same as --exclude.
+  * Put categories in rss feeds for tagged items.
+  * Allow preprocessor directives to be expanded in inlined blog pages.
+    However, to avoid inlining loops etc, don't expand inline directives in
+    inlined pages.
+  * fortune plugin (trivial)
+  * Tag plugins according to type.
+
+ -- Joey Hess <joeyh@debian.org>  Sat, 29 Jul 2006 17:12:56 -0400
+
+ikiwiki (1.11) unstable; urgency=low
+
+  * Patch from Enrico that
+    - Adds a tag plugin that allows more easily tagging pages.
+      The meta plugin can also still be used for that, but the tag plugin
+      also lists a page's tags at the bottom of the page.
+    - Allows preprocessor directives to have parameters with no specified
+      value.
+    - Fixes preprocessor directive parameter parsing so that
+      foo=bar baz now means "foo=bar" and a "baz" with no value.
+  * Run pagetemplate hooks when inlining pages so that inlined pages also
+    list their tags.
+  * Make all plugins with pagetemplate hooks check that variables exist
+    on the template before setting them, for robustness.
+  * Switch pagetemplate hooks to using named parameters.
+  * Pass a destpage parameter to preprocessor and pagetemplate hooks.
+    This will be the page that a source page will be part of, which is
+    different than the source page for inlined pages.
+  * Audited all plugins to endure they pass (page, destpage) to htmllink
+    appropriatly. This means inlining of various plugins will not work
+    properly, with correct links generated.
+
+ -- Joey Hess <joeyh@debian.org>  Thu, 27 Jul 2006 20:51:23 -0400
+
+ikiwiki (1.10) unstable; urgency=low
+
+  * Run page through any relevant filters when generating a page preview.
+  * Noticed a bug in the wikitext markup plugin -- it made CamelCase links the
+    default throughout the wiki, not only on wikitext pages. Decided to call
+    this a feature, and split the camelcase support out into a separate plugin
+    that is independant of wikitext.
+  * Fix CamelCase regexp to not break [[FooBar|BazBar]] WikiLinks.
+
+ -- Joey Hess <joeyh@debian.org>  Wed, 26 Jul 2006 18:06:35 -0400
+
+ikiwiki (1.9) unstable; urgency=low
+
+  * Improve display of parentlinks and page title of toplevel index page.
+  * Patch from Faidon to use svn --limit when possible for recentchanges,
+    speeds up recentchanges a lot for wikis with more history.
+  * Patch from Recai to fix utf8 issues in git backend.
+  * Add wikitext markup plugin, which supports ".wiki" pages written in the
+    original wiki syntax, CamelCase links and all.
+  * Support a w3mmode, which lets w3m run ikiwiki using its local CGI
+    support, to edit pages etc without a web server.
+  * Display CGI processing errors if present.
+  * Fix from Faidon for a XML parser issue that breaks utf-8 for
+    RecentChanges. Avoid using XML::SAX::PurePerl, which is buggy in this
+    area, and also way slow.
+  * Match 'web commit from' in SVN and git, these are web commits too.
+    (Faidon)
+  * Consolidated all decode_utf8 in FormBuilder's fields to make the code more
+    readable and avoid future mistakes. The patch seems to work and for the
+    first time I have a UTF-8 username ;-) (Faidon)
+  * Use form->field consistently, not form->param.
+  * Patch from Recai to allow selection of page type when creating a new page.
+    Default page type is inherited from the link clicked on to create the new
+    page.
+
+ -- Joey Hess <joeyh@debian.org>  Wed, 26 Jul 2006 17:25:30 -0400
+
+ikiwiki (1.8) unstable; urgency=low
+
+  * Fix orphans plugin to not count a link to a nonexistant page as a reason
+    for a page not being an orphan.
+  * Support pinging services such as Technorati using XML-RPC to notify them
+    about changes to rss feeds.
+  * Parse svn log as xml for improved utf8 and security. Note that this makes
+    ikiwiki depend on XML::Simple. Patch by Faidon Liambotis.
+  * POSIX::strftime doesn't know about encodings and doesn't return a utf8
+    flagged string even if the locale causes it to generate utf8 output,
+    so make sure to let perl know it should be handled as utf8. Also,
+    the optimised version used for standard time formats won't work if the
+    user has changed locale, so drop it. Thanks, Faidon Liambotis.
+  * Fix re-encoding of the comments field to utf8 if a commit fails
+    due to a conflict. Thanks, Faidon Liambotis.
+  * Let svn know that commits have utf8 commit messages. Thanks, Faidon
+    Liambotis.
+  * Add insane double encode/decode to utf8 around call to markdown.
+    This works around a truely strange bug, which is apparently a bug in
+    perl, #376329. Also added a test case for it.
+  * Improve layout of edit page so formatting help link is always visible w/o
+    getting in the way of the preview.
+  * Centralised all calls to HTML::Template and force all the templates
+    to be read as utf8.
+  * Support pages with utf8 filenames. Patch by Faidon Liambotis.
+  * Introduce add_plugins and disable_plugins config options in setup files.
+    This allows adding or removing plugins w/o overriding the whole list of
+    default plugins, which makes it easier to upgrade when new default plugins
+    are added.
+  * Support htmlize plugins and make mdwn one such plugin, which is enabled by
+    default (of course!). Based on a patch by Faidon Liambotis.
+  * Add a html plugin, which can be used to write wikis in raw html,
+    if you'd ever want to do such a thing. Slightly tricky, since ikiwiki
+    defaults to not processing .html files, since w/o this plugin they would
+    be copied unsanitised. With this plugin, it will process and html
+    sanitise them, like any other page type.
+  * Rebuilding wrappers is necessary on upgrade to this version.
+  * Make ikiwiki --setup --refresh rebuild wrappers, so wrapper rebuild
+    will be automatically done on all upgrades.
+  * Don't send pings if the wiki is being rebuilt.
+  * Work around very innefficient behavior in File::Spec::abs2rel. Result
+    is a savings of 2 pointless fork/execs per link calculation, which
+    results in ~25% speedup of ikiwiki building its own doc wiki, and
+    about 35% speedup displaying RecentChanges!
+  * Make RecentChanges use a table and some CSS, should be much more readable.
+    No code changes involved.
+  * Encode & in diffurl in examples, to conform to pedantic rules.
+  * Speed up RecentChanges by another 40% or so with some memoization.
+  * Memoize abs2rel, which is still kinda slow, for another 30% speedup
+    in time to build the doc wiki.
+
+ -- Joey Hess <joeyh@debian.org>  Tue,  4 Jul 2006 12:46:29 -0400
+
+ikiwiki (1.7) unstable; urgency=low
+
+  * Updated logo from Recai with some kerning and alingment tuning.
+  * Patch from Recai to fix git recentchanges code to work with git 1.4 which
+    changed some output.
+  * Copyright update.
+
+ -- Joey Hess <joeyh@debian.org>  Sun, 18 Jun 2006 23:33:35 -0400
+
+ikiwiki (1.6) unstable; urgency=low
+
+  * YA utf-8 patch from Recai, this time to fix previewing a page so that
+    the text in the input box is re-encoded back to utf-8.
+  * -CSD does not affect modules, so readfile() was not using the utf-8 input
+    layer, which led to lots of problems; make it force read files as utf-8.
+    Closes: #373203
+  * Note that as a consequence, this version of ikiwiki will actually try to
+    parse utf8 in source files for the first time, which may expose broken
+    utf8 in wiki sources that was hidden before. Most common will be
+    perl warnings like "utf8 "\xE9" does not map to Unicode"
+  * writefile() likewise needs to use the utf8 output layer.
+  * Remove the -CSD from ikiwiki's hashbang since it's useless to have it
+    there.
+  * Revert some of the decode_utf8 changes in CGI.pm that seem unnecessary
+    given the readfile fix.
+  * Add utf-8 testcases for readfile and htmlize.
+  * Put back the encode_utf8 in the input to markdown; it's really not utf-8
+    safe.
+  * More utf-8 fixes from Recai, partly to things I broke above:
+    - The serious problem is that writefile() saves the content in undecoded
+      format in CGI, hence all (non-ascii) chars are corrupted permanently.
+    - Comment field in edit page is not decoded and all the non-ascii chars in
+      this field are corrupted as the result.  We should decode it as we do it
+      for the content.
+    - Add 'use encoding "utf8"' to CGI.pm to avoid warnings about wide
+      character in print.
+  * New SVG logo from Recai.
+
+ -- Joey Hess <joeyh@debian.org>  Sun, 18 Jun 2006 19:18:46 -0400
+
+ikiwiki (1.5) unstable; urgency=low
+
+  * Add --timeformat config option to allow changing how dates are displayed.
+    Note that as a side effect, dates will now be displayed using the local
+    timezone, not as GMT.
+  * More security review.
+  * Patch from Dr. Zini to add link() and backlink() to globlists. This allows
+    for some handy stuff like:
+    - Using links as a kind of tag; creating blog pages that list all pages
+      containing a given tag/link or not containing some other tag.
+    - Subscribing to mail notifications whenever a change is made to a page
+      that is a backlink of page foo. Ie, "Please notify me of changes in all
+      pages that link to my home page in the wiki"
+    - Locking any pages that are linked to from a particular page, so that
+      lists of locks can be exposed in the wiki.
+  * Reorganised the doc wiki's todo/* pages, using a link/tag to flag
+    when a todo item is done, instead of the previous moving it to a different
+    subdir.
+  * Allow pagetemplate plugins to override *anything* in the template.
+  * Add a meta plugin, which allows specifying various metadata about pages,
+    like license and author. It also allows for inserting html link and meta
+    tags into html, overriding the title, and adding hidden WikiLinks, which
+    can be useful when using link-based globbing for page categorisation.
+  * Remove preprocessor directives from inlined pages.
+  * Allow simple preprocessor directive values to be specified w/o quotes.
+  * Add support for using git instead of subversion as the RCS backend,
+    tremendous thanks to Recai Oktaş for this.
+  * Doc updates for git.
+  * Fix absolute url munging in rss generation to support https, ftp, etc urls
+    not just http urls.
+  * Patch from Recai Oktaş to improve utf-8 support, it should now use proper
+    utf-8 for edit and other fields, and for recentchanges. There may still
+    be utf-8 issues with the preferences page though.
+
+ -- Joey Hess <joeyh@debian.org>  Sun, 11 Jun 2006 19:56:54 -0400
+
+ikiwiki (1.4) unstable; urgency=low
+
+  * Tell HTML::Scrubber to treat "/" as a valid attribute which is its
+    very strange way of enabling proper XHTML <br /> type tags. Output html
+    should be always valid again now.
+  * The page name and parent links has switched from using a <h1> to a styled
+    <span>, so pages can use <h1> internally instead of needing to use <h2>.
+  * Updated all of ikiwiki's own wiki pages for that.
+  * Add pagetemplate hook, which can be used by plugins that want to mess
+    around with adding new stuff to the page template.
+  * Remove headercontent; the search plugin now adds the search box to the
+    header by registering a pagetemplate hook, and other plugins should do
+    similarly.
+  * Rebuilding on upgrade to this version is recommended.
+  * Add a html validity check to the test suite, using the wdg-html-validator,
+    if available.
+  * Make the html valid when there is nothing in the actions list.
+  * Reordered some function call parameters for consistency.
+  * Enable full utf-8 support for page input and output.
+  * Add a workaround for markdown, which does not work well with utf-8
+    strings.
+  * --getctime had bitrotted (well I only ever used it the once so far..),
+    fix and make it a bit more flexible
+  * rcs_getctime is changed, now rather than needing to loop over all pages,
+    it should just use the rcs to get the ctime of the passed file.
+  * When inlining a page in another one, links from the inlined page are now
+    expanded the same as they are when rendering the inlined page as a
+    standalone page. So rather than being expanded from the POV of the
+    inlining page, they are expanded from the POV of the inlined page.
+
+    For example, a link from blog/foo to "bar" will now link to blog/bar
+    if it exists. Previously this needed to be a link explicitly to
+    "blog/bar"; such links will also continue to work.
+
+    (This was slightly complex to do as the link still has to be constructed
+    relative to the inlining page.)
+  * Make page edit textarea resize to fit browser window.
+  * Add -refresh option to ikiwiki-mass-rebuild and use that on upgrades that
+    do not need a full rebuild, in order to update any basewiki pages.
+
+ -- Joey Hess <joeyh@debian.org>  Sat, 27 May 2006 15:08:49 -0400
+
+ikiwiki (1.3) unstable; urgency=low
+
+  * Fix the preinst introduced in the last version. Closes: #367458
+
+ -- Joey Hess <joeyh@debian.org>  Tue, 16 May 2006 02:43:02 -0500
+
+ikiwiki (1.2) unstable; urgency=low
+
+  * Remove dups from the brokenlinks list.
+  * Add libc6-dev to dependencies, needed to build wrappers.
+  * Install wikilist in correct location. Closes: #367371
+
+ -- Joey Hess <joeyh@debian.org>  Mon, 15 May 2006 10:53:49 -0500
+
+ikiwiki (1.1) unstable; urgency=low
+
+  * Rename inlinepage to depends, so that it can be used to refer to more
+    dependency relationships than just inlining. This will require a rebuild
+    on upgrade to this version.
+  * Move the rss link, put it in the blogpost form if there is one and at the
+    top if not. This is both nicer because easier to find, and it cleans up
+    the code which had used inlinepage as a flag for adding the link later.
+  * Allow the depends GlobList to be built up from multiple sources (such as
+    plugins) during a page render.
+  * Which means that more than one blog is now supported to appear on a
+    single page. (With some limitations, like only the last one getting an
+    rss file.)
+  * Added a plugin system.
+  * Added a pagecount plugin, enabled by default.
+  * Support PreProcessorDirectives with no parameters, ie "[[pagecount ]]".
+  * Fixed/optimised backlinks code, to avoid rebuilding pages to update
+    backlinks when the backlinks hadn't really changed.
+  * Moved inline page support, rss generation etc into the inline plugin,
+    enabled by default.
+  * Added brokenlinks plugin, not enabled by default, but rather handy.
+  * Fix several broken links in the doc wiki.
+  * Smarter behavior when creating a page and a page of the same name (but
+    different location) already exists.
+  * Add an orphans plugin for finding pages that nothing links to.
+  * Removed backlinks page, which it turns out nothing used.
+  * Split off an IkiWiki.pm out of ikiwiki and have all the other modules use
+    it, this will allow for adding a unit test suite.
+  * Add unit tests for several core functions, including globlist_match,
+    dirname, basename, bestlink, linkify, pagetitle, titlepage.
+  * Smart globlist merging.
+  * Patch from Thomas Schwinge to switch from --svn to --rcs=svn, etc,
+    to pave the way for adding other RCS support. This also changes the
+    setup files, where before they had svn => 1 or svn => 0, now they have
+    rcs => "svn" or rcs => "".
+  * Add a debian/NEWS file with upgrade notes.
+  * Load whatever rcs module is specified, so new ones can be just dropped in
+    as plugins and work. (Well, in theory.)
+  * Add some basic docs about writing RCS modules.
+  * Broke search capability out into a plugin, removed the --hyperestraier
+    switch.
+  * Added smiley plugin, nicely controlled and documented by the smileys page.
+  * Copied in some smileys from Moin Moin.
+  * Allow links of the form [[some page|page]], with whitespace in the link
+    text.
+  * Removed --sanitize and --no-sanitize, replaced with --plugin htmlscrubber
+    and --disable-plugin htmlscrubber.
+  * Allow discussion links on pages to be turned off with --no-discussion.
+  * Add ikiwiki-mass-rebuild script, ripped out of the postinst.
+  * Add some new config items to the estseek.conf template, which are needed
+    by hyperestraier 1.2.3.
+
+ -- Joey Hess <joeyh@debian.org>  Fri,  5 May 2006 17:00:41 -0400
+
+ikiwiki (1.0) unstable; urgency=low
+
+  * First official release.
+
+ -- Joey Hess <joeyh@debian.org>  Tue, 25 Apr 2006 02:08:17 -0400
diff --git a/1.33.2/debian/compat b/1.33.2/debian/compat
new file mode 100644 (file)
index 0000000..7ed6ff8
--- /dev/null
@@ -0,0 +1 @@
+5
diff --git a/1.33.2/debian/control b/1.33.2/debian/control
new file mode 100644 (file)
index 0000000..074a292
--- /dev/null
@@ -0,0 +1,27 @@
+Source: ikiwiki
+Section: web
+Priority: optional
+Build-Depends: perl, debhelper (>= 5)
+Build-Depends-Indep: dpkg-dev (>= 1.9.0), markdown, libhtml-template-perl, libhtml-scrubber-perl, wdg-html-validator, libtext-wikiformat-perl, libhtml-parser-perl, liburi-perl, perlmagick
+Maintainer: Joey Hess <joeyh@debian.org>
+Standards-Version: 3.7.2
+XS-Vcs-Svn: svn://svn.kitenet.net/ikiwiki/trunk
+
+Package: ikiwiki
+Architecture: all
+Depends: ${perl:Depends}, libxml-simple-perl, markdown, libtimedate-perl, libhtml-template-perl, libhtml-scrubber-perl, libcgi-formbuilder-perl (>= 3.02.02), libtime-duration-perl, libcgi-session-perl (>= 4.14-1), libmail-sendmail-perl, gcc | c-compiler, libc6-dev | libc-dev, libhtml-parser-perl, liburi-perl
+Recommends: subversion | git-core | tla | mercurial, hyperestraier
+Suggests: viewcvs, librpc-xml-perl, libtext-wikiformat-perl, python-docutils, polygen, tidy, libxml-feed-perl, libmailtools-perl, perlmagick, libfile-mimeinfo-perl
+Description: a wiki compiler
+ ikiwiki converts a directory full of wiki pages into html pages suitable
+ for publishing on a website. Unlike many wikis, ikiwiki does not have its
+ own ad-hoc means of storing page history, and instead uses a revision control
+ system such as Subversion.
+ .
+ ikiwiki implements all of the other standard features of a wiki, including
+ web-based page editing, user registration and logins, a RecentChanges
+ page, BackLinks, search, Discussion pages, tags, smart merging and conflict
+ resolution, page locking, and commit emails.
+ .
+ It also supports generating RSS feeds and blogging, and a plugin system
+ allows many other features to be added.
diff --git a/1.33.2/debian/copyright b/1.33.2/debian/copyright
new file mode 100644 (file)
index 0000000..9b3639b
--- /dev/null
@@ -0,0 +1,35 @@
+ikiwiki is copyright 2006 by Joey Hess <joey@kitenet.net> and contributors.
+It is licensed under the terms of the GPL version 2 or later. On Debian
+systems, the complete text of the GPL can be found in
+/usr/share/common-licenses/GPL
+
+The git code and logo are copyright 2006 by Recai Oktaş <roktas@debian.org>
+under the terms of the GPL version 2 or later.
+
+The smiley icons were copied from Moin Moin, which has these copyrights:
+       Copyright (c) 2000 - 2004 by Jürgen Hermann <jh@web.de>
+       Copyright (C) 1999, 2000 Martin Pool <mbp@humbug.org.au>
+Moin Moin is licensed under the terms of GPL version 2 or later.
+
+The basewiki and templates are licensed using a variant of the BSD license:
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/1.33.2/debian/postinst b/1.33.2/debian/postinst
new file mode 100755 (executable)
index 0000000..96572ea
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh
+set -e
+#DEBHELPER#
+
+# Change this when some incompatible change is made that requires
+# rebuilding all wikis.
+firstcompat=1.29
+
+if [ "$1" = configure ] && \
+   dpkg --compare-versions "$2" lt "$firstcompat"; then
+       ikiwiki-mass-rebuild
+else
+       ikiwiki-mass-rebuild -refresh -wrappers
+fi
diff --git a/1.33.2/debian/preinst b/1.33.2/debian/preinst
new file mode 100755 (executable)
index 0000000..12d3d83
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+#DEBHELPER#
+
+if [ "$1" = upgrade ] && dpkg --compare-versions "$2" lt 1.2; then
+       if [ -e /etc/wikilist ]; then
+               if [ ! -e /etc/ikiwiki/wikilist ]; then
+                       if [ ! -e /etc/ikiwiki ]; then
+                               mkdir /etc/ikiwiki
+                       fi
+                       mv -f /etc/wikilist /etc/ikiwiki/wikilist
+               else
+                       rm -f /etc/wikilist
+               fi
+       fi
+fi
diff --git a/1.33.2/debian/rules b/1.33.2/debian/rules
new file mode 100755 (executable)
index 0000000..f9a5be8
--- /dev/null
@@ -0,0 +1,45 @@
+#!/usr/bin/make -f
+
+build: build-stamp
+build-stamp:
+       dh_testdir
+       perl Makefile.PL PREFIX=/usr
+       $(MAKE)
+       $(MAKE) test
+       touch build-stamp
+
+clean:
+       dh_testdir
+       dh_testroot
+       rm -f build-stamp
+       perl Makefile.PL
+       -$(MAKE) realclean
+       dh_clean
+
+binary-arch: build
+
+binary-indep: build
+       dh_testdir
+       dh_testroot
+       dh_clean -k
+       $(MAKE) pure_install INSTALLDIRS=vendor \
+               DESTDIR=$(shell pwd)/debian/ikiwiki
+       dh_install wikilist etc/ikiwiki
+       dh_installdocs html
+       dh_installexamples doc/examples/*
+       dh_link usr/share/common-licenses/GPL usr/share/doc/ikiwiki/html/GPL
+       dh_installchangelogs
+       dh_compress -X html
+       dh_fixperms
+       dh_perl
+       dh_installdeb
+       dh_gencontrol
+       dh_md5sums
+       dh_builddeb
+
+# Not intended for use by anyone except the author.
+announcedir:
+       @echo ${HOME}/src/ikiwiki/doc/news
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary
diff --git a/1.33.2/doc/BSD b/1.33.2/doc/BSD
new file mode 100644 (file)
index 0000000..1ba5f11
--- /dev/null
@@ -0,0 +1,20 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/1.33.2/doc/GPL b/1.33.2/doc/GPL
new file mode 100644 (file)
index 0000000..b7b5f53
--- /dev/null
@@ -0,0 +1,340 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/1.33.2/doc/about_rcs_backends.mdwn b/1.33.2/doc/about_rcs_backends.mdwn
new file mode 100644 (file)
index 0000000..84081d6
--- /dev/null
@@ -0,0 +1,164 @@
+A few bits about the RCS backends
+
+[[toc ]]
+
+## Terminology
+
+``web-edit'' means that a page is edited by using the web (CGI) interface
+as opposed to using a editor and the RCS interface.
+
+
+## [[Subversion]]
+
+Subversion was the first RCS to be supported by ikiwiki.
+
+### How does it work internally?
+
+Master repository M.
+
+RCS commits from the outside are installed into M.
+
+There is a working copy of M (a checkout of M): W.
+
+HTML is generated from W.  rcs_update() will update from M to W.
+
+CGI operates on W.  rcs_commit() will commit from W to M.
+
+For all the gory details of how ikiwiki handles this behind the scenes,
+see [[commit-internals]].
+
+You browse and web-edit the wiki on W.
+
+
+## [darcs](http://darcs.net/) (not yet included)
+
+Support for using darcs as a backend is being worked on by [Thomas
+Schwinge](mailto:tschwinge@gnu.org).
+
+### How will it work internally?
+
+``Master'' repository R1.
+
+RCS commits from the outside are installed into R1.
+
+HTML is generated from R1.  HTML is automatically generated (by using a
+``post-hook'') each time a new change is installed into R1.  It follows
+that rcs_update() is not needed.
+
+There is a working copy of R1: R2.
+
+CGI operates on R2.  rcs_commit() will push from R2 to R1.
+
+You browse the wiki on R1 and web-edit it on R2.  This means for example
+that R2 needs to be updated from R1 if you are going to web-edit a page,
+as the user otherwise might be irritated otherwise...
+
+How do changes get from R1 to R2?  Currently only internally in
+rcs\_commit().  Is rcs\_prepedit() suitable?
+
+It follows that the HTML rendering and the CGI handling can be completely
+separated parts in ikiwiki.
+
+What repository should [[RecentChanges]] and [[History]] work on?  R1?
+
+#### Rationale for doing it differently than in the Subversion case
+
+darcs is a distributed RCS, which means that every checkout of a
+repository is equal to the repository it was checked-out from.  There is
+no forced hierarchy.
+
+R1 is nevertheless called the master repository.  It's used for
+collecting all the changes and publishing them: on the one hand via the
+rendered HTML and on the other via the standard darcs RCS interface.
+
+R2, the repository the CGI operates on, is just a checkout of R1 and
+doesn't really differ from the other checkouts that people will branch
+off from R1.
+
+(To be continued.)
+
+#### Another possible approach
+
+Here's what I (tuomov) think, would be a “cleaner” approach:
+
+ 1. Upon starting to edit, Ikiwiki gets a copy of the page, and `darcs changes --context`.
+     This context _and_ the present version of the page are stored in as the “version” of the
+     page in a hidden control of the HTML.
+     Thus the HTML includes all that is needed to generate a patch wrt. to the state of the
+     repository at the time the edit was started. This is of course all that darcs needs.
+ 2. Once the user is done with editing, _Ikiwiki generates a patch bundle_ for darcs.
+     This should be easy with existing `Text::Diff` or somesuch modules, as the Web edits
+     only concern single files. The reason why the old version of the page is stored in
+     the HTML (possibly compressed) is that the diff can be generated.
+ 3. Now this patch bundle is applied with `darcs apply`, or sent by email for moderation…
+     there are many possibilities.
+
+This approach avoids some of the problems of concurrent edits that the previous one may have,
+although there may be conflicts, which may or may not propagate to the displayed web page.
+(Unfortunately there is not an option to `darcs apply` to generate some sort of ‘confliction resolution
+bundle’.) Also, only one repository is needed, as it is never directly modified
+by Ikiwiki. 
+
+This approach might be applicable to other distributed VCSs as well, although they're not as oriented
+towards transmitting changes with standalone patch bundles (often by email) as darcs is.
+
+## [[Git]]
+
+Regarding the Git support, Recai says:
+
+I have been testing it for the past few days and it seems satisfactory.  I
+haven't observed any race condition regarding the concurrent blog commits
+and it handles merge conflicts gracefully as far as I can see.
+
+As you may notice from the patch size, GIT support is not so trivial to
+implement (for me, at least).  Being a fairly fresh code base it has some
+bugs.  It also has some drawbacks (especially wrt merge which was the hard
+part).  GIT doesn't have a similar functionality like 'svn merge -rOLD:NEW
+FILE' (please see the relevant comment in mergepast for more details), so I
+had to invent an ugly hack just for the purpose.
+
+By design, Git backend uses a "master-clone" repository pair approach in contrast
+to the single repository approach (here, _clone_ may be considered as the working
+copy of a fictious web user).  Even though a single repository implementation is
+possible, it somewhat increases the code complexity of backend (I couldn't figure
+out a uniform method which doesn't depend on the prefered repository model, yet).
+By exploiting the fact that the master repo and _web user_'s repo (`srcdir`) are all
+on the same local machine, I suggest to create the latter with the "`git clone -l -s`"
+command to save disk space.
+
+Note that, as a rule of thumb, you should always put the rcs wrapper (`post-update`)
+into the master repository (`.git/hooks/`) as can be noticed in the Git wrappers of
+the sample [[ikiwiki.setup]].
+
+## [[Mercurial]]
+
+The Mercurial backend is still in a early phase, so it may not be mature 
+enough, but it should be simple to understand and use.
+
+As Mercurial is a distributed RCS, it lacks the distinction between 
+repository and working copy (every wc is a repo).
+
+This means that the Mercurial backend uses directly the repository as 
+working copy (the master M and the working copy W described in the svn 
+example are the same thing).
+
+You only need to specify 'srcdir' (the repository M) and 'destdir' (where
+the HTML will be generated).
+
+Master repository M.
+
+RCS commit from the outside are installed into M.
+
+M is directly used as working copy (M is also W).
+
+HTML is generated from the working copy in M. rcs_update() will update 
+to the last committed revision in M (the same as 'hg update').
+If you use an 'update' hook you can generate automatically the HTML
+in the destination directory each time 'hg update' is called.
+
+CGI operates on M. rcs_commit() will commit directly in M.
+
+If you have any question or suggestion about the Mercurial backend 
+please refer to [Emanuele](http://nerd.ocracy.org/em/)
+
+## [[tla]]
\ No newline at end of file
diff --git a/1.33.2/doc/backlinks.mdwn b/1.33.2/doc/backlinks.mdwn
new file mode 100644 (file)
index 0000000..192bc74
--- /dev/null
@@ -0,0 +1,2 @@
+BackLinks are links from a page back to pages that link to it. They're automatically added, and you'll see them at the bottom of most pages in the wiki.
+This aids in navigating around and finding related stuff.
\ No newline at end of file
diff --git a/1.33.2/doc/bugs.mdwn b/1.33.2/doc/bugs.mdwn
new file mode 100644 (file)
index 0000000..5be9e25
--- /dev/null
@@ -0,0 +1,4 @@
+This is ikiwiki's bug list. Link bugs to [[bugs/done]] when done.
+
+[[inline pages="bugs/* and !bugs/done and !link(bugs/done) and !*/Discussion"
+actions=yes rootpage="bugs" show=0]]
diff --git a/1.33.2/doc/bugs/404_when_cancel_create_page.mdwn b/1.33.2/doc/bugs/404_when_cancel_create_page.mdwn
new file mode 100644 (file)
index 0000000..acf5ac9
--- /dev/null
@@ -0,0 +1,60 @@
+If you 
+
+ * Add a link to a non-existant page and save. (e.g. [[somewhere-over-the-rainbow]])
+ * Click the question mark to create the page.
+ * Click the cancel button.
+
+You get a 404 as the page doesn't exist. This patch redirects to the from location
+if it is known.
+
+
+        === modified file 'IkiWiki/CGI.pm'
+        --- IkiWiki/CGI.pm
+        +++ IkiWiki/CGI.pm
+        @@ -427,7 +427,11 @@
+                }
+        
+                if ($form->submitted eq "Cancel") {
+        -               redirect($q, "$config{url}/".htmlpage($page));
+        +               if ( $newpage && defined $from ) {
+        +                       redirect($q, "$config{url}/".htmlpage($from));
+        +               } else {
+        +                       redirect($q, "$config{url}/".htmlpage($page));
+        +               }
+                        return;
+                }
+                elsif ($form->submitted eq "Preview") {
+
+> I think you mean to use `$newfile`? I've applied a modieid version
+> that also deal with creating a new page with no defined $from location.
+> [[bugs/done]] --[[Joey]] 
+
+>> Yes of course, that's what I get for submitting an untested patch!
+>> I must stop doing that.
+
+[P.S. just above that is 
+
+                $type=$form->param('type');
+                if (defined $type && length $type && $hooks{htmlize}{$type}) {
+                        $type=possibly_foolish_untaint($type);
+                }
+                ....
+                $file=$page.".".$type;
+
+I'm a little worried by the `possibly_foolish_untaint` (good name for it by the way,
+makes it stick out). I don't think much can be done to exploit this (if anything), 
+but it seems like you could have a very strict regex there rather than the untaint,
+is there aren't going to be many possible extensions. Something like `/(.\w+)+/`
+(groups of dot separated alpha-num chars if my perl-foo isn't failing me). You could
+at least exclude `/` and `..`. I'm happy to turn this in to a patch if you agree.]
+
+> The reason it's safe to use `possibly_foolish_untaint` here is because
+> of the check for $hooks{htmlize}{$type}. This limits it to types
+> that have a registered htmlize hook (mdwn, etc), and not whatever random
+> garbage an attacker might try to put in. If it wasn't for that check,
+> using `possibly_foolish_untaint` there would be _very_ foolish indeed.. 
+> --[[Joey]]
+
+>> Nice, sorry I missed it. 
+>> I must say thankyou for creating ikiwiki.
+>> The more I look at it, the more I admire what you are doing with it and how you are going about it
diff --git a/1.33.2/doc/bugs/Disappearing_Pages.mdwn b/1.33.2/doc/bugs/Disappearing_Pages.mdwn
new file mode 100644 (file)
index 0000000..5898f10
--- /dev/null
@@ -0,0 +1,35 @@
+#Disappearing Pages
+
+I have a problem where pages within the rendered wiki become empty.  The
+headers, footers, and sidepanel are there, but the body is completely
+missing.  If I do a webedit and change anything (adding whitespace is
+enough) and commiting the change updates the page and the body appears.  If
+I then do a rebuild of the wiki from the command line, I get the blank
+pages again.  I have debug turned up but I don't see anything that makes me
+suspect anything.  When I do a rebuild from the command line I get the
+following warning.
+
+>Use of uninitialized value in substitution (s///) at /usr/share/perl5/IkiWiki/Plugin/inline.pm line 234.
+
+The odd thing is that I have 5 other wikis on this same system and none of
+them seem to be experiencing the same problems.  The only difference seems
+to be the use of sidebars and google calendar in the affected wiki.  
+
+> Could you post a tarball of the wiki and any setup file you use somewhere
+> so I can try to reproduce your problem? --[[Joey]]
+>>[The Wiki](http://www.lcsee.wvu.edu/~scotth/sysstaff.tar.gz) 
+>> I think it has something to do with the plugin selection. --[[ScottHenson]]
+
+>>> Ok, I built your wiki, and got no contentless pages here. I also
+>>> didn't see the uninitialized value warning, which could be connected.
+>>> However, I that uninitialized value come from an inline directive,
+>>> and the wiki source doesn't seem to use inlining at all, so I'm confused
+>>> about that. --[[Joey]]
+
+>>>> Sorry, thats my fault.  The wiki that was having the problem had some 
+>>>> information that I couldn't distribute.  So I reproduced the bug on 
+>>>> another wiki and sent you that.  Those warnings don't seem to have any 
+>>>> effect on the disappearing content.  Sorry for the confusion.  --[[ScottHenson]]
+
+>>>> That's ok, but since I couldn't reproduce it with the data you sent,
+>>>> I can't really fix it. --[[Joey]]
diff --git a/1.33.2/doc/bugs/PREFIX_not_honoured_for_underlaydir.mdwn b/1.33.2/doc/bugs/PREFIX_not_honoured_for_underlaydir.mdwn
new file mode 100644 (file)
index 0000000..11557c8
--- /dev/null
@@ -0,0 +1,44 @@
+I built ikiwiki using
+
+% perl Makefile.PL PREFIX=/home/ed
+% make
+% make install
+
+This installs the files under /home/ed, for example one of the lines it prints is
+
+cp -a basewiki/* /home/ed/share/ikiwiki/basewiki
+
+However when I try to run ikiwiki I get an error as follows:
+
+% ikiwiki --verbose ~/wikiwc/ ~/public_html/wiki/ --url=http://membled.com/wiki/ 
+Can't stat /usr/share/ikiwiki/basewiki: No such file or directory 
+ at /home/ed/lib/perl5/site_perl/5.8.7/IkiWiki/Render.pm line 349 
+
+The PREFIX specified at build time should also affect the share directory -
+it shouldn't try to use /usr/share here.
+
+> Actually, the PREFIX, no matter where you specify it, is only
+> intended to control where files are _installed_, not where they're
+> looked for at runtime.
+
+> There's a good reason not to make PREFIX be used to actually
+> change the program's behavior: Most packaging systems use PREFIX
+> when building the package, to make it install into a temporary
+> directory which gets packaged up.
+
+This is not the case.  That is the difference between PREFIX and DESTDIR.
+
+DESTDIR does what you describe; it causes the files to be installed into some
+directory you specify, which may not be the same place you'd eventually
+run it from.
+
+PREFIX means build the software to run under the location given.  Normally it
+will also affect the location files are copied to, so that 'make install'
+installs a working system.
+
+At least, that's the way I've always understood it; the MakeMaker documentation
+isn't entirely clear (perhaps because ordinary Perl modules do not need to be
+configured at build time depending on the installation directory).  It does mention
+that DESTDIR is the thing used by packaging tools.
+
+> Thanks for clarifying that. [[bugs/done]] --[[Joey]]
diff --git a/1.33.2/doc/bugs/Problems_using_cygwin.mdwn b/1.33.2/doc/bugs/Problems_using_cygwin.mdwn
new file mode 100644 (file)
index 0000000..66cd3f1
--- /dev/null
@@ -0,0 +1,17 @@
+I'd like to run ikiwiki under cygwin.  I'm new to ikiwiki and have tried to follow the setup tutorial as best I could.  I got all the way up to step 7, but I can't get the CGI to run successfully (step 8).
+
+> Moved the formbuilder bug to [[formbuilder_3.0401_broken]] --[[Joey]]
+
+-----
+
+A different problem has reared its ugly head.  When I click on "RecentChanges", the CGI complains about an undefined subroutine:
+
+<pre>
+==> apache2/error_log <==
+[Thu Oct 12 16:20:52 2006] [error] [client 192.168.0.125] Undefined subroutine &IkiWiki::XMLin called at /usr/lib/perl5/site_perl/5.8/IkiWiki/Rcs/svn.pm line 143., referer: http://imrisws36/wiki/index.html?updated
+[Thu Oct 12 16:20:52 2006] [error] [client 192.168.0.125] Premature end of script headers: ikiwiki.cgi, referer: http://imrisws36/wiki/index.html?updated
+</pre>
+
+Indeed there is no such routine IkiWiki::XMLin().  I don't understand how this can possibly work -- as it manifestly does on linux.
+
+> XMLin is supposed to be exported by XML::Simple. My guess is that, due to a missing error check, XML::Simple is failing to load, and it's not aborting then. You probably need to install that module; in the meantime, I've fixed the missing error check in svn. --[[Joey]]
diff --git a/1.33.2/doc/bugs/bestlink_change_update_issue.mdwn b/1.33.2/doc/bugs/bestlink_change_update_issue.mdwn
new file mode 100644 (file)
index 0000000..6730315
--- /dev/null
@@ -0,0 +1,11 @@
+* Has bugs updating things if the bestlink of a page changes due to
+  adding/removing a page. For example, if Foo/Bar links to "Baz", which is
+  Foo/Baz, and Foo/Bar/Baz gets added, it will update the links in Foo/Bar
+  to point to it, but will forget to update the linkbacks in Foo/Baz.
+
+* And if Foo/Bar/Baz is then removed, it forgets to update Foo/Bar to link
+  back to Foo/Baz.
+
+As of 1.33, this is still true. The buggy code is the %linkchanged
+calculation in refresh(), which doesn't detect that the link has changed in
+this case.
diff --git a/1.33.2/doc/bugs/broken_parentlinks.mdwn b/1.33.2/doc/bugs/broken_parentlinks.mdwn
new file mode 100644 (file)
index 0000000..a58ff6f
--- /dev/null
@@ -0,0 +1,23 @@
+The header of subpages always links to its "superpage", even if it doesn't
+exist. I'm not sure if this is a feature or a bug, but I would certainly prefer
+that superpages weren't mandatory.
+
+For example, if you are in 'example/page.html', the header will be something
+like 'wiki / example / page'. Now, if 'example.html' doesn't exist, you'll have
+a dead link for every subpage.
+
+---
+
+This is a bug, but fixing it is very tricky. Consider what would happen if
+example.mdwn were created: example/page.html and the rest of example/*
+would need to be updated to change the parentlink from a bare work to a
+link to the new page. Now if example.mdwn were removed again, they'd need
+to be updated again. So example/* depends on example. But it's even more
+tricky, because if example.mdwn is modified, we _don't_ want to rebuild
+example/*!
+
+ikiwiki doesn't have a way to represent this dependency and can't get one
+without a lot of new complex code being added.
+
+For now the best thing to do is to make sure that you always create
+example if you create example/foo. Which is probably a good idea anyway..
diff --git a/1.33.2/doc/bugs/diff_links_to_backtrace.mdwn b/1.33.2/doc/bugs/diff_links_to_backtrace.mdwn
new file mode 100644 (file)
index 0000000..16f84fa
--- /dev/null
@@ -0,0 +1,5 @@
+The diff links in RecentChanges go to a viewcvs backtrace if the rev in 
+question is when the page was added. Is this a viewcvs bug, or a behavior 
+ikiwiki needs to work around?
+  - As a special case, there should certianly be no history link for
+    pages generated from the underlaydir as it can never work for them.
diff --git a/1.33.2/doc/bugs/done.mdwn b/1.33.2/doc/bugs/done.mdwn
new file mode 100644 (file)
index 0000000..a92862b
--- /dev/null
@@ -0,0 +1,3 @@
+recently fixed [[bugs]]
+
+[[inline pages="link(bugs/done) and !bugs and !*/Discussion" show="10"]]
diff --git a/1.33.2/doc/bugs/formbuilder_3.0401_broken.mdwn b/1.33.2/doc/bugs/formbuilder_3.0401_broken.mdwn
new file mode 100644 (file)
index 0000000..8e5126b
--- /dev/null
@@ -0,0 +1,69 @@
+After editing ikiwiki.setup, and running "ikiwiki --setup", the CGI script is successfully created.  However, if I then click on "Edit Page" link, I see nothing in the browser and the following in the logs:
+
+<pre>
+==> /var/log/apache2/access_log <==
+192.168.0.125 - - [06/Oct/2006:15:12:05 -0500] "GET /cgi-bin/ikiwiki.cgi?page=index&do=edit HTTP/1.1" 500 666
+
+==> /var/log/apache2/error_log <==
+[Fri Oct 06 15:12:07 2006] [error] [client 192.168.0.125] HTML::Template::param() : attempt to set parameter 'form-submit' with an array ref - parameter is not a TMPL_LOOP! at /usr/lib/perl5/site_perl/5.8/CGI/FormBuilder.pm line 1415, referer: http://imrisws36/wiki/
+[Fri Oct 06 15:12:07 2006] [error] [client 192.168.0.125] Premature end of script headers: ikiwiki.cgi, referer: http://imrisws36/wiki/
+</pre>
+
+Can anyone decipher this for me?  I spent some time with cpan earlier today downloading the latest version I could find of prerequisite modules such as HTML::Template and CGI::FormBuilder.
+
+> It would help to know what version of CGI::FormBuilder you have. Mine
+> (3.03.01) does not seem to contain this error message. --[[Joey]]
+
+I have version 3.0401 of CGI::FormBuilder -- the latest from CPAN.  If you are wondering about any other modules, the answer 
+is likely the same: the latest from CPAN.  And you're right: the error string in question does not appear in CGI::FormBuilder.  I found it in HTML::Template (version 2.8).
+
+-----
+
+OK, so downgrading CGI::FormBuilder to 3.0302 makes the problem go away.  I'll leave it to you to figure out whether the bug is in CGI::FormBuilder or in IkiWiki. --Steve
+
+Maybee this bug should be renamed as "doesn't work with CGI::FormBuilder (3.04)." I get same error on FreeBSD.  
+
+    HTML::Template::param() : attempt to set parameter 'form-submit' with an array 
+    ref - parameter is not a TMPL_LOOP! 
+    at /usr/local/lib/perl5/site_perl/5.8.7/CGI/FormBuilder.pm line 1415
+
+version info:
+
+    root@freedom# pkg_info | grep p5-CGI
+    p5-CGI-FastTemplate-1.09 Perl module for manage templates and parses templates
+    p5-CGI-FormBuilder-3.0401 FormBuilder for CGI
+    p5-CGI-Session-4.14 Perl extension for persistent session management
+
+--Mark
+
+----
+
+For the curious, this new version of CGI::FormBuilder changes how it passes
+some values to the HTML::Template template. In particular, FORM-SUBMIT used
+to be just a string containing the buttons used to submit the form. With
+the new version, it's an array of strings, one per button, and the template
+needs to be written differently to deal with this. Oddly, the docs have not
+been updated about this. In fact, from all I can tell, it's a bug, since
+the array is not in the form that HTML::Template expects to receive it. 
+Here's a simple test case:
+
+       #!/usr/bin/perl
+       my @fields=qw(editcontent);
+       my @buttons=("Save", "Preview", "Cancel");
+
+       use CGI::FormBuilder;
+       my $form = CGI::FormBuilder->new(
+               fields => \@fields,
+               template => "foo.tmpl",
+       );
+       print $form->render(submit => \@buttons);
+
+With this test case, it does not seem to be possible to write a foo.tmpl that
+outputs the buttons using the FORM-SUBMIT template variable.
+
+I was able to work around this bug by just not using FORM-SUBMIT in the
+template, and hardcoding the buttons (since they never change anyway).
+Nasty, but it should work. I haven't fully installed the new version of
+CGI::FormBuilder to test it, and it's quite possible that other changes
+in the new version cause other breakage. If you want to test the fix,
+it's in svn now. --[[Joey]]
diff --git a/1.33.2/doc/bugs/helponformatting_link_disappears.mdwn b/1.33.2/doc/bugs/helponformatting_link_disappears.mdwn
new file mode 100644 (file)
index 0000000..11ce548
--- /dev/null
@@ -0,0 +1,5 @@
+If you are editing a page using your www browser and hit the "Preview"
+button, the link to "HelpOnFormatting" on the bottom of the page
+disappears.  This may be expected, or not.
+
+[[bugs/done]]
diff --git a/1.33.2/doc/bugs/html_errors.mdwn b/1.33.2/doc/bugs/html_errors.mdwn
new file mode 100644 (file)
index 0000000..5a60e04
--- /dev/null
@@ -0,0 +1,2 @@
+ikiwiki will generate html formatted error messages to the command
+line if --cgi is set, even if it's not yet running as a cgi
diff --git a/1.33.2/doc/bugs/inline_page_not_updated_on_removal.mdwn b/1.33.2/doc/bugs/inline_page_not_updated_on_removal.mdwn
new file mode 100644 (file)
index 0000000..7f5e498
--- /dev/null
@@ -0,0 +1,32 @@
+If a page inlines some other page (such as this page by the bugs page), 
+and the page is removed (such as by this page being linked to bugs/done),
+the inlining page is not updated to remove it.
+
+This only happens if the page is removed from the inlined pagespec due to
+a tag changing; the problem is that once the tag is changed, ikiwiki does
+not know that the page used to match before.
+
+Another example would be a pagespec that allowed only matching new pages:
+
+       newer(1 day)
+
+Obviously, the pages that matches are going to change, and again once they
+do, ikiwiki will no longer know that they matched before, so it won't know
+to remove them from a page that used that to inline them.
+
+To fix, seems I would need to record the actual list of pages that are
+currently included on an inline page, and do a comparison to see if any
+have changed. 
+
+At first I thought, why not just add them to the dependencies
+explicitly, but that failed because the dependencies GlobList failed to match
+when a negated expression like "!tag(bugs/done)" is matched. It is,
+however, doable with PageSpecs:
+
+       (real deps here) or (list of all currently inlined pages here)
+
+However, it's not really clear to me how to _remove_ inlined pages from the
+deps when they stop being inlined for whatever reason. So a separate list
+would be better.
+
+So this is blocked by [[todo/plugin_data_storage]] I suppose.
diff --git a/1.33.2/doc/bugs/markdown_module_location.mdwn b/1.33.2/doc/bugs/markdown_module_location.mdwn
new file mode 100644 (file)
index 0000000..59b565d
--- /dev/null
@@ -0,0 +1,34 @@
+If the Markdown module is installed via CPAN rather than apt then
+the module is actually Text::Markdown.
+
+I had to edit the source to change this on my old server. I have filed
+a [bug](http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=387687) against
+the Debian markdown, which I guess you can consider a blocking bug of this.
+
+I tried to come up with the magical invocation to allow either location 
+to be used by ikiwiki, but I couldn't do it.
+
+-- [[JamesWestby]]
+
+Fixed, I think --[[Joey]]
+
+> Fraid not. The import works ok, but I get
+     `Undefined subroutine &Markdown::Markdown called at IkiWiki/Plugin/mdwn.pm line 41.`
+> This is what stumped me, I was trying to import as an alias, but couldn't work
+> out how to do it. A flag if you use the second import would be an ugly solution.
+> -- [[JamesWestby]]
+
+Ok, the markdown in CPAN must be an entirely different version then if it
+doesn't has a Markdown::Markdown. Interesting, I'll have a look at it.
+--[[Joey]]
+
+> It works if you use Text::Markdown::Markdown, sorry, I forgot to mention that.
+> --JamesWestby
+
+I think what I've committed now will work in all cases. Well, unless there
+are even more forks of markdown out there (the CPAN module is a fork
+apparently...) 
+
+[[bugs/done]] --[[Joey]]
+
+> It now compiles here, thanks. --JamesWestby
diff --git a/1.33.2/doc/bugs/meta_inline.mdwn b/1.33.2/doc/bugs/meta_inline.mdwn
new file mode 100644 (file)
index 0000000..9ca32a0
--- /dev/null
@@ -0,0 +1,4 @@
+The meta plugin doesn't affect a page if it's being inlined. Probably
+setting the title with it should override the title of the blog post.
+
+[[bugs/done]]
diff --git a/1.33.2/doc/bugs/pruning_is_too_strict.mdwn b/1.33.2/doc/bugs/pruning_is_too_strict.mdwn
new file mode 100644 (file)
index 0000000..ef8d887
--- /dev/null
@@ -0,0 +1,8 @@
+ikiwiki compiles my wiki successfully. But the svn post-commit hook it installs doesn't work at all. Instead of rendering the files, it deletes their rendered versions. The reason is that the src directory, /home/.kelli/glasserc/wikiwc, matches the prune regexp, so no files in the wiki get added to @files.
+
+I think the prune regexp would be more useful if it was only used to check the relative path from the src root to a file in the wiki.
+
+> I agree with this feature wish.  Here is a _first cut_
+> [[implementation|patchqueue/pruning_is_too_strict]] for this feature.
+>
+> --[[roktas]]
\ No newline at end of file
diff --git a/1.33.2/doc/bugs/rss_feed_cleanup_on_delete.mdwn b/1.33.2/doc/bugs/rss_feed_cleanup_on_delete.mdwn
new file mode 100644 (file)
index 0000000..fe0400f
--- /dev/null
@@ -0,0 +1,6 @@
+If a page stops inlining anthing, its rss feed file will linger around and
+not be deleted.
+
+(The linkmap plugin has the same problem with the png files it creates.)
+
+[[bugs/done]]
diff --git a/1.33.2/doc/bugs/rss_output_relative_links.mdwn b/1.33.2/doc/bugs/rss_output_relative_links.mdwn
new file mode 100644 (file)
index 0000000..ff607cb
--- /dev/null
@@ -0,0 +1,3 @@
+RSS output contains relative links. Ie. 
+http://kitenet.net/~joey/blog/index.rss contains a link to 
+http://kitenet.net/~joey/blog/../blog.html
diff --git a/1.33.2/doc/bugs/svn+ssh_commit_fail.mdwn b/1.33.2/doc/bugs/svn+ssh_commit_fail.mdwn
new file mode 100644 (file)
index 0000000..b58f437
--- /dev/null
@@ -0,0 +1,5 @@
+If I try to do a web commit, to a svn+ssh repo, it fails with
+"Host key verification failed."
+I think that the setuid isn't fully taking; it should be running as me,
+but commit log shows www-data. So maybe it has the wrong username? Or
+EUID/Real UID screwage. [[bugs/done]]
diff --git a/1.33.2/doc/bugs/svn_post-commit_wrapper_can__39__t_find_IkiWiki.pm_if_not_installed.mdwn b/1.33.2/doc/bugs/svn_post-commit_wrapper_can__39__t_find_IkiWiki.pm_if_not_installed.mdwn
new file mode 100644 (file)
index 0000000..0c80960
--- /dev/null
@@ -0,0 +1,9 @@
+If you're using ikiwiki without installing it, the svn post-commit wrapper will die (in a difficult-to-debug way) when it tries to execute ikiwiki.pl because it can't find IkiWiki.pm.
+
+I'm not sure how to fix this in a secure way. For now I'm just changing use lib '.' in ikiwiki.pl to point to the hard-coded directory where ikiwiki was unpacked.
+
+> This workaround doesn't work here.  "`./ikiwiki.pl --setup ikiwiki.setup`" is ok, but the
+> wrappers fail in action.  Using "`FindBin`" seems a solution.  Here is a (kinda ugly)
+> [patch](http://git.kirkambar.net/?p=ikiwiki.git;a=commitdiff;h=44511c00b98b3efedd4d31f15ea928fcf221401e) 
+> which also allows you to use `basewiki` + `templates` in the source directory.  The patched
+> version works fine in my [homepage](http://kirkambar.net).  --[[Roktas]]
\ No newline at end of file
diff --git a/1.33.2/doc/bugs/tags_base_dir_not_used_when_creating_new_tags.mdwn b/1.33.2/doc/bugs/tags_base_dir_not_used_when_creating_new_tags.mdwn
new file mode 100644 (file)
index 0000000..71a9ece
--- /dev/null
@@ -0,0 +1,40 @@
+I'm using the tags plugin with tagbase="tags".
+
+Already existing tags, corresponding to pages like tags/foo.html work just
+fine.
+
+If I add to a page a tag which is not existing (e.g. with [[tag newtag]])
+the just modified page will have a link which point to tags/newtag. This is
+in theory correct, but in practice leads to creating a tags/newtag subpage
+of the page I'm editing, while my tagbase is supposed to be relative to the
+wiki root.
+
+When used in a wiki which already have some tags this leads to mixing up
+tags located in tags/ and tags located in whatever/tags/.
+
+> When a new page is being edited, ikiwiki lets you chose where the page
+> will be created, so you'll get a dropdown list of possible locations for
+> the tag page. You should be able to choose between either tags/foo or
+> page/tags/foo.
+>
+> The way that ikiwiki decides which location to default to in this box is
+> fairly involved; but in general it will default to creating the page at
+> the same level as the tagged page. So if the tag is on any toplevel page
+> in the wiki, it will default to creating `tags/foo`; if the tag is on a
+> page in a subdirectory, it will default to creating subdir/tags/foo.
+>
+> I personally like this behavior; it allows me to create a subdirectory
+> for a particular thing and use tags that are specific to that thing,
+> which are kept confined to that subdirectory by default. For example,
+> this is used for ikiwiki's own plugins tags, which are all located
+> under plugins/type/* and which apply to pages under plugins/*.
+>
+> It's clearly not the right default for every situation though. Explcitly
+> setting a tagbase probably lessons the likelyhood that it's the right
+> default for things under that tag base. I'd not be opposed to adding a
+> special case to change the default in this case, or adding a
+> configuration option to change the default globally. On the other hand,
+> it is pretty simple to just check the location and select the right one
+> from the list when creating a new page..
+> 
+> --[[Joey]]
diff --git a/1.33.2/doc/bugs/underlaydir_file_expose.mdwn b/1.33.2/doc/bugs/underlaydir_file_expose.mdwn
new file mode 100644 (file)
index 0000000..0c6f554
--- /dev/null
@@ -0,0 +1,3 @@
+If a file in the srcdir is removed, exposing a file in the underlaydir,
+ikiwiki will not notice the change and rebuild it until the file in the
+underlaydir gets a mtime newer than the mtime the removed file had.
diff --git a/1.33.2/doc/bugs/utf8_html_templates.mdwn b/1.33.2/doc/bugs/utf8_html_templates.mdwn
new file mode 100644 (file)
index 0000000..a750b23
--- /dev/null
@@ -0,0 +1,22 @@
+HTML::Template does not read files as utf-8, so modifying ikiwiki's
+template files to contain utf-8 won't currently work.
+
+It seems that the best way to fix this would be to make HTML::Template
+support utf-8.
+
+A workaround is to change all the template reading code like this:
+
+       -     my $template=HTML::Template->new(blind_cache => 1,
+       -             filename => "$config{templatedir}/page.tmpl");
+       +     open(TMPL, "<:utf8", "$config{templatedir}/page.tmpl");
+       +     my $template=HTML::Template->new(filehandle => *TMPL);
+       +     close(TMPL);
+
+However, this will make ikiwiki slower when rebuilding a wiki, since it
+won't cache templates.
+
+Could be approached by using HTML::Template's support for filters. Just make it use a filter that turns on utf-8
+
+Or by subclassing it and overriding the \_init\_template method, though that's a bit uglier
+
+[[bugs/done]]
diff --git a/1.33.2/doc/bugs/utf8_svn_log.mdwn b/1.33.2/doc/bugs/utf8_svn_log.mdwn
new file mode 100644 (file)
index 0000000..abd9577
--- /dev/null
@@ -0,0 +1,11 @@
+svn log messages containing utf-8 (such as r773) don't get displayed
+right in RecentChanges. The problem is ikiwiki runs svn log in locale C,
+which makes it spit out eacaped charcters for utf-8 chars. If it's run in
+locale en_US.UTF-8, it would be ok, but that would require the system
+have that locale.
+
+Seems that the right fix for this is to use svn log --xml, which is
+always utf-8 and come up with a parser for that. Also fixes the spoofing
+issue in [[security]].
+
+[[bugs/done]]
diff --git a/1.33.2/doc/bugs/word_wrap.mdwn b/1.33.2/doc/bugs/word_wrap.mdwn
new file mode 100644 (file)
index 0000000..8a69bb3
--- /dev/null
@@ -0,0 +1,3 @@
+Web browsers don't word-wrap lines in submitted text, which makes editing a
+page that someone wrote in a web browser annoying (`gqip` is vim user's
+friend here). Is there any way to improve this?
diff --git a/1.33.2/doc/cgi.mdwn b/1.33.2/doc/cgi.mdwn
new file mode 100644 (file)
index 0000000..22d8c43
--- /dev/null
@@ -0,0 +1,3 @@
+While ikiwiki is primarily a wiki compiler, which generates static html pages, it does use CGI for two important wiki features, online page editing and the [[RecentChanges]] display.
+
+To enable CGI, you need to create and install an ikiwiki.cgi wrapper. [[Setup]] explains how to do this.
\ No newline at end of file
diff --git a/1.33.2/doc/commit-internals.mdwn b/1.33.2/doc/commit-internals.mdwn
new file mode 100644 (file)
index 0000000..3a464ff
--- /dev/null
@@ -0,0 +1,20 @@
+Saving this irc transcript here, since it's a fairly in-depth discussion of
+how ikiwiki handles commits, locking, etc, and avoids some races while
+doing so.
+
+       <tschwinge> What happens if I edit a page and in the underground a new version is installed into the svn repository?
+       <tschwinge> The revision when I started editing was saved, right?
+       <joeyh> what happens, exactly is:
+       <joeyh> 1. the new version that was committed first get into svn, and ikiwiki updates its WC to have the new version
+       <joeyh> 2. When you save your edit, ikiwiki detects a conflict.
+       <joeyh> 3. It uses svn merge to try to resolve it; if it's resolved it adds your changes transparently
+       <joeyh> 4. If the conflict needs manual resolution, it displays the page with conflict markers in the editor for you to resolve
+       <tschwinge> Ok.
+       <joeyh> Note that in step 2, it detects the conflict by using svn info to get the current Revision of the page in the WC, and compares that to a revision that is stored when you start to edit the page
+       <joeyh> that's why rcs_prepedit exists, to get that revision info
+       <tschwinge> But isn't there a race condition?
+       <joeyh> well, there is locking going on too
+       <joeyh> ikiwiki won't update the WC in step 1. if another instance of itself is getting the Revision info
+       <tschwinge> Is that lockwiki()?
+       <joeyh> yeah
+       <joeyh> note that when it gets the current Revision info of a page during its conflict detection, svn could have changed the page in the repo, and the WC not been updated yet due to the lock, but this isn't a race since the commit will then fail due to a regular svn conflict and the conflict detction will still work.
diff --git a/1.33.2/doc/css.mdwn b/1.33.2/doc/css.mdwn
new file mode 100644 (file)
index 0000000..8c804db
--- /dev/null
@@ -0,0 +1,11 @@
+## Using CSS with ikiwiki
+
+Ikiwiki comes with two CSS stylesheets: [[style.css]] and [[local.css]].
+The idea is to customize the second one overriding the first one and
+defining brand new rendering rules.
+
+While ikiwiki's default use of stylesheets is intentionally quite plain and
+minimalistic, CSS allows creating any kind of look you can dream up.
+
+The [[css_market]] page is an attempt to collect user contributed local.css
+files.
diff --git a/1.33.2/doc/css_market.mdwn b/1.33.2/doc/css_market.mdwn
new file mode 100644 (file)
index 0000000..418d8e1
--- /dev/null
@@ -0,0 +1,19 @@
+User contributed stylesheet files for ikiwiki. Feel free to add your own
+stylesheets here. (Upload as wiki pages; wiki gnomes will convert them to css
+files..)
+
+* **[[css_market/zack.css]]**, contributed by [[StefanoZacchiroli]],
+  customized mostly for *blogging purposes*, can be seen in action on 
+  [zack's blog](http://www.bononia.it/~zack/blog/)
+  [[meta link="css_market/zack.css" rel="alternate stylesheet" title="zack" type="text/css"]]
+
+* **[[css_market/kirkambar.css]]**, contributed by [[Roktas]].  This far from perfect
+  stylesheet follows a [Gitweb](http://www.kernel.org/git/?p=git/git.git;a=tree;f=gitweb)
+  like theme, so it may provide a consistent look'n feel along with the [[git]] backend. ;-)
+  You can see it in action on [kirkambar](http://kirkambar.net/) (Turkish content).
+  [[meta link="css_market/kirkambar.css" rel="alternate stylesheet" title="kirkambar" type="text/css"]]
+
+If your web browser allows selecting between multiple stylesheets, this
+page can be viewed using any of the stylesheets above. For example, if
+using Epiphany with the Select Stylesheet extention enabled, use View ->
+Style.
diff --git a/1.33.2/doc/css_market/kirkambar.css b/1.33.2/doc/css_market/kirkambar.css
new file mode 100644 (file)
index 0000000..256986e
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * IkiWiki `local.css` stylesheet following the Gitweb theme.
+ *
+ * Copyright © 2006  Recai Oktaş <roktasATdebian.org>
+ *
+ * Licensed under the GNU General Public License, version 2.
+ * See the file `http://www.gnu.org/copyleft/gpl.txt`.
+ *
+ */
+
+
+/* 
+ * -----------------------------------------------------------------------------
+ * Generic style elements.
+ * -----------------------------------------------------------------------------
+ */
+
+body {
+       font-family: "Trebuchet MS",
+                    "Luxi Sans",
+                    "Bitstream Vera Sans",
+                    "Tahoma",
+                    "Verdana",
+                    "Arial",
+                    "Helvetica",
+                    sans-serif;
+       padding: 1em;
+       margin: 0;
+       font-size: 100.01%;
+       line-height: 1.5em;
+       color: black;
+       background-color: white;
+}
+
+pre, tt, code {
+       font-family: "Bitstream Vera Sans Mono",
+                    "Luxi Mono",
+                    "Courier New",
+                    "Courier",
+                    monospace;
+}
+
+pre, tt, code, tr.changeinfo, #blogform {
+       color: inherit;
+       background-color: #f6f6f0;
+}
+
+pre {
+       margin: 0px 96px 0px 48px;
+       padding: 12px 0px 12px 0px;
+}
+
+h1, h2, h3, h4, h5, h6, dl, dt {
+       font-weight: bold;
+       background-color: inherit;
+       color: #c00040 !important;
+}
+
+h1, h2, h3, h4, h5, h6 {
+       letter-spacing: .04em;
+}
+
+
+/* 
+ * -----------------------------------------------------------------------------
+ * Headers, footers.
+ * -----------------------------------------------------------------------------
+ */
+
+.header, #footer, .changeheader {
+       color: black !important;
+       background-color: #d9d8d1;
+}
+       
+.header, #footer {
+       height: 1.8em;
+       padding: 6px 6px;
+       border: 1px solid #aaa;
+       margin-bottom: 4px;
+       display: block;
+}
+
+.header {
+       font-size: 120.01%;
+       font-weight: normal;
+       letter-spacing: .11em;
+}
+
+span.header {
+       background-image: none !important;
+       text-align: right;
+}
+
+.header { /* Optional header logo (right aligned). */
+       background-image: url(/* ENTER HEADER LOGO PATH */);
+       background-repeat: no-repeat;
+       background-position: 99%;
+}
+
+#footer { /* Optional footer logo (right aligned). */
+       background-image: url(/* ENTER FOOTER LOGO PATH */);
+       background-repeat: no-repeat;
+       background-position: 99%;
+}
+
+
+/* 
+ * -----------------------------------------------------------------------------
+ * Specials.
+ * -----------------------------------------------------------------------------
+ */
+
+#searchform {
+       position: absolute;
+       top: 25px;
+       right: 90px;
+}
+
+
+td.changetime {
+       font-style: italic;
+}
+
+td.changelog {
+       font-style: normal;
+       font-size: x-small;
+       font-weight: bold;
+}
+
+/*
+ * Attribution `div` for IkiWiki.  Use something like as follows:
+ *             <div id="attribution">
+ *                 This site is maintained using Joey Hess's
+ *                 <a href="http://ikiwiki.kitenet.net/">
+ *                     <img src="ikiwiki.png" title="IkiWiki" alt="IkiWiki" />
+ *                 </a>.
+ *             </div>
+ */    
+#attribution img {
+       border: 1px solid black;
+       padding: 2px;
+}
diff --git a/1.33.2/doc/css_market/zack.css b/1.33.2/doc/css_market/zack.css
new file mode 100644 (file)
index 0000000..fbb0f2c
--- /dev/null
@@ -0,0 +1,135 @@
+/* local.css stylesheet to be used with ikiwiki
+ *
+ * Copyright: (C) 2006 Stefano Zacchiroli <zack@debian.org>
+ * License: GNU General Public License version 2 or above.
+ *
+ * TODO
+ * - plone-like actions in the toplevel bar, but remember: resiste the
+ *   temptation of making them floating to the right: the breadcrumb trail can
+ *   grow indefinetely
+ * - blog form aligned to the right, keeping the RSS logo to the left
+ * - some rendering for the tags (a la 'xhtml' logo of plone? ...)
+ * - some rendering for backlinks
+ * - some rendering for posting dates
+ */
+
+body {
+  font-family: sans;
+  width: 760px;
+  margin-left: 20px;
+}
+
+div#content {
+  font-size: 11pt;
+}
+
+.header span {
+  font-size: 14pt;
+  font-weight: normal;
+}
+
+div.actions ul {
+  font-size: 10pt;
+}
+
+h1 {
+  font-weight: normal;
+  font-size: 17pt;
+}
+h2 {
+  font-weight: normal;
+  font-size: 16pt;
+}
+h3 {
+  font-weight: normal;
+  font-size: 15pt;
+}
+h4 {
+  font-weight: normal;
+  font-size: 14pt;
+}
+h5 {
+  font-weight: normal;
+  font-size: 13pt;
+}
+h6 {
+  font-weight: normal;
+  font-size: 12pt;
+}
+
+div.inlinepage > span.header > a {
+  float: right;
+  display: block;
+  font-size: 11pt;
+  font-weight: normal;
+  margin: 0;
+  padding: 0;
+}
+div.inlinepage > span.header > a:before {
+  content: "permalink: ";
+  font-size: smaller;
+  text-decoration: none;
+  font-style: italic;
+}
+
+div.inlinepage {
+  margin-bottom: 10px;
+}
+
+div.inlinepage h1 {
+  font-weight: normal;
+  font-size: 14pt;
+  margin: 0;
+}
+div.inlinepage h2 {
+  font-weight: normal;
+  font-size: 13pt;
+  margin: 0;
+}
+div.inlinepage h3 {
+  font-weight: normal;
+  font-size: 12pt;
+  margin: 0;
+}
+div.inlinepage h4 {
+  font-weight: normal;
+  font-size: 11pt;
+  margin: 0;
+}
+div.inlinepage h5 {
+  font-weight: normal;
+  font-size: 11pt;
+  margin: 0;
+}
+div.inlinepage h6 {
+  font-weight: normal;
+  font-size: 11pt;
+  margin: 0;
+}
+
+div#blogform {
+  padding: 0px 5px;
+  margin-bottom: 10px;
+}
+
+pre {
+  width: 90%;
+  font-size: 10pt;
+  font-family: monospace;
+  background: #e1e1e1;
+  margin-left: 4%;
+  padding-top: 5px;
+  padding-bottom: 5px;
+}
+
+.pagecloud {
+  width: 25%;
+  border-top: 1px solid #aaa;
+  border-bottom: 1px solid #aaa;
+  background: #eee;
+  color: black !important;
+}
+
+.pagecloud a {
+  text-decoration: none;
+}
diff --git a/1.33.2/doc/download.mdwn b/1.33.2/doc/download.mdwn
new file mode 100644 (file)
index 0000000..acd27b8
--- /dev/null
@@ -0,0 +1,39 @@
+Here's how to get ikiwiki. See [[setup]] for how to use it, and be sure to
+add your wiki to [[IkiwikiUsers]] if you use ikiwiki.
+
+# tarball
+
+The best place to download a tarball of the latest release is from 
+<http://packages.debian.org/unstable/source/ikiwiki>.
+
+# Debian package
+
+If using Debian unstable or testing:
+
+        apt-get install ikiwiki
+
+Or download the deb from <http://packages.debian.org/unstable/web/ikiwiki>.
+
+While this deb has been developed on Debian unstable, it should also work
+on stable, although to get the CGI stuff working on stable, you will need
+to upgrade to a newer version of libcgi-formbuilder-perl, `3.02.02`, and libcgi-session-perl `4.14-1`
+
+There is also an unofficial backport of ikiwiki for Debian stable, provided by
+Pawel Tecza, at <http://gpa.net.icm.edu.pl/debian/>.
+
+# subversion
+
+The current development version of ikiwiki can be accessed using subversion at 
+`svn://ikiwiki.kitenet.net/ikiwiki/trunk`
+
+The source in subversion can be browsed
+[here](http://ikiwiki.kitenet.net/cgi-bin/viewcvs.cgi/trunk/?root=ikiwiki).
+
+If you would like to be subscribed to svn commit messages for ikiwiki,
+mail joey@kitenet.net.
+
+# arch
+
+An unofficial arch mirror of the subversion repository is at
+`http://arch.debian.org/arch/private/srivasta/archive-2006-misc`
+and can be browsed [here](http://arch.debian.org/cgi-bin/archzoom.cgi/srivasta@debian.org--2006-misc?color=default?layout=larger?expand).
diff --git a/1.33.2/doc/examples.mdwn b/1.33.2/doc/examples.mdwn
new file mode 100644 (file)
index 0000000..8b52c2f
--- /dev/null
@@ -0,0 +1,7 @@
+To make it easier to get started using ikiwiki for some common tasks, this
+page gives some examples of ways to use ikiwiki.
+
+* [[blog]] - a weblog with tags, a tag cloud, archives, and an optional sidebar
+
+Each example is contained in its own subdirectory; just copy the source
+files into your wiki to start using one of the examples.
diff --git a/1.33.2/doc/examples/blog.mdwn b/1.33.2/doc/examples/blog.mdwn
new file mode 100644 (file)
index 0000000..14e9b38
--- /dev/null
@@ -0,0 +1,18 @@
+This is an [[example_blog|index]]. Just copy the blog subdirectory into
+your wiki to quickly get started blogging with ikiwiki.
+
+Some additional configuration you might want to do:
+
+* Change the name of the blog, by editing `index.mdwn` and changing
+  the `title`.
+
+* Make sure to configure ikiwiki to generate RSS or Atom feeds.
+
+* Make sure you have the tag plugin enabled, and tag posts using it. An
+  example of how to tag a post is:
+       \[[tag tags/life]]
+
+* Enable the sidebar plugin to get a sidebar listing all the categories
+  you've tagged posts with.
+
+* Enable the pagestats plugin to get a tag cloud display on the [[index]].
diff --git a/1.33.2/doc/examples/blog/index.mdwn b/1.33.2/doc/examples/blog/index.mdwn
new file mode 100644 (file)
index 0000000..201abed
--- /dev/null
@@ -0,0 +1,10 @@
+[[meta title="example blog"]]
+
+[[pagestats pages="*blog/tags/*"]]
+
+Welcome to my blog. Have a look at the most recent posts below, or
+browse the tag cloud on the right. An archive of all [[posts]] is also
+available.
+
+[[inline pages="*blog/posts/* and !*/Discussion" show="10"
+actions=yes rootpage="*blog/posts"]]
diff --git a/1.33.2/doc/examples/blog/posts.mdwn b/1.33.2/doc/examples/blog/posts.mdwn
new file mode 100644 (file)
index 0000000..c19ca15
--- /dev/null
@@ -0,0 +1,3 @@
+Here is a full list of posts to my [[blog|index]].
+
+[[inline pages="*blog/posts/* and !*/Discussion" archive="yes"]]
diff --git a/1.33.2/doc/examples/blog/posts/first_post.mdwn b/1.33.2/doc/examples/blog/posts/first_post.mdwn
new file mode 100644 (file)
index 0000000..f8a6988
--- /dev/null
@@ -0,0 +1,4 @@
+This is the first post to this example blog. To add new posts, just add
+files to the blog/posts/ subdirectory, or use the web form.
+
+[[tag tags/tech]]
diff --git a/1.33.2/doc/examples/blog/sidebar.mdwn b/1.33.2/doc/examples/blog/sidebar.mdwn
new file mode 100644 (file)
index 0000000..203d2e0
--- /dev/null
@@ -0,0 +1,4 @@
+Example sidebar
+
+Categories:
+[[map pages="*blog/tags/* and !*/Discussion"]]
diff --git a/1.33.2/doc/examples/blog/tags.mdwn b/1.33.2/doc/examples/blog/tags.mdwn
new file mode 100644 (file)
index 0000000..08e7e5c
--- /dev/null
@@ -0,0 +1,3 @@
+[[pagestats pages="*blog/tags/*"]]
+
+On the right you can see the tag cloud for this blog.
diff --git a/1.33.2/doc/examples/blog/tags/life.mdwn b/1.33.2/doc/examples/blog/tags/life.mdwn
new file mode 100644 (file)
index 0000000..b6cf801
--- /dev/null
@@ -0,0 +1,4 @@
+This feed contains pages in the "life" category.
+
+[[inline pages="link(tags/life) and *blog/posts/* and !*/Discussion"
+show="10" actions=yes]]
diff --git a/1.33.2/doc/examples/blog/tags/tech.mdwn b/1.33.2/doc/examples/blog/tags/tech.mdwn
new file mode 100644 (file)
index 0000000..dff92f3
--- /dev/null
@@ -0,0 +1,3 @@
+This feed contains pages in the "tech" category.
+
+[[inline pages="link(tags/tech) and !*/Discussion" show=10 actions=yes]]
diff --git a/1.33.2/doc/features.mdwn b/1.33.2/doc/features.mdwn
new file mode 100644 (file)
index 0000000..cb118f2
--- /dev/null
@@ -0,0 +1,162 @@
+An overview of some of ikiwiki's features:
+[[toc ]]
+
+## Uses a real RCS
+
+Rather than implement its own system for storing page histories etc,
+ikiwiki uses a real Revision Control System. This isn't because we're
+lazy, it's because a real RCS is a good thing to have, and there are
+advantages to using one that are not possible with a standard wiki.
+
+Instead of editing pages in a stupid web form, you can use vim and commit
+changes via [[Subversion]]. Or work disconnected using svk and push your
+changes out when you come online. Or use [[git]], [[tla]], or [[mercurial]]
+to work in a distributed fashion all the time. (It's also possible to
+[[plugins/write]] a plugin to support other systems.)
+
+ikiwiki can be run from a [[post-commit]] hook to update your wiki
+immediately whenever you commit a change using the RCS.
+
+Note that ikiwiki does not require a RCS to function. If you want to
+run a simple wiki without page history, it can do that too.
+
+## A wiki compiler
+
+ikiwiki is a wiki compiler; it builds a static website for your wiki, and
+updates it as pages are edited. It is fast and smart about updating a wiki,
+it only builds pages that have changed (and tracks things like creation of
+new pages and links that can indirectly cause a page to need a rebuild)
+
+## Supports many markup languages
+
+By default, pages in the wiki are written using the [[MarkDown]] format.
+Any page with a filename ending in ".mdwn" is converted from markdown to html
+by ikiwiki. Markdown understands text formatted as it would be in an email,
+and is quite smart about converting it to html. The only additional markup
+provided by ikiwiki on top of regular markdown is the [[WikiLink]] and 
+[[PreprocessorDirective]].
+
+If you prefer to use some other markup language, ikiwiki allows others to
+easily be added by [[plugins]]. For example it also supports traditional
+[[plugins/WikiText]] formatted pages, pages written as pure
+[[plugins/HTML]], or pages written in [[reStructuredText|plugins/rst]].
+
+ikiwiki also supports files of any other type, including plain text,
+images, etc. These are not converted to wiki pages, they are just copied
+unchanged by ikiwiki as it builds your wiki. So you can check in an image,
+program, or other special file and link to it from your wiki pages.
+
+## [[Blogging|blog]]
+
+You can turn any page in the wiki into a [[blog]]. Pages matching a
+specified [[PageSpec]] will be displayed as a weblog within the blog
+page. And RSS or Atom feeds can be generated to follow the blog.
+
+Ikiwiki's own [[TODO]], [[news]], and [[plugins]] pages are good examples
+of some of the flexible ways that this can be used. There is also an 
+[[example_blog|examples/blog]] set up that you can copy into your own wiki.
+
+Ikiwiki can also [[plugins/aggregate]] external blogs, feeding them into
+the wiki. This can be used to create a Planet type site that aggregates
+interesting feeds.
+
+You can also mix blogging with podcasting by dropping audio files where
+they will be picked up like blog posts. This will work for any files that
+you would care to syndicate.
+
+## Valid html and [[css]]
+
+ikiwiki aims to produce 
+[valid XHTML 1.0](http://validator.w3.org/check?url=referer).
+ikiwiki generates html using [[templates]], and uses [[css]], so you can 
+change the look and layout of all pages in any way you would like.
+
+## [[Plugins]]
+
+Plugins can be used to add additional features to ikiwiki. The interface
+is quite flexible, allowing plugins to implement additional markup
+languages, register [[PreProcessorDirective]]s, hook into [[CGI]] mode,
+and more. Most of ikiwiki's features are actually provided by plugins.
+Ikiwiki's backend RCS support is also pluggable, so support for new
+revision control systems can be added to ikiwiki.
+
+## [[todo/utf8]]
+
+After rather a lot of fiddling, we think that ikiwiki correctly and fully
+supports utf8 everywhere.
+
+## Other features
+
+The above are the core design goals and features of ikiwiki, but on that
+foundation a lot of other important features are added. Here is an
+incomplete list of some of them.
+
+### [[Tags]]
+
+You can tag pages and use these tags in various ways. Tags will show
+up in the ways you'd expect, like at the bottom of pages, in blogs, and
+in RSS and Atom feeds.
+
+### [[SubPages|SubPage]]
+
+Arbitrarily deep hierarchies of pages with fairly simple and useful
+[[SubPage/LinkingRules]]
+
+### [[BackLinks]]
+
+Automatically included on pages. Rather faster than eg MoinMoin and
+always there to help with navigation.
+
+### Smart merging and conflict resolution in your web browser
+
+Since it uses a real RCS, ikiwiki takes advantage of its smart merging to
+avoid any conflicts when two people edit different parts of the same page
+at the same time. No annoying warnings about other editors, or locking,
+etc, instead the other person's changes will be automatically merged with
+yours when you commit.
+
+In the rare cases where automatic merging fails due to the same part of a
+page being concurrently edited, regular commit conflict markers are
+shown in the file to resolve the conflict, so if you're already familiar
+with that there's no new commit marker syntax to learn.
+
+### [[RecentChanges]], editing pages in a web browser
+
+Nearly the definition of a wiki, although perhaps ikiwiki challenges how
+much of that web gunk a wiki really needs. These features are optional
+and can be enabled by enabling [[CGI]].
+
+### User registration
+
+Can optionally be configured to allow only registered users to post
+pages; online user registration form, etc.
+
+### Discussion pages
+
+Thanks to subpages, every page can easily and automatically have a
+/Discussion subpage. By default, these links are included in the
+[[templates]] for each page.
+
+### Page locking
+
+Wiki admins can lock pages so that only other admins can edit them.
+
+### [[PageHistory]]
+
+Well, sorta. Rather than implementing YA history browser, it can link to
+[[ViewCVS]] or the like to browse the history of a wiki page.
+
+### Full text search
+
+ikiwiki can use the [[HyperEstraier]] search engine to add powerful
+full text search capabilities to your wiki.
+
+### Commit mails
+
+ikiwiki can be configured to send you commit mails with diffs of changes
+to selected pages.
+
+### [[w3mmode]]
+
+Can be set up so that w3m can be used to browse a wiki and edit pages
+without using a web server.
diff --git a/1.33.2/doc/freesoftware.mdwn b/1.33.2/doc/freesoftware.mdwn
new file mode 100644 (file)
index 0000000..0e18b4d
--- /dev/null
@@ -0,0 +1,4 @@
+ikiwiki is licensed under the terms of the GNU [[GPL]].
+
+The parts of ikiwiki that become part of your own wiki (the basewiki pages
+and the [[templates]]) are licensed using a form of the [[BSD]] license.
diff --git a/1.33.2/doc/git.mdwn b/1.33.2/doc/git.mdwn
new file mode 100644 (file)
index 0000000..672db11
--- /dev/null
@@ -0,0 +1,5 @@
+Git is a distributed revison control system originally developed for the linux kernel. Ikiwiki supports storing a wiki in git.
+
+Ikiwiki can run as a post-update hook to update a wiki whenever commits
+come in. When running as a [[cgi]] with Git, ikiwiki automatically
+commits edited pages, and uses the Git history to generate the [[RecentChanges]] page.
\ No newline at end of file
diff --git a/1.33.2/doc/hyperestraier.mdwn b/1.33.2/doc/hyperestraier.mdwn
new file mode 100644 (file)
index 0000000..e124643
--- /dev/null
@@ -0,0 +1,3 @@
+[Hyper Estraier](http://hyperestraier.sourceforge.net/) is a full text
+search engine. Ikiwiki can be configured to use it as the search engine for
+the wiki, using the [[search_plugin|plugins/search]].
diff --git a/1.33.2/doc/ikiwiki-mass-rebuild.mdwn b/1.33.2/doc/ikiwiki-mass-rebuild.mdwn
new file mode 100644 (file)
index 0000000..e5474dd
--- /dev/null
@@ -0,0 +1,25 @@
+# NAME
+
+ikiwiki-mass-rebuild - rebuild all ikiwiki wikis on a system
+
+# SYNOPSIS
+
+ikiwiki-mass-rebuild
+
+# DESCRIPTION
+
+`ikiwiki-mass-rebuild` can be used to force a rebuild of all the wikis
+on a system. You will need to list the wikis it shuld build in the file
+/etc/ikiwiki/wikilist, which has the format:
+
+user /path/to/wiki
+
+# OPTIONS
+
+All options are passed on to ikiwiki.
+
+# AUTHOR
+
+Joey Hess <joey@kitenet.net>
+
+Warning: this page is automatically made into ikiwiki-mass-rebuild's man page, edit with care
diff --git a/1.33.2/doc/ikiwiki.setup b/1.33.2/doc/ikiwiki.setup
new file mode 100644 (file)
index 0000000..8534c7a
--- /dev/null
@@ -0,0 +1,111 @@
+#!/usr/bin/perl
+# Configuration file for ikiwiki.
+# Passing this to ikiwiki --setup will make ikiwiki generate wrappers and 
+# build the wiki.
+#
+# Remember to re-run ikiwiki --setup any time you edit this file.
+
+use IkiWiki::Setup::Standard {
+       wikiname => "MyWiki",
+       #adminuser => ["yourname", ],
+       adminemail => 'me@myhost',
+       
+       # Be sure to customise these..
+       srcdir => "/path/to/source",
+       destdir => "/var/www/wiki",
+       
+       url => "http://myhost/wiki",
+       cgiurl => "http://myhost/ikiwiki.cgi",
+       #templatedir => "/usr/share/ikiwiki/templates",
+       
+       # Subversion stuff.
+       rcs => "svn",
+       #historyurl => "http://svn.myhost/trunk/[[file]]",
+       #diffurl => "http://svn.someurl/trunk/[[file]]?root=wiki&amp;r1=[[r1]]&amp;r2=[[r2]]",
+       svnrepo => "/svn/wiki",
+       svnpath => "trunk",
+
+       # Git stuff.
+       #rcs => "git",
+       #historyurl => "http://git.host/gitweb.cgi?p=wiki.git;a=history;f=[[file]]",
+       #diffurl => "http://git.host/gitweb.cgi?p=wiki.git;a=blobdiff;h=[[sha1_to]];hp=[[sha1_from]];hb=[[sha1_parent]];f=[[file]]",
+
+       # Tla stuff.
+       #rcs => "tla"
+       #historyurl => ??,
+       #diffurl => ??,
+
+       # Mercurial stuff.
+       #rcs => "mercurial",
+       #historyurl => "http://localhost:8000/", # hg serve'd local repository
+       #diffurl => "http://localhost:8000/?fd=[[changeset]];file=[[file]]",
+
+       wrappers => [
+               #{
+               #       # The cgi wrapper.
+               #       cgi => 1,
+               #       wrapper => "/var/www/wiki/ikiwiki.cgi",
+               #       wrappermode => "06755",
+               #},
+               {
+                       # The svn post-commit wrapper.
+                       # Note that this will overwrite any existing
+                       # post-commit hook script, which may not be
+                       # what you want.
+                       wrapper => "/svn/wikirepo/hooks/post-commit",
+                       wrappermode => "04755",
+                       # Enable mail notifications of commits.
+                       notify => 1,
+               },
+               #{
+               #       # The git post-update wrapper.
+               #       # Note that this will overwrite any existing
+               #       # post-update hook script, which may not be
+               #       # what you want.
+               #       wrapper => "/git/wikirepo/.git/hooks/post-update",
+               #       wrappermode => "04755",
+               #       # Enable mail notifications of commits.
+               #       notify => 1,
+               #},
+       ],
+       
+       # Can anonymous web users edit pages?
+       #anonok => 1,
+       # Generate rss feeds for blogs?
+       rss => 1,
+       # Generate atom feeds for blogs?
+       atom => 1,
+       # Urls to ping with XML-RPC when rss feeds are updated
+       #pingurl => [qw{http://rpc.technorati.com/rpc/ping}],
+       # Include discussion links on all pages?
+       discussion => 1,
+       # To exclude files matching a regexp from processing. This adds to
+       # the default exclude list.
+       #exclude => qr/\*.wav/,
+       # Time format (for strftime)
+       #timeformat => '%c',
+       # Locale to use. Must be a UTF-8 locale.
+       #locale => 'en_US.UTF-8',
+       # Only send cookies over SSL connections.
+       #sslcookie => 1,
+       # Use HTTP Authentication instead of Ikiwiki's.
+       #httpauth => 1,
+       # Logging settings:
+       verbose => 0,
+       syslog => 0,
+       
+       # To add plugins, list them here.
+       #add_plugins => [qw{meta tag pagecount brokenlinks search smiley
+       #                   wikitext camelcase pagestats htmltidy fortune
+       #                   sidebar map rst toc linkmap}],
+       # If you want to disable any of the default plugins, list them here.
+       #disable_plugins => [qw{inline htmlscrubber}],
+
+       # For use with the tag plugin, make all tags be located under a
+       # base page.
+       #tagbase => "tag".
+       
+       # For use with the search plugin if your estseek.cgi is located 
+       # somewhere else.
+       #estseek => "/usr/lib/estraier/estseek.cgi",
+}
diff --git a/1.33.2/doc/ikiwikiusers.mdwn b/1.33.2/doc/ikiwikiusers.mdwn
new file mode 100644 (file)
index 0000000..3531c1a
--- /dev/null
@@ -0,0 +1,38 @@
+Sites that are using ikiwiki include:
+
+* [This wiki](http://ikiwiki.kitenet.net) (of course!)
+* [[Joey]]'s [homepage](http://kitenet.net/~joey/), including his weblog
+* [Jeroen Schot's homepage/weblog](http://schot.a-eskwadraat.nl)
+* [Kyle's MacLea Genealogy wiki](http://kitenet.net/~kyle/family/wiki)
+* [David's Master's Thesis wiki](https://dipl.black.co.at/wiki/) (german)
+* [Ulrik's small collection of small apps](http://www.student.lu.se/~cif04usv/wiki/)
+* [kite](http://kitenet.net)
+* [Bright Cloud](http://brightcloud.lcsee.wvu.edu/), a project of WVU LCSEE
+* [Perl Mongers México](http://www.pm.org.mx/)
+* [UK Software Patents info page](http://www.softwarepatents.co.uk/)
+* [Paul Collins's as-yet purposeless wiki](http://wiki.ondioline.org/)
+* [Andre Luis Lopes's personal website](http://www.andrelop.org/). Brazilian Portuguese only
+* [Alessandro Dotti Contra's personal website](http://www.dotticontra.org/) and [weblog](http://www.dotticontra.org/blog)
+* [Kelly Clowers' personal website](http://www.clowersnet.net/)
+* [Anna's nature features](http://kitenet.net/~anna/nature-feature/)
+* [Planet Debian upstream](http://updo.debian.net/)
+* [Roland Mas's blog](http://roland.entierement.nu/categories/geek-en.html)
+* [Sergio Talens-Oliag's personal wiki](http://mixinet.net/~sto/) and [blog](http://mixinet.net/~sto/blog.html)
+* [Christian Aichinger's homepage](http://greek0.net/)
+* The [ion window manager homepage](http://modeemi.fi/~tuomov/ion/)
+* [Ben A'Lee's homepage](http://bmalee.eu/~bma/)
+* [Recai Oktaş's homepage](http://kirkambar.net/) (uses [[Git]] backend, Turkish language only).
+* [Hess family wiki](http://kitenet.net/~family/)
+* [Debian Mentors wiki](http://jameswestby.net/mentors/)
+* [LinuxWorld.com's monkey.linuxworld.com contributor wiki](https://monkey.linuxworld.com/) ([[Git]] backend)
+* [Stefano Zacchiroli's blog](http://www.bononia.it/~zack/blog/)
+* [Taquiones: Victor Moral's personal website in Spanish](http://taquiones.net)
+* [betacantrips, the personal website of Ethan Glasser-Camp](http://www.betacantrips.com/)
+* [Keith Packard's homepage and blog](http://keithp.com/).
+* [Christian Mock's homepage](http://www.tahina.priv.at/).
+* [Simon Raven's IkiWiki homepage](http://simonraven.nuit.ca/wiki/).
+* The [Sparse wiki](http://kernel.org/pub/linux/kernel/people/josh/sparse).
+
+Please feel free to add your own ikiwiki site!
+
+See also: [ikiwiki popcon graph](http://people.debian.org/~igloo/popcon-graphs/index.php?packages=ikiwiki)
diff --git a/1.33.2/doc/index.mdwn b/1.33.2/doc/index.mdwn
new file mode 100644 (file)
index 0000000..22a08c0
--- /dev/null
@@ -0,0 +1,33 @@
+[[ikiwiki_logo|logo/ikiwiki.png]]  
+ikiwiki is a **wiki compiler**. It converts wiki pages
+into html pages suitable for publishing on a website. Unlike many
+wikis, ikiwiki does not have its own ad-hoc means of storing page history,
+and instead uses a revision control system such as [[Subversion]].
+
+* [[News]] is a blog (built using ikiwiki) of news items about ikiwiki.
+  It's the best way to find out when there's a new version to [[Download]].
+
+* See [[Features]] for a list of ikiwiki's features and [[plugins]] for information about its plugins. [[RoadMap]], [[TODO]]
+  and [[bugs]] might also be of interest. 
+
+* Feel free to post your questions and thoughts about ikiwiki to [[Discussion]].
+
+[[template id=note text="""
+If you use ikiwiki, please list your wiki in [[IkiWikiUsers]].
+Thanks! --[[Joey]]
+"""]]
+
+* [[Setup]] has a tutorial for setting up ikiwiki, and [[Usage]] documents
+  the parameters and usage of the ikiwiki program. There are some
+  [[examples]] that you can copy into your wiki to quickly get started.
+
+* [[Security]] lists potential security problems. ikiwiki is still being
+  developed, and is being written with security as a priority, so don't
+  expect things to stay in this list for long.
+
+* Developers, please document any ikiwiki patches you have in the
+  [[PatchQueue]].
+
+All wikis are supposed to have a [[SandBox]], so this one does too.
+
+ikiwiki is developed by [[Joey]] and is [[FreeSoftware]].
diff --git a/1.33.2/doc/index/discussion.mdwn b/1.33.2/doc/index/discussion.mdwn
new file mode 100644 (file)
index 0000000..f4b8edb
--- /dev/null
@@ -0,0 +1,53 @@
+Seems like there should be a page for you to post your thoughts about
+ikiwiki, both pro and con, anything that didn't work, ideas, or whatever.
+Do so here..
+
+Note that for more formal bug reports or todo items, you can also edit the
+[[bugs]] and [[todo]] pages.
+
+---- 
+
+# ACL
+
+How about adding ACL? So that you can control which users are allowed
+to read, write certain pages. The moinmoin wiki has that, and it is
+something, that I think is very valuable. 
+
+> ikiwiki currently has only the most rudimentary access controls: pages
+> can be locked, or unlocked and only the admin can edit locked pages. That
+> could certianly be expanded on, although it's not an area that I have an
+> overwhelming desire to work on myself right now. Patches appreciated and
+> I'll be happy to point you in the right directions.. --[[Joey]]
+
+----
+
+Some questions about the RecentChanges function. -- Ethan
+
+> (Moved to [[todo/recentchanges]] --[[Joey]])
+
+----
+
+Also, I'd like to request another template parameter which is just
+$config{url}. That way you won't have to hard-code the URL of the wiki into
+the template. -- Ethan
+
+> That's already available in the BASEURL parameter. --[[Joey]]
+
+----
+
+# Canonical feed location?
+
+Any way to use `inline` but point the feed links to a different feed on the
+same site?  I have news in news/*, a news archive in news.mdwn, and the
+first few news items on index.mdwn, but I don't really want two separate
+feeds, one with all news and one with the latest few articles; I'd rather
+point the RSS feed links of both to the same feed.  (Which one, the one
+with all news or the one with the latest news only, I don't know yet.)
+
+> Not currently. It could be implemented, or you could just turn off the
+> rss feed for the index page, and manually put in a wikilink to the news
+> page and rss feed. --[[Joey]]
+
+>> That wouldn't use the same style for the RSS and Atom links, and it
+>> wouldn't embed the feed link into `<head>` so that browsers can automatically
+>> find it.
\ No newline at end of file
diff --git a/1.33.2/doc/install.mdwn b/1.33.2/doc/install.mdwn
new file mode 100644 (file)
index 0000000..22f1a3a
--- /dev/null
@@ -0,0 +1,32 @@
+The easiest way to install ikiwiki is using the Debian package, but you can
+also [[download]] the source and install it by hand. Ikiwiki should work on
+most unix-like systems.
+
+Ikiwiki is a perl program, and needs a recent version of perl such as
+5.8.8. (5.8.0 has been reported not to work).
+
+Ikiwiki requires [[MarkDown]] and the `URI` and `HTML::Parser` perl
+modules be installed, and also uses the following perl modules if
+available: 
+`CGI::Session` `CGI::FormBuilder` (version 3.02.02 or newer)
+`HTML::Template` `Mail::Sendmail` `Time::Duration` `Date::Parse`,
+`HTML::Scrubber`, `RPC::XML`, `XML::Simple`, `XML::Feed`, `File::MimeInfo`.
+
+The [[tla]] support also needs the `MailTools` perl module.
+
+Various [[plugins]] use other libraries and utlities; see their individual
+documentation for details.
+
+If you're installing MarkDown by hand, note that it should be installed as
+`Markdown.pm` somewhere in perl's module search path, or alternately as
+`/usr/bin/markdown`. Ikiwiki will find it under either name.
+
+If you want to install from the tarball, you should make sure that the
+required perl modules are installed, then run:
+
+        perl Makefile.PL # PREFIX=/dir to install elsewhere
+        make
+       make test # optional
+        make install
+
+See [[download]] for where to get it.
diff --git a/1.33.2/doc/joey.mdwn b/1.33.2/doc/joey.mdwn
new file mode 100644 (file)
index 0000000..c60c76f
--- /dev/null
@@ -0,0 +1,6 @@
+Joey Hess is <a href="mailto:joey@kitenet.net">joey@kitenet.net</a>. 
+His web page is [here](http://kitenet.net/~joey/).
+
+Joey hates programming web crap, and hates being locked into a web browser
+to do something, and this probably shows in the design choices made in
+ikiwiki.
diff --git a/1.33.2/doc/jonassmedegaard.mdwn b/1.33.2/doc/jonassmedegaard.mdwn
new file mode 100644 (file)
index 0000000..6538839
--- /dev/null
@@ -0,0 +1,3 @@
+Jonas Smedegaard is a Debian developer, like joey. A big fan of this novel approach to wiki: serving as pages static!
+
+JonasSmedegaard maintains the packaging of another wiki - MoinMoin - for Debian, but is personally tired of the heavy burden of Python on his web servers.
diff --git a/1.33.2/doc/logo.mdwn b/1.33.2/doc/logo.mdwn
new file mode 100644 (file)
index 0000000..ac46099
--- /dev/null
@@ -0,0 +1,51 @@
+The ikiwiki logo *reflects* ikiwiki turning the regular wiki concept 
+on its head by being a wiki compiler. Or maybe just the fact that "ikiwiki"
+is an anagram. 
+
+Anyway, if you have this logo in other fonts or colors, feel free to send
+it to [[Joey]] for inclusion here. (Or upload it, once that feature is
+added).
+
+* [[ikiwiki_logo|ikiwiki.png]]  
+  [[ikiwiki_logo_large|ikiwiki_large.png]]  
+  [[ikiwiki_button|ikiwiki_button.png]]
+
+  [[SVG_source|ikiwiki.svgz]], can be used to generate a logo at any size
+  with a command like:  
+
+       inkscape -w 90 -i logo -e ikiwiki.png ikiwiki.svgz
+       inkscape -w 150 -i logo -e ikiwiki_large.png ikiwiki.svgz
+
+  The [[favicon.ico]] can also be generated from this file, as follows:
+
+       inkscape -w 16 -i favicon -e favicon.ico ikiwiki.svgz
+
+  The button can also be generated as follows:
+
+       inkscape -w 80 -i button -e ikiwiki_button.png ikiwiki.svgz
+
+  Some other alternate icons and buttons are also included in the svg file
+  and can be extracted by specifying their names.
+
+  [[img ikiwiki.png alt="bob" size="200x200"]]
+
+  Contributed by Recai Oktaş
+
+* [[ikiwiki_logo|ikiwiki_old2.png]]
+
+  [[SVG_source|ikiwiki_old2.svgz]] to this older version of the logo.
+
+  Contributed by Recai Oktaş
+
+* [[ikiwiki_logo|ikiwiki_old.png]] 
+
+  LaTeX source to an image approximating the above:
+
+       \documentclass{article}
+       \usepackage{graphicx}
+       \begin{document}
+       \pagestyle{empty}
+       \huge\reflectbox{iki}wiki
+       \end{document}
+
+  Contributed by [[JeroenSchot]]
diff --git a/1.33.2/doc/logo/discussion.mdwn b/1.33.2/doc/logo/discussion.mdwn
new file mode 100644 (file)
index 0000000..7f712a5
--- /dev/null
@@ -0,0 +1 @@
+![ikiwiki logo](http://wiki.ondioline.org/ikiwiki.png) The logo I'm using on my ikiwiki installation. -- Paul Collins
\ No newline at end of file
diff --git a/1.33.2/doc/logo/ikiwiki.png b/1.33.2/doc/logo/ikiwiki.png
new file mode 100644 (file)
index 0000000..c7adffb
Binary files /dev/null and b/1.33.2/doc/logo/ikiwiki.png differ
diff --git a/1.33.2/doc/logo/ikiwiki.svgz b/1.33.2/doc/logo/ikiwiki.svgz
new file mode 100644 (file)
index 0000000..a67774a
Binary files /dev/null and b/1.33.2/doc/logo/ikiwiki.svgz differ
diff --git a/1.33.2/doc/logo/ikiwiki_button.png b/1.33.2/doc/logo/ikiwiki_button.png
new file mode 100644 (file)
index 0000000..ca001d5
Binary files /dev/null and b/1.33.2/doc/logo/ikiwiki_button.png differ
diff --git a/1.33.2/doc/logo/ikiwiki_large.png b/1.33.2/doc/logo/ikiwiki_large.png
new file mode 100644 (file)
index 0000000..76cd490
Binary files /dev/null and b/1.33.2/doc/logo/ikiwiki_large.png differ
diff --git a/1.33.2/doc/logo/ikiwiki_old.png b/1.33.2/doc/logo/ikiwiki_old.png
new file mode 100644 (file)
index 0000000..f16c9ad
Binary files /dev/null and b/1.33.2/doc/logo/ikiwiki_old.png differ
diff --git a/1.33.2/doc/logo/ikiwiki_old2.png b/1.33.2/doc/logo/ikiwiki_old2.png
new file mode 100644 (file)
index 0000000..7864bb1
Binary files /dev/null and b/1.33.2/doc/logo/ikiwiki_old2.png differ
diff --git a/1.33.2/doc/logo/ikiwiki_old2.svgz b/1.33.2/doc/logo/ikiwiki_old2.svgz
new file mode 100644 (file)
index 0000000..a0c3450
Binary files /dev/null and b/1.33.2/doc/logo/ikiwiki_old2.svgz differ
diff --git a/1.33.2/doc/mercurial.mdwn b/1.33.2/doc/mercurial.mdwn
new file mode 100644 (file)
index 0000000..5eaae19
--- /dev/null
@@ -0,0 +1,8 @@
+[Mercurial](http://selenic.com/mercurial) is a distributed revison control
+system developed by Matt Mackall. Ikiwiki supports storing a wiki in a
+mercurial repository.
+
+Ikiwiki can run as a post-update hook to update a wiki whenever commits
+come in. When running as a [[cgi]] with Mercurial, ikiwiki automatically
+commits edited pages, and uses the Mercurial history to generate the
+[[RecentChanges]] page.
diff --git a/1.33.2/doc/news.mdwn b/1.33.2/doc/news.mdwn
new file mode 100644 (file)
index 0000000..781666c
--- /dev/null
@@ -0,0 +1,8 @@
+This is where annoucements of new releases, features, and other news is
+posted. [[IkiWikiUsers]] are recommended to subscribe to this page's RSS
+feed.
+
+[[inline pages="news/* and !*/Discussion" rootpage="news" show="30"]]
+
+By the way, some other pages with RSS feeds about ikiwiki include
+[[plugins]], [[TODO]] and [[bugs]].
diff --git a/1.33.2/doc/news/seeking_article_writer.mdwn b/1.33.2/doc/news/seeking_article_writer.mdwn
new file mode 100644 (file)
index 0000000..3257ae0
--- /dev/null
@@ -0,0 +1,15 @@
+Don Marti asked me if I'd like to write an article about ikiwiki for
+LinuxWorld.com, but I don't have such an article in me right now, and
+thought I'd see if someone else is interested in writing it. Here's Don's
+request:
+
+> I'd be interested in getting a
+> tutorial article on ikiwiki.  Would you be interested
+> in writing one, or do you know someone who is?
+> We have an Artistic Immortality Clause, so you would
+> keep the copyright and could use anything you write as
+> part of the project docs.  I'm especially interested
+> in the lightweight workflow aspects, such as using
+> a wiki as a bug tracking system.
+
+--[[Joey]]
diff --git a/1.33.2/doc/news/seeking_article_writer/discussion.mdwn b/1.33.2/doc/news/seeking_article_writer/discussion.mdwn
new file mode 100644 (file)
index 0000000..ae0c23d
--- /dev/null
@@ -0,0 +1,14 @@
+As this is a wiki, could you set up a page where those of us
+who might be able to contribute a little could work together
+to write the article?
+
+I realise that I could just start it myself, but if you wanted to
+create a page somewhere and state in a few words how you would
+like the article to go (maybe what to emphasise, or what angle
+to work from), we could come up with something.
+
+Do you know if they are just after an overview article, or an
+actual guide to setting up an instance? --JamesWestby
+
+> All I know is what I posted but I could get you in touch with Don.
+> --[[Joey]]
diff --git a/1.33.2/doc/news/stylesheets.mdwn b/1.33.2/doc/news/stylesheets.mdwn
new file mode 100644 (file)
index 0000000..a5f0946
--- /dev/null
@@ -0,0 +1,16 @@
+Some people may consider ikiwiki's default look to be a bit plain. Someone
+on slashdot even suggested perhaps it uses html 1.0. (Yes, an ikiwiki site
+has survived its first slashdotting. With static html, that's not very
+hard..) While the default style is indeed plain, there's more fine-tuning
+going on than you might think, and it's actually all done with xhtml and
+style sheets.
+
+Stefano Zacchiroli came up with the idea of adding a [[css_market]] page
+where [[IkiWikiUsers]] can share style sheets that you've come up with for
+ikiwiki. This is a great idea and I encourage those of you who have
+customised stylesheets to post them.
+
+I'm also always looking for minimalistic yet refined additions to the default
+style sheet, and always appreciate suggestions for it.
+
+--[[Joey]]
diff --git a/1.33.2/doc/news/svn_move.mdwn b/1.33.2/doc/news/svn_move.mdwn
new file mode 100644 (file)
index 0000000..ab218d4
--- /dev/null
@@ -0,0 +1,5 @@
+ikiwiki's subversion repository has moved to a new location, see
+[[download]] for updated details.
+
+(ikiwiki.kitenet.net is also now hosted on a different, rather faster
+server.)
diff --git a/1.33.2/doc/news/version_1.30.mdwn b/1.33.2/doc/news/version_1.30.mdwn
new file mode 100644 (file)
index 0000000..77b4249
--- /dev/null
@@ -0,0 +1,12 @@
+ikiwiki 1.30 released with these changes:
+
+   * Add no\_override parameter to hook().
+   * Add a shortcut plugin, inspired by Victor Moral's contributed shortcuts
+     plugin, but featuring a more ikiwiki-ish syntax and with shortcuts that
+     can be configured using a page in wiki.
+   * Fix support for --pingurl at the command line.
+   * Fix a subtle bug in will\_render that broke some builds, by only clearing
+     items from renderedfiles the first time per build.
+   * Wrap entire technortati ping operation in an eval to catch all possible
+     failure modes, after I observed a simple -&gt;value crashing ikiwiki when
+     a ping failed.
\ No newline at end of file
diff --git a/1.33.2/doc/news/version_1.31.mdwn b/1.33.2/doc/news/version_1.31.mdwn
new file mode 100644 (file)
index 0000000..846ca7f
--- /dev/null
@@ -0,0 +1,16 @@
+ikiwiki 1.31 released with these changes:
+
+   * Patch from Pawel Tecza to cp -a the templates in the Makefile.
+   * Change the rss feed title from the wikiname to the page title, with
+     an exception for the wiki's toplevel index page, which will still use the
+     wikiname as the feed title.
+     Overriding the page title with meta title already overrode the rss feed
+     tittle.
+   * Add an img plugin, based on Christian Mock's img plugin, but stripped
+     down to the bare essentials. Useful for handling large images on websites.
+   * Sanitize possibly problimatic characters out of the polygen grammar names,
+     just in case. Should not be exploitable anyway, since it only tries to run
+     polygen after finding the specified grammar file.
+   * Add missing dependency on the URI perl module.
+   * Add basic spam fighting tool for admins: An admin's prefs page now allows
+     editing a list of banned users.
\ No newline at end of file
diff --git a/1.33.2/doc/news/version_1.32.mdwn b/1.33.2/doc/news/version_1.32.mdwn
new file mode 100644 (file)
index 0000000..6f1d498
--- /dev/null
@@ -0,0 +1,36 @@
+ikiwiki 1.32 released with these changes:
+
+   * Add a separate pass to find page links, and only render each page once,
+     instead of over and over. Typical speedup is ~4x. Max possible speedup:
+     8x.
+   * Add "scan" parameter to hook(), which is used to make the hook be called
+     during the scanning pass, as well as the render pass. The meta and tag
+     plugins need to use the new scan parameter, so will any others that modify
+     %links.
+   * Now that links are calculated in a separate pass, it can also
+     precalculate backlinks in one pass, which is O(N^2) instead of the
+     previous code that was O(N^3). A very nice speedup for wikis with lots
+     (thousands) of pages.
+   * Stylish update to the ikiwiki logo, thanks to Recai Oktaş and Selçuk
+     Erdem.
+   * Add a default stylesheet entry for the pagecloud.
+   * Add examples page with some examples of things that can be done using
+     ikiwiki, like a weblog. The examples can be copied into a user's wiki
+     for a quick start, without needing to learn everything about how to put
+     them together.
+   * Install the source of the examples into /usr/share/doc/ikiwiki/examples.
+   * Add perlmagick to build-depends so syntax check of img plugin works.
+     Closes: #[396702](http://bugs.debian.org/396702)
+   * Improve login/register process, the login dialog has only name and
+     password fields, which allows more web browsers to regognise it as a login
+     field, and is less confusing.
+   * Implemented expiry options for aggregate plugin.
+   * Use precalculated backlinks info when determining if files need an update
+     due to a page they link to being added/removed. Mostly significant if
+     there are lots of pages.
+   * Remove duplicate link info when saving index. In some cases it could
+     pile up rather badly. (Probably not the best way to deal with this
+     problem.)
+   * Patch from James Westby to support podcasting, photoblogging, vidcasting,
+     or what have you, by creating enclosures for non-page items that are
+     included in feeds.
\ No newline at end of file
diff --git a/1.33.2/doc/pagehistory.mdwn b/1.33.2/doc/pagehistory.mdwn
new file mode 100644 (file)
index 0000000..87f2039
--- /dev/null
@@ -0,0 +1 @@
+ikiwiki supports adding "History" links to the top of pages to browse the revison history of a page. This is enabled by the --historyurl switch, which is used to specify the URL to a web interface such as [[ViewCVS]]. [[Setup]] has an example of setting this up.
\ No newline at end of file
diff --git a/1.33.2/doc/patchqueue.mdwn b/1.33.2/doc/patchqueue.mdwn
new file mode 100644 (file)
index 0000000..2702569
--- /dev/null
@@ -0,0 +1,8 @@
+Since we have enough people working on ikiwiki to be dangerous, or at least
+to duplicate work without coordination, and since Joey is still the only
+one committing directly to the tree, here's a queue of suggested patches.
+Feel free to either copy the patch inline, or link to one elsewhere (or nag
+Joey to open up anonymous svn access to this wiki so you can check in the
+patches directly).
+
+[[inline pages="patchqueue/* and !patchqueue/done and !link(patchqueue/done) and !*/Discussion" rootpage="patchqueue" archive="yes"]]
diff --git a/1.33.2/doc/patchqueue/index.html_allowed.mdwn b/1.33.2/doc/patchqueue/index.html_allowed.mdwn
new file mode 100644 (file)
index 0000000..dc527bb
--- /dev/null
@@ -0,0 +1,61 @@
+Instead of having files foo.html "in front of" foo/, I prefer to have foo/index.html. This patch allows that. Specifically, foo/index.type is translated to $links{'foo/'}, and bestlink looks for either "foo" or "foo/" when linking to pages. There are other miscellaneous changes that go with that -- parentlinks for "foo/" are the same as for "foo", except one directory higher; basename of "foo/" is "foo"; links to "foo/" are translated to "foo/index.html" rather than "foo/.html". (Links to "foo/" might be preferred, but that causes an infinite loop in writefile, because apparently dirname("foo/") == "foo/" on my system for reasons that aren't clear to me.)
+
+    diff -ur -x .svn ikiwiki-orig/IkiWiki/Render.pm ikiwiki/IkiWiki/Render.pm
+    --- ikiwiki-orig/IkiWiki/Render.pm  2006-11-08 01:02:33.000000000 -0500
+    +++ ikiwiki/IkiWiki/Render.pm       2006-11-08 01:02:46.000000000 -0500
+    @@ -57,6 +57,10 @@
+        my $path="";
+        my $skip=1;
+        return if $page eq 'index'; # toplevel
+    +   if ($page =~ m{/$}){
+    +           $page =~s{/$}{};
+    +           $path="..";
+    +   }
+        foreach my $dir (reverse split("/", $page)) {
+                if (! $skip) {
+                        $path.="../";
+    diff -ur -x .svn ikiwiki-orig/IkiWiki.pm ikiwiki/IkiWiki.pm
+    --- ikiwiki-orig/IkiWiki.pm 2006-11-08 01:02:38.000000000 -0500
+    +++ ikiwiki/IkiWiki.pm      2006-11-08 01:02:48.000000000 -0500
+    @@ -174,6 +174,7 @@
+     sub basename ($) { #{{{
+        my $file=shift;
+
+    +   $file=~s!/$!!;
+        $file=~s!.*/+!!;
+        return $file;
+     } #}}}
+    @@ -200,12 +201,14 @@
+        my $type=pagetype($file);
+        my $page=$file;
+        $page=~s/\Q.$type\E*$// if defined $type;
+    +   $page=~s#index$## if $page=~m{/index$};
+        return $page;
+     } #}}}
+
+     sub htmlpage ($) { #{{{
+        my $page=shift;
+
+    +   return $page."index.html" if $page=~m{/$};
+        return $page.".html";
+     } #}}}
+
+    @@ -289,6 +292,7 @@
+        my $page=shift;
+        my $link=shift;
+
+    +   $page =~ s!/$!!;
+        my $cwd=$page;
+        do {
+                my $l=$cwd;
+    @@ -298,6 +302,9 @@
+                if (exists $links{$l}) {
+                        return $l;
+                }
+    +           if (exists $links{$l.'/'}){
+    +                   return $l.'/';
+    +           }
+                elsif (exists $pagecase{lc $l}) {
+                        return $pagecase{lc $l};
+                }
+
diff --git a/1.33.2/doc/patchqueue/index.html_allowed/discussion.mdwn b/1.33.2/doc/patchqueue/index.html_allowed/discussion.mdwn
new file mode 100644 (file)
index 0000000..e875ce6
--- /dev/null
@@ -0,0 +1,10 @@
+Any chance of this, or something like this, making it into the trunk?
+
+I realized that when writing Perl modules, having a Foo.pm, and then Foo/Bar.pm is the norm, 
+so maybe that's why Ikiwiki does things this way. But I still think it's "more natural" 
+in a web environment. (And Python, which is where I do my hacking, imports Foo/__init__.py
+if you import Foo.)
+
+Ethan
+
++1 for this patch making it into trunk. --James
\ No newline at end of file
diff --git a/1.33.2/doc/patchqueue/l10n.mdwn b/1.33.2/doc/patchqueue/l10n.mdwn
new file mode 100644 (file)
index 0000000..85e4f21
--- /dev/null
@@ -0,0 +1,97 @@
+From [[Recai]]:
+> Here is my initial work on ikiwiki l10n infrastructure (I'm sending it
+> before finalizing, there may be errors).
+
+I've revised the patches (tested OK):
+
+- $config{lang} patch:
+
+    <http://people.debian.org/~roktas/patches/ikiwiki/ikiwiki-lang.diff>
+
+  + Support for CGI::FormBuilder.
+  + Modify Makefile.PL for l10n.
+
+- l10n infrastructure from Koha project.  (This patch must be applied with
+  '-p1', also, it needs a 'chmod +x l10n/*.pl' after patching.)
+
+  + Leave templates dir untouched, use a temporary translations directory
+    instead.
+  + Fix Makefile (it failed to update templates).
+
+    http://people.debian.org/~roktas/patches/ikiwiki/ikiwiki-l10n.diff
+
+However...
+
+> There are two places in IkiWiki, subject to localization: HTML::Template
+
+Unfortunately this is not correct.  There a few (?) exceptional places, for
+example button texts in CGI.pm:
+
+    my @buttons=("Save Page", "Preview", "Cancel");
+
+> fine.  Also a final note, I haven't examined the quality of generated
+> templates yet.
+
+Looks like, tmpl_process3 cannot preserve line breaks in template files.
+For example, it processed the following template:
+
+    Someone[1], possibly you, requested that you be emailed the password for
+user
+    <TMPL_VAR USER_NAME> on <TMPL_VAR WIKINAME>[2].
+
+    The password is: <TMPL_VAR USER_PASSWORD>
+
+    --
+    ikiwiki
+
+    [1] The user requesting the password was at IP address <TMPL_VAR
+REMOTE_ADDR>
+    [2] Located at <TMPL_VAR WIKIURL>
+
+as (in Turkish):
+
+Birisi[1], ki muhtemelen bu sizsiniz, <TMPL_VAR WIKINAME>[2] üzerindeki
+<TMPL_VAR USER_NAME> kullanıcısına ait parolanın epostalanması isteğinde
+bulundu. Parola: <TMPL_VAR USER_PASSWORD> -- ikiwiki [1] Parolayı isteyen
+kullanıcının ait IP adresi: <TMPL_VAR REMOTE_ADDR>[2] <TMPL_VAR WIKIURL>
+
+----
+
+> Unfortunately this is not correct.  There a few (?) exceptional places, for
+> example button texts in CGI.pm:
+>
+>     my @buttons=("Save Page", "Preview", "Cancel");
+
+Hmm, I've thought on this issue.  Using Locale::gettext seems to be the
+natural solution.  But this would need to create another po file and also,
+ikiwiki would depend another Perl module.  Kinda overkill...
+
+I have another idea...  What about to create another (flat) template file
+for this sort of strings?  Something like strings.tmpl with the content:
+
+    Save Page, Preview, Cancel
+
+or we could categorize these strings in some variables (',' is the
+delimiter for this code snippet):
+
+    <TMPL_IF NAME="BUTTONS">
+    Save Page, Preview, Cancel
+    </TMPL_IF>
+
+and then (preferably in a separate wrapper function in CGI.pm):
+
+     my $template=template("strings.tmpl");
+     $template->param("BUTTONS", 1);
+     my @buttons=split(/\s*,\s*/, $template->output);
+
+You get the idea...  I've tried this method.  All in one po file, kind of
+ugly, but it _really_ works.
+
+> > fine.  Also a final note, I haven't examined the quality of generated
+> > templates yet.
+>
+> Looks like, tmpl_process3 cannot preserve line breaks in template files.
+> For example, it processed the following template:
+
+This could be easily worked around in tmpl_process3, but I wouldn't like to
+maintain a separate utility.
diff --git a/1.33.2/doc/patchqueue/pruning_is_too_strict.mdwn b/1.33.2/doc/patchqueue/pruning_is_too_strict.mdwn
new file mode 100644 (file)
index 0000000..0b7ea76
--- /dev/null
@@ -0,0 +1,80 @@
+Preliminary patch for a feature wishlist item: [[bugs/pruning_is_too_strict]].
+
+    diff -ur ikiwiki-orig/IkiWiki/CGI.pm ikiwiki/IkiWiki/CGI.pm
+    --- ikiwiki-orig/IkiWiki/CGI.pm     2006-10-27 20:15:17.000000000 -0700
+    +++ ikiwiki/IkiWiki/CGI.pm  2006-11-07 22:32:41.000000000 -0800
+    @@ -405,7 +405,7 @@
+        my ($page)=$form->field('page');
+        $page=titlepage(possibly_foolish_untaint($page));
+        if (! defined $page || ! length $page ||
+    -       $page=~/$config{wiki_file_prune_regexp}/ || $page=~/^\//) {
+    +       is_prune($page) || $page=~/^\//) {
+                error("bad page name");
+        }
+
+    @@ -495,8 +495,7 @@
+                        my $best_loc;
+                        if (! defined $from || ! length $from ||
+                            $from ne $form->field('from') ||
+    -                       $from=~/$config{wiki_file_prune_regexp}/ ||
+    -                       $from=~/^\// ||
+    +                       is_prune($from) || $from=~/^\// ||
+                            $form->submitted eq "Preview") {
+                                @page_locs=$best_loc=$page;
+                        }
+    diff -ur ikiwiki-orig/IkiWiki/Render.pm ikiwiki/IkiWiki/Render.pm
+    --- ikiwiki-orig/IkiWiki/Render.pm  2006-10-27 20:15:17.000000000 -0700
+    +++ ikiwiki/IkiWiki/Render.pm       2006-11-07 22:36:48.000000000 -0800
+    @@ -189,7 +193,7 @@
+                no_chdir => 1,
+                wanted => sub {
+                        $_=decode_utf8($_);
+    -                   if (/$config{wiki_file_prune_regexp}/) {
+    +                   if (is_prune($_)) {
+                                $File::Find::prune=1;
+                        }
+                        elsif (! -d $_ && ! -l $_) {
+    @@ -209,7 +213,7 @@
+                no_chdir => 1,
+                wanted => sub {
+                        $_=decode_utf8($_);
+    -                   if (/$config{wiki_file_prune_regexp}/) {
+    +                   if (is_prune($_, $config{underlaydir})) {
+                                $File::Find::prune=1;
+                        }
+                        elsif (! -d $_ && ! -l $_) {
+    diff -ur ikiwiki-orig/IkiWiki.pm ikiwiki/IkiWiki.pm
+    --- ikiwiki-orig/IkiWiki.pm 2006-10-27 20:15:23.000000000 -0700
+    +++ ikiwiki/IkiWiki.pm      2006-11-07 22:21:17.000000000 -0800
+    @@ -21,6 +21,8 @@
+     # Optimisation.
+     use Memoize;
+     memoize("abs2rel");
+    +memoize("basefile");
+    +memoize("is_prune");
+     memoize("pagespec_translate");
+
+     my $installdir=''; # INSTALLDIR_AUTOREPLACE done by Makefile, DNE
+    @@ -343,6 +352,22 @@
+        return $page;
+     } #}}}
+
+    +sub basefile ($;$) { #{{{
+    +   my $file=shift;
+    +   my $base=shift || $config{srcdir};
+    +
+    +   require File::Spec;
+    +   $base=File::Spec->canonpath($base);
+    +   my $ret=File::Spec->canonpath($file);
+    +
+    +   $ret=~s#^$base/*##;
+    +   return $ret;
+    +} #}}}
+    +
+    +sub is_prune ($;$) { #{{{
+    +   return basefile($_[0], $_[1])=~m/$config{wiki_file_prune_regexp}/;
+    +} #}}}
+    +
+     sub abs2rel ($$) { #{{{
+        # Work around very innefficient behavior in File::Spec if abs2rel
+        # is passed two relative paths. It's much faster if paths are
diff --git a/1.33.2/doc/patchqueue/various_fixes.mdwn b/1.33.2/doc/patchqueue/various_fixes.mdwn
new file mode 100644 (file)
index 0000000..318e7e9
--- /dev/null
@@ -0,0 +1,172 @@
+Sorry if you don't appreciate me lumping all of these patches together.
+
+These are various fixes I had to make when installing Ikiwiki. Some are
+due it being a non-Debian system, the others are actual bugs.
+
+    --- upstream/IkiWiki/Rcs/svn.pm 2006-09-16 01:11:55.000000000 +0100
+    +++ main/IkiWiki/Rcs/svn.pm     2006-09-16 01:12:50.000000000 +0100
+    @@ -34,7 +34,7 @@
+            my $field=shift;
+            my $file=shift;
+    
+    -       my $info=`LANG=C svn info $file`;
+    +       my $info=`svn info $file`;
+            my ($ret)=$info=~/^$field: (.*)$/m;
+            return $ret;
+     } #}}}
+    @@ -140,7 +140,7 @@
+                    if $svn_version =~ /\d\.(\d)\.\d/ && $1 >= 2;
+    
+            my $svn_url=svn_info("URL", $config{srcdir});
+    -       my $xml = XMLin(scalar `svn $svn_limit --xml -v log '$svn_url'`,
+    +       my $xml = XMLin(scalar `svn $svn_limit --xml -v log '$svn_url' --config-dir /tmp`,
+                    ForceArray => [ 'logentry', 'path' ],
+                    GroupTags => { paths => 'path' },
+                    KeyAttr => { path => 'content' },
+
+The first hunk of this patch is strange. It just failed to work with this
+in place, and it took me a long time to figure it out. I realise what you
+are trying to do, and it still works here as I use a similar LANG anyway.
+
+For reference svn version 1.3.1 (r19032), my $LANG=en_GB.utf8, but I'm not 
+sure what the CGI was running under. 
+
+> That's strange. Is the problem to do with setting LANG=C or to do
+> with the way it's set and exported on the same line as the svn info call?
+> Can you reproduce the problem running svn info outside of ikiwiki?
+> --[[Joey]]
+
+>> I've now managed to reproduce the problem. I'll try and give some more information.
+>> When going to the Recent Changes link I get 
+
+    [Sat Sep 16 15:16:08 2006] [error] [client xxxx] svn: Can't check path '/home/jw2328/.subversion': Permission denied, referer: http://xxxxx/test/sandbox.html
+    [Sat Sep 16 15:16:08 2006] [error] [client xxxx] Use of uninitialized value in concatenation (.) or string at /usr/lib/perl5/site_perl/5.8.3/IkiWiki/Rcs/svn.pm line 145., referer: http://xxxx/test/sandbox.html
+    [Sat Sep 16 15:16:08 2006] [error] [client xxxxx] svn: Can't check path '/home/jw2328/.subversion': Permission denied, referer: http://xxxx/test/sandbox.html
+    [Sat Sep 16 15:16:09 2006] [error] [client xxxx] File does not exist:  at /usr/lib/perl5/site_perl/5.8.3/IkiWiki/Rcs/svn.pm line 145, referer: http://xxxx/test/sandbox.html
+    [Sat Sep 16 15:16:09 2006] [error] [client xxxx] Premature end of script headers: ikitest, referer: http://xxxx/test/sandbox.html
+
+>> which the $svn_url is causing the uninitialised value, due to the 
+>> LANG=C it seems, as if I remove it it goes away.
+>> The file does not exist is due to the unreadable .subversion.
+>> echoing the LANG before it is set shows that the variable is normally 
+>> empty for the user that is running it.
+
+The second removes problems with cannot access /home/$user/.svnsomething in
+the logs. I think this problem was also fatal (I should have reported these
+sooner). 
+
+I can try and debug these problems if you could suggest some way to do so, 
+but I am probably losing the server in a couple of days, so I can't be of too
+much help I'm afraid.
+
+> I imagine that passing --config-dir /tmp would be either insecure or 
+> would limit ikiwiki use to one user per machine. 
+> `--config-dir /etc/subversion` might be better, though still a hack,
+> since a user's real ~/.subversion might be needed to access some repos.
+> 
+> Maybe I didn't notice this problem since I have a ~/.subversion
+> everywhere that I've used ikiwiki. Hmm, no, I don't reproduce it, svn
+> happily recreated the directory during an ikiwiki run after I moved it
+> out of the way here. Maybe an issue with old versions of svn? Although
+> AFIACR, svn has auto-created ~/.subversion for years.
+> 
+> What's the error message? --[[Joey]]
+
+>> `svn: Can't check path '/home/jw2328/.subversion': Permission denied,`
+>> where jw2328 is my usual user. 
+>> I have restrictive permissions of 0700 on home dirs on the server,
+>> and the CGI is running as uid apache, euid root. (Not my setup anymore).
+>> The way I had it set up, was jw2328 owning thesource dir, and the svn repo,
+>> with g+sw on them both. I ran sudo ikiwiki --setup though, as I was reluctant
+>> to adjust permissions on my cgi-dir. This seems to be the root of the 
+>> problem.
+
+>>> Ah, I think it's better to keep the permissions of the repository
+>>> and source directory sane (755) and make the cgi suid to your user,
+>>> which is how it's designed to work.
+
+>>>> I realise that now, and I now have a much more sane setup that works.
+
+----
+
+    --- IkiWiki.pm
+    +++ IkiWiki.pm
+    @@ -734,7 +734,18 @@
+            my $page=shift;
+            my $spec=shift;
+    
+    -       return eval pagespec_translate($spec);
+    +        my $pagespec = pagespec_translate($spec);
+    +
+    +        my $newpagespec;
+    +
+    +       local($1);
+    +       if ($pagespec =~ /(.*)/) {
+    +               $newpagespec = $1;
+    +       } else {
+    +               die "oh";
+    +       }
+    +
+    +       return eval $newpagespec;
+     } #}}}
+    
+     sub match_glob ($$) { #{{{
+
+This works around a silly, but extremely annoying, taint bug in older
+versions of perl. I'm not sure of the details, but it means that either
+values become tainted from nowhere, or they don't get untainted possibly.
+This also affects backports to sarge. `"oh"` is not going to be very 
+informative if that code path is ever taken, but I hope that it never is.
+
+> You're not the first person to report a problem here with older versions 
+> of perl and pagespec tainting. I suspect that this would work around it:
+       return eval possibly_foolish_untaint(pagespec_translate($spec));
+> I'm _very_ uncomfortable putting that in the shipping version of ikiwiki,
+> because pagespecs are potentially _insanely_ dangerous, given how they're
+> evaled and all. The tainting is the only sanity check there is that
+> `pagespec_translate` manages to clean up any possibly harmful perl code
+> in a pagespec. It's good to have belt and suspenders here. 
+> 
+> For all I know, older versions of perl are keeping it tainted because
+> `pagespec_translate` is somehow broken under old versions of perl and is
+> in fact not fully untainting the pagespec. Ok, probably not, it's more
+> likely that some of the regexps in there don't manage to clear the taint
+> flag with old versions of perl, while still doing a perfectly ok job of
+> sanitising the pagespec.
+> 
+> I suppose that the version of perl ($^V) could be checked and the untaint 
+> only be called for the old version. Though it seems it would be better
+> to try to debug this some first. Maybe instrumenting `pagespec_translate`
+> with calls to Scalar::Utils's tainted() function and seeing which parts
+> of pagespecs arn't getting untainted would be a good start.
+> 
+> --[[Joey]]
+
+>> It seems like it is always the (with instrumentation)
+     
+     elsif ($word =~ /^(link|backlink|created_before|created_after|creation_month|creation_year|creation_day)\((.+)\)$/) {
+          warn("\$1 tainted=".tainted($1).", \$2 tainted=".tainted($2)." \$code tainted=".tainted($code));
+          $code.=" match_$1(\$page, ".safequote($2).")";
+          warn("\$1 tainted=".tainted($1).", \$2 tainted=".tainted($2)." \$code tainted=".tainted($code));
+          warn("safequote tainted=".tainted(safequote($2)));
+     }
+
+>> bit that causes it. With the following trace:
+
+     $1 tainted=0, $2 tainted=0 $code tainted=0 at IkiWiki.pm line 718.
+     $1 tainted=0, $2 tainted=0 $code tainted=1 at IkiWiki.pm line 720.
+     safequote tainted=0 at IkiWiki.pm line 721.
+
+>> which shows that `$code` appears to become tainted from nowhere.
+>> <http://mail-archives.apache.org/mod_mbox/spamassassin-dev/200509.mbox/%3C3838.431C7D9B.5F152B8F.dev@spamassassin.apache.org%3E>
+>> is what pointed me to find the problem/workaround.
+
+>>> Given that verification, an untaint contingent on the value of $^V
+>>> sounds reasonable and I'd accept such a patch. I'm not quite sure which
+>>> version(s) of perl it should check for.
+
+>>>> I'm not going to write one though. I don't know what versions either,
+>>>> but I think the evil of the special case is too much in this case. If
+>>>> you are happy to insist on a newer version of perl then I will leave 
+>>>> it at that and sort something out locally. If you want the patch I will 
+>>>> code it though, as I realise you may want to support sarge installs.
diff --git a/1.33.2/doc/plugins.mdwn b/1.33.2/doc/plugins.mdwn
new file mode 100644 (file)
index 0000000..45e380d
--- /dev/null
@@ -0,0 +1,27 @@
+Most of ikiwiki's [[features]] are implemented as plugins. Beyond the
+[[type/core]] features, there are plugins to [[type/format]] text,
+use [[type/tags]], show [[type/meta]] information, do other [[type/useful]]
+stuff, add [[type/chrome]] to the wiki, or just have [[type/fun]].
+
+There's documentation if you want to [[write]] your own plugins, or you can
+install and use plugins contributed by others. 
+
+The [[mdwn]], [[inline]], and [[htmlscrubber]] plugins are enabled by default.
+To enable other plugins, use the `--plugin` switch described in [[usage]],
+or the equivalent `add_plugins` line in [[ikiwiki.setup]].
+
+# Plugin directory
+
+Add all plugins here. Or add ideas to the [[todo|todo/plugin]] page.
+
+[[inline pages="plugins/* and !plugins/type/* and !plugins/write and !plugins/contrib and !*/Discussion" archive="yes" rootpage="plugins/contrib"]]
+
+# Installing third party plugins
+
+Plugins are perl modules and should be installed somewhere in the perl
+module search path. See the @INC list at the end of the output of `perl -V`
+for a list of the directories in that path. All plugins are in the
+IkiWiki::Plugin namespace, so they go in a IkiWiki/Plugin subdirectory
+inside the perl search path. For example, if your perl looks in
+`/usr/local/lib/site_perl` for modules, you can locally install ikiwiki
+plugins to `/usr/local/lib/site_perl/IkiWiki/Plugin`
diff --git a/1.33.2/doc/plugins/aggregate.mdwn b/1.33.2/doc/plugins/aggregate.mdwn
new file mode 100644 (file)
index 0000000..a3ef105
--- /dev/null
@@ -0,0 +1,57 @@
+[[template id=plugin name=aggregate included=1 author="[[Joey]]"]]
+[[tag type/useful]]
+
+This plugin allows content from other feeds to be aggregated into the wiki.
+Aggregate a feed as follows
+
+       \[[aggregate name="example blog"
+       feedurl="http://example.com/index.rss"
+       url="http://example.com/" updateinterval="15"]]
+
+That example aggregates posts from the expecified RSS feed, updating no
+more frequently than once every 15 minutes, and puts a page per post under
+the example/ directory in the wiki.
+
+You can then use ikiwiki's [[blog]] support to create a blog of one or more
+aggregated feeds.
+
+## setup
+
+Make sure that you have the [[html]] plugin enabled, as the created pages are
+in html format. The [[meta]] and [[tag]] plugins are also recommended. The
+[[htmltidy]] plugin is suggested, since feeds can easily contain html
+problems, some of which tidy can fix.
+
+You will need to run ikiwiki periodically from a cron job, passing it the
+--aggregate parameter, to make it check for new posts. Here's an example
+crontab entry:
+
+       */15 * * * * ikiwiki --setup my.wiki --aggregate --refresh
+
+## usage
+
+Here are descriptions of all the supported parameters to the `aggregate`
+directive:
+
+* `name` - A name for the feed. Each feed must have a unique name.
+  Required.
+* `url` - The url to the web page for the feed that's being aggregated.
+  Required.
+* `dir` - The directory in the wiki where pages should be saved. Optional,
+  if not specified, the directory is based on the name of the feed.
+* `feedurl` - The url to the feed. Optional, if it's not specified ikiwiki
+  will look for feeds on the `url`. RSS and atom feeds are supported.
+* `updateinterval` - How often to check for new posts, in minutes. Default
+  is 15 minutes.
+* `expireage` - Expire old items from this feed if they are older than
+  a specified number of days. Default is to never expire on age.
+* `expirecount` - Expire old items from this feed if there are more than
+  the specified number total. Oldest items will be expired first. Default
+  is to never expire on count.
+* `tag` - A tag to tag each post from the feed with. A good tag to use is
+  the name of the feed. Can be repeated multiple times. The [[tag]] plugin
+  must be enabled for this to work.
+
+Note that even if you are using subversion or another revision control
+system, pages created by aggregation will *not* be checked into revision
+control.
diff --git a/1.33.2/doc/plugins/brokenlinks.mdwn b/1.33.2/doc/plugins/brokenlinks.mdwn
new file mode 100644 (file)
index 0000000..b9a8296
--- /dev/null
@@ -0,0 +1,13 @@
+[[template id=plugin name=brokenlinks included=1 author="[[Joey]]"]]
+[[tag type/link type/meta]]
+
+This plugin generates a list of broken links on pages in the wiki. This is
+a useful way to find pages that still need to be written, or links that
+are written wrong.
+
+The optional parameter "pages" can be a [[PageSpec]] specifying the pages
+to search for broken links, default is search them all.
+
+If this plugin is turned on, here's a list of broken links on this wiki:
+
+[[brokenlinks ]]
diff --git a/1.33.2/doc/plugins/camelcase.mdwn b/1.33.2/doc/plugins/camelcase.mdwn
new file mode 100644 (file)
index 0000000..fd05ac7
--- /dev/null
@@ -0,0 +1,9 @@
+[[template id=plugin name=camelcase included=1 author="[[Joey]]"]]
+
+This plugin makes words in CamelCase be treated as a [[WikiLink]]. That is
+to say, any two or more words capitalised and mashed together are assumed
+to be the name of some other page on the wiki, and so become a link.
+
+If this plugin is enabled, here is a link: SandBox
+
+[[tag type/link]]
diff --git a/1.33.2/doc/plugins/contrib.mdwn b/1.33.2/doc/plugins/contrib.mdwn
new file mode 100644 (file)
index 0000000..939d7da
--- /dev/null
@@ -0,0 +1,3 @@
+Contributed [[plugins]]:
+
+[[inline pages="plugins/contrib/* !*/Discussion" archive="yes" rootpage="contrib" show="60"]]
diff --git a/1.33.2/doc/plugins/contrib/googlemaps.mdwn b/1.33.2/doc/plugins/contrib/googlemaps.mdwn
new file mode 100644 (file)
index 0000000..30f630a
--- /dev/null
@@ -0,0 +1,20 @@
+[[template id=plugin name=googlemaps author="Christian Mock"]]
+[[tag type/special-purpose]]
+[[meta title="googlemaps (third-party plugin)"]]
+
+`googlemaps` is a plugin that allows using the [Google Maps API][2]
+from ikiwiki.
+
+[2]: http://www.google.com/apis/maps/
+
+The plugin supports importing GPS tracks from [gpx][1] files, reducing
+the number of points in those tracks via [gpsbabel][2], and drawing
+them as an overlay on the map. the center of the map and zoom level
+can be calculated automatically.
+
+[1]: http://www.topografix.com/gpx.asp
+[2]: http://www.gpsbabel.org/
+
+It can be [found here][3].
+
+[3]: http://www.tahina.priv.at/hacks/googlemaps.html
diff --git a/1.33.2/doc/plugins/contrib/googlemaps/discussion.mdwn b/1.33.2/doc/plugins/contrib/googlemaps/discussion.mdwn
new file mode 100644 (file)
index 0000000..7518110
--- /dev/null
@@ -0,0 +1,8 @@
+Very neat. The warnings about it not being very secure are of course spot on.
+Seems that the need to embed the api key on the page is a security problem of one sort. 
+
+The call to gpsbabel _seems_ secure thanks to the sanitisation done to the filename passed to gpsbabel.
+
+I probably won't ever add this to ikiwiki, but it's a great third-party plugin!
+
+--[[Joey]]
\ No newline at end of file
diff --git a/1.33.2/doc/plugins/contrib/img.mdwn b/1.33.2/doc/plugins/contrib/img.mdwn
new file mode 100644 (file)
index 0000000..43c5025
--- /dev/null
@@ -0,0 +1,15 @@
+[[template id=plugin name=img author="Christian Mock"]]
+[[tag type/chrome]]
+[[meta title="img (third-party plugin)"]]
+
+`img` is an enhanced image handling plugin.
+
+the intention is to make image handling as easy as possible, so the
+plugin can scale down images for direct inclusion into the page,
+providing a link to one or more larger or full-size versions on their
+own page. `width` and `height` attributes are included in the `<img>`
+tag, and `alt` text can be specified.
+
+the plugin uses the ImageMagick tools via PerlMagick.
+
+it can be found [here](http://www.tahina.priv.at/hacks/img.html).
diff --git a/1.33.2/doc/plugins/contrib/img/discussion.mdwn b/1.33.2/doc/plugins/contrib/img/discussion.mdwn
new file mode 100644 (file)
index 0000000..d4b38fb
--- /dev/null
@@ -0,0 +1,51 @@
+This is a good idea, I was just the other day stuck writing ugly html to
+properly size an image for a blog post. Putting the image sizing support
+into a plugin instead of trying to shoehorn it into a wikilink seems like
+the way to go.
+
+I have two issues with this plugin as it's implemented now, the first is
+that the generation of whole pages containing a scaled version of the image
+seems gratuituous, as well as buggy. If you want three pages with
+differently scaled versions of the image, why not just create three pages
+and use the plugin once per page? Something like this on the first one if
+it's got multiple clickable thumbnails:
+
+       \[[img foo.jpg width=256 link=page2]]
+
+This on the second:
+
+       \[[img foo.jpg width=1024 link=page3]]
+       \[[small|page1]]
+       \[[medium|page2]]
+       \[[large|page3]]
+
+This on the third:
+       
+       \[[img foo.jpg link=page3]]
+       \[[small|page1]]
+       \[[medium|page2]]
+       \[[large|parge3]]
+
+Granted, this is more work, but it's more flexible too, and it doesn't have
+it creating new pages on the fly, which I don't personally like..
+
+----
+
+The second issue is whether it should use imagemagick to scale the image
+and generate a new scaled one, or just emit html that sets the sizes of the
+image. Benefits to scaling:
+
+1. Saves download time and bandwidth, especially if generating a page with a
+   lot of thumbnails of large images.
+
+Benefits of not scaling:
+
+1. Avoids any security issues with imagemagick.
+2. Avoids issue of how to clean up old scaled images that are no longer being
+   used. (Granted, this is a general ikiwiki problem that will eventually
+   be fixed in a general way. (Update: now fixed in a general way, use the
+   will_render function.))
+3. Makes clicking on thumbnails display the full version really fast, since
+   it's cached. :-)
+
+--[[Joey]]
diff --git a/1.33.2/doc/plugins/contrib/linguas.mdwn b/1.33.2/doc/plugins/contrib/linguas.mdwn
new file mode 100644 (file)
index 0000000..7778bf4
--- /dev/null
@@ -0,0 +1,98 @@
+[[template id=plugin name=linguas author="Jordà Polo"]]
+[[meta title="linguas (third-party plugin)"]]
+
+Linguas
+=======
+
+Linguas is a plugin for [ikiwiki](http://ikiwiki.kitenet.net/) that
+allows translations of wiki pages.
+
+Download: [linguas.pm](http://wiki.ettin.org/files/linguas.pm) (2006-08-21).
+
+Usage
+-----
+
+Translatable pages and translations must have the following format:
+`pagename.$LANG`, where `$LANG` is a ISO639-1 (two-letter) language code.
+To enable linguas, add the following line in the source code of the page:
+
+       \[[linguas ]]
+
+Note that linguas is only required in one of the pages (the original,
+for instance); the rest of translations will be automatically
+updated. Additionally, it is also possible to specify the title of
+the translation:
+
+       \[[linguas title="Translated title"]]
+
+
+Template
+--------
+
+This is the template code that should be added to `templates/page.tmpl`:
+
+       <TMPL_IF NAME="LINGUAS">
+       <div id="linguas">
+       <p class="otherlinguas"><TMPL_VAR NAME="OTHERLINGUAS"></p>
+       <ul>
+       <TMPL_LOOP NAME="LINGUAS">
+       <li><TMPL_VAR NAME=LINK></li>
+       </TMPL_LOOP>
+       </ul>
+       </div>
+       </TMPL_IF>
+
+
+TODO/Known Problems
+-------------------
+
+* The current language list only contains 4 languages (ca, de, en,
+es), and is "hardcoded" in linguas.pm. Would be interesting to define
+it in ikiwiki.setup, though some problems were found while trying to do
+so. (Actually, defining hash-like arguments from the command like works
+fine, but it fails from ikiwiki.setup.)
+
+  > My guess about this is that it's because of the way Setup/Standard.pm
+  > untaints the config items from the file. It has code to handle arrays,
+  > but not hashes or more complex data structures. --[[Joey]]
+
+  >  > Right. With this simple
+  >  > [patch](http://wiki.ettin.org/files/hash_setup.patch) it seems to
+  >  > work. However, note that 1) it only allows simple hashes, hashes of
+  >  > hashes will not work (I don't think getops can handle complex hashes
+  >  > anyway); 2) I don't really know when/why you call
+  >  > `possibly_foolish_untaint()`; and 3) I'm no perl guru ;). --Jordà
+
+  >  >  > It's good. Applied..
+
+* Wiki links to other translated pages require the full page name
+including the `.$LANG`. It should be possible to link automatically
+to pages with the same `.$LANG`, but that would probably require some
+changes in IkiWiki. (I'm not sure though, I still haven't looked at
+it... any hints?)
+
+  > Have you considered using the form ll/page? This would let more usual
+  > linking rules  apply amoung pages without needing to specify the
+  > language. I'm not sure if you're supporting browser content
+  > negotiation, or whether that other layout would be harder to support it
+  > though. --[[Joey]]
+
+  >  > Actually, I'm happy with the way it works now (and yeah, it is very
+  >  > easy to take advantage of content negotiation). I just wanted
+  >  > something simple to translatte a single page (or a few pages), not
+  >  > the entire wiki. I'm not even sure it is a good idea to have fully
+  >  > multilingual wikis, in most cases I would go for a different wiki
+  >  > for each language. That said, I think it is an interesting idea, so
+  >  > I'll take a look when I have the time. Thanks for your comments.
+  >  > --Jordà
+
+Examples
+--------
+
+* [Linguas](http://wiki.ettin.org/linguas.en.html). A page with the same
+content than this one.
+
+* [Hello in some languages](http://wiki.ettin.org/hello/hello.en.html). The
+translations were taken from [Hello in many
+languages](http://www.omniglot.com/language/phrases/hello.htm) and from
+the [Debian](http://www.debian.org/) website.
diff --git a/1.33.2/doc/plugins/contrib/syntax.mdwn b/1.33.2/doc/plugins/contrib/syntax.mdwn
new file mode 100644 (file)
index 0000000..3aed3d4
--- /dev/null
@@ -0,0 +1,65 @@
+[[template id=plugin name=syntax author="[[VictorMoral]]"]]
+[[tag type/chrome type/slow]]
+[[meta title="syntax (third-party plugin)"]]
+
+
+`syntax` is a plugin that add support to ikiwiki for syntax highlighting through the *vim* editor and its perl interface [[cpan Text::VimColor]], so it depends on a vim functional installation.
+
+The plugin inserts a fragment of HTML with special marks from a file or a string text. It accepts the following parameters:
+
+* **type** (optional): this is the file type for vim syntax highlighthing. It can be omitted if the param *file* exists.
+* **file**: Path to the source file. It must exist on every rebuild of the wiki.
+* **text**: Text string with the source.
+* **description** (optional): little description about the content.
+* **linenumbers** (optional): enable the line numering of the source page. A value greater than zero is the first line number.
+
+The params *file* and *text* are mutually exclusive.
+
+In the case of file parameter, `syntax` will build a html link for direct download.
+
+Example:
+
+       \[[syntax type="perl" text="""  
+       #!/usr/bin/perl
+
+       my $a = "World";
+       print "Hello, ${a}\n";
+       """]]
+
+or 
+
+       \[[syntax file="/examples/hello.pl" description="My first perl program"]]
+
+This plugin create the following CSS styles:
+
+* syntax
+* synComment
+* synConstant
+* syncIdentifier
+* synPreProc
+* synType
+* synSpecial
+* synUnderlined
+* synError
+* synTodo
+* synTitle
+
+It can be downloaded from [here](http://taquiones.net/files/misc/) or through my personal debian repository at <http://taquiones.net/files/debian/>. There is a page with examples: <http://taquiones.net/software/syntax-examples.html>
+
+Any help, comments or critics are welcome at <victor@taquiones.net>.
+
+## version 0.9
+
+- Add a force_subpage parameter for link build
+- Fix a bug in syntax page link
+- Documented a bug with markdown indented text
+- Documented the syntax directive
+
+## version 0.7
+
+- Version change to GPL
+- Add *linenumbers* parameter
+- The *file* parameter should be point to a ikiwiki source page. 
+- The *description* parameter will be converted on a URL if the *file* parameter exist.
+
+I need help for debugging this module. Thanks in advance.
diff --git a/1.33.2/doc/plugins/contrib/syntax/discussion.mdwn b/1.33.2/doc/plugins/contrib/syntax/discussion.mdwn
new file mode 100644 (file)
index 0000000..af6c07a
--- /dev/null
@@ -0,0 +1,23 @@
+I'd like to include this in ikiwiki. Using vim for syntax highlighting is
+suprising to me, but it seems to work great. Would it be possible to
+license it the same as the rest of ikiwiki (GPL) instead of dragging in the
+perl license?
+
+> Yes, no problem. I'm writing the next version. --[[VictorMoral]]
+
+Text::VimColor will need to be added to Debian..
+
+It looks to me like the file parameter is a security hole, since it allows
+inclusion of arbitrary files into the wiki, including ones outside of the
+wiki source tree. I think this option should either be removed, or be
+limited to reading files inside the wiki source tree. If it's retained it
+should also add an appropriate dependency on the included file.
+
+> You are right, Joey. I didn't think on it because i don't use the cgi mode. :-) I'm working on it. --[[VictorMoral]]
+
+--[[Joey]]
+
+> It looks like the author of Text::VimColor has already made a Debian package.  I've 
+> contacted him, but no answer back yet.  --[[Roktas]]
+
+>>Meanwhile i've got a debian package for Text::VimColor [in my repository](http://taquiones.net/files/debian/). --[[VictorMoral]]
diff --git a/1.33.2/doc/plugins/ddate.mdwn b/1.33.2/doc/plugins/ddate.mdwn
new file mode 100644 (file)
index 0000000..c35afe4
--- /dev/null
@@ -0,0 +1,8 @@
+[[template id=plugin name=ddate included=1 author="[[Joey]]"]]
+[[tag type/fun]]
+
+Enables use of Discordian dates. `--timeformat` can be used to change
+the date format; see `ddate(1)`.
+
+This plugin requires the DateTime and DateTime::Calendar::Discordian
+perl modules.
diff --git a/1.33.2/doc/plugins/favicon.mdwn b/1.33.2/doc/plugins/favicon.mdwn
new file mode 100644 (file)
index 0000000..2973c94
--- /dev/null
@@ -0,0 +1,7 @@
+[[template id=plugin name=favicon included=1 author="[[Joey]]"]]
+[[tag type/chrome]]
+
+If this plugin is enabled, then an icon link is added to pages, for web
+browsers to display. The icon is currently hardcoded to be a favicon.ico,
+which must be in the root of the wiki. The [[logo]] page explains how this
+icon was generated.
diff --git a/1.33.2/doc/plugins/fortune.mdwn b/1.33.2/doc/plugins/fortune.mdwn
new file mode 100644 (file)
index 0000000..93bc4bd
--- /dev/null
@@ -0,0 +1,13 @@
+[[template id=plugin name=fortune included=1 author="[[Joey]]"]]
+[[tag type/fun]]
+
+This just uses the `fortune` program to insert a fortune into the page.
+Usage:
+
+       \[[fortune ]]
+
+If this plugin is enabled, here's a fortune for you:
+
+----
+
+[[fortune ]]
diff --git a/1.33.2/doc/plugins/googlecalendar.mdwn b/1.33.2/doc/plugins/googlecalendar.mdwn
new file mode 100644 (file)
index 0000000..59a4e6e
--- /dev/null
@@ -0,0 +1,18 @@
+[[template id=plugin name=linkmap included=1 author="Joey Hess"]]
+[[tag type/special-purpose]]
+
+This plugin allows embedding a google calendar iframe in the wiki.
+Normally, if the [[htmlscrubber]] is enabled, such iframes are scrubbed out
+of the wiki content since they're not very safe if created by malicious
+users. But some iframes are legitimate, and safe, if you trust the embedded
+content. This plugin is an example of how to deal with this in ikiwiki.
+
+Example use:
+
+       \[[googlecalendar html="""
+       <iframe src="http://www.google.com/calendar/embed?src=adkrdken8mupngh13jshlbenoc%40group.calendar.google.com&title=OSEL%20Calendar&chrome=NAVIGATION&bgcolor=%2371d873&height=588" style=" border-width:0 " width="480" frameborder="0" height="588"></iframe>
+       """]]
+
+The iframe should be the one provided by google. Note that it's used in a
+way that avoids cross-site scripting attacks, assuming you trust google's
+content.
diff --git a/1.33.2/doc/plugins/haiku.mdwn b/1.33.2/doc/plugins/haiku.mdwn
new file mode 100644 (file)
index 0000000..330e936
--- /dev/null
@@ -0,0 +1,20 @@
+[[template id=plugin name=haiku included=1 author="[[Joey]]"]]
+[[tag type/fun]]
+
+This plugin allows inserting a randomly generated haiku into a wiki page.
+Just type:
+
+       \[[haiku hint="argument"]]
+
+[[haiku hint="argument test"]]
+
+The hint parameter can be omitted, it only provides the generator a hint of
+what to write the haiku about. If no hint is given, it might base it on the
+page name. Since the vocabulary it knows is very small, many hints won't
+affect the result at all.
+
+As a special bonus, enabling this plugin makes any error messages ikiwiki
+should display be written in haiku.
+
+You need to have the Coy module installed for this plugin to do anything
+interesting. That does all the heavy lifting.
diff --git a/1.33.2/doc/plugins/html.mdwn b/1.33.2/doc/plugins/html.mdwn
new file mode 100644 (file)
index 0000000..4351ecd
--- /dev/null
@@ -0,0 +1,11 @@
+[[template id=plugin name=html included=1 author="[[Joey]]"]]
+[[tag type/html type/format]]
+
+This plugin lets raw html pages be used as source pages for the wiki. The
+html pages will still be wrapped in the same html template as any other
+page, so for best results you should include only the page body in the html
+file. Also, if the htmlscrubber plugin is enabled, the html pages will be
+sanitised like any other page. You can also use standard [[WikiLink]]s etc
+in the html pages.
+
+This plugin is included in ikiwiki, but is not enabled by default.
diff --git a/1.33.2/doc/plugins/htmlscrubber.mdwn b/1.33.2/doc/plugins/htmlscrubber.mdwn
new file mode 100644 (file)
index 0000000..e3652a8
--- /dev/null
@@ -0,0 +1,34 @@
+[[template id=plugin name=htmlscrubber core=1 included=1
+author="[[Joey]]"]]
+[[tag type/html type/core]]
+
+This plugin is enabled by default. It sanitizes the html on pages it renders
+to avoid XSS attacks and the like.
+
+It excludes all html tags and attributes except for those that are
+whitelisted using the same lists as used by Mark Pilgrim's Universal Feed
+Parser, documented at <http://feedparser.org/docs/html-sanitization.html>.
+Notably it strips `style`, `link`, and the `style` attribute.
+
+It uses the HTML::Scrubber perl module to perform its html
+sanitisation, and this perl module also deals with various entity encoding
+tricks.
+
+While I believe that this makes ikiwiki as resistant to malicious html
+content as anything else on the web, I cannot guarantee that it will
+actually protect every user of every browser from every browser security
+hole, badly designed feature, etc. I can provide NO WARRANTY, like it says
+in ikiwiki's [GPL](GPL) license. 
+
+The web's security model is *fundamentally broken*; ikiwiki's html
+sanitisation is only a patch on the underlying gaping hole that is your web
+browser.
+
+----
+
+Some examples of embedded javascript that won't be let through when this
+plugin is active:
+
+* <span style="background: url(javascript:window.location='http://example.org/')">test</span>
+* <span style="&#x61;&#x6e;&#x79;&#x3a;&#x20;&#x65;&#x78;&#x70;&#x72;&#x65;&#x73;&#x73;&#x69;&#x6f;&#x6e;&#x28;&#x77;&#x69;&#x6e;&#x64;&#x6f;&#x77;&#x2e;&#x6c;&#x6f;&#x63;&#x61;&#x74;&#x69;&#x6f;&#x6e;&#x3d;&#x27;&#x68;&#x74;&#x74;&#x70;&#x3a;&#x2f;&#x2f;&#x65;&#x78;&#x61;&#x6d;&#x70;&#x6c;&#x65;&#x2e;&#x6f;&#x72;&#x67;&#x2f;&#x27;&#x29;">test</span>
+* <span style="&#97;&#110;&#121;&#58;&#32;&#101;&#120;&#112;&#114;&#101;&#115;&#115;&#105;&#111;&#110;&#40;&#119;&#105;&#110;&#100;&#111;&#119;&#46;&#108;&#111;&#99;&#97;&#116;&#105;&#111;&#110;&#61;&#39;&#104;&#116;&#116;&#112;&#58;&#47;&#47;&#101;&#120;&#97;&#109;&#112;&#108;&#101;&#46;&#111;&#114;&#103;&#47;&#39;&#41;">test</span>
diff --git a/1.33.2/doc/plugins/htmltidy.mdwn b/1.33.2/doc/plugins/htmltidy.mdwn
new file mode 100644 (file)
index 0000000..7079a7f
--- /dev/null
@@ -0,0 +1,10 @@
+[[template id=plugin name=htmltidy included=1 author="Faidon Liambotis"]]
+[[tag type/html]]
+[[tag type/slow]]
+
+This plugin uses [tidy](http://tidy.sourceforge.net/) to tidy up the html
+emitted by ikiwiki. Besides being nicely formatted, this helps ensure that
+even if users enter suboptimal html, your wiki generates valid html.
+
+Note that since tidy is an external program, that is run each time a page
+is built, this plugin will slow ikiwiki down somewhat.
diff --git a/1.33.2/doc/plugins/img.mdwn b/1.33.2/doc/plugins/img.mdwn
new file mode 100644 (file)
index 0000000..324d46c
--- /dev/null
@@ -0,0 +1,30 @@
+[[template id=plugin name=img included=1 author="Christian Mock" ]]
+[[tag type/chrome]]
+
+This is an image handling plugin. While ikiwiki supports inlining full-size
+images by making a [[WikiLink]] that points to the image, using this plugin
+you can easily scale down an image for inclusion onto a page, providing a
+link to a full-size version.
+
+This plugin uses the [ImageMagick](http://www.imagemagick.org/) tools via
+[PerlMagick](http://www.imagemagick.org/www/perl-magick.html).
+
+Note that this is a stripped down version of Christian Mock's
+[[original_img_plugin|contrib/img]].
+
+## usage
+
+       \[[img image1.jpg size="200x200" alt="clouds"]]
+
+The `alt` parameter is optional. The `size` parameter is also optional,
+defaulting to full size. Note that the original image's aspect ratio is
+always preserved, even if this means making the image smaller than the
+specified size.
+
+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.
+
+       \[[img defaults size=200x200 alt="wedding photo"]]
+       \[[img photo1.jpg]]
+       \[[img photo2.jpg]]
+       \[[img photo3.jpg size=200x600]]
diff --git a/1.33.2/doc/plugins/inline.mdwn b/1.33.2/doc/plugins/inline.mdwn
new file mode 100644 (file)
index 0000000..3c3d46d
--- /dev/null
@@ -0,0 +1,42 @@
+[[template id=plugin name=inline core=1 included=1 author="[[Joey]]"]]
+[[tag type/core]]
+
+This is a [[PreProcessorDirective]] that allows including one wiki page
+inside another. For example:
+
+       \[[inline pages="blog/*"]]
+
+The most common use of inlining is generating blogs and RSS or Atom feeds.
+See [[blog]] for details.
+
+## usage
+
+Here are descriptions of all the supported parameters to the `inline`
+directive:
+
+* `pages` - A [[PageSpec]] of the pages to inline.
+* `show` - Specify the maximum number of matching pages to inline.
+  Default is 10, unless archiving, when the default is to show all.
+  Set to 0 to show all matching pages.
+* `skip` - Specify a number of pages to skip displaying. Can be useful
+  to produce a feed that only shows archived pages.
+* `rss` - controls generation of an rss feed. On by default if the wiki is
+  configured to use rss feeds, set to "no" to disable.
+* `atom` - controls generation of an atom feed. On by default if the wiki is
+  configured to use atom feeds, set to "no" to disable.
+* `feeds` - controls generation of all types of feeds. Set to "no" to
+  disable generating any feeds.
+* `rootpage` - Enables a form to post new pages to a [[blog]].
+* `archive` - If set to "yes", only list page titles and some metadata, not
+  full controls.
+* `raw` - Rather than the default behavior of creating a [[blog]],
+  if raw is set to "yes", the page will be included raw, without additional
+  markup around it, as if it were a literal part of the source of the 
+  inlining page.
+* `description` - Sets the description of the rss feed if one is generated.
+  Defaults to the name of the wiki.
+* `actions` - If set to "yes" add links to the bottom of the inlined pages 
+  for editing and discussion (if they would be shown at the top of the page
+  itself).
+* `sort` - Controls how inlined pages are sorted. The default, "age" is to
+  sort newest pages first. Setting it to "title" will sort pages by title.
diff --git a/1.33.2/doc/plugins/linkmap.mdwn b/1.33.2/doc/plugins/linkmap.mdwn
new file mode 100644 (file)
index 0000000..e0eda92
--- /dev/null
@@ -0,0 +1,30 @@
+[[template id=plugin name=linkmap included=1 author="Joey Hess"]]
+[[tag type/meta]]
+[[tag type/slow]]
+This plugin uses [graphviz](http://www.graphviz.org/) to generate a graph showing the links between a
+set of pages in the wiki. Example usage:
+
+       \[[linkmap pages="* and !blog/* and !*/Discussion"]]
+
+Only links between mapped pages will be shown; links pointing to or from
+unmapped pages will be omitted. If the pages to include are not specified,
+the links between all pages (and other files) in the wiki are mapped. For
+best results, only a small set of pages should be mapped, since otherwise
+the map can become very large, unweildy, and complicated. Also, the map is
+rebuilt whenever one of the mapped pages is changed, which can make the
+wiki a bit slow.
+
+Here are descriptions of all the supported parameters to the `linkmap`
+directive:
+
+* `pages` - A [[PageSpec]] of the pages to map.
+* `height`, `width` - Limit the size of the map to a given height and width,
+  in inches. Both must be specified for the limiting to take effect, otherwise
+  the map's size is not limited.
+
+This plugin is included in ikiwiki, but is not enabled by default.
+
+If this plugin is enabled, here is a link map of the index page and all
+pages it links to:
+
+[[linkmap pages="index or (backlink(index) and !*.png)"]]
diff --git a/1.33.2/doc/plugins/map.mdwn b/1.33.2/doc/plugins/map.mdwn
new file mode 100644 (file)
index 0000000..01f61e5
--- /dev/null
@@ -0,0 +1,20 @@
+[[template id=plugin name=map included=1 author="Alessandro Dotti Contra"]]
+[[tag type/meta]]
+
+This plugin generates a hierarchical page map for the wiki. Example usage:
+
+       \[[map pages="* and !blog/* and !*/Discussion"]]
+
+If the pages to include are not specified, all pages (and other files) in
+the wiki are mapped.
+
+Hint: To limit the map to displaying pages less than a certian level deep,
+use a [[PageSpec]] like this: `pages="* and !*/*/*"`
+
+This plugin is included in ikiwiki, but is not enabled by default.
+It was contributed by Alessandro Dotti Contra.
+
+If this plugin is enabled, here is a page map for the plugins section
+of this wiki:
+
+[[map pages="(plugins or plugins/*) and !*/*/*"]]
diff --git a/1.33.2/doc/plugins/mdwn.mdwn b/1.33.2/doc/plugins/mdwn.mdwn
new file mode 100644 (file)
index 0000000..c5b6968
--- /dev/null
@@ -0,0 +1,8 @@
+[[template id=plugin name=mdwn core=1 included=1 author="[[Joey]]"]]
+[[tag type/format type/core]]
+
+This plugin lets ikwiki convert files with names ending in ".mdwn" to html.
+It uses the [[markdown]] minimal markup language.
+
+This is the standard markup language used by ikiwiki, although some others
+are also available in other plugins.
diff --git a/1.33.2/doc/plugins/meta.mdwn b/1.33.2/doc/plugins/meta.mdwn
new file mode 100644 (file)
index 0000000..f30efb8
--- /dev/null
@@ -0,0 +1,59 @@
+[[template id=plugin name=meta included=1 author="[[Joey]]"]]
+[[tag type/meta]]
+
+This plugin allows inserting arbitrary metadata into the source of a page.
+Enter the metadata as follows:
+
+       \[[meta field="value"]]
+       \[[meta field="value" param="value" param="value"]]
+
+The first form sets a given field to a given value, while the second form
+also specifies some additional sub-parameters.
+
+You can use any field names you like, but here are some predefined ones:
+
+* link
+
+  Specifies a link to another page. This is used to generate a html
+  &lt;link&gt; tag, and also as a way to make the wiki treat one page as
+  linking to another without displaying a user-visible link. The latter 
+  can be useful when using links to categorise pages. A html link tag
+  would look like this:
+
+       \[[meta link="foo.css" rel="stylesheet" type="text/css"]]
+
+  A non-user-visible [[WikiLink]] would instead look like this:
+
+       \[[meta link=otherpage]]
+
+* title
+
+  Overrides the title of the page, which is generally the same as the
+  page name.
+
+  Note that if the title is overrideen, a "title_overridden" variable will
+  be set to a true value in the template; this can be used to format things
+  differently in this case.
+
+* license
+
+  Specifies a copyright license for the page, for example, "GPL".
+
+* author
+
+  Specifies the author of a page.
+
+* permalink
+
+  Specifies a permanent link to the page, if different than the page
+  generated by ikiwiki.
+
+If the field is not treated specially (as the link and title fields are),
+the metadata will be written to the generated html page as a &lt;meta&gt;
+header.
+
+The field value is treated as HTML entity-escaped text, so you can include
+a quote in the text by writing `&quot;` and so on.
+
+If this plugin is enabled, the title of this page will say that it is.
+[[meta title="meta plugin (enabled)"]]
diff --git a/1.33.2/doc/plugins/orphans.mdwn b/1.33.2/doc/plugins/orphans.mdwn
new file mode 100644 (file)
index 0000000..b83879d
--- /dev/null
@@ -0,0 +1,16 @@
+[[template id=plugin name=orphans included=1 author="[[Joey]]"]]
+[[tag type/meta]]
+
+This plugin generates a list of possibly orphaned pages -- pages that no
+other page links to.
+
+The optional parameter "pages" can be a [[PageSpec]] specifying the pages
+to check for orphans, default is search them all.
+
+Note that it takes [[BackLinks]] into account, but does not count inlining a
+page as linking to it, so will generally count many blog-type pages as
+orphans.
+
+If it is enabled, here's a list of orphaned pages on this wiki:
+
+[[orphans ]]
diff --git a/1.33.2/doc/plugins/otl.mdwn b/1.33.2/doc/plugins/otl.mdwn
new file mode 100644 (file)
index 0000000..2ff9a9e
--- /dev/null
@@ -0,0 +1,6 @@
+[[template id=plugin name=otl included=1 author="[[Joey]]"]]
+[[tag type/format]]
+
+This plugin allows ikiwiki to process `.otl` outline files, as created by 
+[vimoutliner](http://www.vimoutliner.org/). To use it, you need to have 
+vimoutliner installed, since it uses the `otl2html` program.
diff --git a/1.33.2/doc/plugins/pagecount.mdwn b/1.33.2/doc/plugins/pagecount.mdwn
new file mode 100644 (file)
index 0000000..48e3267
--- /dev/null
@@ -0,0 +1,14 @@
+[[template id=plugin name=pagecount included=1 author="[[Joey]]"]]
+[[tag type/meta]]
+
+Provides a \\[[pagecount ]] [[PreProcessorDirective]] that is replaced with
+the total number of pages currently in the wiki.
+
+The optional parameter "pages" can be a [[PageSpec]] specifying the pages
+to count, default is to count them all.
+
+This plugin is included in ikiwiki, but is not enabled by default.
+
+If it is turned on it can tell us that this wiki includes
+[[pagecount ]] pages, of which [[pagecount pages="*/Discussion"]] are
+discussion pages.
diff --git a/1.33.2/doc/plugins/pagestats.mdwn b/1.33.2/doc/plugins/pagestats.mdwn
new file mode 100644 (file)
index 0000000..6c1fd00
--- /dev/null
@@ -0,0 +1,14 @@
+[[template id=plugin name=pagestate included=1 author="Enrico Zini"]]
+[[tag type/meta type/tags]]
+
+This plugin can generate stats about how pages link to each other. It can
+produce either a del.icio.us style cloud, or a table counting the number of
+links to each page.
+
+Here's how to use it to create a [[tag]] cloud:
+
+       \[[pagestats pages="tags/*"]]
+
+And here's how to create a table of all the pages on the wiki:
+
+       \[[pagestats style="table"]]
diff --git a/1.33.2/doc/plugins/polygen.mdwn b/1.33.2/doc/plugins/polygen.mdwn
new file mode 100644 (file)
index 0000000..240edc9
--- /dev/null
@@ -0,0 +1,27 @@
+[[template id=plugin name=polygen included=1 author="Enrico Zini"]]
+[[tag type/fun]]
+
+This plugin allows inserting text generated by polygen into a wiki page.
+For example:
+
+       \[[polygen grammar="genius"]]
+
+It's also possible to specify a starting nonterminal for the grammar by
+including `symbol="text"` in the directive.
+
+----
+
+If this plugin is enabled, and polygen is installed, here are a few notes
+about ikiwiki.
+
+Ikiwiki is internally based on a [[polygen grammar="designpatterns"]]
+coupled to a [[polygen grammar="designpatterns"]], as described in
+"[[polygen grammar="paper"]]" by [[polygen grammar="nipponame"]] of
+[[polygen grammar="boyband"]].
+
+Ikiwiki reviews:
+<ul>
+<li>[[polygen grammar="reviews"]]</li>
+<li>[[polygen grammar="reviews"]]</li>
+<li>[[polygen grammar="reviews"]]</li>
+</ul>
diff --git a/1.33.2/doc/plugins/rst.mdwn b/1.33.2/doc/plugins/rst.mdwn
new file mode 100644 (file)
index 0000000..969d71c
--- /dev/null
@@ -0,0 +1,23 @@
+[[template id=plugin name=rst included=1 author="Sergio Talens-Oliag"]]
+[[tag type/format]]
+[[tag type/slow]]
+
+This plugin lets ikwiki convert files with names ending in ".rst" to html.
+It uses the [reStructuredText](http://docutils.sourceforge.net/rst.html)
+markup syntax. You need to have the python-docutils module installed to use
+it.
+
+Note that this plugin does not interoperate very well with the rest of
+ikiwiki. Limitations include:
+
+* reStructuredText does not allow raw html to be inserted into
+  documents, but ikiwiki does so in many cases, including
+  [[WikiLinks|WikiLink]] and many
+  [[PreprocessorDirectives|PreprocessorDirective]].
+* It's slow; it forks a copy of python for each page. While there is a
+  perl version of the reStructuredText processor, it is not being kept in
+  sync with the standard version, so is not used.
+
+So while you may find this useful for importing old files into your wiki,
+using this as your main markup language in ikiwiki isn't recommended at
+this time.
diff --git a/1.33.2/doc/plugins/search.mdwn b/1.33.2/doc/plugins/search.mdwn
new file mode 100644 (file)
index 0000000..5b53253
--- /dev/null
@@ -0,0 +1,12 @@
+[[template id=plugin name=search included=1 author="[[Joey]]"]]
+[[tag type/useful]]
+
+This plugin is included in ikiwiki, but is not enabled by default. It adds
+full text search to ikiwiki, using the [[HyperEstraier]] engine.
+
+It's possible to configure HyperEstraier via one of ikiwiki's
+[[templates]], but for most users, no configuration should be needed aside
+from enabling the plugin.
+
+This plugin has a configuration option. To change the path to estseek.cgi,
+set `--estseek=/path/to/estseek.cgi`
diff --git a/1.33.2/doc/plugins/shortcut.mdwn b/1.33.2/doc/plugins/shortcut.mdwn
new file mode 100644 (file)
index 0000000..33180b1
--- /dev/null
@@ -0,0 +1,12 @@
+[[template id=plugin name=shortcut included=1 author="[[Joey]]"]]
+[[tag type/format]]
+
+This plugin allows external links to commonly linked to sites to be made
+more easily using shortcuts. Some examples of using shortcuts include:
+
+       \[[google foo]]
+       \[[wikipedia War of 1812]]
+       \[[debbug 12345]]
+
+The available shortcuts are defined on the [[shortcuts]] page in
+the wiki.
diff --git a/1.33.2/doc/plugins/sidebar.mdwn b/1.33.2/doc/plugins/sidebar.mdwn
new file mode 100644 (file)
index 0000000..04bf666
--- /dev/null
@@ -0,0 +1,15 @@
+[[template id=plugin name=sidebar included=1 author="Tuomo Valkonen"]]
+[[tag type/chrome]]
+
+If this plugin is enabled, then a sidebar is added to pages in the wiki.
+The content of the sidebar is simply the content of a page named
+"sidebar" (ie, create a "sidebar.mdwn").
+
+Typically this will be a page in the root of the wiki, but it can also be a
+[[SubPage]]. In fact, this page, [[plugins/sidebar|plugins/sidebar]], will
+be treated as a sidebar for the [[plugins]] page, and of all of its
+SubPages, if the plugin is enabled.
+
+Note that to disable a sidebar for a [[SubPage]] of a page that has a sidebar,
+you can create a sidebar page that is completely empty. This will turn off
+the sidebar altogether.
diff --git a/1.33.2/doc/plugins/smiley.mdwn b/1.33.2/doc/plugins/smiley.mdwn
new file mode 100644 (file)
index 0000000..0e577f5
--- /dev/null
@@ -0,0 +1,9 @@
+[[template id=plugin name=smiley included=1 author="[[Joey]]"]]
+[[tag type/chrome]]
+
+This plugin makes it easy to insert smileys and other special symbols into
+pages in the wiki. The symbols are all listed on the [[smileys]] page,
+which serves as both configuration for the plugin and a list of available
+smileys.
+
+This plugin is included in ikiwiki, but is not enabled by default. :-)
diff --git a/1.33.2/doc/plugins/tag.mdwn b/1.33.2/doc/plugins/tag.mdwn
new file mode 100644 (file)
index 0000000..1bc38e6
--- /dev/null
@@ -0,0 +1,22 @@
+[[template id=plugin name=tag included=1 author="[[Joey]]"]]
+[[tag type/tags type/link]]
+
+This plugin allows tagging pages. List tags as follows:
+
+       \[[tag tech life linux]]
+
+The tags work the same as if you had put a (hidden) [[WikiLink]] on the page
+for each tag, so you can use a [[PageSpec]] match all pages that are
+tagged with a given tag, for example. The tags will also show up on blog
+entries and at the bottom of the tagged pages, as well as in RSS and Atom
+feeds.
+
+This plugin has a configuration option. Set --tagbase=tag and links to tags
+will be located under the specified base page. If ikiwiki is configured
+this way, then the example above actually tags the page with the tags
+tags/tech, tags/life, and tags/linux. This is a useful way to avoid
+having to write the full path to tags, if you want to keep them grouped
+together out of the way.
+
+If this plugin is enabled, you'll see a note below that this page is tagged
+with the "tags" tag.
diff --git a/1.33.2/doc/plugins/template.mdwn b/1.33.2/doc/plugins/template.mdwn
new file mode 100644 (file)
index 0000000..8b089d9
--- /dev/null
@@ -0,0 +1,54 @@
+[[template id=plugin name=template included=1 author="[[Joey]]"]]
+[[tag type/format]]
+
+With this plugin, you can set up templates, and cause them to be filled out
+and inserted into pages in the wiki. Using a template works like this:
+
+       \[[template id=foo name="Charley" color="red" age=11]]
+
+This fills out the template `templates/foo`, filling in the `color` and `age`
+fields on it with the specified values, and inserts the result into the page.
+
+(Note that if the template doesn't exist, the page will provide a link that
+can be used to create it.)
+
+A value can include any markup that would be allowed in the wiki page
+outside the template. Triple-quoting the value even allows quotes to be
+included in it. Combined with multi-line quoted values, this allows for
+large chunks of marked up text to be embedded into a template:
+
+       \[[template id=foo name="Sally" color="green" age=8 notes="""
+       * \[[Charley]]'s sister.
+       * "I want to be an astronaut when I grow up."
+       * Really 8 and a half.
+       """]]
+
+To create a template, make a page in the wiki named `template/foo`. Note
+that this is a different location than the directory used for the
+[[templates]] used to build the wiki itself, which is not inside the wiki.
+
+The template uses the syntax used by the HTML::Template perl module, which
+allows for some fairly complex things to be done. Consult its documentation
+for the full syntax, but all you really need to know are a few things:
+
+* To insert the value of a variable, use `<TMPL_VAR variable>`.
+* To make a block of text conditional on a variable being set use
+  `<TMPL_IF NAME="variable">text</TMPL_IF>`.
+* To use one block of text if a variable is set and a second if it's not,
+  use `<TMPL_IF NAME="variable">text<TMPL_ELSE>other text</TMPL_IF>`
+
+Here's a sample template:
+
+       <span class="infobox">
+       Name: <TMPL_VAR name><br />
+       Age: <TMPL_VAR age><br />
+       <TMPL_IF NAME="color">
+       Favorite color: <TMPL_VAR color><br />
+       <TMPL_ELSE>
+       No favorite color.<br />
+       </TMPL_IF>
+       <TMPL_IF NAME="notes">
+       <hr />
+       <TMPL_VAR notes>
+       </TMPL_IF>
+       </span>
diff --git a/1.33.2/doc/plugins/toc.mdwn b/1.33.2/doc/plugins/toc.mdwn
new file mode 100644 (file)
index 0000000..57bd622
--- /dev/null
@@ -0,0 +1,13 @@
+[[template id=plugin name=toc included=1 author="Joey Hess"]]
+[[tag type/chrome]]
+
+Add a table of contents be to a page:
+
+       \[[toc ]]
+
+The table of contents will be automatically generated based on the
+headers of the page. By default only the largest headers present on the
+page will be shown; to control how many levels of headers are shown, use
+the `levels` parameter:
+
+       \[[toc levels=2]]
diff --git a/1.33.2/doc/plugins/type/chrome.mdwn b/1.33.2/doc/plugins/type/chrome.mdwn
new file mode 100644 (file)
index 0000000..d3f0eb3
--- /dev/null
@@ -0,0 +1 @@
+These plugins affect the look and feel of the wiki.
diff --git a/1.33.2/doc/plugins/type/core.mdwn b/1.33.2/doc/plugins/type/core.mdwn
new file mode 100644 (file)
index 0000000..71d93c4
--- /dev/null
@@ -0,0 +1 @@
+These plugins provide core functionality and are enabled by default.
diff --git a/1.33.2/doc/plugins/type/format.mdwn b/1.33.2/doc/plugins/type/format.mdwn
new file mode 100644 (file)
index 0000000..a60d725
--- /dev/null
@@ -0,0 +1 @@
+These plugins provide ways to format text on wiki pages.
diff --git a/1.33.2/doc/plugins/type/fun.mdwn b/1.33.2/doc/plugins/type/fun.mdwn
new file mode 100644 (file)
index 0000000..4d97c8e
--- /dev/null
@@ -0,0 +1 @@
+These plugins are just for fun.
diff --git a/1.33.2/doc/plugins/type/html.mdwn b/1.33.2/doc/plugins/type/html.mdwn
new file mode 100644 (file)
index 0000000..290208f
--- /dev/null
@@ -0,0 +1 @@
+These plugins generate or process html.
diff --git a/1.33.2/doc/plugins/type/link.mdwn b/1.33.2/doc/plugins/type/link.mdwn
new file mode 100644 (file)
index 0000000..09add73
--- /dev/null
@@ -0,0 +1 @@
+These plugins deal with [[WikiLink]]s.
diff --git a/1.33.2/doc/plugins/type/meta.mdwn b/1.33.2/doc/plugins/type/meta.mdwn
new file mode 100644 (file)
index 0000000..cae30ca
--- /dev/null
@@ -0,0 +1 @@
+These plugins deal in meta-information about the wiki.
diff --git a/1.33.2/doc/plugins/type/slow.mdwn b/1.33.2/doc/plugins/type/slow.mdwn
new file mode 100644 (file)
index 0000000..c0e7215
--- /dev/null
@@ -0,0 +1,3 @@
+These plugins can cause wiki rendering to be significantly slowed down,
+due to things like needing to run an external program for every page
+rendered.
diff --git a/1.33.2/doc/plugins/type/special-purpose.mdwn b/1.33.2/doc/plugins/type/special-purpose.mdwn
new file mode 100644 (file)
index 0000000..b6ed045
--- /dev/null
@@ -0,0 +1 @@
+Special-purpose plugins.
diff --git a/1.33.2/doc/plugins/type/tags.mdwn b/1.33.2/doc/plugins/type/tags.mdwn
new file mode 100644 (file)
index 0000000..bb74066
--- /dev/null
@@ -0,0 +1 @@
+These plugins support tagging.
diff --git a/1.33.2/doc/plugins/type/useful.mdwn b/1.33.2/doc/plugins/type/useful.mdwn
new file mode 100644 (file)
index 0000000..92fcf5a
--- /dev/null
@@ -0,0 +1 @@
+These plugins perform various miscellaneous useful functions.
diff --git a/1.33.2/doc/plugins/typography.mdwn b/1.33.2/doc/plugins/typography.mdwn
new file mode 100644 (file)
index 0000000..c11da94
--- /dev/null
@@ -0,0 +1,7 @@
+[[template id=plugin name=typography included=1 author="[[Roktas]]"]]
+[[tag type/format]]
+
+This plugin, also known as
+[SmartyPants](http://daringfireball.net/projects/smartypants/), translates
+plain ASCII punctuation characters into ``smart'' typographic punctuation HTML
+entities. To use it, you need to have the `Text::Typography` module installed.
diff --git a/1.33.2/doc/plugins/wikitext.mdwn b/1.33.2/doc/plugins/wikitext.mdwn
new file mode 100644 (file)
index 0000000..d7768f0
--- /dev/null
@@ -0,0 +1,23 @@
+[[template id=plugin name=wikitext included=1 author="[[Joey]]"]]
+[[tag type/format]]
+
+This plugin allows ikiwiki to process pages written in the original wiki
+text format. To use it, you need to have the Text::WikiFormat perl module
+installed, enable the plugin, then files with the extention `.wiki` will be
+processed as wiki text.
+
+Wiki formatting is very simple. An item wrapped in three single quotes is
+strong. An item wrapped in two single quotes is emphasized. Four or more
+hyphen characters at the start of a line create a horizontal line. Newlines
+turn into the appropriate tags. Headers are matching equals signs around
+the header text -- the more signs, the lesser the header.
+
+Links are standard [[WikiLinks|WikiLink]], although you can also enable
+[[CamelCase]] links.
+
+Lists are indented text, by one tab or four spaces. In unordered lists,
+where each item has its own bullet point, each item needs a leading
+asterisk and space. Ordered lists consist of items marked with combination
+of one or more alphanumeric characters followed by a period and an optional
+space. Any indented text without either marking is code, handled literally.
+You can nest lists.
diff --git a/1.33.2/doc/plugins/write.mdwn b/1.33.2/doc/plugins/write.mdwn
new file mode 100644 (file)
index 0000000..5cace09
--- /dev/null
@@ -0,0 +1,356 @@
+ikiwiki [[plugins]] are written in perl. Each plugin is a perl module, in
+the `IkiWiki::Plugin` namespace. The name of the plugin is typically in
+lowercase, such as `IkiWiki::Plugin::inline`. Ikiwiki includes a
+`IkiWiki::Plugin::skeleton` that can be fleshed out to make a useful
+plugin. `IkiWiki::Plugin::pagecount` is another simple example.
+
+[[toc levels=2]]
+
+## Considerations
+
+One thing to keep in mind when writing a plugin is that ikiwiki is a wiki
+*compiler*. So plugins influence pages when they are built, not when they
+are loaded. A plugin that inserts the current time into a page, for
+example, will insert the build time. Also, as a compiler, ikiwiki avoids
+rebuilding pages unless they have changed, so a plugin that prints some
+random or changing thing on a page will generate a static page that won't
+change until ikiwiki rebuilds the page for some other reason, like the page
+being edited.
+
+## Registering plugins
+
+All plugins should `use IkiWiki` to import the ikiwiki plugin interface.
+
+Plugins should, when imported, call `hook()` to hook into ikiwiki's
+processing. The function uses named parameters, and use varies depending on
+the type of hook being registered -- see below. Note that a plugin can call
+the function more than once to register multiple hooks. All calls to
+`hook()` should be passed a "type" parameter, which gives the type of
+hook, a "id" paramter, which should be a unique string for this plugin, and
+a "call" parameter, which is a reference to a function to call for the
+hook.
+
+An optional "scan" parameter, if set to a true value, makes the hook be
+called during the preliminary scan that ikiwiki makes of updated pages,
+before begining to render pages. This parameter should be set to true if
+the hook modifies data in `%links`. Note that doing so will make the hook
+be run twice per page build, so avoid doing it for expensive hooks.
+
+## Types of hooks
+
+In roughly the order they are called.
+
+### getopt
+
+       hook(type => "getopt", id => "foo", call => \&getopt);
+
+This allows for plugins to perform their own processing of command-line
+options and so add options to the ikiwiki command line. It's called during
+command line processing, with @ARGV full of any options that ikiwiki was
+not able to process on its own. The function should process any options it
+can, removing them from @ARGV, and probably recording the configuration
+settings in %config. It should take care not to abort if it sees
+an option it cannot process, and should just skip over those options and
+leave them in @ARGV.
+
+### checkconfig
+
+       hook(type => "checkconfig", id => "foo", call => \&checkconfig);
+
+This is useful if the plugin needs to check for or modify ikiwiki's
+configuration. It's called early in the startup process. The
+function is passed no values. It's ok for the function to call
+`error()` if something isn't configured right.
+
+### filter
+
+       hook(type => "filter", id => "foo", call => \&filter);
+
+Runs on the raw source of a page, before anything else touches it, and can
+make arbitrary changes. The function is passed named parameters `page` and
+`content` and should return the filtered content.
+
+### scan
+
+       hook(type => "scan", id => "foo", call => \&scan);
+
+This is identical to a preprocess hook (see below), except that it is
+called in the initial pass that scans pages for data that will be used in
+later passes. Scan hooks are the only hook that should modify 
+
+### preprocess
+
+Adding a [[PreProcessorDirective]] is probably the most common use of a
+plugin.
+
+        hook(type => "preprocess", id => "foo", call => \&preprocess);
+
+Replace "foo" with the command name that will be used inside brackets for
+the preprocessor directive.
+
+Each time the directive is processed, the referenced function (`preprocess`
+in the example above) is called, and is passed named parameters. A "page"
+parameter gives the name of the page that embedded the preprocessor
+directive, while a "destpage" parameter gives the name of the page the
+content is going to (different for inlined pages). All parameters included
+in the directive are included as named parameters as well. Whatever the
+function returns goes onto the page in place of the directive.
+
+Note that if the [[htmlscrubber]] is enabled, html in
+[[PreProcessorDirective]] output is sanitised, which may limit what your
+plugin can do. Also, the rest of the page content is not in html format at
+preprocessor time. Text output by a preprocessor directive will be
+linkified and passed through markdown (or whatever engine is used to htmlize
+the page) along with the rest of the page.
+
+### htmlize
+
+       hook(type => "htmlize", id => "ext", call => \&htmlize);
+
+Runs on the raw source of a page and turns it into html. The id parameter
+specifies the filename extension that a file must have to be htmlized using
+this plugin. This is how you can add support for new and exciting markup
+languages to ikiwiki.
+
+The function is passed named parameters: "page" and "content" and should
+return the htmlized content.
+
+### pagetemplate
+
+       hook(type => "pagetemplate", id => "foo", call => \&pagetemplate);
+
+[[Templates]] are filled out for many different things in ikiwiki, 
+like generating a page, or part of a blog page, or an rss feed, or a cgi.
+This hook allows modifying those templates. The function is passed named
+parameters. The "page" and "destpage" parameters are the same as for a
+preprocess hook. The "template" parameter is a `HTML::Template` object that
+is the template that will be used to generate the page. The function can
+manipulate that template object.
+
+The most common thing to do is probably to call $template->param() to add
+a new custom parameter to the template.
+
+### sanitize
+
+       hook(type => "sanitize", id => "foo", call => \&sanitize);
+
+Use this to implement html sanitization or anything else that needs to
+modify the body of a page after it has been fully converted to html.
+
+The function is passed named parameters: "page" and "content", and 
+should return the sanitized content.
+
+### format
+
+       hook(type => "format", id => "foo", call => \&format);
+
+The difference between format and sanitize is that sanitize only acts on
+the page body, while format can modify the entire html page including the
+header and footer inserted by ikiwiki, the html document type, etc.
+
+The function is passed named parameters: "page" and "content", and 
+should return the formatted content.
+
+### delete
+
+       hook(type => "delete", id => "foo", call => \&delete);
+
+Each time a page or pages is removed from the wiki, the referenced function
+is called, and passed the names of the source files that were removed.
+
+### change
+
+       hook(type => "change", id => "foo", call => \&render);
+
+Each time ikiwiki renders a change or addition (but not deletion) to the
+wiki, the referenced function is called, and passed the names of the
+source files that were rendered.
+
+### cgi
+
+       hook(type => "cgi", id => "foo", call => \&cgi);
+
+Use this to hook into ikiwiki's cgi script. Each registered cgi hook is
+called in turn, and passed a CGI object. The hook should examine the
+parameters, and if it will handle this CGI request, output a page and
+terminate the program.
+
+### savestate
+
+       hook(type => "savestate", id => "foo", call => \&savestate);
+
+This hook is called wheneven ikiwiki normally saves its state, just before
+the state is saved. The function can save other state, modify values before
+they're saved, etc.
+
+## Plugin interface
+
+To import the ikiwiki plugin interface:
+
+       use IkiWiki '1.00';
+
+This will import several variables and functions into your plugin's
+namespace. These variables and functions are the ones most plugins need,
+and a special effort will be made to avoid changing them in incompatible
+ways, and to document any changes that have to be made in the future.
+
+Note that IkiWiki also provides other variables functions that are not
+exported by default. No guarantee is made about these in the future, so if
+it's not exported, the wise choice is to not use it.
+
+### %config
+
+A plugin can access the wiki's configuration via the `%config`
+hash. The best way to understand the contents of the hash is to look at
+[[ikiwiki.setup]], which sets the hash content to configure the wiki.
+
+### Other variables
+
+If your plugin needs to access data about other pages in the wiki. It can
+use the following hashes, using a page name as the key:
+
+* `%links` lists the names of each page that a page links to, in an array
+  reference.
+* `%renderedfiles` lists names of the files rendered by a page, in an array
+  reference.
+* `%pagesources` contains the name of the source file for a page.
+
+Also, the %IkiWiki::version variable contains the version number for the
+ikiwiki program.
+
+### Library functions
+
+#### `hook(@)`
+
+Hook into ikiwiki's processing. See the discussion of hooks above.
+
+Note that in addition to the named parameters described above, a parameter
+named no_override is supported, If it's set to a true value, then this hook
+will not override any existing hook with the same id. This is useful if
+the id can be controled by the user.
+
+#### `debug($)`
+
+Logs a debugging message. These are supressed unless verbose mode is turned
+on.
+
+#### `error($)`
+
+Aborts with an error message.
+
+Note that while any plugin can use this for a fatal error, plugins should
+try to avoid dying on bad input, as that will halt the entire wiki build
+and make the wiki unusable. So for example, if a [[PreProcessorDirective]]
+is passed bad parameters, it's better to return an error message, which can
+appear on the wiki page, rather than calling error().
+
+#### `template($;@)`
+
+Creates and returns a HTML::Template object. The first parameter is the
+name of the file in the template directory. The optional remaining
+parameters are passed to HTML::Template->new.
+
+#### `htmlpage($)`
+
+Passed a page name, returns the base name that will be used for a the html
+page created from it. (Ie, it appends ".html".)
+
+#### `add_depends($$)`
+
+Makes the specified page depend on the specified [[PageSpec]].
+
+#### `pagespec_match($$)`
+
+Passed a page name, and a [[PageSpec]], returns true if the [[PageSpec]]
+matches the page.
+
+#### `bestlink($$)`
+
+Given a page and the text of a link on the page, determine which
+existing page that link best points to. Prefers pages under a
+subdirectory with the same name as the source page, failing that
+goes down the directory tree to the base looking for matching
+pages, as described in [[SubPage/LinkingRules]].
+
+#### `htmllink($$$;$$$)`
+
+Many plugins need to generate html links and add them to a page. This is
+done by using the `htmllink` function. The usual way to call
+`htmlllink` is:
+
+       htmllink($page, $page, $link)
+
+Why is `$page` repeated? Because if a page is inlined inside another, and a
+link is placed on it, the right way to make that link is actually:
+
+       htmllink($page, $destpage, $link)
+
+Here `$destpage` is the inlining page. A `destpage` parameter is passed to
+some of the hook functions above; the ones that are not passed it are not used
+during inlining and don't need to worry about this issue.
+
+The remaining three optional parameters to `htmllink` are:
+
+1. noimageinline - set to true to avoid turning links into inline html images
+1. forcesubpage  - set to force a link to a subpage
+1. linktext - set to force the link text to something
+
+#### `readfile($;$)`
+
+Given a filename, reads and returns the entire file.
+
+The optional second parameter, if set to a true value, makes the file be read
+in binary mode.
+
+A failure to read the file will result in it dying with an error.
+
+#### `writefile($$$;$)`
+
+Given a filename, a directory to put it in, and the file's content,
+writes a file. 
+
+The optional second parameter, if set to a true value, makes the file be
+written in binary mode.
+
+A failure to write the file will result in it dying with an error.
+
+If the destination directory doesn't exist, it will first be created.
+
+### `will_render($$)`
+
+Given a page name and a destination file name (not including the base
+destination directory), register that the page will result in that file
+being rendered. It's important to call this before writing to any file in
+the destination directory.
+
+#### `pagetype($)`
+
+Given the name of a source file, returns the type of page it is, if it's
+a type that ikiwiki knowns how to htmlize. Otherwise, returns undef.
+
+#### `pagename($)`
+
+Given the name of a source file, returns the name of the wiki page
+that corresponds to that file.
+
+#### `srcfile($)`
+
+Given the name of a source file in the wiki, searches for the file in
+the source directory and the underlay directory, and returns the full
+path to the first file found.
+
+#### `displaytime($)`
+
+Given a time, formats it for display.
+
+## RCS plugins
+
+ikiwiki's support for revision control systems also uses pluggable perl
+modules. These are in the `IkiWiki::RCS` namespace, for example
+`IkiWiki::RCS::svn`. 
+
+Each RCS plugin must support all the IkiWiki::rcs\_* functions.
+See IkiWiki::RCS::Stub for the full list of functions. It's ok if
+rcs\_getctime does nothing except for throwing an error.
+
+See [[about_RCS_backends]] for some more info.
diff --git a/1.33.2/doc/post-commit.mdwn b/1.33.2/doc/post-commit.mdwn
new file mode 100644 (file)
index 0000000..84375da
--- /dev/null
@@ -0,0 +1,19 @@
+A post-commit hook is run every time you commit a change to your
+[[subversion]] (or [[git]] or [[mercurial]]) repository. To make the wiki be updated each
+time a commit is made, it can be run from (or as) a post-commit hook.
+
+The best way to run ikiwiki in a post-commit hook is using a wrapper, which
+ikiwiki is usually configured to generate using a setup file.
+
+The generated wrapper is a C program that is designed to safely be made
+suid if necessary. It's hardcoded to run ikiwiki with the settings
+specified when you ran --wrapper, and can only be used to update and
+compile that one checkout into the specified html directory.
+
+Depending on your setup, the post-commit hook might end up
+getting called by users who have write access to the repository, but not to
+your wiki checkout and html directory. If so, you can safely make
+the wrapper suid to a user who can write there (*not* to root!). You might
+want to read [[Security]] first.
+
+[[Setup]] explains setting this up in more detail.
diff --git a/1.33.2/doc/recentchanges.mdwn b/1.33.2/doc/recentchanges.mdwn
new file mode 100644 (file)
index 0000000..9613f24
--- /dev/null
@@ -0,0 +1,4 @@
+ikiwiki generates the list of recent changes by examining the
+history of the revision control system ([[Subversion]], etc) that the wiki
+is configured to use. You have to have [[CGI]] set up for this feature to be
+enabled.
diff --git a/1.33.2/doc/roadmap.mdwn b/1.33.2/doc/roadmap.mdwn
new file mode 100644 (file)
index 0000000..ce1b318
--- /dev/null
@@ -0,0 +1,30 @@
+This is the roadmap for ikiwiki drevelopment.
+
+# 1.0
+
+Generally usable release.
+
+* No severe [[security]] bugs.
+* All the [[features]] people would expect in a wiki. Needs to be a plausable
+  promise of being a wiki that people can commit to [[using|ikiwikiusers]].
+
+Released 29 April 2006.
+
+# 2.0
+
+* Unit test suite (with tests of at least core stuff like
+  [[PageSpec]]). _(status: exists, could of course use more tests)_
+* [[Plugins]] _(status: done)_
+* [[Tags]] _(status: fair)_
+* Should have fully working [[todo/utf8]] support. _(status: good)_
+* [[Optimised_rendering|todo/optimisations]] if possible. Deal with other
+  scalability issues. _(status: scales to thousands of pages, and approximatly
+  3x as fast as version 1.0)_
+* Improved [[todo/html]] stylesheets and templates.
+* Improved scalable [[logo]]. _(status: done)_
+* Support for at other revision control systems aside from svn.
+  See [[about_rcs_backends]] _(status: supports git, tla, mercurial)_
+* Support for one other markup language, probably restructured text.
+  _(status: done, but the rst plugin needs improvement)_
+* No serious known [[bugs]]
+* No severe-to-moderate known [[security]] issues.
diff --git a/1.33.2/doc/sandbox.mdwn b/1.33.2/doc/sandbox.mdwn
new file mode 100644 (file)
index 0000000..286aaa7
--- /dev/null
@@ -0,0 +1,73 @@
+This is the SandBox, a page anyone can edit to try out ikiwiki.
+
+----
+
+Test. Проверка. テスト ığüşöçİ ทดสอบ
+
+Here's a paragraph.
+
+Here's another one with *emphasised* text.
+
+do ë characters work? Sure.
+
+# Header
+
+## Subheader
+
+> This is a blockquote.
+>
+> This is the first level of quoting.
+>
+> > This is nested blockquote.
+>
+>> And without a space works too.
+>>> to three levels
+>
+> Back to the first level.
+
+Numbered list 
+
+1. First item.
+ 1. Sub item.
+1. Another.
+1. And another..
+ 1. foo
+ 2. bar
+  3. baz
+   4. qux
+    5. quux
+
+Bulleted list
+
+* item
+* *item*
+* item
+* one
+  * two
+     * three
+       * four
+
+----
+
+[[haiku hint="sandbox play"]]
+
+----
+
+## Different sorts of links:
+
+* [[WikiLink]]
+* [[different_name_for_a_WikiLink|WikiLink]]
+* [[different name for a WikiLink (with spaces this time)|WikiLink]]
+* <http://www.gnu.org/>
+* [GNU](http://www.gnu.org/)
+* [Email](mailto:noone@invalid)
+* WikiLink without any markup.
+
+-----
+
+This sandbox is also a [[blog]]!
+
+[[inline pages="sandbox/*" rootpage="sandbox" show="5"]]
+
+----
+[[newpage]]
diff --git a/1.33.2/doc/sandbox/foo.wiki b/1.33.2/doc/sandbox/foo.wiki
new file mode 100644 (file)
index 0000000..c3d1c26
--- /dev/null
@@ -0,0 +1 @@
+Look ma, this page uses '''wiki''' markup, not MarkDown!  :-)
diff --git a/1.33.2/doc/sandbox/just_another_test.mdwn b/1.33.2/doc/sandbox/just_another_test.mdwn
new file mode 100644 (file)
index 0000000..cf4a86e
--- /dev/null
@@ -0,0 +1,3 @@
+Well.
+
+Not much to say.
diff --git a/1.33.2/doc/sandbox/my_blog_entry.mdwn b/1.33.2/doc/sandbox/my_blog_entry.mdwn
new file mode 100644 (file)
index 0000000..7c38d03
--- /dev/null
@@ -0,0 +1 @@
+this is my blog entry
\ No newline at end of file
diff --git a/1.33.2/doc/sandbox/test.mdwn b/1.33.2/doc/sandbox/test.mdwn
new file mode 100644 (file)
index 0000000..3bbc982
--- /dev/null
@@ -0,0 +1 @@
+This page, [[test]], is a [[SubPage]] of the [[SandBox]].
diff --git a/1.33.2/doc/sandbox/testtest.mdwn b/1.33.2/doc/sandbox/testtest.mdwn
new file mode 100644 (file)
index 0000000..28eda56
--- /dev/null
@@ -0,0 +1 @@
+test comment
\ No newline at end of file
diff --git a/1.33.2/doc/sandbox/yes.mdwn b/1.33.2/doc/sandbox/yes.mdwn
new file mode 100644 (file)
index 0000000..ccd8065
--- /dev/null
@@ -0,0 +1,3 @@
+yes
+
+[[tags/bar]]
\ No newline at end of file
diff --git a/1.33.2/doc/security.mdwn b/1.33.2/doc/security.mdwn
new file mode 100644 (file)
index 0000000..723c018
--- /dev/null
@@ -0,0 +1,281 @@
+Let's do an ikiwiki security analysis.
+
+If you are using ikiwiki to render pages that only you can edit, do not
+generate any wrappers, and do not use the cgi, then there are no more
+security issues with this program than with cat(1). If, however, you let
+others edit pages in your wiki, then some possible security issues do need
+to be kept in mind.
+
+[[toc levels=2]]
+
+----
+
+# Probable holes
+
+_(The list of things to fix.)_
+
+## commit spoofing
+
+Anyone with direct commit access can forge "web commit from foo" and
+make it appear on [[RecentChanges]] like foo committed. One way to avoid
+this would be to limit web commits to those done by a certian user.
+
+## other stuff to look at
+
+I need to audit the git backend a bit, and have been meaning to
+see if any CRLF injection type things can be done in the CGI code.
+
+----
+
+# Potential gotchas
+
+_(Things not to do.)_
+
+## image file etc attacks
+
+If it enounters a file type it does not understand, ikiwiki just copies it
+into place. So if you let users add any kind of file they like, they can
+upload images, movies, windows executables, css files, etc (though not html
+files). If these files exploit security holes in the browser of someone
+who's viewing the wiki, that can be a security problem.
+
+Of course nobody else seems to worry about this in other wikis, so should we?
+
+Currently only people with direct svn commit access can upload such files
+(and if you wanted to you could block that with a svn pre-commit hook).
+Users with only web commit access are limited to editing pages as ikiwiki
+doesn't support file uploads from browsers (yet), so they can't exploit
+this.
+
+## multiple accessors of wiki directory
+
+If multiple people can write to the source directory ikiwiki is using, or
+to the destination directory it writes files to, then one can cause trouble
+for the other when they run ikiwiki through symlink attacks.
+
+So it's best if only one person can ever write to those directories.
+
+## setup files
+
+Setup files are not safe to keep in subversion with the rest of the wiki.
+Just don't do it. [[ikiwiki.setup]] is *not* used as the setup file for
+this wiki, BTW.
+
+## page locking can be bypassed via direct svn commits
+
+A locked page can only be edited on the web by an admin, but
+anyone who is allowed to commit direct to svn can bypass this. This is by
+design, although a subversion pre-commit hook could be used to prevent
+editing of locked pages when using subversion, if you really need to.
+
+## web server attacks
+
+If your web server does any parsing of special sorts of files (for example,
+server parsed html files), then if you let anyone else add files to the wiki,
+they can try to use this to exploit your web server.
+
+----
+
+# Hopefully non-holes
+
+_(AKA, the assumptions that will be the root of most security holes...)_
+
+## exploting ikiwiki with bad content
+
+Someone could add bad content to the wiki and hope to exploit ikiwiki.
+Note that ikiwiki runs with perl taint checks on, so this is unlikely.
+
+One fun thing in ikiwiki is its handling of a PageSpec, which involves
+translating it into perl and running the perl. Of course, this is done
+*very* carefully to guard against injecting arbitrary perl code.
+
+## publishing cgi scripts
+
+ikiwiki does not allow cgi scripts to be published as part of the wiki. Or
+rather, the script is published, but it's not marked executable (except in
+the case of "destination directory file replacement" below), so hopefully
+your web server will not run it.
+
+## suid wrappers
+
+ikiwiki --wrapper is intended to generate a wrapper program that
+runs ikiwiki to update a given wiki. The wrapper can in turn be made suid,
+for example to be used in a [[post-commit]] hook by people who cannot write
+to the html pages, etc.
+
+If the wrapper script is made suid, then any bugs in this wrapper would be
+security holes. The wrapper is written as securely as I know how, is based
+on code that has a history of security use long before ikiwiki, and there's
+been no problem yet.
+
+## shell exploits
+
+ikiwiki does not expose untrusted data to the shell. In fact it doesn't use
+system() at all, and the only use of backticks is on data supplied by the
+wiki admin and untainted filenames. And it runs with taint checks on of
+course..
+
+## cgi data security
+
+When ikiwiki runs as a cgi to edit a page, it is passed the name of the
+page to edit. It has to make sure to sanitise this page, to prevent eg,
+editing of ../../../foo, or editing of files that are not part of the wiki,
+such as subversion dotfiles. This is done by sanitising the filename
+removing unallowed characters, then making sure it doesn't start with "/"
+or contain ".." or "/.svn/". Annoyingly ad-hoc, this kind of code is where
+security holes breed. It needs a test suite at the very least.
+
+## CGI::Session security
+
+I've audited this module and it is massively insecure by default. ikiwiki
+uses it in one of the few secure ways; by forcing it to write to a
+directory it controls (and not /tmp) and by setting a umask that makes the
+file not be world readable.
+
+## cgi password security
+
+Login to the wiki involves sending a password in cleartext over the net.
+Cracking the password only allows editing the wiki as that user though.
+If you care, you can use https, I suppose. If you do use https either for
+all of the wiki, or just the cgi access, then consider using the sslcookie
+option.
+
+## XSS holes in CGI output
+
+ikiwiki has not yet been audited to ensure that all cgi script input/output
+is sanitised to prevent XSS attacks. For example, a user can't register
+with a username containing html code (anymore).
+
+It's difficult to know for sure if all such avenues have really been
+closed though.
+
+## HTML::Template security
+
+If the [[plugins/template]] plugin is enabled, users can modify templates
+like any other part of the wiki. This assumes that HTML::Template is secure
+when used with untrusted/malicious templates. (Note that includes are not
+allowed, so that's not a problem.)
+
+----
+
+# Plugins
+
+The security of [[plugins]] depends on how well they're written and what
+external tools they use. The plugins included in ikiwiki are all held to
+the same standards as the rest of ikiwiki, but with that said, here are
+some security notes for them.
+
+* The [[plugins/img]] plugin assumes that imagemagick/perlmagick are secure
+  from malformed image attacks. Imagemagick has had security holes in the
+  past. To be able to exploit such a hole, a user would need to be able to
+  upload images to the wiki.
+
+----
+
+# Fixed holes
+
+_(Unless otherwise noted, these were discovered and immediately fixed by the
+ikiwiki developers.)_
+
+## destination directory file replacement
+
+Any file in the destination directory that is a valid page filename can be
+replaced, even if it was not originally rendered from a page. For example,
+ikiwiki.cgi could be edited in the wiki, and it would write out a
+replacement. File permission is preseved. Yipes!
+
+This was fixed by making ikiwiki check if the file it's writing to exists;
+if it does then it has to be a file that it's aware of creating before, or
+it will refuse to create it.
+
+Still, this sort of attack is something to keep in mind.
+
+## symlink attacks
+
+Could a committer trick ikiwiki into following a symlink and operating on
+some other tree that it shouldn't? svn supports symlinks, so one can get
+into the repo. ikiwiki uses File::Find to traverse the repo, and does not
+tell it to follow symlinks, but it might be possible to race replacing a
+directory with a symlink and trick it into following the link.
+
+Also, if someone checks in a symlink to /etc/passwd, ikiwiki would read and
+publish that, which could be used to expose files a committer otherwise
+wouldn't see.
+
+To avoid this, ikiwiki will skip over symlinks when scanning for pages, and
+uses locking to prevent more than one instance running at a time. The lock
+prevents one ikiwiki from running a svn up at the wrong time to race
+another ikiwiki. So only attackers who can write to the working copy on
+their own can race it.
+
+## symlink + cgi attacks
+
+Similarly, a svn commit of a symlink could be made, ikiwiki ignores it
+because of the above, but the symlink is still there, and then you edit the
+page from the web, which follows the symlink when reading the page
+(exposing the content), and again when saving the changed page (changing
+the content).
+
+This was fixed for page saving by making ikiwiki refuse to write to files
+that are symlinks, or that are in subdirectories that are symlinks,
+combined with the above locking.
+
+For page editing, it's fixed by ikiwiki checking to make sure that it
+already has found a page by scanning the tree, before loading it for
+editing, which as described above, also is done in a way that avoids
+symlink attacks.
+
+## underlaydir override attacks
+
+ikiwiki also scans an underlaydir for pages, this is used to provide stock
+pages to all wikis w/o needing to copy them into the wiki. Since ikiwiki
+internally stores only the base filename from the underlaydir or srcdir,
+and searches for a file in either directory when reading a page source,
+there is the potential for ikiwiki's scanner to reject a file from the
+srcdir for some reason (such as it being contained in a directory that is
+symlinked in), find a valid copy of the file in the underlaydir, and then
+when loading the file, mistakenly load the bad file from the srcdir.
+
+This attack is avoided by making ikiwiki refuse to add any files from the
+underlaydir if a file also exists in the srcdir with the same name.
+
+## multiple page source issues
+
+Note that I previously worried that underlay override attacks could also be
+accomplished if ikiwiki were extended to support other page markup
+languages besides markdown. However, a closer look indicates that this is
+not a problem: ikiwiki does preserve the file extension when storing the
+source filename of a page, so a file with another extension that renders to
+the same page name can't bypass the check. Ie, ikiwiki won't skip foo.rst
+in the srcdir, find foo.mdwn in the underlay, decide to render page foo and
+then read the bad foo.mdwn. Instead it will remember the .rst extension and
+only render a file with that extension.
+
+## XSS attacks in page content
+
+ikiwiki supports protecting users from their own broken browsers via the
+[[plugins/htmlscrubber]] plugin, which is enabled by default.
+
+## svn commit logs
+
+It's was possible to force a whole series of svn commits to appear to
+have come just before yours, by forging svn log output. This was
+guarded against by using svn log --xml.
+
+ikiwiki escapes any html in svn commit logs to prevent other mischief.
+
+## XML::Parser
+
+XML::Parser is used by the aggregation plugin, and has some security holes. 
+Bug #[378411](http://bugs.debian.org/378411) does not
+seem to affect our use, since the data is not encoded as utf-8 at that
+point. #[378412](http://bugs.debian.org/378412) could affect us, although it
+doesn't seem very exploitable. It has a simple fix, and has been fixed in
+Debian unstable.
+
+## include loops
+
+Various directives that cause one page to be included into another could
+be exploited to DOS the wiki, by causing a loop. Ikiwiki has always guarded
+against this one way or another; the current solution should detect all
+types of loops involving preprocessor directives.
diff --git a/1.33.2/doc/setup.mdwn b/1.33.2/doc/setup.mdwn
new file mode 100644 (file)
index 0000000..dd1a9be
--- /dev/null
@@ -0,0 +1,142 @@
+So you want to set up your own wiki using ikiwiki? This tutorial will walk
+you through setting up a wiki that is stored in [[Subversion]], [[Git]],
+[[TLA]] or [[Mercurial]], and that has optional support for commits from the web.
+
+1. [[Install]] ikiwiki. See [[download]] for where to get it.
+
+2. Create the master rcs repository for your wiki.
+
+               # Subversion
+               svnadmin create /svn/wikirepo
+               svn mkdir file:///svn/wikirepo/trunk -m create
+                
+               # Git
+               mkdir /git/wikirepo
+               cd /git/wikirepo
+               git init-db
+               # Git requires something be in the repo to start with.
+               cp /usr/share/ikiwiki/basewiki/index.mdwn .
+               git add .
+               git commit -m create -a
+               # No need to keep files in the master repository; so at this
+               # stage, you may want to remove all files (except .git) to
+               # save disk space.
+
+               # TLA
+               mkdir /tla
+               tla make-archive me@localhost--wiki /tla/wikirepo
+               tla my-id "<me@localhost>"
+
+               # Mercurial
+               hg init /hg/wikirepo
+
+3. Check out the repository to make the working copy that ikiwiki will use.
+
+               # Subversion
+               svn co file:///svn/wikirepo/trunk ~/wikiwc
+                
+               # Git
+               # Create a local clone to save disk space and also to
+               # optimize performance. See git-clone(1).
+               git clone -l -s /git/wikirepo ~/wikiwc
+
+               # TLA
+               mkdir ~/wikiwc
+               cd ~/wikiwc
+               tla archive-setup me@localhost--wiki/wiki--0
+               tla init-tree me@localhost--wiki/wiki--0
+               # Edit {arch}/=tagging-method and change the precious
+               # line to add the .ikiwiki directory to the regexp.
+               tla import
+
+               # Mercurial
+               # Mercurial uses a single repo approach, so no need to
+               # clone anything. Because the following examples
+               # refer to the ~/wikiwc working copy we symlink it:
+               ln -s /hg/wikirepo ~/wikiwc
+
+4. Build your wiki for the first time.
+
+               ikiwiki --verbose ~/wikiwc/ ~/public_html/wiki/ \
+                       --url=http://host/~you/wiki/
+
+   Replace the url with the real url to your wiki. You should now
+   be able to visit the url and see your wiki.
+
+5. Customise your wiki. The files in `/usr/share/ikiwiki/basewiki/` are
+   used if you don't have a custom version, so let's start by making a
+   custom version of the wiki's index page:
+
+               cd ~/wikiwc
+               cp /usr/share/ikiwiki/basewiki/index.mdwn .
+               $EDITOR index.mdwn
+                
+               # Subversion
+               svn add index.mdwn
+               svn commit -m customised index.mdwn
+                
+               # Git
+               git add index.mdwn
+               git commit -m customised index.mdwn
+               git push origin
+
+               # TLA
+               tla add index.mdwn
+               tla commit
+
+               # Mercurial
+               hg add index.mdwn
+               hg commit -m customised index.mdwn
+
+   You can also add any files you like from scratch of course.
+
+6. Repeat steps 4 and 5 as desired, editing or adding pages and rebuilding
+   the wiki. You can play around with other ikiwiki parameters such as
+   `--wikiname` and `--rebuild` too. Get comfortable with its command line
+   (see [[usage]]).
+
+7. By now you should be getting tired of typing in all the command line
+   options each time you change something in your wiki's setup. And it's
+   also getting old to have to manualy rebuild the wiki each time you
+   change a file. Time to introduce setup files. 
+   
+   A sample setup file is [[ikiwiki.setup]]. Download it (or copy it from
+   `doc/ikiwiki.setup` in the ikiwiki sources), and edit it. 
+   
+   Most of the options, like `wikiname` in the setup file are the same as
+   ikiwiki's command line options (documented in [[usage]]. `srcdir` and
+   `destdir` are the two directories you specify when running ikiwiki by
+   hand. `svnrepo` is the path to your subversion repository.  Make sure
+   that all of these are pointing to the right directories, and read
+   through and configure the rest of the file to your liking.
+
+   If you want to use something other than subversion, comment out the
+   subversion configuration, and uncomment and edit the configuration for
+   your chosen RCS.
+
+   Note that the default file has a block to configure a [[post-commit]] 
+   wrapper to update the wiki. You need to uncomment the related block for
+   whatever RCS you use and comment out the other rcs blocks.
+
+   When you're satisfied, run `ikiwiki --setup ikiwiki.setup`, and it
+   will set everything up and update your wiki.
+
+8. Set up [[CGI]] to allow editing the wiki from the web.
+
+   Just edit ikiwiki.setup, uncomment the block for the cgi wrapper, make
+   sure the filename for the cgi wrapper is ok, run 
+   `ikiwiki --setup ikiwiki.setup`, and you're done!
+
+9. Add [[PageHistory]] links to the top of pages. This requires you to have
+   setup a repository browser.  For Subversion, you may use [[ViewCVS]] or
+   something similar to access your [[Subversion]] repository.  For Git,
+   [[Gitweb]] can be used, etc.
+   
+   The `historyurl` setting makes ikiwiki add the links, and in that url,
+   "\[[file]]" is replaced with the name of the file to view. So edit
+   ikiwiki.setup and ucomment the appropriate `historyurl` setting and edit
+   it for your setup.
+   
+   Then run `ikiwiki --setup ikiwiki.setup` again.
+
+10. Enjoy your new wiki! Add yourself to [[IkiWikiUsers]].
diff --git a/1.33.2/doc/smileys.mdwn b/1.33.2/doc/smileys.mdwn
new file mode 100644 (file)
index 0000000..8d794cb
--- /dev/null
@@ -0,0 +1,43 @@
+This page is used to control what smileys are supported by the wiki.
+Just write the text of a smiley to display it.
+
+* \:)  [[smileys/smile.png]]
+* \:-) [[smileys/smile.png]]
+* \:D  [[smileys/biggrin.png]]
+* \B)  [[smileys/smile2.png]]
+* \:)) [[smileys/smile3.png]]
+* \:-))        [[smileys/smile3.png]]
+* \;)  [[smileys/smile4.png]]
+* \;-) [[smileys/smile4.png]]
+* \:\  [[smileys/ohwell.png]]
+* \:/  [[smileys/ohwell.png]]
+* \>:> [[smileys/devil.png]]
+* \X-( [[smileys/angry.png]]
+* \<:( [[smileys/frown.png]]
+* \:(  [[smileys/sad.png]]
+* \:-( [[smileys/sad.png]]
+* \:-? [[smileys/tongue.png]]
+* \:o  [[smileys/redface.png]]
+* \|)  [[smileys/tired.png]]
+* \|-) [[smileys/tired.png]]
+* \{OK}        [[smileys/thumbs-up.png]]
+* \{X} [[smileys/icon-error.png]]
+* \(./)        [[smileys/checkmark.png]]
+* \(!) [[smileys/idea.png]]
+* \[!] [[smileys/attention.png]]
+* \/!\ [[smileys/alert.png]]
+* \{*} [[smileys/star_on.png]]
+* \{o} [[smileys/star_off.png]]
+
+For example: {*} B) {*}
+
+----
+
+To change the supported smileys, just edit the lists on this page.
+Note that the format is important; each list item should start with the
+text that is turned into the smiley, escaped so that users can see what
+produces it, followed by a [[WikiLink]] to the image to display.
+
+/!\ Bear in mind that the link to the image needs to be written in a way that
+will work if it's copied to other pages on the wiki. So be sure to include the
+smileys directory in the path to the file.
diff --git a/1.33.2/doc/subversion.mdwn b/1.33.2/doc/subversion.mdwn
new file mode 100644 (file)
index 0000000..7cb994c
--- /dev/null
@@ -0,0 +1,9 @@
+[Subversion](http://subversion.tigris.org/) is a revision control system. While ikiwiki is relatively
+independent of the underlying revision control system, and can easily be
+used without one, using it with Subversion is recommended since it's how
+the author uses it. ([[Git]] is another option.)
+
+Ikiwiki can run as a [[post-commit]] hook to update a wiki whenever commits
+come in. When running as a [[cgi]] with Subversion, ikiwiki automatically
+commits edited pages to the subversion repostory, and uses the Subversion
+log to generate the [[RecentChanges]] page.
diff --git a/1.33.2/doc/tags.mdwn b/1.33.2/doc/tags.mdwn
new file mode 100644 (file)
index 0000000..8d3a85c
--- /dev/null
@@ -0,0 +1,22 @@
+While ikiwiki supports hierarchically categorising pages by creating
+[[SubPage]]s, that's often not flexible enough, and it can also be useful
+to tag pages in various non-hierarchical ways.
+
+Since this is a wiki, tagging is just a form of linking. For example, since
+this page links to [[features]], it can be considered to have something to
+do with ikiwiki's features. If you want to put pages into a category, the
+typical wiki way to do so is to create a "CategoryFoo" page and link pages
+in the category to it. That is just another form of tagging.
+
+Sometimes you may want to tag a page without putting a visible link on it.
+The [[tag_plugin|plugins/tag]] allows you to do so, like this:
+
+       \[[tag mytag othertag thirdtag]]
+
+One way to use these tags is to create a [[blog]] of pages that have a
+particular set of tags. Or just look at the [[BackLinks]] to a tag page to
+see all the pages that are tagged with it. [[Plugins]] can be written to do
+anything else with tags that you might desire.
+
+Once you have tags, you can use the [[plugins/pagestats]] plugin to
+generate tag clouds.
diff --git a/1.33.2/doc/templates.mdwn b/1.33.2/doc/templates.mdwn
new file mode 100644 (file)
index 0000000..05fdc44
--- /dev/null
@@ -0,0 +1,53 @@
+ikiwiki uses the HTML::Template module as its template engine. This
+supports things like conditionals and loops in templates and is pretty easy
+to learn.
+
+The aim is to keep almost all html out of ikiwiki and in the templates.
+
+It ships with some basic templates which can be customised:
+
+* `page.tmpl` - Used for displaying all regular wiki pages.
+* `misc.tmpl` - Generic template used for any page that doesn't
+  have a custom template.
+* `recentchanges.tmpl` - Used for the RecentChanges page.
+* `editpage.tmpl` - Create/edit page.
+* `notifymail.tmpl` - Not a html template, this is used to
+  generate change notification mails for users who have subscribed to
+  changes to a page.
+* `passwordmail.tmpl` - Not a html template, this is used to
+  generate the mail with the user's password in it.
+* `rsspage.tmpl` - Used for generating rss feeds for [[blog]]s.
+* `rssitem.tmpl` - Used for generating individual items on rss feeds.
+* `atompage.tmpl` - Used for generating atom feeds for [[blog]]s.
+* `atomitem.tmpl` - Used for generating individual items on atom feeds.
+* `inlinepage.tmpl` - Used for adding a page inline in a blog
+  page.
+* `inlinepagetitle.tmpl` - Used for listing a page inline in a blog
+  archive page.
+* `estseek.conf` - Not a html template, this is actually a template for
+  a config file for the [[HyperEstraier]] search engine. If you like you
+  can read the [[HyperEstraier]] docs and configure it using this.
+* `blogpost.tmpl` - Used for a form to add a post to a blog (and a rss/atom links)
+* `feedlink.tmpl` - Used to add rss/atom links if blogpost.tmpl is not used.
+* `aggregatepost.tmpl` - Used by the [[plugins/aggregate]] plugin to create
+  a page for a post.
+* `searchform.tmpl` - Used by the [[plugins/search]] plugin to add a search
+  form to wiki pages.
+
+If you like, you can add these to further customise it:
+
+* `signin.tmpl` - If it exists, it is used for customising the
+  layout of the SignIn form and all assciated forms. The misc.tmpl is
+  wrapped around this, so it should only be a template for the form.
+* `prefs.tmpl` - If it exists, it is used for customising the
+  layout of the Prefs form and all assciated forms. The misc.tmpl is
+  wrapped around this, so it should only be a template for the form.
+  
+Note that the SignIn and Prefs forms are implemented using
+CGI::FormBuilder, which interfaces to HTML::Template, so not all of it can
+be customised with templates, although most of it can, by creating these
+templates. Without the templates, CGI::FormBuilder creates the page bodies
+by itself.
+
+The [[plugins/template]] plugin also uses templates, though those templates
+are stored in the wiki.
diff --git a/1.33.2/doc/templates/note.mdwn b/1.33.2/doc/templates/note.mdwn
new file mode 100644 (file)
index 0000000..2cbc230
--- /dev/null
@@ -0,0 +1,3 @@
+<span class="notebox">
+<TMPL_VAR text>
+</span>
diff --git a/1.33.2/doc/templates/plugin.mdwn b/1.33.2/doc/templates/plugin.mdwn
new file mode 100644 (file)
index 0000000..ca69efd
--- /dev/null
@@ -0,0 +1,6 @@
+<span class="infobox">
+Plugin: <TMPL_VAR name><br />
+Author: <TMPL_VAR author><br />
+Enabled by default: <TMPL_IF core>yes<TMPL_ELSE>no</TMPL_IF><br />
+Included in ikiwiki: <TMPL_IF included>yes<TMPL_ELSE>no</TMPL_IF><br />
+</span>
diff --git a/1.33.2/doc/tla.mdwn b/1.33.2/doc/tla.mdwn
new file mode 100644 (file)
index 0000000..4c2b922
--- /dev/null
@@ -0,0 +1,8 @@
+[tla](http://wiki.gnuarch.org/) is an implementation of the
+[GNU](http://www.gnu.org/) [Arch](http://www.gnuarch.org/) revision control
+system. Ikiwiki supports storing a wiki in tla.
+
+Ikiwiki can run as a [[post-commit]] hook to update a wiki whenever commits
+come in. When running as a [[cgi]] with tla, ikiwiki automatically
+commits edited pages to the Arch repostory, and uses the Arch
+log to generate the [[RecentChanges]] page.
diff --git a/1.33.2/doc/todo.mdwn b/1.33.2/doc/todo.mdwn
new file mode 100644 (file)
index 0000000..a395232
--- /dev/null
@@ -0,0 +1,4 @@
+Welcome to ikiwiki's todo list. Link items to [[todo/done]] when done.
+
+[[inline pages="todo/* and !todo/done and !link(todo/done) and !*/Discussion"
+actions=yes rootpage="todo" show=0]]
diff --git a/1.33.2/doc/todo/Case.mdwn b/1.33.2/doc/todo/Case.mdwn
new file mode 100644 (file)
index 0000000..a19dbb2
--- /dev/null
@@ -0,0 +1,4 @@
+ikiwiki should support pages that have uppercase in their filenames.
+However, links to such pages should not need to exactly preserve the case.
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/Moving_Pages.mdwn b/1.33.2/doc/todo/Moving_Pages.mdwn
new file mode 100644 (file)
index 0000000..baf840a
--- /dev/null
@@ -0,0 +1,25 @@
+I thought I'd draw attention to a desire of mine for **ikiwiki**.  I'm no power-user, and mostly I do fairly simple stuff with my [wiki](http://kitenet.net/~kyle/family/wiki).
+
+However, I would like the ability (now) to **rename/move/delete** pages.  As part of having a genealogy wiki, I've put name and dates of birth/death as part of the title of each article (so to avoid cases where people have the same name, but are children/cousins/etc of others with that name).  However, some of this information changes.  For instance, I didn't know a date of death and now I do, or I had it wrong originally, or it turns out someone is still alive I didn't know about.  All of these cases leave me with bad article titles.
+
+So, I can go ahead and move the file to a new page with the correct info, orphan that page, provide a link for the new page if desired, and otherwise ignore that page.  But then, it clutters up the wiki and serves no useful purpose.
+
+Anyway to consider implementing **rename/move/delete** ?  I certainly lack the skills to appreciate what this would entail, but feel free to comment if it appears impossible, and then I'll go back to the aforementioned workaround.  I would prefer simple rename, however.
+
+Thanks again to [Joey](http://kitenet.net/~joey) for putting ikiwiki together.  I love the program. 
+
+*[Kyle](http://kitenet.net/~kyle/)=*
+
+----
+
+The MediaWiki moving/renaming mechanism is pretty nice.  It's easy to get a list of pages that point to the current page.  When renaming a page it sticks a forwarding page in the original place.  The larger the size of the wiki the more important organization tools become.
+
+I see the need for:
+
+* a new type of file to represent a forwarding page
+* a rename tool that can
+  * move the existing page to the new name
+  * optionally drop a forwarding page
+  * optionally rewrite incoming links to the new location
+
+Brad
\ No newline at end of file
diff --git a/1.33.2/doc/todo/Option_to_make_title_an_h1__63__.mdwn b/1.33.2/doc/todo/Option_to_make_title_an_h1__63__.mdwn
new file mode 100644 (file)
index 0000000..6673d7f
--- /dev/null
@@ -0,0 +1 @@
+Currently, the page title (either the name of the page or the title specified with `\[[meta title="..."]]`) shows up in a `<div class="header">`.  I tend to follow the [w3c guideline recommending the use of h1 for the title](http://www.w3.org/QA/Tips/Use_h1_for_Title); for this purpose, how about an option to make the page title an `<h1 class="header">`, and shift the markdown headings down by one (making # an h2, ## an h3, etc; or alternatively making # equivalent to `\[[meta title="..."]]`)?
\ No newline at end of file
diff --git a/1.33.2/doc/todo/RSS_links.mdwn b/1.33.2/doc/todo/RSS_links.mdwn
new file mode 100644 (file)
index 0000000..bfbd495
--- /dev/null
@@ -0,0 +1,17 @@
+The RSS feeds on a page should be indicated with &lt;link rel&gt;, so that
+they can be found by aggregators.
+
+--tumov
+
+I've been wondering about this. Ikiwiki's rss buttons include a
+type="application/rss+xml" and link to the rss file, and this is enough for
+at least some auto-discovery tools to find the rss feed. But apparently not
+all of them.
+
+For example, firefox requires the following:
+
+       <link rel="alternate" type="application/rss+xml" title="RSS" href="index.rss" />
+
+[[todo/done]]
+
+--[[Joey]]
diff --git a/1.33.2/doc/todo/adding_new_pages_by_using_the_web_interface.mdwn b/1.33.2/doc/todo/adding_new_pages_by_using_the_web_interface.mdwn
new file mode 100644 (file)
index 0000000..8ff7f12
--- /dev/null
@@ -0,0 +1,31 @@
+Perhaps I'm just too stupid to find the proper way to do this, but how
+would I add a new page to the wiki without selecting to edit an already
+installed one and frobbing the URL to direct to the to-be-created page?
+--[[ThomasSchwinge]]
+
+Good point. Of course one way is to start with creating a link to the page,
+which also helps prevent orphans. But other wikis based on CGI do have this
+a bit easier, since they can detect an attempt to access a nonexistant page
+and show an edit page. Ikiwiki can't do that (unless its web server is
+configured to do smart things on a 404, like maybe call ikiwiki.cgi which
+could be modified to work as a smart 404 -> edit handler).
+
+Some wikis also provide a UI means for creating a new page. If we can find
+something good, that can be added to ikiwiki's UI. --[[Joey]]
+
+Hmm, maybe just a preprocessor directive that creates a form inside a page,
+like is used for blog posting already would suffice? Then the main page of
+a wiki could have a form for adding new pages, if that directive were
+included there. Won't work for subpages though, unless the directive were
+added to the parent page. However, unconnected subpages are surely an even
+rarer thing to want than unconnected top level pages. --[[Joey]]
+
+> Here is a simple plugin that does that. Perhaps options could be added to
+> it, but I couldn't really think of any.
+> <http://jameswestby.net/scratch/create.diff>
+> -- JamesWestby
+
+Maybe a very simple PHP frontend for serving the
+statically generated pages, that would display a page editing form or
+something like that for non-existent pages, wouldn't be too bad a thing
+and resource hog? Just a thought... --[[Tuomov]]
diff --git a/1.33.2/doc/todo/aggregation.mdwn b/1.33.2/doc/todo/aggregation.mdwn
new file mode 100644 (file)
index 0000000..371d20c
--- /dev/null
@@ -0,0 +1,3 @@
+* Still need to support feed expiry.
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/automatic_rebuilding_of_html_pages.mdwn b/1.33.2/doc/todo/automatic_rebuilding_of_html_pages.mdwn
new file mode 100644 (file)
index 0000000..10482d6
--- /dev/null
@@ -0,0 +1,5 @@
+It seems that pages like [[Todo]] aren't rebuilt automatically when a new item is added using the web interface.
+
+AFAIK this is working ok. For example, this page appears in [[TODO]]. Maybe you need to force-refresh the page in your web browser? --[[Joey]]
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/automatic_use_of_syntax_plugin_on_source_code_files.mdwn b/1.33.2/doc/todo/automatic_use_of_syntax_plugin_on_source_code_files.mdwn
new file mode 100644 (file)
index 0000000..ea48f36
--- /dev/null
@@ -0,0 +1,3 @@
+Wishlist: optionally use the [[plugins/contrib/syntax]] plugin automatically on source code files in the repository with recognized extensions or shebangs, and render them as though they consisted of an [[.mdwn|markdown]] page containing nothing but a single call to the syntax plugin with the file contents as the text argument and the recognized type as the type argument.
+
+Together with the ability to have [[wiki-formatted_comments|wiki-formatted_comments_with_syntax_plugin]], this would allow the use of ikiwiki for [literate programming](http://en.wikipedia.org/wiki/Literate_programming).
\ No newline at end of file
diff --git a/1.33.2/doc/todo/blogging.mdwn b/1.33.2/doc/todo/blogging.mdwn
new file mode 100644 (file)
index 0000000..a316748
--- /dev/null
@@ -0,0 +1,137 @@
+- It would be possible to support rss enclosures for eg, podcasts, pretty easily. 
+
+Here is the last of those items. Using the meta plugin you can give the appropriate 
+info, and the enclosure will be added to the entry. It will also add a <link /> tag
+at the top, but I don't know if this is necessary. It also includes a fix for
+when make is used without PREFIX. 
+
+<http://jameswestby.net/scratch/podcast.diff>
+
+-- JamesWestby
+
+> Hmm. Not quite how I'd envisioned podcasts would work, my idea was
+> more that the sound files would be kept inside the wiki, and the
+> inline plugin could be told to eg, inline *.mp3, and would add
+> those to the rss feed as enclosures. Maybe you'd also inline some
+> regular blog pages to describe the files or the like.
+
+> Do you think that would work or that it's worth pursuing that
+> approach? I haven't looked at podcasts enough to know if that
+> method would be technically feasable; for one thing it would limit
+> the blog items for podcasts to just having an enclosure but no
+> description.
+
+> Even if that doesn't work and pages are needed to desribe the items
+> like you did, it still seems better to keep the podcast items in
+> the wiki..
+
+> --[[Joey]]
+
+That's fair enough. I'm a little unsure of how it all works, so I just did the
+simplest thing I could. 
+
+You don't need a description for podcasts it seems. So there's nothing stopping
+you there. 
+
+I have another patch that I think does what you want. It only supports .mp3 files,
+.ogg or similar could be added easily. 
+
+It has the disadvantage that the filename is all there is to go on, as I can't
+think of a way to associate any information with the mp3 file. I don't 
+want to add a dependency on a IDv3 tag library. You could add another file
+.mp3.info with the title/description in. 
+
+It's obviously up to you which way you want to go.
+
+<http://jameswestby.net/scratch/podcast2.diff>
+
+-- JamesWestby
+
+> Hmm, this could be taken a step further, and assume that if
+> IkiWiki::pagetype doesn't return a defined page type for the page
+> in the blog, then no matter the extension it should be fed into the
+> rss feed in an enclosure. This would allow for not only podcasting,
+> but vidcasting and a form of photo blogging. Or even an rss feed
+> containing the source of ikiwiki. ;-)
+> 
+> --[[Joey]]
+
+Yes I agree that this would be great, but rss2 spec says that enclosure
+must have mime-type. How about I use the File::MimeInfo trick from the 
+first patch to do this? I don't know why I didn't do this before.
+This will probably clean the code up a little as well. 
+
+What do you think of the change that when using raw, if the filetype is not
+known it adds an entry anyway? I did this so that the entries appear if
+this mode is used. It might be that this is not necessary, as can we assume
+that people wont use raw if they want to pod/vid/whatevercast?
+
+-- JamesWestby
+
+> Using File::Mimeinfo makes sense to me.
+
+> I think it probably makes sense to make the (html) blog page
+> add an entry with a link to the file that's in the enclosure in the
+> rss feed. Whether or not raw is being used.
+
+> Note: I'm still unsure about whether podcasts should support
+> descriptions for the enclosures or not. Here's an early podcast
+> that did use descriptions:
+> <http://static.userland.com/gems/backend/gratefulDead.xml>
+> Here's a contemporary podcast, which also uses descriptions:
+> <http://www.lugradio.org/episodes.rss>
+
+> The podcast client I use certianly doesn't care about the
+> descriptions. But it's podracer, probably not the thing most
+> podcast users use. :-)
+
+> --[[Joey]]
+
+I tested with amarok, and that also ignored the description.
+I am thinking of those where you have a mixed feed, and people
+using clients that ignore enclsures get pretty much a blank post,
+with just the filename, and the html page, which also just displays
+the filename.
+
+I don't think this is a big issue though, so I guess it's just which
+you think is the cleaner interface.
+
+I have also added the first of your ideas as well (though you seem to have
+removed it). It adds a parameter to inline `archive_after` which limits
+showing full entries to that number.
+
+<http://jameswestby.net/scratch/limit.diff>
+
+-- JamesWestby
+
+> I removed it because I don't really see the need for it anymore.
+> The added complexity doesn't seem worth it, unless someone needs the
+> features. --[[Joey]]
+
+And here is the updated podcast patch supporting any file type.
+
+<http://jameswestby.net/scratch/podcast2.diff>
+
+-- JamesWestby
+
+And here is a patch for the remaining item. It adds links to the bottom of
+inlined entries for edit and discuss (if they are enabled). It doesn't add
+links for edit if the filetype is not known. 
+
+The stylesheet should probably be done slightly better than I have. I just
+added a bit of spacing as the links were too close to the date. I have no
+skill in this area though. Perhaps you would like to use the list system 
+that you have for the links at the top.
+
+<http://jameswestby.net/scratch/actions.diff>
+
+-- JamesWestby
+
+> Thanks! I did tweak the css a bit. Not totally happy with it, but pretty
+> good I think. (I'll try to get to the other patches soon.) --[[Joey]]
+
+
+---
+
+I'm very happy to report that this is [[todo/done]]. Podcasting patch
+applied (finally!) --[[Joey]]
diff --git a/1.33.2/doc/todo/blogs.mdwn b/1.33.2/doc/todo/blogs.mdwn
new file mode 100644 (file)
index 0000000..8c9cba5
--- /dev/null
@@ -0,0 +1,4 @@
+ikiwiki needs to support blogging. Make subpages of a page turn into a blog
+with a special post-processor rune.
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/discussion_page_as_blog.mdwn b/1.33.2/doc/todo/discussion_page_as_blog.mdwn
new file mode 100644 (file)
index 0000000..eb11caa
--- /dev/null
@@ -0,0 +1,6 @@
+Look at a discussion page here or eg on wikipedia. It tends to turn into a mess. One nice way to avoid the mess would be to set it a discussion page as a blog so each new comment is a separate post.
+
+One issue is, would there be a way to do this for all new discussion pages by default somehow? Setting up the blog means inserting a preprocessor directive; and that could somehow happen automatically when the discussion page is first created. (Creating a bunch of empty discussion pages with such directives ahead of time would be silly.) Maybe some kind of new page template system would do the trick, so pages matching */Discussion start off as a clone of DiscussionTemplate. Although the first person to
+try to create the discussion page would still end up in an edit page with that template, which is not ideal. Hmm.
+
+Another issue is that discussions really want to be threaded. Does that mean that a page like foo/discussion/question should have its own foo/discussion/question/(discussion?)/answer page? Of course, rss feeds don't handle threading, and of course doing this might be dependant on the issue above. Worrying about threading may be overkill.
\ No newline at end of file
diff --git a/1.33.2/doc/todo/done.mdwn b/1.33.2/doc/todo/done.mdwn
new file mode 100644 (file)
index 0000000..8d01666
--- /dev/null
@@ -0,0 +1,3 @@
+recently fixed [[TODO]] items
+
+[[inline pages="link(todo/done) and !todo and !*/Discussion" show="10"]]
diff --git a/1.33.2/doc/todo/firm_up_plugin_interface.mdwn b/1.33.2/doc/todo/firm_up_plugin_interface.mdwn
new file mode 100644 (file)
index 0000000..a8d34ea
--- /dev/null
@@ -0,0 +1,42 @@
+I don't want this interface to be too firm; it's ok for a plugin like
+`ddate` to redefine an internal function like IkiWiki::displaytime if it
+wants to.. But plugins that still access stuff through IkiWiki:: should be
+aware that that stuff can change at any time and break them. Possibly without
+perl's type checking catching the breakage, in some cases. Plugins that
+only use exported symbols should not be broken by future ikiwiki changes.
+
+Functions used by only some plugins, undecided about exporting:
+
+* lockwiki, unlockwiki (aggregate)
+       Too internal to ever be exported.
+* loadindex (aggregate)
+       Too internal to ever be exported.
+* titlepage (aggregate)
+       Not until more than one thing uses it.
+* basename (polygen, inline, search, polygen)
+* dirname (linkmap, inline)
+       For basename and dirname, they could just use standard perl library
+       stuff. Howevever, ikiwiki's versions are slightly different and I'd
+       need to check if the standard versions work for the uses made in
+       these plugins. Inclined not to export.
+* abs2rel (linkmap, inline)
+       This *is* the library version, just optimised to work around a bug.
+       Don't export this.
+* possibly_foolish_untaint (aggregate, polygen)
+       Probably better to implement yourself.
+* htmlize
+* linkify
+* preprocess
+* filter
+       The 4 above are used by a few plugins, but problimatic since plugins 
+       typically also define functions with these names.. I also feel that
+       this part of ikiwiki needs some more work before it's set in stone.
+       These are always called together, in the same order, though
+       sometimes htmlize isn't included.
+
+Variables used by plugins but not exported yet:
+
+* %IkiWiki::pagecase (aggregate)
+* %IkiWIki::backlinks (pagestats)
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/html.mdwn b/1.33.2/doc/todo/html.mdwn
new file mode 100644 (file)
index 0000000..a99f87c
--- /dev/null
@@ -0,0 +1,4 @@
+Create some nice(r) stylesheets.
+
+Should be doable w/o touching a single line of code, just
+editing the [[templates]] and/or editing [[style.css]].
diff --git a/1.33.2/doc/todo/htmlvalidation.mdwn b/1.33.2/doc/todo/htmlvalidation.mdwn
new file mode 100644 (file)
index 0000000..6fe2d56
--- /dev/null
@@ -0,0 +1,47 @@
+  * Doctype is XHTML 1.0 Strict
+       
+       One consideration of course is that regular users might embed html
+       that uses deprecated presentational elements like &lt;center&gt;. At
+        least firefox seems to handle that mixture ok. 
+       --[[Joey]]
+
+  * [ [inlinepage] ] gets wrapped in &lt;p&gt;...&lt;/p&gt; which has a high chance of invalidating the page.
+
+       Since markdown does this, the only way I can think to fix it is to
+       make the inlined page text start with &lt;/p&gt; and end with
+       &lt;p&gt;. Ugly, and of course there could be problems with
+       markdown enclosing it in other spanning tags in some cases.
+       I've implemented this hack now. :-/ --[[Joey]]
+
+       I used this 'hack' myself, but yesterday I came up with a better idea:  
+           &lt;div class="inlinepage"&gt;  
+           [ [inlinepage] ]  
+           &lt;/div&gt;  
+       This prevents markdown enclosing and even adds a useful css identifier. Problem is that this should be added to every page and not in the template(s). --[[JeroenSchot]]
+
+       I can make ikiwiki add that around every inlined page easily
+       enough. However, where is it documented? Came up dry on google.
+       --[[Joey]]
+
+       From <http://daringfireball.net/projects/markdown/syntax#html>:
+       > The only restrictions are that block-level HTML elements e.g. &lt;div&gt;, &lt;table&gt;, &lt;pre&gt;, &lt;p&gt;, etc. must be separated from surrounding content by blank lines, and the start and end tags of the block should not be indented with tabs or spaces. Markdown is smart enough not to add extra (unwanted) &lt;p&gt; tags around HTML block-level tags. [snip]
+       > Note that Markdown formatting syntax is not processed within
+       > block-level HTML tags. E.g., you can't use Markdown-style \*emphasis\* inside an HTML block.
+
+       Because [ [inlinepage] ] isn't separated by a blank line it gets treated as a block-level element. Hmm, will this stop all formatting, including *'s to em-tags? --[[JeroenSchot]]
+
+    Ah didn't realize you meant it fixed it at the markdown level. I'll
+    think about making postprocessordirectives into
+    [[preprocessordirective]]s instead, then I could use that fix (but I'm not
+    sure how feasible it is to do that). --[[Joey]]
+
+    Done.. inlining is now a preprocessor directive, happens before
+    markdown, and the inlinepage template uses div as suggested, this does
+    prevent markdown from doing any annoying escaping of the preprocessor
+    directives, as well as preventing it wrapping subpages in &lt;p&gt;.
+    --[[Joey]]
+
+This page is now valid.
+Test: [validate this page](http://validator.w3.org/check?url=referer)
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/improve_globlists.mdwn b/1.33.2/doc/todo/improve_globlists.mdwn
new file mode 100644 (file)
index 0000000..86a4ba1
--- /dev/null
@@ -0,0 +1,8 @@
+Need to improve globlists, adding more powerful boolean expressions.
+The current behavior is to check for negated expressions, and not match if
+there are any, then check for normal expressions and match if any match,
+This fails if you want to do something like match only pages with tag foo
+that are under directory bar. I think we need parens for grouping, and
+probably also boolean OR.
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/link_map.mdwn b/1.33.2/doc/todo/link_map.mdwn
new file mode 100644 (file)
index 0000000..a02a792
--- /dev/null
@@ -0,0 +1,6 @@
+An idea: Use graphviz to generate a map of all the links between pages.
+(Could it be made clickable somehow?)
+
+Graphviz can output image maps. -- ChristofferSawicki
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/linkify_and_preprocessor_ordering.mdwn b/1.33.2/doc/todo/linkify_and_preprocessor_ordering.mdwn
new file mode 100644 (file)
index 0000000..2936d74
--- /dev/null
@@ -0,0 +1,24 @@
+Currently ikiwiki linkifies text, then runs preprocessor directives. This
+allows a directive to contain a wikilink inside a parameter, but since the
+wikilink expands to some arbitrary html, the parameter needs to be
+triple-quoted to avoid quotes in the expanded text from leaking out. This
+is rather non-obvious.
+
+One fix would be to switch the order, since linkification and preprocessing
+are relatively independant. Some directives, like inline, would need to keep
+on linkifiying the inlined pages, to make the links be resolved correctly,
+but that's ok. Any directives that outputed stuff that looked like a
+wikilink, but wasn't, would need to be changed.
+
+> This solution has been implemented and _seems_ ok.
+
+An alternative would be to change the wikilink regexp so it doesn't apply
+to wikilinks that are embedded inside preprocessor directives. I haven't
+found a way to do that yet, since perl doesn't allow variable-width
+negative lookbehind.
+
+Maybe processing wikilinks and preprocessor directives
+as part of the same loop would work, but that probably has its own
+issues.
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/lists.mdwn b/1.33.2/doc/todo/lists.mdwn
new file mode 100644 (file)
index 0000000..4fc3e68
--- /dev/null
@@ -0,0 +1,3 @@
+* list of all missing pages
+
+  [[todo/done]]
diff --git a/1.33.2/doc/todo/logo.mdwn b/1.33.2/doc/todo/logo.mdwn
new file mode 100644 (file)
index 0000000..616720e
--- /dev/null
@@ -0,0 +1,4 @@
+ikiwiki needs a logo. I'm thinking something simple like the word "ikiwiki"
+with the first "k" backwards; drawn to show that it's "wiki" reflected.
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/mailnotification.mdwn b/1.33.2/doc/todo/mailnotification.mdwn
new file mode 100644 (file)
index 0000000..37fe9a5
--- /dev/null
@@ -0,0 +1,59 @@
+Should support mail notification of new and changed pages.
+
+  Hmm, should be easy to implement this.. it runs as a svn post-coommit hook
+  already, so just look at the userdb, svnlook at what's changed, and send
+  mails to people who have subscribed.
+
+  A few details:
+  1. [[Joey]] mentioned that being able to subscribe to globs as well as
+     explicitly named pages would be desirable.
+  2. I think that since we're using Perl on the backend, being able to
+     let users craft their own arbitrary regexes would be good.
+
+     Joey points out that this is actually a security hole, because Perl
+     regexes let you embed (arbitrary?) Perl expressions inside them.  Yuck!
+
+(This is not actually true unless you "use re 'eval';", without which
+(?{ code }) is disabled for expressions which interpolate variables.
+See perldoc re, second paragraph of DESCRIPTION. It's a little iffy
+to allow arbitrary regexen, since it's fairly easy to craft a regular
+expression that takes unbounded time to run, but this can be avoided
+with the use of alarm to add a time limit. Something like
+
+    eval { # catches invalid regexen
+      no re 'eval'; # to be sure
+      local $SIG{ALRM} = sub { die };
+      alarm(1);
+      ... stuff involving m/$some_random_variable/ ...
+      alarm(0);
+    };
+    if ($@) { ... handle the error ... }
+
+should be safe. --[[WillThompson]])
+
+     It would also be good to be able to subscribe to all pages except discussion pages or the SandBox: `* !*/discussion !sandobx`, maybe --[[Joey]]
+
+  3. Of course if you do that, you want to have form processing on the user
+     page that lets them tune it, and probably choose literal or glob by
+     default.
+
+     I think that the new globlist() function should do everything you need.
+     Adding a field to the prefs page will be trivial --[[Joey]]
+
+  The first cut, I suppose, could use one sendmail process to batch-mail all
+  subscribers for a given page.  However, in the long run, I can see users
+  demanding a bit of feature creep:
+
+  4. Each user should be able to tune whether they see the actual diff parts or
+     not.
+  5. Each user should be able to set a maximum desired email size.
+  6. We might want to support a user-specified shibboleth string that will be
+     included in the email they receive so they can easily procmail the messages
+     into a folder.
+
+  --[[BrandenRobinson]]
+
+  I'm deferring these nicities until there's some demonstrated demand
+  --[[Joey]].
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/mercurial.mdwn b/1.33.2/doc/todo/mercurial.mdwn
new file mode 100644 (file)
index 0000000..e25039b
--- /dev/null
@@ -0,0 +1,4 @@
+* Need to get post commit hook working (or an example of how to use it.)
+* Need --ctime support.
+* rcs_notify is not implemented
+* Is the code sufficiently robust? It just warns when mercurial fails.
diff --git a/1.33.2/doc/todo/metadata.mdwn b/1.33.2/doc/todo/metadata.mdwn
new file mode 100644 (file)
index 0000000..bf81913
--- /dev/null
@@ -0,0 +1,19 @@
+There should be a way to add metadata to a page. Probably a plugin could do
+this, for example:
+
+       \[[meta foo="bar"]]
+
+Uses for this include:
+
+* Setting a page title that's not tied to the filename.
+* Any metadata that's generally useful on html pages.
+* Maybe as an alternate way to tag a page, like linking to the tag,
+  except it doesn't have to show up in the page text.
+* Recording page licenses.
+
+[[meta link=done]]
+[[meta title="supporting metadata..."]]
+[[meta author="Joey Hess"]]
+[[meta link="foo.css" rel="stylesheet" type="text/css"]]
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/multiple_templates.mdwn b/1.33.2/doc/todo/multiple_templates.mdwn
new file mode 100644 (file)
index 0000000..258d584
--- /dev/null
@@ -0,0 +1,9 @@
+> Another useful feature might be to be able to choose a different template
+> file for some pages; blog pages would use a template different from the
+> home page, even if both are managed in the same repository, etc.
+
+Well, that would probably be fairly easy to add if it used pagespecs to
+specify which pages use the non-default template.
+
+Hmm, I think the pagetemplate hook should allow one to get close enough to
+this in a plugin now.
diff --git a/1.33.2/doc/todo/onlinepageediting.mdwn b/1.33.2/doc/todo/onlinepageediting.mdwn
new file mode 100644 (file)
index 0000000..b38af65
--- /dev/null
@@ -0,0 +1,5 @@
+* Eventually, might want page deletion.
+* Eventually, might want file upload.
+* Page move? Link corrections?
+
+>(I left this comment in discussion, but it might be better here on the main page)  This is a function I would really like.  I am dealing with a situation, in creating a link for my family history, for instance to "Peter Richard MacLea (1888-c.1946)" and fleshing out an article with pictures and so on.  Then, I later find out that Peter died in 1948.  So, I want to move that page to "Peter Richard MacLea (1888-1948)".  There doesn't seem to be an easy way to do this.  The main problem being that I can easily create a second page with that data, but what happens to the old one?  Does it remain?  I would like to see at least a rename or page move function.... *[Kyle](http://kitenet.net/~kyle/family/wiki/)=*
diff --git a/1.33.2/doc/todo/onlinepageediting/discussion.mdwn b/1.33.2/doc/todo/onlinepageediting/discussion.mdwn
new file mode 100644 (file)
index 0000000..c3a92a6
--- /dev/null
@@ -0,0 +1,6 @@
+This is a function I would really like.  I am dealing with a situation, in creating a link for my family history, for instance to "Peter Richard MacLea (1888-c.1946)" and fleshing out an article with pictures and so on.
+Then, I later find out that Peter died in 1948.  So, I want to move that page to "Peter Richard MacLea (1888-1948)".  There doesn't seem to be an easy way to do this.  The main problem being that I can easily create a second page with that data, but what happens to the old one?  Does it remain?
+
+I would like to see at least a rename or page move function....
+
+*[Kyle](http://kitenet.net/~kyle/family/wiki/)=*
\ No newline at end of file
diff --git a/1.33.2/doc/todo/optimisations.mdwn b/1.33.2/doc/todo/optimisations.mdwn
new file mode 100644 (file)
index 0000000..40ffaf5
--- /dev/null
@@ -0,0 +1,11 @@
+Ikiwiki has already been optimised a lot, however..
+
+* Don't render blog archive pages unless a page is added/removed. Just
+  changing a page doesn't affect the archives as they show only the title.
+
+* Look at splitting up CGI.pm. But note that too much splitting can slow
+  perl down.
+
+* The backlinks calculation code is still O(N^2) on the number of pages.
+  If backlinks info were stored in the index file, it would go down to
+  constant time for iterative builds, though still N^2 for rebuilds.
diff --git a/1.33.2/doc/todo/pageindexes.mdwn b/1.33.2/doc/todo/pageindexes.mdwn
new file mode 100644 (file)
index 0000000..c2de20a
--- /dev/null
@@ -0,0 +1,5 @@
+Might be nice to support automatically generating an index based on headers
+in a page, for long pages. This could be done as a sanitize hook that
+parsed the html, with a preprocessordirective that controlled it.
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/pluggablerenderers.mdwn b/1.33.2/doc/todo/pluggablerenderers.mdwn
new file mode 100644 (file)
index 0000000..d542597
--- /dev/null
@@ -0,0 +1,3 @@
+Should be able to plug in support for rst or other markup formats.
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/plugin.mdwn b/1.33.2/doc/todo/plugin.mdwn
new file mode 100644 (file)
index 0000000..1188663
--- /dev/null
@@ -0,0 +1,36 @@
+Suggestions of ideas for plugins:
+
+* list of registered users - tricky because it sorta calls for a way to rebuild the page when a new user is registered. Might be better as a cgi?
+* [[sigs]] ?
+
+* Support [[RecentChanges]] as a regular page containing a plugin that
+  updates each time there is a change, and statically builds the recent
+  changes list. (Would this be too expensive/inflexible? There might be
+  other ways to do it as a plugin, like making all links to RecentChanges
+  link to the cgi and have the cgi render it on demand.) 
+
+  Or using an iframe
+  to inline the cgi, although firefox seems to render that nastily with
+  nested scroll bars. :-(
+
+* For PlaceWiki I want to be able to do some custom plugins, including one
+  that links together subpages about the same place created by different
+  users. This seems to call for a plugin that applies to every page w/o any
+  specific marker being used, and pre-or-post-processes the full page
+  content. It also needs to update pages when related pages are added,
+  so it needs to register dependencies pre-emptively between pages,
+  or something. It's possible that this is a special case of backlinks and
+  is best implemented by making backlinks a plugin somehow. --[[Joey]]
+
+* interwiki links
+
+* random page (cgi plugin; how to link to it easily?)
+
+All the kinds of plugins that blogging software has is also a possibility:
+
+* Blog post calendar
+
+* How about an event calendar. Events could be sub-pages with an embedded 
+ code to detail recurrance and/or event date/time
+
+* Vote taking plugin. It would need to store its data in a file in .ikiwiki/
diff --git a/1.33.2/doc/todo/plugin_data_storage.mdwn b/1.33.2/doc/todo/plugin_data_storage.mdwn
new file mode 100644 (file)
index 0000000..f56d41b
--- /dev/null
@@ -0,0 +1,58 @@
+ikiwiki currently stores some key data in .ikiwiki/index. Some plugins need a
+way to store additional data, and ideally it would be something managed by
+ikiwiki instead of ad-hoc because:
+
+* consistency is good
+* ikiwiki knows when a page is removed and can stop storing data for that
+  page; plugins have to go to some lengths to track that and remove their
+  data
+* it's generally too much code and work to maintain a separate data store
+
+The aggregate plugin is a use-case: of 324 lines, 70 are data storage and
+another 10 handle deletion. Also, it's able to use a format very like
+ikiwiki's, but it does need to store some lists in there, which complicates
+it some and means that a very naive translation between a big per-page hash
+and the .index won't be good enough.
+
+The current ikiwiki index format is not very flexible, although it is at
+least fairly easy and inexpensive to parse as well as hand-edit.
+
+Would this do: ?
+
+* Plugins can register savestate and loadstate hooks. The hook id is the
+  key used in the index file that the hook handles.
+* loadstate hooks are called and passed a list of all values for a page
+  that for the registered key, and the page name, and should store the data
+  somewhere
+* savestate hooks are called and passed a page, and should return a list of 
+  all values for that key for that page
+* If they need anything more complex than a list of values, they will need
+  to encode it somehow in the list.
+
+Hmm, that's potentially a lot of function calls per page eave load/save
+though.. For less function calls, only call each hook *once* per load/save,
+and it is passed/returns a big hash of pages and the values for each page.
+(Which probably means `%state=@_` for load and `return %state` for save.)
+
+It may also be better to just punt on lists, and require plugins that need
+even lists to encode them. Especially since in many cases, `join(" ", @list)`
+will do. Er hmm, if I do that though, I'm actually back to a big global
+%page_data that plugins can just toss data into, arn't I? So maybe that's
+%the right approach after all, hmm.. Except that needing to decode/encode list
+data all the time when using it would quite suck, so no, let's not do that.
+
+Note that for the aggregate plugin to use this, it will need some changes:
+
+* guid data will need to be stored as part of the data for the page
+  that was aggregated from that guid. Except, expired pages don't exit, but
+  still have guid data to store. Hmm.
+* All feeds will need to be marked as removable in loadstate, and only
+  unmarked if seen in preprocess. Then savestate will need to not only
+  remove any feeds still marked as such, but do the unlinking of pages
+  aggregated from them too.
+
+If I do this, I might as well also:
+
+* Change the link= link= stuff to just links=link+link etc.
+* Change the delimiter from space to comma; commas are rare in index files,
+  so less ugly escaped delimiters to deal with.
diff --git a/1.33.2/doc/todo/plugin_dependency_calulation.mdwn b/1.33.2/doc/todo/plugin_dependency_calulation.mdwn
new file mode 100644 (file)
index 0000000..a304f3b
--- /dev/null
@@ -0,0 +1,23 @@
+A few plugins need more complex dependency calculations than ikiwiki can do
+on its own:
+
+* Use of a version plugin should only make the page rebuild when it's built
+  with a new version of ikiwiki.
+* The [[plugins/sidebar]] plugin should make any page get rebuilt if a
+  sidebar is created "closer" to it than the current sidebar.
+* Some plugin might want to _always_ rebuild the page that uses it.
+* If backlinks were turned into a plugin, it would need to make a page
+  rebuild when its backlinks changed.
+
+These suggest there should be a way for plugins to have hooks that tweak
+the list of pages to rebuild.
+
+Which in turn suggests that there should *be* a list of pages to rebuild;
+currently there's not, and the best such an interface could do would be to
+rebuild the pages even if they were already going to be rebuilt for some
+other reason. (See [[optimisations]].)
+
+It also suggests that plugins will want to examine pages and/or
+[[store_data|plugin_data_storage]] about them to use in the dependency
+calculations. For example, the version plugin would need to store info
+about what pages use it.
diff --git a/1.33.2/doc/todo/recentchanges.mdwn b/1.33.2/doc/todo/recentchanges.mdwn
new file mode 100644 (file)
index 0000000..7337c3d
--- /dev/null
@@ -0,0 +1,23 @@
+* Why isn't it statically-genereated, but generated dynamically by CGI? It
+  seems like it could be beneficial to have it rendered in the post-commit
+  hook, just like everything else in the wiki. 
+
+  I hope to statically generate it eventually, currently the problem is
+  that it takes at least several seconds to generate the recentchanges
+  page, and adding several seconds to every page edit is not desiriable. If
+  the time can be reduced it could be done, I'm also not adverse to
+  adding an optional way to statically render it even at the current speed.
+
+* Also, is it planned/desired that recent changes generate the same
+  information in RSS feed format? This seems like it could be a useful way
+  to keep track of the wiki as a whole. 
+
+  This is used by various interwiki type things, I think, so should be
+  done..
+
+* Lastly, would it be possible to use the recent changes code with a
+  pagespec? I understand this sort of infringes on territory covered by the
+  inline plugin, but the inline plugin only puts a page in the RSS feed
+  once, when it's created, and I imagine some people -- some deranged,
+  obsessive-compulsive people like myself -- would like to know about the
+  changes made to existing pages as well as newly-created pages.
diff --git a/1.33.2/doc/todo/rss_title_description.mdwn b/1.33.2/doc/todo/rss_title_description.mdwn
new file mode 100644 (file)
index 0000000..cb71a0f
--- /dev/null
@@ -0,0 +1,35 @@
+There could be a better way of setting the title and description of the rss feeds. Perhaps 
+through the meta plugin, or extra options to the inline plugin.
+
+At the moment The description is the same for all feeds from
+a single wiki it seems, and the title is forced to be one word, 
+though I don't think it needs to be.
+
+A few pointers and I might be able to implement this myself. -- JamesWestby
+
+> I don't see any problem with the title, it's the same as the title
+> of the wiki page that the rss feed comes from, which can be set
+> using the meta plugin. There are no restrictions to one word or
+> anything like that. Just made ikiwiki emit the following in a test
+> feed:
+
+> > <title>billy bob&#39;s news</title>
+
+> Now, the description field currently defaults to the wiki name,
+> and that could indeed stand to be made configurable. Since the
+> current (svn) version of ikiwiki supports long, word-wrapped
+> blocks of text as parameters to [[PreProcessorDirective]]s, seems
+> to me the best way would be to simple modify inline.pm to make the
+> descripion configurable by such parameter, with a fallback to the
+> wiki name. You'll need to modify rsspage.tmpl to use whatever new
+> template variable you define, that should be all.
+
+> --[[Joey]]
+
+Apologies for the title thing. I tried it yesterday, and it onlt used the first word.
+I must have done something wrong. I'll have a look at implementing the description.
+Thanks. -- JamesWestby
+
+My patch can be found at <http://jameswestby.net/scratch/blog-desc.diff> -- JamesWestby
+
+> Thanks, [[todo/done]] --[[Joey]]
diff --git a/1.33.2/doc/todo/search.mdwn b/1.33.2/doc/todo/search.mdwn
new file mode 100644 (file)
index 0000000..79342f2
--- /dev/null
@@ -0,0 +1,5 @@
+* page name substring search
+* full text (use third-party tools?)
+    - hyperestraier looks nice
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/sigs.mdwn b/1.33.2/doc/todo/sigs.mdwn
new file mode 100644 (file)
index 0000000..f3ec2cb
--- /dev/null
@@ -0,0 +1,21 @@
+Need a way to sign name in page that's easier to type than "--\[[Joey]]"
+and that includes the date.
+
+What syntax do other wikis use for this? I'm considering "\[[--]]" (with
+spaces removed) as it has a nice nmemonic.
+
+OTOH, adding additional syntax for this would be counter to one of the
+design goals for ikiwiki: keeping as much markup as possible out of the
+wiki and not adding nonstandard markup. And it's not significantly hard to
+type "--\[[Joey]]", and as to the date, we do have page history.
+
+I'm also unsure how to possibly implement this. Seems ikiwiki would need to
+expand the rune to the user's name when a page is saved, but that leaves
+out svn commits.
+
+---
+
+Alternate idea: Make a sig plugin, which would expand --Name to
+--[[user/Name]] (the "user/" bit would be configurable). This would be very
+easy to do, although it would need to try to avoid false positives, such 
+as `--foo` in C code..
diff --git a/1.33.2/doc/todo/skip_option_for_inline_plugin.mdwn b/1.33.2/doc/todo/skip_option_for_inline_plugin.mdwn
new file mode 100644 (file)
index 0000000..ab310dc
--- /dev/null
@@ -0,0 +1,8 @@
+How about a skip option for [[plugins/inline]]?  This would allow things like the following:
+
+    \[[inline pages="news/*" show="5"]]
+    \[[inline pages="news/*" skip="5" show="5" archive="yes"]]
+
+> I just wrote a patch. [[patchqueue/skip_option_for_inline_plugin]] --Ethan
+
+[[todo/done]] --[[Joey]]
diff --git a/1.33.2/doc/todo/spam_fighting.mdwn b/1.33.2/doc/todo/spam_fighting.mdwn
new file mode 100644 (file)
index 0000000..1e20a0c
--- /dev/null
@@ -0,0 +1 @@
+Admins need the ability to block IP ranges. They can already ban users.
diff --git a/1.33.2/doc/todo/spell_check_plug-in.mdwn b/1.33.2/doc/todo/spell_check_plug-in.mdwn
new file mode 100644 (file)
index 0000000..2339b94
--- /dev/null
@@ -0,0 +1,5 @@
+A speel chek plug-in woold be fantaztik.  Anyone working on this?
+
+----
+
+Knot adz fair ass eye no --[[Joey]]
\ No newline at end of file
diff --git a/1.33.2/doc/todo/strftime.mdwn b/1.33.2/doc/todo/strftime.mdwn
new file mode 100644 (file)
index 0000000..3c85439
--- /dev/null
@@ -0,0 +1,4 @@
+There should be a --strftime switch that controls how all the dates are
+formatted.
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/tagging_with_a_publication_date.mdwn b/1.33.2/doc/todo/tagging_with_a_publication_date.mdwn
new file mode 100644 (file)
index 0000000..044ba2e
--- /dev/null
@@ -0,0 +1,17 @@
+Feature idea: I'd like to be able to tag pages in an ikiwiki blog with a
+publication date, and have the option of building a blog that excludes
+publication dates in the future.  (meta pubdate= ?)
+I'm using ikiwiki on git for a "tip of the day" RSS feed, and I'd like to
+be able to queue up a bunch of items instead of literally putting in one
+tip per day.  In the future I think this will come in handy for other
+Mainstream Media-oriented requirements such as "embargo dates" and "editor
+on vacation".
+
+> The problem with implementing a feature like this is that, since ikwiiki
+> is a wiki compiler, if something causes content to change based on the
+> date, then the wiki needs to be rebuilt periodically. So you'd need a
+> cron job or something.
+> 
+> Implemeting this feature probably needs 
+> [[todo/plugin_dependency_calulation]] to be implemented. --[[Joey]]
diff --git a/1.33.2/doc/todo/tags.mdwn b/1.33.2/doc/todo/tags.mdwn
new file mode 100644 (file)
index 0000000..7309ee6
--- /dev/null
@@ -0,0 +1,10 @@
+Stuff still needing to be done with tags:
+
+* It's unfortunate that the rss category (tag) support doesn't include
+  a domain="" attribute in the category elements. That would let readers
+  know how to follow back to the tag page in the wiki. However, the domain
+  attribute is specified to be the base url, to which the category is just
+  appended. So there's no way to add ".html", so the url won't be right.
+
+  This is one good argument for changing ikiwiki so that pages are all
+  dir/index.html, then a link to just "dir" works.
diff --git a/1.33.2/doc/todo/terminalclient.mdwn b/1.33.2/doc/todo/terminalclient.mdwn
new file mode 100644 (file)
index 0000000..b420a3d
--- /dev/null
@@ -0,0 +1,10 @@
+Hack together a local ikiwiki w/o a web server using w3m's cgi-less mode
+and $EDITOR. Browse around a wiki, select pages to edit and get dropped
+right into the editor and have the page committed to svn automatically.
+
+[[todo/done]]
+
+Less grandiosely, a simple command line util to add a new page would be
+useful, especially if it made it easy to add blog entries to the wiki. I
+have a special purpose version of this in my [blog
+script](http://kitenet.net/~joey/code/bin.html).
diff --git a/1.33.2/doc/todo/tla.mdwn b/1.33.2/doc/todo/tla.mdwn
new file mode 100644 (file)
index 0000000..3cca686
--- /dev/null
@@ -0,0 +1,2 @@
+* Need to get post commit hook code working.
+* Need some example urls for web based diffs.
diff --git a/1.33.2/doc/todo/toplevel_index.mdwn b/1.33.2/doc/todo/toplevel_index.mdwn
new file mode 100644 (file)
index 0000000..f5eba96
--- /dev/null
@@ -0,0 +1,63 @@
+Some inconsistences around the toplevel [[index]] page:
+
+* [[ikiwiki]] is a separate page; links to [[ikiwiki]] should better go to
+  the [[index]] though.
+* The toplevel [[ikiwiki/Discussion]] page has some weird parentlinks
+  behavior. This could be special cased around with the following patch.
+  However, I'm unsure if I like the idea of more special cases around this.
+  It would be better to find a way to make the toplevel index page not be a
+  special case at all.
+
+       --- IkiWiki/Render.pm   (revision 1187)
+       +++ IkiWiki/Render.pm   (working copy)
+       @@ -71,6 +71,7 @@
+               my $path="";
+               my $skip=1;
+               return if $page eq 'index'; # toplevel
+       +       $path=".." if $page=~s/^index\///;
+               foreach my $dir (reverse split("/", $page)) {
+                       if (! $skip) {
+                               $path.="../";
+
+---
+
+> I would like to suggest another tack, namely a bigger, better special case. 
+> The basic idea is that all indices of the form foo/bar/index get the wiki path foo/bar.
+> This makes some things more elegant:
+>
+> * All files having to do with foo/bar are in the foo/bar directory, rather 
+>   than the (admittedly minor) wart of having the index be in foo/.
+> * This sort of addresses [[bugs/broken_parentlinks]] in that example/ is 
+>   guaranteed to be a valid path. (There might be no index there, though.)
+> * This is more in line with standard HTML practice, as far as I understand it,
+>   namely that linking to a/b means a/b/index.html rather than a/b.html.
+>
+> This would change the inline plugin in strange ways -- I think if foo/index.html
+> contains \[[inline "* and !*/Discussion"]], it should skip inlining foo/index.html 
+> explicitly, but would inline index pages in child directories 
+> foo/bar/baz/index.html as bar/baz.
+>
+> It always bothers me that foo/bar/ files need a foo/bar.html in front of them, 
+> rather than a foo/bar/index.html, as is (to my mind) traditional.
+> 
+> Ethan
+>
+> Hmm, now I've had time to think about this, and this does conflict pretty hard with foo.html/Discussion 
+> pages. Well, back to the drawing board.
+>
+> Well, it seems unlikely that you'll have both foo/bar.html and foo/bar/index.html, 
+> so why not accept either as foo/bar? This would both preserve backwards
+> compatibility, as well as allow foo/bar/Discussion.
+>
+> Ethan
+>
+> No, in order for this to work, the wiki path foo/bar/baz could be any of:
+>
+> * foo/bar/baz.html
+> * foo/index/bar/index/baz.html
+> * foo/bar/index/baz.html
+> * foo/bar/index/baz/index.html
+>
+> Or many others. Which is probably even hackier than having both foo.html and foo/.
+>
+> Ethan
\ No newline at end of file
diff --git a/1.33.2/doc/todo/underlay.mdwn b/1.33.2/doc/todo/underlay.mdwn
new file mode 100644 (file)
index 0000000..9bcfea6
--- /dev/null
@@ -0,0 +1,13 @@
+Rather than copy the basewiki around everywhere, it should be configured to
+underlay the main srcdir, and pages be rendered from there if not in the
+srcdir. This would allow upgrades to add/edit pages in the basewiki.
+
+Implementaion will be slightly tricky since currently ikiwiki is hardcoded
+in many places to look in srcdir for pages. Also, there are possible
+security attacks in the vein of providing a file ikiwiki would normally
+skip in the srcdir, and tricking it to processing this file instead of the
+one from the underlaydir. -- Fixed by scanning srcdir first, then
+underlaydir, and refusing to add any files from underlaydir if they also
+exist in the srcdir. However, see [[security]] for caveats.
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/upgradehooks.mdwn b/1.33.2/doc/todo/upgradehooks.mdwn
new file mode 100644 (file)
index 0000000..47da734
--- /dev/null
@@ -0,0 +1,8 @@
+It's annoying to have to manually run --setup, especially for multiple
+blogs, on upgrade. Is the deb is used, there could be a postinst hook to do
+this.
+
+Let there be an /etc/ikiwiki/wikis, which just lists setup files and the
+user who owns them. postinst loops through, su's, and runs --setup. Voila!
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/utf8.mdwn b/1.33.2/doc/todo/utf8.mdwn
new file mode 100644 (file)
index 0000000..278fb93
--- /dev/null
@@ -0,0 +1,18 @@
+ikiwiki should support utf-8 pages, both input and output. To test, here's a
+utf-8 smiley:
+
+# ☺
+
+Currently ikiwiki is belived to be utf-8 clean itself; it tells perl to use
+binmode when reading possibly binary files (such as images) and it uses
+utf-8 compatable regexps etc.
+
+There may be the odd corner where utf-8 still doesn't work; these are being
+fixed as they're found.
+
+Notes:
+
+* Apache "AddDefaultCharset on" settings will not play well with utf-8
+  pages. Turn it off.
+
+[[todo/done]]
diff --git a/1.33.2/doc/todo/wiki-formatted_comments_with_syntax_plugin.mdwn b/1.33.2/doc/todo/wiki-formatted_comments_with_syntax_plugin.mdwn
new file mode 100644 (file)
index 0000000..a800aa6
--- /dev/null
@@ -0,0 +1 @@
+Wishlist item: I'd love to see the ability to optionally switch back to wiki syntax within the comments of code pretty-printed with the [[plugins/contrib/syntax]] plugin.  This would allow the use of links and formatting in comments.
\ No newline at end of file
diff --git a/1.33.2/doc/todo/wikilinkfeatures.mdwn b/1.33.2/doc/todo/wikilinkfeatures.mdwn
new file mode 100644 (file)
index 0000000..bf32daf
--- /dev/null
@@ -0,0 +1,4 @@
+- \[[John|Fred]] is a Wikipedia method for linking to the one page
+  while displaying it as the other, Kyle would like this.
+
+[[todo/done]]
diff --git a/1.33.2/doc/usage.mdwn b/1.33.2/doc/usage.mdwn
new file mode 100644 (file)
index 0000000..9e260ad
--- /dev/null
@@ -0,0 +1,267 @@
+# NAME
+
+ikiwiki - a wiki compiler
+
+# SYNOPSIS
+
+ikiwiki [options] source destination
+
+ikiwiki --setup configfile
+
+# DESCRIPTION
+
+`ikiwiki` is a wiki compiler. It builds static html pages for a wiki, from
+`source` in the [[MarkDown]] language (or others), and writes it out to
+`destination`.
+
+Note that most options can be shortened to single letters, and boolean
+flags such as --verbose can be negated with --no-verbose.
+
+# MODE OPTIONS
+
+These options control the mode that ikiwiki is operating in.
+
+* --refresh
+
+  Refresh the wiki, updating any changed pages. This is the default
+  behavior so you don't normally need to specify it.
+
+* --rebuild
+
+  Force a rebuild of all pages.
+
+* --cgi
+
+  Enable [[CGI]] mode. In cgi mode ikiwiki runs as a cgi script, and
+  supports editing pages, signing in, registration, and displaying
+  [[RecentChanges]].
+
+  To use ikiwiki as a [[CGI]] program you need to use --wrapper or --setup
+  to generate a wrapper. The wrapper will generally need to run suid 6755 to
+  the user who owns the `source` and `destination` directories.
+
+* --wrapper [file]
+
+  Generate a wrapper binary that is hardcoded to do action specified by
+  the other options, using the specified input files and `destination`
+  directory. The filename to use for the wrapper is optional.
+
+  The wrapper is designed to be safely made suid and be run by untrusted
+  users, as a [[post-commit]] hook, or as a [[CGI]].
+
+  Note that the generated wrapper will ignore all command line parameters.
+
+* --setup configfile
+
+  In setup mode, ikiwiki reads the config file, which is really a perl
+  program that can call ikiwiki internal functions.
+
+  The default action when --setup is specified is to automatically generate
+  wrappers for a wiki based on data in a config file, and rebuild the wiki.
+
+  [[ikiwiki.setup]] is an example of such a config file.
+
+* --wrappers
+
+  If used with --setup --refresh, this makes it also update any configured
+  wrappers.
+
+* --aggregate
+
+  If the [[plugins/aggregate]] plugin is enabled, this makes ikiwiki poll
+  configured feeds and save new posts to the srcdir.
+
+  Note that to rebuild previously aggregated posts, use the --rebuild option
+  along with this one. --rebuild will also force feeds to be polled even if
+  they were polled recently.
+
+* --render file
+
+  Renders a single file, outputting the resulting html. Does not save state,
+  so this cannot be used for building whole wikis, but it is useful for
+  previewing an edited file at the command line. Generally used in conjunction
+  with --setup to load in a wiki's setup:
+
+       ikiwiki --setup ~/ikiwiki.setup --render foo.mdwn
+
+* --version
+
+  Print ikiwiki version number.
+
+# CONFIG OPTIONS
+
+These options configure the wiki. Note that [[plugins]] can add additional
+configuration options of their own.
+
+* --wikiname
+
+  The name of the wiki, default is "wiki".
+
+* --templatedir
+
+  Specify the directory that the page [[templates]] are stored in.
+  Default is `/usr/share/ikiwiki/templates`, or another location as
+  configured at build time.
+
+* --underlaydir
+
+  Specify the directory that is used to underlay the source directory.
+  Source files will be taken from here unless overridden by a file in the
+  source directory. Default is `/usr/share/ikiwiki/basewiki` or another
+  location as configured at build time.
+
+* --wrappermode mode
+
+  Specify a mode to chmod the wrapper to after creating it.
+
+* --notify
+
+  Enable email notification of commits. This should be used when running
+  ikiwiki as a [[post-commit]] hook.
+
+* --rcs=svn, --no-rcs
+
+  Enable or disable use of a revision control system.
+
+  If you use svn, the `source` directory is assumed to be
+  a [[Subversion]] working copy.
+
+  If you use git, the `source` directory is assumed to be a clone of the
+  [[git]] repository.
+
+  If you use tla, the `source` directory is assumed to be a tla import.
+
+  If you use mercurial, the `source` directory is assumed to be the
+  [[mercurial]] repository.
+
+  In [[CGI]] mode, with a revision control system enabled pages edited via
+  the web will be committed. Also, the [[RecentChanges]] link will be placed
+  on pages.
+
+  svn is enabled by default.
+
+* --svnrepo /svn/wiki
+
+  Specify the location of the svn repository for the wiki. This is required
+  for using --notify with [[subversion]].
+
+* --svnpath trunk
+
+  Specify the path inside your svn reporistory where the wiki is located.
+  This defaults to trunk; change it if your wiki is at some other location
+  inside the repository.
+
+* --anonok, --noanonok
+
+  If anonok is set, it will allow anonymous web users, who have not signed in, to make changes to the wiki.
+
+  By default, anonymous users cannot edit the wiki.
+
+* --rss, --norss
+
+  If rss is set, ikiwiki will generate RSS feeds for pages that inline
+  a [[blog]].
+
+* --atom, --noatom
+
+  If atom is set, ikiwiki will generate Arom feeds for pages that inline
+  a [[blog]].
+
+* --pingurl url
+
+  Set this to the url to an XML-RPC service to ping when an RSS feed is
+  updated. For example, to ping Technorati, use the url
+  http://rpc.technorati.com/rpc/ping
+
+  This parameter can be specified multiple times to specify more than one
+  url to ping.
+
+* --url url
+
+  Specifies the url to the wiki. This is a required parameter in [[CGI]] mode.
+
+* --cgiurl http://url/ikiwiki.cgi
+
+  Specifies the url to the ikiwiki [[CGI]] script wrapper. Required when
+  building the wiki for links to the cgi script to be generated.
+
+* --historyurl url
+
+  Specifies the url to link to for page history browsing. In the url,
+  "\[[file]]" is replaced with the file to browse. It's common to use
+  [[ViewCVS]] for this.
+
+* --adminemail you@yourhost
+
+  Specifies the email address that ikiwiki should use for sending email.
+
+* --diffurl url
+
+  Specifies the url to link to for a diff of changes to a page. In the url,
+  "\[[file]]" is replaced with the file to browse, "\[[r1]]" is the old
+  revision of the page, and "\[[r2]]" is the new revision. It's common to use
+  [[ViewCVS]] for this.
+
+* --exclude regexp
+
+  Specifies a rexexp of source files to exclude from processing.
+  May be specified multiple times to add to exclude list.
+
+* --adminuser name
+
+  Specifies a username of a user who has the powers of a wiki admin.
+  Currently allows locking of any page, other powers may be added later.
+  May be specified multiple times for multiple admins.
+
+* --plugin name
+
+  Enables the use of the specified [[plugin|plugins]] in the wiki. 
+  Note that plugin names are case sensative.
+
+* --disable-plugin name
+
+  Disables use of a plugin. For example "--disable-plugin htmlscrubber"
+  to do away with html sanitization.
+
+* --discussion, --no-discussion
+
+  Enables or disables "Discussion" links from being added to the header of
+  every page. The links are enabled by default.
+
+* --timeformat format
+
+  Specify how to display the time or date. The format string is passed to the
+  strftime(3) function.
+
+* --verbose, --no-verbose
+
+  Be vebose about what is being done.
+
+* --syslog, --no-syslog
+
+  Log to syslog.
+
+* --w3mmode, --no-w3mmode
+
+  Enable [[w3mmode]], which allows w3m to use ikiwiki as a local CGI script,
+  without a web server.
+
+* --sslcookie
+
+  Only send cookies over an SSL connection. This should prevent them being
+  intercepted. If you enable this option then you must run at least the 
+  CGI portion of ikiwiki over SSL.
+
+* --getctime
+
+  Pull last changed time for each new page out of the revision control
+  system. This rarely used option provides a way to get the real creation
+  times of items in weblogs, for example when building a wiki from a new
+  subversion checkout. It is unoptimised and quite slow. It is best used
+  with --rebuild, to force ikiwiki to get the ctime for all pages.
+
+# AUTHOR
+
+Joey Hess <joey@kitenet.net>
+
+Warning: this page is automatically made into ikiwiki's man page, edit with care
diff --git a/1.33.2/doc/w3mmode.mdwn b/1.33.2/doc/w3mmode.mdwn
new file mode 100644 (file)
index 0000000..3afee5c
--- /dev/null
@@ -0,0 +1,11 @@
+It's possible to use all of ikiwiki's web features (page editing, etc) in
+the `w3m` web browser without using a web server. `w3m` supports local CGI
+scripts, and ikiwiki can be set up to run that way. This requires some
+special configuration:
+
+ * `w3mmode` must be enabled
+ * A CGI wrapper must be created, in ~/.ikiwiki/wrappers/
+ * `cgiurl` should be set to just the base of the filename of the CGI
+   wrapper.
+
+This [[ikiwiki.setup]] is an example of setting up a wiki using w3mmode.
diff --git a/1.33.2/doc/w3mmode/ikiwiki.setup b/1.33.2/doc/w3mmode/ikiwiki.setup
new file mode 100644 (file)
index 0000000..216e066
--- /dev/null
@@ -0,0 +1,33 @@
+#!/usr/bin/perl
+# Configuration file for ikiwiki (w3m mode).
+# Passing this to ikiwiki --setup will make ikiwiki generate wrappers and 
+# build the wiki.
+#
+# Remember to re-run ikiwiki --setup any time you edit this file.
+
+use IkiWiki::Setup::Standard {
+       wikiname => "ikiwiki",
+       
+       # Be sure to customise these..
+       srcdir => "doc",
+       destdir => "html",
+       
+       # Enable w3m mode.
+       w3mmode => 1,
+       cgiurl => 'ikiwiki.cgi',
+       rcs => "",
+
+       wrappers => [
+               {
+                       # The cgi wrapper.
+                       cgi => 1,
+                       wrapper => "$ENV{HOME}/.ikiwiki/wrappers/ikiwiki.cgi",
+                       wrappermode => "0755",
+               },
+       ],
+       
+       anonok => 1,
+       rss => 1,
+       atom => 1,
+       discussion => 1,
+}
diff --git a/1.33.2/doc/whyikiwiki.mdwn b/1.33.2/doc/whyikiwiki.mdwn
new file mode 100644 (file)
index 0000000..2bc1fe4
--- /dev/null
@@ -0,0 +1,15 @@
+Why call it ikiwiki? Well, partly because I'm sure some people will find
+this a pretty Iky Wiki, since it's so different from other Wikis. Partly
+because "ikiwiki" is a nice palindrome. Partly because its design turns
+the usual design for a Wiki inside-out and backwards.
+
+(BTW, I'm told that "iki" is Finnish for "forever" so ikiwiki is "forever
+wiki".)
+
+Oh, maybe you wanted to know why you'd want to choose ikiwiki instead of
+all the other wikis out there? Unless your personal strangeness
+significantly aligns with [[Joey]]'s, so that keeping everything in
+subversion, compiling websites to static html, and like design [[features]]
+appeal to you, you probably won't.
+
+Hmm, the above paragraph is less true today than it was when I wrote it.
diff --git a/1.33.2/ikiwiki-mass-rebuild b/1.33.2/ikiwiki-mass-rebuild
new file mode 100755 (executable)
index 0000000..7ec41e9
--- /dev/null
@@ -0,0 +1,29 @@
+#!/bin/sh
+set -e
+
+action="$@"
+
+wikilist=/etc/ikiwiki/wikilist
+
+processline () {
+       user="$1"
+       setup="$2"
+       
+       if [ -z "$user" ] || [ -z "$setup" ]; then
+               echo "parse failure in /etc/ikiwiki/wikilist, line: '$user $setup'" >&2
+               exit 1
+       fi
+       
+       if [ ! -f "$setup" ]; then
+               echo "warning: $setup specified in /etc/ikiwiki/wikilist does not exist, skipping" >&2
+       else
+               echo "Processing $setup as user $user ..."
+               su "$user" -c "ikiwiki -setup $setup $action"
+       fi
+}
+
+if [ -e "$wikilist" ]; then
+       grep -v '^#' $wikilist | grep -v '^$' | while read line; do 
+               processline $line
+       done
+fi
diff --git a/1.33.2/ikiwiki-w3m.cgi b/1.33.2/ikiwiki-w3m.cgi
new file mode 100755 (executable)
index 0000000..fd0b0d6
--- /dev/null
@@ -0,0 +1,15 @@
+#!/usr/bin/perl
+# ikiwiki w3m cgi meta-wrapper
+if (! exists $ENV{PATH_INFO} || ! length $ENV{PATH_INFO}) {
+       die "PATH_INFO should be set";
+}
+my $path=$ENV{PATH_INFO};
+$path=~s!/!!g;
+$path="$ENV{HOME}/.ikiwiki/wrappers/$path";
+if (! -x $path) {
+       print "Content-type: text/html\n\n";
+       print "Cannot find ikiwiki wrapper: $path\n";
+       exit 1;
+}
+exec $path;
+die "$path: exec error: $!";
diff --git a/1.33.2/ikiwiki.pl b/1.33.2/ikiwiki.pl
new file mode 100755 (executable)
index 0000000..60ba5e1
--- /dev/null
@@ -0,0 +1,134 @@
+#!/usr/bin/perl -T
+$ENV{PATH}="/usr/local/bin:/usr/bin:/bin";
+delete @ENV{qw{IFS CDPATH ENV BASH_ENV}};
+
+package IkiWiki;
+
+use warnings;
+use strict;
+use lib '.'; # For use without installation, removed by Makefile.
+use IkiWiki;
+
+sub usage () { #{{{
+       die "usage: ikiwiki [options] source dest\n";
+} #}}}
+
+sub getconfig () { #{{{
+       if (! exists $ENV{WRAPPED_OPTIONS}) {
+               %config=defaultconfig();
+               eval q{use Getopt::Long};
+               Getopt::Long::Configure('pass_through');
+               GetOptions(
+                       "setup|s=s" => \$config{setup},
+                       "wikiname=s" => \$config{wikiname},
+                       "verbose|v!" => \$config{verbose},
+                       "syslog!" => \$config{syslog},
+                       "rebuild!" => \$config{rebuild},
+                       "refresh!" => \$config{refresh},
+                       "render=s" => \$config{render},
+                       "wrappers!" => \$config{wrappers},
+                       "getctime" => \$config{getctime},
+                       "wrappermode=i" => \$config{wrappermode},
+                       "rcs=s" => \$config{rcs},
+                       "no-rcs" => sub { $config{rcs}="" },
+                       "anonok!" => \$config{anonok},
+                       "rss!" => \$config{rss},
+                       "atom!" => \$config{atom},
+                       "cgi!" => \$config{cgi},
+                       "discussion!" => \$config{discussion},
+                       "w3mmode!" => \$config{w3mmode},
+                       "notify!" => \$config{notify},
+                       "url=s" => \$config{url},
+                       "cgiurl=s" => \$config{cgiurl},
+                       "historyurl=s" => \$config{historyurl},
+                       "diffurl=s" => \$config{diffurl},
+                       "svnrepo" => \$config{svnrepo},
+                       "svnpath" => \$config{svnpath},
+                       "adminemail=s" => \$config{adminemail},
+                       "timeformat=s" => \$config{timeformat},
+                       "sslcookie!" => \$config{sslcookie},
+                       "httpauth!" => \$config{httpauth},
+                       "exclude=s@" => sub {
+                               $config{wiki_file_prune_regexp}=qr/$config{wiki_file_prune_regexp}|$_[1]/;
+                       },
+                       "adminuser=s@" => sub {
+                               push @{$config{adminuser}}, $_[1]
+                       },
+                       "templatedir=s" => sub {
+                               $config{templatedir}=possibly_foolish_untaint($_[1])
+                       },
+                       "underlaydir=s" => sub {
+                               $config{underlaydir}=possibly_foolish_untaint($_[1])
+                       },
+                       "wrapper:s" => sub {
+                               $config{wrapper}=$_[1] ? $_[1] : "ikiwiki-wrap"
+                       },
+                       "plugin=s@" => sub {
+                               push @{$config{plugin}}, $_[1];
+                       },
+                       "disable-plugin=s@" => sub {
+                               $config{plugin}=[grep { $_ ne $_[1] } @{$config{plugin}}];
+                       },
+                       "pingurl=s" => sub {
+                               push @{$config{pingurl}}, $_[1];
+                       },
+                       "version" => sub {
+                               print "ikiwiki version $IkiWiki::version\n";
+                               exit;
+                       },
+               ) || usage();
+
+               if (! $config{setup} && ! $config{render}) {
+                       loadplugins();
+                       usage() unless @ARGV == 2;
+                       $config{srcdir} = possibly_foolish_untaint(shift @ARGV);
+                       $config{destdir} = possibly_foolish_untaint(shift @ARGV);
+                       checkconfig();
+               }
+       }
+       else {
+               # wrapper passes a full config structure in the environment
+               # variable
+               eval possibly_foolish_untaint($ENV{WRAPPED_OPTIONS});
+               if ($@) {
+                       error("WRAPPED_OPTIONS: $@");
+               }
+               loadplugins();
+               checkconfig();
+       }
+} #}}}
+
+sub main () { #{{{
+       getconfig();
+       
+       if ($config{cgi}) {
+               lockwiki();
+               loadindex();
+               require IkiWiki::CGI;
+               cgi();
+       }
+       elsif ($config{setup}) {
+               require IkiWiki::Setup;
+               setup();
+       }
+       elsif ($config{wrapper}) {
+               lockwiki();
+               require IkiWiki::Wrapper;
+               gen_wrapper();
+       }
+       elsif ($config{render}) {
+               require IkiWiki::Render;
+               commandline_render();
+       }
+       else {
+               lockwiki();
+               loadindex();
+               require IkiWiki::Render;
+               rcs_update();
+               refresh();
+               rcs_notify() if $config{notify};
+               saveindex();
+       }
+} #}}}
+
+main;
diff --git a/1.33.2/mdwn2man b/1.33.2/mdwn2man
new file mode 100755 (executable)
index 0000000..e78a4d1
--- /dev/null
@@ -0,0 +1,41 @@
+#!/usr/bin/perl
+# Warning: hack
+
+my $prog=shift;
+my $section=shift;
+
+print ".TH $prog $section\n";
+
+while (<>) {
+       s{(\\?)\[\[([^\s\]]+)\]\]}{$1 ? "[[$2]]" : $2}eg;
+       if (/^#\s/) {
+               s/^#\s/.SH /;
+               <>; # blank;
+       }
+       s/^\s+//;
+       s/-/\\-/g;
+       s/^Warning:.*//g;
+       s/^$/.PP\n/;
+       s/\`//g;
+       s/^\*\s+(.*)/.IP "$1"/;
+       next if $_ eq ".PP\n" && $skippara;
+       if (/^.IP /) {
+               $inlist=1;
+               $spippara=0;
+       }
+       elsif (/.SH/) {
+               $skippara=0;
+               $inlist=0;
+       }
+       elsif (/^\./) {
+               $skippara=1;
+       }
+       else {
+               $skippara=0;
+       }
+       if ($inlist && $_ eq ".PP\n") {
+               $_=".IP\n";
+       }
+
+       print $_;
+}
diff --git a/1.33.2/pm_filter b/1.33.2/pm_filter
new file mode 100755 (executable)
index 0000000..89449bd
--- /dev/null
@@ -0,0 +1,16 @@
+#!/usr/bin/perl -i -p
+
+BEGIN {
+       $prefix=shift;
+       $ver=shift;
+}
+
+if (/INSTALLDIR_AUTOREPLACE/) {
+       $_=qq{my \$installdir="$prefix";};
+}
+elsif (/VERSION_AUTOREPLACE/) {
+       $_=qq{our \$version="$ver";};
+}
+elsif (/^use lib/) {
+       $_="";
+}
diff --git a/1.33.2/t/basename.t b/1.33.2/t/basename.t
new file mode 100755 (executable)
index 0000000..87ae42c
--- /dev/null
@@ -0,0 +1,12 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 6;
+
+BEGIN { use_ok("IkiWiki"); }
+
+is(IkiWiki::basename("/home/joey/foo/bar"), "bar");
+is(IkiWiki::basename("./foo"), "foo");
+is(IkiWiki::basename("baz"), "baz");
+is(IkiWiki::basename("/tmp/"), "");
+is(IkiWiki::basename("/home/joey/foo/"), "");
diff --git a/1.33.2/t/bestlink.t b/1.33.2/t/bestlink.t
new file mode 100755 (executable)
index 0000000..9358bf3
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 9;
+
+BEGIN { use_ok("IkiWiki"); }
+
+sub test ($$$) {
+       my $page=shift;
+       my $link=shift;
+       my @existing_pages=@{shift()};
+       
+       %IkiWiki::pagecase=();
+       %links=();
+       foreach my $page (@existing_pages) {
+               $IkiWiki::pagecase{lc $page}=$page;
+               $links{$page}=[];
+       }
+
+       return bestlink($page, $link);
+}
+
+is(test("bar", "foo", ["bar"]), "", "broken link");
+is(test("bar", "foo", ["bar", "foo"]), "foo", "simple link");
+is(test("bar", "FoO", ["bar", "foo"]), "foo", "simple link with different input case");
+is(test("bar", "foo", ["bar", "fOo"]), "fOo", "simple link with different page case");
+is(test("bar", "FoO", ["bar", "fOo"]), "fOo", "simple link with different page and input case");
+is(test("bar", "Foo", ["bar", "fOo", "foo", "fOO", "Foo", "fOo"]), "Foo", "in case of ambiguity, like case wins");
+is(test("bar", "foo", ["bar", "foo", "bar/foo"]), "bar/foo", "simple subpage link");
+is(test("bar", "foo/subpage", ["bar", "foo", "bar/subpage", "foo/subpage"]), "foo/subpage", "cross subpage link");
diff --git a/1.33.2/t/crazy-badass-perl-bug.t b/1.33.2/t/crazy-badass-perl-bug.t
new file mode 100755 (executable)
index 0000000..2781255
--- /dev/null
@@ -0,0 +1,18 @@
+#!/usr/bin/perl
+# DO NOT CHANGE ANYTHING IN THIS FILE.
+# THe crazy bug reproduced here will go away if any of the calls
+# to htmlize are changed.
+use warnings;
+use strict;
+use Test::More tests => 102;
+use Encode;
+
+BEGIN { use_ok("IkiWiki"); }
+
+# Initialize htmlscrubber plugin
+%config=IkiWiki::defaultconfig();
+$config{srcdir}=$config{destdir}="/dev/null";
+IkiWiki::loadplugins(); IkiWiki::checkconfig();
+ok(IkiWiki::htmlize("foo", "mdwn", readfile("t/test1.mdwn")));
+ok(IkiWiki::htmlize("foo", "mdwn", readfile("t/test3.mdwn")),
+       "wtf?") for 1..100;
diff --git a/1.33.2/t/dirname.t b/1.33.2/t/dirname.t
new file mode 100755 (executable)
index 0000000..197d00d
--- /dev/null
@@ -0,0 +1,12 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 6;
+
+BEGIN { use_ok("IkiWiki"); }
+
+is(IkiWiki::dirname("/home/joey/foo/bar"), "/home/joey/foo");
+is(IkiWiki::dirname("./foo"), ".");
+is(IkiWiki::dirname("baz"), "");
+is(IkiWiki::dirname("/tmp/"), "/tmp/");
+is(IkiWiki::dirname("/home/joey/foo/"), "/home/joey/foo/");
diff --git a/1.33.2/t/html.t b/1.33.2/t/html.t
new file mode 100755 (executable)
index 0000000..66e90d8
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More;
+
+my @pages;
+
+BEGIN {
+       @pages=qw(index todo features news plugins/map security);
+       if (! -x "/usr/bin/validate") {
+               plan skip_all => "/usr/bin/validate html validator not present";
+       }
+       else {
+               plan(tests => int @pages + 2);
+       }
+       use_ok("IkiWiki");
+}
+
+# Have to build the html pages first.
+# Note that just building them like this doesn't exersise all the possible
+# html that can be generated, in particular it misses some of the action
+# links at the top, etc.
+ok(system("make >/dev/null") == 0);
+
+foreach my $page (@pages) {
+        print "# Validating $page\n";
+       ok(system("validate html/$page.html") == 0);
+}
+
+# TODO: validate form output html
diff --git a/1.33.2/t/htmlize.t b/1.33.2/t/htmlize.t
new file mode 100755 (executable)
index 0000000..a9ccfed
--- /dev/null
@@ -0,0 +1,21 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 4;
+use Encode;
+
+BEGIN { use_ok("IkiWiki"); }
+
+# Initialize htmlscrubber plugin
+%config=IkiWiki::defaultconfig();
+$config{srcdir}=$config{destdir}="/dev/null";
+IkiWiki::loadplugins();
+IkiWiki::checkconfig();
+
+is(IkiWiki::htmlize("foo", "mdwn", "foo\n\nbar\n"), "<p>foo</p>\n\n<p>bar</p>\n",
+       "basic");
+is(IkiWiki::htmlize("foo", "mdwn", readfile("t/test1.mdwn")),
+       Encode::decode_utf8(qq{<p><img src="../images/o.jpg" alt="o" title="&oacute;" />\nóóóóó</p>\n}),
+       "utf8; bug #373203");
+ok(IkiWiki::htmlize("foo", "mdwn", readfile("t/test2.mdwn")),
+       "this file crashes markdown if it's fed in as decoded utf-8");
diff --git a/1.33.2/t/linkify.t b/1.33.2/t/linkify.t
new file mode 100755 (executable)
index 0000000..4de2b51
--- /dev/null
@@ -0,0 +1,81 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 13;
+
+BEGIN { use_ok("IkiWiki"); }
+
+sub linkify ($$$$) {
+       my $lpage=shift;
+       my $page=shift;
+
+       my $content=shift;
+       my @existing_pages=@{shift()};
+       
+       # This is what linkify and htmllink need set right now to work.
+       # This could change, if so, update it..
+       %IkiWiki::pagecase=();
+       %links=();
+       foreach my $page (@existing_pages) {
+               $IkiWiki::pagecase{lc $page}=$page;
+               $links{$page}=[];
+               $renderedfiles{"$page.mdwn"}=[$page];
+       }
+       %config=IkiWiki::defaultconfig();
+
+       return IkiWiki::linkify($lpage, $page, $content);
+}
+
+sub links_to ($$) {
+       my $link=shift;
+       my $content=shift;
+       
+       if ($content =~ m!<a href="[^"]*\Q$link\E[^"]*">!) {
+               return 1;
+       }
+       else {
+               print STDERR "# expected link to $link in $content\n";
+               return;
+       }
+}
+
+sub not_links_to ($$) {
+       my $link=shift;
+       my $content=shift;
+       
+       if ($content !~ m!<a href="[^"]*\Q$link\E[^"]*">!) {
+               return 1;
+       }
+       else {
+               print STDERR "# expected no link to $link in $content\n";
+               return;
+       }
+}
+
+sub links_text ($$) {
+       my $text=shift;
+       my $content=shift;
+       
+       if ($content =~ m!>\Q$text\E</a>!) {
+               return 1;
+       }
+       else {
+               print STDERR "# expected link text $text in $content\n";
+               return;
+       }
+}
+
+
+ok(links_to("bar", linkify("foo", "foo", "link to [[bar]] ok", ["foo", "bar"])), "ok link");
+ok(not_links_to("bar", linkify("foo", "foo", "link to \\[[bar]] ok", ["foo", "bar"])), "escaped link");
+ok(links_to("page=bar", linkify("foo", "foo", "link to [[bar]] ok", ["foo"])), "broken link");
+ok(links_to("bar", linkify("foo", "foo", "link to [[baz]] and [[bar]] ok", ["foo", "baz", "bar"])), "dual links");
+ok(links_to("baz", linkify("foo", "foo", "link to [[baz]] and [[bar]] ok", ["foo", "baz", "bar"])), "dual links");
+ok(links_to("bar", linkify("foo", "foo", "link to [[some_page|bar]] ok", ["foo", "bar"])), "named link");
+ok(links_text("some page", linkify("foo", "foo", "link to [[some_page|bar]] ok", ["foo", "bar"])), "named link text");
+ok(links_to("bar", linkify("foo", "foo", "link to [[some page|bar]] ok", ["foo", "bar"])), "named link, with whitespace");
+ok(links_text("some page", linkify("foo", "foo", "link to [[some page|bar]] ok", ["foo", "bar"])), "named link text, with whitespace");
+ok(links_text("Some long, & complex page name.", linkify("foo", "foo", "link to [[Some long, & complex page name.|bar]] ok, and this is not a link]] here", ["foo", "bar"])), "complex named link text");
+ok(links_to("foo/bar", linkify("foo/item", "foo", "link to [[bar]] ok", ["foo", "foo/item", "foo/bar"])), "inline page link");
+ok(links_to("bar", linkify("foo", "foo", "link to [[bar]] ok", ["foo", "foo/item", "foo/bar"])), "same except not inline");
+
diff --git a/1.33.2/t/pagename.t b/1.33.2/t/pagename.t
new file mode 100755 (executable)
index 0000000..96e6a87
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 5;
+
+BEGIN { use_ok("IkiWiki"); }
+
+# Used internally.
+$IkiWiki::hooks{htmlize}{mdwn}=1;
+
+is(pagename("foo.mdwn"), "foo");
+is(pagename("foo/bar.mdwn"), "foo/bar");
+is(pagename("foo.png"), "foo.png");
+is(pagename("foo"), "foo");
diff --git a/1.33.2/t/pagespec_match.t b/1.33.2/t/pagespec_match.t
new file mode 100755 (executable)
index 0000000..bf6c8cb
--- /dev/null
@@ -0,0 +1,48 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 35;
+
+BEGIN { use_ok("IkiWiki"); }
+
+ok(pagespec_match("foo", "*"));
+ok(pagespec_match("page", "?ag?"));
+ok(! pagespec_match("page", "?a?g?"));
+ok(pagespec_match("foo.png", "*.*"));
+ok(! pagespec_match("foo", "*.*"));
+ok(pagespec_match("foo", "foo or bar"), "simple list");
+ok(pagespec_match("bar", "foo or bar"), "simple list 2");
+ok(pagespec_match("foo", "f?? and !foz"));
+ok(! pagespec_match("foo", "f?? and !foo"));
+ok(! pagespec_match("foo", "* and !foo"));
+ok(! pagespec_match("foo", "foo and !foo"));
+ok(! pagespec_match("foo.png", "* and !*.*"));
+ok(pagespec_match("foo", "(bar or ((meep and foo) or (baz or foo) or beep))"));
+
+$links{foo}=[qw{bar baz}];
+ok(pagespec_match("foo", "link(bar)"));
+ok(! pagespec_match("foo", "link(quux)"));
+ok(pagespec_match("bar", "backlink(foo)"));
+ok(! pagespec_match("quux", "backlink(foo)"));
+
+$IkiWiki::pagectime{foo}=1154532692; # Wed Aug  2 11:26 EDT 2006
+$IkiWiki::pagectime{bar}=1154532695; # after
+ok(pagespec_match("foo", "created_before(bar)"));
+ok(! pagespec_match("foo", "created_after(bar)"));
+ok(! pagespec_match("bar", "created_before(foo)"));
+ok(pagespec_match("bar", "created_after(foo)"));
+ok(pagespec_match("foo", "creation_year(2006)"), "year");
+ok(! pagespec_match("foo", "creation_year(2005)"), "other year");
+ok(pagespec_match("foo", "creation_month(8)"), "month");
+ok(! pagespec_match("foo", "creation_month(9)"), "other month");
+ok(pagespec_match("foo", "creation_day(2)"), "day");
+ok(! pagespec_match("foo", "creation_day(3)"), "other day");
+
+# old style globlists
+ok(pagespec_match("foo", "foo bar"), "simple list");
+ok(pagespec_match("bar", "foo bar"), "simple list 2");
+ok(pagespec_match("foo", "f?? !foz"));
+ok(! pagespec_match("foo", "f?? !foo"));
+ok(! pagespec_match("foo", "* !foo"));
+ok(! pagespec_match("foo", "foo !foo"));
+ok(! pagespec_match("foo.png", "* !*.*"));
diff --git a/1.33.2/t/pagespec_merge.t b/1.33.2/t/pagespec_merge.t
new file mode 100755 (executable)
index 0000000..cbb0621
--- /dev/null
@@ -0,0 +1,44 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 25;
+
+BEGIN { use_ok("IkiWiki"); }
+
+sub same {
+       my $a=shift;
+       my $b=shift;
+       my $match=shift;
+       
+       my $imatch=(pagespec_match($match, $a) ||
+                   pagespec_match($match, $b));
+       my $cmatch=pagespec_match($match, IkiWiki::pagespec_merge($a, $b));
+       
+       return $imatch == $cmatch;
+}
+
+ok(same("foo", "bar", "foo"), "basic match 1");
+ok(same("foo", "bar", "bar"), "basic match 2");
+ok(same("foo", "bar", "foobar"), "basic failed match");
+ok(same("foo", "!bar", "foo"), "basic match with inversion");
+ok(same("foo", "!bar", "bar"), "basic failed match with inversion");
+ok(same("!foo", "bar", "foo"), "basic failed match with inversion 2");
+ok(same("!foo", "bar", "bar"), "basic match with inversion 2");
+ok(same("!foo", "!bar", "foo"), "double inversion failed match");
+ok(same("!foo", "!bar", "bar"), "double inversion failed match 2");
+ok(same("*", "!bar", "foo"), "glob+inversion match");
+ok(same("*", "!bar", "bar"), "matching glob and matching inversion");
+ok(same("* !foo", "!bar", "bar"), "matching glob and matching inversion");
+ok(same("* !foo", "!bar", "foo"), "matching glob with matching inversion and non-matching inversion");
+ok(same("* !foo", "!foo", "foo"), "matching glob with matching inversion and matching inversion");
+ok(same("b??", "!b??", "bar"), "matching glob and matching inverted glob");
+ok(same("f?? !f??", "!bar", "bar"), "matching glob and matching inverted glob");
+ok(same("b??", "!b?z", "bar"), "matching glob and non-matching inverted glob");
+ok(same("f?? !f?z", "!bar", "bar"), "matching glob and non-matching inverted glob");
+ok(same("!foo bar baz", "!bar", "bar"), "matching list and matching inversion");
+ok(pagespec_match("foo/Discussion",
+       IkiWiki::pagespec_merge("* !*/Discussion", "*/Discussion")), "should match");
+ok(same("* !*/Discussion", "*/Discussion", "foo/Discussion"), "Discussion merge 1");
+ok(same("*/Discussion", "* !*/Discussion", "foo/Discussion"), "Discussion merge 2");
+ok(same("*/Discussion !*/bar", "*/bar !*/Discussion", "foo/Discussion"), "bidirectional merge 1");
+ok(same("*/Discussion !*/bar", "*/bar !*/Discussion", "foo/bar"), "bidirectional merge 2");
diff --git a/1.33.2/t/pagetitle.t b/1.33.2/t/pagetitle.t
new file mode 100755 (executable)
index 0000000..1bb4421
--- /dev/null
@@ -0,0 +1,12 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 6;
+
+BEGIN { use_ok("IkiWiki"); }
+
+is(IkiWiki::pagetitle("foo_bar"), "foo bar");
+is(IkiWiki::pagetitle("foo_bar_baz"), "foo bar baz");
+is(IkiWiki::pagetitle("foo_bar__33__baz"), "foo bar&#33;baz");
+is(IkiWiki::pagetitle("foo_bar__1234__baz"), "foo bar&#1234;baz");
+is(IkiWiki::pagetitle("foo_bar___33___baz"), "foo bar &#33; baz");
diff --git a/1.33.2/t/pagetype.mdwn b/1.33.2/t/pagetype.mdwn
new file mode 100755 (executable)
index 0000000..76cacd8
--- /dev/null
@@ -0,0 +1,14 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 5;
+
+BEGIN { use_ok("IkiWiki"); }
+
+# Used internally.
+$IkiWiki::hooks{htmlize}{mdwn}=1;
+
+is(pagetype("foo.mdwn"), "mdwn");
+is(pagetype("foo/bar.mdwn"), "mdwn");
+is(pagename("foo.png"), undef);
+is(pagename("foo"), undef);
diff --git a/1.33.2/t/readfile.t b/1.33.2/t/readfile.t
new file mode 100755 (executable)
index 0000000..bb1c6ba
--- /dev/null
@@ -0,0 +1,12 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 3;
+use Encode;
+
+BEGIN { use_ok("IkiWiki"); }
+
+# should read files as utf8
+ok(Encode::is_utf8(readfile("t/test1.mdwn"), 1));
+is(readfile("t/test1.mdwn"),
+       Encode::decode_utf8('![o](../images/o.jpg "ó")'."\n".'óóóóó'."\n"));
diff --git a/1.33.2/t/syntax.t b/1.33.2/t/syntax.t
new file mode 100755 (executable)
index 0000000..cbbdee6
--- /dev/null
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More;
+
+my @progs="ikiwiki.pl";
+my @libs="IkiWiki.pm";
+push @libs, map { chomp; $_ } `find IkiWiki -type f -name \\*.pm`;
+
+plan(tests => (@progs + @libs));
+
+foreach my $file (@progs) {
+        ok(system("perl -T -c $file >/dev/null 2>&1") eq 0, $file);
+}
+foreach my $file (@libs) {
+        ok(system("perl -c $file >/dev/null 2>&1") eq 0, $file);
+}
diff --git a/1.33.2/t/test1.mdwn b/1.33.2/t/test1.mdwn
new file mode 100644 (file)
index 0000000..f4ebc2c
--- /dev/null
@@ -0,0 +1,2 @@
+![o](../images/o.jpg "ó")
+óóóóó
diff --git a/1.33.2/t/test2.mdwn b/1.33.2/t/test2.mdwn
new file mode 100644 (file)
index 0000000..7e9b15f
--- /dev/null
@@ -0,0 +1,5 @@
+<form>
+</form>
+<ul>
+<li>ş <--
+</ul>
diff --git a/1.33.2/t/test3.mdwn b/1.33.2/t/test3.mdwn
new file mode 100644 (file)
index 0000000..541628b
--- /dev/null
@@ -0,0 +1 @@
+<h1>☺</h1>
diff --git a/1.33.2/t/titlepage.t b/1.33.2/t/titlepage.t
new file mode 100755 (executable)
index 0000000..6e1856a
--- /dev/null
@@ -0,0 +1,12 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 6;
+
+BEGIN { use_ok("IkiWiki"); }
+
+is(IkiWiki::titlepage("foo bar"), "foo_bar");
+is(IkiWiki::titlepage("foo bar baz"), "foo_bar_baz");
+is(IkiWiki::titlepage("foo bar/baz"), "foo_bar/baz");
+is(IkiWiki::titlepage("foo bar&baz"), "foo_bar__38__baz");
+is(IkiWiki::titlepage("foo bar & baz"), "foo_bar___38___baz");
diff --git a/1.33.2/templates/aggregatepost.tmpl b/1.33.2/templates/aggregatepost.tmpl
new file mode 100644 (file)
index 0000000..5b0f2f4
--- /dev/null
@@ -0,0 +1,12 @@
+<TMPL_VAR CONTENT>
+<TMPL_LOOP NAME="TAGS">
+[[tag <TMPL_VAR TAG>]]
+</TMPL_LOOP>
+<TMPL_IF NAME="TITLE">
+[[meta title="<TMPL_VAR NAME="TITLE" ESCAPE=HTML>"]]
+</TMPL_IF>
+<TMPL_IF NAME="PERMALINK">
+[[meta permalink="<TMPL_VAR NAME="PERMALINK" ESCAPE=HTML>"]]
+</TMPL_IF>
+[[meta author="<TMPL_VAR NAME="NAME" ESCAPE=HTML>"]]
+[[meta authorurl="<TMPL_VAR NAME="URL" ESCAPE=HTML>"]]
diff --git a/1.33.2/templates/atomitem.tmpl b/1.33.2/templates/atomitem.tmpl
new file mode 100644 (file)
index 0000000..0055192
--- /dev/null
@@ -0,0 +1,24 @@
+<entry>
+       <title><TMPL_VAR TITLE ESCAPE=HTML></title>
+       <TMPL_IF NAME="AUTHOR">
+       <author><TMPL_VAR AUTHOR ESCAPE=HTML></author>
+       <TMPL_ELSE>
+       </TMPL_IF>
+       <id><TMPL_VAR URL></id>
+       <link href="<TMPL_VAR PERMALINK>"/>
+       <TMPL_IF NAME="CATEGORIES">
+       <TMPL_LOOP NAME="CATEGORIES">
+       <category><TMPL_VAR CATEGORY></category>
+       </TMPL_LOOP>
+       </TMPL_IF>
+       <updated><TMPL_VAR DATE_3339></updated>
+       <TMPL_IF NAME="ENCLOSURE">
+       <link rel="enclosure" type="<TMPL_VAR TYPE>" href="<TMPL_VAR ENCLOSURE>" length="<TMPL_VAR LENGTH>" />
+       <TMPL_ELSE>
+       <content type="xhtml" xml:lang="en">
+        <div xmlns="http://www.w3.org/1999/xhtml">
+        ![CDATA[<TMPL_VAR CONTENT>]]
+        </div>
+       </content>
+       </TMPL_IF>
+</entry>
diff --git a/1.33.2/templates/atompage.tmpl b/1.33.2/templates/atompage.tmpl
new file mode 100644 (file)
index 0000000..1c672f4
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<feed xmlns="http://www.w3.org/2005/Atom">
+<title><TMPL_VAR TITLE ESCAPE=HTML></title>
+<link href="<TMPL_VAR PAGEURL>"/>
+<link href="<TMPL_VAR FEEDURL>" rel="self"/>
+<author>
+<name><TMPL_VAR WIKINAME></name>
+</author>
+<id><TMPL_VAR PAGEURL></id>
+<subtitle type="html"><TMPL_VAR FEEDDESC ESCAPE=HTML></subtitle>
+<generator uri="http://ikiwiki.kitenet.net/" version="<TMPL_VAR VERSION>">ikiwiki</generator>
+<updated><TMPL_VAR FEEDDATE></updated>
+<TMPL_VAR CONTENT>
+</feed>
diff --git a/1.33.2/templates/blogpost.tmpl b/1.33.2/templates/blogpost.tmpl
new file mode 100644 (file)
index 0000000..9fbf9a7
--- /dev/null
@@ -0,0 +1,15 @@
+<form action="<TMPL_VAR CGIURL>" method="get">
+<div id="blogform">
+<TMPL_IF NAME="RSSURL">
+<a class="feedbutton" type="application/rss+xml" href="<TMPL_VAR NAME=RSSURL>">RSS</a>
+</TMPL_IF>
+<TMPL_IF NAME="ATOMURL">
+<a class="feedbutton" type="application/atom+xml" href="<TMPL_VAR NAME=ATOMURL>">Atom</a>
+</TMPL_IF>
+<input type="hidden" name="do" value="blog" />
+<input type="hidden" name="from" value="<TMPL_VAR ROOTPAGE>" />
+<input type="hidden" name="subpage" value="1" />
+Add a new post titled: <input name="title" size="40" />
+<input type="submit" value="Edit" />
+</div>
+</form>
diff --git a/1.33.2/templates/editpage.tmpl b/1.33.2/templates/editpage.tmpl
new file mode 100644 (file)
index 0000000..f63a4b0
--- /dev/null
@@ -0,0 +1,57 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+<base href="<TMPL_VAR BASEURL>" />
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title><TMPL_VAR FORM-TITLE></title>
+<link rel="stylesheet" href="<TMPL_VAR BASEURL>style.css" type="text/css" />
+<link rel="stylesheet" href="<TMPL_VAR BASEURL>local.css" type="text/css" />
+<TMPL_IF NAME="FAVICON">
+<link rel="icon" href="<TMPL_VAR BASEURL><TMPL_VAR FAVICON>" type="image/x-icon" />
+</TMPL_IF>
+</head>
+<body>
+<TMPL_IF NAME="PAGE_CONFLICT">
+<p>
+<b>Your changes conflict with other changes made to the page.</b>
+</p>
+<p>
+Conflict markers have been inserted into the page content. Reconcile the
+conflict and commit again to save your changes.
+</p>
+</TMPL_IF>
+<TMPL_VAR FORM-START>
+<div class="header">
+<span><TMPL_VAR INDEXLINK>/ <TMPL_VAR FORM-TITLE></span>
+</div>
+<TMPL_VAR FIELD-DO>
+<TMPL_VAR FIELD-FROM>
+<TMPL_VAR FIELD-RCSINFO>
+<TMPL_IF NAME="PAGE_SELECT">
+Page location: <TMPL_VAR FIELD-PAGE>
+Page type: <TMPL_VAR FIELD-TYPE>
+<TMPL_ELSE>
+<br />
+<TMPL_VAR FIELD-PAGE>
+<TMPL_VAR FIELD-TYPE>
+</TMPL_IF>
+<TMPL_VAR FIELD-EDITCONTENT><br />
+<TMPL_IF NAME="CAN_COMMIT">
+Optional comment about this change:<br />
+<TMPL_VAR FIELD-COMMENTS><br />
+</TMPL_IF>
+<input id="_submit" name="_submit" type="submit" value="Save Page" /><input id="_submit_2" name="_submit" type="submit" value="Preview" /><input id="_submit_3" name="_submit" type="submit" value="Cancel" />
+<TMPL_VAR HELPONFORMATTINGLINK>
+<TMPL_VAR FORM-END>
+<TMPL_IF NAME="PAGE_PREVIEW">
+<hr />
+<div class="header">
+<span>Page preview:</span>
+</div>
+<div id="content">
+<TMPL_VAR PAGE_PREVIEW>
+</div>
+</TMPL_IF>
+</body>
+</html>
diff --git a/1.33.2/templates/estseek.conf b/1.33.2/templates/estseek.conf
new file mode 100644 (file)
index 0000000..43bd303
--- /dev/null
@@ -0,0 +1,31 @@
+indexname: <TMPL_VAR INDEX>
+tmplfile: <TMPL_VAR TMPLFILE>
+topfile: /dev/null
+logfile:
+logformat: 
+replace: ^file://<TMPL_VAR DESTDIR>{{!}}<TMPL_VAR URL>
+showreal: false
+perpage: 10,20,30,40,50,100
+attrselect: false
+showscore: false
+extattr: date|Date
+snipwwidth: 480
+sniphwidth: 96
+snipawidth: 96
+condgstep: 2
+dotfidf: true
+scancheck: false
+smplphrase: true
+phraseform: 2
+candetail: true
+smlrvnum: 0
+smlrtune: 16 1024 4096
+clipview: 2
+relkeynum: 0
+spcache:
+wildmax: 256
+qxpndcmd:
+helpfile: estseek.help
+deftitle: 
+attrwidth: 80
+dispproxy: 
diff --git a/1.33.2/templates/feedlink.tmpl b/1.33.2/templates/feedlink.tmpl
new file mode 100644 (file)
index 0000000..2963156
--- /dev/null
@@ -0,0 +1,8 @@
+<div id="feedlink">
+<TMPL_IF NAME="RSSURL">
+<a class="feedbutton" type="application/rss+xml" href="<TMPL_VAR NAME=RSSURL>">RSS</a>
+</TMPL_IF>
+<TMPL_IF NAME="ATOMURL">
+<a class="feedbutton" type="application/atom+xml" href="<TMPL_VAR NAME=ATOMURL>">Atom</a>
+</TMPL_IF>
+</div>
diff --git a/1.33.2/templates/inlinepage.tmpl b/1.33.2/templates/inlinepage.tmpl
new file mode 100644 (file)
index 0000000..3657a17
--- /dev/null
@@ -0,0 +1,46 @@
+<div class="inlinepage">
+<TMPL_IF NAME="AUTHOR">
+<span class="author">
+<TMPL_IF NAME="AUTHORURL">
+<a href="<TMPL_VAR NAME=AUTHORURL>"><TMPL_VAR NAME=AUTHOR></a>
+<TMPL_ELSE>
+<TMPL_VAR NAME=AUTHOR>
+</TMPL_IF>
+</span>
+</TMPL_IF>
+<span class="header">
+<TMPL_IF NAME="PERMALINK">
+<a href="<TMPL_VAR PERMALINK>"><TMPL_VAR TITLE></a>
+<TMPL_ELSE>
+<a href="<TMPL_VAR PAGEURL>"><TMPL_VAR TITLE></a>
+</TMPL_IF>
+</span>
+<TMPL_VAR CONTENT>
+
+<span class="pageinfo">
+Posted <TMPL_VAR CTIME>
+</span>
+
+<span class="tags">
+<TMPL_IF NAME="TAGS">
+Tags:
+<TMPL_LOOP NAME="TAGS">
+<TMPL_VAR NAME=LINK>
+</TMPL_LOOP>
+</TMPL_IF>
+</span>
+
+<TMPL_IF NAME="HAVE_ACTIONS">
+<span class="actions">
+<ul>
+<TMPL_IF NAME="EDITURL">
+<li><a href="<TMPL_VAR EDITURL>">Edit</a></li>
+</TMPL_IF>
+<TMPL_IF NAME="DISCUSSIONLINK">
+<li><TMPL_VAR DISCUSSIONLINK></li>
+</TMPL_IF>
+</ul>
+</span>
+</TMPL_IF>
+
+</div>
diff --git a/1.33.2/templates/inlinepagetitle.tmpl b/1.33.2/templates/inlinepagetitle.tmpl
new file mode 100644 (file)
index 0000000..6bc789d
--- /dev/null
@@ -0,0 +1,7 @@
+<p>
+<a href="<TMPL_VAR PAGEURL>"><TMPL_VAR TITLE></a><br />
+<i>
+Posted <TMPL_VAR CTIME>
+</i>
+
+</p>
diff --git a/1.33.2/templates/misc.tmpl b/1.33.2/templates/misc.tmpl
new file mode 100644 (file)
index 0000000..32e2c93
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+<base href="<TMPL_VAR BASEURL>" />
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title><TMPL_VAR TITLE></title>
+<link rel="stylesheet" href="<TMPL_VAR BASEURL>style.css" type="text/css" />
+<link rel="stylesheet" href="<TMPL_VAR BASEURL>local.css" type="text/css" />
+<TMPL_IF NAME="FAVICON">
+<link rel="icon" href="<TMPL_VAR BASEURL><TMPL_VAR FAVICON>" type="image/x-icon" />
+</TMPL_IF>
+</head>
+<body>
+
+<div class="header">
+<span>
+<TMPL_VAR INDEXLINK>/ <TMPL_VAR TITLE>
+</span>
+</div>
+
+<div id="content">
+<TMPL_VAR PAGEBODY>
+</div>
+
+<div id="footer">
+<!-- from <TMPL_VAR NAME=WIKINAME> -->
+</div>
+
+</body>
+</html>
diff --git a/1.33.2/templates/notifymail.tmpl b/1.33.2/templates/notifymail.tmpl
new file mode 100644 (file)
index 0000000..978b8a2
--- /dev/null
@@ -0,0 +1,4 @@
+The following change was made to <TMPL_VAR WIKINAME> by <TMPL_VAR USER>:
+
+<TMPL_VAR MESSAGE>
+<TMPL_VAR DIFF>
diff --git a/1.33.2/templates/page.tmpl b/1.33.2/templates/page.tmpl
new file mode 100644 (file)
index 0000000..305e779
--- /dev/null
@@ -0,0 +1,87 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title><TMPL_VAR TITLE></title>
+<link rel="stylesheet" href="<TMPL_VAR BASEURL>style.css" type="text/css" />
+<link rel="stylesheet" href="<TMPL_VAR BASEURL>local.css" type="text/css" />
+<TMPL_IF NAME="FAVICON">
+<link rel="icon" href="<TMPL_VAR BASEURL><TMPL_VAR FAVICON>" type="image/x-icon" />
+</TMPL_IF>
+<TMPL_IF NAME="FEEDLINKS"><TMPL_VAR FEEDLINKS></TMPL_IF>
+<TMPL_IF NAME="META"><TMPL_VAR META></TMPL_IF>
+</head>
+<body>
+
+<div class="header">
+<span>
+<TMPL_LOOP NAME="PARENTLINKS">
+<a href="<TMPL_VAR NAME=URL>"><TMPL_VAR NAME=PAGE></a>/ 
+</TMPL_LOOP>
+<TMPL_VAR TITLE>
+</span>
+<TMPL_IF NAME="SEARCHFORM">
+<TMPL_VAR SEARCHFORM>
+</TMPL_IF>
+</div>
+
+<TMPL_IF NAME="HAVE_ACTIONS">
+<div class="actions">
+<ul>
+<TMPL_IF NAME="EDITURL">
+<li><a href="<TMPL_VAR EDITURL>">Edit</a></li>
+</TMPL_IF>
+<TMPL_IF NAME="RECENTCHANGESURL">
+<li><a href="<TMPL_VAR RECENTCHANGESURL>">RecentChanges</a></li>
+</TMPL_IF>
+<TMPL_IF NAME="HISTORYURL">
+<li><a href="<TMPL_VAR HISTORYURL>">History</a></li>
+</TMPL_IF>
+<TMPL_IF NAME="PREFSURL">
+<li><a href="<TMPL_VAR PREFSURL>">Preferences</a></li>
+</TMPL_IF>
+<TMPL_IF NAME="DISCUSSIONLINK">
+<li><TMPL_VAR DISCUSSIONLINK><br /></li>
+</TMPL_IF>
+</ul>
+</div>
+</TMPL_IF>
+
+<TMPL_IF SIDEBAR>
+<div id="sidebar">
+<TMPL_VAR SIDEBAR>
+</div>
+</TMPL_IF>
+
+<div id="content">
+<TMPL_VAR CONTENT>
+</div>
+
+<div class="tags">
+<TMPL_IF NAME="TAGS">
+Tags:
+<TMPL_LOOP NAME="TAGS">
+<TMPL_VAR NAME=LINK>
+</TMPL_LOOP>
+</TMPL_IF>
+</div>
+
+<div id="backlinks">
+<TMPL_IF NAME="BACKLINKS">
+Links:
+<TMPL_LOOP NAME="BACKLINKS">
+<a href="<TMPL_VAR NAME=URL>"><TMPL_VAR NAME=PAGE></a>
+</TMPL_LOOP>
+</TMPL_IF>
+</div>
+
+<div id="footer">
+<span class="pageinfo">
+<!-- from <TMPL_VAR NAME=WIKINAME> -->
+Last edited <TMPL_VAR NAME=MTIME>
+</span>
+</div>
+
+</body>
+</html>
diff --git a/1.33.2/templates/passwordmail.tmpl b/1.33.2/templates/passwordmail.tmpl
new file mode 100644 (file)
index 0000000..8484d39
--- /dev/null
@@ -0,0 +1,10 @@
+Someone[1], possibly you, requested that you be emailed the password for user
+<TMPL_VAR USER_NAME> on <TMPL_VAR WIKINAME>[2].
+
+The password is: <TMPL_VAR USER_PASSWORD>
+
+-- 
+ikiwiki
+
+[1] The user requesting the password was at IP address <TMPL_VAR REMOTE_ADDR>
+[2] Located at <TMPL_VAR WIKIURL>
diff --git a/1.33.2/templates/recentchanges.tmpl b/1.33.2/templates/recentchanges.tmpl
new file mode 100644 (file)
index 0000000..9d4ba40
--- /dev/null
@@ -0,0 +1,69 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<head>
+<base href="<TMPL_VAR BASEURL>" />
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title><TMPL_VAR TITLE></title>
+<link rel="stylesheet" href="<TMPL_VAR BASEURL>style.css" type="text/css" />
+<link rel="stylesheet" href="<TMPL_VAR BASEURL>local.css" type="text/css" />
+<TMPL_IF NAME="FAVICON">
+<link rel="icon" href="<TMPL_VAR BASEURL><TMPL_VAR FAVICON>" type="image/x-icon" />
+</TMPL_IF>
+</head>
+<body>
+
+<div class="header">
+<span>
+<TMPL_VAR INDEXLINK>/ <TMPL_VAR TITLE>
+</span>
+</div>
+
+<div id="content">
+<br />
+<table border="1" frame="border" rules="groups">
+<thead>
+       <tr class="changeheader">
+               <th class="changeheader" align="left">user</th>
+               <th class="changeheader" align="left">time</th>
+               <th class="changeheader" align="left" colspan="2">changes</th>
+       </tr>
+</thead>
+<tbody>
+<TMPL_LOOP NAME="CHANGELOG">
+       <!-- <TMPL_VAR NAME="REV"> -->
+       <tr class="changeinfo">
+               <td class="changeinfo"><TMPL_VAR NAME="USER"></td>
+               <td class="changetime"><TMPL_VAR NAME="WHEN"></td>
+               <td class="changeinfo">
+               <TMPL_LOOP NAME="PAGES">
+                       <TMPL_IF NAME="DIFFURL">
+                               <a href="<TMPL_VAR NAME="DIFFURL">">
+                               <img alt="diff" src="wikiicons/diff.png" style="border-style: none" />
+                               </a>
+                               <TMPL_VAR NAME="LINK">
+                       <TMPL_ELSE>
+                               <TMPL_VAR NAME="LINK">
+                       </TMPL_IF>
+               </TMPL_LOOP>
+               </td>
+               <td class="changeinfo"><TMPL_VAR NAME="COMMITTYPE"></td>
+       </tr>
+       <tr>
+               <td class="changelog" colspan="4">
+                       <TMPL_LOOP NAME="MESSAGE">
+                               <TMPL_IF NAME="LINE">
+                                       <TMPL_VAR NAME="LINE" ESCAPE="HTML"><br />
+                               </TMPL_IF>
+                       </TMPL_LOOP>
+               </td>
+       </tr>
+</TMPL_LOOP>
+</tbody>
+</table>
+</div>
+
+<!-- from <TMPL_VAR NAME=WIKINAME> -->
+
+</body>
+</html>
diff --git a/1.33.2/templates/rssitem.tmpl b/1.33.2/templates/rssitem.tmpl
new file mode 100644 (file)
index 0000000..0fab42e
--- /dev/null
@@ -0,0 +1,21 @@
+<item>
+       <TMPL_IF NAME="AUTHOR">
+       <title><TMPL_VAR AUTHOR ESCAPE=HTML>: <TMPL_VAR TITLE ESCAPE=HTML></title>
+       <dc:creator><TMPL_VAR AUTHOR ESCAPE=HTML></dc:creator>
+       <TMPL_ELSE>
+       <title><TMPL_VAR TITLE ESCAPE=HTML></title>
+       </TMPL_IF>
+       <guid><TMPL_VAR URL></guid>
+       <link><TMPL_VAR PERMALINK></link>
+       <TMPL_IF NAME="CATEGORIES">
+       <TMPL_LOOP NAME="CATEGORIES">
+       <category><TMPL_VAR CATEGORY></category>
+       </TMPL_LOOP>
+       </TMPL_IF>
+       <pubDate><TMPL_VAR DATE_822></pubDate>
+       <TMPL_IF NAME="ENCLOSURE">
+       <enclosure url="<TMPL_VAR ENCLOSURE>" type="<TMPL_VAR TYPE>" length="<TMPL_VAR LENGTH>" />
+       <TMPL_ELSE>
+       <description><![CDATA[<TMPL_VAR CONTENT>]]></description>
+       </TMPL_IF>
+</item>
diff --git a/1.33.2/templates/rsspage.tmpl b/1.33.2/templates/rsspage.tmpl
new file mode 100644 (file)
index 0000000..38f9b16
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<channel>
+<title><TMPL_VAR TITLE ESCAPE=HTML></title>
+<link><TMPL_VAR PAGEURL></link>
+<description><TMPL_VAR FEEDDESC ESCAPE=HTML></description>
+<TMPL_VAR CONTENT>
+</channel>
+</rss>
diff --git a/1.33.2/templates/searchform.tmpl b/1.33.2/templates/searchform.tmpl
new file mode 100644 (file)
index 0000000..7c4fdb0
--- /dev/null
@@ -0,0 +1,7 @@
+<form method="get" action="<TMPL_VAR SEARCHACTION>" id="searchform">
+<div>
+<input type="text" name="phrase" value="" size="16" />
+<input type="hidden" name="enc" value="UTF-8" />
+<input type="hidden" name="do" value="hyperestraier" />
+</div>
+</form>
diff --git a/1.33.2/wikilist b/1.33.2/wikilist
new file mode 100644 (file)
index 0000000..f047b67
--- /dev/null
@@ -0,0 +1,8 @@
+# This file is used by ikiwiki-mass-rebuild script rebuild the listed
+# wikis. Run this script when upgrading ikiwiki to an incompatible new
+# version that requires rebuilding everything.
+#
+# ikiwiki-mass-rebuild su's to the listed user and then runs ikiwiki -setup
+# on the specified ikiwiki setup file.
+
+#joey /home/joey/.ikiwiki/ikiwiki.setup