]> sipb.mit.edu Git - ikiwiki.git/commitdiff
Merge branch 'master' of git://git.ikiwiki.info
authorJonas Smedegaard <dr@jones.dk>
Fri, 27 Aug 2010 08:01:58 +0000 (10:01 +0200)
committerJonas Smedegaard <dr@jones.dk>
Fri, 27 Aug 2010 08:01:58 +0000 (10:01 +0200)
1056 files changed:
.gitattributes [new file with mode: 0644]
.gitignore
Bundle/IkiWiki.pm
Bundle/IkiWiki/Extras.pm
IkiWiki.pm
IkiWiki/CGI.pm
IkiWiki/Plugin/404.pm
IkiWiki/Plugin/aggregate.pm
IkiWiki/Plugin/amazon_s3.pm
IkiWiki/Plugin/anonok.pm
IkiWiki/Plugin/attachment.pm
IkiWiki/Plugin/autoindex.pm
IkiWiki/Plugin/blogspam.pm
IkiWiki/Plugin/brokenlinks.pm
IkiWiki/Plugin/bzr.pm
IkiWiki/Plugin/calendar.pm
IkiWiki/Plugin/color.pm
IkiWiki/Plugin/comments.pm
IkiWiki/Plugin/conditional.pm
IkiWiki/Plugin/creole.pm
IkiWiki/Plugin/cutpaste.pm
IkiWiki/Plugin/cvs.pm [new file with mode: 0644]
IkiWiki/Plugin/darcs.pm
IkiWiki/Plugin/date.pm [new file with mode: 0644]
IkiWiki/Plugin/editdiff.pm
IkiWiki/Plugin/editpage.pm
IkiWiki/Plugin/edittemplate.pm
IkiWiki/Plugin/external.pm
IkiWiki/Plugin/filecheck.pm
IkiWiki/Plugin/flattr.pm [new file with mode: 0644]
IkiWiki/Plugin/format.pm
IkiWiki/Plugin/fortune.pm
IkiWiki/Plugin/getsource.pm [new file with mode: 0644]
IkiWiki/Plugin/git.pm
IkiWiki/Plugin/google.pm
IkiWiki/Plugin/goto.pm
IkiWiki/Plugin/graphviz.pm
IkiWiki/Plugin/haiku.pm
IkiWiki/Plugin/highlight.pm
IkiWiki/Plugin/hnb.pm
IkiWiki/Plugin/html.pm
IkiWiki/Plugin/htmlscrubber.pm
IkiWiki/Plugin/htmltidy.pm
IkiWiki/Plugin/httpauth.pm
IkiWiki/Plugin/img.pm
IkiWiki/Plugin/inline.pm
IkiWiki/Plugin/link.pm
IkiWiki/Plugin/linkmap.pm
IkiWiki/Plugin/listdirectives.pm
IkiWiki/Plugin/localstyle.pm [new file with mode: 0644]
IkiWiki/Plugin/lockedit.pm
IkiWiki/Plugin/map.pm
IkiWiki/Plugin/mdwn.pm
IkiWiki/Plugin/mercurial.pm
IkiWiki/Plugin/meta.pm
IkiWiki/Plugin/mirrorlist.pm
IkiWiki/Plugin/moderatedcomments.pm [new file with mode: 0644]
IkiWiki/Plugin/monotone.pm
IkiWiki/Plugin/more.pm
IkiWiki/Plugin/norcs.pm
IkiWiki/Plugin/opendiscussion.pm
IkiWiki/Plugin/openid.pm
IkiWiki/Plugin/orphans.pm
IkiWiki/Plugin/otl.pm
IkiWiki/Plugin/pagecount.pm
IkiWiki/Plugin/pagestats.pm
IkiWiki/Plugin/parentlinks.pm
IkiWiki/Plugin/passwordauth.pm
IkiWiki/Plugin/po.pm
IkiWiki/Plugin/poll.pm
IkiWiki/Plugin/polygen.pm
IkiWiki/Plugin/postsparkline.pm
IkiWiki/Plugin/progress.pm
IkiWiki/Plugin/rawhtml.pm
IkiWiki/Plugin/recentchanges.pm
IkiWiki/Plugin/relativedate.pm
IkiWiki/Plugin/remove.pm
IkiWiki/Plugin/rename.pm
IkiWiki/Plugin/repolist.pm
IkiWiki/Plugin/rsync.pm [new file with mode: 0644]
IkiWiki/Plugin/search.pm
IkiWiki/Plugin/shortcut.pm
IkiWiki/Plugin/sidebar.pm
IkiWiki/Plugin/signinedit.pm
IkiWiki/Plugin/skeleton.pm.example
IkiWiki/Plugin/smiley.pm
IkiWiki/Plugin/sortnaturally.pm [new file with mode: 0644]
IkiWiki/Plugin/sparkline.pm
IkiWiki/Plugin/svn.pm
IkiWiki/Plugin/table.pm
IkiWiki/Plugin/tag.pm
IkiWiki/Plugin/template.pm
IkiWiki/Plugin/teximg.pm
IkiWiki/Plugin/textile.pm
IkiWiki/Plugin/theme.pm [new file with mode: 0644]
IkiWiki/Plugin/tla.pm
IkiWiki/Plugin/toc.pm
IkiWiki/Plugin/toggle.pm
IkiWiki/Plugin/txt.pm
IkiWiki/Plugin/typography.pm
IkiWiki/Plugin/underlay.pm
IkiWiki/Plugin/version.pm
IkiWiki/Plugin/websetup.pm
IkiWiki/Plugin/wikitext.pm
IkiWiki/Plugin/wmd.pm
IkiWiki/Receive.pm
IkiWiki/Render.pm
IkiWiki/Setup.pm
IkiWiki/Setup/Automator.pm
IkiWiki/Setup/Standard.pm
IkiWiki/Setup/Yaml.pm [new file with mode: 0644]
IkiWiki/Wrapper.pm
Makefile.PL
README
auto-blog.setup
auto.setup
debian/NEWS
debian/changelog
debian/control
debian/copyright
debian/examples [deleted file]
debian/postinst
doc/banned_users.mdwn
doc/basewiki/index.mdwn
doc/bugs/2.45_Compilation_error.mdwn
doc/bugs/404_plugin_and_lighttpd.mdwn [new file with mode: 0644]
doc/bugs/Another_UTF-8_problem.mdwn
doc/bugs/Building_a_sidebar_does_not_regenerate_the_subpages.mdwn
doc/bugs/Cannot_inline_pages_with_apostrophes_in_title.mdwn
doc/bugs/Comments_dissapeared.mdwn [new file with mode: 0644]
doc/bugs/Error:_Your_login_session_has_expired._.mdwn
doc/bugs/Exception:_Unknown_function___96__this__39___.mdwn [new file with mode: 0644]
doc/bugs/External_links_with_Creole.mdwn [new file with mode: 0644]
doc/bugs/Git:_changed_behavior_w.r.t._timestamps.mdwn [new file with mode: 0644]
doc/bugs/HTML_for_parentlinks_makes_theming_hard.mdwn [new file with mode: 0644]
doc/bugs/Highlight_extension_uses_hard_coded_paths.mdwn [new file with mode: 0644]
doc/bugs/Inline_doesn__39__t_wikilink_to_pages.mdwn
doc/bugs/Links_to_missing_pages_should_always_be_styled.mdwn [new file with mode: 0644]
doc/bugs/Problems_with_graphviz.pm_plug-in.mdwn
doc/bugs/Problems_with_graphviz.pm_plug-in_previews.mdwn [new file with mode: 0644]
doc/bugs/SSI_include_stripped_from_mdwn.mdwn
doc/bugs/Search_summary_includes_text_from_navigational_elements.mdwn [new file with mode: 0644]
doc/bugs/Tab_delimited_tables_don__39__t_work.mdwn [new file with mode: 0644]
doc/bugs/__34__First_post__34___deletion_does_not_refresh_front_page.mdwn [new file with mode: 0644]
doc/bugs/absolute_sizes_in_default_CSS.mdwn [new file with mode: 0644]
doc/bugs/align_doesn__39__t_always_work_with_img_plugin_.mdwn [new file with mode: 0644]
doc/bugs/anonok_vs._httpauth.mdwn [new file with mode: 0644]
doc/bugs/attachment_upload_does_not_work_for_windows_clients.mdwn [new file with mode: 0644]
doc/bugs/barfs_on_recentchange_entry_for_a_change_removing_an_invalid_pagespec.mdwn
doc/bugs/bestlink_change_update_issue.mdwn
doc/bugs/bestlink_returns_deleted_pages.mdwn [new file with mode: 0644]
doc/bugs/broken_parentlinks.mdwn
doc/bugs/brokenlinks_accumulates_duplicate_items.mdwn [new file with mode: 0644]
doc/bugs/build_fails_oddly_when_older_ikiwiki_is_installed.mdwn [new file with mode: 0644]
doc/bugs/bzr_2.0_breaks_bzr_plugin.mdwn [new file with mode: 0644]
doc/bugs/cgi_does_not_use_templatedir_overlay.mdwn
doc/bugs/clearenv_not_present_at_FreeBSD_.mdwn [new file with mode: 0644]
doc/bugs/clearenv_not_present_at_FreeBSD_/discussion.mdwn [new file with mode: 0644]
doc/bugs/comments_not_searchable.mdwn [new file with mode: 0644]
doc/bugs/comments_preview_unsafe_with_allowdirectives.mdwn [new file with mode: 0644]
doc/bugs/conflicts.mdwn [new file with mode: 0644]
doc/bugs/debbug_shortcut_should_expand_differently.mdwn
doc/bugs/defintion_lists_appear_to_be_disabled.mdwn [new file with mode: 0644]
doc/bugs/deletion_warnings.mdwn [new file with mode: 0644]
doc/bugs/depends_simple_mixup.mdwn [new file with mode: 0644]
doc/bugs/disable_sub-discussion_pages.mdwn
doc/bugs/discussion_of_what__63__.mdwn
doc/bugs/external_links_inside_headings_don__39__t_work.mdwn
doc/bugs/filecheck_failing_to_find_files.mdwn [new file with mode: 0644]
doc/bugs/firefox_doesn__39__t_want_to_load_updated_pages_at_ikiwiki.info.mdwn
doc/bugs/git_utf8.mdwn
doc/bugs/gitremotes_script_picks_up_tags_from_anywhere.mdwn [new file with mode: 0644]
doc/bugs/html5_support.mdwn
doc/bugs/html5_time_element__39__s_pubdate_wrong_when_using_xhtml5___34__mode__34__.mdwn [new file with mode: 0644]
doc/bugs/htmlscrubber_breaks_multimarkdown_footnotes.mdwn [new file with mode: 0644]
doc/bugs/http_proxy_for_openid.mdwn
doc/bugs/ikiwiki-transition_does_not_set_perl_moduels_path_properly.mdwn [new file with mode: 0644]
doc/bugs/img_plugin_and_missing_heigth_value.mdwn [new file with mode: 0644]
doc/bugs/img_vs_align.mdwn [new file with mode: 0644]
doc/bugs/inline_breaks_PERMALINK_variable.mdwn [new file with mode: 0644]
doc/bugs/inline_plugin_sets_editurl_even_when_editpage_is_disabled.html [new file with mode: 0644]
doc/bugs/inline_raw_broken_on_unknown_pagetype.mdwn [new file with mode: 0644]
doc/bugs/inline_skip_causes_empty_inline.mdwn [new file with mode: 0644]
doc/bugs/librpc-xml-perl_0.69_breaks_XML-RPC_plugins.mdwn [new file with mode: 0644]
doc/bugs/login_page_non-obvious_with_openid.mdwn
doc/bugs/login_page_should_note_cookie_requirement.mdwn
doc/bugs/map_fails_to_close_ul_element_for_empty_list.mdwn
doc/bugs/map_sorts_by_pagename_and_not_title_when_show__61__title_is_used.mdwn [new file with mode: 0644]
doc/bugs/minor:_tiny_rendering_error.mdwn [new file with mode: 0644]
doc/bugs/misctemplate_does_not_respect_the_current_page___40__if_any__41__.mdwn [new file with mode: 0644]
doc/bugs/nested_raw_included_inlines.mdwn
doc/bugs/pagecount_is_broken.mdwn
doc/bugs/pagemtime_in_refresh_mode.mdwn [new file with mode: 0644]
doc/bugs/pages_missing_top-level_directory.mdwn [new file with mode: 0644]
doc/bugs/pagespec:_tagged__40____41____44___globbing.mdwn [new file with mode: 0644]
doc/bugs/pagespec_error_on_refresh_but_not_rebuild.mdwn [new file with mode: 0644]
doc/bugs/pagetitle_function_does_not_respect_meta_titles.mdwn
doc/bugs/plugins__47__relativedate_depends_on_locale_at_setup_file.mdwn [new file with mode: 0644]
doc/bugs/po:_double_commits_of_po_files.mdwn [new file with mode: 0644]
doc/bugs/po:_new_pages_not_translatable.mdwn [new file with mode: 0644]
doc/bugs/po:_po_files_instead_of_html_files.mdwn [new file with mode: 0644]
doc/bugs/po:_ugly_messages_with_empty_files.mdwn [new file with mode: 0644]
doc/bugs/po_plugin_adds_new_dependency.mdwn [new file with mode: 0644]
doc/bugs/po_plugin_cannot_add_po_files_into_git.mdwn [new file with mode: 0644]
doc/bugs/po_vs_templates.mdwn [new file with mode: 0644]
doc/bugs/post-commit_hangs.mdwn [new file with mode: 0644]
doc/bugs/post-update_hook_can__39__t_be_compiled_with_tcc.mdwn [new file with mode: 0644]
doc/bugs/preview_pagestate.mdwn [new file with mode: 0644]
doc/bugs/rebuild_after_changing_the_underlaydir_config_option.mdwn [new file with mode: 0644]
doc/bugs/remove_orphaned_sparkline-php_from_Suggests.mdwn
doc/bugs/removing_pages_with_utf8_characters.mdwn [new file with mode: 0644]
doc/bugs/rst_plugin_has_python_hardcode_in_shebang_line.mdwn [new file with mode: 0644]
doc/bugs/rst_tweak.mdwn
doc/bugs/some_but_not_all_meta_fields_are_stored_escaped.mdwn [new file with mode: 0644]
doc/bugs/stray___60____47__p__62___tags.mdwn
doc/bugs/support_for_openid2_logins.mdwn
doc/bugs/svn_commit_failures_interpreted_as_merge_conflicts.mdwn [new file with mode: 0644]
doc/bugs/tag_plugin:_autotag_vs._staged_changes.mdwn [new file with mode: 0644]
doc/bugs/tagged__40____41___matching_wikilinks.mdwn
doc/bugs/templateForRecentChangesMissingCloseSpan.mdwn [new file with mode: 0644]
doc/bugs/the_login_page_is_unclear_when_multiple_methods_exist.mdwn [new file with mode: 0644]
doc/bugs/toggle_expects_body_element_without_attributes.mdwn [new file with mode: 0644]
doc/bugs/transitive_dependencies.mdwn [new file with mode: 0644]
doc/bugs/underlaydir_file_expose.mdwn
doc/bugs/unicode_encoded_urls_and_recentchanges.mdwn
doc/bugs/utf-8_bug_in_websetup.pm.mdwn [new file with mode: 0644]
doc/bugs/wrapper_can__39__t_find_the_perl_modules.mdwn [new file with mode: 0644]
doc/competition.mdwn [new file with mode: 0644]
doc/css.mdwn
doc/css/discussion.mdwn [new file with mode: 0644]
doc/css_market.mdwn
doc/css_market/discussion.mdwn
doc/download.mdwn
doc/examples/blog.mdwn
doc/examples/blog/archives.mdwn [new file with mode: 0644]
doc/examples/blog/comments.mdwn [new file with mode: 0644]
doc/examples/blog/index.mdwn
doc/examples/blog/posts.mdwn
doc/examples/blog/posts/first_post.mdwn
doc/examples/blog/sidebar.mdwn
doc/examples/blog/tags.mdwn
doc/examples/blog/tags/life.mdwn [deleted file]
doc/examples/blog/tags/tech.mdwn [deleted file]
doc/examples/softwaresite.mdwn
doc/examples/softwaresite/news.mdwn
doc/features.mdwn
doc/forum.mdwn
doc/forum/Can_OpenID_users_be_adminusers__63__.mdwn
doc/forum/Can__39__t_get_comments_plugin_working.mdwn [new file with mode: 0644]
doc/forum/Cannot_write_to_commitlock.mdwn [new file with mode: 0644]
doc/forum/Error:_bad_page_name.mdwn [new file with mode: 0644]
doc/forum/How_does_ikiwiki_remember_times__63__.mdwn
doc/forum/Ikiwiki_CGI_not_working_on_my_server__44___and_it__39__s_a_binary_file__63__.mdwn [new file with mode: 0644]
doc/forum/Migrating_old_repository_to_new_ikiwiki_system__63__.mdwn
doc/forum/News_site_where_articles_are_submitted_and_then_reviewed_before_posting.mdwn [new file with mode: 0644]
doc/forum/PERL5LIB__44___wrappers_and_homedir_install.mdwn [new file with mode: 0644]
doc/forum/Regex_for_Valid_Characters_in_Filenames.mdwn [new file with mode: 0644]
doc/forum/Render_more_than_one_dest_page_from_same_source_page.mdwn [new file with mode: 0644]
doc/forum/Should_not_create_an_existing_page.mdwn [new file with mode: 0644]
doc/forum/Sidebar_with_links__63__.mdwn [new file with mode: 0644]
doc/forum/Spaces_in_wikilinks.mdwn [new file with mode: 0644]
doc/forum/The_requested_URL___47____126__jean__47__blog__47__ikiwiki.cgi_was_not_found_on_this_server..mdwn [new file with mode: 0644]
doc/forum/The_requested_URL___47____126__jean__47__blog__47__ikiwiki.cgi_was_not_found_on_this_server./comment_1_d36ce6fab90e0a086ac84369af38d205._comment [new file with mode: 0644]
doc/forum/The_requested_URL___47____126__jean__47__blog__47__ikiwiki.cgi_was_not_found_on_this_server./comment_2_5836bba08172d2ddf6a43da87ebb0332._comment [new file with mode: 0644]
doc/forum/The_requested_URL___47____126__jean__47__blog__47__ikiwiki.cgi_was_not_found_on_this_server./comment_3_4eec15c8c383275db5401c8e3c2d9242._comment [new file with mode: 0644]
doc/forum/The_requested_URL___47____126__jean__47__blog__47__ikiwiki.cgi_was_not_found_on_this_server./comment_4_43ac867621efb68affa6ae2b92740cad._comment [new file with mode: 0644]
doc/forum/The_requested_URL___47____126__jean__47__blog__47__ikiwiki.cgi_was_not_found_on_this_server./comment_5_e098723bb12adfb91ab561cae21b492b._comment [new file with mode: 0644]
doc/forum/The_requested_URL___47____126__jean__47__blog__47__ikiwiki.cgi_was_not_found_on_this_server./comment_6_101183817ca4394890bd56a7694bedd9._comment [new file with mode: 0644]
doc/forum/Upgrade_steps_from_RecentChanges_CGI_to_static_page.mdwn [new file with mode: 0644]
doc/forum/Various_ways_to_use_Subversion_with_ikiwiki.mdwn [new file with mode: 0644]
doc/forum/an_alternative_approach_to_structured_data.mdwn [new file with mode: 0644]
doc/forum/appear_if_you_are_login_or_not_in_a_page.mdwn
doc/forum/cleaning_up_discussion_pages_and_the_like.mdwn [new file with mode: 0644]
doc/forum/cutpaste.pm_not_only_file-local.mdwn [new file with mode: 0644]
doc/forum/cutpaste.pm_not_only_file-local/comment_1_497c62f21fd1b87625b806407c72dbad._comment [new file with mode: 0644]
doc/forum/debian_backports_update_someone_please.mdwn [new file with mode: 0644]
doc/forum/double_forward_slash___39____47____47____39___in_the_address_bar.mdwn [new file with mode: 0644]
doc/forum/editing_a_comment.mdwn [new file with mode: 0644]
doc/forum/editing_the_style_sheet.mdwn [new file with mode: 0644]
doc/forum/ever-growing_list_of_pages.mdwn [new file with mode: 0644]
doc/forum/formating:_how_to_align_text_to_the_right.mdwn [new file with mode: 0644]
doc/forum/google_openid_broken__63__.mdwn [new file with mode: 0644]
doc/forum/how_do_I_revert_edits_in_the_web_mode__63__.mdwn [new file with mode: 0644]
doc/forum/how_do_I_translate_a_TWiki_site.mdwn [new file with mode: 0644]
doc/forum/how_to_add_post_titles_in_ikiwiki_blog__63__.mdwn [new file with mode: 0644]
doc/forum/how_to_enable_multimarkdown__63__.mdwn [new file with mode: 0644]
doc/forum/how_to_enable_multimarkdown__63__/comment_1_037f858c4d0bcbb708c3efd264379500._comment [new file with mode: 0644]
doc/forum/how_to_enable_multimarkdown__63__/comment_2_b7d512a535490dabf8d6ce55439741c7._comment [new file with mode: 0644]
doc/forum/how_to_load_an_external_page_and_still_have_it_under_ikiwiki_template.mdwn [new file with mode: 0644]
doc/forum/how_to_login_as_admin.mdwn [new file with mode: 0644]
doc/forum/how_to_setup_ikiwiki_on_a_remote_host.mdwn [new file with mode: 0644]
doc/forum/html_source_pages_in_version_3.20100704.mdwn [new file with mode: 0644]
doc/forum/ikiwiki_and_big_files.mdwn [new file with mode: 0644]
doc/forum/ikiwiki_development_environment_tips.mdwn [new file with mode: 0644]
doc/forum/ikiwiki_over_database__63__.wiki
doc/forum/ikiwiki_vim_syntaxfile.mdwn [new file with mode: 0644]
doc/forum/installation_and_setup_questions.mdwn [new file with mode: 0644]
doc/forum/installation_as_non-root_user.mdwn [new file with mode: 0644]
doc/forum/installation_of_selected_docs.mdwn [new file with mode: 0644]
doc/forum/link_autocompletion_in_vim.mdwn [new file with mode: 0644]
doc/forum/link_to_an_image_inside_the_wiki_without_inlining_it.mdwn [new file with mode: 0644]
doc/forum/missing_pages_redirected_to_search-SOLVED.mdwn [new file with mode: 0644]
doc/forum/multi-user_setup_of_ikiwiki__44___gitosis_and_apache2_in_Debian_Sid.mdwn
doc/forum/multi_domain_setup_possible__63__.mdwn [new file with mode: 0644]
doc/forum/multi_domain_setup_possible__63__/comment_1_43f5df30d09046ccc4f7c44703979a11._comment [new file with mode: 0644]
doc/forum/multi_domain_setup_possible__63__/comment_2_75d6581f81b71fb8acbe3561047ea759._comment [new file with mode: 0644]
doc/forum/navigation_of_wiki_pages_on_local_filesystem_with_vim.mdwn [new file with mode: 0644]
doc/forum/recentchanges_dir_should_be_under_control_of_RCS__63__.mdwn [new file with mode: 0644]
doc/forum/remove_css__63__.mdwn [new file with mode: 0644]
doc/forum/report_pagination.mdwn [new file with mode: 0644]
doc/forum/speeding_up_ikiwiki.mdwn
doc/forum/square_brackets_inside_backticks_generates_incorrect_html___40__interpreted_as_wikilinks__41____63__.html [new file with mode: 0644]
doc/forum/suppressing_output_of_pages_included_only_for_their_side_effects.mdwn [new file with mode: 0644]
doc/forum/tag_plugin:_rebuilding_autocreated_pages.mdwn [new file with mode: 0644]
doc/forum/transition_from_handwritten_html_to_ikiwiki.mdwn [new file with mode: 0644]
doc/forum/understanding_filter_hooks.mdwn
doc/forum/upgrade_steps.mdwn [new file with mode: 0644]
doc/forum/use_php-markdown-extra_with_ikiwiki__63__.mdwn [new file with mode: 0644]
doc/forum/use_php-markdown-extra_with_ikiwiki__63__/comment_1_66d48218361caa4c07bd714b82ed0021._comment [new file with mode: 0644]
doc/forum/use_php-markdown-extra_with_ikiwiki__63__/comment_2_f2ee0a4dce571d329f795e52139084c0._comment [new file with mode: 0644]
doc/forum/use_php-markdown-extra_with_ikiwiki__63__/comment_3_e388714f457ccb6ef73630179914558c._comment [new file with mode: 0644]
doc/forum/utf8_warnings_for___34____92__xAB__34__.mdwn [new file with mode: 0644]
doc/forum/web_service_API__44___fastcgi_support.mdwn [new file with mode: 0644]
doc/forum/what_is_the_easiest_way_to_implement_order:_disallow_all__44___allow_chosen__95__few_page_editing_policy__63__.mdwn [new file with mode: 0644]
doc/forum/where_are_the_tags.mdwn [new file with mode: 0644]
doc/forum/wiki_clones_on_dynamic_IPs.mdwn [new file with mode: 0644]
doc/forum/wiki_name_in_page_titles.mdwn
doc/forum/wishlist-discussion:_Editformular_showing_existing_tags.mdwn [new file with mode: 0644]
doc/freesoftware.mdwn
doc/git.mdwn
doc/ikiwiki-calendar.mdwn [new file with mode: 0644]
doc/ikiwiki-makerepo.mdwn
doc/ikiwiki-makerepo/discussion.mdwn [new file with mode: 0644]
doc/ikiwiki.mdwn
doc/ikiwiki/directive/brokenlinks/discussion.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/calendar.mdwn
doc/ikiwiki/directive/comment.mdwn
doc/ikiwiki/directive/commentmoderation.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/date.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/edittemplate.mdwn
doc/ikiwiki/directive/flattr.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/format.mdwn
doc/ikiwiki/directive/img.mdwn
doc/ikiwiki/directive/inline.mdwn
doc/ikiwiki/directive/inline/discussion.mdwn
doc/ikiwiki/directive/linkmap.mdwn
doc/ikiwiki/directive/map.mdwn
doc/ikiwiki/directive/map/discussion.mdwn
doc/ikiwiki/directive/meta.mdwn
doc/ikiwiki/directive/pagestats.mdwn
doc/ikiwiki/directive/pagestats/discussion.mdwn
doc/ikiwiki/directive/pagetemplate.mdwn
doc/ikiwiki/directive/postsparkline.mdwn
doc/ikiwiki/directive/sidebar.mdwn [new file with mode: 0644]
doc/ikiwiki/directive/sparkline.mdwn
doc/ikiwiki/directive/table.mdwn
doc/ikiwiki/directive/tag.mdwn
doc/ikiwiki/directive/template.mdwn
doc/ikiwiki/directive/toc.mdwn
doc/ikiwiki/formatting.mdwn
doc/ikiwiki/openid.mdwn
doc/ikiwiki/pagespec.mdwn
doc/ikiwiki/pagespec/attachment.mdwn
doc/ikiwiki/pagespec/discussion.mdwn
doc/ikiwiki/pagespec/po.mdwn
doc/ikiwiki/pagespec/sorting.mdwn [new file with mode: 0644]
doc/ikiwiki/searching.mdwn
doc/ikiwiki/subpage.mdwn
doc/ikiwiki/wikilink.mdwn
doc/ikiwiki/wikilink/discussion.mdwn
doc/ikiwiki_is_so_sexy__33__.mdwn [deleted file]
doc/ikiwikiusers.mdwn
doc/ikiwikiusers/discussion.mdwn
doc/index.mdwn
doc/index/discussion.mdwn
doc/news/code_swarm/discussion.mdwn [new file with mode: 0644]
doc/news/discussion.mdwn
doc/news/ikiwiki-hosting.mdwn [new file with mode: 0644]
doc/news/openid.mdwn
doc/news/openid/discussion.mdwn
doc/news/server_move_2009.mdwn [new file with mode: 0644]
doc/news/version_3.14.mdwn [deleted file]
doc/news/version_3.141.mdwn [deleted file]
doc/news/version_3.141/discussion.mdwn [deleted file]
doc/news/version_3.1415.mdwn [deleted file]
doc/news/version_3.14159.mdwn [deleted file]
doc/news/version_3.20100610.mdwn [new file with mode: 0644]
doc/news/version_3.20100623.mdwn [new file with mode: 0644]
doc/news/version_3.20100704.mdwn [new file with mode: 0644]
doc/news/version_3.20100722.mdwn [new file with mode: 0644]
doc/news/version_3.20100804.mdwn [new file with mode: 0644]
doc/news/version_3.20100815.mdwn [new file with mode: 0644]
doc/peteg.mdwn [new file with mode: 0644]
doc/plugins.mdwn
doc/plugins/404.mdwn
doc/plugins/404/discussion.mdwn [new file with mode: 0644]
doc/plugins/aggregate.mdwn
doc/plugins/autoindex.mdwn
doc/plugins/autoindex/discussion.mdwn
doc/plugins/calendar.mdwn
doc/plugins/calendar/discussion.mdwn
doc/plugins/color.mdwn
doc/plugins/comments.mdwn
doc/plugins/comments/discussion.mdwn
doc/plugins/conditional.mdwn
doc/plugins/conditional/discussion.mdwn
doc/plugins/contrib.mdwn
doc/plugins/contrib/album.mdwn
doc/plugins/contrib/album/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/cvs.mdwn [deleted file]
doc/plugins/contrib/field.mdwn [new file with mode: 0644]
doc/plugins/contrib/field/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/flattr.mdwn [new file with mode: 0644]
doc/plugins/contrib/flattr/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/ftemplate.mdwn [new file with mode: 0644]
doc/plugins/contrib/ftemplate/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/ftemplate/ikiwiki/directive/ftemplate.mdwn [new file with mode: 0644]
doc/plugins/contrib/getfield.mdwn [new file with mode: 0644]
doc/plugins/contrib/getfield/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/groupfile.mdwn [new file with mode: 0644]
doc/plugins/contrib/highlightcode.mdwn
doc/plugins/contrib/ikiwiki/directive/ymlfront.mdwn [new file with mode: 0644]
doc/plugins/contrib/linguas.mdwn
doc/plugins/contrib/mailbox/discussion.mdwn
doc/plugins/contrib/mediawiki.mdwn
doc/plugins/contrib/navbar/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/pod.mdwn [new file with mode: 0644]
doc/plugins/contrib/pod/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/postal.mdwn
doc/plugins/contrib/postal/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/report.mdwn [new file with mode: 0644]
doc/plugins/contrib/report/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/report/ikiwiki/directive/report.mdwn [new file with mode: 0644]
doc/plugins/contrib/tracking.mdwn [new file with mode: 0644]
doc/plugins/contrib/unixauth.mdwn
doc/plugins/contrib/unixrelpagespec.mdwn [new file with mode: 0644]
doc/plugins/contrib/xslt.mdwn [new file with mode: 0644]
doc/plugins/contrib/xslt/discussion.mdwn [new file with mode: 0644]
doc/plugins/contrib/ymlfront.mdwn [new file with mode: 0644]
doc/plugins/contrib/ymlfront/discussion.mdwn [new file with mode: 0644]
doc/plugins/creole/discussion.mdwn
doc/plugins/cutpaste.mdwn
doc/plugins/date.mdwn [new file with mode: 0644]
doc/plugins/ddate.mdwn
doc/plugins/discussion.mdwn
doc/plugins/editpage.mdwn
doc/plugins/edittemplate.mdwn
doc/plugins/filecheck.mdwn
doc/plugins/filecheck/discussion.mdwn
doc/plugins/flattr.mdwn [new file with mode: 0644]
doc/plugins/format.mdwn
doc/plugins/fortune.mdwn
doc/plugins/getsource.mdwn [new file with mode: 0644]
doc/plugins/getsource/discussion.mdwn [new file with mode: 0644]
doc/plugins/goodstuff/discussion.mdwn [new file with mode: 0644]
doc/plugins/google.mdwn
doc/plugins/google/discussion.mdwn
doc/plugins/goto.mdwn
doc/plugins/graphviz.mdwn
doc/plugins/haiku.mdwn
doc/plugins/highlight.mdwn
doc/plugins/highlight/discussion.mdwn
doc/plugins/htmlscrubber/discussion.mdwn [new file with mode: 0644]
doc/plugins/httpauth.mdwn
doc/plugins/img.mdwn
doc/plugins/inline.mdwn
doc/plugins/link.mdwn
doc/plugins/linkmap.mdwn
doc/plugins/listdirectives.mdwn
doc/plugins/localstyle.mdwn [new file with mode: 0644]
doc/plugins/lockedit.mdwn
doc/plugins/lockedit/discussion.mdwn [new file with mode: 0644]
doc/plugins/map.mdwn
doc/plugins/map/discussion.mdwn
doc/plugins/mdwn.mdwn
doc/plugins/mirrorlist.mdwn
doc/plugins/moderatedcomments.mdwn [new file with mode: 0644]
doc/plugins/more.mdwn
doc/plugins/opendiscussion.mdwn
doc/plugins/openid.mdwn
doc/plugins/openid/discussion.mdwn
doc/plugins/orphans.mdwn
doc/plugins/pagecount.mdwn
doc/plugins/pagestats.mdwn
doc/plugins/pagetemplate.mdwn
doc/plugins/parentlinks.mdwn
doc/plugins/po.mdwn
doc/plugins/po/discussion.mdwn
doc/plugins/poll.mdwn
doc/plugins/polygen.mdwn
doc/plugins/postsparkline.mdwn
doc/plugins/prettydate.mdwn
doc/plugins/progress.mdwn
doc/plugins/rawhtml/discussion.mdwn
doc/plugins/recentchanges.mdwn
doc/plugins/recentchangesdiff.mdwn
doc/plugins/relativedate.mdwn
doc/plugins/rename.mdwn
doc/plugins/repolist.mdwn
doc/plugins/rst/discussion.mdwn
doc/plugins/rsync.mdwn [new file with mode: 0644]
doc/plugins/rsync/discussion.mdwn [new file with mode: 0644]
doc/plugins/search.mdwn
doc/plugins/shortcut.mdwn
doc/plugins/shortcut/discussion.mdwn
doc/plugins/sidebar.mdwn
doc/plugins/sidebar/discussion.mdwn [new file with mode: 0644]
doc/plugins/sortnaturally.mdwn [new file with mode: 0644]
doc/plugins/sparkline.mdwn
doc/plugins/table.mdwn
doc/plugins/table/discussion.mdwn
doc/plugins/tag.mdwn
doc/plugins/tag/discussion.mdwn
doc/plugins/template.mdwn
doc/plugins/testpagespec.mdwn
doc/plugins/teximg.mdwn
doc/plugins/theme.mdwn [new file with mode: 0644]
doc/plugins/theme/discussion.mdwn [new file with mode: 0644]
doc/plugins/toc.mdwn
doc/plugins/toggle.mdwn
doc/plugins/txt.mdwn
doc/plugins/type/chrome.mdwn
doc/plugins/type/useful.mdwn [deleted file]
doc/plugins/type/widget.mdwn [new file with mode: 0644]
doc/plugins/typography.mdwn
doc/plugins/underlay.mdwn
doc/plugins/version.mdwn
doc/plugins/websetup.mdwn
doc/plugins/wmd.mdwn
doc/plugins/write.mdwn
doc/post-commit/discussion.mdwn
doc/quotes.mdwn [new file with mode: 0644]
doc/quotes/pizza.mdwn [new file with mode: 0644]
doc/quotes/pizza/discussion.mdwn [new file with mode: 0644]
doc/quotes/sold.mdwn [new file with mode: 0644]
doc/rcs.mdwn
doc/rcs/cvs.mdwn [new file with mode: 0644]
doc/rcs/cvs/discussion.mdwn [new file with mode: 0644]
doc/rcs/details.mdwn
doc/rcs/git.mdwn
doc/rcs/svn.mdwn
doc/rcs/tla.mdwn
doc/roadmap.mdwn
doc/roadmap/discussion.mdwn
doc/sandbox.mdwn
doc/sandbox/Blagging_is_cool.mdwn [deleted file]
doc/sandbox/Bleep.mdwn [deleted file]
doc/sandbox/I_hate_making_new_blog_entries_-_sometimes.wiki [deleted file]
doc/sandbox/Omgwtf_a_blof_post__33____33____33____33____33__1__33__1__33__11111__33____33____33__1__33__1__33____33__1five.html [deleted file]
doc/sandbox/Post.mdwn [new file with mode: 0644]
doc/sandbox/Test:_with_a_colon_in_its_name.mdwn [deleted file]
doc/sandbox/Teximg.mdwn [deleted file]
doc/sandbox/Try_some_math_formulas.mdwn [deleted file]
doc/sandbox/bar.mdwn [deleted file]
doc/sandbox/blech.mdwn [deleted file]
doc/sandbox/castle/discussion/jon_tests_too.mdwn [deleted file]
doc/sandbox/castle/discussion/test_comment.mdwn [deleted file]
doc/sandbox/check_openID.mdwn [deleted file]
doc/sandbox/danc.mdwn [new file with mode: 0644]
doc/sandbox/discussion.mdwn [deleted file]
doc/sandbox/foo.mdwn [deleted file]
doc/sandbox/foobak.mdwn [deleted file]
doc/sandbox/hello.mdwn [deleted file]
doc/sandbox/ikiwiki_flexibility_makes_me_dream.mdwn [deleted file]
doc/sandbox/ikiwiki_flexibility_makes_me_dream/discussion.mdwn [deleted file]
doc/sandbox/plop.mdwn [new file with mode: 0644]
doc/sandbox/prova_blog.html [new file with mode: 0644]
doc/sandbox/sidebar.mdwn [new file with mode: 0644]
doc/sandbox/test.mdwn [deleted file]
doc/sandbox/test_nested_inlines.mdwn [deleted file]
doc/sandbox/test_pi.mdwn [deleted file]
doc/sandbox/test_post.mdwn [deleted file]
doc/sandbox/testpage.mdwn [deleted file]
doc/sandbox/testsubpage.mdwn [deleted file]
doc/sandbox/this_is_pretty_cool.mdwn [deleted file]
doc/sandbox/한글.mdwn [deleted file]
doc/sandbox/한글페이지.mdwn [deleted file]
doc/security.mdwn
doc/setup.mdwn
doc/setup/byhand.mdwn
doc/setup/byhand/discussion.mdwn [new file with mode: 0644]
doc/setup/discussion.mdwn
doc/shortcuts.mdwn
doc/style.css
doc/templates.mdwn
doc/templates/discussion.mdwn
doc/templates/gitbranch.mdwn
doc/templates/links.mdwn
doc/templates/note.mdwn
doc/templates/plugin.mdwn
doc/templates/popup.mdwn
doc/tipjar.mdwn
doc/tips/DreamHost/discussion.mdwn
doc/tips/Importing_posts_from_Wordpress.mdwn
doc/tips/add_chatterbox_to_blog.mdwn
doc/tips/comments_feed.mdwn
doc/tips/convert_mediawiki_to_ikiwiki.mdwn
doc/tips/convert_mediawiki_to_ikiwiki/discussion.mdwn
doc/tips/dot_cgi.mdwn
doc/tips/dot_cgi/discussion.mdwn
doc/tips/follow_wikilinks_from_inside_vim.mdwn [new file with mode: 0644]
doc/tips/github.mdwn
doc/tips/howto_limit_to_admin_users.mdwn [new file with mode: 0644]
doc/tips/htaccess_file.mdwn [new file with mode: 0644]
doc/tips/html5.mdwn [new file with mode: 0644]
doc/tips/ikiwiki_as_a_requirements_management_tool.mdwn [new file with mode: 0644]
doc/tips/ikiwiki_as_a_requirements_management_tool/discussion.mdwn [new file with mode: 0644]
doc/tips/importing_posts_from_typo.mdwn [new file with mode: 0644]
doc/tips/inside_dot_ikiwiki.mdwn
doc/tips/inside_dot_ikiwiki/discussion.mdwn
doc/tips/laptop_wiki_with_git.mdwn
doc/tips/laptop_wiki_with_git_extended.mdwn
doc/tips/mathopd_permissions.mdwn [new file with mode: 0644]
doc/tips/nearlyfreespeech/discussion.mdwn [new file with mode: 0644]
doc/tips/optimising_ikiwiki.mdwn [new file with mode: 0644]
doc/tips/parentlinks_style.mdwn
doc/tips/spam_and_softwaresites.mdwn [new file with mode: 0644]
doc/tips/switching_to_usedirs.mdwn
doc/tips/untrusted_git_push.mdwn
doc/tips/upgrade_to_3.0.mdwn
doc/tips/vim_syntax_highlighting.mdwn
doc/tips/yaml_setup_files.mdwn [new file with mode: 0644]
doc/todo/ACL.mdwn
doc/todo/Add_HTML_support_to_po_plugin.mdwn [new file with mode: 0644]
doc/todo/Add_label_to_search_form_input_field.mdwn
doc/todo/Add_nicer_math_formatting.mdwn [new file with mode: 0644]
doc/todo/CSS_classes_for_links.mdwn
doc/todo/CVS_backend.mdwn
doc/todo/Configurable_minimum_length_of_log_message_for_web_edits.mdwn
doc/todo/Fix_selflink_in_po_plugin.mdwn [new file with mode: 0644]
doc/todo/Google_Sitemap_protocol.mdwn
doc/todo/Mailing_list.mdwn
doc/todo/More_flexible_po-plugin_for_translation.mdwn [new file with mode: 0644]
doc/todo/Multiple_categorization_namespaces.mdwn [new file with mode: 0644]
doc/todo/OpenSearch.mdwn
doc/todo/Option_to_make_title_an_h1__63__.mdwn
doc/todo/Raw_view_link.mdwn
doc/todo/Resolve_native_reStructuredText_links_to_ikiwiki_pages.mdwn [new file with mode: 0644]
doc/todo/Restrict_page_viewing.mdwn [new file with mode: 0644]
doc/todo/Separate_OpenIDs_and_usernames.mdwn
doc/todo/Set_templates_for_whole_sections_of_the_site.mdwn [new file with mode: 0644]
doc/todo/Suggested_location_should_be_subpage_if_siblings_exist.mdwn
doc/todo/Support_XML-RPC-based_blogging.mdwn
doc/todo/a_navbar_based_on_page_properties.mdwn
doc/todo/abbreviation.mdwn
doc/todo/adjust_commit_message_for_rename__44___remove.mdwn [new file with mode: 0644]
doc/todo/allow_displaying_number_of_comments.mdwn [new file with mode: 0644]
doc/todo/allow_plugins_to_add_sorting_methods.mdwn [new file with mode: 0644]
doc/todo/allow_site-wide_meta_definitions.mdwn
doc/todo/anon_push_of_comments.mdwn [new file with mode: 0644]
doc/todo/auto-create_tag_pages_according_to_a_template.mdwn
doc/todo/auto_getctime_on_fresh_build.mdwn [new file with mode: 0644]
doc/todo/auto_publish_expire.mdwn [new file with mode: 0644]
doc/todo/auto_rebuild_on_template_change.mdwn [new file with mode: 0644]
doc/todo/avatar.mdwn
doc/todo/avoid_attachement_ui_if_upload_not_allowed.mdwn [new file with mode: 0644]
doc/todo/backlinks_result_is_lossy.mdwn
doc/todo/beef_up_sidebar_to_allow_for_multiple_sidebars.mdwn
doc/todo/blocking_ip_ranges.mdwn
doc/todo/cache_backlinks.mdwn [new file with mode: 0644]
doc/todo/cas_authentication.mdwn
doc/todo/cdate_and_mdate_available_for_templates.mdwn [new file with mode: 0644]
doc/todo/comment_moderation_feed.mdwn [new file with mode: 0644]
doc/todo/conflict_free_comment_merges.mdwn [new file with mode: 0644]
doc/todo/dependency_types.mdwn [new file with mode: 0644]
doc/todo/description_meta_param_passed_to_templates.mdwn [new file with mode: 0644]
doc/todo/double-click_protection_for_form_buttons.mdwn [new file with mode: 0644]
doc/todo/edit_form:_no_fixed_size_for_textarea.mdwn
doc/todo/edittemplate_should_look_in_templates_directory_by_default.mdwn [new file with mode: 0644]
doc/todo/enable-htaccess-files.mdwn
doc/todo/enable_arbitrary_markup_for_directives.mdwn [new file with mode: 0644]
doc/todo/finer_control_over___60__object___47____62__s.mdwn [new file with mode: 0644]
doc/todo/generated_po_stuff_not_ignored_by_git.mdwn
doc/todo/generic_insert_links [new file with mode: 0644]
doc/todo/git_attribution/discussion.mdwn
doc/todo/html.mdwn
doc/todo/htpasswd_mirror_of_the_userdb.mdwn [new file with mode: 0644]
doc/todo/http_bl_support.mdwn [new file with mode: 0644]
doc/todo/inline_plugin:_specifying_ordered_page_names.mdwn
doc/todo/l10n.mdwn
doc/todo/language_definition_for_the_meta_plugin.mdwn
doc/todo/link_plugin_perhaps_too_general__63__.mdwn [new file with mode: 0644]
doc/todo/make_link_target_search_all_paths_as_fallback.mdwn [new file with mode: 0644]
doc/todo/mark_edit_as_trivial__44___identify__47__filter_on_trivial_changes.mdwn [new file with mode: 0644]
doc/todo/matching_different_kinds_of_links.mdwn
doc/todo/mercurial.mdwn
doc/todo/mirrorlist_with_per-mirror_usedirs_settings.mdwn [new file with mode: 0644]
doc/todo/more_flexible_inline_postform.mdwn
doc/todo/multiple_template_directories.mdwn
doc/todo/multiple_templates.mdwn
doc/todo/openid_user_filtering.mdwn
doc/todo/optimize_simple_dependencies.mdwn [new file with mode: 0644]
doc/todo/optional_underlaydir_prefix.mdwn [new file with mode: 0644]
doc/todo/pagespec_to_disable_ikiwiki_directives.mdwn [new file with mode: 0644]
doc/todo/pagestats_among_a_subset_of_pages.mdwn
doc/todo/paste_plugin.mdwn [new file with mode: 0644]
doc/todo/po:_avoid_rebuilding_to_fix_meta_titles.mdwn [new file with mode: 0644]
doc/todo/po:_better_documentation.mdwn [new file with mode: 0644]
doc/todo/po:_better_links.mdwn [new file with mode: 0644]
doc/todo/po:_better_translation_interface.mdwn [new file with mode: 0644]
doc/todo/po:_remove_po_files_when_disabling_plugin.mdwn [new file with mode: 0644]
doc/todo/po:_rethink_pagespecs.mdwn [new file with mode: 0644]
doc/todo/po:_translation_of_directives.mdwn [new file with mode: 0644]
doc/todo/po_needstranslation_pagespec.mdwn [new file with mode: 0644]
doc/todo/preview_changes_before_git_commit.mdwn [new file with mode: 0644]
doc/todo/rewrite_ikiwiki_in_haskell.mdwn
doc/todo/salmon_protocol_for_comment_sharing.mdwn [new file with mode: 0644]
doc/todo/should_optimise_pagespecs.mdwn
doc/todo/smarter_sorting.mdwn [new file with mode: 0644]
doc/todo/sort_parameter_for_map_plugin_and_directive.mdwn [new file with mode: 0644]
doc/todo/source_link.mdwn
doc/todo/structured_page_data.mdwn
doc/todo/support_link__40__.__41___in_pagespec.mdwn [new file with mode: 0644]
doc/todo/svg.mdwn
doc/todo/tagging_with_a_publication_date.mdwn
doc/todo/tmplvars_plugin/discussion.mdwn [new file with mode: 0644]
doc/todo/toc_plugin:_set_a_header_ceiling___40__opposite_of_levels__61____41__.mdwn
doc/todo/tracking_bugs_with_dependencies.mdwn
doc/todo/two-way_convert_of_wikis.mdwn [new file with mode: 0644]
doc/todo/user-defined_templates_outside_the_wiki.mdwn [new file with mode: 0644]
doc/todo/want_to_avoid_ikiwiki_using_http_or_https_in_urls_to_allow_serving_both.mdwn
doc/todo/wrapperuser.mdwn [new file with mode: 0644]
doc/translation.mdwn
doc/usage.mdwn
doc/users/BerndZeimetz.mdwn [new file with mode: 0644]
doc/users/Christine_Spang.mdwn [new file with mode: 0644]
doc/users/David_Riebenbauer.mdwn [new file with mode: 0644]
doc/users/Edward_Betts.mdwn
doc/users/Jimmy_Tang.mdwn [new file with mode: 0644]
doc/users/KarlMW/discussion.mdwn
doc/users/KathrynAndersen.mdwn [new file with mode: 0644]
doc/users/KathrynAndersen/discussion.mdwn [new file with mode: 0644]
doc/users/Mick_Pollard.mdwn [new file with mode: 0644]
doc/users/NicolasLimare.mdwn
doc/users/Oblomov.mdwn [new file with mode: 0644]
doc/users/Perry.mdwn [new file with mode: 0644]
doc/users/Tim_Lavoie.mdwn [new file with mode: 0644]
doc/users/Will.mdwn
doc/users/blipvert.mdwn [new file with mode: 0644]
doc/users/emptty.mdwn [new file with mode: 0644]
doc/users/ericdrechsel.mdwn [new file with mode: 0644]
doc/users/harishcm.mdwn
doc/users/ivan_shmakov.mdwn [new file with mode: 0644]
doc/users/jasonblevins.mdwn
doc/users/jaywalk.mdwn [new file with mode: 0644]
doc/users/jeanprivat.mdwn [new file with mode: 0644]
doc/users/jerojasro.mdwn [new file with mode: 0644]
doc/users/jmtd.mdwn [new file with mode: 0644]
doc/users/jogo.mdwn [new file with mode: 0644]
doc/users/jon.mdwn
doc/users/joshtriplett.mdwn
doc/users/joshtriplett/discussion.mdwn [new file with mode: 0644]
doc/users/nil.mdwn [new file with mode: 0644]
doc/users/rubykat.mdwn [new file with mode: 0644]
doc/users/schmonz.mdwn
doc/users/simonraven.mdwn
doc/users/svend.mdwn
doc/users/tschwinge.mdwn
doc/users/tupyakov_vladimir.mdwn [new file with mode: 0644]
doc/users/tychoish.mdwn
doc/users/ulrik.mdwn [new file with mode: 0644]
doc/users/weakish.mdwn
doc/users/xma.mdwn [deleted file]
doc/w3mmode.mdwn
doc/wikitemplates.mdwn [deleted file]
doc/wikitemplates/discussion.mdwn [deleted file]
docwiki.setup
gitremotes
ikiwiki-calendar.in [new file with mode: 0755]
ikiwiki-makerepo
ikiwiki-transition.in [moved from ikiwiki-transition with 95% similarity]
ikiwiki.in
ikiwiki.spec [new file with mode: 0644]
mdwn2man
plugins/externaldemo
plugins/pythondemo
plugins/rst
po/Makefile
po/bg.po
po/cs.po
po/da.po
po/de.po
po/es.po
po/fr.po
po/gu.po
po/ikiwiki.pot
po/it.po [new file with mode: 0644]
po/pl.po
po/sv.po
po/tr.po [new file with mode: 0644]
po/underlay.setup
po/underlays/basewiki/ikiwiki.cs.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki.da.po
po/underlays/basewiki/ikiwiki.de.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki.es.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki.fr.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/blog.da.po [deleted file]
po/underlays/basewiki/ikiwiki/directive.cs.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/directive.de.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/directive.es.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/directive.fr.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/formatting.cs.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/formatting.da.po
po/underlays/basewiki/ikiwiki/formatting.de.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/formatting.es.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/formatting.fr.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/markdown.cs.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/markdown.de.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/markdown.es.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/markdown.fr.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/openid.cs.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/openid.da.po
po/underlays/basewiki/ikiwiki/openid.de.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/openid.es.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/openid.fr.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/pagespec.cs.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/pagespec.da.po
po/underlays/basewiki/ikiwiki/pagespec.de.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/pagespec.es.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/pagespec.fr.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/pagespec/attachment.cs.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/pagespec/attachment.da.po
po/underlays/basewiki/ikiwiki/pagespec/attachment.de.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/pagespec/attachment.es.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/pagespec/attachment.fr.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/pagespec/po.cs.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/pagespec/po.da.po
po/underlays/basewiki/ikiwiki/pagespec/po.de.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/pagespec/po.es.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/pagespec/po.fr.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/pagespec/sorting.de.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/preprocessordirective.da.po [deleted file]
po/underlays/basewiki/ikiwiki/searching.cs.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/searching.da.po
po/underlays/basewiki/ikiwiki/searching.de.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/searching.es.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/searching.fr.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/subpage.cs.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/subpage.da.po
po/underlays/basewiki/ikiwiki/subpage.de.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/subpage.es.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/subpage.fr.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/subpage/linkingrules.cs.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/subpage/linkingrules.de.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/subpage/linkingrules.es.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/subpage/linkingrules.fr.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/wikilink.cs.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/wikilink.da.po
po/underlays/basewiki/ikiwiki/wikilink.de.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/wikilink.es.po [new file with mode: 0644]
po/underlays/basewiki/ikiwiki/wikilink.fr.po [new file with mode: 0644]
po/underlays/basewiki/index.cs.po [new file with mode: 0644]
po/underlays/basewiki/index.da.po
po/underlays/basewiki/index.de.po [new file with mode: 0644]
po/underlays/basewiki/index.es.po [new file with mode: 0644]
po/underlays/basewiki/index.fr.po [new file with mode: 0644]
po/underlays/basewiki/recentchanges.cs.po [new file with mode: 0644]
po/underlays/basewiki/recentchanges.de.po [new file with mode: 0644]
po/underlays/basewiki/recentchanges.es.po [new file with mode: 0644]
po/underlays/basewiki/recentchanges.fr.po [new file with mode: 0644]
po/underlays/basewiki/sandbox.cs.po [new file with mode: 0644]
po/underlays/basewiki/sandbox.de.po [new file with mode: 0644]
po/underlays/basewiki/sandbox.es.po [new file with mode: 0644]
po/underlays/basewiki/sandbox.fr.po [new file with mode: 0644]
po/underlays/basewiki/shortcuts.cs.po [new file with mode: 0644]
po/underlays/basewiki/shortcuts.da.po
po/underlays/basewiki/shortcuts.de.po [new file with mode: 0644]
po/underlays/basewiki/shortcuts.es.po [new file with mode: 0644]
po/underlays/basewiki/shortcuts.fr.po [new file with mode: 0644]
po/underlays/basewiki/templates.cs.po [new file with mode: 0644]
po/underlays/basewiki/templates.da.po
po/underlays/basewiki/templates.de.po [new file with mode: 0644]
po/underlays/basewiki/templates.es.po [new file with mode: 0644]
po/underlays/basewiki/templates.fr.po [new file with mode: 0644]
po/underlays/basewiki/templates/note.cs.po [new file with mode: 0644]
po/underlays/basewiki/templates/note.da.po
po/underlays/basewiki/templates/note.de.po [new file with mode: 0644]
po/underlays/basewiki/templates/note.es.po [new file with mode: 0644]
po/underlays/basewiki/templates/note.fr.po [new file with mode: 0644]
po/underlays/basewiki/templates/popup.cs.po [new file with mode: 0644]
po/underlays/basewiki/templates/popup.da.po
po/underlays/basewiki/templates/popup.de.po [new file with mode: 0644]
po/underlays/basewiki/templates/popup.es.po [new file with mode: 0644]
po/underlays/basewiki/templates/popup.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/aggregate.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/aggregate.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/brokenlinks.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/brokenlinks.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/calendar.da.po
po/underlays/directives/ikiwiki/directive/calendar.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/calendar.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/color.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/color.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/comment.da.po
po/underlays/directives/ikiwiki/directive/comment.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/comment.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/copy.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/copy.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/cut.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/cut.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/cutpaste.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/cutpaste.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/date.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/edittemplate.da.po
po/underlays/directives/ikiwiki/directive/edittemplate.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/edittemplate.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/format.da.po
po/underlays/directives/ikiwiki/directive/format.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/format.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/fortune.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/fortune.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/graph.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/graph.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/haiku.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/haiku.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/if.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/if.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/img.da.po
po/underlays/directives/ikiwiki/directive/img.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/img.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/inline.da.po
po/underlays/directives/ikiwiki/directive/inline.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/inline.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/linkmap.da.po
po/underlays/directives/ikiwiki/directive/linkmap.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/linkmap.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/listdirectives.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/listdirectives.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/map.da.po
po/underlays/directives/ikiwiki/directive/map.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/map.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/meta.da.po
po/underlays/directives/ikiwiki/directive/meta.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/meta.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/more.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/more.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/orphans.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/orphans.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/pagecount.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/pagecount.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/pagestats.da.po
po/underlays/directives/ikiwiki/directive/pagestats.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/pagestats.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/pagetemplate.da.po
po/underlays/directives/ikiwiki/directive/pagetemplate.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/pagetemplate.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/paste.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/paste.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/ping.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/ping.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/poll.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/poll.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/polygen.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/polygen.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/postsparkline.da.po
po/underlays/directives/ikiwiki/directive/postsparkline.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/postsparkline.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/progress.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/progress.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/shortcut.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/shortcut.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/sparkline.da.po
po/underlays/directives/ikiwiki/directive/sparkline.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/sparkline.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/table.da.po
po/underlays/directives/ikiwiki/directive/table.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/table.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/tag.da.po
po/underlays/directives/ikiwiki/directive/tag.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/tag.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/taglink.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/taglink.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/template.da.po
po/underlays/directives/ikiwiki/directive/template.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/template.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/testpagespec.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/testpagespec.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/teximg.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/teximg.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/toc.da.po
po/underlays/directives/ikiwiki/directive/toc.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/toc.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/toggle.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/toggle.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/toggleable.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/toggleable.fr.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/version.de.po [new file with mode: 0644]
po/underlays/directives/ikiwiki/directive/version.fr.po [new file with mode: 0644]
po/underlays/smiley/smileys.de.po [new file with mode: 0644]
po/underlays/smiley/smileys.fr.po [new file with mode: 0644]
po/vi.po
t/add_depends.t [new file with mode: 0755]
t/basewiki_brokenlinks.t
t/bazaar.t
t/bestlink.t
t/calculate_changed_links.t [new file with mode: 0755]
t/conflicts.t [new file with mode: 0755]
t/cvs.t [new file with mode: 0755]
t/file_pruned.t
t/find_src_files.t [new file with mode: 0755]
t/git.t
t/htmlize.t
t/index.t
t/mercurial.t
t/openiduser.t
t/pagespec_match.t
t/pagespec_match_list.t [new file with mode: 0755]
t/pagespec_match_result.t [new file with mode: 0755]
t/pagespec_merge.t [deleted file]
t/parentlinks.t
t/permalink.t
t/po.t
t/preprocess.t
t/svn.t
t/tag.t [new file with mode: 0755]
t/template_syntax.t [new file with mode: 0755]
t/templates_documented.t [new file with mode: 0755]
t/yesno.t
templates/aggregatepost.tmpl
templates/archivepage.tmpl
templates/atomitem.tmpl
templates/atompage.tmpl
templates/autotag.tmpl [new file with mode: 0644]
templates/blogpost.tmpl
templates/calendarmonth.tmpl [new file with mode: 0644]
templates/calendaryear.tmpl [new file with mode: 0644]
templates/change.tmpl
templates/comment.tmpl
templates/commentmoderation.tmpl
templates/editcomment.tmpl
templates/editpage.tmpl
templates/feedlink.tmpl
templates/googleform.tmpl
templates/inlinepage.tmpl
templates/microblog.tmpl
templates/misc.tmpl [deleted file]
templates/openid-selector.tmpl [new file with mode: 0644]
templates/page.tmpl
templates/pocreatepage.tmpl
templates/renamesummary.tmpl
templates/rssitem.tmpl
templates/searchform.tmpl
templates/searchquery.tmpl
templates/titlepage.tmpl
themes/actiontabs/style.css [new file with mode: 0644]
themes/blueview/background_darkness.png [new file with mode: 0644]
themes/blueview/header_background.png [new file with mode: 0644]
themes/blueview/style.css [new file with mode: 0644]
underlays/basewiki/ikiwiki/blog.mdwn [deleted file]
underlays/basewiki/ikiwiki/pagespec/sorting.mdwn [new symlink]
underlays/basewiki/ikiwiki/preprocessordirective.mdwn [deleted file]
underlays/javascript/ikiwiki/ikiwiki.js [moved from underlays/javascript/ikiwiki.js with 95% similarity]
underlays/javascript/ikiwiki/relativedate.js [moved from underlays/javascript/relativedate.js with 67% similarity]
underlays/javascript/ikiwiki/toggle.js [moved from underlays/javascript/toggle.js with 100% similarity]
underlays/openid-selector/ikiwiki/openid/jquery.js [new file with mode: 0644]
underlays/openid-selector/ikiwiki/openid/openid-jquery.js [new file with mode: 0644]

diff --git a/.gitattributes b/.gitattributes
new file mode 100644 (file)
index 0000000..5d42584
--- /dev/null
@@ -0,0 +1 @@
+debian/changelog merge=dpkg-mergechangelogs
index 8de36e2c8df25ab30f7fadeffbcdf25f189863f3..e9ab152b6413d20385e317c7020406b01268f607 100644 (file)
@@ -5,9 +5,10 @@ blib/*
 doc/.ikiwiki/*
 html/*
 ikiwiki.out
+ikiwiki-transition.out
+ikiwiki-calendar.out
 pm_to_blib
 *.man
-build-stamp
 po/po2wiki_stamp
 po/underlays/*/*.mdwn
 po/underlays/basewiki/*/*.mdwn
index 769791d305b17ce03f6159a8d3094dbdb026cb80..d6c344d6a0a2b7b6bfacec2abb49edb77a085a09 100644 (file)
@@ -20,7 +20,7 @@ Text::Markdown
 HTML::Scrubber
 HTML::Template
 HTML::Parser
-URI
+URI 1.36
 XML::Simple
 Date::Parse
 CGI::FormBuilder
index 48bd127f1745c72459c213247cde1b3ffa3e4430..64e907306544b150a48cc0668ded1f3cccae745e 100644 (file)
@@ -16,7 +16,6 @@ perl -MCPAN -e 'install Bundle::IkiWiki::Extras'
 
 =head1 CONTENTS
 
-Digest::SHA1
 Authen::Passphrase
 Search::Xapian
 RPC::XML
@@ -35,6 +34,7 @@ Text::WikiCreole
 Term::ReadLine::Gnu
 HTML::Tree
 Sort::Naturally
+YAML
 
 =head1 AUTHOR
 
index a11b330f2126a038f69678512e1a1ba2f2c238fb..df8abe2c2711281c220a604aa0ddca09ec915a02 100644 (file)
@@ -5,34 +5,41 @@ package IkiWiki;
 use warnings;
 use strict;
 use Encode;
-use HTML::Entities;
 use URI::Escape q{uri_escape_utf8};
-use POSIX;
+use POSIX ();
 use Storable;
 use open qw{:utf8 :std};
 
 use vars qw{%config %links %oldlinks %pagemtime %pagectime %pagecase
-           %pagestate %wikistate %renderedfiles %oldrenderedfiles
-           %pagesources %destsources %depends %hooks %forcerebuild
-           %loaded_plugins};
+       %pagestate %wikistate %renderedfiles %oldrenderedfiles
+       %pagesources %delpagesources %destsources %depends %depends_simple
+       @mass_depends %hooks %forcerebuild %loaded_plugins %typedlinks
+       %oldtypedlinks %autofiles};
 
 use Exporter q{import};
-our @EXPORT = qw(hook debug error template htmlpage add_depends pagespec_match
-                 pagespec_match_list bestlink htmllink readfile writefile
-                pagetype srcfile pagename displaytime will_render gettext urlto
-                targetpage add_underlay pagetitle titlepage linkpage
-                newpagefile inject add_link
-                 %config %links %pagestate %wikistate %renderedfiles
-                 %pagesources %destsources);
+our @EXPORT = qw(hook debug error htmlpage template template_depends
+       deptype add_depends pagespec_match pagespec_match_list bestlink
+       htmllink readfile writefile pagetype srcfile pagename
+       displaytime will_render gettext ngettext urlto targetpage
+       add_underlay pagetitle titlepage linkpage newpagefile
+       inject add_link add_autofile
+       %config %links %pagestate %wikistate %renderedfiles
+       %pagesources %destsources %typedlinks);
 our $VERSION = 3.00; # plugin interface version, next is ikiwiki version
 our $version='unknown'; # VERSION_AUTOREPLACE done by Makefile, DNE
 our $installdir='/usr'; # INSTALLDIR_AUTOREPLACE done by Makefile, DNE
 
+# Page dependency types.
+our $DEPEND_CONTENT=1;
+our $DEPEND_PRESENCE=2;
+our $DEPEND_LINKS=4;
+
 # Optimisation.
 use Memoize;
 memoize("abs2rel");
+memoize("sortspec_translate");
 memoize("pagespec_translate");
-memoize("file_pruned");
+memoize("template_file");
 
 sub getsetup () {
        wikiname => {
@@ -144,7 +151,7 @@ sub getsetup () {
        templatedir => {
                type => "string",
                default => "$installdir/share/ikiwiki/templates",
-               description => "location of template files",
+               description => "additional directory to search for template files",
                advanced => 1,
                safe => 0, # path
                rebuild => 1,
@@ -220,6 +227,21 @@ sub getsetup () {
                safe => 1,
                rebuild => 1,
        },
+       discussionpage => {
+               type => "string",
+               default => gettext("Discussion"),
+               description => "name of Discussion pages",
+               safe => 1,
+               rebuild => 1,
+       },
+       html5 => {
+               type => "boolean",
+               default => 0,
+               description => "generate HTML5? (experimental)",
+               advanced => 1,
+               safe => 1,
+               rebuild => 1,
+       },
        sslcookie => {
                type => "boolean",
                default => 0,
@@ -314,22 +336,31 @@ sub getsetup () {
                safe => 0, # paranoia
                rebuild => 0,
        },
+       include => {
+               type => "string",
+               default => undef,
+               example => '^\.htaccess$',
+               description => "regexp of normally excluded files to include",
+               advanced => 1,
+               safe => 0, # regexp
+               rebuild => 1,
+       },
        exclude => {
                type => "string",
                default => undef,
-               example => '\.wav$',
-               description => "regexp of source files to ignore",
+               example => '^(*\.private|Makefile)$',
+               description => "regexp of files that should be skipped",
                advanced => 1,
                safe => 0, # regexp
                rebuild => 1,
        },
        wiki_file_prune_regexps => {
                type => "internal",
-               default => [qr/(^|\/)\.\.(\/|$)/, qr/^\./, qr/\/\./,
+               default => [qr/(^|\/)\.\.(\/|$)/, qr/^\//, qr/^\./, qr/\/\./,
                        qr/\.x?html?$/, qr/\.ikiwiki-new$/,
                        qr/(^|\/).svn\//, qr/.arch-ids\//, qr/{arch}\//,
                        qr/(^|\/)_MTN\//, qr/(^|\/)_darcs\//,
-                       qr/\.dpkg-tmp$/],
+                       qr/(^|\/)CVS\//, qr/\.dpkg-tmp$/],
                description => "regexps of source files to ignore",
                safe => 0,
                rebuild => 1,
@@ -349,7 +380,7 @@ sub getsetup () {
        },
        web_commit_regexp => {
                type => "internal",
-               default => qr/^web commit (by (.*?(?=: |$))|from (\d+\.\d+\.\d+\.\d+)):?(.*)/,
+               default => qr/^web commit (by (.*?(?=: |$))|from ([0-9a-fA-F:.]+[0-9a-fA-F])):?(.*)/,
                description => "regexp to parse web commits from logs",
                safe => 0,
                rebuild => 0,
@@ -389,6 +420,13 @@ sub getsetup () {
                safe => 0,
                rebuild => 0,
        },
+       clean => {
+               type => "internal",
+               default => 0,
+               description => "running in clean mode",
+               safe => 0,
+               rebuild => 0,
+       },
        refresh => {
                type => "internal",
                default => 0,
@@ -403,10 +441,16 @@ sub getsetup () {
                safe => 0,
                rebuild => 0,
        },
-       getctime => {
+       wrapper_background_command => {
                type => "internal",
-               default => 0,
-               description => "running in getctime mode",
+               default => '',
+               description => "background shell command to run",
+               safe => 0,
+               rebuild => 0,
+       },
+       gettime => {
+               type => "internal",
+               description => "running in gettime mode",
                safe => 0,
                rebuild => 0,
        },
@@ -431,6 +475,13 @@ sub getsetup () {
                safe => 0,
                rebuild => 0,
        },
+       setuptype => {
+               type => "internal",
+               default => "Standard",
+               description => "perl class to use to dump setup file",
+               safe => 0,
+               rebuild => 0,
+       },
        allow_symlinks_before_srcdir => {
                type => "boolean",
                default => 0,
@@ -529,12 +580,12 @@ sub loadplugins () {
        }
        
        if ($config{rcs}) {
-               if (exists $IkiWiki::hooks{rcs}) {
+               if (exists $hooks{rcs}) {
                        error(gettext("cannot use multiple rcs plugins"));
                }
                loadplugin($config{rcs});
        }
-       if (! exists $IkiWiki::hooks{rcs}) {
+       if (! exists $hooks{rcs}) {
                loadplugin("norcs");
        }
 
@@ -548,10 +599,11 @@ sub loadplugins () {
        return 1;
 }
 
-sub loadplugin ($) {
+sub loadplugin ($;$) {
        my $plugin=shift;
+       my $force=shift;
 
-       return if grep { $_ eq $plugin} @{$config{disable_plugins}};
+       return if ! $force && grep { $_ eq $plugin} @{$config{disable_plugins}};
 
        foreach my $dir (defined $config{libdir} ? possibly_foolish_untaint($config{libdir}) : undef,
                         "$installdir/lib/ikiwiki") {
@@ -654,9 +706,15 @@ sub pagetype ($) {
        return;
 }
 
+my %pagename_cache;
+
 sub pagename ($) {
        my $file=shift;
 
+       if (exists $pagename_cache{$file}) {
+               return $pagename_cache{$file};
+       }
+
        my $type=pagetype($file);
        my $page=$file;
        $page=~s/\Q.$type\E*$//
@@ -665,6 +723,8 @@ sub pagename ($) {
        if ($config{indexpages} && $page=~/(.*)\/index$/) {
                $page=$1;
        }
+
+       $pagename_cache{$file} = $page;
        return $page;
 }
 
@@ -763,6 +823,17 @@ sub prep_writefile ($$) {
                if (-l "$destdir/$test") {
                        error("cannot write to a symlink ($test)");
                }
+               if (-f _ && $test ne $file) {
+                       # Remove conflicting file.
+                       foreach my $p (keys %renderedfiles, keys %oldrenderedfiles) {
+                               foreach my $f (@{$renderedfiles{$p}}, @{$oldrenderedfiles{$p}}) {
+                                       if ($f eq $test) {
+                                               unlink("$destdir/$test");
+                                               last;
+                                       }
+                               }
+                       }
+               }
                $test=dirname($test);
        }
 
@@ -816,10 +887,36 @@ sub will_render ($$;$) {
        my $dest=shift;
        my $clear=shift;
 
-       # Important security check.
+       # Important security check for independently created files.
        if (-e "$config{destdir}/$dest" && ! $config{rebuild} &&
            ! grep { $_ eq $dest } (@{$renderedfiles{$page}}, @{$oldrenderedfiles{$page}}, @{$wikistate{editpage}{previews}})) {
-               error("$config{destdir}/$dest independently created, not overwriting with version from $page");
+               my $from_other_page=0;
+               # Expensive, but rarely runs.
+               foreach my $p (keys %renderedfiles, keys %oldrenderedfiles) {
+                       if (grep {
+                               $_ eq $dest ||
+                               dirname($_) eq $dest
+                           } @{$renderedfiles{$p}}, @{$oldrenderedfiles{$p}}) {
+                               $from_other_page=1;
+                               last;
+                       }
+               }
+
+               error("$config{destdir}/$dest independently created, not overwriting with version from $page")
+                       unless $from_other_page;
+       }
+
+       # If $dest exists as a directory, remove conflicting files in it
+       # rendered from other pages.
+       if (-d _) {
+               foreach my $p (keys %renderedfiles, keys %oldrenderedfiles) {
+                       foreach my $f (@{$renderedfiles{$p}}, @{$oldrenderedfiles{$p}}) {
+                               if (dirname($f) eq $dest) {
+                                       unlink("$config{destdir}/$f");
+                                       rmdir(dirname("$config{destdir}/$f"));
+                               }
+                       }
+               }
        }
 
        if (! $clear || $cleared{$page}) {
@@ -853,7 +950,7 @@ sub bestlink ($$) {
                $l.="/" if length $l;
                $l.=$link;
 
-               if (exists $links{$l}) {
+               if (exists $pagesources{$l}) {
                        return $l;
                }
                elsif (exists $pagecase{lc $l}) {
@@ -863,7 +960,7 @@ sub bestlink ($$) {
 
        if (length $config{userdir}) {
                my $l = "$config{userdir}/".lc($link);
-               if (exists $links{$l}) {
+               if (exists $pagesources{$l}) {
                        return $l;
                }
                elsif (exists $pagecase{lc $l}) {
@@ -913,7 +1010,12 @@ sub linkpage ($) {
 sub cgiurl (@) {
        my %params=@_;
 
-       return $config{cgiurl}."?".
+       my $cgiurl=$config{cgiurl};
+       if (exists $params{cgiurl}) {
+               $cgiurl=$params{cgiurl};
+               delete $params{cgiurl};
+       }
+       return $cgiurl."?".
                join("&amp;", map $_."=".uri_escape_utf8($params{$_}), keys %params);
 }
 
@@ -941,10 +1043,18 @@ sub abs2rel ($$) {
        return $ret;
 }
 
-sub displaytime ($;$) {
+sub displaytime ($;$$) {
        # Plugins can override this function to mark up the time to
        # display.
-       return '<span class="date">'.formattime(@_).'</span>';
+       my $time=formattime($_[0], $_[1]);
+       if ($config{html5}) {
+               return '<time datetime="'.date_3339($_[0]).'"'.
+                       ($_[2] ? ' pubdate="pubdate"' : '').
+                       '>'.$time.'</time>';
+       }
+       else {
+               return '<span class="date">'.$time.'</span>';
+       }
 }
 
 sub formattime ($;$) {
@@ -960,6 +1070,16 @@ sub formattime ($;$) {
        return decode_utf8(POSIX::strftime($format, localtime($time)));
 }
 
+sub date_3339 ($) {
+       my $time=shift;
+
+       my $lc_time=POSIX::setlocale(&POSIX::LC_TIME);
+       POSIX::setlocale(&POSIX::LC_TIME, "C");
+       my $ret=POSIX::strftime("%Y-%m-%dT%H:%M:%SZ", gmtime($time));
+       POSIX::setlocale(&POSIX::LC_TIME, $lc_time);
+       return $ret;
+}
+
 sub beautify_urlpath ($) {
        my $url=shift;
 
@@ -998,6 +1118,15 @@ sub urlto ($$;$) {
        return beautify_urlpath($link);
 }
 
+sub isselflink ($$) {
+       # Plugins can override this function to support special types
+       # of selflinks.
+       my $page=shift;
+       my $link=shift;
+
+        return $page eq $link;
+}
+
 sub htmllink ($$$;@) {
        my $lpage=shift; # the page doing the linking
        my $page=shift; # the page that will contain the link (different for inline)
@@ -1023,21 +1152,23 @@ sub htmllink ($$$;@) {
        }
        
        return "<span class=\"selflink\">$linktext</span>"
-               if length $bestlink && $page eq $bestlink &&
+               if length $bestlink && isselflink($page, $bestlink) &&
                   ! defined $opts{anchor};
        
        if (! $destsources{$bestlink}) {
                $bestlink=htmlpage($bestlink);
 
                if (! $destsources{$bestlink}) {
-                       return $linktext unless length $config{cgiurl};
-                       return "<span class=\"createlink\"><a href=\"".
-                               cgiurl(
-                                       do => "create",
-                                       page => lc($link),
-                                       from => $lpage
-                               ).
-                               "\" rel=\"nofollow\">?</a>$linktext</span>"
+                       my $cgilink = "";
+                       if (length $config{cgiurl}) {
+                               $cgilink = "<a href=\"".
+                                       cgiurl(
+                                               do => "create",
+                                               page => lc($link),
+                                               from => $lpage
+                                       )."\" rel=\"nofollow\">?</a>";
+                       }
+                       return "<span class=\"createlink\">$cgilink$linktext</span>"
                }
        }
        
@@ -1053,16 +1184,20 @@ sub htmllink ($$$;@) {
        }
 
        my @attrs;
-       if (defined $opts{rel}) {
-               push @attrs, ' rel="'.$opts{rel}.'"';
-       }
-       if (defined $opts{class}) {
-               push @attrs, ' class="'.$opts{class}.'"';
+       foreach my $attr (qw{rel class title}) {
+               if (defined $opts{$attr}) {
+                       push @attrs, " $attr=\"$opts{$attr}\"";
+               }
        }
 
        return "<a href=\"$bestlink\"@attrs>$linktext</a>";
 }
 
+sub userpage ($) {
+       my $user=shift;
+       return length $config{userdir} ? "$config{userdir}/$user" : $user;
+}
+
 sub openiduser ($) {
        my $user=shift;
 
@@ -1071,11 +1206,10 @@ sub openiduser ($) {
                my $display;
 
                if (Net::OpenID::VerifiedIdentity->can("DisplayOfURL")) {
-                       # this works in at least 2.x
                        $display = Net::OpenID::VerifiedIdentity::DisplayOfURL($user);
                }
                else {
-                       # this only works in 1.x
+                       # backcompat with old version
                        my $oid=Net::OpenID::VerifiedIdentity->new(identity => $user);
                        $display=$oid->display;
                }
@@ -1088,7 +1222,7 @@ sub openiduser ($) {
                # Convert "http://somehost.com/user" to "user [somehost.com]".
                # (also "https://somehost.com/user/")
                if ($display !~ /\[/) {
-                       $display=~s/^https?:\/\/(.+)\/([^\/]+)\/?$/$2 [$1]/;
+                       $display=~s/^https?:\/\/(.+)\/([^\/#?]+)\/?(?:[#?].*)?$/$2 [$1]/;
                }
                $display=~s!^https?://!!; # make sure this is removed
                eval q{use CGI 'escapeHTML'};
@@ -1098,23 +1232,6 @@ sub openiduser ($) {
        return;
 }
 
-sub userlink ($) {
-       my $user=shift;
-
-       my $oiduser=eval { openiduser($user) };
-       if (defined $oiduser) {
-               return "<a href=\"$user\">$oiduser</a>";
-       }
-       else {
-               eval q{use CGI 'escapeHTML'};
-               error($@) if $@;
-
-               return htmllink("", "", escapeHTML(
-                       length $config{userdir} ? $config{userdir}."/".$user : $user
-               ), noimageinline => 1);
-       }
-}
-
 sub htmlize ($$$$) {
        my $page=shift;
        my $destpage=shift;
@@ -1122,7 +1239,7 @@ sub htmlize ($$$$) {
        my $content=shift;
        
        my $oneline = $content !~ /\n/;
-
+       
        if (exists $hooks{htmlize}{$type}) {
                $content=$hooks{htmlize}{$type}{call}->(
                        page => $page,
@@ -1143,10 +1260,9 @@ sub htmlize ($$$$) {
        
        if ($oneline) {
                # hack to get rid of enclosing junk added by markdown
-               # and other htmlizers
+               # and other htmlizers/sanitizers
                $content=~s/^<p>//i;
-               $content=~s/<\/p>$//i;
-               chomp $content;
+               $content=~s/<\/p>\n*$//i;
        }
 
        return $content;
@@ -1201,7 +1317,7 @@ sub preprocess ($$$;$$) {
                                (?:
                                        """(.*?)"""     # 2: triple-quoted value
                                |
-                                       "([^"]+)"       # 3: single-quoted value
+                                       "([^"]*?)"      # 3: single-quoted value
                                |
                                        (\S+)           # 4: unquoted value
                                )
@@ -1248,9 +1364,10 @@ sub preprocess ($$$;$$) {
                                        );
                                };
                                if ($@) {
-                                       chomp $@;
+                                       my $error=$@;
+                                       chomp $error;
                                        $ret="[[!$command <span class=\"error\">".
-                                               gettext("Error").": $@"."</span>]]";
+                                               gettext("Error").": $error"."</span>]]";
                                }
                        }
                        else {
@@ -1286,7 +1403,7 @@ sub preprocess ($$$;$$) {
                                        (?:
                                                """.*?"""       # triple-quoted value
                                                |
-                                               "[^"]+"         # single-quoted value
+                                               "[^"]*?"        # single-quoted value
                                                |
                                                [^"\s\]]+       # unquoted value
                                        )
@@ -1309,7 +1426,7 @@ sub preprocess ($$$;$$) {
                                        (?:
                                                """.*?"""       # triple-quoted value
                                                |
-                                               "[^"]+"         # single-quoted value
+                                               "[^"]*?"        # single-quoted value
                                                |
                                                [^"\s\]]+       # unquoted value
                                        )
@@ -1338,10 +1455,6 @@ sub filter ($$$) {
        return $content;
 }
 
-sub indexlink () {
-       return "<a href=\"$config{url}\">$config{wikiname}</a>";
-}
-
 sub check_canedit ($$$;$) {
        my $page=shift;
        my $q=shift;
@@ -1379,7 +1492,7 @@ sub check_content (@) {
                my %old=map { $_ => 1 }
                        split("\n", readfile(srcfile($pagesources{$params{page}})));
                foreach my $line (split("\n", $params{content})) {
-                       push @diff, $line if ! exists $old{$_};
+                       push @diff, $line if ! exists $old{$line};
                }
                $params{diff}=join("\n", @diff);
        }
@@ -1459,7 +1572,8 @@ sub loadindex () {
        %oldrenderedfiles=%pagectime=();
        if (! $config{rebuild}) {
                %pagesources=%pagemtime=%oldlinks=%links=%depends=
-               %destsources=%renderedfiles=%pagecase=%pagestate=();
+               %destsources=%renderedfiles=%pagecase=%pagestate=
+               %depends_simple=%typedlinks=%oldtypedlinks=();
        }
        my $in;
        if (! open ($in, "<", "$config{wikistatedir}/indexdb")) {
@@ -1468,6 +1582,7 @@ sub loadindex () {
                        open ($in, "<", "$config{wikistatedir}/indexdb") || return;
                }
                else {
+                       $config{gettime}=1; # first build
                        return;
                }
        }
@@ -1481,6 +1596,12 @@ sub loadindex () {
        if (exists $index->{version} && ! ref $index->{version}) {
                $pages=$index->{page};
                %wikistate=%{$index->{state}};
+               # Handle plugins that got disabled by loading a new setup.
+               if (exists $config{setupfile}) {
+                       require IkiWiki::Setup;
+                       IkiWiki::Setup::disabled_plugins(
+                               grep { ! $loaded_plugins{$_} } keys %wikistate);
+               }
        }
        else {
                $pages=$index;
@@ -1491,20 +1612,48 @@ sub loadindex () {
                my $d=$pages->{$src};
                my $page=pagename($src);
                $pagectime{$page}=$d->{ctime};
+               $pagesources{$page}=$src;
                if (! $config{rebuild}) {
-                       $pagesources{$page}=$src;
                        $pagemtime{$page}=$d->{mtime};
                        $renderedfiles{$page}=$d->{dest};
                        if (exists $d->{links} && ref $d->{links}) {
                                $links{$page}=$d->{links};
                                $oldlinks{$page}=[@{$d->{links}}];
                        }
-                       if (exists $d->{depends}) {
+                       if (ref $d->{depends_simple} eq 'ARRAY') {
+                               # old format
+                               $depends_simple{$page}={
+                                       map { $_ => 1 } @{$d->{depends_simple}}
+                               };
+                       }
+                       elsif (exists $d->{depends_simple}) {
+                               $depends_simple{$page}=$d->{depends_simple};
+                       }
+                       if (exists $d->{dependslist}) {
+                               # old format
+                               $depends{$page}={
+                                       map { $_ => $DEPEND_CONTENT }
+                                               @{$d->{dependslist}}
+                               };
+                       }
+                       elsif (exists $d->{depends} && ! ref $d->{depends}) {
+                               # old format
+                               $depends{$page}={$d->{depends} => $DEPEND_CONTENT };
+                       }
+                       elsif (exists $d->{depends}) {
                                $depends{$page}=$d->{depends};
                        }
                        if (exists $d->{state}) {
                                $pagestate{$page}=$d->{state};
                        }
+                       if (exists $d->{typedlinks}) {
+                               $typedlinks{$page}=$d->{typedlinks};
+
+                               while (my ($type, $links) = each %{$typedlinks{$page}}) {
+                                       next unless %$links;
+                                       $oldtypedlinks{$page}{$type} = {%$links};
+                               }
+                       }
                }
                $oldrenderedfiles{$page}=[@{$d->{dest}}];
        }
@@ -1520,11 +1669,7 @@ sub loadindex () {
 sub saveindex () {
        run_hooks(savestate => sub { shift->() });
 
-       my %hookids;
-       foreach my $type (keys %hooks) {
-               $hookids{$_}=1 foreach keys %{$hooks{$type}};
-       }
-       my @hookids=keys %hookids;
+       my @plugins=keys %loaded_plugins;
 
        if (! -d $config{wikistatedir}) {
                mkdir($config{wikistatedir});
@@ -1549,8 +1694,16 @@ sub saveindex () {
                        $index{page}{$src}{depends} = $depends{$page};
                }
 
+               if (exists $depends_simple{$page}) {
+                       $index{page}{$src}{depends_simple} = $depends_simple{$page};
+               }
+
+               if (exists $typedlinks{$page} && %{$typedlinks{$page}}) {
+                       $index{page}{$src}{typedlinks} = $typedlinks{$page};
+               }
+
                if (exists $pagestate{$page}) {
-                       foreach my $id (@hookids) {
+                       foreach my $id (@plugins) {
                                foreach my $key (keys %{$pagestate{$page}{$id}}) {
                                        $index{page}{$src}{state}{$id}{$key}=$pagestate{$page}{$id}{$key};
                                }
@@ -1559,7 +1712,8 @@ sub saveindex () {
        }
 
        $index{state}={};
-       foreach my $id (@hookids) {
+       foreach my $id (@plugins) {
+               $index{state}{$id}={}; # used to detect disabled plugins
                foreach my $key (keys %{$wikistate{$id}}) {
                        $index{state}{$id}{$key}=$wikistate{$id}{$key};
                }
@@ -1576,59 +1730,127 @@ sub saveindex () {
 }
 
 sub template_file ($) {
-       my $template=shift;
+       my $name=shift;
+       
+       my $tpage=($name =~ s/^\///) ? $name : "templates/$name";
+       my $template;
+       if ($name !~ /\.tmpl$/ && exists $pagesources{$tpage}) {
+               $template=srcfile($pagesources{$tpage}, 1);
+               $name.=".tmpl";
+       }
+       else {
+               $template=srcfile($tpage, 1);
+       }
 
-       foreach my $dir ($config{templatedir}, "$installdir/share/ikiwiki/templates") {
-               return "$dir/$template" if -e "$dir/$template";
+       if (defined $template) {
+               return $template, $tpage, 1 if wantarray;
+               return $template;
        }
+       else {
+               $name=~s:/::; # avoid path traversal
+               foreach my $dir ($config{templatedir},
+                                "$installdir/share/ikiwiki/templates") {
+                       if (-e "$dir/$name") {
+                               $template="$dir/$name";
+                               last;
+                       }
+               }
+               if (defined $template) {        
+                       return $template, $tpage if wantarray;
+                       return $template;
+               }
+       }
+
        return;
 }
 
-sub template_params (@) {
-       my $filename=template_file(shift);
-
-       if (! defined $filename) {
-               return if wantarray;
-               return "";
+sub template_depends ($$;@) {
+       my $name=shift;
+       my $page=shift;
+       
+       my ($filename, $tpage, $untrusted)=template_file($name);
+       if (defined $page && defined $tpage) {
+               add_depends($page, $tpage);
        }
 
-       my @ret=(
+       return unless defined $filename;
+
+       my @opts=(
                filter => sub {
                        my $text_ref = shift;
                        ${$text_ref} = decode_utf8(${$text_ref});
                },
-               filename => $filename,
                loop_context_vars => 1,
                die_on_bad_params => 0,
-               @_
+               filename => $filename,
+               @_,
+               ($untrusted ? (no_includes => 1) : ()),
        );
-       return wantarray ? @ret : {@ret};
+       return @opts if wantarray;
+
+       require HTML::Template;
+       return HTML::Template->new(@opts);
 }
 
 sub template ($;@) {
-       require HTML::Template;
-       return HTML::Template->new(template_params(@_));
+       template_depends(shift, undef, @_);
 }
 
 sub misctemplate ($$;@) {
        my $title=shift;
-       my $pagebody=shift;
+       my $content=shift;
+       my %params=@_;
        
-       my $template=template("misc.tmpl");
+       my $template=template("page.tmpl");
+
+       my $page="";
+       if (exists $params{page}) {
+               $page=delete $params{page};
+       }
+       run_hooks(pagetemplate => sub {
+               shift->(
+                       page => $page,
+                       destpage => $page,
+                       template => $template,
+               );
+       });
+       templateactions($template, "");
+
        $template->param(
+               dynamic => 1,
                title => $title,
-               indexlink => indexlink(),
                wikiname => $config{wikiname},
-               pagebody => $pagebody,
+               content => $content,
                baseurl => baseurl(),
-               @_,
+               html5 => $config{html5},
+               %params,
        );
-       run_hooks(pagetemplate => sub {
-               shift->(page => "", destpage => "", template => $template);
-       });
+       
        return $template->output;
 }
 
+sub templateactions ($$) {
+       my $template=shift;
+       my $page=shift;
+
+       my $have_actions=0;
+       my @actions;
+       run_hooks(pageactions => sub {
+               push @actions, map { { action => $_ } } 
+                       grep { defined } shift->(page => $page);
+       });
+       $template->param(actions => \@actions);
+
+       if ($config{cgiurl} && exists $hooks{auth}) {
+               $template->param(prefsurl => cgiurl(do => "prefs"));
+               $have_actions=1;
+       }
+
+       if ($have_actions || @actions) {
+               $template->param(have_actions => 1);
+       }
+}
+
 sub hook (@) {
        my %param=@_;
        
@@ -1677,11 +1899,11 @@ sub rcs_prepedit ($) {
        $hooks{rcs}{rcs_prepedit}{call}->(@_);
 }
 
-sub rcs_commit ($$$;$$) {
+sub rcs_commit (@) {
        $hooks{rcs}{rcs_commit}{call}->(@_);
 }
 
-sub rcs_commit_staged ($$$) {
+sub rcs_commit_staged (@) {
        $hooks{rcs}{rcs_commit_staged}{call}->(@_);
 }
 
@@ -1709,60 +1931,110 @@ sub rcs_getctime ($) {
        $hooks{rcs}{rcs_getctime}{call}->(@_);
 }
 
+sub rcs_getmtime ($) {
+       $hooks{rcs}{rcs_getmtime}{call}->(@_);
+}
+
 sub rcs_receive () {
        $hooks{rcs}{rcs_receive}{call}->();
 }
 
-sub add_depends ($$) {
+sub add_depends ($$;$) {
        my $page=shift;
        my $pagespec=shift;
-       
-       return unless pagespec_valid($pagespec);
-
-       if (! exists $depends{$page}) {
-               $depends{$page}=$pagespec;
-       }
-       else {
-               $depends{$page}=pagespec_merge($depends{$page}, $pagespec);
+       my $deptype=shift || $DEPEND_CONTENT;
+
+       # Is the pagespec a simple page name?
+       if ($pagespec =~ /$config{wiki_file_regexp}/ &&
+           $pagespec !~ /[\s*?()!]/) {
+               $depends_simple{$page}{lc $pagespec} |= $deptype;
+               return 1;
+       }
+
+       # Add explicit dependencies for influences.
+       my $sub=pagespec_translate($pagespec);
+       return unless defined $sub;
+       foreach my $p (keys %pagesources) {
+               my $r=$sub->($p, location => $page);
+               my $i=$r->influences;
+               my $static=$r->influences_static;
+               foreach my $k (keys %$i) {
+                       next unless $r || $static || $k eq $page;
+                       $depends_simple{$page}{lc $k} |= $i->{$k};
+               }
+               last if $static;
        }
 
+       $depends{$page}{$pagespec} |= $deptype;
        return 1;
 }
 
-sub file_pruned ($$) {
-       require File::Spec;
-       my $file=File::Spec->canonpath(shift);
-       my $base=File::Spec->canonpath(shift);
-       $file =~ s#^\Q$base\E/+##;
+sub deptype (@) {
+       my $deptype=0;
+       foreach my $type (@_) {
+               if ($type eq 'presence') {
+                       $deptype |= $DEPEND_PRESENCE;
+               }
+               elsif ($type eq 'links') { 
+                       $deptype |= $DEPEND_LINKS;
+               }
+               elsif ($type eq 'content') {
+                       $deptype |= $DEPEND_CONTENT;
+               }
+       }
+       return $deptype;
+}
+
+my $file_prune_regexp;
+sub file_pruned ($) {
+       my $file=shift;
+
+       if (defined $config{include} && length $config{include}) {
+               return 0 if $file =~ m/$config{include}/;
+       }
 
-       my $regexp='('.join('|', @{$config{wiki_file_prune_regexps}}).')';
-       return $file =~ m/$regexp/ && $file ne $base;
+       if (! defined $file_prune_regexp) {
+               $file_prune_regexp='('.join('|', @{$config{wiki_file_prune_regexps}}).')';
+               $file_prune_regexp=qr/$file_prune_regexp/;
+       }
+       return $file =~ m/$file_prune_regexp/;
 }
 
 sub define_gettext () {
        # If translation is needed, redefine the gettext function to do it.
        # Otherwise, it becomes a quick no-op.
-       no warnings 'redefine';
+       my $gettext_obj;
+       my $getobj;
        if ((exists $ENV{LANG} && length $ENV{LANG}) ||
            (exists $ENV{LC_ALL} && length $ENV{LC_ALL}) ||
            (exists $ENV{LC_MESSAGES} && length $ENV{LC_MESSAGES})) {
-               *gettext=sub {
-                       my $gettext_obj=eval q{
+               $getobj=sub {
+                       $gettext_obj=eval q{
                                use Locale::gettext q{textdomain};
                                Locale::gettext->domain('ikiwiki')
                        };
-
-                       if ($gettext_obj) {
-                               $gettext_obj->get(shift);
-                       }
-                       else {
-                               return shift;
-                       }
                };
        }
-       else {
-               *gettext=sub { return shift };
-       }
+
+       no warnings 'redefine';
+       *gettext=sub {
+               $getobj->() if $getobj;
+               if ($gettext_obj) {
+                       $gettext_obj->get(shift);
+               }
+               else {
+                       return shift;
+               }
+       };
+       *ngettext=sub {
+               $getobj->() if $getobj;
+               if ($gettext_obj) {
+                       $gettext_obj->nget(@_);
+               }
+               else {
+                       return ($_[2] == 1 ? $_[0] : $_[1])
+               }
+       };
 }
 
 sub gettext {
@@ -1770,6 +2042,11 @@ sub gettext {
        gettext(@_);
 }
 
+sub ngettext {
+       define_gettext();
+       ngettext(@_);
+}
+
 sub yesno ($) {
        my $val=shift;
 
@@ -1801,20 +2078,91 @@ sub inject {
        use warnings;
 }
 
-sub add_link ($$) {
+sub add_link ($$;$) {
        my $page=shift;
        my $link=shift;
+       my $type=shift;
 
        push @{$links{$page}}, $link
                unless grep { $_ eq $link } @{$links{$page}};
+
+       if (defined $type) {
+               $typedlinks{$page}{$type}{$link} = 1;
+       }
 }
 
-sub pagespec_merge ($$) {
-       my $a=shift;
-       my $b=shift;
+sub add_autofile ($$$) {
+       my $file=shift;
+       my $plugin=shift;
+       my $generator=shift;
+       
+       $autofiles{$file}{plugin}=$plugin;
+       $autofiles{$file}{generator}=$generator;
+}
+
+sub sortspec_translate ($$) {
+       my $spec = shift;
+       my $reverse = shift;
+
+       my $code = "";
+       my @data;
+       while ($spec =~ m{
+               \s*
+               (-?)            # group 1: perhaps negated
+               \s*
+               (               # group 2: a word
+                       \w+\([^\)]*\)   # command(params)
+                       |
+                       [^\s]+          # or anything else
+               )
+               \s*
+       }gx) {
+               my $negated = $1;
+               my $word = $2;
+               my $params = undef;
+
+               if ($word =~ m/^(\w+)\((.*)\)$/) {
+                       # command with parameters
+                       $params = $2;
+                       $word = $1;
+               }
+               elsif ($word !~ m/^\w+$/) {
+                       error(sprintf(gettext("invalid sort type %s"), $word));
+               }
+
+               if (length $code) {
+                       $code .= " || ";
+               }
+
+               if ($negated) {
+                       $code .= "-";
+               }
+
+               if (exists $IkiWiki::SortSpec::{"cmp_$word"}) {
+                       if (defined $params) {
+                               push @data, $params;
+                               $code .= "IkiWiki::SortSpec::cmp_$word(\$data[$#data])";
+                       }
+                       else {
+                               $code .= "IkiWiki::SortSpec::cmp_$word(undef)";
+                       }
+               }
+               else {
+                       error(sprintf(gettext("unknown sort type %s"), $word));
+               }
+       }
+
+       if (! length $code) {
+               # undefined sorting method... sort arbitrarily
+               return sub { 0 };
+       }
+
+       if ($reverse) {
+               $code="-($code)";
+       }
 
-       return $a if $a eq $b;
-       return "($a) or ($b)";
+       no warnings;
+       return eval 'sub { '.$code.' }';
 }
 
 sub pagespec_translate ($) {
@@ -1837,13 +2185,13 @@ sub pagespec_translate ($) {
                        [^\s()]+        # any other text
                )
                \s*             # ignore whitespace
-       }igx) {
+       }gx) {
                my $word=$1;
                if (lc $word eq 'and') {
-                       $code.=' &&';
+                       $code.=' &';
                }
                elsif (lc $word eq 'or') {
-                       $code.=' ||';
+                       $code.=' |';
                }
                elsif ($word eq "(" || $word eq ")" || $word eq "!") {
                        $code.=' '.$word;
@@ -1884,39 +2232,91 @@ sub pagespec_match ($$;@) {
 
        my $sub=pagespec_translate($spec);
        return IkiWiki::ErrorReason->new("syntax error in pagespec \"$spec\"")
-               if $@ || ! defined $sub;
+               if ! defined $sub;
        return $sub->($page, @params);
 }
 
 sub pagespec_match_list ($$;@) {
-       my $pages=shift;
-       my $spec=shift;
-       my @params=@_;
+       my $page=shift;
+       my $pagespec=shift;
+       my %params=@_;
 
-       my $sub=pagespec_translate($spec);
-       error "syntax error in pagespec \"$spec\""
-               if $@ || ! defined $sub;
+       # Backwards compatability with old calling convention.
+       if (ref $page) {
+               print STDERR "warning: a plugin (".caller().") is using pagespec_match_list in an obsolete way, and needs to be updated\n";
+               $params{list}=$page;
+               $page=$params{location}; # ugh!
+       }
+
+       my $sub=pagespec_translate($pagespec);
+       error "syntax error in pagespec \"$pagespec\""
+               if ! defined $sub;
+       my $sort=sortspec_translate($params{sort}, $params{reverse})
+               if defined $params{sort};
+
+       my @candidates;
+       if (exists $params{list}) {
+               @candidates=exists $params{filter}
+                       ? grep { ! $params{filter}->($_) } @{$params{list}}
+                       : @{$params{list}};
+       }
+       else {
+               @candidates=exists $params{filter}
+                       ? grep { ! $params{filter}->($_) } keys %pagesources
+                       : keys %pagesources;
+       }
        
-       my @ret;
-       my $r;
-       foreach my $page (@$pages) {
-               $r=$sub->($page, @params);
-               push @ret, $page if $r;
+       # clear params, remainder is passed to pagespec
+       $depends{$page}{$pagespec} |= ($params{deptype} || $DEPEND_CONTENT);
+       my $num=$params{num};
+       delete @params{qw{num deptype reverse sort filter list}};
+       
+       # when only the top matches will be returned, it's efficient to
+       # sort before matching to pagespec,
+       if (defined $num && defined $sort) {
+               @candidates=IkiWiki::SortSpec::sort_pages(
+                       $sort, @candidates);
+       }
+       
+       my @matches;
+       my $firstfail;
+       my $count=0;
+       my $accum=IkiWiki::SuccessReason->new();
+       foreach my $p (@candidates) {
+               my $r=$sub->($p, %params, location => $page);
+               error(sprintf(gettext("cannot match pages: %s"), $r))
+                       if $r->isa("IkiWiki::ErrorReason");
+               unless ($r || $r->influences_static) {
+                       $r->remove_influence($p);
+               }
+               $accum |= $r;
+               if ($r) {
+                       push @matches, $p;
+                       last if defined $num && ++$count == $num;
+               }
+       }
+
+       # Add simple dependencies for accumulated influences.
+       my $i=$accum->influences;
+       foreach my $k (keys %$i) {
+               $depends_simple{$page}{lc $k} |= $i->{$k};
        }
 
-       if (! @ret && defined $r && $r->isa("IkiWiki::ErrorReason")) {
-               error(sprintf(gettext("cannot match pages: %s"), $r));
+       # when all matches will be returned, it's efficient to
+       # sort after matching
+       if (! defined $num && defined $sort) {
+               return IkiWiki::SortSpec::sort_pages(
+                       $sort, @matches);
        }
        else {
-               return @ret;
+               return @matches;
        }
 }
 
 sub pagespec_valid ($) {
        my $spec=shift;
 
-       my $sub=pagespec_translate($spec);
-       return ! $@;
+       return defined pagespec_translate($spec);
 }
 
 sub glob2re ($) {
@@ -1929,36 +2329,72 @@ sub glob2re ($) {
 package IkiWiki::FailReason;
 
 use overload (
-       '""'    => sub { ${$_[0]} },
+       '""'    => sub { $_[0][0] },
        '0+'    => sub { 0 },
        '!'     => sub { bless $_[0], 'IkiWiki::SuccessReason'},
+       '&'     => sub { $_[0]->merge_influences($_[1], 1); $_[0] },
+       '|'     => sub { $_[1]->merge_influences($_[0]); $_[1] },
        fallback => 1,
 );
 
-sub new {
-       my $class = shift;
-       my $value = shift;
-       return bless \$value, $class;
-}
-
-package IkiWiki::ErrorReason;
-
-our @ISA = 'IkiWiki::FailReason';
+our @ISA = 'IkiWiki::SuccessReason';
 
 package IkiWiki::SuccessReason;
 
 use overload (
-       '""'    => sub { ${$_[0]} },
+       '""'    => sub { $_[0][0] },
        '0+'    => sub { 1 },
        '!'     => sub { bless $_[0], 'IkiWiki::FailReason'},
+       '&'     => sub { $_[1]->merge_influences($_[0], 1); $_[1] },
+       '|'     => sub { $_[0]->merge_influences($_[1]); $_[0] },
        fallback => 1,
 );
 
 sub new {
        my $class = shift;
        my $value = shift;
-       return bless \$value, $class;
-};
+       return bless [$value, {@_}], $class;
+}
+
+sub influences {
+       my $this=shift;
+       $this->[1]={@_} if @_;
+       my %i=%{$this->[1]};
+       delete $i{""};
+       return \%i;
+}
+
+sub influences_static {
+       return ! $_[0][1]->{""};
+}
+
+sub merge_influences {
+       my $this=shift;
+       my $other=shift;
+       my $anded=shift;
+
+       if (! $anded || (($this || %{$this->[1]}) &&
+                        ($other || %{$other->[1]}))) {
+               foreach my $influence (keys %{$other->[1]}) {
+                       $this->[1]{$influence} |= $other->[1]{$influence};
+               }
+       }
+       else {
+               # influence blocker
+               $this->[1]={};
+       }
+}
+
+sub remove_influence {
+       my $this=shift;
+       my $torm=shift;
+
+       delete $this->[1]{$torm};
+}
+
+package IkiWiki::ErrorReason;
+
+our @ISA = 'IkiWiki::FailReason';
 
 package IkiWiki::PageSpec;
 
@@ -1969,7 +2405,7 @@ sub derel ($$) {
        if ($path =~ m!^\./!) {
                $from=~s#/?[^/]+$## if defined $from;
                $path=~s#^\./##;
-               $path="$from/$path" if length $from;
+               $path="$from/$path" if defined $from && length $from;
        }
 
        return $path;
@@ -1997,7 +2433,22 @@ sub match_glob ($$;@) {
 }
 
 sub match_internal ($$;@) {
-       return match_glob($_[0], $_[1], @_, internal => 1)
+       return match_glob(shift, shift, @_, internal => 1)
+}
+
+sub match_page ($$;@) {
+       my $page=shift;
+       my $match=match_glob($page, shift, @_);
+       if ($match) {
+               my $source=exists $IkiWiki::pagesources{$page} ?
+                       $IkiWiki::pagesources{$page} :
+                       $IkiWiki::delpagesources{$page};
+               my $type=defined $source ? IkiWiki::pagetype($source) : undef;
+               if (! defined $type) {  
+                       return IkiWiki::FailReason->new("$page is not a page");
+               }
+       }
+       return $match;
 }
 
 sub match_link ($$;@) {
@@ -2007,29 +2458,42 @@ sub match_link ($$;@) {
 
        $link=derel($link, $params{location});
        my $from=exists $params{location} ? $params{location} : '';
+       my $linktype=$params{linktype};
+       my $qualifier='';
+       if (defined $linktype) {
+               $qualifier=" with type $linktype";
+       }
 
        my $links = $IkiWiki::links{$page};
-       return IkiWiki::FailReason->new("$page has no links") unless $links && @{$links};
+       return IkiWiki::FailReason->new("$page has no links", $page => $IkiWiki::DEPEND_LINKS, "" => 1)
+               unless $links && @{$links};
        my $bestlink = IkiWiki::bestlink($from, $link);
        foreach my $p (@{$links}) {
+               next unless (! defined $linktype || exists $IkiWiki::typedlinks{$page}{$linktype}{$p});
+
                if (length $bestlink) {
-                       return IkiWiki::SuccessReason->new("$page links to $link")
-                               if $bestlink eq IkiWiki::bestlink($page, $p);
+                       if ($bestlink eq IkiWiki::bestlink($page, $p)) {
+                               return IkiWiki::SuccessReason->new("$page links to $link$qualifier", $page => $IkiWiki::DEPEND_LINKS, "" => 1)
+                       }
                }
                else {
-                       return IkiWiki::SuccessReason->new("$page links to page $p matching $link")
-                               if match_glob($p, $link, %params);
-                       $p=~s/^\///;
+                       if (match_glob($p, $link, %params)) {
+                               return IkiWiki::SuccessReason->new("$page links to page $p$qualifier, matching $link", $page => $IkiWiki::DEPEND_LINKS, "" => 1)
+                       }
+                       my ($p_rel)=$p=~/^\/?(.*)/;
                        $link=~s/^\///;
-                       return IkiWiki::SuccessReason->new("$page links to page $p matching $link")
-                               if match_glob($p, $link, %params);
+                       if (match_glob($p_rel, $link, %params)) {
+                               return IkiWiki::SuccessReason->new("$page links to page $p_rel$qualifier, matching $link", $page => $IkiWiki::DEPEND_LINKS, "" => 1)
+                       }
                }
        }
-       return IkiWiki::FailReason->new("$page does not link to $link");
+       return IkiWiki::FailReason->new("$page does not link to $link$qualifier", $page => $IkiWiki::DEPEND_LINKS, "" => 1);
 }
 
 sub match_backlink ($$;@) {
-       return match_link($_[1], $_[0], @_);
+       my $ret=match_link($_[1], $_[0], @_);
+       $ret->influences($_[1] => $IkiWiki::DEPEND_LINKS);
+       return $ret;
 }
 
 sub match_created_before ($$;@) {
@@ -2041,14 +2505,14 @@ sub match_created_before ($$;@) {
 
        if (exists $IkiWiki::pagectime{$testpage}) {
                if ($IkiWiki::pagectime{$page} < $IkiWiki::pagectime{$testpage}) {
-                       return IkiWiki::SuccessReason->new("$page created before $testpage");
+                       return IkiWiki::SuccessReason->new("$page created before $testpage", $testpage => $IkiWiki::DEPEND_PRESENCE);
                }
                else {
-                       return IkiWiki::FailReason->new("$page not created before $testpage");
+                       return IkiWiki::FailReason->new("$page not created before $testpage", $testpage => $IkiWiki::DEPEND_PRESENCE);
                }
        }
        else {
-               return IkiWiki::FailReason->new("$testpage has no ctime");
+               return IkiWiki::ErrorReason->new("$testpage does not exist", $testpage => $IkiWiki::DEPEND_PRESENCE);
        }
 }
 
@@ -2061,19 +2525,19 @@ sub match_created_after ($$;@) {
 
        if (exists $IkiWiki::pagectime{$testpage}) {
                if ($IkiWiki::pagectime{$page} > $IkiWiki::pagectime{$testpage}) {
-                       return IkiWiki::SuccessReason->new("$page created after $testpage");
+                       return IkiWiki::SuccessReason->new("$page created after $testpage", $testpage => $IkiWiki::DEPEND_PRESENCE);
                }
                else {
-                       return IkiWiki::FailReason->new("$page not created after $testpage");
+                       return IkiWiki::FailReason->new("$page not created after $testpage", $testpage => $IkiWiki::DEPEND_PRESENCE);
                }
        }
        else {
-               return IkiWiki::FailReason->new("$testpage has no ctime");
+               return IkiWiki::ErrorReason->new("$testpage does not exist", $testpage => $IkiWiki::DEPEND_PRESENCE);
        }
 }
 
 sub match_creation_day ($$;@) {
-       if ((gmtime($IkiWiki::pagectime{shift()}))[3] == shift) {
+       if ((localtime($IkiWiki::pagectime{shift()}))[3] == shift) {
                return IkiWiki::SuccessReason->new('creation_day matched');
        }
        else {
@@ -2082,7 +2546,7 @@ sub match_creation_day ($$;@) {
 }
 
 sub match_creation_month ($$;@) {
-       if ((gmtime($IkiWiki::pagectime{shift()}))[4] + 1 == shift) {
+       if ((localtime($IkiWiki::pagectime{shift()}))[4] + 1 == shift) {
                return IkiWiki::SuccessReason->new('creation_month matched');
        }
        else {
@@ -2091,7 +2555,7 @@ sub match_creation_month ($$;@) {
 }
 
 sub match_creation_year ($$;@) {
-       if ((gmtime($IkiWiki::pagectime{shift()}))[5] + 1900 == shift) {
+       if ((localtime($IkiWiki::pagectime{shift()}))[5] + 1900 == shift) {
                return IkiWiki::SuccessReason->new('creation_year matched');
        }
        else {
@@ -2104,11 +2568,13 @@ sub match_user ($$;@) {
        my $user=shift;
        my %params=@_;
        
+       my $regexp=IkiWiki::glob2re($user);
+       
        if (! exists $params{user}) {
                return IkiWiki::ErrorReason->new("no user specified");
        }
 
-       if (defined $params{user} && lc $params{user} eq lc $user) {
+       if (defined $params{user} && $params{user}=~/^$regexp$/i) {
                return IkiWiki::SuccessReason->new("user is $user");
        }
        elsif (! defined $params{user}) {
@@ -2156,4 +2622,22 @@ sub match_ip ($$;@) {
        }
 }
 
+package IkiWiki::SortSpec;
+
+# This is in the SortSpec namespace so that the $a and $b that sort() uses
+# are easily available in this namespace, for cmp functions to use them.
+sub sort_pages {
+       my $f=shift;
+       sort $f @_
+}
+
+sub cmp_title {
+       IkiWiki::pagetitle(IkiWiki::basename($a))
+       cmp
+       IkiWiki::pagetitle(IkiWiki::basename($b))
+}
+
+sub cmp_mtime { $IkiWiki::pagemtime{$b} <=> $IkiWiki::pagemtime{$a} }
+sub cmp_age { $IkiWiki::pagectime{$b} <=> $IkiWiki::pagectime{$a} }
+
 1
index af58d7cb56893a831d5ae798d5c5f16fc96b23fd..f2a32a9581077553d5b542fde40f428c15a5e41a 100644 (file)
@@ -15,13 +15,14 @@ sub printheader ($) {
        if ($config{sslcookie}) {
                print $session->header(-charset => 'utf-8',
                        -cookie => $session->cookie(-httponly => 1, -secure => 1));
-       } else {
+       }
+       else {
                print $session->header(-charset => 'utf-8',
                        -cookie => $session->cookie(-httponly => 1));
        }
 }
 
-sub showform ($$$$;@) {
+sub prepform {
        my $form=shift;
        my $buttons=shift;
        my $session=shift;
@@ -34,13 +35,24 @@ sub showform ($$$$;@) {
                });
        }
 
+       return $form;
+}
+
+sub showform ($$$$;@) {
+       my $form=prepform(@_);
+       shift;
+       my $buttons=shift;
+       my $session=shift;
+       my $cgi=shift;
+
        printheader($session);
        print misctemplate($form->title, $form->render(submit => $buttons), @_);
 }
 
 sub redirect ($$) {
        my $q=shift;
-       my $url=shift;
+       eval q{use URI};
+       my $url=URI->new(shift);
        if (! $config{w3mmode}) {
                print $q->redirect($url);
        }
@@ -51,7 +63,7 @@ sub redirect ($$) {
 }
 
 sub decode_cgi_utf8 ($) {
-       # decode_form_utf8 method is needed for 5.10
+       # decode_form_utf8 method is needed for 5.01
        if ($] < 5.01) {
                my $cgi = shift;
                foreach my $f ($cgi->param) {
@@ -64,8 +76,9 @@ sub decode_form_utf8 ($) {
        if ($] >= 5.01) {
                my $form = shift;
                foreach my $f ($form->field) {
+                       my @value=map { decode_utf8($_) } $form->field($f);
                        $form->field(name  => $f,
-                                    value => decode_utf8($form->field($f)),
+                                    value => \@value,
                                     force => 1,
                        );
                }
@@ -87,9 +100,10 @@ sub needsignin ($$) {
        }
 }
 
-sub cgi_signin ($$) {
+sub cgi_signin ($$;$) {
        my $q=shift;
        my $session=shift;
+       my $returnhtml=shift;
 
        decode_cgi_utf8($q);
        eval q{use CGI::FormBuilder};
@@ -105,13 +119,10 @@ sub cgi_signin ($$) {
                action => $config{cgiurl},
                header => 0,
                template => {type => 'div'},
-               stylesheet => baseurl()."style.css",
+               stylesheet => 1,
        );
        my $buttons=["Login"];
        
-       if ($q->param("do") ne "signin" && !$form->submitted) {
-               $form->text(gettext("You need to log in first."));
-       }
        $form->field(name => "do", type => "hidden", value => "signin",
                force => 1);
        
@@ -126,6 +137,11 @@ sub cgi_signin ($$) {
                $form->validate;
        }
 
+       if ($returnhtml) {
+               $form=prepform($form, $buttons, $session, $q);
+               return $form->render(submit => $buttons);
+       }
+
        showform($form, $buttons, $session, $q);
 }
 
@@ -184,7 +200,7 @@ sub cgi_prefs ($$) {
                params => $q,
                action => $config{cgiurl},
                template => {type => 'div'},
-               stylesheet => baseurl()."style.css",
+               stylesheet => 1,
                fieldsets => [
                        [login => gettext("Login")],
                        [preferences => gettext("Preferences")],
@@ -231,14 +247,20 @@ sub cgi_prefs ($$) {
                $form->text(gettext("Preferences saved."));
        }
        
-       showform($form, $buttons, $session, $q);
+       showform($form, $buttons, $session, $q,
+               prefsurl => "", # avoid showing the preferences link
+       );
 }
 
-sub cgi_custom_failure ($$) {
-       my $header=shift;
+sub cgi_custom_failure ($$$) {
+       my $q=shift;
+       my $httpstatus=shift;
        my $message=shift;
 
-       print $header;
+       print $q->header(
+               -status => $httpstatus,
+               -charset => 'utf-8',
+       );
        print $message;
 
        # Internet Explod^Hrer won't show custom 404 responses
@@ -252,16 +274,30 @@ sub check_banned ($$) {
        my $q=shift;
        my $session=shift;
 
+       my $banned=0;
        my $name=$session->param("name");
-       if (defined $name) {
-               if (grep { $name eq $_ } @{$config{banned_users}}) {
-                       $session->delete();
-                       cgi_savesession($session);
-                       cgi_custom_failure(
-                               $q->header(-status => "403 Forbidden"),
-                               gettext("You are banned."));
+       if (defined $name && 
+           grep { $name eq $_ } @{$config{banned_users}}) {
+               $banned=1;
+       }
+
+       foreach my $b (@{$config{banned_users}}) {
+               if (pagespec_match("", $b,
+                       ip => $session->remote_addr(),
+                       name => defined $name ? $name : "",
+               )) {
+                       $banned=1;
+                       last;
                }
        }
+
+       if ($banned) {
+               $session->delete();
+               cgi_savesession($session);
+               cgi_custom_failure(
+                       $q, "403 Forbidden",
+                       gettext("You are banned."));
+       }
 }
 
 sub cgi_getsession ($) {
index bae9e15d1a67ea8705626d69dc69cdc486e68306..42cfa9e8aad04fc69b050df92b38a18905a33495 100644 (file)
@@ -10,6 +10,7 @@ use IkiWiki 3.00;
 
 sub import {
        hook(type => "cgi", id => '404',  call => \&cgi);
+       hook(type => "getsetup", id => '404',  call => \&getsetup);
        IkiWiki::loadplugin("goto");
 }
 
@@ -21,6 +22,7 @@ sub getsetup () {
                        # server admin action too
                        safe => 0,
                        rebuild => 0,
+                       section => "web",
                }
 }
 
@@ -69,7 +71,8 @@ sub cgi ($) {
 
        if (exists $ENV{REDIRECT_STATUS} && 
            $ENV{REDIRECT_STATUS} eq '404') {
-               my $page = cgi_page_from_404($ENV{REDIRECT_URL},
+               my $page = cgi_page_from_404(
+                       Encode::decode_utf8($ENV{REDIRECT_URL}),
                        $config{url}, $config{usedirs});
                IkiWiki::Plugin::goto::cgi_goto($cgi, $page);
        }
index 5a9eb433de8311e0a9d77909aa45343c609bdea5..7789c4c2a9d38b7e616d9d3b4df8e4d96fe74ec6 100644 (file)
@@ -298,7 +298,7 @@ sub loadstate () {
        return if $state_loaded;
        $state_loaded=1;
        if (-e "$config{wikistatedir}/aggregate") {
-               open(IN, "$config{wikistatedir}/aggregate") ||
+               open(IN, "<", "$config{wikistatedir}/aggregate") ||
                        die "$config{wikistatedir}/aggregate: $!";
                while (<IN>) {
                        $_=IkiWiki::possibly_foolish_untaint($_);
@@ -335,7 +335,7 @@ sub savestate () {
        garbage_collect();
        my $newfile="$config{wikistatedir}/aggregate.new";
        my $cleanup = sub { unlink($newfile) };
-       open (OUT, ">$newfile") || error("open $newfile: $!", $cleanup);
+       open (OUT, ">", $newfile) || error("open $newfile: $!", $cleanup);
        foreach my $data (values %feeds, values %guids) {
                my @line;
                foreach my $field (keys %$data) {
@@ -356,6 +356,20 @@ sub savestate () {
        close OUT || error("save $newfile: $!", $cleanup);
        rename($newfile, "$config{wikistatedir}/aggregate") ||
                error("rename $newfile: $!", $cleanup);
+
+       my $timestamp=undef;
+       foreach my $feed (keys %feeds) {
+               my $t=$feeds{$feed}->{lastupdate}+$feeds{$feed}->{updateinterval};
+               if (! defined $timestamp || $timestamp > $t) {
+                       $timestamp=$t;
+               }
+       }
+       $newfile=~s/\.new$/time/;
+       open (OUT, ">", $newfile) || error("open $newfile: $!", $cleanup);
+       if (defined $timestamp) {
+               print OUT $timestamp."\n";
+       }
+       close OUT || error("save $newfile: $!", $cleanup);
 }
 
 sub garbage_collect () {
index 3571c4189e43fe5b70e1032832a6978cded1af6b..cfd8cd3477f81dd0758564994f35979419e330a0 100644 (file)
@@ -132,6 +132,10 @@ sub getbucket {
                });
        }
 
+       if (! $bucket) {
+               # Try to use existing bucket.
+               $bucket=$s3->bucket($config{amazon_s3_bucket});
+       }
        if (! $bucket) {
                error(gettext("Failed to create S3 bucket: ").
                        $s3->err.": ".$s3->errstr."\n");
@@ -178,7 +182,7 @@ sub writefile ($$$;$$) {
 
        # First, write the file to disk.
        my $ret=$IkiWiki::Plugin::amazon_s3::subs{'IkiWiki::writefile'}->($file, $destdir, $content, $binary, $writer);
-               
+
        my @keys=IkiWiki::Plugin::amazon_s3::file2keys("$destdir/$file");
 
        # Store the data in S3.
index 243b9892056028ea3cd289257c70274a54a410f6..0e74cbfadfbe71986ae2755b98d979cd3d00cb9b 100644 (file)
@@ -15,6 +15,7 @@ sub getsetup () {
                plugin => {
                        safe => 1,
                        rebuild => 0,
+                       section => "auth",
                },
                anonok_pagespec => {
                        type => "pagespec",
index 087c315a9af355569921c9150c05c0ba89ec8df1..ee105a1709f3fe71e0e44a47782e9596791dbbf9 100644 (file)
@@ -19,6 +19,7 @@ sub getsetup () {
                plugin => {
                        safe => 1,
                        rebuild => 0,
+                       section => "web",
                },
                allowed_attachments => {
                        type => "pagespec",
@@ -57,7 +58,7 @@ sub check_canattach ($$;$) {
                        $config{allowed_attachments},
                        file => $file,
                        user => $session->param("name"),
-                       ip => $ENV{REMOTE_ADDR},
+                       ip => $session->remote_addr(),
                );
        }
 
@@ -112,7 +113,7 @@ sub formbuilder (@) {
 
        return if ! defined $form->field("do") || ($form->field("do") ne "edit" && $form->field("do") ne "create") ;
 
-       my $filename=$q->param('attachment');
+       my $filename=Encode::decode_utf8($q->param('attachment'));
        if (defined $filename && length $filename &&
             ($form->submitted eq "Upload Attachment" || $form->submitted eq "Save Page")) {
                my $session=$params{session};
@@ -133,10 +134,13 @@ sub formbuilder (@) {
                        }
                }
 
+               $filename=IkiWiki::basename($filename);
+               $filename=~s/.*\\+(.+)/$1/; # hello, windows
+
                $filename=linkpage(IkiWiki::possibly_foolish_untaint(
                                attachment_location($form->field('page')).
-                               IkiWiki::basename($filename)));
-               if (IkiWiki::file_pruned($filename, $config{srcdir})) {
+                               $filename));
+               if (IkiWiki::file_pruned($filename)) {
                        error(gettext("bad attachment filename"));
                }
                
@@ -179,9 +183,12 @@ sub formbuilder (@) {
                if ($config{rcs}) {
                        IkiWiki::rcs_add($filename);
                        IkiWiki::disable_commit_hook();
-                       IkiWiki::rcs_commit($filename, gettext("attachment upload"),
-                               IkiWiki::rcs_prepedit($filename),
-                               $session->param("name"), $ENV{REMOTE_ADDR});
+                       IkiWiki::rcs_commit(
+                               file => $filename,
+                               message => gettext("attachment upload"),
+                               token => IkiWiki::rcs_prepedit($filename),
+                               session => $session,
+                       );
                        IkiWiki::enable_commit_hook();
                        IkiWiki::rcs_update();
                }
@@ -189,11 +196,19 @@ sub formbuilder (@) {
                IkiWiki::saveindex();
        }
        elsif ($form->submitted eq "Insert Links") {
-               my $page=quotemeta($q->param("page"));
+               my $page=quotemeta(Encode::decode_utf8($q->param("page")));
                my $add="";
                foreach my $f ($q->param("attachment_select")) {
+                       $f=Encode::decode_utf8($f);
                        $f=~s/^$page\///;
-                       $add.="[[$f]]\n";
+                       if (IkiWiki::isinlinableimage($f) &&
+                           UNIVERSAL::can("IkiWiki::Plugin::img", "import")) {
+                               $add.='[[!img '.$f.' align="right" size="" alt=""]]';
+                       }
+                       else {
+                               $add.="[[$f]]";
+                       }
+                       $add.="\n";
                }
                $form->field(name => 'editcontent',
                        value => $form->field('editcontent')."\n\n".$add,
@@ -223,13 +238,13 @@ sub attachment_list ($) {
        my @ret;
        foreach my $f (values %pagesources) {
                if (! defined pagetype($f) &&
-                   $f=~m/^\Q$loc\E[^\/]+$/ &&
-                   -e "$config{srcdir}/$f") {
+                   $f=~m/^\Q$loc\E[^\/]+$/) {
                        push @ret, {
                                "field-select" => '<input type="checkbox" name="attachment_select" value="'.$f.'" />',
                                link => htmllink($page, $page, $f, noimageinline => 1),
                                size => IkiWiki::Plugin::filecheck::humansize((stat(_))[7]),
                                mtime => displaytime($IkiWiki::pagemtime{$f}),
+                               mtime_raw => $IkiWiki::pagemtime{$f},
                        };
                }
        }
index 555856b1189fe4508ac25997cad15669fb28ceea..11595e217cdccf6d7bb571a3bb9f6c79ef4ddd7f 100644 (file)
@@ -33,21 +33,26 @@ sub genindex ($) {
 sub refresh () {
        eval q{use File::Find};
        error($@) if $@;
+       eval q{use Cwd};
+       error($@) if $@;
+       my $origdir=getcwd();
 
        my (%pages, %dirs);
        foreach my $dir ($config{srcdir}, @{$config{underlaydirs}}, $config{underlaydir}) {
+               chdir($dir) || next;
+
                find({
                        no_chdir => 1,
                        wanted => sub {
-                               $_=decode_utf8($_);
-                               if (IkiWiki::file_pruned($_, $dir)) {
+                               my $file=decode_utf8($_);
+                               $file=~s/^\.\/?//;
+                               return unless length $file;
+                               if (IkiWiki::file_pruned($file)) {
                                        $File::Find::prune=1;
                                }
                                elsif (! -l $_) {
-                                       my ($f)=/$config{wiki_file_regexp}/; # untaint
+                                       my ($f) = $file =~ /$config{wiki_file_regexp}/; # untaint
                                        return unless defined $f;
-                                       $f=~s/^\Q$dir\E\/?//;
-                                       return unless length $f;
                                        return if $f =~ /\._([^.]+)$/; # skip internal page
                                        if (! -d _) {
                                                $pages{pagename($f)}=1;
@@ -57,12 +62,22 @@ sub refresh () {
                                        }
                                }
                        }
-               }, $dir);
+               }, '.');
+
+               chdir($origdir) || die "chdir $origdir: $!";
        }
        
        my %deleted;
-        if (ref $pagestate{index}{autoindex}{deleted}) {
-              %deleted=%{$pagestate{index}{autoindex}{deleted}};
+       if (ref $wikistate{autoindex}{deleted}) {
+               %deleted=%{$wikistate{autoindex}{deleted}};
+       }
+        elsif (ref $pagestate{index}{autoindex}{deleted}) {
+               # compatability code
+               %deleted=%{$pagestate{index}{autoindex}{deleted}};
+               delete $pagestate{index}{autoindex};
+       }
+
+       if (keys %deleted) {
                foreach my $dir (keys %deleted) {
                        # remove deleted page state if the deleted page is re-added,
                        # or if all its subpages are deleted
@@ -71,7 +86,7 @@ sub refresh () {
                                delete $deleted{$dir};
                        }
                }
-               $pagestate{index}{autoindex}{deleted}=\%deleted;
+               $wikistate{autoindex}{deleted}=\%deleted;
        }
 
        my @needed;
@@ -82,10 +97,10 @@ sub refresh () {
                                # This page must have just been deleted, so
                                # don't re-add it. And remember it was
                                # deleted.
-                               if (! ref $pagestate{index}{autoindex}{deleted}) {
-                                       $pagestate{index}{autoindex}{deleted}={};
+                               if (! ref $wikistate{autoindex}{deleted}) {
+                                       $wikistate{autoindex}{deleted}={};
                                }
-                               ${$pagestate{index}{autoindex}{deleted}}{$dir}=1;
+                               ${$wikistate{autoindex}{deleted}}{$dir}=1;
                        }
                        else {
                                push @needed, $dir;
@@ -102,8 +117,8 @@ sub refresh () {
                }
                if ($config{rcs}) {
                        IkiWiki::rcs_commit_staged(
-                               gettext("automatic index generation"),
-                               undef, undef);
+                               message => gettext("automatic index generation"),
+                       );
                        IkiWiki::enable_commit_hook();
                }
        }
index 626c8ec42acc8f69297d416ef358e66702a153b3..8db3780e8888ee9c9188881e80ae26b6715436ff 100644 (file)
@@ -18,6 +18,7 @@ sub getsetup () {
                plugin => {
                        safe => 1,
                        rebuild => 0,
+                       section => "auth",
                },
                blogspam_pagespec => {
                        type => 'pagespec',
@@ -57,6 +58,7 @@ sub checkconfig () {
 
 sub checkcontent (@) {
        my %params=@_;
+       my $session=$params{session};
        
        if (exists $config{blogspam_pagespec}) {
                return undef
@@ -87,7 +89,7 @@ sub checkcontent (@) {
        push @options, "exclude=stopwords";
 
        my %req=(
-               ip => $ENV{REMOTE_ADDR},
+               ip => $session->remote_addr(),
                comment => defined $params{diff} ? $params{diff} : $params{content},
                subject => defined $params{subject} ? $params{subject} : "",
                name => defined $params{author} ? $params{author} : "",
index cf8f25281585fff56ee8b11dd9c58bdfc64b793c..8ee734bf947b6137a2925bac3eeb69ebc965a9bd 100644 (file)
@@ -23,36 +23,27 @@ 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 (pagespec_match_list([keys %links],
-                       $params{pages}, location => $params{page})) {
-               my $discussion=gettext("Discussion");
-               my %seen;
-               foreach my $link (@{$links{$page}}) {
-                       next if $seen{$link};
-                       $seen{$link}=1;
-                       next if $link =~ /.*\/\Q$discussion\E/i && $config{discussion};
-                       my $bestlink=bestlink($page, $link);
-                       next if length $bestlink;
-                       push @{$broken{$link}}, $page;
-               }
-       }
-
        my @broken;
-       foreach my $link (keys %broken) {
-               my $page=$broken{$link}->[0];
+       foreach my $link (keys %IkiWiki::brokenlinks) {
+               next if $link =~ /.*\/\Q$config{discussionpage}\E/i && $config{discussion};
+
+               my @pages=pagespec_match_list($params{page}, $params{pages},
+                       list => $IkiWiki::brokenlinks{$link},
+                       # needs to update when links on a page change
+                       deptype => deptype("links")
+               );
+               next unless @pages;
+
+               my $page=$IkiWiki::brokenlinks{$link}->[0];
                push @broken, sprintf(gettext("%s from %s"),
                        htmllink($page, $params{destpage}, $link, noimageinline => 1),
                        join(", ", map {
                                htmllink($params{page}, $params{destpage}, $_,  noimageinline => 1)
-                       } @{$broken{$link}}));
+                       } @pages)
+               );
        }
        
-       return gettext("There are no broken links!") unless %broken;
+       return gettext("There are no broken links!") unless @broken;
        return "<ul>\n"
                .join("\n",
                        map {
index 8830073672663b77d2e21fb837a15a913b7b6c0d..562d5d3893fcf5c2c0c6ba0b82e574c362f36891 100644 (file)
@@ -20,6 +20,7 @@ sub import {
        hook(type => "rcs", id => "rcs_recentchanges", call => \&rcs_recentchanges);
        hook(type => "rcs", id => "rcs_diff", call => \&rcs_diff);
        hook(type => "rcs", id => "rcs_getctime", call => \&rcs_getctime);
+       hook(type => "rcs", id => "rcs_getmtime", call => \&rcs_getmtime);
 }
 
 sub checkconfig () {
@@ -36,6 +37,7 @@ sub getsetup () {
                plugin => {
                        safe => 0, # rcs plugin
                        rebuild => undef,
+                       section => "rcs",
                },
                bzr_wrapper => {
                        type => "string",
@@ -72,31 +74,40 @@ sub bzr_log ($) {
        my @infos = ();
        my $key = undef;
 
+       my %info;
        while (<$out>) {
                my $line = $_;
                my ($value);
                if ($line =~ /^message:/) {
                        $key = "message";
-                       $infos[$#infos]{$key} = "";
+                       $info{$key} = "";
                }
                elsif ($line =~ /^(modified|added|renamed|renamed and modified|removed):/) {
                        $key = "files";
-                       unless (defined($infos[$#infos]{$key})) { $infos[$#infos]{$key} = ""; }
+                       $info{$key} = "" unless defined $info{$key};
                }
                elsif (defined($key) and $line =~ /^  (.*)/) {
-                       $infos[$#infos]{$key} .= "$1\n";
+                       $info{$key} .= "$1\n";
                }
                elsif ($line eq "------------------------------------------------------------\n") {
+                       push @infos, {%info} if keys %info;
+                       %info = ();
                        $key = undef;
-                       push (@infos, {});
                }
-               else {
+               elsif ($line =~ /: /) {
                        chomp $line;
+                       if ($line =~ /^revno: (\d+)/) {
+                           $key = "revno";
+                           $value = $1;
+                       }
+                       else {
                                ($key, $value) = split /: +/, $line, 2;
-                       $infos[$#infos]{$key} = $value;
-               } 
+                       }
+                       $info{$key} = $value;
+               }
        }
        close $out;
+       push @infos, {%info} if keys %info;
 
        return @infos;
 }
@@ -112,8 +123,13 @@ sub rcs_prepedit ($) {
        return "";
 }
 
-sub bzr_author ($$) {
-       my ($user, $ipaddr) = @_;
+sub bzr_author ($) {
+       my $session=shift;
+
+       return unless defined $session;
+
+       my $user=$session->param("name");
+       my $ipaddr=$session->remote_addr();
 
        if (defined $user) {
                return IkiWiki::possibly_foolish_untaint($user);
@@ -126,18 +142,19 @@ sub bzr_author ($$) {
        }
 }
 
-sub rcs_commit ($$$;$$) {
-       my ($file, $message, $rcstoken, $user, $ipaddr) = @_;
+sub rcs_commit (@) {
+       my %params=@_;
 
-       $user = bzr_author($user, $ipaddr);
+       my $user=bzr_author($params{session});
 
-       $message = IkiWiki::possibly_foolish_untaint($message);
-       if (! length $message) {
-               $message = "no message given";
+       $params{message} = IkiWiki::possibly_foolish_untaint($params{message});
+       if (! length $params{message}) {
+               $params{message} = "no message given";
        }
 
-       my @cmdline = ("bzr", "commit", "--quiet", "-m", $message, "--author", $user,
-                      $config{srcdir}."/".$file);
+       my @cmdline = ("bzr", "commit", "--quiet", "-m", $params{message},
+                      (defined $user ? ("--author", $user) : ()),
+                      $config{srcdir}."/".$params{file});
        if (system(@cmdline) != 0) {
                warn "'@cmdline' failed: $!";
        }
@@ -145,19 +162,18 @@ sub rcs_commit ($$$;$$) {
        return undef; # success
 }
 
-sub rcs_commit_staged ($$$) {
-       # Commits all staged changes. Changes can be staged using rcs_add,
-       # rcs_remove, and rcs_rename.
-       my ($message, $user, $ipaddr)=@_;
+sub rcs_commit_staged (@) {
+       my %params=@_;
 
-       $user = bzr_author($user, $ipaddr);
+       my $user=bzr_author($params{session});
 
-       $message = IkiWiki::possibly_foolish_untaint($message);
-       if (! length $message) {
-               $message = "no message given";
+       $params{message} = IkiWiki::possibly_foolish_untaint($params{message});
+       if (! length $params{message}) {
+               $params{message} = "no message given";
        }
 
-       my @cmdline = ("bzr", "commit", "--quiet", "-m", $message, "--author", $user,
+       my @cmdline = ("bzr", "commit", "--quiet", "-m", $params{message},
+                      (defined $user ? ("--author", $user) : ()),
                       $config{srcdir});
        if (system(@cmdline) != 0) {
                warn "'@cmdline' failed: $!";
@@ -212,7 +228,7 @@ sub rcs_recentchanges ($) {
        foreach my $info (bzr_log($out)) {
                my @pages = ();
                my @message = ();
-        
+
                foreach my $msgline (split(/\n/, $info->{message})) {
                        push @message, { line => $msgline };
                }
@@ -275,14 +291,8 @@ sub rcs_diff ($) {
        }
 }
 
-sub rcs_getctime ($) {
-       my ($file) = @_;
-
-       # XXX filename passes through the shell here, should try to avoid
-       # that just in case
-       my @cmdline = ("bzr", "log", "--limit", '1', "$config{srcdir}/$file");
-       open (my $out, "@cmdline |");
-
+sub extract_timestamp (@) {
+       open (my $out, "-|", @_);
        my @log = bzr_log($out);
 
        if (length @log < 1) {
@@ -292,8 +302,22 @@ sub rcs_getctime ($) {
        eval q{use Date::Parse};
        error($@) if $@;
        
-       my $ctime = str2time($log[0]->{"timestamp"});
-       return $ctime;
+       my $time = str2time($log[0]->{"timestamp"});
+       return $time;
+}
+
+sub rcs_getctime ($) {
+       my ($file) = @_;
+
+       my @cmdline = ("bzr", "log", "--forward", "--limit", '1', "$config{srcdir}/$file");
+       return extract_timestamp(@cmdline);
+}
+
+sub rcs_getmtime ($) {
+       my ($file) = @_;
+
+       my @cmdline = ("bzr", "log", "--limit", '1', "$config{srcdir}/$file");
+       return extract_timestamp(@cmdline);
 }
 
 1
index fe4b16072131eea5571a86d75c65a7a117bb3efc..bb995d49956e27234e5bb9b621c2caa641b93d40 100644 (file)
@@ -22,10 +22,8 @@ use warnings;
 use strict;
 use IkiWiki 3.00;
 use Time::Local;
-use POSIX;
+use POSIX ();
 
-my %cache;
-my %linkcache;
 my $time=time;
 my @now=localtime($time);
 
@@ -40,6 +38,7 @@ sub getsetup () {
                plugin => {
                        safe => 1,
                        rebuild => undef,
+                       section => "widget",
                },
                archivebase => {
                        type => "string",
@@ -48,6 +47,14 @@ sub getsetup () {
                        safe => 1,
                        rebuild => 1,
                },
+               archive_pagespec => {
+                       type => "pagespec",
+                       example => "page(posts/*) and !*/Discussion",
+                       description => "PageSpec of pages to include in the archives; used by ikiwiki-calendar command",
+                       link => 'ikiwiki/PageSpec',
+                       safe => 1,
+                       rebuild => 0,
+               },
 }
 
 sub is_leap_year (@) {
@@ -67,28 +74,56 @@ sub month_days {
 sub format_month (@) {
        my %params=@_;
 
-       my $pagespec = $params{pages};
-       my $year     = $params{year};
-       my $month    = $params{month};
-       my $pmonth   = $params{pmonth};
-       my $nmonth   = $params{nmonth};
-       my $pyear    = $params{pyear};
-       my $nyear    = $params{nyear};
+       my %linkcache;
+       foreach my $p (pagespec_match_list($params{page}, 
+                               "creation_year($params{year}) and creation_month($params{month}) and ($params{pages})",
+                               # add presence dependencies to update
+                               # month calendar when pages are added/removed
+                               deptype => deptype("presence"))) {
+               my $mtime = $IkiWiki::pagectime{$p};
+               my @date  = localtime($mtime);
+               my $mday  = $date[3];
+               my $month = $date[4] + 1;
+               my $year  = $date[5] + 1900;
+               my $mtag  = sprintf("%02d", $month);
+
+               # Only one posting per day is being linked to.
+               $linkcache{"$year/$mtag/$mday"} = $p;
+       }
+               
+       my $pmonth = $params{month} - 1;
+       my $nmonth = $params{month} + 1;
+       my $pyear  = $params{year};
+       my $nyear  = $params{year};
+
+       # Adjust for January and December
+       if ($params{month} == 1) {
+               $pmonth = 12;
+               $pyear--;
+       }
+       if ($params{month} == 12) {
+               $nmonth = 1;
+               $nyear++;
+       }
+
+       # Add padding.
+       $pmonth=sprintf("%02d", $pmonth);
+       $nmonth=sprintf("%02d", $nmonth);
 
-       my @list;
        my $calendar="\n";
 
        # When did this month start?
-       my @monthstart = localtime(timelocal(0,0,0,1,$month-1,$year-1900));
+       my @monthstart = localtime(timelocal(0,0,0,1,$params{month}-1,$params{year}-1900));
 
        my $future_dom = 0;
        my $today      = 0;
-       if ($year == $now[5]+1900 && $month == $now[4]+1) {
+       if ($params{year} == $now[5]+1900 && $params{month} == $now[4]+1) {
                $future_dom = $now[3]+1;
                $today      = $now[3];
        }
 
        # Find out month names for this, next, and previous months
+       my $monthabbrev=POSIX::strftime("%b", @monthstart);
        my $monthname=POSIX::strftime("%B", @monthstart);
        my $pmonthname=POSIX::strftime("%B", localtime(timelocal(0,0,0,1,$pmonth-1,$pyear-1900)));
        my $nmonthname=POSIX::strftime("%B", localtime(timelocal(0,0,0,1,$nmonth-1,$nyear-1900)));
@@ -98,34 +133,43 @@ sub format_month (@) {
        $archivebase = $params{archivebase} if defined $params{archivebase};
   
        # Calculate URL's for monthly archives.
-       my ($url, $purl, $nurl)=("$monthname",'','');
-       if (exists $cache{$pagespec}{"$year/$month"}) {
+       my ($url, $purl, $nurl)=("$monthname $params{year}",'','');
+       if (exists $pagesources{"$archivebase/$params{year}/$params{month}"}) {
                $url = htmllink($params{page}, $params{destpage}, 
-                       "$archivebase/$year/".sprintf("%02d", $month),
-                       linktext => " $monthname ");
+                       "$archivebase/$params{year}/".$params{month},
+                       noimageinline => 1,
+                       linktext => "$monthabbrev $params{year}",
+                       title => $monthname);
        }
-       add_depends($params{page}, "$archivebase/$year/".sprintf("%02d", $month));
-       if (exists $cache{$pagespec}{"$pyear/$pmonth"}) {
+       add_depends($params{page}, "$archivebase/$params{year}/$params{month}",
+               deptype("presence"));
+       if (exists $pagesources{"$archivebase/$pyear/$pmonth"}) {
                $purl = htmllink($params{page}, $params{destpage}, 
-                       "$archivebase/$pyear/" . sprintf("%02d", $pmonth),
-                       linktext => " $pmonthname ");
+                       "$archivebase/$pyear/$pmonth",
+                       noimageinline => 1,
+                       linktext => "\&larr;",
+                       title => $pmonthname);
        }
-       add_depends($params{page}, "$archivebase/$pyear/".sprintf("%02d", $pmonth));
-       if (exists $cache{$pagespec}{"$nyear/$nmonth"}) {
+       add_depends($params{page}, "$archivebase/$pyear/$pmonth",
+               deptype("presence"));
+       if (exists $pagesources{"$archivebase/$nyear/$nmonth"}) {
                $nurl = htmllink($params{page}, $params{destpage}, 
-                       "$archivebase/$nyear/" . sprintf("%02d", $nmonth),
-                       linktext => " $nmonthname ");
+                       "$archivebase/$nyear/$nmonth",
+                       noimageinline => 1,
+                       linktext => "\&rarr;",
+                       title => $nmonthname);
        }
-       add_depends($params{page}, "$archivebase/$nyear/".sprintf("%02d", $nmonth));
+       add_depends($params{page}, "$archivebase/$nyear/$nmonth",
+               deptype("presence"));
 
        # Start producing the month calendar
        $calendar=<<EOF;
 <table class="month-calendar">
-       <caption class="month-calendar-head">
-       $purl
-       $url
-       $nurl
-       </caption>
+       <tr>
+       <th class="month-calendar-arrow">$purl</th>
+       <th class="month-calendar-head" colspan="5">$url</th>
+       <th class="month-calendar-arrow">$nurl</th>
+       </tr>
        <tr>
 EOF
 
@@ -137,12 +181,12 @@ EOF
        my %downame;
        my %dowabbr;
        for my $dow ($week_start_day..$week_start_day+6) {
-               my @day=localtime(timelocal(0,0,0,$start_day++,$month-1,$year-1900));
+               my @day=localtime(timelocal(0,0,0,$start_day++,$params{month}-1,$params{year}-1900));
                my $downame = POSIX::strftime("%A", @day);
-               my $dowabbr = POSIX::strftime("%a", @day);
+               my $dowabbr = substr($downame, 0, 1);
                $downame{$dow % 7}=$downame;
                $dowabbr{$dow % 7}=$dowabbr;
-               $calendar.= qq{\t\t<th class="month-calendar-day-head $downame">$dowabbr</th>\n};
+               $calendar.= qq{\t\t<th class="month-calendar-day-head $downame" title="$downame">$dowabbr</th>\n};
        }
 
        $calendar.=<<EOF;
@@ -158,9 +202,9 @@ EOF
 
        # At this point, either the first is a week_start_day, in which case
        # nothing has been printed, or else we are in the middle of a row.
-       for (my $day = 1; $day <= month_days(year => $year, month => $month);
+       for (my $day = 1; $day <= month_days(year => $params{year}, month => $params{month});
             $day++, $wday++, $wday %= 7) {
-               # At tihs point, on a week_start_day, we close out a row,
+               # At this point, on a week_start_day, we close out a row,
                # and start a new one -- unless it is week_start_day on the
                # first, where we do not close a row -- since none was started.
                if ($wday == $week_start_day) {
@@ -169,8 +213,8 @@ EOF
                }
                
                my $tag;
-               my $mtag = sprintf("%02d", $month);
-               if (defined $cache{$pagespec}{"$year/$mtag/$day"}) {
+               my $key="$params{year}/$params{month}/$day";
+               if (defined $linkcache{$key}) {
                        if ($day == $today) {
                                $tag='month-calendar-day-this-day';
                        }
@@ -179,9 +223,10 @@ EOF
                        }
                        $calendar.=qq{\t\t<td class="$tag $downame{$wday}">};
                        $calendar.=htmllink($params{page}, $params{destpage}, 
-                                           pagename($linkcache{"$year/$mtag/$day"}),
-                                           "linktext" => "$day");
-                       push @list, pagename($linkcache{"$year/$mtag/$day"});
+                     &