]> git.mjollnir.org Git - s9y.git/commitdiff
Import Serendipity 0.8 into trunk.
authors_bergmann <s_bergmann>
Sat, 16 Apr 2005 06:39:31 +0000 (06:39 +0000)
committers_bergmann <s_bergmann>
Sat, 16 Apr 2005 06:39:31 +0000 (06:39 +0000)
770 files changed:
bundled-libs/Cache/Lite.php [new file with mode: 0644]
bundled-libs/Cache/Lite/Function.php [new file with mode: 0644]
bundled-libs/Cache/Lite/Output.php [new file with mode: 0644]
bundled-libs/HTTP/Request.php [new file with mode: 0644]
bundled-libs/HTTP/Request/Listener.php [new file with mode: 0644]
bundled-libs/Net/CheckIP.php [new file with mode: 0644]
bundled-libs/Net/DNSBL.php [new file with mode: 0644]
bundled-libs/Net/DNSBL/SURBL.php [new file with mode: 0644]
bundled-libs/Net/Socket.php [new file with mode: 0644]
bundled-libs/Net/URL.php [new file with mode: 0644]
bundled-libs/Onyx/RSS.php [new file with mode: 0644]
bundled-libs/PEAR.php [new file with mode: 0644]
bundled-libs/Smarty/BUGS [new file with mode: 0644]
bundled-libs/Smarty/COPYING.lib [new file with mode: 0644]
bundled-libs/Smarty/ChangeLog [new file with mode: 0644]
bundled-libs/Smarty/FAQ [new file with mode: 0644]
bundled-libs/Smarty/INSTALL [new file with mode: 0644]
bundled-libs/Smarty/NEWS [new file with mode: 0644]
bundled-libs/Smarty/README [new file with mode: 0644]
bundled-libs/Smarty/RELEASE_NOTES [new file with mode: 0644]
bundled-libs/Smarty/libs/Config_File.class.php [new file with mode: 0644]
bundled-libs/Smarty/libs/Smarty.class.php [new file with mode: 0644]
bundled-libs/Smarty/libs/Smarty_Compiler.class.php [new file with mode: 0644]
bundled-libs/Smarty/libs/debug.tpl [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.assemble_plugin_filepath.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.assign_smarty_interface.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.create_dir_structure.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.display_debug_console.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.get_include_path.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.get_microtime.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.get_php_resource.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.is_secure.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.is_trusted.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.load_plugins.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.load_resource_plugin.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.process_cached_inserts.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.process_compiled_include.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.read_cache_file.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.rm_auto.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.rmdir.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.run_insert_handler.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.smarty_include_php.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.write_cache_file.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.write_compiled_include.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.write_compiled_resource.php [new file with mode: 0644]
bundled-libs/Smarty/libs/internals/core.write_file.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/block.textformat.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/compiler.assign.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.assign_debug_info.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.config_load.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.counter.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.cycle.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.debug.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.eval.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.fetch.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.html_checkboxes.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.html_image.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.html_options.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.html_radios.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.html_select_date.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.html_select_time.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.html_table.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.mailto.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.math.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.popup.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/function.popup_init.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.capitalize.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.cat.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.count_characters.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.count_paragraphs.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.count_sentences.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.count_words.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.date_format.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.debug_print_var.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.default.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.escape.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.indent.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.lower.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.nl2br.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.regex_replace.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.replace.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.spacify.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.string_format.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.strip.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.strip_tags.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.truncate.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.upper.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/modifier.wordwrap.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/outputfilter.trimwhitespace.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/shared.escape_special_chars.php [new file with mode: 0644]
bundled-libs/Smarty/libs/plugins/shared.make_timestamp.php [new file with mode: 0644]
bundled-libs/Text/Wiki.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/blockquote.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/bold.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/break.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/center.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/code.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/colortext.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/deflist.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/delimiter.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/embed.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/emphasis.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/entities.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/freelink.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/heading.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/horiz.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/html.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/image.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/include.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/interwiki.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/italic.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/list.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/newline.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/paragraph.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/phpcode.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/phplookup.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/prefilter.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/raw.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/revise.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/strong.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/superscript.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/table.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/tighten.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/toc.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/tt.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/url.php [new file with mode: 0644]
bundled-libs/Text/Wiki/Rule/wikilink.php [new file with mode: 0644]
bundled-libs/XML/RPC.php [new file with mode: 0644]
bundled-libs/XML/RPC/Server.php [new file with mode: 0644]
bundled-libs/create_release.sh [new file with mode: 0644]
bundled-libs/docs/HomePage.wiki.txt [new file with mode: 0644]
bundled-libs/docs/SamplePage.wiki.txt [new file with mode: 0644]
bundled-libs/docs/SmashWordsTogether.wiki.txt [new file with mode: 0644]
bundled-libs/docs/TextWikiProposal.wiki.txt [new file with mode: 0644]
bundled-libs/docs/TokenRuleKeys.wiki.txt [new file with mode: 0644]
bundled-libs/docs/WikiPage.wiki.txt [new file with mode: 0644]
bundled-libs/docs/WordsSmashedTogether.wiki.txt [new file with mode: 0644]
bundled-libs/docs/free links.wiki.txt [new file with mode: 0644]
bundled-libs/docs/index.php [new file with mode: 0644]
bundled-libs/docs/stylesheet.css [new file with mode: 0644]
bundled-libs/tests/README [new file with mode: 0644]
comment.php [new file with mode: 0644]
deployment/comment.php [new file with mode: 0644]
deployment/exit.php [new file with mode: 0644]
deployment/index.php [new file with mode: 0644]
deployment/rss.php [new file with mode: 0644]
deployment/serendipity.css.php [new file with mode: 0644]
deployment/serendipity_admin.php [new file with mode: 0644]
deployment/serendipity_admin_image_selector.php [new file with mode: 0644]
deployment/serendipity_config.inc.php [new file with mode: 0644]
deployment/serendipity_define.js.php [new file with mode: 0644]
deployment/serendipity_editor.js [new file with mode: 0644]
deployment/serendipity_xmlrpc.php [new file with mode: 0644]
deployment/wfwcomment.php [new file with mode: 0644]
docs/CHANGED_FILES [new file with mode: 0644]
docs/INSTALL [new file with mode: 0644]
docs/INSTALL_EMBEDED [new file with mode: 0644]
docs/INSTALL_SHARED [new file with mode: 0644]
docs/LICENSE [new file with mode: 0644]
docs/NEWS [new file with mode: 0644]
docs/NEWS_OLD [new file with mode: 0644]
docs/README [new file with mode: 0644]
docs/UPGRADE [new file with mode: 0644]
docs/upgrade.sh [new file with mode: 0644]
exit.php [new file with mode: 0644]
htmlarea/ChangeLog [new file with mode: 0644]
htmlarea/dialog.js [new file with mode: 0644]
htmlarea/examples/2-areas.html [new file with mode: 0644]
htmlarea/examples/context-menu.html [new file with mode: 0644]
htmlarea/examples/core.html [new file with mode: 0644]
htmlarea/examples/css.html [new file with mode: 0644]
htmlarea/examples/custom.css [new file with mode: 0644]
htmlarea/examples/full-page.html [new file with mode: 0644]
htmlarea/examples/fully-loaded.html [new file with mode: 0644]
htmlarea/examples/index.html [new file with mode: 0644]
htmlarea/examples/spell-checker.html [new file with mode: 0644]
htmlarea/examples/table-operations.html [new file with mode: 0644]
htmlarea/htmlarea.css [new file with mode: 0644]
htmlarea/htmlarea.js [new file with mode: 0644]
htmlarea/images/ed_about.gif [new file with mode: 0644]
htmlarea/images/ed_align_center.gif [new file with mode: 0644]
htmlarea/images/ed_align_justify.gif [new file with mode: 0644]
htmlarea/images/ed_align_left.gif [new file with mode: 0644]
htmlarea/images/ed_align_right.gif [new file with mode: 0644]
htmlarea/images/ed_blank.gif [new file with mode: 0644]
htmlarea/images/ed_charmap.gif [new file with mode: 0644]
htmlarea/images/ed_color_bg.gif [new file with mode: 0644]
htmlarea/images/ed_color_fg.gif [new file with mode: 0644]
htmlarea/images/ed_copy.gif [new file with mode: 0644]
htmlarea/images/ed_custom.gif [new file with mode: 0644]
htmlarea/images/ed_cut.gif [new file with mode: 0644]
htmlarea/images/ed_delete.gif [new file with mode: 0644]
htmlarea/images/ed_format_bold.gif [new file with mode: 0644]
htmlarea/images/ed_format_italic.gif [new file with mode: 0644]
htmlarea/images/ed_format_strike.gif [new file with mode: 0644]
htmlarea/images/ed_format_sub.gif [new file with mode: 0644]
htmlarea/images/ed_format_sup.gif [new file with mode: 0644]
htmlarea/images/ed_format_underline.gif [new file with mode: 0644]
htmlarea/images/ed_help.gif [new file with mode: 0644]
htmlarea/images/ed_hr.gif [new file with mode: 0644]
htmlarea/images/ed_html.gif [new file with mode: 0644]
htmlarea/images/ed_image.gif [new file with mode: 0644]
htmlarea/images/ed_indent_less.gif [new file with mode: 0644]
htmlarea/images/ed_indent_more.gif [new file with mode: 0644]
htmlarea/images/ed_killword.gif [new file with mode: 0644]
htmlarea/images/ed_left_to_right.gif [new file with mode: 0644]
htmlarea/images/ed_link.gif [new file with mode: 0644]
htmlarea/images/ed_list_bullet.gif [new file with mode: 0644]
htmlarea/images/ed_list_num.gif [new file with mode: 0644]
htmlarea/images/ed_paste.gif [new file with mode: 0644]
htmlarea/images/ed_print.gif [new file with mode: 0644]
htmlarea/images/ed_redo.gif [new file with mode: 0644]
htmlarea/images/ed_right_to_left.gif [new file with mode: 0644]
htmlarea/images/ed_rmformat.gif [new file with mode: 0644]
htmlarea/images/ed_s9yimage.gif [new file with mode: 0644]
htmlarea/images/ed_save.gif [new file with mode: 0644]
htmlarea/images/ed_save.png [new file with mode: 0644]
htmlarea/images/ed_show_border.gif [new file with mode: 0644]
htmlarea/images/ed_splitcel.gif [new file with mode: 0644]
htmlarea/images/ed_undo.gif [new file with mode: 0644]
htmlarea/images/fullscreen_maximize.gif [new file with mode: 0644]
htmlarea/images/fullscreen_minimize.gif [new file with mode: 0644]
htmlarea/images/insert_table.gif [new file with mode: 0644]
htmlarea/index.html [new file with mode: 0644]
htmlarea/lang/b5.js [new file with mode: 0644]
htmlarea/lang/ch.js [new file with mode: 0644]
htmlarea/lang/cz.js [new file with mode: 0644]
htmlarea/lang/da.js [new file with mode: 0644]
htmlarea/lang/de.js [new file with mode: 0644]
htmlarea/lang/ee.js [new file with mode: 0644]
htmlarea/lang/el.js [new file with mode: 0644]
htmlarea/lang/en.js [new file with mode: 0644]
htmlarea/lang/es.js [new file with mode: 0644]
htmlarea/lang/fi.js [new file with mode: 0644]
htmlarea/lang/fr.js [new file with mode: 0644]
htmlarea/lang/gb.js [new file with mode: 0644]
htmlarea/lang/he.js [new file with mode: 0644]
htmlarea/lang/hu.js [new file with mode: 0644]
htmlarea/lang/it.js [new file with mode: 0644]
htmlarea/lang/ja-euc.js [new file with mode: 0644]
htmlarea/lang/ja-jis.js [new file with mode: 0644]
htmlarea/lang/ja-sjis.js [new file with mode: 0644]
htmlarea/lang/ja-utf8.js [new file with mode: 0644]
htmlarea/lang/lt.js [new file with mode: 0644]
htmlarea/lang/lv.js [new file with mode: 0644]
htmlarea/lang/nb.js [new file with mode: 0644]
htmlarea/lang/nl.js [new file with mode: 0644]
htmlarea/lang/no.js [new file with mode: 0644]
htmlarea/lang/pl.js [new file with mode: 0644]
htmlarea/license.txt [new file with mode: 0644]
htmlarea/plugins/CSS/css.js [new file with mode: 0644]
htmlarea/plugins/CSS/lang/en.js [new file with mode: 0644]
htmlarea/plugins/ContextMenu/context-menu.js [new file with mode: 0644]
htmlarea/plugins/ContextMenu/lang/de.js [new file with mode: 0644]
htmlarea/plugins/ContextMenu/lang/el.js [new file with mode: 0644]
htmlarea/plugins/ContextMenu/lang/en.js [new file with mode: 0644]
htmlarea/plugins/ContextMenu/lang/nl.js [new file with mode: 0644]
htmlarea/plugins/ContextMenu/menu.css [new file with mode: 0644]
htmlarea/plugins/FullPage/full-page.js [new file with mode: 0644]
htmlarea/plugins/FullPage/img/docprop.gif [new file with mode: 0644]
htmlarea/plugins/FullPage/lang/en.js [new file with mode: 0644]
htmlarea/plugins/FullPage/lang/ro.js [new file with mode: 0644]
htmlarea/plugins/FullPage/popups/docprop.html [new file with mode: 0644]
htmlarea/plugins/FullPage/test.html [new file with mode: 0644]
htmlarea/plugins/TableOperations/img/cell-delete.gif [new file with mode: 0644]
htmlarea/plugins/TableOperations/img/cell-insert-after.gif [new file with mode: 0644]
htmlarea/plugins/TableOperations/img/cell-insert-before.gif [new file with mode: 0644]
htmlarea/plugins/TableOperations/img/cell-merge.gif [new file with mode: 0644]
htmlarea/plugins/TableOperations/img/cell-prop.gif [new file with mode: 0644]
htmlarea/plugins/TableOperations/img/cell-split.gif [new file with mode: 0644]
htmlarea/plugins/TableOperations/img/col-delete.gif [new file with mode: 0644]
htmlarea/plugins/TableOperations/img/col-insert-after.gif [new file with mode: 0644]
htmlarea/plugins/TableOperations/img/col-insert-before.gif [new file with mode: 0644]
htmlarea/plugins/TableOperations/img/col-split.gif [new file with mode: 0644]
htmlarea/plugins/TableOperations/img/row-delete.gif [new file with mode: 0644]
htmlarea/plugins/TableOperations/img/row-insert-above.gif [new file with mode: 0644]
htmlarea/plugins/TableOperations/img/row-insert-under.gif [new file with mode: 0644]
htmlarea/plugins/TableOperations/img/row-prop.gif [new file with mode: 0644]
htmlarea/plugins/TableOperations/img/row-split.gif [new file with mode: 0644]
htmlarea/plugins/TableOperations/img/table-prop.gif [new file with mode: 0644]
htmlarea/plugins/TableOperations/lang/cz.js [new file with mode: 0644]
htmlarea/plugins/TableOperations/lang/da.js [new file with mode: 0644]
htmlarea/plugins/TableOperations/lang/de.js [new file with mode: 0644]
htmlarea/plugins/TableOperations/lang/el.js [new file with mode: 0644]
htmlarea/plugins/TableOperations/lang/en.js [new file with mode: 0644]
htmlarea/plugins/TableOperations/lang/fi.js [new file with mode: 0644]
htmlarea/plugins/TableOperations/lang/hu.js [new file with mode: 0644]
htmlarea/plugins/TableOperations/lang/it.js [new file with mode: 0644]
htmlarea/plugins/TableOperations/lang/nl.js [new file with mode: 0644]
htmlarea/plugins/TableOperations/lang/no.js [new file with mode: 0644]
htmlarea/plugins/TableOperations/lang/ro.js [new file with mode: 0644]
htmlarea/plugins/TableOperations/table-operations.js [new file with mode: 0644]
htmlarea/popupdiv.js [new file with mode: 0644]
htmlarea/popups/about.html [new file with mode: 0644]
htmlarea/popups/blank.html [new file with mode: 0644]
htmlarea/popups/custom2.html [new file with mode: 0644]
htmlarea/popups/editor_help.html [new file with mode: 0644]
htmlarea/popups/fullscreen.html [new file with mode: 0644]
htmlarea/popups/insert_image.html [new file with mode: 0644]
htmlarea/popups/insert_table.html [new file with mode: 0644]
htmlarea/popups/link.html [new file with mode: 0644]
htmlarea/popups/old-fullscreen.html [new file with mode: 0644]
htmlarea/popups/old_insert_image.html [new file with mode: 0644]
htmlarea/popups/popup.js [new file with mode: 0644]
htmlarea/popups/select_color.html [new file with mode: 0644]
htmlarea/popupwin.js [new file with mode: 0644]
htmlarea/reference.html [new file with mode: 0644]
htmlarea/release-notes.html [new file with mode: 0644]
include/admin/category.inc.php [new file with mode: 0644]
include/admin/comments.inc.php [new file with mode: 0644]
include/admin/configuration.inc.php [new file with mode: 0644]
include/admin/entries.inc.php [new file with mode: 0644]
include/admin/entries_overview.inc.php [new file with mode: 0644]
include/admin/export.inc.php [new file with mode: 0644]
include/admin/images.inc.php [new file with mode: 0644]
include/admin/import.inc.php [new file with mode: 0644]
include/admin/importers/b2evolution.inc.php [new file with mode: 0644]
include/admin/importers/bblog.inc.php [new file with mode: 0644]
include/admin/importers/bmachine.inc.php [new file with mode: 0644]
include/admin/importers/geeklog.inc.php [new file with mode: 0644]
include/admin/importers/generic.inc.php [new file with mode: 0644]
include/admin/importers/movabletype.inc.php [new file with mode: 0644]
include/admin/importers/nucleus.inc.php [new file with mode: 0644]
include/admin/importers/phpbb.inc.php [new file with mode: 0644]
include/admin/importers/pmachine.inc.php [new file with mode: 0644]
include/admin/importers/sunlog.inc.php [new file with mode: 0644]
include/admin/importers/textpattern.inc.php [new file with mode: 0644]
include/admin/importers/wordpress.inc.php [new file with mode: 0644]
include/admin/installer.inc.php [new file with mode: 0644]
include/admin/overview.inc.php [new file with mode: 0644]
include/admin/personal.inc.php [new file with mode: 0644]
include/admin/plugins.inc.php [new file with mode: 0644]
include/admin/templates.inc.php [new file with mode: 0644]
include/admin/upgrader.inc.php [new file with mode: 0644]
include/admin/users.inc.php [new file with mode: 0644]
include/compat.inc.php [new file with mode: 0644]
include/db/db.inc.php [new file with mode: 0644]
include/db/mysql.inc.php [new file with mode: 0644]
include/db/mysqli.inc.php [new file with mode: 0644]
include/db/postgres.inc.php [new file with mode: 0644]
include/db/sqlite.inc.php [new file with mode: 0644]
include/functions.inc.php [new file with mode: 0644]
include/functions_comments.inc.php [new file with mode: 0644]
include/functions_config.inc.php [new file with mode: 0644]
include/functions_entries.inc.php [new file with mode: 0644]
include/functions_images.inc.php [new file with mode: 0644]
include/functions_installer.inc.php [new file with mode: 0644]
include/functions_smarty.inc.php [new file with mode: 0644]
include/functions_trackbacks.inc.php [new file with mode: 0644]
include/functions_upgrader.inc.php [new file with mode: 0644]
include/genpage.inc.php [new file with mode: 0644]
include/lang.inc.php [new file with mode: 0644]
include/plugin_api.inc.php [new file with mode: 0644]
include/plugin_internal.inc.php [new file with mode: 0644]
include/tpl/config_local.inc.php [new file with mode: 0644]
include/tpl/config_personal.inc.php [new file with mode: 0644]
include/tpl/htaccess_cgi_errordocs.tpl [new file with mode: 0644]
include/tpl/htaccess_cgi_normal.tpl [new file with mode: 0644]
include/tpl/htaccess_cgi_rewrite.tpl [new file with mode: 0644]
include/tpl/htaccess_errordocs.tpl [new file with mode: 0644]
include/tpl/htaccess_normal.tpl [new file with mode: 0644]
include/tpl/htaccess_rewrite.tpl [new file with mode: 0644]
index.php [new file with mode: 0644]
lang/serendipity_lang_bg.inc.php [new file with mode: 0644]
lang/serendipity_lang_cn.inc.php [new file with mode: 0644]
lang/serendipity_lang_cs.inc.php [new file with mode: 0644]
lang/serendipity_lang_cz.inc.php [new file with mode: 0644]
lang/serendipity_lang_da.inc.php [new file with mode: 0644]
lang/serendipity_lang_de.inc.php [new file with mode: 0644]
lang/serendipity_lang_en.inc.php [new file with mode: 0644]
lang/serendipity_lang_es.inc.php [new file with mode: 0644]
lang/serendipity_lang_fa.inc.php [new file with mode: 0644]
lang/serendipity_lang_fi.inc.php [new file with mode: 0644]
lang/serendipity_lang_fr.inc.php [new file with mode: 0644]
lang/serendipity_lang_is.inc.php [new file with mode: 0644]
lang/serendipity_lang_it.inc.php [new file with mode: 0644]
lang/serendipity_lang_ja.inc.php [new file with mode: 0644]
lang/serendipity_lang_ko.inc.php [new file with mode: 0644]
lang/serendipity_lang_nl.inc.php [new file with mode: 0644]
lang/serendipity_lang_no.inc.php [new file with mode: 0644]
lang/serendipity_lang_pt.inc.php [new file with mode: 0644]
lang/serendipity_lang_ru.inc.php [new file with mode: 0644]
lang/serendipity_lang_tn.inc.php [new file with mode: 0644]
lang/serendipity_lang_tw.inc.php [new file with mode: 0644]
lang/serendipity_lang_zh.inc.php [new file with mode: 0644]
plugins/serendipity_event_bbcode/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_bbcode/serendipity_event_bbcode.php [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/courier.php [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/helvetica.php [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/helveticab.php [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/helveticabi.php [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/helveticai.php [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/cp1250.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/cp1251.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/cp1252.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/cp1253.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/cp1254.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/cp1255.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/cp1257.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/cp1258.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/cp874.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/iso-8859-1.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/iso-8859-11.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/iso-8859-15.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/iso-8859-16.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/iso-8859-2.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/iso-8859-4.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/iso-8859-5.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/iso-8859-7.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/iso-8859-9.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/koi8-r.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/makefont/koi8-u.map [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/symbol.php [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/times.php [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/timesb.php [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/timesbi.php [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/timesi.php [new file with mode: 0644]
plugins/serendipity_event_blogpdf/font/zapfdingbats.php [new file with mode: 0644]
plugins/serendipity_event_blogpdf/fpdf.php [new file with mode: 0644]
plugins/serendipity_event_blogpdf/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_blogpdf/serendipity_event_blogpdf.php [new file with mode: 0644]
plugins/serendipity_event_browsercompatibility/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_browsercompatibility/pngbehavior.htc [new file with mode: 0644]
plugins/serendipity_event_browsercompatibility/serendipity_event_browsercompatibility.php [new file with mode: 0644]
plugins/serendipity_event_contentrewrite/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_contentrewrite/serendipity_event_contentrewrite.php [new file with mode: 0644]
plugins/serendipity_event_creativecommons/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_creativecommons/serendipity_event_creativecommons.php [new file with mode: 0644]
plugins/serendipity_event_emoticate/lang_is.inc.php [new file with mode: 0644]
plugins/serendipity_event_emoticate/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_emoticate/serendipity_event_emoticate.php [new file with mode: 0644]
plugins/serendipity_event_entryproperties/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_entryproperties/serendipity_event_entryproperties.php [new file with mode: 0644]
plugins/serendipity_event_htmlvalidator/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_htmlvalidator/serendipity_event_htmlvalidator.php [new file with mode: 0644]
plugins/serendipity_event_karma/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_karma/serendipity_event_karma.php [new file with mode: 0644]
plugins/serendipity_event_livesearch/serendipity_event_livesearch.js [new file with mode: 0644]
plugins/serendipity_event_livesearch/serendipity_event_livesearch.php [new file with mode: 0644]
plugins/serendipity_event_mailer/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_mailer/serendipity_event_mailer.php [new file with mode: 0644]
plugins/serendipity_event_nl2br/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_nl2br/serendipity_event_nl2br.php [new file with mode: 0644]
plugins/serendipity_event_s9ymarkup/lang_is.inc.php [new file with mode: 0644]
plugins/serendipity_event_s9ymarkup/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_s9ymarkup/serendipity_event_s9ymarkup.php [new file with mode: 0644]
plugins/serendipity_event_searchhighlight/serendipity_event_searchhighlight.php [new file with mode: 0644]
plugins/serendipity_event_spamblock/36daysago.ttf [new file with mode: 0644]
plugins/serendipity_event_spamblock/36daysago.txt [new file with mode: 0644]
plugins/serendipity_event_spamblock/Vera.ttf [new file with mode: 0644]
plugins/serendipity_event_spamblock/VeraSe.ttf [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_2.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_3.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_4.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_7.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_9.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_a.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_b.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_c.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_d.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_e.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_f.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_h.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_j.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_k.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_l.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_m.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_n.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_p.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_q.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_r.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_t.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_u.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_v.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_w.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_x.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_y.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/captcha_z.png [new file with mode: 0644]
plugins/serendipity_event_spamblock/chumbly.ttf [new file with mode: 0644]
plugins/serendipity_event_spamblock/chumbly.txt [new file with mode: 0644]
plugins/serendipity_event_spamblock/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_spamblock/serendipity_event_spamblock.php [new file with mode: 0644]
plugins/serendipity_event_spartacus/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_spartacus/serendipity_event_spartacus.php [new file with mode: 0644]
plugins/serendipity_event_statistics/lang_cz.php [new file with mode: 0644]
plugins/serendipity_event_statistics/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_statistics/serendipity_event_statistics.php [new file with mode: 0644]
plugins/serendipity_event_templatechooser/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_templatechooser/serendipity_event_templatechooser.php [new file with mode: 0644]
plugins/serendipity_event_textile/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_textile/serendipity_event_textile.php [new file with mode: 0644]
plugins/serendipity_event_textile/textile.php [new file with mode: 0644]
plugins/serendipity_event_textwiki/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_textwiki/serendipity_event_textwiki.php [new file with mode: 0644]
plugins/serendipity_event_trackexits/serendipity_event_trackexits.php [new file with mode: 0644]
plugins/serendipity_event_weblogping/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_weblogping/serendipity_event_weblogping.php [new file with mode: 0644]
plugins/serendipity_event_weblogping/servicesdb_en.inc.php [new file with mode: 0644]
plugins/serendipity_event_weblogping/servicesdb_ja.inc.php [new file with mode: 0644]
plugins/serendipity_event_xhtmlcleanup/serendipity_event_xhtmlcleanup.php [new file with mode: 0644]
plugins/serendipity_plugin_comments/lang_is.inc.php [new file with mode: 0644]
plugins/serendipity_plugin_comments/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_plugin_comments/serendipity_plugin_comments.php [new file with mode: 0644]
plugins/serendipity_plugin_creativecommons/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_plugin_creativecommons/serendipity_plugin_creativecommons.php [new file with mode: 0644]
plugins/serendipity_plugin_entrylinks/serendipity_plugin_entrylinks.php [new file with mode: 0644]
plugins/serendipity_plugin_eventwrapper/serendipity_plugin_eventwrapper.php [new file with mode: 0644]
plugins/serendipity_plugin_history/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_plugin_history/serendipity_plugin_history.php [new file with mode: 0644]
plugins/serendipity_plugin_recententries/lang_is.inc.php [new file with mode: 0644]
plugins/serendipity_plugin_recententries/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_plugin_recententries/serendipity_plugin_recententries.php [new file with mode: 0644]
plugins/serendipity_plugin_remoterss/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_plugin_remoterss/serendipity_plugin_remoterss.php [new file with mode: 0644]
plugins/serendipity_plugin_shoutbox/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_plugin_shoutbox/serendipity_plugin_shoutbox.php [new file with mode: 0644]
plugins/serendipity_plugin_templatedropdown/lang_ja.inc.php [new file with mode: 0644]
plugins/serendipity_plugin_templatedropdown/serendipity_plugin_templatedropdown.php [new file with mode: 0644]
rss.php [new file with mode: 0644]
serendipity.css.php [new file with mode: 0644]
serendipity_admin.php [new file with mode: 0644]
serendipity_admin_image_selector.php [new file with mode: 0644]
serendipity_config.inc.php [new file with mode: 0644]
serendipity_define.js.php [new file with mode: 0644]
serendipity_editor.js [new file with mode: 0644]
serendipity_xmlrpc.php [new file with mode: 0644]
sql/db.sql [new file with mode: 0644]
sql/db_update_0.2_0.3_mysql.sql [new file with mode: 0644]
sql/db_update_0.2_0.3_postgres.sql [new file with mode: 0644]
sql/db_update_0.3_0.4_mysql.sql [new file with mode: 0644]
sql/db_update_0.3_0.4_postgres.sql [new file with mode: 0644]
sql/db_update_0.5.1_0.6_mysql.sql [new file with mode: 0644]
sql/db_update_0.5.1_0.6_postgres.sql [new file with mode: 0644]
sql/db_update_0.5_0.5.1_mysql.sql [new file with mode: 0644]
sql/db_update_0.5_0.5.1_postgres.sql [new file with mode: 0644]
sql/db_update_0.6.10_0.6.11_mysql.sql [new file with mode: 0644]
sql/db_update_0.6.10_0.6.11_postgres.sql [new file with mode: 0644]
sql/db_update_0.6.1_0.6.2_mysql.sql [new file with mode: 0644]
sql/db_update_0.6.1_0.6.2_postgres.sql [new file with mode: 0644]
sql/db_update_0.6.2_0.6.3_mysql.sql [new file with mode: 0644]
sql/db_update_0.6.2_0.6.3_postgres.sql [new file with mode: 0644]
sql/db_update_0.6.3_0.6.4_mysql.sql [new file with mode: 0644]
sql/db_update_0.6.3_0.6.4_postgres.sql [new file with mode: 0644]
sql/db_update_0.6.4_0.6.5_mysql.sql [new file with mode: 0644]
sql/db_update_0.6.4_0.6.5_postgres.sql [new file with mode: 0644]
sql/db_update_0.6.5_0.6.6_mysql.sql [new file with mode: 0644]
sql/db_update_0.6.5_0.6.6_postgres.sql [new file with mode: 0644]
sql/db_update_0.6.6_0.6.7_mysql.sql [new file with mode: 0644]
sql/db_update_0.6.6_0.6.7_postgres.sql [new file with mode: 0644]
sql/db_update_0.6.8_0.6.9_mysql.sql [new file with mode: 0644]
sql/db_update_0.6.8_0.6.9_postgres.sql [new file with mode: 0644]
sql/db_update_0.6.9_0.7.0_mysql.sql [new file with mode: 0644]
sql/db_update_0.6.9_0.7.0_postgresql.sql [new file with mode: 0644]
sql/db_update_0.6_0.6.1_mysql.sql [new file with mode: 0644]
sql/db_update_0.6_0.6.1_postgres.sql [new file with mode: 0644]
sql/db_update_0.8-alpha10_0.8-alpha11_mysql.sql [new file with mode: 0644]
sql/db_update_0.8-alpha11_0.8-alpha12_mysql.sql [new file with mode: 0644]
sql/db_update_0.8-alpha11_0.8-alpha12_postgres.sql [new file with mode: 0644]
sql/db_update_0.8-alpha11_0.8-alpha12_sqlite.sql [new file with mode: 0644]
sql/db_update_0.8-alpha12_0.8-alpha13_mysql.sql [new file with mode: 0644]
sql/db_update_0.8-alpha12_0.8-alpha13_postgres.sql [new file with mode: 0644]
sql/db_update_0.8-alpha12_0.8-alpha13_sqlite.sql [new file with mode: 0644]
sql/db_update_0.8-alpha1_0.8-alpha2_mysql.sql [new file with mode: 0644]
sql/db_update_0.8-alpha4_0.8-alpha5_mysql.sql [new file with mode: 0644]
sql/db_update_0.8-alpha4_0.8-alpha5_postgres.sql [new file with mode: 0644]
sql/db_update_0.8-alpha4_0.8-alpha5_sqlite.sql [new file with mode: 0644]
sql/db_update_0.8-alpha5_0.8-alpha6_mysql.sql [new file with mode: 0644]
sql/db_update_0.8-alpha5_0.8-alpha6_postgres.sql [new file with mode: 0644]
sql/db_update_0.8-alpha5_0.8-alpha6_sqlite.sql [new file with mode: 0644]
sql/db_update_0.8-beta3_0.8-beta4_mysql.sql [new file with mode: 0644]
sql/db_update_0.8-beta3_0.8-beta4_postgres.sql [new file with mode: 0644]
sql/db_update_0.8-beta3_0.8-beta4_sqlite.sql [new file with mode: 0644]
sql/db_update_0.8-beta5_0.8-beta6_mysql.sql [new file with mode: 0644]
sql/db_update_0.8-beta5_0.8-beta6_postgres.sql [new file with mode: 0644]
sql/db_update_0.8-beta5_0.8-beta6_sqlite.sql [new file with mode: 0644]
templates/HOWTO [new file with mode: 0644]
templates/blue/htmlarea.css [new file with mode: 0644]
templates/blue/info.txt [new file with mode: 0644]
templates/blue/preview.png [new file with mode: 0644]
templates/blue/style.css [new file with mode: 0644]
templates/default-rtl/admin/img/background.jpg [new file with mode: 0644]
templates/default-rtl/admin/img/banner_background.png [new file with mode: 0644]
templates/default-rtl/admin/img/button_background.png [new file with mode: 0644]
templates/default-rtl/admin/img/infobar_background.png [new file with mode: 0644]
templates/default-rtl/admin/img/menu_background.png [new file with mode: 0644]
templates/default-rtl/admin/img/menuheader_background.png [new file with mode: 0644]
templates/default-rtl/admin/style.css [new file with mode: 0644]
templates/default-rtl/htmlarea.css [new file with mode: 0644]
templates/default-rtl/img/background.png [new file with mode: 0644]
templates/default-rtl/info.txt [new file with mode: 0644]
templates/default-rtl/preview.png [new file with mode: 0644]
templates/default-rtl/style.css [new file with mode: 0644]
templates/default/admin/img/accept.png [new file with mode: 0644]
templates/default/admin/img/background.jpg [new file with mode: 0644]
templates/default/admin/img/banner_background.png [new file with mode: 0644]
templates/default/admin/img/big_delete.png [new file with mode: 0644]
templates/default/admin/img/big_rename.png [new file with mode: 0644]
templates/default/admin/img/big_resize.png [new file with mode: 0644]
templates/default/admin/img/big_rotate_ccw.png [new file with mode: 0644]
templates/default/admin/img/big_rotate_cw.png [new file with mode: 0644]
templates/default/admin/img/big_zoom.png [new file with mode: 0644]
templates/default/admin/img/button_background.png [new file with mode: 0644]
templates/default/admin/img/clock.png [new file with mode: 0644]
templates/default/admin/img/clock_future.png [new file with mode: 0644]
templates/default/admin/img/configure.png [new file with mode: 0644]
templates/default/admin/img/delete.png [new file with mode: 0644]
templates/default/admin/img/downarrow.png [new file with mode: 0644]
templates/default/admin/img/edit.png [new file with mode: 0644]
templates/default/admin/img/folder.png [new file with mode: 0644]
templates/default/admin/img/infobar_background.png [new file with mode: 0644]
templates/default/admin/img/install.png [new file with mode: 0644]
templates/default/admin/img/install_now.png [new file with mode: 0644]
templates/default/admin/img/install_template.png [new file with mode: 0644]
templates/default/admin/img/menu_background.png [new file with mode: 0644]
templates/default/admin/img/menuheader_background.png [new file with mode: 0644]
templates/default/admin/img/menuitem.png [new file with mode: 0644]
templates/default/admin/img/mime_unknown.png [new file with mode: 0644]
templates/default/admin/img/next.png [new file with mode: 0644]
templates/default/admin/img/previous.png [new file with mode: 0644]
templates/default/admin/img/rotate.png [new file with mode: 0644]
templates/default/admin/img/thumbnail.png [new file with mode: 0644]
templates/default/admin/img/uparrow.png [new file with mode: 0644]
templates/default/admin/img/upgrade_now.png [new file with mode: 0644]
templates/default/admin/img/user_admin.png [new file with mode: 0644]
templates/default/admin/img/user_chief.png [new file with mode: 0644]
templates/default/admin/img/user_editor.png [new file with mode: 0644]
templates/default/admin/img/zoom.png [new file with mode: 0644]
templates/default/admin/style.css [new file with mode: 0644]
templates/default/atom.css [new file with mode: 0644]
templates/default/commentform.tpl [new file with mode: 0644]
templates/default/commentpopup.tpl [new file with mode: 0644]
templates/default/comments.tpl [new file with mode: 0644]
templates/default/content.tpl [new file with mode: 0644]
templates/default/entries.tpl [new file with mode: 0644]
templates/default/entries_archives.tpl [new file with mode: 0644]
templates/default/entries_summary.tpl [new file with mode: 0644]
templates/default/htmlarea.css [new file with mode: 0644]
templates/default/img/back.png [new file with mode: 0644]
templates/default/img/background.png [new file with mode: 0644]
templates/default/img/blank.gif [new file with mode: 0644]
templates/default/img/blank.png [new file with mode: 0644]
templates/default/img/delete.png [new file with mode: 0644]
templates/default/img/down.png [new file with mode: 0644]
templates/default/img/emoticons/cool.png [new file with mode: 0644]
templates/default/img/emoticons/cry.png [new file with mode: 0644]
templates/default/img/emoticons/eek.png [new file with mode: 0644]
templates/default/img/emoticons/laugh.png [new file with mode: 0644]
templates/default/img/emoticons/normal.png [new file with mode: 0644]
templates/default/img/emoticons/sad.png [new file with mode: 0644]
templates/default/img/emoticons/smile.png [new file with mode: 0644]
templates/default/img/emoticons/tongue.png [new file with mode: 0644]
templates/default/img/emoticons/wink.png [new file with mode: 0644]
templates/default/img/forward.png [new file with mode: 0644]
templates/default/img/graph_bar_horisontal.png [new file with mode: 0644]
templates/default/img/img_align_left.png [new file with mode: 0644]
templates/default/img/img_align_right.png [new file with mode: 0644]
templates/default/img/img_align_top.png [new file with mode: 0644]
templates/default/img/minus.png [new file with mode: 0644]
templates/default/img/norights.png [new file with mode: 0644]
templates/default/img/plus.png [new file with mode: 0644]
templates/default/img/rename.png [new file with mode: 0644]
templates/default/img/s9y_banner_small.png [new file with mode: 0644]
templates/default/img/scale.png [new file with mode: 0644]
templates/default/img/somerights20.gif [new file with mode: 0644]
templates/default/img/up.png [new file with mode: 0644]
templates/default/img/xml.gif [new file with mode: 0644]
templates/default/img/zoom.png [new file with mode: 0644]
templates/default/index.tpl [new file with mode: 0644]
templates/default/info.txt [new file with mode: 0644]
templates/default/plugin_calendar.tpl [new file with mode: 0644]
templates/default/preview.png [new file with mode: 0644]
templates/default/sidebar.tpl [new file with mode: 0644]
templates/default/style.css [new file with mode: 0644]
templates/default/trackbacks.tpl [new file with mode: 0644]
templates/idea/img/I_had_an_idea.jpg [new file with mode: 0644]
templates/idea/img/bullet.gif [new file with mode: 0644]
templates/idea/img/clock_face_messy_paint_runs.jpg [new file with mode: 0644]
templates/idea/img/quote.gif [new file with mode: 0644]
templates/idea/info.txt [new file with mode: 0644]
templates/idea/preview.png [new file with mode: 0644]
templates/idea/style.css [new file with mode: 0644]
templates/kubrick/comments.tpl [new file with mode: 0644]
templates/kubrick/config.inc.php [new file with mode: 0644]
templates/kubrick/entries.tpl [new file with mode: 0644]
templates/kubrick/images/kubrickbg.jpg [new file with mode: 0644]
templates/kubrick/images/kubrickbgcolor.jpg [new file with mode: 0644]
templates/kubrick/images/kubrickbgwide.jpg [new file with mode: 0644]
templates/kubrick/images/kubrickfooter.jpg [new file with mode: 0644]
templates/kubrick/images/kubrickheader.jpg [new file with mode: 0644]
templates/kubrick/images/kubricklogo.jpg [new file with mode: 0644]
templates/kubrick/images/kubrickportrait.png [new file with mode: 0644]
templates/kubrick/index.tpl [new file with mode: 0644]
templates/kubrick/info.txt [new file with mode: 0644]
templates/kubrick/lang_de.inc.php [new file with mode: 0644]
templates/kubrick/lang_en.inc.php [new file with mode: 0644]
templates/kubrick/preview.png [new file with mode: 0644]
templates/kubrick/sidebar.tpl [new file with mode: 0644]
templates/kubrick/style.css [new file with mode: 0644]
templates/kubrick/trackbacks.tpl [new file with mode: 0644]
templates/moz-modern/htmlarea.css [new file with mode: 0644]
templates/moz-modern/img/back.png [new file with mode: 0644]
templates/moz-modern/img/background.png [new file with mode: 0644]
templates/moz-modern/img/background2.png [new file with mode: 0644]
templates/moz-modern/img/forward.png [new file with mode: 0644]
templates/moz-modern/index.tpl [new file with mode: 0644]
templates/moz-modern/info.txt [new file with mode: 0644]
templates/moz-modern/preview.png [new file with mode: 0644]
templates/moz-modern/style.css [new file with mode: 0644]
templates/mt-clean/info.txt [new file with mode: 0644]
templates/mt-clean/preview.png [new file with mode: 0644]
templates/mt-clean/style.css [new file with mode: 0644]
templates/mt-georgiablue/info.txt [new file with mode: 0644]
templates/mt-georgiablue/preview.png [new file with mode: 0644]
templates/mt-georgiablue/style.css [new file with mode: 0644]
templates/mt-gettysburg/info.txt [new file with mode: 0644]
templates/mt-gettysburg/preview.png [new file with mode: 0644]
templates/mt-gettysburg/style.css [new file with mode: 0644]
templates/mt-plainjane/info.txt [new file with mode: 0644]
templates/mt-plainjane/preview.png [new file with mode: 0644]
templates/mt-plainjane/style.css [new file with mode: 0644]
templates/mt-rusty/info.txt [new file with mode: 0644]
templates/mt-rusty/preview.png [new file with mode: 0644]
templates/mt-rusty/style.css [new file with mode: 0644]
templates/mt-stormy/inactive.txt [new file with mode: 0644]
templates/mt-stormy/info.txt [new file with mode: 0644]
templates/mt-stormy/style.css [new file with mode: 0644]
templates/mt-trendy/htmlarea.css [new file with mode: 0644]
templates/mt-trendy/img/back.png [new file with mode: 0644]
templates/mt-trendy/img/forward.png [new file with mode: 0644]
templates/mt-trendy/info.txt [new file with mode: 0644]
templates/mt-trendy/preview.png [new file with mode: 0644]
templates/mt-trendy/style.css [new file with mode: 0644]
templates/mt3-chalkboard/info.txt [new file with mode: 0644]
templates/mt3-chalkboard/preview.png [new file with mode: 0644]
templates/mt3-chalkboard/style.css [new file with mode: 0644]
templates/mt3-gettysburg/info.txt [new file with mode: 0644]
templates/mt3-gettysburg/preview.png [new file with mode: 0644]
templates/mt3-gettysburg/style.css [new file with mode: 0644]
templates/mt3-independence/info.txt [new file with mode: 0644]
templates/mt3-independence/preview.png [new file with mode: 0644]
templates/mt3-independence/style.css [new file with mode: 0644]
templates/mt3-squash/info.txt [new file with mode: 0644]
templates/mt3-squash/preview.png [new file with mode: 0644]
templates/mt3-squash/style.css [new file with mode: 0644]
templates/newspaper/htmlarea.css [new file with mode: 0644]
templates/newspaper/img/shadowb.png [new file with mode: 0644]
templates/newspaper/img/shadowbl.png [new file with mode: 0644]
templates/newspaper/img/shadowbr.png [new file with mode: 0644]
templates/newspaper/img/shadowr.png [new file with mode: 0644]
templates/newspaper/img/shadowt.png [new file with mode: 0644]
templates/newspaper/info.txt [new file with mode: 0644]
templates/newspaper/layout.php [new file with mode: 0644]
templates/newspaper/preview.png [new file with mode: 0644]
templates/newspaper/style.css [new file with mode: 0644]
templates/wp/atom.css [new file with mode: 0644]
templates/wp/commentform.tpl [new file with mode: 0644]
templates/wp/comments.tpl [new file with mode: 0644]
templates/wp/content.tpl [new file with mode: 0644]
templates/wp/entries.tpl [new file with mode: 0644]
templates/wp/entries_archives.tpl [new file with mode: 0644]
templates/wp/entries_summary.tpl [new file with mode: 0644]
templates/wp/htmlarea.css [new file with mode: 0644]
templates/wp/index.tpl [new file with mode: 0644]
templates/wp/info.txt [new file with mode: 0644]
templates/wp/plugin_calendar.tpl [new file with mode: 0644]
templates/wp/sidebar.tpl [new file with mode: 0644]
templates/wp/trackbacks.tpl [new file with mode: 0644]
templates/wp/wp-layout.css [new file with mode: 0644]
wfwcomment.php [new file with mode: 0644]

diff --git a/bundled-libs/Cache/Lite.php b/bundled-libs/Cache/Lite.php
new file mode 100644 (file)
index 0000000..9b39342
--- /dev/null
@@ -0,0 +1,615 @@
+<?php
+
+/**
+* Fast, light and safe Cache Class
+*
+* Cache_Lite is a fast, light and safe cache system. It's optimized
+* for file containers. It is fast and safe (because it uses file
+* locking and/or anti-corruption tests).
+*
+* There are some examples in the 'docs/examples' file
+* Technical choices are described in the 'docs/technical' file
+*
+* A tutorial is available in english at this url :
+* http://www.pearfr.org/index.php/en/article/cache_lite
+* (big thanks to Pierre-Alain Joye for the translation)
+*
+* The same tutorial is also available in french at this url :
+* http://www.pearfr.org/index.php/fr/article/cache_lite
+*
+* Memory Caching is from an original idea of
+* Mike BENOIT <ipso@snappymail.ca>
+*
+* @package Cache_Lite
+* @category Caching
+* @version $Id: Lite.php,v 1.1 2004/12/02 14:23:52 nohn Exp $
+* @author Fabien MARTY <fab@php.net>
+*/
+
+define('CACHE_LITE_ERROR_RETURN', 1);
+define('CACHE_LITE_ERROR_DIE', 8);
+
+class Cache_Lite
+{
+
+    // --- Private properties ---
+
+    /**
+    * Directory where to put the cache files
+    * (make sure to add a trailing slash)
+    *
+    * @var string $_cacheDir
+    */
+    var $_cacheDir = '/tmp/';
+
+    /**
+    * Enable / disable caching
+    *
+    * (can be very usefull for the debug of cached scripts)
+    *
+    * @var boolean $_caching
+    */
+    var $_caching = true;
+
+    /**
+    * Cache lifetime (in seconds)
+    *
+    * @var int $_lifeTime
+    */
+    var $_lifeTime = 3600;
+
+    /**
+    * Enable / disable fileLocking
+    *
+    * (can avoid cache corruption under bad circumstances)
+    *
+    * @var boolean $_fileLocking
+    */
+    var $_fileLocking = true;
+
+    /**
+    * Timestamp of the last valid cache
+    *
+    * @var int $_refreshTime
+    */
+    var $_refreshTime;
+
+    /**
+    * File name (with path)
+    *
+    * @var string $_file
+    */
+    var $_file;
+
+    /**
+    * Enable / disable write control (the cache is read just after writing to detect corrupt entries)
+    *
+    * Enable write control will lightly slow the cache writing but not the cache reading
+    * Write control can detect some corrupt cache files but maybe it's not a perfect control
+    *
+    * @var boolean $_writeControl
+    */
+    var $_writeControl = true;
+
+    /**
+    * Enable / disable read control
+    *
+    * If enabled, a control key is embeded in cache file and this key is compared with the one
+    * calculated after the reading.
+    *
+    * @var boolean $_writeControl
+    */
+    var $_readControl = true;
+
+    /**
+    * Type of read control (only if read control is enabled)
+    *
+    * Available values are :
+    * 'md5' for a md5 hash control (best but slowest)
+    * 'crc32' for a crc32 hash control (lightly less safe but faster, better choice)
+    * 'strlen' for a length only test (fastest)
+    *
+    * @var boolean $_readControlType
+    */
+    var $_readControlType = 'crc32';
+
+    /**
+    * Pear error mode (when raiseError is called)
+    *
+    * (see PEAR doc)
+    *
+    * @see setToDebug()
+    * @var int $_pearErrorMode
+    */
+    var $_pearErrorMode = CACHE_LITE_ERROR_RETURN;
+    
+    /**
+    * Current cache id
+    *
+    * @var string $_id
+    */
+    var $_id;
+
+    /**
+    * Current cache group
+    *
+    * @var string $_group
+    */
+    var $_group;
+
+    /**
+    * Enable / Disable "Memory Caching"
+    *
+    * NB : There is no lifetime for memory caching ! 
+    *
+    * @var boolean $_memoryCaching
+    */
+    var $_memoryCaching = false;
+
+    /**
+    * Enable / Disable "Only Memory Caching"
+    * (be carefull, memory caching is "beta quality")
+    *
+    * @var boolean $_onlyMemoryCaching
+    */
+    var $_onlyMemoryCaching = false;
+
+    /**
+    * Memory caching array
+    *
+    * @var array $_memoryCachingArray
+    */
+    var $_memoryCachingArray = array();
+
+    /**
+    * Memory caching counter
+    *
+    * @var int $memoryCachingCounter
+    */
+    var $_memoryCachingCounter = 0;
+
+    /**
+    * Memory caching limit
+    *
+    * @var int $memoryCachingLimit
+    */
+    var $_memoryCachingLimit = 1000;
+    
+    /**
+    * File Name protection
+    *
+    * if set to true, you can use any cache id or group name
+    * if set to false, it can be faster but cache ids and group names
+    * will be used directly in cache file names so be carefull with
+    * special characters...
+    *
+    * @var boolean $fileNameProtection
+    */
+    var $_fileNameProtection = true;
+    
+    /**
+    * Enable / disable automatic serialization
+    *
+    * it can be used to save directly datas which aren't strings
+    * (but it's slower)    
+    *
+    * @var boolean $_serialize
+    */
+    var $_automaticSerialization = false;
+    
+    // --- Public methods ---
+
+    /**
+    * Constructor
+    *
+    * $options is an assoc. Available options are :
+    * $options = array(
+    *     'cacheDir' => directory where to put the cache files (string),
+    *     'caching' => enable / disable caching (boolean),
+    *     'lifeTime' => cache lifetime in seconds (int),
+    *     'fileLocking' => enable / disable fileLocking (boolean),
+    *     'writeControl' => enable / disable write control (boolean),
+    *     'readControl' => enable / disable read control (boolean),
+    *     'readControlType' => type of read control 'crc32', 'md5', 'strlen' (string),
+    *     'pearErrorMode' => pear error mode (when raiseError is called) (cf PEAR doc) (int),
+    *     'memoryCaching' => enable / disable memory caching (boolean),
+    *     'onlyMemoryCaching' => enable / disable only memory caching (boolean),
+    *     'memoryCachingLimit' => max nbr of records to store into memory caching (int),
+    *     'fileNameProtection' => enable / disable automatic file name protection (boolean),
+    *     'automaticSerialization' => enable / disable automatic serialization (boolean)
+    * );
+    *
+    * @param array $options options
+    * @access public
+    */
+    function Cache_Lite($options = array(NULL))
+    {
+        $availableOptions = array('automaticSerialization', 'fileNameProtection', 'memoryCaching', 'onlyMemoryCaching', 'memoryCachingLimit', 'cacheDir', 'caching', 'lifeTime', 'fileLocking', 'writeControl', 'readControl', 'readControlType', 'pearErrorMode');
+        foreach($options as $key => $value) {
+            if(in_array($key, $availableOptions)) {
+                $property = '_'.$key;
+                $this->$property = $value;
+            }
+        }
+        $this->_refreshTime = time() - $this->_lifeTime;
+    }
+    
+    /**
+    * Test if a cache is available and (if yes) return it
+    *
+    * @param string $id cache id
+    * @param string $group name of the cache group
+    * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
+    * @return string data of the cache (or false if no cache available)
+    * @access public
+    */
+    function get($id, $group = 'default', $doNotTestCacheValidity = false)
+    {
+        $this->_id = $id;
+        $this->_group = $group;
+        $data = false;
+        if ($this->_caching) {
+            $this->_setFileName($id, $group);
+            if ($this->_memoryCaching) {
+                if (isset($this->_memoryCachingArray[$this->_file])) {
+                    if ($this->_automaticSerialization) {
+                        return unserialize($this->_memoryCachingArray[$this->_file]);
+                    } else {
+                        return $this->_memoryCachingArray[$this->_file];
+                    }
+                } else {
+                    if ($this->_onlyMemoryCaching) {
+                        return false;
+                    }
+                }
+            }
+            if ($doNotTestCacheValidity) {
+                if (file_exists($this->_file)) {
+                    $data = $this->_read();
+                }
+            } else {
+                if ((file_exists($this->_file)) && (@filemtime($this->_file) > $this->_refreshTime)) {
+                    $data = $this->_read();
+                }
+            }
+            if (($data) and ($this->_memoryCaching)) {
+                $this->_memoryCacheAdd($this->_file, $data);
+            }
+            if (($this->_automaticSerialization) and (is_string($data))) {
+                $data = unserialize($data);
+            }
+            return $data;
+        }
+        return false;
+    }
+    
+    /**
+    * Save some data in a cache file
+    *
+    * @param string $data data to put in cache (can be another type than strings if automaticSerialization is on)
+    * @param string $id cache id
+    * @param string $group name of the cache group
+    * @return boolean true if no problem
+    * @access public
+    */
+    function save($data, $id = NULL, $group = 'default')
+    {
+        if ($this->_caching) {
+            if ($this->_automaticSerialization) {
+                $data = serialize($data);
+            }
+            if (isset($id)) {
+                $this->_setFileName($id, $group);
+            }
+            if ($this->_memoryCaching) {
+                $this->_memoryCacheAdd($this->_file, $data);
+                if ($this->_onlyMemoryCaching) {
+                    return true;
+                }
+            }
+            if ($this->_writeControl) {
+                if (!$this->_writeAndControl($data)) {
+                    @touch($this->_file, time() - 2*abs($this->_lifeTime));
+                    return false;
+                } else {
+                    return true;
+                }
+            } else {
+                return $this->_write($data);
+            }
+        }
+        return false;
+    }
+
+    /**
+    * Remove a cache file
+    *
+    * @param string $id cache id
+    * @param string $group name of the cache group
+    * @return boolean true if no problem
+    * @access public
+    */
+    function remove($id, $group = 'default')
+    {
+        $this->_setFileName($id, $group);
+        if ($this->_memoryCaching) {
+            if (isset($this->_memoryCachingArray[$this->_file])) {
+                unset($this->_memoryCachingArray[$this->_file]);
+                $this->_memoryCachingCounter = $this->_memoryCachingCounter - 1;
+            }
+            if ($this->_onlyMemoryCaching) {
+                return true;
+            }
+        }
+        if (!@unlink($this->_file)) {
+            $this->raiseError('Cache_Lite : Unable to remove cache !', -3);   
+            return false;
+        }
+        return true;
+    }
+
+    /**
+    * Clean the cache
+    *
+    * if no group is specified all cache files will be destroyed
+    * else only cache files of the specified group will be destroyed
+    *
+    * @param string $group name of the cache group
+    * @return boolean true if no problem
+    * @access public
+    */
+    function clean($group = false)     
+    {
+        if ($this->_fileNameProtection) {
+            $motif = ($group) ? 'cache_'.md5($group).'_' : 'cache_';
+        } else {
+            $motif = ($group) ? 'cache_'.$group.'_' : 'cache_';
+        }
+        if ($this->_memoryCaching) {
+            while (list($key, $value) = each($this->_memoryCachingArray)) {
+                if (strpos($key, $motif, 0)) {
+                    unset($this->_memoryCachingArray[$key]);
+                    $this->_memoryCachingCounter = $this->_memoryCachingCounter - 1;
+                }
+            }
+            if ($this->_onlyMemoryCaching) {
+                return true;
+            }
+        }
+        if (!($dh = opendir($this->_cacheDir))) {
+            $this->raiseError('Cache_Lite : Unable to open cache directory !', -4);
+            return false;
+        }
+        while ($file = readdir($dh)) {
+            if (($file != '.') && ($file != '..')) {
+                $file = $this->_cacheDir . $file;
+                if (is_file($file)) {
+                    if (strpos($file, $motif, 0)) {
+                        if (!@unlink($file)) {
+                            $this->raiseError('Cache_Lite : Unable to remove cache !', -3);
+                            return false;
+                        }
+                    }
+                }
+            }
+        }
+        return true;
+    }
+    
+    /**
+    * Set to debug mode
+    *
+    * When an error is found, the script will stop and the message will be displayed
+    * (in debug mode only).
+    *
+    * @access public
+    */
+    function setToDebug()
+    {
+        $this->_pearErrorMode = CACHE_LITE_ERROR_DIE;
+    }
+
+    /**
+    * Set a new life time
+    *
+    * @param int $newLifeTime new life time (in seconds)
+    * @access public
+    */
+    function setLifeTime($newLifeTime)
+    {
+        $this->_lifeTime = $newLifeTime;
+        $this->_refreshTime = time() - $newLifeTime;
+    }
+
+    /**
+    *
+    * @access public
+    */
+    function saveMemoryCachingState($id, $group = 'default')
+    {
+        if ($this->_caching) {
+            $array = array(
+                'counter' => $this->_memoryCachingCounter,
+                'array' => $this->_memoryCachingState
+            );
+            $data = serialize($array);
+            $this->save($data, $id, $group);
+        }
+    }
+
+    /**
+    *
+    * @access public
+    */
+    function getMemoryCachingState($id, $group = 'default', $doNotTestCacheValidity = false)
+    {
+        if ($this->_caching) {
+            if ($data = $this->get($id, $group, $doNotTestCacheValidity)) {
+                $array = unserialize($data);
+                $this->_memoryCachingCounter = $array['counter'];
+                $this->_memoryCachingArray = $array['array'];
+            }
+        }
+    }
+    
+    /**
+    * Return the cache last modification time
+    *
+    * BE CAREFUL : THIS METHOD IS FOR HACKING ONLY !
+    *
+    * @return int last modification time
+    */
+    function lastModified() {
+        return filemtime($this->_file);
+    }
+    
+    /**
+    * Trigger a PEAR error
+    *
+    * To improve performances, the PEAR.php file is included dynamically.
+    * The file is so included only when an error is triggered. So, in most
+    * cases, the file isn't included and perfs are much better.
+    *
+    * @param string $msg error message
+    * @param int $code error code
+    * @access public
+    */
+    function raiseError($msg, $code)
+    {
+        include_once('PEAR.php');
+        PEAR::raiseError($msg, $code, $this->_pearErrorMode);
+    }
+
+    // --- Private methods ---
+
+    /**
+    *
+    * @access private
+    */
+    function _memoryCacheAdd($id, $data)
+    {
+        $this->_memoryCachingArray[$this->_file] = $data;
+        if ($this->_memoryCachingCounter >= $this->_memoryCachingLimit) {
+            list($key, $value) = each($this->_memoryCachingArray);
+            unset($this->_memoryCachingArray[$key]);
+        } else {
+            $this->_memoryCachingCounter = $this->_memoryCachingCounter + 1;
+        }
+    }
+
+    /**
+    * Make a file name (with path)
+    *
+    * @param string $id cache id
+    * @param string $group name of the group
+    * @access private
+    */
+    function _setFileName($id, $group)
+    {
+        if ($this->_fileNameProtection) {
+            $this->_file = ($this->_cacheDir.'cache_'.md5($group).'_'.md5($id));
+        } else {
+            $this->_file = $this->_cacheDir.'cache_'.$group.'_'.$id;
+        }
+    }
+    
+    /**
+    * Read the cache file and return the content
+    *
+    * @return string content of the cache file
+    * @access private
+    */
+    function _read()
+    {
+        $fp = @fopen($this->_file, "rb");
+        if ($this->_fileLocking) @flock($fp, LOCK_SH);
+        if ($fp) {
+            clearstatcache(); // because the filesize can be cached by PHP itself...
+            $length = @filesize($this->_file);
+            $mqr = get_magic_quotes_runtime();
+            set_magic_quotes_runtime(0);
+            if ($this->_readControl) {
+                $hashControl = @fread($fp, 32);
+                $length = $length - 32;
+            } 
+            $data = @fread($fp, $length);
+            set_magic_quotes_runtime($mqr);
+            if ($this->_fileLocking) @flock($fp, LOCK_UN);
+            @fclose($fp);
+            if ($this->_readControl) {
+                $hashData = $this->_hash($data, $this->_readControlType);
+                if ($hashData != $hashControl) {
+                    @touch($this->_file, time() - 2*abs($this->_lifeTime)); 
+                    return false;
+                }
+            }
+            return $data;
+        }
+        $this->raiseError('Cache_Lite : Unable to read cache !', -2);   
+        return false;
+    }
+    
+    /**
+    * Write the given data in the cache file
+    *
+    * @param string $data data to put in cache
+    * @return boolean true if ok
+    * @access private
+    */
+    function _write($data)
+    {
+        $fp = @fopen($this->_file, "wb");
+        if ($fp) {
+            if ($this->_fileLocking) @flock($fp, LOCK_EX);
+            if ($this->_readControl) {
+                @fwrite($fp, $this->_hash($data, $this->_readControlType), 32);
+            }
+            $len = strlen($data);
+            @fwrite($fp, $data, $len);
+            if ($this->_fileLocking) @flock($fp, LOCK_UN);
+            @fclose($fp);
+            return true;
+        }
+        $this->raiseError('Cache_Lite : Unable to write cache !', -1);
+        return false;
+    }
+    
+    /**
+    * Write the given data in the cache file and control it just after to avoir corrupted cache entries
+    *
+    * @param string $data data to put in cache
+    * @return boolean true if the test is ok
+    * @access private
+    */
+    function _writeAndControl($data)
+    {
+        $this->_write($data);
+        $dataRead = $this->_read($data);
+        return ($dataRead==$data);
+    }
+    
+    /**
+    * Make a control key with the string containing datas
+    *
+    * @param string $data data
+    * @param string $controlType type of control 'md5', 'crc32' or 'strlen'
+    * @return string control key
+    * @access private
+    */
+    function _hash($data, $controlType)
+    {
+        switch ($controlType) {
+        case 'md5':
+            return md5($data);
+        case 'crc32':
+            return sprintf('% 32d', crc32($data));
+        case 'strlen':
+            return sprintf('% 32d', strlen($data));
+        default:
+            $this->raiseError('Unknown controlType ! (available values are only \'md5\', \'crc32\', \'strlen\')', -5);
+        }
+    }
+    
+} 
+
+?>
diff --git a/bundled-libs/Cache/Lite/Function.php b/bundled-libs/Cache/Lite/Function.php
new file mode 100644 (file)
index 0000000..a72023f
--- /dev/null
@@ -0,0 +1,111 @@
+<?php
+
+/**
+* This class extends Cache_Lite and can be used to cache the result and output of functions/methods
+*
+* This class is completly inspired from Sebastian Bergmann's
+* PEAR/Cache_Function class. This is only an adaptation to
+* Cache_Lite
+*
+* There are some examples in the 'docs/examples' file
+* Technical choices are described in the 'docs/technical' file
+*
+* @package Cache_Lite
+* @version $Id: Function.php,v 1.1 2004/12/02 14:23:52 nohn Exp $
+* @author Sebastian BERGMANN <sb@sebastian-bergmann.de>
+* @author Fabien MARTY <fab@php.net>
+*/
+require_once('Cache/Lite.php');
+
+class Cache_Lite_Function extends Cache_Lite
+{
+
+    // --- Private properties ---
+    
+    /**
+    * Default cache group for function caching
+    *
+    * @var string $_defaultGroup
+    */
+    var $_defaultGroup = 'Cache_Lite_Function';
+    
+    // --- Public methods ----
+    
+    /**
+    * Constructor
+    *
+    * $options is an assoc. To have a look at availables options,
+    * see the constructor of the Cache_Lite class in 'Cache_Lite.php'
+    *
+    * Comparing to Cache_Lite constructor, there is another option :
+    * $options = array(
+    *     (...) see Cache_Lite constructor
+    *     'defaultGroup' => default cache group for function caching (string)
+    * );
+    *
+    * @param array $options options
+    * @access public
+    */
+    function Cache_Lite_Function($options = array(NULL))
+    {
+        if (isset($options['defaultGroup'])) {
+            $this->_defaultGroup = $options['defaultGroup'];
+        }
+        $this->Cache_Lite($options);
+    }
+    
+    /**
+    * Calls a cacheable function or method (or not if there is already a cache for it)
+    *
+    * Arguments of this method are read with func_get_args. So it doesn't appear
+    * in the function definition. Synopsis : 
+    * call('functionName', $arg1, $arg2, ...)
+    * (arg1, arg2... are arguments of 'functionName')
+    *
+    * @return mixed result of the function/method
+    * @access public
+    */
+    function call()
+    {
+        $arguments = func_get_args();
+        $id = serialize($arguments); // Generate a cache id
+        if (!$this->_fileNameProtection) {
+            $id = md5($id);
+            // if fileNameProtection is set to false, then the id has to be hashed
+            // because it's a very bad file name in most cases
+        }
+        $data = $this->get($id, $this->_defaultGroup);
+        if ($data !== false) {
+            $array = unserialize($data);
+            $output = $array['output'];
+            $result = $array['result'];
+        } else {
+            ob_start();
+            ob_implicit_flush(false);
+            $target = array_shift($arguments);
+            if (strstr($target, '::')) { // classname::staticMethod
+                list($class, $method) = explode('::', $target);
+                $result = call_user_func_array(array($class, $method), $arguments);
+            } else if (strstr($target, '->')) { // object->method
+                // use a stupid name ($objet_123456789 because) of problems when the object
+                // name is the same as this var name
+                list($object_123456789, $method) = explode('->', $target);
+                global $$object_123456789;
+                $result = call_user_func_array(array($$object_123456789, $method), $arguments);
+            } else { // function
+                $result = call_user_func_array($target, $arguments);
+            }
+            $output = ob_get_contents();
+            ob_end_clean();
+            $array['output'] = $output;
+            $array['result'] = $result;
+            $this->save(serialize($array), $id, $this->_defaultGroup);
+        }
+        echo($output);
+        return $result;
+    }
+    
+}
+
+?>
diff --git a/bundled-libs/Cache/Lite/Output.php b/bundled-libs/Cache/Lite/Output.php
new file mode 100644 (file)
index 0000000..d6d2460
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+
+/**
+* This class extends Cache_Lite and uses output buffering to get the data to cache.
+*
+* There are some examples in the 'docs/examples' file
+* Technical choices are described in the 'docs/technical' file
+*
+* @package Cache_Lite
+* @version $Id: Output.php,v 1.1 2004/12/02 14:23:52 nohn Exp $
+* @author Fabien MARTY <fab@php.net>
+*/
+
+require_once('Cache/Lite.php');
+
+class Cache_Lite_Output extends Cache_Lite
+{
+
+    // --- Public methods ---
+
+    /**
+    * Constructor
+    *
+    * $options is an assoc. To have a look at availables options,
+    * see the constructor of the Cache_Lite class in 'Cache_Lite.php'
+    *
+    * @param array $options options
+    * @access public
+    */
+    function Cache_Lite_Output($options)
+    {
+        $this->Cache_Lite($options);
+    }
+
+    /**
+    * Start the cache
+    *
+    * @param string $id cache id
+    * @param string $group name of the cache group
+    * @return boolean true if the cache is hit (false else)
+    * @access public
+    */
+    function start($id, $group = 'default')
+    {
+        $data = $this->get($id, $group);
+        if ($data !== false) {
+            echo($data);
+            return true;
+        } else {
+            ob_start();
+            ob_implicit_flush(false);
+            return false;
+        }
+    }
+
+    /**
+    * Stop the cache
+    *
+    * @access public
+    */
+    function end()
+    {
+        $data = ob_get_contents();
+        ob_end_clean();
+        $this->save($data, $this->_id, $this->_group);
+        echo($data);
+    }
+
+}
+
+
+?>
diff --git a/bundled-libs/HTTP/Request.php b/bundled-libs/HTTP/Request.php
new file mode 100644 (file)
index 0000000..ce918fb
--- /dev/null
@@ -0,0 +1,1132 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Copyright (c) 2002-2003, Richard Heyes                                |
+// | All rights reserved.                                                  |
+// |                                                                       |
+// | Redistribution and use in source and binary forms, with or without    |
+// | modification, are permitted provided that the following conditions    |
+// | are met:                                                              |
+// |                                                                       |
+// | o Redistributions of source code must retain the above copyright      |
+// |   notice, this list of conditions and the following disclaimer.       |
+// | o Redistributions in binary form must reproduce the above copyright   |
+// |   notice, this list of conditions and the following disclaimer in the |
+// |   documentation and/or other materials provided with the distribution.|
+// | o The names of the authors may not be used to endorse or promote      |
+// |   products derived from this software without specific prior written  |
+// |   permission.                                                         |
+// |                                                                       |
+// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
+// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
+// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
+// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
+// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
+// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
+// |                                                                       |
+// +-----------------------------------------------------------------------+
+// | Author: Richard Heyes <richard@phpguru.org>                           |
+// +-----------------------------------------------------------------------+
+//
+// $Id: Request.php,v 1.1 2004/12/06 09:18:15 nohn Exp $
+//
+// HTTP_Request Class
+//
+// Simple example, (Fetches yahoo.com and displays it):
+//
+// $a = &new HTTP_Request('http://www.yahoo.com/');
+// $a->sendRequest();
+// echo $a->getResponseBody();
+//
+
+require_once 'PEAR.php';
+require_once 'Net/Socket.php';
+require_once 'Net/URL.php';
+
+define('HTTP_REQUEST_METHOD_GET',     'GET',     true);
+define('HTTP_REQUEST_METHOD_HEAD',    'HEAD',    true);
+define('HTTP_REQUEST_METHOD_POST',    'POST',    true);
+define('HTTP_REQUEST_METHOD_PUT',     'PUT',     true);
+define('HTTP_REQUEST_METHOD_DELETE',  'DELETE',  true);
+define('HTTP_REQUEST_METHOD_OPTIONS', 'OPTIONS', true);
+define('HTTP_REQUEST_METHOD_TRACE',   'TRACE',   true);
+
+define('HTTP_REQUEST_HTTP_VER_1_0', '1.0', true);
+define('HTTP_REQUEST_HTTP_VER_1_1', '1.1', true);
+
+class HTTP_Request {
+
+    /**
+    * Instance of Net_URL
+    * @var object    
+    */
+    var $_url;
+
+    /**
+    * Type of request
+    * @var string
+    */
+    var $_method;
+
+    /**
+    * HTTP Version
+    * @var string
+    */
+    var $_http;
+
+    /**
+    * Request headers
+    * @var array
+    */
+    var $_requestHeaders;
+
+    /**
+    * Basic Auth Username
+    * @var string
+    */
+    var $_user;
+    
+    /**
+    * Basic Auth Password
+    * @var string
+    */
+    var $_pass;
+
+    /**
+    * Socket object
+    * @var object
+    */
+    var $_sock;
+    
+    /**
+    * Proxy server
+    * @var string
+    */
+    var $_proxy_host;
+    
+    /**
+    * Proxy port
+    * @var integer
+    */
+    var $_proxy_port;
+    
+    /**
+    * Proxy username
+    * @var string
+    */
+    var $_proxy_user;
+    
+    /**
+    * Proxy password
+    * @var string
+    */
+    var $_proxy_pass;
+
+    /**
+    * Post data
+    * @var mixed
+    */
+    var $_postData;
+
+   /**
+    * Files to post 
+    * @var array
+    */
+    var $_postFiles = array();
+
+    /**
+    * Connection timeout.
+    * @var integer
+    */
+    var $_timeout;
+    
+    /**
+    * HTTP_Response object
+    * @var object
+    */
+    var $_response;
+    
+    /**
+    * Whether to allow redirects
+    * @var boolean
+    */
+    var $_allowRedirects;
+    
+    /**
+    * Maximum redirects allowed
+    * @var integer
+    */
+    var $_maxRedirects;
+    
+    /**
+    * Current number of redirects
+    * @var integer
+    */
+    var $_redirects;
+
+   /**
+    * Whether to append brackets [] to array variables
+    * @var bool
+    */
+    var $_useBrackets = true;
+
+   /**
+    * Attached listeners
+    * @var array
+    */
+    var $_listeners = array();
+
+   /**
+    * Whether to save response body in response object property  
+    * @var bool
+    */
+    var $_saveBody = true;
+
+   /**
+    * Timeout for reading from socket (array(seconds, microseconds))
+    * @var array
+    */
+    var $_readTimeout = null;
+
+   /**
+    * Options to pass to Net_Socket::connect. See stream_context_create
+    * @var array
+    */
+    var $_socketOptions = null;
+
+    /**
+    * Constructor
+    *
+    * Sets up the object
+    * @param $url The url to fetch/access
+    * @param $params Associative array of parameters which can be:
+    *                  method         - Method to use, GET, POST etc
+    *                  http           - HTTP Version to use, 1.0 or 1.1
+    *                  user           - Basic Auth username
+    *                  pass           - Basic Auth password
+    *                  proxy_host     - Proxy server host
+    *                  proxy_port     - Proxy server port
+    *                  proxy_user     - Proxy auth username
+    *                  proxy_pass     - Proxy auth password
+    *                  timeout        - Connection timeout in seconds.
+    *                  allowRedirects - Whether to follow redirects or not
+    *                  maxRedirects   - Max number of redirects to follow
+    *                  useBrackets    - Whether to append [] to array variable names
+    *                  saveBody       - Whether to save response body in response object property
+    * @access public
+    */
+    function HTTP_Request($url = '', $params = array())
+    {
+        $this->_sock           = &new Net_Socket();
+        $this->_method         =  HTTP_REQUEST_METHOD_GET;
+        $this->_http           =  HTTP_REQUEST_HTTP_VER_1_1;
+        $this->_requestHeaders = array();
+        $this->_postData       = null;
+
+        $this->_user = null;
+        $this->_pass = null;
+
+        $this->_proxy_host = null;
+        $this->_proxy_port = null;
+        $this->_proxy_user = null;
+        $this->_proxy_pass = null;
+
+        $this->_allowRedirects = false;
+        $this->_maxRedirects   = 3;
+        $this->_redirects      = 0;
+
+        $this->_timeout  = null;
+        $this->_response = null;
+
+        foreach ($params as $key => $value) {
+            $this->{'_' . $key} = $value;
+        }
+
+        if (!empty($url)) {
+            $this->setURL($url);
+        }
+
+        // Default useragent
+        $this->addHeader('User-Agent', 'PEAR HTTP_Request class ( http://pear.php.net/ )');
+
+        // Make sure keepalives dont knobble us
+        $this->addHeader('Connection', 'close');
+
+        // Basic authentication
+        if (!empty($this->_user)) {
+            $this->_requestHeaders['Authorization'] = 'Basic ' . base64_encode($this->_user . ':' . $this->_pass);
+        }
+
+        // Use gzip encoding if possible
+        // Avoid gzip encoding if using multibyte functions (see #1781)
+        if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && extension_loaded('zlib') &&
+            0 == (2 & ini_get('mbstring.func_overload'))) {
+
+            $this->addHeader('Accept-Encoding', 'gzip');
+        }
+    }
+    
+    /**
+    * Generates a Host header for HTTP/1.1 requests
+    *
+    * @access private
+    * @return string
+    */
+    function _generateHostHeader()
+    {
+        if ($this->_url->port != 80 AND strcasecmp($this->_url->protocol, 'http') == 0) {
+            $host = $this->_url->host . ':' . $this->_url->port;
+
+        } elseif ($this->_url->port != 443 AND strcasecmp($this->_url->protocol, 'https') == 0) {
+            $host = $this->_url->host . ':' . $this->_url->port;
+
+        } elseif ($this->_url->port == 443 AND strcasecmp($this->_url->protocol, 'https') == 0 AND strpos($this->_url->url, ':443') !== false) {
+            $host = $this->_url->host . ':' . $this->_url->port;
+        
+        } else {
+            $host = $this->_url->host;
+        }
+
+        return $host;
+    }
+    
+    /**
+    * Resets the object to its initial state (DEPRECATED).
+    * Takes the same parameters as the constructor.
+    *
+    * @param  string $url    The url to be requested
+    * @param  array  $params Associative array of parameters
+    *                        (see constructor for details)
+    * @access public
+    * @deprecated deprecated since 1.2, call the constructor if this is necessary
+    */
+    function reset($url, $params = array())
+    {
+        $this->HTTP_Request($url, $params);
+    }
+
+    /**
+    * Sets the URL to be requested
+    *
+    * @param  string The url to be requested
+    * @access public
+    */
+    function setURL($url)
+    {
+        $this->_url = &new Net_URL($url, $this->_useBrackets);
+
+        if (!empty($this->_url->user) || !empty($this->_url->pass)) {
+            $this->setBasicAuth($this->_url->user, $this->_url->pass);
+        }
+
+        if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http) {
+            $this->addHeader('Host', $this->_generateHostHeader());
+        }
+    }
+    
+    /**
+    * Sets a proxy to be used
+    *
+    * @param string     Proxy host
+    * @param int        Proxy port
+    * @param string     Proxy username
+    * @param string     Proxy password
+    * @access public
+    */
+    function setProxy($host, $port = 8080, $user = null, $pass = null)
+    {
+        $this->_proxy_host = $host;
+        $this->_proxy_port = $port;
+        $this->_proxy_user = $user;
+        $this->_proxy_pass = $pass;
+
+        if (!empty($user)) {
+            $this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($user . ':' . $pass));
+        }
+    }
+
+    /**
+    * Sets basic authentication parameters
+    *
+    * @param string     Username
+    * @param string     Password
+    */
+    function setBasicAuth($user, $pass)
+    {
+        $this->_user = $user;
+        $this->_pass = $pass;
+
+        $this->addHeader('Authorization', 'Basic ' . base64_encode($user . ':' . $pass));
+    }
+
+    /**
+    * Sets the method to be used, GET, POST etc.
+    *
+    * @param string     Method to use. Use the defined constants for this
+    * @access public
+    */
+    function setMethod($method)
+    {
+        $this->_method = $method;
+    }
+
+    /**
+    * Sets the HTTP version to use, 1.0 or 1.1
+    *
+    * @param string     Version to use. Use the defined constants for this
+    * @access public
+    */
+    function setHttpVer($http)
+    {
+        $this->_http = $http;
+    }
+
+    /**
+    * Adds a request header
+    *
+    * @param string     Header name
+    * @param string     Header value
+    * @access public
+    */
+    function addHeader($name, $value)
+    {
+        $this->_requestHeaders[$name] = $value;
+    }
+
+    /**
+    * Removes a request header
+    *
+    * @param string     Header name to remove
+    * @access public
+    */
+    function removeHeader($name)
+    {
+        if (isset($this->_requestHeaders[$name])) {
+            unset($this->_requestHeaders[$name]);
+        }
+    }
+
+    /**
+    * Adds a querystring parameter
+    *
+    * @param string     Querystring parameter name
+    * @param string     Querystring parameter value
+    * @param bool       Whether the value is already urlencoded or not, default = not
+    * @access public
+    */
+    function addQueryString($name, $value, $preencoded = false)
+    {
+        $this->_url->addQueryString($name, $value, $preencoded);
+    }    
+    
+    /**
+    * Sets the querystring to literally what you supply
+    *
+    * @param string     The querystring data. Should be of the format foo=bar&x=y etc
+    * @param bool       Whether data is already urlencoded or not, default = already encoded
+    * @access public
+    */
+    function addRawQueryString($querystring, $preencoded = true)
+    {
+        $this->_url->addRawQueryString($querystring, $preencoded);
+    }
+
+    /**
+    * Adds postdata items
+    *
+    * @param string     Post data name
+    * @param string     Post data value
+    * @param bool       Whether data is already urlencoded or not, default = not
+    * @access public
+    */
+    function addPostData($name, $value, $preencoded = false)
+    {
+        if ($preencoded) {
+            $this->_postData[$name] = $value;
+        } else {
+            $this->_postData[$name] = $this->_arrayMapRecursive('urlencode', $value);
+        }
+    }
+
+   /**
+    * Recursively applies the callback function to the value
+    * 
+    * @param    mixed   Callback function
+    * @param    mixed   Value to process
+    * @access   private
+    * @return   mixed   Processed value
+    */
+    function _arrayMapRecursive($callback, $value)
+    {
+        if (!is_array($value)) {
+            return call_user_func($callback, $value);
+        } else {
+            $map = array();
+            foreach ($value as $k => $v) {
+                $map[$k] = $this->_arrayMapRecursive($callback, $v);
+            }
+            return $map;
+        }
+    }
+
+   /**
+    * Adds a file to upload
+    * 
+    * This also changes content-type to 'multipart/form-data' for proper upload
+    * 
+    * @access public
+    * @param  string    name of file-upload field
+    * @param  mixed     file name(s)
+    * @param  mixed     content-type(s) of file(s) being uploaded
+    * @return bool      true on success
+    * @throws PEAR_Error
+    */
+    function addFile($inputName, $fileName, $contentType = 'application/octet-stream')
+    {
+        if (!is_array($fileName) && !is_readable($fileName)) {
+            return PEAR::raiseError("File '{$fileName}' is not readable");
+        } elseif (is_array($fileName)) {
+            foreach ($fileName as $name) {
+                if (!is_readable($name)) {
+                    return PEAR::raiseError("File '{$name}' is not readable");
+                }
+            }
+        }
+        $this->addHeader('Content-Type', 'multipart/form-data');
+        $this->_postFiles[$inputName] = array(
+            'name' => $fileName,
+            'type' => $contentType
+        );
+        return true;
+    }
+
+    /**
+    * Adds raw postdata
+    *
+    * @param string     The data
+    * @param bool       Whether data is preencoded or not, default = already encoded
+    * @access public
+    */
+    function addRawPostData($postdata, $preencoded = true)
+    {
+        $this->_postData = $preencoded ? $postdata : urlencode($postdata);
+    }
+
+    /**
+    * Clears any postdata that has been added (DEPRECATED). 
+    * 
+    * Useful for multiple request scenarios.
+    *
+    * @access public
+    * @deprecated deprecated since 1.2
+    */
+    function clearPostData()
+    {
+        $this->_postData = null;
+    }
+
+    /**
+    * Appends a cookie to "Cookie:" header
+    * 
+    * @param string $name cookie name
+    * @param string $value cookie value
+    * @access public
+    */
+    function addCookie($name, $value)
+    {
+        $cookies = isset($this->_requestHeaders['Cookie']) ? $this->_requestHeaders['Cookie']. '; ' : '';
+        $this->addHeader('Cookie', $cookies . $name . '=' . $value);
+    }
+    
+    /**
+    * Clears any cookies that have been added (DEPRECATED). 
+    * 
+    * Useful for multiple request scenarios
+    *
+    * @access public
+    * @deprecated deprecated since 1.2
+    */
+    function clearCookies()
+    {
+        $this->removeHeader('Cookie');
+    }
+
+    /**
+    * Sends the request
+    *
+    * @access public
+    * @param  bool   Whether to store response body in Response object property,
+    *                set this to false if downloading a LARGE file and using a Listener
+    * @return mixed  PEAR error on error, true otherwise
+    */
+    function sendRequest($saveBody = true)
+    {
+        if (!is_a($this->_url, 'Net_URL')) {
+            return PEAR::raiseError('No URL given.');
+        }
+
+        $host = isset($this->_proxy_host) ? $this->_proxy_host : $this->_url->host;
+        $port = isset($this->_proxy_port) ? $this->_proxy_port : $this->_url->port;
+
+        // 4.3.0 supports SSL connections using OpenSSL. The function test determines
+        // we running on at least 4.3.0
+        if (strcasecmp($this->_url->protocol, 'https') == 0 AND function_exists('file_get_contents') AND extension_loaded('openssl')) {
+            if (isset($this->_proxy_host)) {
+                return PEAR::raiseError('HTTPS proxies are not supported.');
+            }
+            $host = 'ssl://' . $host;
+        }
+
+        // If this is a second request, we may get away without
+        // re-connecting if they're on the same server
+        if (PEAR::isError($err = $this->_sock->connect($host, $port, null, $this->_timeout, $this->_socketOptions)) ||
+            PEAR::isError($err = $this->_sock->write($this->_buildRequest()))) {
+
+            return $err;
+        }
+        if (!empty($this->_readTimeout)) {
+            $this->_sock->setTimeout($this->_readTimeout[0], $this->_readTimeout[1]);
+        }
+
+        $this->_notify('sentRequest');
+
+        // Read the response
+        $this->_response = &new HTTP_Response($this->_sock, $this->_listeners);
+        if (PEAR::isError($err = $this->_response->process($this->_saveBody && $saveBody)) ) {
+            return $err;
+        }
+
+        // Check for redirection
+        // Bugfix (PEAR) bug #18, 6 oct 2003 by Dave Mertens (headers are also stored lowercase, so we're gonna use them here)
+        // some non RFC2616 compliant servers (scripts) are returning lowercase headers ('location: xxx')
+        if (    $this->_allowRedirects
+            AND $this->_redirects <= $this->_maxRedirects
+            AND $this->getResponseCode() > 300
+            AND $this->getResponseCode() < 399
+            AND !empty($this->_response->_headers['location'])) {
+
+            
+            $redirect = $this->_response->_headers['location'];
+
+            // Absolute URL
+            if (preg_match('/^https?:\/\//i', $redirect)) {
+                $this->_url = &new Net_URL($redirect);
+                $this->addHeader('Host', $this->_generateHostHeader());
+            // Absolute path
+            } elseif ($redirect{0} == '/') {
+                $this->_url->path = $redirect;
+            
+            // Relative path
+            } elseif (substr($redirect, 0, 3) == '../' OR substr($redirect, 0, 2) == './') {
+                if (substr($this->_url->path, -1) == '/') {
+                    $redirect = $this->_url->path . $redirect;
+                } else {
+                    $redirect = dirname($this->_url->path) . '/' . $redirect;
+                }
+                $redirect = Net_URL::resolvePath($redirect);
+                $this->_url->path = $redirect;
+                
+            // Filename, no path
+            } else {
+                if (substr($this->_url->path, -1) == '/') {
+                    $redirect = $this->_url->path . $redirect;
+                } else {
+                    $redirect = dirname($this->_url->path) . '/' . $redirect;
+                }
+                $this->_url->path = $redirect;
+            }
+
+            $this->_redirects++;
+            return $this->sendRequest($saveBody);
+
+        // Too many redirects
+        } elseif ($this->_allowRedirects AND $this->_redirects > $this->_maxRedirects) {
+            return PEAR::raiseError('Too many redirects');
+        }
+
+        $this->_sock->disconnect();
+
+        return true;
+    }
+
+    /**
+    * Returns the response code
+    *
+    * @access public
+    * @return mixed     Response code, false if not set
+    */
+    function getResponseCode()
+    {
+        return isset($this->_response->_code) ? $this->_response->_code : false;
+    }
+
+    /**
+    * Returns either the named header or all if no name given
+    *
+    * @access public
+    * @param string     The header name to return, do not set to get all headers
+    * @return mixed     either the value of $headername (false if header is not present)
+    *                   or an array of all headers
+    */
+    function getResponseHeader($headername = null)
+    {
+        if (!isset($headername)) {
+            return isset($this->_response->_headers)? $this->_response->_headers: array();
+        } else {
+            return isset($this->_response->_headers[$headername]) ? $this->_response->_headers[$headername] : false;
+        }
+    }
+
+    /**
+    * Returns the body of the response
+    *
+    * @access public
+    * @return mixed     response body, false if not set
+    */
+    function getResponseBody()
+    {
+        return isset($this->_response->_body) ? $this->_response->_body : false;
+    }
+
+    /**
+    * Returns cookies set in response
+    * 
+    * @access public
+    * @return mixed     array of response cookies, false if none are present
+    */
+    function getResponseCookies()
+    {
+        return isset($this->_response->_cookies) ? $this->_response->_cookies : false;
+    }
+
+    /**
+    * Builds the request string
+    *
+    * @access private
+    * @return string The request string
+    */
+    function _buildRequest()
+    {
+        $separator = ini_get('arg_separator.output');
+        ini_set('arg_separator.output', '&');
+        $querystring = ($querystring = $this->_url->getQueryString()) ? '?' . $querystring : '';
+        ini_set('arg_separator.output', $separator);
+
+        $host = isset($this->_proxy_host) ? $this->_url->protocol . '://' . $this->_url->host : '';
+        $port = (isset($this->_proxy_host) AND $this->_url->port != 80) ? ':' . $this->_url->port : '';
+        $path = (empty($this->_url->path)? '/': $this->_url->path) . $querystring;
+        $url  = $host . $port . $path;
+
+        $request = $this->_method . ' ' . $url . ' HTTP/' . $this->_http . "\r\n";
+
+        if (HTTP_REQUEST_METHOD_POST != $this->_method && HTTP_REQUEST_METHOD_PUT != $this->_method) {
+            $this->removeHeader('Content-Type');
+        } else {
+            if (empty($this->_requestHeaders['Content-Type'])) {
+                // Add default content-type
+                $this->addHeader('Content-Type', 'application/x-www-form-urlencoded');
+            } elseif ('multipart/form-data' == $this->_requestHeaders['Content-Type']) {
+                $boundary = 'HTTP_Request_' . md5(uniqid('request') . microtime());
+                $this->addHeader('Content-Type', 'multipart/form-data; boundary=' . $boundary);
+            }
+        }
+
+        // Request Headers
+        if (!empty($this->_requestHeaders)) {
+            foreach ($this->_requestHeaders as $name => $value) {
+                $request .= $name . ': ' . $value . "\r\n";
+            }
+        }
+
+        // No post data or wrong method, so simply add a final CRLF
+        if ((HTTP_REQUEST_METHOD_POST != $this->_method && HTTP_REQUEST_METHOD_PUT != $this->_method) ||
+            (empty($this->_postData) && empty($this->_postFiles))) {
+
+            $request .= "\r\n";
+        // Post data if it's an array
+        } elseif ((!empty($this->_postData) && is_array($this->_postData)) || !empty($this->_postFiles)) {
+            // "normal" POST request
+            if (!isset($boundary)) {
+                $postdata = implode('&', array_map(
+                    create_function('$a', 'return $a[0] . \'=\' . $a[1];'), 
+                    $this->_flattenArray('', $this->_postData)
+                ));
+
+            // multipart request, probably with file uploads
+            } else {
+                $postdata = '';
+                if (!empty($this->_postData)) {
+                    $flatData = $this->_flattenArray('', $this->_postData);
+                    foreach ($flatData as $item) {
+                        $postdata .= '--' . $boundary . "\r\n";
+                        $postdata .= 'Content-Disposition: form-data; name="' . $item[0] . '"';
+                        $postdata .= "\r\n\r\n" . urldecode($item[1]) . "\r\n";
+                    }
+                }
+                foreach ($this->_postFiles as $name => $value) {
+                    if (is_array($value['name'])) {
+                        $varname       = $name . ($this->_useBrackets? '[]': '');
+                    } else {
+                        $varname       = $name;
+                        $value['name'] = array($value['name']);
+                    }
+                    foreach ($value['name'] as $key => $filename) {
+                        $fp   = fopen($filename, 'r');
+                        $data = fread($fp, filesize($filename));
+                        fclose($fp);
+                        $basename = basename($filename);
+                        $type     = is_array($value['type'])? @$value['type'][$key]: $value['type'];
+
+                        $postdata .= '--' . $boundary . "\r\n";
+                        $postdata .= 'Content-Disposition: form-data; name="' . $varname . '"; filename="' . $basename . '"';
+                        $postdata .= "\r\nContent-Type: " . $type;
+                        $postdata .= "\r\n\r\n" . $data . "\r\n";
+                    }
+                }
+                $postdata .= '--' . $boundary . "\r\n";
+            }
+            $request .= 'Content-Length: ' . strlen($postdata) . "\r\n\r\n";
+            $request .= $postdata;
+
+        // Post data if it's raw
+        } elseif(!empty($this->_postData)) {
+            $request .= 'Content-Length: ' . strlen($this->_postData) . "\r\n\r\n";
+            $request .= $this->_postData;
+        }
+        
+        return $request;
+    }
+
+   /**
+    * Helper function to change the (probably multidimensional) associative array
+    * into the simple one.
+    *
+    * @param    string  name for item
+    * @param    mixed   item's values
+    * @return   array   array with the following items: array('item name', 'item value');
+    */
+    function _flattenArray($name, $values)
+    {
+        if (!is_array($values)) {
+            return array(array($name, $values));
+        } else {
+            $ret = array();
+            foreach ($values as $k => $v) {
+                if (empty($name)) {
+                    $newName = $k;
+                } elseif ($this->_useBrackets) {
+                    $newName = $name . '[' . $k . ']';
+                } else {
+                    $newName = $name;
+                }
+                $ret = array_merge($ret, $this->_flattenArray($newName, $v));
+            }
+            return $ret;
+        }
+    }
+
+
+   /**
+    * Adds a Listener to the list of listeners that are notified of
+    * the object's events
+    * 
+    * @param    object   HTTP_Request_Listener instance to attach
+    * @return   boolean  whether the listener was successfully attached
+    * @access   public
+    */
+    function attach(&$listener)
+    {
+        if (!is_a($listener, 'HTTP_Request_Listener')) {
+            return false;
+        }
+        $this->_listeners[$listener->getId()] =& $listener;
+        return true;
+    }
+
+
+   /**
+    * Removes a Listener from the list of listeners 
+    * 
+    * @param    object   HTTP_Request_Listener instance to detach
+    * @return   boolean  whether the listener was successfully detached
+    * @access   public
+    */
+    function detach(&$listener)
+    {
+        if (!is_a($listener, 'HTTP_Request_Listener') || 
+            !isset($this->_listeners[$listener->getId()])) {
+            return false;
+        }
+        unset($this->_listeners[$listener->getId()]);
+        return true;
+    }
+
+
+   /**
+    * Notifies all registered listeners of an event.
+    * 
+    * Events sent by HTTP_Request object
+    * 'sentRequest': after the request was sent
+    * Events sent by HTTP_Response object
+    * 'gotHeaders': after receiving response headers (headers are passed in $data)
+    * 'tick': on receiving a part of response body (the part is passed in $data)
+    * 'gzTick': on receiving a gzip-encoded part of response body (ditto)
+    * 'gotBody': after receiving the response body (passes the decoded body in $data if it was gzipped)
+    * 
+    * @param    string  Event name
+    * @param    mixed   Additional data
+    * @access   private
+    */
+    function _notify($event, $data = null)
+    {
+        foreach (array_keys($this->_listeners) as $id) {
+            $this->_listeners[$id]->update($this, $event, $data);
+        }
+    }
+}
+
+
+/**
+* Response class to complement the Request class
+*/
+class HTTP_Response
+{
+    /**
+    * Socket object
+    * @var object
+    */
+    var $_sock;
+
+    /**
+    * Protocol
+    * @var string
+    */
+    var $_protocol;
+    
+    /**
+    * Return code
+    * @var string
+    */
+    var $_code;
+    
+    /**
+    * Response headers
+    * @var array
+    */
+    var $_headers;
+
+    /**
+    * Cookies set in response  
+    * @var array
+    */
+    var $_cookies;
+
+    /**
+    * Response body
+    * @var string
+    */
+    var $_body = '';
+
+   /**
+    * Used by _readChunked(): remaining length of the current chunk
+    * @var string
+    */
+    var $_chunkLength = 0;
+
+   /**
+    * Attached listeners
+    * @var array
+    */
+    var $_listeners = array();
+
+    /**
+    * Constructor
+    *
+    * @param  object Net_Socket     socket to read the response from
+    * @param  array                 listeners attached to request
+    * @return mixed PEAR Error on error, true otherwise
+    */
+    function HTTP_Response(&$sock, &$listeners)
+    {
+        $this->_sock      =& $sock;
+        $this->_listeners =& $listeners;
+    }
+
+
+   /**
+    * Processes a HTTP response
+    * 
+    * This extracts response code, headers, cookies and decodes body if it 
+    * was encoded in some way
+    *
+    * @access public
+    * @param  bool      Whether to store response body in object property, set
+    *                   this to false if downloading a LARGE file and using a Listener.
+    *                   This is assumed to be true if body is gzip-encoded.
+    * @throws PEAR_Error
+    * @return mixed     true on success, PEAR_Error in case of malformed response
+    */
+    function process($saveBody = true)
+    {
+        do {
+            $line = $this->_sock->readLine();
+            if (sscanf($line, 'HTTP/%s %s', $http_version, $returncode) != 2) {
+                return PEAR::raiseError('Malformed response.');
+            } else {
+                $this->_protocol = 'HTTP/' . $http_version;
+                $this->_code     = intval($returncode);
+            }
+            while ('' !== ($header = $this->_sock->readLine())) {
+                $this->_processHeader($header);
+            }
+        } while (100 == $this->_code);
+
+        $this->_notify('gotHeaders', $this->_headers);
+
+        // If response body is present, read it and decode
+        $chunked = isset($this->_headers['transfer-encoding']) && ('chunked' == $this->_headers['transfer-encoding']);
+        $gzipped = isset($this->_headers['content-encoding']) && ('gzip' == $this->_headers['content-encoding']);
+        $hasBody = false;
+        while (!$this->_sock->eof()) {
+            if ($chunked) {
+                $data = $this->_readChunked();
+            } else {
+                $data = $this->_sock->read(4096);
+            }
+            if ('' != $data) {
+                $hasBody = true;
+                if ($saveBody || $gzipped) {
+                    $this->_body .= $data;
+                }
+                $this->_notify($gzipped? 'gzTick': 'tick', $data);
+            }
+        }
+        if ($hasBody) {
+            // Uncompress the body if needed
+            if ($gzipped) {
+                $this->_body = gzinflate(substr($this->_body, 10));
+                $this->_notify('gotBody', $this->_body);
+            } else {
+                $this->_notify('gotBody');
+            }
+        }
+        return true;
+    }
+
+
+   /**
+    * Processes the response header
+    *
+    * @access private
+    * @param  string    HTTP header
+    */
+    function _processHeader($header)
+    {
+        list($headername, $headervalue) = explode(':', $header, 2);
+        $headername_i = strtolower($headername);
+        $headervalue  = ltrim($headervalue);
+        
+        if ('set-cookie' != $headername_i) {
+            $this->_headers[$headername]   = $headervalue;
+            $this->_headers[$headername_i] = $headervalue;
+        } else {
+            $this->_parseCookie($headervalue);
+        }
+    }
+
+
+   /**
+    * Parse a Set-Cookie header to fill $_cookies array
+    *
+    * @access private
+    * @param  string    value of Set-Cookie header
+    */
+    function _parseCookie($headervalue)
+    {
+        $cookie = array(
+            'expires' => null,
+            'domain'  => null,
+            'path'    => null,
+            'secure'  => false
+        );
+
+        // Only a name=value pair
+        if (!strpos($headervalue, ';')) {
+            $pos = strpos($headervalue, '=');
+            $cookie['name']  = trim(substr($headervalue, 0, $pos));
+            $cookie['value'] = trim(substr($headervalue, $pos + 1));
+
+        // Some optional parameters are supplied
+        } else {
+            $elements = explode(';', $headervalue);
+            $pos = strpos($elements[0], '=');
+            $cookie['name']  = trim(substr($elements[0], 0, $pos));
+            $cookie['value'] = trim(substr($elements[0], $pos + 1));
+
+            for ($i = 1; $i < count($elements); $i++) {
+                list ($elName, $elValue) = array_map('trim', explode('=', $elements[$i]));
+                $elName = strtolower($elName);
+                if ('secure' == $elName) {
+                    $cookie['secure'] = true;
+                } elseif ('expires' == $elName) {
+                    $cookie['expires'] = str_replace('"', '', $elValue);
+                } elseif ('path' == $elName || 'domain' == $elName) {
+                    $cookie[$elName] = urldecode($elValue);
+                } else {
+                    $cookie[$elName] = $elValue;
+                }
+            }
+        }
+        $this->_cookies[] = $cookie;
+    }
+
+
+   /**
+    * Read a part of response body encoded with chunked Transfer-Encoding
+    * 
+    * @access private
+    * @return string
+    */
+    function _readChunked()
+    {
+        // at start of the next chunk?
+        if (0 == $this->_chunkLength) {
+            $line = $this->_sock->readLine();
+            if (preg_match('/^([0-9a-f]+)/i', $line, $matches)) {
+                $this->_chunkLength = hexdec($matches[1]); 
+                // Chunk with zero length indicates the end
+                if (0 == $this->_chunkLength) {
+                    $this->_sock->readAll(); // make this an eof()
+                    return '';
+                }
+            }
+        }
+        $data = $this->_sock->read($this->_chunkLength);
+        $this->_chunkLength -= strlen($data);
+        if (0 == $this->_chunkLength) {
+            $this->_sock->readLine(); // Trailing CRLF
+        }
+        return $data;
+    }
+
+
+   /**
+    * Notifies all registered listeners of an event.
+    * 
+    * @param    string  Event name
+    * @param    mixed   Additional data
+    * @access   private
+    * @see HTTP_Request::_notify()
+    */
+    function _notify($event, $data = null)
+    {
+        foreach (array_keys($this->_listeners) as $id) {
+            $this->_listeners[$id]->update($this, $event, $data);
+        }
+    }
+} // End class HTTP_Response
+?>
diff --git a/bundled-libs/HTTP/Request/Listener.php b/bundled-libs/HTTP/Request/Listener.php
new file mode 100644 (file)
index 0000000..70d4731
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Copyright (c) 2002-2003, Richard Heyes                                |
+// | All rights reserved.                                                  |
+// |                                                                       |
+// | Redistribution and use in source and binary forms, with or without    |
+// | modification, are permitted provided that the following conditions    |
+// | are met:                                                              |
+// |                                                                       |
+// | o Redistributions of source code must retain the above copyright      |
+// |   notice, this list of conditions and the following disclaimer.       |
+// | o Redistributions in binary form must reproduce the above copyright   |
+// |   notice, this list of conditions and the following disclaimer in the |
+// |   documentation and/or other materials provided with the distribution.|
+// | o The names of the authors may not be used to endorse or promote      |
+// |   products derived from this software without specific prior written  |
+// |   permission.                                                         |
+// |                                                                       |
+// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
+// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
+// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
+// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
+// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
+// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
+// |                                                                       |
+// +-----------------------------------------------------------------------+
+// | Author: Alexey Borzov <avb@php.net>                                  |
+// +-----------------------------------------------------------------------+
+//
+// $Id: Listener.php,v 1.1 2004/12/06 09:18:23 nohn Exp $
+//
+
+/**
+ * This class implements the Observer part of a Subject-Observer
+ * design pattern. It listens to the events sent by a 
+ * HTTP_Request or HTTP_Response instance.
+ *
+ * @package HTTP_Request
+ * @author  Alexey Borzov <avb@php.net>
+ * @version $Revision: 1.1 $
+ */
+class HTTP_Request_Listener 
+{
+   /**
+    * A listener's identifier
+    * @var string
+    */
+    var $_id;
+
+   /**
+    * Constructor, sets the object's identifier
+    *
+    * @access public
+    */
+    function HTTP_Request_Listener()
+    {
+        $this->_id = md5(uniqid('http_request_', 1));
+    }
+
+
+   /**
+    * Returns the listener's identifier
+    *
+    * @access public
+    * @return string
+    */
+    function getId()
+    {
+        return $this->_id;
+    }
+
+
+   /**
+    * This method is called when Listener is notified of an event
+    *
+    * @access   public
+    * @param    object  an object the listener is attached to
+    * @param    string  Event name
+    * @param    mixed   Additional data
+    * @abstract
+    */
+    function update(&$subject, $event, $data = null)
+    {
+        echo "Notified of event: '$event'\n";
+        if (null !== $data) {
+            echo "Additional data: ";
+            var_dump($data);
+        }
+    }
+}
+?>
diff --git a/bundled-libs/Net/CheckIP.php b/bundled-libs/Net/CheckIP.php
new file mode 100644 (file)
index 0000000..2e3f15a
--- /dev/null
@@ -0,0 +1,75 @@
+<?php
+//
+// +----------------------------------------------------------------------+
+// | PHP Version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2002 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Martin Jansen <mj@php.net>                                  |
+// |          Guido Haeger <gh-lists@ecora.de>                            |
+// +----------------------------------------------------------------------+
+//
+// $Id: CheckIP.php,v 1.2 2004/11/19 11:05:24 garvinhicking Exp $
+
+/**
+* Class to validate the syntax of IPv4 adresses
+*
+* Usage:
+*   <?php
+*   require_once "Net/CheckIP.php";
+*     
+*   if (Net_CheckIP::check_ip("your_ip_goes_here")) {
+*       // Syntax of the IP is ok
+*   }
+*   ?>
+*
+* @author  Martin Jansen <mj@php.net>
+* @author  Guido Haeger <gh-lists@ecora.de>
+* @package Net_CheckIP
+* @version 1.1
+* @access  public
+*/
+class Net_CheckIP
+{
+
+    /**
+    * Validate the syntax of the given IP adress
+    *
+    * This function splits the IP address in 4 pieces
+    * (separated by ".") and checks for each piece
+    * if it's an integer value between 0 and 255.
+    * If all 4 parameters pass this test, the function
+    * returns true.
+    *
+    * @param  string $ip IP adress
+    * @return bool       true if syntax is valid, otherwise false
+    */
+    function check_ip($ip)
+    {
+        $oct = explode('.', $ip);
+        if (count($oct) != 4) {
+            return false;
+        }
+
+        for ($i = 0; $i < 4; $i++) {
+            if (!is_numeric($oct[$i])) {
+                return false;
+            }
+
+            if ($oct[$i] < 0 || $oct[$i] > 255) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+}
+?>
diff --git a/bundled-libs/Net/DNSBL.php b/bundled-libs/Net/DNSBL.php
new file mode 100644 (file)
index 0000000..ce6837b
--- /dev/null
@@ -0,0 +1,153 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+// +----------------------------------------------------------------------+
+// | PEAR::Net_DNSBL                                                      |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 2004 Sebastian Nohn <sebastian@nohn.net>               |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 3.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at the following url:           |
+// | http://www.php.net/license/3_0.txt.                                  |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Sebastian Nohn <sebastian@nohn.net>                         |
+// +----------------------------------------------------------------------+
+//
+// $Id: DNSBL.php,v 1.4 2004/12/02 14:23:51 nohn Exp $
+
+/**
+ * PEAR::Net_DNSBL
+ *
+ * This class acts as interface to generic Realtime Blocking Lists
+ * (RBL)
+ *
+ * Net_RBL looks up an supplied host if it's listed in 1-n supplied
+ * Blacklists
+ *
+ * @author  Sebastian Nohn <sebastian@nohn.net>
+ * @package Net_DNSBL
+ * @license http://www.php.net/license/3_0.txt
+ * @version 0.5.3
+ */
+require_once 'Net/CheckIP.php';
+
+class Net_DNSBL {
+
+    /**     
+     * Array of blacklists.
+     *
+     * Must have one or more elements.
+     *
+     * @var    array
+     * @access protected
+     */
+    var $blacklists = array('sbl-xbl.spamhaus.net',
+                            'bl.spamcop.net');
+
+    /**
+     * Set the blacklist to a desired blacklist.
+     *
+     * @param  array Array of blacklists to use. May contain only one element.
+     * @access public
+     * @return bool true if the operation was successful
+     */
+    function setBlacklists($blacklists)
+    {
+        if (is_array($blacklists)) {
+            $this->blacklists = $blacklists;
+            return true;
+        } else {
+            return false;
+        } // if
+    } // function
+
+    /**
+     * Get the blacklists.
+     *
+     * @access public
+     * @return array Currently set blacklists.
+     */
+    function getBlacklists()
+    {
+        return $this->blacklists;
+    }
+
+    /** 
+     * Checks if the supplied Host is listed in one or more of the
+     * RBLs.
+     *
+     * @param  string Host to check for being listed.
+     * @access public
+     * @return boolean true if the checked host is listed in a blacklist.
+     */
+    function isListed($host)
+    {
+        
+        $isListed = false;
+        
+        foreach ($this->blacklists as $blacklist) {
+            $result = gethostbyname($this->getHostForLookup($host, $blacklist));
+            if ($result != $this->getHostForLookup($host, $blacklist)) { 
+                $isListed = true;
+                
+                //if the Host was listed we don't need to check other RBLs,
+                break;
+                
+            } // if
+        } // foreach
+        
+        return $isListed;
+    } // function
+
+    /** 
+     * Get host to lookup. Lookup a host if neccessary and get the
+     * complete FQDN to lookup.
+     *
+     * @param  string Host OR IP to use for building the lookup.
+     * @param  string Blacklist to use for building the lookup.
+     * @access protected
+     * @return string Ready to use host to lookup
+     */    
+    function getHostForLookup($host, $blacklist) 
+    {
+        // Currently only works for v4 addresses.
+        if (!Net_CheckIP::check_ip($host)) {
+            $ip = gethostbyname($host);
+        } else {
+            $ip = $host;
+        }
+
+        return $this->buildLookUpHost($ip, $blacklist);
+    } // function
+
+    /**
+     * Build the host to lookup from an IP.
+     *
+     * @param  string IP to use for building the lookup.
+     * @param  string Blacklist to use for building the lookup.
+     * @access protected
+     * @return string Ready to use host to lookup
+     */    
+    function buildLookUpHost($ip, $blacklist)
+    {
+        return $this->reverseIp($ip).'.'.$blacklist;        
+    } // function
+
+    /**
+     * Reverse the order of an IP. 127.0.0.1 -> 1.0.0.127. Currently
+     * only works for v4-adresses
+     *
+     * @param  string IP to reverse.
+     * @access protected
+     * @return string Reversed IP
+     */    
+    function reverseIp($ip) 
+    {        
+        return implode('.', array_reverse(explode('.', $ip)));        
+    } // function
+
+} // class
+?>
\ No newline at end of file
diff --git a/bundled-libs/Net/DNSBL/SURBL.php b/bundled-libs/Net/DNSBL/SURBL.php
new file mode 100644 (file)
index 0000000..d239fd5
--- /dev/null
@@ -0,0 +1,164 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
+// +----------------------------------------------------------------------+
+// | PEAR::Net_DNSBL_SURBL                                                |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 2004 Sebastian Nohn <sebastian@nohn.net>               |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 3.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at the following url:           |
+// | http://www.php.net/license/3_0.txt.                                  |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Sebastian Nohn <sebastian@nohn.net>                         |
+// +----------------------------------------------------------------------+
+//
+// $Id: SURBL.php,v 1.4 2004/12/02 14:23:51 nohn Exp $
+
+/**
+ * PEAR::Net_DNSBL_SURBL
+ *
+ * This class acts as interface to the SURBL - Spam URI Realtime Blocklists.
+ *
+ * Services_SURBL looks up an supplied URI if it's listed in a
+ * Spam URI Realtime Blocklists.
+ *
+ * @author  Sebastian Nohn <sebastian@nohn.net>
+ * @package Net_DNSBL
+ * @license http://www.php.net/license/3_0.txt
+ * @version 0.5.4
+ */
+require_once 'Cache/Lite.php';
+require_once 'HTTP/Request.php';
+require_once 'Net/CheckIP.php';
+require_once 'Net/DNSBL.php';
+
+class Net_DNSBL_SURBL extends Net_DNSBL {
+
+    /**     
+     * Array of blacklists.
+     *
+     * Must have one or more elements.
+     *
+     * @var    string[]
+     * @access protected
+     */
+    var $blacklists = array('multi.surbl.org');
+
+    /**
+     * File containing whitelisted hosts.
+     *
+     * There are some whitelisted hosts (co.uk for example). This
+     * requires the package to not ask the domain name but the host
+     * name (spammer.co.uk instead of co.uk).
+     * 
+     * @var    string
+     * @see    $twoLevelCcTld
+     * @access protected
+     */
+    var $doubleCcTldFile = 'http://spamcheck.freeapp.net/two-level-tlds';
+
+    /**
+     * Array of whitelisted hosts.
+     *
+     * @var    array
+     * @see    $twoLevelCcTldFile
+     * @access private
+     */
+    var $twoLevelCcTld = array();
+
+    /**
+     * Check if the last two parts of the FQDN are whitelisted.
+     *
+     * @param  string Host to check if it is whitelisted
+     * @access protected
+     * @return boolean True if the host is whitelisted
+     */
+    function isDoubleCcTld($fqdn)
+    {
+        // 30 Days should be way enough
+        $options = array(
+                         'lifeTime' => '2592000',
+                         'automaticSerialization' => true
+                         );
+        $id = md5($this->doubleCcTldFile);
+
+        $cache = new Cache_Lite($options);
+        if ($data = $cache->get($id)) {
+            // Cache hit
+        } else {
+            // Cache miss
+            $http = &new HTTP_Request($this->doubleCcTldFile);
+            if (!PEAR::isError($http->sendRequest())) {
+                $data = $http->getResponseBody();
+            }
+            $data = explode("\n", $data);
+            $data = array_flip($data);
+            $cache->save($data, $id);
+        } // if 
+        if (array_key_exists($fqdn, $data)) {
+            return true;
+        } else {
+            return false;
+        } // if
+    } // function
+
+    /**
+     * Get Hostname to ask for.
+     *
+     * Performs the following steps:
+     *
+     * (1) Extract the hostname from the given URI
+     * (2) Check if the "hostname" is an ip
+     * (3a) IS_IP Reverse the IP (1.2.3.4 -> 4.3.2.1)
+     * (3b) IS_FQDN Check if is in "CC-2-level-TLD"
+     * (3b1) IS_IN_2LEVEL: we want the last three names
+     * (3b2) IS_NOT_2LEVEL: we want the last two names
+     * (4) return the FQDN to query.
+     *
+     * @param  string URL to check. 
+     * @access protected
+     * @return string Host to lookup
+     */
+    function getHostForLookup($uri, $blacklist) 
+    {
+        $host       = '';
+        // (1) Extract the hostname from the given URI
+        $parsed_uri = parse_url($uri);
+        $host       = $parsed_uri['host'];
+        // (2) Check if the "hostname" is an ip
+        if (Net_CheckIP::check_ip($host)) {
+            // (3a) IS_IP Reverse the IP (1.2.3.4 -> 4.3.2.1)
+            $host = $this->reverseIp($host);
+        } else {
+            $host_elements = explode('.', $host);
+            while (count($host_elements) > 3) {
+                array_shift($host_elements);
+            } // while
+            $host_3_elements = implode('.', $host_elements);
+
+            $host_elements = explode('.', $host);
+            while (count($host_elements) > 2) {
+                array_shift($host_elements);
+            } // while
+            $host_2_elements = implode('.', $host_elements);
+
+            // (3b) IS_FQDN Check if is in "CC-2-level-TLD"
+            if ($this->isDoubleCcTld($host_2_elements)) {
+                // (3b1) IS_IN_2LEVEL: we want the last three names
+                $host = $host_3_elements;
+            } else {
+                // (3b2) IS_NOT_2LEVEL: we want the last two names
+                $host = $host_2_elements;
+            } // if
+        } // if
+        // (4) return the FQDN to query
+        $host      .= '.'.$blacklist;
+        return $host;
+    } // function
+
+} // class
+?>
\ No newline at end of file
diff --git a/bundled-libs/Net/Socket.php b/bundled-libs/Net/Socket.php
new file mode 100644 (file)
index 0000000..9d73e06
--- /dev/null
@@ -0,0 +1,456 @@
+<?php
+//
+// +----------------------------------------------------------------------+
+// | PHP Version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Stig Bakken <ssb@php.net>                                   |
+// |          Chuck Hagenbuch <chuck@horde.org>                           |
+// +----------------------------------------------------------------------+
+//
+// $Id: Socket.php,v 1.1 2004/12/06 09:18:23 nohn Exp $
+//
+
+require_once 'PEAR.php';
+
+/**
+ * Generalized Socket class. More docs to be written.
+ *
+ * @version 1.0
+ * @author Stig Bakken <ssb@php.net>
+ * @author Chuck Hagenbuch <chuck@horde.org>
+ */
+class Net_Socket extends PEAR {
+    // {{{ properties
+
+    /** Socket file pointer. */
+    var $fp = null;
+
+    /** Whether the socket is blocking. */
+    var $blocking = true;
+
+    /** Whether the socket is persistent. */
+    var $persistent = false;
+
+    /** The IP address to connect to. */
+    var $addr = '';
+
+    /** The port number to connect to. */
+    var $port = 0;
+
+    /** Number of seconds to wait on socket connections before
+        assuming there's no more data. */
+    var $timeout = false;
+
+    /** Number of bytes to read at a time in readLine() and
+        readAll(). */
+    var $lineLength = 2048;
+    // }}}
+
+    // {{{ constructor
+    /**
+     * Constructs a new Net_Socket object.
+     *
+     * @access public
+     */
+    function Net_Socket()
+    {
+        $this->PEAR();
+    }
+    // }}}
+
+    // {{{ connect()
+    /**
+     * Connect to the specified port. If called when the socket is
+     * already connected, it disconnects and connects again.
+     *
+     * @param $addr string IP address or host name
+     * @param $port int TCP port number
+     * @param $persistent bool (optional) whether the connection is
+     *        persistent (kept open between requests by the web server)
+     * @param $timeout int (optional) how long to wait for data
+     * @param $options array see options for stream_context_create
+     * @access public
+     * @return mixed true on success or error object
+     */
+    function connect($addr, $port, $persistent = null, $timeout = null, $options = null)
+    {
+        if (is_resource($this->fp)) {
+            @fclose($this->fp);
+            $this->fp = null;
+        }
+
+        if (strspn($addr, '.0123456789') == strlen($addr)) {
+            $this->addr = $addr;
+        } else {
+            $this->addr = gethostbyname($addr);
+        }
+        $this->port = $port % 65536;
+        if ($persistent !== null) {
+            $this->persistent = $persistent;
+        }
+        if ($timeout !== null) {
+            $this->timeout = $timeout;
+        }
+        $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen';
+        $errno = 0;
+        $errstr = '';
+        if ($options && function_exists('stream_context_create')) {
+            if ($this->timeout) {
+                $timeout = $this->timeout;
+            } else {
+                $timeout = 0;
+            }
+            $context = stream_context_create($options);
+            $fp = $openfunc($this->addr, $this->port, $errno, $errstr, $timeout, $context);
+        } else {
+            if ($this->timeout) {
+                $fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $this->timeout);
+            } else {
+                $fp = @$openfunc($this->addr, $this->port, $errno, $errstr);
+            }
+        }
+
+        if (!$fp) {
+            return $this->raiseError($errstr, $errno);
+        }
+
+        $this->fp = $fp;
+
+        return $this->setBlocking($this->blocking);
+    }
+    // }}}
+
+    // {{{ disconnect()
+    /**
+     * Disconnects from the peer, closes the socket.
+     *
+     * @access public
+     * @return mixed true on success or an error object otherwise
+     */
+    function disconnect()
+    {
+        if (is_resource($this->fp)) {
+            fclose($this->fp);
+            $this->fp = null;
+            return true;
+        }
+        return $this->raiseError("not connected");
+    }
+    // }}}
+
+    // {{{ isBlocking()
+    /**
+     * Find out if the socket is in blocking mode.
+     *
+     * @access public
+     * @return bool the current blocking mode.
+     */
+    function isBlocking()
+    {
+        return $this->blocking;
+    }
+    // }}}
+
+    // {{{ setBlocking()
+    /**
+     * Sets whether the socket connection should be blocking or
+     * not. A read call to a non-blocking socket will return immediately
+     * if there is no data available, whereas it will block until there
+     * is data for blocking sockets.
+     *
+     * @param $mode bool true for blocking sockets, false for nonblocking
+     * @access public
+     * @return mixed true on success or an error object otherwise
+     */
+    function setBlocking($mode)
+    {
+        if (is_resource($this->fp)) {
+            $this->blocking = $mode;
+            socket_set_blocking($this->fp, $this->blocking);
+            return true;
+        }
+        return $this->raiseError("not connected");
+    }
+    // }}}
+
+    // {{{ setTimeout()
+    /**
+     * Sets the timeout value on socket descriptor,
+     * expressed in the sum of seconds and microseconds
+     *
+     * @param $seconds int seconds
+     * @param $microseconds int microseconds
+     * @access public
+     * @return mixed true on success or an error object otherwise
+     */
+    function setTimeout($seconds, $microseconds)
+    {
+        if (is_resource($this->fp)) {
+            socket_set_timeout($this->fp, $seconds, $microseconds);
+            return true;
+        }
+        return $this->raiseError("not connected");
+    }
+    // }}}
+
+    // {{{ getStatus()
+    /**
+     * Returns information about an existing socket resource.
+     * Currently returns four entries in the result array:
+     *
+     * <p>
+     * timed_out (bool) - The socket timed out waiting for data<br>
+     * blocked (bool) - The socket was blocked<br>
+     * eof (bool) - Indicates EOF event<br>
+     * unread_bytes (int) - Number of bytes left in the socket buffer<br>
+     * </p>
+     *
+     * @access public
+     * @return mixed Array containing information about existing socket resource or an error object otherwise
+     */
+    function getStatus()
+    {
+        if (is_resource($this->fp)) {
+            return socket_get_status($this->fp);
+        }
+        return $this->raiseError("not connected");
+    }
+    // }}}
+
+    // {{{ gets()
+    /**
+     * Get a specified line of data
+     *
+     * @access public
+     * @return $size bytes of data from the socket, or a PEAR_Error if
+     *         not connected.
+     */
+    function gets($size)
+    {
+        if (is_resource($this->fp)) {
+            return fgets($this->fp, $size);
+        }
+        return $this->raiseError("not connected");
+    }
+    // }}}
+
+    // {{{ read()
+    /**
+     * Read a specified amount of data. This is guaranteed to return,
+     * and has the added benefit of getting everything in one fread()
+     * chunk; if you know the size of the data you're getting
+     * beforehand, this is definitely the way to go.
+     *
+     * @param $size The number of bytes to read from the socket.
+     * @access public
+     * @return $size bytes of data from the socket, or a PEAR_Error if
+     *         not connected.
+     */
+    function read($size)
+    {
+        if (is_resource($this->fp)) {
+            return fread($this->fp, $size);
+        }
+        return $this->raiseError("not connected");
+    }
+    // }}}
+
+    // {{{ write()
+    /**
+     * Write a specified amount of data.
+     *
+     * @access public
+     * @return mixed true on success or an error object otherwise
+     */
+    function write($data)
+    {
+        if (is_resource($this->fp)) {
+            return fwrite($this->fp, $data);
+        }
+        return $this->raiseError("not connected");
+    }
+    // }}}
+
+    // {{{ writeLine()
+    /**
+     * Write a line of data to the socket, followed by a trailing "\r\n".
+     *
+     * @access public
+     * @return mixed fputs result, or an error
+     */
+    function writeLine ($data)
+    {
+        if (is_resource($this->fp)) {
+            return $this->write($data . "\r\n");
+        }
+        return $this->raiseError("not connected");
+    }
+    // }}}
+
+    // {{{ eof()
+    /**
+     * Tests for end-of-file on a socket descriptor
+     *
+     * @access public
+     * @return bool
+     */
+    function eof()
+    {
+        return (is_resource($this->fp) && feof($this->fp));
+    }
+    // }}}
+
+    // {{{ readByte()
+    /**
+     * Reads a byte of data
+     *
+     * @access public
+     * @return 1 byte of data from the socket, or a PEAR_Error if
+     *         not connected.
+     */
+    function readByte()
+    {
+        if (is_resource($this->fp)) {
+            return ord($this->read(1));
+        }
+        return $this->raiseError("not connected");
+    }
+    // }}}
+
+    // {{{ readWord()
+    /**
+     * Reads a word of data
+     *
+     * @access public
+     * @return 1 word of data from the socket, or a PEAR_Error if
+     *         not connected.
+     */
+    function readWord()
+    {
+        if (is_resource($this->fp)) {
+            $buf = $this->read(2);
+            return (ord($buf[0]) + (ord($buf[1]) << 8));
+        }
+        return $this->raiseError("not connected");
+    }
+    // }}}
+
+    // {{{ readInt()
+    /**
+     * Reads an int of data
+     *
+     * @access public
+     * @return 1 int of data from the socket, or a PEAR_Error if
+     *         not connected.
+     */
+    function readInt()
+    {
+        if (is_resource($this->fp)) {
+            $buf = $this->read(4);
+            return (ord($buf[0]) + (ord($buf[1]) << 8) +
+                    (ord($buf[2]) << 16) + (ord($buf[3]) << 24));
+        }
+        return $this->raiseError("not connected");
+    }
+    // }}}
+
+    // {{{ readString()
+    /**
+     * Reads a zeroterminated string of data
+     *
+     * @access public
+     * @return string, or a PEAR_Error if
+     *         not connected.
+     */
+    function readString()
+    {
+        if (is_resource($this->fp)) {
+            $string = '';
+            while (($char = $this->read(1)) != "\x00")  {
+                $string .= $char;
+            }
+            return $string;
+        }
+        return $this->raiseError("not connected");
+    }
+    // }}}
+
+    // {{{ readIPAddress()
+    /**
+     * Reads an IP Address and returns it in a dot formated string
+     *
+     * @access public
+     * @return Dot formated string, or a PEAR_Error if
+     *         not connected.
+     */
+    function readIPAddress()
+    {
+        if (is_resource($this->fp)) {
+            $buf = $this->read(4);
+            return sprintf("%s.%s.%s.%s", ord($buf[0]), ord($buf[1]),
+                           ord($buf[2]), ord($buf[3]));
+        }
+        return $this->raiseError("not connected");
+    }
+    // }}}
+
+    // {{{ readLine()
+    /**
+     * Read until either the end of the socket or a newline, whichever
+     * comes first. Strips the trailing newline from the returned data.
+     *
+     * @access public
+     * @return All available data up to a newline, without that
+     *         newline, or until the end of the socket, or a PEAR_Error if
+     *         not connected.
+     */
+    function readLine()
+    {
+        if (is_resource($this->fp)) {
+            $line = '';
+            $timeout = time() + $this->timeout;
+            while (!$this->eof() && (!$this->timeout || time() < $timeout)) {
+                $line .= $this->gets($this->lineLength);
+                if (substr($line, -2) == "\r\n" ||
+                    substr($line, -1) == "\n") {
+                    return rtrim($line, "\r\n");
+                }
+            }
+            return $line;
+        }
+        return $this->raiseError("not connected");
+    }
+    // }}}
+
+    // {{{ readAll()
+    /**
+     * Read until the socket closes. THIS FUNCTION WILL NOT EXIT if the
+     * socket is in blocking mode until the socket closes.
+     *
+     * @access public
+     * @return All data until the socket closes, or a PEAR_Error if
+     *         not connected.
+     */
+    function readAll()
+    {
+        if (is_resource($this->fp)) {
+            $data = '';
+            while (!$this->eof())
+                $data .= $this->read($this->lineLength);
+            return $data;
+        }
+        return $this->raiseError("not connected");
+    }
+    // }}}
+
+}
diff --git a/bundled-libs/Net/URL.php b/bundled-libs/Net/URL.php
new file mode 100644 (file)
index 0000000..349c59c
--- /dev/null
@@ -0,0 +1,410 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | Copyright (c) 2002-2004, Richard Heyes                                |
+// | All rights reserved.                                                  |
+// |                                                                       |
+// | Redistribution and use in source and binary forms, with or without    |
+// | modification, are permitted provided that the following conditions    |
+// | are met:                                                              |
+// |                                                                       |
+// | o Redistributions of source code must retain the above copyright      |
+// |   notice, this list of conditions and the following disclaimer.       |
+// | o Redistributions in binary form must reproduce the above copyright   |
+// |   notice, this list of conditions and the following disclaimer in the |
+// |   documentation and/or other materials provided with the distribution.|
+// | o The names of the authors may not be used to endorse or promote      |
+// |   products derived from this software without specific prior written  |
+// |   permission.                                                         |
+// |                                                                       |
+// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
+// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
+// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
+// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
+// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
+// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
+// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
+// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
+// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
+// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
+// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
+// |                                                                       |
+// +-----------------------------------------------------------------------+
+// | Author: Richard Heyes <richard at php net>                            |
+// +-----------------------------------------------------------------------+
+//
+// $Id: URL.php,v 1.1 2004/12/06 09:18:23 nohn Exp $
+//
+// Net_URL Class
+
+class Net_URL
+{
+    /**
+    * Full url
+    * @var string
+    */
+    var $url;
+
+    /**
+    * Protocol
+    * @var string
+    */
+    var $protocol;
+
+    /**
+    * Username
+    * @var string
+    */
+    var $username;
+
+    /**
+    * Password
+    * @var string
+    */
+    var $password;
+
+    /**
+    * Host
+    * @var string
+    */
+    var $host;
+
+    /**
+    * Port
+    * @var integer
+    */
+    var $port;
+
+    /**
+    * Path
+    * @var string
+    */
+    var $path;
+
+    /**
+    * Query string
+    * @var array
+    */
+    var $querystring;
+
+    /**
+    * Anchor
+    * @var string
+    */
+    var $anchor;
+
+    /**
+    * Whether to use []
+    * @var bool
+    */
+    var $useBrackets;
+
+    /**
+    * PHP4 Constructor
+    *
+    * @see __construct()
+    */
+    function Net_URL($url = null, $useBrackets = true)
+    {
+        $this->__construct($url, $useBrackets);
+    }
+
+    /**
+    * PHP5 Constructor
+    *
+    * Parses the given url and stores the various parts
+    * Defaults are used in certain cases
+    *
+    * @param string $url         Optional URL
+    * @param bool   $useBrackets Whether to use square brackets when
+    *                            multiple querystrings with the same name
+    *                            exist
+    */
+    function __construct($url = null, $useBrackets = true)
+    {
+        $HTTP_SERVER_VARS  = !empty($_SERVER) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
+
+        $this->useBrackets = $useBrackets;
+        $this->url         = $url;
+        $this->user        = '';
+        $this->pass        = '';
+        $this->host        = '';
+        $this->port        = 80;
+        $this->path        = '';
+        $this->querystring = array();
+        $this->anchor      = '';
+
+        // Only use defaults if not an absolute URL given
+        if (!preg_match('/^[a-z0-9]+:\/\//i', $url)) {
+
+            $this->protocol    = (@$HTTP_SERVER_VARS['HTTPS'] == 'on' ? 'https' : 'http');
+
+            /**
+            * Figure out host/port
+            */
+            if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) AND preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches)) {
+                $host = $matches[1];
+                if (!empty($matches[3])) {
+                    $port = $matches[3];
+                } else {
+                    $port = $this->getStandardPort($this->protocol);
+                }
+            }
+
+            $this->user        = '';
+            $this->pass        = '';
+            $this->host        = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost');
+            $this->port        = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol));
+            $this->path        = !empty($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : '/';
+            $this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null;
+            $this->anchor      = '';
+        }
+
+        // Parse the url and store the various parts
+        if (!empty($url)) {
+            $urlinfo = parse_url($url);
+
+            // Default querystring
+            $this->querystring = array();
+
+            foreach ($urlinfo as $key => $value) {
+                switch ($key) {
+                    case 'scheme':
+                        $this->protocol = $value;
+                        $this->port     = $this->getStandardPort($value);
+                        break;
+
+                    case 'user':
+                    case 'pass':
+                    case 'host':
+                    case 'port':
+                        $this->$key = $value;
+                        break;
+
+                    case 'path':
+                        if ($value{0} == '/') {
+                            $this->path = $value;
+                        } else {
+                            $path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path);
+                            $this->path = sprintf('%s/%s', $path, $value);
+                        }
+                        break;
+
+                    case 'query':
+                        $this->querystring = $this->_parseRawQueryString($value);
+                        break;
+
+                    case 'fragment':
+                        $this->anchor = $value;
+                        break;
+                }
+            }
+        }
+    }
+
+    /**
+    * Returns full url
+    *
+    * @return string Full url
+    * @access public
+    */
+    function getURL()
+    {
+        $querystring = $this->getQueryString();
+
+        $this->url = $this->protocol . '://'
+                   . $this->user . (!empty($this->pass) ? ':' : '')
+                   . $this->pass . (!empty($this->user) ? '@' : '')
+                   . $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port)
+                   . $this->path
+                   . (!empty($querystring) ? '?' . $querystring : '')
+                   . (!empty($this->anchor) ? '#' . $this->anchor : '');
+
+        return $this->url;
+    }
+
+    /**
+    * Adds a querystring item
+    *
+    * @param  string $name       Name of item
+    * @param  string $value      Value of item
+    * @param  bool   $preencoded Whether value is urlencoded or not, default = not
+    * @access public
+    */
+    function addQueryString($name, $value, $preencoded = false)
+    {
+        if ($preencoded) {
+            $this->querystring[$name] = $value;
+        } else {
+            $this->querystring[$name] = is_array($value) ? array_map('rawurlencode', $value): rawurlencode($value);
+        }
+    }
+
+    /**
+    * Removes a querystring item
+    *
+    * @param  string $name Name of item
+    * @access public
+    */
+    function removeQueryString($name)
+    {
+        if (isset($this->querystring[$name])) {
+            unset($this->querystring[$name]);
+        }
+    }
+
+    /**
+    * Sets the querystring to literally what you supply
+    *
+    * @param  string $querystring The querystring data. Should be of the format foo=bar&x=y etc
+    * @access public
+    */
+    function addRawQueryString($querystring)
+    {
+        $this->querystring = $this->_parseRawQueryString($querystring);
+    }
+
+    /**
+    * Returns flat querystring
+    *
+    * @return string Querystring
+    * @access public
+    */
+    function getQueryString()
+    {
+        if (!empty($this->querystring)) {
+            foreach ($this->querystring as $name => $value) {
+                if (is_array($value)) {
+                    foreach ($value as $k => $v) {
+                        $querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v);
+                    }
+                } elseif (!is_null($value)) {
+                    $querystring[] = $name . '=' . $value;
+                } else {
+                    $querystring[] = $name;
+                }
+            }
+            $querystring = implode(ini_get('arg_separator.output'), $querystring);
+        } else {
+            $querystring = '';
+        }
+
+        return $querystring;
+    }
+
+    /**
+    * Parses raw querystring and returns an array of it
+    *
+    * @param  string  $querystring The querystring to parse
+    * @return array                An array of the querystring data
+    * @access private
+    */
+    function _parseRawQuerystring($querystring)
+    {
+        $parts  = preg_split('/[' . preg_quote(ini_get('arg_separator.input'), '/') . ']/', $querystring, -1, PREG_SPLIT_NO_EMPTY);
+        $return = array();
+
+        foreach ($parts as $part) {
+            if (strpos($part, '=') !== false) {
+                $value = substr($part, strpos($part, '=') + 1);
+                $key   = substr($part, 0, strpos($part, '='));
+            } else {
+                $value = null;
+                $key   = $part;
+            }
+            if (substr($key, -2) == '[]') {
+                $key = substr($key, 0, -2);
+                if (@!is_array($return[$key])) {
+                    $return[$key]   = array();
+                    $return[$key][] = $value;
+                } else {
+                    $return[$key][] = $value;
+                }
+            } elseif (!$this->useBrackets AND !empty($return[$key])) {
+                $return[$key]   = (array)$return[$key];
+                $return[$key][] = $value;
+            } else {
+                $return[$key] = $value;
+            }
+        }
+
+        return $return;
+    }
+
+    /**
+    * Resolves //, ../ and ./ from a path and returns
+    * the result. Eg:
+    *
+    * /foo/bar/../boo.php    => /foo/boo.php
+    * /foo/bar/../../boo.php => /boo.php
+    * /foo/bar/.././/boo.php => /foo/boo.php
+    *
+    * This method can also be called statically.
+    *
+    * @param  string $url URL path to resolve
+    * @return string      The result
+    */
+    function resolvePath($path)
+    {
+        $path = explode('/', str_replace('//', '/', $path));
+
+        for ($i=0; $i<count($path); $i++) {
+            if ($path[$i] == '.') {
+                unset($path[$i]);
+                $path = array_values($path);
+                $i--;
+
+            } elseif ($path[$i] == '..' AND ($i > 1 OR ($i == 1 AND $path[0] != '') ) ) {
+                unset($path[$i]);
+                unset($path[$i-1]);
+                $path = array_values($path);
+                $i -= 2;
+
+            } elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') {
+                unset($path[$i]);
+                $path = array_values($path);
+                $i--;
+
+            } else {
+                continue;
+            }
+        }
+
+        return implode('/', $path);
+    }
+
+    /**
+    * Returns the standard port number for a protocol
+    *
+    * @param  string  $scheme The protocol to lookup
+    * @return integer         Port number or NULL if no scheme matches
+    *
+    * @author Philippe Jausions <Philippe.Jausions@11abacus.com>
+    */
+    function getStandardPort($scheme)
+    {
+        switch (strtolower($scheme)) {
+            case 'http':    return 80;
+            case 'https':   return 443;
+            case 'ftp':     return 21;
+            case 'imap':    return 143;
+            case 'imaps':   return 993;
+            case 'pop3':    return 110;
+            case 'pop3s':   return 995;
+            default:        return null;
+       }
+    }
+
+    /**
+    * Forces the URL to a particular protocol
+    *
+    * @param string  $protocol Protocol to force the URL to
+    * @param integer $port     Optional port (standard port is used by default)
+    */
+    function setProtocol($protocol, $port = null)
+    {
+        $this->protocol = $protocol;
+        $this->port = is_null($port) ? $this->getStandardPort() : $port;
+    }
+
+}
+?>
diff --git a/bundled-libs/Onyx/RSS.php b/bundled-libs/Onyx/RSS.php
new file mode 100644 (file)
index 0000000..7f4aeee
--- /dev/null
@@ -0,0 +1,382 @@
+<?php
+
+/* Copyright 2002-2003 Edward Swindelles (ed@readinged.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+if (!defined('ONYX_RSS_VERS'))
+{
+   define('ONYX_RSS_VERS', '1.0');
+   define('ONYX_ERR_NO_PARSER', '<a href="http://www.php.net/manual/en/ref.xml.php">PHP\'s XML Extension</a> is not loaded or available.');
+   define('ONYX_ERR_NOT_WRITEABLE', 'The specified cache directory is not writeable.');
+   define('ONYX_ERR_INVALID_URI', 'The specified file could not be opened.');
+   define('ONYX_ERR_INVALID_ITEM', 'Invalid item index specified.');
+   define('ONYX_ERR_NO_STREAM', 'Could not open the specified file.  Check the path, and make sure that you have write permissions to this file.');
+   define('ONYX_META', 'meta');
+   define('ONYX_ITEMS', 'items');
+   define('ONYX_IMAGE', 'image');
+   define('ONYX_TEXTINPUT', 'textinput');
+   define('ONYX_NAMESPACES', 'namespaces');
+   define('ONYX_CACHE_AGE', 'cache_age');
+   define('ONYX_FETCH_ASSOC', 1);
+   define('ONYX_FETCH_OBJECT', 2);
+}
+
+class ONYX_RSS
+{
+   var $parser;
+   var $conf;
+   var $rss;
+   var $data;
+   var $type;
+   /* For when PHP v.5 is released
+    * http://www.phpvolcano.com/eide/php5.php?page=variables
+    * private $parser;
+    * private $conf;
+    * private $rss;
+    * private $data;
+    * private $type;
+   */
+
+   function ONYX_RSS()
+   {
+      $this->__construct();
+   }
+
+   // Forward compatibility with PHP v.5
+   // http://www.phpvolcano.com/eide/php5.php?page=start
+   function __construct()
+   {
+      $this->conf = array();
+      $this->conf['error'] = '<br /><strong>Error on line %s of '.__FILE__.'</strong>: %s<br />';
+      $this->conf['cache_path'] = dirname(__FILE__);
+      $this->conf['cache_time'] = 180;
+      $this->conf['debug_mode'] = true;
+      $this->conf['fetch_mode'] = ONYX_FETCH_ASSOC;
+
+      if (!function_exists('xml_parser_create'))
+      {
+         $this->raiseError((__LINE__-2), ONYX_ERR_NO_PARSER);
+         return false;
+      }
+
+      $this->parser = @xml_parser_create();
+      if (!is_resource($this->parser))
+      {
+         $this->raiseError((__LINE__-3), ONYX_ERR_NO_PARSER);
+         return false;
+      }
+      xml_set_object($this->parser, $this);
+      xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, false);
+      xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, LANG_CHARSET);
+      xml_set_element_handler($this->parser, 'tag_open', 'tag_close');
+      xml_set_character_data_handler($this->parser, 'cdata');
+   }
+
+   function parse($uri, $file=false, $time=false, $local=false)
+   {
+      $this->rss = array();
+      $this->rss['cache_age'] = 0;
+      $this->rss['current_tag'] = '';
+      $this->rss['index'] = 0;
+      $this->rss['output_index'] = -1;
+      $this->data = array();
+
+      if ($file)
+      {
+         if (!is_writeable($this->conf['cache_path']))
+         {
+            $this->raiseError((__LINE__-2), ONYX_ERR_NOT_WRITEABLE);
+            return false;
+         }
+         $file = str_replace('//', '/', $this->conf['cache_path'].'/'.$file);
+         if (!$time)
+            $time = $this->conf['cache_time'];
+         $this->rss['cache_age'] = file_exists($file) ? ceil((time() - filemtime($file)) / 60) : 0;
+
+         clearstatcache();
+         if (!$local && file_exists($file))
+            if (($mod = $this->mod_time($uri)) === false)
+            {
+               $this->raiseError((__LINE__-2), ONYX_ERR_INVALID_URI);
+               return false;
+            }
+            else
+               $mod = ($mod !== 0) ? strtotime($mod) : (time()+3600);
+         elseif ($local)
+            $mod = (file_exists($file) && ($m = filemtime($uri))) ? $m : time()+3600;
+      }
+      if ( !$file ||
+           ($file && !file_exists($file)) ||
+           ($file && file_exists($file) && $time <= $this->rss['cache_age'] && $mod >= (time() - ($this->rss['cache_age'] * 60))))
+      {
+         clearstatcache();
+         if (!($fp = @fopen($uri, 'r')))
+         {
+            $this->raiseError((__LINE__-2), ONYX_ERR_INVALID_URI);
+            return false;
+         }
+         $firstchunk_read = false;
+         while ($chunk = fread($fp, 4096))
+         {
+            if (!$firstchunk_read && @preg_match('@<?xml[^>]*encoding="([^"]+)"@i', $chunk, $xml_encoding)) {
+                $this->rss['encoding'] = strtolower($xml_encoding[1]);
+            }
+            $parsedOkay = xml_parse($this->parser, $chunk, feof($fp));
+            if (!$parsedOkay && xml_get_error_code($this->parser) != XML_ERROR_NONE)
+            {
+               $this->raiseError((__LINE__-3), 'File has an XML error (<em>'.xml_error_string(xml_get_error_code($this->parser)).'</em> at line <em>'.xml_get_current_line_number($this->parser).'</em>).');
+               return false;
+            }
+            $firstchunk_read = true;
+         }
+         fclose($fp);
+         clearstatcache();
+         if ($file)
+         {
+            if (!($cache = @fopen($file, 'w')))
+            {
+               $this->raiseError((__LINE__-2), 'Could not write to cache file (<em>'.$file.'</em>).  The path may be invalid or you may not have write permissions.');
+               return false;
+            }
+            fwrite($cache, serialize($this->data));
+            fclose($cache);
+            $this->rss['cache_age'] = 0;
+         }
+      }
+      else
+      {
+         clearstatcache();
+         if (!($fp = @fopen($file, 'r')))
+         {
+            $this->raiseError((__LINE__-2), 'Could not read contents of cache file (<em>'.$cache_file.'</em>).');
+            return false;
+         }
+         $this->data = unserialize(fread($fp, filesize($file)));
+         fclose($fp);
+      }
+      return true;
+   }
+
+   function parseLocal($uri, $file=false, $time=false)
+   {
+      return $this->parse($uri, $file, $time, true);
+   }
+
+   //private function tag_open($parser, $tag, $attrs)
+   function tag_open($parser, $tag, $attrs)
+   {
+      $this->rss['current_tag'] = $tag = strtolower($tag);
+      switch ($tag)
+      {
+         case 'channel':
+         case 'image':
+         case 'textinput':
+            $this->type = $tag;
+            break;
+         case 'item':
+            $this->type = $tag;
+            $this->rss['index']++;
+            break;
+         default:
+            break;
+      }
+      if (sizeof($attrs))
+         foreach ($attrs as $k => $v)
+            if (strpos($k, 'xmlns') !== false)
+               $this->data['namespaces'][$k] = $v;
+   }
+
+   //private function tag_close($parser, $tag){}
+   function tag_close($parser, $tag){}
+
+   //private function cdata($parser, $cdata)
+   function cdata($parser, $cdata)
+   {
+      if (strlen(trim($cdata)) && $cdata != "\n")
+         switch ($this->type)
+         {
+            case 'channel':
+            case 'image':
+            case 'textinput':
+               (!isset($this->data[$this->type][$this->rss['current_tag']]) ||
+                !strlen($this->data[$this->type][$this->rss['current_tag']])) ?
+                  $this->data[$this->type][$this->rss['current_tag']] = $cdata :
+                  $this->data[$this->type][$this->rss['current_tag']].= $cdata;
+               break;
+            case 'item':
+               (!isset($this->data['items'][$this->rss['index']-1][$this->rss['current_tag']]) ||
+                !strlen($this->data['items'][$this->rss['index']-1][$this->rss['current_tag']])) ?
+                  $this->data['items'][$this->rss['index']-1][$this->rss['current_tag']] = $cdata :
+                  $this->data['items'][$this->rss['index']-1][$this->rss['current_tag']].= $cdata;
+               break;
+         }
+   }
+
+   function getData($type)
+   {
+      if ($type == ONYX_META)
+         return $this->conf['fetch_mode'] == 1 ? $this->data['channel'] : (object)$this->data['channel'];
+      if ($type == ONYX_IMAGE)
+         return $this->conf['fetch_mode'] == 1 ? $this->data['image'] : (object)$this->data['image'];
+      if ($type == ONYX_TEXTINPUT)
+         return $this->conf['fetch_mode'] == 1 ? $this->data['textinput'] : (object)$this->data['textinput'];
+      if ($type == ONYX_ITEMS)
+      {
+         if ($this->conf['fetch_mode'] == 1)
+            return $this->data['items'];
+
+         $temp = array();
+         for ($i=0; $i < sizeof($this->data['items']); $i++)
+            $temp[] = (object)$this->data['items'][$i];
+
+         return $temp;
+      }
+      if ($type == ONYX_NAMESPACES)
+         return $this->conf['fetch_mode'] == 1 ? $this->data['namespaces'] : (object)$this->data['namespaces'];
+      if ($type == ONYX_CACHE_AGE)
+         return $this->rss['cache_age'];
+
+      return false;
+   }
+
+   function numItems()
+   {
+      return sizeof($this->data['items']);
+   }
+
+   function getNextItem($max=false)
+   {
+      $type = $this->conf['fetch_mode'];
+      $this->rss['output_index']++;
+      if (($max && $this->rss['output_index'] > $max) || !isset($this->data['items'][$this->rss['output_index']]))
+         return false;
+
+      return ($type == ONYX_FETCH_ASSOC) ? $this->data['items'][$this->rss['output_index']] :
+             (($type == ONYX_FETCH_OBJECT) ? (object)$this->data['items'][$this->rss['output_index']] : false);
+   }
+
+   function itemAt($num)
+   {
+      if (!isset($this->data['items'][$num]))
+      {
+         $this->raiseError((__LINE__-3), ONYX_ERR_INVALID_ITEM);
+         return false;
+      }
+
+      $type = $this->conf['fetch_mode'];
+      return ($type == ONYX_FETCH_ASSOC) ? $this->data['items'][$num] :
+             (($type == ONYX_FETCH_OBJECT) ? (object)$this->data['items'][$num] : false);
+   }
+
+   function startBuffer($file=false)
+   {
+      $this->conf['output_file'] = $file;
+      ob_start();
+   }
+
+   function endBuffer()
+   {
+      if (!$this->conf['output_file'])
+         ob_end_flush();
+      else
+      {
+         if (!($fp = @fopen($this->conf['output_file'], 'w')))
+         {
+            $this->raiseError((__LINE__-2), ONYX_ERR_NO_STREAM);
+            ob_end_flush();
+            return;
+         }
+         fwrite($fp, ob_get_contents());
+         fclose($fp);
+         ob_end_clean();
+      }
+   }
+
+   //private function raiseError($line, $err)
+   function raiseError($line, $err)
+   {
+      if ($this->conf['debug_mode'])
+         printf($this->conf['error'], $line, $err);
+   }
+
+   function setCachePath($path)
+   {
+      $this->conf['cache_path'] = $path;
+   }
+
+   function setExpiryTime($time)
+   {
+      $this->conf['cache_time'] = $time;
+   }
+
+   function setDebugMode($state)
+   {
+      $this->conf['debug_mode'] = (bool)$state;
+   }
+
+   function setFetchMode($mode)
+   {
+      $this->conf['fetch_mode'] = $mode;
+   }
+
+   //private function mod_time($uri)
+   function mod_time($uri)
+   {
+      if (function_exists('version_compare') && version_compare(phpversion(), '4.3.0') >= 0)
+      {
+         if (!($fp = @fopen($uri, 'r')))
+            return false;
+
+         $meta = stream_get_meta_data($fp);
+         for ($j = 0; isset($meta['wrapper_data'][$j]); $j++)
+            if (strpos(strtolower($meta['wrapper_data'][$j]), 'last-modified') !== false)
+            {
+               $modtime = substr($meta['wrapper_data'][$j], 15);
+               break;
+            }
+         fclose($fp);
+      }
+      else
+      {
+         $parts = parse_url($uri);
+         $host  = $parts['host'];
+         $path  = $parts['path'];
+
+         if (!($fp = @fsockopen($host, 80)))
+            return false;
+
+         $req = "HEAD $path HTTP/1.1\r\nUser-Agent: PHP/".phpversion();
+         $req.= "\r\nHost: $host\r\nAccept: */*\r\n\r\n";
+         fputs($fp, $req);
+
+         while (!feof($fp))
+         {
+            $str = fgets($fp, 4096);
+            if (strpos(strtolower($str), 'last-modified') !== false)
+            {
+               $modtime = substr($str, 15);
+               break;
+            }
+         }
+         fclose($fp);
+      }
+      return (isset($modtime)) ? $modtime : 0;
+   }
+}
+
+
+?>
diff --git a/bundled-libs/PEAR.php b/bundled-libs/PEAR.php
new file mode 100644 (file)
index 0000000..5ed8eac
--- /dev/null
@@ -0,0 +1,956 @@
+<?php
+//
+// +----------------------------------------------------------------------+
+// | PEAR, the PHP Extension and Application Repository                   |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available at through the world-wide-web at                           |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Sterling Hughes <sterling@php.net>                          |
+// |          Stig Bakken <ssb@fast.no>                                   |
+// |          Tomas V.V.Cox <cox@idecnet.com>                             |
+// +----------------------------------------------------------------------+
+//
+// $Id: PEAR.php,v 1.1.1.1 2003/03/28 20:05:27 sterling Exp $
+//
+
+define('PEAR_ERROR_RETURN',     1);
+define('PEAR_ERROR_PRINT',      2);
+define('PEAR_ERROR_TRIGGER',    4);
+define('PEAR_ERROR_DIE',        8);
+define('PEAR_ERROR_CALLBACK',  16);
+define('PEAR_ERROR_EXCEPTION', 32);
+define('PEAR_ZE2', (function_exists('version_compare') &&
+                    version_compare(zend_version(), "2-dev", "ge")));
+
+if (substr(PHP_OS, 0, 3) == 'WIN') {
+    define('OS_WINDOWS', true);
+    define('OS_UNIX',    false);
+    define('PEAR_OS',    'Windows');
+} else {
+    define('OS_WINDOWS', false);
+    define('OS_UNIX',    true);
+    define('PEAR_OS',    'Unix'); // blatant assumption
+}
+
+$GLOBALS['_PEAR_default_error_mode']     = PEAR_ERROR_RETURN;
+$GLOBALS['_PEAR_default_error_options']  = E_USER_NOTICE;
+$GLOBALS['_PEAR_destructor_object_list'] = array();
+$GLOBALS['_PEAR_shutdown_funcs']         = array();
+$GLOBALS['_PEAR_error_handler_stack']    = array();
+
+ini_set('track_errors', true);
+
+/**
+ * Base class for other PEAR classes.  Provides rudimentary
+ * emulation of destructors.
+ *
+ * If you want a destructor in your class, inherit PEAR and make a
+ * destructor method called _yourclassname (same name as the
+ * constructor, but with a "_" prefix).  Also, in your constructor you
+ * have to call the PEAR constructor: $this->PEAR();.
+ * The destructor method will be called without parameters.  Note that
+ * at in some SAPI implementations (such as Apache), any output during
+ * the request shutdown (in which destructors are called) seems to be
+ * discarded.  If you need to get any debug information from your
+ * destructor, use error_log(), syslog() or something similar.
+ *
+ * IMPORTANT! To use the emulated destructors you need to create the
+ * objects by reference, ej: $obj =& new PEAR_child;
+ *
+ * @since PHP 4.0.2
+ * @author Stig Bakken <ssb@fast.no>
+ * @see http://pear.php.net/manual/
+ */
+class PEAR
+{
+    // {{{ properties
+
+    /**
+     * Whether to enable internal debug messages.
+     *
+     * @var     bool
+     * @access  private
+     */
+    var $_debug = false;
+
+    /**
+     * Default error mode for this object.
+     *
+     * @var     int
+     * @access  private
+     */
+    var $_default_error_mode = null;
+
+    /**
+     * Default error options used for this object when error mode
+     * is PEAR_ERROR_TRIGGER.
+     *
+     * @var     int
+     * @access  private
+     */
+    var $_default_error_options = null;
+
+    /**
+     * Default error handler (callback) for this object, if error mode is
+     * PEAR_ERROR_CALLBACK.
+     *
+     * @var     string
+     * @access  private
+     */
+    var $_default_error_handler = '';
+
+    /**
+     * Which class to use for error objects.
+     *
+     * @var     string
+     * @access  private
+     */
+    var $_error_class = 'PEAR_Error';
+
+    /**
+     * An array of expected errors.
+     *
+     * @var     array
+     * @access  private
+     */
+    var $_expected_errors = array();
+
+    // }}}
+
+    // {{{ constructor
+
+    /**
+     * Constructor.  Registers this object in
+     * $_PEAR_destructor_object_list for destructor emulation if a
+     * destructor object exists.
+     *
+     * @param string $error_class  (optional) which class to use for
+     *        error objects, defaults to PEAR_Error.
+     * @access public
+     * @return void
+     */
+    function PEAR($error_class = null)
+    {
+        $classname = get_class($this);
+        if ($this->_debug) {
+            print "PEAR constructor called, class=$classname\n";
+        }
+        if ($error_class !== null) {
+            $this->_error_class = $error_class;
+        }
+        while ($classname) {
+            $destructor = "_$classname";
+            if (method_exists($this, $destructor)) {
+                global $_PEAR_destructor_object_list;
+                $_PEAR_destructor_object_list[] = &$this;
+                break;
+            } else {
+                $classname = get_parent_class($classname);
+            }
+        }
+    }
+
+    // }}}
+    // {{{ destructor
+
+    /**
+     * Destructor (the emulated type of...).  Does nothing right now,
+     * but is included for forward compatibility, so subclass
+     * destructors should always call it.
+     *
+     * See the note in the class desciption about output from
+     * destructors.
+     *
+     * @access public
+     * @return void
+     */
+    function _PEAR() {
+        if ($this->_debug) {
+            printf("PEAR destructor called, class=%s\n", get_class($this));
+        }
+    }
+
+    // }}}
+    // {{{ getStaticProperty()
+
+    /**
+    * If you have a class that's mostly/entirely static, and you need static
+    * properties, you can use this method to simulate them. Eg. in your method(s)
+    * do this: $myVar = &PEAR::getStaticProperty('myVar');
+    * You MUST use a reference, or they will not persist!
+    *
+    * @access public
+    * @param  string $class  The calling classname, to prevent clashes
+    * @param  string $var    The variable to retrieve.
+    * @return mixed   A reference to the variable. If not set it will be
+    *                 auto initialised to NULL.
+    */
+    function &getStaticProperty($class, $var)
+    {
+        static $properties;
+        return $properties[$class][$var];
+    }
+
+    // }}}
+    // {{{ registerShutdownFunc()
+
+    /**
+    * Use this function to register a shutdown method for static
+    * classes.
+    *
+    * @access public
+    * @param  mixed $func  The function name (or array of class/method) to call
+    * @param  mixed $args  The arguments to pass to the function
+    * @return void
+    */
+    function registerShutdownFunc($func, $args = array())
+    {
+        $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
+    }
+
+    // }}}
+    // {{{ isError()
+
+    /**
+     * Tell whether a value is a PEAR error.
+     *
+     * @param   mixed $data   the value to test
+     * @param   int   $code   if $data is an error object, return true
+     *                        only if $obj->getCode() == $code
+     * @access  public
+     * @return  bool    true if parameter is an error
+     */
+    function isError($data, $code = null)
+    {
+        if (is_object($data) && (get_class($data) == 'pear_error' ||
+                                 is_subclass_of($data, 'pear_error'))) {
+            return $code === null ? true : $data->getCode() == $code;
+        }
+        return false;
+    }
+
+    // }}}
+    // {{{ setErrorHandling()
+
+    /**
+     * Sets how errors generated by this object should be handled.
+     * Can be invoked both in objects and statically.  If called
+     * statically, setErrorHandling sets the default behaviour for all
+     * PEAR objects.  If called in an object, setErrorHandling sets
+     * the default behaviour for that object.
+     *
+     * @param int $mode
+     *        One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
+     *        PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
+     *        PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
+     *
+     * @param mixed $options
+     *        When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
+     *        of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
+     *
+     *        When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
+     *        to be the callback function or method.  A callback
+     *        function is a string with the name of the function, a
+     *        callback method is an array of two elements: the element
+     *        at index 0 is the object, and the element at index 1 is
+     *        the name of the method to call in the object.
+     *
+     *        When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
+     *        a printf format string used when printing the error
+     *        message.
+     *
+     * @access public
+     * @return void
+     * @see PEAR_ERROR_RETURN
+     * @see PEAR_ERROR_PRINT
+     * @see PEAR_ERROR_TRIGGER
+     * @see PEAR_ERROR_DIE
+     * @see PEAR_ERROR_CALLBACK
+     * @see PEAR_ERROR_EXCEPTION
+     *
+     * @since PHP 4.0.5
+     */
+
+    function setErrorHandling($mode = null, $options = null)
+    {
+        if (isset($this)) {
+            $setmode     = &$this->_default_error_mode;
+            $setoptions  = &$this->_default_error_options;
+        } else {
+            $setmode     = &$GLOBALS['_PEAR_default_error_mode'];
+            $setoptions  = &$GLOBALS['_PEAR_default_error_options'];
+        }
+
+        switch ($mode) {
+            case PEAR_ERROR_RETURN:
+            case PEAR_ERROR_PRINT:
+            case PEAR_ERROR_TRIGGER:
+            case PEAR_ERROR_DIE:
+            case PEAR_ERROR_EXCEPTION:
+            case null:
+                $setmode = $mode;
+                $setoptions = $options;
+                break;
+
+            case PEAR_ERROR_CALLBACK:
+                $setmode = $mode;
+                if ((is_string($options) && function_exists($options)) ||
+                    (is_array($options) && method_exists(@$options[0], @$options[1])))
+                {
+                    $setoptions = $options;
+                } else {
+                    trigger_error("invalid error callback", E_USER_WARNING);
+                }
+                break;
+
+            default:
+                trigger_error("invalid error mode", E_USER_WARNING);
+                break;
+        }
+    }
+
+    // }}}
+    // {{{ expectError()
+
+    /**
+     * This method is used to tell which errors you expect to get.
+     * Expected errors are always returned with error mode
+     * PEAR_ERROR_RETURN.  Expected error codes are stored in a stack,
+     * and this method pushes a new element onto it.  The list of
+     * expected errors are in effect until they are popped off the
+     * stack with the popExpect() method.
+     *
+     * Note that this method can not be called statically
+     *
+     * @param mixed $code a single error code or an array of error codes to expect
+     *
+     * @return int     the new depth of the "expected errors" stack
+     * @access public
+     */
+    function expectError($code = '*')
+    {
+        if (is_array($code)) {
+            array_push($this->_expected_errors, $code);
+        } else {
+            array_push($this->_expected_errors, array($code));
+        }
+        return sizeof($this->_expected_errors);
+    }
+
+    // }}}
+    // {{{ popExpect()
+
+    /**
+     * This method pops one element off the expected error codes
+     * stack.
+     *
+     * @return array   the list of error codes that were popped
+     */
+    function popExpect()
+    {
+        return array_pop($this->_expected_errors);
+    }
+
+    // }}}
+    // {{{ _checkDelExpect()
+
+    /**
+     * This method checks unsets an error code if available
+     *
+     * @param mixed error code
+     * @return bool true if the error code was unset, false otherwise
+     * @access private
+     * @since PHP 4.3.0
+     */
+    function _checkDelExpect($error_code)
+    {
+        $deleted = false;
+
+        foreach ($this->_expected_errors AS $key => $error_array) {
+            if (in_array($error_code, $error_array)) {
+                unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
+                $deleted = true;
+            }
+
+            // clean up empty arrays
+            if (0 == count($this->_expected_errors[$key])) {
+                unset($this->_expected_errors[$key]);
+            }
+        }
+        return $deleted;
+    }
+
+    // }}}
+    // {{{ delExpect()
+
+    /**
+     * This method deletes all occurences of the specified element from
+     * the expected error codes stack.
+     *
+     * @param  mixed $error_code error code that should be deleted
+     * @return mixed list of error codes that were deleted or error
+     * @access public
+     * @since PHP 4.3.0
+     */
+    function delExpect($error_code)
+    {
+        $deleted = false;
+
+        if ((is_array($error_code) && (0 != count($error_code)))) {
+            // $error_code is a non-empty array here;
+            // we walk through it trying to unset all
+            // values
+            foreach($error_code AS $key => $error) {
+                if ($this->_checkDelExpect($error)) {
+                    $deleted =  true;
+                } else {
+                    $deleted = false;
+                }
+            }
+            return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
+        } elseif (!empty($error_code)) {
+            // $error_code comes alone, trying to unset it
+            if ($this->_checkDelExpect($error_code)) {
+                return true;
+            } else {
+                return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
+            }
+        } else {
+            // $error_code is empty
+            return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
+        }
+    }
+
+    // }}}
+    // {{{ raiseError()
+
+    /**
+     * This method is a wrapper that returns an instance of the
+     * configured error class with this object's default error
+     * handling applied.  If the $mode and $options parameters are not
+     * specified, the object's defaults are used.
+     *
+     * @param mixed $message a text error message or a PEAR error object
+     *
+     * @param int $code      a numeric error code (it is up to your class
+     *                  to define these if you want to use codes)
+     *
+     * @param int $mode      One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
+     *                  PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
+     *                  PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
+     *
+     * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
+     *                  specifies the PHP-internal error level (one of
+     *                  E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
+     *                  If $mode is PEAR_ERROR_CALLBACK, this
+     *                  parameter specifies the callback function or
+     *                  method.  In other error modes this parameter
+     *                  is ignored.
+     *
+     * @param string $userinfo If you need to pass along for example debug
+     *                  information, this parameter is meant for that.
+     *
+     * @param string $error_class The returned error object will be
+     *                  instantiated from this class, if specified.
+     *
+     * @param bool $skipmsg If true, raiseError will only pass error codes,
+     *                  the error message parameter will be dropped.
+     *
+     * @access public
+     * @return object   a PEAR error object
+     * @see PEAR::setErrorHandling
+     * @since PHP 4.0.5
+     */
+    function &raiseError($message = null,
+                         $code = null,
+                         $mode = null,
+                         $options = null,
+                         $userinfo = null,
+                         $error_class = null,
+                         $skipmsg = false)
+    {
+        // The error is yet a PEAR error object
+        if (is_object($message)) {
+            $code        = $message->getCode();
+            $userinfo    = $message->getUserInfo();
+            $error_class = $message->getType();
+            $message     = $message->getMessage();
+        }
+
+        if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) {
+            if ($exp[0] == "*" ||
+                (is_int(reset($exp)) && in_array($code, $exp)) ||
+                (is_string(reset($exp)) && in_array($message, $exp))) {
+                $mode = PEAR_ERROR_RETURN;
+            }
+        }
+        // No mode given, try global ones
+        if ($mode === null) {
+            // Class error handler
+            if (isset($this) && isset($this->_default_error_mode)) {
+                $mode    = $this->_default_error_mode;
+                $options = $this->_default_error_options;
+            // Global error handler
+            } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
+                $mode    = $GLOBALS['_PEAR_default_error_mode'];
+                $options = $GLOBALS['_PEAR_default_error_options'];
+            }
+        }
+
+        if ($error_class !== null) {
+            $ec = $error_class;
+        } elseif (isset($this) && isset($this->_error_class)) {
+            $ec = $this->_error_class;
+        } else {
+            $ec = 'PEAR_Error';
+        }
+        if ($skipmsg) {
+            return new $ec($code, $mode, $options, $userinfo);
+        } else {
+            return new $ec($message, $code, $mode, $options, $userinfo);
+        }
+    }
+
+    // }}}
+    // {{{ throwError()
+
+    /**
+     * Simpler form of raiseError with fewer options.  In most cases
+     * message, code and userinfo are enough.
+     *
+     * @param string $message
+     *
+     */
+    function &throwError($message = null,
+                         $code = null,
+                         $userinfo = null)
+    {
+        if (isset($this)) {
+            return $this->raiseError($message, $code, null, null, $userinfo);
+        } else {
+            return PEAR::raiseError($message, $code, null, null, $userinfo);
+        }
+    }
+
+    // }}}
+    // {{{ pushErrorHandling()
+
+    /**
+     * Push a new error handler on top of the error handler options stack. With this
+     * you can easily override the actual error handler for some code and restore
+     * it later with popErrorHandling.
+     *
+     * @param mixed $mode (same as setErrorHandling)
+     * @param mixed $options (same as setErrorHandling)
+     *
+     * @return bool Always true
+     *
+     * @see PEAR::setErrorHandling
+     */
+    function pushErrorHandling($mode, $options = null)
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        if (isset($this)) {
+            $def_mode    = &$this->_default_error_mode;
+            $def_options = &$this->_default_error_options;
+        } else {
+            $def_mode    = &$GLOBALS['_PEAR_default_error_mode'];
+            $def_options = &$GLOBALS['_PEAR_default_error_options'];
+        }
+        $stack[] = array($def_mode, $def_options);
+
+        if (isset($this)) {
+            $this->setErrorHandling($mode, $options);
+        } else {
+            PEAR::setErrorHandling($mode, $options);
+        }
+        $stack[] = array($mode, $options);
+        return true;
+    }
+
+    // }}}
+    // {{{ popErrorHandling()
+
+    /**
+    * Pop the last error handler used
+    *
+    * @return bool Always true
+    *
+    * @see PEAR::pushErrorHandling
+    */
+    function popErrorHandling()
+    {
+        $stack = &$GLOBALS['_PEAR_error_handler_stack'];
+        array_pop($stack);
+        list($mode, $options) = $stack[sizeof($stack) - 1];
+        array_pop($stack);
+        if (isset($this)) {
+            $this->setErrorHandling($mode, $options);
+        } else {
+            PEAR::setErrorHandling($mode, $options);
+        }
+        return true;
+    }
+
+    // }}}
+    // {{{ loadExtension()
+
+    /**
+    * OS independant PHP extension load. Remember to take care
+    * on the correct extension name for case sensitive OSes.
+    *
+    * @param string $ext The extension name
+    * @return bool Success or not on the dl() call
+    */
+    function loadExtension($ext)
+    {
+        if (!extension_loaded($ext)) {
+            if (OS_WINDOWS) {
+                $suffix = '.dll';
+            } elseif (PHP_OS == 'HP-UX') {
+                $suffix = '.sl';
+            } elseif (PHP_OS == 'AIX') {
+                $suffix = '.a';
+            } elseif (PHP_OS == 'OSX') {
+                $suffix = '.bundle';
+            } else {
+                $suffix = '.so';
+            }
+            return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
+        }
+        return true;
+    }
+
+    // }}}
+}
+
+// {{{ _PEAR_call_destructors()
+
+function _PEAR_call_destructors()
+{
+    global $_PEAR_destructor_object_list;
+    if (is_array($_PEAR_destructor_object_list) &&
+        sizeof($_PEAR_destructor_object_list))
+    {
+        reset($_PEAR_destructor_object_list);
+        while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
+            $classname = get_class($objref);
+            while ($classname) {
+                $destructor = "_$classname";
+                if (method_exists($objref, $destructor)) {
+                    $objref->$destructor();
+                    break;
+                } else {
+                    $classname = get_parent_class($classname);
+                }
+            }
+        }
+        // Empty the object list to ensure that destructors are
+        // not called more than once.
+        $_PEAR_destructor_object_list = array();
+    }
+
+    // Now call the shutdown functions
+    if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) {
+        foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
+            call_user_func_array($value[0], $value[1]);
+        }
+    }
+}
+
+// }}}
+
+class PEAR_Error
+{
+    // {{{ properties
+
+    var $error_message_prefix = '';
+    var $mode                 = PEAR_ERROR_RETURN;
+    var $level                = E_USER_NOTICE;
+    var $code                 = -1;
+    var $message              = '';
+    var $userinfo             = '';
+    var $backtrace            = null;
+
+    // }}}
+    // {{{ constructor
+
+    /**
+     * PEAR_Error constructor
+     *
+     * @param string $message  message
+     *
+     * @param int $code     (optional) error code
+     *
+     * @param int $mode     (optional) error mode, one of: PEAR_ERROR_RETURN,
+     * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
+     * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
+     *
+     * @param mixed $options   (optional) error level, _OR_ in the case of
+     * PEAR_ERROR_CALLBACK, the callback function or object/method
+     * tuple.
+     *
+     * @param string $userinfo (optional) additional user/debug info
+     *
+     * @access public
+     *
+     */
+    function PEAR_Error($message = 'unknown error', $code = null,
+                        $mode = null, $options = null, $userinfo = null)
+    {
+        if ($mode === null) {
+            $mode = PEAR_ERROR_RETURN;
+        }
+        $this->message   = $message;
+        $this->code      = $code;
+        $this->mode      = $mode;
+        $this->userinfo  = $userinfo;
+        if (function_exists("debug_backtrace")) {
+            $this->backtrace = debug_backtrace();
+        }
+        if ($mode & PEAR_ERROR_CALLBACK) {
+            $this->level = E_USER_NOTICE;
+            $this->callback = $options;
+        } else {
+            if ($options === null) {
+                $options = E_USER_NOTICE;
+            }
+            $this->level = $options;
+            $this->callback = null;
+        }
+        if ($this->mode & PEAR_ERROR_PRINT) {
+            if (is_null($options) || is_int($options)) {
+                $format = "%s";
+            } else {
+                $format = $options;
+            }
+            printf($format, $this->getMessage());
+        }
+        if ($this->mode & PEAR_ERROR_TRIGGER) {
+            trigger_error($this->getMessage(), $this->level);
+        }
+        if ($this->mode & PEAR_ERROR_DIE) {
+            $msg = $this->getMessage();
+            if (is_null($options) || is_int($options)) {
+                $format = "%s";
+                if (substr($msg, -1) != "\n") {
+                    $msg .= "\n";
+                }
+            } else {
+                $format = $options;
+            }
+            die(sprintf($format, $msg));
+        }
+        if ($this->mode & PEAR_ERROR_CALLBACK) {
+            if (is_string($this->callback) && strlen($this->callback)) {
+                call_user_func($this->callback, $this);
+            } elseif (is_array($this->callback) &&
+                      sizeof($this->callback) == 2 &&
+                      is_object($this->callback[0]) &&
+                      is_string($this->callback[1]) &&
+                      strlen($this->callback[1])) {
+                      @call_user_func($this->callback, $this);
+            }
+        }
+        if (PEAR_ZE2 && $this->mode & PEAR_ERROR_EXCEPTION) {
+            eval('throw $this;');
+        }
+    }
+
+    // }}}
+    // {{{ getMode()
+
+    /**
+     * Get the error mode from an error object.
+     *
+     * @return int error mode
+     * @access public
+     */
+    function getMode() {
+        return $this->mode;
+    }
+
+    // }}}
+    // {{{ getCallback()
+
+    /**
+     * Get the callback function/method from an error object.
+     *
+     * @return mixed callback function or object/method array
+     * @access public
+     */
+    function getCallback() {
+        return $this->callback;
+    }
+
+    // }}}
+    // {{{ getMessage()
+
+
+    /**
+     * Get the error message from an error object.
+     *
+     * @return  string  full error message
+     * @access public
+     */
+    function getMessage()
+    {
+        return ($this->error_message_prefix . $this->message);
+    }
+
+
+    // }}}
+    // {{{ getCode()
+
+    /**
+     * Get error code from an error object
+     *
+     * @return int error code
+     * @access public
+     */
+     function getCode()
+     {
+        return $this->code;
+     }
+
+    // }}}
+    // {{{ getType()
+
+    /**
+     * Get the name of this error/exception.
+     *
+     * @return string error/exception name (type)
+     * @access public
+     */
+    function getType()
+    {
+        return get_class($this);
+    }
+
+    // }}}
+    // {{{ getUserInfo()
+
+    /**
+     * Get additional user-supplied information.
+     *
+     * @return string user-supplied information
+     * @access public
+     */
+    function getUserInfo()
+    {
+        return $this->userinfo;
+    }
+
+    // }}}
+    // {{{ getDebugInfo()
+
+    /**
+     * Get additional debug information supplied by the application.
+     *
+     * @return string debug information
+     * @access public
+     */
+    function getDebugInfo()
+    {
+        return $this->getUserInfo();
+    }
+
+    // }}}
+    // {{{ getBacktrace()
+
+    /**
+     * Get the call backtrace from where the error was generated.
+     * Supported with PHP 4.3.0 or newer.
+     *
+     * @param int $frame (optional) what frame to fetch
+     * @return array Backtrace, or NULL if not available.
+     * @access public
+     */
+    function getBacktrace($frame = null)
+    {
+        if ($frame === null) {
+            return $this->backtrace;
+        }
+        return $this->backtrace[$frame];
+    }
+
+    // }}}
+    // {{{ addUserInfo()
+
+    function addUserInfo($info)
+    {
+        if (empty($this->userinfo)) {
+            $this->userinfo = $info;
+        } else {
+            $this->userinfo .= " ** $info";
+        }
+    }
+
+    // }}}
+    // {{{ toString()
+
+    /**
+     * Make a string representation of this object.
+     *
+     * @return string a string with an object summary
+     * @access public
+     */
+    function toString() {
+        $modes = array();
+        $levels = array(E_USER_NOTICE  => 'notice',
+                        E_USER_WARNING => 'warning',
+                        E_USER_ERROR   => 'error');
+        if ($this->mode & PEAR_ERROR_CALLBACK) {
+            if (is_array($this->callback)) {
+                $callback = get_class($this->callback[0]) . '::' .
+                    $this->callback[1];
+            } else {
+                $callback = $this->callback;
+            }
+            return sprintf('[%s: message="%s" code=%d mode=callback '.
+                           'callback=%s prefix="%s" info="%s"]',
+                           get_class($this), $this->message, $this->code,
+                           $callback, $this->error_message_prefix,
+                           $this->userinfo);
+        }
+        if ($this->mode & PEAR_ERROR_PRINT) {
+            $modes[] = 'print';
+        }
+        if ($this->mode & PEAR_ERROR_TRIGGER) {
+            $modes[] = 'trigger';
+        }
+        if ($this->mode & PEAR_ERROR_DIE) {
+            $modes[] = 'die';
+        }
+        if ($this->mode & PEAR_ERROR_RETURN) {
+            $modes[] = 'return';
+        }
+        return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
+                       'prefix="%s" info="%s"]',
+                       get_class($this), $this->message, $this->code,
+                       implode("|", $modes), $levels[$this->level],
+                       $this->error_message_prefix,
+                       $this->userinfo);
+    }
+
+    // }}}
+}
+
+register_shutdown_function("_PEAR_call_destructors");
+
+/*
+ * Local Variables:
+ * mode: php
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ */
+?>
diff --git a/bundled-libs/Smarty/BUGS b/bundled-libs/Smarty/BUGS
new file mode 100644 (file)
index 0000000..9f1a80f
--- /dev/null
@@ -0,0 +1,7 @@
+Smarty is supported only in PHP 4.0.6 or later.
+
+Smarty versions previous to 2.0 require the PEAR libraries. Be sure to include
+the path to the PEAR libraries in your php include_path. Config_file.class.php
+uses the PEAR library for its error handling routines. PEAR comes with the PHP
+distribution. Unix users check /usr/local/lib/php, windows users check
+C:/php/pear.
diff --git a/bundled-libs/Smarty/COPYING.lib b/bundled-libs/Smarty/COPYING.lib
new file mode 100644 (file)
index 0000000..3b20440
--- /dev/null
@@ -0,0 +1,458 @@
+                 GNU LESSER GENERAL PUBLIC LICENSE
+                      Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+                 GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                           NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
diff --git a/bundled-libs/Smarty/ChangeLog b/bundled-libs/Smarty/ChangeLog
new file mode 100644 (file)
index 0000000..2b3cf33
--- /dev/null
@@ -0,0 +1,6778 @@
+2004-09-11  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/plugins/function.debug.php:
+      removed notice from {debug}
+      thanks to Peter Billen for pointing this one out!
+
+2004-09-11  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Smarty_Compiler.class.php:
+      fix more object calling syntax issues
+
+2004-09-10  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      added $smarty->security_settings['ALLOW_CONSTANTS']
+      including test-cases for them
+
+2004-09-09  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Smarty_Compiler.class.php:
+      break down regex to digestable chunks, fix multiple param problem with
+      method calls,
+      add object method testing to unit_test cases
+
+    * libs/Smarty_Compiler.class.php:
+      update code comment with more examples
+
+    * libs/Smarty_Compiler.class.php:
+      allow objects in arbitrary param positions
+
+    * libs/Smarty_Compiler.class.php:
+      fix object parameter regex, allow one level of object indirection
+
+    * libs/Smarty_Compiler.class.php:
+      fix compile problem with numeric constants and math operator matching
+
+2004-09-07  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Config_File.class.php
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      update files to 2.6.5-dev
+
+    * (Smarty_2_6_4)
+      NEWS:
+      update NEWS file with 2.6.4 header
+
+2004-08-31  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Smarty_Compiler.class.php:
+      fix preg_quote
+
+    * libs/Smarty_Compiler.class.php:
+      fix math in object params, clean up some regex on the way, change
+      preg_ delimiters to ~ to avoid character clashes with ! and %
+
+2004-08-30  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      add $smarty.ldelim and $smarty.rdelim to smarty special var
+
+2004-08-29  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/core/core.write_file.php:
+      tempnam() seems to be borken on many installation.
+      
+      now we try tempnam first and if that fails we generate our own
+      temp-filename with uniqid()
+
+2004-08-23  Monte Ohrt  <monte@ispi.net>
+
+    * libs/plugins/modifier.capitalize.php:
+      dont use constant, use static var instead
+
+    * libs/plugins/modifier.capitalize.php:
+      implement optional param to capitalize for digit behavior
+
+    * libs/plugins/modifier.capitalize.php:
+      another commit to capitalize, taking special chars into account
+
+2004-08-23  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      cleaned up attribute-handling in Smarty_Compiler::_compile_foreach_start()
+
+2004-08-23  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/plugins/function.html_select_date.php
+      libs/plugins/modifier.capitalize.php:
+      fix capitalize modifier to not rely on buggy ucwords() func
+
+2004-08-20  Monte Ohrt  <monte@ispi.net>
+
+    * libs/plugins/function.html_select_date.php:
+      update version
+
+    * NEWS
+      libs/plugins/function.html_select_date.php:
+      make time param work with negative timestamps, force year range to include
+      given date unless explicitly set
+
+2004-08-19  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/plugins/function.fetch.php:
+      fix bug with fetch, passing user/pass in url did not work
+
+2004-08-13  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      fixed handling of {foreachelse} and {sectionelse} that got borked with
+      the latest commit (v 1.330)
+
+2004-08-12  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      fixed occasional wrong error messages on mismatched tags when
+      {else}, {elseif}, {foreachelse} or {sectionelse} is involved
+      
+      thanks to Ooypunk for pointing me on this
+
+2004-08-12  Nuno Lopes  <nunoplopes@sapo.pt>
+
+    * docs/.cvsignore
+      docs/Makefile.in
+      docs/configure.in:
+      enable russian PDF builds
+
+2004-07-30  Nuno Lopes  <nunoplopes@sapo.pt>
+
+    * docs/configure.in:
+      typo
+
+    * docs/Makefile.in
+      docs/README
+      docs/configure.in:
+      add make test_xml
+      this is usefull to detect XML problems
+
+2004-07-29  Nuno Lopes  <nunoplopes@sapo.pt>
+
+    * docs/configure.in:
+      avoid warnings in head
+
+    * docs/.cvsignore
+      docs/Makefile.in
+      docs/README
+      docs/configure.in:
+      build pdf files
+      just type make pdf
+
+2004-07-27  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      fixed handling of methods arguments.
+      
+      thanks to Manfred Wischin for finding this one and providing the
+      conceptual fix.
+
+2004-07-23  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/plugins/function.html_checkboxes.php
+      libs/plugins/function.html_radios.php:
+      there was little flaw in smarty_function_html_radios() and
+      smarty_function_html_checkboxes():
+      
+      the newly introduced assign-attribute was still added to the
+      tag-output as an extra-attribute.
+      
+      fixed.
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/core/core.load_plugins.php
+      libs/core/core.load_resource_plugin.php
+      libs/plugins/function.html_checkboxes.php
+      libs/plugins/function.html_image.php
+      libs/plugins/function.html_options.php
+      libs/plugins/function.html_radios.php
+      libs/plugins/function.html_select_date.php
+      libs/plugins/function.html_select_time.php
+      libs/plugins/modifier.date_format.php:
+      backed out renaming of _get_plugin_filepath() to get_plugin_filepath()
+      
+      we'll stick to _get_plugin_filepath() and look for a more viable
+      solution to be exposed to plugin-writers.
+
+2004-07-20  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php
+      libs/core/core.is_trusted.php
+      libs/plugins/compiler.assign.php:
+      Some fixes on PhpDocumentor comments. Thanks go to Ruben Vermeersch.
+
+2004-07-16  andreas halter  <phpcvs@andreashalter.ch>
+
+    * docs/de/bookinfo.xml
+      docs/de/getting-started.xml
+      docs/de/language-defs.ent
+      docs/de/language-snippets.ent
+      docs/de/preface.xml:
+      - updated for 2.6.3
+      - updates for new build system
+      - added missing files
+      - corrections from users
+      - revcheck comments for all files
+      - big up to didou and nuno, brilliant work
+      - make test: ok
+      - make: ok
+
+2004-07-16  Nuno Lopes  <nunoplopes@sapo.pt>
+
+    * docs/de/getting-started.xml:
+      fix the revision tracking tag
+      the revision number might not be right. just check it, please
+
+2004-07-16  andreas halter  <phpcvs@andreashalter.ch>
+
+    * docs/de/getting-started.xml:
+      - updated version (incl revcheck comment) for revcheck testing
+
+2004-07-14  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Smarty.class.php:
+      replace " with ' where literal strings are quoted (ever so slight speedup)
+
+2004-07-12  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/plugins/modifier.date_format.php:
+      changed call from $smarty->_get_plugin_filepath() to
+      $smarty->get_plugin_filepath()
+
+    * libs/plugins/function.html_checkboxes.php
+      libs/plugins/function.html_image.php
+      libs/plugins/function.html_options.php
+      libs/plugins/function.html_radios.php
+      libs/plugins/function.html_select_date.php
+      libs/plugins/function.html_select_time.php:
+      renamed calls to $smarty->_get_plugin_filepath() to
+      $smarty->get_plugin_filepath()
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/core/core.load_plugins.php
+      libs/core/core.load_resource_plugin.php:
+      renamed Smarty::_get_plugin_filepath() to Smarty::get_plugin_filepath()
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/core/core.write_compiled_include.php
+      libs/core/core.write_compiled_resource.php
+      libs/core/core.write_file.php:
+      removed touch() call. changing the timestamp of the compiled-template
+      to the source template's may be irritating for certain
+      source-code-caches. now a newly compiled template gets the current
+      time as timestamp.
+
+2004-07-02  gerald croes  <gerald@phpside.org>
+
+    * docs/fr/getting-started.xml
+      docs/fr/preface.xml:
+      Fixed missing tags to be able to make doc again
+
+    * docs/fr/preface.xml:
+      added the "is a good thing [TM]" as in en docs
+
+    * docs/fr/getting-started.xml:
+      added ctags, updated screen => programm listing.
+      added the technical note founded on the en doc
+
+2004-07-02  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/plugins/function.html_checkboxes.php
+      libs/plugins/function.html_radios.php
+      libs/plugins/function.mailto.php:
+      add assign attribute to html_checkboxes and html_radios
+
+2004-07-01  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php:
+      removed use of get_include_filepath() inside
+      get_auto_filename(). thanks go to c960657
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      enhanced error-reporting for {foreach}
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      fixed handling of digits inside tagnames. this problem slipped into
+      the regexps by adding support for numeric contants next to string
+      constants as variables.
+
+2004-06-27  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      fixed escaping of backslashes in Smarty_Compiler::_quote_replace()
+
+2004-06-23  Monte Ohrt  <monte@ispi.net>
+
+    * libs/plugins/modifier.date_format.php:
+      display date_format %e, %T and %D as expected for windows
+
+2004-06-17  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Config_File.class.php
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      changed version-number to 2.6.4-dev
+
+2004-06-16  Monte Ohrt  <monte@ispi.net>
+
+    * (Smarty_2_6_3)
+      NEWS:
+      update NEWS file with version number
+
+2004-06-09  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/plugins/modifier.escape.php:
+      added escapement of '</' to javascript escaping
+
+2004-06-08  gerald croes  <gerald@phpside.org>
+
+    * docs/fr/translation.xml:
+      Add other translators.
+
+2004-06-08  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php:
+      made the correct value of "use_sub_dirs" available to the compiler.
+      (not worth a NEWS-entry, i think)
+
+2004-06-01  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/plugins/function.fetch.php:
+      fix: proper initialistaion of $content.
+      thanks to Dmitry Koteroff for pointing this out.
+
+2004-05-29  Mehdi Achour  <didou@keliglia.com>
+
+    * docs/fr/translation.xml:
+      oups :)
+
+    * docs/fr/translation.xml:
+      added translation file
+
+2004-05-28  Nuno Lopes  <nunoplopes@sapo.pt>
+
+    * docs/Makefile.in:
+      clean also file-entities.php
+
+2004-05-28  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/plugins/function.mailto.php:
+      added obfuscation of protocol-string in {mailto} when using
+      hex-encoding (thanks to bharat)
+
+2004-05-26  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php:
+      enhanced auto-generated filenames for templates_c and cache
+      
+      incremented Smarty::_version because the tempfiles' structure changed
+      a little
+
+2004-05-23  Mehdi Achour  <didou@keliglia.com>
+
+    * docs/fr/bookinfo.xml
+      docs/fr/getting-started.xml
+      docs/fr/preface.xml:
+      WS and added revcheck
+
+2004-05-21  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      fixed typo in error-messages
+
+    * docs/de/language-snippets.ent
+      docs/fr/language-snippets.ent:
+      added empty language-snippets.ent to fix "make web"
+
+2004-05-12  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/plugins/modifier.escape.php:
+      add 'nonstd' escape modifier
+
+2004-05-07  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/plugins/block.textformat.php:
+      update textformat to not output wrap chars after last para
+
+2004-05-06  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/core/core.write_file.php:
+      use tempnam() instead of unqid() to create better temporary files in
+      smarty_core_write_file().
+      
+      (thanks to xces for finding this race-condition and his work on
+      fixing it)
+
+2004-05-04  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php:
+      added check if for file_exists() to Smarty::_read_file()
+
+2004-04-30  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/plugins/modifier.escape.php:
+      add 'mail' attribute to escape modifier
+
+2004-04-20  Mehdi Achour  <didou@keliglia.com>
+
+    * docs/manual.xml.in:
+      added the language-snippets.ent file and started using entities for notes
+      under en/programmers/api-functions
+
+2004-04-18  Mehdi Achour  <didou@keliglia.com>
+
+    * docs/de/getting-started.xml
+      docs/fr/getting-started.xml:
+      new global entity for zend and php-accelerator
+
+    * docs/fr/bookinfo.xml
+      docs/fr/getting-started.xml
+      docs/fr/preface.xml:
+      added myself as translator and added vim comments and xml tags
+
+2004-04-16  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS:
+      added entry for numeric constants
+
+    * libs/Smarty_Compiler.class.php:
+      removed unused 2nd param in call to _parse_var()
+
+    * libs/Smarty_Compiler.class.php:
+      added explanation for $this->_num_const_regexp
+
+    * NEWS
+      libs/plugins/modifier.escape.php:
+      added escape type "decentity" to smarty_modifier_escape()
+
+    * libs/Smarty_Compiler.class.php:
+      enabled numerical constants be parsed as statements.
+      (like {10} or {10|@range:12} )
+
+    * libs/Smarty_Compiler.class.php:
+      removed unused $smarty_compiler->_dvar_num_var_regexp
+
+    * libs/Smarty.class.php:
+      reverted Stuff
+
+    * libs/debug.tpl
+      libs/core/core.assemble_plugin_filepath.php
+      libs/core/core.read_cache_file.php
+      libs/core/core.write_file.php
+      libs/plugins/function.eval.php
+      libs/plugins/function.popup.php
+      libs/plugins/modifier.escape.php
+      libs/plugins/shared.make_timestamp.php:
+      reverted stuff
+
+    * libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/debug.tpl
+      libs/core/core.assemble_plugin_filepath.php
+      libs/core/core.read_cache_file.php
+      libs/core/core.write_file.php
+      libs/plugins/function.eval.php
+      libs/plugins/function.popup.php
+      libs/plugins/modifier.escape.php
+      libs/plugins/shared.make_timestamp.php:
+      Smarty_Compiler.class.php
+
+2004-04-15  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/core/core.write_compiled_include.php:
+      made smarty_core_write_compiled_include() php5-aware
+      
+      if someone knows a better way than patching the source with the
+      tokenizer, please stand up!
+
+2004-04-14  Nuno Lopes  <nunoplopes@sapo.pt>
+
+    * docs/Makefile.in:
+      remove file-entities.ent also
+
+    * docs/.cvsignore
+      docs/Makefile.in
+      docs/README:
+      allow make revcheck
+
+2004-04-13  Nuno Lopes  <nunoplopes@sapo.pt>
+
+    * docs/configure.in:
+      do not need inipath
+
+2004-04-13  Mehdi Achour  <didou@keliglia.com>
+
+    * docs/TODO:
+      done
+
+    * docs/configure.in
+      docs/manual.xml.in:
+      now the files entites are generated dynamically
+
+2004-04-12  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Config_File.class.php
+      libs/Smarty.class.php:
+      removed unused functionality to load a subset of lines from a file in
+      Smarty::_read_file()
+      
+      additionally removed a warning that is emitted since php-4.3.5 when
+      fread() is called on an empty file (with filesize()==0). thanks to
+      Andreas Streichardt who pointed this out.
+
+    * NEWS
+      libs/core/core.is_secure.php:
+      smarty_core_is_secure() only checks the file for readability now, not
+      the directory where is in.
+
+    * libs/Smarty.class.php:
+      removed unused security_setting 'ALLOW_CONSTANTS'
+
+2004-04-07  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/plugins/function.assign_debug_info.php
+      libs/plugins/function.cycle.php
+      libs/plugins/function.mailto.php:
+      removed trailing spaces
+
+    * libs/Smarty.class.php:
+      removed unused $smarty->_error_msg
+
+2004-04-04  Nuno Lopes  <nunoplopes@sapo.pt>
+
+    * docs/configure.in:
+      fixing my crap
+      put build_date back on-line
+
+2004-04-03  Nuno Lopes  <nunoplopes@sapo.pt>
+
+    * docs/Makefile.in
+      docs/configure.in
+      docs/manual.xml.in:
+      trying to fix ru problems
+
+2004-03-30  Monte Ohrt  <monte@ispi.net>
+
+    * libs/core/core.display_debug_console.php:
+      fix problem with debug_tpl path and security
+
+    * NEWS
+      libs/core/core.display_debug_console.php:
+      fix problem displaying debug console when $default_resource_type is not
+      "file:"
+
+2004-03-29  Mehdi Achour  <didou@keliglia.com>
+
+    * docs/TODO:
+      and finally, add a TODO here
+
+    * docs/de/bookinfo.xml
+      docs/de/manual.sgml
+      docs/fr/bookinfo.xml
+      docs/fr/manual.xml:
+      translate bookinfo.xml and put back the translators
+
+2004-03-28  Mehdi Achour  <didou@keliglia.com>
+
+    * docs/manual.xml.in:
+      add global.ent and define some general entities
+
+    * docs/de/bookinfo.xml
+      docs/de/getting-started.xml
+      docs/de/language-defs.ent
+      docs/de/preface.xml:
+      add new de files
+
+    * docs/de/appendixes.sgml
+      docs/de/designers.sgml
+      docs/de/getting-started.sgml
+      docs/de/html-common.dsl
+      docs/de/preface.sgml
+      docs/de/programmers.sgml:
+      drop old de files
+
+    * docs/fr/bookinfo.xml
+      docs/fr/getting-started.xml
+      docs/fr/manual.xml
+      docs/fr/preface.xml:
+      add ommited files
+
+    * docs/fr/language-defs.ent:
+      split the french dir
+
+    * docs/fr/appendixes.sgml
+      docs/fr/designers.sgml
+      docs/fr/getting-started.sgml
+      docs/fr/html-common.dsl
+      docs/fr/manual.sgml
+      docs/fr/preface.sgml
+      docs/fr/programmers.sgml:
+      drop old french files
+
+    * docs/manual.xml.in:
+      let's put the new build system
+
+2004-03-26  Mehdi Achour  <didou@keliglia.com>
+
+    * docs/de/common.dsl
+      docs/de/html.dsl
+      docs/fr/common.dsl
+      docs/fr/html.dsl
+      docs/fr/php.dsl:
+      not needed anymore
+
+2004-03-24  Nuno Lopes  <nunoplopes@sapo.pt>
+
+    * docs/Makefile.in:
+      updated stylesheets
+      highlight PHP automatically
+
+    * docs/Makefile.in
+      docs/html.dsl:
+      remove unneeded file
+
+2004-03-23  Nuno Lopes  <nunoplopes@sapo.pt>
+
+    * docs/version.ent.in:
+      remove this also
+
+    * docs/getting-started.sgml:
+      remove this one too
+
+    * docs/appendixes.sgml
+      docs/common.dsl
+      docs/designers.sgml
+      docs/html-common.dsl
+      docs/manual.sgml
+      docs/php.dsl
+      docs/preface.sgml
+      docs/programmers.sgml:
+      removing uneeded files
+
+    * docs/.cvsignore:
+      commiting missing files for docbook
+
+    * docs/.cvsignore
+      docs/Makefile.in
+      docs/configure.in
+      docs/manual.xml.in:
+      bundling docbook 4
+      now make and make web works
+
+2004-03-23  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/plugins/function.config_load.php:
+      unrolled call to the is_compiled()-check to be able to supply the
+      correct resource_base_path for config_load. this avoids errors when
+      config-files are accessed where security is enabled.
+      
+      thanks to shuther for pointing out this bug.
+
+2004-03-20  Nuno Lopes  <nunoplopes@sapo.pt>
+
+    * docs/manual.xml.in:
+      fix build date
+
+2004-03-18  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/core/core.is_secure.php:
+      removed merging of $smarty->template_dir into $smarty->secure_dir
+      
+      the resource_base_path is considerd secure instead. this change should
+      have absolutely no impact on smarty's security's behaviour
+
+2004-03-18  Nuno Lopes  <nunoplopes@sapo.pt>
+
+    * docs/configure.in:
+      correcting non-existent var
+
+    * docs/.cvsignore
+      docs/Makefile.in
+      docs/configure.in
+      docs/manual.xml.in
+      docs/version.ent.in:
+      generate build date
+
+    * docs/.cvsignore
+      docs/Makefile.in
+      docs/README
+      docs/configure.in
+      docs/manual.xml.in:
+      new build/test system
+
+2004-03-18  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php:
+      moved setting of a default resource_base_path from
+      Smarty::_parse_resource_name() to Smarty::_fetch_resource_info()
+      
+      this shouldn't affect anything, since all calls to
+      _parse_resource_name() that are not done from within
+      _fetch_resource_info() all pass their own resource_base_path
+
+2004-03-17  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php:
+      removed '.' from the list of default resource_base_paths in
+      _parse_resource_name()
+      
+      this should only affect _parse_resource_name() for templates, not for
+      php-resources and not for config_files. the latter pass two their own
+      resource_base_path.
+
+2004-03-16  Mehdi Achour  <didou@keliglia.com>
+
+    * docs/appendixes.sgml
+      docs/getting-started.sgml
+      docs/preface.sgml:
+      adding editor comments
+
+    * docs/appendixes.sgml
+      docs/getting-started.sgml:
+      cleaning words spacing, killing tabulations, using roles for
+      programlisting..
+
+2004-03-15  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php:
+      simplified Smarty::clear_all_cache();
+
+2004-03-12  boots  <jayboots@yahoo.com>
+
+    * docs/programmers.sgml:
+      Updated is_cached prototype to indicate proper return type. (thanks to
+      Geoffrey Hoffman)
+
+2004-03-11  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/core/core.assemble_plugin_filepath.php:
+      fixed little bug that prevented plugins filepaths that are found in
+      php's include_path (and not in one of the plugins_dirs) from being
+      cached in the internal plugins-filepath-cache
+
+2004-03-01  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml:
+      update include_php docs:wq
+      :q
+
+    * docs/appendixes.sgml:
+      update componentized template example to something useful
+
+2004-02-24  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php:
+      _parse_resource_name() returned true on non-existant absolute
+      paths. This caused a warning on _fetch_resource_info() when used in
+      conjunction with template_exists(). It should be fixed now without
+      negative effects.
+
+2004-02-24  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml:
+      one more typo
+
+    * docs/designers.sgml:
+      fix typo
+
+2004-02-24  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/core/core.is_secure.php:
+      smarty_resource_*_secure got &$smarty passed errornously as 3rd
+      parameter and not as 2nd. this is fixed.
+
+2004-02-23  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS:
+      fix handling of integer values like width and delay im
+      smarty_function_popup()
+
+    * libs/plugins/function.popup.php:
+      fixed handling of integer-attributes
+
+    * libs/Config_File.class.php
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      updated version to 2.6.3-dev
+
+2004-02-22  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/plugins/function.html_select_date.php:
+      removed notice on html_select_date with the month_empty-attribute
+
+    * libs/plugins/function.mailto.php:
+      removed 2 notices of undefined vars (thanks Cit)
+
+2004-02-17  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS:
+      add header
+
+    * (Smarty_2_6_2)
+      libs/Config_File.class.php
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      change some info in headers, remove fluff
+
+2004-02-13  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/plugins/function.html_select_date.php:
+      correctly handle partially empty dates (like "2004--" or "-12-").
+
+    * docs/programmers.sgml:
+      learned something about <note> and sgml and applied this to the
+      use.sub.dirs-section :)
+
+    * docs/designers.sgml:
+      changed attribute-name "checked" to "selected" in the docs for
+      html_radios and html_checkboxes. "checked" is deprecated for ages
+      AFAIK and selected is recommended for consistency with {html_options}
+
+    * docs/programmers.sgml:
+      added note about use_sub_dirs and Smarty-2.6.2 .
+      fixed markup for section about clear_compiled_tpl() .
+
+2004-02-12  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Config_File.class.php:
+      YES and NO should not be booleanized inside triple-quotes in a
+      config-file. this behaviour changed by accident in 2.6.1 and is now
+      reverted to pre-2.6.1 behaviour
+
+2004-02-10  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Config_File.class.php:
+      fixed slurping of a the next line following a triple-quoted value in a
+      config-file
+
+2004-02-07  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Config_File.class.php:
+      avoid @-operator for handling empty lines in Config_File.class.php
+
+    * libs/Smarty_Compiler.class.php:
+      removed two notices from Smarty_Compiler::_parse_is_expr()
+      (thanks shuther!)
+
+    * NEWS
+      libs/Smarty.class.php:
+      changed default for use_sub_dirs to false
+
+    * libs/plugins/function.mailto.php:
+      removed notice of undefined variable. (thanks shuther!)
+
+2004-01-29  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      added file and line-number-information to error-messages regarding
+      assigned objects an an error messages regarding modifiers with
+      security.
+
+2004-01-27  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      removed use of temporary var $_params in compiled code of block-plugins
+
+    * NEWS
+      libs/plugins/function.popup.php:
+      fixed quoting of values in smarty_function_popup()
+
+2004-01-25  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/programmers.sgml:
+      documented parameters of Smarty::clear_compiled_tpl()
+
+    * libs/Smarty_Compiler.class.php:
+      Smarty_Compiler::_syntax_error() uses Smarty::_trigger_fatal_error() now
+      instead of the trigger_error()-function
+
+    * libs/Smarty.class.php:
+      Smarty::_trigger_fatal_error() uses Smarty::trigger_error() now,
+      instead of the native trigger_error()-function
+
+    * libs/Smarty_Compiler.class.php:
+      unrecognized custom-functions trigger an error at compile now, not at
+      display-time.
+
+2004-01-23  Monte Ohrt  <monte@ispi.net>
+
+    * docs/getting-started.sgml:
+      reword a paragraph
+
+2004-01-22  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/plugins/function.config_load.php:
+      removed emission of unnecessary notices for unavailable config-files
+      in config_load()
+
+    * NEWS
+      libs/Config_File.class.php:
+      fixed handling of hidden sections in Config_File
+
+2004-01-21  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/plugins/function.config_load.php:
+      added handling of resources for {config_load}
+
+2004-01-19  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/plugins/function.html_table.php:
+      fixed bug when using arrays with tr_attr and td_attr in {html_table}
+
+2004-01-16  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS:
+      add unit testing
+
+    * NEWS
+      libs/Config_File.class.php
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      update version numbers, add initial unit test directory
+
+    * (Smarty_2_6_1)
+      libs/Config_File.class.php
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      update version numbers for 2.6.1 release
+
+2004-01-16  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * (Smarty_2_6_1)
+      NEWS
+      docs/programmers.sgml
+      libs/Smarty.class.php:
+      renamed $smarty->tpl_rror_reporting to $smarty->error_reporting
+      "tpl_" is a bit redundant here (it's a TemPLate-engine overall :)
+
+2004-01-15  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/plugins/function.html_image.php:
+      forgot to remove duplicate is_secure()-check
+
+    * NEWS
+      libs/plugins/function.html_image.php:
+      fix: $smarty->security is now correctly handled
+      
+      minor optimizations:
+         core/core.is_secure.php is only included when needed
+         $dpi_default is only determined when needed
+
+2004-01-14  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/appendixes.sgml
+      docs/programmers.sgml:
+      removed suggestions to use extract() from the manual
+
+    * docs/designers.sgml:
+      fixed typo
+
+2004-01-12  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/designers.sgml:
+      mention SCRIPT_NAME below {$smarty} reserved variable because it got
+      lost in the docs for $smarty->global_assign
+
+    * docs/designers.sgml:
+      added docs for {$smarty.version} special variable
+
+    * docs/programmers.sgml:
+      removed docs for $global_assign
+
+    * docs/programmers.sgml:
+      added docs for tpl_error_reporting
+
+    * docs/designers.sgml:
+      added docs for year_empty-, month_empty- and day_emtpy-attributes of
+      html_select_date. maybe an example is needed to better explain empty
+      values in YYY-MM-DD.
+
+2004-01-10  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      fixed handling of {php}-tags
+
+2004-01-10  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml:
+      fix html_checkboxes examples
+
+2004-01-08  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/core/core.assemble_plugin_filepath.php:
+      added caching of requested paths to smarty_core_assemble_plugin_filepath()
+
+    * NEWS:
+      fix handling of comments inside {php}- and {literal}-blocks
+
+    * libs/Smarty_Compiler.class.php:
+      fixed handling of comments inside {php} and {literal}
+
+2004-01-06  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Config_File.class.php:
+      fixed bug handling triple-quotes in config-files
+
+    * libs/Config_File.class.php:
+      fixed bugs with triple-quotes in config-files
+      thanks BRDude for finding them testing!
+
+2004-01-02  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php:
+      removed unnecessary param in call to _fetch_resource_info()
+
+2003-12-30  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php:
+      oops! removed tabs.
+
+2003-12-27  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php:
+      made $SCRIPT_NAME available again
+      changes default for request_use_auto_global to prefer autoglobals
+
+    * libs/Smarty.class.php:
+      removed tabs and trailing spaces
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      readded default_modifiers. who removed that?
+
+2003-12-23  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS:
+      add portuguese docs
+
+2003-12-22  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml:
+      fix counter example
+
+2003-12-19  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Smarty.class.php:
+      add debug console persistance feature
+
+2003-12-19  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/plugins/block.textformat.php
+      libs/plugins/function.html_table.php
+      libs/plugins/function.popup.php:
+      removed extract(). enhanced parameter parsing.
+
+    * libs/plugins/function.counter.php
+      libs/plugins/function.fetch.php
+      libs/plugins/function.popup_init.php
+      libs/plugins/modifier.capitalize.php
+      libs/plugins/modifier.cat.php
+      libs/plugins/modifier.date_format.php
+      libs/plugins/modifier.debug_print_var.php
+      libs/plugins/modifier.escape.php
+      libs/plugins/modifier.indent.php
+      libs/plugins/modifier.lower.php
+      libs/plugins/modifier.nl2br.php
+      libs/plugins/modifier.strip.php
+      libs/plugins/modifier.upper.php
+      libs/plugins/modifier.wordwrap.php
+      libs/plugins/outputfilter.trimwhitespace.php
+      libs/plugins/shared.escape_special_chars.php:
+      removed tabs. fixed indentiation.
+
+    * libs/plugins/modifier.truncate.php:
+      removed tabs
+
+    * libs/plugins/function.counter.php
+      libs/plugins/function.cycle.php:
+      removed extract() from parameter-parsing
+
+2003-12-17  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/plugins/function.html_select_date.php:
+      fix plugin-name in error message
+
+    * libs/plugins/function.html_select_time.php:
+      remove extract-call from {html_select_time}
+
+    * NEWS
+      libs/plugins/function.html_select_date.php:
+      allow single-digit days and months without smarty_make_timestamp()
+      this makes dates like "1968-11-6" work correctly since no strtotime()
+      is involved
+      
+      add warning when unknown parameter is passed
+
+2003-12-16  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php:
+      fix headers sent erroneously with cache_modified_check and fetch()
+
+2003-12-12  Monte Ohrt  <monte@ispi.net>
+
+    * libs/plugins/function.config_load.php:
+      move set_path() call below the conditional bracket
+
+    * NEWS
+      libs/plugins/function.config_load.php:
+      fix config_load filepath bug
+
+2003-12-12  boots  <jayboots@yahoo.com>
+
+    * docs/designers.sgml:
+      Updated language.function.if with additional annotation and to fix error
+      that broke docs build process
+
+2003-12-11  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      little optimization for "is odd" and "is even"
+
+2003-12-11  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      fix 'is even by' and 'is odd by' logic
+
+2003-12-11  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/designers.sgml:
+      update example-output of {mailto}
+
+    * libs/plugins/function.mailto.php:
+      removed extract-call -> cleaner parameter-handling
+
+    * libs/plugins/function.mailto.php:
+      fixed indentiation
+
+    * TODO:
+      removed two done topics
+
+2003-12-11  boots  <jayboots@yahoo.com>
+
+    * docs/designers.sgml:
+      Updated language.function.if to describe qualifiers (thanks andre)
+
+2003-12-10  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/plugins/function.html_select_date.php:
+      added day_empty, month_empty, year_empty and all_empty attributes
+      to pass an undefined date use {html_select_date time="--" ...}
+
+    * libs/plugins/function.html_select_date.php:
+      removed extract()-call
+
+    * libs/plugins/function.html_select_date.php:
+      fixed indetiation
+
+2003-12-10  boots  <jayboots@yahoo.com>
+
+    * NEWS
+      docs/designers.sgml:
+      Added table to language.function.if to describe qualifiers
+
+2003-12-09  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/plugins/function.html_checkboxes.php
+      libs/plugins/function.html_options.php:
+      strict comparason didn't work in all cases. use type-casting now.
+
+    * NEWS
+      libs/plugins/function.html_checkboxes.php
+      libs/plugins/function.html_options.php:
+      fix bug when comparing array-keys to "selected" in html_options and
+      html_checkboxes
+      
+      in_array() uses "strict" comparason now.
+
+    * libs/plugins/function.html_checkboxes.php
+      libs/plugins/function.html_options.php
+      libs/plugins/function.html_radios.php:
+      removed tabs, fixed indentiation
+
+2003-12-08  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      add better checks for correctly nested tags when compiling
+
+2003-12-04  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php
+      libs/plugins/function.html_image.php:
+      fix: check $smarty->request_use_auto_globals at the last occurences of
+           HTTP_*_VARS
+
+2003-12-03  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php:
+      remove $global_assign property from Smarty and $global_assign-handling
+      from the constructor. the only visible change is, that $SCRIPT_NAME is
+      not available in the tempates anymore. $smarty.server.SCRIPT_NAME has
+      to be used from now.
+
+2003-12-03  boots  <jayboots@yahoo.com>
+
+    * docs/designers.sgml:
+      Fixed example for count_characters
+
+2003-12-01  boots  <jayboots@yahoo.com>
+
+    * docs/designers.sgml:
+      Added section "Escaping Smarty Parsing" under Basic Syntax.
+
+2003-12-01  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/core/core.create_dir_structure.php:
+      thought again about my latest commit and backed it out.
+
+    * libs/core/core.create_dir_structure.php:
+      fix root-dir-handling on windows filepath
+
+2003-11-29  boots  <jayboots@yahoo.com>
+
+    * libs/plugins/function.config_load.php:
+      really make the fixes the last patch was supposed to do
+
+    * libs/plugins/function.config_load.php:
+      removed tabs and killed trailing white-space
+
+    * libs/plugins/function.config_load.php:
+      changed $smarty->_syntax_error to $smarty->trigger_error
+
+2003-11-27  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/plugins/modifier.debug_print_var.php:
+      remove warning in debug_print_var on php-resources
+
+    * README:
+      fix version number
+
+2003-11-26  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      raise max_level for $smarty.config... to 3 to allow arrays of config-vars
+
+2003-11-25  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php:
+      changed version-tag to indicate incompatibility to older compiled
+      templates
+
+2003-11-24  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/plugins/compiler.assign.php
+      libs/plugins/function.assign.php:
+      move function.assign.php to compiler.assign.php
+
+    * libs/core/core.get_include_path.php:
+      silence occasional warnings of open_basedir- and
+      safe_mode-restrictions in core.get_include_path.php
+
+2003-11-23  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/core/core.write_compiled_resource.php
+      libs/core/core.write_file.php:
+      avoid touch()-ing of recently unlinked files by touch()-ing the
+      tempfile before rename instead of touch()-ing the resulting file after
+      rename.
+
+    * NEWS
+      libs/Smarty.class.php:
+      add property $tpl_error_reporting
+
+2003-11-22  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/plugins/function.assign.php:
+      remove use of extract() in smarty_function_assign()
+
+    * NEWS
+      libs/Smarty.class.php:
+      remove property $undefined. "null" is used literally instead
+
+2003-11-21  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      remove two E_NOTICES
+
+2003-11-20  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Config_File.class.php
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      change version to 2.6.1-dev
+
+2003-11-19  Monte Ohrt  <monte@ispi.net>
+
+    * (Smarty_2_6_0)
+      NEWS:
+      update NEWS file
+
+    * (Smarty_2_6_0)
+      docs/designers.sgml
+      libs/Config_File.class.php
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      change version numbers to 2.6.0
+
+2003-11-19  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/designers.sgml
+      docs/de/designers.sgml
+      docs/fr/designers.sgml:
+      fix examples of escape-modifier (in docs, docs/de and docs/fr !)
+
+2003-11-18  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      move Smarty::quote_replace() to Smarty_Compiler::_quote_replace()
+
+    * libs/Smarty.class.php:
+      removed extract-calls from _include()- and _eval()-wrappers
+      variables passed with {include_php} have to accessed as members of $params
+      now
+
+2003-11-17  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/designers.sgml:
+      fixed typo
+
+2003-11-13  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Config_File.class.php:
+      fix occasional notice
+
+2003-11-13  andreas halter  <phpcvs@andreashalter.ch>
+
+    * docs/de/designers.sgml:
+      - added cat modifier, thanks messju :-)
+
+2003-11-13  Monte Ohrt  <monte@ispi.net>
+
+    * (Smarty_2_6_0-RC3)
+      NEWS
+      libs/Config_File.class.php
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      commit RC3 tags
+
+2003-11-13  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      fix handling of $var.key inside []
+
+    * libs/Smarty.class.php:
+      fix unnecessary loading of core.load_resource_plugin.php
+
+    * (Smarty_2_6_0-RC3)
+      docs/fr/designers.sgml:
+      fixed example of html_table
+
+2003-11-11  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/core/core.process_cached_inserts.php:
+      fix handling of assign inside {insert}-tags
+
+2003-11-06  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/core/core.read_cache_file.php:
+      added $exp_time-parameter
+
+    * docs/programmers.sgml:
+      added $exp_time to cache_handler_func-example
+
+    * libs/Smarty.class.php
+      libs/core/core.write_cache_file.php:
+      added $exp_time-parameter of clear_cache() and clear_all_cache() to
+      cache_handler_func.
+
+2003-11-05  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Config_File.class.php:
+      fix handling if [...] inside triple-quotes in config-files
+
+2003-11-04  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php:
+      fixed little bug in _parse_resource_name() (jlgunter, messju)
+
+2003-11-03  andreas halter  <phpcvs@andreashalter.ch>
+
+    * docs/designers.sgml
+      docs/de/designers.sgml
+      docs/fr/designers.sgml:
+      - changed Smarty.php.class occurences to Smarty.class.php
+
+2003-10-29  boots  <jayboots@yahoo.com>
+
+    * docs/appendixes.sgml
+      docs/designers.sgml
+      docs/manual.sgml
+      docs/programmers.sgml
+      docs/de/appendixes.sgml
+      docs/de/designers.sgml
+      docs/de/programmers.sgml
+      docs/fr/appendixes.sgml
+      docs/fr/designers.sgml
+      docs/fr/getting-started.sgml
+      docs/fr/manual.sgml
+      docs/fr/preface.sgml
+      docs/fr/programmers.sgml:
+      Fixes to documentation syntax so that all content can be processed used
+      xsltproc docbook-xsl tools. In particular, fixes unescaped entities,
+      broken tags, unquoted attributes.
+
+2003-10-27  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      fix handling of simple-math-operators inside modifiers
+
+2003-10-25  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      removed unused property _output_type
+      removed unused param $tag_attrs of _parse_var_props()
+      cleaned up alignment of class-properties
+
+2003-10-23  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      removed notice in php-tag handling in Smarty_Compiler::_compile_file()
+
+    * libs/Smarty_Compiler.class.php:
+      removed two occasional E_NOTICES from
+      Smarty_Compiler::_compile_include_php_tag()
+
+    * NEWS
+      libs/core/core.create_dir_structure.php:
+      fix handling of trailing-slashes in open_basedir in
+      smarty_core_create_dir_structure()
+
+2003-10-20  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      elements inside `` are bracketed now inside the compiled-tpl. this
+      fixes some issues with simple-math inside backticks.
+
+2003-10-16  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml:
+      update overlib docs, no working examples
+
+2003-10-12  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php
+      libs/core/core.is_secure.php:
+      move check for template_dir in secure_dir-array into core.is_secure.php
+      
+      this makes template_exists() work correctly with security=true even if
+      template_dir is not inside the secure_dir-array
+
+2003-10-11  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/plugins/shared.make_timestamp.php:
+      tightened check for YYYYMMDDHHMMSS-format. thanks konstantin for
+      pointing this out.
+      
+      removed a few tabs.
+
+    * libs/Smarty_Compiler.class.php:
+      fix precedence of simple-math-operators before modifiers.
+      thanks dominik!
+
+    * libs/Config_File.class.php
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/core/core.assemble_plugin_filepath.php
+      libs/core/core.assign_smarty_interface.php
+      libs/core/core.create_dir_structure.php
+      libs/core/core.display_debug_console.php
+      libs/core/core.get_include_path.php
+      libs/core/core.get_microtime.php
+      libs/core/core.get_php_resource.php
+      libs/core/core.is_secure.php
+      libs/core/core.is_trusted.php
+      libs/core/core.load_plugins.php
+      libs/core/core.load_resource_plugin.php
+      libs/core/core.process_cached_inserts.php
+      libs/core/core.process_compiled_include.php
+      libs/core/core.read_cache_file.php
+      libs/core/core.rm_auto.php
+      libs/core/core.rmdir.php
+      libs/core/core.run_insert_handler.php
+      libs/core/core.smarty_include_php.php
+      libs/core/core.write_compiled_include.php
+      libs/core/core.write_compiled_resource.php
+      libs/core/core.write_file.php:
+      removed tabs from the main and the core/*.php files
+
+2003-10-08  Monte Ohrt  <monte@ispi.net>
+
+    * (Smarty_2_6_0-RC2)
+      NEWS
+      libs/Config_File.class.php
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      update version numbers to RC2
+
+2003-09-18  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/designers.sgml
+      docs/de/designers.sgml:
+      fixed description of cycle's advance-attribute
+
+2003-09-16  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      apply modifiers only once to section-loop and foreach-from attributes
+
+2003-09-15  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/core/core.write_cache_paths_file.php:
+      backed out _smarty_cached_paths-file-handling
+
+    * libs/Smarty.class.php
+      libs/core/core.rm_auto.php:
+      fixed clear_compiled_tpl with explicit $tpl_file given
+      fixed return value of smarty_core_rm_auto() + Smarty::_unlink()
+
+    * libs/Smarty.class.php:
+      little fix in _get_auto_filename()
+
+2003-09-14  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php
+      libs/core/core.assemble_auto_filename.php:
+      removed auto-filenames from path-cache. merged assemble_auto_filename
+      back into Smarty::_get_auto_filename()
+
+2003-09-12  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      fixed quoting of modifier parameters
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/core/core.get_php_resource.php
+      libs/core/core.load_plugins.php
+      libs/core/core.load_resource_plugin.php:
+      remove Smarty::_plugin_implementation_exists() - use php's native
+      is_callable()
+
+2003-09-11  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php:
+      silenced two notices acces HTTP_SERVER_VARS
+
+2003-09-10  andreas halter  <phpcvs@andreashalter.ch>
+
+    * docs/de/designers.sgml
+      docs/de/getting-started.sgml
+      docs/de/programmers.sgml:
+      - minor fixes (2 rep), slight wording changes
+      - jade transform problem fixed
+
+2003-09-08  andreas halter  <phpcvs@andreashalter.ch>
+
+    * docs/de/designers.sgml
+      docs/de/getting-started.sgml
+      docs/de/manual.sgml
+      docs/de/preface.sgml
+      docs/de/programmers.sgml:
+      all updated for 2.6.0 release, translated everything from 2_5_0 branch to
+      20030908
+
+2003-09-04  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php:
+      proper checking for files in  _fetch_resource_info()
+
+2003-09-02  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      ignore {strip}/{/strip) inside {strip}-blocks
+
+    * libs/plugins/function.mailto.php:
+      fixed 2 notices in smarty_function_mailto()
+
+2003-09-01  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php:
+      re-include cache_paths on multiple calls to fetch() to avoid
+      inconsistencies
+      at multiple calls to fetch() in one script
+
+    * libs/Smarty_Compiler.class.php:
+      fixed handling of \r in {strip}
+      renamed $_trailing_lf to $_additional_newline
+
+    * libs/Smarty_Compiler.class.php:
+      the weekly fix for {strip} :)
+
+    * docs/designers.sgml:
+      fixed example for simple math.
+
+2003-08-29  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/core/core.assign_smarty_interface.php
+      libs/core/core.display_debug_console.php
+      libs/plugins/function.assign.php
+      libs/plugins/function.html_options.php
+      libs/plugins/function.html_table.php:
+      fixed PHPDocumentor-comments (thanks Konstantin)
+
+    * libs/core/core.rmdir.php:
+      made rmdir a bit more optimistic. especially it now removes
+      directories correctly that where created accidently by "safe_mode=On
+      && $use_sub_dirs=true"
+
+2003-08-27  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      fixed removal of leading/trailing newlines in {strip}-blocks
+
+2003-08-25  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * INSTALL:
+      added note emphasizing the introduction of "libs/" with 2.5.0
+
+    * NEWS
+      libs/plugins/modifier.escape.php:
+      fixed proper escaping of " and ' with escape:javascript
+
+2003-08-22  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/core/core.assemble_plugin_filepath.php:
+      fixed bug in traversal of $smarty->plugins_dir-array in
+      smarty_core_assemble_plugin_filepath(). the first matching plugin in
+      the path should be used, not the last one.
+
+    * libs/core/core.read_cache_file.php:
+      discard $_cache_info when the cache should be regenerated
+
+2003-08-20  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php
+      libs/plugins/block.strip.php:
+      reverted {strip} from a block-plugin back into the compiler
+
+    * docs/programmers.sgml:
+      fixed examples for register_function() and register_block()
+
+    * libs/Smarty.class.php:
+      made template_exists() quiet when the template does not exist (thanks
+      to konstatin for pointing this out)
+
+2003-08-18  Monte Ohrt  <monte@ispi.net>
+
+    * docs/getting-started.sgml:
+      fix example title
+
+    * docs/README
+      docs/getting-started.sgml:
+      change installation wording confusion
+
+2003-08-18  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php
+      libs/core/core.read_cache_file.php:
+      fixed unnecessary load of source in template_exists() and the
+      compile-check of smarty_core_read_cache_file()
+
+    * libs/Smarty_Compiler.class.php:
+      allow section-, array- and object-dereference in $smarty-references
+
+2003-08-15  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/designers.sgml:
+      added parameter-descriptions for count_characters (thanks Konstantin
+      A. Pelepelin)
+      
+      fixed docs for {html_checkboxes}
+
+2003-08-14  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php
+      libs/core/core.read_cache_file.php:
+      fixed timestamp-check of config-files in smarty_core_read_cache_file()
+
+    * libs/Smarty.class.php:
+      fixed typecasting for arrays in _parse_resource_name()
+
+    * NEWS
+      libs/plugins/function.config_load.php:
+      fixes in config_load:
+      - handling of section-attribute
+      - reusing the same config-file multiple times
+      - serialization of config-data for php<4.2.0 (no var_export)
+      
+      many thanks to atu for pointing this out and for testing
+
+2003-08-13  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php
+      libs/core/core.smarty_include_php.php:
+      fixed problem with vars as attributes in {include_php}
+
+2003-08-13  Monte Ohrt  <monte@ispi.net>
+
+    * docs/README:
+      commit README file for documentation compiling
+
+2003-08-13  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/debug.tpl
+      libs/plugins/modifier.debug_print_var.php:
+      removed '\r' from debug_print_vars' output
+      properly escape vars in javascript-version of debug.tpl
+
+2003-08-11  Monte Ohrt  <monte@ispi.net>
+
+    * (Smarty_2_6_0_RC1)
+      NEWS
+      docs/designers.sgml
+      docs/html.dsl
+      docs/php.dsl
+      libs/Config_File.class.php
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      get ready for 2.6.0-RC1 release
+
+2003-08-10  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php:
+      fixed status-header for cache_modified_check under cgi-sapi
+
+2003-08-09  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/core/core.is_secure.php
+      libs/core/core.is_trusted.php:
+      synced secure_dir-checking with trusted_dir-checking
+
+    * libs/core/core.is_secure.php:
+      tightenend path checking in smarty_core_is_secure()
+
+2003-08-08  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php:
+      fix: proper nesting of $smarty->_cache_including flag in cascaded
+      cached/not-cached/fetched/inserted/foo-templates
+
+    * libs/debug.tpl:
+      better escaping for $_debug_tpls[templates].filenames
+
+    * libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      removed redundant $smarty from Smarty::_smarty_include()
+
+    * libs/debug.tpl:
+      proper escaping of filenames in debug-console (thanks to prossel).
+
+2003-08-07  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/programmers.sgml:
+      added docs for block-methods of registered objects
+
+    * docs/programmers.sgml:
+      fixed typo in example for registered objects
+
+    * docs/designers.sgml:
+      fixed exampls of html_image and html_checkboxes
+
+    * libs/plugins/function.debug.php:
+      fixed {debug} and removed tabs in function.debug.php
+
+    * docs/programmers.sgml:
+      fixed example for register_object
+
+    * docs/designers.sgml
+      docs/programmers.sgml:
+      updated docs for capture, html_table, html_image and register_object
+
+2003-08-07  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml
+      docs/programmers.sgml:
+      add math and default_resource_type to docs
+
+    * docs/getting-started.sgml:
+      add core to example, add tech note
+
+2003-08-07  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/manual.sgml
+      docs/fr/manual.sgml:
+      upd copyright in the docs
+
+2003-08-07  Monte Ohrt  <monte@ispi.net>
+
+    * docs/getting-started.sgml:
+      added core directory to install instructions
+
+2003-08-07  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/designers.sgml
+      docs/programmers.sgml:
+      added docs for php-functions as modifiers
+
+    * libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      better caching of attributes for $cacheable=false-plugins
+
+    * docs/programmers.sgml:
+      added section "caching.cacheable" to the docs, explaining the usage of
+      the $cacheable-flag of the register_(block|compiler|function)-functions
+
+    * libs/Smarty_Compiler.class.php:
+      fixed output of custom-functions with cached attributes
+
+    * docs/programmers.sgml:
+      docs update on callbacks to the register_*-functions
+
+2003-08-06  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/core/core.process_compiled_include.php:
+      added optional parameter $cache_attrs to register_function() and
+      register_block(). $cache_attrs is an array containing attribute- names
+      that should be cached on calls to functions that have $cacheable set
+      to false.
+
+    * libs/Smarty.class.php:
+      fixed bug in _run_mod_handler
+
+    * libs/Smarty_Compiler.class.php:
+      fixed bug with autoload-handling of modifiers. thanks ándre.
+
+2003-08-05  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Config_File.class.php
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      updated copyright notice
+
+    * libs/Smarty.class.php
+      libs/core/core.load_plugins.php:
+      fixed bug that occurred when using the same not-cacheable plugin in
+      multiple includes
+
+    * docs/programmers.sgml:
+      docs-update for plugins.writing
+
+2003-08-04  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/designers.sgml
+      docs/programmers.sgml:
+      updated docs for register_block_function(), block-functions,
+      $request_use_auto_globals and html_checkboxes
+
+2003-07-31  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      enabled registration of class-methods as callbacks for the
+      register_*-functions
+      
+      use: array('classname', 'method_name')) as callback
+
+2003-07-29  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      modifiers are resolved at compile-time now. _run_mod_handler() is
+      still used for modifiers with map_array=true (== no preceeding '@')
+
+    * libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/core/core.smarty_include.php:
+      moved _smarty_include() back into Smarty.class.php
+
+    * libs/Smarty.class.php
+      libs/core/core.load_plugins.php:
+      prevent unnecessary calls to _read_file() in _is_compiled()
+      converted method-call to internal function-call in
+      smarty_core_load_plugins()
+
+2003-07-28  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      quote smarty-header properly to prevent resource-names from escaping from
+      the comment
+
+2003-07-25  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/core/core.create_dir_structure.php:
+      weakend race-condition and removed bogus error-message caused by that
+      in smarty_core_create_dir_structure().
+
+2003-07-23  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php
+      libs/core/core.display_debug_console.php
+      libs/core/core.fetch_resource_info.php
+      libs/core/core.get_php_resource.php
+      libs/core/core.parse_resource_name.php
+      libs/core/core.process_cached_inserts.php
+      libs/core/core.read_cache_file.php
+      libs/core/core.run_insert_handler.php
+      libs/core/core.smarty_include.php
+      libs/core/core.smarty_include_php.php
+      libs/plugins/function.eval.php:
+      moved  _fetch_resource_info and _parse_resource_name back into
+      Smarty.class.php
+      renamed smarty_include and smarty_eval wrappers to _include and _eval
+
+2003-07-17  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/core/core.process_compiled_include.php
+      libs/core/core.read_cache_file.php:
+      improved checking of compiled_include against cached-template with
+      non-cached-chunks
+
+    * libs/core/core.write_compiled_include.php:
+      fixed too short open-tag
+
+    * libs/plugins/function.eval.php:
+      fixed assign parameter for eval (must have gotton lost on its way to 2.5.0)
+      cleaned up indentiation
+
+2003-07-03  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      resurrected $foo->$bar syntax
+
+    * libs/Smarty_Compiler.class.php:
+      i'm so stupid. kick me.
+
+    * libs/Smarty_Compiler.class.php:
+      fixed initialisation of $this->_plugins in compile_block_tag()
+
+2003-07-03  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Config_File.class.php:
+      add preg_quote delimiter
+
+2003-07-03  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      applied fix for {$var1->p1|modifier:$var2->p2}-syntax - thanks Dominik
+
+2003-07-02  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      fixed duplicate generation of arg-list in _compile_block_tag()
+
+    * libs/Smarty_Compiler.class.php:
+      fixed off-by-one-error in nocache-tag-handling
+
+2003-06-30  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      backed out errornously committed support for $foo->$bar
+
+    * libs/core/core.write_file.php:
+      fixed indentiation, silenced occasional warning
+
+    * libs/plugins/function.html_image.php:
+      match first character of file-attribute against "/" instead of
+      DIRECTORY_SEPARATOR since it is a url-path and not a file-path.
+
+    * libs/Smarty_Compiler.class.php
+      libs/core/core.write_file.php
+      libs/plugins/function.html_image.php:
+      libs/plugins/function.html_image.php
+
+    * libs/Smarty_Compiler.class.php:
+      re-fixed cacheable_state-handling
+
+    * libs/core/core.display_debug_console.php
+      libs/core/core.process_cached_inserts.php
+      libs/core/core.process_compiled_include.php
+      libs/core/core.run_insert_handler.php:
+      extincting $this out of smarty_core_*-functions
+
+    * libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      fixed handling of nocache-state
+
+2003-06-29  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php
+      libs/core/core.smarty_include.php
+      libs/core/core.smarty_include_php.php
+      libs/plugins/function.eval.php:
+      removed $this from smarty_include and smarty_include_php
+      added cleaner handling of $this to {eval}
+
+    * libs/core/core.load_resource_plugin.php:
+      fixed inlude_once-call
+
+    * docs/de/designers.sgml
+      docs/fr/designers.sgml:
+      fixed examples of html_radios and html_checkboxes in german and french docs
+
+2003-06-25  Monte Ohrt  <monte@ispi.net>
+
+    * libs/core/core.assemble_auto_filename.php
+      libs/core/core.write_cache_paths_file.php:
+      fix typo, fix write_cache_paths logic
+
+    * libs/Smarty.class.php
+      libs/core/core.assemble_auto_filename.php:
+      fix SMARTY_COMPILE_DIR_SEP problem, make local var
+
+2003-06-24  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Smarty.class.php
+      libs/core/core.assemble_auto_filename.php
+      libs/core/core.write_cache_paths_file.php:
+      fixed cache_paths bug, simplified filename assembly logic
+
+2003-06-24  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/plugins/function.html_image.php:
+      added parsing of forgotton param "basedir"
+
+    * libs/Smarty_Compiler.class.php:
+      fixed $smarty.get-reference
+
+    * libs/plugins/block.textformat.php:
+      removed warning
+
+    * libs/Smarty_Compiler.class.php:
+      fixed value of _cacheable_state on compiler-startup
+
+2003-06-23  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/core/core.write_cache_paths_file.php:
+      make cache_path per resource, fix a couple directory path issues
+
+2003-06-23  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      removed warning when compiling empty template
+
+    * libs/core/core.write_compiled_include.php:
+      fixed bug in write_compiled_include
+
+    * libs/core/core.assemble_plugin_filepath.php:
+      fixed warning
+
+2003-06-22  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/plugins/function.eval.php:
+      fixed propagation of $this into evald code in smarty_function_eval()
+
+    * libs/core/core.write_cache_paths_file.php
+      libs/core/core.write_compiled_include.php:
+      fix in compiled-include-handling
+
+    * libs/core/core.assemble_auto_filename.php
+      libs/core/core.assemble_plugin_filepath.php
+      libs/core/core.assign_smarty_interface.php
+      libs/core/core.create_dir_structure.php
+      libs/core/core.fetch_resource_info.php
+      libs/core/core.get_include_path.php
+      libs/core/core.get_microtime.php
+      libs/core/core.get_php_resource.php
+      libs/core/core.is_secure.php
+      libs/core/core.is_trusted.php
+      libs/core/core.load_plugins.php
+      libs/core/core.load_resource_plugin.php
+      libs/core/core.parse_resource_name.php
+      libs/core/core.read_cache_file.php
+      libs/core/core.rm_auto.php
+      libs/core/core.rmdir.php
+      libs/core/core.write_cache_file.php
+      libs/core/core.write_cache_paths_file.php
+      libs/core/core.write_compiled_include.php
+      libs/core/core.write_compiled_resource.php
+      libs/core/core.write_file.php
+      libs/plugins/modifier.date_format.php:
+      started moving from $this to $smarty in core.*.php
+
+2003-06-21  Monte Ohrt  <monte@ispi.net>
+
+    * libs/core/core.create_dir_structure.php
+      libs/core/core.write_file.php
+      libs/plugins/function.config_load.php:
+      fix more dir paths
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/core/core.assemble_auto_filename.php
+      libs/core/core.assemble_plugin_filepath.php
+      libs/core/core.fetch_resource_info.php
+      libs/core/core.get_php_resource.php
+      libs/core/core.parse_resource_name.php
+      libs/core/core.process_cached_inserts.php
+      libs/core/core.read_cache_file.php
+      libs/core/core.rm_auto.php
+      libs/core/core.rmdir.php
+      libs/core/core.run_insert_handler.php
+      libs/core/core.smarty_include.php
+      libs/core/core.smarty_include_php.php
+      libs/core/core.write_cache_file.php
+      libs/core/core.write_cache_paths_file.php
+      libs/core/core.write_compiled_include.php
+      libs/core/core.write_compiled_resource.php
+      libs/core/core.write_file.php
+      libs/plugins/function.config_load.php
+      libs/plugins/function.fetch.php
+      libs/plugins/function.html_image.php:
+      fix filepaths to core files to use DIRECTORY_SEPARATOR
+
+2003-06-21  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      fixed {plugin|modifier} syntax
+
+    * libs/Smarty.class.php
+      libs/core/core.write_compiled_include.php:
+      fixed compiled include handling
+
+2003-06-21  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/core/core.assemble_auto_filename.php
+      libs/core/core.assemble_plugin_filepath.php
+      libs/core/core.write_cache_paths_file.php:
+      added filepath caching
+
+2003-06-20  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Smarty_Compiler.class.php:
+      update more varnames
+
+    * libs/Smarty.class.php
+      libs/core/core.display_debug_console.php
+      libs/core/core.fetch_file_info.php
+      libs/core/core.fetch_resource_info.php
+      libs/core/core.get_php_resource.php
+      libs/core/core.parse_file_path.php
+      libs/core/core.parse_resource_name.php
+      libs/core/core.process_cached_inserts.php
+      libs/core/core.read_cache_file.php
+      libs/core/core.run_insert_handler.php
+      libs/core/core.smarty_include.php
+      libs/core/core.smarty_include_php.php
+      libs/core/core.write_compiled_resource.php
+      libs/core/core.write_compiled_template.php
+      libs/plugins/function.config_load.php:
+      refactored var naming to better reflect "resource" instead of "file" where
+      appropriate
+
+2003-06-19  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php:
+      updated version-number to 2.5.0-cvs
+
+    * libs/core/core.write_cache_file.php:
+      omit is-cache_dir-writable-check if a cache_handler_function is in use
+
+    * libs/core/core.smarty_include_php.php:
+      fixed comments in smarty_include_php
+
+2003-06-19  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/core/core.display_debug_console.php
+      libs/core/core.smarty_include.php
+      libs/plugins/function.eval.php:
+      split up _compile_template to _compile_file and _compile_source, fix eval
+      function
+      VS: ----------------------------------------------------------------------
+
+    * libs/plugins/function.config_load.php:
+      fix logic for _is_compiled()
+
+2003-06-19  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      added optional assign-attribute to {capture}-tag
+
+    * NEWS
+      libs/Smarty.class.php:
+      added $cacheable-parameter to register_compiler_function()
+
+2003-06-18  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/core/core.load_plugins.php
+      libs/core/core.process_compiled_include.php
+      libs/core/core.read_cache_file.php
+      libs/core/core.write_cache_file.php
+      libs/core/core.write_compiled_include.php:
+      added $cacheable-parameter to register_function() and register_block()
+
+    * libs/Smarty.class.php:
+      append '.php' to all compiled templates regardless of the settings of
+      $use_sub_dirs
+
+    * libs/Smarty.class.php
+      libs/core/core.read_cache_file.php:
+      fixed $file_path-parameters  passed to smarty_core_fetch_file_info()
+
+2003-06-17  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS:
+      fix name
+
+    * libs/Smarty_Compiler.class.php:
+      change varnames to follow coding methods
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      add math patch to core
+
+2003-06-17  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/core/core.smarty_include.php:
+      switched _process_template() to _is_compiled()-logic
+
+2003-06-17  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Smarty.class.php:
+      fix _is_compiled logic
+
+    * NEWS:
+      update news file
+
+    * libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      fix _run_mod_handler routine
+
+    * libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/core/core.display_debug_console.php
+      libs/core/core.fetch_file_info.php
+      libs/core/core.parse_file_path.php
+      libs/core/core.write_compiled_template.php
+      libs/plugins/function.config_load.php:
+      fix path problems, rename some varibles from "template" to "file"
+
+2003-06-16  Monte Ohrt  <monte@ispi.net>
+
+    * libs/core/core.fetch_file_info.php
+      libs/core/core.fetch_template_info.php:
+      rename file, commit
+
+    * libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/core/core.parse_file_path.php
+      libs/core/core.read_cache_file.php
+      libs/plugins/block.strip.php
+      libs/plugins/block.textformat.php
+      libs/plugins/compiler.config_load.php
+      libs/plugins/function.config_load.php
+      libs/plugins/function.eval.php
+      libs/plugins/function.fetch.php
+      libs/plugins/function.html_image.php:
+      fix config_load, compile fetched arrays to compile_dir, switch display
+      back to runtime. clean up var names and function names,  split up compile
+      testing and compiling to separate funcs, rename some template_* functions
+      to
+      file_* functions and update logic so they can be used for file resources
+      other than templates.
+
+2003-06-16  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      fixed little bug in _compile_custom_tag()
+
+2003-06-16  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/core/core.assign_smarty_interface.php
+      libs/core/core.create_dir_structure.php
+      libs/core/core.display_debug_console.php
+      libs/core/core.fetch_template_info.php
+      libs/core/core.get_include_path.php
+      libs/core/core.get_microtime.php
+      libs/core/core.get_php_resource.php
+      libs/core/core.is_secure.php
+      libs/core/core.is_trusted.php
+      libs/core/core.load_plugins.php
+      libs/core/core.load_resource_plugin.php
+      libs/core/core.parse_file_path.php
+      libs/core/core.process_cached_inserts.php
+      libs/core/core.read_cache_file.php
+      libs/core/core.rm_auto.php
+      libs/core/core.rmdir.php
+      libs/core/core.run_insert_handler.php
+      libs/core/core.smarty_include.php
+      libs/core/core.smarty_include_php.php
+      libs/core/core.write_cache_file.php
+      libs/core/core.write_compiled_template.php
+      libs/core/core.write_file.php
+      libs/plugins/core.assign_smarty_interface.php
+      libs/plugins/core.create_dir_structure.php
+      libs/plugins/core.display_debug_console.php
+      libs/plugins/core.fetch_template_info.php
+      libs/plugins/core.get_include_path.php
+      libs/plugins/core.get_microtime.php
+      libs/plugins/core.get_php_resource.php
+      libs/plugins/core.is_secure.php
+      libs/plugins/core.is_trusted.php
+      libs/plugins/core.load_plugins.php
+      libs/plugins/core.load_resource_plugin.php
+      libs/plugins/core.parse_file_path.php
+      libs/plugins/core.process_cached_inserts.php
+      libs/plugins/core.read_cache_file.php
+      libs/plugins/core.rm_auto.php
+      libs/plugins/core.rmdir.php
+      libs/plugins/core.run_insert_handler.php
+      libs/plugins/core.smarty_include.php
+      libs/plugins/core.smarty_include_php.php
+      libs/plugins/core.write_cache_file.php
+      libs/plugins/core.write_compiled_template.php
+      libs/plugins/core.write_file.php:
+      move core files into their own directory under SMARTY_DIR,
+      remove abstraction function _execute_core_function
+
+    * libs/Smarty_Compiler.class.php:
+      fix newline handling for template for all template tags
+
+2003-06-11  Monte Ohrt  <monte@ispi.net>
+
+    * libs/plugins/compiler.config_load.php:
+      add compiler function to cvs repository
+
+2003-06-11  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      added config-option "request_use_auto_globals" to make auto-globals be
+      used as request vars instead of HTTP_*_VARS
+
+2003-06-11  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/plugins/function.config_load.php:
+      make config vars compile statically
+
+2003-06-11  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      backed out newlines patch
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      removed newlines in compiled templates after closing tags
+
+2003-06-10  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/de/designers.sgml:
+      fixed german note on html_image and disk-access
+
+2003-06-10  Monte Ohrt  <monte@ispi.net>
+
+    * libs/plugins/core.parse_file_path.php:
+      fix bug with resource_type resolving
+
+2003-06-09  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml:
+      replace example with more practical one
+
+2003-06-08  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      added block-methods for registered objects
+
+2003-06-07  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/programmers.sgml:
+      fixed bug in documentation for $smarty->default_modifiers
+
+2003-06-06  Monte Ohrt  <monte@ispi.net>
+
+    * libs/plugins/core.parse_file_path.php:
+      fix problem with new default_resource_type changes
+
+    * NEWS:
+      update NEWS file info
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/plugins/core.parse_file_path.php:
+      add default_resource_type, ignore 1 char resource names
+
+    * NEWS
+      libs/Config_File.class.php:
+      fix bug where config file starts with hidden section
+
+2003-06-04  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/Smarty.class.php:
+      -** empty log message ***
+
+2003-06-03  Monte Ohrt  <monte@ispi.net>
+
+    * libs/plugins/function.html_image.php:
+      fix example in code comments
+
+2003-06-03  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/plugins/function.counter.php:
+      fixed behaviour of start=... for {counter}
+
+2003-06-02  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/plugins/function.counter.php:
+      fixed assign for {counter}
+
+2003-05-30  Monte Ohrt  <monte@ispi.net>
+
+    * libs/plugins/core.write_cache_file.php
+      libs/plugins/core.write_compiled_template.php:
+      add discrete error checking pertaining to $cache_dir
+      and $compile_dir, their existance and writability
+
+2003-05-28  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/plugins/function.html_table.php:
+      added params vdir, hdir and inner to html_table to allow looping over
+      the data in various directions
+
+2003-05-28  Monte Ohrt  <monte@ispi.net>
+
+    * libs/plugins/core.compile_template.php
+      libs/plugins/core.display_debug_console.php:
+      fix problem with security and debug.tpl file
+
+2003-05-23  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS:
+      upd NEWS file
+
+    * libs/Smarty_Compiler.class.php:
+      allow spaces in literal tags
+
+2003-05-22  Monte Ohrt  <monte@ispi.net>
+
+    * docs/fr/programmers.sgml:
+      fix special chars
+
+2003-05-19  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      speed up compiled templates, hardcode plugin filepaths instead of
+      recalculate at runtime
+
+2003-05-19  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/designers.sgml:
+      fixed example of {html_image}
+
+    * docs/designers.sgml:
+      fixed typo
+
+2003-05-12  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php
+      libs/plugins/core.read_cache_file.php
+      libs/plugins/core.smarty_include.php
+      libs/plugins/function.config_load.php:
+      fixed multiple redundant occurrences for 'config' and 'template' in
+      $smarty->_cache_info
+
+2003-05-10  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/plugins/core.create_dir_structure.php:
+      refurbished create_dir_structure to use '/' internally
+
+    * libs/plugins/core.create_dir_structure.php:
+      fixed windows absolute-paths in smarty_core_create_dir_structure()
+
+    * libs/plugins/core.create_dir_structure.php:
+      fixed error-message
+
+2003-05-09  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      fixed warning due to missing param to _execute_core_function()
+
+    * libs/Smarty_Compiler.class.php:
+      fixed quoting in _compile_include_php
+
+    * libs/Smarty_Compiler.class.php:
+      fixed quoting of "file"-parameter in _compile_include_tag()
+
+2003-05-08  Monte Ohrt  <monte@ispi.net>
+
+    * docs/programmers.sgml:
+      fix typo
+
+    * libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/plugins/core.compile_template.php
+      libs/plugins/core.create_dir_structure.php
+      libs/plugins/core.fetch_template_info.php
+      libs/plugins/core.get_include_path.php
+      libs/plugins/core.get_microtime.php
+      libs/plugins/core.get_php_resource.php
+      libs/plugins/core.is_secure.php
+      libs/plugins/core.is_trusted.php
+      libs/plugins/core.load_plugins.php
+      libs/plugins/core.load_resource_plugin.php
+      libs/plugins/core.parse_file_path.php
+      libs/plugins/core.process_cached_inserts.php
+      libs/plugins/core.read_cache_file.php
+      libs/plugins/core.rm_auto.php
+      libs/plugins/core.rmdir.php
+      libs/plugins/core.run_insert_handler.php
+      libs/plugins/core.smarty_include.php
+      libs/plugins/core.smarty_include_php.php
+      libs/plugins/core.write_cache_file.php
+      libs/plugins/core.write_compiled_template.php
+      libs/plugins/core.write_file.php
+      libs/plugins/function.config_load.php
+      libs/plugins/function.fetch.php
+      libs/plugins/function.html_image.php:
+      abstract more private functions to plugin directory
+
+    * libs/Config_File.class.php:
+      only add DIRECTORY_SEPARATOR if it isn't already present
+
+    * libs/Config_File.class.php:
+      fix directory separator code, use DIRECTORY_SEPARATOR
+
+2003-05-08  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/designers.sgml:
+      fixed example of html_checkboxes
+
+    * NEWS
+      libs/Smarty.class.php:
+      fixed bug in _create_dir_structure() when used with
+      open_basedir-restriction and relative paths
+
+    * docs/designers.sgml:
+      fixed example for html_radios
+
+2003-05-07  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php
+      libs/plugins/core.assign_smarty_interface.php
+      libs/plugins/core.display_debug_console.php
+      libs/plugins/function.display_debug_console.php:
+      abstracted display_debug_console and assign_smarty_interface to plugin dir
+      as a test
+
+    * libs/Smarty.class.php
+      libs/plugins/function.display_debug_console.php:
+      correct misc varnames, abstract debug console display to plugin function
+
+    * libs/plugins/modifier.escape.php:
+      fix typo
+
+2003-05-05  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Smarty_Compiler.class.php:
+      add % to math
+
+    * libs/Smarty.class.php:
+      clean up comments, formatting
+
+    * NEWS
+      libs/Smarty.class.php:
+      keep DIR_SEP for 3rd party compatability
+
+    * NEWS
+      libs/Smarty.class.php:
+      remove DIR_SEP, use DIRECTORY_SEPARATOR exclusively
+
+    * libs/Smarty_Compiler.class.php:
+      remove ++ and -- math operators on template vars
+
+2003-05-04  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty_Compiler.class.php:
+      removed unused parameter $quote from Smarty_Compiler::_parse_attrs()
+
+    * libs/plugins/function.html_image.php:
+      fixed DIR_SEP in html_image-plugin
+
+2003-05-04  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/Smarty.class.php:
+      rename DIR_SEP to SMARTY_DIR_SEP to avoid varname collisions
+
+2003-05-04  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/plugins/function.html_image.php:
+      changed "link" to "href" in html_image. "link" is still working but
+      deprecated
+      html_image always renders an alt-tag now (default alt="")
+      cleaned up indentiation of function.html_image.php
+
+2003-05-03  Monte Ohrt  <monte@ispi.net>
+
+    * libs/debug.tpl:
+      fix typo
+
+2003-05-02  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/plugins/function.counter.php:
+      fixed assign attribute for multiple counters
+
+2003-05-02  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Smarty_Compiler.class.php:
+      allow math on negative number
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      added simple math operators to variables
+
+2003-05-02  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/designers.sgml:
+      fixed typos
+
+2003-04-30  Monte Ohrt  <monte@ispi.net>
+
+    * docs/fr/appendixes.sgml
+      docs/fr/common.dsl
+      docs/fr/designers.sgml
+      docs/fr/getting-started.sgml
+      docs/fr/html-common.dsl
+      docs/fr/html.dsl
+      docs/fr/manual.sgml
+      docs/fr/php.dsl
+      docs/fr/preface.sgml
+      docs/fr/programmers.sgml:
+      add frech docs to cvs repository
+
+2003-04-29  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      reverted patch for case-insensitive tag-names
+
+2003-04-28  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/programmers.sgml:
+      reverted back to humerous redundancy in the docs :). although we all
+      know we are here to generate template-based output, and not to have
+      fun ;-)
+
+    * docs/getting-started.sgml:
+      fixed default user and group for max os x installation
+
+    * libs/Smarty.class.php:
+      made $function[2] and $function[3] options for register_resource
+
+    * libs/Smarty.class.php:
+      fixed issue with object-callback when fetching a php-resource
+
+    * NEWS
+      libs/Smarty.class.php:
+      enabled array(&$obj. 'source', 'timestamp', 'secure', 'trusted') as
+      callback for register_resource()
+      
+      enabled array(&$obj, 'method') as callback for
+      $default_template_handler_func
+
+2003-04-27  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/designers.sgml
+      docs/programmers.sgml:
+      fixed some typos, thank to mehdi
+
+    * libs/plugins/function.counter.php:
+      prevent assign from overruling print-attribute in function.counter.php
+
+    * libs/plugins/function.counter.php:
+      fixed problem with counter and assign
+
+    * libs/Smarty.class.php:
+      fixed notice in  _load_plugins()
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      made plugin-names case-insensitive. this affects
+      compiler/block/custom-functions and modifers.
+
+2003-04-26  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      remove unnecessary close/open tags from compiled templates
+
+2003-04-26  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/designers.sgml:
+      added documentation for foreach.property.*
+
+2003-04-24  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * docs/designers.sgml:
+      fixed example table_attr and tr_attr in html_table-example
+
+2003-04-21  Greg Beaver  <greg@chiaraquartet.net>
+
+    * libs/Smarty.class.php:
+      fixed small bug in doc comments
+
+2003-04-21  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/plugins/function.html_image.php:
+      fixed errornous creation of '//' in image_path in html_image
+
+2003-04-21  Monte Ohrt  <monte@ispi.net>
+
+    * libs/plugins/modifier.debug_print_var.php:
+      fix htmlspecialchars() conflict
+
+    * NEWS
+      libs/plugins/modifier.debug_print_var.php:
+      fix escapement of special chars in key values of debug console
+
+    * NEWS
+      libs/plugins/function.config_load.php:
+      fixed debug timing logic for config_load
+
+    * docs/designers.sgml:
+      fix example text
+
+
+2003-04-20  Greg Beaver <cellog@users.sourceforge.net>
+    * plugins/*
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      Config_File.class.php:
+      updated all doc comments to phpDocumentor format (whew!)
+
+2003-04-06  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/plugins/function.math.php:
+      allowed "_" in the name of variable-parameters to {math}-function
+
+2003-04-04  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      docs/designers.sgml
+      libs/Smarty_Compiler.class.php:
+      change backtic syntax from $`foo` to `$foo`
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      recognize $foo[][] syntax in embedded quotes without backticks
+
+2003-04-03  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      name=123 is passed as an integer (not a string) to plugins now
+
+2003-04-01  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      added CVS $Id: ChangeLog,v 1.2 2004/11/19 11:05:24 garvinhicking Exp $
+
+2003-03-31  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php:
+      added missing compile_id inside Smarty_Compiler
+
+    * libs/Smarty_Compiler.class.php:
+      fixed flaw when generating an error for missing postfilter
+
+2003-03-31  Monte Ohrt  <monte@ispi.net>
+
+    * docs/getting-started.sgml
+      docs/programmers.sgml:
+      fix typos
+
+2003-03-27  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/plugins/modifier.debug_print_var.php:
+      $length is now propagated to sub-values in debug_print_var
+
+2003-03-26  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS:
+      update header
+
+    * RELEASE_NOTES:
+      commit changes to release notes
+
+    * (Smarty_2_5_0_RC2)
+      libs/Config_File.class.php
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      committing RC2
+
+2003-03-24  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php:
+      made clear_cache() ignore compile_id when clearing cache_groups
+
+    * libs/plugins/function.popup.php:
+      made onmouseout XHTML-compatible in function.popup.php
+
+2003-03-21  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php:
+      applied new var-names to fetch()
+
+    * NEWS
+      libs/Smarty.class.php:
+      renamed $localvars to $_localvars in cache-file-handling-functions,
+      added _get_auto_id()-function
+
+2003-03-21  Monte Ohrt  <monte@ispi.net>
+
+    * libs/plugins/function.mailto.php
+      libs/plugins/function.popup.php:
+      update functions for XHTML compatability
+
+2003-03-21  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * libs/Smarty.class.php:
+      fixed wrong $auto_id in _read_cache_file()
+
+    * NEWS
+      libs/Smarty.class.php:
+      swapped compile_id and cache_id in read_cache_file and write_cache_file
+
+    * libs/Smarty.class.php:
+      reverted patch for ignoring compile-id back to -r1.364, due to problems
+
+    * NEWS
+      libs/plugins/function.html_checkboxes.php
+      libs/plugins/function.html_radios.php:
+      html_radios and html_checkboxes accept "selected" instead of "checked"
+      optionally now
+
+    * NEWS
+      libs/Smarty.class.php:
+      swapped compile_id and cache_id for cache-file-handling again
+
+2003-03-20  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Smarty_Compiler.class.php:
+      fix notice when no parameter is passed to default
+
+2003-03-20  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php:
+      removed notice of undefined var in _rm_auto()
+
+2003-03-19  Monte Ohrt  <monte@ispi.net>
+
+    * libs/plugins/function.html_checkboxes.php
+      libs/plugins/function.html_radios.php
+      libs/plugins/function.html_table.php:
+      fix a few error messages, follow consistancy format plugin_name: errormsg
+
+    * libs/plugins/function.html_radios.php:
+      update error messages
+
+    * NEWS
+      libs/plugins/function.html_radios.php:
+      add a warning when an array is passed as the 'checked' value of html_radios
+
+2003-03-19  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      fixed errormessage in _compile_smarty_ref()
+
+    * NEWS
+      docs/designers.sgml:
+      updated docs for html_image
+
+2003-03-18  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/Smarty.class.php:
+      cleaned up calls to readdir()
+
+    * libs/plugins/function.html_options.php:
+      fixed label for optgroup in html_options
+
+2003-03-18  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      fix (newly introduced) bug with passing multiple modifiers to a parameter
+
+2003-03-18  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      docs/designers.sgml:
+      updated docs for html_checkboxes, html_options and html_radios
+
+    * libs/plugins/function.html_options.php:
+      fixed wrong default-"name" in function.html_options.php
+
+    * NEWS
+      libs/plugins/function.html_checkboxes.php
+      libs/plugins/function.html_radios.php:
+      renamed "checkbox" and "radios" to "options" in {html_checkboxes} and
+      {html_radios}
+
+    * libs/plugins/outputfilter.trimwhitespace.php:
+      tried to optimize re-replacement in outputfilter.trimwhitespace.php a
+      little
+
+    * libs/plugins/outputfilter.trimwhitespace.php:
+      fixed greedy str_replace in outputfilter.trimwhitespace.php
+
+    * NEWS
+      libs/plugins/function.html_checkboxes.php
+      libs/plugins/function.html_options.php
+      libs/plugins/function.html_radios.php:
+      html_options, html_checkboxes and html_radios now pass-thru all unknown
+      paramters
+
+2003-03-17  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/plugins/function.html_options.php:
+      html_options passthru all unknown paramters now
+
+2003-03-17  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/plugins/function.html_image.php:
+      Fix link bug in html_image function, also make output XHTML compatible
+
+    * libs/Smarty_Compiler.class.php:
+      fix issue of embedded var and escaped double quotes
+
+2003-03-15  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      back out "@" logic, apply only to default modifier special case
+
+    * libs/Smarty_Compiler.class.php:
+      fix @ logic, only use upon an echo
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      append "@" to template var echoes to supress possible notices
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      append "@" to _run_mod_handler to supress warnings
+
+2003-03-14  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      fix problem with escaped double quotes
+
+    * NEWS
+      libs/plugins/function.html_radios.php:
+      fixed html_options to not return an array
+
+2003-03-12  Messju Mohr  <messju@lammfellpuschen.de>
+
+    * NEWS
+      libs/plugins/modifier.truncate.php:
+      fixed length in modifier.truncate.php
+
+    * NEWS
+      libs/plugins/outputfilter.trimwhitespace.php:
+      fixed handling of '$'-signs in trimwhitespace outputfilter (messju)
+
+2003-03-12  Monte Ohrt  <monte@ispi.net>
+
+    * docs/programmers.sgml:
+      update technical explanation of assign_by_ref and append_by_ref
+
+2003-03-11  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/Smarty.class.php:
+      fix config file recompiling code
+
+2003-03-07  Monte Ohrt  <monte@ispi.net>
+
+    * libs/plugins/function.html_image.php:
+      change E_USER_ERROR to E_USER_NOTICE
+
+    * libs/plugins/function.html_image.php:
+      suppress warning in html_image
+
+    * NEWS
+      libs/plugins/function.html_image.php:
+      update changes to html_image
+
+2003-03-06  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml
+      docs/de/appendixes.sgml
+      docs/de/common.dsl
+      docs/de/designers.sgml
+      docs/de/getting-started.sgml
+      docs/de/html-common.dsl
+      docs/de/html.dsl
+      docs/de/manual.sgml
+      docs/de/preface.sgml
+      docs/de/programmers.sgml:
+      add german docs to dist
+
+    * NEWS:
+      update news file
+
+    * libs/plugins/function.html_image.php:
+      fix width/height parameter index
+
+    * NEWS
+      libs/Smarty.class.php:
+      get rid of unsetting name and script attributes to insert tags
+
+2003-03-05  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      RELEASE_NOTES:
+      update NEWS file
+
+    * libs/plugins/modifier.string_format.php:
+      fix argument order, erroneously swapped a while back
+
+    * (Smarty_2_5_0_RC1)
+      NEWS
+      README
+      RELEASE_NOTES
+      libs/Config_File.class.php
+      libs/Smarty.class.php
+      libs/Smarty_Compiler.class.php:
+      commit final changes for 2.5.0-RC1
+
+2003-03-04  Monte Ohrt  <monte@ispi.net>
+
+    * docs/programmers.sgml:
+      remove $show_info_header and $show_info_include property vars from docs
+
+2003-03-03  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/plugins/function.popup.php:
+      fixed PHP notice
+
+2003-02-28  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Smarty_Compiler.class.php:
+      simplify smarty.const.foo and smarty.const.$foo logic
+
+    * libs/Smarty_Compiler.class.php:
+      only allow $foo syntax in embedded quotes, unless escaped with backticks
+      then allow any dollar var
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      fix "once" var compiling to work with new attr compiling methods for
+      include_php
+
+    * FAQ
+      NEWS
+      README
+      docs/designers.sgml
+      docs/getting-started.sgml
+      libs/Smarty_Compiler.class.php
+      libs/plugins/function.html_checkboxes.php
+      libs/plugins/function.html_image.php
+      libs/plugins/function.html_options.php
+      libs/plugins/function.html_radios.php
+      libs/plugins/function.html_select_date.php
+      libs/plugins/function.html_select_time.php
+      libs/plugins/function.html_table.php:
+      fix $smarty.const.foo compiling, clean up double quoted strings,
+      allow full dollar var syntax in quotes again
+
+2003-02-27  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml
+      docs/programmers.sgml
+      libs/Smarty_Compiler.class.php:
+      update docs, fix smarty var compiling, allow any $smarty.*.$foo syntax,
+      add $`foobar` for embedded variables
+
+    * libs/plugins/function.html_image.php:
+      update functionality
+
+2003-02-26  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      libs/plugins/modifier.nl2br.php:
+      add nl2br modifier
+
+    * libs/plugins/function.html_image.php:
+      add link parameter
+
+2003-02-24  Monte Ohrt  <monte@ispi.net>
+
+    * libs/Smarty.class.php
+      libs/plugins/function.html_image.php:
+      fix rename problem in windows, unlink first
+
+    * libs/plugins/function.html_checkboxes.php
+      libs/plugins/function.html_image.php
+      libs/plugins/function.html_options.php
+      libs/plugins/function.html_radios.php
+      libs/plugins/shared.escape_special_chars.php:
+      update functions with separate escape_special_chars routine
+
+    * NEWS
+      libs/plugins/function.html_checkboxes.php
+      libs/plugins/function.html_radios.php:
+      commit checkboxes, update radios
+
+    * NEWS
+      libs/Smarty.class.php
+      libs/plugins/function.html_image.php:
+      fix bug with get_registered_object
+
+    * NEWS
+      libs/plugins/modifier.cat.php:
+      added cat modifier to distribution
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      added << >> <> support to IF statements
+
+    * libs/plugins/function.html_radios.php:
+      apply patch to initial html_radios function
+
+    * NEWS
+      libs/Smarty.class.php:
+      fix _assign_smarty_interface to not overwrite keys other than 'request'
+
+    * NEWS
+      libs/plugins/function.html_radios.php:
+      added html_radios to distribution
+
+    * NEWS
+      libs/plugins/modifier.string_format.php:
+      fixed arg order of string_format
+
+    * NEWS
+      libs/Smarty.class.php:
+      use tmp file for file writes, avoid race condition
+
+    * NEWS
+      libs/Smarty_Compiler.class.php:
+      add $smarty.config.foo var, handle embedded smarty var correctly
+
+    * NEWS
+      libs/plugins/function.fetch.php:
+      silence warnings in fetch plugin
+
+2003-02-21  Monte Ohrt  <monte@ispi.net>
+
+    * INSTALL:
+      update wording
+
+    * INSTALL:
+      update install instructions
+
+    * AUTHORS
+      BUGS
+      CREDITS
+      QUICKSTART
+      README
+      RESOURCES
+      TESTIMONIALS:
+      remove some files already in docs or elsewhere
+
+    * demo/index.php:
+      add templates_c to repository
+
+    * index.php:
+      move demo files to demo directory
+
+    * Config_File.class.php
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      debug.tpl:
+      moved lib files under libs directory
+
+2003-02-20  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.class.php:
+      add get_config_vars() method, update get_template_vars() functionality
+
+    * NEWS
+      Smarty.class.php:
+      fix minor logic in _fetch_template_info()
+
+    * NEWS
+      Smarty.class.php:
+      support merging appended vars
+
+    * NEWS
+      Smarty.class.php:
+      fix cache groups behavior with compile_id set
+
+2003-02-19  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php:
+      back out third parameter, extend functionality of append
+
+    * NEWS
+      Smarty_Compiler.class.php:
+      update imbedded vars, allow special $smarty vars
+
+    * plugins/function.html_table.php:
+      add plugin html_table
+
+    * NEWS
+      Smarty.class.php:
+      support appending key=>val pairs
+
+    * NEWS
+      Smarty_Compiler.class.php:
+      change embedded variable logic to only recognize $foo and $foo[0][bar]
+      syntax
+
+    * NEWS
+      Smarty_Compiler.class.php:
+      allow null as function attribute value
+
+2003-02-18  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+      support foo->bar[index] syntax
+
+    * Smarty_Compiler.class.php:
+      allow $foo->bar[0] syntax
+
+2003-02-17  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/modifier.escape.php:
+      fix syntax error from previous commit
+
+    * NEWS
+      Smarty.class.php:
+      add error msgs to get_registered_object
+
+    * Smarty.class.php:
+      add function for getting reference to registered object
+
+    * Smarty_Compiler.class.php:
+      back out patches for object and objref calls on $smarty var
+
+    * NEWS
+      Smarty_Compiler.class.php:
+      treat unrecognized param attribute syntax as a string
+
+    * NEWS
+      Smarty_Compiler.class.php:
+      support $smarty.const.$foo syntax
+
+    * NEWS
+      debug.tpl
+      plugins/modifier.count_words.php
+      plugins/modifier.escape.php:
+      fix E_NOTICE messages
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+      add @ and === to if tokens, few param cleanups
+
+2003-02-16  Greg Beaver  <greg@chiaraquartet.net>
+
+    * ChangeLog
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+      many more phpdoc comment upgrades
+
+2003-02-15  Greg Beaver <cellog@sourceforge.net>
+    * Smarty.class.php
+      Smarty_Compiler.class.php
+      continue cleaning of phpdoc comments.  All that is needed is the
+      addition of @return tags and perhaps a bit more verbose comments
+      and they are finished.
+
+2003-02-14  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.class.php:
+      enable config_load error messages
+
+    * NEWS
+      plugins/function.html_options.php:
+      fix html_options to not escape already escaped entities
+
+    * NEWS
+      Smarty.class.php:
+      send Last-Modified header on cache creation, misc tab/spacing cleanup
+
+2003-02-13  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php
+      docs/designers.sgml:
+      allow dash in plain text
+
+    * NEWS
+      Smarty_Compiler.class.php:
+      check strict syntax of function attributes
+
+2003-02-12  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty_Compiler.class.php:
+      dropped support for modifiers on object parameters,
+      added support for objects as modifier parameters
+
+    * NEWS
+      Smarty_Compiler.class.php
+      docs/designers.sgml:
+      fix bug with decimal numbers in if statements, misc doc updates
+
+2003-02-11  Monte Ohrt  <monte@ispi.net>
+
+    * (Smarty_2_4_2)
+      Config_File.class.php
+      NEWS
+      README
+      RELEASE_NOTES
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+      update version numbers
+
+2003-02-10  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty_Compiler.class.php:
+      add support for $foo->$bar syntax
+
+    * NEWS:
+      update NEWS file
+
+    * NEWS
+      Smarty_Compiler.class.php:
+      support full var syntax in quoted text, fix problem with const var access,
+      clean up some more regex code, fix object problem with no properties
+
+2003-02-06  Monte Ohrt  <monte@ispi.net>
+
+    * (Smarty_2_4_1)
+      Config_File.class.php
+      NEWS
+      README
+      RELEASE_NOTES
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+      committed 2.4.1 changes
+
+    * NEWS
+      Smarty_Compiler.class.php:
+      ignore case in IF statements
+
+2003-02-05  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty_Compiler.class.php:
+      treat undefined constants as null
+
+    * NEWS
+      Smarty.class.php:
+      fix problem with inserts and nested fetches
+
+    * Smarty_Compiler.class.php:
+      fix "if" regex for math tokens
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      docs/getting-started.sgml:
+      added support for extracting params to include_php
+
+2003-02-04  Monte Ohrt  <monte@ispi.net>
+
+    * RELEASE_NOTES:
+      reformat text
+
+2003-02-03  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS:
+      update news file
+
+2003-02-03  Greg Beaver  <greg@chiaraquartet.net>
+
+    * ChangeLog
+      Smarty.class.php:
+      begin fixing phpdoc comments in Smarty.class.php
+
+    * ChangeLog
+      Config_File.class.php:
+      fixed phpdoc comments
+
+2003-02-03  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php:
+      allow $foo->bar[$x].foo syntax
+
+    * Smarty_Compiler.class.php
+      index.php
+      configs/test.conf
+      templates/index.tpl:
+      fix accidental commit
+
+    * index.php
+      configs/test.conf
+      templates/index.tpl:
+      allow $foo->bar[$j].blah type of syntax
+
+2003-02-02  Greg Beaver  <cellog@php.net>
+
+    * Smarty.class.php
+      begin fixing of phpdoc comments
+
+    * Config_File.class.php
+      fix phpdoc comments, add phpDocumentor docblock templates
+
+2003-02-02  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php
+      docs/html.dsl
+      docs/php.dsl:
+      fix version number
+
+    * (Smarty_2_4_0)
+      Config_File.class.php
+      NEWS
+      README
+      RELEASE_NOTES
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      docs/appendixes.sgml
+      docs/designers.sgml
+      docs/programmers.sgml:
+      update Smarty version numbers
+
+2003-01-30  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty_Compiler.class.php
+      TODO:
+      fix order of php tag comparisons
+
+    * NEWS
+      Smarty_Compiler.class.php:
+      fix known php tag handling problems
+
+2003-01-29  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php:
+      change comments to phpdoc style
+
+2003-01-28  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php
+      docs/programmers.sgml:
+      make separate var for compiler file
+
+    * plugins/function.fetch.php:
+      fix error call
+
+2003-01-25  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php:
+      add support for restriction to registered methods
+
+    * plugins/outputfilter.trimwhitespace.php:
+      update with textarea support
+
+2003-01-24  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php:
+      fix compiling problem with {foreach} tags
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php:
+      put objects in own array, add object param format support, change
+      object syntax from foo.bar to foo->bar
+
+2003-01-23  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+      add support for object registration
+
+2003-01-22  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php:
+      add file & line number of calling error to error message
+
+2003-01-21  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php:
+      put php style object syntax back in
+
+2003-01-20  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php:
+      move security settings to fetch function for template_dir
+
+    * NEWS
+      Smarty.class.php:
+      fix debug template and security, add template_dir to secure_dir at runtime
+
+2003-01-17  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+      added new object support without new template syntax
+
+2003-01-15  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+      fix if statement syntax for negative integers, fix issue with directories
+      named '0'
+
+2003-01-08  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php
+      plugins/function.counter.php
+      plugins/function.cycle.php
+      plugins/function.debug.php
+      plugins/function.eval.php
+      plugins/function.fetch.php
+      plugins/function.html_options.php
+      plugins/function.html_select_date.php
+      plugins/function.html_select_time.php
+      plugins/function.mailto.php
+      plugins/function.math.php
+      plugins/function.popup.php
+      plugins/function.popup_init.php:
+      update plugins to return values instead of echo, fix config file cache
+      to include global config variables in cache file
+
+    * Smarty_Compiler.class.php:
+      fix bug with >= tests in if statements, comment out full object support
+
+2003-01-06  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      docs/html.dsl
+      plugins/modifier.escape.php:
+      add javascript escape parameter to escape modifier
+
+2003-01-02  Monte Ohrt  <monte@ispi.net>
+
+    * templates/header.tpl:
+      move the title into head where it should be
+
+2002-12-24  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php:
+      added correct line numbers to smarty syntax error messages
+
+    * docs/programmers.sgml:
+      update append documentation, make more clear on its function
+
+    * Smarty_Compiler.class.php:
+      fix modifier matching regexp
+
+2002-12-23  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php:
+      support nested function calls in IF statements
+
+2002-12-20  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php:
+      few more fixes, spaces around function parameters
+
+    * Smarty_Compiler.class.php:
+      fix misc syntax issues with {if} tags
+
+2002-12-20  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php:
+      fix misc syntax issues with {if} tags
+
+2002-12-19  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php:
+      commit updates, passes all smoke tests
+
+    * NEWS:
+      update NEWS file
+
+    * Smarty_Compiler.class.php:
+      fixed literal string not in quotes as parameters
+
+    * NEWS
+      Smarty_Compiler.class.php:
+      fix misc syntax issues, add ability to pass modifiers to functions
+
+2002-12-18  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS:
+      update NEWS
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+      update compiler code, clean up regex, add new syntax features
+
+2002-12-16  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS:
+      update NEWS file
+
+    * Smarty_Compiler.class.php:
+      commit updates for objects
+
+2002-12-14  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php:
+      fix bug with compiling config files with caching on
+
+2002-12-13  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php:
+      fix problem with matching single quoted strings
+
+    * Smarty_Compiler.class.php:
+      update embedded variable logic, get rid of ."" at end of output
+
+    * NEWS
+      docs/designers.sgml
+      plugins/function.html_select_date.php:
+      add day_value_format to html_select_date
+
+2002-12-12  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/modifier.debug_print_var.php:
+      fix bug, double escaped values in display
+
+    * Smarty.class.php:
+      move debug test back into fetch()
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      plugins/outputfilter.trimwhitespace.php:
+      assigned vars are no longer in global name space, few debug cleanups
+
+2002-12-11  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/function.popup.php:
+      fix error in newline code
+
+    * plugins/function.popup.php:
+      fix popup to allow newlines in text data
+
+2002-12-10  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php:
+      fix plugin error logic
+
+    * docs/designers.sgml
+      docs/programmers.sgml:
+      edit examples, make more verbose
+
+    * NEWS
+      plugins/function.html_options.php:
+      escape html entities in the option values and output
+
+    * NEWS
+      plugins/function.html_options.php:
+      fixed bug with label of html_options
+
+2002-12-09  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php:
+      add support for var_export()
+
+    * Config_File.class.php
+      Smarty.class.php:
+      clean up code, respect force_compile and compile_check flags
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      docs/designers.sgml
+      plugins/function.mailto.php:
+      add caching feature to config loading, document update, add mailto plugin
+
+2002-12-08  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/function.fetch.php:
+      fix query part of URL
+
+2002-12-05  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml:
+      fix typos
+
+2002-11-22  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php:
+      patch for warning message
+
+2002-11-21  Monte Ohrt  <monte@ispi.net>
+
+    * RELEASE_NOTES
+      Smarty.class.php:
+      get rid of testing for a set value with assign function, just set to
+      whatever is passed into the template
+
+    * docs/programmers.sgml:
+      fix typo
+
+2002-11-19  Monte Ohrt  <monte@ispi.net>
+
+    * Config_File.class.php
+      NEWS
+      README
+      RELEASE_NOTES
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+      commit changes, ready for 2.3.1 release
+
+2002-11-01  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/function.html_options.php:
+    added label attribute to all option outputs, cover w3c spec.
+
+    * NEWS: update NEWS file
+
+    * docs/designers.sgml: update docs for optgroup output
+
+    * plugins/function.html_options.php:
+    make html_options work with optgroup, make func modular and recursive.
+
+2002-10-29  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.class.php: set mtime on compile files so they match source files
+
+2002-10-18  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.class.php: added proper support for open_basedir setting
+
+    * docs/designers.sgml: clear up docs on index, iteration and rownum
+
+2002-10-16  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/modifier.default.php: fix warning message in default modifier
+
+2002-09-25  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml
+      plugins/modifier.strip.php
+      NEWS: added strip variable modifier
+
+2002-09-24  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: *** empty log message ***
+
+    * Smarty_Compiler.class.php:
+    Fix to be able to use $smarty.x variables as arrays.
+
+2002-09-23  Monte Ohrt  <monte@ispi.net>
+
+    * Config_File.class.php:
+    add support for mac/dos formatted config files (fix newlines)
+
+    * docs/programmers.sgml: add optional tags to clear_cache parameters
+
+    * docs/designers.sgml:
+    fix error with include_php description, add $this to description
+
+2002-09-20  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      docs/getting-started.sgml: fixed errors with example setup docs
+
+2002-09-16  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/block.textformat.php
+      docs/designers.sgml
+      NEWS: add textformat block function
+
+2002-09-10  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml:
+    add assign attribute to cycle function documentation
+
+    * docs/designers.sgml
+      docs/programmers.sgml: fix typos
+
+2002-09-09  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/function.debug.php
+      templates/header.tpl:
+    fix header in debug template, fix typo in header.tpl example
+
+2002-08-15  mohrt  <mohrt@pb1.pair.com>
+
+    * docs/programmers.sgml: fix typos
+
+2002-08-08  mohrt  <mohrt@pb1.pair.com>
+
+    * RELEASE_NOTES
+      Smarty.class.php:
+    supress warnings from unlink() and is_dir(), let error handler deal with it
+
+2002-08-07  mohrt  <mohrt@pb1.pair.com>
+
+    * docs/appendixes.sgml
+      docs/designers.sgml
+      docs/programmers.sgml
+      Config_File.class.php
+      NEWS
+      README
+      RELEASE_NOTES
+      Smarty.class.php
+      Smarty_Compiler.class.php: update files with new version numbers
+
+2002-08-02  mohrt  <mohrt@pb1.pair.com>
+
+    * NEWS: update NEWS file with credits
+
+    * NEWS
+      Smarty.class.php: added assign_by_ref() and append_by_ref() functions
+
+2002-08-01  mohrt  <mohrt@pb1.pair.com>
+
+    * TODO
+      NEWS
+      Smarty.class.php:
+    changed default warning type for plugin errors from E_USER_WARNING to E_USER_ERROR
+
+2002-07-29  mohrt  <mohrt@pb1.pair.com>
+
+    * plugins/function.html_select_time.php
+      docs/designers.sgml
+      NEWS: added paramters to html_select_time plugin
+
+2002-07-25  Andrei Zmievski  <andrei@pb1.pair.com>
+
+    * TODO: *** empty log message ***
+
+2002-07-24  mohrt  <mohrt@pb1.pair.com>
+
+    * QUICKSTART: update QUICKSTART guide
+
+    * NEWS
+      debug.tpl
+      plugins/modifier.debug_print_var.php:
+    update debug console to show objects, fix warning in debug.tpl
+
+2002-07-23  mohrt  <mohrt@pb1.pair.com>
+
+    * docs/programmers.sgml: fix load_filter examples
+
+    * Config_File.class.php
+      NEWS: fix error when there are no sections in config file
+
+2002-07-19  mohrt  <mohrt@pb1.pair.com>
+
+    * docs/getting-started.sgml: fix error in install guide
+
+2002-07-18  mohrt  <mohrt@pb1.pair.com>
+
+    * Smarty_Compiler.class.php:
+    correct the expression match for smarty:nodefaults
+
+2002-07-17  mohrt  <mohrt@pb1.pair.com>
+
+    * Smarty_Compiler.class.php: fix default modifier to work with config vars
+
+    * Smarty_Compiler.class.php: got args to strstr backwards...
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+    change default modifiers to array instead of string
+
+    * Smarty_Compiler.class.php
+      docs/designers.sgml
+      Smarty.class.php: add default modifier logic, minor doc updates
+
+    * NEWS
+      Smarty.class.php
+      plugins/function.popup_init.php:
+    make popup_init xhtml compliant, minor variable name changes for consistancy
+
+2002-07-16  mohrt  <mohrt@pb1.pair.com>
+
+    * NEWS: update NEWS file
+
+    * plugins/function.debug.php
+      Smarty.class.php
+      debug.tpl
+      NEWS:
+    fix problem with filenames on windows, add ability to supply expire time in seconds when clearing cache or compiled files
+
+2002-07-15  mohrt  <mohrt@pb1.pair.com>
+
+    * Smarty.class.php:
+    fixed problem with insert tags when loading function from script attribute
+    and caching enabled (Monte)
+
+2002-07-14  mohrt  <mohrt@pb1.pair.com>
+
+    * NEWS
+      Smarty.class.php: fix bug with debug_tpl file path for Windows
+
+2002-07-12  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: fix append function with array/string issue
+
+2002-07-11  Monte Ohrt  <monte@ispi.net>
+
+    * RELEASE_NOTES: update release notes
+
+    * NEWS
+      README
+      RELEASE_NOTES
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      Config_File.class.php: update files to 2.2.0 tags, get ready for release
+
+2002-07-09  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.class.php: make debug.tpl work with any delimiter
+
+    * NEWS
+      Smarty.class.php:
+    change tests in append and assign to != '' instead of empty(), which is more accurate
+
+2002-07-08  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml: minor doc update
+
+    * Smarty.class.php:
+    cast var as an array, simplify and get rid of PHP warning messages
+
+2002-07-03  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: one more N
+
+    * Smarty.class.php:
+    prepend "N" to filenames to avoid possible OS issues with dir names starting with "-"
+
+    * Smarty.class.php: only set $debug_tpl in constructor if empty
+
+    * Smarty.class.php
+      docs/designers.sgml
+      docs/getting-started.sgml
+      docs/programmers.sgml:
+    make use_sub_dirs go back to crc32 for subdir separation
+
+2002-06-29  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/function.eval.php: do nothing if $val is empty
+
+    * TODO
+      plugins/function.eval.php
+      plugins/function.popup_init.php:
+    add zindex to popup init, fix error message for eval.
+
+2002-06-27  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php:
+    only loop through relative paths for PHP include_path, remove $_relative variable
+
+    * Smarty_Compiler.class.php: added {$smarty.version} variable
+
+2002-06-26  Monte Ohrt  <monte@ispi.net>
+
+    * docs/appendixes.sgml
+      docs/designers.sgml
+      docs/getting-started.sgml
+      docs/programmers.sgml
+      Smarty.class.php:
+    update plugin loading logic, look in SMARTY_DIR, then cwd. If all fail, then retry all with include_path
+
+    * templates/header.tpl
+      Smarty.class.php: update get_include_path, get _path_array only once
+
+    * Smarty.class.php: fix get_include_path function for windows
+
+    * Smarty.class.php: update plugin search logic
+
+    * Smarty.class.php: only search include_path if relative path
+
+    * plugins/function.html_select_date.php
+      plugins/function.html_select_time.php
+      plugins/modifier.date_format.php
+      Smarty_Compiler.class.php
+      NEWS
+      Smarty.class.php: allow plugins_dir to be an array of directories
+
+2002-06-25  Monte Ohrt  <monte@ispi.net>
+
+    * docs/programmers.sgml
+      docs/getting-started.sgml: update installation docs
+
+    * debug.tpl
+      docs/getting-started.sgml
+      templates/debug.tpl
+      NEWS
+      Smarty.class.php: move debug.tpl to SMARTY_DIR, add to constructor
+
+2002-06-24  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/function.assign_debug_info.php
+      NEWS: fixed warning message in function.assign_debug_info
+
+    * Smarty.class.php: update include_path fixes
+
+    * NEWS:
+    fixed $template_dir, $compile_dir, $cache_dir, $config_dir to respect include_path
+
+2002-06-23  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/shared.make_timestamp.php:
+    update timestamp plugin to work when passed a timestamp
+
+2002-06-19  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS: update NEWS file
+
+    * plugins/modifier.date_format.php
+      docs/designers.sgml:
+    update date_format, allow optional 2nd paramater as default date if passed date is empty. update docs.
+
+    * plugins/modifier.date_format.php:
+    fix date_format modifier, return nothing if given empty string
+
+2002-06-18  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      plugins/function.cycle.php:
+    gave $reset a default value in cycle function
+
+    * plugins/function.html_select_date.php
+      plugins/shared.make_timestamp.php
+      NEWS:
+    corrected warnings in html_select_time function, made make timestamp always return a timestamp
+
+2002-06-17  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: swapped around cache_id and compile_id order
+
+2002-06-14  Monte Ohrt  <monte@ispi.net>
+
+    * docs/programmers.sgml
+      plugins/function.popup_init.php
+      Smarty.class.php:
+    change directory delimiter to "^" for cache and compile files
+
+2002-06-13  Andrei Zmievski  <andrei@php.net>
+
+    * TODO: done.
+
+    * Smarty_Compiler.class.php:
+    Optimize the calculation of section 'total' property.
+
+2002-06-11  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.class.php:
+    added support for subdir exclusion, deletion by full or partial cache_id and compile_id, change file format to urlencoded values instead of crc32
+
+2002-06-07  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: fix bug with last_modified_check code
+
+    * NEWS
+      Smarty.class.php:
+    updated $GLOBALS refererence for HTTP_IF_MODIFIED_SINCE
+
+2002-06-06  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml
+      overlib.js:
+    remove overlib.js file from distribution, update plugin and docs
+
+2002-06-05  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml
+      NEWS
+      Smarty.class.php: fix 304 Not Modified, don't send content
+
+2002-06-03  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/function.cycle.php: update version number
+
+    * plugins/function.cycle.php
+      NEWS:
+    fixed cycle function to respect delimiter setting after initial setting
+
+    * Smarty.class.php
+      NEWS:
+    update $GLOBALS references to work properly with track_globals settings
+
+    * plugins/function.math.php: fixed bug with call $assign
+
+    * docs/appendixes.sgml
+      docs/designers.sgml
+      plugins/function.html_options.php
+      plugins/function.html_select_time.php
+      NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+    optimized for loops with count() function calls
+
+2002-06-01  Andrei Zmievski  <andrei@php.net>
+
+    * TODO: *** empty log message ***
+
+2002-05-21  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS: update NEWS file
+
+    * plugins/function.html_select_date.php
+      RESOURCES
+      docs/designers.sgml
+      Config_File.class.php:
+    update html_select_date with month_value_format attribute for controlling the format of the month values.
+
+2002-05-17  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty_Compiler.class.php:
+    Made it possible to use simple variables inside [] for indexing.
+
+2002-05-16  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml
+      docs/getting-started.sgml
+      NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      TESTIMONIALS: add "once" attribute to php_include, update docs
+
+2002-05-09  Andrei Zmievski  <andrei@ispi.net>
+
+    * NEWS
+      TODO: *** empty log message ***
+
+2002-05-07  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/function.cycle.php: remove \n from cycle function
+
+    * docs/designers.sgml
+      plugins/function.cycle.php
+      README
+      RELEASE_NOTES
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      NEWS:
+    update cycle function to handle array as input, update files to 2.1.1
+
+2002-05-06  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/function.fetch.php:
+    update fetch function with more error checking
+
+2002-05-03  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml
+      plugins/function.counter.php:
+    update counter to use name instead of id (id still works though)
+
+    * plugins/function.cycle.php
+      docs/designers.sgml: rename id to name for cycle function
+
+    * plugins/function.cycle.php:
+    update cycle function to allow blank values parameter after initialized
+
+    * plugins/function.cycle.php: fix syntax error
+
+2002-05-02  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/function.cycle.php: ugh, another typo
+
+    * plugins/function.cycle.php: update comments
+
+    * docs/designers.sgml
+      plugins/function.cycle.php
+      NEWS: added function cycle
+
+    * FAQ
+      Smarty.class.php: fix register_outputfilter function
+
+2002-05-01  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml
+      NEWS
+      Smarty.class.php: fixed bug with resource testing and include_path
+
+2002-04-30  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      README
+      RELEASE_NOTES
+      Smarty.class.php
+      Smarty_Compiler.class.php: update files for 2.1.0 release
+
+2002-04-30  Andrei Zmievski  <andrei@ispi.net>
+
+    * plugins/function.fetch.php
+      docs/programmers.sgml
+      Smarty.class.php: Fix.
+
+2002-04-29  Andrei Zmievski  <andrei@ispi.net>
+
+    * docs/programmers.sgml
+      docs/designers.sgml: A whole bunch of docs.
+
+2002-04-26  Monte Ohrt  <monte@ispi.net>
+
+    * FAQ
+      QUICKSTART
+      docs/programmers.sgml: update FAQ, QUICKSTART, small doc syntax fix
+
+2002-04-24  Monte Ohrt  <monte@ispi.net>
+
+    * docs/programmers.sgml
+      templates/debug.tpl
+      Smarty.class.php: changed doc structure a bit
+
+2002-04-16  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php: Add register/unregister API for output filters.
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      TODO:
+    Changed the way filters are loaded, which now has to be done explicitly,
+    either through load_filter() API or by filling in $autoload_filters variable.
+    Also renamed internal variable to avoid namespace pollution.
+
+2002-04-15  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php:
+    Fixed _get_php_resource() to take include_path into account.
+
+2002-04-15  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml:
+    update docs, get modifiers and functions into index for easy access
+
+    * docs/programmers.sgml
+      NEWS
+      Smarty.class.php: update caching documentation
+
+2002-04-15  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: *** empty log message ***
+
+    * Smarty.class.php: Only turn down error notices if $debugging is false.
+
+2002-04-15  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS: update NEWS file
+
+    * plugins/function.html_select_date.php:
+    fixed logic so this works right when field_separator = "/"
+
+    * plugins/function.html_select_date.php:
+    fix regular expression for matching date
+
+2002-04-13  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml: updated html_select_date docs to reflect changes
+
+    * NEWS
+      plugins/function.html_select_date.php:
+    added YYYY-MM-DD support to html_select_date
+
+2002-04-12  Andrei Zmievski  <andrei@php.net>
+
+    * TESTIMONIALS: New entry.
+
+2002-04-12  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/modifier.strip_tags.php: back out changes to strip_tags
+
+    * docs/programmers.sgml: update docs regarding cache_lifetime
+
+    * plugins/modifier.strip_tags.php
+      Smarty.class.php:
+    update cache_lifetime logic: -1 = never expire, 0 = always expire
+
+2002-04-11  Andrei Zmievski  <andrei@php.net>
+
+    * BUGS
+      FAQ
+      INSTALL
+      NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      docs/getting-started.sgml:
+    Fixed directory separtor issue. Requiring PHP 4.0.6 now.
+
+    * NEWS
+      Smarty_Compiler.class.php:
+    Added ability to use simple variables for array indices or object properties.
+
+    * TESTIMONIALS: Another one.
+
+    * TESTIMONIALS: Adding one from Mark P.
+
+2002-04-05  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty_Compiler.class.php
+      NEWS
+      Smarty.class.php: Make it possible to unregister pre/postfilter plugins.
+
+2002-04-05  Monte Ohrt  <monte@ispi.net>
+
+    * INSTALL: Remove addons file from INSTALL instructions
+
+2002-04-04  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml: update doc error
+
+    * docs/designers.sgml
+      plugins/modifier.escape.php
+      NEWS
+      Smarty.class.php: added htmlall attribute to escape modifier
+
+2002-04-03  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty_Compiler.class.php: Fixed undefined offset warning in {if} tag.
+
+    * Smarty.class.php
+      NEWS: Added template_exists() API.
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php
+      NEWS:
+    - Added $smarty.template variable.
+    - Fixed {include_php} tag when dynamic values were used for 'file' attribute.
+
+    * Config_File.class.php: Separator setting fix.
+
+2002-03-28  Monte Ohrt  <monte@ispi.net>
+
+    * FAQ
+      README: add digest address
+
+    * FAQ
+      README
+      Smarty.class.php: update mailing list addresses
+
+2002-03-28  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: *** empty log message ***
+
+    * plugins/function.html_select_date.php
+      plugins/function.html_select_time.php
+      plugins/modifier.date_format.php:
+    Fix for when plugins directory is not the default one.
+
+2002-03-28  Andrei Zmievski  <andrei@ispi.net>
+
+    * NEWS: *** empty log message ***
+
+    * plugins/function.html_select_date.php
+      plugins/function.html_select_time.php
+      plugins/modifier.date_format.php:
+    Fix for when plugins directory is not the default one.
+
+2002-03-27  Monte Ohrt  <monte@ispi.net>
+
+    * FAQ: update FAQ page
+
+2002-03-26  Andrei Zmievski  <andrei@ispi.net>
+
+    * CREDITS
+      NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      TODO: Block functions changes.
+
+    * Config_File.class.php: *** empty log message ***
+
+2002-03-25  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php: Initial implementation of block functions.
+
+2002-03-22  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml: fix documentation error in capture
+
+2002-03-22  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php: *** empty log message ***
+
+    * Smarty.class.php: Turn off notices.
+
+2002-03-21  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty_Compiler.class.php: Make _current_file available to prefilters.
+
+    * NEWS
+      Smarty.class.php:
+    Made is possible to assign variables in pre/postfilters.
+
+2002-03-20  Andrei Zmievski  <andrei@php.net>
+
+    * plugins/function.html_select_date.php: Fixed +/- functionality.
+
+    * NEWS: *** empty log message ***
+
+2002-03-20  Monte Ohrt  <monte@ispi.net>
+
+    * Config_File.class.php
+      NEWS
+      README
+      RELEASE_NOTES
+      Smarty.class.php
+      Smarty_Compiler.class.php: update version numbers
+
+    * plugins/function.html_select_date.php
+      plugins/function.html_select_time.php
+      plugins/modifier.date_format.php:
+    move .make_timestamp.php to shared.make_timestamp.php
+
+    * NEWS
+      Smarty.class.php
+      docs/designers.sgml
+      plugins/function.fetch.php
+      plugins/function.html_select_date.php:
+    update file generation, replace crc32() '-' with 'N'
+
+2002-03-20  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty_Compiler.class.php: *** empty log message ***
+
+2002-03-19  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: *** empty log message ***
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php:
+    Fix plugin behavior for inserts with script attribute.
+
+    * NEWS: *** empty log message ***
+
+    * Smarty_Compiler.class.php: Fix bug with $smarty.cookies.
+
+    * TESTIMONIALS: *** empty log message ***
+
+2002-03-15  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      docs/designers.sgml: update Changelog
+
+    * plugins/modifier.indent.php
+      plugins/modifier.wordwrap.php: add wordwrap and indent to repository
+
+2002-03-14  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php:
+    remove show_info_include and show_info_header functions
+
+2002-03-13  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/function.fetch.php: update fetch function
+
+    * plugins/function.fetch.php: update fetch function with new parameters
+
+2002-03-12  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml: update doc tables
+
+    * docs/designers.sgml: update docs columns
+
+    * docs/getting-started.sgml
+      docs/appendixes.sgml: update docs
+
+    * TESTIMONIALS
+      docs/appendixes.sgml: update syntax error in docs, add to testimonials
+
+2002-03-04  Monte Ohrt  <monte@ispi.net>
+
+    * FAQ
+      README: update FAQ, README with digest mode info
+
+2002-03-02  Monte Ohrt  <monte@ispi.net>
+
+    * QUICKSTART: update quickstart
+
+    * Smarty.class.php:
+    change behavior so cache_lifetime = 0 never expires (instead of always regenerate)
+
+2002-03-01  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml: update doc example
+
+2002-03-01  Andrei Zmievski  <andrei@php.net>
+
+    * CREDITS
+      RELEASE_NOTES
+      TODO
+      NEWS: *** empty log message ***
+
+2002-03-01  Monte Ohrt  <monte@ispi.net>
+
+    * docs/appendixes.sgml
+      docs/designers.sgml
+      docs/getting-started.sgml
+      docs/programmers.sgml: update document id tags
+
+    * docs.sgml: remove docs.sgml
+
+    * RESOURCES
+      Smarty.class.php: update resources
+
+2002-02-28  Andrei Zmievski  <andrei@php.net>
+
+    * TESTIMONIALS
+      docs/appendixes.sgml
+      docs/designers.sgml
+      docs/programmers.sgml: *** empty log message ***
+
+2002-02-27  Andrei Zmievski  <andrei@php.net>
+
+    * plugins/function.eval.php
+      docs/designers.sgml: *** empty log message ***
+
+2002-02-27  Monte Ohrt  <monte@ispi.net>
+
+    * plugins/function.eval.php: added eval function to plugin dir
+
+2002-02-27  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: *** empty log message ***
+
+2002-02-27  Monte Ohrt  <monte@ispi.net>
+
+    * docs/designers.sgml: fix syntax error
+
+    * docs/appendixes.sgml
+      docs/designers.sgml
+      docs/getting-started.sgml
+      docs/programmers.sgml: convert technical notes to docbook format
+
+    * NEWS
+      docs/designers.sgml: added "eval" plugin docs
+
+2002-02-26  Andrei Zmievski  <andrei@php.net>
+
+    * docs/programmers.sgml
+      docs/designers.sgml
+      docs/appendixes.sgml
+      docs/getting-started.sgml
+      docs/html-common.dsl
+      docs/.cvsignore: *** empty log message ***
+
+    * docs/appendixes.sgml
+      docs/common.dsl
+      docs/designers.sgml
+      docs/getting-started.sgml
+      docs/html-common.dsl
+      docs/html.dsl
+      docs/manual.sgml
+      docs/preface.sgml
+      docs/programmers.sgml: Split up docs.
+
+2002-02-25  Andrei Zmievski  <andrei@php.net>
+
+    * docs.sgml: *** empty log message ***
+
+2002-02-22  Monte Ohrt  <monte@ispi.net>
+
+    * docs.sgml: update docs
+
+2002-02-22  Andrei Zmievski  <andrei@php.net>
+
+    * docs.sgml
+      AUTHORS
+      NEWS: *** empty log message ***
+
+2002-02-21  Monte Ohrt  <monte@ispi.net>
+
+    * Config_File.class.php
+      NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      docs.sgml: update misc changes
+
+2002-02-21  Andrei Zmievski  <andrei@php.net>
+
+    * docs.sgml: *** empty log message ***
+
+2002-02-20  Monte Ohrt  <monte@ispi.net>
+
+    * docs.sgml: misc updates
+
+2002-02-20  Andrei Zmievski  <andrei@php.net>
+
+    * docs.sgml: *** empty log message ***
+
+    * Smarty.class.php
+      plugins/function.assign.php
+      plugins/function.assign_debug_info.php
+      plugins/function.counter.php
+      plugins/function.fetch.php
+      plugins/function.math.php
+      plugins/function.popup.php
+      plugins/function.popup_init.php
+      plugins/modifier.escape.php: Fixup some naming.
+
+2002-02-20  Monte Ohrt  <monte@ispi.net>
+
+    * docs.sgml: update docs
+
+2002-02-20  Andrei Zmievski  <andrei@php.net>
+
+    * docs.sgml: *** empty log message ***
+
+2002-02-20  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      docs.sgml
+      plugins/modifier.escape.php:
+    removed global vars from fetch function, added attrs to escape modifier
+
+    * docs.sgml: add plugin chapter outline
+
+2002-02-19  Monte Ohrt  <monte@ispi.net>
+
+    * README
+      RELEASE_NOTES
+      RESOURCES
+      Smarty.class.php
+      docs.sgml
+      BUGS
+      FAQ
+      INSTALL
+      QUICKSTART: update docs
+
+2002-02-19  Andrei Zmievski  <andrei@php.net>
+
+    * docs.sgml: Updated resources docs.
+
+    * README: *** empty log message ***
+
+    * docs.sgml: Updated description of {$smarty} variable.
+
+    * BUGS
+      FAQ
+      INSTALL
+      QUICKSTART
+      RELEASE_NOTES
+      docs.sgml: Remove PEAR notes.
+
+2002-02-18  Andrei Zmievski  <andrei@php.net>
+
+    * Config_File.class.php
+      NEWS: Removed dependency on PEAR.
+
+2002-02-18  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      docs.sgml
+      plugins/function.popup_init.php: add src attribute to popup_init
+
+2002-02-15  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty_Compiler.class.php
+      plugins/modifier.debug_print_var.php
+      NEWS
+      Smarty.class.php: Performance enhancements.
+
+2002-02-06  Andrei Zmievski  <andrei@php.net>
+
+    * plugins/function.html_options.php:
+    Fix html_options output to be XHTML compatible.
+
+2002-02-05  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php: Fix up plugin inclusion.
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php
+      TODO
+      plugins/function.html_select_date.php
+      plugins/function.html_select_time.php
+      plugins/modifier.date_format.php: Fix plugin directory access.
+
+2002-02-04  Andrei Zmievski  <andrei@php.net>
+
+    * .cvsignore
+      Smarty_Compiler.class.php: *** empty log message ***
+
+2002-01-31  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: *** empty log message ***
+
+    * Smarty.addons.php
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      TODO
+      plugins/function.assign.php
+      plugins/function.assign_debug_info.php
+      plugins/function.counter.php
+      plugins/function.fetch.php
+      plugins/function.html_options.php
+      plugins/function.html_select_date.php
+      plugins/function.html_select_time.php
+      plugins/function.math.php
+      plugins/function.popup.php
+      plugins/function.popup_init.php
+      plugins/modifier.capitalize.php
+      plugins/modifier.count_characters.php
+      plugins/modifier.count_paragraphs.php
+      plugins/modifier.count_sentences.php
+      plugins/modifier.count_words.php
+      plugins/modifier.date_format.php
+      plugins/modifier.debug_print_var.php
+      plugins/modifier.default.php
+      plugins/modifier.escape.php
+      plugins/modifier.lower.php
+      plugins/modifier.regex_replace.php
+      plugins/modifier.replace.php
+      plugins/modifier.spacify.php
+      plugins/modifier.string_format.php
+      plugins/modifier.strip_tags.php
+      plugins/modifier.truncate.php
+      plugins/modifier.upper.php
+      plugins/shared.make_timestamp.php
+      templates/index.tpl
+      AUTHORS
+      CREDITS
+      Config_File.class.php
+      README: Implemented plugin architecture.
+
+    * NEWS: *** empty log message ***
+
+2002-01-30  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.addons.php
+      Smarty.class.php
+      docs.sgml: added modifiers wordwrap and indent
+
+2002-01-28  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php
+      docs.sgml:
+    add support for is-modified-since headers, adjust a doc example
+
+2002-01-24  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: cleanup formatting
+
+    * NEWS
+      Smarty.class.php
+      docs.sgml: update ChangeLog, remove insert_tag_check parameter
+
+2002-01-24  Andrei Zmievski  <andrei@php.net>
+
+    * plugins/standard.plugin.php: *** empty log message ***
+
+2002-01-24  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: fix syntax error
+
+    * Smarty.class.php: removed unneccesary test from fetch()
+
+2002-01-23  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.addons.php: update overlib fixes
+
+    * NEWS: update changelog
+
+    * FAQ
+      NEWS
+      RESOURCES
+      Smarty.addons.php: updated overlib fixes
+
+2001-12-31  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php: Fixed compile_id problem.
+
+2001-12-28  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+    fixed problem with using assigned var with include_php filepath
+
+2001-12-21  Monte Ohrt  <monte@ispi.net>
+
+    * RESOURCES: update RESOURCES
+
+2001-12-20  Monte Ohrt  <monte@ispi.net>
+
+    * FAQ
+      README: update FAQ
+
+2001-12-18  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php
+      docs.sgml
+      Config_File.class.php
+      NEWS
+      README
+      RELEASE_NOTES
+      Smarty.addons.php
+      Smarty.class.php: update version numbers
+
+2001-12-18  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php: Fixed clear_cache().
+
+2001-12-14  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.addons.php:
+    fixed bug in smarty_make_timestamp introduced in PHP 4.1.0
+
+2001-12-13  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.class.php
+      docs.sgml: update default function args, fix cached insert debug timing
+
+2001-12-12  Monte Ohrt  <monte@ispi.net>
+
+    * docs.sgml: fix syntax error in documentation
+
+    * Smarty.class.php: update default template handling functionality
+
+2001-12-11  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php: update file fetching logic
+
+2001-12-11  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php: Added 'script' attribute to {insert..}.
+
+2001-12-10  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.class.php: added default template function handler
+
+    * Config_File.class.php
+      NEWS
+      README
+      RELEASE_NOTES
+      Smarty.addons.php
+      Smarty.class.php
+      Smarty_Compiler.class.php: update version numbers in files to 1.5.1
+
+2001-12-10  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php: Removed error message from the _read_file() method.
+
+    * Smarty.class.php: Fix check for compile and cache IDs.
+
+2001-12-06  Monte Ohrt  <monte@ispi.net>
+
+    * QUICKSTART: fix spelling error in QUICKSTART
+
+    * docs.sgml: fixed spelling errors in documenation
+
+    * Smarty_Compiler.class.php
+      docs.sgml
+      Config_File.class.php
+      NEWS
+      README
+      RELEASE_NOTES
+      Smarty.addons.php
+      Smarty.class.php: commit 1.5.0 release
+
+    * RESOURCES
+      docs.sgml: added RESOURCES file
+
+2001-12-05  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty_Compiler.class.php: Refactor.
+
+2001-12-05  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty_Compiler.class.php
+      docs.sgml: added assign to include and php_include
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php
+      docs.sgml: *** empty log message ***
+
+2001-12-04  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty_Compiler.class.php: Formatting.
+
+2001-12-04  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php
+      NEWS
+      Smarty.class.php: update ChangeLog
+
+2001-12-04  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php: Formatting.
+
+2001-12-04  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: removed SMARTY_DIR setting in constructor
+
+    * Smarty.class.php: fix Smarty.class.php indention error
+
+    * Smarty.class.php: update trusted logic
+
+2001-12-03  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php:
+    fix up is_secure, is_trusted, make _parse_tpl_path function
+
+    * Smarty.class.php: fix problem with testing SMARTY_DIR as empty
+
+    * NEWS
+      docs.sgml: update documentation, change log
+
+    * Smarty.class.php:
+    update constructor to check for SMARTY_DIR before assigning
+
+2001-12-03  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php: *** empty log message ***
+
+2001-12-03  Monte Ohrt  <monte@ispi.net>
+
+    * FAQ
+      INSTALL
+      RELEASE_NOTES: update a few files
+
+    * NEWS
+      QUICKSTART
+      Smarty.class.php
+      docs.sgml: added trusted_dir functionality, cleaned up secure_dir logic
+
+2001-12-03  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: *** empty log message ***
+
+    * NEWS
+      Smarty.class.php: - Introduced $compile_id class variable.
+    - Fixed a situation where if $cache_id and $compile_id were both null
+      they were passed to auto functions as empty string instead of null.
+
+2001-11-30  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.class.php:
+    change variable names in fetch() fuction to smarty_* to avoid namespace conflicts
+
+    * NEWS
+      Smarty.class.php: fixed bug in _rm_auto with catenated null values
+
+2001-11-29  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty_Compiler.class.php: Added $smarty.section.* syntax.
+
+    * Smarty_Compiler.class.php: Made 'name' attribute optional for {foreach}.
+
+2001-11-29  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php
+      index.php: remove assign "now" in index.tpl
+
+2001-11-29  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.addons.php
+      Smarty.class.php: Fix formatting.
+
+2001-11-28  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.class.php
+      docs.sgml:
+    removed return statements from _read_cache_file (how did they get in there?)
+
+2001-11-27  Monte Ohrt  <monte@ispi.net>
+
+    * docs.sgml
+      NEWS
+      Smarty.addons.php
+      Smarty.class.php:
+    fixed bugs and added assign attribute to several functions
+
+2001-11-27  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: Some rewording.
+
+    * Smarty_Compiler.class.php: Fix $smarty.capture access.
+
+    * TODO: *** empty log message ***
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+    Made {config_load ..} merge globals from each config file only once per scope.
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php: - Added {foreach ...}.
+    - Made certain $smarty.* references handled at compilation time.
+
+2001-11-26  Monte Ohrt  <monte@ispi.net>
+
+    * Config_File.class.php
+      NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      docs.sgml: commit cache handler functionality
+
+2001-11-20  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.addons.php
+      Smarty_Compiler.class.php: Various fixes and additions.
+
+    * NEWS
+      index.php: *** empty log message ***
+
+2001-11-05  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: changed _read_file parameter from $end to $lines
+
+    * NEWS
+      Smarty.class.php: fixed is_cache, make cache reading more efficient
+
+2001-11-02  Monte Ohrt  <monte@ispi.net>
+
+    * FAQ
+      NEWS: update FAQ with mailing list Reply-To header FAQ
+
+    * NEWS
+      Smarty.class.php
+      index.php: supress fopen errors, return false if cache file won't load
+
+2001-11-01  Monte Ohrt  <monte@ispi.net>
+
+    * QUICKSTART
+      docs.sgml
+      index.php: update QUICKSTART guide with index key example
+
+    * Config_File.class.php
+      NEWS
+      README
+      RELEASE_NOTES
+      Smarty.addons.php
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      docs.sgml: commit all updates for 1.4.6
+
+2001-11-01  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: *** empty log message ***
+
+2001-10-30  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.addons.php: fix assign function problem with empty value passed
+
+    * NEWS
+      Smarty.addons.php
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      templates/debug.tpl:
+    fixed bug in assign function when passing an empty value
+
+2001-10-26  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.addons.php
+      Smarty.class.php
+      index.php: fix minor typo in debug code
+
+2001-10-26  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php: Typo.
+
+2001-10-26  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.addons.php:
+    update debug console output, handle html encoding correctly
+
+2001-10-26  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.addons.php
+      templates/debug.tpl: Debug formatting.
+
+    * Smarty.class.php: Disable rmdir warning.
+
+2001-10-26  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.addons.php
+      Smarty.class.php
+      templates/debug.tpl: update debugging to expand array variables
+
+    * Smarty.class.php
+      docs.sgml:
+    update docs for fetching only timestamp with custom template source functions
+
+    * Smarty.addons.php: fix debug console error
+
+2001-10-26  Andrei Zmievski  <andrei@php.net>
+
+    * docs.sgml: Typos.
+
+    * Smarty.addons.php: Cleanup whitespace.
+
+    * Smarty_Compiler.class.php: Clean up whitespace.
+
+    * Smarty.class.php: Cleaning up code, formatting mostly.
+
+    * NEWS: *** empty log message ***
+
+2001-10-25  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      docs.sgml: update documentation to current version
+
+    * NEWS
+      Smarty.addons.php:
+    updated fetch to give proper warning when fetching unreadable or nonexistant files
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+    fixed problem with newline at the end of compiled templates
+
+    * NEWS
+      Smarty.class.php: recompile cache if config file gets modified too.
+
+    * NEWS
+      Smarty.class.php:
+    added feature to regenerate cache if compile_check is enabled and an
+    involved template is modified
+
+2001-10-23  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: fix indent for insert tags in debug console
+
+    * templates/debug.tpl: update debug.tpl file format
+
+    * NEWS
+      Smarty.addons.php
+      Smarty.class.php
+      templates/debug.tpl:
+    update execution time debugging, move into include list
+
+2001-10-10  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.addons.php
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+    fixed up execution time output in debug console
+
+2001-10-09  Andrei Zmievski  <andrei@php.net>
+
+    * Config_File.class.php
+      NEWS
+      Smarty.class.php
+      TODO: Added support for hidden config vars.
+
+2001-10-04  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.addons.php
+      Smarty.class.php
+      templates/debug.tpl: added execution times to debug console
+
+2001-10-02  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty_Compiler.class.php: Add space.
+
+2001-10-01  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php: Fix reference to compile_id.
+
+2001-09-28  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php: Added postfilter functions.
+
+2001-09-26  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php
+      docs.sgml: Rename to clear_compiled_tpl().
+
+2001-09-25  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty_Compiler.class.php:
+    Fixed line number reporting when removing comments.
+
+2001-09-20  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      RELEASE_NOTES
+      Smarty.addons.php: made html_options output xhtml compatible
+
+2001-09-19  Monte Ohrt  <monte@ispi.net>
+
+    * Config_File.class.php
+      NEWS
+      README
+      RELEASE_NOTES
+      Smarty.addons.php
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      templates/debug.tpl: updated version numbers
+
+2001-09-16  Monte Ohrt  <monte@ispi.net>
+
+    * FAQ
+      NEWS
+      docs.sgml: fix doc error with insert function
+
+2001-09-06  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: *** empty log message ***
+
+2001-08-31  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS: update ChangeLog
+
+    * overlib.js
+      Smarty.addons.php
+      Smarty.class.php
+      docs.sgml:
+    update overlib to 3.50, adjust addon code so that the overlib.js file isn't modified
+
+2001-08-31  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php: - compile_id changes
+
+    * NEWS
+      Smarty.addons.php: - compile_id support
+    - new options for html_select_date
+
+2001-08-23  Andrei Zmievski  <andrei@php.net>
+
+    * TODO: *** empty log message ***
+
+2001-08-10  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.addons.php
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+    Modified to pass Smarty object as second parameter to insert functions.
+    Also moved _smarty_mod_handler() and _smarty_insert_handler() into the class.
+
+    * NEWS
+      Smarty_Compiler.class.php:
+    Passing Smarty as second parameter to prefilter functions.
+
+2001-08-09  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: *** empty log message ***
+
+2001-08-09  Monte Ohrt  <monte@ispi.net>
+
+    * templates/index.tpl
+      Smarty.class.php: add smarty.now variable to template
+
+2001-08-06  Monte Ohrt  <monte@ispi.net>
+
+    * templates/index.tpl: change config_load section back to setup
+
+2001-08-06  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.addons.php: Optimize a bit.
+
+2001-08-04  Monte Ohrt  <monte@ispi.net>
+
+    * docs.sgml: update capture documentation
+
+2001-08-03  Monte Ohrt  <monte@ispi.net>
+
+    * FAQ
+      NEWS
+      Smarty.class.php:
+    fix bug with URL controlled debugging, works now (Monte)
+
+2001-08-01  Andrei Zmievski  <andrei@php.net>
+
+    * Config_File.class.php: *** empty log message ***
+
+    * Smarty_Compiler.class.php
+      Smarty.class.php: - Fixed some E_NOTICE stuff in compiler.
+    - Generalized assign_smarty_interface() a bit.
+
+2001-07-24  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty_Compiler.class.php
+      TODO: See ChangeLog for details.
+
+2001-07-20  Andrei Zmievski  <andrei@php.net>
+
+    * Config_File.class.php: Booleanize case-insensitively.
+
+2001-07-17  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS: update ChangeLog
+
+    * Smarty.class.php
+      docs.sgml: put SMARTY_DIR on Config_File require
+
+2001-07-11  Monte Ohrt  <monte@ispi.net>
+
+    * docs.sgml
+      FAQ
+      NEWS
+      Smarty.class.php:
+    updated security to not include insecure docs, only warning
+
+2001-07-10  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php: Adding 'sizeof' as an allowed {if} function.
+
+2001-07-06  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: *** empty log message ***
+
+2001-07-06  Monte Ohrt  <monte@ispi.net>
+
+    * Config_File.class.php
+      NEWS
+      README
+      RELEASE_NOTES
+      Smarty.addons.php
+      Smarty.class.php
+      Smarty_Compiler.class.php: update version number to 1.4.4
+
+    * NEWS
+      Smarty.addons.php
+      Smarty_Compiler.class.php
+      docs.sgml
+      templates/header.tpl
+      templates/index.tpl: update documenatation, template examples
+
+2001-07-03  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php: Implemented access to request vars via $smarty var.
+
+    * NEWS
+      Smarty_Compiler.class.php:
+    Fixed a bug with parsing function arguments in {if} tags.
+
+2001-06-30  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS: update ChangeLog
+
+2001-06-29  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.addons.php
+      Smarty.class.php
+      docs.sgml
+      overlib.js:
+    moved overlib to separate file, added SMARTY_DIR, documented. added much documentation
+
+2001-06-29  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      RELEASE_NOTES
+      TODO: *** empty log message ***
+
+2001-06-29  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      README
+      RELEASE_NOTES
+      Smarty.addons.php
+      Smarty.class.php
+      docs.sgml
+      index.php
+      templates/debug.tpl
+      templates/header.tpl
+      templates/index.tpl: update release notes
+
+2001-06-27  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty_Compiler.class.php: *** empty log message ***
+
+    * NEWS
+      Smarty_Compiler.class.php: Implemented 'step' section attribute.
+
+    * Smarty_Compiler.class.php: Negative values of 'max' will mean no max.
+
+    * AUTHORS
+      NEWS: *** empty log message ***
+
+2001-06-26  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      index.php: Added 'max' and 'start' section attributes.
+    Added 'total' and 'iteration' section properties.
+
+2001-06-25  Andrei Zmievski  <andrei@php.net>
+
+    * Config_File.class.php
+      RELEASE_NOTES
+      Smarty.addons.php
+      Smarty.class.php
+      Smarty_Compiler.class.php: Update version numbers.
+
+2001-06-23  Andrei Zmievski  <andrei@php.net>
+
+    * TODO: *** empty log message ***
+
+2001-06-21  Andrei Zmievski  <andrei@php.net>
+
+    * Config_File.class.php
+      NEWS: Fixed booleanization bug.
+
+2001-06-20  Monte Ohrt  <monte@ispi.net>
+
+    * docs.sgml:
+    update documents to reflect changes to cached content & debugging
+
+2001-06-20  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.addons.php
+      Smarty.class.php: Remove debug output for cached and fetched cases.
+
+2001-06-20  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: update include_info to false
+
+    * Smarty.class.php
+      docs.sgml
+      index.php
+      templates/footer.tpl:
+    moved debug logic into Smarty completely, created flags for it
+
+2001-06-19  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.addons.php
+      Smarty.class.php
+      templates/debug.tpl: *** empty log message ***
+
+    * NEWS
+      Smarty.class.php: Remove unneeded debug functions.
+
+2001-06-19  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.addons.php
+      Smarty.class.php
+      docs.sgml
+      templates/debug.tpl
+      templates/footer.tpl: commit updates, add debug template
+
+2001-06-19  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php
+      TODO:
+    Moved config loading code inside main class, the compiled template now
+    simply calls that method.
+
+2001-06-15  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      templates/index.tpl: * moved config array into class itself
+    * added 'scope' attribute for config_load
+
+    * Smarty_Compiler.class.php
+      Smarty.addons.php
+      Smarty.class.php: Finishing up secure mode.
+
+2001-06-15  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS: update ChangeLog
+
+    * Smarty_Compiler.class.php: cleaned up logic of if statement security
+
+    * Smarty_Compiler.class.php: update if logic to cover more situations
+
+    * Smarty_Compiler.class.php
+      docs.sgml: update if statement security feature
+
+2001-06-14  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.addons.php
+      Smarty.class.php: *** empty log message ***
+
+    * NEWS
+      Smarty_Compiler.class.php:
+    Fixed a bug with quoted strings inside if statements.
+
+2001-06-13  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.addons.php
+      Smarty.class.php: added secure_dir array for multiple secure directories
+
+    * Smarty.addons.php: update fetch funtion to respect security setting
+
+    * NEWS
+      Smarty.addons.php
+      Smarty.class.php
+      docs.sgml: update documentation, changelog
+
+    * Smarty.addons.php
+      Smarty.class.php: moved _extract setting to assign functions
+
+    * Smarty.addons.php
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+    added assign/unassign custom functions, ability to re-extract tpl_vars
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php
+      docs.sgml
+      index.php: commit security features
+
+2001-06-11  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php: Version variable typo.
+
+2001-06-05  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php:
+    Create config object in fetch() or just set the config path if it already
+    exists.
+
+2001-06-04  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php: *** empty log message ***
+
+    * NEWS
+      Smarty_Compiler.class.php:
+    Fixed a problem with $<number> inside strip tags.
+
+2001-05-31  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: *** empty log message ***
+
+    * Config_File.class.php: Allow empty config_path.
+
+2001-05-29  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php
+      docs.sgml
+      NEWS
+      README
+      RELEASE_NOTES
+      Smarty.addons.php
+      Smarty.class.php: update version numbers
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      docs.sgml: moved version variable to internal variable
+
+2001-05-22  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php:
+    Moved $_smarty_sections and $_smarty_conf_obj into Smarty class.
+
+2001-05-18  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS: update ChangeLog
+
+    * FAQ
+      QUICKSTART: update FAQ, QUICKSTART for windows include_path setup
+
+    * configs/test.conf: added configs directory to cvs
+
+2001-05-18  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php: Use compiler_class for including the file.
+
+2001-05-18  Monte Ohrt  <monte@ispi.net>
+
+    * docs.sgml: fix typo
+
+2001-05-16  Monte Ohrt  <monte@ispi.net>
+
+    * README
+      RELEASE_NOTES
+      Smarty.addons.php
+      Smarty.class.php
+      Smarty_Compiler.class.php: update files to version 1.4.1
+
+    * NEWS: update ChangeLog
+
+2001-05-15  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: *** empty log message ***
+
+    * index.php: forget that!
+
+    * NEWS
+      Smarty_Compiler.class.php
+      index.php: Fixed a few E_NOTICE warnings.
+
+2001-05-09  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      RELEASE_NOTES
+      Smarty.addons.php
+      Smarty.class.php
+      docs.sgml: update dates versions
+
+2001-05-09  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: *** empty log message ***
+
+    * Smarty.class.php:
+    Use absolute paths when requiring/including Smart components.
+
+    * NEWS: *** empty log message ***
+
+    * Smarty.class.php: Use write mode instead of append.
+
+2001-05-02  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty_Compiler.class.php: Fix indexing by section properties.
+
+2001-05-02  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS: update changelog
+
+    * Smarty.class.php: remove period from syntax error
+
+2001-05-02  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty_Compiler.class.php: Double-quote the attribute values by default.
+
+2001-04-30  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php
+      NEWS: added simple {capture} logic
+
+2001-04-30  Andrei Zmievski  <andrei@php.net>
+
+    * TODO: *** empty log message ***
+
+    * Smarty_Compiler.class.php
+      Smarty.class.php: Fix passing config vars to included files.
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php: Fix inclusion again.
+
+2001-04-30  Monte Ohrt  <monte@ispi.net>
+
+    * FAQ
+      RELEASE_NOTES
+      Smarty.class.php
+      misc/fix_vars.php
+      NEWS: update paths for windows (c:)
+
+2001-04-28  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php: Fix passing variables to included files.
+
+    * templates/index.tpl: *** empty log message ***
+
+2001-04-27  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty_Compiler.class.php: Fix includes.
+
+2001-04-26  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty_Compiler.class.php
+      docs.sgml
+      Smarty.class.php: Formatting mostly.
+
+    * Smarty_Compiler.class.php
+      Config_File.class.php: *** empty log message ***
+
+2001-04-26  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php
+      docs.sgml
+      FAQ
+      NEWS
+      QUICKSTART
+      RELEASE_NOTES
+      Smarty.class.php: update docs with new changes
+
+2001-04-26  Andrei Zmievski  <andrei@php.net>
+
+    * RELEASE_NOTES: *** empty log message ***
+
+    * docs.sgml
+      templates/index.tpl
+      NEWS
+      Smarty_Compiler.class.php: Added ability to reference object properties.
+
+2001-04-25  Andrei Zmievski  <andrei@php.net>
+
+    * README
+      Smarty.addons.php
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      docs.sgml
+      AUTHORS
+      Config_File.class.php
+      CREDITS
+      RELEASE_NOTES
+      NEWS: *** empty log message ***
+
+    * docs.sgml: Docs on new parameter to custom functions.
+
+    * NEWS: *** empty log message ***
+
+    * Smarty_Compiler.class.php:
+    Changing the way tpl vars are referenced and passing smarty object
+    to custom functions.
+
+    * RELEASE_NOTES
+      docs.sgml: Fixing docs a bit.
+
+2001-04-24  Andrei Zmievski  <andrei@php.net>
+
+    * docs.sgml: Docs for $compiler_class and compiler functions.
+
+    * templates/index.tpl: *** empty log message ***
+
+    * Smarty_Compiler.class.php: Remove debugging.
+
+2001-04-24  Monte Ohrt  <monte@ispi.net>
+
+    * docs.sgml: update compiler function docs
+
+2001-04-24  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      templates/index.tpl: Added compiler function support.
+
+2001-04-24  Monte Ohrt  <monte@ispi.net>
+
+    * RELEASE_NOTES
+      Smarty.class.php:
+    update notes, change show_info_header to false by default
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php
+      docs.sgml
+      CREDITS
+      FAQ
+      NEWS
+      README
+      RELEASE_NOTES: update documenation, bug fixes
+
+2001-04-24  Andrei Zmievski  <andrei@php.net>
+
+    * misc/fix_vars.php: Hopefully fix for sure.
+
+2001-04-23  Monte Ohrt  <monte@ispi.net>
+
+    * misc/fix_vars.php: uncomment copy/unlink
+
+2001-04-23  Andrei Zmievski  <andrei@php.net>
+
+    * misc/fix_vars.php: Do it more thoroughly.
+
+    * misc/fix_vars.php: check for }
+
+2001-04-22  Andrei Zmievski  <andrei@php.net>
+
+    * misc/fix_vars.php: Fix variable parsing.
+
+2001-04-20  Monte Ohrt  <monte@ispi.net>
+
+    * misc/fix_vars.php: fix problem with 4.0.5-dev and preg_replace_callback
+
+2001-04-19  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php
+      docs.sgml
+      misc/fix_vars.php
+      NEWS
+      RELEASE_NOTES
+      Smarty.class.php: update notes/documentation
+
+    * NEWS
+      README
+      RELEASE_NOTES
+      Smarty.addons.php
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      docs.sgml: update files for 1.4.0 release
+
+2001-04-16  Andrei Zmievski  <andrei@php.net>
+
+    * misc/fix_vars.php: Added fix_vars.php script.
+
+2001-04-16  Monte Ohrt  <monte@ispi.net>
+
+    * QUICKSTART
+      RELEASE_NOTES
+      docs.sgml
+      templates/index.tpl:
+    update RELEASE_NOTES & scripts with new section var syntax
+
+2001-04-13  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty_Compiler.class.php: * Implement new variable format parser.
+    * Optimizing config load a bit.
+
+2001-04-13  Monte Ohrt  <monte@ispi.net>
+
+    * FAQ
+      NEWS
+      RELEASE_NOTES
+      Smarty.class.php:
+    added $check_cached_insert_tags to speed up cached pages if
+          {insert ...} is not used (Monte)
+
+2001-04-12  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php
+      RELEASE_NOTES: *** empty log message ***
+
+    * Smarty_Compiler.class.php: Remove redundant functions.
+
+    * Smarty.class.php: Formatting.
+
+2001-04-12  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: update file: parsing
+
+    * Smarty.class.php
+      docs.sgml: update documentation
+
+2001-04-12  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php
+      TODO: *** empty log message ***
+
+2001-04-11  Monte Ohrt  <monte@ispi.net>
+
+    * FAQ
+      QUICKSTART
+      RELEASE_NOTES: added RELEASE_NOTES file to cvs
+
+    * NEWS
+      docs.sgml: update ChangeLog, update documentation
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php
+      templates/index.tpl:
+    update Smarty to compile at run-time. added ability to get files from
+    absolute paths, added work around for LOCK_EX and windows, changed a few
+    file permissions to be more secure.
+
+2001-03-29  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.addons.php:
+    allow arbitrary date strings instead of just timestamps
+
+2001-03-28  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php
+      docs.sgml
+      FAQ
+      NEWS
+      README
+      Smarty.addons.php:
+    update version in class, update docs for count_ and new vars
+
+    * templates/index.tpl
+      docs.sgml: update docs, example template
+
+2001-03-28  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty_Compiler.class.php: Some variable renaming.
+
+2001-03-23  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty_Compiler.class.php
+      NEWS: Fixed nested include infinite repeat bug.
+
+2001-03-23  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: fix version number
+
+    * Smarty.class.php
+      NEWS: added optional HTML header to output
+
+2001-03-22  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty_Compiler.class.php: Fixed inclusion of dynamic files.
+
+2001-03-16  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty_Compiler.class.php: Fixing the config_load scoping.
+
+    * Smarty_Compiler.class.php: making config variables global for now.
+
+2001-03-15  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: *** empty log message ***
+
+    * Smarty_Compiler.class.php:
+    * Includes are now always done via generated function call to protect
+      namespace.
+    * config_load now always uses global config object to improve
+      performance.
+
+2001-03-13  Monte Ohrt  <monte@ispi.net>
+
+    * docs.sgml: update math documentation with format attribute
+
+2001-03-11  Monte Ohrt  <monte@ispi.net>
+
+    * docs.sgml
+      NEWS
+      Smarty.addons.php
+      Smarty.class.php
+      Smarty_Compiler.class.php: update math function with format attribute
+
+2001-03-10  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.addons.php: *** empty log message ***
+
+    * NEWS
+      Smarty.addons.php
+      Smarty.class.php: Added html_select_time custom function.
+
+2001-03-08  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php
+      NEWS
+      README
+      Smarty.addons.php: rename 1.3.1b to 1.3.1pl1
+
+    * NEWS
+      Smarty.addons.php
+      Smarty.class.php
+      Smarty_Compiler.class.php: update version numbers, changelog
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php:
+    moved _syntax_error to Smarty_Compiler.class.php
+
+    * Smarty.class.php
+      docs.sgml:
+    missing _syntax_error function recovered. fixed minor syntax in docs
+
+2001-03-07  Monte Ohrt  <monte@ispi.net>
+
+    * QUICKSTART
+      README
+      Smarty.addons.php
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      BUGS
+      INSTALL
+      NEWS: update everything to 1.3.1
+
+2001-03-03  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty_Compiler.class.php
+      Smarty.class.php: fixed bug with cached insert tags
+
+2001-03-02  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php
+      Smarty_Compiler.class.php:
+    fix cache fuctions with separated compiled class
+
+    * FAQ
+      NEWS
+      docs.sgml: update changelog
+
+2001-03-02  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty_Compiler.class.php: Added 'first' and 'last' section properties.
+
+2001-03-02  Monte Ohrt  <monte@ispi.net>
+
+    * TODO: remove compiling separation TODO
+
+    * Smarty_Compiler.class.php
+      Smarty.addons.php
+      Smarty.class.php: update function headers
+
+    * templates/index.tpl
+      NEWS
+      Smarty.class.php
+      Smarty_Compiler.class.php
+      index.php: split out compiling code for faster execution
+
+    * Smarty.class.php: fixed a few warning messages
+
+    * Smarty.addons.php
+      Smarty.class.php
+      docs.sgml
+      NEWS: added fetch, unregister mod/fun, updated docs
+
+2001-03-01  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.addons.php: added "int" to available list
+
+    * docs.sgml
+      FAQ
+      Smarty.class.php: update FAQ, add math functions & update documetation
+
+    * index.php
+      Smarty.addons.php
+      Smarty.class.php
+      docs.sgml: fixed literal tags and other optional delimiters
+
+2001-02-26  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php:
+    Added index_prev, index_next section properties and ability to
+    index by them.
+
+    * NEWS
+      Smarty.addons.php
+      Smarty.class.php: Reverting the plugins patch - needs more thought.
+
+    * Smarty.class.php: Fixing plugin loading.
+
+2001-02-23  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.addons.php
+      Smarty.class.php
+      plugins/standard.plugin.php
+      NEWS: Added plugin functionality.
+
+2001-02-22  Monte Ohrt  <monte@ispi.net>
+
+    * docs.sgml
+      templates/index.tpl
+      NEWS
+      README
+      Smarty.class.php: fixed issue with php tags executed in literal blocks
+
+2001-02-21  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS: update changelog for LGPL change
+
+    * Smarty.class.php
+      docs.sgml
+      README
+      Smarty.addons.php: updated version numbers to 1.3.0
+
+    * NEWS
+      templates/index.tpl: update changelog, rearrange index.tpl file
+
+2001-02-21  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php: *** empty log message ***
+
+2001-02-21  Monte Ohrt  <monte@ispi.net>
+
+    * docs.sgml: update parameters for is_cached and fetch
+
+2001-02-21  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php: *** empty log message ***
+
+2001-02-21  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS
+      Smarty.addons.php
+      docs.sgml: update docs, remove header function from addons
+
+2001-02-20  Monte Ohrt  <monte@ispi.net>
+
+    * FAQ
+      NEWS: update changelog
+
+    * TODO: update todo
+
+    * TODO: update todo list
+
+    * Smarty.class.php: update php tag handling logic
+
+2001-02-19  Monte Ohrt  <monte@ispi.net>
+
+    * index.php
+      Config_File.class.php
+      FAQ
+      Smarty.class.php
+      docs.sgml: fixed <?php tag at beginning of files, updated docs
+
+2001-02-19  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.addons.php: *** empty log message ***
+
+2001-02-13  Andrei Zmievski  <andrei@php.net>
+
+    * TODO: *** empty log message ***
+
+2001-02-12  Andrei Zmievski  <andrei@php.net>
+
+    * templates/index.tpl
+      Smarty.class.php: *** empty log message ***
+
+2001-02-10  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: remove  unneeded preg_match
+
+    * Smarty.class.php: remove comment
+
+    * Smarty.class.php: updated php escape to handle <script language="php">
+
+    * NEWS
+      Smarty.class.php: fix php tag escapement logic
+
+    * NEWS: commit changelog
+
+    * docs.sgml: update header docs
+
+    * docs.sgml
+      Smarty.addons.php
+      Smarty.class.php: added header custom function
+
+2001-02-09  Monte Ohrt  <monte@ispi.net>
+
+    * index.php
+      templates/header.tpl
+      templates/index.tpl
+      INSTALL
+      QUICKSTART
+      docs.sgml: update documentation, add examples to test script.
+
+2001-02-08  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php: *** empty log message ***
+
+2001-02-08  Monte Ohrt  <monte@ispi.net>
+
+    * COPYING.lib: added COPYING.lib
+
+    * COPYING
+      Config_File.class.php
+      Smarty.addons.php
+      Smarty.class.php
+      docs.sgml: changed license to LGPL for commercial use
+
+    * docs.sgml
+      Smarty.class.php: fix clear_assign syntax error
+
+2001-02-07  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: added ability to pass array to clear_assign
+
+    * index.php
+      templates/index.tpl
+      docs.sgml:
+    update documentation, remove tests from index file and template
+
+2001-02-07  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php: Adding file locking.
+
+    * templates/index.tpl
+      Smarty.addons.php
+      Smarty.class.php
+      index.php: More cache work.
+
+2001-02-06  Monte Ohrt  <monte@ispi.net>
+
+    * docs.sgml
+      Smarty.class.php:
+    change register_ function names, update documents with tables
+
+2001-02-06  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php
+      templates/index.tpl: Reworking and optimizing the cache system.
+
+    * Smarty.class.php: Restoring ?> in patterns.
+
+2001-02-05  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php
+      docs.sgml: update cache directory creation logic
+
+2001-02-05  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php: Removing once-only subpattern for now..
+
+    * Smarty.class.php: Fix modifier arg parsing.
+
+2001-02-02  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      Smarty.class.php
+      templates/index.tpl: See changelog.
+
+2001-02-01  Andrei Zmievski  <andrei@php.net>
+
+    * README: *** empty log message ***
+
+    * Smarty.class.php: Use 'echo' instead of 'print'.
+
+    * Smarty.addons.php: *** empty log message ***
+
+2001-02-01  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: rearranged variables at top of script
+
+2001-02-01  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php: Retabbing.
+
+    * templates/index.tpl
+      Smarty.class.php
+      index.php: *** empty log message ***
+
+2001-02-01  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: update caching logic
+
+    * Smarty.class.php: fixed clear_all_cache bugs
+
+    * Smarty.class.php: fix .cache check
+
+    * docs.sgml
+      FAQ
+      Smarty.class.php: update .che to .cache
+
+    * FAQ
+      Smarty.class.php
+      docs.sgml: updated docs for caching, added clear_all_cache() directive
+
+2001-01-31  Monte Ohrt  <monte@ispi.net>
+
+    * index.php
+      templates/index.tpl
+      docs.sgml: upated docs for date_format and html_options
+
+2001-01-31  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: *** empty log message ***
+
+    * Smarty.addons.php
+      index.php: Added ability to pass 'options' attribute to html_options.
+
+    * Smarty.addons.php
+      Smarty.class.php
+      docs.sgml
+      index.php
+      templates/index.tpl
+      Config_File.class.php
+      NEWS
+      README: Reworking, simplifying, and speeding up cache implementation.
+    Fixing the infelicity where you couldn't have '|' and ':' inside
+    quoted modifier arguments.
+
+2001-01-31  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php
+      index.php
+      templates/index.tpl: removed DEBUG lines
+
+2001-01-30  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: changed default expire to 3600
+
+    * Config_File.class.php
+      NEWS
+      README
+      Smarty.addons.php
+      Smarty.class.php: updated version numbers
+
+    * docs.sgml
+      NEWS
+      Smarty.class.php:
+    added caching, force compile, force cache, misc performance updates
+
+2001-01-30  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS: *** empty log message ***
+
+    * Smarty.class.php
+      templates/index.tpl: Remove debug message.
+
+    * Smarty.class.php
+      templates/index.tpl: Fixing the compile directory mayhem...
+
+    * Smarty.class.php:
+    Fix problem with {strip} around {section} and {include}
+
+    * Smarty.addons.php: *** empty log message ***
+
+2001-01-29  Monte Ohrt  <monte@ispi.net>
+
+    * FAQ
+      NEWS
+      README
+      Smarty.class.php: fixed PHP_VERSION check, misc doc updates
+
+    * index.php
+      Config_File.class.php
+      NEWS
+      QUICKSTART
+      README
+      Smarty.addons.php
+      Smarty.class.php
+      docs.sgml: updated for 1.2.1 compile_dir changes, misc doc updates
+
+2001-01-26  Monte Ohrt  <monte@ispi.net>
+
+    * BUGS
+      README: update BUGS and README files
+
+    * FAQ: updated FAQ
+
+    * Config_File.class.php
+      FAQ
+      NEWS
+      README
+      Smarty.addons.php
+      docs.sgml
+      templates/index.tpl
+      AUTHORS: update again
+
+2001-01-26  Andrei Zmievski  <andrei@php.net>
+
+    * docs.sgml
+      NEWS
+      README
+      Smarty.class.php
+      templates/index.tpl: *** empty log message ***
+
+    * Smarty.class.php
+      index.php
+      templates/index.tpl: Added ability to index by key.
+
+2001-01-25  Monte Ohrt  <monte@ispi.net>
+
+    * NEWS: update changelog
+
+    * README
+      Smarty.addons.php
+      Smarty.class.php
+      docs.sgml
+      AUTHORS: updated versions to 1.1.0
+
+    * docs.sgml
+      templates/index.tpl
+      Config_File.class.php
+      Smarty.addons.php
+      Smarty.class.php: update copyright notice
+
+    * Config_File.class.php
+      Smarty.addons.php
+      Smarty.class.php
+      docs.sgml: added misc info
+
+2001-01-24  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.addons.php
+      index.php
+      templates/index.tpl
+      Config_File.class.php: initial commit
+
+2001-01-23  Monte Ohrt  <monte@ispi.net>
+
+    * docs.sgml: fix typo
+
+2001-01-22  Monte Ohrt  <monte@ispi.net>
+
+    * doc.sgm
+      docs.sgml: updated docs, renamed file
+
+    * FAQ: updated FAQ
+
+    * NEWS
+      README: updated Changelog and Readme
+
+    * doc.sgm: updated doc.sgm error
+
+    * AUTHORS
+      COPYING
+      INSTALL
+      NEWS
+      QUICKSTART: misc doc changes, added AUTHORS, COPYING
+
+2001-01-22  Andrei Zmievski  <andrei@php.net>
+
+    * NEWS
+      templates/index.tpl: *** empty log message ***
+
+    * Smarty.class.php
+      templates/index.tpl:
+    Fixed bug that wouldn't let you do specify non-array values for 'loop'
+    attribute.
+
+2001-01-22  Monte Ohrt  <monte@ispi.net>
+
+    * QUICKSTART: updated QUICKSTART
+
+    * BUGS
+      FAQ
+      INSTALL
+      README
+      doc.sgm: added BUGS and INSTALL, updated docs, FAQ, README
+
+2001-01-21  Monte Ohrt  <monte@ispi.net>
+
+    * FAQ
+      doc.sgm: updates to FAQ and docs
+
+2001-01-19  Monte Ohrt  <monte@ispi.net>
+
+    * FAQ: initial commit of FAQ
+
+    * QUICKSTART
+      README
+      doc.sgm
+      index.php:
+    updated README, doc.sgm with preg_replace() parameter issue. also removed "./" from index.php file
+
+    * NEWS: initial commit of changelog
+
+    * doc.sgm
+      QUICKSTART: update quickstart text
+
+2001-01-19  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php: Fix the compiled template check.
+
+2001-01-18  Andrei Zmievski  <andrei@php.net>
+
+    * doc.sgm: *** empty log message ***
+
+2001-01-18  Monte Ohrt  <monte@ispi.net>
+
+    * index.php
+      templates/index.tpl
+      QUICKSTART
+      Smarty.addons.php
+      Smarty.class.php
+      doc.sgm: update changes
+
+2001-01-18  Andrei Zmievski  <andrei@php.net>
+
+    * QUICKSTART
+      Smarty.addons.php: *** empty log message ***
+
+2001-01-18  Monte Ohrt  <monte@ispi.net>
+
+    * QUICKSTART
+      doc.sgm: add QUICKSTART, update docs for default modifier
+
+    * Smarty.addons.php
+      Smarty.class.php: added default modifier
+
+    * README
+      Smarty.addons.php
+      Smarty.class.php
+      doc.sgm
+      templates/index.tpl: added dislaimers
+
+2001-01-18  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php: *** empty log message ***
+
+2001-01-16  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php
+      templates/index.tpl: Implement 'div by'.
+
+2001-01-12  Monte Ohrt  <monte@ispi.net>
+
+    * doc.sgm: update docs
+
+    * doc.sgm: doc changes
+
+    * doc.sgm: update docs
+
+2001-01-12  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php
+      doc.sgm: *** empty log message ***
+
+    * Smarty.class.php: Fix template traversal.
+
+2001-01-11  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php: *** empty log message ***
+
+2001-01-09  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.addons.php
+      Smarty.class.php: *** empty log message ***
+
+2001-01-09  Monte Ohrt  <monte@ispi.net>
+
+    * doc.sgm: update manual
+
+2001-01-05  Monte Ohrt  <monte@ispi.net>
+
+    * doc.sgm
+      Smarty.addons.php: commit changes
+
+2001-01-04  Monte Ohrt  <monte@ispi.net>
+
+    * doc.sgm
+      templates/index.tpl
+      Smarty.class.php: update changes
+
+    * index.php
+      Smarty.addons.php
+      doc.sgm: add documentation
+
+2001-01-02  Monte Ohrt  <monte@ispi.net>
+
+    * index.php
+      templates/index.tpl
+      Smarty.addons.php
+      Smarty.class.php: prepend insert_ to insert tag functions
+
+    * Smarty.class.php
+      index.php
+      templates/index.tpl: remove caching logic
+
+    * README
+      Smarty.class.php
+      index.php
+      templates/index.tpl: update changes
+
+2000-12-27  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php
+      templates/header.tpl
+      templates/index.tpl
+      Smarty.addons.php: *** empty log message ***
+
+2000-12-21  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php: Fix access to template variables.
+
+    * Smarty.class.php
+      templates/header.tpl:
+    Added support for passing variables to included files.
+
+2000-12-20  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php:
+    Added support for inserting results of function processing a template.
+
+2000-12-18  Monte Ohrt  <monte@ispi.net>
+
+    * Smarty.class.php: added string_format function
+
+    * Smarty.addons.php: update format to string_format
+
+    * README
+      Smarty.addons.php
+      Smarty.class.php: added format addon function
+
+2000-12-13  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.addons.php
+      Smarty.class.php: Fix sectionelse.
+
+2000-12-07  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.addons.php
+      Smarty.class.php
+      templates/index.tpl: *** empty log message ***
+
+2000-12-04  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php
+      templates/index.tpl
+      Smarty.addons.php: *** empty log message ***
+
+2000-11-27  Andrei Zmievski  <andrei@php.net>
+
+    * templates/index.tpl
+      Smarty.class.php: *** empty log message ***
+
+2000-11-22  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php
+      templates/index.tpl: *** empty log message ***
+
+2000-11-21  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php
+      templates/index.tpl
+      Smarty.addons.php: *** empty log message ***
+
+2000-11-20  Andrei Zmievski  <andrei@php.net>
+
+    * templates/index.tpl
+      Smarty.class.php
+      Smarty.addons.php
+      index.php: *** empty log message ***
+
+    * Smarty.class.php
+      index.php
+      templates/index.tpl: Made sections work mostly.
+
+2000-11-19  Andrei Zmievski  <andrei@php.net>
+
+    * index.php
+      templates/index.tpl: *** empty log message ***
+
+2000-11-17  Andrei Zmievski  <andrei@php.net>
+
+    * Smarty.class.php
+      Smarty.addons.php: *** empty log message ***
+
+2000-11-15  Monte Ohrt  <monte@ispi.net>
+
+    * index.php
+      templates/footer.tpl
+      templates/header.tpl
+      templates/index.tpl: added template files to cvs dir
+
+    * README
+      Smarty.class.php: commit changes
+
+2000-08-08  Monte Ohrt  <monte@ispi.net>
+
+    * README
+      Smarty.class.php: update include path bug
+
+    * README: add README file
+
+    * Smarty.class.php: New file.
+
+    * Smarty.class.php: initial import
+
diff --git a/bundled-libs/Smarty/FAQ b/bundled-libs/Smarty/FAQ
new file mode 100644 (file)
index 0000000..1860678
--- /dev/null
@@ -0,0 +1,284 @@
+QUESTION INDEX
+--------------
+
+GENERAL
+
+Q: What is Smarty?
+Q: What's the difference between Smarty and other template engines?
+Q: What do you mean "Compiled PHP Scripts" ?
+Q: Why can't I just use PHPA (http://php-accelerator.co.uk) or Zend Cache?
+Q: Why does smarty have a built in cache? Wouldn't it be better to handle this
+   in a separate class?
+Q: Is Smarty faster than <insert other PHP template engine>?
+Q: How can I be sure to get the best performance from Smarty?
+Q: Do you have a mailing list?
+Q: Can you change the mailing list so reply-to sends to the list and not the
+   user?
+
+TROUBLESHOOTING
+
+Q: Smarty doesn't work.
+Q: I get the following error when running Smarty:
+   Warning:  Smarty error: problem creating directory "templates_c/239/239105369"
+   in /path/to/Smarty.class.php on line 542
+Q: I get the following error when running Smarty:
+   Warning: Wrong parameter count for preg_replace() in
+   Smarty.class.php on line 371
+Q: I get this error when passing variables to {include}:
+   Fatal error: Call to undefined function: get_defined_vars() in
+   /path/to/Smarty/templates_c/index.tpl.php on line 8
+Q: I get PHP errors in my {if} tag logic.
+Q: I'm changing my php code and/or templates, and my results are not getting
+   updated.
+Q: I'm running Windows 2000 and I get blank content. My compiled PHP files are
+   also zero length.
+Q: The template goes into an infinite loop when I include included templates
+   that pass local variables
+Q: Javascript is causing Smarty errors in my templates.
+Q: I get "SAFE MODE Restriction in effect. ..."-errors when running smarty.
+
+MISC
+
+Q: Can I use Macromedia's Dreamweaver to edit my templates?
+Q: Dreamweaver is urlencoding the template delimiters when they are in a SRC or
+   HREF link. How do I get around this?
+
+HOWTO
+
+Q: How do I generate different cache files per template based on arguments
+   passed to the page?
+Q: How do I pass a template variable as a parameter? {function param={$varname}}
+   does not work.
+Q: How do I include cached template(s) within a non-cached template?
+
+
+GENERAL
+-------
+
+Q: What is Smarty?
+A: Smarty is a template engine for PHP... but be aware this isn't just another
+   PHP template engine. It's much more than that.
+
+Q: What's the difference between Smarty and other template engines?
+A: Most other template engines for PHP provide basic variable substitution and
+   dynamic block functionality. Smarty takes a step further to be a "smart"
+   template engine, adding features such as configuration files, template
+   functions, variable modifiers (see the docs!) and making all of this
+   functionality as easy as possible to use for both programmers and template
+   designers. Smarty also compiles the templates into PHP scripts, eliminating
+   the need to parse the templates on every invocation, making Smarty extremely
+   scalable and manageable for large application needs.
+
+Q: What do you mean "Compiled PHP Scripts" ?
+A: Smarty reads the template files and creates PHP scripts from them. Once
+   these PHP scripts are created, Smarty executes these, never having to parse
+   the template files again. If you change a template file, Smarty will
+   recreate the PHP script for it. All this is done automatically by Smarty.
+   Template designers never need to mess with the generated PHP scripts or even
+   know of their existance. (NOTE: you can turn off this compile checking step
+   in Smarty for increased performance.)
+
+Q: Why can't I just use PHPA (http://php-accelerator.co.uk) or Zend Cache?
+A: You certainly can, and we highly recommend it! What PHPA does is caches
+   compiled bytecode of your PHP scripts in shared memory or in a file. This
+   speeds up server response and saves the compilation step. Smarty creates PHP
+   scripts, which PHPA will cache nicely. Now, Smarty's built-in cache is
+   something completely different. It caches the _output_ of the template
+   contents. For example, if you have a template that requires several database
+   queries, Smarty can cache this output, saving the need to call the database
+   every time. Smarty and PHPA (or Zend Cache) complement each other nicely. If
+   performance is of the utmost importance, we would recommend using one of
+   these with any PHP application, using Smarty or not. As you can see in the
+   benchmarks, Smartys performance _really_ excels in combination with a PHP
+   accelerator.
+
+Q: Why does Smarty have a built in cache? Wouldn't it be better to handle this
+   in a separate class?
+A: Smarty's caching functionality is tightly integrated with the template
+   engine, making it quite a bit more flexible than a simple caching wrapper.
+   For instance, you can cache select portions of a template page. Let's say
+   you have a polling box on your site. With Smarty, you can leave the poll
+   dynamic and cache the rest of the page. You can also pass templates
+   multiple cache ids, meaning that a template can have several caches
+   depending on URL, cookies, etc.
+
+Q: Is Smarty faster than <insert other PHP template engine>?
+A: See the benchmark page for some performance comparisons. Smarty's approach
+   to templates is a bit different from some languages: it compiles templates
+   into PHP scripts instead of parsing them on each invocation. This usually
+   results in great performance gains, especially with complex templates.
+   Coupled with the built-in caching of Smarty templates, the performance is
+   outstanding.
+
+Q: How can I be sure to get the best performance from Smarty?
+A: Be sure you set $compile_check=false once your templates are initially
+   compiled. This will skip the unneeded step of testing if the template has
+   changed since it was last compiled. If you have complex pages that don't
+   change too often, turn on the caching engine and adjust your application so
+   it doesn't do unnecessary work (like db calls) if a cached page is
+   available. See the documentation for examples.
+   
+Q: Do you have a mailing list?
+A:  We have a few mailing lists. "general" for you to share your ideas or ask
+       questions, "dev" for those interested in the development efforts of Smarty,
+       and "cvs" for those that would like to track the updates made in the cvs
+       repository.
+
+    send a blank e-mail message to:
+      smarty-general-subscribe@lists.php.net (subscribe to the general list)
+      smarty-general-unsubscribe@lists.php.net (unsubscribe from the general list)
+      smarty-general-digest-subscribe@lists.php.net (subscribe to digest)
+      smarty-general-digest-unsubscribe@lists.php.net (unsubscribe from digest)
+      smarty-dev-subscribe@lists.php.net (subscribe to the dev list)
+      smarty-dev-unsubscribe@lists.php.net (unsubscribe from the dev list)
+      smarty-cvs-subscribe@lists.php.net (subscribe to the cvs list)
+      smarty-cvs-unsubscribe@lists.php.net (unsubscribe from the cvs list)
+    You can also browse the mailing list archives at
+    http://marc.theaimsgroup.com/?l=smarty&r=1&w=2
+
+
+
+Q: Can you change the mailing list so Reply-To sends to the list and not the
+   user?
+A: Yes we could, but no we won't. Use "Reply-All" in your e-mail client to send
+   to the list. http://www.unicom.com/pw/reply-to-harmful.html
+
+TROUBLESHOOTING
+---------------
+
+Q: Smarty doesn't work.
+A: You must be using PHP 4.0.6 or later if you use any version of Smarty
+   past 2.0.1. Read the BUGS file for more info.
+
+Q: I get the following error when running Smarty:
+   Warning:  Smarty error: problem creating directory "templates_c/239/239105369"
+   in /path/to/Smarty.class.php on line 542
+A: Your web server user does not have permission to write to the templates_c
+   directory, or is unable to create the templates_c directory. Be sure the
+   templates_c directory exists in the location defined in Smarty.class.php,
+   and the web server user can write to it. If you do not know the web server
+   user, chmod 777 the templates_c directory, reload the page, then check the
+   file ownership of the files created in templates_c. Or, you can check the
+   httpd.conf (usually in /usr/local/apache/conf) file for this setting:
+   User nobody
+   Group nobody
+
+Q: I get the following error when running Smarty: Warning: Wrong parameter
+   count for preg_replace() in Smarty.class.php on line 371
+A: preg_replace had a parameter added in PHP 4.0.2 that Smarty
+   requires. Upgrade to at least 4.0.6 to fix all known PHP issues with
+   Smarty.
+
+Q: I get this error when passing variables to {include}:
+   Fatal error: Call to undefined function: get_defined_vars() in
+   /path/to/Smarty/templates_c/index.tpl.php on line 8
+A: get_defined_vars() was added to PHP 4.0.4. If you plan on passing
+   variables to included templates, you will need PHP 4.0.6 or later.
+
+Q: I get PHP errors in my {if} tag logic.
+A: All conditional qualifiers must be separated by spaces. This syntax will not
+   work: {if $name=="Wilma"} You must instead do this: {if $name == "Wilma"}.
+   The reason for this is syntax ambiguity. Both "==" and "eq" are equivalent
+   in the template parser, so something like {if $nameeq"Wilma"} wouldn't be
+   parsable by the tokenizer.
+
+Q: I'm changing my php code and/or templates, and my results are not getting
+   updated.
+A: This may be the result of your compile or cache settings. If you are
+   changing your php code, your templates will not necessarily get recompiled
+   to reflect the changes. Use $force_compile during develpment to avoid these
+   situations. Also turn off caching during development when you aren't
+   specifically testing it. You can also remove everything from your
+   compile_dir and cache_dir and reload the page to be sure everything gets
+   regenerated.
+
+Q: I'm running Windows 2000 and I get blank content. My compiled PHP files are
+   also zero length.
+A: There seems to be a problem with some W2k machines and exclusive file
+   locking. Comment out the flock() call in _write_file to get around this,
+   although be aware this could possibly cause a problem with simultaneous
+   writes to a file, especially with caching turned on. NOTE: As of Smarty
+   1.4.0, a workaround was put in place that should solve this.
+
+Q: The template goes into an infinite loop when I include included templates
+   that pass local variables
+A: This was fixed in 1.3.2 (new global attribute)
+
+Q: Javascript is causing Smarty errors in my templates.
+A: Surround your javascript with {literal}{/literal} tags. See the docs.
+
+Q: I get "SAFE MODE Restriction in effect. ..."-errors when running smarty.
+A: Use $smarty->use_sub_dirs = false when running php in safe mode.
+
+MISC
+----
+
+Q: Can I use Macromedia's Dreamweaver to edit my templates?
+A: Certainly. You might want to change your tag delimiters from {} to something
+   that resembles valid HTML, like <!--{ }--> or <{ }> or something similar.
+   This way the editor won't view the template tags as errors.
+
+Q: Dreamweaver is urlencoding the template delimiters when they are in a SRC or
+   HREF link. How do I get around this?
+A: In Edit - Properties - Rewrite HTML you can specify if Dreamweaver should
+   change special letters to %-equivalent or not. The default is on which
+   produces this error.
+
+HOWTO
+-----
+   
+Q: How do I generate different cache files per template based on arguments
+   passed to the page?
+A: Use your $REQUEST_URI as the cache_id when fetching the page:
+
+   global $REQUEST_URI; // if not already present
+   $smarty->display('index.tpl',$REQUEST_URI);
+
+   This will create a separate cache file for each unique URL when you call
+   index.tpl. See the documentation for display() and fetch()
+
+Q: How do I pass a template variable as a parameter? {function param={$varname}}
+   does not work.
+A: {function param=$varname} (You cannot nest template delimiters.)
+
+Q: How do I include cached template(s) within a non-cached template?
+A: One way to do it:
+
+   $smarty->caching = true;
+   $tpl1 = $smarty->fetch("internal1.tpl");
+   $tpl2 = $smarty->fetch("internal2.tpl");
+   $tpl3 = $smarty->fetch("internal3.tpl");
+
+   $smarty->assign("tpl1_contents",$tpl1);
+   $smarty->assign("tpl2_contents",$tpl2);
+   $smarty->assign("tpl3_contents",$tpl3);
+
+   $smarty->caching = false;
+   $smarty->display('index.tpl');
+
+   index.tpl
+   ---------
+
+   <table>
+           <tr>
+                   <td>{$tpl1_contents}</td>
+                   <td>{$tpl2_contents}</td>
+                   <td>{$tpl3_contents}</td>
+           </tr>
+   </table>
+
+
+
+
+   Another approach:
+
+   You could write a custom insert function to fetch your internal
+   templates:
+
+   <table>
+           <tr>
+                   <td>{insert name=fetch_tpl tpl="internal1.tpl"}</td>
+                   <td>{insert name=fetch_tpl tpl="internal2.tpl"}</td>
+                   <td>{insert name=fetch_tpl tpl="internal3.tpl"}</td>
+           </tr>
+   </table>
diff --git a/bundled-libs/Smarty/INSTALL b/bundled-libs/Smarty/INSTALL
new file mode 100644 (file)
index 0000000..f622ee8
--- /dev/null
@@ -0,0 +1,29 @@
+REQUIREMENTS:
+
+Smarty requires PHP 4.0.6 or later.
+See the on-line documentation for complete install instructions.
+
+INSTALLATION (quick):
+
+* copy the files under the libs/ directory to a directory that is in your PHP
+  include_path, or set the SMARTY_DIR constant and put them in this directory.
+  (if you upgrade from versions before 2.5.0 be aware that up to Smarty 2.4.2
+  all necessary files where in the distribution's root directory, but are now
+  in libs/.)
+
+* for each application using Smarty, create a "templates", "configs", and a
+  "templates_c" directory, be sure to set the appropriate directory settings in
+  Smarty for them. If they are located in the same directory as your
+  application, they shouldn't need to be modified. Be sure the "templates_c"
+  directory is writable by your web server user (usually nobody). chown
+  nobody:nobody templates_c; chmod 700 templates_c You can also chmod 777 this
+  directory, but be aware of security issues for multi-user systems. If you are
+  using Smarty's built-in caching, create a "cache" directory and also chown
+  nobody:nobody.
+
+* setup your php and template files. A good working example is in the on-line
+  documentation.
+
+* TECHNICAL NOTE: If you do not have access to the php.ini file, you can change
+  non-server settings (such as your include_path) with the ini_set() command.
+  example: ini_set("include_path",".:/usr/local/lib/php");
diff --git a/bundled-libs/Smarty/NEWS b/bundled-libs/Smarty/NEWS
new file mode 100644 (file)
index 0000000..75c4d31
--- /dev/null
@@ -0,0 +1,858 @@
+Version 2.6.5 (Sept 13, 2004)
+-----------------------------
+
+  - fixed some parsing problems with object calls introduced
+    in 2.6.4 (Monte)
+  - add $smarty->security_settings['ALLOW_CONSTANTS']. note: this
+    defaults to false which means you have to allow them explicitely
+    in your secured templates from now on! (messju)
+
+Version 2.6.4 (Sept 7, 2004)
+----------------------------
+
+  - add $smarty.ldelim and $smarty.rdelim to smarty special var (Monte)
+  - fall back to old uniqid()-behaviour when tempnam() fails in
+    core.write_file.php (messju)
+  - fix capitalize modifier, don't rely on buggy ucwords (Monte)
+  - make html_select_date work with negative timestamps, also
+    force year range to include given date unless explicitly
+    set (Garo, Monte)
+  - fix bug with {fetch}, passing user/pass in url did not work
+    (Monte)
+  - fix occasional wrong error messages on mismatched tags when
+    {else}, {elseif}, {foreachelse} or {sectionelse} is involved (messju)
+  - fix handling of methods arguments (messju, Manfred Wischin)
+  - remove touch() call that made the compiled-template's timestamp the
+    same as the source-template's one. (messju)
+  - add assign attribute to html_checkboxes and html_radios
+    (pcg, Monte)
+  - remove non-xhtml conformant tag from mailto function
+    (tacker, Monte)
+  - handle date_format codes %e, %T and %D for windows (tip,
+    Monte)
+  - fix unnecessary call to smarty_core_get_include_path() inside
+    Smarty::_get_auto_filename() (c960657, messju)
+  - add error-messages when anything else than an identifier is passed
+    to foreach's key- or item-attribute (messju)
+  - fix handling of digits inside tagnames (messju)
+  - fix escaping of backslashes in Smarty_Compiler::_quote_replace() (messju)
+
+Version 2.6.3 (June 16, 2004)
+-----------------------------
+
+  - added escapement of '</' to '<\/' in escape:javascript
+    modifier (c960657, Monte)
+  - added obfuscation of protocol-string in {mailto} when using hex-
+    encoding (bharat, messju)
+  - enhanced auto-generated filenames for templates_c and cache (messju)
+  - add 'nonstd' to escape modifier for escaping non-std chars,
+    such as ms doc quote (Monte)
+  - adjusted textformat to not output wrap chars after last para
+    (Monte)
+  - use tempnam() instead of unqid() to create better temporary files in
+    smarty_core_write_file() (xces, messju)
+  - add 'mail' to escape modifier for safe display of e-mail
+    addresses (Monte)
+  - add cycle function attribute "reset" to english docs (Monte)
+  - enhanced support of numeric constants as variable-expressions (messju)
+  - add case decentity to smarty_modifier_escape() (Konstantin A. Pelepelin,
+    messju)
+  - make smarty_core_write_compiled_include() php5-aware (messju)
+  - removed unused functionality to load a subset of lines from a file (messju)
+  - fix is_secure() should only check if a file is_readable, not if
+    the directory where it is in is readable (sagi, messju)
+  - fix problem displaying debug console when $default_resource_type
+    is not "file:" (c960657, Monte)
+  - fix permission handling with security and config_load (messju)
+  - removed '.' from the list of default template locations in
+    _parse_resource_name() (messju)
+  - fix avoid warning with template_exists() on an absolute paths (messju)
+  - fix parameters passed to resource's secure()-function (messju)
+  - fix handling of integer values like width and delay im
+    smarty_function_popup() (messju)
+
+Version 2.6.2 (Feb 17, 2004)
+----------------------------
+
+  - fix allow empty years, months and days in html_select_date's
+    time-attribute (messju)
+  - fix YES and NO should not be booleanized inside triple-quotes in a
+    config-file (messju)
+  - fix accidently slurped line following a triple-quoted value in a
+    config-file (messju)
+  - change default for use_sub_dirs to false (messju)
+  - fix quoting of values in smarty_function_popup() (messju)
+  - fix handling of hidden sections in Config_File (messju)
+  - add handling of resources for {config_load} (messju)
+  - fix bug when using arrays with tr_attr and td_attr in {html_table} (messju)
+  - add unit testing to cvs core (Monte)
+
+Version 2.6.1 (Jan 16, 2004)
+----------------------------
+
+  - rename $smarty->tpl_error_reporting to $smarty->error_reporting
+    (messju)
+  - fix interpretation of $smarty->security in {html_image} (messju)
+  - add caching of requested paths to _assemble_plugin_filepath() (messju)
+  - fix handling of comments inside {php}- and {literal}-blocks (messju)
+  - fix bug handling triple-quotes in config-files (BRDude, messju)
+  - change default of request_use_auto_globals to true - $_SERVER is
+    now preferred over $HTTP_SERVER_VARS (messju)
+  - re-add support for $SCRIPT_NAME (messju)
+  - reactivate $smarty->default_modifiers (messju)
+  - add cookie persistance to debug console (Monte)
+  - allow single-digit days and months without smarty_make_timestamp()
+    in html_select_date (messju)
+  - fix headers sent erroneously with cache_modified_check and fetch()
+    (wphilips, messju)
+  - fix config_file path bug (Marc Cabadas, Monte)
+  - fix 'is even by' and 'is odd by' logic (Monte)
+  - add day_empty, month_empty, year_empty and all_empty attributes to
+    html_select_date (messju)
+  - add table of explanation for {if} qualifiers in docs (boots)
+  - fix bug when comparing array-keys to "selected" in html_options
+    and html_checkboxes (messju)
+  - add better checks for correctly nested tags when compiling (messju)
+  - remove {$SCRIPT_NAME}. use {$smarty.server.SCRIPT_NAME} instead (messju)
+  - remove $global_assign. assign global variables explicitly instead (messju)
+  - fix example for count_characters in docs (boots)
+  - add section new basic syntax section "Escaping Smarty Parsing" in docs (boots)
+  - fix error handler call in config_load (boots)
+  - remove warning in debug_print_var on php-resources (messju)
+  - move function.assign.php to compiler.assign.php (messju)
+  - add property $tpl_error_reporting (messju)
+  - remove property $undefined. "null" is used literally instead (messju)
+
+Version 2.6.0 (Nov 19, 2003)
+----------------------------
+
+  - move Smarty::quote_replace() to Smarty_Compiler::_quote_replace() (messju)
+  - remove import of of attributes of {include_php} to php's namespace.
+    use $params[name] instead (messju)
+
+Version 2.6.0-RC3 (Nov 13, 2003)
+--------------------------------
+
+  - fix handling of $var.key inside [] (messju)
+  - fix handling of assign inside {insert}-tags (messju)
+  - fix handling if [...] inside triple-quotes in config-files (messju)
+  - fix handling of simple-math-operators inside modifiers (Dominik, messju)
+  - fix handling of trailing-slashes in open_basedir in
+    smarty_core_create_dir_structure() (packman, messju)
+
+Version 2.6.0-RC2 (Oct 8, 2003)
+-------------------------------
+
+  - apply modifiers only once to section-loop and foreach-from attrs (messju)
+  - remove use of _smarty_cached_paths-files (messju)
+  - remove Smarty::_plugin_implementation_exists() - use is_callable() (messju)
+  - ignore {strip}/{/strip) inside {strip}-blocks (messju)
+  - fixed removal of leading/trailing newlines in {strip}-blocks (messju)
+  - fixed proper escaping of " and ' with escape:javascript (messju)
+  - fixed bug in traversal of $smarty->plugins_dir-array. now the
+    first matching plugin is taken (messju)
+  - moved {strip} back into the compiler (messju)
+  - fixed config_load: handling of section-attribute and use of
+    multiple config-files in one template (atu, messju)
+
+Version 2.6.0-RC1 (August 11, 2003)
+-----------------------------------
+
+  - fixed status-header for cache_modified_check under cgi-sapi (messju)
+  - added optional parameter $cache_attrs to register_function() and
+    register_block(). $cache_attrs is an array containing attribute-
+    names that should be cached on calls to functions that have
+    $cacheable set to false. (messju)
+  - enabled registration of class-methods as callbacks for the register_*-
+    functions (use: array('classname', 'method_name')) as callback) (messju)
+  - added filepath caching (Monte)
+  - added optional assign-attribute to {capture}-tag (messju)
+  - added $cacheable-parameter to register_compiler_function() (messju)
+  - added $cacheable-parameter with default=true to register_function()
+    and register_block() (messju)
+  - add math speedup to core (Dominik, Monte)
+  - fix newlines for tags without template output (Monte)
+  - added config-option "request_use_auto_globals" to make auto-globals be
+    used as request vars instead of HTTP_*_VARS (messju)
+  - speed up config_load, simplify compiling (Monte)
+  - added block-methods for registered objects (Bharat Mediratta, messju)
+  - ignore one char resource names like c:foo.tpl (Monte)
+  - added default_resource_type feature (Monte)
+  - fix bug where config file starts with hidden section (boots, Monte)
+  - add discrete error checking pertaining to $cache_dir
+    and $compile_dir, their existance and writability (Monte)
+  - fixed behaviour of start=... for {counter} (messju)
+  - fixed assign for {counter} (messju)
+  - added params vdir, hdir and inner to html_table to allow looping
+    over the data in various directions (messju)
+  - allow spaces in literal tags (Paul Lockaby, Monte)
+  - speed up compiled templates, hardcode plugin filepaths
+    instead of dynamically calculate at runtime. (Monte)
+  - abstract many core components from Smarty.class.php,
+    speeding up core class instantiation (Monte)
+  - fixed bug in _create_dir_structure() when used with open_basedir-
+    restriction and relative paths (messju)
+  - use DIRECTORY_SEPARATOR exclusively, keep DIR_SEP for BC (Monte)
+  - changed "link" to "href" in html_image. "link" is still working
+    but deprecated (messju)
+  - html_image always renders an alt-tag now (default alt="") (messju)
+  - fixed assign attribute for multiple counters (messju)
+  - added simple math operators to variables (Monte)
+  - enabled array(&$obj. 'source', 'timestamp', 'secure', 'trusted')
+    as callback for register_resource() (messju);
+  - enabled array(&$obj, 'method') as callback for
+    $default_template_handler_func (messju)
+  - remove unnecessary close/open tags from compiled templates
+    (Monte)
+  - fixed errornous creation of '//' in image_path in html_image (messju)
+  - fix escapement of special chars for key vals in debug
+    console (Monte)
+  - fixed debug timing logic for config_load (Tom Sommer, Monte)
+  - all in-code doc comments converted to phpDocumentor format (Greg)
+  - moved strip from smarty core to plugin (Monte)
+  - moved config_load from smarty core to plugin (Monte)
+  - added &$repeat-parameter to block-functions (messju)
+  - enabled hex-constants in function.math.php (messju)
+  - enabled hex-constants (0x...) as function-attributes, inside if-statements
+    and as modifier-parameters (messju)
+  - fixed bug with passing $smarty as reference in Smarty.compiler.class
+    (messju)
+  - corrected output with {strip} and PHP tag newlines (Monte)
+  - added possibility to register function-callbacks as "array(&$obj, 'method)"
+    this affects register_function(), -block, -compiler_function, -modifier,
+    -prefilter, -postfilter, -outputfilter-functions() and $cache_handler_func
+    (messju)
+  - added <labels> to html_checkboxes and html_radios (Philippe, messju)
+  - added "labels"-options to turn off labels in html_checkboxes and _radios
+    (messju)
+
+Version 2.5.0 (April 11, 2003)
+------------------------------
+
+   - fixed bug with default modifier when passing integer 0
+     (Monte)
+   - change backtic syntax from $`foo` to `$foo` (Monte)
+   - recognize $foo[][] syntax inside embedded quotes without
+     backtics (Monte)
+   - name=123 is passed as an integer (not a string) to plugins now (messju)
+   - $length is now propagated to sub-values in debug_print_var (messju)
+
+Version 2.5.0-RC2 (March 26, 2003)
+----------------------------------
+
+    - made clear_cache() ignore compile_id, when clearing cache-groups (this
+      is when no $tpl_file is supplied) (messju)
+    - made onmouseout XHTML-compliant in function.popup.php (messju)
+    - applied local-var-naming-scheme to fetch() (messju)
+    - renamed $localvars to $_localvars in cache-file-handling-functions,
+      added _get_auto_id()-function (messju)
+    - swapped compile_id and cache_id in read_cache_file and write_cache_file
+      (messju)
+    - reverted patch for cache-file-handling (messju)
+    - made html_radios and html_checkboxes accept "selected" instead
+      of "checked" optionally. (messju)
+    - made compile_id ignored in clear_cache, made order of
+      auto_file_name $cache_id.$compile_id again, applied the the new
+      variable-naming-scheme for cache_file_handing functions (messju)
+    - removed notice of undefined var in _rm_auto() (messju)
+    - added warning message when an array is passed as
+      the "checked" value of html_radios (Monte)
+    - fixed errormessage in _compile_smarty_ref() (messju)
+    - updated docs for html_image "name" -> "file" (messju)
+    - fixed bug with html_options-optgroups (Nichlas Löfdahl, messju)
+    - cleaned up calls to readdir() (messju)
+    - fixed bug with passing multiple modifiers to a parameter
+      (Monte)
+    - updated docs for html_checkboxes, html_options and html_radios (messju)
+    - fixed wrong default "name" attribute for html_options (messju)
+    - html_checkboxes now expect the options as attribute "options" instead
+      of "checkboxes. html_radios expect "options" instead of "radios".
+      cleaned up indentiation (messju)
+    - fixed too greedy str_replace in trimwhitespace outputfilter (messju)
+    - html_checkboxes and html_radios passthru all unknown paramters now
+      additionally their output is now XHTML compliant (messju)
+    - html_options passthru all unknown paramters now (messju)
+    - fix link functionality of html_image, also make
+      output XHTML compatible (Hinrich Donner, Monte)
+    - append "@" to default modifier vars/args
+      supress possible warnings (Monte)
+    - fix problem with escaped double quotes (Monte)
+    - fix html_radios to not return an array (Monte)
+    - fixed length in modifier.truncate.php (messju)
+    - fixed handling of '$'-signs in trimwhitespace outputfilter (messju)
+    - fix bug that makes config files recompile every time
+      (Nagger, Monte)
+    - add dpi functionality to html_image, change "name"
+      parameter to "file" (Thomas Shulz, Monte)
+    - fix height/width parameter index in html_image (Gerard,
+      Monte)
+    - get rid of unsetting name and script attributes
+      to insert tag (Thomas Schulz, Monte)
+    - changed argument order of string_format modifier back,
+      was right in the first place (Monte)
+
+Version 2.5.0-RC1 (March 5, 2003)
+---------------------------------
+
+    - fixed notice in popup function (Nagger, Monte)
+    - fix "once" var compiling for include_php (Monte)
+    - added nl2br modifier to distribution (Monte)
+    - added html_image to distribution (Monte)
+    - added cat modifier to distribution (Monte)
+    - added html_table to distribution (Monte)
+    - added << >> <> support to if statments (SMK, Monte)
+    - fix _assign_smarty_interface to not overwrite keys
+      other than 'request' (Jerome Poudevigne, Monte)
+    - added html_checkboxes to distribution (Christopher Kvarme, Monte)
+    - added html_radios to distribution (Christopher Kvarme, Monte)
+    - fixed string_format modifier args (wrong order) (Paul
+      Lockaby, Monte)
+    - use tmp file for file writes, avoid file lock race (Monte)
+    - support syntax "$`smarty.config.foo`.tpl" for embedded
+      vars in quotes, and allow full dollar var syntax (Monte)
+    - add $smarty.config.varname variable for accessing config vars (Paul
+      Lockaby, Monte)
+    - silence PHP warnings in function.fetch.php (Eduardo,
+      Monte)
+    - added get_config_vars(), same basic functionality as
+      get_template_vars() (Monte)
+    - update get_template_vars() to be able to get
+      individual vars (Monte)
+    - fix minor logic in _fetch_template_info (Dennis Gearon,
+      Monte)
+    - fix cache groups with compile_id set (Monte)
+    - add support for merging appended vars (messju, Monte)
+    - allow null as function attribute value
+      (André Rabold, Monte)
+    - support $foo->bar[index] syntax (Monte)
+    - add get_registered_object function (messju, Monte)
+    - treat unrecognized param attribute syntax as string (Monte)
+    - support $smarty.const.$foo syntax (messju, Monte)
+    - remove E_NOTICE warnings from debug.tpl,
+      escape modifier (Kanstantin, Monte)
+    - don't count non-ascii chars in count_words modifier
+      (Kanstantin, Monte)
+    - clean up param calls to _parse_var and _parse_attrs (Monte)
+    - define $template_source var, elude possible warning
+      (Monte)
+    - fix syntax problem with evaluating PHP constants (Monte)
+    - add @ and === as valid if statement tokens (Monte)
+    - enable error messages for config_load errors,
+      use $this->config_class for loading class name (Monte)
+    - fix html_options to not escape already escaped entities (Monte)
+    - send Last-Modified header on cache creation (Monte)
+    - check strict syntax of function attributes (Monte)
+    - dropped support for modifers on object parameters,
+      added support for objects as modifier parameters (Monte)
+    - fixed bug with decimal numbers in if statements (Monte)
+
+Version 2.4.2 (Feb 11, 2003)
+----------------------------
+    - support embedded variables in objects (Monte)
+    - fix bug with objects with no properties (M Mohr, Monte)
+    - support full dollar var syntax in quoted text (Monte)
+    - fixed bug in $smarty.const.FOO introduced in 2.4.1 (M
+      Mohr, Monte)
+
+Version 2.4.1 (Feb 6, 2003)
+---------------------------
+
+    - ignore case in IF statements (Rainer Collet, Monte)
+    - treat undefined constants as null (Ferdinand Beyer, Monte)
+    - fix problem with inserts and nested fetches
+      (Rainer Collet, Monte)
+    - added support for passing params to include_php
+      (Tim Riley, Monte)
+    - added support for math operators in if statements (Monte)
+    - added support for $foo->bar[$x].blah syntax (Monte)
+
+Version 2.4.0 (Feb 2, 2003)
+---------------------------
+
+    - fix known problems with php tag handling in templates
+      (recursion, echoing xml tags) (Monte)
+    - add support for object registration (Monte)
+    - add debug template to secure_dir, add template_dir
+      to secure_dir by default (Ferdinand Beyer, Monte)
+    - added support for assigned object access (Monte)
+    - fixed bug with directories named '0' (Frank Bauer, Monte)
+    - add javascript parameter to escape modifier (Monte)
+    - added calling function line numbers to syntax error
+      messages in compiler (Monte)
+    - added support for modifiers to function calls (Monte)
+    - support return value for custom functions
+      instead of echoing (but echo still works) (Monte)
+    - added direct access to constants
+      via $smarty.const.FOO (Monte)
+    - added support for passing modifiers
+      to static values (Monte)
+    - fix up regex code in compiler, more accurate and
+      maintainable (Monte)
+    - added day_value_format to html_select_date (Marcus
+      Bointon, Monte)
+    - assigned variables are no longer in global
+      namespace, saving extract() calls and speeding
+      up fetch() and display() linearly with no. of
+      assigned variables (Monte)
+    - added trimwhitespace output filter to dist. (Monte)
+    - fix popup function to allow newlines in text (Monte)
+    - escape html entities in html_options (Monte)
+    - fixed bug with label for html_options (Monte)
+    - added config_load API function (Monte)
+    - added caching to config file loading (Monte)
+    - added "extra" parameter to mailto function (Monte,
+      Massimiliano Perantoni)
+    - added mailto plugin to dist.  (Monte)
+
+Version 2.3.1 (Nov 19, 2002)
+----------------------------
+
+    - added optgroup support to html_options (Monte, Robert
+      Amos)
+    - set mtime on compile files so they match source
+      files (Monte, Peter Bowen)
+    - added proper support for open_basedir setting
+      (Monte, Alessandro Astarita)
+    - added strip variable modifier, updated docs (Monte)
+    - fixed access to $smarty.x variables as arrays. (Andrei)
+    - fixed errors with example setup docs (Monte, Matthew
+      Hagerty)
+    - added textformat block function (Monte)
+
+Version 2.3.0 (Aug 7, 2002)
+---------------------------
+
+    - added assign_by_ref() and append_by_ref() functions
+      (Bob Silva, Monte)
+    - changed default warning type for plugin errors from
+      E_USER_WARNING to E_USER_ERROR (Monte)
+    - added $all_extra, $hour_extra, $minute_extra,
+      $second_extra and $meridian_extra parameters to
+      html_select_time function (Rainer Collet, Monte)
+    - update debug console to print objects (Simon Willison,
+      Monte)
+    - fix Config_File class to not error when there are no
+      sections (Peter Kmet, Monte)
+    - add default modifier logic (Monte)
+    - updated popup_init to be xhtml compliant (Tom Oram, Monte)
+    - fix filename bug with windows (Gary Loescher, Monte)
+    - add ability to supply expire time in seconds when clearing
+      cache or compile files (Monte)
+    - add {debug} plugin to distribution (Monte)
+    - fixed bug with insert tags, loading from "script" attribute
+      when caching is enabled (Monte)
+    - fix bug with debug_tpl file path with Windows (.SMK., Monte)
+    - fix append() function with string/array problem (Monte)
+
+Version 2.2.0 (July 11, 2002)
+-----------------------------
+
+    - make debug.tpl work with any delimiter (Monte)
+    - change logic in assign() and append() to test var names
+      against != '' instead of empty() (Monte)
+    - fix PHP notice in append() function (Monte)
+    - allow $plugins_dir to be an array of directories
+      (Andreas Kossmeier, Monte)
+    - move debug.tpl to SMARTY_DIR, add to constructor (Monte)
+    - fixed warning message in function.assign_debug_info (Monte)
+    - fixed $template_dir, $compile_dir, $cache_dir, $config_dir,
+      $plugin_dir to respect include_path (Monte)
+    - fixed warning message with output filter array (Monte)
+    - add optional 2nd parameter to date_format, used as
+      the default date if the passed date is empty (Monte)
+    - gave $reset a default value in cycle plugin (Monte)
+    - fixed warnings with html_select_date and timestamp
+      functions (Monte)
+    - added support for sub directory exlusion format (Monte)
+    - added support for grouping by cache_id, compile_id
+      and segments thereof (Monte)
+    - changed cache and compile files to human readable
+      format (Monte)
+    - remove overlib.js file from distribution (Monte)
+    - fixed bug with 304 Not Modified response sending
+      content (Monte)
+    - fixed cycle function to respect delimiter after
+      initial setting (Monte)
+    - update $GLOBALS references to work properly with
+      track_globals settings (Michal Prinke, Monte)
+    - fixed bug in math function with call to assign
+      (Grigory V. Kareev, Monte)
+    - optimized for loops with count() function calls (Monte)
+    - add month_value_format attribute to html_select_date
+      plugin (Gary Loescher, Monte)
+    - made it possible to use simple variables inside [] for
+      indexing. (Andrei)
+    - added "once" attribute to {include_php}. (Monte)
+
+Version 2.1.1
+-------------
+    - added cycle function. (Monte)
+    - fixed bug with resource testing, and include_path. (Monte)
+    - fixed a bug with register_outputfilter function. (Monte)
+
+Version 2.1.0
+-------------
+
+    - introduced output filters. (Andrei)
+    - changed the way filters are loaded, added load_filter()
+      API function and $autoload_filters variable. (Andrei)
+    - added caching logic for expire times per cache file
+      (Norbert Rocher, Monte)
+    - fixed html_select_date when field separator is "/"
+      (Roberto Berto, Monte)
+    - added YYYY-MM-DD format support to html_select_date
+      (Jan Rosier, Monte)
+    - fixed cache_lifetime logic bug, also made -1 = never
+      expire (Monte)
+    - fixed directory separator issue for Windows. (Andrei)
+    - added ability to use simple variables as array indices or
+      object properties. (Andrei)
+    - added ability to unregister pre/postfilters plugins at
+      runtime. (Andrei)
+    - added 'htmlall' attribute to escape modifier. (Monte)
+    - added template_exists() API function. (Andrei)
+    - fixed a problem with using dynamic values for 'file'
+      attribute of {include_php} tag. (Andrei)
+    - added $smarty.template variable. (Andrei)
+    - fixed several plugins that would not work if the plugin
+      directory was not the default one. (Andrei)
+    - implemented support for block functions. (Andrei)
+    - made it possible to assign variables in pre/postfilter
+      plugins. (Andrei)
+
+Version 2.0.1
+-------------
+    - rename plugin .make_timestamp.php to shared.make_timestamp.php.
+      (Monte)
+    - changed crc32() generated values, replace '-' with 'N'. (Monte)
+    - added support for +/- N syntax in html_select_date year values.
+      (Monte)
+    - fixed behavior of inserts with script attribute. (Andrei)
+    - fixed bug with $smarty.cookies and $smarty.server. (Andrei)
+    - wordwrap and indent are missing from 2.0 release, now fixed.
+      (Monte)
+    - removed show_info_header and show_info_include variables. (Monte)
+
+Version 2.0.0
+-------------
+    - added "eval" function plugin for evaluating variables as
+      templates. (Monte)
+    - removed $tpl_file_ext class variable, no longer used. (Monte)
+    - added "hex" and "hexentity" escape types to escape modifier.
+      (Monte)
+    - removed dependency on PEAR. (Andrei)
+    - update popup_init to accept src attribute. (Monte, Duncan Forrest)
+    - implemented several optimizations, speeding up Smarty
+      significantly in most cases. (Andrei,Monte)
+    - implemented plugin architecture. (Andrei)
+    - added wordwrap and indent modifiers. (Monte)
+    - added support for 'If-Modified-Since' headers for cached content.
+      (Monte)
+    - removed insert_tag_check class variable, no longer needed. (Monte)
+    - optimized cache fetches by scanning for insert tags only if they
+      exist. (Monte)
+    - fixed bugs in overlib. (Monte, Duncan Forrest)
+    - fixed a problem with compile_id usage. (Andrei)
+    - fixed problem with using assigned vars with {include_php ...}
+      filepath. (Monte)
+
+Version 1.5.2
+-------------
+    - added Smarty object as fifth argument for template resource functions.
+      (Monte)
+    - fixed a bug with incorrectly combined cache and compile id in
+      clear_cache(). (Andrei)
+    - fixed bug in smarty_make_timestamp introduced in PHP 4.1.0. (Monte)
+    - fixed bug with cached insert debug timing. (Monte)
+    - added 'script' attribute to {insert..} which specifies the script that
+      the insert function can be found in. (Andrei)
+    - added default template function handler. (Monte)
+
+Version 1.5.1
+-------------
+    - removed error message from the generic _read_file() method, the caller
+      should take care of that. (Andrei)
+    - fixed a bug with incorrectly combined cache and compile id. (Andrei)
+
+Version 1.5.0
+-------------
+    - added include_php built-in function, documented. (Monte)
+    - added trusted_dir functionality, documented. (Monte)
+    - consolidated secure_dir tests to one function. (Monte)
+    - prepended _smarty_ to variable names in fetch() class function to avoid
+      namespace conflicts. (Monte)
+    - introduced $compile_id class variable that can be used to set persistent
+      compile identifier across multiple display calls, documented. (Andrei)
+    - fixed bug with concatenated null cache and compile identifiers. (Andrei)
+    - added $smarty.section.* syntax for accessing section properties,
+      documented. (Andrei)
+    - added custom cache handling function ability, documented. (Monte)
+    - added assign attribute to include, include_php, insert, fetch, math, and
+      counter functions, documented. (Monte)
+    - fixed bug with fetch testing for local file when http address. (Monte)
+    - fixed bug with counter and skipval setting. (Monte)
+    - made {config_load ...} merge globals from each config file only once per
+      scope, thus avoiding several problems. (Andrei)
+    - added {foreach ...} tag that can be used to iterate through
+      non-sequential and associative arrays, documented. (Andrei)
+    - speeded up section property access a bit. (Andrei)
+    - removed $smarty variable from storage used by normal template variables,
+      to prevent any problems. (Andrei)
+    - fixed a bug that could cause parse error with quotes inside literal
+      blocks. (Andrei, Alexander Belonosov)
+    - added 'field_array' attribute to html_select_time function, documented.
+      (Andrei, Michael Caplan)
+    - documented {section} "max" attribute. (Monte)
+    - fixed notice message in Smarty_Compiler.class.php. (Monte)
+    - fixed bug with clear_cache introduced in 1.4.6, third parameter should
+      default to null. (Monte)
+    - updated Config_File class to support '\' path separator in OS/2. (Monte,
+      Francesco Cipriani)
+    - removed secure_ext setting (not used). (Monte)
+    - made cache reading process more efficient. (Monte)
+    - fixed bug, is_cached() now supports new 1.4.6 caching behavior. (Monte)
+    - update FAQ with mailing list Reply-To header FAQ. (Monte)
+    - supress error messages for fopen(), fix cache to regenerate if cache
+      file is not available (i.e. cluster race condition). (Monte)
+    - added index key example to QUICKSTART guide. (Monte)
+
+Version 1.4.6
+-------------
+    - fixed bug with {assign ...} when passing an empty value. (Monte)
+    - add more warning message fixes. (Monte, Tara Johnson)
+    - documentation updates. (Monte)
+    - update fetch function to give proper warning when fetching a non-readable
+      or non-existant file. (Monte)
+    - fixed problem with newline at the end of included templates (Monte, Andrei)
+    - added feature to regenerate cache if compile_check is enabled and an
+      involved template or config file gets modified. (Monte)
+    - added DEBUG execution times to included files: REQUIRES updated debug.tpl
+      file! (Monte)
+    - added support for hidden config variables that cannot be read by
+      templates. (Andrei)
+    - added execution time to DEBUG console, total and inserts. (Monte)
+    - fixed bug where DEBUG console would not appear with cached content. (Monte)
+    - added support for postfilter functions that are applied to compiled
+      template right after compilation. (Andrei)
+    - fixed the name of clear_compile_tpl() API function to clear_compiled_tpl.
+      (Andrei)
+    - added fix for removing comments so that the line numbers are reported
+      correctly in case of errors. (patch from Anders Janson)
+    - made html_options output xhtml compatible code. (Monte, Arnaud Limbourg)
+
+Version 1.4.5
+-------------
+    - update FAQ with index of questions at the top
+    - update overlib to 3.50, adjust addon code so that the overlib.js
+      file isn't modified, and not using the mini one. (Monte)
+    - added many more options to html_select_date. (Alexander Skwar, Andrei)
+    - added support for generating different compiled templates from the same
+      source template. (Hans-Peter Oeri, Andrei)
+    - modified Smarty to pass itself to insert functions as the second
+      parameter. (Andrei)
+    - modified Smarty to pass itself to prefilter functions as the second
+      parameter. (Andrei)
+    - fixed syntax error when including a non-existant template with security
+      enabled. (Monte)
+    - fixed comments handling to allow commenting out template blocks. (Andrei)
+    - implemented named capture buffers, with results accessible via
+      $smarty.capture.<name>. (Andrei)
+    - added ability to index arrays directly by numbers. (Andrei)
+    - fixed bug with SMARTY_DIR not prepended to Config_File include. (Monte)
+
+Version 1.4.4
+-------------
+    - fixed problem with including insecure templates with security enabled.
+      (Monte)
+    - numerous documentation updates. (Monte)
+    - added ENT_QUOTES to escapement of html. (Monte, Sam Beckwith)
+    - implemented access to request variables via auto-assigned $smarty
+      template variable. (Andrei)
+    - fixed a bug with parsing function arguments inside {if} tags if a comma
+      was present. (Andrei)
+    - updated debug console with config file vars. (Monte)
+    - added SMARTY_DIR constant as an alternative to relying on include_path.
+      (Monte)
+    - added popup_init and popup functions (requires overlib.js). (Monte)
+    - updated debug console with config file vars. (Monte)
+    - added debugging url control. (Monte)
+    - added 'quotes' type to escape modifier. (Monte, Mike Krus)
+    - added 'total' and 'iteration' section properties. (Andrei)
+    - added 'start', 'max', and 'step' section attributes/properties. (Andrei)
+    - fixed a bug with security checking of functions inside {if} tags.
+      (Andrei)
+    - fixed a bug in Config_File that would incorrectly booleanize values that
+      weren't really booleans. (Andrei)
+
+Version 1.4.3
+-------------
+    - added regex_replace modifier, documented. (Monte)
+    - added debugging console feature and custom function assign_debug_info,
+      documented. (Monte)
+    - added 'scope' attribute for {config_load}, 'global' is now deprecated but
+      is still supported. (Andrei)
+    - reduced template symbol table pollution by moving config array into the
+      class itself. (Andrei)
+    - fixed a bug with passing quoted arguments to modifiers inside {if}
+      statements. (Andrei, Sam Beckwith)
+    - added security features for third party template editing, documented
+      (Monte)
+    - added assign custom function, documented. (Monte)
+    - fixed bug with template header using version instead of _version. (Monte)
+    - fixed a problem with putting $ followed by numbers inside {strip} and
+      {/strip} tags. (Andrei)
+    - fixed Config_File class to allow empty config paths (defaults to current
+      directory). (Andrei)
+
+Version 1.4.2
+-------------
+    - move $version to internal variable, remove from docs. (Monte)
+    - cleaned up compiled templates global scope by moving some variables into
+      the class itself. (Andrei)
+    - fixed a bug that would not allow referring to a section in the including
+      file from the included file. (Andrei)
+    - configs directory missing from 1.4.1 release, added back in. (Monte)
+    - added windows include_path setup instructions to FAQ & QUICKSTART.
+      (Monte)
+
+Version 1.4.1
+-------------
+    - fix LOCK_EX logic for all windows platforms (Monte)
+    - fixed indexing by section properties with the new syntax. (Andrei)
+    - updated Smarty to use absolute paths when requiring/including Smarty
+      components. (Andrei, John Lim)
+
+Version 1.4.0
+-------------
+    - added {capture}{/capture} function, documented (Monte)
+    - added {counter} function, documented (Monte)
+
+Version 1.4.0b2
+---------------
+    - fixed issue in Config_File.class with referencing blank sections (Andrei)
+    - fixed problem with passing variables to included files (Andrei)
+    - fixed resource path recognition for windows (Monte)
+
+Version 1.4.0b1
+---------------
+    - added "componentized templates" tip into documentation (Monte)
+    - added {php}{/php} tags for embedding php code into templates (Monte)
+    - changed default value of $show_info_header to false (Monte)
+    - implemented '->' syntax for accessing properties of objects passed to the
+      template. (Andrei)
+    - allowed custom functions to receive Smarty object as the second
+      parameter; this can be used to dynamically change template variables, for
+      example. (Andrei)
+    - added custom compiler functions support, register_compiler_function() and
+      unregister_compiler_function() API functions. (Andrei, Ivo Jansch).
+    - updated GLOBAL_ASSIGN to take SCRIPT_NAME from HTTP_SERVER_VARS
+      instead of global variable. You can also assign several variables
+      in one shot with an array. (Monte, Roman Neuhauser)
+    - added template prefilters, register_prefilter() and
+      unregister_prefilter() API functions. (Monte)
+    - added RELEASE_NOTES file to distribution. (Monte)
+    - moved CREDITS out of manual into its own file. (Monte)
+    - added register_resource() and unregister_resource() API functions. (Monte)
+    - changed the syntax of indexing template variables, thus supporting
+      structures of arbitrary complexity; supplied fix_vars.php script to fix
+      old syntax. (Andrei)
+    - added $insert_tag_check to speed up cached pages if {insert ...} is not
+      used. (Monte)
+    - added $compiler_class variable to allow specifying a different compiler
+      class. (Andrei)
+    - changed Smarty to compile templates at runtime, allowing for arbitrary
+      template resources. (Monte)
+    - added fix for LOCK_EX under Windows and changed a couple of file
+      permissions for security. (Monte, Fernando Nunes)
+    - allow arbitrary date strings to date_format, html_select_date and
+      html_select_time (Monte)
+
+Version 1.3.2
+-------------
+    - fixed a bug that caused some nested includes to loop infinitely. (Andrei)
+    - added optional HTML header to output. (Monte)
+    - significantly improved config_load performance. (Andrei)
+    - added format attribute to math function. (Monte)
+    - added html_select_time custom function. (Andrei)
+    - fixed minor PHP warning when attempting to unset an unset variable
+      (Monte)
+    - added count_characters, count_words, count_sentences, count_paragraphs
+      modifiers (Monte)
+
+Version 1.3.1pl1
+--------------
+    - bug fix, recovered missing _syntax_error function (Monte)
+
+Version 1.3.1
+-------------
+    - document first, last, index_prev, index_next (Monte)
+    - added 'first' and 'last' section properties. (Andrei)
+    - split out compiling code to separate class for faster template execution
+      time (Monte)
+    - fixed a couple of minor PHP warnings (Monte)
+    - added and documented unregister_modifier() and unregister_function() API
+      calls. (Monte)
+    - added and documented 'fetch' and 'math' functions. (Monte)
+    - added ability to index looped variables by section properties, e.g.
+      $foo.index_prev/bar. (Andrei)
+    - added index_prev and index_next section properties. (Andrei)
+    - fixed issue with php executing in literal blocks. (Monte)
+
+Version 1.3.0
+-------------
+    - moved license from GPL to LGPL (Monte)
+    - implemented workaround for PHP "feature" that eats carriage returns
+      if the PHP tag is at the end of the line. (Andrei)
+    - removed $allow_php, added $php_handling logic (Monte)
+    - added file locking to prevent reader/writer problem. (Andrei)
+    - made Smarty catch unimplemented modifiers and custom functions and output
+      error messages during compilation instead of failing during run time.
+      (Andrei)
+    - removed short-tags at the top of the smarty scripts (Monte)
+    - added register_function() and register_modifier() API calls to make
+      registering stuff easier. (Andrei)
+    - added template results caching capability. (Monte, Andrei)
+    - added optional 'options' attribute to html_options custom function
+      that allows passing associative arrays for values/output. (Andrei)
+    - modifier arguments can now contain '|' and ':' characters inside quoted
+      strings. (Andrei)
+
+Version 1.2.2
+-------------
+    - fixed bug that would not respect nested template directories and would
+      put all compiled files into top-level one. (Andrei)
+    - fixed bug using $PHP_VERSION instead of environment var PHP_VERSION.
+      (Monte)
+    - a couple small warning fixes. (Monte)
+
+Version 1.2.1
+-------------
+    - added $compile_dir, removed $compile_dir_ext, simplified usage. (Monte)
+    - added tips & tricks chapter to documentation. (Monte)
+    - misc documentation updates. (Monte)
+
+Version 1.2.0
+-------------
+    - updated documentation (Monte)
+    - added file and line number information to syntax error messages. (Andrei)
+    - added ability to index template vars by a key. (Andrei)
+
+Version 1.1.0
+-------------
+    - misc documentation changes, official stable release
+
+Version 1.0b
+------------
+    - fixed the bug that prevented using non-array values for 'loop' attribute.
+      (Andrei)
+    - many misc documentation changes & additions (Monte)
+
+Version 1.0a
+------------
+    - fixed bug that caused templates to recompile every time (Monte)
+
+Version 1.0
+------------
+    - initial release
+
+/* vim: set et tw=64 ft=changelog: */
diff --git a/bundled-libs/Smarty/README b/bundled-libs/Smarty/README
new file mode 100644 (file)
index 0000000..10ff6ea
--- /dev/null
@@ -0,0 +1,80 @@
+NAME:
+
+    Smarty - the PHP compiling template engine
+
+VERSION: 2.6.0
+
+AUTHORS:
+    
+    Monte Ohrt <monte@ispi.net>
+    Andrei Zmievski <andrei@php.net>
+
+MAILING LISTS:
+
+    We have a few mailing lists. "general" for you to share your ideas or ask
+       questions, "dev" for those interested in the development efforts of Smarty,
+       and "cvs" for those that would like to track the updates made in the cvs
+       repository.
+
+    send a blank e-mail message to:
+      smarty-general-subscribe@lists.php.net (subscribe to the general list)
+      smarty-general-unsubscribe@lists.php.net (unsubscribe from the general list)
+      smarty-general-digest-subscribe@lists.php.net (subscribe to digest)
+      smarty-general-digest-unsubscribe@lists.php.net (unsubscribe from digest)
+      smarty-dev-subscribe@lists.php.net (subscribe to the dev list)
+      smarty-dev-unsubscribe@lists.php.net (unsubscribe from the dev list)
+      smarty-cvs-subscribe@lists.php.net (subscribe to the cvs list)
+      smarty-cvs-unsubscribe@lists.php.net (unsubscribe from the cvs list)
+    You can also browse the mailing list archives at
+    http://marc.theaimsgroup.com/?l=smarty&r=1&w=2
+
+SYNOPSIS:
+
+    require("Smarty.class.php");
+
+    $smarty = new Smarty;
+
+    $smarty->assign("Title","My Homepage");
+    $smarty->assign("Names",array("John","Gary","Gregg","James"));
+
+    $smarty->display("index.tpl");
+
+
+DESCRIPTION:
+
+    What is Smarty?
+
+    Smarty is a template engine for PHP. Many other template engines for PHP
+    provide basic variable substitution and dynamic block functionality.
+    Smarty takes a step further to be a "smart" template engine, adding
+    features such as configuration files, template functions, and variable
+    modifiers, and making all of this functionality as easy as possible to
+    use for both programmers and template designers. Smarty also converts
+    the templates into PHP scripts, eliminating the need to parse the
+    templates on every invocation. This makes Smarty extremely scalable and
+    manageable for large application needs.
+
+    Some of Smarty's features:
+
+    * it is extremely fast
+    * no template parsing overhead, only compiles once.
+       * it is smart about recompiling only the template files that have
+         changed.
+    * the template language is remarkably extensible via the plugin
+      architecture.
+    * configurable template delimiter tag syntax, so you can use
+      {}, {{}}, <!--{}-->, or whatever you like.
+    * built-in caching of template output.
+    * arbitrary template sources (filesystem, databases, etc.)
+    * template if/elseif/else/endif constructs are passed to the PHP parser,
+      so the if syntax can be as simple or as complex as you like.
+    * unlimited nesting of sections, conditionals, etc. allowed
+    * it is possible to embed PHP code right in your template files,
+      although not recommended and doubtfully needed since the engine
+      is so customizable.
+    * and many more.
+
+COPYRIGHT:
+    Copyright (c) 2001,2002 ispi of Lincoln, Inc. All rights reserved.
+    This software is released under the GNU Lesser General Public License.
+    Please read the disclaimer at the top of the Smarty.class.php file.
diff --git a/bundled-libs/Smarty/RELEASE_NOTES b/bundled-libs/Smarty/RELEASE_NOTES
new file mode 100644 (file)
index 0000000..d5e95f5
--- /dev/null
@@ -0,0 +1,423 @@
+2.5.0
+-----
+
+Very minor adjustments since RC2, see the NEWS file for details.
+
+2.5.0-RC2
+---------
+
+Many fixes since the RC1 release. This one is as close to production quality as
+they come, so this will be the last release before 2.5.0. The SGML documentation
+files have also been removed from the tarball. If you want them, get them from
+the CVS repository.
+
+2.5.0-RC1
+---------
+
+Release Candidate 1. All $smarty vars can now be dynamic, such as
+$smarty.get.$foo. A new class function get_function_object() gets you a
+reference to an assigned object, useful within your own custom functions.
+append() can now merge as well as append with a third optional attribute. A new
+class function get_config_vars() was added, and get_template_vars() can now be
+used to get individual vars. Full variable syntax is now supported within
+double quotes via a backtick (`) syntax. Files created by smarty are now
+written to a tmp file then renamed to avoid file lock retention. html_radios,
+html_checkboxes, html_table, html_image, nl2br functions added, see the NEWS
+file for full details.
+
+2.4.2
+-----
+Another point release. Added support for dynamic object reference syntax
+($foo->$bar), support for full variable syntax within quotes ("$foo[0].bar"),
+and other minor fixes. See the NEWS file for full details.
+
+2.4.1
+-----
+
+This is basically a point release, cleaning up a few things caught
+in the 2.4.0 release. See the NEWS file for full details.
+
+2.4.0
+-----
+
+Smarty now supports the ability to access objects within the templates. Two
+methods are available, one which closely follows Smartys conventions, and
+another that follows more traditional object syntax for those familiar with
+PHP.
+
+The internal compiling engine has also undergone some major work. The regex
+parsing was rewritten to be much more strict, more secure and more
+maintainable. Config files are now compiled, which can speed up pages quite a
+bit that use config files extensively. Assigned variables are no longer
+extracted to PHP namespace, saving an extract call for every template. There is
+now support for applying modifiers to static values and functions. You can now
+access constants with $smarty.const.VAR.  See the NEWS file for complete
+changes.
+2.3.1
+-----
+
+The mtime on compiled files will now match the source files, in the case where
+the source file may not get the current timestamp, recompiling will still work
+as expected. Proper support for open_basedir has been added, so Smarty should
+work correctly in safe mode. Added a few new features such as textformat block
+function, strip variable modifier and optgroup support for html_options. Also
+other minor bug fixes, see the Change Log.
+
+2.3.0
+-----
+
+Smarty now has a {debug} template function that brings up the debugging console
+right where {debug} is called, regardless of $debugging settings. This works a
+little different than turning on $debugging in the sense that it shows all the
+template variables available at the time {debug} is called, including local
+scope vars. It does not show the templates names however, since this
+executed during runtime of the template.
+
+You can now supply an expire time when clearing cache or compile files. This is
+mostly useful for removing stale files via the API.
+
+Plugins now stop execution upon error, instead of outputting a warning and
+continuing.
+
+Two new API functions, assign_by_ref() and append_by_ref() were added. They
+allow assigning template variables by reference. This can make a significant
+performance gain, especially if you are assigning large arrays of data. PHP 5.0
+will do this implicitly, so these functions are basically workarounds.
+
+Several misc bug fixes, see the Change Log for information.
+
+
+2.2.0
+-----
+
+Smarty now allows an array of paths for the $plugin_dir class variable. The
+directories will be searched in the order they are given, so for efficiency keep
+the most-used plugins at the top. Also, absolute paths to the plugin directories are
+more efficient than relying on the PHP include_path.
+
+Cache files can now be grouped with the cache_id. See the documentation under
+the new "Caching" section for details. compile_id also respects the same
+grouping syntax. The cache/compile file structure changed, so be sure to clear
+out all your cache and compile files when upgrading Smarty. Also if you are
+using PHP-accelerator, restart apache. I've seen some quirky things happen if
+the phpa files do not get cleared (known issue with phpa and parent
+class-member changes, so just clear 'em.)
+
+Smarty now correctly respects the PHP include_path for $template_dir, $compile_dir,
+$cache_dir, $config_dir and $plugin_dir. Be aware that relying on the
+include_path is an overhead, try to use absolute pathnames when possible
+(or relative to working directory.)
+
+Documentation has been updated and rearranged a bit. Most notably, the
+installation instructions are completely revamped, and a new Caching section
+explains Smarty's caching in detail along with the new grouping functionality.
+
+Many misc. bug fixes and enhancements, see the full ChangeLog (NEWS file) for
+details.
+
+2.1.1
+-----
+
+There was a bug with template paths and the include_path, this has been fixed.
+Also register_outputfilter() did not work, this is fixed. A new template
+function named "cycle" has been added to the distribution, nice for cycling
+through a list (or array) of values.
+
+2.1.0
+-----
+
+This release has quite a few new features and fixes. Most notable are the
+introduction of block functions, so you can write plugins that work on a block
+of text with {func}{/func} notation. Also output filters were added, so you can
+apply a function against the output of your templates. This differs from the 
+postfilter function, which works on the compiled template at compile time, and
+output filters work on the template output at runtime.
+
+Many other features and bug fixes are noted in the NEWS file.
+
+
+2.0.1
+-----
+
+This is a point release, fixing a few bugs and cleaning things up. A plugin
+was renamed, the dash "-" was removed from compiled template and cached file
+names. If you're upgrading, you might want to clear them out first.  See the
+ChangeLog for details.
+
+2.0.0
+-----
+
+This release is a huge milestone for Smarty. Most notable new things are a
+plugin architecture, removal of PEAR dependency, and optimizations that
+drastically improve the performance of Smarty in most cases.
+
+The plugin architecture allows modifiers, custom functions, compiler functions,
+prefilters, postfilters, resources, and insert functions to be added by
+simply dropping a file into the plugins directory. Once dropped in, they are
+automatically registered by the template engine. This makes user-contributed
+plugins easy to manage, as well as the internal workings of Smarty easy to
+control and customize. This new architecture depends on the __FILE__ constant,
+which contains the full path to the executing script. Some older versions of
+PHP incorrectly gave the script name and not the full filesystem path. Be sure
+your version of PHP populates __FILE__ correctly. If you use custom template
+resource functions, the format of these changed with the plugin architecture.
+Be sure to update your functions accordingly. See the template resource section
+of the documentation.
+
+The PEAR dependancy was removed from Smarty. The Config_File class that comes
+with Smarty was actually what needed PEAR for error handling which Smarty didn't
+use, but now everything is self-contained.
+
+Performance improvements are graphed on the benchmark page, you will see that
+overall performance has been sped up by as much as 80% in some cases.
+
+Smarty-cached pages now support If-Modified-Since headers, meaning that if a
+cached template page has not changed since the last request, a "304 Not
+Modified" header will be sent instead of resending the same page. This is
+disabled by default, change the setting of $cache_modified_check.
+
+
+1.5.2
+-----
+
+Mostly bug fixes, added a default template resource handler.
+
+
+1.5.1
+-----
+
+Critical bug fix release. If you use caching, you'll need to upgrade.
+
+
+1.5.0
+-----
+
+Several feature enhancements were made to this version, most notably the
+{foreach ...} command which is an alternative to {section ...} with an easier
+syntax for looping through a single array of values. Several functions were
+enhanced so that the output can be automatically assigned to a template
+variable instead of displayed (assign attribute). Cache files can now be
+controlled with a custom function as an alternative to the built-in file based
+method. Many code cleanups and bug fixed went into this release as well.
+
+
+1.4.6
+-----
+
+The behavior with caching and compile_check has been slightly enhanced. If
+caching is enabled AND compile_check is enabled, the cache will immediately get
+regenerated if _any_ involved template or config file is updated. This imposes
+a slight performance hit because it must check all the files for changes, so be
+sure to run live sites with caching enabled and compile_check disabled for best
+performance. If you update a template or config file, simply turn on
+compile_check, load the page, then turn it back off. This will update the cache
+file with the new content. This is accomplished by maintaining a list of
+included/loaded templates and config files at the beginning of the cache file.
+Therefore it is advisable to remove all cache files after upgrading to 1.4.6
+(although not absolutely necessary, old cache files will regenerate)
+
+The debug console now has script timing and array values printed. You MUST
+update your debug.tpl file with this version of Smarty. Also, the new debug.tpl
+will not work with older versions of Smarty.
+
+
+1.4.5
+-----
+
+Mostly bug fixes and minor improvements. Added compile id for separate compiled
+versions of the same script. The directory format and filename convention for
+the files in templates_c has changed, so you may want to remove all of the
+existing ones before you upgrade.
+
+
+1.4.4
+-----
+
+A few bug fixes, new section looping attributes and properties, debugging
+console function for control via URL, and overLib integration and access
+to request variables from within the template.
+
+
+1.4.3
+-----
+
+This release has a few bug fixes and several enhancements. Smarty now supports
+template security for third-party template editing. These features disallow the
+ability for someone to execute commands or PHP code from the template language.
+Smarty also now has a built-in debugging console, which is a javascript pop-up
+window that displays all the included template names and assigned variables.
+
+
+1.4.2
+-----
+
+This was mostly one bug fix with variable scoping within included templates
+and a few documentation changes and updates. See the ChangeLog file for full
+details.
+
+
+1.4.1
+-----
+
+It seems that the EX_LOCK logic from the previous release didn't fix all the
+problems with windows platforms. Hopefully this one does. It basically
+disables file locking on windows, so there is a potential that two programs
+could write over the same file at the same time, fyi.
+
+The reset is minor bug fixes, please refer to the ChangeLog file.
+
+
+1.4.0
+-----
+
+IMPORTANT NOTICE
+
+Smarty now has a new syntax for accessing elements within section loops. The
+new syntax is easier to use and nicely handles data structures of any
+complexity. Consequently, this breaks the old syntax.
+
+Here is an example of the syntax change:
+
+old syntax:
+{$sec1/sec2/sec3/customer.phone}
+
+new syntax:
+{$customer[$sec1][$sec2][$sec3].phone}
+
+The section names used to come first, followed by the variable name. Now the
+variable name always comes first, followed by the section names in brackets.
+You can access variable indexes anywhere, depending on how you passed the
+variables in.
+
+To fix your current templates, we have provided a script that will adjust the
+syntax for you. Located in misc/fix_vars.php, run this script from the the
+command line, giving each template as an argument. Be sure to use absolute
+pathnames, or pathnames relative to the executing script. Probably the easiest
+way to do this is to copy the fix_vars.php script into your template directory
+and run 'php -q fix_vars.php *.tpl' Be sure you have proper write permission,
+and backup your scripts first to be safe! The examples in the 1.4.0
+documentation have been updated to reflect the changes.
+
+cd /path/to/templates
+cp /path/to/fix_vars.php .
+find . -name "*.tpl" -exec php -q ./fix_vars.php {} \;
+
+NEW AND IMPROVED COMPILATION PROCESS
+
+Smarty 1.4.0 also has a new compilation process. Instead of compiling all the
+templates up front, it now compiles them at runtime. This has several
+advantages. First of all, there is no longer a need to have a single template
+directory. You can now have arbitrary template sources, such as multiple
+directories or even database calls. This also speeds the performance of Smarty
+when $compile_check is enabled, since it is only checking the template that is
+being executed instead of everything found in the template directory. The
+$tpl_file_ext is no longer needed, but kept for backward compatability.
+Templates can now be named anything you like with any extension.
+
+MINOR FIXES
+
+A workaround for LOCK_EX on Windows systems was added, and changed a couple of
+file permissions for better security on public servers.
+
+$show_info_header is now defaulted to false instead of true. This header causes
+problems when displaying content other than HTML, so now you must explicitly
+set this flag to true to show the header information (or change the default in
+your copy of Smarty.)
+
+Documentation is written in docbook format. I updated the docbook -> HTML
+generating software & style-sheets, and consequently the examples are no longer
+in a different background color. If anyone wants to contribute a better
+stylesheet or help with documentation, drop me a line. <monte@ispi.net>
+
+CHANGES/ENHANCEMENTS/UPDATES
+
+date_format, html_select_date and html_select_time used to require a unix
+timestamp as the format of the date passed into the template. Smarty is now a
+bit smarter at this. It will take a unix timestamp, a mysql timestamp, or any
+date string that is parsable by strtotime, such as 10/01/2001 or 2001-10-01,
+etc. Just give some formats a try and see what works.
+
+Smarty now has template prefilters, meaning that you can run your templates
+through custom functions before they are compiled. This is good for things like
+removing unwanted comments, keeping an eye on words or functionality people are
+putting in templates, translating XML -> HTML, etc. See the register_prefilter
+documentation for more info.
+
+Another addition are the so-called compiler functions. These are custom
+functions registered by the user that are executed at compilation time of the
+template. They can be used to inject PHP code or time-sensitive static content
+into the compiled template.
+
+The run-time custom functions are now passed the Smarty object as the second
+parameter. This can be used, for example, to assign or clear template variables
+from inside the custom function.
+
+clear_compile_dir() was added for clearing out compiled versions of your
+templates. Not something normally needed, but you may have a need for this if
+you have $compile_check set to false and you periodically update templates via
+some automated process. As of 1.4.0, uncompiled templates _always_ get
+compiled regardless of $compile_check setting, although they won't be checked
+for recompile if $compile_check is set to false.
+
+You can now refer to properties of objects assigned from PHP by using the '->'
+symbol and specifying the property name after it, e.g. $foo->bar.
+
+{php}{/php} tags were added to embed php into the templates. Not normally
+needed, but some circumstances may call for it. Check out the "componentized
+templates" tip in the documentation for an example.
+
+{capture}{/capture} and {counter} functions were added. See the documentation
+for a complete description and examples.
+
+UPGRADE NOTES
+
+The format of the files created in the $compile_dir are now a bit different.
+The compiled template filename is the template resource name url-encoded.
+Therefore, all compiled files are now in the top directory of $compile_dir.
+This was done to make way for arbitrary template resources. Each compiled
+template also has a header that states what template resource was used to
+create it. From a unix command prompt, you can use "head -2 *" to see the first
+two lines of each file.
+
+When upgrading to 1.4.0, you will want to clear out all your old files in the
+$compile_dir. If you have $compile_check set to false and the compiled template
+does not yet exist, it will compile it regardless of this setting. This way you
+can clear out the $compile_dir and not worry about setting $compile_check to
+true to get the inital compilation under way.
+
+
+1.3.2
+-----
+
+Smarty now has (an optional) header prepended to the output of the Smarty
+templates. This displays the Smarty version and the date/time when the page was
+generated. This is useful for debugging your cache routines, and purely
+informational so there is evidence that the page was generated by Smarty. Set
+$show_info_header to false to disable it.
+
+{config_load ...} performance was tuned by placing the loaded variables into a
+global array, so basically a config file is read from the file system and
+placed into a php array structure only once, no matter how many times it is
+called in any of the templates. The scope of the loaded variables has changed a
+bit as well. Variables loaded by config_load used to be treated as global
+variables, meaning that parent templates (templates that included the current
+template) could see them. Now the default behavior is such that loaded
+variables are only visible by the current template and child templates (all
+templates included after the {config_load ...} is called.) To mimic the
+original behavior, provide the attribute "global=yes" like so: {config_load
+file="mystuff.conf" global=yes}. Now when you load in mystuff.conf, the
+variables will be visible to parent templates (merged with any existing config
+variables.)
+
+A formatting attribute was added to the {math ...} function, adding the ability
+to control the format of the output. Use the same formatting syntax as the PHP
+function sprintf().
+
+{html_select_time ...} was added, a custom function that works much like
+{html_select_date ...} except it displays time elements instead of dates.
+
+A few custom modifiers were added: count_characters, count_words,
+count_sentences, count_paragraphs. All pretty self-explanatory.
+
+/* vim: set et: */
diff --git a/bundled-libs/Smarty/libs/Config_File.class.php b/bundled-libs/Smarty/libs/Config_File.class.php
new file mode 100644 (file)
index 0000000..923508a
--- /dev/null
@@ -0,0 +1,389 @@
+<?php
+
+/**
+ * Config_File class.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @link http://smarty.php.net/
+ * @version 2.6.9
+ * @copyright Copyright: 2001-2005 New Digital Group, Inc.
+ * @author Andrei Zmievski <andrei@php.net>
+ * @access public
+ * @package Smarty
+ */
+
+/* $Id: Config_File.class.php,v 1.4 2005/04/01 08:38:11 tomsommer Exp $ */
+
+/**
+ * Config file reading class
+ * @package Smarty
+ */
+class Config_File {
+    /**#@+
+     * Options
+     * @var boolean
+     */
+    /**
+     * Controls whether variables with the same name overwrite each other.
+     */
+    var $overwrite        =    true;
+
+    /**
+     * Controls whether config values of on/true/yes and off/false/no get
+     * converted to boolean values automatically.
+     */
+    var $booleanize        =    true;
+
+    /**
+     * Controls whether hidden config sections/vars are read from the file.
+     */
+    var $read_hidden     =    true;
+
+    /**
+     * Controls whether or not to fix mac or dos formatted newlines.
+     * If set to true, \r or \r\n will be changed to \n.
+     */
+    var $fix_newlines =    true;
+    /**#@-*/
+
+    /** @access private */
+    var $_config_path    = "";
+    var $_config_data    = array();
+    /**#@-*/
+
+    /**
+     * Constructs a new config file class.
+     *
+     * @param string $config_path (optional) path to the config files
+     */
+    function Config_File($config_path = NULL)
+    {
+        if (isset($config_path))
+            $this->set_path($config_path);
+    }
+
+
+    /**
+     * Set the path where configuration files can be found.
+     *
+     * @param string $config_path path to the config files
+     */
+    function set_path($config_path)
+    {
+        if (!empty($config_path)) {
+            if (!is_string($config_path) || !file_exists($config_path) || !is_dir($config_path)) {
+                $this->_trigger_error_msg("Bad config file path '$config_path'");
+                return;
+            }
+            if(substr($config_path, -1) != DIRECTORY_SEPARATOR) {
+                $config_path .= DIRECTORY_SEPARATOR;
+            }
+
+            $this->_config_path = $config_path;
+        }
+    }
+
+
+    /**
+     * Retrieves config info based on the file, section, and variable name.
+     *
+     * @param string $file_name config file to get info for
+     * @param string $section_name (optional) section to get info for
+     * @param string $var_name (optional) variable to get info for
+     * @return string|array a value or array of values
+     */
+    function &get($file_name, $section_name = NULL, $var_name = NULL)
+    {
+        if (empty($file_name)) {
+            $this->_trigger_error_msg('Empty config file name');
+            return;
+        } else {
+            $file_name = $this->_config_path . $file_name;
+            if (!isset($this->_config_data[$file_name]))
+                $this->load_file($file_name, false);
+        }
+
+        if (!empty($var_name)) {
+            if (empty($section_name)) {
+                return $this->_config_data[$file_name]["vars"][$var_name];
+            } else {
+                if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name]))
+                    return $this->_config_data[$file_name]["sections"][$section_name]["vars"][$var_name];
+                else
+                    return array();
+            }
+        } else {
+            if (empty($section_name)) {
+                return (array)$this->_config_data[$file_name]["vars"];
+            } else {
+                if(isset($this->_config_data[$file_name]["sections"][$section_name]["vars"]))
+                    return (array)$this->_config_data[$file_name]["sections"][$section_name]["vars"];
+                else
+                    return array();
+            }
+        }
+    }
+
+
+    /**
+     * Retrieves config info based on the key.
+     *
+     * @param $file_name string config key (filename/section/var)
+     * @return string|array same as get()
+     * @uses get() retrieves information from config file and returns it
+     */
+    function &get_key($config_key)
+    {
+        list($file_name, $section_name, $var_name) = explode('/', $config_key, 3);
+        $result = &$this->get($file_name, $section_name, $var_name);
+        return $result;
+    }
+
+    /**
+     * Get all loaded config file names.
+     *
+     * @return array an array of loaded config file names
+     */
+    function get_file_names()
+    {
+        return array_keys($this->_config_data);
+    }
+
+
+    /**
+     * Get all section names from a loaded file.
+     *
+     * @param string $file_name config file to get section names from
+     * @return array an array of section names from the specified file
+     */
+    function get_section_names($file_name)
+    {
+        $file_name = $this->_config_path . $file_name;
+        if (!isset($this->_config_data[$file_name])) {
+            $this->_trigger_error_msg("Unknown config file '$file_name'");
+            return;
+        }
+
+        return array_keys($this->_config_data[$file_name]["sections"]);
+    }
+
+
+    /**
+     * Get all global or section variable names.
+     *
+     * @param string $file_name config file to get info for
+     * @param string $section_name (optional) section to get info for
+     * @return array an array of variables names from the specified file/section
+     */
+    function get_var_names($file_name, $section = NULL)
+    {
+        if (empty($file_name)) {
+            $this->_trigger_error_msg('Empty config file name');
+            return;
+        } else if (!isset($this->_config_data[$file_name])) {
+            $this->_trigger_error_msg("Unknown config file '$file_name'");
+            return;
+        }
+
+        if (empty($section))
+            return array_keys($this->_config_data[$file_name]["vars"]);
+        else
+            return array_keys($this->_config_data[$file_name]["sections"][$section]["vars"]);
+    }
+
+
+    /**
+     * Clear loaded config data for a certain file or all files.
+     *
+     * @param string $file_name file to clear config data for
+     */
+    function clear($file_name = NULL)
+    {
+        if ($file_name === NULL)
+            $this->_config_data = array();
+        else if (isset($this->_config_data[$file_name]))
+            $this->_config_data[$file_name] = array();
+    }
+
+
+    /**
+     * Load a configuration file manually.
+     *
+     * @param string $file_name file name to load
+     * @param boolean $prepend_path whether current config path should be
+     *                              prepended to the filename
+     */
+    function load_file($file_name, $prepend_path = true)
+    {
+        if ($prepend_path && $this->_config_path != "")
+            $config_file = $this->_config_path . $file_name;
+        else
+            $config_file = $file_name;
+
+        ini_set('track_errors', true);
+        $fp = @fopen($config_file, "r");
+        if (!is_resource($fp)) {
+            $this->_trigger_error_msg("Could not open config file '$config_file'");
+            return false;
+        }
+
+        $contents = ($size = filesize($config_file)) ? fread($fp, $size) : '';
+        fclose($fp);
+
+        $this->_config_data[$config_file] = $this->parse_contents($contents);
+        return true;
+    }
+
+    /**
+     * Store the contents of a file manually.
+     *
+     * @param string $config_file file name of the related contents
+     * @param string $contents the file-contents to parse
+     */
+    function set_file_contents($config_file, $contents)
+    {
+        $this->_config_data[$config_file] = $this->parse_contents($contents);
+        return true;
+    }
+
+    /**
+     * parse the source of a configuration file manually.
+     *
+     * @param string $contents the file-contents to parse
+     */
+    function parse_contents($contents)
+    {
+        if($this->fix_newlines) {
+            // fix mac/dos formatted newlines
+            $contents = preg_replace('!\r\n?!', "\n", $contents);
+        }
+
+        $config_data = array();
+        $config_data['sections'] = array();
+        $config_data['vars'] = array();
+
+        /* reference to fill with data */
+        $vars =& $config_data['vars'];
+
+        /* parse file line by line */
+        preg_match_all('!^.*\r?\n?!m', $contents, $match);
+        $lines = $match[0];
+        for ($i=0, $count=count($lines); $i<$count; $i++) {
+            $line = $lines[$i];
+            if (empty($line)) continue;
+
+            if ( $line{0} == '[' && preg_match('!^\[(.*?)\]!', $line, $match) ) {
+                /* section found */
+                if ($match[1]{0} == '.') {
+                    /* hidden section */
+                    if ($this->read_hidden) {
+                        $section_name = substr($match[1], 1);
+                    } else {
+                        /* break reference to $vars to ignore hidden section */
+                        unset($vars);
+                        $vars = array();
+                        continue;
+                    }
+                } else {                    
+                    $section_name = $match[1];
+                }
+                if (!isset($config_data['sections'][$section_name]))
+                    $config_data['sections'][$section_name] = array('vars' => array());
+                $vars =& $config_data['sections'][$section_name]['vars'];
+                continue;
+            }
+
+            if (preg_match('/^\s*(\.?\w+)\s*=\s*(.*)/s', $line, $match)) {
+                /* variable found */
+                $var_name = rtrim($match[1]);
+                if (strpos($match[2], '"""') === 0) {
+                    /* handle multiline-value */
+                    $lines[$i] = substr($match[2], 3);
+                    $var_value = '';
+                    while ($i<$count) {
+                        if (($pos = strpos($lines[$i], '"""')) === false) {
+                            $var_value .= $lines[$i++];
+                        } else {
+                            /* end of multiline-value */
+                            $var_value .= substr($lines[$i], 0, $pos);
+                            break;
+                        }
+                    }
+                    $booleanize = false;
+
+                } else {
+                    /* handle simple value */
+                    $var_value = preg_replace('/^([\'"])(.*)\1$/', '\2', rtrim($match[2]));
+                    $booleanize = $this->booleanize;
+
+                }
+                $this->_set_config_var($vars, $var_name, $var_value, $booleanize);
+            }
+            /* else unparsable line / means it is a comment / means ignore it */
+        }
+        return $config_data;
+    }
+
+    /**#@+ @access private */
+    /**
+     * @param array &$container
+     * @param string $var_name
+     * @param mixed $var_value
+     * @param boolean $booleanize determines whether $var_value is converted to
+     *                            to true/false
+     */
+    function _set_config_var(&$container, $var_name, $var_value, $booleanize)
+    {
+        if ($var_name{0} == '.') {
+            if (!$this->read_hidden)
+                return;
+            else
+                $var_name = substr($var_name, 1);
+        }
+
+        if (!preg_match("/^[a-zA-Z_]\w*$/", $var_name)) {
+            $this->_trigger_error_msg("Bad variable name '$var_name'");
+            return;
+        }
+
+        if ($booleanize) {
+            if (preg_match("/^(on|true|yes)$/i", $var_value))
+                $var_value = true;
+            else if (preg_match("/^(off|false|no)$/i", $var_value))
+                $var_value = false;
+        }
+
+        if (!isset($container[$var_name]) || $this->overwrite)
+            $container[$var_name] = $var_value;
+        else {
+            settype($container[$var_name], 'array');
+            $container[$var_name][] = $var_value;
+        }
+    }
+
+    /**
+     * @uses trigger_error() creates a PHP warning/error
+     * @param string $error_msg
+     * @param integer $error_type one of
+     */
+    function _trigger_error_msg($error_msg, $error_type = E_USER_WARNING)
+    {
+        trigger_error("Config_File error: $error_msg", $error_type);
+    }
+    /**#@-*/
+}
+
+?>
diff --git a/bundled-libs/Smarty/libs/Smarty.class.php b/bundled-libs/Smarty/libs/Smarty.class.php
new file mode 100644 (file)
index 0000000..54628f1
--- /dev/null
@@ -0,0 +1,1934 @@
+<?php
+
+/**
+ * Project:     Smarty: the PHP compiling template engine
+ * File:        Smarty.class.php
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * For questions, help, comments, discussion, etc., please join the
+ * Smarty mailing list. Send a blank e-mail to
+ * smarty-general-subscribe@lists.php.net
+ *
+ * @link http://smarty.php.net/
+ * @copyright 2001-2005 New Digital Group, Inc.
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author Andrei Zmievski <andrei@php.net>
+ * @package Smarty
+ * @version 2.6.9
+ */
+
+/* $Id: Smarty.class.php,v 1.4 2005/04/01 08:38:11 tomsommer Exp $ */
+
+/**
+ * DIR_SEP isn't used anymore, but third party apps might
+ */
+if(!defined('DIR_SEP')) {
+    define('DIR_SEP', DIRECTORY_SEPARATOR);
+}
+
+/**
+ * set SMARTY_DIR to absolute path to Smarty library files.
+ * if not defined, include_path will be used. Sets SMARTY_DIR only if user
+ * application has not already defined it.
+ */
+
+if (!defined('SMARTY_DIR')) {
+    define('SMARTY_DIR', dirname(__FILE__) . DIRECTORY_SEPARATOR);
+}
+
+if (!defined('SMARTY_CORE_DIR')) {
+    define('SMARTY_CORE_DIR', SMARTY_DIR . 'internals' . DIRECTORY_SEPARATOR);
+}
+
+define('SMARTY_PHP_PASSTHRU',   0);
+define('SMARTY_PHP_QUOTE',      1);
+define('SMARTY_PHP_REMOVE',     2);
+define('SMARTY_PHP_ALLOW',      3);
+
+/**
+ * @package Smarty
+ */
+class Smarty
+{
+    /**#@+
+     * Smarty Configuration Section
+     */
+
+    /**
+     * The name of the directory where templates are located.
+     *
+     * @var string
+     */
+    var $template_dir    =  'templates';
+
+    /**
+     * The directory where compiled templates are located.
+     *
+     * @var string
+     */
+    var $compile_dir     =  'templates_c';
+
+    /**
+     * The directory where config files are located.
+     *
+     * @var string
+     */
+    var $config_dir      =  'configs';
+
+    /**
+     * An array of directories searched for plugins.
+     *
+     * @var array
+     */
+    var $plugins_dir     =  array('plugins');
+
+    /**
+     * If debugging is enabled, a debug console window will display
+     * when the page loads (make sure your browser allows unrequested
+     * popup windows)
+     *
+     * @var boolean
+     */
+    var $debugging       =  false;
+
+    /**
+     * When set, smarty does uses this value as error_reporting-level.
+     *
+     * @var boolean
+     */
+    var $error_reporting  =  null;
+
+    /**
+     * This is the path to the debug console template. If not set,
+     * the default one will be used.
+     *
+     * @var string
+     */
+    var $debug_tpl       =  '';
+
+    /**
+     * This determines if debugging is enable-able from the browser.
+     * <ul>
+     *  <li>NONE => no debugging control allowed</li>
+     *  <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>
+     * </ul>
+     * @link http://www.foo.dom/index.php?SMARTY_DEBUG
+     * @var string
+     */
+    var $debugging_ctrl  =  'NONE';
+
+    /**
+     * This tells Smarty whether to check for recompiling or not. Recompiling
+     * does not need to happen unless a template or config file is changed.
+     * Typically you enable this during development, and disable for
+     * production.
+     *
+     * @var boolean
+     */
+    var $compile_check   =  true;
+
+    /**
+     * This forces templates to compile every time. Useful for development
+     * or debugging.
+     *
+     * @var boolean
+     */
+    var $force_compile   =  false;
+
+    /**
+     * This enables template caching.
+     * <ul>
+     *  <li>0 = no caching</li>
+     *  <li>1 = use class cache_lifetime value</li>
+     *  <li>2 = use cache_lifetime in cache file</li>
+     * </ul>
+     * @var integer
+     */
+    var $caching         =  0;
+
+    /**
+     * The name of the directory for cache files.
+     *
+     * @var string
+     */
+    var $cache_dir       =  'cache';
+
+    /**
+     * This is the number of seconds cached content will persist.
+     * <ul>
+     *  <li>0 = always regenerate cache</li>
+     *  <li>-1 = never expires</li>
+     * </ul>
+     *
+     * @var integer
+     */
+    var $cache_lifetime  =  3600;
+
+    /**
+     * Only used when $caching is enabled. If true, then If-Modified-Since headers
+     * are respected with cached content, and appropriate HTTP headers are sent.
+     * This way repeated hits to a cached page do not send the entire page to the
+     * client every time.
+     *
+     * @var boolean
+     */
+    var $cache_modified_check = false;
+
+    /**
+     * This determines how Smarty handles "<?php ... ?>" tags in templates.
+     * possible values:
+     * <ul>
+     *  <li>SMARTY_PHP_PASSTHRU -> print tags as plain text</li>
+     *  <li>SMARTY_PHP_QUOTE    -> escape tags as entities</li>
+     *  <li>SMARTY_PHP_REMOVE   -> remove php tags</li>
+     *  <li>SMARTY_PHP_ALLOW    -> execute php tags</li>
+     * </ul>
+     *
+     * @var integer
+     */
+    var $php_handling    =  SMARTY_PHP_PASSTHRU;
+
+    /**
+     * This enables template security. When enabled, many things are restricted
+     * in the templates that normally would go unchecked. This is useful when
+     * untrusted parties are editing templates and you want a reasonable level
+     * of security. (no direct execution of PHP in templates for example)
+     *
+     * @var boolean
+     */
+    var $security       =   false;
+
+    /**
+     * This is the list of template directories that are considered secure. This
+     * is used only if {@link $security} is enabled. One directory per array
+     * element.  {@link $template_dir} is in this list implicitly.
+     *
+     * @var array
+     */
+    var $secure_dir     =   array();
+
+    /**
+     * These are the security settings for Smarty. They are used only when
+     * {@link $security} is enabled.
+     *
+     * @var array
+     */
+    var $security_settings  = array(
+                                    'PHP_HANDLING'    => false,
+                                    'IF_FUNCS'        => array('array', 'list',
+                                                               'isset', 'empty',
+                                                               'count', 'sizeof',
+                                                               'in_array', 'is_array',
+                                                               'true', 'false', 'null'),
+                                    'INCLUDE_ANY'     => false,
+                                    'PHP_TAGS'        => false,
+                                    'MODIFIER_FUNCS'  => array('count'),
+                                    'ALLOW_CONSTANTS'  => false
+                                   );
+
+    /**
+     * This is an array of directories where trusted php scripts reside.
+     * {@link $security} is disabled during their inclusion/execution.
+     *
+     * @var array
+     */
+    var $trusted_dir        = array();
+
+    /**
+     * The left delimiter used for the template tags.
+     *
+     * @var string
+     */
+    var $left_delimiter  =  '{';
+
+    /**
+     * The right delimiter used for the template tags.
+     *
+     * @var string
+     */
+    var $right_delimiter =  '}';
+
+    /**
+     * The order in which request variables are registered, similar to
+     * variables_order in php.ini E = Environment, G = GET, P = POST,
+     * C = Cookies, S = Server
+     *
+     * @var string
+     */
+    var $request_vars_order    = 'EGPCS';
+
+    /**
+     * Indicates wether $HTTP_*_VARS[] (request_use_auto_globals=false)
+     * are uses as request-vars or $_*[]-vars. note: if
+     * request_use_auto_globals is true, then $request_vars_order has
+     * no effect, but the php-ini-value "gpc_order"
+     *
+     * @var boolean
+     */
+    var $request_use_auto_globals      = true;
+
+    /**
+     * Set this if you want different sets of compiled files for the same
+     * templates. This is useful for things like different languages.
+     * Instead of creating separate sets of templates per language, you
+     * set different compile_ids like 'en' and 'de'.
+     *
+     * @var string
+     */
+    var $compile_id            = null;
+
+    /**
+     * This tells Smarty whether or not to use sub dirs in the cache/ and
+     * templates_c/ directories. sub directories better organized, but
+     * may not work well with PHP safe mode enabled.
+     *
+     * @var boolean
+     *
+     */
+    var $use_sub_dirs          = false;
+
+    /**
+     * This is a list of the modifiers to apply to all template variables.
+     * Put each modifier in a separate array element in the order you want
+     * them applied. example: <code>array('escape:"htmlall"');</code>
+     *
+     * @var array
+     */
+    var $default_modifiers        = array();
+
+    /**
+     * This is the resource type to be used when not specified
+     * at the beginning of the resource path. examples:
+     * $smarty->display('file:index.tpl');
+     * $smarty->display('db:index.tpl');
+     * $smarty->display('index.tpl'); // will use default resource type
+     * {include file="file:index.tpl"}
+     * {include file="db:index.tpl"}
+     * {include file="index.tpl"} {* will use default resource type *}
+     *
+     * @var array
+     */
+    var $default_resource_type    = 'file';
+
+    /**
+     * The function used for cache file handling. If not set, built-in caching is used.
+     *
+     * @var null|string function name
+     */
+    var $cache_handler_func   = null;
+
+    /**
+     * This indicates which filters are automatically loaded into Smarty.
+     *
+     * @var array array of filter names
+     */
+    var $autoload_filters = array();
+
+    /**#@+
+     * @var boolean
+     */
+    /**
+     * This tells if config file vars of the same name overwrite each other or not.
+     * if disabled, same name variables are accumulated in an array.
+     */
+    var $config_overwrite = true;
+
+    /**
+     * This tells whether or not to automatically booleanize config file variables.
+     * If enabled, then the strings "on", "true", and "yes" are treated as boolean
+     * true, and "off", "false" and "no" are treated as boolean false.
+     */
+    var $config_booleanize = true;
+
+    /**
+     * This tells whether hidden sections [.foobar] are readable from the
+     * tempalates or not. Normally you would never allow this since that is
+     * the point behind hidden sections: the application can access them, but
+     * the templates cannot.
+     */
+    var $config_read_hidden = false;
+
+    /**
+     * This tells whether or not automatically fix newlines in config files.
+     * It basically converts \r (mac) or \r\n (dos) to \n
+     */
+    var $config_fix_newlines = true;
+    /**#@-*/
+
+    /**
+     * If a template cannot be found, this PHP function will be executed.
+     * Useful for creating templates on-the-fly or other special action.
+     *
+     * @var string function name
+     */
+    var $default_template_handler_func = '';
+
+    /**
+     * The file that contains the compiler class. This can a full
+     * pathname, or relative to the php_include path.
+     *
+     * @var string
+     */
+    var $compiler_file        =    'Smarty_Compiler.class.php';
+
+    /**
+     * The class used for compiling templates.
+     *
+     * @var string
+     */
+    var $compiler_class        =   'Smarty_Compiler';
+
+    /**
+     * The class used to load config vars.
+     *
+     * @var string
+     */
+    var $config_class          =   'Config_File';
+
+/**#@+
+ * END Smarty Configuration Section
+ * There should be no need to touch anything below this line.
+ * @access private
+ */
+    /**
+     * where assigned template vars are kept
+     *
+     * @var array
+     */
+    var $_tpl_vars             = array();
+
+    /**
+     * stores run-time $smarty.* vars
+     *
+     * @var null|array
+     */
+    var $_smarty_vars          = null;
+
+    /**
+     * keeps track of sections
+     *
+     * @var array
+     */
+    var $_sections             = array();
+
+    /**
+     * keeps track of foreach blocks
+     *
+     * @var array
+     */
+    var $_foreach              = array();
+
+    /**
+     * keeps track of tag hierarchy
+     *
+     * @var array
+     */
+    var $_tag_stack            = array();
+
+    /**
+     * configuration object
+     *
+     * @var Config_file
+     */
+    var $_conf_obj             = null;
+
+    /**
+     * loaded configuration settings
+     *
+     * @var array
+     */
+    var $_config               = array(array('vars'  => array(), 'files' => array()));
+
+    /**
+     * md5 checksum of the string 'Smarty'
+     *
+     * @var string
+     */
+    var $_smarty_md5           = 'f8d698aea36fcbead2b9d5359ffca76f';
+
+    /**
+     * Smarty version number
+     *
+     * @var string
+     */
+    var $_version              = '2.6.9';
+
+    /**
+     * current template inclusion depth
+     *
+     * @var integer
+     */
+    var $_inclusion_depth      = 0;
+
+    /**
+     * for different compiled templates
+     *
+     * @var string
+     */
+    var $_compile_id           = null;
+
+    /**
+     * text in URL to enable debug mode
+     *
+     * @var string
+     */
+    var $_smarty_debug_id      = 'SMARTY_DEBUG';
+
+    /**
+     * debugging information for debug console
+     *
+     * @var array
+     */
+    var $_smarty_debug_info    = array();
+
+    /**
+     * info that makes up a cache file
+     *
+     * @var array
+     */
+    var $_cache_info           = array();
+
+    /**
+     * default file permissions
+     *
+     * @var integer
+     */
+    var $_file_perms           = 0644;
+
+    /**
+     * default dir permissions
+     *
+     * @var integer
+     */
+    var $_dir_perms               = 0771;
+
+    /**
+     * registered objects
+     *
+     * @var array
+     */
+    var $_reg_objects           = array();
+
+    /**
+     * table keeping track of plugins
+     *
+     * @var array
+     */
+    var $_plugins              = array(
+                                       'modifier'      => array(),
+                                       'function'      => array(),
+                                       'block'         => array(),
+                                       'compiler'      => array(),
+                                       'prefilter'     => array(),
+                                       'postfilter'    => array(),
+                                       'outputfilter'  => array(),
+                                       'resource'      => array(),
+                                       'insert'        => array());
+
+
+    /**
+     * cache serials
+     *
+     * @var array
+     */
+    var $_cache_serials = array();
+
+    /**
+     * name of optional cache include file
+     *
+     * @var string
+     */
+    var $_cache_include = null;
+
+    /**
+     * indicate if the current code is used in a compiled
+     * include
+     *
+     * @var string
+     */
+    var $_cache_including = false;
+
+    /**#@-*/
+    /**
+     * The class constructor.
+     */
+    function Smarty()
+    {
+      $this->assign('SCRIPT_NAME', isset($_SERVER['SCRIPT_NAME']) ? $_SERVER['SCRIPT_NAME']
+                    : @$GLOBALS['HTTP_SERVER_VARS']['SCRIPT_NAME']);
+    }
+
+    /**
+     * assigns values to template variables
+     *
+     * @param array|string $tpl_var the template variable name(s)
+     * @param mixed $value the value to assign
+     */
+    function assign($tpl_var, $value = null)
+    {
+        if (is_array($tpl_var)){
+            foreach ($tpl_var as $key => $val) {
+                if ($key != '') {
+                    $this->_tpl_vars[$key] = $val;
+                }
+            }
+        } else {
+            if ($tpl_var != '')
+                $this->_tpl_vars[$tpl_var] = $value;
+        }
+    }
+
+    /**
+     * assigns values to template variables by reference
+     *
+     * @param string $tpl_var the template variable name
+     * @param mixed $value the referenced value to assign
+     */
+    function assign_by_ref($tpl_var, &$value)
+    {
+        if ($tpl_var != '')
+            $this->_tpl_vars[$tpl_var] = &$value;
+    }
+
+    /**
+     * appends values to template variables
+     *
+     * @param array|string $tpl_var the template variable name(s)
+     * @param mixed $value the value to append
+     */
+    function append($tpl_var, $value=null, $merge=false)
+    {
+        if (is_array($tpl_var)) {
+            // $tpl_var is an array, ignore $value
+            foreach ($tpl_var as $_key => $_val) {
+                if ($_key != '') {
+                    if(!@is_array($this->_tpl_vars[$_key])) {
+                        settype($this->_tpl_vars[$_key],'array');
+                    }
+                    if($merge && is_array($_val)) {
+                        foreach($_val as $_mkey => $_mval) {
+                            $this->_tpl_vars[$_key][$_mkey] = $_mval;
+                        }
+                    } else {
+                        $this->_tpl_vars[$_key][] = $_val;
+                    }
+                }
+            }
+        } else {
+            if ($tpl_var != '' && isset($value)) {
+                if(!@is_array($this->_tpl_vars[$tpl_var])) {
+                    settype($this->_tpl_vars[$tpl_var],'array');
+                }
+                if($merge && is_array($value)) {
+                    foreach($value as $_mkey => $_mval) {
+                        $this->_tpl_vars[$tpl_var][$_mkey] = $_mval;
+                    }
+                } else {
+                    $this->_tpl_vars[$tpl_var][] = $value;
+                }
+            }
+        }
+    }
+
+    /**
+     * appends values to template variables by reference
+     *
+     * @param string $tpl_var the template variable name
+     * @param mixed $value the referenced value to append
+     */
+    function append_by_ref($tpl_var, &$value, $merge=false)
+    {
+        if ($tpl_var != '' && isset($value)) {
+            if(!@is_array($this->_tpl_vars[$tpl_var])) {
+             settype($this->_tpl_vars[$tpl_var],'array');
+            }
+            if ($merge && is_array($value)) {
+                foreach($value as $_key => $_val) {
+                    $this->_tpl_vars[$tpl_var][$_key] = &$value[$_key];
+                }
+            } else {
+                $this->_tpl_vars[$tpl_var][] = &$value;
+            }
+        }
+    }
+
+
+    /**
+     * clear the given assigned template variable.
+     *
+     * @param string $tpl_var the template variable to clear
+     */
+    function clear_assign($tpl_var)
+    {
+        if (is_array($tpl_var))
+            foreach ($tpl_var as $curr_var)
+                unset($this->_tpl_vars[$curr_var]);
+        else
+            unset($this->_tpl_vars[$tpl_var]);
+    }
+
+
+    /**
+     * Registers custom function to be used in templates
+     *
+     * @param string $function the name of the template function
+     * @param string $function_impl the name of the PHP function to register
+     */
+    function register_function($function, $function_impl, $cacheable=true, $cache_attrs=null)
+    {
+        $this->_plugins['function'][$function] =
+            array($function_impl, null, null, false, $cacheable, $cache_attrs);
+
+    }
+
+    /**
+     * Unregisters custom function
+     *
+     * @param string $function name of template function
+     */
+    function unregister_function($function)
+    {
+        unset($this->_plugins['function'][$function]);
+    }
+
+    /**
+     * Registers object to be used in templates
+     *
+     * @param string $object name of template object
+     * @param object &$object_impl the referenced PHP object to register
+     * @param null|array $allowed list of allowed methods (empty = all)
+     * @param boolean $smarty_args smarty argument format, else traditional
+     * @param null|array $block_functs list of methods that are block format
+     */
+    function register_object($object, &$object_impl, $allowed = array(), $smarty_args = true, $block_methods = array())
+    {
+        settype($allowed, 'array');
+        settype($smarty_args, 'boolean');
+        $this->_reg_objects[$object] =
+            array(&$object_impl, $allowed, $smarty_args, $block_methods);
+    }
+
+    /**
+     * Unregisters object
+     *
+     * @param string $object name of template object
+     */
+    function unregister_object($object)
+    {
+        unset($this->_reg_objects[$object]);
+    }
+
+
+    /**
+     * Registers block function to be used in templates
+     *
+     * @param string $block name of template block
+     * @param string $block_impl PHP function to register
+     */
+    function register_block($block, $block_impl, $cacheable=true, $cache_attrs=null)
+    {
+        $this->_plugins['block'][$block] =
+            array($block_impl, null, null, false, $cacheable, $cache_attrs);
+    }
+
+    /**
+     * Unregisters block function
+     *
+     * @param string $block name of template function
+     */
+    function unregister_block($block)
+    {
+        unset($this->_plugins['block'][$block]);
+    }
+
+    /**
+     * Registers compiler function
+     *
+     * @param string $function name of template function
+     * @param string $function_impl name of PHP function to register
+     */
+    function register_compiler_function($function, $function_impl, $cacheable=true)
+    {
+        $this->_plugins['compiler'][$function] =
+            array($function_impl, null, null, false, $cacheable);
+    }
+
+    /**
+     * Unregisters compiler function
+     *
+     * @param string $function name of template function
+     */
+    function unregister_compiler_function($function)
+    {
+        unset($this->_plugins['compiler'][$function]);
+    }
+
+    /**
+     * Registers modifier to be used in templates
+     *
+     * @param string $modifier name of template modifier
+     * @param string $modifier_impl name of PHP function to register
+     */
+    function register_modifier($modifier, $modifier_impl)
+    {
+        $this->_plugins['modifier'][$modifier] =
+            array($modifier_impl, null, null, false);
+    }
+
+    /**
+     * Unregisters modifier
+     *
+     * @param string $modifier name of template modifier
+     */
+    function unregister_modifier($modifier)
+    {
+        unset($this->_plugins['modifier'][$modifier]);
+    }
+
+    /**
+     * Registers a resource to fetch a template
+     *
+     * @param string $type name of resource
+     * @param array $functions array of functions to handle resource
+     */
+    function register_resource($type, $functions)
+    {
+        if (count($functions)==4) {
+            $this->_plugins['resource'][$type] =
+                array($functions, false);
+
+        } elseif (count($functions)==5) {
+            $this->_plugins['resource'][$type] =
+                array(array(array(&$functions[0], $functions[1])
+                            ,array(&$functions[0], $functions[2])
+                            ,array(&$functions[0], $functions[3])
+                            ,array(&$functions[0], $functions[4]))
+                      ,false);
+
+        } else {
+            $this->trigger_error("malformed function-list for '$type' in register_resource");
+
+        }
+    }
+
+    /**
+     * Unregisters a resource
+     *
+     * @param string $type name of resource
+     */
+    function unregister_resource($type)
+    {
+        unset($this->_plugins['resource'][$type]);
+    }
+
+    /**
+     * Registers a prefilter function to apply
+     * to a template before compiling
+     *
+     * @param string $function name of PHP function to register
+     */
+    function register_prefilter($function)
+    {
+    $_name = (is_array($function)) ? $function[1] : $function;
+        $this->_plugins['prefilter'][$_name]
+            = array($function, null, null, false);
+    }
+
+    /**
+     * Unregisters a prefilter function
+     *
+     * @param string $function name of PHP function
+     */
+    function unregister_prefilter($function)
+    {
+        unset($this->_plugins['prefilter'][$function]);
+    }
+
+    /**
+     * Registers a postfilter function to apply
+     * to a compiled template after compilation
+     *
+     * @param string $function name of PHP function to register
+     */
+    function register_postfilter($function)
+    {
+    $_name = (is_array($function)) ? $function[1] : $function;
+        $this->_plugins['postfilter'][$_name]
+            = array($function, null, null, false);
+    }
+
+    /**
+     * Unregisters a postfilter function
+     *
+     * @param string $function name of PHP function
+     */
+    function unregister_postfilter($function)
+    {
+        unset($this->_plugins['postfilter'][$function]);
+    }
+
+    /**
+     * Registers an output filter function to apply
+     * to a template output
+     *
+     * @param string $function name of PHP function
+     */
+    function register_outputfilter($function)
+    {
+    $_name = (is_array($function)) ? $function[1] : $function;
+        $this->_plugins['outputfilter'][$_name]
+            = array($function, null, null, false);
+    }
+
+    /**
+     * Unregisters an outputfilter function
+     *
+     * @param string $function name of PHP function
+     */
+    function unregister_outputfilter($function)
+    {
+        unset($this->_plugins['outputfilter'][$function]);
+    }
+
+    /**
+     * load a filter of specified type and name
+     *
+     * @param string $type filter type
+     * @param string $name filter name
+     */
+    function load_filter($type, $name)
+    {
+        switch ($type) {
+            case 'output':
+                $_params = array('plugins' => array(array($type . 'filter', $name, null, null, false)));
+                require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
+                smarty_core_load_plugins($_params, $this);
+                break;
+
+            case 'pre':
+            case 'post':
+                if (!isset($this->_plugins[$type . 'filter'][$name]))
+                    $this->_plugins[$type . 'filter'][$name] = false;
+                break;
+        }
+    }
+
+    /**
+     * clear cached content for the given template and cache id
+     *
+     * @param string $tpl_file name of template file
+     * @param string $cache_id name of cache_id
+     * @param string $compile_id name of compile_id
+     * @param string $exp_time expiration time
+     * @return boolean
+     */
+    function clear_cache($tpl_file = null, $cache_id = null, $compile_id = null, $exp_time = null)
+    {
+
+        if (!isset($compile_id))
+            $compile_id = $this->compile_id;
+
+        if (!isset($tpl_file))
+            $compile_id = null;
+
+        $_auto_id = $this->_get_auto_id($cache_id, $compile_id);
+
+        if (!empty($this->cache_handler_func)) {
+            return call_user_func_array($this->cache_handler_func,
+                                  array('clear', &$this, &$dummy, $tpl_file, $cache_id, $compile_id, $exp_time));
+        } else {
+            $_params = array('auto_base' => $this->cache_dir,
+                            'auto_source' => $tpl_file,
+                            'auto_id' => $_auto_id,
+                            'exp_time' => $exp_time);
+            require_once(SMARTY_CORE_DIR . 'core.rm_auto.php');
+            return smarty_core_rm_auto($_params, $this);
+        }
+
+    }
+
+
+    /**
+     * clear the entire contents of cache (all templates)
+     *
+     * @param string $exp_time expire time
+     * @return boolean results of {@link smarty_core_rm_auto()}
+     */
+    function clear_all_cache($exp_time = null)
+    {
+        return $this->clear_cache(null, null, null, $exp_time);
+    }
+
+
+    /**
+     * test to see if valid cache exists for this template
+     *
+     * @param string $tpl_file name of template file
+     * @param string $cache_id
+     * @param string $compile_id
+     * @return string|false results of {@link _read_cache_file()}
+     */
+    function is_cached($tpl_file, $cache_id = null, $compile_id = null)
+    {
+        if (!$this->caching)
+            return false;
+
+        if (!isset($compile_id))
+            $compile_id = $this->compile_id;
+
+        $_params = array(
+            'tpl_file' => $tpl_file,
+            'cache_id' => $cache_id,
+            'compile_id' => $compile_id
+        );
+        require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php');
+        return smarty_core_read_cache_file($_params, $this);
+    }
+
+
+    /**
+     * clear all the assigned template variables.
+     *
+     */
+    function clear_all_assign()
+    {
+        $this->_tpl_vars = array();
+    }
+
+    /**
+     * clears compiled version of specified template resource,
+     * or all compiled template files if one is not specified.
+     * This function is for advanced use only, not normally needed.
+     *
+     * @param string $tpl_file
+     * @param string $compile_id
+     * @param string $exp_time
+     * @return boolean results of {@link smarty_core_rm_auto()}
+     */
+    function clear_compiled_tpl($tpl_file = null, $compile_id = null, $exp_time = null)
+    {
+        if (!isset($compile_id)) {
+            $compile_id = $this->compile_id;
+        }
+        $_params = array('auto_base' => $this->compile_dir,
+                        'auto_source' => $tpl_file,
+                        'auto_id' => $compile_id,
+                        'exp_time' => $exp_time,
+                        'extensions' => array('.inc', '.php'));
+        require_once(SMARTY_CORE_DIR . 'core.rm_auto.php');
+        return smarty_core_rm_auto($_params, $this);
+    }
+
+    /**
+     * Checks whether requested template exists.
+     *
+     * @param string $tpl_file
+     * @return boolean
+     */
+    function template_exists($tpl_file)
+    {
+        $_params = array('resource_name' => $tpl_file, 'quiet'=>true, 'get_source'=>false);
+        return $this->_fetch_resource_info($_params);
+    }
+
+    /**
+     * Returns an array containing template variables
+     *
+     * @param string $name
+     * @param string $type
+     * @return array
+     */
+    function &get_template_vars($name=null)
+    {
+        if(!isset($name)) {
+            return $this->_tpl_vars;
+        }
+        if(isset($this->_tpl_vars[$name])) {
+            return $this->_tpl_vars[$name];
+        }
+    }
+
+    /**
+     * Returns an array containing config variables
+     *
+     * @param string $name
+     * @param string $type
+     * @return array
+     */
+    function &get_config_vars($name=null)
+    {
+        if(!isset($name) && is_array($this->_config[0])) {
+            return $this->_config[0]['vars'];
+        } else if(isset($this->_config[0]['vars'][$name])) {
+            return $this->_config[0]['vars'][$name];
+        }
+    }
+
+    /**
+     * trigger Smarty error
+     *
+     * @param string $error_msg
+     * @param integer $error_type
+     */
+    function trigger_error($error_msg, $error_type = E_USER_WARNING)
+    {
+        trigger_error("Smarty error: $error_msg", $error_type);
+    }
+
+
+    /**
+     * executes & displays the template results
+     *
+     * @param string $resource_name
+     * @param string $cache_id
+     * @param string $compile_id
+     */
+    function display($resource_name, $cache_id = null, $compile_id = null)
+    {
+        $this->fetch($resource_name, $cache_id, $compile_id, true);
+    }
+
+    /**
+     * executes & returns or displays the template results
+     *
+     * @param string $resource_name
+     * @param string $cache_id
+     * @param string $compile_id
+     * @param boolean $display
+     */
+    function fetch($resource_name, $cache_id = null, $compile_id = null, $display = false)
+    {
+        static $_cache_info = array();
+        
+        $_smarty_old_error_level = $this->debugging ? error_reporting() : error_reporting(isset($this->error_reporting)
+               ? $this->error_reporting : error_reporting() & ~E_NOTICE);
+
+        if (!$this->debugging && $this->debugging_ctrl == 'URL') {
+            $_query_string = $this->request_use_auto_globals ? $_SERVER['QUERY_STRING'] : $GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING'];
+            if (@strstr($_query_string, $this->_smarty_debug_id)) {
+                if (@strstr($_query_string, $this->_smarty_debug_id . '=on')) {
+                    // enable debugging for this browser session
+                    @setcookie('SMARTY_DEBUG', true);
+                    $this->debugging = true;
+                } elseif (@strstr($_query_string, $this->_smarty_debug_id . '=off')) {
+                    // disable debugging for this browser session
+                    @setcookie('SMARTY_DEBUG', false);
+                    $this->debugging = false;
+                } else {
+                    // enable debugging for this page
+                    $this->debugging = true;
+                }
+            } else {
+                $this->debugging = (bool)($this->request_use_auto_globals ? @$_COOKIE['SMARTY_DEBUG'] : @$GLOBALS['HTTP_COOKIE_VARS']['SMARTY_DEBUG']);
+            }
+        }
+
+        if ($this->debugging) {
+            // capture time for debugging info
+            $_params = array();
+            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+            $_debug_start_time = smarty_core_get_microtime($_params, $this);
+            $this->_smarty_debug_info[] = array('type'      => 'template',
+                                                'filename'  => $resource_name,
+                                                'depth'     => 0);
+            $_included_tpls_idx = count($this->_smarty_debug_info) - 1;
+        }
+
+        if (!isset($compile_id)) {
+            $compile_id = $this->compile_id;
+        }
+
+        $this->_compile_id = $compile_id;
+        $this->_inclusion_depth = 0;
+
+        if ($this->caching) {
+            // save old cache_info, initialize cache_info
+            array_push($_cache_info, $this->_cache_info);
+            $this->_cache_info = array();
+            $_params = array(
+                'tpl_file' => $resource_name,
+                'cache_id' => $cache_id,
+                'compile_id' => $compile_id,
+                'results' => null
+            );
+            require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php');
+            if (smarty_core_read_cache_file($_params, $this)) {
+                $_smarty_results = $_params['results'];
+                if (!empty($this->_cache_info['insert_tags'])) {
+                    $_params = array('plugins' => $this->_cache_info['insert_tags']);
+                    require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
+                    smarty_core_load_plugins($_params, $this);
+                    $_params = array('results' => $_smarty_results);
+                    require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php');
+                    $_smarty_results = smarty_core_process_cached_inserts($_params, $this);
+                }
+                if (!empty($this->_cache_info['cache_serials'])) {
+                    $_params = array('results' => $_smarty_results);
+                    require_once(SMARTY_CORE_DIR . 'core.process_compiled_include.php');
+                    $_smarty_results = smarty_core_process_compiled_include($_params, $this);
+                }
+
+
+                if ($display) {
+                    if ($this->debugging)
+                    {
+                        // capture time for debugging info
+                        $_params = array();
+                        require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+                        $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $_debug_start_time;
+                        require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php');
+                        $_smarty_results .= smarty_core_display_debug_console($_params, $this);
+                    }
+                    if ($this->cache_modified_check) {
+                        $_server_vars = ($this->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
+                        $_last_modified_date = @substr($_server_vars['HTTP_IF_MODIFIED_SINCE'], 0, strpos($_server_vars['HTTP_IF_MODIFIED_SINCE'], 'GMT') + 3);
+                        $_gmt_mtime = gmdate('D, d M Y H:i:s', $this->_cache_info['timestamp']).' GMT';
+                        if (@count($this->_cache_info['insert_tags']) == 0
+                            && !$this->_cache_serials
+                            && $_gmt_mtime == $_last_modified_date) {
+                            if (php_sapi_name()=='cgi')
+                                header('Status: 304 Not Modified');
+                            else
+                                header('HTTP/1.1 304 Not Modified');
+
+                        } else {
+                            header('Last-Modified: '.$_gmt_mtime);
+                            echo $_smarty_results;
+                        }
+                    } else {
+                            echo $_smarty_results;
+                    }
+                    error_reporting($_smarty_old_error_level);
+                    // restore initial cache_info
+                    $this->_cache_info = array_pop($_cache_info);
+                    return true;
+                } else {
+                    error_reporting($_smarty_old_error_level);
+                    // restore initial cache_info
+                    $this->_cache_info = array_pop($_cache_info);
+                    return $_smarty_results;
+                }
+            } else {
+                $this->_cache_info['template'][$resource_name] = true;
+                if ($this->cache_modified_check && $display) {
+                    header('Last-Modified: '.gmdate('D, d M Y H:i:s', time()).' GMT');
+                }
+            }
+        }
+
+        // load filters that are marked as autoload
+        if (count($this->autoload_filters)) {
+            foreach ($this->autoload_filters as $_filter_type => $_filters) {
+                foreach ($_filters as $_filter) {
+                    $this->load_filter($_filter_type, $_filter);
+                }
+            }
+        }
+
+        $_smarty_compile_path = $this->_get_compile_path($resource_name);
+
+        // if we just need to display the results, don't perform output
+        // buffering - for speed
+        $_cache_including = $this->_cache_including;
+        $this->_cache_including = false;
+        if ($display && !$this->caching && count($this->_plugins['outputfilter']) == 0) {
+            if ($this->_is_compiled($resource_name, $_smarty_compile_path)
+                    || $this->_compile_resource($resource_name, $_smarty_compile_path))
+            {
+                include($_smarty_compile_path);
+            }
+        } else {
+            ob_start();
+            if ($this->_is_compiled($resource_name, $_smarty_compile_path)
+                    || $this->_compile_resource($resource_name, $_smarty_compile_path))
+            {
+                include($_smarty_compile_path);
+            }
+            $_smarty_results = ob_get_contents();
+            ob_end_clean();
+
+            foreach ((array)$this->_plugins['outputfilter'] as $_output_filter) {
+                $_smarty_results = call_user_func_array($_output_filter[0], array($_smarty_results, &$this));
+            }
+        }
+
+        if ($this->caching) {
+            $_params = array('tpl_file' => $resource_name,
+                        'cache_id' => $cache_id,
+                        'compile_id' => $compile_id,
+                        'results' => $_smarty_results);
+            require_once(SMARTY_CORE_DIR . 'core.write_cache_file.php');
+            smarty_core_write_cache_file($_params, $this);
+            require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php');
+            $_smarty_results = smarty_core_process_cached_inserts($_params, $this);
+
+            if ($this->_cache_serials) {
+                // strip nocache-tags from output
+                $_smarty_results = preg_replace('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!s'
+                                                ,''
+                                                ,$_smarty_results);
+            }
+            // restore initial cache_info
+            $this->_cache_info = array_pop($_cache_info);
+        }
+        $this->_cache_including = $_cache_including;
+
+        if ($display) {
+            if (isset($_smarty_results)) { echo $_smarty_results; }
+            if ($this->debugging) {
+                // capture time for debugging info
+                $_params = array();
+                require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+                $this->_smarty_debug_info[$_included_tpls_idx]['exec_time'] = (smarty_core_get_microtime($_params, $this) - $_debug_start_time);
+                require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php');
+                echo smarty_core_display_debug_console($_params, $this);
+            }
+            error_reporting($_smarty_old_error_level);
+            return;
+        } else {
+            error_reporting($_smarty_old_error_level);
+            if (isset($_smarty_results)) { return $_smarty_results; }
+        }
+    }
+
+    /**
+     * load configuration values
+     *
+     * @param string $file
+     * @param string $section
+     * @param string $scope
+     */
+    function config_load($file, $section = null, $scope = 'global')
+    {
+        require_once($this->_get_plugin_filepath('function', 'config_load'));
+        smarty_function_config_load(array('file' => $file, 'section' => $section, 'scope' => $scope), $this);
+    }
+
+    /**
+     * return a reference to a registered object
+     *
+     * @param string $name
+     * @return object
+     */
+    function &get_registered_object($name) {
+        if (!isset($this->_reg_objects[$name]))
+        $this->_trigger_fatal_error("'$name' is not a registered object");
+
+        if (!is_object($this->_reg_objects[$name][0]))
+        $this->_trigger_fatal_error("registered '$name' is not an object");
+
+        return $this->_reg_objects[$name][0];
+    }
+
+    /**
+     * clear configuration values
+     *
+     * @param string $var
+     */
+    function clear_config($var = null)
+    {
+        if(!isset($var)) {
+            // clear all values
+            $this->_config = array(array('vars'  => array(),
+                                         'files' => array()));
+        } else {
+            unset($this->_config[0]['vars'][$var]);
+        }
+    }
+
+    /**
+     * get filepath of requested plugin
+     *
+     * @param string $type
+     * @param string $name
+     * @return string|false
+     */
+    function _get_plugin_filepath($type, $name)
+    {
+        $_params = array('type' => $type, 'name' => $name);
+        require_once(SMARTY_CORE_DIR . 'core.assemble_plugin_filepath.php');
+        return smarty_core_assemble_plugin_filepath($_params, $this);
+    }
+
+   /**
+     * test if resource needs compiling
+     *
+     * @param string $resource_name
+     * @param string $compile_path
+     * @return boolean
+     */
+    function _is_compiled($resource_name, $compile_path)
+    {
+        if (!$this->force_compile && file_exists($compile_path)) {
+            if (!$this->compile_check) {
+                // no need to check compiled file
+                return true;
+            } else {
+                // get file source and timestamp
+                $_params = array('resource_name' => $resource_name, 'get_source'=>false);
+                if (!$this->_fetch_resource_info($_params)) {
+                    return false;
+                }
+                if ($_params['resource_timestamp'] <= filemtime($compile_path)) {
+                    // template not expired, no recompile
+                    return true;
+                } else {
+                    // compile template
+                    return false;
+                }
+            }
+        } else {
+            // compiled template does not exist, or forced compile
+            return false;
+        }
+    }
+
+   /**
+     * compile the template
+     *
+     * @param string $resource_name
+     * @param string $compile_path
+     * @return boolean
+     */
+    function _compile_resource($resource_name, $compile_path)
+    {
+
+        $_params = array('resource_name' => $resource_name);
+        if (!$this->_fetch_resource_info($_params)) {
+            return false;
+        }
+
+        $_source_content = $_params['source_content'];
+        $_cache_include    = substr($compile_path, 0, -4).'.inc';
+
+        if ($this->_compile_source($resource_name, $_source_content, $_compiled_content, $_cache_include)) {
+            // if a _cache_serial was set, we also have to write an include-file:
+            if ($this->_cache_include_info) {
+                require_once(SMARTY_CORE_DIR . 'core.write_compiled_include.php');
+                smarty_core_write_compiled_include(array_merge($this->_cache_include_info, array('compiled_content'=>$_compiled_content, 'resource_name'=>$resource_name)),  $this);
+            }
+
+            $_params = array('compile_path'=>$compile_path, 'compiled_content' => $_compiled_content);
+            require_once(SMARTY_CORE_DIR . 'core.write_compiled_resource.php');
+            smarty_core_write_compiled_resource($_params, $this);
+
+            return true;
+        } else {
+            return false;
+        }
+
+    }
+
+   /**
+     * compile the given source
+     *
+     * @param string $resource_name
+     * @param string $source_content
+     * @param string $compiled_content
+     * @return boolean
+     */
+    function _compile_source($resource_name, &$source_content, &$compiled_content, $cache_include_path=null)
+    {
+        if (file_exists(SMARTY_DIR . $this->compiler_file)) {
+            require_once(SMARTY_DIR . $this->compiler_file);
+        } else {
+            // use include_path
+            require_once($this->compiler_file);
+        }
+
+
+        $smarty_compiler = new $this->compiler_class;
+
+        $smarty_compiler->template_dir      = $this->template_dir;
+        $smarty_compiler->compile_dir       = $this->compile_dir;
+        $smarty_compiler->plugins_dir       = $this->plugins_dir;
+        $smarty_compiler->config_dir        = $this->config_dir;
+        $smarty_compiler->force_compile     = $this->force_compile;
+        $smarty_compiler->caching           = $this->caching;
+        $smarty_compiler->php_handling      = $this->php_handling;
+        $smarty_compiler->left_delimiter    = $this->left_delimiter;
+        $smarty_compiler->right_delimiter   = $this->right_delimiter;
+        $smarty_compiler->_version          = $this->_version;
+        $smarty_compiler->security          = $this->security;
+        $smarty_compiler->secure_dir        = $this->secure_dir;
+        $smarty_compiler->security_settings = $this->security_settings;
+        $smarty_compiler->trusted_dir       = $this->trusted_dir;
+        $smarty_compiler->use_sub_dirs      = $this->use_sub_dirs;
+        $smarty_compiler->_reg_objects      = &$this->_reg_objects;
+        $smarty_compiler->_plugins          = &$this->_plugins;
+        $smarty_compiler->_tpl_vars         = &$this->_tpl_vars;
+        $smarty_compiler->default_modifiers = $this->default_modifiers;
+        $smarty_compiler->compile_id        = $this->_compile_id;
+        $smarty_compiler->_config            = $this->_config;
+        $smarty_compiler->request_use_auto_globals  = $this->request_use_auto_globals;
+
+        if (isset($cache_include_path) && isset($this->_cache_serials[$cache_include_path])) {
+            $smarty_compiler->_cache_serial = $this->_cache_serials[$cache_include_path];
+        }
+        $smarty_compiler->_cache_include = $cache_include_path;
+
+
+        $_results = $smarty_compiler->_compile_file($resource_name, $source_content, $compiled_content);
+
+        if ($smarty_compiler->_cache_serial) {
+            $this->_cache_include_info = array(
+                'cache_serial'=>$smarty_compiler->_cache_serial
+                ,'plugins_code'=>$smarty_compiler->_plugins_code
+                ,'include_file_path' => $cache_include_path);
+
+        } else {
+            $this->_cache_include_info = null;
+
+        }
+
+        return $_results;
+    }
+
+    /**
+     * Get the compile path for this resource
+     *
+     * @param string $resource_name
+     * @return string results of {@link _get_auto_filename()}
+     */
+    function _get_compile_path($resource_name)
+    {
+        return $this->_get_auto_filename($this->compile_dir, $resource_name,
+                                         $this->_compile_id) . '.php';
+    }
+
+    /**
+     * fetch the template info. Gets timestamp, and source
+     * if get_source is true
+     *
+     * sets $source_content to the source of the template, and
+     * $resource_timestamp to its time stamp
+     * @param string $resource_name
+     * @param string $source_content
+     * @param integer $resource_timestamp
+     * @param boolean $get_source
+     * @param boolean $quiet
+     * @return boolean
+     */
+
+    function _fetch_resource_info(&$params)
+    {
+        if(!isset($params['get_source'])) { $params['get_source'] = true; }
+        if(!isset($params['quiet'])) { $params['quiet'] = false; }
+
+        $_return = false;
+        $_params = array('resource_name' => $params['resource_name']) ;
+        if (isset($params['resource_base_path']))
+            $_params['resource_base_path'] = $params['resource_base_path'];
+        else
+            $_params['resource_base_path'] = $this->template_dir;
+
+        if ($this->_parse_resource_name($_params)) {
+            $_resource_type = $_params['resource_type'];
+            $_resource_name = $_params['resource_name'];
+            switch ($_resource_type) {
+                case 'file':
+                    if ($params['get_source']) {
+                        $params['source_content'] = $this->_read_file($_resource_name);
+                    }
+                    $params['resource_timestamp'] = filemtime($_resource_name);
+                    $_return = is_file($_resource_name);
+                    break;
+
+                default:
+                    // call resource functions to fetch the template source and timestamp
+                    if ($params['get_source']) {
+                        $_source_return = isset($this->_plugins['resource'][$_resource_type]) &&
+                            call_user_func_array($this->_plugins['resource'][$_resource_type][0][0],
+                                                 array($_resource_name, &$params['source_content'], &$this));
+                    } else {
+                        $_source_return = true;
+                    }
+
+                    $_timestamp_return = isset($this->_plugins['resource'][$_resource_type]) &&
+                        call_user_func_array($this->_plugins['resource'][$_resource_type][0][1],
+                                             array($_resource_name, &$params['resource_timestamp'], &$this));
+
+                    $_return = $_source_return && $_timestamp_return;
+                    break;
+            }
+        }
+
+        if (!$_return) {
+            // see if we can get a template with the default template handler
+            if (!empty($this->default_template_handler_func)) {
+                if (!is_callable($this->default_template_handler_func)) {
+                    $this->trigger_error("default template handler function \"$this->default_template_handler_func\" doesn't exist.");
+                } else {
+                    $_return = call_user_func_array(
+                        $this->default_template_handler_func,
+                        array($_params['resource_type'], $_params['resource_name'], &$params['source_content'], &$params['resource_timestamp'], &$this));
+                }
+            }
+        }
+
+        if (!$_return) {
+            if (!$params['quiet']) {
+                $this->trigger_error('unable to read resource: "' . $params['resource_name'] . '"');
+            }
+        } else if ($_return && $this->security) {
+            require_once(SMARTY_CORE_DIR . 'core.is_secure.php');
+            if (!smarty_core_is_secure($_params, $this)) {
+                if (!$params['quiet'])
+                    $this->trigger_error('(secure mode) accessing "' . $params['resource_name'] . '" is not allowed');
+                $params['source_content'] = null;
+                $params['resource_timestamp'] = null;
+                return false;
+            }
+        }
+        return $_return;
+    }
+
+
+    /**
+     * parse out the type and name from the resource
+     *
+     * @param string $resource_base_path
+     * @param string $resource_name
+     * @param string $resource_type
+     * @param string $resource_name
+     * @return boolean
+     */
+
+    function _parse_resource_name(&$params)
+    {
+
+        // split tpl_path by the first colon
+        $_resource_name_parts = explode(':', $params['resource_name'], 2);
+
+        if (count($_resource_name_parts) == 1) {
+            // no resource type given
+            $params['resource_type'] = $this->default_resource_type;
+            $params['resource_name'] = $_resource_name_parts[0];
+        } else {
+            if(strlen($_resource_name_parts[0]) == 1) {
+                // 1 char is not resource type, but part of filepath
+                $params['resource_type'] = $this->default_resource_type;
+                $params['resource_name'] = $params['resource_name'];
+            } else {
+                $params['resource_type'] = $_resource_name_parts[0];
+                $params['resource_name'] = $_resource_name_parts[1];
+            }
+        }
+
+        if ($params['resource_type'] == 'file') {
+            if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $params['resource_name'])) {
+                // relative pathname to $params['resource_base_path']
+                // use the first directory where the file is found
+                foreach ((array)$params['resource_base_path'] as $_curr_path) {
+                    $_fullpath = $_curr_path . DIRECTORY_SEPARATOR . $params['resource_name'];
+                    if (file_exists($_fullpath) && is_file($_fullpath)) {
+                        $params['resource_name'] = $_fullpath;
+                        return true;
+                    }
+                    // didn't find the file, try include_path
+                    $_params = array('file_path' => $_fullpath);
+                    require_once(SMARTY_CORE_DIR . 'core.get_include_path.php');
+                    if(smarty_core_get_include_path($_params, $this)) {
+                        $params['resource_name'] = $_params['new_file_path'];
+                        return true;
+                    }
+                }
+                return false;
+            } else {
+                /* absolute path */
+                return file_exists($params['resource_name']);
+            }
+        } elseif (empty($this->_plugins['resource'][$params['resource_type']])) {
+            $_params = array('type' => $params['resource_type']);
+            require_once(SMARTY_CORE_DIR . 'core.load_resource_plugin.php');
+            smarty_core_load_resource_plugin($_params, $this);
+        }
+
+        return true;
+    }
+
+
+    /**
+     * Handle modifiers
+     *
+     * @param string|null $modifier_name
+     * @param array|null $map_array
+     * @return string result of modifiers
+     */
+    function _run_mod_handler()
+    {
+        $_args = func_get_args();
+        list($_modifier_name, $_map_array) = array_splice($_args, 0, 2);
+        list($_func_name, $_tpl_file, $_tpl_line) =
+            $this->_plugins['modifier'][$_modifier_name];
+
+        $_var = $_args[0];
+        foreach ($_var as $_key => $_val) {
+            $_args[0] = $_val;
+            $_var[$_key] = call_user_func_array($_func_name, $_args);
+        }
+        return $_var;
+    }
+
+    /**
+     * Remove starting and ending quotes from the string
+     *
+     * @param string $string
+     * @return string
+     */
+    function _dequote($string)
+    {
+        if (($string{0} == "'" || $string{0} == '"') &&
+            $string{strlen($string)-1} == $string{0})
+            return substr($string, 1, -1);
+        else
+            return $string;
+    }
+
+
+    /**
+     * read in a file
+     *
+     * @param string $filename
+     * @return string
+     */
+    function _read_file($filename)
+    {
+        if ( file_exists($filename) && ($fd = @fopen($filename, 'rb')) ) {
+            $contents = ($size = filesize($filename)) ? fread($fd, $size) : '';
+            fclose($fd);
+            return $contents;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * get a concrete filename for automagically created content
+     *
+     * @param string $auto_base
+     * @param string $auto_source
+     * @param string $auto_id
+     * @return string
+     * @staticvar string|null
+     * @staticvar string|null
+     */
+    function _get_auto_filename($auto_base, $auto_source = null, $auto_id = null)
+    {
+        $_compile_dir_sep =  $this->use_sub_dirs ? DIRECTORY_SEPARATOR : '^';
+        $_return = $auto_base . DIRECTORY_SEPARATOR;
+
+        if(isset($auto_id)) {
+            // make auto_id safe for directory names
+            $auto_id = str_replace('%7C',$_compile_dir_sep,(urlencode($auto_id)));
+            // split into separate directories
+            $_return .= $auto_id . $_compile_dir_sep;
+        }
+
+        if(isset($auto_source)) {
+            // make source name safe for filename
+            $_filename = urlencode(basename($auto_source));
+            $_crc32 = sprintf('%08X', crc32($auto_source));
+            // prepend %% to avoid name conflicts with
+            // with $params['auto_id'] names
+            $_crc32 = substr($_crc32, 0, 2) . $_compile_dir_sep .
+                      substr($_crc32, 0, 3) . $_compile_dir_sep . $_crc32;
+            $_return .= '%%' . $_crc32 . '%%' . $_filename;
+        }
+
+        return $_return;
+    }
+
+    /**
+     * unlink a file, possibly using expiration time
+     *
+     * @param string $resource
+     * @param integer $exp_time
+     */
+    function _unlink($resource, $exp_time = null)
+    {
+        if(isset($exp_time)) {
+            if(time() - @filemtime($resource) >= $exp_time) {
+                return @unlink($resource);
+            }
+        } else {
+            return @unlink($resource);
+        }
+    }
+
+    /**
+     * returns an auto_id for auto-file-functions
+     *
+     * @param string $cache_id
+     * @param string $compile_id
+     * @return string|null
+     */
+    function _get_auto_id($cache_id=null, $compile_id=null) {
+    if (isset($cache_id))
+        return (isset($compile_id)) ? $cache_id . '|' . $compile_id  : $cache_id;
+    elseif(isset($compile_id))
+        return $compile_id;
+    else
+        return null;
+    }
+
+    /**
+     * trigger Smarty plugin error
+     *
+     * @param string $error_msg
+     * @param string $tpl_file
+     * @param integer $tpl_line
+     * @param string $file
+     * @param integer $line
+     * @param integer $error_type
+     */
+    function _trigger_fatal_error($error_msg, $tpl_file = null, $tpl_line = null,
+            $file = null, $line = null, $error_type = E_USER_ERROR)
+    {
+        if(isset($file) && isset($line)) {
+            $info = ' ('.basename($file).", line $line)";
+        } else {
+            $info = '';
+        }
+        if (isset($tpl_line) && isset($tpl_file)) {
+            $this->trigger_error('[in ' . $tpl_file . ' line ' . $tpl_line . "]: $error_msg$info", $error_type);
+        } else {
+            $this->trigger_error($error_msg . $info, $error_type);
+        }
+    }
+
+
+    /**
+     * callback function for preg_replace, to call a non-cacheable block
+     * @return string
+     */
+    function _process_compiled_include_callback($match) {
+        $_func = '_smarty_tplfunc_'.$match[2].'_'.$match[3];
+        ob_start();
+        $_func($this);
+        $_ret = ob_get_contents();
+        ob_end_clean();
+        return $_ret;
+    }
+
+
+    /**
+     * called for included templates
+     *
+     * @param string $_smarty_include_tpl_file
+     * @param string $_smarty_include_vars
+     */
+
+    // $_smarty_include_tpl_file, $_smarty_include_vars
+
+    function _smarty_include($params)
+    {
+        if ($this->debugging) {
+            $_params = array();
+            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+            $debug_start_time = smarty_core_get_microtime($_params, $this);
+            $this->_smarty_debug_info[] = array('type'      => 'template',
+                                                  'filename'  => $params['smarty_include_tpl_file'],
+                                                  'depth'     => ++$this->_inclusion_depth);
+            $included_tpls_idx = count($this->_smarty_debug_info) - 1;
+        }
+
+        $this->_tpl_vars = array_merge($this->_tpl_vars, $params['smarty_include_vars']);
+
+        // config vars are treated as local, so push a copy of the
+        // current ones onto the front of the stack
+        array_unshift($this->_config, $this->_config[0]);
+
+        $_smarty_compile_path = $this->_get_compile_path($params['smarty_include_tpl_file']);
+
+
+        if ($this->_is_compiled($params['smarty_include_tpl_file'], $_smarty_compile_path)
+            || $this->_compile_resource($params['smarty_include_tpl_file'], $_smarty_compile_path))
+        {
+            include($_smarty_compile_path);
+        }
+
+        // pop the local vars off the front of the stack
+        array_shift($this->_config);
+
+        $this->_inclusion_depth--;
+
+        if ($this->debugging) {
+            // capture time for debugging info
+            $_params = array();
+            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+            $this->_smarty_debug_info[$included_tpls_idx]['exec_time'] = smarty_core_get_microtime($_params, $this) - $debug_start_time;
+        }
+
+        if ($this->caching) {
+            $this->_cache_info['template'][$params['smarty_include_tpl_file']] = true;
+        }
+    }
+
+
+    /**
+     * get or set an array of cached attributes for function that is
+     * not cacheable
+     * @return array
+     */
+    function &_smarty_cache_attrs($cache_serial, $count) {
+        $_cache_attrs =& $this->_cache_info['cache_attrs'][$cache_serial][$count];
+
+        if ($this->_cache_including) {
+            /* return next set of cache_attrs */
+            $_return =& current($_cache_attrs);
+            next($_cache_attrs);
+            return $_return;
+
+        } else {
+            /* add a reference to a new set of cache_attrs */
+            $_cache_attrs[] = array();
+            return $_cache_attrs[count($_cache_attrs)-1];
+
+        }
+
+    }
+
+
+    /**
+     * wrapper for include() retaining $this
+     * @return mixed
+     */
+    function _include($filename, $once=false, $params=null)
+    {
+        if ($once) {
+            return include_once($filename);
+        } else {
+            return include($filename);
+        }
+    }
+
+
+    /**
+     * wrapper for eval() retaining $this
+     * @return mixed
+     */
+    function _eval($code, $params=null)
+    {
+        return eval($code);
+    }
+    /**#@-*/
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/Smarty_Compiler.class.php b/bundled-libs/Smarty/libs/Smarty_Compiler.class.php
new file mode 100644 (file)
index 0000000..acc3de8
--- /dev/null
@@ -0,0 +1,2304 @@
+<?php
+
+/**
+ * Project:     Smarty: the PHP compiling template engine
+ * File:        Smarty_Compiler.class.php
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ * @link http://smarty.php.net/
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author Andrei Zmievski <andrei@php.net>
+ * @version 2.6.9
+ * @copyright 2001-2005 New Digital Group, Inc.
+ * @package Smarty
+ */
+
+/* $Id: Smarty_Compiler.class.php,v 1.4 2005/04/01 08:38:12 tomsommer Exp $ */
+
+/**
+ * Template compiling class
+ * @package Smarty
+ */
+class Smarty_Compiler extends Smarty {
+
+    // internal vars
+    /**#@+
+     * @access private
+     */
+    var $_folded_blocks         =   array();    // keeps folded template blocks
+    var $_current_file          =   null;       // the current template being compiled
+    var $_current_line_no       =   1;          // line number for error messages
+    var $_capture_stack         =   array();    // keeps track of nested capture buffers
+    var $_plugin_info           =   array();    // keeps track of plugins to load
+    var $_init_smarty_vars      =   false;
+    var $_permitted_tokens      =   array('true','false','yes','no','on','off','null');
+    var $_db_qstr_regexp        =   null;        // regexps are setup in the constructor
+    var $_si_qstr_regexp        =   null;
+    var $_qstr_regexp           =   null;
+    var $_func_regexp           =   null;
+    var $_reg_obj_regexp        =   null;
+    var $_var_bracket_regexp    =   null;
+    var $_num_const_regexp      =   null;
+    var $_dvar_guts_regexp      =   null;
+    var $_dvar_regexp           =   null;
+    var $_cvar_regexp           =   null;
+    var $_svar_regexp           =   null;
+    var $_avar_regexp           =   null;
+    var $_mod_regexp            =   null;
+    var $_var_regexp            =   null;
+    var $_parenth_param_regexp  =   null;
+    var $_func_call_regexp      =   null;
+    var $_obj_ext_regexp        =   null;
+    var $_obj_start_regexp      =   null;
+    var $_obj_params_regexp     =   null;
+    var $_obj_call_regexp       =   null;
+    var $_cacheable_state       =   0;
+    var $_cache_attrs_count     =   0;
+    var $_nocache_count         =   0;
+    var $_cache_serial          =   null;
+    var $_cache_include         =   null;
+
+    var $_strip_depth           =   0;
+    var $_additional_newline    =   "\n";
+
+    /**#@-*/
+    /**
+     * The class constructor.
+     */
+    function Smarty_Compiler()
+    {
+        // matches double quoted strings:
+        // "foobar"
+        // "foo\"bar"
+        $this->_db_qstr_regexp = '"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"';
+
+        // matches single quoted strings:
+        // 'foobar'
+        // 'foo\'bar'
+        $this->_si_qstr_regexp = '\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\'';
+
+        // matches single or double quoted strings
+        $this->_qstr_regexp = '(?:' . $this->_db_qstr_regexp . '|' . $this->_si_qstr_regexp . ')';
+
+        // matches bracket portion of vars
+        // [0]
+        // [foo]
+        // [$bar]
+        $this->_var_bracket_regexp = '\[\$?[\w\.]+\]';
+
+        // matches numerical constants
+        // 30
+        // -12
+        // 13.22
+        $this->_num_const_regexp = '(?:\-?\d+(?:\.\d+)?)';
+
+        // matches $ vars (not objects):
+        // $foo
+        // $foo.bar
+        // $foo.bar.foobar
+        // $foo[0]
+        // $foo[$bar]
+        // $foo[5][blah]
+        // $foo[5].bar[$foobar][4]
+        $this->_dvar_math_regexp = '(?:[\+\*\/\%]|(?:-(?!>)))';
+        $this->_dvar_math_var_regexp = '[\$\w\.\+\-\*\/\%\d\>\[\]]';
+        $this->_dvar_guts_regexp = '\w+(?:' . $this->_var_bracket_regexp
+                . ')*(?:\.\$?\w+(?:' . $this->_var_bracket_regexp . ')*)*(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?';
+        $this->_dvar_regexp = '\$' . $this->_dvar_guts_regexp;
+
+        // matches config vars:
+        // #foo#
+        // #foobar123_foo#
+        $this->_cvar_regexp = '\#\w+\#';
+
+        // matches section vars:
+        // %foo.bar%
+        $this->_svar_regexp = '\%\w+\.\w+\%';
+
+        // matches all valid variables (no quotes, no modifiers)
+        $this->_avar_regexp = '(?:' . $this->_dvar_regexp . '|'
+           . $this->_cvar_regexp . '|' . $this->_svar_regexp . ')';
+
+        // matches valid variable syntax:
+        // $foo
+        // $foo
+        // #foo#
+        // #foo#
+        // "text"
+        // "text"
+        $this->_var_regexp = '(?:' . $this->_avar_regexp . '|' . $this->_qstr_regexp . ')';
+
+        // matches valid object call (one level of object nesting allowed in parameters):
+        // $foo->bar
+        // $foo->bar()
+        // $foo->bar("text")
+        // $foo->bar($foo, $bar, "text")
+        // $foo->bar($foo, "foo")
+        // $foo->bar->foo()
+        // $foo->bar->foo->bar()
+        // $foo->bar($foo->bar)
+        // $foo->bar($foo->bar())
+        // $foo->bar($foo->bar($blah,$foo,44,"foo",$foo[0].bar))
+        $this->_obj_ext_regexp = '\->(?:\$?' . $this->_dvar_guts_regexp . ')';
+        $this->_obj_restricted_param_regexp = '(?:'
+                . '(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')(?:' . $this->_obj_ext_regexp . '(?:\((?:(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . ')'
+                . '(?:\s*,\s*(?:' . $this->_var_regexp . '|' . $this->_num_const_regexp . '))*)?\))?)*)';
+        $this->_obj_single_param_regexp = '(?:\w+|' . $this->_obj_restricted_param_regexp . '(?:\s*,\s*(?:(?:\w+|'
+                . $this->_var_regexp . $this->_obj_restricted_param_regexp . ')))*)';
+        $this->_obj_params_regexp = '\((?:' . $this->_obj_single_param_regexp
+                . '(?:\s*,\s*' . $this->_obj_single_param_regexp . ')*)?\)';
+        $this->_obj_start_regexp = '(?:' . $this->_dvar_regexp . '(?:' . $this->_obj_ext_regexp . ')+)';
+        $this->_obj_call_regexp = '(?:' . $this->_obj_start_regexp . '(?:' . $this->_obj_params_regexp . ')?(?:' . $this->_dvar_math_regexp . '(?:' . $this->_num_const_regexp . '|' . $this->_dvar_math_var_regexp . ')*)?)';
+        
+        // matches valid modifier syntax:
+        // |foo
+        // |@foo
+        // |foo:"bar"
+        // |foo:$bar
+        // |foo:"bar":$foobar
+        // |foo|bar
+        // |foo:$foo->bar
+        $this->_mod_regexp = '(?:\|@?\w+(?::(?:\w+|' . $this->_num_const_regexp . '|'
+           . $this->_obj_call_regexp . '|' . $this->_avar_regexp . '|' . $this->_qstr_regexp .'))*)';
+
+        // matches valid function name:
+        // foo123
+        // _foo_bar
+        $this->_func_regexp = '[a-zA-Z_]\w*';
+
+        // matches valid registered object:
+        // foo->bar
+        $this->_reg_obj_regexp = '[a-zA-Z_]\w*->[a-zA-Z_]\w*';
+
+        // matches valid parameter values:
+        // true
+        // $foo
+        // $foo|bar
+        // #foo#
+        // #foo#|bar
+        // "text"
+        // "text"|bar
+        // $foo->bar
+        $this->_param_regexp = '(?:\s*(?:' . $this->_obj_call_regexp . '|'
+           . $this->_var_regexp . '|' . $this->_num_const_regexp  . '|\w+)(?>' . $this->_mod_regexp . '*)\s*)';
+
+        // matches valid parenthesised function parameters:
+        //
+        // "text"
+        //    $foo, $bar, "text"
+        // $foo|bar, "foo"|bar, $foo->bar($foo)|bar
+        $this->_parenth_param_regexp = '(?:\((?:\w+|'
+                . $this->_param_regexp . '(?:\s*,\s*(?:(?:\w+|'
+                . $this->_param_regexp . ')))*)?\))';
+
+        // matches valid function call:
+        // foo()
+        // foo_bar($foo)
+        // _foo_bar($foo,"bar")
+        // foo123($foo,$foo->bar(),"foo")
+        $this->_func_call_regexp = '(?:' . $this->_func_regexp . '\s*(?:'
+           . $this->_parenth_param_regexp . '))';
+    }
+
+    /**
+     * compile a resource
+     *
+     * sets $compiled_content to the compiled source
+     * @param string $resource_name
+     * @param string $source_content
+     * @param string $compiled_content
+     * @return true
+     */
+    function _compile_file($resource_name, $source_content, &$compiled_content)
+    {
+
+        if ($this->security) {
+            // do not allow php syntax to be executed unless specified
+            if ($this->php_handling == SMARTY_PHP_ALLOW &&
+                !$this->security_settings['PHP_HANDLING']) {
+                $this->php_handling = SMARTY_PHP_PASSTHRU;
+            }
+        }
+
+        $this->_load_filters();
+
+        $this->_current_file = $resource_name;
+        $this->_current_line_no = 1;
+        $ldq = preg_quote($this->left_delimiter, '~');
+        $rdq = preg_quote($this->right_delimiter, '~');
+
+        // run template source through prefilter functions
+        if (count($this->_plugins['prefilter']) > 0) {
+            foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) {
+                if ($prefilter === false) continue;
+                if ($prefilter[3] || is_callable($prefilter[0])) {
+                    $source_content = call_user_func_array($prefilter[0],
+                                                            array($source_content, &$this));
+                    $this->_plugins['prefilter'][$filter_name][3] = true;
+                } else {
+                    $this->_trigger_fatal_error("[plugin] prefilter '$filter_name' is not implemented");
+                }
+            }
+        }
+
+        /* fetch all special blocks */
+        $search = "~{$ldq}\*(.*?)\*{$rdq}|{$ldq}\s*literal\s*{$rdq}(.*?){$ldq}\s*/literal\s*{$rdq}|{$ldq}\s*php\s*{$rdq}(.*?){$ldq}\s*/php\s*{$rdq}~s";
+
+        preg_match_all($search, $source_content, $match,  PREG_SET_ORDER);
+        $this->_folded_blocks = $match;
+        reset($this->_folded_blocks);
+
+        /* replace special blocks by "{php}" */
+        $source_content = preg_replace($search.'e', "'"
+                                       . $this->_quote_replace($this->left_delimiter) . 'php'
+                                       . "' . str_repeat(\"\n\", substr_count('\\0', \"\n\")) .'"
+                                       . $this->_quote_replace($this->right_delimiter)
+                                       . "'"
+                                       , $source_content);
+
+        /* Gather all template tags. */
+        preg_match_all("~{$ldq}\s*(.*?)\s*{$rdq}~s", $source_content, $_match);
+        $template_tags = $_match[1];
+        /* Split content by template tags to obtain non-template content. */
+        $text_blocks = preg_split("~{$ldq}.*?{$rdq}~s", $source_content);
+
+        /* loop through text blocks */
+        for ($curr_tb = 0, $for_max = count($text_blocks); $curr_tb < $for_max; $curr_tb++) {
+            /* match anything resembling php tags */
+            if (preg_match_all('~(<\?(?:\w+|=)?|\?>|language\s*=\s*[\"\']?php[\"\']?)~is', $text_blocks[$curr_tb], $sp_match)) {
+                /* replace tags with placeholders to prevent recursive replacements */
+                $sp_match[1] = array_unique($sp_match[1]);
+                usort($sp_match[1], '_smarty_sort_length');
+                for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {
+                    $text_blocks[$curr_tb] = str_replace($sp_match[1][$curr_sp],'%%%SMARTYSP'.$curr_sp.'%%%',$text_blocks[$curr_tb]);
+                }
+                /* process each one */
+                for ($curr_sp = 0, $for_max2 = count($sp_match[1]); $curr_sp < $for_max2; $curr_sp++) {
+                    if ($this->php_handling == SMARTY_PHP_PASSTHRU) {
+                        /* echo php contents */
+                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '<?php echo \''.str_replace("'", "\'", $sp_match[1][$curr_sp]).'\'; ?>'."\n", $text_blocks[$curr_tb]);
+                    } else if ($this->php_handling == SMARTY_PHP_QUOTE) {
+                        /* quote php tags */
+                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', htmlspecialchars($sp_match[1][$curr_sp]), $text_blocks[$curr_tb]);
+                    } else if ($this->php_handling == SMARTY_PHP_REMOVE) {
+                        /* remove php tags */
+                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', '', $text_blocks[$curr_tb]);
+                    } else {
+                        /* SMARTY_PHP_ALLOW, but echo non php starting tags */
+                        $sp_match[1][$curr_sp] = preg_replace('~(<\?(?!php|=|$))~i', '<?php echo \'\\1\'?>'."\n", $sp_match[1][$curr_sp]);
+                        $text_blocks[$curr_tb] = str_replace('%%%SMARTYSP'.$curr_sp.'%%%', $sp_match[1][$curr_sp], $text_blocks[$curr_tb]);
+                    }
+                }
+            }
+        }
+
+        /* Compile the template tags into PHP code. */
+        $compiled_tags = array();
+        for ($i = 0, $for_max = count($template_tags); $i < $for_max; $i++) {
+            $this->_current_line_no += substr_count($text_blocks[$i], "\n");
+            $compiled_tags[] = $this->_compile_tag($template_tags[$i]);
+            $this->_current_line_no += substr_count($template_tags[$i], "\n");
+        }
+        if (count($this->_tag_stack)>0) {
+            list($_open_tag, $_line_no) = end($this->_tag_stack);
+            $this->_syntax_error("unclosed tag \{$_open_tag} (opened line $_line_no).", E_USER_ERROR, __FILE__, __LINE__);
+            return;
+        }
+
+        /* Reformat $text_blocks between 'strip' and '/strip' tags,
+           removing spaces, tabs and newlines. */
+        $strip = false;
+        for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {
+            if ($compiled_tags[$i] == '{strip}') {
+                $compiled_tags[$i] = '';
+                $strip = true;
+                /* remove leading whitespaces */
+                $text_blocks[$i + 1] = ltrim($text_blocks[$i + 1]);
+            }
+            if ($strip) {
+                /* strip all $text_blocks before the next '/strip' */
+                for ($j = $i + 1; $j < $for_max; $j++) {
+                    /* remove leading and trailing whitespaces of each line */
+                    $text_blocks[$j] = preg_replace('![\t ]*[\r\n]+[\t ]*!', '', $text_blocks[$j]);
+                    if ($compiled_tags[$j] == '{/strip}') {                       
+                        /* remove trailing whitespaces from the last text_block */
+                        $text_blocks[$j] = rtrim($text_blocks[$j]);
+                    }
+                    $text_blocks[$j] = "<?php echo '" . strtr($text_blocks[$j], array("'"=>"\'", "\\"=>"\\\\")) . "'; ?>";
+                    if ($compiled_tags[$j] == '{/strip}') {
+                        $compiled_tags[$j] = "\n"; /* slurped by php, but necessary
+                                    if a newline is following the closing strip-tag */
+                        $strip = false;
+                        $i = $j;
+                        break;
+                    }
+                }
+            }
+        }
+        $compiled_content = '';
+
+        /* Interleave the compiled contents and text blocks to get the final result. */
+        for ($i = 0, $for_max = count($compiled_tags); $i < $for_max; $i++) {
+            if ($compiled_tags[$i] == '') {
+                // tag result empty, remove first newline from following text block
+                $text_blocks[$i+1] = preg_replace('~^(\r\n|\r|\n)~', '', $text_blocks[$i+1]);
+            }
+            $compiled_content .= $text_blocks[$i].$compiled_tags[$i];
+        }
+        $compiled_content .= $text_blocks[$i];
+
+        // remove \n from the end of the file, if any
+        if (($_len=strlen($compiled_content)) && ($compiled_content{$_len - 1} == "\n" )) {
+            $compiled_content = substr($compiled_content, 0, -1);
+        }
+
+        if (!empty($this->_cache_serial)) {
+            $compiled_content = "<?php \$this->_cache_serials['".$this->_cache_include."'] = '".$this->_cache_serial."'; ?>" . $compiled_content;
+        }
+
+        // remove unnecessary close/open tags
+        $compiled_content = preg_replace('~\?>\n?<\?php~', '', $compiled_content);
+
+        // run compiled template through postfilter functions
+        if (count($this->_plugins['postfilter']) > 0) {
+            foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) {
+                if ($postfilter === false) continue;
+                if ($postfilter[3] || is_callable($postfilter[0])) {
+                    $compiled_content = call_user_func_array($postfilter[0],
+                                                              array($compiled_content, &$this));
+                    $this->_plugins['postfilter'][$filter_name][3] = true;
+                } else {
+                    $this->_trigger_fatal_error("Smarty plugin error: postfilter '$filter_name' is not implemented");
+                }
+            }
+        }
+
+        // put header at the top of the compiled template
+        $template_header = "<?php /* Smarty version ".$this->_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n";
+        $template_header .= "         compiled from ".strtr(urlencode($resource_name), array('%2F'=>'/', '%3A'=>':'))." */ ?>\n";
+
+        /* Emit code to load needed plugins. */
+        $this->_plugins_code = '';
+        if (count($this->_plugin_info)) {
+            $_plugins_params = "array('plugins' => array(";
+            foreach ($this->_plugin_info as $plugin_type => $plugins) {
+                foreach ($plugins as $plugin_name => $plugin_info) {
+                    $_plugins_params .= "array('$plugin_type', '$plugin_name', '" . strtr($plugin_info[0], array("'" => "\\'", "\\" => "\\\\")) . "', $plugin_info[1], ";
+                    $_plugins_params .= $plugin_info[2] ? 'true),' : 'false),';
+                }
+            }
+            $_plugins_params .= '))';
+            $plugins_code = "<?php require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');\nsmarty_core_load_plugins($_plugins_params, \$this); ?>\n";
+            $template_header .= $plugins_code;
+            $this->_plugin_info = array();
+            $this->_plugins_code = $plugins_code;
+        }
+
+        if ($this->_init_smarty_vars) {
+            $template_header .= "<?php require_once(SMARTY_CORE_DIR . 'core.assign_smarty_interface.php');\nsmarty_core_assign_smarty_interface(null, \$this); ?>\n";
+            $this->_init_smarty_vars = false;
+        }
+
+        $compiled_content = $template_header . $compiled_content;
+        return true;
+    }
+
+    /**
+     * Compile a template tag
+     *
+     * @param string $template_tag
+     * @return string
+     */
+    function _compile_tag($template_tag)
+    {
+        /* Matched comment. */
+        if ($template_tag{0} == '*' && $template_tag{strlen($template_tag) - 1} == '*')
+            return '';
+        
+        /* Split tag into two three parts: command, command modifiers and the arguments. */
+        if(! preg_match('~^(?:(' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp
+                . '|\/?' . $this->_reg_obj_regexp . '|\/?' . $this->_func_regexp . ')(' . $this->_mod_regexp . '*))
+                      (?:\s+(.*))?$
+                    ~xs', $template_tag, $match)) {
+            $this->_syntax_error("unrecognized tag: $template_tag", E_USER_ERROR, __FILE__, __LINE__);
+        }
+        
+        $tag_command = $match[1];
+        $tag_modifier = isset($match[2]) ? $match[2] : null;
+        $tag_args = isset($match[3]) ? $match[3] : null;
+
+        if (preg_match('~^' . $this->_num_const_regexp . '|' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$~', $tag_command)) {
+            /* tag name is a variable or object */
+            $_return = $this->_parse_var_props($tag_command . $tag_modifier);
+            return "<?php echo $_return; ?>" . $this->_additional_newline;
+        }
+
+        /* If the tag name is a registered object, we process it. */
+        if (preg_match('~^\/?' . $this->_reg_obj_regexp . '$~', $tag_command)) {
+            return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier);
+        }
+
+        switch ($tag_command) {
+            case 'include':
+                return $this->_compile_include_tag($tag_args);
+
+            case 'include_php':
+                return $this->_compile_include_php_tag($tag_args);
+
+            case 'if':
+                $this->_push_tag('if');
+                return $this->_compile_if_tag($tag_args);
+
+            case 'else':
+                list($_open_tag) = end($this->_tag_stack);
+                if ($_open_tag != 'if' && $_open_tag != 'elseif')
+                    $this->_syntax_error('unexpected {else}', E_USER_ERROR, __FILE__, __LINE__);
+                else
+                    $this->_push_tag('else');
+                return '<?php else: ?>';
+
+            case 'elseif':
+                list($_open_tag) = end($this->_tag_stack);
+                if ($_open_tag != 'if' && $_open_tag != 'elseif')
+                    $this->_syntax_error('unexpected {elseif}', E_USER_ERROR, __FILE__, __LINE__);
+                if ($_open_tag == 'if')
+                    $this->_push_tag('elseif');
+                return $this->_compile_if_tag($tag_args, true);
+
+            case '/if':
+                $this->_pop_tag('if');
+                return '<?php endif; ?>';
+
+            case 'capture':
+                return $this->_compile_capture_tag(true, $tag_args);
+
+            case '/capture':
+                return $this->_compile_capture_tag(false);
+
+            case 'ldelim':
+                return $this->left_delimiter;
+
+            case 'rdelim':
+                return $this->right_delimiter;
+
+            case 'section':
+                $this->_push_tag('section');
+                return $this->_compile_section_start($tag_args);
+
+            case 'sectionelse':
+                $this->_push_tag('sectionelse');
+                return "<?php endfor; else: ?>";
+                break;
+
+            case '/section':
+                $_open_tag = $this->_pop_tag('section');
+                if ($_open_tag == 'sectionelse')
+                    return "<?php endif; ?>";
+                else
+                    return "<?php endfor; endif; ?>";
+
+            case 'foreach':
+                $this->_push_tag('foreach');
+                return $this->_compile_foreach_start($tag_args);
+                break;
+
+            case 'foreachelse':
+                $this->_push_tag('foreachelse');
+                return "<?php endforeach; else: ?>";
+
+            case '/foreach':
+                $_open_tag = $this->_pop_tag('foreach');
+                if ($_open_tag == 'foreachelse')
+                    return "<?php endif; unset(\$_from); ?>";
+                else
+                    return "<?php endforeach; endif; unset(\$_from); ?>";
+                break;
+
+            case 'strip':
+            case '/strip':
+                if ($tag_command{0}=='/') {
+                    $this->_pop_tag('strip');
+                    if (--$this->_strip_depth==0) { /* outermost closing {/strip} */
+                        $this->_additional_newline = "\n";
+                        return '{' . $tag_command . '}';
+                    }
+                } else {
+                    $this->_push_tag('strip');
+                    if ($this->_strip_depth++==0) { /* outermost opening {strip} */
+                        $this->_additional_newline = "";
+                        return '{' . $tag_command . '}';
+                    }
+                }
+                return '';
+
+            case 'php':
+                /* handle folded tags replaced by {php} */
+                list(, $block) = each($this->_folded_blocks);
+                $this->_current_line_no += substr_count($block[0], "\n");
+                /* the number of matched elements in the regexp in _compile_file()
+                   determins the type of folded tag that was found */
+                switch (count($block)) {
+                    case 2: /* comment */
+                        return '';
+
+                    case 3: /* literal */
+                        return "<?php echo '" . strtr($block[2], array("'"=>"\'", "\\"=>"\\\\")) . "'; ?>" . $this->_additional_newline;
+
+                    case 4: /* php */
+                        if ($this->security && !$this->security_settings['PHP_TAGS']) {
+                            $this->_syntax_error("(secure mode) php tags not permitted", E_USER_WARNING, __FILE__, __LINE__);
+                            return;
+                        }
+                        return '<?php ' . $block[3] .' ?>';
+                }
+                break;
+
+            case 'insert':
+                return $this->_compile_insert_tag($tag_args);
+
+            default:
+                if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) {
+                    return $output;
+                } else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) {
+                    return $output;
+                } else if ($this->_compile_custom_tag($tag_command, $tag_args, $tag_modifier, $output)) {
+                    return $output;                    
+                } else {
+                    $this->_syntax_error("unrecognized tag '$tag_command'", E_USER_ERROR, __FILE__, __LINE__);
+                }
+
+        }
+    }
+
+
+    /**
+     * compile the custom compiler tag
+     *
+     * sets $output to the compiled custom compiler tag
+     * @param string $tag_command
+     * @param string $tag_args
+     * @param string $output
+     * @return boolean
+     */
+    function _compile_compiler_tag($tag_command, $tag_args, &$output)
+    {
+        $found = false;
+        $have_function = true;
+
+        /*
+         * First we check if the compiler function has already been registered
+         * or loaded from a plugin file.
+         */
+        if (isset($this->_plugins['compiler'][$tag_command])) {
+            $found = true;
+            $plugin_func = $this->_plugins['compiler'][$tag_command][0];
+            if (!is_callable($plugin_func)) {
+                $message = "compiler function '$tag_command' is not implemented";
+                $have_function = false;
+            }
+        }
+        /*
+         * Otherwise we need to load plugin file and look for the function
+         * inside it.
+         */
+        else if ($plugin_file = $this->_get_plugin_filepath('compiler', $tag_command)) {
+            $found = true;
+
+            include_once $plugin_file;
+
+            $plugin_func = 'smarty_compiler_' . $tag_command;
+            if (!is_callable($plugin_func)) {
+                $message = "plugin function $plugin_func() not found in $plugin_file\n";
+                $have_function = false;
+            } else {
+                $this->_plugins['compiler'][$tag_command] = array($plugin_func, null, null, null, true);
+            }
+        }
+
+        /*
+         * True return value means that we either found a plugin or a
+         * dynamically registered function. False means that we didn't and the
+         * compiler should now emit code to load custom function plugin for this
+         * tag.
+         */
+        if ($found) {
+            if ($have_function) {
+                $output = call_user_func_array($plugin_func, array($tag_args, &$this));
+                if($output != '') {
+                $output = '<?php ' . $this->_push_cacheable_state('compiler', $tag_command)
+                                   . $output
+                                   . $this->_pop_cacheable_state('compiler', $tag_command) . ' ?>';
+                }
+            } else {
+                $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+
+    /**
+     * compile block function tag
+     *
+     * sets $output to compiled block function tag
+     * @param string $tag_command
+     * @param string $tag_args
+     * @param string $tag_modifier
+     * @param string $output
+     * @return boolean
+     */
+    function _compile_block_tag($tag_command, $tag_args, $tag_modifier, &$output)
+    {
+        if ($tag_command{0} == '/') {
+            $start_tag = false;
+            $tag_command = substr($tag_command, 1);
+        } else
+            $start_tag = true;
+
+        $found = false;
+        $have_function = true;
+
+        /*
+         * First we check if the block function has already been registered
+         * or loaded from a plugin file.
+         */
+        if (isset($this->_plugins['block'][$tag_command])) {
+            $found = true;
+            $plugin_func = $this->_plugins['block'][$tag_command][0];
+            if (!is_callable($plugin_func)) {
+                $message = "block function '$tag_command' is not implemented";
+                $have_function = false;
+            }
+        }
+        /*
+         * Otherwise we need to load plugin file and look for the function
+         * inside it.
+         */
+        else if ($plugin_file = $this->_get_plugin_filepath('block', $tag_command)) {
+            $found = true;
+
+            include_once $plugin_file;
+
+            $plugin_func = 'smarty_block_' . $tag_command;
+            if (!function_exists($plugin_func)) {
+                $message = "plugin function $plugin_func() not found in $plugin_file\n";
+                $have_function = false;
+            } else {
+                $this->_plugins['block'][$tag_command] = array($plugin_func, null, null, null, true);
+
+            }
+        }
+
+        if (!$found) {
+            return false;
+        } else if (!$have_function) {
+            $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
+            return true;
+        }
+
+        /*
+         * Even though we've located the plugin function, compilation
+         * happens only once, so the plugin will still need to be loaded
+         * at runtime for future requests.
+         */
+        $this->_add_plugin('block', $tag_command);
+
+        if ($start_tag)
+            $this->_push_tag($tag_command);
+        else
+            $this->_pop_tag($tag_command);
+
+        if ($start_tag) {
+            $output = '<?php ' . $this->_push_cacheable_state('block', $tag_command);
+            $attrs = $this->_parse_attrs($tag_args);
+            $arg_list = $this->_compile_arg_list('block', $tag_command, $attrs, $_cache_attrs='');
+            $output .= "$_cache_attrs\$this->_tag_stack[] = array('$tag_command', array(".implode(',', $arg_list).')); ';
+            $output .= $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], null, $this, $_block_repeat=true);';
+            $output .= 'while ($_block_repeat) { ob_start(); ?>';
+        } else {
+            $output = '<?php $_block_content = ob_get_contents(); ob_end_clean(); ';
+            $_out_tag_text = $this->_compile_plugin_call('block', $tag_command).'($this->_tag_stack[count($this->_tag_stack)-1][1], $_block_content, $this, $_block_repeat=false)';
+            if ($tag_modifier != '') {
+                $this->_parse_modifiers($_out_tag_text, $tag_modifier);
+            }
+            $output .= 'echo '.$_out_tag_text.'; } ';
+            $output .= " array_pop(\$this->_tag_stack); " . $this->_pop_cacheable_state('block', $tag_command) . '?>';
+        }
+
+        return true;
+    }
+
+
+    /**
+     * compile custom function tag
+     *
+     * @param string $tag_command
+     * @param string $tag_args
+     * @param string $tag_modifier
+     * @return string
+     */
+    function _compile_custom_tag($tag_command, $tag_args, $tag_modifier, &$output)
+    {
+        $found = false;
+        $have_function = true;
+
+        /*
+         * First we check if the custom function has already been registered
+         * or loaded from a plugin file.
+         */
+        if (isset($this->_plugins['function'][$tag_command])) {
+            $found = true;
+            $plugin_func = $this->_plugins['function'][$tag_command][0];
+            if (!is_callable($plugin_func)) {
+                $message = "custom function '$tag_command' is not implemented";
+                $have_function = false;
+            }
+        }
+        /*
+         * Otherwise we need to load plugin file and look for the function
+         * inside it.
+         */
+        else if ($plugin_file = $this->_get_plugin_filepath('function', $tag_command)) {
+            $found = true;
+
+            include_once $plugin_file;
+
+            $plugin_func = 'smarty_function_' . $tag_command;
+            if (!function_exists($plugin_func)) {
+                $message = "plugin function $plugin_func() not found in $plugin_file\n";
+                $have_function = false;
+            } else {
+                $this->_plugins['function'][$tag_command] = array($plugin_func, null, null, null, true);
+
+            }
+        }
+
+        if (!$found) {
+            return false;
+        } else if (!$have_function) {
+            $this->_syntax_error($message, E_USER_WARNING, __FILE__, __LINE__);
+            return true;
+        }
+
+        /* declare plugin to be loaded on display of the template that
+           we compile right now */
+        $this->_add_plugin('function', $tag_command);
+
+        $_cacheable_state = $this->_push_cacheable_state('function', $tag_command);
+        $attrs = $this->_parse_attrs($tag_args);
+        $arg_list = $this->_compile_arg_list('function', $tag_command, $attrs, $_cache_attrs='');
+
+        $output = $this->_compile_plugin_call('function', $tag_command).'(array('.implode(',', $arg_list)."), \$this)";
+        if($tag_modifier != '') {
+            $this->_parse_modifiers($output, $tag_modifier);
+        }
+
+        if($output != '') {
+            $output =  '<?php ' . $_cacheable_state . $_cache_attrs . 'echo ' . $output . ';'
+                . $this->_pop_cacheable_state('function', $tag_command) . "?>" . $this->_additional_newline;
+        }
+
+        return true;
+    }
+
+    /**
+     * compile a registered object tag
+     *
+     * @param string $tag_command
+     * @param array $attrs
+     * @param string $tag_modifier
+     * @return string
+     */
+    function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier)
+    {
+        if ($tag_command{0} == '/') {
+            $start_tag = false;
+            $tag_command = substr($tag_command, 1);
+        } else {
+            $start_tag = true;
+        }
+
+        list($object, $obj_comp) = explode('->', $tag_command);
+
+        $arg_list = array();
+        if(count($attrs)) {
+            $_assign_var = false;
+            foreach ($attrs as $arg_name => $arg_value) {
+                if($arg_name == 'assign') {
+                    $_assign_var = $arg_value;
+                    unset($attrs['assign']);
+                    continue;
+                }
+                if (is_bool($arg_value))
+                    $arg_value = $arg_value ? 'true' : 'false';
+                $arg_list[] = "'$arg_name' => $arg_value";
+            }
+        }
+
+        if($this->_reg_objects[$object][2]) {
+            // smarty object argument format
+            $args = "array(".implode(',', (array)$arg_list)."), \$this";
+        } else {
+            // traditional argument format
+            $args = implode(',', array_values($attrs));
+            if (empty($args)) {
+                $args = 'null';
+            }
+        }
+
+        $prefix = '';
+        $postfix = '';
+        $newline = '';
+        if(!is_object($this->_reg_objects[$object][0])) {
+            $this->_trigger_fatal_error("registered '$object' is not an object" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
+        } elseif(!empty($this->_reg_objects[$object][1]) && !in_array($obj_comp, $this->_reg_objects[$object][1])) {
+            $this->_trigger_fatal_error("'$obj_comp' is not a registered component of object '$object'", $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
+        } elseif(method_exists($this->_reg_objects[$object][0], $obj_comp)) {
+            // method
+            if(in_array($obj_comp, $this->_reg_objects[$object][3])) {
+                // block method
+                if ($start_tag) {
+                    $prefix = "\$this->_tag_stack[] = array('$obj_comp', $args); ";
+                    $prefix .= "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], null, \$this, \$_block_repeat=true); ";
+                    $prefix .= "while (\$_block_repeat) { ob_start();";
+                    $return = null;
+                    $postfix = '';
+            } else {
+                    $prefix = "\$_obj_block_content = ob_get_contents(); ob_end_clean(); ";
+                    $return = "\$this->_reg_objects['$object'][0]->$obj_comp(\$this->_tag_stack[count(\$this->_tag_stack)-1][1], \$_obj_block_content, \$this, \$_block_repeat=false)";
+                    $postfix = "} array_pop(\$this->_tag_stack);";
+                }
+            } else {
+                // non-block method
+                $return = "\$this->_reg_objects['$object'][0]->$obj_comp($args)";
+            }
+        } else {
+            // property
+            $return = "\$this->_reg_objects['$object'][0]->$obj_comp";
+        }
+
+        if($return != null) {
+            if($tag_modifier != '') {
+                $this->_parse_modifiers($return, $tag_modifier);
+            }
+
+            if(!empty($_assign_var)) {
+                $output = "\$this->assign('" . $this->_dequote($_assign_var) ."',  $return);";
+            } else {
+                $output = 'echo ' . $return . ';';
+                $newline = $this->_additional_newline;
+            }
+        } else {
+            $output = '';
+        }
+
+        return '<?php ' . $prefix . $output . $postfix . "?>" . $newline;
+    }
+
+    /**
+     * Compile {insert ...} tag
+     *
+     * @param string $tag_args
+     * @return string
+     */
+    function _compile_insert_tag($tag_args)
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+        $name = $this->_dequote($attrs['name']);
+
+        if (empty($name)) {
+            $this->_syntax_error("missing insert name", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        if (!empty($attrs['script'])) {
+            $delayed_loading = true;
+        } else {
+            $delayed_loading = false;
+        }
+
+        foreach ($attrs as $arg_name => $arg_value) {
+            if (is_bool($arg_value))
+                $arg_value = $arg_value ? 'true' : 'false';
+            $arg_list[] = "'$arg_name' => $arg_value";
+        }
+
+        $this->_add_plugin('insert', $name, $delayed_loading);
+
+        $_params = "array('args' => array(".implode(', ', (array)$arg_list)."))";
+
+        return "<?php require_once(SMARTY_CORE_DIR . 'core.run_insert_handler.php');\necho smarty_core_run_insert_handler($_params, \$this); ?>" . $this->_additional_newline;
+    }
+
+    /**
+     * Compile {include ...} tag
+     *
+     * @param string $tag_args
+     * @return string
+     */
+    function _compile_include_tag($tag_args)
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+        $arg_list = array();
+
+        if (empty($attrs['file'])) {
+            $this->_syntax_error("missing 'file' attribute in include tag", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        foreach ($attrs as $arg_name => $arg_value) {
+            if ($arg_name == 'file') {
+                $include_file = $arg_value;
+                continue;
+            } else if ($arg_name == 'assign') {
+                $assign_var = $arg_value;
+                continue;
+            }
+            if (is_bool($arg_value))
+                $arg_value = $arg_value ? 'true' : 'false';
+            $arg_list[] = "'$arg_name' => $arg_value";
+        }
+
+        $output = '<?php ';
+
+        if (isset($assign_var)) {
+            $output .= "ob_start();\n";
+        }
+
+        $output .=
+            "\$_smarty_tpl_vars = \$this->_tpl_vars;\n";
+
+
+        $_params = "array('smarty_include_tpl_file' => " . $include_file . ", 'smarty_include_vars' => array(".implode(',', (array)$arg_list)."))";
+        $output .= "\$this->_smarty_include($_params);\n" .
+        "\$this->_tpl_vars = \$_smarty_tpl_vars;\n" .
+        "unset(\$_smarty_tpl_vars);\n";
+
+        if (isset($assign_var)) {
+            $output .= "\$this->assign(" . $assign_var . ", ob_get_contents()); ob_end_clean();\n";
+        }
+
+        $output .= ' ?>';
+
+        return $output;
+
+    }
+
+    /**
+     * Compile {include ...} tag
+     *
+     * @param string $tag_args
+     * @return string
+     */
+    function _compile_include_php_tag($tag_args)
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+
+        if (empty($attrs['file'])) {
+            $this->_syntax_error("missing 'file' attribute in include_php tag", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        $assign_var = (empty($attrs['assign'])) ? '' : $this->_dequote($attrs['assign']);
+        $once_var = (empty($attrs['once']) || $attrs['once']=='false') ? 'false' : 'true';
+
+        $arg_list = array();
+        foreach($attrs as $arg_name => $arg_value) {
+            if($arg_name != 'file' AND $arg_name != 'once' AND $arg_name != 'assign') {
+                if(is_bool($arg_value))
+                    $arg_value = $arg_value ? 'true' : 'false';
+                $arg_list[] = "'$arg_name' => $arg_value";
+            }
+        }
+
+        $_params = "array('smarty_file' => " . $attrs['file'] . ", 'smarty_assign' => '$assign_var', 'smarty_once' => $once_var, 'smarty_include_vars' => array(".implode(',', $arg_list)."))";
+
+        return "<?php require_once(SMARTY_CORE_DIR . 'core.smarty_include_php.php');\nsmarty_core_smarty_include_php($_params, \$this); ?>" . $this->_additional_newline;
+    }
+
+
+    /**
+     * Compile {section ...} tag
+     *
+     * @param string $tag_args
+     * @return string
+     */
+    function _compile_section_start($tag_args)
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+        $arg_list = array();
+
+        $output = '<?php ';
+        $section_name = $attrs['name'];
+        if (empty($section_name)) {
+            $this->_syntax_error("missing section name", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        $output .= "unset(\$this->_sections[$section_name]);\n";
+        $section_props = "\$this->_sections[$section_name]";
+
+        foreach ($attrs as $attr_name => $attr_value) {
+            switch ($attr_name) {
+                case 'loop':
+                    $output .= "{$section_props}['loop'] = is_array(\$_loop=$attr_value) ? count(\$_loop) : max(0, (int)\$_loop); unset(\$_loop);\n";
+                    break;
+
+                case 'show':
+                    if (is_bool($attr_value))
+                        $show_attr_value = $attr_value ? 'true' : 'false';
+                    else
+                        $show_attr_value = "(bool)$attr_value";
+                    $output .= "{$section_props}['show'] = $show_attr_value;\n";
+                    break;
+
+                case 'name':
+                    $output .= "{$section_props}['$attr_name'] = $attr_value;\n";
+                    break;
+
+                case 'max':
+                case 'start':
+                    $output .= "{$section_props}['$attr_name'] = (int)$attr_value;\n";
+                    break;
+
+                case 'step':
+                    $output .= "{$section_props}['$attr_name'] = ((int)$attr_value) == 0 ? 1 : (int)$attr_value;\n";
+                    break;
+
+                default:
+                    $this->_syntax_error("unknown section attribute - '$attr_name'", E_USER_ERROR, __FILE__, __LINE__);
+                    break;
+            }
+        }
+
+        if (!isset($attrs['show']))
+            $output .= "{$section_props}['show'] = true;\n";
+
+        if (!isset($attrs['loop']))
+            $output .= "{$section_props}['loop'] = 1;\n";
+
+        if (!isset($attrs['max']))
+            $output .= "{$section_props}['max'] = {$section_props}['loop'];\n";
+        else
+            $output .= "if ({$section_props}['max'] < 0)\n" .
+                       "    {$section_props}['max'] = {$section_props}['loop'];\n";
+
+        if (!isset($attrs['step']))
+            $output .= "{$section_props}['step'] = 1;\n";
+
+        if (!isset($attrs['start']))
+            $output .= "{$section_props}['start'] = {$section_props}['step'] > 0 ? 0 : {$section_props}['loop']-1;\n";
+        else {
+            $output .= "if ({$section_props}['start'] < 0)\n" .
+                       "    {$section_props}['start'] = max({$section_props}['step'] > 0 ? 0 : -1, {$section_props}['loop'] + {$section_props}['start']);\n" .
+                       "else\n" .
+                       "    {$section_props}['start'] = min({$section_props}['start'], {$section_props}['step'] > 0 ? {$section_props}['loop'] : {$section_props}['loop']-1);\n";
+        }
+
+        $output .= "if ({$section_props}['show']) {\n";
+        if (!isset($attrs['start']) && !isset($attrs['step']) && !isset($attrs['max'])) {
+            $output .= "    {$section_props}['total'] = {$section_props}['loop'];\n";
+        } else {
+            $output .= "    {$section_props}['total'] = min(ceil(({$section_props}['step'] > 0 ? {$section_props}['loop'] - {$section_props}['start'] : {$section_props}['start']+1)/abs({$section_props}['step'])), {$section_props}['max']);\n";
+        }
+        $output .= "    if ({$section_props}['total'] == 0)\n" .
+                   "        {$section_props}['show'] = false;\n" .
+                   "} else\n" .
+                   "    {$section_props}['total'] = 0;\n";
+
+        $output .= "if ({$section_props}['show']):\n";
+        $output .= "
+            for ({$section_props}['index'] = {$section_props}['start'], {$section_props}['iteration'] = 1;
+                 {$section_props}['iteration'] <= {$section_props}['total'];
+                 {$section_props}['index'] += {$section_props}['step'], {$section_props}['iteration']++):\n";
+        $output .= "{$section_props}['rownum'] = {$section_props}['iteration'];\n";
+        $output .= "{$section_props}['index_prev'] = {$section_props}['index'] - {$section_props}['step'];\n";
+        $output .= "{$section_props}['index_next'] = {$section_props}['index'] + {$section_props}['step'];\n";
+        $output .= "{$section_props}['first']      = ({$section_props}['iteration'] == 1);\n";
+        $output .= "{$section_props}['last']       = ({$section_props}['iteration'] == {$section_props}['total']);\n";
+
+        $output .= "?>";
+
+        return $output;
+    }
+
+
+    /**
+     * Compile {foreach ...} tag.
+     *
+     * @param string $tag_args
+     * @return string
+     */
+    function _compile_foreach_start($tag_args)
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+        $arg_list = array();
+
+        if (empty($attrs['from'])) {
+            return $this->_syntax_error("foreach: missing 'from' attribute", E_USER_ERROR, __FILE__, __LINE__);
+        }
+        $from = $attrs['from'];
+
+        if (empty($attrs['item'])) {
+            return $this->_syntax_error("foreach: missing 'item' attribute", E_USER_ERROR, __FILE__, __LINE__);
+        }
+        $item = $this->_dequote($attrs['item']);
+        if (!preg_match('~^\w+$~', $item)) {
+            return $this->_syntax_error("'foreach: item' must be a variable name (literal string)", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        if (isset($attrs['key'])) {
+            $key  = $this->_dequote($attrs['key']);
+            if (!preg_match('~^\w+$~', $key)) {
+                return $this->_syntax_error("foreach: 'key' must to be a variable name (literal string)", E_USER_ERROR, __FILE__, __LINE__);
+            }
+            $key_part = "\$this->_tpl_vars['$key'] => ";
+        } else {
+            $key = null;
+            $key_part = '';
+        }
+
+        if (isset($attrs['name'])) {
+            $name = $attrs['name'];
+        } else {
+            $name = null;
+        }
+
+        $output = '<?php ';
+        $output .= "\$_from = $from; if (!is_array(\$_from) && !is_object(\$_from)) { settype(\$_from, 'array'); }";
+        if (isset($name)) {
+            $foreach_props = "\$this->_foreach[$name]";
+            $output .= "{$foreach_props} = array('total' => count(\$_from), 'iteration' => 0);\n";
+            $output .= "if ({$foreach_props}['total'] > 0):\n";
+            $output .= "    foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n";
+            $output .= "        {$foreach_props}['iteration']++;\n";
+        } else {
+            $output .= "if (count(\$_from)):\n";
+            $output .= "    foreach (\$_from as $key_part\$this->_tpl_vars['$item']):\n";
+        }
+        $output .= '?>';
+
+        return $output;
+    }
+
+
+    /**
+     * Compile {capture} .. {/capture} tags
+     *
+     * @param boolean $start true if this is the {capture} tag
+     * @param string $tag_args
+     * @return string
+     */
+
+    function _compile_capture_tag($start, $tag_args = '')
+    {
+        $attrs = $this->_parse_attrs($tag_args);
+
+        if ($start) {
+            if (isset($attrs['name']))
+                $buffer = $attrs['name'];
+            else
+                $buffer = "'default'";
+
+            if (isset($attrs['assign']))
+                $assign = $attrs['assign'];
+            else
+                $assign = null;
+            $output = "<?php ob_start(); ?>";
+            $this->_capture_stack[] = array($buffer, $assign);
+        } else {
+            list($buffer, $assign) = array_pop($this->_capture_stack);
+            $output = "<?php \$this->_smarty_vars['capture'][$buffer] = ob_get_contents(); ";
+            if (isset($assign)) {
+                $output .= " \$this->assign($assign, ob_get_contents());";
+            }
+            $output .= "ob_end_clean(); ?>";
+        }
+
+        return $output;
+    }
+
+    /**
+     * Compile {if ...} tag
+     *
+     * @param string $tag_args
+     * @param boolean $elseif if true, uses elseif instead of if
+     * @return string
+     */
+    function _compile_if_tag($tag_args, $elseif = false)
+    {
+
+        /* Tokenize args for 'if' tag. */
+        preg_match_all('~(?>
+                ' . $this->_obj_call_regexp . '(?:' . $this->_mod_regexp . '*)? | # valid object call
+                ' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)?    | # var or quoted string
+                \-?0[xX][0-9a-fA-F]+|\-?\d+(?:\.\d+)?|\.\d+|!==|===|==|!=|<>|<<|>>|<=|>=|\&\&|\|\||\(|\)|,|\!|\^|=|\&|\~|<|>|\||\%|\+|\-|\/|\*|\@    | # valid non-word token
+                \b\w+\b                                                        | # valid word token
+                \S+                                                           # anything else
+                )~x', $tag_args, $match);
+
+        $tokens = $match[0];
+
+        // make sure we have balanced parenthesis
+        $token_count = array_count_values($tokens);
+        if(isset($token_count['(']) && $token_count['('] != $token_count[')']) {
+            $this->_syntax_error("unbalanced parenthesis in if statement", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        $is_arg_stack = array();
+
+        for ($i = 0; $i < count($tokens); $i++) {
+
+            $token = &$tokens[$i];
+
+            switch (strtolower($token)) {
+                case '!':
+                case '%':
+                case '!==':
+                case '==':
+                case '===':
+                case '>':
+                case '<':
+                case '!=':
+                case '<>':
+                case '<<':
+                case '>>':
+                case '<=':
+                case '>=':
+                case '&&':
+                case '||':
+                case '|':
+                case '^':
+                case '&':
+                case '~':
+                case ')':
+                case ',':
+                case '+':
+                case '-':
+                case '*':
+                case '/':
+                case '@':
+                    break;
+
+                case 'eq':
+                    $token = '==';
+                    break;
+
+                case 'ne':
+                case 'neq':
+                    $token = '!=';
+                    break;
+
+                case 'lt':
+                    $token = '<';
+                    break;
+
+                case 'le':
+                case 'lte':
+                    $token = '<=';
+                    break;
+
+                case 'gt':
+                    $token = '>';
+                    break;
+
+                case 'ge':
+                case 'gte':
+                    $token = '>=';
+                    break;
+
+                case 'and':
+                    $token = '&&';
+                    break;
+
+                case 'or':
+                    $token = '||';
+                    break;
+
+                case 'not':
+                    $token = '!';
+                    break;
+
+                case 'mod':
+                    $token = '%';
+                    break;
+
+                case '(':
+                    array_push($is_arg_stack, $i);
+                    break;
+
+                case 'is':
+                    /* If last token was a ')', we operate on the parenthesized
+                       expression. The start of the expression is on the stack.
+                       Otherwise, we operate on the last encountered token. */
+                    if ($tokens[$i-1] == ')')
+                        $is_arg_start = array_pop($is_arg_stack);
+                    else
+                        $is_arg_start = $i-1;
+                    /* Construct the argument for 'is' expression, so it knows
+                       what to operate on. */
+                    $is_arg = implode(' ', array_slice($tokens, $is_arg_start, $i - $is_arg_start));
+
+                    /* Pass all tokens from next one until the end to the
+                       'is' expression parsing function. The function will
+                       return modified tokens, where the first one is the result
+                       of the 'is' expression and the rest are the tokens it
+                       didn't touch. */
+                    $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1));
+
+                    /* Replace the old tokens with the new ones. */
+                    array_splice($tokens, $is_arg_start, count($tokens), $new_tokens);
+
+                    /* Adjust argument start so that it won't change from the
+                       current position for the next iteration. */
+                    $i = $is_arg_start;
+                    break;
+
+                default:
+                    if(preg_match('~^' . $this->_func_regexp . '$~', $token) ) {
+                            // function call
+                            if($this->security &&
+                               !in_array($token, $this->security_settings['IF_FUNCS'])) {
+                                $this->_syntax_error("(secure mode) '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__);
+                            }
+                    } elseif(preg_match('~^' . $this->_var_regexp . '$~', $token) && isset($tokens[$i+1]) && $tokens[$i+1] == '(') {
+                        // variable function call
+                        $this->_syntax_error("variable function call '$token' not allowed in if statement", E_USER_ERROR, __FILE__, __LINE__);                      
+                    } elseif(preg_match('~^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . '*)$~', $token)) {
+                        // object or variable
+                        $token = $this->_parse_var_props($token);
+                    } elseif(is_numeric($token)) {
+                        // number, skip it
+                    } else {
+                        $this->_syntax_error("unidentified token '$token'", E_USER_ERROR, __FILE__, __LINE__);
+                    }
+                    break;
+            }
+        }
+
+        if ($elseif)
+            return '<?php elseif ('.implode(' ', $tokens).'): ?>';
+        else
+            return '<?php if ('.implode(' ', $tokens).'): ?>';
+    }
+
+
+    function _compile_arg_list($type, $name, $attrs, &$cache_code) {
+        $arg_list = array();
+
+        if (isset($type) && isset($name)
+            && isset($this->_plugins[$type])
+            && isset($this->_plugins[$type][$name])
+            && empty($this->_plugins[$type][$name][4])
+            && is_array($this->_plugins[$type][$name][5])
+            ) {
+            /* we have a list of parameters that should be cached */
+            $_cache_attrs = $this->_plugins[$type][$name][5];
+            $_count = $this->_cache_attrs_count++;
+            $cache_code = "\$_cache_attrs =& \$this->_smarty_cache_attrs('$this->_cache_serial','$_count');";
+
+        } else {
+            /* no parameters are cached */
+            $_cache_attrs = null;
+        }
+
+        foreach ($attrs as $arg_name => $arg_value) {
+            if (is_bool($arg_value))
+                $arg_value = $arg_value ? 'true' : 'false';
+            if (is_null($arg_value))
+                $arg_value = 'null';
+            if ($_cache_attrs && in_array($arg_name, $_cache_attrs)) {
+                $arg_list[] = "'$arg_name' => (\$this->_cache_including) ? \$_cache_attrs['$arg_name'] : (\$_cache_attrs['$arg_name']=$arg_value)";
+            } else {
+                $arg_list[] = "'$arg_name' => $arg_value";
+            }
+        }
+        return $arg_list;
+    }
+
+    /**
+     * Parse is expression
+     *
+     * @param string $is_arg
+     * @param array $tokens
+     * @return array
+     */
+    function _parse_is_expr($is_arg, $tokens)
+    {
+        $expr_end = 0;
+        $negate_expr = false;
+
+        if (($first_token = array_shift($tokens)) == 'not') {
+            $negate_expr = true;
+            $expr_type = array_shift($tokens);
+        } else
+            $expr_type = $first_token;
+
+        switch ($expr_type) {
+            case 'even':
+                if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') {
+                    $expr_end++;
+                    $expr_arg = $tokens[$expr_end++];
+                    $expr = "!(1 & ($is_arg / " . $this->_parse_var_props($expr_arg) . "))";
+                } else
+                    $expr = "!(1 & $is_arg)";
+                break;
+
+            case 'odd':
+                if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') {
+                    $expr_end++;
+                    $expr_arg = $tokens[$expr_end++];
+                    $expr = "(1 & ($is_arg / " . $this->_parse_var_props($expr_arg) . "))";
+                } else
+                    $expr = "(1 & $is_arg)";
+                break;
+
+            case 'div':
+                if (@$tokens[$expr_end] == 'by') {
+                    $expr_end++;
+                    $expr_arg = $tokens[$expr_end++];
+                    $expr = "!($is_arg % " . $this->_parse_var_props($expr_arg) . ")";
+                } else {
+                    $this->_syntax_error("expecting 'by' after 'div'", E_USER_ERROR, __FILE__, __LINE__);
+                }
+                break;
+
+            default:
+                $this->_syntax_error("unknown 'is' expression - '$expr_type'", E_USER_ERROR, __FILE__, __LINE__);
+                break;
+        }
+
+        if ($negate_expr) {
+            $expr = "!($expr)";
+        }
+
+        array_splice($tokens, 0, $expr_end, $expr);
+
+        return $tokens;
+    }
+
+
+    /**
+     * Parse attribute string
+     *
+     * @param string $tag_args
+     * @return array
+     */
+    function _parse_attrs($tag_args)
+    {
+
+        /* Tokenize tag attributes. */
+        preg_match_all('~(?:' . $this->_obj_call_regexp . '|' . $this->_qstr_regexp . ' | (?>[^"\'=\s]+)
+                         )+ |
+                         [=]
+                        ~x', $tag_args, $match);
+        $tokens       = $match[0];
+
+        $attrs = array();
+        /* Parse state:
+            0 - expecting attribute name
+            1 - expecting '='
+            2 - expecting attribute value (not '=') */
+        $state = 0;
+
+        foreach ($tokens as $token) {
+            switch ($state) {
+                case 0:
+                    /* If the token is a valid identifier, we set attribute name
+                       and go to state 1. */
+                    if (preg_match('~^\w+$~', $token)) {
+                        $attr_name = $token;
+                        $state = 1;
+                    } else
+                        $this->_syntax_error("invalid attribute name: '$token'", E_USER_ERROR, __FILE__, __LINE__);
+                    break;
+
+                case 1:
+                    /* If the token is '=', then we go to state 2. */
+                    if ($token == '=') {
+                        $state = 2;
+                    } else
+                        $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__);
+                    break;
+
+                case 2:
+                    /* If token is not '=', we set the attribute value and go to
+                       state 0. */
+                    if ($token != '=') {
+                        /* We booleanize the token if it's a non-quoted possible
+                           boolean value. */
+                        if (preg_match('~^(on|yes|true)$~', $token)) {
+                            $token = 'true';
+                        } else if (preg_match('~^(off|no|false)$~', $token)) {
+                            $token = 'false';
+                        } else if ($token == 'null') {
+                            $token = 'null';
+                        } else if (preg_match('~^' . $this->_num_const_regexp . '|0[xX][0-9a-fA-F]+$~', $token)) {
+                            /* treat integer literally */
+                        } else if (!preg_match('~^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '(?:' . $this->_mod_regexp . ')*$~', $token)) {
+                            /* treat as a string, double-quote it escaping quotes */
+                            $token = '"'.addslashes($token).'"';
+                        }
+
+                        $attrs[$attr_name] = $token;
+                        $state = 0;
+                    } else
+                        $this->_syntax_error("'=' cannot be an attribute value", E_USER_ERROR, __FILE__, __LINE__);
+                    break;
+            }
+            $last_token = $token;
+        }
+
+        if($state != 0) {
+            if($state == 1) {
+                $this->_syntax_error("expecting '=' after attribute name '$last_token'", E_USER_ERROR, __FILE__, __LINE__);
+            } else {
+                $this->_syntax_error("missing attribute value", E_USER_ERROR, __FILE__, __LINE__);
+            }
+        }
+
+        $this->_parse_vars_props($attrs);
+
+        return $attrs;
+    }
+
+    /**
+     * compile multiple variables and section properties tokens into
+     * PHP code
+     *
+     * @param array $tokens
+     */
+    function _parse_vars_props(&$tokens)
+    {
+        foreach($tokens as $key => $val) {
+            $tokens[$key] = $this->_parse_var_props($val);
+        }
+    }
+
+    /**
+     * compile single variable and section properties token into
+     * PHP code
+     *
+     * @param string $val
+     * @param string $tag_attrs
+     * @return string
+     */
+    function _parse_var_props($val)
+    {
+        $val = trim($val);
+
+        if(preg_match('~^(' . $this->_obj_call_regexp . '|' . $this->_dvar_regexp . ')(' . $this->_mod_regexp . '*)$~', $val, $match)) {
+            // $ variable or object
+            $return = $this->_parse_var($match[1]);
+            $modifiers = $match[2];
+            if (!empty($this->default_modifiers) && !preg_match('~(^|\|)smarty:nodefaults($|\|)~',$modifiers)) {
+                $_default_mod_string = implode('|',(array)$this->default_modifiers);
+                $modifiers = empty($modifiers) ? $_default_mod_string : $_default_mod_string . '|' . $modifiers;
+            }
+            $this->_parse_modifiers($return, $modifiers);
+            return $return;
+        } elseif (preg_match('~^' . $this->_db_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
+                // double quoted text
+                preg_match('~^(' . $this->_db_qstr_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);
+                $return = $this->_expand_quoted_text($match[1]);
+                if($match[2] != '') {
+                    $this->_parse_modifiers($return, $match[2]);
+                }
+                return $return;
+            }
+        elseif(preg_match('~^' . $this->_num_const_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
+                // numerical constant
+                preg_match('~^(' . $this->_num_const_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);
+                if($match[2] != '') {
+                    $this->_parse_modifiers($match[1], $match[2]);
+                    return $match[1];
+                }
+            }
+        elseif(preg_match('~^' . $this->_si_qstr_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
+                // single quoted text
+                preg_match('~^(' . $this->_si_qstr_regexp . ')('. $this->_mod_regexp . '*)$~', $val, $match);
+                if($match[2] != '') {
+                    $this->_parse_modifiers($match[1], $match[2]);
+                    return $match[1];
+                }
+            }
+        elseif(preg_match('~^' . $this->_cvar_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
+                // config var
+                return $this->_parse_conf_var($val);
+            }
+        elseif(preg_match('~^' . $this->_svar_regexp . '(?:' . $this->_mod_regexp . '*)$~', $val)) {
+                // section var
+                return $this->_parse_section_prop($val);
+            }
+        elseif(!in_array($val, $this->_permitted_tokens) && !is_numeric($val)) {
+            // literal string
+            return $this->_expand_quoted_text('"' . $val .'"');
+        }
+        return $val;
+    }
+
+    /**
+     * expand quoted text with embedded variables
+     *
+     * @param string $var_expr
+     * @return string
+     */
+    function _expand_quoted_text($var_expr)
+    {
+        // if contains unescaped $, expand it
+        if(preg_match_all('~(?:\`(?<!\\\\)\$' . $this->_dvar_guts_regexp . '(?:' . $this->_obj_ext_regexp . ')*\`)|(?:(?<!\\\\)\$\w+(\[[a-zA-Z0-9]+\])*)~', $var_expr, $_match)) {
+            $_match = $_match[0];
+            rsort($_match);
+            reset($_match);
+            foreach($_match as $_var) {
+                $var_expr = str_replace ($_var, '".(' . $this->_parse_var(str_replace('`','',$_var)) . ')."', $var_expr);
+            }
+            $_return = preg_replace('~\.""|(?<!\\\\)""\.~', '', $var_expr);
+        } else {
+            $_return = $var_expr;
+        }
+        // replace double quoted literal string with single quotes
+        $_return = preg_replace('~^"([\s\w]+)"$~',"'\\1'",$_return);
+        return $_return;
+    }
+
+    /**
+     * parse variable expression into PHP code
+     *
+     * @param string $var_expr
+     * @param string $output
+     * @return string
+     */
+    function _parse_var($var_expr)
+    {
+        $_has_math = false;
+        $_math_vars = preg_split('~('.$this->_dvar_math_regexp.'|'.$this->_qstr_regexp.')~', $var_expr, -1, PREG_SPLIT_DELIM_CAPTURE);
+
+        if(count($_math_vars) > 1) {
+            $_first_var = "";
+            $_complete_var = "";
+            $_output = "";
+            // simple check if there is any math, to stop recursion (due to modifiers with "xx % yy" as parameter)
+            foreach($_math_vars as $_k => $_math_var) {
+                $_math_var = $_math_vars[$_k];
+
+                if(!empty($_math_var) || is_numeric($_math_var)) {
+                    // hit a math operator, so process the stuff which came before it
+                    if(preg_match('~^' . $this->_dvar_math_regexp . '$~', $_math_var)) {
+                        $_has_math = true;
+                        if(!empty($_complete_var) || is_numeric($_complete_var)) {
+                            $_output .= $this->_parse_var($_complete_var);
+                        }
+
+                        // just output the math operator to php
+                        $_output .= $_math_var;
+
+                        if(empty($_first_var))
+                            $_first_var = $_complete_var;
+
+                        $_complete_var = "";
+                    } else {
+                        $_complete_var .= $_math_var;
+                    }
+                }
+            }
+            if($_has_math) {
+                if(!empty($_complete_var) || is_numeric($_complete_var))
+                    $_output .= $this->_parse_var($_complete_var);
+
+                // get the modifiers working (only the last var from math + modifier is left)
+                $var_expr = $_complete_var;
+            }
+        }
+
+        // prevent cutting of first digit in the number (we _definitly_ got a number if the first char is a digit)
+        if(is_numeric($var_expr{0}))
+            $_var_ref = $var_expr;
+        else
+            $_var_ref = substr($var_expr, 1);
+        
+        if(!$_has_math) {
+            
+            // get [foo] and .foo and ->foo and (...) pieces
+            preg_match_all('~(?:^\w+)|' . $this->_obj_params_regexp . '|(?:' . $this->_var_bracket_regexp . ')|->\$?\w+|\.\$?\w+|\S+~', $_var_ref, $match);
+                        
+            $_indexes = $match[0];
+            $_var_name = array_shift($_indexes);
+
+            /* Handle $smarty.* variable references as a special case. */
+            if ($_var_name == 'smarty') {
+                /*
+                 * If the reference could be compiled, use the compiled output;
+                 * otherwise, fall back on the $smarty variable generated at
+                 * run-time.
+                 */
+                if (($smarty_ref = $this->_compile_smarty_ref($_indexes)) !== null) {
+                    $_output = $smarty_ref;
+                } else {
+                    $_var_name = substr(array_shift($_indexes), 1);
+                    $_output = "\$this->_smarty_vars['$_var_name']";
+                }
+            } elseif(is_numeric($_var_name) && is_numeric($var_expr{0})) {
+                // because . is the operator for accessing arrays thru inidizes we need to put it together again for floating point numbers
+                if(count($_indexes) > 0)
+                {
+                    $_var_name .= implode("", $_indexes);
+                    $_indexes = array();
+                }
+                $_output = $_var_name;
+            } else {
+                $_output = "\$this->_tpl_vars['$_var_name']";
+            }
+
+            foreach ($_indexes as $_index) {
+                if ($_index{0} == '[') {
+                    $_index = substr($_index, 1, -1);
+                    if (is_numeric($_index)) {
+                        $_output .= "[$_index]";
+                    } elseif ($_index{0} == '$') {
+                        if (strpos($_index, '.') !== false) {
+                            $_output .= '[' . $this->_parse_var($_index) . ']';
+                        } else {
+                            $_output .= "[\$this->_tpl_vars['" . substr($_index, 1) . "']]";
+                        }
+                    } else {
+                        $_var_parts = explode('.', $_index);
+                        $_var_section = $_var_parts[0];
+                        $_var_section_prop = isset($_var_parts[1]) ? $_var_parts[1] : 'index';
+                        $_output .= "[\$this->_sections['$_var_section']['$_var_section_prop']]";
+                    }
+                } else if ($_index{0} == '.') {
+                    if ($_index{1} == '$')
+                        $_output .= "[\$this->_tpl_vars['" . substr($_index, 2) . "']]";
+                    else
+                        $_output .= "['" . substr($_index, 1) . "']";
+                } else if (substr($_index,0,2) == '->') {
+                    if(substr($_index,2,2) == '__') {
+                        $this->_syntax_error('call to internal object members is not allowed', E_USER_ERROR, __FILE__, __LINE__);
+                    } elseif($this->security && substr($_index, 2, 1) == '_') {
+                        $this->_syntax_error('(secure) call to private object member is not allowed', E_USER_ERROR, __FILE__, __LINE__);
+                    } elseif ($_index{2} == '$') {
+                        if ($this->security) {
+                            $this->_syntax_error('(secure) call to dynamic object member is not allowed', E_USER_ERROR, __FILE__, __LINE__);
+                        } else {
+                            $_output .= '->{(($_var=$this->_tpl_vars[\''.substr($_index,3).'\']) && substr($_var,0,2)!=\'__\') ? $_var : $this->trigger_error("cannot access property \\"$_var\\"")}';
+                        }
+                    } else {
+                        $_output .= $_index;
+                    }
+                } elseif ($_index{0} == '(') {
+                    $_index = $this->_parse_parenth_args($_index);
+                    $_output .= $_index;
+                } else {
+                    $_output .= $_index;
+                }
+            }
+        }
+
+        return $_output;
+    }
+
+    /**
+     * parse arguments in function call parenthesis
+     *
+     * @param string $parenth_args
+     * @return string
+     */
+    function _parse_parenth_args($parenth_args)
+    {
+        preg_match_all('~' . $this->_param_regexp . '~',$parenth_args, $match);
+        $orig_vals = $match = $match[0];
+        $this->_parse_vars_props($match);
+        $replace = array();
+        for ($i = 0, $count = count($match); $i < $count; $i++) {
+            $replace[$orig_vals[$i]] = $match[$i];
+        }
+        return strtr($parenth_args, $replace);
+    }
+
+    /**
+     * parse configuration variable expression into PHP code
+     *
+     * @param string $conf_var_expr
+     */
+    function _parse_conf_var($conf_var_expr)
+    {
+        $parts = explode('|', $conf_var_expr, 2);
+        $var_ref = $parts[0];
+        $modifiers = isset($parts[1]) ? $parts[1] : '';
+
+        $var_name = substr($var_ref, 1, -1);
+
+        $output = "\$this->_config[0]['vars']['$var_name']";
+
+        $this->_parse_modifiers($output, $modifiers);
+
+        return $output;
+    }
+
+    /**
+     * parse section property expression into PHP code
+     *
+     * @param string $section_prop_expr
+     * @return string
+     */
+    function _parse_section_prop($section_prop_expr)
+    {
+        $parts = explode('|', $section_prop_expr, 2);
+        $var_ref = $parts[0];
+        $modifiers = isset($parts[1]) ? $parts[1] : '';
+
+        preg_match('!%(\w+)\.(\w+)%!', $var_ref, $match);
+        $section_name = $match[1];
+        $prop_name = $match[2];
+
+        $output = "\$this->_sections['$section_name']['$prop_name']";
+
+        $this->_parse_modifiers($output, $modifiers);
+
+        return $output;
+    }
+
+
+    /**
+     * parse modifier chain into PHP code
+     *
+     * sets $output to parsed modified chain
+     * @param string $output
+     * @param string $modifier_string
+     */
+    function _parse_modifiers(&$output, $modifier_string)
+    {
+        preg_match_all('~\|(@?\w+)((?>:(?:'. $this->_qstr_regexp . '|[^|]+))*)~', '|' . $modifier_string, $_match);
+        list(, $_modifiers, $modifier_arg_strings) = $_match;
+
+        for ($_i = 0, $_for_max = count($_modifiers); $_i < $_for_max; $_i++) {
+            $_modifier_name = $_modifiers[$_i];
+
+            if($_modifier_name == 'smarty') {
+                // skip smarty modifier
+                continue;
+            }
+
+            preg_match_all('~:(' . $this->_qstr_regexp . '|[^:]+)~', $modifier_arg_strings[$_i], $_match);
+            $_modifier_args = $_match[1];
+
+            if ($_modifier_name{0} == '@') {
+                $_map_array = false;
+                $_modifier_name = substr($_modifier_name, 1);
+            } else {
+                $_map_array = true;
+            }
+
+            if (empty($this->_plugins['modifier'][$_modifier_name])
+                && !$this->_get_plugin_filepath('modifier', $_modifier_name)
+                && function_exists($_modifier_name)) {
+                if ($this->security && !in_array($_modifier_name, $this->security_settings['MODIFIER_FUNCS'])) {
+                    $this->_trigger_fatal_error("[plugin] (secure mode) modifier '$_modifier_name' is not allowed" , $this->_current_file, $this->_current_line_no, __FILE__, __LINE__);
+                } else {
+                    $this->_plugins['modifier'][$_modifier_name] = array($_modifier_name,  null, null, false);
+                }
+            }
+            $this->_add_plugin('modifier', $_modifier_name);
+
+            $this->_parse_vars_props($_modifier_args);
+
+            if($_modifier_name == 'default') {
+                // supress notifications of default modifier vars and args
+                if($output{0} == '$') {
+                    $output = '@' . $output;
+                }
+                if(isset($_modifier_args[0]) && $_modifier_args[0]{0} == '$') {
+                    $_modifier_args[0] = '@' . $_modifier_args[0];
+                }
+            }
+            if (count($_modifier_args) > 0)
+                $_modifier_args = ', '.implode(', ', $_modifier_args);
+            else
+                $_modifier_args = '';
+
+            if ($_map_array) {
+                $output = "((is_array(\$_tmp=$output)) ? \$this->_run_mod_handler('$_modifier_name', true, \$_tmp$_modifier_args) : " . $this->_compile_plugin_call('modifier', $_modifier_name) . "(\$_tmp$_modifier_args))";
+
+            } else {
+
+                $output = $this->_compile_plugin_call('modifier', $_modifier_name)."($output$_modifier_args)";
+
+            }
+        }
+    }
+
+
+    /**
+     * add plugin
+     *
+     * @param string $type
+     * @param string $name
+     * @param boolean? $delayed_loading
+     */
+    function _add_plugin($type, $name, $delayed_loading = null)
+    {
+        if (!isset($this->_plugin_info[$type])) {
+            $this->_plugin_info[$type] = array();
+        }
+        if (!isset($this->_plugin_info[$type][$name])) {
+            $this->_plugin_info[$type][$name] = array($this->_current_file,
+                                                      $this->_current_line_no,
+                                                      $delayed_loading);
+        }
+    }
+
+
+    /**
+     * Compiles references of type $smarty.foo
+     *
+     * @param string $indexes
+     * @return string
+     */
+    function _compile_smarty_ref(&$indexes)
+    {
+        /* Extract the reference name. */
+        $_ref = substr($indexes[0], 1);
+        foreach($indexes as $_index_no=>$_index) {
+            if ($_index{0} != '.' && $_index_no<2 || !preg_match('~^(\.|\[|->)~', $_index)) {
+                $this->_syntax_error('$smarty' . implode('', array_slice($indexes, 0, 2)) . ' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__);
+            }
+        }
+
+        switch ($_ref) {
+            case 'now':
+                $compiled_ref = 'time()';
+                $_max_index = 1;
+                break;
+
+            case 'foreach':
+                array_shift($indexes);
+                $_var = $this->_parse_var_props(substr($indexes[0], 1));
+                $_propname = substr($indexes[1], 1);
+                $_max_index = 1;
+                switch ($_propname) {
+                    case 'index':
+                        array_shift($indexes);
+                        $compiled_ref = "(\$this->_foreach[$_var]['iteration']-1)";
+                        break;
+                        
+                    case 'first':
+                        array_shift($indexes);
+                        $compiled_ref = "(\$this->_foreach[$_var]['iteration'] <= 1)";
+                        break;
+
+                    case 'last':
+                        array_shift($indexes);
+                        $compiled_ref = "(\$this->_foreach[$_var]['iteration'] == \$this->_foreach[$_var]['total'])";
+                        break;
+                        
+                    case 'show':
+                        array_shift($indexes);
+                        $compiled_ref = "(\$this->_foreach[$_var]['total'] > 0)";
+                        break;
+                        
+                    default:
+                        unset($_max_index);
+                        $compiled_ref = "\$this->_foreach[$_var]";
+                }
+                break;
+
+            case 'section':
+                array_shift($indexes);
+                $_var = $this->_parse_var_props(substr($indexes[0], 1));
+                $compiled_ref = "\$this->_sections[$_var]";
+                break;
+
+            case 'get':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_GET' : "\$GLOBALS['HTTP_GET_VARS']";
+                break;
+
+            case 'post':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_POST' : "\$GLOBALS['HTTP_POST_VARS']";
+                break;
+
+            case 'cookies':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_COOKIE' : "\$GLOBALS['HTTP_COOKIE_VARS']";
+                break;
+
+            case 'env':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_ENV' : "\$GLOBALS['HTTP_ENV_VARS']";
+                break;
+
+            case 'server':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_SERVER' : "\$GLOBALS['HTTP_SERVER_VARS']";
+                break;
+
+            case 'session':
+                $compiled_ref = ($this->request_use_auto_globals) ? '$_SESSION' : "\$GLOBALS['HTTP_SESSION_VARS']";
+                break;
+
+            /*
+             * These cases are handled either at run-time or elsewhere in the
+             * compiler.
+             */
+            case 'request':
+                if ($this->request_use_auto_globals) {
+                    $compiled_ref = '$_REQUEST';
+                    break;
+                } else {
+                    $this->_init_smarty_vars = true;
+                }
+                return null;
+
+            case 'capture':
+                return null;
+
+            case 'template':
+                $compiled_ref = "'$this->_current_file'";
+                $_max_index = 1;
+                break;
+
+            case 'version':
+                $compiled_ref = "'$this->_version'";
+                $_max_index = 1;
+                break;
+
+            case 'const':
+                if ($this->security && !$this->security_settings['ALLOW_CONSTANTS']) {
+                    $this->_syntax_error("(secure mode) constants not permitted",
+                                         E_USER_WARNING, __FILE__, __LINE__);
+                    return;
+                }
+                array_shift($indexes);
+                if (preg_match('!^\.\w+$!', $indexes[0])) {
+                    $compiled_ref = '@' . substr($indexes[0], 1);
+                } else {
+                    $_val = $this->_parse_var_props(substr($indexes[0], 1));
+                    $compiled_ref = '@constant(' . $_val . ')';
+                }
+                $_max_index = 1;
+                break;
+
+            case 'config':
+                $compiled_ref = "\$this->_config[0]['vars']";
+                $_max_index = 3;
+                break;
+
+            case 'ldelim':
+                $compiled_ref = "'$this->left_delimiter'";
+                break;
+
+            case 'rdelim':
+                $compiled_ref = "'$this->right_delimiter'";
+                break;
+                
+            default:
+                $this->_syntax_error('$smarty.' . $_ref . ' is an unknown reference', E_USER_ERROR, __FILE__, __LINE__);
+                break;
+        }
+
+        if (isset($_max_index) && count($indexes) > $_max_index) {
+            $this->_syntax_error('$smarty' . implode('', $indexes) .' is an invalid reference', E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        array_shift($indexes);
+        return $compiled_ref;
+    }
+
+    /**
+     * compiles call to plugin of type $type with name $name
+     * returns a string containing the function-name or method call
+     * without the paramter-list that would have follow to make the
+     * call valid php-syntax
+     *
+     * @param string $type
+     * @param string $name
+     * @return string
+     */
+    function _compile_plugin_call($type, $name) {
+        if (isset($this->_plugins[$type][$name])) {
+            /* plugin loaded */
+            if (is_array($this->_plugins[$type][$name][0])) {
+                return ((is_object($this->_plugins[$type][$name][0][0])) ?
+                        "\$this->_plugins['$type']['$name'][0][0]->"    /* method callback */
+                        : (string)($this->_plugins[$type][$name][0][0]).'::'    /* class callback */
+                       ). $this->_plugins[$type][$name][0][1];
+
+            } else {
+                /* function callback */
+                return $this->_plugins[$type][$name][0];
+
+            }
+        } else {
+            /* plugin not loaded -> auto-loadable-plugin */
+            return 'smarty_'.$type.'_'.$name;
+
+        }
+    }
+
+    /**
+     * load pre- and post-filters
+     */
+    function _load_filters()
+    {
+        if (count($this->_plugins['prefilter']) > 0) {
+            foreach ($this->_plugins['prefilter'] as $filter_name => $prefilter) {
+                if ($prefilter === false) {
+                    unset($this->_plugins['prefilter'][$filter_name]);
+                    $_params = array('plugins' => array(array('prefilter', $filter_name, null, null, false)));
+                    require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
+                    smarty_core_load_plugins($_params, $this);
+                }
+            }
+        }
+        if (count($this->_plugins['postfilter']) > 0) {
+            foreach ($this->_plugins['postfilter'] as $filter_name => $postfilter) {
+                if ($postfilter === false) {
+                    unset($this->_plugins['postfilter'][$filter_name]);
+                    $_params = array('plugins' => array(array('postfilter', $filter_name, null, null, false)));
+                    require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
+                    smarty_core_load_plugins($_params, $this);
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Quote subpattern references
+     *
+     * @param string $string
+     * @return string
+     */
+    function _quote_replace($string)
+    {
+        return strtr($string, array('\\' => '\\\\', '$' => '\\$'));
+    }
+
+    /**
+     * display Smarty syntax error
+     *
+     * @param string $error_msg
+     * @param integer $error_type
+     * @param string $file
+     * @param integer $line
+     */
+    function _syntax_error($error_msg, $error_type = E_USER_ERROR, $file=null, $line=null)
+    {
+        $this->_trigger_fatal_error("syntax error: $error_msg", $this->_current_file, $this->_current_line_no, $file, $line, $error_type);
+    }
+
+
+    /**
+     * check if the compilation changes from cacheable to
+     * non-cacheable state with the beginning of the current
+     * plugin. return php-code to reflect the transition.
+     * @return string
+     */
+    function _push_cacheable_state($type, $name) {
+        $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4];
+        if ($_cacheable
+            || 0<$this->_cacheable_state++) return '';
+        if (!isset($this->_cache_serial)) $this->_cache_serial = md5(uniqid('Smarty'));
+        $_ret = 'if ($this->caching && !$this->_cache_including) { echo \'{nocache:'
+            . $this->_cache_serial . '#' . $this->_nocache_count
+            . '}\';}';
+        return $_ret;
+    }
+
+
+    /**
+     * check if the compilation changes from non-cacheable to
+     * cacheable state with the end of the current plugin return
+     * php-code to reflect the transition.
+     * @return string
+     */
+    function _pop_cacheable_state($type, $name) {
+        $_cacheable = !isset($this->_plugins[$type][$name]) || $this->_plugins[$type][$name][4];
+        if ($_cacheable
+            || --$this->_cacheable_state>0) return '';
+        return 'if ($this->caching && !$this->_cache_including) { echo \'{/nocache:'
+            . $this->_cache_serial . '#' . ($this->_nocache_count++)
+            . '}\';}';
+    }
+
+
+    /**
+     * push opening tag-name, file-name and line-number on the tag-stack
+     * @param string the opening tag's name
+     */
+    function _push_tag($open_tag)
+    {
+        array_push($this->_tag_stack, array($open_tag, $this->_current_line_no));
+    }
+
+    /**
+     * pop closing tag-name
+     * raise an error if this stack-top doesn't match with the closing tag
+     * @param string the closing tag's name
+     * @return string the opening tag's name
+     */
+    function _pop_tag($close_tag)
+    {
+        $message = '';
+        if (count($this->_tag_stack)>0) {
+            list($_open_tag, $_line_no) = array_pop($this->_tag_stack);
+            if ($close_tag == $_open_tag) {
+                return $_open_tag;
+            }
+            if ($close_tag == 'if' && ($_open_tag == 'else' || $_open_tag == 'elseif' )) {
+                return $this->_pop_tag($close_tag);
+            }
+            if ($close_tag == 'section' && $_open_tag == 'sectionelse') {
+                $this->_pop_tag($close_tag);
+                return $_open_tag;
+            }
+            if ($close_tag == 'foreach' && $_open_tag == 'foreachelse') {
+                $this->_pop_tag($close_tag);
+                return $_open_tag;
+            }
+            if ($_open_tag == 'else' || $_open_tag == 'elseif') {
+                $_open_tag = 'if';
+            } elseif ($_open_tag == 'sectionelse') {
+                $_open_tag = 'section';
+            } elseif ($_open_tag == 'foreachelse') {
+                $_open_tag = 'foreach';
+            }
+            $message = " expected {/$_open_tag} (opened line $_line_no).";
+        }
+        $this->_syntax_error("mismatched tag {/$close_tag}.$message",
+                             E_USER_ERROR, __FILE__, __LINE__);
+    }
+
+}
+
+/**
+ * compare to values by their string length
+ *
+ * @access private
+ * @param string $a
+ * @param string $b
+ * @return 0|-1|1
+ */
+function _smarty_sort_length($a, $b)
+{
+    if($a == $b)
+        return 0;
+
+    if(strlen($a) == strlen($b))
+        return ($a > $b) ? -1 : 1;
+
+    return (strlen($a) > strlen($b)) ? -1 : 1;
+}
+
+
+/* vim: set et: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/debug.tpl b/bundled-libs/Smarty/libs/debug.tpl
new file mode 100644 (file)
index 0000000..7f1c9d4
--- /dev/null
@@ -0,0 +1,64 @@
+{* Smarty *}
+
+{* debug.tpl, last updated version 2.0.1 *}
+
+{assign_debug_info}
+
+{if isset($_smarty_debug_output) and $_smarty_debug_output eq "html"}
+       <table border=0 width=100%>
+       <tr bgcolor=#cccccc><th colspan=2>Smarty Debug Console</th></tr>
+       <tr bgcolor=#cccccc><td colspan=2><b>included templates & config files (load time in seconds):</b></td></tr>
+       {section name=templates loop=$_debug_tpls}
+               <tr bgcolor={if %templates.index% is even}#eeeeee{else}#fafafa{/if}><td colspan=2><tt>{section name=indent loop=$_debug_tpls[templates].depth}&nbsp;&nbsp;&nbsp;{/section}<font color={if $_debug_tpls[templates].type eq "template"}brown{elseif $_debug_tpls[templates].type eq "insert"}black{else}green{/if}>{$_debug_tpls[templates].filename|escape:html}</font>{if isset($_debug_tpls[templates].exec_time)} <font size=-1><i>({$_debug_tpls[templates].exec_time|string_format:"%.5f"}){if %templates.index% eq 0} (total){/if}</i></font>{/if}</tt></td></tr>
+       {sectionelse}
+               <tr bgcolor=#eeeeee><td colspan=2><tt><i>no templates included</i></tt></td></tr>       
+       {/section}
+       <tr bgcolor=#cccccc><td colspan=2><b>assigned template variables:</b></td></tr>
+       {section name=vars loop=$_debug_keys}
+               <tr bgcolor={if %vars.index% is even}#eeeeee{else}#fafafa{/if}><td valign=top><tt><font color=blue>{ldelim}${$_debug_keys[vars]}{rdelim}</font></tt></td><td nowrap><tt><font color=green>{$_debug_vals[vars]|@debug_print_var}</font></tt></td></tr>
+       {sectionelse}
+               <tr bgcolor=#eeeeee><td colspan=2><tt><i>no template variables assigned</i></tt></td></tr>      
+       {/section}
+       <tr bgcolor=#cccccc><td colspan=2><b>assigned config file variables (outer template scope):</b></td></tr>
+       {section name=config_vars loop=$_debug_config_keys}
+               <tr bgcolor={if %config_vars.index% is even}#eeeeee{else}#fafafa{/if}><td valign=top><tt><font color=maroon>{ldelim}#{$_debug_config_keys[config_vars]}#{rdelim}</font></tt></td><td><tt><font color=green>{$_debug_config_vals[config_vars]|@debug_print_var}</font></tt></td></tr>
+       {sectionelse}
+               <tr bgcolor=#eeeeee><td colspan=2><tt><i>no config vars assigned</i></tt></td></tr>     
+       {/section}
+       </table>
+</BODY></HTML>
+{else}
+<SCRIPT language=javascript>
+       if( self.name == '' ) {ldelim}
+          var title = 'Console';
+       {rdelim}
+       else {ldelim}
+          var title = 'Console_' + self.name;
+       {rdelim}
+       _smarty_console = window.open("",title.value,"width=680,height=600,resizable,scrollbars=yes");
+       _smarty_console.document.write("<HTML><HEAD><TITLE>Smarty Debug Console_"+self.name+"</TITLE></HEAD><BODY bgcolor=#ffffff>");
+       _smarty_console.document.write("<table border=0 width=100%>");
+       _smarty_console.document.write("<tr bgcolor=#cccccc><th colspan=2>Smarty Debug Console</th></tr>");
+       _smarty_console.document.write("<tr bgcolor=#cccccc><td colspan=2><b>included templates & config files (load time in seconds):</b></td></tr>");
+       {section name=templates loop=$_debug_tpls}
+               _smarty_console.document.write("<tr bgcolor={if %templates.index% is even}#eeeeee{else}#fafafa{/if}><td colspan=2><tt>{section name=indent loop=$_debug_tpls[templates].depth}&nbsp;&nbsp;&nbsp;{/section}<font color={if $_debug_tpls[templates].type eq "template"}brown{elseif $_debug_tpls[templates].type eq "insert"}black{else}green{/if}>{$_debug_tpls[templates].filename|escape:html|escape:javascript}</font>{if isset($_debug_tpls[templates].exec_time)} <font size=-1><i>({$_debug_tpls[templates].exec_time|string_format:"%.5f"}){if %templates.index% eq 0} (total){/if}</i></font>{/if}</tt></td></tr>");
+       {sectionelse}
+               _smarty_console.document.write("<tr bgcolor=#eeeeee><td colspan=2><tt><i>no templates included</i></tt></td></tr>");    
+       {/section}
+       _smarty_console.document.write("<tr bgcolor=#cccccc><td colspan=2><b>assigned template variables:</b></td></tr>");
+       {section name=vars loop=$_debug_keys}
+               _smarty_console.document.write("<tr bgcolor={if %vars.index% is even}#eeeeee{else}#fafafa{/if}><td valign=top><tt><font color=blue>{ldelim}${$_debug_keys[vars]}{rdelim}</font></tt></td><td nowrap><tt><font color=green>{$_debug_vals[vars]|@debug_print_var|escape:javascript}</font></tt></td></tr>");
+       {sectionelse}
+               _smarty_console.document.write("<tr bgcolor=#eeeeee><td colspan=2><tt><i>no template variables assigned</i></tt></td></tr>");   
+       {/section}
+       _smarty_console.document.write("<tr bgcolor=#cccccc><td colspan=2><b>assigned config file variables (outer template scope):</b></td></tr>");
+       {section name=config_vars loop=$_debug_config_keys}
+               _smarty_console.document.write("<tr bgcolor={if %config_vars.index% is even}#eeeeee{else}#fafafa{/if}><td valign=top><tt><font color=maroon>{ldelim}#{$_debug_config_keys[config_vars]}#{rdelim}</font></tt></td><td><tt><font color=green>{$_debug_config_vals[config_vars]|@debug_print_var|escape:javascript}</font></tt></td></tr>");
+       {sectionelse}
+               _smarty_console.document.write("<tr bgcolor=#eeeeee><td colspan=2><tt><i>no config vars assigned</i></tt></td></tr>");  
+       {/section}
+       _smarty_console.document.write("</table>");
+       _smarty_console.document.write("</BODY></HTML>");
+       _smarty_console.document.close();
+</SCRIPT>
+{/if}
diff --git a/bundled-libs/Smarty/libs/internals/core.assemble_plugin_filepath.php b/bundled-libs/Smarty/libs/internals/core.assemble_plugin_filepath.php
new file mode 100644 (file)
index 0000000..690d3dd
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * assemble filepath of requested plugin
+ *
+ * @param string $type
+ * @param string $name
+ * @return string|false
+ */
+function smarty_core_assemble_plugin_filepath($params, &$smarty)
+{
+    static $_filepaths_cache = array();
+
+    $_plugin_filename = $params['type'] . '.' . $params['name'] . '.php';
+    if (isset($_filepaths_cache[$_plugin_filename])) {
+        return $_filepaths_cache[$_plugin_filename];
+    }
+    $_return = false;
+
+    foreach ((array)$smarty->plugins_dir as $_plugin_dir) {
+
+        $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename;
+
+        // see if path is relative
+        if (!preg_match("/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/", $_plugin_dir)) {
+            $_relative_paths[] = $_plugin_dir;
+            // relative path, see if it is in the SMARTY_DIR
+            if (@is_readable(SMARTY_DIR . $_plugin_filepath)) {
+                $_return = SMARTY_DIR . $_plugin_filepath;
+                break;
+            }
+        }
+        // try relative to cwd (or absolute)
+        if (@is_readable($_plugin_filepath)) {
+            $_return = $_plugin_filepath;
+            break;
+        }
+    }
+
+    if($_return === false) {
+        // still not found, try PHP include_path
+        if(isset($_relative_paths)) {
+            foreach ((array)$_relative_paths as $_plugin_dir) {
+
+                $_plugin_filepath = $_plugin_dir . DIRECTORY_SEPARATOR . $_plugin_filename;
+
+                $_params = array('file_path' => $_plugin_filepath);
+                require_once(SMARTY_CORE_DIR . 'core.get_include_path.php');
+                if(smarty_core_get_include_path($_params, $smarty)) {
+                    $_return = $_params['new_file_path'];
+                    break;
+                }
+            }
+        }
+    }
+    $_filepaths_cache[$_plugin_filename] = $_return;
+    return $_return;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.assign_smarty_interface.php b/bundled-libs/Smarty/libs/internals/core.assign_smarty_interface.php
new file mode 100644 (file)
index 0000000..7e65a73
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty assign_smarty_interface core plugin
+ *
+ * Type:     core<br>
+ * Name:     assign_smarty_interface<br>
+ * Purpose:  assign the $smarty interface variable
+ * @param array Format: null
+ * @param Smarty
+ */
+function smarty_core_assign_smarty_interface($params, &$smarty)
+{
+        if (isset($smarty->_smarty_vars) && isset($smarty->_smarty_vars['request'])) {
+            return;
+        }
+
+        $_globals_map = array('g'  => 'HTTP_GET_VARS',
+                             'p'  => 'HTTP_POST_VARS',
+                             'c'  => 'HTTP_COOKIE_VARS',
+                             's'  => 'HTTP_SERVER_VARS',
+                             'e'  => 'HTTP_ENV_VARS');
+
+        $_smarty_vars_request  = array();
+
+        foreach (preg_split('!!', strtolower($smarty->request_vars_order)) as $_c) {
+            if (isset($_globals_map[$_c])) {
+                $_smarty_vars_request = array_merge($_smarty_vars_request, $GLOBALS[$_globals_map[$_c]]);
+            }
+        }
+        $_smarty_vars_request = @array_merge($_smarty_vars_request, $GLOBALS['HTTP_SESSION_VARS']);
+
+        $smarty->_smarty_vars['request'] = $_smarty_vars_request;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.create_dir_structure.php b/bundled-libs/Smarty/libs/internals/core.create_dir_structure.php
new file mode 100644 (file)
index 0000000..999cf59
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * create full directory structure
+ *
+ * @param string $dir
+ */
+
+// $dir
+
+function smarty_core_create_dir_structure($params, &$smarty)
+{
+    if (!file_exists($params['dir'])) {
+        $_open_basedir_ini = ini_get('open_basedir');
+
+        if (DIRECTORY_SEPARATOR=='/') {
+            /* unix-style paths */
+            $_dir = $params['dir'];
+            $_dir_parts = preg_split('!/+!', $_dir, -1, PREG_SPLIT_NO_EMPTY);
+            $_new_dir = ($_dir{0}=='/') ? '/' : getcwd().'/';
+            if($_use_open_basedir = !empty($_open_basedir_ini)) {
+                $_open_basedirs = explode(':', $_open_basedir_ini);
+            }
+
+        } else {
+            /* other-style paths */
+            $_dir = str_replace('\\','/', $params['dir']);
+            $_dir_parts = preg_split('!/+!', $_dir, -1, PREG_SPLIT_NO_EMPTY);
+            if (preg_match('!^((//)|([a-zA-Z]:/))!', $_dir, $_root_dir)) {
+                /* leading "//" for network volume, or "[letter]:/" for full path */
+                $_new_dir = $_root_dir[1];
+                /* remove drive-letter from _dir_parts */
+                if (isset($_root_dir[3])) array_shift($_dir_parts);
+
+            } else {
+                $_new_dir = str_replace('\\', '/', getcwd()).'/';
+
+            }
+
+            if($_use_open_basedir = !empty($_open_basedir_ini)) {
+                $_open_basedirs = explode(';', str_replace('\\', '/', $_open_basedir_ini));
+            }
+
+        }
+
+        /* all paths use "/" only from here */
+        foreach ($_dir_parts as $_dir_part) {
+            $_new_dir .= $_dir_part;
+
+            if ($_use_open_basedir) {
+                // do not attempt to test or make directories outside of open_basedir
+                $_make_new_dir = false;
+                foreach ($_open_basedirs as $_open_basedir) {
+                    if (substr($_new_dir, 0, strlen($_open_basedir)) == $_open_basedir) {
+                        $_make_new_dir = true;
+                        break;
+                    }
+                }
+            } else {
+                $_make_new_dir = true;
+            }
+
+            if ($_make_new_dir && !file_exists($_new_dir) && !@mkdir($_new_dir, $smarty->_dir_perms) && !is_dir($_new_dir)) {
+                $smarty->trigger_error("problem creating directory '" . $_new_dir . "'");
+                return false;
+            }
+            $_new_dir .= '/';
+        }
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.display_debug_console.php b/bundled-libs/Smarty/libs/internals/core.display_debug_console.php
new file mode 100644 (file)
index 0000000..a5d7291
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty debug_console function plugin
+ *
+ * Type:     core<br>
+ * Name:     display_debug_console<br>
+ * Purpose:  display the javascript debug console window
+ * @param array Format: null
+ * @param Smarty
+ */
+function smarty_core_display_debug_console($params, &$smarty)
+{
+    // we must force compile the debug template in case the environment
+    // changed between separate applications.
+
+    if(empty($smarty->debug_tpl)) {
+        // set path to debug template from SMARTY_DIR
+        $smarty->debug_tpl = SMARTY_DIR . 'debug.tpl';
+        if($smarty->security && is_file($smarty->debug_tpl)) {
+            $smarty->secure_dir[] = dirname(realpath($smarty->debug_tpl));
+        }
+        $smarty->debug_tpl = 'file:' . SMARTY_DIR . 'debug.tpl';
+    }
+
+    $_ldelim_orig = $smarty->left_delimiter;
+    $_rdelim_orig = $smarty->right_delimiter;
+
+    $smarty->left_delimiter = '{';
+    $smarty->right_delimiter = '}';
+
+    $_compile_id_orig = $smarty->_compile_id;
+    $smarty->_compile_id = null;
+
+    $_compile_path = $smarty->_get_compile_path($smarty->debug_tpl);
+    if ($smarty->_compile_resource($smarty->debug_tpl, $_compile_path))
+    {
+        ob_start();
+        $smarty->_include($_compile_path);
+        $_results = ob_get_contents();
+        ob_end_clean();
+    } else {
+        $_results = '';
+    }
+
+    $smarty->_compile_id = $_compile_id_orig;
+
+    $smarty->left_delimiter = $_ldelim_orig;
+    $smarty->right_delimiter = $_rdelim_orig;
+
+    return $_results;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.get_include_path.php b/bundled-libs/Smarty/libs/internals/core.get_include_path.php
new file mode 100644 (file)
index 0000000..4343241
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Get path to file from include_path
+ *
+ * @param string $file_path
+ * @param string $new_file_path
+ * @return boolean
+ * @staticvar array|null
+ */
+
+//  $file_path, &$new_file_path
+
+function smarty_core_get_include_path(&$params, &$smarty)
+{
+    static $_path_array = null;
+
+    if(!isset($_path_array)) {
+        $_ini_include_path = ini_get('include_path');
+
+        if(strstr($_ini_include_path,';')) {
+            // windows pathnames
+            $_path_array = explode(';',$_ini_include_path);
+        } else {
+            $_path_array = explode(':',$_ini_include_path);
+        }
+    }
+    foreach ($_path_array as $_include_path) {
+        if (@is_readable($_include_path . DIRECTORY_SEPARATOR . $params['file_path'])) {
+               $params['new_file_path'] = $_include_path . DIRECTORY_SEPARATOR . $params['file_path'];
+            return true;
+        }
+    }
+    return false;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.get_microtime.php b/bundled-libs/Smarty/libs/internals/core.get_microtime.php
new file mode 100644 (file)
index 0000000..f1a28e0
--- /dev/null
@@ -0,0 +1,23 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Get seconds and microseconds
+ * @return double
+ */
+function smarty_core_get_microtime($params, &$smarty)
+{
+    $mtime = microtime();
+    $mtime = explode(" ", $mtime);
+    $mtime = (double)($mtime[1]) + (double)($mtime[0]);
+    return ($mtime);
+}
+
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.get_php_resource.php b/bundled-libs/Smarty/libs/internals/core.get_php_resource.php
new file mode 100644 (file)
index 0000000..786d4e7
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Retrieves PHP script resource
+ *
+ * sets $php_resource to the returned resource
+ * @param string $resource
+ * @param string $resource_type
+ * @param  $php_resource
+ * @return boolean
+ */
+
+function smarty_core_get_php_resource(&$params, &$smarty)
+{
+
+    $params['resource_base_path'] = $smarty->trusted_dir;
+    $smarty->_parse_resource_name($params, $smarty);
+
+    /*
+     * Find out if the resource exists.
+     */
+
+    if ($params['resource_type'] == 'file') {
+        $_readable = false;
+        if(file_exists($params['resource_name']) && is_readable($params['resource_name'])) {
+            $_readable = true;
+        } else {
+            // test for file in include_path
+            $_params = array('file_path' => $params['resource_name']);
+            require_once(SMARTY_CORE_DIR . 'core.get_include_path.php');
+            if(smarty_core_get_include_path($_params, $smarty)) {
+                $_include_path = $_params['new_file_path'];
+                $_readable = true;
+            }
+        }
+    } else if ($params['resource_type'] != 'file') {
+        $_template_source = null;
+        $_readable = is_callable($smarty->_plugins['resource'][$params['resource_type']][0][0])
+            && call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][0],
+                                    array($params['resource_name'], &$_template_source, &$smarty));
+    }
+
+    /*
+     * Set the error function, depending on which class calls us.
+     */
+    if (method_exists($smarty, '_syntax_error')) {
+        $_error_funcc = '_syntax_error';
+    } else {
+        $_error_funcc = 'trigger_error';
+    }
+
+    if ($_readable) {
+        if ($smarty->security) {
+            require_once(SMARTY_CORE_DIR . 'core.is_trusted.php');
+            if (!smarty_core_is_trusted($params, $smarty)) {
+                $smarty->$_error_funcc('(secure mode) ' . $params['resource_type'] . ':' . $params['resource_name'] . ' is not trusted');
+                return false;
+            }
+        }
+    } else {
+        $smarty->$_error_funcc($params['resource_type'] . ':' . $params['resource_name'] . ' is not readable');
+        return false;
+    }
+
+    if ($params['resource_type'] == 'file') {
+        $params['php_resource'] = $params['resource_name'];
+    } else {
+        $params['php_resource'] = $_template_source;
+    }
+    return true;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.is_secure.php b/bundled-libs/Smarty/libs/internals/core.is_secure.php
new file mode 100644 (file)
index 0000000..342f3af
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * determines if a resource is secure or not.
+ *
+ * @param string $resource_type
+ * @param string $resource_name
+ * @return boolean
+ */
+
+//  $resource_type, $resource_name
+
+function smarty_core_is_secure($params, &$smarty)
+{
+    if (!$smarty->security || $smarty->security_settings['INCLUDE_ANY']) {
+        return true;
+    }
+
+    if ($params['resource_type'] == 'file') {
+        $_rp = realpath($params['resource_name']);
+        if (isset($params['resource_base_path'])) {
+            foreach ((array)$params['resource_base_path'] as $curr_dir) {
+                if ( ($_cd = realpath($curr_dir)) !== false &&
+                     strncmp($_rp, $_cd, strlen($_cd)) == 0 &&
+                     $_rp{strlen($_cd)} == DIRECTORY_SEPARATOR ) {
+                    return true;
+                }
+            }
+        }
+        if (!empty($smarty->secure_dir)) {
+            foreach ((array)$smarty->secure_dir as $curr_dir) {
+                if ( ($_cd = realpath($curr_dir)) !== false &&
+                     strncmp($_rp, $_cd, strlen($_cd)) == 0 &&
+                     $_rp{strlen($_cd)} == DIRECTORY_SEPARATOR ) {
+                    return true;
+                }            
+            }
+        }
+    } else {
+        // resource is not on local file system
+        return call_user_func_array(
+            $smarty->_plugins['resource'][$params['resource_type']][0][2],
+            array($params['resource_name'], &$smarty));
+    }
+
+    return false;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.is_trusted.php b/bundled-libs/Smarty/libs/internals/core.is_trusted.php
new file mode 100644 (file)
index 0000000..f0bd2fb
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * determines if a resource is trusted or not
+ *
+ * @param string $resource_type
+ * @param string $resource_name
+ * @return boolean
+ */
+
+ // $resource_type, $resource_name
+
+function smarty_core_is_trusted($params, &$smarty)
+{
+    $_smarty_trusted = false;
+    if ($params['resource_type'] == 'file') {
+        if (!empty($smarty->trusted_dir)) {
+            $_rp = realpath($params['resource_name']);
+            foreach ((array)$smarty->trusted_dir as $curr_dir) {
+                if (!empty($curr_dir) && is_readable ($curr_dir)) {
+                    $_cd = realpath($curr_dir);
+                    if (strncmp($_rp, $_cd, strlen($_cd)) == 0
+                        && $_rp{strlen($_cd)} == DIRECTORY_SEPARATOR ) {
+                        $_smarty_trusted = true;
+                        break;
+                    }
+                }
+            }
+        }
+
+    } else {
+        // resource is not on local file system
+        $_smarty_trusted = call_user_func_array($smarty->_plugins['resource'][$params['resource_type']][0][3],
+                                                array($params['resource_name'], $smarty));
+    }
+
+    return $_smarty_trusted;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.load_plugins.php b/bundled-libs/Smarty/libs/internals/core.load_plugins.php
new file mode 100644 (file)
index 0000000..6db1dc5
--- /dev/null
@@ -0,0 +1,125 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Load requested plugins
+ *
+ * @param array $plugins
+ */
+
+// $plugins
+
+function smarty_core_load_plugins($params, &$smarty)
+{
+
+    foreach ($params['plugins'] as $_plugin_info) {
+        list($_type, $_name, $_tpl_file, $_tpl_line, $_delayed_loading) = $_plugin_info;
+        $_plugin = &$smarty->_plugins[$_type][$_name];
+
+        /*
+         * We do not load plugin more than once for each instance of Smarty.
+         * The following code checks for that. The plugin can also be
+         * registered dynamically at runtime, in which case template file
+         * and line number will be unknown, so we fill them in.
+         *
+         * The final element of the info array is a flag that indicates
+         * whether the dynamically registered plugin function has been
+         * checked for existence yet or not.
+         */
+        if (isset($_plugin)) {
+            if (empty($_plugin[3])) {
+                if (!is_callable($_plugin[0])) {
+                    $smarty->_trigger_fatal_error("[plugin] $_type '$_name' is not implemented", $_tpl_file, $_tpl_line, __FILE__, __LINE__);
+                } else {
+                    $_plugin[1] = $_tpl_file;
+                    $_plugin[2] = $_tpl_line;
+                    $_plugin[3] = true;
+                    if (!isset($_plugin[4])) $_plugin[4] = true; /* cacheable */
+                }
+            }
+            continue;
+        } else if ($_type == 'insert') {
+            /*
+             * For backwards compatibility, we check for insert functions in
+             * the symbol table before trying to load them as a plugin.
+             */
+            $_plugin_func = 'insert_' . $_name;
+            if (function_exists($_plugin_func)) {
+                $_plugin = array($_plugin_func, $_tpl_file, $_tpl_line, true, false);
+                continue;
+            }
+        }
+
+        $_plugin_file = $smarty->_get_plugin_filepath($_type, $_name);
+
+        if (! $_found = ($_plugin_file != false)) {
+            $_message = "could not load plugin file '$_type.$_name.php'\n";
+        }
+
+        /*
+         * If plugin file is found, it -must- provide the properly named
+         * plugin function. In case it doesn't, simply output the error and
+         * do not fall back on any other method.
+         */
+        if ($_found) {
+            include_once $_plugin_file;
+
+            $_plugin_func = 'smarty_' . $_type . '_' . $_name;
+            if (!function_exists($_plugin_func)) {
+                $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", $_tpl_file, $_tpl_line, __FILE__, __LINE__);
+                continue;
+            }
+        }
+        /*
+         * In case of insert plugins, their code may be loaded later via
+         * 'script' attribute.
+         */
+        else if ($_type == 'insert' && $_delayed_loading) {
+            $_plugin_func = 'smarty_' . $_type . '_' . $_name;
+            $_found = true;
+        }
+
+        /*
+         * Plugin specific processing and error checking.
+         */
+        if (!$_found) {
+            if ($_type == 'modifier') {
+                /*
+                 * In case modifier falls back on using PHP functions
+                 * directly, we only allow those specified in the security
+                 * context.
+                 */
+                if ($smarty->security && !in_array($_name, $smarty->security_settings['MODIFIER_FUNCS'])) {
+                    $_message = "(secure mode) modifier '$_name' is not allowed";
+                } else {
+                    if (!function_exists($_name)) {
+                        $_message = "modifier '$_name' is not implemented";
+                    } else {
+                        $_plugin_func = $_name;
+                        $_found = true;
+                    }
+                }
+            } else if ($_type == 'function') {
+                /*
+                 * This is a catch-all situation.
+                 */
+                $_message = "unknown tag - '$_name'";
+            }
+        }
+
+        if ($_found) {
+            $smarty->_plugins[$_type][$_name] = array($_plugin_func, $_tpl_file, $_tpl_line, true, true);
+        } else {
+            // output error
+            $smarty->_trigger_fatal_error('[plugin] ' . $_message, $_tpl_file, $_tpl_line, __FILE__, __LINE__);
+        }
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.load_resource_plugin.php b/bundled-libs/Smarty/libs/internals/core.load_resource_plugin.php
new file mode 100644 (file)
index 0000000..a7d37d1
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * load a resource plugin
+ *
+ * @param string $type
+ */
+
+// $type
+
+function smarty_core_load_resource_plugin($params, &$smarty)
+{
+    /*
+     * Resource plugins are not quite like the other ones, so they are
+     * handled differently. The first element of plugin info is the array of
+     * functions provided by the plugin, the second one indicates whether
+     * all of them exist or not.
+     */
+
+    $_plugin = &$smarty->_plugins['resource'][$params['type']];
+    if (isset($_plugin)) {
+        if (!$_plugin[1] && count($_plugin[0])) {
+            $_plugin[1] = true;
+            foreach ($_plugin[0] as $_plugin_func) {
+                if (!is_callable($_plugin_func)) {
+                    $_plugin[1] = false;
+                    break;
+                }
+            }
+        }
+
+        if (!$_plugin[1]) {
+            $smarty->_trigger_fatal_error("[plugin] resource '" . $params['type'] . "' is not implemented", null, null, __FILE__, __LINE__);
+        }
+
+        return;
+    }
+
+    $_plugin_file = $smarty->_get_plugin_filepath('resource', $params['type']);
+    $_found = ($_plugin_file != false);
+
+    if ($_found) {            /*
+         * If the plugin file is found, it -must- provide the properly named
+         * plugin functions.
+         */
+        include_once($_plugin_file);
+
+        /*
+         * Locate functions that we require the plugin to provide.
+         */
+        $_resource_ops = array('source', 'timestamp', 'secure', 'trusted');
+        $_resource_funcs = array();
+        foreach ($_resource_ops as $_op) {
+            $_plugin_func = 'smarty_resource_' . $params['type'] . '_' . $_op;
+            if (!function_exists($_plugin_func)) {
+                $smarty->_trigger_fatal_error("[plugin] function $_plugin_func() not found in $_plugin_file", null, null, __FILE__, __LINE__);
+                return;
+            } else {
+                $_resource_funcs[] = $_plugin_func;
+            }
+        }
+
+        $smarty->_plugins['resource'][$params['type']] = array($_resource_funcs, true);
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.process_cached_inserts.php b/bundled-libs/Smarty/libs/internals/core.process_cached_inserts.php
new file mode 100644 (file)
index 0000000..29cb007
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Replace cached inserts with the actual results
+ *
+ * @param string $results
+ * @return string
+ */
+function smarty_core_process_cached_inserts($params, &$smarty)
+{
+    preg_match_all('!'.$smarty->_smarty_md5.'{insert_cache (.*)}'.$smarty->_smarty_md5.'!Uis',
+                   $params['results'], $match);
+    list($cached_inserts, $insert_args) = $match;
+
+    for ($i = 0, $for_max = count($cached_inserts); $i < $for_max; $i++) {
+        if ($smarty->debugging) {
+            $_params = array();
+            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+            $debug_start_time = smarty_core_get_microtime($_params, $smarty);
+        }
+
+        $args = unserialize($insert_args[$i]);
+        $name = $args['name'];
+
+        if (isset($args['script'])) {
+            $_params = array('resource_name' => $smarty->_dequote($args['script']));
+            require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php');
+            if(!smarty_core_get_php_resource($_params, $smarty)) {
+                return false;
+            }
+            $resource_type = $_params['resource_type'];
+            $php_resource = $_params['php_resource'];
+
+
+            if ($resource_type == 'file') {
+                $smarty->_include($php_resource, true);
+            } else {
+                $smarty->_eval($php_resource);
+            }
+        }
+
+        $function_name = $smarty->_plugins['insert'][$name][0];
+        if (empty($args['assign'])) {
+            $replace = $function_name($args, $smarty);
+        } else {
+            $smarty->assign($args['assign'], $function_name($args, $smarty));
+            $replace = '';
+        }
+
+        $params['results'] = str_replace($cached_inserts[$i], $replace, $params['results']);
+        if ($smarty->debugging) {
+            $_params = array();
+            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+            $smarty->_smarty_debug_info[] = array('type'      => 'insert',
+                                                'filename'  => 'insert_'.$name,
+                                                'depth'     => $smarty->_inclusion_depth,
+                                                'exec_time' => smarty_core_get_microtime($_params, $smarty) - $debug_start_time);
+        }
+    }
+
+    return $params['results'];
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.process_compiled_include.php b/bundled-libs/Smarty/libs/internals/core.process_compiled_include.php
new file mode 100644 (file)
index 0000000..3e1d4c1
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Replace nocache-tags by results of the corresponding non-cacheable
+ * functions and return it
+ *
+ * @param string $compiled_tpl
+ * @param string $cached_source
+ * @return string
+ */
+
+function smarty_core_process_compiled_include($params, &$smarty)
+{
+    $_cache_including = $smarty->_cache_including;
+    $smarty->_cache_including = true;
+
+    $_return = $params['results'];
+    foreach ($smarty->_cache_serials as $_include_file_path=>$_cache_serial) {
+        $_return = preg_replace_callback('!(\{nocache\:('.$_cache_serial.')#(\d+)\})!s',
+                                         array(&$smarty, '_process_compiled_include_callback'),
+                                         $_return);
+    }
+    $smarty->_cache_including = $_cache_including;
+    return $_return;
+}
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.read_cache_file.php b/bundled-libs/Smarty/libs/internals/core.read_cache_file.php
new file mode 100644 (file)
index 0000000..ecb1470
--- /dev/null
@@ -0,0 +1,111 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * read a cache file, determine if it needs to be
+ * regenerated or not
+ *
+ * @param string $tpl_file
+ * @param string $cache_id
+ * @param string $compile_id
+ * @param string $results
+ * @return boolean
+ */
+
+//  $tpl_file, $cache_id, $compile_id, &$results
+
+function smarty_core_read_cache_file(&$params, &$smarty)
+{
+    static  $content_cache = array();
+
+    if ($smarty->force_compile) {
+        // force compile enabled, always regenerate
+        return false;
+    }
+
+    if (isset($content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']])) {
+        list($params['results'], $smarty->_cache_info) = $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']];
+        return true;
+    }
+
+    if (!empty($smarty->cache_handler_func)) {
+        // use cache_handler function
+        call_user_func_array($smarty->cache_handler_func,
+                             array('read', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null));
+    } else {
+        // use local cache file
+        $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']);
+        $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id);
+        $params['results'] = $smarty->_read_file($_cache_file);
+    }
+
+    if (empty($params['results'])) {
+        // nothing to parse (error?), regenerate cache
+        return false;
+    }
+
+    $_contents = $params['results'];
+    $_info_start = strpos($_contents, "\n") + 1;
+    $_info_len = (int)substr($_contents, 0, $_info_start - 1);
+    $_cache_info = unserialize(substr($_contents, $_info_start, $_info_len));
+    $params['results'] = substr($_contents, $_info_start + $_info_len);
+
+    if ($smarty->caching == 2 && isset ($_cache_info['expires'])){
+        // caching by expiration time
+        if ($_cache_info['expires'] > -1 && (time() > $_cache_info['expires'])) {
+            // cache expired, regenerate
+            return false;
+        }
+    } else {
+        // caching by lifetime
+        if ($smarty->cache_lifetime > -1 && (time() - $_cache_info['timestamp'] > $smarty->cache_lifetime)) {
+            // cache expired, regenerate
+            return false;
+        }
+    }
+
+    if ($smarty->compile_check) {
+        $_params = array('get_source' => false, 'quiet'=>true);
+        foreach (array_keys($_cache_info['template']) as $_template_dep) {
+            $_params['resource_name'] = $_template_dep;
+            if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) {
+                // template file has changed, regenerate cache
+                return false;
+            }
+        }
+
+        if (isset($_cache_info['config'])) {
+            $_params = array('resource_base_path' => $smarty->config_dir, 'get_source' => false, 'quiet'=>true);
+            foreach (array_keys($_cache_info['config']) as $_config_dep) {
+                $_params['resource_name'] = $_config_dep;
+                if (!$smarty->_fetch_resource_info($_params) || $_cache_info['timestamp'] < $_params['resource_timestamp']) {
+                    // config file has changed, regenerate cache
+                    return false;
+                }
+            }
+        }
+    }
+
+    foreach ($_cache_info['cache_serials'] as $_include_file_path=>$_cache_serial) {
+        if (empty($smarty->_cache_serials[$_include_file_path])) {
+            $smarty->_include($_include_file_path, true);
+        }
+
+        if ($smarty->_cache_serials[$_include_file_path] != $_cache_serial) {
+            /* regenerate */
+            return false;
+        }
+    }
+    $content_cache[$params['tpl_file'].','.$params['cache_id'].','.$params['compile_id']] = array($params['results'], $_cache_info);
+
+    $smarty->_cache_info = $_cache_info;
+    return true;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.rm_auto.php b/bundled-libs/Smarty/libs/internals/core.rm_auto.php
new file mode 100644 (file)
index 0000000..b251f64
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * delete an automagically created file by name and id
+ *
+ * @param string $auto_base
+ * @param string $auto_source
+ * @param string $auto_id
+ * @param integer $exp_time
+ * @return boolean
+ */
+
+// $auto_base, $auto_source = null, $auto_id = null, $exp_time = null
+
+function smarty_core_rm_auto($params, &$smarty)
+{
+    if (!@is_dir($params['auto_base']))
+      return false;
+
+    if(!isset($params['auto_id']) && !isset($params['auto_source'])) {
+        $_params = array(
+            'dirname' => $params['auto_base'],
+            'level' => 0,
+            'exp_time' => $params['exp_time']
+        );
+        require_once(SMARTY_CORE_DIR . 'core.rmdir.php');
+        $_res = smarty_core_rmdir($_params, $smarty);
+    } else {
+        $_tname = $smarty->_get_auto_filename($params['auto_base'], $params['auto_source'], $params['auto_id']);
+
+        if(isset($params['auto_source'])) {
+            if (isset($params['extensions'])) {
+                $_res = false;
+                foreach ((array)$params['extensions'] as $_extension)
+                    $_res |= $smarty->_unlink($_tname.$_extension, $params['exp_time']);
+            } else {
+                $_res = $smarty->_unlink($_tname, $params['exp_time']);
+            }
+        } elseif ($smarty->use_sub_dirs) {
+            $_params = array(
+                'dirname' => $_tname,
+                'level' => 1,
+                'exp_time' => $params['exp_time']
+            );
+            require_once(SMARTY_CORE_DIR . 'core.rmdir.php');
+            $_res = smarty_core_rmdir($_params, $smarty);
+        } else {
+            // remove matching file names
+            $_handle = opendir($params['auto_base']);
+            $_res = true;
+            while (false !== ($_filename = readdir($_handle))) {
+                if($_filename == '.' || $_filename == '..') {
+                    continue;
+                } elseif (substr($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, 0, strlen($_tname)) == $_tname) {
+                    $_res &= (bool)$smarty->_unlink($params['auto_base'] . DIRECTORY_SEPARATOR . $_filename, $params['exp_time']);
+                }
+            }
+        }
+    }
+
+    return $_res;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.rmdir.php b/bundled-libs/Smarty/libs/internals/core.rmdir.php
new file mode 100644 (file)
index 0000000..4fdbccc
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * delete a dir recursively (level=0 -> keep root)
+ * WARNING: no tests, it will try to remove what you tell it!
+ *
+ * @param string $dirname
+ * @param integer $level
+ * @param integer $exp_time
+ * @return boolean
+ */
+
+//  $dirname, $level = 1, $exp_time = null
+
+function smarty_core_rmdir($params, &$smarty)
+{
+   if(!isset($params['level'])) { $params['level'] = 1; }
+   if(!isset($params['exp_time'])) { $params['exp_time'] = null; }
+
+   if($_handle = @opendir($params['dirname'])) {
+
+        while (false !== ($_entry = readdir($_handle))) {
+            if ($_entry != '.' && $_entry != '..') {
+                if (@is_dir($params['dirname'] . DIRECTORY_SEPARATOR . $_entry)) {
+                    $_params = array(
+                        'dirname' => $params['dirname'] . DIRECTORY_SEPARATOR . $_entry,
+                        'level' => $params['level'] + 1,
+                        'exp_time' => $params['exp_time']
+                    );
+                    require_once(SMARTY_CORE_DIR . 'core.rmdir.php');
+                    smarty_core_rmdir($_params, $smarty);
+                }
+                else {
+                    $smarty->_unlink($params['dirname'] . DIRECTORY_SEPARATOR . $_entry, $params['exp_time']);
+                }
+            }
+        }
+        closedir($_handle);
+   }
+
+   if ($params['level']) {
+       return @rmdir($params['dirname']);
+   }
+   return (bool)$_handle;
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.run_insert_handler.php b/bundled-libs/Smarty/libs/internals/core.run_insert_handler.php
new file mode 100644 (file)
index 0000000..71c3845
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Handle insert tags
+ *
+ * @param array $args
+ * @return string
+ */
+function smarty_core_run_insert_handler($params, &$smarty)
+{
+
+    require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+    if ($smarty->debugging) {
+        $_params = array();
+        $_debug_start_time = smarty_core_get_microtime($_params, $smarty);
+    }
+
+    if ($smarty->caching) {
+        $_arg_string = serialize($params['args']);
+        $_name = $params['args']['name'];
+        if (!isset($smarty->_cache_info['insert_tags'][$_name])) {
+            $smarty->_cache_info['insert_tags'][$_name] = array('insert',
+                                                             $_name,
+                                                             $smarty->_plugins['insert'][$_name][1],
+                                                             $smarty->_plugins['insert'][$_name][2],
+                                                             !empty($params['args']['script']) ? true : false);
+        }
+        return $smarty->_smarty_md5."{insert_cache $_arg_string}".$smarty->_smarty_md5;
+    } else {
+        if (isset($params['args']['script'])) {
+            $_params = array('resource_name' => $smarty->_dequote($params['args']['script']));
+            require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php');
+            if(!smarty_core_get_php_resource($_params, $smarty)) {
+                return false;
+            }
+
+            if ($_params['resource_type'] == 'file') {
+                $smarty->_include($_params['php_resource'], true);
+            } else {
+                $smarty->_eval($_params['php_resource']);
+            }
+            unset($params['args']['script']);
+        }
+
+        $_funcname = $smarty->_plugins['insert'][$params['args']['name']][0];
+        $_content = $_funcname($params['args'], $smarty);
+        if ($smarty->debugging) {
+            $_params = array();
+            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+            $smarty->_smarty_debug_info[] = array('type'      => 'insert',
+                                                'filename'  => 'insert_'.$params['args']['name'],
+                                                'depth'     => $smarty->_inclusion_depth,
+                                                'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time);
+        }
+
+        if (!empty($params['args']["assign"])) {
+            $smarty->assign($params['args']["assign"], $_content);
+        } else {
+            return $_content;
+        }
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.smarty_include_php.php b/bundled-libs/Smarty/libs/internals/core.smarty_include_php.php
new file mode 100644 (file)
index 0000000..30c6e76
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * called for included php files within templates
+ *
+ * @param string $smarty_file
+ * @param string $smarty_assign variable to assign the included template's
+ *               output into
+ * @param boolean $smarty_once uses include_once if this is true
+ * @param array $smarty_include_vars associative array of vars from
+ *              {include file="blah" var=$var}
+ */
+
+//  $file, $assign, $once, $_smarty_include_vars
+
+function smarty_core_smarty_include_php($params, &$smarty)
+{
+    $_params = array('resource_name' => $params['smarty_file']);
+    require_once(SMARTY_CORE_DIR . 'core.get_php_resource.php');
+    smarty_core_get_php_resource($_params, $smarty);
+    $_smarty_resource_type = $_params['resource_type'];
+    $_smarty_php_resource = $_params['php_resource'];
+
+    if (!empty($params['smarty_assign'])) {
+        ob_start();
+        if ($_smarty_resource_type == 'file') {
+            $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']);
+        } else {
+            $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']);
+        }
+        $smarty->assign($params['smarty_assign'], ob_get_contents());
+        ob_end_clean();
+    } else {
+        if ($_smarty_resource_type == 'file') {
+            $smarty->_include($_smarty_php_resource, $params['smarty_once'], $params['smarty_include_vars']);
+        } else {
+            $smarty->_eval($_smarty_php_resource, $params['smarty_include_vars']);
+        }
+    }
+}
+
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.write_cache_file.php b/bundled-libs/Smarty/libs/internals/core.write_cache_file.php
new file mode 100644 (file)
index 0000000..72f785b
--- /dev/null
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Prepend the cache information to the cache file
+ * and write it
+ *
+ * @param string $tpl_file
+ * @param string $cache_id
+ * @param string $compile_id
+ * @param string $results
+ * @return true|null
+ */
+
+ // $tpl_file, $cache_id, $compile_id, $results
+
+function smarty_core_write_cache_file($params, &$smarty)
+{
+
+    // put timestamp in cache header
+    $smarty->_cache_info['timestamp'] = time();
+    if ($smarty->cache_lifetime > -1){
+        // expiration set
+        $smarty->_cache_info['expires'] = $smarty->_cache_info['timestamp'] + $smarty->cache_lifetime;
+    } else {
+        // cache will never expire
+        $smarty->_cache_info['expires'] = -1;
+    }
+
+    // collapse nocache.../nocache-tags
+    if (preg_match_all('!\{(/?)nocache\:[0-9a-f]{32}#\d+\}!', $params['results'], $match, PREG_PATTERN_ORDER)) {
+        // remove everything between every pair of outermost noache.../nocache-tags
+        // and replace it by a single nocache-tag
+        // this new nocache-tag will be replaced by dynamic contents in
+        // smarty_core_process_compiled_includes() on a cache-read
+        
+        $match_count = count($match[0]);
+        $results = preg_split('!(\{/?nocache\:[0-9a-f]{32}#\d+\})!', $params['results'], -1, PREG_SPLIT_DELIM_CAPTURE);
+        
+        $level = 0;
+        $j = 0;
+        for ($i=0, $results_count = count($results); $i < $results_count && $j < $match_count; $i++) {
+            if ($results[$i] == $match[0][$j]) {
+                // nocache tag
+                if ($match[1][$j]) { // closing tag
+                    $level--;
+                    unset($results[$i]);
+                } else { // opening tag
+                    if ($level++ > 0) unset($results[$i]);
+                }
+                $j++;
+            } elseif ($level > 0) {
+                unset($results[$i]);
+            }
+        }
+        $params['results'] = implode('', $results);
+    }
+    $smarty->_cache_info['cache_serials'] = $smarty->_cache_serials;
+
+    // prepend the cache header info into cache file
+    $_cache_info = serialize($smarty->_cache_info);
+    $params['results'] = strlen($_cache_info) . "\n" . $_cache_info . $params['results'];
+
+    if (!empty($smarty->cache_handler_func)) {
+        // use cache_handler function
+        call_user_func_array($smarty->cache_handler_func,
+                             array('write', &$smarty, &$params['results'], $params['tpl_file'], $params['cache_id'], $params['compile_id'], null));
+    } else {
+        // use local cache file
+
+        if(!@is_writable($smarty->cache_dir)) {
+            // cache_dir not writable, see if it exists
+            if(!@is_dir($smarty->cache_dir)) {
+                $smarty->trigger_error('the $cache_dir \'' . $smarty->cache_dir . '\' does not exist, or is not a directory.', E_USER_ERROR);
+                return false;
+            }
+            $smarty->trigger_error('unable to write to $cache_dir \'' . realpath($smarty->cache_dir) . '\'. Be sure $cache_dir is writable by the web server user.', E_USER_ERROR);
+            return false;
+        }
+
+        $_auto_id = $smarty->_get_auto_id($params['cache_id'], $params['compile_id']);
+        $_cache_file = $smarty->_get_auto_filename($smarty->cache_dir, $params['tpl_file'], $_auto_id);
+        $_params = array('filename' => $_cache_file, 'contents' => $params['results'], 'create_dirs' => true);
+        require_once(SMARTY_CORE_DIR . 'core.write_file.php');
+        smarty_core_write_file($_params, $smarty);
+        return true;
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.write_compiled_include.php b/bundled-libs/Smarty/libs/internals/core.write_compiled_include.php
new file mode 100644 (file)
index 0000000..5e0b2e0
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Extract non-cacheable parts out of compiled template and write it
+ *
+ * @param string $compile_path
+ * @param string $template_compiled
+ * @return boolean
+ */
+
+function smarty_core_write_compiled_include($params, &$smarty)
+{
+    $_tag_start = 'if \(\$this->caching && \!\$this->_cache_including\) \{ echo \'\{nocache\:('.$params['cache_serial'].')#(\d+)\}\';\}';
+    $_tag_end   = 'if \(\$this->caching && \!\$this->_cache_including\) \{ echo \'\{/nocache\:(\\2)#(\\3)\}\';\}';
+
+    preg_match_all('!('.$_tag_start.'(.*)'.$_tag_end.')!Us',
+                   $params['compiled_content'], $_match_source, PREG_SET_ORDER);
+
+    // no nocache-parts found: done
+    if (count($_match_source)==0) return;
+
+    // convert the matched php-code to functions
+    $_include_compiled =  "<?php /* Smarty version ".$smarty->_version.", created on ".strftime("%Y-%m-%d %H:%M:%S")."\n";
+    $_include_compiled .= "         compiled from " . strtr(urlencode($params['resource_name']), array('%2F'=>'/', '%3A'=>':')) . " */\n\n";
+
+    $_compile_path = $params['include_file_path'];
+
+    $smarty->_cache_serials[$_compile_path] = $params['cache_serial'];
+    $_include_compiled .= "\$this->_cache_serials['".$_compile_path."'] = '".$params['cache_serial']."';\n\n?>";
+
+    $_include_compiled .= $params['plugins_code'];
+    $_include_compiled .= "<?php";
+
+    $this_varname = ((double)phpversion() >= 5.0) ? '_smarty' : 'this';
+    for ($_i = 0, $_for_max = count($_match_source); $_i < $_for_max; $_i++) {
+        $_match =& $_match_source[$_i];
+        $source = $_match[4];
+        if ($this_varname == '_smarty') {
+            /* rename $this to $_smarty in the sourcecode */
+            $tokens = token_get_all('<?php ' . $_match[4]);
+
+            /* remove trailing <?php */
+            $open_tag = '';
+            while ($tokens) {
+                $token = array_shift($tokens);
+                if (is_array($token)) {
+                    $open_tag .= $token[1];
+                } else {
+                    $open_tag .= $token;
+                }
+                if ($open_tag == '<?php ') break;
+            }
+
+            for ($i=0, $count = count($tokens); $i < $count; $i++) {
+                if (is_array($tokens[$i])) {
+                    if ($tokens[$i][0] == T_VARIABLE && $tokens[$i][1] == '$this') {
+                        $tokens[$i] = '$' . $this_varname;
+                    } else {
+                        $tokens[$i] = $tokens[$i][1];
+                    }                   
+                }
+            }
+            $source = implode('', $tokens);
+        }
+
+        /* add function to compiled include */
+        $_include_compiled .= "
+function _smarty_tplfunc_$_match[2]_$_match[3](&\$$this_varname)
+{
+$source
+}
+
+";
+    }
+    $_include_compiled .= "\n\n?>\n";
+
+    $_params = array('filename' => $_compile_path,
+                     'contents' => $_include_compiled, 'create_dirs' => true);
+
+    require_once(SMARTY_CORE_DIR . 'core.write_file.php');
+    smarty_core_write_file($_params, $smarty);
+    return true;
+}
+
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.write_compiled_resource.php b/bundled-libs/Smarty/libs/internals/core.write_compiled_resource.php
new file mode 100644 (file)
index 0000000..b902eff
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * write the compiled resource
+ *
+ * @param string $compile_path
+ * @param string $compiled_content
+ * @return true
+ */
+function smarty_core_write_compiled_resource($params, &$smarty)
+{
+    if(!@is_writable($smarty->compile_dir)) {
+        // compile_dir not writable, see if it exists
+        if(!@is_dir($smarty->compile_dir)) {
+            $smarty->trigger_error('the $compile_dir \'' . $smarty->compile_dir . '\' does not exist, or is not a directory.', E_USER_ERROR);
+            return false;
+        }
+        $smarty->trigger_error('unable to write to $compile_dir \'' . realpath($smarty->compile_dir) . '\'. Be sure $compile_dir is writable by the web server user.', E_USER_ERROR);
+        return false;
+    }
+
+    $_params = array('filename' => $params['compile_path'], 'contents' => $params['compiled_content'], 'create_dirs' => true);
+    require_once(SMARTY_CORE_DIR . 'core.write_file.php');
+    smarty_core_write_file($_params, $smarty);
+    return true;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/internals/core.write_file.php b/bundled-libs/Smarty/libs/internals/core.write_file.php
new file mode 100644 (file)
index 0000000..09e1698
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * write out a file to disk
+ *
+ * @param string $filename
+ * @param string $contents
+ * @param boolean $create_dirs
+ * @return boolean
+ */
+function smarty_core_write_file($params, &$smarty)
+{
+    $_dirname = dirname($params['filename']);
+
+    if ($params['create_dirs']) {
+        $_params = array('dir' => $_dirname);
+        require_once(SMARTY_CORE_DIR . 'core.create_dir_structure.php');
+        smarty_core_create_dir_structure($_params, $smarty);
+    }
+
+    // write to tmp file, then rename it to avoid
+    // file locking race condition
+    $_tmp_file = tempnam($_dirname, 'wrt');
+
+    if (!($fd = @fopen($_tmp_file, 'wb'))) {
+        $_tmp_file = $_dirname . DIRECTORY_SEPARATOR . uniqid('wrt');
+        if (!($fd = @fopen($_tmp_file, 'wb'))) {
+            $smarty->trigger_error("problem writing temporary file '$_tmp_file'");
+            return false;
+        }
+    }
+
+    fwrite($fd, $params['contents']);
+    fclose($fd);
+
+    // Delete the file if it allready exists (this is needed on Win,
+    // because it cannot overwrite files with rename()
+    if (file_exists($params['filename'])) {
+        @unlink($params['filename']);
+    }
+    @rename($_tmp_file, $params['filename']);
+    @chmod($params['filename'], $smarty->_file_perms);
+
+    return true;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/block.textformat.php b/bundled-libs/Smarty/libs/plugins/block.textformat.php
new file mode 100644 (file)
index 0000000..aaebab2
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {textformat}{/textformat} block plugin
+ *
+ * Type:     block function<br>
+ * Name:     textformat<br>
+ * Purpose:  format text a certain way with preset styles
+ *           or custom wrap/indent settings<br>
+ * @link http://smarty.php.net/manual/en/language.function.textformat.php {textformat}
+ *       (Smarty online manual)
+ * @param array
+ * <pre>
+ * Params:   style: string (email)
+ *           indent: integer (0)
+ *           wrap: integer (80)
+ *           wrap_char string ("\n")
+ *           indent_char: string (" ")
+ *           wrap_boundary: boolean (true)
+ * </pre>
+ * @param string contents of the block
+ * @param Smarty clever simulation of a method
+ * @return string string $content re-formatted
+ */
+function smarty_block_textformat($params, $content, &$smarty)
+{
+    if (is_null($content)) {
+        return;
+    }
+
+    $style = null;
+    $indent = 0;
+    $indent_first = 0;
+    $indent_char = ' ';
+    $wrap = 80;
+    $wrap_char = "\n";
+    $wrap_cut = false;
+    $assign = null;
+    
+    foreach ($params as $_key => $_val) {
+        switch ($_key) {
+            case 'style':
+            case 'indent_char':
+            case 'wrap_char':
+            case 'assign':
+                $$_key = (string)$_val;
+                break;
+
+            case 'indent':
+            case 'indent_first':
+            case 'wrap':
+                $$_key = (int)$_val;
+                break;
+
+            case 'wrap_cut':
+                $$_key = (bool)$_val;
+                break;
+
+            default:
+                $smarty->trigger_error("textformat: unknown attribute '$_key'");
+        }
+    }
+
+    if ($style == 'email') {
+        $wrap = 72;
+    }
+
+    // split into paragraphs
+    $_paragraphs = preg_split('![\r\n][\r\n]!',$content);
+    $_output = '';
+
+    for($_x = 0, $_y = count($_paragraphs); $_x < $_y; $_x++) {
+        if ($_paragraphs[$_x] == '') {
+            continue;
+        }
+        // convert mult. spaces & special chars to single space
+        $_paragraphs[$_x] = preg_replace(array('!\s+!','!(^\s+)|(\s+$)!'), array(' ',''), $_paragraphs[$_x]);
+        // indent first line
+        if($indent_first > 0) {
+            $_paragraphs[$_x] = str_repeat($indent_char, $indent_first) . $_paragraphs[$_x];
+        }
+        // wordwrap sentences
+        $_paragraphs[$_x] = wordwrap($_paragraphs[$_x], $wrap - $indent, $wrap_char, $wrap_cut);
+        // indent lines
+        if($indent > 0) {
+            $_paragraphs[$_x] = preg_replace('!^!m', str_repeat($indent_char, $indent), $_paragraphs[$_x]);
+        }
+    }
+    $_output = implode($wrap_char . $wrap_char, $_paragraphs);
+
+    return $assign ? $smarty->assign($assign, $_output) : $_output;
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/compiler.assign.php b/bundled-libs/Smarty/libs/plugins/compiler.assign.php
new file mode 100644 (file)
index 0000000..2e02017
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {assign} compiler function plugin
+ *
+ * Type:     compiler function<br>
+ * Name:     assign<br>
+ * Purpose:  assign a value to a template variable
+ * @link http://smarty.php.net/manual/en/language.custom.functions.php#LANGUAGE.FUNCTION.ASSIGN {assign}
+ *       (Smarty online manual)
+ * @param string containing var-attribute and value-attribute
+ * @param Smarty_Compiler
+ */
+function smarty_compiler_assign($tag_attrs, &$compiler)
+{
+    $_params = $compiler->_parse_attrs($tag_attrs);
+
+    if (!isset($_params['var'])) {
+        $compiler->_syntax_error("assign: missing 'var' parameter", E_USER_WARNING);
+        return;
+    }
+
+    if (!isset($_params['value'])) {
+        $compiler->_syntax_error("assign: missing 'value' parameter", E_USER_WARNING);
+        return;
+    }
+
+    return "\$this->assign({$_params['var']}, {$_params['value']});";
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.assign_debug_info.php b/bundled-libs/Smarty/libs/plugins/function.assign_debug_info.php
new file mode 100644 (file)
index 0000000..8015624
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {assign_debug_info} function plugin
+ *
+ * Type:     function<br>
+ * Name:     assign_debug_info<br>
+ * Purpose:  assign debug info to the template<br>
+ * @param array unused in this plugin, this plugin uses {@link Smarty::$_config},
+ *              {@link Smarty::$_tpl_vars} and {@link Smarty::$_smarty_debug_info}
+ * @param Smarty
+ */
+function smarty_function_assign_debug_info($params, &$smarty)
+{
+    $assigned_vars = $smarty->_tpl_vars;
+    ksort($assigned_vars);
+    if (@is_array($smarty->_config[0])) {
+        $config_vars = $smarty->_config[0];
+        ksort($config_vars);
+        $smarty->assign("_debug_config_keys", array_keys($config_vars));
+        $smarty->assign("_debug_config_vals", array_values($config_vars));
+    }
+    
+    $included_templates = $smarty->_smarty_debug_info;
+    
+    $smarty->assign("_debug_keys", array_keys($assigned_vars));
+    $smarty->assign("_debug_vals", array_values($assigned_vars));
+    
+    $smarty->assign("_debug_tpls", $included_templates);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.config_load.php b/bundled-libs/Smarty/libs/plugins/function.config_load.php
new file mode 100644 (file)
index 0000000..db7f8f6
--- /dev/null
@@ -0,0 +1,140 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {config_load} function plugin
+ *
+ * Type:     function<br>
+ * Name:     config_load<br>
+ * Purpose:  load config file vars
+ * @link http://smarty.php.net/manual/en/language.function.config.load.php {config_load}
+ *       (Smarty online manual)
+ * @param array Format:
+ * <pre>
+ * array('file' => required config file name,
+ *       'section' => optional config file section to load
+ *       'scope' => local/parent/global
+ *       'global' => overrides scope, setting to parent if true)
+ * </pre>
+ * @param Smarty
+ */
+function smarty_function_config_load($params, &$smarty)
+{
+        if ($smarty->debugging) {
+            $_params = array();
+            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+            $_debug_start_time = smarty_core_get_microtime($_params, $smarty);
+        }
+
+        $_file = isset($params['file']) ? $smarty->_dequote($params['file']) : null;
+        $_section = isset($params['section']) ? $smarty->_dequote($params['section']) : null;
+        $_scope = isset($params['scope']) ? $smarty->_dequote($params['scope']) : 'global';
+        $_global = isset($params['global']) ? $smarty->_dequote($params['global']) : false;
+
+        if (!isset($_file) || strlen($_file) == 0) {
+            $smarty->trigger_error("missing 'file' attribute in config_load tag", E_USER_ERROR, __FILE__, __LINE__);
+        }
+
+        if (isset($_scope)) {
+            if ($_scope != 'local' &&
+                $_scope != 'parent' &&
+                $_scope != 'global') {
+                $smarty->trigger_error("invalid 'scope' attribute value", E_USER_ERROR, __FILE__, __LINE__);
+            }
+        } else {
+            if ($_global) {
+                $_scope = 'parent';
+            } else {
+                $_scope = 'local';
+            }
+        }
+
+        $_params = array('resource_name' => $_file,
+                         'resource_base_path' => $smarty->config_dir,
+                         'get_source' => false);
+        $smarty->_parse_resource_name($_params);
+        $_file_path = $_params['resource_type'] . ':' . $_params['resource_name'];
+        if (isset($_section))
+            $_compile_file = $smarty->_get_compile_path($_file_path.'|'.$_section);
+        else
+            $_compile_file = $smarty->_get_compile_path($_file_path);
+
+        if($smarty->force_compile || !file_exists($_compile_file)) {
+            $_compile = true;
+        } elseif ($smarty->compile_check) {
+            $_params = array('resource_name' => $_file,
+                             'resource_base_path' => $smarty->config_dir,
+                             'get_source' => false);
+            $_compile = $smarty->_fetch_resource_info($_params) &&
+                $_params['resource_timestamp'] > filemtime($_compile_file);
+        } else {
+            $_compile = false;
+        }
+
+        if($_compile) {
+            // compile config file
+            if(!is_object($smarty->_conf_obj)) {
+                require_once SMARTY_DIR . $smarty->config_class . '.class.php';
+                $smarty->_conf_obj = new $smarty->config_class();
+                $smarty->_conf_obj->overwrite = $smarty->config_overwrite;
+                $smarty->_conf_obj->booleanize = $smarty->config_booleanize;
+                $smarty->_conf_obj->read_hidden = $smarty->config_read_hidden;
+                $smarty->_conf_obj->fix_newlines = $smarty->config_fix_newlines;
+            }
+
+            $_params = array('resource_name' => $_file,
+                             'resource_base_path' => $smarty->config_dir,
+                             $_params['get_source'] = true);
+            if (!$smarty->_fetch_resource_info($_params)) {
+                return;
+            }
+            $smarty->_conf_obj->set_file_contents($_file, $_params['source_content']);
+            $_config_vars = array_merge($smarty->_conf_obj->get($_file),
+                    $smarty->_conf_obj->get($_file, $_section));
+            if(function_exists('var_export')) {
+                $_output = '<?php $_config_vars = ' . var_export($_config_vars, true) . '; ?>';
+            } else {
+                $_output = '<?php $_config_vars = unserialize(\'' . strtr(serialize($_config_vars),array('\''=>'\\\'', '\\'=>'\\\\')) . '\'); ?>';
+            }
+            $_params = (array('compile_path' => $_compile_file, 'compiled_content' => $_output, 'resource_timestamp' => $_params['resource_timestamp']));
+            require_once(SMARTY_CORE_DIR . 'core.write_compiled_resource.php');
+            smarty_core_write_compiled_resource($_params, $smarty);
+        } else {
+            include($_compile_file);
+        }
+
+        if ($smarty->caching) {
+            $smarty->_cache_info['config'][$_file] = true;
+        }
+
+        $smarty->_config[0]['vars'] = @array_merge($smarty->_config[0]['vars'], $_config_vars);
+        $smarty->_config[0]['files'][$_file] = true;
+
+        if ($_scope == 'parent') {
+                $smarty->_config[1]['vars'] = @array_merge($smarty->_config[1]['vars'], $_config_vars);
+                $smarty->_config[1]['files'][$_file] = true;
+        } else if ($_scope == 'global') {
+            for ($i = 1, $for_max = count($smarty->_config); $i < $for_max; $i++) {
+                $smarty->_config[$i]['vars'] = @array_merge($smarty->_config[$i]['vars'], $_config_vars);
+                $smarty->_config[$i]['files'][$_file] = true;
+            }
+        }
+
+        if ($smarty->debugging) {
+            $_params = array();
+            require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
+            $smarty->_smarty_debug_info[] = array('type'      => 'config',
+                                                'filename'  => $_file.' ['.$_section.'] '.$_scope,
+                                                'depth'     => $smarty->_inclusion_depth,
+                                                'exec_time' => smarty_core_get_microtime($_params, $smarty) - $_debug_start_time);
+        }
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.counter.php b/bundled-libs/Smarty/libs/plugins/function.counter.php
new file mode 100644 (file)
index 0000000..cfe5dd8
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {counter} function plugin
+ *
+ * Type:     function<br>
+ * Name:     counter<br>
+ * Purpose:  print out a counter value
+ * @link http://smarty.php.net/manual/en/language.function.counter.php {counter}
+ *       (Smarty online manual)
+ * @param array parameters
+ * @param Smarty
+ * @return string|null
+ */
+function smarty_function_counter($params, &$smarty)
+{
+    static $counters = array();
+
+    $name = (isset($params['name'])) ? $params['name'] : 'default';
+    if (!isset($counters[$name])) {
+        $counters[$name] = array(
+            'start'=>1,
+            'skip'=>1,
+            'direction'=>'up',
+            'count'=>1
+            );
+    }
+    $counter =& $counters[$name];
+
+    if (isset($params['start'])) {
+        $counter['start'] = $counter['count'] = (int)$params['start'];
+    }
+
+    if (!empty($params['assign'])) {
+        $counter['assign'] = $params['assign'];
+    }
+
+    if (isset($counter['assign'])) {
+        $smarty->assign($counter['assign'], $counter['count']);
+    }
+    
+    if (isset($params['print'])) {
+        $print = (bool)$params['print'];
+    } else {
+        $print = empty($counter['assign']);
+    }
+
+    if ($print) {
+        $retval = $counter['count'];
+    } else {
+        $retval = null;
+    }
+
+    if (isset($params['skip'])) {
+        $counter['skip'] = $params['skip'];
+    }
+    
+    if (isset($params['direction'])) {
+        $counter['direction'] = $params['direction'];
+    }
+
+    if ($counter['direction'] == "down")
+        $counter['count'] -= $counter['skip'];
+    else
+        $counter['count'] += $counter['skip'];
+    
+    return $retval;
+    
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.cycle.php b/bundled-libs/Smarty/libs/plugins/function.cycle.php
new file mode 100644 (file)
index 0000000..fe78bb8
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {cycle} function plugin
+ *
+ * Type:     function<br>
+ * Name:     cycle<br>
+ * Date:     May 3, 2002<br>
+ * Purpose:  cycle through given values<br>
+ * Input:
+ *         - name = name of cycle (optional)
+ *         - values = comma separated list of values to cycle,
+ *                    or an array of values to cycle
+ *                    (this can be left out for subsequent calls)
+ *         - reset = boolean - resets given var to true
+ *         - print = boolean - print var or not. default is true
+ *         - advance = boolean - whether or not to advance the cycle
+ *         - delimiter = the value delimiter, default is ","
+ *         - assign = boolean, assigns to template var instead of
+ *                    printed.
+ *
+ * Examples:<br>
+ * <pre>
+ * {cycle values="#eeeeee,#d0d0d0d"}
+ * {cycle name=row values="one,two,three" reset=true}
+ * {cycle name=row}
+ * </pre>
+ * @link http://smarty.php.net/manual/en/language.function.cycle.php {cycle}
+ *       (Smarty online manual)
+ * @author Monte Ohrt <monte at ohrt dot com>
+ * @author credit to Mark Priatel <mpriatel@rogers.com>
+ * @author credit to Gerard <gerard@interfold.com>
+ * @author credit to Jason Sweat <jsweat_php@yahoo.com>
+ * @version  1.3
+ * @param array
+ * @param Smarty
+ * @return string|null
+ */
+function smarty_function_cycle($params, &$smarty)
+{
+    static $cycle_vars;
+    
+    $name = (empty($params['name'])) ? 'default' : $params['name'];
+    $print = (isset($params['print'])) ? (bool)$params['print'] : true;
+    $advance = (isset($params['advance'])) ? (bool)$params['advance'] : true;
+    $reset = (isset($params['reset'])) ? (bool)$params['reset'] : false;
+            
+    if (!in_array('values', array_keys($params))) {
+        if(!isset($cycle_vars[$name]['values'])) {
+            $smarty->trigger_error("cycle: missing 'values' parameter");
+            return;
+        }
+    } else {
+        if(isset($cycle_vars[$name]['values'])
+            && $cycle_vars[$name]['values'] != $params['values'] ) {
+            $cycle_vars[$name]['index'] = 0;
+        }
+        $cycle_vars[$name]['values'] = $params['values'];
+    }
+
+    $cycle_vars[$name]['delimiter'] = (isset($params['delimiter'])) ? $params['delimiter'] : ',';
+    
+    if(is_array($cycle_vars[$name]['values'])) {
+        $cycle_array = $cycle_vars[$name]['values'];
+    } else {
+        $cycle_array = explode($cycle_vars[$name]['delimiter'],$cycle_vars[$name]['values']);
+    }
+    
+    if(!isset($cycle_vars[$name]['index']) || $reset ) {
+        $cycle_vars[$name]['index'] = 0;
+    }
+    
+    if (isset($params['assign'])) {
+        $print = false;
+        $smarty->assign($params['assign'], $cycle_array[$cycle_vars[$name]['index']]);
+    }
+        
+    if($print) {
+        $retval = $cycle_array[$cycle_vars[$name]['index']];
+    } else {
+        $retval = null;
+    }
+
+    if($advance) {
+        if ( $cycle_vars[$name]['index'] >= count($cycle_array) -1 ) {
+            $cycle_vars[$name]['index'] = 0;
+        } else {
+            $cycle_vars[$name]['index']++;
+        }
+    }
+    
+    return $retval;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.debug.php b/bundled-libs/Smarty/libs/plugins/function.debug.php
new file mode 100644 (file)
index 0000000..4345230
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {debug} function plugin
+ *
+ * Type:     function<br>
+ * Name:     debug<br>
+ * Date:     July 1, 2002<br>
+ * Purpose:  popup debug window
+ * @link http://smarty.php.net/manual/en/language.function.debug.php {debug}
+ *       (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @version  1.0
+ * @param array
+ * @param Smarty
+ * @return string output from {@link Smarty::_generate_debug_output()}
+ */
+function smarty_function_debug($params, &$smarty)
+{
+    if (isset($params['output'])) {
+        $smarty->assign('_smarty_debug_output', $params['output']);
+    }
+    require_once(SMARTY_CORE_DIR . 'core.display_debug_console.php');
+    return smarty_core_display_debug_console(null, $smarty);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.eval.php b/bundled-libs/Smarty/libs/plugins/function.eval.php
new file mode 100644 (file)
index 0000000..3a4b8b2
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {eval} function plugin
+ *
+ * Type:     function<br>
+ * Name:     eval<br>
+ * Purpose:  evaluate a template variable as a template<br>
+ * @link http://smarty.php.net/manual/en/language.function.eval.php {eval}
+ *       (Smarty online manual)
+ * @param array
+ * @param Smarty
+ */
+function smarty_function_eval($params, &$smarty)
+{
+
+    if (!isset($params['var'])) {
+        $smarty->trigger_error("eval: missing 'var' parameter");
+        return;
+    }
+
+    if($params['var'] == '') {
+        return;
+    }
+
+    $smarty->_compile_source('evaluated template', $params['var'], $_var_compiled);
+
+    ob_start();
+    $smarty->_eval('?>' . $_var_compiled);
+    $_contents = ob_get_contents();
+    ob_end_clean();
+
+    if (!empty($params['assign'])) {
+        $smarty->assign($params['assign'], $_contents);
+    } else {
+        return $_contents;
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.fetch.php b/bundled-libs/Smarty/libs/plugins/function.fetch.php
new file mode 100644 (file)
index 0000000..f5a6987
--- /dev/null
@@ -0,0 +1,220 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {fetch} plugin
+ *
+ * Type:     function<br>
+ * Name:     fetch<br>
+ * Purpose:  fetch file, web or ftp data and display results
+ * @link http://smarty.php.net/manual/en/language.function.fetch.php {fetch}
+ *       (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string|null if the assign parameter is passed, Smarty assigns the
+ *                     result to a template variable
+ */
+function smarty_function_fetch($params, &$smarty)
+{
+    if (empty($params['file'])) {
+        $smarty->_trigger_fatal_error("[plugin] parameter 'file' cannot be empty");
+        return;
+    }
+
+    $content = '';
+    if ($smarty->security && !preg_match('!^(http|ftp)://!i', $params['file'])) {
+        $_params = array('resource_type' => 'file', 'resource_name' => $params['file']);
+        require_once(SMARTY_CORE_DIR . 'core.is_secure.php');
+        if(!smarty_core_is_secure($_params, $smarty)) {
+            $smarty->_trigger_fatal_error('[plugin] (secure mode) fetch \'' . $params['file'] . '\' is not allowed');
+            return;
+        }
+        
+        // fetch the file
+        if($fp = @fopen($params['file'],'r')) {
+            while(!feof($fp)) {
+                $content .= fgets ($fp,4096);
+            }
+            fclose($fp);
+        } else {
+            $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] . '\'');
+            return;
+        }
+    } else {
+        // not a local file
+        if(preg_match('!^http://!i',$params['file'])) {
+            // http fetch
+            if($uri_parts = parse_url($params['file'])) {
+                // set defaults
+                $host = $server_name = $uri_parts['host'];
+                $timeout = 30;
+                $accept = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*";
+                $agent = "Smarty Template Engine ".$smarty->_version;
+                $referer = "";
+                $uri = !empty($uri_parts['path']) ? $uri_parts['path'] : '/';
+                $uri .= !empty($uri_parts['query']) ? '?' . $uri_parts['query'] : '';
+                $_is_proxy = false;
+                if(empty($uri_parts['port'])) {
+                    $port = 80;
+                } else {
+                    $port = $uri_parts['port'];
+                }
+                if(!empty($uri_parts['user'])) {
+                    $user = $uri_parts['user'];
+                }
+                if(!empty($uri_parts['pass'])) {
+                    $pass = $uri_parts['pass'];
+                }
+                // loop through parameters, setup headers
+                foreach($params as $param_key => $param_value) {
+                    switch($param_key) {
+                        case "file":
+                        case "assign":
+                        case "assign_headers":
+                            break;
+                        case "user":
+                            if(!empty($param_value)) {
+                                $user = $param_value;
+                            }
+                            break;
+                        case "pass":
+                            if(!empty($param_value)) {
+                                $pass = $param_value;
+                            }
+                            break;
+                        case "accept":
+                            if(!empty($param_value)) {
+                                $accept = $param_value;
+                            }
+                            break;
+                        case "header":
+                            if(!empty($param_value)) {
+                                if(!preg_match('![\w\d-]+: .+!',$param_value)) {
+                                    $smarty->_trigger_fatal_error("[plugin] invalid header format '".$param_value."'");
+                                    return;
+                                } else {
+                                    $extra_headers[] = $param_value;
+                                }
+                            }
+                            break;
+                        case "proxy_host":
+                            if(!empty($param_value)) {
+                                $proxy_host = $param_value;
+                            }
+                            break;
+                        case "proxy_port":
+                            if(!preg_match('!\D!', $param_value)) {
+                                $proxy_port = (int) $param_value;
+                            } else {
+                                $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'");
+                                return;
+                            }
+                            break;
+                        case "agent":
+                            if(!empty($param_value)) {
+                                $agent = $param_value;
+                            }
+                            break;
+                        case "referer":
+                            if(!empty($param_value)) {
+                                $referer = $param_value;
+                            }
+                            break;
+                        case "timeout":
+                            if(!preg_match('!\D!', $param_value)) {
+                                $timeout = (int) $param_value;
+                            } else {
+                                $smarty->_trigger_fatal_error("[plugin] invalid value for attribute '".$param_key."'");
+                                return;
+                            }
+                            break;
+                        default:
+                            $smarty->_trigger_fatal_error("[plugin] unrecognized attribute '".$param_key."'");
+                            return;
+                    }
+                }
+                if(!empty($proxy_host) && !empty($proxy_port)) {
+                    $_is_proxy = true;
+                    $fp = fsockopen($proxy_host,$proxy_port,$errno,$errstr,$timeout);
+                } else {
+                    $fp = fsockopen($server_name,$port,$errno,$errstr,$timeout);
+                }
+
+                if(!$fp) {
+                    $smarty->_trigger_fatal_error("[plugin] unable to fetch: $errstr ($errno)");
+                    return;
+                } else {
+                    if($_is_proxy) {
+                        fputs($fp, 'GET ' . $params['file'] . " HTTP/1.0\r\n");
+                    } else {
+                        fputs($fp, "GET $uri HTTP/1.0\r\n");
+                    }
+                    if(!empty($host)) {
+                        fputs($fp, "Host: $host\r\n");
+                    }
+                    if(!empty($accept)) {
+                        fputs($fp, "Accept: $accept\r\n");
+                    }
+                    if(!empty($agent)) {
+                        fputs($fp, "User-Agent: $agent\r\n");
+                    }
+                    if(!empty($referer)) {
+                        fputs($fp, "Referer: $referer\r\n");
+                    }
+                    if(isset($extra_headers) && is_array($extra_headers)) {
+                        foreach($extra_headers as $curr_header) {
+                            fputs($fp, $curr_header."\r\n");
+                        }
+                    }
+                    if(!empty($user) && !empty($pass)) {
+                        fputs($fp, "Authorization: BASIC ".base64_encode("$user:$pass")."\r\n");
+                    }
+
+                    fputs($fp, "\r\n");
+                    while(!feof($fp)) {
+                        $content .= fgets($fp,4096);
+                    }
+                    fclose($fp);
+                    $csplit = split("\r\n\r\n",$content,2);
+
+                    $content = $csplit[1];
+
+                    if(!empty($params['assign_headers'])) {
+                        $smarty->assign($params['assign_headers'],split("\r\n",$csplit[0]));
+                    }
+                }
+            } else {
+                $smarty->_trigger_fatal_error("[plugin] unable to parse URL, check syntax");
+                return;
+            }
+        } else {
+            // ftp fetch
+            if($fp = @fopen($params['file'],'r')) {
+                while(!feof($fp)) {
+                    $content .= fgets ($fp,4096);
+                }
+                fclose($fp);
+            } else {
+                $smarty->_trigger_fatal_error('[plugin] fetch cannot read file \'' . $params['file'] .'\'');
+                return;
+            }
+        }
+
+    }
+
+
+    if (!empty($params['assign'])) {
+        $smarty->assign($params['assign'],$content);
+    } else {
+        return $content;
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.html_checkboxes.php b/bundled-libs/Smarty/libs/plugins/function.html_checkboxes.php
new file mode 100644 (file)
index 0000000..ed8ad7f
--- /dev/null
@@ -0,0 +1,143 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_checkboxes} function plugin
+ *
+ * File:       function.html_checkboxes.php<br>
+ * Type:       function<br>
+ * Name:       html_checkboxes<br>
+ * Date:       24.Feb.2003<br>
+ * Purpose:    Prints out a list of checkbox input types<br>
+ * Input:<br>
+ *           - name       (optional) - string default "checkbox"
+ *           - values     (required) - array
+ *           - options    (optional) - associative array
+ *           - checked    (optional) - array default not set
+ *           - separator  (optional) - ie <br> or &nbsp;
+ *           - output     (optional) - the output next to each checkbox
+ *           - assign     (optional) - assign the output as an array to this variable
+ * Examples:
+ * <pre>
+ * {html_checkboxes values=$ids output=$names}
+ * {html_checkboxes values=$ids name='box' separator='<br>' output=$names}
+ * {html_checkboxes values=$ids checked=$checked separator='<br>' output=$names}
+ * </pre>
+ * @link http://smarty.php.net/manual/en/language.function.html.checkboxes.php {html_checkboxes}
+ *      (Smarty online manual)
+ * @author     Christopher Kvarme <christopher.kvarme@flashjab.com>
+ * @author credits to Monte Ohrt <monte at ohrt dot com>
+ * @version    1.0
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_checkboxes($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
+
+    $name = 'checkbox';
+    $values = null;
+    $options = null;
+    $selected = null;
+    $separator = '';
+    $labels = true;
+    $output = null;
+
+    $extra = '';
+
+    foreach($params as $_key => $_val) {
+        switch($_key) {
+            case 'name':
+            case 'separator':
+                $$_key = $_val;
+                break;
+
+            case 'labels':
+                $$_key = (bool)$_val;
+                break;
+
+            case 'options':
+                $$_key = (array)$_val;
+                break;
+
+            case 'values':
+            case 'output':
+                $$_key = array_values((array)$_val);
+                break;
+
+            case 'checked':
+            case 'selected':
+                $selected = array_map('strval', array_values((array)$_val));
+                break;
+
+            case 'checkboxes':
+                $smarty->trigger_error('html_checkboxes: the use of the "checkboxes" attribute is deprecated, use "options" instead', E_USER_WARNING);
+                $options = (array)$_val;
+                break;
+
+            case 'assign':
+                break;
+
+            default:
+                if(!is_array($_val)) {
+                    $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
+                } else {
+                    $smarty->trigger_error("html_checkboxes: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (!isset($options) && !isset($values))
+        return ''; /* raise error here? */
+
+    settype($selected, 'array');
+    $_html_result = array();
+
+    if (isset($options)) {
+
+        foreach ($options as $_key=>$_val)
+            $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
+
+
+    } else {
+        foreach ($values as $_i=>$_key) {
+            $_val = isset($output[$_i]) ? $output[$_i] : '';
+            $_html_result[] = smarty_function_html_checkboxes_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
+        }
+
+    }
+
+    if(!empty($params['assign'])) {
+        $smarty->assign($params['assign'], $_html_result);
+    } else {
+        return implode("\n",$_html_result);
+    }
+
+}
+
+function smarty_function_html_checkboxes_output($name, $value, $output, $selected, $extra, $separator, $labels) {
+    $_output = '';
+    if ($labels) $_output .= '<label>';
+    $_output .= '<input type="checkbox" name="'
+        . smarty_function_escape_special_chars($name) . '[]" value="'
+        . smarty_function_escape_special_chars($value) . '"';
+
+    if (in_array((string)$value, $selected)) {
+        $_output .= ' checked="checked"';
+    }
+    $_output .= $extra . ' />' . $output;
+    if ($labels) $_output .= '</label>';
+    $_output .=  $separator;
+
+    return $_output;
+}
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.html_image.php b/bundled-libs/Smarty/libs/plugins/function.html_image.php
new file mode 100644 (file)
index 0000000..c62b0fe
--- /dev/null
@@ -0,0 +1,139 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_image} function plugin
+ *
+ * Type:     function<br>
+ * Name:     html_image<br>
+ * Date:     Feb 24, 2003<br>
+ * Purpose:  format HTML tags for the image<br>
+ * Input:<br>
+ *         - file = file (and path) of image (required)
+ *         - height = image height (optional, default actual height)
+ *         - width = image width (optional, default actual width)
+ *         - basedir = base directory for absolute paths, default
+ *                     is environment variable DOCUMENT_ROOT
+ *
+ * Examples: {html_image file="images/masthead.gif"}
+ * Output:   <img src="images/masthead.gif" width=400 height=23>
+ * @link http://smarty.php.net/manual/en/language.function.html.image.php {html_image}
+ *      (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @author credits to Duda <duda@big.hu> - wrote first image function
+ *           in repository, helped with lots of functionality
+ * @version  1.0
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_image($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
+    
+    $alt = '';
+    $file = '';
+    $height = '';
+    $width = '';
+    $extra = '';
+    $prefix = '';
+    $suffix = '';
+    $server_vars = ($smarty->request_use_auto_globals) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
+    $basedir = isset($server_vars['DOCUMENT_ROOT']) ? $server_vars['DOCUMENT_ROOT'] : '';
+    foreach($params as $_key => $_val) {
+        switch($_key) {
+            case 'file':
+            case 'height':
+            case 'width':
+            case 'dpi':
+            case 'basedir':
+                $$_key = $_val;
+                break;
+
+            case 'alt':
+                if(!is_array($_val)) {
+                    $$_key = smarty_function_escape_special_chars($_val);
+                } else {
+                    $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+
+            case 'link':
+            case 'href':
+                $prefix = '<a href="' . $_val . '">';
+                $suffix = '</a>';
+                break;
+
+            default:
+                if(!is_array($_val)) {
+                    $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
+                } else {
+                    $smarty->trigger_error("html_image: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (empty($file)) {
+        $smarty->trigger_error("html_image: missing 'file' parameter", E_USER_NOTICE);
+        return;
+    }
+
+    if (substr($file,0,1) == '/') {
+        $_image_path = $basedir . $file;
+    } else {
+        $_image_path = $file;
+    }
+
+    if(!isset($params['width']) || !isset($params['height'])) {
+        if ($smarty->security &&
+            ($_params = array('resource_type' => 'file', 'resource_name' => $_image_path)) &&
+            (require_once(SMARTY_CORE_DIR . 'core.is_secure.php')) &&
+            (!smarty_core_is_secure($_params, $smarty)) ) {
+            $smarty->trigger_error("html_image: (secure) '$_image_path' not in secure directory", E_USER_NOTICE);
+
+        } elseif (!$_image_data = @getimagesize($_image_path)) {
+            if(!file_exists($_image_path)) {
+                $smarty->trigger_error("html_image: unable to find '$_image_path'", E_USER_NOTICE);
+                return;
+            } else if(!is_readable($_image_path)) {
+                $smarty->trigger_error("html_image: unable to read '$_image_path'", E_USER_NOTICE);
+                return;
+            } else {
+                $smarty->trigger_error("html_image: '$_image_path' is not a valid image file", E_USER_NOTICE);
+                return;
+            }
+        }
+
+        if(!isset($params['width'])) {
+            $width = $_image_data[0];
+        }
+        if(!isset($params['height'])) {
+            $height = $_image_data[1];
+        }
+
+    }
+
+    if(isset($params['dpi'])) {
+        if(strstr($server_vars['HTTP_USER_AGENT'], 'Mac')) {
+            $dpi_default = 72;
+        } else {
+            $dpi_default = 96;
+        }
+        $_resize = $dpi_default/$params['dpi'];
+        $width = round($width * $_resize);
+        $height = round($height * $_resize);
+    }
+
+    return $prefix . '<img src="'.$file.'" alt="'.$alt.'" width="'.$width.'" height="'.$height.'"'.$extra.' />' . $suffix;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.html_options.php b/bundled-libs/Smarty/libs/plugins/function.html_options.php
new file mode 100644 (file)
index 0000000..ae864f7
--- /dev/null
@@ -0,0 +1,121 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_options} function plugin
+ *
+ * Type:     function<br>
+ * Name:     html_options<br>
+ * Input:<br>
+ *           - name       (optional) - string default "select"
+ *           - values     (required if no options supplied) - array
+ *           - options    (required if no values supplied) - associative array
+ *           - selected   (optional) - string default not set
+ *           - output     (required if not options supplied) - array
+ * Purpose:  Prints the list of <option> tags generated from
+ *           the passed parameters
+ * @link http://smarty.php.net/manual/en/language.function.html.options.php {html_image}
+ *      (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_options($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
+    
+    $name = null;
+    $values = null;
+    $options = null;
+    $selected = array();
+    $output = null;
+    
+    $extra = '';
+    
+    foreach($params as $_key => $_val) {
+        switch($_key) {
+            case 'name':
+                $$_key = (string)$_val;
+                break;
+            
+            case 'options':
+                $$_key = (array)$_val;
+                break;
+                
+            case 'values':
+            case 'output':
+                $$_key = array_values((array)$_val);
+                break;
+
+            case 'selected':
+                $$_key = array_map('strval', array_values((array)$_val));
+                break;
+                
+            default:
+                if(!is_array($_val)) {
+                    $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
+                } else {
+                    $smarty->trigger_error("html_options: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (!isset($options) && !isset($values))
+        return ''; /* raise error here? */
+
+    $_html_result = '';
+
+    if (isset($options)) {
+        
+        foreach ($options as $_key=>$_val)
+            $_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected);
+
+    } else {
+        
+        foreach ($values as $_i=>$_key) {
+            $_val = isset($output[$_i]) ? $output[$_i] : '';
+            $_html_result .= smarty_function_html_options_optoutput($_key, $_val, $selected);
+        }
+
+    }
+
+    if(!empty($name)) {
+        $_html_result = '<select name="' . $name . '"' . $extra . '>' . "\n" . $_html_result . '</select>' . "\n";
+    }
+
+    return $_html_result;
+
+}
+
+function smarty_function_html_options_optoutput($key, $value, $selected) {
+    if(!is_array($value)) {
+        $_html_result = '<option label="' . smarty_function_escape_special_chars($value) . '" value="' .
+            smarty_function_escape_special_chars($key) . '"';
+        if (in_array((string)$key, $selected))
+            $_html_result .= ' selected="selected"';
+        $_html_result .= '>' . smarty_function_escape_special_chars($value) . '</option>' . "\n";
+    } else {
+        $_html_result = smarty_function_html_options_optgroup($key, $value, $selected);
+    }
+    return $_html_result;
+}
+
+function smarty_function_html_options_optgroup($key, $values, $selected) {
+    $optgroup_html = '<optgroup label="' . smarty_function_escape_special_chars($key) . '">' . "\n";
+    foreach ($values as $key => $value) {
+        $optgroup_html .= smarty_function_html_options_optoutput($key, $value, $selected);
+    }
+    $optgroup_html .= "</optgroup>\n";
+    return $optgroup_html;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.html_radios.php b/bundled-libs/Smarty/libs/plugins/function.html_radios.php
new file mode 100644 (file)
index 0000000..dc7baee
--- /dev/null
@@ -0,0 +1,150 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_radios} function plugin
+ *
+ * File:       function.html_radios.php<br>
+ * Type:       function<br>
+ * Name:       html_radios<br>
+ * Date:       24.Feb.2003<br>
+ * Purpose:    Prints out a list of radio input types<br>
+ * Input:<br>
+ *           - name       (optional) - string default "radio"
+ *           - values     (required) - array
+ *           - options    (optional) - associative array
+ *           - checked    (optional) - array default not set
+ *           - separator  (optional) - ie <br> or &nbsp;
+ *           - output     (optional) - the output next to each radio button
+ *           - assign     (optional) - assign the output as an array to this variable
+ * Examples:
+ * <pre>
+ * {html_radios values=$ids output=$names}
+ * {html_radios values=$ids name='box' separator='<br>' output=$names}
+ * {html_radios values=$ids checked=$checked separator='<br>' output=$names}
+ * </pre>
+ * @link http://smarty.php.net/manual/en/language.function.html.radios.php {html_radios}
+ *      (Smarty online manual)
+ * @author     Christopher Kvarme <christopher.kvarme@flashjab.com>
+ * @author credits to Monte Ohrt <monte at ohrt dot com>
+ * @version    1.0
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_function_escape_special_chars()
+ */
+function smarty_function_html_radios($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','escape_special_chars');
+   
+    $name = 'radio';
+    $values = null;
+    $options = null;
+    $selected = null;
+    $separator = '';
+    $labels = true;
+    $output = null;
+    $extra = '';
+
+    foreach($params as $_key => $_val) {
+        switch($_key) {
+            case 'name':
+            case 'separator':
+                $$_key = (string)$_val;
+                break;
+
+            case 'checked':
+            case 'selected':
+                if(is_array($_val)) {
+                    $smarty->trigger_error('html_radios: the "' . $_key . '" attribute cannot be an array', E_USER_WARNING);
+                } else {
+                    $selected = (string)$_val;
+                }
+                break;
+
+            case 'labels':
+                $$_key = (bool)$_val;
+                break;
+
+            case 'options':
+                $$_key = (array)$_val;
+                break;
+
+            case 'values':
+            case 'output':
+                $$_key = array_values((array)$_val);
+                break;
+
+            case 'radios':
+                $smarty->trigger_error('html_radios: the use of the "radios" attribute is deprecated, use "options" instead', E_USER_WARNING);
+                $options = (array)$_val;
+                break;
+
+            case 'assign':
+                break;
+
+            default:
+                if(!is_array($_val)) {
+                    $extra .= ' '.$_key.'="'.smarty_function_escape_special_chars($_val).'"';
+                } else {
+                    $smarty->trigger_error("html_radios: extra attribute '$_key' cannot be an array", E_USER_NOTICE);
+                }
+                break;
+        }
+    }
+
+    if (!isset($options) && !isset($values))
+        return ''; /* raise error here? */
+
+    $_html_result = array();
+
+    if (isset($options)) {
+
+        foreach ($options as $_key=>$_val)
+            $_html_result[] = smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
+
+    } else {
+
+        foreach ($values as $_i=>$_key) {
+            $_val = isset($output[$_i]) ? $output[$_i] : '';
+            $_html_result[] = smarty_function_html_radios_output($name, $_key, $_val, $selected, $extra, $separator, $labels);
+        }
+
+    }
+
+    if(!empty($params['assign'])) {
+        $smarty->assign($params['assign'], $_html_result);
+    } else {
+        return implode("\n",$_html_result);
+    }
+
+}
+
+function smarty_function_html_radios_output($name, $value, $output, $selected, $extra, $separator, $labels) {
+    $_output = '';
+    if ($labels) {
+      $_id = smarty_function_escape_special_chars($name . '_' . $value);
+      $_output .= '<label for="' . $_id . '">';
+   }
+   $_output .= '<input type="radio" name="'
+        . smarty_function_escape_special_chars($name) . '" value="'
+        . smarty_function_escape_special_chars($value) . '"';
+
+   if ($labels) $_output .= ' id="' . $_id . '"';
+
+    if ($value==$selected) {
+        $_output .= ' checked="checked"';
+    }
+    $_output .= $extra . ' />' . $output;
+    if ($labels) $_output .= '</label>';
+    $_output .=  $separator;
+
+    return $_output;
+}
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.html_select_date.php b/bundled-libs/Smarty/libs/plugins/function.html_select_date.php
new file mode 100644 (file)
index 0000000..fc2d449
--- /dev/null
@@ -0,0 +1,316 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty {html_select_date} plugin
+ *
+ * Type:     function<br>
+ * Name:     html_select_date<br>
+ * Purpose:  Prints the dropdowns for date selection.
+ *
+ * ChangeLog:<br>
+ *           - 1.0 initial release
+ *           - 1.1 added support for +/- N syntax for begin
+ *                and end year values. (Monte)
+ *           - 1.2 added support for yyyy-mm-dd syntax for
+ *                time value. (Jan Rosier)
+ *           - 1.3 added support for choosing format for
+ *                month values (Gary Loescher)
+ *           - 1.3.1 added support for choosing format for
+ *                day values (Marcus Bointon)
+ *           - 1.3.2 suppport negative timestamps, force year
+ *             dropdown to include given date unless explicitly set (Monte)
+ * @link http://smarty.php.net/manual/en/language.function.html.select.date.php {html_select_date}
+ *      (Smarty online manual)
+ * @version 1.3.2
+ * @author   Andrei Zmievski
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_html_select_date($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','make_timestamp');
+    require_once $smarty->_get_plugin_filepath('function','html_options');
+    /* Default values. */
+    $prefix          = "Date_";
+    $start_year      = strftime("%Y");
+    $end_year        = $start_year;
+    $display_days    = true;
+    $display_months  = true;
+    $display_years   = true;
+    $month_format    = "%B";
+    /* Write months as numbers by default  GL */
+    $month_value_format = "%m";
+    $day_format      = "%02d";
+    /* Write day values using this format MB */
+    $day_value_format = "%d";
+    $year_as_text    = false;
+    /* Display years in reverse order? Ie. 2000,1999,.... */
+    $reverse_years   = false;
+    /* Should the select boxes be part of an array when returned from PHP?
+       e.g. setting it to "birthday", would create "birthday[Day]",
+       "birthday[Month]" & "birthday[Year]". Can be combined with prefix */
+    $field_array     = null;
+    /* <select size>'s of the different <select> tags.
+       If not set, uses default dropdown. */
+    $day_size        = null;
+    $month_size      = null;
+    $year_size       = null;
+    /* Unparsed attributes common to *ALL* the <select>/<input> tags.
+       An example might be in the template: all_extra ='class ="foo"'. */
+    $all_extra       = null;
+    /* Separate attributes for the tags. */
+    $day_extra       = null;
+    $month_extra     = null;
+    $year_extra      = null;
+    /* Order in which to display the fields.
+       "D" -> day, "M" -> month, "Y" -> year. */
+    $field_order     = 'MDY';
+    /* String printed between the different fields. */
+    $field_separator = "\n";
+    $time = time();
+    $all_empty       = null;
+    $day_empty       = null;
+    $month_empty     = null;
+    $year_empty      = null;
+
+    foreach ($params as $_key=>$_value) {
+        switch ($_key) {
+            case 'prefix':
+            case 'time':
+            case 'start_year':
+            case 'end_year':
+            case 'month_format':
+            case 'day_format':
+            case 'day_value_format':
+            case 'field_array':
+            case 'day_size':
+            case 'month_size':
+            case 'year_size':
+            case 'all_extra':
+            case 'day_extra':
+            case 'month_extra':
+            case 'year_extra':
+            case 'field_order':
+            case 'field_separator':
+            case 'month_value_format':
+            case 'month_empty':
+            case 'day_empty':
+            case 'year_empty':
+                $$_key = (string)$_value;
+                break;
+
+            case 'all_empty':
+                $$_key = (string)$_value;
+                $day_empty = $month_empty = $year_empty = $all_empty;
+                break;
+
+            case 'display_days':
+            case 'display_months':
+            case 'display_years':
+            case 'year_as_text':
+            case 'reverse_years':
+                $$_key = (bool)$_value;
+                break;
+
+            default:
+                $smarty->trigger_error("[html_select_date] unknown parameter $_key", E_USER_WARNING);
+
+        }
+    }
+
+    if(preg_match('!^-\d+$!',$time)) {
+        // negative timestamp, use date()
+        $time = date('Y-m-d',$time);
+    }
+    // If $time is not in format yyyy-mm-dd
+    if (!preg_match('/^\d{0,4}-\d{0,2}-\d{0,2}$/', $time)) {
+        // use smarty_make_timestamp to get an unix timestamp and
+        // strftime to make yyyy-mm-dd
+        $time = strftime('%Y-%m-%d', smarty_make_timestamp($time));
+    }
+    // Now split this in pieces, which later can be used to set the select
+    $time = explode("-", $time);
+    
+    // make syntax "+N" or "-N" work with start_year and end_year
+    if (preg_match('!^(\+|\-)\s*(\d+)$!', $end_year, $match)) {
+        if ($match[1] == '+') {
+            $end_year = strftime('%Y') + $match[2];
+        } else {
+            $end_year = strftime('%Y') - $match[2];
+        }
+    }
+    if (preg_match('!^(\+|\-)\s*(\d+)$!', $start_year, $match)) {
+        if ($match[1] == '+') {
+            $start_year = strftime('%Y') + $match[2];
+        } else {
+            $start_year = strftime('%Y') - $match[2];
+        }
+    }
+    if (strlen($time[0]) > 0) { 
+        if ($start_year > $time[0] && !isset($params['start_year'])) {
+            // force start year to include given date if not explicitly set
+            $start_year = $time[0];
+        }
+        if($end_year < $time[0] && !isset($params['end_year'])) {
+            // force end year to include given date if not explicitly set
+            $end_year = $time[0];
+        }
+    }
+
+    $field_order = strtoupper($field_order);
+
+    $html_result = $month_result = $day_result = $year_result = "";
+
+    if ($display_months) {
+        $month_names = array();
+        $month_values = array();
+        if(isset($month_empty)) {
+            $month_names[''] = $month_empty;
+            $month_values[''] = '';
+        }
+        for ($i = 1; $i <= 12; $i++) {
+            $month_names[$i] = strftime($month_format, mktime(0, 0, 0, $i, 1, 2000));
+            $month_values[$i] = strftime($month_value_format, mktime(0, 0, 0, $i, 1, 2000));
+        }
+
+        $month_result .= '<select name=';
+        if (null !== $field_array){
+            $month_result .= '"' . $field_array . '[' . $prefix . 'Month]"';
+        } else {
+            $month_result .= '"' . $prefix . 'Month"';
+        }
+        if (null !== $month_size){
+            $month_result .= ' size="' . $month_size . '"';
+        }
+        if (null !== $month_extra){
+            $month_result .= ' ' . $month_extra;
+        }
+        if (null !== $all_extra){
+            $month_result .= ' ' . $all_extra;
+        }
+        $month_result .= '>'."\n";
+
+        $month_result .= smarty_function_html_options(array('output'     => $month_names,
+                                                            'values'     => $month_values,
+                                                            'selected'   => $a=$time[1] ? strftime($month_value_format, mktime(0, 0, 0, (int)$time[1], 1, 2000)) : '',
+                                                            'print_result' => false),
+                                                      $smarty);
+        $month_result .= '</select>';
+    }
+
+    if ($display_days) {
+        $days = array();
+        if (isset($day_empty)) {
+            $days[''] = $day_empty;
+            $day_values[''] = '';
+        }
+        for ($i = 1; $i <= 31; $i++) {
+            $days[] = sprintf($day_format, $i);
+            $day_values[] = sprintf($day_value_format, $i);
+        }
+
+        $day_result .= '<select name=';
+        if (null !== $field_array){
+            $day_result .= '"' . $field_array . '[' . $prefix . 'Day]"';
+        } else {
+            $day_result .= '"' . $prefix . 'Day"';
+        }
+        if (null !== $day_size){
+            $day_result .= ' size="' . $day_size . '"';
+        }
+        if (null !== $all_extra){
+            $day_result .= ' ' . $all_extra;
+        }
+        if (null !== $day_extra){
+            $day_result .= ' ' . $day_extra;
+        }
+        $day_result .= '>'."\n";
+        $day_result .= smarty_function_html_options(array('output'     => $days,
+                                                          'values'     => $day_values,
+                                                          'selected'   => $time[2],
+                                                          'print_result' => false),
+                                                    $smarty);
+        $day_result .= '</select>';
+    }
+
+    if ($display_years) {
+        if (null !== $field_array){
+            $year_name = $field_array . '[' . $prefix . 'Year]';
+        } else {
+            $year_name = $prefix . 'Year';
+        }
+        if ($year_as_text) {
+            $year_result .= '<input type="text" name="' . $year_name . '" value="' . $time[0] . '" size="4" maxlength="4"';
+            if (null !== $all_extra){
+                $year_result .= ' ' . $all_extra;
+            }
+            if (null !== $year_extra){
+                $year_result .= ' ' . $year_extra;
+            }
+            $year_result .= '>';
+        } else {
+            $years = range((int)$start_year, (int)$end_year);
+            if ($reverse_years) {
+                rsort($years, SORT_NUMERIC);
+            } else {
+                sort($years, SORT_NUMERIC);
+            }
+            $yearvals = $years;
+            if(isset($year_empty)) {
+                array_unshift($years, $year_empty);
+                array_unshift($yearvals, '');
+            }
+            $year_result .= '<select name="' . $year_name . '"';
+            if (null !== $year_size){
+                $year_result .= ' size="' . $year_size . '"';
+            }
+            if (null !== $all_extra){
+                $year_result .= ' ' . $all_extra;
+            }
+            if (null !== $year_extra){
+                $year_result .= ' ' . $year_extra;
+            }
+            $year_result .= '>'."\n";
+            $year_result .= smarty_function_html_options(array('output' => $years,
+                                                               'values' => $yearvals,
+                                                               'selected'   => $time[0],
+                                                               'print_result' => false),
+                                                         $smarty);
+            $year_result .= '</select>';
+        }
+    }
+
+    // Loop thru the field_order field
+    for ($i = 0; $i <= 2; $i++){
+        $c = substr($field_order, $i, 1);
+        switch ($c){
+            case 'D':
+                $html_result .= $day_result;
+                break;
+
+            case 'M':
+                $html_result .= $month_result;
+                break;
+
+            case 'Y':
+                $html_result .= $year_result;
+                break;
+        }
+        // Add the field seperator
+        if($i != 2) {
+            $html_result .= $field_separator;
+        }
+    }
+
+    return $html_result;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.html_select_time.php b/bundled-libs/Smarty/libs/plugins/function.html_select_time.php
new file mode 100644 (file)
index 0000000..00cd1ae
--- /dev/null
@@ -0,0 +1,192 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_select_time} function plugin
+ *
+ * Type:     function<br>
+ * Name:     html_select_time<br>
+ * Purpose:  Prints the dropdowns for time selection
+ * @link http://smarty.php.net/manual/en/language.function.html.select.time.php {html_select_time}
+ *          (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ * @uses smarty_make_timestamp()
+ */
+function smarty_function_html_select_time($params, &$smarty)
+{
+    require_once $smarty->_get_plugin_filepath('shared','make_timestamp');
+    require_once $smarty->_get_plugin_filepath('function','html_options');
+    /* Default values. */
+    $prefix             = "Time_";
+    $time               = time();
+    $display_hours      = true;
+    $display_minutes    = true;
+    $display_seconds    = true;
+    $display_meridian   = true;
+    $use_24_hours       = true;
+    $minute_interval    = 1;
+    $second_interval    = 1;
+    /* Should the select boxes be part of an array when returned from PHP?
+       e.g. setting it to "birthday", would create "birthday[Hour]",
+       "birthday[Minute]", "birthday[Seconds]" & "birthday[Meridian]".
+       Can be combined with prefix. */
+    $field_array        = null;
+    $all_extra          = null;
+    $hour_extra         = null;
+    $minute_extra       = null;
+    $second_extra       = null;
+    $meridian_extra     = null;
+
+    foreach ($params as $_key=>$_value) {
+        switch ($_key) {
+            case 'prefix':
+            case 'time':
+            case 'field_array':
+            case 'all_extra':
+            case 'hour_extra':
+            case 'minute_extra':
+            case 'second_extra':
+            case 'meridian_extra':
+                $$_key = (string)$_value;
+                break;
+
+            case 'display_hours':
+            case 'display_minutes':
+            case 'display_seconds':
+            case 'display_meridian':
+            case 'use_24_hours':
+                $$_key = (bool)$_value;
+                break;
+
+            case 'minute_interval':
+            case 'second_interval':
+                $$_key = (int)$_value;
+                break;
+
+            default:
+                $smarty->trigger_error("[html_select_time] unknown parameter $_key", E_USER_WARNING);
+        }
+    }
+
+    $time = smarty_make_timestamp($time);
+
+    $html_result = '';
+
+    if ($display_hours) {
+        $hours       = $use_24_hours ? range(0, 23) : range(1, 12);
+        $hour_fmt = $use_24_hours ? '%H' : '%I';
+        for ($i = 0, $for_max = count($hours); $i < $for_max; $i++)
+            $hours[$i] = sprintf('%02d', $hours[$i]);
+        $html_result .= '<select name=';
+        if (null !== $field_array) {
+            $html_result .= '"' . $field_array . '[' . $prefix . 'Hour]"';
+        } else {
+            $html_result .= '"' . $prefix . 'Hour"';
+        }
+        if (null !== $hour_extra){
+            $html_result .= ' ' . $hour_extra;
+        }
+        if (null !== $all_extra){
+            $html_result .= ' ' . $all_extra;
+        }
+        $html_result .= '>'."\n";
+        $html_result .= smarty_function_html_options(array('output'          => $hours,
+                                                           'values'          => $hours,
+                                                           'selected'      => strftime($hour_fmt, $time),
+                                                           'print_result' => false),
+                                                     $smarty);
+        $html_result .= "</select>\n";
+    }
+
+    if ($display_minutes) {
+        $all_minutes = range(0, 59);
+        for ($i = 0, $for_max = count($all_minutes); $i < $for_max; $i+= $minute_interval)
+            $minutes[] = sprintf('%02d', $all_minutes[$i]);
+        $selected = intval(floor(strftime('%M', $time) / $minute_interval) * $minute_interval);
+        $html_result .= '<select name=';
+        if (null !== $field_array) {
+            $html_result .= '"' . $field_array . '[' . $prefix . 'Minute]"';
+        } else {
+            $html_result .= '"' . $prefix . 'Minute"';
+        }
+        if (null !== $minute_extra){
+            $html_result .= ' ' . $minute_extra;
+        }
+        if (null !== $all_extra){
+            $html_result .= ' ' . $all_extra;
+        }
+        $html_result .= '>'."\n";
+        
+        $html_result .= smarty_function_html_options(array('output'          => $minutes,
+                                                           'values'          => $minutes,
+                                                           'selected'      => $selected,
+                                                           'print_result' => false),
+                                                     $smarty);
+        $html_result .= "</select>\n";
+    }
+
+    if ($display_seconds) {
+        $all_seconds = range(0, 59);
+        for ($i = 0, $for_max = count($all_seconds); $i < $for_max; $i+= $second_interval)
+            $seconds[] = sprintf('%02d', $all_seconds[$i]);
+        $selected = intval(floor(strftime('%S', $time) / $second_interval) * $second_interval);
+        $html_result .= '<select name=';
+        if (null !== $field_array) {
+            $html_result .= '"' . $field_array . '[' . $prefix . 'Second]"';
+        } else {
+            $html_result .= '"' . $prefix . 'Second"';
+        }
+        
+        if (null !== $second_extra){
+            $html_result .= ' ' . $second_extra;
+        }
+        if (null !== $all_extra){
+            $html_result .= ' ' . $all_extra;
+        }
+        $html_result .= '>'."\n";
+        
+        $html_result .= smarty_function_html_options(array('output'          => $seconds,
+                                                           'values'          => $seconds,
+                                                           'selected'      => $selected,
+                                                           'print_result' => false),
+                                                     $smarty);
+        $html_result .= "</select>\n";
+    }
+
+    if ($display_meridian && !$use_24_hours) {
+        $html_result .= '<select name=';
+        if (null !== $field_array) {
+            $html_result .= '"' . $field_array . '[' . $prefix . 'Meridian]"';
+        } else {
+            $html_result .= '"' . $prefix . 'Meridian"';
+        }
+        
+        if (null !== $meridian_extra){
+            $html_result .= ' ' . $meridian_extra;
+        }
+        if (null !== $all_extra){
+            $html_result .= ' ' . $all_extra;
+        }
+        $html_result .= '>'."\n";
+        
+        $html_result .= smarty_function_html_options(array('output'          => array('AM', 'PM'),
+                                                           'values'          => array('am', 'pm'),
+                                                           'selected'      => strtolower(strftime('%p', $time)),
+                                                           'print_result' => false),
+                                                     $smarty);
+        $html_result .= "</select>\n";
+    }
+
+    return $html_result;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.html_table.php b/bundled-libs/Smarty/libs/plugins/function.html_table.php
new file mode 100644 (file)
index 0000000..62d7410
--- /dev/null
@@ -0,0 +1,137 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {html_table} function plugin
+ *
+ * Type:     function<br>
+ * Name:     html_table<br>
+ * Date:     Feb 17, 2003<br>
+ * Purpose:  make an html table from an array of data<br>
+ * Input:<br>
+ *         - loop = array to loop through
+ *         - cols = number of columns
+ *         - rows = number of rows
+ *         - table_attr = table attributes
+ *         - tr_attr = table row attributes (arrays are cycled)
+ *         - td_attr = table cell attributes (arrays are cycled)
+ *         - trailpad = value to pad trailing cells with
+ *         - vdir = vertical direction (default: "down", means top-to-bottom)
+ *         - hdir = horizontal direction (default: "right", means left-to-right)
+ *         - inner = inner loop (default "cols": print $loop line by line,
+ *                   $loop will be printed column by column otherwise)
+ *
+ *
+ * Examples:
+ * <pre>
+ * {table loop=$data}
+ * {table loop=$data cols=4 tr_attr='"bgcolor=red"'}
+ * {table loop=$data cols=4 tr_attr=$colors}
+ * </pre>
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @version  1.0
+ * @link http://smarty.php.net/manual/en/language.function.html.table.php {html_table}
+ *          (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_html_table($params, &$smarty)
+{
+    $table_attr = 'border="1"';
+    $tr_attr = '';
+    $td_attr = '';
+    $cols = 3;
+    $rows = 3;
+    $trailpad = '&nbsp;';
+    $vdir = 'down';
+    $hdir = 'right';
+    $inner = 'cols';
+
+    if (!isset($params['loop'])) {
+        $smarty->trigger_error("html_table: missing 'loop' parameter");
+        return;
+    }
+
+    foreach ($params as $_key=>$_value) {
+        switch ($_key) {
+            case 'loop':
+                $$_key = (array)$_value;
+                break;
+
+            case 'cols':
+            case 'rows':
+                $$_key = (int)$_value;
+                break;
+
+            case 'table_attr':
+            case 'trailpad':
+            case 'hdir':
+            case 'vdir':
+            case 'inner':
+                $$_key = (string)$_value;
+                break;
+
+            case 'tr_attr':
+            case 'td_attr':
+                $$_key = $_value;
+                break;
+        }
+    }
+
+    $loop_count = count($loop);
+    if (empty($params['rows'])) {
+        /* no rows specified */
+        $rows = ceil($loop_count/$cols);
+    } elseif (empty($params['cols'])) {
+        if (!empty($params['rows'])) {
+            /* no cols specified, but rows */
+            $cols = ceil($loop_count/$rows);
+        }
+    }
+
+    $output = "<table $table_attr>\n";
+
+    for ($r=0; $r<$rows; $r++) {
+        $output .= "<tr" . smarty_function_html_table_cycle('tr', $tr_attr, $r) . ">\n";
+        $rx =  ($vdir == 'down') ? $r*$cols : ($rows-1-$r)*$cols;
+
+        for ($c=0; $c<$cols; $c++) {
+            $x =  ($hdir == 'right') ? $rx+$c : $rx+$cols-1-$c;
+            if ($inner!='cols') {
+                /* shuffle x to loop over rows*/
+                $x = floor($x/$cols) + ($x%$cols)*$rows;
+            }
+
+            if ($x<$loop_count) {
+                $output .= "<td" . smarty_function_html_table_cycle('td', $td_attr, $c) . ">" . $loop[$x] . "</td>\n";
+            } else {
+                $output .= "<td" . smarty_function_html_table_cycle('td', $td_attr, $c) . ">$trailpad</td>\n";
+            }
+        }
+        $output .= "</tr>\n";
+    }
+    $output .= "</table>\n";
+    
+    return $output;
+}
+
+function smarty_function_html_table_cycle($name, $var, $no) {
+    if(!is_array($var)) {
+        $ret = $var;
+    } else {
+        $ret = $var[$no % count($var)];
+    }
+    
+    return ($ret) ? ' '.$ret : '';
+}
+
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.mailto.php b/bundled-libs/Smarty/libs/plugins/function.mailto.php
new file mode 100644 (file)
index 0000000..64c122c
--- /dev/null
@@ -0,0 +1,163 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {mailto} function plugin
+ *
+ * Type:     function<br>
+ * Name:     mailto<br>
+ * Date:     May 21, 2002
+ * Purpose:  automate mailto address link creation, and optionally
+ *           encode them.<br>
+ * Input:<br>
+ *         - address = e-mail address
+ *         - text = (optional) text to display, default is address
+ *         - encode = (optional) can be one of:
+ *                * none : no encoding (default)
+ *                * javascript : encode with javascript
+ *                * javascript_charcode : encode with javascript charcode
+ *                * hex : encode with hexidecimal (no javascript)
+ *         - cc = (optional) address(es) to carbon copy
+ *         - bcc = (optional) address(es) to blind carbon copy
+ *         - subject = (optional) e-mail subject
+ *         - newsgroups = (optional) newsgroup(s) to post to
+ *         - followupto = (optional) address(es) to follow up to
+ *         - extra = (optional) extra tags for the href link
+ *
+ * Examples:
+ * <pre>
+ * {mailto address="me@domain.com"}
+ * {mailto address="me@domain.com" encode="javascript"}
+ * {mailto address="me@domain.com" encode="hex"}
+ * {mailto address="me@domain.com" subject="Hello to you!"}
+ * {mailto address="me@domain.com" cc="you@domain.com,they@domain.com"}
+ * {mailto address="me@domain.com" extra='class="mailto"'}
+ * </pre>
+ * @link http://smarty.php.net/manual/en/language.function.mailto.php {mailto}
+ *          (Smarty online manual)
+ * @version  1.2
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @author   credits to Jason Sweat (added cc, bcc and subject functionality)
+ * @param    array
+ * @param    Smarty
+ * @return   string
+ */
+function smarty_function_mailto($params, &$smarty)
+{
+    $extra = '';
+
+    if (empty($params['address'])) {
+        $smarty->trigger_error("mailto: missing 'address' parameter");
+        return;
+    } else {
+        $address = $params['address'];
+    }
+
+    $text = $address;
+
+    // netscape and mozilla do not decode %40 (@) in BCC field (bug?)
+    // so, don't encode it.
+    $mail_parms = array();
+    foreach ($params as $var=>$value) {
+        switch ($var) {
+            case 'cc':
+            case 'bcc':
+            case 'followupto':
+                if (!empty($value))
+                    $mail_parms[] = $var.'='.str_replace('%40','@',rawurlencode($value));
+                break;
+                
+            case 'subject':
+            case 'newsgroups':
+                $mail_parms[] = $var.'='.rawurlencode($value);
+                break;
+
+            case 'extra':
+            case 'text':
+                $$var = $value;
+
+            default:
+        }
+    }
+
+    $mail_parm_vals = '';
+    for ($i=0; $i<count($mail_parms); $i++) {
+        $mail_parm_vals .= (0==$i) ? '?' : '&';
+        $mail_parm_vals .= $mail_parms[$i];
+    }
+    $address .= $mail_parm_vals;
+
+    $encode = (empty($params['encode'])) ? 'none' : $params['encode'];
+    if (!in_array($encode,array('javascript','javascript_charcode','hex','none')) ) {
+        $smarty->trigger_error("mailto: 'encode' parameter must be none, javascript or hex");
+        return;
+    }
+
+    if ($encode == 'javascript' ) {
+        $string = 'document.write(\'<a href="mailto:'.$address.'" '.$extra.'>'.$text.'</a>\');';
+
+        $js_encode = '';
+        for ($x=0; $x < strlen($string); $x++) {
+            $js_encode .= '%' . bin2hex($string[$x]);
+        }
+
+        return '<script type="text/javascript">eval(unescape(\''.$js_encode.'\'))</script>';
+
+    } elseif ($encode == 'javascript_charcode' ) {
+        $string = '<a href="mailto:'.$address.'" '.$extra.'>'.$text.'</a>';
+
+        for($x = 0, $y = strlen($string); $x < $y; $x++ ) {
+            $ord[] = ord($string[$x]);   
+        }
+
+        $_ret = "<script type=\"text/javascript\" language=\"javascript\">\n";
+        $_ret .= "<!--\n";
+        $_ret .= "{document.write(String.fromCharCode(";
+        $_ret .= implode(',',$ord);
+        $_ret .= "))";
+        $_ret .= "}\n";
+        $_ret .= "//-->\n";
+        $_ret .= "</script>\n";
+        
+        return $_ret;
+        
+        
+    } elseif ($encode == 'hex') {
+
+        preg_match('!^(.*)(\?.*)$!',$address,$match);
+        if(!empty($match[2])) {
+            $smarty->trigger_error("mailto: hex encoding does not work with extra attributes. Try javascript.");
+            return;
+        }
+        $address_encode = '';
+        for ($x=0; $x < strlen($address); $x++) {
+            if(preg_match('!\w!',$address[$x])) {
+                $address_encode .= '%' . bin2hex($address[$x]);
+            } else {
+                $address_encode .= $address[$x];
+            }
+        }
+        $text_encode = '';
+        for ($x=0; $x < strlen($text); $x++) {
+            $text_encode .= '&#x' . bin2hex($text[$x]).';';
+        }
+
+        $mailto = "&#109;&#97;&#105;&#108;&#116;&#111;&#58;";
+        return '<a href="'.$mailto.$address_encode.'" '.$extra.'>'.$text_encode.'</a>';
+
+    } else {
+        // no encoding
+        return '<a href="mailto:'.$address.'" '.$extra.'>'.$text.'</a>';
+
+    }
+
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.math.php b/bundled-libs/Smarty/libs/plugins/function.math.php
new file mode 100644 (file)
index 0000000..0439107
--- /dev/null
@@ -0,0 +1,83 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {math} function plugin
+ *
+ * Type:     function<br>
+ * Name:     math<br>
+ * Purpose:  handle math computations in template<br>
+ * @link http://smarty.php.net/manual/en/language.function.math.php {math}
+ *          (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_math($params, &$smarty)
+{
+    // be sure equation parameter is present
+    if (empty($params['equation'])) {
+        $smarty->trigger_error("math: missing equation parameter");
+        return;
+    }
+
+    $equation = $params['equation'];
+
+    // make sure parenthesis are balanced
+    if (substr_count($equation,"(") != substr_count($equation,")")) {
+        $smarty->trigger_error("math: unbalanced parenthesis");
+        return;
+    }
+
+    // match all vars in equation, make sure all are passed
+    preg_match_all("!(?:0x[a-fA-F0-9]+)|([a-zA-Z][a-zA-Z0-9_]+)!",$equation, $match);
+    $allowed_funcs = array('int','abs','ceil','cos','exp','floor','log','log10',
+                           'max','min','pi','pow','rand','round','sin','sqrt','srand','tan');
+    
+    foreach($match[1] as $curr_var) {
+        if ($curr_var && !in_array($curr_var, array_keys($params)) && !in_array($curr_var, $allowed_funcs)) {
+            $smarty->trigger_error("math: function call $curr_var not allowed");
+            return;
+        }
+    }
+
+    foreach($params as $key => $val) {
+        if ($key != "equation" && $key != "format" && $key != "assign") {
+            // make sure value is not empty
+            if (strlen($val)==0) {
+                $smarty->trigger_error("math: parameter $key is empty");
+                return;
+            }
+            if (!is_numeric($val)) {
+                $smarty->trigger_error("math: parameter $key: is not numeric");
+                return;
+            }
+            $equation = preg_replace("/\b$key\b/",$val, $equation);
+        }
+    }
+
+    eval("\$smarty_math_result = ".$equation.";");
+
+    if (empty($params['format'])) {
+        if (empty($params['assign'])) {
+            return $smarty_math_result;
+        } else {
+            $smarty->assign($params['assign'],$smarty_math_result);
+        }
+    } else {
+        if (empty($params['assign'])){
+            printf($params['format'],$smarty_math_result);
+        } else {
+            $smarty->assign($params['assign'],sprintf($params['format'],$smarty_math_result));
+        }
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.popup.php b/bundled-libs/Smarty/libs/plugins/function.popup.php
new file mode 100644 (file)
index 0000000..2ba54de
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {popup} function plugin
+ *
+ * Type:     function<br>
+ * Name:     popup<br>
+ * Purpose:  make text pop up in windows via overlib
+ * @link http://smarty.php.net/manual/en/language.function.popup.php {popup}
+ *          (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_popup($params, &$smarty)
+{
+    $append = '';
+    foreach ($params as $_key=>$_value) {
+        switch ($_key) {
+            case 'text':
+            case 'trigger':
+            case 'function':
+            case 'inarray':
+                $$_key = (string)$_value;
+                if ($_key == 'function' || $_key == 'inarray')
+                    $append .= ',' . strtoupper($_key) . ",'$_value'";
+                break;
+
+            case 'caption':
+            case 'closetext':
+            case 'status':
+                $append .= ',' . strtoupper($_key) . ",'" . str_replace("'","\'",$_value) . "'";
+                break;
+
+            case 'fgcolor':
+            case 'bgcolor':
+            case 'textcolor':
+            case 'capcolor':
+            case 'closecolor':
+            case 'textfont':
+            case 'captionfont':
+            case 'closefont':
+            case 'fgbackground':
+            case 'bgbackground':
+            case 'caparray':
+            case 'capicon':
+            case 'background':
+            case 'frame':
+                $append .= ',' . strtoupper($_key) . ",'$_value'";
+                break;
+
+            case 'textsize':
+            case 'captionsize':
+            case 'closesize':
+            case 'width':
+            case 'height':
+            case 'border':
+            case 'offsetx':
+            case 'offsety':
+            case 'snapx':
+            case 'snapy':
+            case 'fixx':
+            case 'fixy':
+            case 'padx':
+            case 'pady':
+            case 'timeout':
+            case 'delay':
+                $append .= ',' . strtoupper($_key) . ",$_value";
+                break;
+
+            case 'sticky':
+            case 'left':
+            case 'right':
+            case 'center':
+            case 'above':
+            case 'below':
+            case 'noclose':
+            case 'autostatus':
+            case 'autostatuscap':
+            case 'fullhtml':
+            case 'hauto':
+            case 'vauto':
+            case 'mouseoff':
+            case 'followmouse':
+                if ($_value) $append .= ',' . strtoupper($_key);
+                break;
+
+            default:
+                $smarty->trigger_error("[popup] unknown parameter $_key", E_USER_WARNING);
+        }
+    }
+
+    if (empty($text) && !isset($inarray) && empty($function)) {
+        $smarty->trigger_error("overlib: attribute 'text' or 'inarray' or 'function' required");
+        return false;
+    }
+
+    if (empty($trigger)) { $trigger = "onmouseover"; }
+
+    $retval = $trigger . '="return overlib(\''.preg_replace(array("!'!","![\r\n]!"),array("\'",'\r'),$text).'\'';
+    $retval .= $append . ');"';
+    if ($trigger == 'onmouseover')
+       $retval .= ' onmouseout="nd();"';
+
+
+    return $retval;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/function.popup_init.php b/bundled-libs/Smarty/libs/plugins/function.popup_init.php
new file mode 100644 (file)
index 0000000..f62c33c
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty {popup_init} function plugin
+ *
+ * Type:     function<br>
+ * Name:     popup_init<br>
+ * Purpose:  initialize overlib
+ * @link http://smarty.php.net/manual/en/language.function.popup.init.php {popup_init}
+ *          (Smarty online manual)
+ * @param array
+ * @param Smarty
+ * @return string
+ */
+function smarty_function_popup_init($params, &$smarty)
+{
+    $zindex = 1000;
+    
+    if (!empty($params['zindex'])) {
+        $zindex = $params['zindex'];
+    }
+    
+    if (!empty($params['src'])) {
+        return '<div id="overDiv" style="position:absolute; visibility:hidden; z-index:'.$zindex.';"></div>' . "\n"
+         . '<script type="text/javascript" language="JavaScript" src="'.$params['src'].'"></script>' . "\n";
+    } else {
+        $smarty->trigger_error("popup_init: missing src parameter");
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.capitalize.php b/bundled-libs/Smarty/libs/plugins/modifier.capitalize.php
new file mode 100644 (file)
index 0000000..2b9169c
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty capitalize modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     capitalize<br>
+ * Purpose:  capitalize words in the string
+ * @link http://smarty.php.net/manual/en/language.modifiers.php#LANGUAGE.MODIFIER.CAPITALIZE
+ *      capitalize (Smarty online manual)
+ * @param string
+ * @return string
+ */
+function smarty_modifier_capitalize($string, $uc_digits = false)
+{
+    smarty_modifier_capitalize_ucfirst(null, $uc_digits);
+    return preg_replace_callback('!\b\w+\b!', 'smarty_modifier_capitalize_ucfirst', $string);
+}
+
+function smarty_modifier_capitalize_ucfirst($string, $uc_digits = null)
+{
+    static $_uc_digits = false;
+    
+    if(isset($uc_digits)) {
+        $_uc_digits = $uc_digits;
+        return;
+    }
+    
+    if(!preg_match('!\d!',$string[0]) || $_uc_digits)
+        return ucfirst($string[0]);
+    else
+        return $string[0];
+}
+
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.cat.php b/bundled-libs/Smarty/libs/plugins/modifier.cat.php
new file mode 100644 (file)
index 0000000..2e37940
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty cat modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     cat<br>
+ * Date:     Feb 24, 2003
+ * Purpose:  catenate a value to a variable
+ * Input:    string to catenate
+ * Example:  {$var|cat:"foo"}
+ * @link http://smarty.php.net/manual/en/language.modifier.cat.php cat
+ *          (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @version 1.0
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_cat($string, $cat)
+{
+    return $string . $cat;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.count_characters.php b/bundled-libs/Smarty/libs/plugins/modifier.count_characters.php
new file mode 100644 (file)
index 0000000..49ce655
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty count_characters modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     count_characteres<br>
+ * Purpose:  count the number of characters in a text
+ * @link http://smarty.php.net/manual/en/language.modifier.count.characters.php
+ *          count_characters (Smarty online manual)
+ * @param string
+ * @param boolean include whitespace in the character count
+ * @return integer
+ */
+function smarty_modifier_count_characters($string, $include_spaces = false)
+{
+    if ($include_spaces)
+       return(strlen($string));
+
+    return preg_match_all("/[^\s]/",$string, $match);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.count_paragraphs.php b/bundled-libs/Smarty/libs/plugins/modifier.count_paragraphs.php
new file mode 100644 (file)
index 0000000..6a9833c
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty count_paragraphs modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     count_paragraphs<br>
+ * Purpose:  count the number of paragraphs in a text
+ * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php
+ *          count_paragraphs (Smarty online manual)
+ * @param string
+ * @return integer
+ */
+function smarty_modifier_count_paragraphs($string)
+{
+    // count \r or \n characters
+    return count(preg_split('/[\r\n]+/', $string));
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.count_sentences.php b/bundled-libs/Smarty/libs/plugins/modifier.count_sentences.php
new file mode 100644 (file)
index 0000000..0c210f0
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty count_sentences modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     count_sentences
+ * Purpose:  count the number of sentences in a text
+ * @link http://smarty.php.net/manual/en/language.modifier.count.paragraphs.php
+ *          count_sentences (Smarty online manual)
+ * @param string
+ * @return integer
+ */
+function smarty_modifier_count_sentences($string)
+{
+    // find periods with a word before but not after.
+    return preg_match_all('/[^\s]\.(?!\w)/', $string, $match);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.count_words.php b/bundled-libs/Smarty/libs/plugins/modifier.count_words.php
new file mode 100644 (file)
index 0000000..42c8a74
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty count_words modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     count_words<br>
+ * Purpose:  count the number of words in a text
+ * @link http://smarty.php.net/manual/en/language.modifier.count.words.php
+ *          count_words (Smarty online manual)
+ * @param string
+ * @return integer
+ */
+function smarty_modifier_count_words($string)
+{
+    // split text by ' ',\r,\n,\f,\t
+    $split_array = preg_split('/\s+/',$string);
+    // count matches that contain alphanumerics
+    $word_count = preg_grep('/[a-zA-Z0-9\\x80-\\xff]/', $split_array);
+
+    return count($word_count);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.date_format.php b/bundled-libs/Smarty/libs/plugins/modifier.date_format.php
new file mode 100644 (file)
index 0000000..2f36b3b
--- /dev/null
@@ -0,0 +1,48 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Include the {@link shared.make_timestamp.php} plugin
+ */
+require_once $smarty->_get_plugin_filepath('shared','make_timestamp');
+/**
+ * Smarty date_format modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     date_format<br>
+ * Purpose:  format datestamps via strftime<br>
+ * Input:<br>
+ *         - string: input date string
+ *         - format: strftime format for output
+ *         - default_date: default date if $string is empty
+ * @link http://smarty.php.net/manual/en/language.modifier.date.format.php
+ *          date_format (Smarty online manual)
+ * @param string
+ * @param string
+ * @param string
+ * @return string|void
+ * @uses smarty_make_timestamp()
+ */
+function smarty_modifier_date_format($string, $format="%b %e, %Y", $default_date=null)
+{
+    if (substr(PHP_OS,0,3) == 'WIN') {
+           $_win_from = array ('%e',  '%T',       '%D');
+           $_win_to   = array ('%#d', '%H:%M:%S', '%m/%d/%y');
+           $format = str_replace($_win_from, $_win_to, $format);
+    }
+    if($string != '') {
+        return strftime($format, smarty_make_timestamp($string));
+    } elseif (isset($default_date) && $default_date != '') {
+        return strftime($format, smarty_make_timestamp($default_date));
+    } else {
+        return;
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.debug_print_var.php b/bundled-libs/Smarty/libs/plugins/modifier.debug_print_var.php
new file mode 100644 (file)
index 0000000..b9bb184
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty debug_print_var modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     debug_print_var<br>
+ * Purpose:  formats variable contents for display in the console
+ * @link http://smarty.php.net/manual/en/language.modifier.debug.print.var.php
+ *          debug_print_var (Smarty online manual)
+ * @param array|object
+ * @param integer
+ * @param integer
+ * @return string
+ */
+function smarty_modifier_debug_print_var($var, $depth = 0, $length = 40)
+{
+    $_replace = array("\n"=>'<i>&#92;n</i>', "\r"=>'<i>&#92;r</i>', "\t"=>'<i>&#92;t</i>');
+    if (is_array($var)) {
+        $results = "<b>Array (".count($var).")</b>";
+        foreach ($var as $curr_key => $curr_val) {
+            $return = smarty_modifier_debug_print_var($curr_val, $depth+1, $length);
+            $results .= "<br>".str_repeat('&nbsp;', $depth*2)."<b>".strtr($curr_key, $_replace)."</b> =&gt; $return";
+        }
+    } else if (is_object($var)) {
+        $object_vars = get_object_vars($var);
+        $results = "<b>".get_class($var)." Object (".count($object_vars).")</b>";
+        foreach ($object_vars as $curr_key => $curr_val) {
+            $return = smarty_modifier_debug_print_var($curr_val, $depth+1, $length);
+            $results .= "<br>".str_repeat('&nbsp;', $depth*2)."<b>$curr_key</b> =&gt; $return";
+        }
+    } else if (is_resource($var)) {
+        $results = '<i>'.(string)$var.'</i>';
+    } else if (empty($var) && $var != "0") {
+        $results = '<i>empty</i>';
+    } else {
+        if (strlen($var) > $length ) {
+            $results = substr($var, 0, $length-3).'...';
+        } else {
+            $results = $var;
+        }
+        $results = htmlspecialchars($results);
+        $results = strtr($results, $_replace);
+    }
+    return $results;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.default.php b/bundled-libs/Smarty/libs/plugins/modifier.default.php
new file mode 100644 (file)
index 0000000..8268e39
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty default modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     default<br>
+ * Purpose:  designate default value for empty variables
+ * @link http://smarty.php.net/manual/en/language.modifier.default.php
+ *          default (Smarty online manual)
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_default($string, $default = '')
+{
+    if (!isset($string) || $string === '')
+        return $default;
+    else
+        return $string;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.escape.php b/bundled-libs/Smarty/libs/plugins/modifier.escape.php
new file mode 100644 (file)
index 0000000..a32a876
--- /dev/null
@@ -0,0 +1,89 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty escape modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     escape<br>
+ * Purpose:  Escape the string according to escapement type
+ * @link http://smarty.php.net/manual/en/language.modifier.escape.php
+ *          escape (Smarty online manual)
+ * @param string
+ * @param html|htmlall|url|quotes|hex|hexentity|javascript
+ * @return string
+ */
+function smarty_modifier_escape($string, $esc_type = 'html')
+{
+    switch ($esc_type) {
+        case 'html':
+            return htmlspecialchars($string, ENT_QUOTES);
+
+        case 'htmlall':
+            return htmlentities($string, ENT_QUOTES);
+
+        case 'url':
+            return rawurlencode($string);
+
+        case 'quotes':
+            // escape unescaped single quotes
+            return preg_replace("%(?<!\\\\)'%", "\\'", $string);
+
+        case 'hex':
+            // escape every character into hex
+            $return = '';
+            for ($x=0; $x < strlen($string); $x++) {
+                $return .= '%' . bin2hex($string[$x]);
+            }
+            return $return;
+            
+        case 'hexentity':
+            $return = '';
+            for ($x=0; $x < strlen($string); $x++) {
+                $return .= '&#x' . bin2hex($string[$x]) . ';';
+            }
+            return $return;
+
+        case 'decentity':
+            $return = '';
+            for ($x=0; $x < strlen($string); $x++) {
+                $return .= '&#' . ord($string[$x]) . ';';
+            }
+            return $return;
+
+        case 'javascript':
+            // escape quotes and backslashes, newlines, etc.
+            return strtr($string, array('\\'=>'\\\\',"'"=>"\\'",'"'=>'\\"',"\r"=>'\\r',"\n"=>'\\n','</'=>'<\/'));
+            
+        case 'mail':
+            // safe way to display e-mail address on a web page
+            return str_replace(array('@', '.'),array(' [AT] ', ' [DOT] '), $string);
+            
+        case 'nonstd':
+           // escape non-standard chars, such as ms document quotes
+           $_res = '';
+           for($_i = 0, $_len = strlen($string); $_i < $_len; $_i++) {
+               $_ord = ord($string{$_i});
+               // non-standard char, escape it
+               if($_ord >= 126){
+                   $_res .= '&#' . $_ord . ';';
+               }
+               else {
+                   $_res .= $string{$_i};
+               }
+           }
+           return $_res;
+
+        default:
+            return $string;
+    }
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.indent.php b/bundled-libs/Smarty/libs/plugins/modifier.indent.php
new file mode 100644 (file)
index 0000000..1642bac
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty indent modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     indent<br>
+ * Purpose:  indent lines of text
+ * @link http://smarty.php.net/manual/en/language.modifier.indent.php
+ *          indent (Smarty online manual)
+ * @param string
+ * @param integer
+ * @param string
+ * @return string
+ */
+function smarty_modifier_indent($string,$chars=4,$char=" ")
+{
+    return preg_replace('!^!m',str_repeat($char,$chars),$string);
+}
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.lower.php b/bundled-libs/Smarty/libs/plugins/modifier.lower.php
new file mode 100644 (file)
index 0000000..0b4d151
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty lower modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     lower<br>
+ * Purpose:  convert string to lowercase
+ * @link http://smarty.php.net/manual/en/language.modifier.lower.php
+ *          lower (Smarty online manual)
+ * @param string
+ * @return string
+ */
+function smarty_modifier_lower($string)
+{
+    return strtolower($string);
+}
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.nl2br.php b/bundled-libs/Smarty/libs/plugins/modifier.nl2br.php
new file mode 100644 (file)
index 0000000..d6fabff
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty plugin
+ *
+ * Type:     modifier<br>
+ * Name:     nl2br<br>
+ * Date:     Feb 26, 2003
+ * Purpose:  convert \r\n, \r or \n to <<br>>
+ * Input:<br>
+ *         - contents = contents to replace
+ *         - preceed_test = if true, includes preceeding break tags
+ *           in replacement
+ * Example:  {$text|nl2br}
+ * @link http://smarty.php.net/manual/en/language.modifier.nl2br.php
+ *          nl2br (Smarty online manual)
+ * @version  1.0
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @param string
+ * @return string
+ */
+function smarty_modifier_nl2br($string)
+{
+    return nl2br($string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.regex_replace.php b/bundled-libs/Smarty/libs/plugins/modifier.regex_replace.php
new file mode 100644 (file)
index 0000000..7eee497
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty regex_replace modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     regex_replace<br>
+ * Purpose:  regular epxression search/replace
+ * @link http://smarty.php.net/manual/en/language.modifier.regex.replace.php
+ *          regex_replace (Smarty online manual)
+ * @param string
+ * @param string|array
+ * @param string|array
+ * @return string
+ */
+function smarty_modifier_regex_replace($string, $search, $replace)
+{
+    if (preg_match('!\W(\w+)$!s', $search, $match) && (strpos($match[1], 'e') !== false)) {
+        /* remove eval-modifier from $search */
+        $search = substr($search, 0, -strlen($match[1])) . str_replace('e', '', $match[1]);
+    }
+    return preg_replace($search, $replace, $string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.replace.php b/bundled-libs/Smarty/libs/plugins/modifier.replace.php
new file mode 100644 (file)
index 0000000..2a43515
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty replace modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     replace<br>
+ * Purpose:  simple search/replace
+ * @link http://smarty.php.net/manual/en/language.modifier.replace.php
+ *          replace (Smarty online manual)
+ * @param string
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_replace($string, $search, $replace)
+{
+    return str_replace($search, $replace, $string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.spacify.php b/bundled-libs/Smarty/libs/plugins/modifier.spacify.php
new file mode 100644 (file)
index 0000000..dad057f
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty spacify modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     spacify<br>
+ * Purpose:  add spaces between characters in a string
+ * @link http://smarty.php.net/manual/en/language.modifier.spacify.php
+ *          spacify (Smarty online manual)
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_spacify($string, $spacify_char = ' ')
+{
+    return implode($spacify_char,
+                   preg_split('//', $string, -1, PREG_SPLIT_NO_EMPTY));
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.string_format.php b/bundled-libs/Smarty/libs/plugins/modifier.string_format.php
new file mode 100644 (file)
index 0000000..efd6215
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty string_format modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     string_format<br>
+ * Purpose:  format strings via sprintf
+ * @link http://smarty.php.net/manual/en/language.modifier.string.format.php
+ *          string_format (Smarty online manual)
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_string_format($string, $format)
+{
+    return sprintf($format, $string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.strip.php b/bundled-libs/Smarty/libs/plugins/modifier.strip.php
new file mode 100644 (file)
index 0000000..cc5c453
--- /dev/null
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty strip modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     strip<br>
+ * Purpose:  Replace all repeated spaces, newlines, tabs
+ *           with a single space or supplied replacement string.<br>
+ * Example:  {$var|strip} {$var|strip:"&nbsp;"}
+ * Date:     September 25th, 2002
+ * @link http://smarty.php.net/manual/en/language.modifier.strip.php
+ *          strip (Smarty online manual)
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @version  1.0
+ * @param string
+ * @param string
+ * @return string
+ */
+function smarty_modifier_strip($text, $replace = ' ')
+{
+    return preg_replace('!\s+!', $replace, $text);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.strip_tags.php b/bundled-libs/Smarty/libs/plugins/modifier.strip_tags.php
new file mode 100644 (file)
index 0000000..45f1ec1
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty strip_tags modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     strip_tags<br>
+ * Purpose:  strip html tags from text
+ * @link http://smarty.php.net/manual/en/language.modifier.strip.tags.php
+ *          strip_tags (Smarty online manual)
+ * @param string
+ * @param boolean
+ * @return string
+ */
+function smarty_modifier_strip_tags($string, $replace_with_space = true)
+{
+    if ($replace_with_space)
+        return preg_replace('!<[^>]*?>!', ' ', $string);
+    else
+        return strip_tags($string);
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.truncate.php b/bundled-libs/Smarty/libs/plugins/modifier.truncate.php
new file mode 100644 (file)
index 0000000..15a26ba
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty truncate modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     truncate<br>
+ * Purpose:  Truncate a string to a certain length if necessary,
+ *           optionally splitting in the middle of a word, and
+ *           appending the $etc string.
+ * @link http://smarty.php.net/manual/en/language.modifier.truncate.php
+ *          truncate (Smarty online manual)
+ * @param string
+ * @param integer
+ * @param string
+ * @param boolean
+ * @return string
+ */
+function smarty_modifier_truncate($string, $length = 80, $etc = '...',
+                                  $break_words = false)
+{
+    if ($length == 0)
+        return '';
+
+    if (strlen($string) > $length) {
+        $length -= strlen($etc);
+        if (!$break_words)
+            $string = preg_replace('/\s+?(\S+)?$/', '', substr($string, 0, $length+1));
+      
+        return substr($string, 0, $length).$etc;
+    } else
+        return $string;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.upper.php b/bundled-libs/Smarty/libs/plugins/modifier.upper.php
new file mode 100644 (file)
index 0000000..69960ae
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty upper modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     upper<br>
+ * Purpose:  convert string to uppercase
+ * @link http://smarty.php.net/manual/en/language.modifier.upper.php
+ *          upper (Smarty online manual)
+ * @param string
+ * @return string
+ */
+function smarty_modifier_upper($string)
+{
+    return strtoupper($string);
+}
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/modifier.wordwrap.php b/bundled-libs/Smarty/libs/plugins/modifier.wordwrap.php
new file mode 100644 (file)
index 0000000..b9a9fe9
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Smarty wordwrap modifier plugin
+ *
+ * Type:     modifier<br>
+ * Name:     wordwrap<br>
+ * Purpose:  wrap a string of text at a given length
+ * @link http://smarty.php.net/manual/en/language.modifier.wordwrap.php
+ *          wordwrap (Smarty online manual)
+ * @param string
+ * @param integer
+ * @param string
+ * @param boolean
+ * @return string
+ */
+function smarty_modifier_wordwrap($string,$length=80,$break="\n",$cut=false)
+{
+    return wordwrap($string,$length,$break,$cut);
+}
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/outputfilter.trimwhitespace.php b/bundled-libs/Smarty/libs/plugins/outputfilter.trimwhitespace.php
new file mode 100644 (file)
index 0000000..01e35e0
--- /dev/null
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Smarty plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+/**
+ * Smarty trimwhitespace outputfilter plugin
+ *
+ * File:     outputfilter.trimwhitespace.php<br>
+ * Type:     outputfilter<br>
+ * Name:     trimwhitespace<br>
+ * Date:     Jan 25, 2003<br>
+ * Purpose:  trim leading white space and blank lines from
+ *           template source after it gets interpreted, cleaning
+ *           up code and saving bandwidth. Does not affect
+ *           <<PRE>></PRE> and <SCRIPT></SCRIPT> blocks.<br>
+ * Install:  Drop into the plugin directory, call
+ *           <code>$smarty->load_filter('output','trimwhitespace');</code>
+ *           from application.
+ * @author   Monte Ohrt <monte at ohrt dot com>
+ * @author Contributions from Lars Noschinski <lars@usenet.noschinski.de>
+ * @version  1.3
+ * @param string
+ * @param Smarty
+ */
+function smarty_outputfilter_trimwhitespace($source, &$smarty)
+{
+    // Pull out the script blocks
+    preg_match_all("!<script[^>]+>.*?</script>!is", $source, $match);
+    $_script_blocks = $match[0];
+    $source = preg_replace("!<script[^>]+>.*?</script>!is",
+                           '@@@SMARTY:TRIM:SCRIPT@@@', $source);
+
+    // Pull out the pre blocks
+    preg_match_all("!<pre>.*?</pre>!is", $source, $match);
+    $_pre_blocks = $match[0];
+    $source = preg_replace("!<pre>.*?</pre>!is",
+                           '@@@SMARTY:TRIM:PRE@@@', $source);
+
+    // Pull out the textarea blocks
+    preg_match_all("!<textarea[^>]+>.*?</textarea>!is", $source, $match);
+    $_textarea_blocks = $match[0];
+    $source = preg_replace("!<textarea[^>]+>.*?</textarea>!is",
+                           '@@@SMARTY:TRIM:TEXTAREA@@@', $source);
+
+    // remove all leading spaces, tabs and carriage returns NOT
+    // preceeded by a php close tag.
+    $source = trim(preg_replace('/((?<!\?>)\n)[\s]+/m', '\1', $source));
+
+    // replace script blocks
+    smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:SCRIPT@@@",$_script_blocks, $source);
+
+    // replace pre blocks
+    smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:PRE@@@",$_pre_blocks, $source);
+
+    // replace textarea blocks
+    smarty_outputfilter_trimwhitespace_replace("@@@SMARTY:TRIM:TEXTAREA@@@",$_textarea_blocks, $source);
+
+    return $source;
+}
+
+function smarty_outputfilter_trimwhitespace_replace($search_str, $replace, &$subject) {
+    $_len = strlen($search_str);
+    $_pos = 0;
+    for ($_i=0, $_count=count($replace); $_i<$_count; $_i++)
+        if (($_pos=strpos($subject, $search_str, $_pos))!==false)
+            $subject = substr_replace($subject, $replace[$_i], $_pos, $_len);
+        else
+            break;
+
+}
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/shared.escape_special_chars.php b/bundled-libs/Smarty/libs/plugins/shared.escape_special_chars.php
new file mode 100644 (file)
index 0000000..515763a
--- /dev/null
@@ -0,0 +1,30 @@
+<?php
+/**
+ * Smarty shared plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * escape_special_chars common function
+ *
+ * Function: smarty_function_escape_special_chars<br>
+ * Purpose:  used by other smarty functions to escape
+ *           special chars except for already escaped ones
+ * @param string
+ * @return string
+ */
+function smarty_function_escape_special_chars($string)
+{
+    if(!is_array($string)) {
+        $string = preg_replace('!&(#?\w+);!', '%%%SMARTY_START%%%\\1%%%SMARTY_END%%%', $string);
+        $string = htmlspecialchars($string);
+        $string = str_replace(array('%%%SMARTY_START%%%','%%%SMARTY_END%%%'), array('&',';'), $string);
+    }
+    return $string;
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Smarty/libs/plugins/shared.make_timestamp.php b/bundled-libs/Smarty/libs/plugins/shared.make_timestamp.php
new file mode 100644 (file)
index 0000000..acdd777
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Smarty shared plugin
+ * @package Smarty
+ * @subpackage plugins
+ */
+
+
+/**
+ * Function: smarty_make_timestamp<br>
+ * Purpose:  used by other smarty functions to make a timestamp
+ *           from a string.
+ * @param string
+ * @return string
+ */
+function smarty_make_timestamp($string)
+{
+    if(empty($string)) {
+        $string = "now";
+    }
+    $time = strtotime($string);
+    if (is_numeric($time) && $time != -1)
+        return $time;
+
+    // is mysql timestamp format of YYYYMMDDHHMMSS?
+    if (preg_match('/^\d{14}$/', $string)) {
+        $time = mktime(substr($string,8,2),substr($string,10,2),substr($string,12,2),
+               substr($string,4,2),substr($string,6,2),substr($string,0,4));
+
+        return $time;
+    }
+
+    // couldn't recognize it, try to return a time
+    $time = (int) $string;
+    if ($time > 0)
+        return $time;
+    else
+        return time();
+}
+
+/* vim: set expandtab: */
+
+?>
diff --git a/bundled-libs/Text/Wiki.php b/bundled-libs/Text/Wiki.php
new file mode 100644 (file)
index 0000000..72f805e
--- /dev/null
@@ -0,0 +1,557 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: Wiki.php,v 1.3 2004/12/02 10:54:30 nohn Exp $
+
+require_once 'Text/Wiki/Rule.php';
+
+
+/**
+* 
+* This is the "master" class for handling the management and convenience
+* functions to transform Wiki-formatted text.
+* 
+* @author Paul M. Jones <pmjones@ciaweb.net>
+* 
+* @version 0.15 alpha
+* 
+*/
+
+class Text_Wiki {
+       
+       
+       /**
+       * 
+       * The array of rules to apply to the source text, in order.
+       * 
+       * @access public
+       * 
+       * @var array
+       * 
+       */
+       
+       var $rules = array();
+
+
+       /**
+       * 
+       * The delimiter that surrounds a token number embedded in the source
+       * wiki text.
+       * 
+       * @access public
+       * 
+       * @var string
+       * 
+       */
+       
+       var $delim = "\xFF"; 
+       
+       
+       /**
+       * 
+       * An array of tokens generated by rules as the source text is
+       * parsed.
+       * 
+       * As Text_Wiki applies rule classes to the source text, it will
+       * replace portions of the text with a delimited token number.  This
+       * is the array of those tokens, representing the replaced text and
+       * any options set by the parser for that replaced text.
+       * 
+       * The tokens array is seqential; each element is itself a sequential
+       * array where element 0 is the name of the rule that generated the
+       * token, and element 1 is an associative array where the key is an
+       * option name and the value is an option value.
+       * 
+       * @access private
+       * 
+       * @var string
+       * 
+       */
+       
+       var $_tokens = array();
+       
+       
+       /**
+       * 
+       * The source text to which rules will be applied.  This text will be
+       * transformed in-place, which means that it will change as the rules
+       * are applied.
+       * 
+       * @access private
+       * 
+       * @var string
+       * 
+       */
+       
+       var $_source = '';
+       
+       
+       /**
+       * 
+       * Text_Wiki creates one instance of every rule that is applied to
+       * the source text; this array holds those instances.  The array key
+       * is the rule name, and the array value is an instance of the rule
+       * class.
+       * 
+       * @access private
+       * 
+       * @var string
+       * 
+       */
+       
+       var $_rule_obj = array();
+       
+       
+       /**
+       * 
+       * Constructor.  Loads the rule objects.
+       * 
+       * @access public
+       * 
+       * @param array $rules The set of rules to load for this object.
+       *        
+       */
+       
+       function Text_Wiki($rules = null)
+       {
+               // set up the list of rules
+               if (is_array($rules)) {
+                       $this->rules = $rules;
+               }
+       }
+       
+       
+       /**
+       * 
+       * Inserts a rule into to the rule set.
+       * 
+       * @access public
+       * 
+       * @param string $key The key name for the rule.  Should be different from
+       * all other keys in the rule set.
+       * 
+       * @param string $val The rule values; should be an associative array with 
+       * the keys 'file', 'name', 'flag', and 'conf'.
+       * 
+       * @param string $tgt The rule after which to insert this new rule.  By
+       * default (null) the rule is inserted at the end; if set to '', inserts
+       * at the beginning.
+       * 
+       * @return void
+       * 
+       */
+       
+       function insertRule($key, $val, $tgt = null)
+       {
+               // does the rule key to be inserted already exist?
+               if (isset($this->rules[$key])) {
+                       // yes, return
+                       return false;
+               }
+               
+               // the target name is not null, not '', but does not exist. this
+               // means we're trying to insert after a target key, but the
+               // target key isn't there.
+               if (! is_null($tgt) && $tgt != '' && ! isset($this->rules[$tgt])) {
+                       return false;
+               }
+               
+               // if $tgt is null, insert at the end.  We know this is at the
+               // end (instead of resetting an existing rule) becuase we exited
+               // at the top of this method if the rule was already in place.
+               if (is_null($tgt)) {
+                       $this->rules[$key] = $val;
+                       return true;
+               }
+               
+               // save a copy of the current rules, then reset the rule set
+               // so we can insert in the proper place later.
+               $tmp = $this->rules;
+               $this->rules = array();
+               
+               // where to insert the rule?
+               if ($tgt == '') {
+                       // insert at the beginning
+                       $this->rules[$key] = $val;
+                       foreach ($tmp as $k => $v) {
+                               $this->rules[$k] = $v;
+                       }
+                       return true;
+               } else {
+                       // insert after the named rule
+                       foreach ($tmp as $k => $v) {
+                               $this->rules[$k] = $v;
+                               if ($k == $tgt) {
+                                       $this->rules[$key] = $val;
+                               }
+                       }
+               }
+               return true;
+       }
+       
+       
+       /**
+       * 
+       * Delete (remove or unset) a rule from the $rules property.
+       * 
+       * @access public
+       * 
+       * @param string $rule The name of the rule to remove.
+       * 
+       * @return void
+       *        
+       */
+       
+       function deleteRule($key)
+       {
+               unset($this->rules[$key]);
+       }
+       
+       
+       /**
+       * 
+       * Sets the value of a rule's configuration keys.
+       * 
+       * @access public
+       * 
+       * @param string $rule The name of the rule for which to set
+       * configuration keys.
+       * 
+       * @param array|string $arg1 If an array, sets the entire 'conf' key
+       * for the rule; if a string, specifies which 'conf' subkey to set.
+       * 
+       * @param mixed $arg2 If $arg1 is a string, the 'conf' subkey
+       * specified by $arg1 is set to this value.
+       * 
+       * @return void
+       *        
+       */
+       
+       function setRuleConf($rule, $arg1, $arg2 = null)
+       {
+               if (! isset($this->rules[$rule])) {
+                       return;
+               }
+               
+               if (! isset($this->rules[$rule]['conf'])) {
+                       $this->rules[$rule]['conf'] = array();
+               }
+               
+               if (is_array($arg1)) {
+                       $this->rules[$rule]['conf'] = $arg1;
+               } else {
+                       $this->rules[$rule]['conf'][$arg1] = $arg2;
+               }
+       }
+       
+       
+       /**
+       * 
+       * Sets the value of a rule's configuration keys.
+       * 
+       * @access public
+       * 
+       * @param string $rule The name of the rule from which to get
+       * configuration keys.
+       * 
+       * @param string $key Which 'conf' subkey to retrieve.  If null,
+       * gets the entire 'conf' key for the rule.
+       * 
+       * @return void
+       *        
+       */
+       
+       function getRuleConf($rule, $key = null)
+       {
+               if (! isset($this->rules[$rule])) {
+                       return null;
+               }
+               
+               if (! isset($this->rules[$rule]['conf'])) {
+                       $this->rules[$rule]['conf'] = array();
+               }
+               
+               if (is_null($key)) {
+                       return $this->rules[$rule]['conf'];
+               }
+               
+               if (! isset($this->rules[$rule]['conf'][$key])) {
+                       return null;
+               } else {
+                       return $this->rules[$rule]['conf'][$key];
+               }
+               
+       }
+       
+       
+       /**
+       * 
+       * Enables a rule so that it is applied when parsing.
+       * 
+       * @access public
+       * 
+       * @param string $rule The name of the rule to enable.
+       * 
+       * @return void
+       *        
+       */
+       
+       function enableRule($rule)
+       {
+               if (isset($this->rules[$rule])) {
+                       $this->rules[$rule]['flag'] = true;
+               }
+       }
+       
+       
+       /**
+       * 
+       * Disables a rule so that it is not applied when parsing.
+       * 
+       * @access public
+       * 
+       * @param string $rule The name of the rule to disable.
+       * 
+       * @return void
+       *        
+       */
+       
+       function disableRule($rule)
+       {
+               if (isset($this->rules[$rule])) {
+                       $this->rules[$rule]['flag'] = false;
+               }
+       }
+       
+       
+       /**
+       * 
+       * Parses and renders the text passed to it, and returns the results.
+       * 
+       * First, the method parses the source text, applying rules to the
+       * text as it goes.  These rules will modify the source text
+       * in-place, replacing some text with delimited tokens (and
+       * populating the $this->_tokens array as it goes).
+       * 
+       * Next, the method renders the in-place tokens into the requested
+       * output format.
+       * 
+       * Finally, the method returns the transformed text.  Note that the
+       * source text is transformed in place; once it is transformed, it is
+       * no longer the same as the original source text.
+       * 
+       * @access public
+       * 
+       * @param string $text The source text to which wiki rules should be
+       * applied, both for parsing and for rendering.
+       * 
+       * @param string $format The target output format, typically 'xhtml'.
+       *  If a rule does not support a given format, the output from that
+       * rule is rule-specific.
+       * 
+       * @return string The transformed wiki text.
+       * 
+       */
+       
+       function transform($text, $format = 'Xhtml')
+       {
+               $this->parse($text);
+               return $this->render($format);
+       }
+       
+       
+       /**
+       * 
+       * Sets the $_source text property, then parses it in place and
+       * retains tokens in the $_tokens array property.
+       * 
+       * @access public
+       * 
+       * @param string $text The source text to which wiki rules should be
+       * applied, both for parsing and for rendering.
+       * 
+       * @return void
+       * 
+       */
+       
+       function parse($text)
+       {
+               // set the object property for the source text
+               $this->_source = $text;
+               
+               // apply the parse() method of each requested rule to the source
+               // text.
+               foreach ($this->rules as $key => $val) {
+                       // if flag is not set to 'true' (active),
+                       // do not parse under this rule.  assume
+                       // that if a rule exists, but has no flag,
+                       // that it wants to be parsed with.
+                       if (! isset($val['flag']) || $val['flag'] == true) {
+                               $this->_loadRuleObject($key);
+                               $this->_rule_obj[$key]->parse();
+                       }
+               }
+       }
+       
+       
+       /**
+       * 
+       * Renders tokens back into the source text, based on the requested format.
+       * 
+       * @access public
+       * 
+       * @param string $format The target output format, typically 'xhtml'.
+       *  If a rule does not support a given format, the output from that
+       * rule is rule-specific.
+       * 
+       * @return string The transformed wiki text.
+       * 
+       */
+       
+       function render($format = 'Xhtml')
+       {
+               // the rendering method we're going to use from each rule
+               $method = "render$format";
+               
+               // the eventual output text
+               $output = '';
+               
+               // when passing through the parsed source text, keep track of when
+               // we are in a delimited section
+               $in_delim = false;
+               
+               // when in a delimited section, capture the token key number
+               $key = '';
+               
+               // pass through the parsed source text character by character
+               $k = strlen($this->_source);
+               for ($i = 0; $i < $k; $i++) {
+                       
+                       // the current character
+                       $char = $this->_source{$i};
+                       
+                       // are alredy in a delimited section?
+                       if ($in_delim) {
+                       
+                               // yes; are we ending the section?
+                               if ($char == $this->delim) {
+                                       
+                                       // yes, get the replacement text for the delimited
+                                       // token number and unset the flag.
+                                       $key = (int)$key;
+                                       $rule = $this->_tokens[$key][0];
+                                       $opts = $this->_tokens[$key][1];
+                                       $output .= $this->_rule_obj[$rule]->$method($opts);
+                                       $in_delim = false;
+                                       
+                               } else {
+                               
+                                       // no, add to the dlimited token key number
+                                       $key .= $char;
+                                       
+                               }
+                               
+                       } else {
+                               
+                               // not currently in a delimited section.
+                               // are we starting into a delimited section?
+                               if ($char == $this->delim) {
+                                       // yes, reset the previous key and
+                                       // set the flag.
+                                       $key = '';
+                                       $in_delim = true;
+                               } else {
+                                       // no, add to the output as-is
+                                       $output .= $char;
+                               }
+                       }
+               }
+               
+               // return the rendered source text
+               return $output;
+       }
+       
+       
+       /**
+       * 
+       * Returns the parsed source text with delimited token placeholders.
+       * 
+       * @access public
+       * 
+       * @return string The parsed source text.
+       * 
+       */
+       
+       function getSource()
+       {
+               return $this->_source;
+       }
+       
+       
+       /**
+       * 
+       * Returns tokens that have been parsed out of the source text.
+       * 
+       * @access public
+       * 
+       * @param array $rules If an array of rule names is passed, only return
+       * tokens matching these rule names.  If no array is passed, return all
+       * tokens.
+       * 
+       * @return array An array of tokens.
+       * 
+       */
+       
+       function getTokens($rules = null)
+       {
+               if (is_null($rules)) {
+                       return $this->_tokens;
+               } else {
+                       settype($rules, 'array');
+                       $result = array();
+                       foreach ($this->_tokens as $key => $val) {
+                               if (in_array($val[0], $rules)) {
+                                       $result[] = $val;
+                               }
+                       }
+                       return $result;
+               }
+       }
+       
+       
+       /**
+       * 
+       * Loads a rule class file and creates an instance of it.
+       * 
+       * @access public
+       * 
+       * @return void
+       * 
+       */
+       
+       function _loadRuleObject($key)
+       {
+               $name = $this->rules[$key]['name'];
+               if (! class_exists($name)) {
+                       include_once $this->rules[$key]['file'];
+               }
+               $this->_rule_obj[$key] =& new $name($this, $key);
+       }
+}
+
+?>
diff --git a/bundled-libs/Text/Wiki/Rule.php b/bundled-libs/Text/Wiki/Rule.php
new file mode 100644 (file)
index 0000000..bdfe865
--- /dev/null
@@ -0,0 +1,345 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: Rule.php,v 1.3 2004/12/02 10:54:31 nohn Exp $
+
+/**
+* 
+* Baseline rule class for extension into a "real" wiki rule.
+* 
+* Text_Wiki_Rule classes do not stand on their own; they are called by a
+* Text_Wiki object, typcially in the transform()method. Each rule class
+* performs three main activities: parse, process, and render.
+* 
+* The parse() method takes a regex and applies it to the whole block of
+* source text at one time. Each match is sent as $matches to the
+* process() method.
+* 
+* The process() method acts on the matched text from the source, and
+* then processes the source text is some way.  This may mean the
+* creation of a delimited token using addToken().  In every case, the
+* process() method returns the text that should replace the matched text
+* from parse().
+* 
+* Finally, the render*() methods take any token created by the rule and
+* creates output text matching a specific format.  Individual rules may
+* or may not have options for specific formats.
+*
+* Typically, the extended rule only needs to define the process() and
+* render() methods; the parse() method is generally the same from rule
+* to rule, and has been included here.  However, there is no reason that
+* rules cannot override these methods, so long as the new methods operate
+* in substantially the same manner; similarly, the rule need not generate
+* any tokens at all, and may use a specialized parse() method to filter
+* the source text.  See the default rule classes for many examples.
+* 
+* @author Paul M. Jones <pmjones@ciaweb.net>
+* 
+* @package Text_Wiki
+* 
+*/
+
+class Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex = null;
+    
+    
+    /**
+    * 
+    * A reference to the calling Text_Wiki object.  This is needed so
+    * that each rule has access to the same source text, token set,
+    * URLs, interwiki maps, page names, etc.
+    * 
+    * @access public
+    * 
+    * @var object
+    */
+    
+    var $_wiki = null;
+    
+    
+    /**
+    * 
+    * The name of this rule; used when inserting new token array
+    * elements.
+    * 
+    * @access private
+    * 
+    * @var string
+    * 
+    */
+    
+    var $_rule = null;
+    
+    
+    /**
+    * 
+    * Configuration options for this rule.
+    * 
+    * @access private
+    * 
+    * @var string
+    * 
+    */
+    
+    var $_conf = null;
+    
+    
+    /**
+    * 
+    * Constructor for the rule.
+    * 
+    * @access public
+    * 
+    * @param object &$obj The calling "parent" Text_Wiki object.
+    * 
+    * @param string $name The token name to use for this rule.
+    * 
+    */
+    
+    function Text_Wiki_Rule(&$obj, $name)
+    {
+        // set the reference to the calling Text_Wiki object;
+        // this allows us access to the shared source text, token
+        // array, etc.
+        $this->_wiki =& $obj;
+        
+        // set the name of this rule; generally used when adding
+        // to the tokens array.
+        $this->_rule = $name;
+        
+        // config options reference
+        $this->_conf =& $this->_wiki->rules[$this->_rule]['conf'];
+    }
+    
+    
+    /**
+    * 
+    * Add a token to the Text_Wiki tokens array, and return a delimited
+    * token number.
+    * 
+    * @access public
+    * 
+    * @param array $options An associative array of options for the new
+    * token array element.  The keys and values are specific to the
+    * rule, and may or may not be common to other rule options.  Typical
+    * options keys are 'text' and 'type' but may include others.
+    * 
+    * @param boolean $id_only If true, return only the token number, not
+    * a delimited token string.
+    * 
+    * @return string|int By default, return the number of the
+    * newly-created token array element with a delimiter prefix and
+    * suffix; however, if $id_only is set to true, return only the token
+    * number (no delimiters).
+    * 
+    */
+    
+    function addToken($options = array(), $id_only = false)
+    {
+        // force the options to be an array
+        settype($options, 'array');
+        
+        // find the next token number
+        $id = count($this->_wiki->_tokens);
+        
+        // add the token
+        $this->_wiki->_tokens[$id] = array(
+            0 => $this->_rule,
+            1 => $options
+        );
+        
+        // return a value
+        if ($id_only) {
+            // return the last token number
+            return $id;
+        } else {
+            // return the token number with delimiters
+            return $this->_wiki->delim . $id . $this->_wiki->delim;
+        }
+    }
+    
+    
+    /**
+    * 
+    * Set or re-set a token with specific information, overwriting any
+    * previous rule name and rule options.
+    * 
+    * @access public
+    * 
+    * @param int $id The token number to reset.
+    * 
+    * @param int $rule The rule name to use; by default, use the current
+    * rule name, although you can specify any rule.
+    * 
+    * @param array $options An associative array of options for the
+    * token array element.  The keys and values are specific to the
+    * rule, and may or may not be common to other rule options.  Typical
+    * options keys are 'text' and 'type' but may include others.
+    * 
+    * @return void
+    * 
+    */
+    
+    function setToken($id, $rule = null, $options = array())
+    {
+        // get a rule name
+        if (is_null($rule)) {
+            $rule = $this->_rule;
+        }
+        
+        // reset the token
+        $this->_wiki->_tokens[$id] = array(
+            0 => $rule,
+            1 => $options
+        );
+    }
+    
+    
+    /**
+    * 
+    * Simple parsing method to apply the rule's regular expression to
+    * the source text, pass every match to the process() method, and
+    * replace the matched text with the results of the processing.
+    *
+    * @access public
+    * 
+    */
+    
+    function parse()
+    {
+        $this->_wiki->_source = preg_replace_callback(
+            $this->regex,
+            array(&$this, 'process'),
+            $this->_wiki->_source
+        );
+    }
+    
+    
+    /**
+    * 
+    * Simple processing mathod to take matched text and generate
+    * replacement text. This is one of the methods you will definitely
+    * want to override in your rule class extensions.
+    * 
+    * @access public
+    * 
+    * @param array $matches An array of matches from the parse() method
+    * as generated by preg_replace_callback.  $matches[0] is the full
+    * matched string, $matches[1] is the first matched pattern,
+    * $matches[2] is the second matched pattern, and so on.
+    * 
+    * @return string The processed text replacement; defaults to the
+    * full matched string (i.e., no changes to the text).
+    * 
+    */
+    
+    function process(&$matches)
+    {
+        return $matches[0];
+    }
+    
+    
+    /**
+    * 
+    * Simple rendering method to take a set of token options and
+    * generate replacement text for it.  This is another method you will
+    * definitely want to override in your rule subclass extensions.
+    *
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second element).
+    * 
+    * @return string The text rendered from the token options; by default,
+    * no text is returned.  You should change this in your subclass.  ;-)
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        return '';
+    }
+    
+    
+    /**
+    * 
+       * Simple method to extract 'option="value"' portions of wiki markup,
+       * typically used only in macros.
+       * 
+       * The syntax is pretty strict; there can be no spaces between the
+       * option name, the equals, and the first double-quote; the value
+       * must be surrounded by double-quotes.  You can escape characters in
+       * the value with a backslash, and the backslash will be stripped for
+       * you.
+       * 
+       * @access public
+       * 
+       * @param string $text The "macro options" portion of macro markup.
+       * 
+       * @return array An associative array of key-value pairs where the
+       * key is the option name and the value is the option value.
+    * 
+    */
+    
+    function getMacroArgs($text)
+    {
+       // find the =" sections;
+               $tmp = explode('="', trim($text));
+               
+               // basic setup
+               $k = count($tmp) - 1;
+               $arg = array();
+               $key = null;
+               
+               // loop through the sections
+               foreach ($tmp as $i => $val) {
+                       
+                       // first element is always the first key
+                       if ($i == 0) {
+                               $key = trim($val);
+                               continue;
+                       }
+                       
+                       // find the last double-quote in the value.
+                       // the part to the left is the value for the last key,
+                       // the part to the right is the next key name
+                       $pos = strrpos($val, '"');
+                       $arg[$key] = stripslashes(substr($val, 0, $pos));
+                       $key = trim(substr($val, $pos+1));
+                       
+               }
+               
+               return $arg;
+               
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/blockquote.php b/bundled-libs/Text/Wiki/Rule/blockquote.php
new file mode 100644 (file)
index 0000000..b777dbd
--- /dev/null
@@ -0,0 +1,209 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: blockquote.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked as a
+* blockquote, identified by any number of greater-than signs '>' at the
+* start of the line, followed by a space, and then the quote text; each
+* '>' indicates an additional level of quoting.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_blockquote extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex = '/\n((\>).*\n)(?!(\>))/Us';
+    
+    
+    /**
+    * 
+    * Generates a replacement for the matched text.  Token options are:
+    * 
+    * 'type' =>
+    *     'start' : the start of a blockquote
+    *     'end'   : the end of a blockquote
+    *
+    * 'level' => the indent level (0 for the first level, 1 for the
+    * second, etc)
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A series of text and delimited tokens marking the different
+    * list text and list elements.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        // the replacement text we will return to parse()
+        $return = '';
+        
+        // the list of post-processing matches
+        $list = array();
+        
+        // $matches[1] is the text matched as a list set by parse();
+        // create an array called $list that contains a new set of
+        // matches for the various list-item elements.
+        preg_match_all(
+            '=^(\>+) (.*\n)=Ums',
+            $matches[1],
+            $list,
+            PREG_SET_ORDER
+        );
+        
+        // a stack of starts and ends; we keep this so that we know what
+        // indent level we're at.
+        $stack = array();
+        
+        // loop through each list-item element.
+        foreach ($list as $key => $val) {
+            
+            // $val[0] is the full matched list-item line
+            // $val[1] is the number of initial '>' chars (indent level)
+            // $val[2] is the quote text
+            
+            // we number levels starting at 1, not zero
+            $level = strlen($val[1]);
+            
+            // get the text of the line
+            $text = $val[2];
+            
+            // add a level to the list?
+            if ($level > count($stack)) {
+                
+                // the current indent level is greater than the number
+                // of stack elements, so we must be starting a new
+                // level.  push the new level onto the stack with a 
+                // dummy value (boolean true)...
+                array_push($stack, true);
+                
+                $return .= "\n";
+                
+                // ...and add a start token to the return.
+                $return .= $this->addToken(
+                    array(
+                        'type' => 'start',
+                        'level' => $level - 1
+                    )
+                );
+                
+                $return .= "\n\n";
+            }
+            
+            // remove a level?
+            while (count($stack) > $level) {
+                
+                // as long as the stack count is greater than the
+                // current indent level, we need to end list types.
+                // continue adding end-list tokens until the stack count
+                // and the indent level are the same.
+                array_pop($stack);
+                
+                $return .= "\n\n";
+                
+                $return .= $this->addToken(
+                    array (
+                        'type' => 'end',
+                        'level' => count($stack)
+                    )
+                );
+                
+                $return .= "\n";
+            }
+            
+            // add the line text.
+            $return .= $text;
+        }
+        
+        // the last line may have been indented.  go through the stack
+        // and create end-tokens until the stack is empty.
+        $return .= "\n";
+        
+        while (count($stack) > 0) {
+            array_pop($stack);
+            $return .= $this->addToken(
+                array (
+                    'type' => 'end',
+                    'level' => count($stack)
+                )
+            );
+        }
+        
+        // we're done!  send back the replacement text.
+        return "$return\n";
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        $type = $options['type'];
+        $level = $options['level'];
+       
+               // set up indenting so that the results look nice; we do this
+               // in two steps to avoid str_pad mathematics.  ;-)
+               $pad = str_pad('', $level, "\t");
+               $pad = str_replace("\t", '    ', $pad);
+               
+               // starting
+               if ($type == 'start') {
+                       return "$pad<blockquote>";
+               }
+               
+               // ending
+               if ($type == 'end') {
+                       return $pad . "</blockquote>\n";
+               }
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/bold.php b/bundled-libs/Text/Wiki/Rule/bold.php
new file mode 100644 (file)
index 0000000..4155b98
--- /dev/null
@@ -0,0 +1,103 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: bold.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked for
+* strong emphasis (bold) as defined by text surrounded by three
+* single-quotes. On parsing, the text itself is left in place, but the
+* starting and ending instances of three single-quotes are replaced with
+* tokens.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_bold extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex =  "/'''(()|[^'].*)'''/U";
+    
+    
+    /**
+    * 
+    * Generates a replacement for the matched text.  Token options are:
+    * 
+    * 'type' => ['start'|'end'] The starting or ending point of the
+    * emphasized text.  The text itself is left in the source.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A pair of delimited tokens to be used as a placeholder in
+    * the source text surrounding the text to be emphasized.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        $start = $this->addToken(array('type' => 'start'));
+        $end = $this->addToken(array('type' => 'end'));
+        return $start . $matches[1] . $end;
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        if ($options['type'] == 'start') {
+            return '<b>';
+        }
+        
+        if ($options['type'] == 'end') {
+            return '</b>';
+        }
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/break.php b/bundled-libs/Text/Wiki/Rule/break.php
new file mode 100644 (file)
index 0000000..fcc7413
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: break.php,v 1.2 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to mark forced line breaks in the
+* source text.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_break extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex = '/ _\n/';
+    
+    
+    /**
+    * 
+    * Generates a replacement token for the matched text.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return string A delimited token to be used as a placeholder in
+    * the source text.
+    *
+    */
+    
+    function process(&$matches)
+    {    
+        return $this->addToken();
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        return "<br />\n";
+    }
+}
+
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/center.php b/bundled-libs/Text/Wiki/Rule/center.php
new file mode 100644 (file)
index 0000000..49aef0c
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: center.php,v 1.2 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find lines marked for centering.
+* The line must start with "= " (i.e., an equal-sign followed by a space).
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_center extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to find source text matching this
+    * rule.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    */
+    
+    //var $regex = '/\n(\<center\>)\n(.+)\n(\<\/center\>)\n/Umsi';
+    var $regex = '/\n\= (.*?)\n/';
+    
+    /**
+    * 
+    * Generates a token entry for the matched text.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A delimited token number to be used as a placeholder in
+    * the source text.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        $start = $this->addToken(array('type' => 'start'));
+        $end = $this->addToken(array('type' => 'end'));
+        //return "\n" . $start . "\n" . $matches[2] . "\n\n" . $end . "\n";
+        return "\n" . $start . $matches[1] . $end . "\n";
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+       if ($options['type'] == 'start') {
+               //return "\n<center>\n";
+               return '<div style="text-align: center;">';
+       }
+       
+       if ($options['type'] == 'end') {
+               //return "</center>\n";
+               return '</div>';
+       }
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/code.php b/bundled-libs/Text/Wiki/Rule/code.php
new file mode 100644 (file)
index 0000000..3526ee8
--- /dev/null
@@ -0,0 +1,177 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: code.php,v 1.4 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find sections marked as code
+* examples.  Blocks are marked as the string <code> on a line by itself,
+* followed by the inline code example, and terminated with the string
+* </code> on a line by itself.  The code example is run through the
+* native PHP highlight_string() function to colorize it, then surrounded
+* with <pre>...</pre> tags when rendered as XHTML.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_code extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to find source text matching this
+    * rule.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    */
+    
+    var $regex = '/^(\<code( .+)?\>)\n(.+)\n(\<\/code\>)(\s|$)/Umsi';
+    
+    
+    /**
+    * 
+    * Generates a token entry for the matched text.  Token options are:
+    * 
+    * 'text' => The full matched text, not including the <code></code> tags.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A delimited token number to be used as a placeholder in
+    * the source text.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        // are there additional arguments?
+        $args = trim($matches[2]);
+        
+        if ($args == '') {
+            $options = array(
+                'text' => $matches[3],
+                'args' => array('type' => '')
+            );
+        } else {
+            $options = array(
+                'text' => $matches[3],
+                'args' => $this->getMacroArgs($args)
+            );
+        }
+        
+        return $this->addToken($options) . $matches[5];
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        // trim opening and closing whitespace
+        $text = trim($options['text']);
+        $args = $options['args'];
+        
+        if (strtolower($args['type']) == 'php') {
+               
+               // PHP code example
+               
+            // add the PHP tags
+            $text = "<?php\n" . $options['text'] . "\n?>"; // <?php
+            
+            // convert tabs to four spaces
+            $text = str_replace("\t", "    ", $text);
+            
+            // colorize the code block (also converts HTML entities and adds
+            // <code>...</code> tags)
+            ob_start();
+            highlight_string($text);
+            $text = ob_get_contents();
+            ob_end_clean();
+            
+            // replace <br /> tags with simple newlines
+            //$text = str_replace("<br />", "\n", $text);
+            
+            // replace non-breaking space with simple spaces
+            //$text = str_replace("&nbsp;", " ", $text);
+            
+            // replace <br /> tags with simple newlines
+            // replace non-breaking space with simple spaces
+            // translate old HTML to new XHTML
+            // courtesy of research by A. Kalin :-)
+            $map = array(
+                '<br />'  => "\n",
+                '&nbsp;'  => ' ',
+                '<font'   => '<span',
+                '</font>' => '</span>',
+                'color="' => 'style="color:'
+            );
+            $text = strtr($text, $map);
+           
+            // get rid of the last newline inside the code block
+            // (becuase higlight_string puts one there)
+            if (substr($text, -8) == "\n</code>") {
+                $text = substr($text, 0, -8) . "</code>";
+            }
+            
+            // done
+            $text = "<pre>$text</pre>";
+        
+        } elseif (strtolower($args['type']) == 'html') {
+        
+            // HTML code example:
+            // add <html> opening and closing tags,
+            // convert tabs to four spaces,
+            // convert entities.
+            $text = str_replace("\t", "    ", $text);
+            $text = "<html>\n$text\n</html>";
+            $text = htmlentities($text);
+            $text = "<pre><code>$text</code></pre>";
+            
+        } else {
+            // generic code example:
+            // convert tabs to four spaces,
+            // convert entities.
+            $text = str_replace("\t", "    ", $text);
+            $text = htmlentities($text);
+            $text = "<pre><code>$text</code></pre>";
+        }
+        
+        return "\n$text\n";
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/colortext.php b/bundled-libs/Text/Wiki/Rule/colortext.php
new file mode 100644 (file)
index 0000000..7db577a
--- /dev/null
@@ -0,0 +1,139 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: colortext.php,v 1.2 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked for
+* coloring.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_colortext extends Text_Wiki_Rule {
+    
+    var $colors = array(
+        'aqua',
+        'black',
+        'blue',
+        'fuchsia',
+        'gray',
+        'green',
+        'lime',
+        'maroon',
+        'navy',
+        'olive',
+        'purple',
+        'red',
+        'silver',
+        'teal',
+        'white',
+        'yellow'
+    );
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex = "/\#\#(.+?)\|(.+?)\#\#/";
+    
+    
+    /**
+    * 
+    * Generates a replacement for the matched text.  Token options are:
+    * 
+    * 'type' => ['start'|'end'] The starting or ending point of the
+    * emphasized text.  The text itself is left in the source.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return string A pair of delimited tokens to be used as a
+    * placeholder in the source text surrounding the text to be
+    * emphasized.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        $start = $this->addToken(
+               array(
+                       'type' => 'start',
+                       'color' => $matches[1]
+               )
+        );
+        
+        $end = $this->addToken(
+               array(
+                       'type' => 'end',
+                       'color' => $matches[1]
+               )
+        );
+        
+        return $start . $matches[2] . $end;
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        $type = $options['type'];
+        $color = $options['color'];
+        
+        if (! in_array($color, $this->colors)) {
+            $color = '#' . $color;
+        }
+        
+        if ($type == 'start') {
+            return "<span style=\"color: $color;\">";
+        }
+        
+        if ($options['type'] == 'end') {
+            return '</span>';
+        }
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/deflist.php b/bundled-libs/Text/Wiki/Rule/deflist.php
new file mode 100644 (file)
index 0000000..68ff89e
--- /dev/null
@@ -0,0 +1,172 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: deflist.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked as a
+* definition list.  In short, if a line starts with ':' then it is a
+* definition list item; another ':' on the same lines indicates the end
+* of the definition term and the beginning of the definition narrative.
+* The list items must be on sequential lines (no blank lines between
+* them) -- a blank line indicates the beginning of a new list.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_deflist extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex = '/\n((:).*\n)(?!(:))/Us';
+    
+    
+    /**
+    * 
+    * Generates a replacement for the matched text.  Token options are:
+    * 
+    * 'type' =>
+    *     'list_start'    : the start of a definition list
+    *     'list_end'      : the end of a definition list
+    *     'term_start'    : the start of a definition term
+    *     'term_end'      : the end of a definition term
+    *     'narr_start'    : the start of definition narrative
+    *     'narr_end'      : the end of definition narrative
+    *     'unknown'       : unknown type of definition portion
+    *
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A series of text and delimited tokens marking the different
+    * list text and list elements.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        // the replacement text we will return to parse()
+        $return = '';
+        
+        // the list of post-processing matches
+        $list = array();
+        
+        // start the deflist
+        $options = array('type' => 'list_start');
+        $return .= $this->addToken($options);
+        
+        // $matches[1] is the text matched as a list set by parse();
+        // create an array called $list that contains a new set of
+        // matches for the various definition-list elements.
+        preg_match_all(
+            '/^(:)(.*)?(:)(.*)?$/Ums',
+            $matches[1],
+            $list,
+            PREG_SET_ORDER
+        );
+        
+        // add each term and narrative
+        foreach ($list as $key => $val) {
+            $return .= (
+                $this->addToken(array('type' => 'term_start')) .
+                trim($val[2]) .
+                $this->addToken(array('type' => 'term_end')) .
+                $this->addToken(array('type' => 'narr_start')) .
+                trim($val[4]) . 
+                $this->addToken(array('type' => 'narr_end'))
+            );
+        }
+        
+        
+        // end the deflist
+        $options = array('type' => 'list_end');
+        $return .= $this->addToken($options);
+        
+        // done!
+        return "\n" . $return . "\n";
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        $type = $options['type'];
+        $pad = "    ";
+        
+        switch ($type) {
+        
+        case 'list_start':
+            return "<dl>\n";
+            break;
+        
+        case 'list_end':
+            return "</dl>\n";
+            break;
+        
+        case 'term_start':
+            return $pad . "<dt>";
+            break;
+        
+        case 'term_end':
+            return "</dt>\n";
+            break;
+        
+        case 'narr_start':
+            return $pad . $pad . "<dd>";
+            break;
+        
+        case 'narr_end':
+            return "</dd>\n";
+            break;
+        
+        default:
+            return '';
+        
+        }
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/delimiter.php b/bundled-libs/Text/Wiki/Rule/delimiter.php
new file mode 100644 (file)
index 0000000..27782ee
--- /dev/null
@@ -0,0 +1,95 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: delimiter.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find instances of the delimiter
+* character already embedded in the source text; it extracts them and replaces
+* them with a delimited token, then renders them as the delimiter itself
+* when the target format is XHTML.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_delimiter extends Text_Wiki_Rule {
+    
+    /**
+    * 
+    * Constructor.  Overrides the Text_Wiki_Rule constructor so that we
+    * can set the $regex property dynamically (we need to include the
+    * Text_Wiki $delim character.
+    * 
+    * @param object &$obj The calling "parent" Text_Wiki object.
+    * 
+    * @param string $name The token name to use for this rule.
+    * 
+    */
+    
+    function Text_Wiki_Rule_delimiter(&$obj, $name)
+    {
+        parent::Text_Wiki_Rule($obj, $name);
+        $this->regex = '/' . $this->_wiki->delim . '/';
+    }
+    
+    
+    /**
+    * 
+    * Generates a token entry for the matched text.  Token options are:
+    * 
+    * 'text' => The full matched text.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A delimited token number to be used as a placeholder in
+    * the source text.
+    *
+    */
+    
+    function process(&$matches)
+    {    
+        return $this->addToken();
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        return $this->_wiki->delim;
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/embed.php b/bundled-libs/Text/Wiki/Rule/embed.php
new file mode 100644 (file)
index 0000000..617a9e3
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: embed.php,v 1.2 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to embed the contents of a URL
+* inside the page at render-time.  Typically used to get script output.
+* This differs from the 'include' rule, which incorporates results at
+* parse-time; 'embed' output does not get parsed by Text_Wiki, while
+* 'include' ouput does.
+*
+* This rule is inherently not secure; it allows cross-site scripting to
+* occur if the embedded output has <script> or other similar tags.  Be
+* careful.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_embed extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to find source text matching this
+    * rule.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    */
+    
+    var $regex = '/(\[\[embed )(.+?)(\]\])/i';
+    
+    
+    /**
+    * 
+    * Generates a token entry for the matched text.  Token options are:
+    * 
+    * 'text' => The full matched text, not including the <code></code> tags.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A delimited token number to be used as a placeholder in
+    * the source text.
+    *
+    */
+    
+    function process(&$matches)
+    {    
+        $options = array('path' => $matches[2]);
+        return $this->addToken($options);
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+       $file = $this->_conf['base'] . $options['path'];
+       ob_start();
+       include($file);
+       $output = ob_get_contents();
+       ob_end_clean();
+               return $output;
+       }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/emphasis.php b/bundled-libs/Text/Wiki/Rule/emphasis.php
new file mode 100644 (file)
index 0000000..897bb66
--- /dev/null
@@ -0,0 +1,103 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: emphasis.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked for
+* emphasis (italics) as defined by text surrounded by two single-quotes.
+* On parsing, the text itself is left in place, but the starting and ending
+* instances of two single-quotes are replaced with tokens.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_emphasis extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex = "/\/\/(()|.*)\/\//U";
+    
+    
+    /**
+    * 
+    * Generates a replacement for the matched text.  Token options are:
+    * 
+    * 'type' => ['start'|'end'] The starting or ending point of the
+    * emphasized text.  The text itself is left in the source.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return string A pair of delimited tokens to be used as a
+    * placeholder in the source text surrounding the text to be
+    * emphasized.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        $start = $this->addToken(array('type' => 'start'));
+        $end = $this->addToken(array('type' => 'end'));
+        return $start . $matches[1] . $end;
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+               if ($options['type'] == 'start') {
+                       return '<em>';
+               }
+               
+               if ($options['type'] == 'end') {
+                       return '</em>';
+               }
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/entities.php b/bundled-libs/Text/Wiki/Rule/entities.php
new file mode 100644 (file)
index 0000000..f6461c3
--- /dev/null
@@ -0,0 +1,57 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: entities.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to convert HTML entities in the
+* source text.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_entities extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * Simple parsing method to apply the rule.
+    *
+    * @access public
+    * 
+    */
+    
+    function parse()
+    {
+        // first, decode any entities already in the text so that they
+        // don't get double-encoded
+        $trans_table = get_html_translation_table(HTML_SPECIALCHARS);
+        $this->_wiki->_source = strtr($this->_wiki->_source,
+            array_flip($trans_table));
+            
+        // now encode all html special characters
+        $this->_wiki->_source = htmlspecialchars($this->_wiki->_source);
+    }
+
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/freelink.php b/bundled-libs/Text/Wiki/Rule/freelink.php
new file mode 100644 (file)
index 0000000..4cf789e
--- /dev/null
@@ -0,0 +1,179 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: freelink.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked as a
+* wiki freelink, and automatically create a link to that page.
+* 
+* A freelink is any page name not conforming to the standard
+* StudlyCapsStyle for a wiki page name.  For example, a page normally
+* named MyHomePage can be renamed and referred to as ((My Home Page)) --
+* note the spaces in the page name.  You can also make a "nice-looking"
+* link without renaming the target page; e.g., ((MyHomePage|My Home
+* Page)).  Finally, you can use named anchors on the target page:
+* ((MyHomePage|My Home Page#Section1)).
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_freelink extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * Constructor.  We override the Text_Wiki_Rule constructor so we can
+    * explicitly comment each part of the $regex property.
+    * 
+    * @access public
+    * 
+    * @param object &$obj The calling "parent" Text_Wiki object.
+    * 
+    * @param string $name The token name to use for this rule.
+    * 
+    */
+    
+    function Text_Wiki_Rule_freelink(&$obj, $name)
+    {
+        parent::Text_Wiki_Rule($obj, $name);
+        
+        $this->regex =
+            '/' .                                                  // START regex
+            "\\(\\(" .                                             // double open-parens
+            "(" .                                                  // START freelink page patter
+            "[-A-Za-z0-9 _+\\/.,;:!?'\"\\[\\]\\{\\}&\xc0-\xff]+" . // 1 or more of just about any character
+            ")" .                                                  // END  freelink page pattern
+            "(" .                                                  // START display-name
+            "\|" .                                                 // a pipe to start the display name
+            "[-A-Za-z0-9 _+\\/.,;:!?'\"\\[\\]\\{\\}&\xc0-\xff]+" . // 1 or more of just about any character
+            ")?" .                                                 // END display-name pattern 0 or 1
+            "(" .                                                  // START pattern for named anchors
+            "\#" .                                                 // a hash mark
+            "[A-Za-z]" .                                           // 1 alpha
+            "[-A-Za-z0-9_:.]*" .                                   // 0 or more alpha, digit, underscore
+            ")?" .                                                 // END named anchors pattern 0 or 1
+            "()\\)\\)" .                                           // double close-parens
+            '/';                                                   // END regex
+    }
+    
+    
+    /**
+    * 
+    * Generates a replacement for the matched text.  Token options are:
+    * 
+    * 'page' => the wiki page name (e.g., HomePage).
+    * 
+    * 'text' => alternative text to be displayed in place of the wiki
+    * page name.
+    * 
+    * 'anchor' => a named anchor on the target wiki page
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A delimited token to be used as a placeholder in
+    * the source text, plus any text priot to the match.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        // use nice variable names
+        $page = $matches[1];
+        $text = $matches[2];
+        
+        // get rid of the leading # from the anchor, if any
+        $anchor = substr($matches[3], 1);
+        
+        // is the page given a new text appearance?
+        if (trim($text) == '') {
+            // no
+            $text = $page;
+        } else {
+            // yes, strip the leading | character
+            $text = substr($text, 1);
+        }
+        
+        // set the options
+        $options = array(
+            'page'   => $page,
+            'text'   => $text,
+            'anchor' => $anchor
+        );
+        
+        // return a token placeholder
+        return $this->addToken($options);
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        // get nice variable names (page, text, anchor)
+        extract($options);
+        
+        if (in_array($page, $this->_conf['pages'])) {
+        
+            // the page exists, show a link to the page
+            $href = $this->_conf['view_url'];
+            if (strpos($href, '%s') === false) {
+               // use the old form
+                   $href = $href . $page . '#' . $anchor;
+               } else {
+                       // use the new form
+                       $href = sprintf($href, $page . '#' . $anchor);
+               }
+            return "<a href=\"$href\">$text</a>";
+            
+        } else {
+        
+            // the page does not exist, show the page name and
+            // the "new page" text
+            $href = $this->_conf['new_url'];
+            if (strpos($href, '%s') === false) {
+               // use the old form
+                   $href = $href . $page;
+               } else {
+                       // use the new form
+                       $href = sprintf($href, $page);
+               }
+            return $text . "<a href=\"$href\">{$this->_conf['new_text']}</a>";
+            
+        }
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/heading.php b/bundled-libs/Text/Wiki/Rule/heading.php
new file mode 100644 (file)
index 0000000..db3c5c3
--- /dev/null
@@ -0,0 +1,119 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: heading.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked to
+* be a heading element, as defined by text on a line by itself prefixed
+* with a number of plus signs (+). The heading text itself is left in
+* the source, but is prefixed and suffixed with delimited tokens marking
+* the start and end of the heading.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_heading extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex = '/^(\+{1,6}) (.*)/m';
+    
+    
+    /**
+    * 
+    * Generates a replacement for the matched text.  Token options are:
+    * 
+    * 'type' => ['start'|'end'] The starting or ending point of the
+    * heading text.  The text itself is left in the source.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return string A pair of delimited tokens to be used as a
+    * placeholder in the source text surrounding the heading text.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        $start = $this->addToken(
+            array(
+                'type' => 'start',
+                'level' => strlen($matches[1]),
+                'text' => $matches[2]
+            )
+        );
+        
+        $end = $this->addToken(
+            array(
+                'type' => 'end',
+                'level' => strlen($matches[1])
+            )
+        );
+        
+        return $start . $matches[2] . $end . "\n";
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        // get nice variable names (type, level)
+        extract($options);
+        
+        if ($type == 'start') {
+            return "<h$level>";
+        }
+        
+        if ($type == 'end') {
+            return "</h$level>\n";
+        }
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/horiz.php b/bundled-libs/Text/Wiki/Rule/horiz.php
new file mode 100644 (file)
index 0000000..d282e8b
--- /dev/null
@@ -0,0 +1,88 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: horiz.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked to
+* be a horizontal rule, as defined by four dashed on their own line.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_horiz extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex = '/^([-]{4,})$/m';
+    
+    
+    /**
+    * 
+    * Generates a replacement token for the matched text.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return string A token marking the horizontal rule.
+    *
+    */
+    
+    function process(&$matches)
+    {    
+        return $this->addToken();
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        return "<hr />\n";
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/html.php b/bundled-libs/Text/Wiki/Rule/html.php
new file mode 100644 (file)
index 0000000..5a6c5ce
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: html.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked as
+* HTML to be redndred as-is.  The block start is marked by <html> on its
+* own line, and the block end is marked by </html> on its own line.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_html extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex = '/^\<html\>\n(.+)\n\<\/html\>(\s|$)/Umsi';
+    
+    
+    /**
+    * 
+    * Generates a replacement for the matched text.  Token options are:
+    * 
+    * 'text' => The text of the HTML to be rendered as-is.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A delimited token to be used as a placeholder in
+    * the source text, plus any text following the HTML block.
+    *
+    */
+    
+    function process(&$matches)
+    {    
+        $options = array('text' => $matches[1]);
+        return $this->addToken($options) . $matches[2];
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        return $options['text'];
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/image.php b/bundled-libs/Text/Wiki/Rule/image.php
new file mode 100644 (file)
index 0000000..f1cc0a3
--- /dev/null
@@ -0,0 +1,136 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: image.php,v 1.2 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to embed the contents of a URL
+* inside the page.  Typically used to get script output.
+*
+* This rule is inherently not secure; it allows cross-site scripting to
+* occur if the embedded output has <script> or other similar tags.  Be
+* careful.
+*
+* In the future, we'll add a rule config options to set the base embed
+* path so that it is limited to one directory.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_image extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to find source text matching this
+    * rule.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    */
+    
+    var $regex = '/(\[\[image )(.+?)(\]\])/i';
+    
+    
+    /**
+    * 
+    * Generates a token entry for the matched text.  Token options are:
+    * 
+    * 'src' => The image source, typically a relative path name.
+    *
+    * 'opts' => Any macro options following the source.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A delimited token number to be used as a placeholder in
+    * the source text.
+    *
+    */
+    
+    function process(&$matches)
+    {
+       $pos = strpos($matches[2], ' ');
+       
+       if ($pos === false) {
+               $options = array(
+                       'src' => $matches[2],
+                       'args' => array());
+       } else {
+               // everything after the space is macro options
+               $options = array(
+                       'src' => substr($matches[2], 0, $pos),
+                       'args' => $this->getMacroArgs(substr($matches[2], $pos+1))
+               );
+       }
+       
+        return $this->addToken($options);
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+       $src = '"' . $this->_conf['base'] . $options['src'] . '"';
+       
+       if (isset($options['args']['link'])) {
+                       // this image has a wikilink
+               $href = $this->_wiki->getRuleConf('wikilink', 'view_url') .
+                       $options['args']['link'];
+       } else {
+               // image is not linked
+               $href = null;
+       }
+       
+       // unset these so they don't show up as attributes
+       unset($options['args']['src']);
+       unset($options['args']['link']);
+       
+       $attr = '';
+       foreach ($options['args'] as $key => $val) {
+               $attr .= "$key=\"$val\" ";
+       }
+       
+       if ($href) {
+               return "<a href=\"$href\"><img src=$src $attr/></a>";
+       } else {
+               return "<img src=$src $attr/>";
+           }
+       }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/include.php b/bundled-libs/Text/Wiki/Rule/include.php
new file mode 100644 (file)
index 0000000..d7c140f
--- /dev/null
@@ -0,0 +1,80 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: include.php,v 1.2 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to include the results of a
+* script directly into the source at parse-time; thus, the output of the
+* script will be parsed by Text_Wiki.  This differs from the 'embed'
+* rule, which incorporates the results at render-time, meaning that the
+* 'embed' content is not parsed by Text_Wiki.
+*
+* This rule is inherently not secure; it allows cross-site scripting to
+* occur if the embedded output has <script> or other similar tags.  Be
+* careful.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_include extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to find source text matching this
+    * rule.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    */
+    
+    var $regex = '/(\[\[include )(.+?)(\]\])/i';
+    
+    
+    /**
+    * 
+    * Includes the results of the script directly into the source; the output
+    * will subsequently be parsed by the remaining Text_Wiki rules.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return The results of the included script.
+    *
+    */
+    
+    function process(&$matches)
+    {
+       $file = $this->_conf['base'] . $matches[2];
+       ob_start();
+       include($file);
+       $output = ob_get_contents();
+       ob_end_clean();
+               return $output;
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/interwiki.php b/bundled-libs/Text/Wiki/Rule/interwiki.php
new file mode 100644 (file)
index 0000000..15f9058
--- /dev/null
@@ -0,0 +1,195 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: interwiki.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked as
+* an Interwiki link.  See the regex for a detailed explanation of the
+* text matching procedure; e.g., "InterWikiName:PageName".
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_interwiki extends Text_Wiki_Rule {
+    
+    
+    var $regex = '([A-Za-z0-9_]+):([\/=&~#A-Za-z0-9_]+)';
+    
+    
+    /**
+    * 
+    * Parser.  We override the standard parser so we can
+    * find both described interwiki links and standalone links.
+    * 
+    * @access public
+    * 
+    * @return void
+    * 
+    */
+    
+    function parse()
+    {
+       // described interwiki links
+       $tmp_regex = '/\[' . $this->regex . ' (.+?)\]/';
+        $this->_wiki->_source = preg_replace_callback(
+            $tmp_regex,
+            array(&$this, 'processDescr'),
+            $this->_wiki->_source
+        );
+        
+       // standalone interwiki links
+        $tmp_regex = '/' . $this->regex . '/';
+        $this->_wiki->_source = preg_replace_callback(
+            $tmp_regex,
+            array(&$this, 'process'),
+            $this->_wiki->_source
+        );
+       
+    }
+    
+    
+    /**
+    * 
+       * Generates a replacement for the matched standalone interwiki text.
+       * Token options are:
+       * 
+       * 'site' => The key name for the Text_Wiki interwiki array map,
+       * usually the name of the interwiki site.
+       * 
+       * 'page' => The page on the target interwiki to link to.
+       * 
+       * 'text' => The text to display as the link.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A delimited token to be used as a placeholder in
+    * the source text, plus any text priot to the match.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        $options = array(
+            'site' => $matches[1],
+            'page' => $matches[2],
+            'text' => $matches[0]
+        );
+        
+        // if not in the interwiki map, don't make it an interwiki link
+        if (isset($this->_conf['sites'][$options['site']])) {
+               return $this->addToken($options);
+           } else {
+               return $matches[0];
+           }
+    }
+    
+    
+    /**
+    * 
+       * Generates a replacement for described interwiki links. Token
+       * options are:
+       * 
+       * 'site' => The key name for the Text_Wiki interwiki array map,
+       * usually the name of the interwiki site.
+       * 
+       * 'page' => The page on the target interwiki to link to.
+       * 
+       * 'text' => The text to display as the link.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A delimited token to be used as a placeholder in
+    * the source text, plus any text priot to the match.
+    *
+    */
+    
+    function processDescr(&$matches)
+    {
+        $options = array(
+            'site' => $matches[1],
+            'page' => $matches[2],
+            'text' => $matches[3]
+        );
+        
+        // if not in the interwiki map, don't make it an interwiki link
+        if (isset($this->_conf['sites'][$options['site']])) {
+               return $this->addToken($options);
+           } else {
+               return $matches[0];
+           }
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        $site = $options['site'];
+        $page = $options['page'];
+        $text = $options['text'];
+        
+        if (isset($this->_conf['sites'][$site])) {
+            $href = $this->_conf['sites'][$site];
+        } else {
+            return $text;
+        }
+        
+               // old form where page is at end,
+               // or new form with %s placeholder for sprintf()?
+               if (strpos($href, '%s') === false) {
+                       // use the old form
+                       $href = $href . $page;
+               } else {
+                       // use the new form
+                       $href = sprintf($href, $page);
+               }
+               
+               // allow for alternative targets
+               if (isset($this->_conf['target']) &&
+                       trim($this->_conf['target']) != '') {
+                       $target = 'target="' . $this->_conf['target'] . '"';
+               } else {
+                       $target = '';
+               }
+               
+               
+        return "<a $target href=\"$href\">$text</a>";
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/italic.php b/bundled-libs/Text/Wiki/Rule/italic.php
new file mode 100644 (file)
index 0000000..a28a237
--- /dev/null
@@ -0,0 +1,103 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: italic.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked for
+* emphasis (italics) as defined by text surrounded by two single-quotes.
+* On parsing, the text itself is left in place, but the starting and ending
+* instances of two single-quotes are replaced with tokens.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_italic extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex = "/''(()|[^'].*)''/U";
+    
+    
+    /**
+    * 
+    * Generates a replacement for the matched text.  Token options are:
+    * 
+    * 'type' => ['start'|'end'] The starting or ending point of the
+    * emphasized text.  The text itself is left in the source.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return string A pair of delimited tokens to be used as a
+    * placeholder in the source text surrounding the text to be
+    * emphasized.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        $start = $this->addToken(array('type' => 'start'));
+        $end = $this->addToken(array('type' => 'end'));
+        return $start . $matches[1] . $end;
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+               if ($options['type'] == 'start') {
+                       return '<i>';
+               }
+               
+               if ($options['type'] == 'end') {
+                       return '</i>';
+               }
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/list.php b/bundled-libs/Text/Wiki/Rule/list.php
new file mode 100644 (file)
index 0000000..437a140
--- /dev/null
@@ -0,0 +1,295 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: list.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked as
+* a bulleted or numbered list.  In short, if a line starts with '* ' then
+* it is a bullet list item; if a line starts with '# ' then it is a 
+* number list item.  Spaces in front of the * or # indicate an indented
+* sub-list.  The list items must be on sequential lines (no blank lines
+* between them) -- a blank line indicates the beginning of a new list.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_list extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex = '/\n((\*|#) .*\n)(?! {0,}(\*|#))/Us';
+    
+    
+    /**
+    * 
+    * Generates a replacement for the matched text.  Token options are:
+    * 
+    * 'type' =>
+    *     'bullet_start' : the start of a bullet list
+    *     'bullet_end'   : the end of a bullet list
+    *     'number_start' : the start of a number list
+    *     'number_end'   : the end of a number list
+    *     'item_start'   : the start of item text (bullet or number)
+    *     'item_end'     : the end of item text (bullet or number)
+    *     'unknown'      : unknown type of list or item
+    *
+    * 'level' => the indent level (0 for the first level, 1 for the
+    * second, etc)
+    *
+    * 'count' => the list item number at this level. not needed for
+    * xhtml, but very useful for PDF and RTF.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A series of text and delimited tokens marking the different
+    * list text and list elements.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        // the replacement text we will return
+        $return = '';
+        
+        // the list of post-processing matches
+        $list = array();
+        
+        // a stack of list-start and list-end types; we keep this
+        // so that we know what kind of list we're working with
+        // (bullet or number) and what indent level we're at.
+        $stack = array();
+        
+        // the item count is the number of list items for any
+        // given list-type on the stack
+        $itemcount = array();
+        
+        // populate $list with this set of matches. $matches[1] is the
+        // text matched as a list set by parse().
+        preg_match_all(
+            '=^( {0,})(\*|#) (.*)$=Ums',
+            $matches[1],
+            $list,
+            PREG_SET_ORDER
+        );
+        
+        // loop through each list-item element.
+        foreach ($list as $key => $val) {
+            
+            // $val[0] is the full matched list-item line
+            // $val[1] is the number of initial spaces (indent level)
+            // $val[2] is the list item type (* or #)
+            // $val[3] is the list item text
+            
+            // how many levels are we indented? (1 means the "root"
+            // list level, no indenting.)
+            $level = strlen($val[1]) + 1;
+            
+            // get the list item type
+            if ($val[2] == '*') {
+                $type = 'bullet';
+            } elseif ($val[2] == '#') {
+                $type = 'number';
+            } else {
+                $type = 'unknown';
+            }
+            
+            // get the text of the list item
+            $text = $val[3];
+            
+            // add a level to the list?
+            if ($level > count($stack)) {
+                
+                // the current indent level is greater than the
+                // number of stack elements, so we must be starting
+                // a new list.  push the new list type onto the
+                // stack...
+                array_push($stack, $type);
+                
+                // ...and add a list-start token to the return.
+                $return .= $this->addToken(
+                    array(
+                        'type' => $type . '_start',
+                        'level' => $level - 1
+                    )
+                );
+            }
+            
+            // remove a level from the list?
+            while (count($stack) > $level) {
+                
+                // so we don't keep counting the stack, we set up a temp
+                // var for the count.  -1 becuase we're going to pop the
+                // stack in the next command.  $tmp will then equal the
+                // current level of indent.
+                $tmp = count($stack) - 1;
+                
+                // as long as the stack count is greater than the
+                // current indent level, we need to end list types. 
+                // continue adding end-list tokens until the stack count
+                // and the indent level are the same.
+                $return .= $this->addToken(
+                    array (
+                        'type' => array_pop($stack) . '_end',
+                        'level' => $tmp
+                    )
+                );
+                
+                // reset to the current (previous) list type so that
+                // the new list item matches the proper list type.
+                $type = $stack[$tmp - 1];
+                
+                // reset the item count for the popped indent level
+                $itemcount[$tmp + 1] = 0;
+            }
+            
+            // add to the item count for this list (taking into account
+            // which level we are at).
+            if (! isset($itemcount[$level])) {
+                // first count
+                $itemcount[$level] = 1;
+            } else {
+                // increment count
+                $itemcount[$level]++;
+            }
+            
+            // create a list-item starting token.
+            $start = $this->addToken(
+                array(
+                    'type' => 'item_start',
+                    'level' => $level,
+                    'count' => $itemcount[$level]
+                )
+            );
+            
+            // create a list-item ending token.
+            $end = $this->addToken(
+                array(
+                    'type' => 'item_end',
+                    'level' => $level,
+                    'count' => $itemcount[$level]
+                )
+            );
+            
+            // add the starting token, list-item text, and ending token
+            // to the return.
+            $return .= $start . $val[3] . $end;
+        }
+        
+        // the last list-item may have been indented.  go through the
+        // list-type stack and create end-list tokens until the stack
+        // is empty.
+        while (count($stack) > 0) {
+            $return .= $this->addToken(
+                array (
+                    'type' => array_pop($stack) . '_end',
+                    'level' => count($stack)
+                )
+            );
+        }
+        
+        // we're done!  send back the replacement text.
+        return "\n" . $return . "\n";
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        // make nice variables (type, level, count)
+        extract($options);
+        
+        // set up indenting so that the results look nice; we do this
+        // in two steps to avoid str_pad mathematics.  ;-)
+        $pad = str_pad('', $level, "\t");
+        $pad = str_replace("\t", '    ', $pad);
+        
+        // attempt XHTML compliance so that sub-lists are part
+        // of a list item, not between list items
+        if ($level > 0) {
+               $pre = '<li style="list-style: none;">';
+               $post = '</li>';
+        } else {
+               $pre = '';
+               $post = '';
+        }
+        
+        switch ($type) {
+        
+        case 'bullet_start':
+            return "$pad$pre<ul>\n";
+            break;
+        
+        case 'bullet_end':
+            return "$pad</ul>$post\n";
+            break;
+        
+        case 'number_start':
+            return "$pad$pre<ol>\n";
+            break;
+        
+        case 'number_end':
+            return "$pad</ol>$post\n";
+            break;
+        
+        case 'item_start':
+            return "$pad<li>";
+            break;
+        
+        case 'item_end':
+            return "</li>\n";
+            break;
+        
+        default:
+            return '';
+        
+        }
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/newline.php b/bundled-libs/Text/Wiki/Rule/newline.php
new file mode 100644 (file)
index 0000000..76018b0
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: newline.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to mark implied line breaks in the
+* source text, usually a single carriage return in the middle of a paragraph
+* or block-quoted text.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_newline extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex = '/([^\n])\n([^\n])/m';
+    
+    
+    /**
+    * 
+    * Generates a replacement token for the matched text.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return string A delimited token to be used as a placeholder in
+    * the source text.
+    *
+    */
+    
+    function process(&$matches)
+    {    
+        return $matches[1] . $this->addToken() . $matches[2];
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        return "<br />\n";
+    }
+}
+
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/paragraph.php b/bundled-libs/Text/Wiki/Rule/paragraph.php
new file mode 100644 (file)
index 0000000..58127fa
--- /dev/null
@@ -0,0 +1,141 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: paragraph.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki rule to find sections of the source
+* text that are paragraphs.  A para is any line not starting with a token
+* delimiter, followed by two newlines.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_paragraph extends Text_Wiki_Rule {
+    
+    /**
+    * 
+    * The regular expression used to find source text matching this
+    * rule.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    */
+    
+    var $regex = "/^.*?\n\n/m";
+    
+    
+    /**
+    * 
+    * Generates a token entry for the matched text.  Token options are:
+    * 
+    * 'start' => The starting point of the paragraph.
+    * 
+    * 'end' => The endinging point of the paragraph.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A delimited token number to be used as a placeholder in
+    * the source text.
+    *
+    */
+    
+    function process(&$matches)
+    {
+       $delim = $this->_wiki->delim;
+       
+       // was anything there?
+       if (trim($matches[0]) == '') {
+               return '';
+       }
+       
+       // does the match start with a delimiter?
+       if (substr($matches[0], 0, 1) != $delim) { 
+               // no.
+            $start = $this->addToken(array('type' => 'start'));
+            $end = $this->addToken(array('type' => 'end'));
+            return $start . trim($matches[0]) . $end;
+        }
+        
+        // the line starts with a delimiter.  read in the delimited
+        // token number, check the token, and see if we should
+        // skip it.
+        
+        // loop starting at the second character (we already know
+        // the first is a delimiter) until we find another
+        // delimiter; the text between them is a token key number.
+        $key = '';
+               $len = strlen($matches[0]);
+               for ($i = 1; $i < $len; $i++) {
+               $char = $matches[0]{$i};
+               if ($char == $delim) {
+                       break;
+               } else {
+                       $key .= $char;
+               }
+        }
+        
+        // look at the token and see if it's skippable (if we skip,
+        // it will not be marked as a paragraph)
+        $token_type = $this->_wiki->_tokens[$key][0];
+        if (in_array($token_type, $this->_conf['skip'])) {
+               return $matches[0];
+        } else {
+            $start = $this->addToken(array('type' => 'start'));
+            $end = $this->addToken(array('type' => 'end'));
+            return $start . trim($matches[0]) . $end;
+        }
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        extract($options); //type
+        
+        if ($type == 'start') {
+            return '<p>';
+        }
+        
+        if ($type == 'end') {
+            return "</p>\n\n";
+        }
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/phpcode.php b/bundled-libs/Text/Wiki/Rule/phpcode.php
new file mode 100644 (file)
index 0000000..c1ca071
--- /dev/null
@@ -0,0 +1,133 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: phpcode.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find sections marked as code
+* examples.  Blocks are marked as the string <code> on a line by itself,
+* followed by the inline code example, and terminated with the string
+* </code> on a line by itself.  The code example is run through the
+* native PHP highlight_string() function to colorize it, then surrounded
+* with <pre>...</pre> tags when rendered as XHTML.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_phpcode extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to find source text matching this
+    * rule.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    */
+    
+    var $regex = '/^(\<php\>)\n(.+)\n(\<\/php\>)(\s|$)/Umsi';
+    
+    
+    /**
+    * 
+    * Generates a token entry for the matched text.  Token options are:
+    * 
+    * 'text' => The full matched text, not including the <code></code> tags.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A delimited token number to be used as a placeholder in
+    * the source text.
+    *
+    */
+    
+    function process(&$matches)
+    {    
+        $options = array('text' => $matches[2]);
+        return $this->addToken($options) . $matches[4];
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+               // add the PHP tags
+               $text = "<?php\n" . $options['text'] . "\n?>"; // <?php
+               
+               // convert tabs to four spaces
+               $text = str_replace("\t", "    ", $text);
+               
+               // colorize the code block (also converts HTML entities and adds
+               // <code>...</code> tags)
+               ob_start();
+               highlight_string($text);
+               $text = ob_get_contents();
+               ob_end_clean();
+               
+               // replace <br /> tags with simple newlines
+               //$text = str_replace("<br />", "\n", $text);
+               
+               // replace non-breaking space with simple spaces
+               //$text = str_replace("&nbsp;", " ", $text);
+               
+               // replace <br /> tags with simple newlines
+               // replace non-breaking space with simple spaces
+               // translate old HTML to new XHTML
+               // courtesy of research by A. Kalin :-)
+               $map = array(
+                       '<br />'  => "\n",
+                       '&nbsp;'  => ' ',
+                       '<font'   => '<span',
+                       '</font>' => '</span>',
+                       'color="' => 'style="color:'
+               );
+               $text = strtr($text, $map);
+          
+               // get rid of the last newline inside the code block
+               // (becuase higlight_string puts one there)
+               if (substr($text, -8) == "\n</code>") {
+                       $text = substr($text, 0, -8) . "</code>";
+               }
+               
+          // done
+               return "\n<pre>$text</pre>\n";
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/phplookup.php b/bundled-libs/Text/Wiki/Rule/phplookup.php
new file mode 100644 (file)
index 0000000..16fe2fa
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: phplookup.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked for
+* lookup in the PHP online manual.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_phplookup extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex = "/\[\[php (.+?)\]\]/";
+    
+    
+    /**
+    * 
+    * Generates a replacement for the matched text.  Token options are:
+    * 
+    * 'type' => ['start'|'end'] The starting or ending point of the
+    * teletype text.  The text itself is left in the source.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return string A pair of delimited tokens to be used as a
+    * placeholder in the source text surrounding the teletype text.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        return $this->addToken(array('text' => $matches[1]));
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+       $text = trim($options['text']);
+        return "<a href=\"http://php.net/$text\">$text</a>";
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/prefilter.php b/bundled-libs/Text/Wiki/Rule/prefilter.php
new file mode 100644 (file)
index 0000000..0269c18
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: prefilter.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to "pre-filter" source text so
+* that line endings are consistently \n, lines ending in a backslash \
+* are concatenated with the next line, and tabs are converted to spaces.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_prefilter extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * Simple parsing method to apply the rule directly to the source
+    * text.
+    *
+    * @access public
+    * 
+    */
+    
+    function parse()
+    {
+        // convert DOS line endings
+        $this->_wiki->_source = str_replace("\r\n", "\n",
+            $this->_wiki->_source);
+        
+        // convert Macintosh line endings
+        $this->_wiki->_source = str_replace("\r", "\n",
+            $this->_wiki->_source);
+        
+        // concat lines ending in a backslash
+        $this->_wiki->_source = str_replace("\\\n", "",
+            $this->_wiki->_source);
+        
+        // convert tabs to spaces
+        $this->_wiki->_source = str_replace("\t", "    ",
+            $this->_wiki->_source);
+           
+        // add extra newlines at the top and end; this
+        // seems to help many rules.
+        $this->_wiki->_source = "\n" . $this->_wiki->_source . "\n\n";
+        
+        // finally, compress all instances of 3 or more newlines
+        // down to two newlines.
+       $find = "/\n{3,}/m";
+       $replace = "\n\n";
+       $this->_wiki->_source = preg_replace($find, $replace,
+               $this->_wiki->_source);
+    }
+
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/raw.php b/bundled-libs/Text/Wiki/Rule/raw.php
new file mode 100644 (file)
index 0000000..ba8c729
--- /dev/null
@@ -0,0 +1,91 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: raw.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki rule to find sections of the source
+* text that are not to be processed by Text_Wiki.  These blocks of "raw"
+* text will be rendered as they were found.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_raw extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to find source text matching this
+    * rule.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    */
+    
+    var $regex = "/``(.*)``/U";
+    
+    
+    /**
+    * 
+    * Generates a token entry for the matched text.  Token options are:
+    * 
+    * 'text' => The full matched text.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A delimited token number to be used as a placeholder in
+    * the source text.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        $options = array('text' => $matches[1]);
+        return $this->addToken($options);
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        return $options['text'];
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/revise.php b/bundled-libs/Text/Wiki/Rule/revise.php
new file mode 100644 (file)
index 0000000..6218c54
--- /dev/null
@@ -0,0 +1,182 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: revise.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked for
+* revision.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_revise extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex = "/\@\@({*?.*}*?)\@\@/U";
+    
+    
+    /**
+    * 
+    * The characters to use as marking text to be stricken.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    *
+    */
+    
+    var $delmark = '---';
+    
+    
+    /**
+    * 
+    * The characters to use as marking text to be added.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $insmark = '+++';
+    
+    
+    /**
+    * 
+    * Generates a replacement for the matched text.  Token options are:
+    * 
+    * 'type' => ['start'|'end'] The starting or ending point of the
+    * inserted text.  The text itself is left in the source.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return string A pair of delimited tokens to be used as a
+    * placeholder in the source text surrounding the teletype text.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        $output = '';
+        $src = $matches[1];
+        $delmark = $this->delmark;
+        $insmark = $this->insmark;
+        
+        // '---' must be before '+++' (if they both appear)
+        $del = strpos($src, $delmark);
+        $ins = strpos($src, $insmark);
+        
+        // if neither is found, return right away
+        if ($del === false && $ins === false) {
+            return $matches[0];
+        }
+        
+        // handle text to be deleted
+        if ($del !== false) {
+            
+            // move forward to the end of the deletion mark
+            $del += strlen($delmark);
+            
+            if ($ins === false) {
+                // there is no insertion text following
+                $text = substr($src, $del);
+            } else {
+                // there is insertion text following,
+                // mitigate the length
+                $text = substr($src, $del, $ins - $del);
+            }
+            
+            $output .= $this->addToken(array('type' => 'del_start'));
+            $output .= $text;
+            $output .= $this->addToken(array('type' => 'del_end'));
+        }
+        
+        // handle text to be inserted
+        if ($ins !== false) {
+            
+            // move forward to the end of the insert mark
+            $ins += strlen($insmark);
+            $text = substr($src, $ins);
+            
+            $output .= $this->addToken(array('type' => 'ins_start'));
+            $output .= $text;
+            $output .= $this->addToken(array('type' => 'ins_end'));
+        }
+        
+        return $output;
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        if ($options['type'] == 'del_start') {
+            return '<del>';
+        }
+        
+        if ($options['type'] == 'del_end') {
+            return '</del>';
+        }
+        
+        if ($options['type'] == 'ins_start') {
+            return '<ins>';
+        }
+        
+        if ($options['type'] == 'ins_end') {
+            return '</ins>';
+        }
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/strong.php b/bundled-libs/Text/Wiki/Rule/strong.php
new file mode 100644 (file)
index 0000000..2446719
--- /dev/null
@@ -0,0 +1,103 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: strong.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked for
+* strong emphasis (bold) as defined by text surrounded by three
+* single-quotes. On parsing, the text itself is left in place, but the
+* starting and ending instances of three single-quotes are replaced with
+* tokens.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_strong extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex =  "/\*\*(()|.*)\*\*/U";
+    
+    
+    /**
+    * 
+    * Generates a replacement for the matched text.  Token options are:
+    * 
+    * 'type' => ['start'|'end'] The starting or ending point of the
+    * emphasized text.  The text itself is left in the source.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A pair of delimited tokens to be used as a placeholder in
+    * the source text surrounding the text to be emphasized.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        $start = $this->addToken(array('type' => 'start'));
+        $end = $this->addToken(array('type' => 'end'));
+        return $start . $matches[1] . $end;
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        if ($options['type'] == 'start') {
+            return '<strong>';
+        }
+        
+        if ($options['type'] == 'end') {
+            return '</strong>';
+        }
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/superscript.php b/bundled-libs/Text/Wiki/Rule/superscript.php
new file mode 100644 (file)
index 0000000..19a8003
--- /dev/null
@@ -0,0 +1,103 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: superscript.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked for
+* strong emphasis (bold) as defined by text surrounded by three
+* single-quotes. On parsing, the text itself is left in place, but the
+* starting and ending instances of three single-quotes are replaced with
+* tokens.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_superscript extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex =  "/\^\^(()|.*)\^\^/U";
+    
+    
+    /**
+    * 
+    * Generates a replacement for the matched text.  Token options are:
+    * 
+    * 'type' => ['start'|'end'] The starting or ending point of the
+    * emphasized text.  The text itself is left in the source.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A pair of delimited tokens to be used as a placeholder in
+    * the source text surrounding the text to be emphasized.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        $start = $this->addToken(array('type' => 'start'));
+        $end = $this->addToken(array('type' => 'end'));
+        return $start . $matches[1] . $end;
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        if ($options['type'] == 'start') {
+            return '<sup>';
+        }
+        
+        if ($options['type'] == 'end') {
+            return '</sup>';
+        }
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/table.php b/bundled-libs/Text/Wiki/Rule/table.php
new file mode 100644 (file)
index 0000000..1c89b18
--- /dev/null
@@ -0,0 +1,249 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: table.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked as a
+* set of table rows, where a line start and ends with double-pipes (||)
+* and uses double-pipes to separate table cells.  The rows must be on
+* sequential lines (no blank lines between them) -- a blank line
+* indicates the beginning of a new table.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_table extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex = '/\n((\|\|).*)(\n)(?!(\|\|))/Us';
+    
+    
+    /**
+    * 
+    * Generates a replacement for the matched text.  Token options are:
+    * 
+    * 'type' =>
+    *     'table_start' : the start of a bullet list
+    *     'table_end'   : the end of a bullet list
+    *     'row_start' : the start of a number list
+    *     'row_end'   : the end of a number list
+    *     'cell_start'   : the start of item text (bullet or number)
+    *     'cell_end'     : the end of item text (bullet or number)
+    * 
+    * 'colspan' => column span (for a cell)
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A series of text and delimited tokens marking the different
+    * table elements and cell text.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        // out eventual return value
+        $return = '';
+        
+        // start a new table
+        $return .= $this->addToken(array('type' => 'table_start'));
+        
+        // rows are separated by newlines in the matched text
+        $rows = explode("\n", $matches[1]);
+        
+        // loop through each row
+        foreach ($rows as $row) {
+            
+            // start a new row
+            $return .= $this->addToken(array('type' => 'row_start'));
+            
+            // cells are separated by double-pipes
+            $cell = explode("||", $row);
+            
+            // get the last cell number
+            $last = count($cell) - 1;
+            
+            // by default, cells span only one column (their own)
+            $span = 1;
+            
+            // ignore cell zero, and ignore the "last" cell; cell zero
+            // is before the first double-pipe, and the "last" cell is
+            // after the last double-pipe. both are always empty.
+            for ($i = 1; $i < $last; $i ++) {
+                
+                // if there is no content at all, then it's an instance
+                // of two sets of || next to each other, indicating a
+                // colspan.
+                if ($cell[$i] == '') {
+                    
+                    // add to the span and loop to the next cell
+                    $span += 1;
+                    continue;
+                    
+                } else {
+                    
+                    // this cell has content.
+                    
+                    // find the alignment, if any.
+                    if (substr($cell[$i], 0, 2) == '> ') {
+                       // set to right-align and strip the tag
+                       $align = 'right';
+                       $cell[$i] = substr($cell[$i], 2);
+                    } elseif (substr($cell[$i], 0, 2) == '= ') {
+                       // set to center-align and strip the tag
+                       $align = 'center';
+                       $cell[$i] = substr($cell[$i], 2);
+                    } elseif (substr($cell[$i], 0, 2) == '< ') {
+                       // set to left-align and strip the tag
+                       $align = 'left';
+                       $cell[$i] = substr($cell[$i], 2);
+                    } else {
+                       $align = null;
+                    }
+                    
+                    // start a new cell...
+                    $return .= $this->addToken(
+                        array (
+                            'type' => 'cell_start',
+                            'align' => $align,
+                            'colspan' => $span
+                        )
+                    );
+                    
+                    // ...add the content...
+                    $return .= trim($cell[$i]);
+                    
+                    // ...and end the cell.
+                    $return .= $this->addToken(
+                        array (
+                            'type' => 'cell_end',
+                            'align' => $align,
+                            'colspan' => $span
+                        )
+                    );
+                    
+                    // reset the colspan.
+                    $span = 1;
+                }
+                    
+            }
+            
+            // end the row
+            $return .= $this->addToken(array('type' => 'row_end'));
+            
+        }
+        
+        // end the table
+        $return .= $this->addToken(array('type' => 'table_end'));
+        
+        // we're done!
+        return "\n$return\n";
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        // make nice variable names (type, align, colspan)
+        extract($options);
+        
+        $pad = '    ';
+        
+        $border = (isset($this->_conf['border']))
+               ? $this->_conf['border'] : '1';
+               
+        $spacing = (isset($this->_conf['spacing']))
+               ? $this->_conf['spacing'] : '0';
+        
+        $padding = (isset($this->_conf['padding']))
+               ? $this->_conf['padding'] : '4';
+        
+        switch ($type) {
+        
+        case 'table_start':
+            return "<table border=\"$border\" " .
+               "cellspacing=\"$spacing\" " .
+               "cellpadding=\"$padding\">\n";
+            break;
+        
+        case 'table_end':
+            return "</table>\n";
+            break;
+        
+        case 'row_start':
+            return "$pad<tr>\n";
+            break;
+        
+        case 'row_end':
+            return "$pad</tr>\n";
+            break;
+        
+        case 'cell_start':
+               $tmp = $pad . $pad . '<td';
+            if ($colspan > 1) {
+                $tmp .= " colspan=\"$colspan\"";
+            }
+            if ($align) {
+               $tmp .= " align=\"$align\"";
+            }
+            return $tmp . '>';
+            break;
+        
+        case 'cell_end':
+            return "</td>\n";
+            break;
+        
+        default:
+            return '';
+        
+        }
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/tighten.php b/bundled-libs/Text/Wiki/Rule/tighten.php
new file mode 100644 (file)
index 0000000..9243818
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: tighten.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* The rule removes all remaining newlines.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_tighten extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * Simple parsing method to apply tightening directly to the tokens
+    * array.
+    *
+    * @access public
+    * 
+    */
+    
+    function parse()
+    {
+       $this->_wiki->_source = str_replace("\n", '',
+               $this->_wiki->_source);
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/toc.php b/bundled-libs/Text/Wiki/Rule/toc.php
new file mode 100644 (file)
index 0000000..ad74589
--- /dev/null
@@ -0,0 +1,352 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: toc.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find all heading tokens and
+* build a table of contents.  The [[toc]] tag gets replaced with a list
+* of all the level-2 through level-6 headings.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+
+class Text_Wiki_Rule_toc extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex = "/\[\[toc\]\]/m";
+    
+    
+    /**
+    * 
+    * The collection of headings (text and levels).
+    * 
+    * @access public
+    * 
+    * @var array
+    * 
+    * @see _getEntries()
+    * 
+    */
+    
+    var $entry = array();
+    
+    
+    /**
+    * 
+    * Custom parsing (have to process heading entries first).
+    * 
+    * @access public
+    * 
+    * @see Text_Wiki::parse()
+    * 
+    */
+    
+    function parse()
+    {
+        $this->_getEntries();
+        parent::parse();
+    }
+    
+    
+    /**
+    * 
+    * Generates a replacement for the matched text.  Token options are:
+    * 
+    * 'type' => ['list_start'|'list_end'|'item_end'|'item_end'|'target']
+    *
+    * 'level' => The heading level (1-6).
+    *
+    * 'count' => Which heading this is in the list.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return string A token indicating the TOC collection point.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        $output = $this->addToken(array('type' => 'list_start'));
+        
+        foreach ($this->entry as $key => $val) {
+        
+            $options = array(
+                'type' => 'item_start',
+                'count' => $val['count'],
+                'level' => $val['level']
+            );
+            
+            $output .= $this->addToken($options);
+            
+            $output .= $val['text'];
+            
+            $output .= $this->addToken(array('type' => 'item_end'));
+        }
+        
+        $output .= $this->addToken(array('type' => 'list_end'));
+        return $output;
+    }
+    
+    
+    /**
+    * 
+    * Finds all headings in the text and saves them in $this->entry.
+    * 
+    * @access private
+    *
+    * @return void
+    * 
+    */
+    
+    function _getEntries()
+    {
+        // the wiki delimiter
+        $delim = $this->_wiki->delim;
+        
+        // list of all TOC entries (h2, h3, etc)
+        $this->entry = array();
+        
+        // the new source text with TOC entry tokens
+        $newsrc = '';
+        
+        // when passing through the parsed source text, keep track of when
+        // we are in a delimited section
+        $in_delim = false;
+        
+        // when in a delimited section, capture the token key number
+        $key = '';
+        
+        // TOC entry count
+        $count = 0;
+        
+        // pass through the parsed source text character by character
+        $k = strlen($this->_wiki->_source);
+        for ($i = 0; $i < $k; $i++) {
+            
+            // the current character
+            $char = $this->_wiki->_source{$i};
+            
+            // are alredy in a delimited section?
+            if ($in_delim) {
+            
+                // yes; are we ending the section?
+                if ($char == $delim) {
+                    
+                    // yes, get the replacement text for the delimited
+                    // token number and unset the flag.
+                    $key = (int)$key;
+                    $rule = $this->_wiki->_tokens[$key][0];
+                    $opts = $this->_wiki->_tokens[$key][1];
+                    $in_delim = false;
+                    
+                    // is the key a start heading token
+                    // of level 2 or deeper?
+                    if ($rule == 'heading' &&
+                        $opts['type'] == 'start' &&
+                        $opts['level'] > 1) {
+                        
+                        // yes, add a TOC target link to the
+                        // tokens array...
+                        $token = $this->addToken(
+                            array(
+                                'type' => 'target',
+                                'count' => $count,
+                                'level' => $opts['level']
+                            )
+                        );
+                        
+                        // ... and to the new source, before the
+                        // heading-start token.
+                        $newsrc .= $token . $delim . $key . $delim;
+                        
+                        // retain the toc item
+                        $this->entry[] = array (
+                            'count' => $count,
+                            'level' => $opts['level'],
+                            'text' => $opts['text']
+                        );
+                        
+                        // increase the count for the next entry
+                        $count++;
+                        
+                    } else {
+                        // not a heading-start of 2 or deeper.
+                        // re-add the delimited token number
+                        // as it was in the original source.
+                        $newsrc .= $delim . $key . $delim;
+                    }
+                    
+                } else {
+                
+                    // no, add to the delimited token key number
+                    $key .= $char;
+                    
+                }
+                
+            } else {
+                
+                // not currently in a delimited section.
+                // are we starting into a delimited section?
+                if ($char == $delim) {
+                    // yes, reset the previous key and
+                    // set the flag.
+                    $key = '';
+                    $in_delim = true;
+                } else {
+                    // no, add to the output as-is
+                    $newsrc .= $char;
+                }
+            }
+        }
+        
+        // replace with changed source text
+        $this->_wiki->_source = $newsrc;
+        
+        
+        /*
+        // PRIOR VERSION
+        // has problems mistaking marked-up numbers for delimited tokens
+        
+        // creates target tokens, retrieves heading level and text
+        $this->entry = array();
+        $count = 0;
+        
+        // loop through all tokens and get headings
+        foreach ($this->_wiki->_tokens as $key => $val) {
+            
+            // only get heading starts of level 2 or deeper
+            if ($val[0] == 'heading' &&
+                $val[1]['type'] == 'start' &&
+                $val[1]['level'] > 1) {
+                
+                // the level of this header
+                $level = $val[1]['level'];
+                
+                // the text of this header
+                $text = $val[1]['text'];
+                
+                // add a toc-target link to the tokens array
+                $token = $this->addToken(
+                    array(
+                        'type' => 'target',
+                        'count' => $count,
+                        'level' => $level
+                    )
+                );
+                
+                // put the toc target token in front of the
+                // heading-start token
+                $start = $delim . $key . $delim;
+                $this->_wiki->_source = str_replace($start, $token.$start,
+                    $this->_wiki->_source);
+                
+                // retain the toc item
+                $this->entry[] = array (
+                    'count' => $count,
+                    'level' => $level,
+                    'text' => $text
+                );
+                
+                // increase the count for the next item
+                $count++;
+            }
+        }
+        */
+    }
+
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        // type, count, level
+        extract($options);
+        
+        // the prefix used for anchor names
+        $prefix = 'toc';
+        
+        if ($type == 'target') {
+            // ... generate an anchor.
+            return "<a id=\"$prefix$count\"></a>";
+        }
+        
+        if ($type == 'list_start') {
+            return "<p>\n";
+        }
+        
+        if ($type == 'list_end') {
+            return "</p>\n";
+        }
+        
+        if ($type == 'item_start') {
+            
+            // build some indenting spaces for the text
+            $indent = ($level - 2) * 4;
+            $pad = str_pad('', $indent);
+            $pad = str_replace(' ', '&nbsp;', $pad);
+            
+            // add an extra linebreak in front of heading-2
+            // entries (makes for nice section separations)
+            if ($level <= 2 && $count > 0) {
+                $pad = "<br />\n$pad";
+            }
+            
+            // create the entry line as a link to the toc anchor
+            return "$pad<a href=\"#$prefix$count\">";
+        }
+        
+        if ($type == 'item_end') {
+            return "</a><br />\n";
+        }
+    }
+
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/tt.php b/bundled-libs/Text/Wiki/Rule/tt.php
new file mode 100644 (file)
index 0000000..526f5c4
--- /dev/null
@@ -0,0 +1,102 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: tt.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked for
+* teletype (monospace) as defined by text surrounded by two curly
+* braces. On parsing, the text itself is left in place, but the starting
+* and ending instances of curly braces are replaced with tokens.
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_tt extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * The regular expression used to parse the source text and find
+    * matches conforming to this rule.  Used by the parse() method.
+    * 
+    * @access public
+    * 
+    * @var string
+    * 
+    * @see parse()
+    * 
+    */
+    
+    var $regex = "/{{({*?.*}*?)}}/U";
+    
+    
+    /**
+    * 
+    * Generates a replacement for the matched text.  Token options are:
+    * 
+    * 'type' => ['start'|'end'] The starting or ending point of the
+    * teletype text.  The text itself is left in the source.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return string A pair of delimited tokens to be used as a
+    * placeholder in the source text surrounding the teletype text.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        $start = $this->addToken(array('type' => 'start'));
+        $end = $this->addToken(array('type' => 'end'));
+        return $start . $matches[1] . $end;
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        if ($options['type'] == 'start') {
+            return '<tt>';
+        }
+        
+        if ($options['type'] == 'end') {
+            return '</tt>';
+        }
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/url.php b/bundled-libs/Text/Wiki/Rule/url.php
new file mode 100644 (file)
index 0000000..b4f5598
--- /dev/null
@@ -0,0 +1,316 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: url.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked as a
+* URL.  Various URL markings are supported: inline (the URL by itself),
+* numbered or footnote reference (where the URL is enclosed in square brackets), and
+* named reference (where the URL is enclosed in square brackets and has a
+* name included inside the brackets).  E.g.:
+*
+* inline    -- http://example.com
+* numbered  -- [http://example.com]
+* described -- [http://example.com Example Description]
+*
+* When rendering a URL token, this will convert URLs pointing to a .gif,
+* .jpg, or .png image into an inline <img /> tag (for the 'xhtml'
+* format).
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_url extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * When doing numbered references (footnote-style references), we
+    * need to keep a running count of how many references there are.
+    * 
+    * @access public
+    * 
+    * @var int
+    * 
+    */
+    
+    var $footnoteCount = 0;
+    
+    
+    /**
+    * 
+    * An array of filename extensions that indicate a file is an image.
+    * 
+    * @access public
+    * 
+    * @var array
+    * 
+    */
+    
+    var $img_ext = array('.jpg', '.png', '.gif');
+    
+    
+    function Text_Wiki_Rule_url(&$obj, $name)
+    {
+       parent::Text_Wiki_Rule($obj, $name);
+       
+        $this->regex = 
+               "(http:\/\/|https:\/\/|ftp:\/\/|gopher:\/\/|news:\/\/|mailto:)" . // protocols
+               "(" . 
+               "[^ \\/\"\'{$this->_wiki->delim}]*\\/" . // no spaces, \, /, ", or single quotes;
+               ")*" . 
+               "[^ \\t\\n\\/\"\'{$this->_wiki->delim}]*" .
+               "[A-Za-z0-9\\/?=&~_]";
+               
+    }
+    
+    
+    /**
+    * 
+    * A somewhat complex parsing method to find three different kinds
+    * of URLs in the source text.
+    *
+    * @access public
+    * 
+    */
+    
+    function parse()
+    {
+        // -------------------------------------------------------------
+        // 
+        // Described-reference (named) URLs.
+        // 
+        
+        // the regular expression for this kind of URL
+        $tmp_regex = '/\[(' . $this->regex . ') ([^\]]+)\]/';
+        
+        // use a custom callback processing method to generate
+        // the replacement text for matches.
+        $this->_wiki->_source = preg_replace_callback(
+            $tmp_regex,
+            array(&$this, 'processDescr'),
+            $this->_wiki->_source
+        );
+        
+        
+        // -------------------------------------------------------------
+        // 
+        // Numbered-reference (footnote-style) URLs.
+        // 
+        
+        // the regular expression for this kind of URL
+        $tmp_regex = '/\[(' . $this->regex . ')\]/U';
+        
+        // use a custom callback processing method to generate
+        // the replacement text for matches.
+        $this->_wiki->_source = preg_replace_callback(
+            $tmp_regex,
+            array(&$this, 'processFootnote'),
+            $this->_wiki->_source
+        );
+        
+        
+        // -------------------------------------------------------------
+        // 
+        // Normal inline URLs.
+        // 
+        
+        // the regular expression for this kind of URL
+               
+               $tmp_regex = '/(^|[^A-Za-z])(' . $this->regex . ')(.*?)/';
+               
+        // use the standard callback for inline URLs
+        $this->_wiki->_source = preg_replace_callback(
+            $tmp_regex,
+            array(&$this, 'process'),
+            $this->_wiki->_source
+        );
+    }
+    
+    
+    /**
+    * 
+    * Process inline URLs and return replacement text with a delimited
+    * token.
+    * 
+    * Token options are:
+    *     'type' => ['inline'|'footnote'|'descr'] the type of URL
+    *     'href' => the URL link href portion
+    *     'text' => the displayed text of the URL link
+    * 
+    * @param array &$matches
+    * 
+    * @param array $matches An array of matches from the parse() method
+    * as generated by preg_replace_callback.  $matches[0] is the full
+    * matched string, $matches[1] is the first matched pattern,
+    * $matches[2] is the second matched pattern, and so on.
+    * 
+    * @return string The processed text replacement.
+    * 
+    */ 
+    
+    function process(&$matches)
+    {
+        // set options
+        $options = array(
+            'type' => 'inline',
+            'href' => $matches[2],
+            'text' => $matches[2]
+        );
+        
+        // tokenize
+        return $matches[1] . $this->addToken($options) . $matches[5];
+    }
+    
+    
+    /**
+    * 
+    * Process numbered (footnote) URLs and return replacement text with
+    * a delimited token.
+    * 
+    * Token options are:
+    *     'type' => ['inline'|'footnote'|'descr'] the type of URL
+    *     'href' => the URL link href portion
+    *     'text' => the displayed text of the URL link
+    * 
+    * @param array &$matches
+    * 
+    * @param array $matches An array of matches from the parse() method
+    * as generated by preg_replace_callback.  $matches[0] is the full
+    * matched string, $matches[1] is the first matched pattern,
+    * $matches[2] is the second matched pattern, and so on.
+    * 
+    * @return string The processed text replacement.
+    * 
+    */ 
+    
+    function processFootnote(&$matches)
+    {
+        // keep a running count for footnotes 
+        $this->footnoteCount++;
+        
+        // set options
+        $options = array(
+            'type' => 'footnote',
+            'href' => $matches[1],
+            'text' => $this->footnoteCount
+        );
+        
+        // tokenize
+        return $this->addToken($options);
+    }
+    
+    
+    /**
+    * 
+    * Process described-reference (named-reference) URLs and return
+    * replacement text with a delimited token.
+    * 
+    * Token options are:
+    *     'type' => ['inline'|'footnote'|'descr'] the type of URL
+    *     'href' => the URL link href portion
+    *     'text' => the displayed text of the URL link
+    * 
+    * @param array &$matches
+    * 
+    * @param array $matches An array of matches from the parse() method
+    * as generated by preg_replace_callback.  $matches[0] is the full
+    * matched string, $matches[1] is the first matched pattern,
+    * $matches[2] is the second matched pattern, and so on.
+    * 
+    * @return string The processed text replacement.
+    * 
+    */ 
+    
+    function processDescr(&$matches)
+    {
+        // set options
+        $options = array(
+            'type' => 'descr',
+            'href' => $matches[1],
+            'text' => $matches[4]
+        );
+        
+        // tokenize
+        return $this->addToken($options);
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        // create local variables from the options array (text,
+        // href, type)
+        extract($options);
+        
+        // find the rightmost dot and determine the filename
+        // extension.
+        $pos = strrpos($href, '.');
+        $ext = strtolower(substr($href, $pos));
+        
+        // does the filename extension indicate an image file?
+        if (in_array($ext, $this->img_ext)) {
+            
+            // create alt text for the image
+            if (! isset($text) || $text == '') {
+                $text = basename($href);
+            }
+            
+            // generate an image tag
+            $output = "<img src=\"$href\" alt=\"$text\" />";
+            
+        } else {
+               
+               // allow for alternative targets
+               if (isset($this->_conf['target']) &&
+                       trim($this->_conf['target']) != '') {
+                       $target = 'target="' . $this->_conf['target'] . '"';
+               } else {
+                       $target = '';
+               }
+               
+            // generate a regular link (not an image)
+            $output = "<a $target href=\"$href\">$text</a>";
+            
+            // make numbered references look like footnotes
+            if ($type == 'footnote') {
+                $output = '<sup>' . $output . '</sup>';
+            }
+        }
+        
+        return $output;
+    }
+}
+?>
diff --git a/bundled-libs/Text/Wiki/Rule/wikilink.php b/bundled-libs/Text/Wiki/Rule/wikilink.php
new file mode 100644 (file)
index 0000000..c2fefd6
--- /dev/null
@@ -0,0 +1,241 @@
+<?php
+/* vim: set expandtab tabstop=4 shiftwidth=4: */
+// +----------------------------------------------------------------------+
+// | PHP version 4                                                        |
+// +----------------------------------------------------------------------+
+// | Copyright (c) 1997-2003 The PHP Group                                |
+// +----------------------------------------------------------------------+
+// | This source file is subject to version 2.0 of the PHP license,       |
+// | that is bundled with this package in the file LICENSE, and is        |
+// | available through the world-wide-web at                              |
+// | http://www.php.net/license/2_02.txt.                                 |
+// | If you did not receive a copy of the PHP license and are unable to   |
+// | obtain it through the world-wide-web, please send a note to          |
+// | license@php.net so we can mail you a copy immediately.               |
+// +----------------------------------------------------------------------+
+// | Authors: Paul M. Jones <pmjones@ciaweb.net>                          |
+// +----------------------------------------------------------------------+
+//
+// $Id: wikilink.php,v 1.3 2004/12/02 10:54:32 nohn Exp $
+
+
+/**
+* 
+* This class implements a Text_Wiki_Rule to find source text marked as a
+* wiki page name and automatically create a link to that page.
+*
+* Wiki page names are typically in StudlyCapsStyle made of
+* WordsSmashedTogether.
+*
+* You can also create described links to pages in this style:
+* [WikiPageName nice text link to use for display]
+*
+* @author Paul M. Jones <pmjones@ciaweb.net>
+*
+* @package Text_Wiki
+*
+*/
+
+class Text_Wiki_Rule_wikilink extends Text_Wiki_Rule {
+    
+    
+    /**
+    * 
+    * Constructor.  We override the Text_Wiki_Rule constructor so we can
+    * explicitly comment each part of the $regex property.
+    * 
+    * @access public
+    * 
+    * @param object &$obj The calling "parent" Text_Wiki object.
+    * 
+    * @param string $name The token name to use for this rule.
+    * 
+    */
+    
+    function Text_Wiki_Rule_wikilink(&$obj, $name)
+    {
+        parent::Text_Wiki_Rule($obj, $name);
+        
+        $this->regex =
+            "(!?" .              // START WikiPage pattern (1)
+            "[A-Z]" .            // 1 upper
+            "[A-Za-z]*" .        // 0+ alpha
+            "[a-z]+" .           // 1+ lower
+            "[A-Z]" .            // 1 upper
+            "[A-Za-z]*" .        // 0+ or more alpha
+            ")" .                // END WikiPage pattern (/1)
+            "((\#" .             // START Anchor pattern (2)(3)
+            "[A-Za-z]" .         // 1 alpha
+            "(" .                // start sub pattern (4)
+            "[-A-Za-z0-9_:.]*" . // 0+ dash, alpha, digit, underscore, colon, dot
+            "[-A-Za-z0-9_]" .    // 1 dash, alpha, digit, or underscore
+            ")?)?)";             // end subpatterns (/4)(/3)(/2)
+    }
+    
+    
+    /**
+    * 
+    * First parses for described links, then for standalone links.
+    * 
+    * @access public
+    * 
+    * @return void
+    * 
+    */
+    
+    function parse()
+    {
+       // described wiki links
+       $tmp_regex = '/\[' . $this->regex . ' (.+?)\]/';
+        $this->_wiki->_source = preg_replace_callback(
+            $tmp_regex,
+            array(&$this, 'processDescr'),
+            $this->_wiki->_source
+        );
+       
+        // standalone wiki links
+        $tmp_regex = '/(^|[^A-Za-z0-9\-_])' . $this->regex . '/';
+        $this->_wiki->_source = preg_replace_callback(
+            $tmp_regex,
+            array(&$this, 'process'),
+            $this->_wiki->_source
+        );
+    }
+    
+    
+    /**
+    * 
+    * Generates a replacement for described links.  Token options are:
+    * 
+    * 'page' => the wiki page name.
+    * 
+    * 'text' => the displayed link text.
+    * 
+    * 'anchor' => a named anchor on the target wiki page.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A delimited token to be used as a placeholder in
+    * the source text, plus any text priot to the match.
+    *
+    */
+    
+    function processDescr(&$matches)
+    {
+        // set the options
+        $options = array(
+            'page' => $matches[1],
+            'text' => $matches[5],
+            'anchor' => $matches[3]
+        );
+        
+        // create and return the replacement token and preceding text
+        return $this->addToken($options); // . $matches[7];
+    }
+    
+    
+    /**
+    * 
+    * Generates a replacement for standalone links.  Token options are:
+    * 
+    * 'page' => the wiki page name.
+    * 
+    * 'text' => the displayed link text.
+    * 
+    * 'anchor' => a named anchor on the target wiki page.
+    * 
+    * @access public
+    *
+    * @param array &$matches The array of matches from parse().
+    *
+    * @return A delimited token to be used as a placeholder in
+    * the source text, plus any text prior to the match.
+    *
+    */
+    
+    function process(&$matches)
+    {
+        // when prefixed with !, it's explicitly not a wiki link.
+        // return everything as it was.
+        if ($matches[2]{0} == '!') {
+            return $matches[1] . substr($matches[2], 1) . $matches[3];
+        }
+        
+        // set the options
+        $options = array(
+            'page' => $matches[2],
+            'text' => $matches[2] . $matches[3],
+            'anchor' => $matches[3]
+        );
+        
+        // create and return the replacement token and preceding text
+        return $matches[1] . $this->addToken($options);
+    }
+    
+    
+    /**
+    * 
+    * Renders a token into text matching the requested format.
+    * 
+    * @access public
+    * 
+    * @param array $options The "options" portion of the token (second
+    * element).
+    * 
+    * @return string The text rendered from the token options.
+    * 
+    */
+    
+    function renderXhtml($options)
+    {
+        // make nice variable names (page, anchor, text)
+        extract($options);
+        
+        // does the page exist?
+        if (in_array($page, $this->_conf['pages'])) {
+        
+            // yes, link to the page view, but we have to build
+            // the HREF.  we support both the old form where
+            // the page always comes at the end, and the new
+            // form that uses %s for sprintf()
+            $href = $this->_conf['view_url'];
+            
+            if (strpos($href, '%s') === false) {
+               // use the old form
+                   $href = $href . $page . $anchor;
+               } else {
+                       // use the new form
+                       $href = sprintf($href, $page . $anchor);
+               }
+               
+            return "<a href=\"$href\">$text</a>";
+            
+        }
+        
+               // no, link to a create-page url, but only if new_url is set
+               if (! isset($this->_conf['new_url']) ||
+                       trim($this->_conf['new_url']) == '') {
+                       return $text;
+               } else {
+               
+            // yes, link to the page view, but we have to build
+            // the HREF.  we support both the old form where
+            // the page always comes at the end, and the new
+            // form that uses sprintf()
+            $href = $this->_conf['new_url'];
+            
+            if (strpos($href, '%s') === false) {
+               // use the old form
+                   $href = $href . $page;
+               } else {
+                       // use the new form
+                       $href = sprintf($href, $page);
+               }
+               
+                       return $text . "<a href=\"$href\">{$this->_conf['new_text']}</a>";
+               }
+    }
+}
+?>
diff --git a/bundled-libs/XML/RPC.php b/bundled-libs/XML/RPC.php
new file mode 100644 (file)
index 0000000..ad3bfc1
--- /dev/null
@@ -0,0 +1,1188 @@
+<?php
+// /* vim: set expandtab tabstop=4 shiftwidth=4: */
+// by Edd Dumbill (C) 1999-2001
+// <edd@usefulinc.com>
+// $Id: RPC.php,v 1.2 2004/07/26 15:07:54 nohn Exp $
+
+// License is granted to use or modify this software ("XML-RPC for PHP")
+// for commercial or non-commercial use provided the copyright of the author
+// is preserved in any distributed or derivative work.
+
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
+// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Adapted to PEAR standards by Stig S�her Bakken <stig@php.net> and
+// Martin Jansen <mj@php.net>
+// /* $id$ */
+
+if (!function_exists('xml_parser_create')) {
+// Win 32 fix. From: "Leo West" <lwest@imaginet.fr>
+    if ($WINDIR) {
+        dl("php_xml.dll");
+    } else {
+        dl("xml.so");
+    }
+}
+
+define('XML_RPC_ERROR_INVALID_TYPE',        101);
+define('XML_RPC_ERROR_NON_NUMERIC_FOUND',   102);
+define('XML_RPC_ERROR_CONNECTION_FAILED',   103);
+define('XML_RPC_ERROR_ALREADY_INITIALIZED', 104);
+
+$GLOBALS['XML_RPC_I4'] = "i4";
+$GLOBALS['XML_RPC_Int'] = "int";
+$GLOBALS['XML_RPC_Boolean'] = "boolean";
+$GLOBALS['XML_RPC_Double'] = "double";
+$GLOBALS['XML_RPC_String'] = "string";
+$GLOBALS['XML_RPC_DateTime'] = "dateTime.iso8601";
+$GLOBALS['XML_RPC_Base64'] = "base64";
+$GLOBALS['XML_RPC_Array'] = "array";
+$GLOBALS['XML_RPC_Struct'] = "struct";
+
+$GLOBALS['XML_RPC_Types'] = array($GLOBALS['XML_RPC_I4'] => 1,
+                                $GLOBALS['XML_RPC_Int'] => 1,
+                                $GLOBALS['XML_RPC_Boolean'] => 1,
+                                $GLOBALS['XML_RPC_String'] => 1,
+                                $GLOBALS['XML_RPC_Double'] => 1,
+                                $GLOBALS['XML_RPC_DateTime'] => 1,
+                                $GLOBALS['XML_RPC_Base64'] => 1,
+                                $GLOBALS['XML_RPC_Array'] => 2,
+                                $GLOBALS['XML_RPC_Struct'] => 3);
+
+$GLOBALS['XML_RPC_entities'] = array("quot" => '"',
+                                     "amp" => "&",
+                                     "lt" => "<",
+                                     "gt" => ">",
+                                     "apos" => "'");
+
+$GLOBALS['XML_RPC_err']["unknown_method"] = 1;
+$GLOBALS['XML_RPC_str']["unknown_method"] = "Unknown method";
+$GLOBALS['XML_RPC_err']["invalid_return"] = 2;
+$GLOBALS['XML_RPC_str']["invalid_return"] = "Invalid return payload: enabling debugging to examine incoming payload";
+$GLOBALS['XML_RPC_err']["incorrect_params"] = 3;
+$GLOBALS['XML_RPC_str']["incorrect_params"] = "Incorrect parameters passed to method";
+$GLOBALS['XML_RPC_err']["introspect_unknown"] = 4;
+$GLOBALS['XML_RPC_str']["introspect_unknown"] = "Can't introspect: method unknown";
+$GLOBALS['XML_RPC_err']["http_error"] = 5;
+$GLOBALS['XML_RPC_str']["http_error"] = "Didn't receive 200 OK from remote server.";
+
+$GLOBALS['XML_RPC_defencoding'] = "UTF-8";
+
+// let user errors start at 800
+$GLOBALS['XML_RPC_erruser'] = 800;
+
+// let XML parse errors start at 100
+$GLOBALS['XML_RPC_errxml'] = 100;
+
+// formulate backslashes for escaping regexp
+$GLOBALS['XML_RPC_backslash'] = chr(92) . chr(92);
+
+$GLOBALS['XML_RPC_twoslash'] = $GLOBALS['XML_RPC_backslash'] . $GLOBALS['XML_RPC_backslash'];
+$GLOBALS['XML_RPC_twoslash'] = "2SLS";
+
+// used to store state during parsing
+// quick explanation of components:
+//   st - used to build up a string for evaluation
+//   ac - used to accumulate values
+//   qt - used to decide if quotes are needed for evaluation
+//   cm - used to denote struct or array (comma needed)
+//   isf - used to indicate a fault
+//   lv - used to indicate "looking for a value": implements
+//        the logic to allow values with no types to be strings
+//   params - used to store parameters in method calls
+//   method - used to store method name
+
+$GLOBALS['XML_RPC_xh'] = array();
+
+function XML_RPC_entity_decode($string)
+{
+    $top = split("&", $string);
+    $op = "";
+    $i = 0;
+    while($i < sizeof($top)) {
+        if (ereg("^([#a-zA-Z0-9]+);", $top[$i], $regs)) {
+            $op .= ereg_replace("^[#a-zA-Z0-9]+;",
+                                XML_RPC_lookup_entity($regs[1]),
+                                $top[$i]);
+        } else {
+            if ($i == 0) {
+                $op = $top[$i];
+            } else {
+                $op .= "&" . $top[$i];
+            }
+        }
+
+        $i++;
+    }
+    return $op;
+}
+
+
+function XML_RPC_lookup_entity($ent)
+{
+    global $XML_RPC_entities;
+
+    if ($XML_RPC_entities[strtolower($ent)]) {
+        return $XML_RPC_entities[strtolower($ent)];
+    }
+
+    if (ereg("^#([0-9]+)$", $ent, $regs)) {
+        return chr($regs[1]);
+    }
+
+    return "?";
+}
+
+
+function XML_RPC_se($parser, $name, $attrs)
+{
+    global $XML_RPC_xh, $XML_RPC_DateTime, $XML_RPC_String;
+
+    switch ($name) {
+    case "STRUCT":
+    case "ARRAY":
+        $XML_RPC_xh[$parser]['st'] .= "array(";
+        $XML_RPC_xh[$parser]['cm']++;
+        // this last line turns quoting off
+        // this means if we get an empty array we'll
+        // simply get a bit of whitespace in the eval
+        $XML_RPC_xh[$parser]['qt'] = 0;
+        break;
+
+    case "NAME":
+        $XML_RPC_xh[$parser]['st'] .= "'";
+        $XML_RPC_xh[$parser]['ac'] = "";
+        break;
+
+    case "FAULT":
+        $XML_RPC_xh[$parser]['isf'] = 1;
+        break;
+
+    case "PARAM":
+        $XML_RPC_xh[$parser]['st'] = "";
+        break;
+
+    case "VALUE":
+        $XML_RPC_xh[$parser]['st'] .= "new XML_RPC_Value(";
+        $XML_RPC_xh[$parser]['lv'] = 1;
+        $XML_RPC_xh[$parser]['vt'] = $XML_RPC_String;
+        $XML_RPC_xh[$parser]['ac'] = "";
+        $XML_RPC_xh[$parser]['qt'] = 0;
+        // look for a value: if this is still 1 by the
+        // time we reach the first data segment then the type is string
+        // by implication and we need to add in a quote
+        break;
+
+    case "I4":
+    case "INT":
+    case "STRING":
+    case "BOOLEAN":
+    case "DOUBLE":
+    case "DATETIME.ISO8601":
+    case "BASE64":
+        $XML_RPC_xh[$parser]['ac'] = ""; // reset the accumulator
+
+        if ($name == "DATETIME.ISO8601" || $name == "STRING") {
+            $XML_RPC_xh[$parser]['qt'] = 1;
+
+            if ($name == "DATETIME.ISO8601") {
+                $XML_RPC_xh[$parser]['vt'] = $XML_RPC_DateTime;
+            }
+
+        } elseif ($name == "BASE64") {
+            $XML_RPC_xh[$parser]['qt'] = 2;
+        } else {
+            // No quoting is required here -- but
+            // at the end of the element we must check
+            // for data format errors.
+            $XML_RPC_xh[$parser]['qt'] = 0;
+        }
+        break;
+
+    case "MEMBER":
+        $XML_RPC_xh[$parser]['ac'] = "";
+        break;
+
+    default:
+        break;
+    }
+
+    if ($name!="VALUE") {
+        $XML_RPC_xh[$parser]['lv'] = 0;
+    }
+}
+
+
+function XML_RPC_ee($parser, $name)
+{
+    global $XML_RPC_xh,$XML_RPC_Types,$XML_RPC_String;
+
+    switch ($name) {
+    case "STRUCT":
+    case "ARRAY":
+        if ($XML_RPC_xh[$parser]['cm'] && substr($XML_RPC_xh[$parser]['st'], -1) == ',') {
+            $XML_RPC_xh[$parser]['st'] = substr($XML_RPC_xh[$parser]['st'],0,-1);
+        }
+
+        $XML_RPC_xh[$parser]['st'] .= ")";
+        $XML_RPC_xh[$parser]['vt'] = strtolower($name);
+        $XML_RPC_xh[$parser]['cm']--;
+        break;
+
+    case "NAME":
+        $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'] . "' => ";
+        break;
+
+    case "BOOLEAN":
+        // special case here: we translate boolean 1 or 0 into PHP
+        // constants true or false
+        if ($XML_RPC_xh[$parser]['ac'] == '1') {
+            $XML_RPC_xh[$parser]['ac'] = "true";
+        } else {
+            $XML_RPC_xh[$parser]['ac'] = "false";
+        }
+
+        $XML_RPC_xh[$parser]['vt'] = strtolower($name);
+        // Drop through intentionally.
+
+    case "I4":
+    case "INT":
+    case "STRING":
+    case "DOUBLE":
+    case "DATETIME.ISO8601":
+    case "BASE64":
+        if ($XML_RPC_xh[$parser]['qt'] == 1) {
+            // we use double quotes rather than single so backslashification works OK
+            $XML_RPC_xh[$parser]['st'] .= "\"" . $XML_RPC_xh[$parser]['ac'] . "\"";
+        } elseif ($XML_RPC_xh[$parser]['qt'] == 2) {
+            $XML_RPC_xh[$parser]['st'] .= "base64_decode('" . $XML_RPC_xh[$parser]['ac'] . "')";
+        } elseif ($name=="BOOLEAN") {
+            $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'];
+        } else {
+            // we have an I4, INT or a DOUBLE
+            // we must check that only 0123456789-.<space> are characters here
+            if (!ereg("^\-?[0123456789 \t\.]+$", $XML_RPC_xh[$parser]['ac'])) {
+                PEAR::raiseError("Non-numeric value received in INT or DOUBLE", XML_RPC_ERROR_NON_NUMERIC_FOUND);
+                $XML_RPC_xh[$parser]['st'] .= "ERROR_NON_NUMERIC_FOUND";
+            } else {
+                // it's ok, add it on
+                $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'];
+            }
+        }
+
+        $XML_RPC_xh[$parser]['ac'] = "";
+        $XML_RPC_xh[$parser]['qt'] = 0;
+        $XML_RPC_xh[$parser]['lv'] = 3; // indicate we've found a value
+        break;
+
+    case "VALUE":
+        // deal with a string value
+        if (strlen($XML_RPC_xh[$parser]['ac']) > 0 &&
+            $XML_RPC_xh[$parser]['vt'] == $XML_RPC_String) {
+
+            $XML_RPC_xh[$parser]['st'] .= "\"" . $XML_RPC_xh[$parser]['ac'] . "\"";
+        }
+
+        // This if () detects if no scalar was inside <VALUE></VALUE>
+        // and pads an empty "".
+        if ($XML_RPC_xh[$parser]['st'][strlen($XML_RPC_xh[$parser]['st'])-1] == '(') {
+            $XML_RPC_xh[$parser]['st'] .= '""';
+        }
+        $XML_RPC_xh[$parser]['st'] .= ", '" . $XML_RPC_xh[$parser]['vt'] . "')";
+        if ($XML_RPC_xh[$parser]['cm']) {
+            $XML_RPC_xh[$parser]['st'] .= ",";
+        }
+        break;
+
+    case "MEMBER":
+        $XML_RPC_xh[$parser]['ac'] = "";
+        $XML_RPC_xh[$parser]['qt'] = 0;
+        break;
+
+    case "DATA":
+        $XML_RPC_xh[$parser]['ac'] = "";
+        $XML_RPC_xh[$parser]['qt'] = 0;
+        break;
+
+    case "PARAM":
+        $XML_RPC_xh[$parser]['params'][] = $XML_RPC_xh[$parser]['st'];
+        break;
+
+    case "METHODNAME":
+        $XML_RPC_xh[$parser]['method'] = ereg_replace("^[\n\r\t ]+", "", $XML_RPC_xh[$parser]['ac']);
+        break;
+
+    case "BOOLEAN":
+        // special case here: we translate boolean 1 or 0 into PHP
+        // constants true or false
+        if ($XML_RPC_xh[$parser]['ac'] == '1') {
+            $XML_RPC_xh[$parser]['ac'] = "true";
+        } else {
+            $XML_RPC_xh[$parser]['ac'] = "false";
+        }
+
+        $XML_RPC_xh[$parser]['vt'] = strtolower($name);
+        break;
+
+    default:
+        break;
+    }
+
+    // if it's a valid type name, set the type
+    if (isset($XML_RPC_Types[strtolower($name)])) {
+        $XML_RPC_xh[$parser]['vt'] = strtolower($name);
+    }
+}
+
+
+function XML_RPC_cd($parser, $data)
+{
+    global $XML_RPC_xh, $XML_RPC_backslash;
+
+    if ($XML_RPC_xh[$parser]['lv'] != 3) {
+        // "lookforvalue==3" means that we've found an entire value
+        // and should discard any further character data
+
+        if ($XML_RPC_xh[$parser]['lv'] == 1) {
+            // if we've found text and we're just in a <value> then
+            // turn quoting on, as this will be a string
+            $XML_RPC_xh[$parser]['qt'] = 1;
+            // and say we've found a value
+            $XML_RPC_xh[$parser]['lv'] = 2;
+        }
+
+        // replace characters that eval would
+        // do special things with
+        if (!isset($XML_RPC_xh[$parser]['ac'])) {
+            $XML_RPC_xh[$parser]['ac'] = '';
+        }
+        $XML_RPC_xh[$parser]['ac'] .= str_replace('$', '\$',
+            str_replace('"', '\"', str_replace(chr(92),
+            $XML_RPC_backslash, $data)));
+    }
+}
+
+
+function XML_RPC_dh($parser, $data)
+{
+    global $XML_RPC_xh;
+
+    if (substr($data, 0, 1) == "&" && substr($data, -1, 1) == ";") {
+        if ($XML_RPC_xh[$parser]['lv'] == 1) {
+            $XML_RPC_xh[$parser]['qt'] = 1;
+            $XML_RPC_xh[$parser]['lv'] = 2;
+        }
+        $XML_RPC_xh[$parser]['ac'] .= str_replace('$', '\$',
+            str_replace('"', '\"', str_replace(chr(92),
+                $XML_RPC_backslash, $data)));
+    }
+}
+
+/**
+ * Base class
+ *
+ * This class provides common functions for all of the XML_RPC classes.
+ */
+class XML_RPC_Base {
+    function raiseError($msg, $code)
+    {
+        include_once 'PEAR.php';
+        PEAR::raiseError(get_class($this) . ": " . $msg, $code);
+    }
+}
+
+class XML_RPC_Client extends XML_RPC_Base {
+    var $path;
+    var $server;
+    var $port;
+    var $errno;
+    var $errstring;
+    var $debug = 0;
+    var $username = "";
+    var $password = "";
+
+    function XML_RPC_Client($path, $server, $port = 80,
+                            $proxy = '', $proxy_port = 8080,
+                            $proxy_user = '', $proxy_pass = '')
+    {
+        $this->port = $port;
+        $this->server = $server;
+        $this->path = $path;
+        $this->proxy = $proxy;
+        $this->proxy_port = $proxy_port;
+        $this->proxy_user = $proxy_user;
+        $this->proxy_pass = $proxy_pass;
+    }
+
+    function setDebug($in)
+    {
+        if ($in) {
+            $this->debug = 1;
+        } else {
+            $this->debug = 0;
+        }
+    }
+
+    function setCredentials($u, $p)
+    {
+        $this->username = $u;
+        $this->password = $p;
+    }
+
+    function send($msg, $timeout = 0)
+    {
+        // where msg is an xmlrpcmsg
+        $msg->debug = $this->debug;
+        return $this->sendPayloadHTTP10($msg, $this->server, $this->port,
+                                        $timeout, $this->username,
+                                        $this->password);
+    }
+
+    function sendPayloadHTTP10($msg, $server, $port, $timeout=0,
+                               $username = "", $password = "")
+    {
+        // If we're using a proxy open a socket to the proxy server instead to the xml-rpc server
+        if ($this->proxy){
+            if ($timeout > 0) {
+                $fp = fsockopen($this->proxy, $this->proxy_port, $this->errno, $this->errstr, $timeout);
+            } else {
+                $fp = fsockopen($this->proxy, $this->proxy_port, $this->errno, $this->errstr);
+            }
+        } else {
+            if ($timeout > 0) {
+                $fp = fsockopen($server, $port, $this->errno, $this->errstr, $timeout);
+            } else {
+                $fp = fsockopen($server, $port, $this->errno, $this->errstr);
+            }
+        }
+
+        if (!$fp && $this->proxy) {
+            $this->raiseError(
+                "Connection to proxy server " . $this->proxy . ":" . $this->proxy_port . " failed",
+                XML_RPC_ERROR_CONNECTION_FAILED);
+        } elseif (!$fp) {
+            $this->raiseError(
+                "Connection to RPC server " . $this->server . " failed",
+                XML_RPC_ERROR_CONNECTION_FAILED);
+        }
+
+        // Only create the payload if it was not created previously
+        if (empty($msg->payload)) {
+            $msg->createPayload();
+        }
+
+        // thanks to Grant Rauscher <grant7@firstworld.net> for this
+        $credentials = "";
+        if ($username != "") {
+            $credentials = "Authorization: Basic " .
+                base64_encode($username . ":" . $password) . "\r\n";
+        }
+
+
+        if ($this->proxy) {
+            $op = "POST http://" . $this->server;
+
+            if ($this->proxy_port) {
+                $op .= ":" . $this->port;
+            }
+        } else {
+           $op = "POST ";
+        }
+
+        $op .= $this->path. " HTTP/1.0\r\n" .
+               "User-Agent: PEAR XML_RPC\r\n" .
+               "Host: " . $this->server . "\r\n";
+        if ($this->proxy && $this->proxy_user != '') {
+            $op .= 'Proxy-Authorization: Basic ' .
+                base64_encode($this->proxy_user . ':' . $this->proxy_pass) .
+                "\r\n";
+        }
+        $op .= $credentials .
+               "Content-Type: text/xml\r\n" .
+               "Content-Length: " . strlen($msg->payload) . "\r\n\r\n" .
+               $msg->payload;
+
+        if (!fputs($fp, $op, strlen($op))) {
+            $this->errstr = "Write error";
+            return 0;
+        }
+        $resp = $msg->parseResponseFile($fp);
+        fclose($fp);
+        return $resp;
+    }
+}
+
+
+class XML_RPC_Response extends XML_RPC_Base
+{
+    var $xv;
+    var $fn;
+    var $fs;
+    var $hdrs;
+
+    function XML_RPC_Response($val, $fcode = 0, $fstr = "")
+    {
+        if ($fcode != 0) {
+            $this->fn = $fcode;
+            $this->fs = htmlspecialchars($fstr);
+        } else {
+            $this->xv = $val;
+        }
+    }
+
+    function faultCode()
+    {
+        if (isset($this->fn)) {
+            return $this->fn;
+        } else {
+            return 0;
+        }
+    }
+
+    function faultString()
+    {
+        return $this->fs;
+    }
+
+    function value()
+    {
+        return $this->xv;
+    }
+
+    function serialize()
+    {
+        $rs = "<methodResponse>\n";
+        if ($this->fn) {
+            $rs .= "<fault>
+  <value>
+    <struct>
+      <member>
+        <name>faultCode</name>
+        <value><int>" . $this->fn . "</int></value>
+      </member>
+      <member>
+        <name>faultString</name>
+        <value><string>" . $this->fs . "</string></value>
+      </member>
+    </struct>
+  </value>
+</fault>";
+        } else {
+            $rs .= "<params>\n<param>\n" . $this->xv->serialize() .
+        "</param>\n</params>";
+        }
+        $rs .= "\n</methodResponse>";
+        return $rs;
+    }
+}
+
+
+class XML_RPC_Message extends XML_RPC_Base
+{
+    var $payload;
+    var $methodname;
+    var $params = array();
+    var $debug = 0;
+
+    function XML_RPC_Message($meth, $pars = 0)
+    {
+        $this->methodname = $meth;
+        if (is_array($pars) && sizeof($pars)>0) {
+            for($i = 0; $i < sizeof($pars); $i++) {
+                $this->addParam($pars[$i]);
+            }
+        }
+    }
+
+    function xml_header()
+    {
+        return "<?xml version=\"1.0\"?>\n<methodCall>\n";
+    }
+
+    function xml_footer()
+    {
+        return "</methodCall>\n";
+    }
+
+    function createPayload()
+    {
+        $this->payload = $this->xml_header();
+        $this->payload .= "<methodName>" . $this->methodname . "</methodName>\n";
+        $this->payload .= "<params>\n";
+        for($i = 0; $i < sizeof($this->params); $i++) {
+            $p = $this->params[$i];
+            $this->payload .= "<param>\n" . $p->serialize() . "</param>\n";
+        }
+        $this->payload .= "</params>\n";
+        $this->payload .= $this->xml_footer();
+        $this->payload = str_replace("\n", "\r\n", $this->payload);
+    }
+
+    function method($meth = "")
+    {
+        if ($meth != "") {
+            $this->methodname = $meth;
+        }
+        return $this->methodname;
+    }
+
+    function serialize()
+    {
+        $this->createPayload();
+        return $this->payload;
+    }
+
+    function addParam($par)
+    {
+        $this->params[] = $par;
+    }
+
+    function getParam($i)
+    {
+        return $this->params[$i];
+    }
+
+    function getNumParams()
+    {
+        return sizeof($this->params);
+    }
+
+    function parseResponseFile($fp)
+    {
+        $ipd = "";
+
+        while($data = fread($fp, 32768)) {
+            $ipd .= $data;
+        }
+        return $this->parseResponse($ipd);
+    }
+
+    function parseResponse($data = "")
+    {
+        global $XML_RPC_xh,$XML_RPC_err,$XML_RPC_str;
+        global $XML_RPC_defencoding;
+
+        $parser = xml_parser_create($XML_RPC_defencoding);
+
+        $XML_RPC_xh[$parser] = array();
+
+        $XML_RPC_xh[$parser]['st'] = "";
+        $XML_RPC_xh[$parser]['cm'] = 0;
+        $XML_RPC_xh[$parser]['isf'] = 0;
+        $XML_RPC_xh[$parser]['ac'] = "";
+        $XML_RPC_xh[$parser]['qt'] = "";
+
+        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
+        xml_set_element_handler($parser, "XML_RPC_se", "XML_RPC_ee");
+        xml_set_character_data_handler($parser, "XML_RPC_cd");
+        xml_set_default_handler($parser, "XML_RPC_dh");
+        $xmlrpc_value = new XML_RPC_Value;
+
+        $hdrfnd = 0;
+        if ($this->debug) {
+            print "<PRE>---GOT---\n";
+            print isset($_SERVER['SERVER_PROTOCOL']) ? htmlspecialchars($data) : $data;
+            print "\n---END---\n</PRE>";
+        }
+
+        // see if we got an HTTP 200 OK, else bomb
+        // but only do this if we're using the HTTP protocol.
+        if (ereg("^HTTP",$data) &&
+            !ereg("^HTTP/[0-9\.]+ 200 ", $data)) {
+                $errstr = substr($data, 0, strpos($data, "\n")-1);
+                error_log("HTTP error, got response: " . $errstr);
+                $r = new XML_RPC_Response(0, $XML_RPC_err["http_error"],
+                                          $XML_RPC_str["http_error"] . " (" .
+                                          $errstr . ")");
+                xml_parser_free($parser);
+                return $r;
+        }
+        // gotta get rid of headers here
+
+
+        if ((!$hdrfnd) && ($brpos = strpos($data,"\r\n\r\n"))) {
+            $XML_RPC_xh[$parser]['ha'] = substr($data, 0, $brpos);
+            $data = substr($data, $brpos + 4);
+            $hdrfnd = 1;
+        }
+
+        // be tolerant of junk after methodResponse (e.g. javascript automatically inserted by free hosts)
+        // thanks to Luca Mariano <luca.mariano@email.it>
+        $data = substr($data, 0, strpos($data, "</methodResponse>") + 17);
+
+        if (!xml_parse($parser, $data, sizeof($data))) {
+            // thanks to Peter Kocks <peter.kocks@baygate.com>
+            if ((xml_get_current_line_number($parser)) == 1) {
+                $errstr = "XML error at line 1, check URL";
+            } else {
+                $errstr = sprintf("XML error: %s at line %d",
+                                  xml_error_string(xml_get_error_code($parser)),
+                                  xml_get_current_line_number($parser));
+            }
+            error_log($errstr);
+            $r = new XML_RPC_Response(0, $XML_RPC_err["invalid_return"],
+                                      $XML_RPC_str["invalid_return"]);
+            xml_parser_free($parser);
+            return $r;
+        }
+        xml_parser_free($parser);
+        if ($this->debug) {
+            print "<PRE>---EVALING---[" .
+            strlen($XML_RPC_xh[$parser]['st']) . " chars]---\n" .
+            htmlspecialchars($XML_RPC_xh[$parser]['st']) . ";\n---END---</PRE>";
+        }
+        if (strlen($XML_RPC_xh[$parser]['st']) == 0) {
+            // then something odd has happened
+            // and it's time to generate a client side error
+            // indicating something odd went on
+            $r = new XML_RPC_Response(0, $XML_RPC_err["invalid_return"],
+                                         $XML_RPC_str["invalid_return"]);
+        } else {
+            eval('$v=' . $XML_RPC_xh[$parser]['st'] . '; $allOK=1;');
+            if ($XML_RPC_xh[$parser]['isf']) {
+                $f = $v->structmem("faultCode");
+                $fs = $v->structmem("faultString");
+                $r = new XML_RPC_Response($v, $f->scalarval(),
+                                              $fs->scalarval());
+            } else {
+                $r = new XML_RPC_Response($v);
+            }
+        }
+        $r->hdrs = split("\r?\n", $XML_RPC_xh[$parser]['ha'][1]);
+        return $r;
+    }
+
+}
+
+
+class XML_RPC_Value extends XML_RPC_Base
+{
+    var $me = array();
+    var $mytype = 0;
+
+    function XML_RPC_Value($val = -1, $type = "")
+    {
+        global $XML_RPC_Types;
+        $this->me = array();
+        $this->mytype = 0;
+        if ($val != -1 || $type != "") {
+            if ($type == "") {
+                $type="string";
+            }
+            if ($XML_RPC_Types[$type] == 1) {
+                $this->addScalar($val,$type);
+            } elseif ($XML_RPC_Types[$type] == 2) {
+                $this->addArray($val);
+            } elseif ($XML_RPC_Types[$type] == 3) {
+                $this->addStruct($val);
+            }
+        }
+    }
+
+    function addScalar($val, $type = "string")
+    {
+        global $XML_RPC_Types, $XML_RPC_Boolean;
+
+        if ($this->mytype == 1) {
+            $this->raiseError("Scalar can have only one value", XML_RPC_ERROR_INVALID_TYPE);
+            return 0;
+        }
+        $typeof = $XML_RPC_Types[$type];
+        if ($typeof != 1) {
+            $this->raiseError("Not a scalar type (${typeof})", XML_RPC_ERROR_INVALID_TYPE);
+            return 0;
+        }
+
+        if ($type == $XML_RPC_Boolean) {
+            if (strcasecmp($val,"true") == 0 ||
+                $val == 1 ||
+                ($val == true &&
+                    strcasecmp($val,"false"))) {
+
+                $val = 1;
+            } else {
+                $val = 0;
+            }
+        }
+
+        if ($this->mytype == 2) {
+            // we're adding to an array here
+            $ar = $this->me["array"];
+            $ar[] = new XML_RPC_Value($val, $type);
+            $this->me["array"] = $ar;
+        } else {
+            // a scalar, so set the value and remember we're scalar
+            $this->me[$type] = $val;
+            $this->mytype = $typeof;
+        }
+        return 1;
+    }
+
+    function addArray($vals)
+    {
+        global $XML_RPC_Types;
+        if ($this->mytype != 0) {
+            $this->raiseError(
+                "Already initialized as a [" . $this->kindOf() . "]",
+                XML_RPC_ERROR_ALREADY_INITIALIZED);
+            return 0;
+        }
+        $this->mytype = $XML_RPC_Types["array"];
+        $this->me["array"] = $vals;
+        return 1;
+    }
+
+    function addStruct($vals)
+    {
+        global $XML_RPC_Types;
+        if ($this->mytype != 0) {
+            $this->raiseError(
+                "Already initialized as a [" . $this->kindOf() . "]",
+                XML_RPC_ERROR_ALREADY_INITIALIZED);
+            return 0;
+        }
+        $this->mytype = $XML_RPC_Types["struct"];
+        $this->me["struct"] = $vals;
+        return 1;
+    }
+
+    function dump($ar)
+    {
+        reset($ar);
+        while (list( $key, $val ) = each($ar)) {
+            echo "$key => $val<br>";
+            if ($key == 'array') {
+                while ( list( $key2, $val2 ) = each( $val ) ) {
+                    echo "-- $key2 => $val2<br>";
+                }
+            }
+        }
+    }
+
+    function kindOf()
+    {
+        switch ($this->mytype) {
+        case 3:
+            return "struct";
+            break;
+        case 2:
+            return "array";
+            break;
+        case 1:
+            return "scalar";
+            break;
+        default:
+            return "undef";
+        }
+    }
+
+    function serializedata($typ, $val)
+    {
+        $rs = "";
+        global $XML_RPC_Types, $XML_RPC_Base64, $XML_RPC_String, $XML_RPC_Boolean;
+        switch ($XML_RPC_Types[$typ]) {
+        case 3:
+            // struct
+            $rs .= "<struct>\n";
+            reset($val);
+            while(list($key2, $val2) = each($val)) {
+                $rs .= "<member><name>${key2}</name>\n";
+                $rs .= $this->serializeval($val2);
+                $rs .= "</member>\n";
+            }
+            $rs .= "</struct>";
+            break;
+        case 2:
+            // array
+            $rs .= "<array>\n<data>\n";
+            for($i = 0; $i < sizeof($val); $i++) {
+                $rs .= $this->serializeval($val[$i]);
+            }
+            $rs .= "</data>\n</array>";
+            break;
+        case 1:
+            switch ($typ) {
+            case $XML_RPC_Base64:
+                $rs .= "<${typ}>" . base64_encode($val) . "</${typ}>";
+                break;
+            case $XML_RPC_Boolean:
+                $rs .= "<${typ}>" . ($val ? "1" : "0") . "</${typ}>";
+                break;
+            case $XML_RPC_String:
+                $rs .= "<${typ}>" . htmlspecialchars($val). "</${typ}>";
+                break;
+            default:
+                $rs .= "<${typ}>${val}</${typ}>";
+            }
+            break;
+        default:
+            break;
+        }
+        return $rs;
+    }
+
+    function serialize()
+    {
+        return $this->serializeval($this);
+    }
+
+    function serializeval($o)
+    {
+        $rs = "";
+        $ar = $o->me;
+        reset($ar);
+        list($typ, $val) = each($ar);
+        $rs .= "<value>";
+        $rs .= $this->serializedata($typ, $val);
+        $rs .= "</value>\n";
+        return $rs;
+    }
+
+    function structmem($m)
+    {
+        $nv = $this->me["struct"][$m];
+        return $nv;
+    }
+
+    function structreset()
+    {
+        reset($this->me["struct"]);
+    }
+
+    function structeach()
+    {
+        return each($this->me["struct"]);
+    }
+
+    function getval() {
+        // UNSTABLE
+        global $XML_RPC_BOOLEAN, $XML_RPC_Base64;
+
+        reset($this->me);
+        list($a,$b) = each($this->me);
+
+        // contributed by I Sofer, 2001-03-24
+        // add support for nested arrays to scalarval
+        // i've created a new method here, so as to
+        // preserve back compatibility
+
+        if (is_array($b)) {
+            foreach ($b as $id => $cont) {
+                $b[$id] = $cont->scalarval();
+            }
+        }
+
+        // add support for structures directly encoding php objects
+        if (is_object($b)) {
+            $t = get_object_vars($b);
+            foreach ($t as $id => $cont) {
+                $t[$id] = $cont->scalarval();
+            }
+            foreach ($t as $id => $cont) {
+                eval('$b->'.$id.' = $cont;');
+            }
+        }
+
+        // end contrib
+        return $b;
+    }
+
+    function scalarval()
+    {
+        global $XML_RPC_Boolean, $XML_RPC_Base64;
+        reset($this->me);
+        list($a,$b) = each($this->me);
+        return $b;
+    }
+
+    function scalartyp()
+    {
+        global $XML_RPC_I4, $XML_RPC_Int;
+        reset($this->me);
+        list($a,$b) = each($this->me);
+        if ($a == $XML_RPC_I4) {
+            $a = $XML_RPC_Int;
+        }
+        return $a;
+    }
+
+    function arraymem($m)
+    {
+        $nv = $this->me["array"][$m];
+        return $nv;
+    }
+
+    function arraysize()
+    {
+        reset($this->me);
+        list($a,$b) = each($this->me);
+        return sizeof($b);
+    }
+}
+
+
+/**
+ * date helpers
+ */
+function XML_RPC_iso8601_encode($timet, $utc = 0) {
+    // return an ISO8601 encoded string
+    // really, timezones ought to be supported
+    // but the XML-RPC spec says:
+    //
+    // "Don't assume a timezone. It should be specified by the server in its
+    // documentation what assumptions it makes about timezones."
+    //
+    // these routines always assume localtime unless
+    // $utc is set to 1, in which case UTC is assumed
+    // and an adjustment for locale is made when encoding
+    if (!$utc) {
+        $t = strftime("%Y%m%dT%H:%M:%S", $timet);
+    } else {
+        if (function_exists("gmstrftime")) {
+            // gmstrftime doesn't exist in some versions
+            // of PHP
+            $t = gmstrftime("%Y%m%dT%H:%M:%S", $timet);
+        } else {
+            $t = strftime("%Y%m%dT%H:%M:%S", $timet - date("Z"));
+        }
+    }
+
+    return $t;
+}
+
+function XML_RPC_iso8601_decode($idate, $utc = 0) {
+    // return a timet in the localtime, or UTC
+    $t = 0;
+    if (ereg("([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})", $idate, $regs)) {
+
+        if ($utc) {
+            $t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
+        } else {
+            $t = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]);
+        }
+    }
+
+    return $t;
+}
+
+/**
+ * Takes a message in PHP XML_RPC object format and translates it into native PHP types.
+ *
+ * @author Dan Libby <dan@libby.com>
+ **/
+function XML_RPC_decode($XML_RPC_val) {
+    $kind = $XML_RPC_val->kindOf();
+
+   if ($kind == "scalar") {
+      return $XML_RPC_val->scalarval();
+
+   } elseif ($kind == "array") {
+      $size = $XML_RPC_val->arraysize();
+      $arr = array();
+
+      for($i = 0; $i < $size; $i++) {
+         $arr[] = XML_RPC_decode($XML_RPC_val->arraymem($i));
+      }
+      return $arr;
+
+   } elseif ($kind == "struct") {
+      $XML_RPC_val->structreset();
+      $arr = array();
+
+      while(list($key,$value) = $XML_RPC_val->structeach()) {
+         $arr[$key] = XML_RPC_decode($value);
+      }
+      return $arr;
+   }
+}
+
+/**
+ * Takes native php types and encodes them into XML_RPC PHP object format.
+ *
+ * Feature creep -- could support more types via optional type argument.
+ *
+ * @author Dan Libby <dan@libby.com>
+ **/
+function XML_RPC_encode($php_val) {
+   global $XML_RPC_Boolean;
+   global $XML_RPC_Int;
+   global $XML_RPC_Double;
+   global $XML_RPC_String;
+   global $XML_RPC_Array;
+   global $XML_RPC_Struct;
+
+   $type = gettype($php_val);
+   $XML_RPC_val = new XML_RPC_Value;
+
+   switch ($type) {
+   case "array":
+       $keys = array_keys($php_val);
+       $count = count($php_val);
+       $firstkey = $keys[0];
+       $lastkey = $keys[$count - 1];
+       if ($firstkey === 0 && is_int($lastkey) && ($lastkey + 1) == $count) {
+           $is_continuous = true;
+           $expected = 0;
+           foreach ($keys as $actual) {
+               if ($actual != $expected) {
+                   $is_continuous = false;
+                   break;
+               }
+               $expected++;
+           }
+
+           if ($is_continuous) {
+               $arr = array();
+               foreach ($php_val as $k => $v) {
+                   $arr[$k] = XML_RPC_encode($v);
+               }
+               $XML_RPC_val->addArray($arr);
+               break;
+           }
+       }
+       // fall though if not numerical and continuous
+   case "object":
+       $arr = array();
+       foreach ($php_val as $k => $v) {
+           $arr[$k] = XML_RPC_encode($v);
+       }
+       $XML_RPC_val->addStruct($arr);
+       break;
+
+   case "integer":
+       $XML_RPC_val->addScalar($php_val, $XML_RPC_Int);
+       break;
+
+   case "double":
+       $XML_RPC_val->addScalar($php_val, $XML_RPC_Double);
+       break;
+
+   case "string":
+   case "NULL":
+       $XML_RPC_val->addScalar($php_val, $XML_RPC_String);
+       break;
+
+   // <G_Giunta_2001-02-29>
+   // Add support for encoding/decoding of booleans, since they are supported in PHP
+   case "boolean":
+       $XML_RPC_val->addScalar($php_val, $XML_RPC_Boolean);
+       break;
+   // </G_Giunta_2001-02-29>
+
+   case "unknown type":
+   default:
+       $XML_RPC_val = false;
+       break;
+   }
+   return $XML_RPC_val;
+}
+
+?>
diff --git a/bundled-libs/XML/RPC/Server.php b/bundled-libs/XML/RPC/Server.php
new file mode 100644 (file)
index 0000000..9f2f743
--- /dev/null
@@ -0,0 +1,312 @@
+<?php
+// /* vim: set expandtab tabstop=4 shiftwidth=4: */
+// by Edd Dumbill (C) 1999,2000
+// <edd@usefulinc.com>
+
+// License is granted to use or modify this software ("XML-RPC for PHP")
+// for commercial or non-commercial use provided the copyright of the author
+// is preserved in any distributed or derivative work.
+
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
+// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Adapted to PEAR standards by Stig S�her Bakken <stig@php.net>
+// /* $Id: Server.php,v 1.2 2004/07/26 15:08:11 nohn Exp $ */
+
+require_once "XML/RPC.php";
+
+// listMethods: either a string, or nothing
+$GLOBALS['XML_RPC_Server_listMethods_sig'] =
+    array(array($GLOBALS['XML_RPC_Array'], $GLOBALS['XML_RPC_String']),
+          array($GLOBALS['XML_RPC_Array']));
+$GLOBALS['XML_RPC_Server_listMethods_doc'] =
+    'This method lists all the methods that the XML-RPC server knows how to dispatch';
+
+function XML_RPC_Server_listMethods($server, $m)
+{
+    global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
+    $v = new XML_RPC_Value();
+    $dmap = $server->dmap;
+    $outAr = array();
+    for (reset($dmap); list($key, $val) = each($dmap); ) {
+        $outAr[] = new XML_RPC_Value($key, "string");
+    }
+    $dmap = $XML_RPC_Server_dmap;
+    for (reset($dmap); list($key, $val) = each($dmap); ) {
+        $outAr[] = new XML_RPC_Value($key, "string");
+    }
+    $v->addArray($outAr);
+    return new XML_RPC_Response($v);
+}
+
+$GLOBALS['XML_RPC_Server_methodSignature_sig'] =
+    array(array($GLOBALS['XML_RPC_Array'], $GLOBALS['XML_RPC_String']));
+$GLOBALS['XML_RPC_Server_methodSignature_doc'] =
+    'Returns an array of known signatures (an array of arrays) for the method name passed. If no signatures are known, returns a none-array (test for type != array to detect missing signature)';
+
+function XML_RPC_Server_methodSignature($server, $m)
+{
+    global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
+
+    $methName = $m->getParam(0);
+    $methName = $methName->scalarval();
+    if (strpos($methName, "system.") === 0) {
+        $dmap = $XML_RPC_Server_dmap;
+        $sysCall = 1;
+    } else {
+        $dmap = $server->dmap;
+        $sysCall = 0;
+    }
+    //  print "<!-- ${methName} -->\n";
+    if (isset($dmap[$methName])) {
+        if ($dmap[$methName]["signature"]) {
+            $sigs = array();
+            $thesigs = $dmap[$methName]["signature"];
+            for ($i = 0; $i < sizeof($thesigs); $i++) {
+                $cursig = array();
+                $inSig = $thesigs[$i];
+                for ($j = 0; $j < sizeof($inSig); $j++) {
+                    $cursig[] = new XML_RPC_Value($inSig[$j], "string");
+                }
+                $sigs[] = new XML_RPC_Value($cursig, "array");
+            }
+            $r = new XML_RPC_Response(new XML_RPC_Value($sigs, "array"));
+        } else {
+            $r = new XML_RPC_Response(new XML_RPC_Value("undef", "string"));
+        }
+    } else {
+        $r = new XML_RPC_Response(0, $XML_RPC_err["introspect_unknown"],
+                                     $XML_RPC_str["introspect_unknown"]);
+    }
+    return $r;
+}
+
+$GLOBALS['XML_RPC_Server_methodHelp_sig'] =
+    array(array($GLOBALS['XML_RPC_String'], $GLOBALS['XML_RPC_String']));
+$GLOBALS['XML_RPC_Server_methodHelp_doc'] =
+    'Returns help text if defined for the method passed, otherwise returns an empty string';
+
+function XML_RPC_Server_methodHelp($server, $m)
+{
+    global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap;
+
+    $methName = $m->getParam(0);
+    $methName = $methName->scalarval();
+    if (strpos($methName, "system.") === 0) {
+        $dmap = $XML_RPC_Server_dmap;
+        $sysCall = 1;
+    } else {
+        $dmap = $server->dmap;
+        $sysCall = 0;
+    }
+    //  print "<!-- ${methName} -->\n";
+    if (isset($dmap[$methName])) {
+        if ($dmap[$methName]["docstring"]) {
+            $r = new XML_RPC_Response(new XML_RPC_Value($dmap[$methName]["docstring"]), "string");
+        } else {
+            $r = new XML_RPC_Response(new XML_RPC_Value("", "string"));
+        }
+    } else {
+        $r = new XML_RPC_Response(0, $XML_RPC_err["introspect_unknown"],
+                                     $XML_RPC_str["introspect_unknown"]);
+    }
+    return $r;
+}
+
+$GLOBALS['XML_RPC_Server_dmap'] = array(
+    "system.listMethods" =>
+        array("function"  => "XML_RPC_Server_listMethods",
+              "signature" => $GLOBALS['XML_RPC_Server_listMethods_sig'],
+              "docstring" => $GLOBALS['XML_RPC_Server_listMethods_doc']),
+
+    "system.methodHelp" =>
+        array("function"  => "XML_RPC_Server_methodHelp",
+              "signature" => $GLOBALS['XML_RPC_Server_methodHelp_sig'],
+              "docstring" => $GLOBALS['XML_RPC_Server_methodHelp_doc']),
+
+    "system.methodSignature" =>
+        array("function"  => "XML_RPC_Server_methodSignature",
+              "signature" => $GLOBALS['XML_RPC_Server_methodSignature_sig'],
+              "docstring" => $GLOBALS['XML_RPC_Server_methodSignature_doc'])
+);
+
+$GLOBALS['XML_RPC_Server_debuginfo'] = "";
+
+function XML_RPC_Server_debugmsg($m)
+{
+    global $XML_RPC_Server_debuginfo;
+    $XML_RPC_Server_debuginfo = $XML_RPC_Server_debuginfo . $m . "\n";
+}
+
+class XML_RPC_Server
+{
+    var $dmap = array();
+
+    function XML_RPC_Server($dispMap, $serviceNow = 1)
+    {
+        global $HTTP_RAW_POST_DATA;
+        // dispMap is a despatch array of methods
+        // mapped to function names and signatures
+        // if a method
+        // doesn't appear in the map then an unknown
+        // method error is generated
+        $this->dmap = $dispMap;
+        if ($serviceNow) {
+            $this->service();
+        }
+    }
+
+    function serializeDebug()
+    {
+        global $XML_RPC_Server_debuginfo;
+        if ($XML_RPC_Server_debuginfo != "") {
+            return "<!-- DEBUG INFO:\n\n" . preg_replace('/-(?=-)/', '- ',
+                    $XML_RPC_Server_debuginfo) . "\n-->\n";
+        } else {
+            return "";
+        }
+    }
+
+    function service()
+    {
+        $r = $this->parseRequest();
+        $payload = "<?xml version=\"1.0\"?>\n" .
+            $this->serializeDebug() .
+            $r->serialize();
+        header('Content-Length: ' . strlen($payload));
+        header('Content-Type: text/xml');
+        print $payload;
+    }
+
+    function verifySignature($in, $sig)
+    {
+        for ($i = 0; $i < sizeof($sig); $i++) {
+            // check each possible signature in turn
+            $cursig = $sig[$i];
+            if (sizeof($cursig) == $in->getNumParams() + 1) {
+                $itsOK = 1;
+                for ($n = 0; $n < $in->getNumParams(); $n++) {
+                    $p = $in->getParam($n);
+                    // print "<!-- $p -->\n";
+                    if ($p->kindOf() == "scalar") {
+                        $pt = $p->scalartyp();
+                    } else {
+                        $pt = $p->kindOf();
+                    }
+                    // $n+1 as first type of sig is return type
+                    if ($pt != $cursig[$n+1]) {
+                        $itsOK = 0;
+                        $pno = $n+1;
+                        $wanted = $cursig[$n+1];
+                        $got = $pt;
+                        break;
+                    }
+                }
+                if ($itsOK)
+                    return array(1);
+            }
+        }
+        return array(0, "Wanted ${wanted}, got ${got} at param ${pno})");
+    }
+
+    function parseRequest($data = "")
+    {
+        global $XML_RPC_xh,$HTTP_RAW_POST_DATA;
+        global $XML_RPC_err, $XML_RPC_str, $XML_RPC_errxml,
+            $XML_RPC_defencoding, $XML_RPC_Server_dmap;
+
+        if ($data == "") {
+            $data = $HTTP_RAW_POST_DATA;
+        }
+        $parser = xml_parser_create($XML_RPC_defencoding);
+
+        $XML_RPC_xh[$parser] = array();
+        $XML_RPC_xh[$parser]['st'] = "";
+        $XML_RPC_xh[$parser]['cm'] = 0;
+        $XML_RPC_xh[$parser]['isf'] = 0;
+        $XML_RPC_xh[$parser]['params'] = array();
+        $XML_RPC_xh[$parser]['method'] = "";
+
+        $plist = '';
+
+        // decompose incoming XML into request structure
+
+        xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true);
+        xml_set_element_handler($parser, "XML_RPC_se", "XML_RPC_ee");
+        xml_set_character_data_handler($parser, "XML_RPC_cd");
+        xml_set_default_handler($parser, "XML_RPC_dh");
+        if (!xml_parse($parser, $data, 1)) {
+            // return XML error as a faultCode
+            $r = new XML_RPC_Response(0,
+                                      $XML_RPC_errxml+xml_get_error_code($parser),
+                                      sprintf("XML error: %s at line %d",
+                                              xml_error_string(xml_get_error_code($parser)),
+                                              xml_get_current_line_number($parser)));
+            xml_parser_free($parser);
+        } else {
+            xml_parser_free($parser);
+            $m = new XML_RPC_Message($XML_RPC_xh[$parser]['method']);
+            // now add parameters in
+            for ($i = 0; $i < sizeof($XML_RPC_xh[$parser]['params']); $i++) {
+                // print "<!-- " . $XML_RPC_xh[$parser]['params'][$i]. "-->\n";
+                $plist .= "$i - " . $XML_RPC_xh[$parser]['params'][$i] . " \n";
+                eval('$m->addParam(' . $XML_RPC_xh[$parser]['params'][$i] . ");");
+            }
+            XML_RPC_Server_debugmsg($plist);
+            // now to deal with the method
+            $methName = $XML_RPC_xh[$parser]['method'];
+            if (strpos($methName, "system.") === 0) {
+                $dmap = $XML_RPC_Server_dmap;
+                $sysCall = 1;
+            } else {
+                $dmap = $this->dmap;
+                $sysCall = 0;
+            }
+            if (isset($dmap[$methName]['function']) && is_callable($dmap[$methName]['function'])) {
+                // dispatch if exists
+                if (isset($dmap[$methName]['signature'])) {
+                    $sr = $this->verifySignature($m,
+                                                 $dmap[$methName]['signature'] );
+                }
+                if ( (!isset($dmap[$methName]['signature'])) || $sr[0]) {
+                    // if no signature or correct signature
+                    if ($sysCall) {
+                        $r = call_user_func($dmap[$methName]['function'], $this, $m);
+                    } else {
+                        $r = call_user_func($dmap[$methName]['function'], $m);
+                    }
+                } else {
+                    $r = new XML_RPC_Response(0, $XML_RPC_err["incorrect_params"],
+                                                 $XML_RPC_str["incorrect_params"] .
+                                                 ": " . $sr[1]);
+                }
+            } else {
+                // else prepare error response
+                $r = new XML_RPC_Response(0, $XML_RPC_err["unknown_method"],
+                                             $XML_RPC_str["unknown_method"]);
+            }
+        }
+        return $r;
+    }
+
+  function echoInput() {
+        global $HTTP_RAW_POST_DATA;
+
+        // a debugging routine: just echos back the input
+        // packet as a string value
+
+        $r = new XML_RPC_Response;
+        $r->xv = new XML_RPC_Value("'Aha said I: '" . $HTTP_RAW_POST_DATA, "string");
+        print $r->serialize();
+  }
+}
+
+?>
diff --git a/bundled-libs/create_release.sh b/bundled-libs/create_release.sh
new file mode 100644 (file)
index 0000000..ea26db8
--- /dev/null
@@ -0,0 +1,104 @@
+#!/bin/sh
+# File: create_release.sh
+# Author: Garvin Hicing
+# $Id: create_release.sh,v 1.6 2005/03/04 10:16:38 garvinhicking Exp $
+#
+# Description:
+# This file is only used for developers to create a Serendipity release file
+# with all the proper file permissions. CVS doesn't track the rightly, so we
+# need to fix it before releasing.
+#
+# Usage:
+# As security precaution for any other users just executing this script, there
+# are two required input parameters. The first being the basename path of the
+# serendipity installation. The second parameter is the target owner of the files.
+
+echo ""
+echo "-[serendipity create_release.sh START]---------------------------------"
+
+if [ "x$1" = "x" ] || [ "x$2" = "x" ] || [ "x$3" = "x" ] || [ "x$4" = "x" ];
+then
+    echo "usage: ./create_release.sh
+            [tar.gz dump filename]
+            [serendipity installation dirname, without paths]
+            [username, i.e. nobody]
+            [group, i.e. nogroup]"
+    echo ""
+    echo "example:"
+    echo " $> cd serendipity/bundled-libs/"
+    echo " $> ./create_release.sh serendipity-0.7.tar.gz serendipity nobody nogroup"
+    echo ""
+    echo "WARNING: Running this script in a productive blog environment will do"
+    echo "         serious harm!"
+    echo "-[serendipity create_release.sh END]----------------------------------"
+    echo ""
+    exit 1
+else
+    if test "../../$2"
+    then
+        echo "WARNING: Running this script in a productive blog environment will do"
+        echo "         serious harm! Only use it, if you are a developer and about"
+        echo "         to bundle a new release version!"
+        echo ""
+        echo "Hit [ENTER] to continue, or abort this script"
+        read -n 1
+
+        echo "1. Operating on basedirectory ../../$2"
+            cd ../../
+            echo "    [DONE]"
+            echo ""
+
+        echo "2. Adjusting all subdirectory permissions to 755"
+            find "$2" -type d -exec chmod 755 {} \;
+            echo "    [DONE]"
+            echo ""
+
+        echo "3. Adjusting core directory permissions to 777"
+            chmod 777 "$2"
+            chmod 777 "$2/templates_c"
+            chmod 777 "$2/plugins"
+            echo "    [DONE]"
+            echo ""
+
+        echo "4. Adjusting all file permissions to 644"
+            find "$2" -type f -exec chmod 644 {} \;
+            echo "    [DONE]"
+            echo ""
+
+        echo "5. Adjusting special files..."
+            echo "   - $2/.htaccess [666]"
+            chmod 666 "$2/.htaccess"
+
+            echo "   - $2/upgrade.sh [744]"
+            chmod 744 "$2/upgrade.sh"
+
+            echo "   - $2/bundled-libs/create_release.sh [766]"
+            chmod 766 "$2/bundled-libs/create_release.sh"
+            echo "    [DONE]"
+            echo ""
+
+        echo "6. Altering CVS to be useful for anonymous users..."
+            echo "   - Removing CVS branch tag, so that a user can upgrade to latest CVS"
+            find "$2" -type f -name Tag -exec rm {} \;
+            echo "       [DONE]"
+
+            echo "   - Inserting ANONYMOUS user instead of Developer account"
+            for i in `find $2 -type f -name Root` ; do
+                echo ':pserver:anonymous@cvs.sf.net:/cvsroot/php-blog' > $i;
+            done
+            echo "       [DONE]"
+            echo ""
+
+        echo "7. Creating .tgz file $1"
+            tar --owner=$3 --group=$4 -czf "$1" "$2"
+            echo "    [DONE]"
+            echo ""
+
+        echo "8. All Done. Bybe-Bye."
+    else
+        echo "Basedirectory ../../$2 not found. Check parameters"
+    fi
+    echo "-[serendipity create_release.sh END]----------------------------------"
+    echo ""
+fi
+
diff --git a/bundled-libs/docs/HomePage.wiki.txt b/bundled-libs/docs/HomePage.wiki.txt
new file mode 100644 (file)
index 0000000..5e156a7
--- /dev/null
@@ -0,0 +1,263 @@
++ Text_Wiki
+
+%%TOC%%
+
+++ Overview and Background
+
+We assume you know what [http://c2.com/cgi/wiki Wiki] is.  The Wiki Way entails a lot more than just rules for structured-text markup, but that's the only part of the Wiki Way that this package, {{Text_Wiki}}, is concerned with.
+
+The {{Text_Wiki}} package allows you to transform text structured using Wiki rules into any defined target output format. For example, you can convert...
+
+* Tavi-style Wiki text into XHTML
+* Original C2-style Wiki text into XML
+* !MeatBall style Wiki text into !LaTeX
+* Any other Wiki markup rules into any other format (provided it's programmed properly ;-)
+
+{{Text_Wiki}} achieves this level of flexibility by using one class per transformation rule, instead of using a monolithic set of functions.  Each Text_Wiki rule has these methods:
+
+* A constructor that links back to the "master" Text_Wiki class, which the source text as well as any optional confugration parameters
+* A parse() method that looks through the source text for strings that match a regular expression
+* A process() method that takes the parsed regular expression matches and converts them to an intermediate "meta-format" (generally a delimited token that is re-inserted into the source text, along with a set of options for that specific token)
+* A render() method that replaces a saved token with output for a specific target format (e.g., XHTML or !LaTeX).
+
+{{Text_Wiki}} draws its inspiration from a number of codebases, most notably !WikkiTikkiTavi and coWiki; while no code has been directly copied from those codebases, they were indispensible in learning how to process Wiki text.
+
+Also see these pages for more information:
+
+* SamplePage -- for a full list of default markup rules
+* TokenRuleKeys -- for a list of the tokens keys generated by different rules
+* TextWikiProposal -- a modified version of the initial Text_Wiki proposal to PEAR
+
+++ What Text_Wiki Does Not Do
+
+The {{Text_Wiki}} package does not implement storage, saving, editing, diffs, page counts, and so on.  Those functions are more properly the domain of a full Wiki application and environment, which is outside the stated {{Text_Wiki}} goals (i.e., to transform Wiki text according to defined rules for a target output format).
+
+++ Using Text_Wiki
+
+Here is a quick example of how to use {{Text_Wiki}} to parse from the default markup style (combined from [http://tavi.sourceforge.net/ Tavi] and [http://develnet.org/ coWiki]), do some basic filtering, and render to XHTML.
+
+<php>
+       
+       // require the Text_Wiki class and create an instance of a new wiki
+       // parse-and-render object
+       require_once 'Text/Wiki.php';
+       $wiki = new Text_Wiki();
+       
+       // load up some source text
+       $text = file_get_contents('sample.wiki.txt');
+       
+       // transform the text using the default rules for parsing and rendering.
+       // the extra \n newlines seem to help with some parsing rules.
+       echo $wiki->transform("\n" . $text . "\n");
+       
+</php>
+
+
+
+++ Text_Wiki Options
+
+When you create an instance of Text_Wiki, you can pass a set of options as an associative array. 
+
+The array keys for the options are:
+
+|| '''option key''' || '''variable type''' || '''description''' ||
+|| {{delim}}        || string              || the source text delimiter for tokens ||
+|| {{interwiki}}    || array               || interwiki site names and URLs ||
+|| {{new_text}}     || string              || link-text for new pages ||
+|| {{new_url}}      || string              || URL for new pages ||
+|| {{pages}}        || array               || list of pages existing in the wiki ||
+|| {{rules}}        || array               || the list of rules to be applied to source text ||
+|| {{view_url}}     || string              || URL for viewing pages in the wiki ||
+
+For example:
+
+<php>
+       // the list of rules, and in which order, to use when
+       // transforming structured text; the key is the name to use for
+       // identifying tokens for the rule, and the value is the file
+       // name of the rule class.
+       $rules = array(
+        'prefilter'   => 'Text/Wiki/Rule/prefilter.php',
+        'delimiter'   => 'Text/Wiki/Rule/delimiter.php',
+        'code'        => 'Text/Wiki/Rule/code.php',
+        'phpcode'     => 'Text/Wiki/Rule/phpcode.php',
+        'html'        => 'Text/Wiki/Rule/html.php',
+        'heading'     => 'Text/Wiki/Rule/heading.php',
+        'horiz'       => 'Text/Wiki/Rule/horiz.php',
+        'blockquote'  => 'Text/Wiki/Rule/blockquote.php',
+        'deflist'     => 'Text/Wiki/Rule/deflist.php',
+        'table'       => 'Text/Wiki/Rule/table.php',
+        'list'        => 'Text/Wiki/Rule/list.php',
+        'toc'         => 'Text/Wiki/Rule/toc.php',
+        'paragraph'   => 'Text/Wiki/Rule/paragraph.php',
+        'raw'         => 'Text/Wiki/Rule/raw.php',
+        'phplookup'   => 'Text/Wiki/Rule/phplookup.php',
+        'url'         => 'Text/Wiki/Rule/url.php',
+        'interwiki'   => 'Text/Wiki/Rule/interwiki.php',
+        'freelink'    => 'Text/Wiki/Rule/freelink.php',
+        'wikilink'    => 'Text/Wiki/Rule/wikilink.php',
+        'strong'      => 'Text/Wiki/Rule/strong.php',
+        'bold'        => 'Text/Wiki/Rule/bold.php',
+        'emphasis'    => 'Text/Wiki/Rule/emphasis.php',
+        'italic'      => 'Text/Wiki/Rule/italic.php',
+        'tt'          => 'Text/Wiki/Rule/tt.php',
+        'superscript' => 'Text/Wiki/Rule/superscript.php',
+        'revise'      => 'Text/Wiki/Rule/revise.php',
+        'entities'    => 'Text/Wiki/Rule/entities.php',
+        'tighten'     => 'Text/Wiki/Rule/tighten.php'
+       );
+       
+       // the list of InterWiki names and URLs
+       $interwiki = array(
+               'MeatBall' => 'http://www.usemod.com/cgi-bin/mb.pl?',
+               'Advogato' => 'http://advogato.org/',
+               'Wiki'     => 'http://c2.com/cgi/wiki?'
+       );
+       
+       // the URL used to view local WikiWeb pages
+       $view_url = "http://example.com/wiki.php?page=";
+       
+       // create a Text_Wiki options array
+       $options = array(
+               'rules'     => $rules,
+               'interwiki' => $interwiki,
+               'view_url'  => $view_url
+       );
+       
+       // instantiate a Text_Wiki object with the options
+       $wiki =& new Text_Wiki($options);
+</php>
+
+
+
++++ {{delim}}
+
+The {{delim}} option is a string, and sets the value of the delimiter character used to mark a token number in the Wiki source text.  When a rule needs to set a token, it replaces the source text with a token number surrounded by this delimiter.
+
+The default delmiter is {{```\xFF```}}, but you can change it to anything you like.  Be aware that the token you choose may be subject to Wiki rules, so be sure to choose something that the rules don't affect.
+
+For example:
+
+<php>
+       // use a nullchar delimiter
+       $options['delim'] = '\x00');
+</php>
+
+
+
++++ {{interwiki}}
+
+The {{interwiki}} option is an associative array where the key is an !InterWiki site name, and the value is the URL for pages at that site.  For example, if you want to refer to the !MeatBall site in your pages using the !InterWiki rule, you need to pass this option.
+
+<php>
+       // name and link to the MeatBall Wiki
+       $options['interwiki'] = array(
+               'MeatBall' => 'http://www.usemod.com/cgi-bin/mb.pl?'
+       );
+</php>
+
+
+
+
++++ {{new_text}}
+
+The {{new_text}} option is a string.  If your wiki source text refers to a page that does not exist (as provided by the {{pages}} option) then it is considered to be a "new" page; thus, the Text_Wiki will link to a web page for creating new pages.
+
+The {{new_text}} option specifies the literal linked text to be appended to the page name on display.  It can be text proper, or an HTML image tag, or anything else.
+
+See also the {{new_url}} option.
+
+<php>
+       // use a question mark and a space
+       $options['new_text'] = '? ';
+       
+       // use an image
+       $options['new_text'] = '<img src="http://example.com/newpage.gif />';
+</php>
+
+
+
++++ {{new_url}}
+
+The {{new_url}} option is a string.  If your wiki source text refers to a page that does not exist (as provided by the {{pages}} option) then it is considered to be a "new" page; thus, Text_Wiki will link to a web page for creating new pages.
+
+The {{new_url}} specifies the URL to the application-specific page creation utility.
+
+See also the {{new_text}} option.
+
+<php>
+       // link to the new-page script
+       $options['new_url']  = 'http://example.com/newpage.php?page=';
+</php>
+
+
++++ {{pages}}
+
+The {{pages}} option is a sequential array where each element is the name of page in the Wiki.  See also the {{view_url}} option.
+
+<php>
+       // only three pages in this wiki
+       $options['pages'] = array(
+               'HomePage',
+               'SamplePage',
+               'TokenRuleKeys'
+       )
+</php>
+
+
++++ {{rules}}
+
+This option is a associative array; it specifies the rule names to apply to wiki source text.  The key is the token name to be used when idenitfying text marked by that rule, and the value is the file name of the rule class.  (Previously, rule class names and rule file names had to adhere to a specific convention; that is no longer necessary.)
+
+<php>
+       $options['rules'] = array(
+        'prefilter'   => 'Text/Wiki/Rule/prefilter.php',
+        'delimiter'   => 'Text/Wiki/Rule/delimiter.php',
+        'code'        => 'Text/Wiki/Rule/code.php',
+        'phpcode'     => 'Text/Wiki/Rule/phpcode.php',
+        'html'        => 'Text/Wiki/Rule/html.php',
+        'heading'     => 'Text/Wiki/Rule/heading.php',
+        'horiz'       => 'Text/Wiki/Rule/horiz.php',
+        'blockquote'  => 'Text/Wiki/Rule/blockquote.php',
+        'deflist'     => 'Text/Wiki/Rule/deflist.php',
+        'table'       => 'Text/Wiki/Rule/table.php',
+        'list'        => 'Text/Wiki/Rule/list.php',
+        'toc'         => 'Text/Wiki/Rule/toc.php',
+        'paragraph'   => 'Text/Wiki/Rule/paragraph.php',
+        'raw'         => 'Text/Wiki/Rule/raw.php',
+        'phplookup'   => 'Text/Wiki/Rule/phplookup.php',
+        'url'         => 'Text/Wiki/Rule/url.php',
+        'interwiki'   => 'Text/Wiki/Rule/interwiki.php',
+        'freelink'    => 'Text/Wiki/Rule/freelink.php',
+        'wikilink'    => 'Text/Wiki/Rule/wikilink.php',
+        'strong'      => 'Text/Wiki/Rule/strong.php',
+        'bold'        => 'Text/Wiki/Rule/bold.php',
+        'emphasis'    => 'Text/Wiki/Rule/emphasis.php',
+        'italic'      => 'Text/Wiki/Rule/italic.php',
+        'tt'          => 'Text/Wiki/Rule/tt.php',
+        'superscript' => 'Text/Wiki/Rule/superscript.php',
+        'revise'      => 'Text/Wiki/Rule/revise.php',
+        'entities'    => 'Text/Wiki/Rule/entities.php',
+        'tighten'     => 'Text/Wiki/Rule/tighten.php'
+       );
+</php>
+
+The above is the default list of rules.  If you want to use your own (for example) {{wikilink}} rule to override the default rule, you can replace the array element with the path to your modified rule:
+
+<php>
+       // [snip] set up $options
+       $wiki =& new Text_Wiki($options);
+       
+       // replace the 'wikilink' default rule
+       $wiki->rules['wikilink'] = '/path/to/my/rules/my_wikilink.php';
+</php>
+
+
++++ {{view_url}}
+
+The {{view_url}} option is a string that specifies the URL to the application-specific page viewing utility.  If your wiki source text refers to a page listed in the {{pages}} option array, the Text_Wiki rules for 'wiki' and 'wikifreelink' will create a link to that page using this URL.
+
+<php>
+       // link to the page-viewing script
+       $options['view_url'] = 'http://example.com/wiki.php?page=';
+</php>
diff --git a/bundled-libs/docs/SamplePage.wiki.txt b/bundled-libs/docs/SamplePage.wiki.txt
new file mode 100644 (file)
index 0000000..f78522e
--- /dev/null
@@ -0,0 +1,374 @@
++ Sample Page for Text_Wiki Default Markup
+
+%%TOC%%
+
+----
+
+++ General Notes
+
+The markup described on this page is for the default {{Text_Wiki}} rules; \
+it is a combination of the [http://tavi.sourceforge.net WikkTikkiTavi] \
+and [http://develnet.org/ coWiki] markup styles.
+
+All text is entered as plain text, and will be converted to HTML entities as \
+necessary.  This means that {{<}}, {{>}}, {{&}}, and so on are converted for \
+you (except in special situations where the characters are Wiki markup; \
+Text_Wiki is generally smart enough to know when to convert and when not to).
+
+Just hit "return" twice to make a paragraph break.  If you want \
+to keep the same logical line but have to split it across \
+two physical lines (such as when your editor only shows a certain number \
+of characters per line), end the line with a backslash {{\}} and hit \
+return once.  This will cause the two lines to be joined on display, and the \
+backslash will not show.  (If you end a line with a backslash and a tab \
+or space, it will ''not'' be joined with the next line, and the backslash \
+will be printed.)
+
+
+----
+
+++ Inline Formatting
+
+|| {{```''italic text''```}}                      || ''italic text'' ||
+|| {{```'''bold text'''```}}                      || '''bold text''' ||
+|| {{```'''''italic and bold'''''```}}            || '''''italic and bold''''' ||
+|| {{```//emphasis//```}} || //emphasis// ||
+|| {{```**strong**```}} || **strong** ||
+|| {{```//**emphasis and strong**//```}} || //**emphasis and strong**// ||
+|| {{```**//strong and emphasis//**```}} || **//strong and emphasis//** ||
+|| {{```{{teletype text}}```}}                    || {{teletype text}} ||
+|| {{<```php:function()```>}}                     || <php:function()> ||
+|| {{```@@--- delete text +++ insert text @@```}} || @@--- delete text +++ insert text @@ ||
+|| {{```@@--- delete only @@```}}                 || @@--- delete only @@ ||
+|| {{```@@+++ insert only @@```}}                 || @@+++ insert only @@ ||
+|| {{```super ^^1^^ script```}}                   || super ^^1^^ script ||
+
+----
+
+++ Literal Text
+
+If you don't want Text_Wiki to parse some text, enclose it in 3 backticks (not 3 single-quotes).
+
+<code>
+
+This '''text''' gets {{parsed}}.
+
+```This '''text''' does not get {{parsed}}.```
+
+</code>
+
+This '''text''' gets {{parsed}}.
+
+```This '''text''' does not get {{parsed}}.```
+
+----
+
+++ Headings
+
+You can make various levels of heading by putting \
+equals-signs before and after the text (all on its \
+own line):
+
+<code>
++++ Level 3 Heading
+++++ Level 4 Heading
++++++ Level 5 Heading
+++++++ Level 6 Heading
+</code>
+
++++ Level 3 Heading
+++++ Level 4 Heading
++++++ Level 5 Heading
+++++++ Level 6 Heading
+
+----
+
+++ Table of Contents
+
+To create a list of every heading, with a link to that heading, put a table of contents tag on its own line.
+
+<code>
+%%TOC%%
+</code>
+----
+
+++ Horizontal Rules
+
+Use four dashes ({{```----```}}) to create a horizontal rule.
+
+----
+
+++ Lists
+
++++ Bullet Lists
+
+You can create bullet lists by starting a paragraph with one or \
+more asterisks.
+
+<code>
+* Bullet one
+ * Sub-bullet
+</code>
+
+* Bullet one
+ * Sub-bullet
+
++++ Numbered Lists
+
+Similarly, you can create numbered lists by starting a paragraph \
+with one or more hashes.
+
+<code>
+# Numero uno
+# Number two
+ # Sub-item
+</code>
+
+# Numero uno
+# Number two
+ # Sub-item
+
+
++++ Mixing Bullet and Number List Items
+
+You can mix and match bullet and number lists:
+
+<code>
+# Number one
+ * Bullet
+ * Bullet
+# Number two
+ * Bullet
+ * Bullet
+  * Sub-bullet
+   # Sub-sub-number
+   # Sub-sub-number
+# Number three
+ * Bullet
+ * Bullet
+</code>
+
+# Number one
+ * Bullet
+ * Bullet
+# Number two
+ * Bullet
+ * Bullet
+  * Sub-bullet
+   # Sub-sub-number
+   # Sub-sub-number
+# Number three
+ * Bullet
+ * Bullet
+
+
+
++++ Definition Lists
+
+You can create a definition (description) list with the following syntax:
+
+<code>
+:Item 1: Something
+:Item 2: Something else
+</code>
+
+:Item 1: Something
+:Item 2: Something else
+
+----
+
+++ Block Quotes
+
+You can mark a blockquote by starting a line with one or more '>' \
+characters, followed by a space and the text to be quoted.
+
+<code>
+This is normal text here.
+
+> Indent me! The quick brown fox jumps over the lazy dog. \ 
+Now this the time for all good men to come to the aid of \ 
+their country. Notice how we can continue the block-quote \ 
+in the same "paragraph" by using a backslash at the end of \ 
+the line.
+>
+> Another block, leading to...
+>> Second level of indenting.  This second is indented even \ 
+more than the previous one.
+
+Back to normal text.
+</code>
+
+This is normal text here.
+
+> Indent me! The quick brown fox jumps over the lazy dog. \
+Now this the time for all good men to come to the aid of \
+their country. Notice how we can continue the block-quote \
+in the same "paragraph" by using a backslash at the end of \
+the line.
+>
+> Another block, leading to...
+>> Second level of indenting.  This second is indented even \
+more than the previous one.
+
+Back to normal text.
+
+
+----
+
+++ Links and Images
+
++++ Wiki Links
+
+SmashWordsTogether to create a page link.
+
+You can force a WikiPage name '''not''' to be clickable by putting \
+an exclamation mark in front of it.
+
+<code>
+WikiPage !WikiPage
+</code>
+
+WikiPage !WikiPage
+
+(Note: existing wiki pages must be in the Text_Wiki {{pages}} option array, \
+and the {{view_url}} option must be set for the linking to work.)
+
++++ Free Links
+
+Freelinks are "non-standard" Wiki links.
+
+* You can refer to named anchors within pages like this: \
+{{```((WikiPage#NamedAnchor))```}} becomes ((WikiPage#NamedAnchor)).
+* You can create nice-looking links from WordsSmashedTogether like this: \
+{{```((WordsSmashedTogether|Nice Link))```}} becomes \
+((WordsSmashedTogether|Nice Link)).
+* Refer to named anchors within nice-looking links like this: \
+{{```((WikiPage|Nice Link#Anchor))```}} becomes \
+((WikiPage|Nice Link#Anchor)).
+* You can also create links that aren't WordsSmashedTogether \
+(i.e., that have spaces) like this: {{```((free links))```}} \
+becomes ((free links)).
+
+(Note: existing wiki pages must be in the Text_Wiki {{pages}} option array, \
+and the {{view_url}} option must be set for the linking to work.)
+
++++ Interwiki Links
+
+Interwiki links are links to pages on other Wiki sites. \
+Type the {{```SiteName:PageName```}} like this:
+
+* MeatBall:RecentChanges
+* Advogato:proj/WikkiTikkiTavi
+* Wiki:WorseIsBetter
+
+(Note: the interwiki site must be in the Text_Wiki {{interwiki}} option array.)
+
++++ URLs
+
+Create a remote link simply by typing its URL: http://ciaweb.net.
+
+If you like, enclose it in brackets to create a numbered reference \
+and avoid cluttering the page; {{```[http://ciaweb.net/free/]```}} becomes [http://ciaweb.net/free/].
+
+Or you can have a described-reference instead of a numbered reference:
+<code>
+[http://pear.php.net PEAR]
+</code>
+[http://pear.php.net PEAR]
+
++++ Images
+
+You can put a picture in a page by typing the URL to the picture \
+(it must end in gif, jpg, or png).
+<code>
+http://c2.com/sig/wiki.gif
+</code>
+
+http://c2.com/sig/wiki.gif
+
+You can use the described-reference URL markup to give the image an ALT tag:
+<code>
+[http://www.netropolisusa.biz/billthemarmet/MT/index/images/sunset_07_10_03.jpg Sunset]
+</code>
+
+[http://www.netropolisusa.biz/billthemarmet/MT/index/images/sunset_07_10_03.jpg Sunset]
+
+
+----
+++ Code Blocks
+
+Create code blocks by using {{<code>...</code>}} tags (each on its own line).
+
+<code>
+This is an example code block!
+</code>
+
+
+To create PHP blocks that get automatically colorized when you use PHP tags, \
+simply surround the code with {{<php>...</php>}} tags (the tags themselves \
+should each be on their own lines, and no need for the {{&lt;?php ... ?&gt;}} tags).
+
+<code>
+<php>
+// Set up the wiki options
+$options = array();
+$options['view_url'] = "index.php?page=";
+
+// load the text for the requested page
+$text = implode('', file($page . '.wiki.txt'));
+
+// create a Wiki objext with the loaded options
+$wiki = new Text_Wiki($options);
+
+// transform the wiki text.
+echo $wiki->transform($text);
+</php>
+</code>
+
+<php>
+// Set up the wiki options
+$options = array();
+$options['view_url'] = "index.php?page=";
+
+// load the text for the requested page
+$text = implode('', file($page . '.wiki.txt'));
+
+// create a Wiki objext with the loaded options
+$wiki = new Text_Wiki($options);
+
+// transform the wiki text.
+echo $wiki->transform($text);
+</php>
+
+----
+
+++ Tables
+
+You can create tables using pairs of vertical bars:
+
+<code>
+|| cell one || cell two ||
+|||| big ol' line ||
+|| cell four || cell five ||
+|| cell six || here's a very long cell ||
+</code>
+
+|| cell one || cell two ||
+|||| big ol' line ||
+|| cell four || cell five ||
+|| cell six || here's a very long cell ||
+
+<code>
+|| lines must start and end || with double vertical bars || nothing ||
+|| cells are separated by || double vertical bars || nothing ||
+|||| you can span multiple columns by || starting each cell ||
+|| with extra cell |||| separators ||
+|||||| but perhaps an example is the easiest way to see ||
+</code>
+
+|| lines must start and end || with double vertical bars || nothing ||
+|| cells are separated by || double vertical bars || nothing ||
+|||| you can span multiple columns by || starting each cell ||
+|| with extra cell |||| separators ||
+|||||| but perhaps an example is the easiest way to see ||
+
diff --git a/bundled-libs/docs/SmashWordsTogether.wiki.txt b/bundled-libs/docs/SmashWordsTogether.wiki.txt
new file mode 100644 (file)
index 0000000..f8b8483
--- /dev/null
@@ -0,0 +1 @@
+Smash words together to create a link.
diff --git a/bundled-libs/docs/TextWikiProposal.wiki.txt b/bundled-libs/docs/TextWikiProposal.wiki.txt
new file mode 100644 (file)
index 0000000..9f1009c
--- /dev/null
@@ -0,0 +1,151 @@
++ Text_Wiki Proposal
+
+This is an updated version of the proposal to PEAR group for {{Text_Wiki}} by [mailto:pmjones@ciaweb.net Paul M. Jones].
+
+%%TOC%%
+
+----
+
+++ Overview
+
+Most Wiki projects use their own internal, specialized parsing and rendering engines to transform source Wiki text to HTML.  The rule structures of different Wiki implementations are usually incompatible, leading developers to write their own engine to parse and render their own specialized Wiki markup.  This makes it difficult to extract and compare rule structure, as well as making it troublesome to add/modify/delete existing markup rules.  In addition, this makes it near-impossible to "drop in" Wiki text transformation processes to a nominally non-Wiki project.
+
+To solve the rule-modification and drop-in problems noted above, {{Text_Wiki}} abstracts the process of displaying Wiki-formatted text by using an object-oriented rule structure for parsing and rendering.
+
+A default set of parsing and rendering rule classes is provided with {{Text_Wiki}}; they serve to implement basic Wiki transformation into XHTML, and provide useful, well-commented examples of how to write a Wiki transformation rule.
+
+In addition, individual parsing and rendering rules can be added, modified, and removed with a user-defined rules directory.  Depending on the rendering method for a rule, source Wiki text may be transformed into XHTML, Latex, PDF, RTF, and so on.
+
+The properties of a {{Text_Wiki}} object determine...
+
+* which rules are applied to the source Wiki text (and in what order),
+* what the !WikiWeb URLs are for viewing and editing pages,
+* Interwiki mappings,
+* which pages exist in the !WikiWeb,
+* and much more.
+
+{{Text_Wiki}} does not implement a full !WikiWikiWeb; it only handles the transformation of Wiki source text to an output format.
+
+----
+
+++ History and Research
+
+Please note that {{Text_Wiki}} was pre-proposed earlier this year with some positive response[http://marc.theaimsgroup.com/?t=105838978200001&r=1&w=2] and that the call for votes is complete.[http://marc.theaimsgroup.com/?t=106994688000001&r=1&w=2]
+
+Primary research for {{Text_Wiki}} was based on two open-source Wiki projects, [http://tavi.sourceforge.net/ WikkiTikkiTavi] and [http://www.develnet.org/ coWiki].  Other Wiki engines and rule sets were also used in research, but these two provide sufficient examples for Wiki implementation.
+
+----
+
+++ What Is Wiki?
+
+A !WikiWikiWeb (a "Wiki") is a web-based collaboration tool in which any user can edit any page on the site.
+
+To quote C2: "Wiki is a composition system, it's a discussion medium, it's a repository, it's a mail system, it's a chat room, and it's a tool for collaboration."[http://c2.com/cgi/wiki]
+
+
++++ Wiki Markup Is Easy To Understand...
+
+Wikis allow rich text markup and automatic page linking.
+
+Because Wiki content is entered as plain text in a web environment, Wikis do not generally use HTML for rich text markup; instead, they use structured text to mark the elements of a page.
+
+For example, in HTML, one would mark a heading using {{<hN>...</hN>}} tags.
+
+<code>
+<html>
+<h3>This is a heading.</h3>
+<p>This is not.</p>
+</html>
+</code>
+
+To mark a heading in a Wiki, you put the heading on its own line and prefix it with a number of plus-signs.  Thus, the corresponding Wiki markup for the above example would look something like this:
+
+<code>
++++ This is a heading.
+This is not.
+</code>
+
+There are different structure rules for different markup elements.  For example, bold text might be enclosed in a paired sets of three single quotes, teletype text is set off my matched pairs of 2 curly braces, lists are noted by starting the like with a hash or a star, and so on.
+
+Wikis also automate the creation and linking of pages.  In a Wiki, page names are made of WordsSmashedTogether; the Wiki sees WordsSmashedTogether on a page and creates a link to the corresponding page in the Wiki.  If the page exists on the Wiki, the page name itself becomes a link; if the page does not exist, a suffix is added to the page name, usually a question mark, and that suffix is linked to the "create a new page" URL.
+
+This means that in order to translate Wiki-formatted structured text (from the source) to HTML (for display), it is necessary to do a find-and-replace on the text, looking for text lines that match the Wiki structured text rules, and convert them to HTML for display.  Most Wiki engines parse-and-render within a single class, or with a series of functions within a single include file.
+
+
++++ ...But It's Not Standardized...
+
+The problem with Wiki markup is that it is not standardized.  Different Wiki engines use different rule structures.  In general, Wiki implementors want the source text to be make sense when read by humans, and also be translatable to HTML.  What "makes sense" to one developer or community might not make sense to another.
+
+By way of example, let's take a look at headings.  In HTML, a heading is always marked the same way.  In different Wikis, headings are not always the same.  In !WikkiTikkiTavi, a heading-2 looks like this:
+
+<code>
+== My Heading ==
+</code>
+
+But in coWiki, it looks like this:
+
+<code>
+++ My Heading
+</code>
+
+And in another wiki, it might look like this:
+
+<code>
+---- My Heading
+</code>
+
+(Why four dashes instead of two?  Because the implementor decided that a heading-1 should use six dashes as the most-important, and work down to a heading-6 that uses one dash as the least-important.)
+
+It's even worse when we get to bold, italics, and so on.
+
+* Some Wikis use {{```''italic''```}}, others use {{```//italic//```}}, and others use {{```_italic_```}}.
+* Some Wikis implement partial HTML support so you can embed tables, others use a double-pipe markup style to mark cells.
+* Some Wikis implement XML-ish tags to mark elements.
+* Some Wikis implement plugins or macros to embed custom behaviors into Wiki pages.
+
+
+
++++ ...And It's Hard To Share.
+
+But what some Wikis do, others do not.  This means that if you want Wiki implementation "A" to support a rule or behavior from Wiki implementation "B", it becomes difficult or impossible, because the different implementations use different parsing and rendering routines that apply their rule structures in different ways.
+
+Not only that, but the parsing and rendering routines generally depend on the whole remainder of the Wiki implementation.  This means the Wiki transformation engine exists within a full !WikiWikiWeb system that handles page creation, versioning, storage, and linking, sometimes along with {{diff()}} functions to see the differences between page edits.
+
+----
+
+++ Text_Wiki Makes It Easy To Share
+
+{{Text_Wiki}} solves the problem of sharing rules and behaviors by using a unified parsing and rendering mechanism with an object-oriented system of rules for transforming Wiki markup elements.
+
+Each Wiki element gets its own rule class.  The rule class handles its own parsing and rendering within the context of the primary {{Text_Wiki}} object, but has full access to the primary {{Text_Wiki}} object properties (the source text, the elements that have already been parsed, and so on).
+
+This means that you can add, change, and remove rules for any specific Wiki markup set you happen to like.  It also means that if you see a Wiki behavior that you like, you can easily write a new rule that mimics the behavior and plug it into the {{Text_Wiki}} engine without rewriting the parser or renderer.
+
+Thus, instead of implementing a full !WikiWikiWeb system, {{Text_Wiki}} only deals with the transformation of Wiki source text to an output format.  (Incidentally, it needs to know whether a page exists within a !WikiWeb, but that is abstracted and does not depend on any specific storage or retrieval system.)
+
+
++++ How Does This Work?
+
+In general, {{Text_Wiki}} uses a replace-with-token methodology to mark source text matching a Wiki rule.  Any source text matching a rule (usually found through a regular expression) is replaced with a pair of delimiters surrounding a token number, and a matching token number is entered into the {{Text_Wiki}} {{$_tokens}} array property.  Any optional information about the matching text, and sometimes the matching text itself, is stored in the token entry.  After parsing, the tokens are rendered into a target format depending on the rule's render() method.
+
+As a side-benefit, this means that once the source text has been parsed and tokenized, the combination of the source text and replacement tokens allows you to target any output format, not just XHTML.  If a rule supports it, that rule can render a token into Latex, PDF, RTF, and so on.
+
+
++++ Examples
+
+The best example of {{Text_Wiki}} is the {{Text_Wiki}} sample page, included in the package documentation.  After you use PEAR to install {{Text_Wiki}}, look in the docs/ directory.  The index.php file show how to instantiate a {{Text_Wiki}} object with a set of custom options, and Sample.wiki.txt shows how to write up Wiki source text.  Finally, open index.php in your browser to see the Wiki source text transformed into HTML.
+
+----
+
+++ Download the Package
+
+http://pear.php.net/package/Text_Wiki
+
++++ Known Issues
+
+Need to create full documentation, including how to write a rule.
+
+{{Text_Wiki}} should return {{PEAR_Error}} objects and error codes, not echo errors to output.
+
+Should add {{renderLatex()}} method for all default rules (from !WikkiTikkiTavi?)
+
diff --git a/bundled-libs/docs/TokenRuleKeys.wiki.txt b/bundled-libs/docs/TokenRuleKeys.wiki.txt
new file mode 100644 (file)
index 0000000..c002f3a
--- /dev/null
@@ -0,0 +1,57 @@
++ Token Rule Keys
+
+|| '''Rule Name'''       || '''Description'''                                 || '''Options''' ||
+|| {{blockquote}}        || Block-quoted text.                                || {{type:[start|end] }} ||
+|| {{bold}}              || Bold text.                                        || {{type:[start|end]}} ||
+|| {{code}}              || A block of generic computer code.                 || {{text}} ||
+|| {{deflist}}           || Definition list element.                          || {{type:[list|term|narr]_[start|end]}} ||
+|| {{delimiter}}         || An existing delimiter.                            || - ||
+|| {{emphasis}}          || Emphasized (usually italic) text.                 || {{type:[start|end]}} ||
+|| {{freelink}}          || A local !WikiPage reference in free link format.  || {{page}}, {{text}}, {{anchor}} ||
+|| {{heading}}           || A heading.                                        || {{type:[start|end], level, text}} ||
+|| {{horiz}}             || A horizontal rule.                                || - ||
+|| {{html}}              || A block of HTML text to be displayed as-is.       || {{text}}  ||
+|| {{interwiki}}         || An !InterWiki reference.                          || {{site}}, {{page}} ||
+|| {{italic}}            || Italic text.                                      || {{type:[start|end]}} ||
+|| {{list}}              || Bullet or number list elements.                   || {{type:[bullet|number|item]_[start|end], level, count}} ||
+|| {{newline}}           || A new line or line break.                         || - ||
+|| {{phpcode}}           || A block of PHP code to be colorized.              || {{text}} ||
+|| {{phplookup}}         || A function name to link to at php.net             || {{text}} ||
+|| {{raw}}               || Raw or plain text to be displayed as-is.          || {{text}} ||
+|| {{strong}}            || Strong (usually bold) text.                       || {{type:[start|end]}} ||
+|| {{superscript}}       || Superscript text.                                 || {{type:[start|end]}} ||
+|| {{table}}             || Table elements.                                   || {{type:[table|row|cell]_[start|end], colspan}} ||
+|| {{tt}}                || Teletype (monospaced) text.                 || {{type:[start|end]}} ||
+|| {{url}}               || A page URL.                                       || {{type:[inline|footnote|descr]}}, {{href}}, {{text}} ||
+|| {{wikilink}}          || A local !WikiPage reference.                      || {{page}}, {{anchor}} ||
+|| {{toc}}               || Table of contents.                                || {{type:[list_start|list_end|item_start|item_end|target], level, count}} ||
+
+++ Tokens Entry Format
+
+Simple format (no options).
+
+<code>
+$_tokens[] = Array
+    (
+        [0] => 'rule_name'
+        [1] => array
+            (
+            )
+    )
+</code>
+
+Complex format (with options).
+
+<code>
+$_tokens[] = Array
+    (
+        [0] => 'rule_name'
+        [1] => Array
+            (
+                ['opt0'] => 'value 0'
+                ['opt1'] => 'value 1'
+                ...
+                ['optN'] => 'value N'
+            )
+    )
+</code>
diff --git a/bundled-libs/docs/WikiPage.wiki.txt b/bundled-libs/docs/WikiPage.wiki.txt
new file mode 100644 (file)
index 0000000..ec7cc3d
--- /dev/null
@@ -0,0 +1 @@
+A generic blank Wiki page.
diff --git a/bundled-libs/docs/WordsSmashedTogether.wiki.txt b/bundled-libs/docs/WordsSmashedTogether.wiki.txt
new file mode 100644 (file)
index 0000000..f8b8483
--- /dev/null
@@ -0,0 +1 @@
+Smash words together to create a link.
diff --git a/bundled-libs/docs/free links.wiki.txt b/bundled-libs/docs/free links.wiki.txt
new file mode 100644 (file)
index 0000000..410f31d
--- /dev/null
@@ -0,0 +1 @@
+A "free link" Wiki page.
\ No newline at end of file
diff --git a/bundled-libs/docs/index.php b/bundled-libs/docs/index.php
new file mode 100644 (file)
index 0000000..a4c6c12
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+
+error_reporting(E_ALL);
+require_once 'Text/Wiki.php';
+
+
+/**
+* 
+* Gets microtime; for timing how long it takes to process code.
+* 
+*/
+
+function getmicrotime()
+{ 
+    list($usec, $sec) = explode(" ",microtime()); 
+    return ((float)$usec + (float)$sec); 
+}
+
+// Set up the wiki options
+$options = array();
+$options['view_url'] = "index.php?page=";
+
+
+// Get the list of existing wiki pages, based on the .wiki.txt
+// files in the current directory.
+$options['pages'] = array();
+
+$dir = opendir(dirname(__FILE__));
+
+while ($file = readdir($dir)) {
+    if (substr($file, -9) == '.wiki.txt') {
+        $options['pages'][] = substr($file, 0, -9);
+    }
+}
+
+closedir($dir);
+
+// what page is being requested?
+if (isset($_GET['page'])) {
+    $page = $_GET['page'];
+} else {
+    $page = 'HomePage';
+}
+
+// load the text for the requested page
+$text = implode('', file($page . '.wiki.txt'));
+
+// create a Wiki objext with the loaded options
+$wiki =& new Text_Wiki($options);
+
+// time the operation, and transform the wiki text.
+$before = getMicroTime();
+$output = $wiki->transform($text);
+$after = getMicroTime();
+$time = (float)$after - (float)$before;
+
+
+// output the page!
+?>
+<?xml version="1.0" encoding="iso-8859-1" ?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+        
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+
+    <head>
+        <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
+        <title>Text_Wiki::<?php echo $page ?></title>
+        <link rel="stylesheet" href="stylesheet.css" type="text/css" />
+    </head>
+    
+    <body>
+        <?php echo $output ?>
+        <?php echo "<hr /><p>Transformed in $time seconds.</p>" ?>
+    </body>
+</html>
diff --git a/bundled-libs/docs/stylesheet.css b/bundled-libs/docs/stylesheet.css
new file mode 100644 (file)
index 0000000..44d598b
--- /dev/null
@@ -0,0 +1,69 @@
+body, p, br, th, td {
+ font-family: "Verdana", "Arial", "Geneva";
+ font-size: 12px;
+}
+
+th {
+ font-weight: bold;
+ background: black;
+ color: white;
+}
+
+h1 {
+ font-size: 30px;
+ font-family: "Arial Narrow", "N Helvectica Narrow", "Tahoma";
+ font-weight: bold;
+}
+
+h2 {
+ font-size: 24px;
+ font-family: "Arial Narrow", "N Helvectica Narrow", "Tahoma";
+ font-weight: bold;
+}
+
+h3 {
+ font-size: 18px;
+ font-family: "Arial Narrow", "N Helvectica Narrow", "Tahoma";
+ font-weight: bold;
+}
+
+h4 {
+ font-size: 16px;
+ font-family: "Arial Narrow", "N Helvectica Narrow", "Tahoma";
+ font-weight: bold;
+}
+
+h5 {
+ font-size: 14px;
+ font-family: "Arial Narrow", "N Helvectica Narrow", "Tahoma";
+ font-weight: bold;
+}
+
+h6 {
+ font-size: 12px;
+ font-family: "Arial Narrow", "N Helvectica Narrow", "Tahoma";
+ font-weight: bold;
+}
+
+a:link {
+ color: blue;
+ text-decoration: none;
+}
+
+a:visited {
+ color: blue;
+ text-decoration: none;
+}
+
+a:hover {
+ color: red;
+ text-decoration: underline;
+}
+
+pre {
+ border: 1px dashed #003366;
+ background: #eeeeee;
+ padding: 6px;
+ font-family: Profont, Monaco, Courier, "Andale Mono", monospace;
+}
+
diff --git a/bundled-libs/tests/README b/bundled-libs/tests/README
new file mode 100644 (file)
index 0000000..8a5af84
--- /dev/null
@@ -0,0 +1,4 @@
+Placeholder for Text_Wiki unit tests.
+
+For now, attempt to transform the the docs/SamplePage.wiki.txt file.
+
diff --git a/comment.php b/comment.php
new file mode 100644 (file)
index 0000000..6c3d79b
--- /dev/null
@@ -0,0 +1,164 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+include_once('serendipity_config.inc.php');
+header('Content-Type: text/html; charset=' . LANG_CHARSET);
+
+if (isset($serendipity['GET']['delete'], $serendipity['GET']['entry'], $serendipity['GET']['type'])) {
+    serendipity_deleteComment($serendipity['GET']['delete'], $serendipity['GET']['entry'], $serendipity['GET']['type']);
+    if (serendipity_isResponseClean($_SERVER['HTTP_REFERER'])) {
+        header('Location: '. $_SERVER['HTTP_REFERER']);
+    }
+}
+
+if (isset($serendipity['GET']['switch'], $serendipity['GET']['entry'])) {
+    serendipity_allowCommentsToggle($serendipity['GET']['entry'], $serendipity['GET']['switch']);
+}
+
+serendipity_rememberComment();
+
+if (!($type = @$_REQUEST['type'])) {
+    $type = 'normal';
+}
+
+$tb_logging = false; // for developers: can be switched to true!
+
+if ($type == 'trackback') {
+    if ($tb_logging) {
+        # PHP 4.2.2 way of doing things
+        ob_start();
+        print_r($_REQUEST);
+        $tmp = ob_get_contents();
+        ob_end_clean();
+
+        $fp = fopen('trackback2.log', 'a');
+        fwrite($fp, '[' . date('d.m.Y H:i') . '] RECEIVED TRACKBACK' . "\n");
+        fwrite($fp, '[' . date('d.m.Y H:i') . '] ' . $tmp . "\n");
+    }
+
+    $uri = $_SERVER['REQUEST_URI'];
+    if (isset($_REQUEST['entry_id'])) {
+        $id = (int)$_REQUEST['entry_id'];
+    } else if ($_REQUEST['amp;entry_id']) {
+        // For possible buggy variable transmission caused by an intermediate CVS-release of s9y
+        $id = (int)$_REQUEST['amp;entry_id'];
+    } else if (preg_match('@/(\d+)_[^/]*$@', $uri, $matches)) {
+        $id = (int)$matches[1];
+    }
+
+    if ($tb_logging) {
+        fwrite($fp, '[' . date('d.m.Y H:i') . '] Match on ' . $uri . "\n");
+        fwrite($fp, '[' . date('d.m.Y H:i') . '] ID: ' . $id . "\n");
+        fclose($fp);
+    }
+
+    if (add_trackback($id, $_REQUEST['title'], $_REQUEST['url'], $_REQUEST['blog_name'], $_REQUEST['excerpt'])) {
+        if ($tb_logging) {
+            $fp = fopen('trackback2.log', 'a');
+            fwrite($fp, '[' . date('d.m.Y H:i') . '] TRACKBACK SUCCESS' . "\n");
+        }
+        report_trackback_success();
+    } else {
+        if ($tb_logging) {
+            $fp = fopen('trackback2.log', 'a');
+            fwrite($fp, '[' . date('d.m.Y H:i') . '] TRACKBACK FAILURE' . "\n");
+        }
+        report_trackback_failure();
+    }
+
+    if ($tb_logging) {
+        fclose($fp);
+    }
+} else if ($type == 'pingback') {
+    if (add_pingback($_REQUEST['entry_id'], $HTTP_RAW_POST_DATA)) {
+        report_pingback_success();
+    } else {
+        report_pingback_failure();
+    }
+} else {
+    $id = (int)(!empty($serendipity['POST']['entry_id']) ? $serendipity['POST']['entry_id'] : $serendipity['GET']['entry_id']);
+    $serendipity['head_subtitle'] = COMMENTS;
+    $serendipity['smarty_file'] = 'commentpopup.tpl';
+    serendipity_smarty_init();
+
+    if ($id == 0) {
+        return false;
+    } else {
+        $serendipity['smarty']->assign('entry_id', $id);
+    }
+
+    if (isset($_GET['success']) && $_GET['success'] == 'true') {
+        $serendipity['smarty']->assign(
+            array(
+                'is_comment_added'   => true,
+                'comment_url'        => htmlspecialchars($_GET['url']) . '&amp;serendipity[entry_id]=' . $id,
+                'comment_string'     => explode('%s', COMMENT_ADDED_CLICK)
+            )
+        );
+    } else if (!isset($serendipity['POST']['submit'])) {
+        if ($serendipity['GET']['type'] == 'trackbacks') {
+            $query = "SELECT title FROM {$serendipity['dbPrefix']}entries WHERE id = '". $id ."'";
+            $entry = serendipity_db_query($query);
+            $entry = serendipity_archiveURL($id, $entry[0]['title'], 'baseURL');
+
+            $serendipity['smarty']->assign(
+                array(
+                    'is_showtrackbacks' => true,
+                    'comment_url'       => $serendipity['baseURL'] . 'comment.php?type=trackback&amp;entry_id=' . $id,
+                    'comment_entryurl'  => $entry
+                )
+            );
+        } else {
+            $query = "SELECT id, last_modified, timestamp, allow_comments, moderate_comments FROM {$serendipity['dbPrefix']}entries WHERE id = '" . $id . "'";
+            $ca    = serendipity_db_query($query, true);
+            $comment_allowed = serendipity_db_bool($ca['allow_comments']) || !is_array($ca) ? true : false;
+            $serendipity['smarty']->assign(
+                array(
+                    'is_showcomments'    => true,
+                    'is_comment_allowed' => $comment_allowed
+                )
+            );
+
+            if ($comment_allowed) {
+                serendipity_displayCommentForm($id, '?', NULL, $serendipity['POST'], true, serendipity_db_bool($ca['moderate_comments']), $ca);
+            }
+        }
+    } else {
+        $comment['url']       = $serendipity['POST']['url'];
+        $comment['comment']   = trim($serendipity['POST']['comment']);
+        $comment['name']      = $serendipity['POST']['name'];
+        $comment['email']     = $serendipity['POST']['email'];
+        $comment['subscribe'] = $serendipity['POST']['subscribe'];
+        $comment['parent_id'] = $serendipity['POST']['replyTo'];
+        if (!empty($comment['comment'])) {
+            if (serendipity_saveComment($id, $comment, 'NORMAL')) {
+                $sc_url = $serendipity['baseURL'] . 'comment.php?serendipity[entry_id]=' . $id . '&success=true&url=' . urlencode($_SERVER['HTTP_REFERER']);
+                if (serendipity_isResponseClean($sc_url)) {
+                    header('Location: ' . $sc_url);
+                }
+                exit;
+            } else {
+                $serendipity['smarty']->assign(
+                    array(
+                        'is_comment_notadded' => true,
+                        'comment_url'         => htmlspecialchars($_SERVER['HTTP_REFERER']),
+                        'comment_string'      => explode('%s', COMMENT_NOT_ADDED_CLICK)
+                    )
+                );
+            }
+        } else {
+            $serendipity['smarty']->assign(
+                array(
+                    'is_comment_empty' => true,
+                    'comment_url'      => htmlspecialchars($_SERVER['HTTP_REFERER']),
+                    'comment_string'   => explode('%s', EMPTY_COMMENT)
+                )
+            );
+        }
+    }
+
+    $serendipity['smarty']->display(serendipity_getTemplateFile($serendipity['smarty_file'], 'serendipityPath'));
+}
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/deployment/comment.php b/deployment/comment.php
new file mode 100644 (file)
index 0000000..66a792c
--- /dev/null
@@ -0,0 +1,8 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Serendipity is provided in managed mode here
+
+require_once 's9y/comment.php';
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/deployment/exit.php b/deployment/exit.php
new file mode 100644 (file)
index 0000000..9746d10
--- /dev/null
@@ -0,0 +1,8 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Serendipity is provided in managed mode here
+
+require_once 's9y/exit.php';
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/deployment/index.php b/deployment/index.php
new file mode 100644 (file)
index 0000000..c3d46a6
--- /dev/null
@@ -0,0 +1,8 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Serendipity is provided in managed mode here
+
+require_once 's9y/index.php';
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/deployment/rss.php b/deployment/rss.php
new file mode 100644 (file)
index 0000000..e97447e
--- /dev/null
@@ -0,0 +1,8 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Serendipity is provided in managed mode here
+
+require_once 's9y/rss.php';
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/deployment/serendipity.css.php b/deployment/serendipity.css.php
new file mode 100644 (file)
index 0000000..806a762
--- /dev/null
@@ -0,0 +1,8 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Serendipity is provided in managed mode here
+
+require_once 's9y/serendipity.css.php';
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/deployment/serendipity_admin.php b/deployment/serendipity_admin.php
new file mode 100644 (file)
index 0000000..749b5bf
--- /dev/null
@@ -0,0 +1,8 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Serendipity is provided in managed mode here
+
+require_once 's9y/serendipity_admin.php';
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/deployment/serendipity_admin_image_selector.php b/deployment/serendipity_admin_image_selector.php
new file mode 100644 (file)
index 0000000..677c1db
--- /dev/null
@@ -0,0 +1,8 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Serendipity is provided in managed mode here
+
+require_once 's9y/serendipity_admin_image_selector.php';
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/deployment/serendipity_config.inc.php b/deployment/serendipity_config.inc.php
new file mode 100644 (file)
index 0000000..6cb468f
--- /dev/null
@@ -0,0 +1,9 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Serendipity is provided in managed mode here
+
+#@define('S9Y_INCLUDE_PATH', 's9y/');
+require_once 's9y/serendipity_config.inc.php';
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/deployment/serendipity_define.js.php b/deployment/serendipity_define.js.php
new file mode 100644 (file)
index 0000000..b3d6606
--- /dev/null
@@ -0,0 +1,8 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Serendipity is provided in managed mode here
+
+require_once 's9y/serendipity_define.js.php';
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/deployment/serendipity_editor.js b/deployment/serendipity_editor.js
new file mode 100644 (file)
index 0000000..5d246fe
--- /dev/null
@@ -0,0 +1,227 @@
+<!-- // Hide from older browsers
+/* $Id$
+/*
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+*/
+
+/*
+    Written by chris wetherell
+    http://www.massless.org
+    chris [THE AT SIGN] massless.org
+
+    warning: it only works for IE4+/Win and Moz1.1+
+    feel free to take it for your site
+    if there are any problems, let chris know.
+*/
+
+var thisForm;
+
+function getMozSelection(txtarea) {
+    var selLength = txtarea.textLength;
+    var selStart = txtarea.selectionStart;
+    var selEnd = txtarea.selectionEnd;
+
+    if (selEnd==1 || selEnd==2) {
+        selEnd=selLength;
+    }
+    return (txtarea.value).substring(selStart, selEnd);
+}
+
+function getIESelection(txtarea) {
+    return document.selection.createRange().text;
+}
+
+function mozWrap(txtarea, lft, rgt) {
+    var selLength = txtarea.textLength;
+    var selStart = txtarea.selectionStart;
+    var selEnd = txtarea.selectionEnd;
+
+    if (selEnd==1 || selEnd==2) selEnd=selLength;
+    var s1 = (txtarea.value).substring(0,selStart);
+    var s2 = (txtarea.value).substring(selStart, selEnd)
+    var s3 = (txtarea.value).substring(selEnd, selLength);
+    txtarea.value = s1 + lft + s2 + rgt + s3;
+}
+
+function IEWrap(txtarea, lft, rgt) {
+    strSelection = document.selection.createRange().text;
+    if (strSelection != "") {
+        document.selection.createRange().text = lft + strSelection + rgt;
+    } else {
+        txtarea.value = txtarea.value + lft + rgt;
+    }
+}
+
+function wrapSelection(txtarea, lft, rgt) {
+    if (document.all) {
+        IEWrap(txtarea, lft, rgt);
+    } else if (document.getElementById) {
+        mozWrap(txtarea, lft, rgt);
+    }
+}
+
+function wrapSelectionWithLink(txtarea) {
+    var my_link = prompt("Enter URL:","http://");
+
+    if (document.all && getIESelection(txtarea) == "" ||
+         document.getElementById && getMozSelection(txtarea) == "") {
+        var my_desc = prompt("Enter Description", '');
+    }
+
+    if (my_link != null) {
+        lft = "<a href=\"" + my_link + "\">";
+        if (my_desc != null && my_desc != "") {
+            rgt = my_desc + "</a>";
+        } else {
+            rgt = "</a>";
+        }
+        wrapSelection(txtarea, lft, rgt);
+    }
+
+    return;
+}
+/* end chris w. script */
+
+function mozInsert(txtarea, str) {
+    var selLength = txtarea.textLength;
+    var selStart = txtarea.selectionStart;
+    var selEnd = txtarea.selectionEnd;
+    if (selEnd==1 || selEnd==2) {
+        selEnd=selLength;
+    }
+    var s1 = (txtarea.value).substring(0,selStart);
+    var s2 = (txtarea.value).substring(selStart, selEnd)
+    var s3 = (txtarea.value).substring(selEnd, selLength);
+    txtarea.value = s1 + str + s2 + s3;
+}
+
+function wrapInsImage(area) {
+    var loc = prompt('Enter the Image Location: ');
+    if (!loc) {
+        return;
+    }
+    mozInsert(area,'<img src="'+ loc + '" alt="" />');
+}
+
+/* end Better-Editor functions */
+
+function serendipity_insImage (area) {
+    var loc = prompt('Enter the Image Location: ');
+    if (!loc) {
+        area.focus();
+        return;
+    }
+
+    area.value = area.value + '<img src="' + loc + '" alt="" />';
+    area.focus();
+}
+
+function serendipity_insBasic (area, tag) {
+    area.value = area.value + "<" + tag + "></" + tag + ">";
+    area.focus();
+}
+
+function serendipity_insLink (area) {
+    var loc  = prompt('Enter URL Location: ');
+    var text = prompt('Enter Description: ');
+
+    if (!loc) {
+        area.focus();
+        return;
+    }
+
+    area.value = area.value + '<a href="' + loc + '">' + (text ? text : loc) + '</a>';
+    area.focus();
+}
+
+function serendipity_imageSelector_addToElement (str, el)
+{
+    document.getElementById(el).value = str;
+    document.getElementById(el).focus();
+}
+
+function serendipity_imageSelector_addToBody (str, textarea)
+{
+    document.forms['serendipityEntry']['serendipity['+ textarea +']'].value += str;
+    document.forms['serendipityEntry']['serendipity['+ textarea +']'].focus();
+}
+
+function serendipity_imageSelector_done(textarea)
+{
+    var insert = '';
+    var img = '';
+    var src = '';
+    var f = document.forms['serendipity[selForm]'].elements;
+
+    if (f['serendipity[linkThumbnail]'][0].checked == true) {
+        img       = f['thumbName'].value;
+        imgWidth  = f['imgThumbWidth'].value;
+        imgHeight = f['imgThumbHeight'].value;
+    } else {
+        img       = f['imgName'].value;
+        imgWidth  = f['imgWidth'].value;
+        imgHeight = f['imgHeight'].value;
+    }
+
+    if (f['serendipity[filename_only]'] && f['serendipity[filename_only]'].value == 'true') {
+        self.opener.serendipity_imageSelector_addToElement(img, f['serendipity[htmltarget]'].value);
+        self.close();
+        return true;
+    }
+
+    if (document.getElementById('serendipity_imagecomment').value != '') {
+        styled = false;
+    } else {
+        styled = true;
+    }
+
+    floating = 'center';
+    if (XHTML11) {
+        if (f['serendipity[align]'][0].checked == true) {
+            img = "<img width='" + imgWidth + "' height='" + imgHeight + "' " + (styled ? 'style="border: 0px; padding-left: 5px; padding-right: 5px;"' : '') + ' src="' + img + "\" alt=\"\" />";
+        } else if (f['serendipity[align]'][1].checked == true) {
+            img = "<img width='" + imgWidth + "' height='" + imgHeight + "' " + (styled ? 'style="float: left; border: 0px; padding-left: 5px; padding-right: 5px;"' : '') + ' src="' + img + "\" alt=\"\" />";
+            floating = 'left';
+        } else if (f['serendipity[align]'][2].checked == true) {
+            img = "<img width='" + imgWidth + "' height='" + imgHeight + "' " + (styled ? 'style="float: right; border: 0px; padding-left: 5px; padding-right: 5px;"' : '') + ' src="' + img + "\" alt=\"\" />";
+            floating = 'right';
+        }
+    } else {
+        if (f['serendipity[align]'][0].checked == true) {
+            img = "<img width='" + imgWidth + "' height='" + imgHeight + "' border='0' hspace='5' src='" + img + "' alt='' />";
+        } else if (f['serendipity[align]'][1].checked == true) {
+            img = "<img width='" + imgWidth + "' height='" + imgHeight + "' border='0' hspace='5' align='left' src='" + img + "' alt='' />";
+            floating = 'left';
+        } else if (f['serendipity[align]'][2].checked == true) {
+            img = "<img width='" + imgWidth + "' height='" + imgHeight + "' border='0' hspace='5' align='right' src='" + img + "' alt='' />";
+            floating = 'right';
+        }
+    }
+
+    if (f['serendipity[isLink]'][1].checked == true) {
+        insert = "<a href='" + f['serendipity[url]'].value + "'>" + img + "</a>";
+    } else {
+        insert = img;
+    }
+
+    if (document.getElementById('serendipity_imagecomment').value != '') {
+        comment = f['serendipity[imagecomment]'].value;
+        block = '<div class="serendipity_imageComment_' + floating + '" style="width: ' + imgWidth + 'px">'
+              +     '<div class="serendipity_imageComment_img">' + insert + '</div>'
+              +     '<div class="serendipity_imageComment_txt">' + comment + '</div>'
+              + '</div>';
+    } else {
+        block = insert;
+    }
+
+    if (self.opener.editorref) {
+        self.opener.editorref.surroundHTML(block, '');
+    } else {
+        self.opener.serendipity_imageSelector_addToBody(block, textarea);
+    }
+
+    self.close();
+}
+
+// -->
diff --git a/deployment/serendipity_xmlrpc.php b/deployment/serendipity_xmlrpc.php
new file mode 100644 (file)
index 0000000..483d502
--- /dev/null
@@ -0,0 +1,8 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Serendipity is provided in managed mode here
+
+require_once 's9y/serendipity_xmlrpc.php';
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/deployment/wfwcomment.php b/deployment/wfwcomment.php
new file mode 100644 (file)
index 0000000..9293ef3
--- /dev/null
@@ -0,0 +1,8 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Serendipity is provided in managed mode here
+
+require_once 's9y/wfwcomment.php';
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/docs/CHANGED_FILES b/docs/CHANGED_FILES
new file mode 100644 (file)
index 0000000..6f6e14d
--- /dev/null
@@ -0,0 +1,248 @@
+This documents the change of filestructure between version 0.7 and 0.8:
+
+Where functions from serendipity_config.inc.php went to:
+------------------------------------------------------------------------
+./include/functions_comments.inc.php
+    * serendipity_rememberComment() {
+    * serendipity_rememberCommentDetails()
+    * serendipity_forgetCommentDetails()
+    * serendipity_displayCommentForm()
+    * serendipity_fetchComments()
+    * serendipity_generateCommentList()
+    * serendipity_printComments()
+    * serendipity_deleteComment()
+    * serendipity_allowCommentsToggle()
+    * serendipity_approveComment()
+    * serendipity_saveComment()
+    * serendipity_mailSubscribers()
+    * serendipity_cancelSubscription()
+    * serendipity_sendComment()
+
+./include/functions_trackbacks.inc.php
+    * serendipity_fetchTrackbacks()
+    * serendipity_printTrackbacks()
+    * serendipity_trackback_is_success()
+    * serendipity_pingback_autodiscover()
+    * _serendipity_send()
+    * serendipity_trackback_autodiscover()
+    * serendipity_reference_autodiscover()
+    * add_trackback()
+    * add_pingback()
+    * serendipity_trackback_excerpt()
+    * report_trackback_success()
+    * report_trackback_failure()
+    * report_pingback_success()
+    * report_pingback_failure()
+    * serendipity_handle_references()
+
+./include/functions_smarty.inc.php
+    * serendipity_smarty_fetch()
+    * serendipity_emptyPrefix()
+    * serendipity_smarty_hookPlugin()
+    * serendipity_smarty_printSidebar()
+    * serendipity_smarty_getFile()
+    * serendipity_smarty_formatTime()
+    * serendipity_smarty_printComments()
+    * serendipity_smarty_printTrackbacks()
+
+./include/functions_entries.inc.php
+    * serendipity_fetchCategoryRange()
+    * serendipity_fetchCategoryInfo()
+    * serendipity_fetchEntryCategories()
+    * serendipity_fetchEntries()
+    * serendipity_fetchEntry()
+    * serendipity_fetchEntryProperties()
+    * serendipity_fetchCategories()
+    * serendipity_rebuildCategoryTree()
+    * serendipity_searchEntries()
+    * serendipity_printEntryFooter()
+    * serendipity_getTotalEntries()
+    * serendipity_printEntries()
+    * serendipity_printEntries_rss()
+    * serendipity_purgeEntry()
+    * serendipity_updertEntry()
+    * serendipity_deleteEntry()
+    * serendipity_generateCategoryList()
+    * serendipity_printEntryForm()
+    * serendipity_emit_htmlarea_code()
+    * serendipity_updateEntryCategories()
+    * serendipity_printArchives()
+
+./include/functions.inc.php (remaining)
+    * serendipity_truncateString()
+    * serendipity_formatTime()
+    * serendipity_logout()
+    * serendipity_login()
+    * serendipity_userLoggedIn()
+    * serendipity_fetchTemplates()
+    * serendipity_fetchTemplateInfo()
+    * serendipity_setCookie()
+    * serendipity_deleteCookie()
+    * serendipity_fetchUsers()
+    * serendipity_makeFilename()
+    * serendipity_fetchReferences()
+    * serendipity_utf8_encode()
+    * serendipity_rss_getguid()
+    * xhtml_cleanup()
+    * serendipity_rewriteURL()
+    * serendipity_archiveURL()
+    * serendipity_archiveDateUrl()
+    * serendipity_maxfileuploadsize()
+    * serendipity_fetchAuthor()
+    * serendipity_parseFileName()
+    * serendipity_authenticate_author()
+    * serendipity_track_referrer()
+    * serendipity_track_referrer_gc()
+    * serendipity_track_url()
+    * serendipity_displayTopReferrers()
+    * serendipity_displayTopExits()
+    * serendipity_displayTopUrlList()
+    * serendipity_discover_rss()
+    * serendipity_isResponseClean()
+    * serendipity_printLogin()
+
+Moved functions:
+------------------------------------------------------------------------
+serendipity_saveTemplateSelection()
+    -> OBSOLETE
+
+serendipity_importWP()
+    -> ./include/admin/rss_exchange.inc.php
+
+serendipity_importMT()
+    -> ./include/admin/rss_exchange.inc.php
+
+serendipity_load_configuration()
+    -> ./include/functions_config.inc.php
+
+Removed files:
+------------------------------------------------------------------------
+./serendipity.inc.php
+./serendipity_layout.inc.php
+./serendipity_layout_table.inc.php
+
+Moved/Renamed files:
+------------------------------------------------------------------------
+./serendipity_entries_overview.inc.php
+    -> ./include/admin/entries_overview.inc.php
+
+./serendipity_rss_exchange.inc.php
+    -> ./include/admin/rss_exchange.inc.php
+
+./serendipity_admin_category.inc.php
+    -> ./include/admin/category.inc.php
+
+./serendipity_admin_comments.inc.php
+    -> ./include/admin/comments.inc.php
+
+./serendipity_admin_entries.inc.php
+    -> ./include/admin/entries.inc.php
+
+./serendipity_admin_images.inc.php
+    -> ./include/admin/images.inc.php
+
+./serendipity_admin_installer.inc.php
+    -> ./include/admin/installer.inc.php
+
+./serendipity_admin_interop.inc.php
+    -> ./include/admin/interop.inc.php
+
+./serendipity_admin_overview.inc.php
+    -> ./include/admin/overview.inc.php
+
+./serendipity_admin_plugins.inc.php
+    -> ./include/admin/plugins.inc.php
+
+./serendipity_admin_templates.inc.php
+    -> ./include/admin/templates.inc.php
+
+./serendipity_admin_upgrader.inc.php
+    -> ./include/admin/upgrader.inc.php
+
+./serendipity_admin_users.inc.php
+    -> ./include/admin/users.inc.php
+
+
+./compat.php
+    -> ./include/compat.inc.php
+
+./serendipity_functions_config.inc.php
+    -> ./include/functions_config.inc.php
+
+./serendipity_functions_images.inc.php
+    -> ./include/functions_images.inc.php
+
+./serendipity_functions_installer.inc.php
+    -> ./include/functions_installer.inc.php
+
+./serendipity_genpage.inc.php
+    -> ./include/genpage.inc.php
+
+./serendipity_lang.inc.php
+    -> ./include/lang.inc.php
+
+./serendipity_plugin_api.php
+    -> ./include/plugin_api.inc.php
+
+./serendipity_sidebar_items.php
+    -> ./include/plugin_internal.inc.php
+
+
+./serendipity_db.inc.php
+    -> ./include/db/db.inc.php
+
+./serendipity_db_mysql.inc.php
+    -> ./include/db/mysql.inc.php
+
+./serendipity_db_mysqli.inc.php
+    -> ./include/db/mysqli.inc.php
+
+./serendipity_db_postgres.inc.php
+    -> ./include/db/postgres.inc.php
+
+./serendipity_db_sqlite.inc.php
+    -> ./include/db/sqlite.inc.php
+
+
+./htaccess.cgi.errordocs.tpl
+    -> ./include/tpl/htaccess_cgi_errordocs.tpl
+
+./htaccess.cgi.normal.tpl
+    -> ./include/tpl/htaccess_cgi_normal.tpl
+
+./htaccess.cgi.rewrite.tpl
+    -> ./include/tpl/htaccess_cgi_rewrite.tpl
+
+./htaccess.errordocs.tpl
+    -> ./include/tpl/htaccess_errordocs.tpl
+
+./htaccess.normal.tpl
+    -> ./include/tpl/htaccess_normal.tpl
+
+./htaccess.rewrite.tpl
+    -> ./include/tpl/htaccess_rewrite.tpl
+
+./serendipity_config_local.tpl
+    -> ./include/tpl/config_local.tpl
+
+./serendipity_config_user.tpl
+    -> ./include/tpl/config_user.tpl
+
+
+./INSTALL
+    -> ./docs/INSTALL
+
+./LICENSE
+    -> ./docs/LICENSE
+
+./NEWS
+    -> ./docs/NEWS
+
+./README
+    -> ./docs/README
+
+./TODO
+    -> ./docs/TODO
+
+./upgrade.sh
+    -> ./docs/upgrade.sh
diff --git a/docs/INSTALL b/docs/INSTALL
new file mode 100644 (file)
index 0000000..a8d1a9d
--- /dev/null
@@ -0,0 +1,74 @@
+###############################################################################
+# INSTALLATION                                                                #
+###############################################################################
+
+1. Decompress and put this folder somewhere inside your document root
+2. If you want the directory to be called something other than "serendipity",
+change the directory name now
+3. Open serendipity in your browser (installer will say hi to you)
+4. Serendipity ships world-writeable (777) to make installation easier.
+After the install is complete,  you should change the permissions to allow
+only your web-server user (e.g. Nobody) to access the serendipity directory.
+If you have enabled file-upload and/or caching, you need to do something
+like this:
+  chown -R Nobody serendipity/
+  chmod -R 744 serendipity/
+because the web server needs to be able to write to directories inside the
+distribution.  Otherwise, you should probably chmod -R 644 serendipity.
+5. Done!
+
+###############################################################################
+# UPGRADE                                                                     #
+###############################################################################
+
+See README file for detailed actions.
+
+###############################################################################
+# REQUIREMENTS                                                                #
+###############################################################################
+
+1. The Apache Webserver
+2. .htaccess support allowing overrides for DirectoryIndex
+3. PHP Version 4 or greater (PHP 4.3.1 or greater recommended)
+4. php.ini options:
+   - error_reporting E_ALL & ~E_NOTICE (or lower)
+   - file_uploads on (For import/image upload features)
+5. Any of the following database engines:
+   - Mysql
+   - PostGreSQL
+   - SQLite (not quite!)
+
+###############################################################################
+# FILE STRUCTURE                                                                #
+###############################################################################
+serendipity consists of 3 parts:
+
+1. Function library / API
+   -serendipity_admin_entries.inc.php
+   -serendipity_admin_overview.inc.php
+   -serendipity_config.inc.php
+   -serendipity_functions.inc.php
+   -lang/serendipity_lang_*.inc.php
+   These files are never loaded in the browser, but included (as their
+   suffix suggests).
+
+3. Sample usage of the API
+  -layout.php (in templates/[theme]/)
+   This file displays the calendar, the search field, and the diary entries.
+   You can either include this file somewhere in your site, or use the 
+   callback functions directly in your site. It's up to you. I designed this,
+   so you can quickly start off with a default layout :)
+
+4. Dummy page
+   -index.php
+   This file "simulates" your homepage, you can safely ignore it, it is mainly
+   for testing, whether serendipity works (currently it just prints a standard
+   HTML header and includes layout.php
+
+###############################################################################
+
+Serendipity Weblog - http://s9y.org
+
+Licensed under the BSD License
+
+# $Id$
diff --git a/docs/INSTALL_EMBEDED b/docs/INSTALL_EMBEDED
new file mode 100644 (file)
index 0000000..934d92a
--- /dev/null
@@ -0,0 +1,77 @@
+########################################################################
+# THE 'embed' CONFIGURATION DIRECTIVE                                  #
+########################################################################
+
+In your serendipity configuration, you can set an 'embed' option to true
+or false.
+
+This defines, whether you use your blog as a standalone webpage - or if
+you have different content wrapped around your blog, like the menu of
+your usual homepage.
+
+By setting the 'embed' option to true, you have to make sure the
+following things to get everything to work well:
+
+1. 'indexFile' option.
+
+   This configuration option needs to be set to the wrapper file you
+   want to use. Let's say you normally have a 'content.php' file for
+   your webpage. This 'content.php' file sets up your internal
+   templates, your menu structure and such.
+   Now you want this file to be used to include your weblog. A simple
+   content.php could look like this:
+
+   <?php
+   $homepage = new Template_Class;
+   $homepage->set_template($_REQUEST['page']);
+   $homepage->output_header();
+   $homepage->output_content();
+   $homepage->output_footer();
+   $homepage->track_statistics();
+   ?>
+
+   So normally your file would be called with 'content.php?page=about'
+   to display your 'about' page of your personal homepage.
+
+   Now we want this file to be displayed, having the 'page' variable
+   being set to 'blog'.
+
+   For this, we set up a 'wrapper.php' file:
+
+   <?php
+   $_REQUEST['page'] = 'blog';
+   // Let serendipity generate our content:
+   ob_start();
+   require 'index.php';
+   $blog_data = ob_get_contents();
+   ob_end_clean();
+
+   // Now we include our normal content building file.
+   // This one has to make use of your $blog_data variable to print
+   // the content where appropriate!
+   require 'content.php';
+   ?>
+
+   You would then set your 'indexFile' serendipity-option to the
+   'wrapper.php' file.
+
+  2. Plugin panes & HTML-headers
+
+   With the example above, we only get the main blog data printed. One
+   of the most visible actions when using the 'embed' option is that the
+   plugin panes are not generated. And HTML headers/foooters are also
+   not provided by s9y in this case, as this should be done by your
+   'content.php' file.
+
+   So you have to include them in your 'content.php' file, to have them
+   visible in your embedded setup.
+
+   You can use this snippet:
+   <?php
+   serendipity_plugin_api::generate_plugins('left','div');
+   serendipity_plugin_api::generate_plugins('right','div');
+   ?>
+   somewhere in your 'content.php' file.
+
+The 'embed' option is therefore only recommended to be used by advanced
+users going for a most flexible setup!
diff --git a/docs/INSTALL_SHARED b/docs/INSTALL_SHARED
new file mode 100644 (file)
index 0000000..a449f24
--- /dev/null
@@ -0,0 +1,139 @@
+########################################################################
+# HOW TO USE SERENDIPITY AS SHARED LIBRARY                             #
+########################################################################
+
+******************************************
+* WARNING: THIS FEATURE IS EXPERIMENTAL! *
+******************************************
+
+You can install ONE s9y distribution and manage multiple users on it by
+sharing the core files and then deploying specially crafted files in
+each user's directory.
+
+Let's do this using an example. You own the domain 's9yblogs.org'.
+You want to have multiple virtual hosts for as many users as you like.
+They are going to be called 'username.s9yblogs.org'. We choose the users
+'garvin', 'j' and 'tom' for example hosts. We assume that your webserver
+runs as user 'www', group 'www'. We also assume that all your users
+are called like the subdomains, and they are also in group 'www'. We
+further assume that PHP's safe_mod is turned off.
+
+Of course, for security reasons, you should set the open_basedir
+directive to the user's document root, so he can't access other
+installations on your host.
+
+So your Apache-Webser should contain VirtualHosts like this:
+
+-- httpd.conf
+<VirtualHost 42.42.42.42:80>
+    ServerName garvin.s9yblogs.org
+    DocumentRoot /home/www/garvin.s9yblogs.org/htdocs
+    <Directory "/home/www/garvin.s9yblogs.org/htdocs">
+        AllowOverride All
+    </Directory>
+    php_value include_path ".:/usr/local/lib/php:/usr/local/lib/php/s9y/:/usr/local/lib/php/s9y/bundled-libs/"
+    php_admin_value open_basedir "/usr/local/lib/php/:/usr/local/lib/php/s9y/:/home/www/garvin.s9yblogs.org/"
+</VirtualHost>
+
+<VirtualHost 42.42.42.42:80>
+    ServerName j.s9yblogs.org
+    DocumentRoot /home/www/j.s9yblogs.org/htdocs
+    <Directory "/home/www/j.s9yblogs.org/htdocs">
+        AllowOverride All
+    </Directory>
+    php_value include_path ".:/usr/local/lib/php:/usr/local/lib/php/s9y/:/usr/local/lib/php/s9y/bundled-libs/"
+    php_admin_value open_basedir "/usr/local/lib/php/:/usr/local/lib/php/s9y/:/home/www/j.s9yblogs.org/"
+</VirtualHost>
+
+<VirtualHost 42.42.42.42:80>
+    ServerName tom.s9yblogs.org
+    DocumentRoot /home/www/tom.s9yblogs.org/htdocs
+    <Directory "/home/www/tom.s9yblogs.org/htdocs">
+        AllowOverride All
+    </Directory>
+    php_value include_path ".:/usr/local/lib/php:/usr/local/lib/php/s9y/:/usr/local/lib/php/s9y/bundled-libs/"
+    php_admin_value open_basedir "/usr/local/lib/php/:/usr/local/lib/php/s9y/:/home/www/tom.s9yblogs.org/"
+</VirtualHost>
+-- httpd.conf
+
+You will unpack the default s9y distribution files in
+"/usr/local/lib/php/s9y/". Where you store the directory 's9y' is
+not important, as long as you adjust the include_path setting in the
+VirtualHosts. But the directory name 's9y' is significant.
+
+Now copy the subdirectories called
+
+ * "/usr/local/lib/php/s9y/deployment/"  [core redirection files]
+ * "/usr/local/lib/php/s9y/templates/"   [templates so that users can change them]
+ * "/usr/local/lib/php/s9y/htmlarea/"    [htmlarea WYSIWYG-editor]
+
+ to each of the user's subdirectories:
+
+$ cp -r /usr/local/lib/php/s9y/deployment/* /home/www/garvin.s9yblogs.org/htdocs/
+$ cp -r /usr/local/lib/php/s9y/templates /home/www/garvin.s9yblogs.org/htdocs/
+$ cp -r /usr/local/lib/php/s9y/htmlarea /home/www/garvin.s9yblogs.org/htdocs/
+$ chown -R garvin.www /home/www/garvin.s9yblogs.org/htdocs/*
+$ chmod ug+rwx /home/www/garvin.s9yblogs.org/htdocs
+$ chmod ug+rwx /home/www/garvin.s9yblogs.org/htdocs/uploads/
+
+$ cp -r /usr/local/lib/php/s9y/deployment/* /home/www/j.s9yblogs.org/htdocs/
+$ cp -r /usr/local/lib/php/s9y/templates /home/www/j.s9yblogs.org/htdocs/
+$ cp -r /usr/local/lib/php/s9y/htmlarea /home/www/j.s9yblogs.org/htdocs/
+$ chown -R j.www /home/www/j.s9yblogs.org/htdocs/*
+$ chmod ug+rwx /home/www/j.s9yblogs.org/htdocs
+$ chmod ug+rwx /home/www/j.s9yblogs.org/htdocs/uploads/
+
+$ cp -r /usr/local/lib/php/s9y/deployment/* /home/www/tom.s9yblogs.org/htdocs/
+$ cp -r /usr/local/lib/php/s9y/templates /home/www/tom.s9yblogs.org/htdocs/
+$ cp -r /usr/local/lib/php/s9y/htmlarea /home/www/tom.s9yblogs.org/htdocs/
+$ chown -R tom.www /home/www/tom.s9yblogs.org/htdocs/*
+$ chmod ug+rwx /home/www/tom.s9yblogs.org/htdocs
+$ chmod ug+rwx /home/www/tom.s9yblogs.org/htdocs/uploads/
+
+For later management access, it is advised you keep a list of all URLs
+for your s9y-managed blogs. We suggest to create a SQL table like
+'my_managed_s9y_blogs':
+
+sql> CREATE TABLE my_managed_s9y_blogs (url varchar(255) default null);
+sql> INSERT INTO my_managed_s9y_blogs (url) VALUES ('http://garvin.s9yblogs.org/');
+sql> INSERT INTO my_managed_s9y_blogs (url) VALUES ('http://j.s9yblogs.org/');
+sql> INSERT INTO my_managed_s9y_blogs (url) VALUES ('http://tom.s9yblogs.org/');
+
+Now you are almost ready for take-off. We assume that every user has
+access to a seperate SQL database where his blog-data is later stored
+in. You can already see, that the steps needed above shouldn't be to
+hard to put into a customized script.sh file for use in your setup.
+
+Open up your http://garvin.s9yblogs.org/ file. You should now see s9y's
+installation screen. Enter the database- and username and the
+corresponding password. Everything else can be left to the user.
+
+Now every user can manage his/her blog just as if it were a standalone
+installation.
+
+SPECIAL NOTES:
+========================================================================
+
+* Each blog is still a standalone blog.
+
+* If you update the core library files from version 0.5 to 0.6 (for
+  example) every user of your core library will get the default s9y-
+  Upgrader script to see and needs to update his local configuration.
+
+  As a provider for s9y blogs to your users, you are advised to migrate
+  the user's blogs on your own. To do so, it is best that you always
+  have a "spare" testing blog installed just like your user's blogs.
+
+  Open that installation and look at the upgrader. Execute it and see
+  that it completes without errors. If that happened, you should cycle
+  through a list of ALL your s9y-managed blogs like this:
+
+  <?php
+  $sql = mysql_query('SELECT url FROM my_managed_s9y_blogs');
+  while ($row = mysql_fetch_array($sql, MYSQL_ASSOC)) {
+     $fp = fopen($row['url'] . 'serendipity_admin.php?serendipity[action]=upgrade');
+  }
+  ?>
+
+  So basically all you need to do is call that script for every s9y-
+  powered blog you host.
diff --git a/docs/LICENSE b/docs/LICENSE
new file mode 100644 (file)
index 0000000..3403a5b
--- /dev/null
@@ -0,0 +1,24 @@
+Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright notice,
+      this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+    * Neither the name of the serendipity developer group nor the names of its contributors
+      may be used to endorse or promote products derived from this software without
+      specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/docs/NEWS b/docs/NEWS
new file mode 100644 (file)
index 0000000..a0c54cf
--- /dev/null
+++ b/docs/NEWS
@@ -0,0 +1,1318 @@
+# $Id$
+
+Version 0.8 (April, 15th 2005)
+------------------------------------------------------------------------
+
+    * Added icelandic translation by Örn Arnarson
+
+    * Fixed a possible SQL injection issue in Tracking methods. Also
+      fixed possible XSS exploit in BBCode markup, if enabled for
+      comments. Thanks to ADZ Security Team for detecting this. Next
+      time please give us more time to respond to your public announced
+      exploits. ;) (garvinhicking)
+
+    * Reverted more JavaScript-patches introduced in beta5 to make
+      the extended body text visible when using WYSIWYG editor
+      (garvinhicking)
+
+    * Fix SQLite bug when fetching authorname in quicksearch. Thanks to
+      Sven Oliver Moll!
+
+Version 0.8-beta6 (April 8th, 2005)
+------------------------------------------------------------------------
+
+    * Remove unique constraint for url_idx on the referrer suppress table
+      and replaced it by a simple index. Fixes fatal errors on postgresql
+      (garvinhicking)
+
+    * Fix inserting media manager items: Non-images were not properly
+      detected (garvinhicking)
+
+    * Fix broken SQL for inserting comments which showed in SQLite/PGSql
+      and got introduced in beta5. (garvinhicking)
+
+    * Reverted JavaScript-patches from nohn introduced in beta5 to make
+      IE6 again show the category and extended entry toggle buttons
+      (garvinhicking)
+
+Version 0.8-beta5 (April 1st, 2005)
+------------------------------------------------------------------------
+
+    * Fix XMLRPC problems for getting existing posts. Thanks a lot to
+      TimothyP from the forums! (garvinhicking)
+
+    * Fix directory creation error; the mode 1777 failed on several setups,
+      so we use 0777 again (garvinhicking)
+
+    * Fix installer not being able to go above page 2 on special setups
+      with register_globals On (garvinhicking)
+
+    * Fixed buggy referrer tracking for MySQL (Bug #1170251)
+
+    * Upgrade Smarty to v2.6.9 (tomsommer)
+
+    * Added 'Cache-Control: no-cache' header to our CSS file; this may
+      fix IE bugs where CSS was only loaded after 1-2 reloads.
+      (TomSommer)
+
+    * Fixed a XMLRPC problem for metaWeblog_newMediaObject() to properly
+      save a binary file. Thanks to marco from the forums! (garvinhicking)
+      
+    * Fixed possible SQL-Injection in Pingbacks (nohn; reported by Stefan
+      Esser)
+
+    * Kubrick template: Fix comments always printed as 'Anonymous',
+      put entry/extended parts not together (garvinhicking)
+
+    * Fix installer: Serendipity does not run with magic_quotes_runtime
+      set to on. Emit warning and try to switch off the directive.
+      (garvinhicking)
+
+    * Updated chinese language files, thanks to Andrew Huang
+
+Version 0.8-beta3/4 (March 15th, 2005)
+------------------------------------------------------------------------
+
+    * Drop SQL index on comment's body. This was not used in our code,
+      and caused trouble with large comments on pgsql and MySQL.
+      (garvinhicking)
+
+    * Monthly entry summary shows correct date header (garvinhicking)
+
+    * RSS / Syndication plugin now offers to hide E-Mail adresses from
+      XML feeds (garvinhicking)
+
+    * After installing a plugin you will be either redirected to
+      plugin config or to plugin overview, so that an accidental
+      browser refresh does not install the plugin twice
+      (garvinhicking)
+
+    * Fixed wrong date format in portuguese and czech languages
+      (garvinhicking)
+
+    * Fix buggy wordfiltering of spamblock plugin (garvinhicking)
+
+    * Fixed variable name for all markup plugins. They previously used
+      localized versions like 'Extended entry' and now use a proper
+      language independent string. The upgrader takes care of replacing
+      the variables so that no options will get lost (garvinhicking)
+
+    * Fixed bug with Markup plugins not getting their right settings
+      under certain circumstances (only for autologin cookie users)
+      (garvinhicking)
+
+    * Correctly detect 500 Internal Server Error when installing
+      (garvinhicking)
+
+    * Emitting language headers only if no headers were sent yet.
+      This fixes problems with embedded serendipity installations.
+      (garvinhicking)
+
+    * Fix postgresql query problem, when using the entryproperties
+      plugin and browsing the calendar with category restriction(s).
+      Thanks to Larry Rosenman for helping out with this!
+      (garvinhicking)
+      
+    * Introduce "div.container_X" CSS class for sidebar plugin items.
+      X is substituted with the plugin classname, like
+      "serendipity_plugin_categories". This class is contained in the
+      'default' template and all templates based on the sidebar.tpl
+      file. (garvinhicking)
+
+    * Fixed broken category pagination for "Newspaper" template
+      (garvinhicking)
+
+    * Bundle Tom Sommer's port of the Kubrick template
+    
+    * Fix hardcoded "templates" directory reference inside the admin
+      style selector.
+
+    * Updated czech language files, thanks to Josef Klimosz
+    
+    * Updated persian language files, thanks to Omid Mottaghi
+
+    * Do not display rotation/resize image manipulation methods for
+      hotlinked images (garvinhicking)
+
+    * Do not use "layout.php" in Default template for upgrading users
+      who did not delete that file from their directory (because the
+      upgrade may not have sufficient write privileges to remove the
+      file) (garvinhicking)
+
+    * Make RSS import parse ISO-8601 dates (like
+      '2004-11-24T22:43:08-05:00'), as PHPs strtotime() does not parse
+      that. (garvinhicking)
+
+Version 0.8-beta2 (March 5th, 2005)
+------------------------------------------------------------------------
+
+    * Show "create entry" toolbar for plugins like the Emoticon Chooser
+      also when WYSIWYG editor is enabled (garvinhicking)
+
+    * Do not display template engines in the template selector
+      (tomsommer)
+
+    * Fix HTML escaping of special characters for comments
+      (garvinhicking)
+
+    * Fix wrong username displayed in RSS comment feeds (garvinhicking)
+
+    * Fixed bug that may occur on few plugins executing other plugins,
+      like serendipity_event_entrypaging [this is the only bundled or
+      internal plugin affected by the issue] (garvinhicking)
+
+Version 0.8-beta1 (March 4th, 2005)
+------------------------------------------------------------------------
+
+    * Added Persian language and template for RTL-Languages by Omid
+      Mottaghi
+
+    * Fixed Windows path problems when synching with media manager.
+      Thanks to Thomas Klinger for helping!
+      (garvinhicking)
+
+    * Media files can now be hotlinked to foreign servers and thus not
+      using bandwidth from your own server. Media files can now also
+      be searched by name. Thanks to Chris Chan for this feature!
+
+    * Added ability to define a real name for each author. This is the
+      name seen by readers of the blog. The username is now only used for
+      logging into the administration suite (tomsommer)
+
+    * Added ability to toggle the amounts of comments per page within
+      a dropdown instead of needing to edit a Serendipity core file.
+      (garvinhicking)
+
+    * New configuration directive to tell Serendipity if the baseURL
+      shall be autodetected. This can be useful if you use multiple
+      domainnames listening on one blog installation. (Note: This auto-
+      detection was previously already enabled if using 'embedded mode')
+      (garvinhicking)
+
+    * Fixed bug for postgreSQL: Comments for entries within multiple
+      categories showed up as many times as the entry was within multiple
+      categories. Thanks to rickmans from the forums for detecting this.
+      (garvinhicking)
+
+    * Added configuration directive to allow visitor language negotiation
+      via browser language. (garvinhicking)
+
+    * Added native importers to migrate entries, comments,
+      categories and authors for:
+      - geeklog 1.3.11
+      - sunlog 0.4.4
+      - b2Evolution "Paris"
+      - boastMachine 3.0
+      - Textpattern 1.0rc1
+      - pMachine Pro 2.4
+      - bBlog 0.7.4
+      - Nucleus 3.15
+      - WordPress 1.5 / 1.2
+      - phpBB
+      (garvinhicking)
+
+    * Remember last state of media library (sort order, files per page,
+      directory, sortfield), via JavaScript+Cookies (garvinhicking)
+
+    * The config option 'extCSS' has been removed. It is now re-
+      commended to set external stylesheets in the template's index.tpl
+      file, or to @import it within the templates style.css file.
+      (garvinhicking)
+
+    * Personal Configuration allows to set defaults for creating new
+      entries (allow comments, moderate comments, publish/draft)
+      (garvinhicking)
+
+    * When deleting a comment with nested comments, move nested ones
+      to the parent of the deleted comment (fixes Bug #1079349)
+      (garvinhicking)
+
+    * Spamblock plugin allows to moderate/reject comments made via APIs
+      like wfw:commentApi or trackbacks, but still allow normal comments
+      (garvinhicking)
+
+    * Fixed SQL index key creation on fresh installation (garvinhicking)
+
+    * Upgraded htmlarea WYSIWYG editor to latest version. Entering
+      links now properly works, as finally does Copy+Paste from Mozilla!
+      (garvinhicking)
+
+    * New pretty URLs "/blog/serendipity.css" and
+      "/blog/serendipity_admin.css" as links to the Stylesheets.
+      (garvinhicking)
+
+    * Chief users are not allowed to hide plugins installed by other
+      users. (garvinhicking)
+
+    * Forbid uploading of active content files (.php, .shtml, ...) as
+      user without Administrator privileges (garvinhicking)
+
+    * Allow searching of the blog with pretty URLs, allow pagination
+      of searched entries (garvinhicking)
+
+    * Added handling of CONVERT BREAKS-directive in MT-Importer. Do the
+      whole importing process in a transaction to ensure either all or
+      no entires are imported. (pilif)
+
+    * Added hook for external authentication. First implementation draft
+      of LDAP auth added to additional_plugins CVS (garvinhicking)
+
+    * Added an extended property to disable nl2br() for specific
+      entries (pilif)
+
+    * Added korean language by Erich Iseli (garvinhicking)
+
+    * Change RSS feed's <guid> element to contain isPermaLink=false.
+      Only the link of the <link> element should be used as Permalink.
+      This fixes problems with copying links to send a trackback to from
+      RSS readers/clients that used the <guid> element as Permalink.
+      (garvinhicking)
+
+    * Fixed flaw in the function used to validate path-names.
+      Thanks to raperu2000 from the forums! (garvinhicking)
+
+    * Added Finnish language by Mauri Sahlberg (garvinhicking)
+
+    * Added Japanese language by Tadashi Jokagi (garvinhicking)
+
+    * Add ability to see all entries made by a single user (tomsommer)
+
+    * The "edit entry" overview will now highlight entries to be
+      published in the future (garvinhicking)
+
+    * Allow authors to easier reset the time for each entry, by clicking
+      an icon (tomsommer)
+
+    * Added new plugin, enabled by default, to enforce maximum browser
+      compatibility. The only thing which 'serendipity_event_browsercompatibility'
+      currently does is to add the transparent PNG Behaviour for IE.
+      (garvinhicking)
+
+    * 'Track Exits' plugin will no longer be enabled by default, as
+      requested and discussed on the Mailinglist. (garvinhicking)
+
+    * Added Simplified Chinese (GB2312, UTF-8) and Traditional Chinese
+      (Big5, UTF-8) languages, thanks to skyroam!
+
+    * Split up the configuration and the installer. Add a diagnostic
+      page to the installer. Allow for simple or expert installation
+      (tomsommer)
+
+    * Fix problem in Imagemagick detection when checking the apache PATH,
+      added /usr/local/bin to possible locations of Imagemagick
+      (tomsommer)
+
+    * Spam Protector can now log failed comments to either plaintext-
+      file or database. Dedicated to all those trigger-happy logfile-
+      statistic-hunters out there... (garvinhicking)
+
+    * When using ImageMagick, create a thumbnail of a PDF for media
+      browsing (nohn, garvinhicking)
+
+    * More than one plugin cannow be saved per plugin/ subdirectory,
+      event + sidebar plugins can be put together in one directory.
+      Names of subdirectores are irrelevant now, but the filenames
+      need to match 'serendipity_(event|plugin)_*.php'. (garvinhicking)
+
+    * When entering a comment, the referring URL to the blog is saved
+      (garvinhicking)
+
+    * Use mbstring extension where available to correctly utilize PHPs
+      string functions for multibyte chars. This is needed for UTF-8
+      only languages like Chinese (garvinhicking)
+
+    * Move the page where you change your details out of the
+      configuration and into its own menuitem and page (tomsommer)
+
+    * Allow the usage of persistent database connections (tomsommer)
+
+    * New configuration directive to let user choose if entries in the
+      future are hidden (default) or displayed. (garvinhicking)
+
+    * Add ability to gzip compress pages (tomsommer)
+
+    * Separate administration CSS layout from the rest of the blog
+      (tomsommer)
+
+    * Merge Administration and Author suite into one (tomsommer)
+
+    * Allow $plugin->get_config([var]) to return the default value from
+      introspect_config_item() if no value is found (tomsommer)
+
+    * Preview/Saving entries now utilizes iframe techniques to faster
+      send visual feedback and properly be able to style the entry
+      preview independent from the Admin CSS code. [For older browsers,
+      this can be turned of in serendipity_config.inc.php]
+      (garvinhicking)
+
+    * Allow sending trackbacks and tracking links of https URLs. Fix
+      "Entry's Links" plugin to properly display trackable links.
+      (garvinhicking)
+
+    * Spamblock plugin can be configured to hide E-Mail adresses when
+      displaying comments. (garvinhicking)
+
+    * FIX: CSS classes in the comment manager was always set to uneven
+      (tomsommer)
+
+    * When a document does not exist and Serendipity has no idea how
+      to create it, a 404 (not found) is sent instead of a 200 (OK)
+      (tadpole9)
+
+    * serendipity_config_local.inc.php can now contain user-defined
+      variables, which are not overwritten when changing Configuration.
+      (garvinhicking)
+
+    * Improved overall performance of Plugin API, code improvements,
+      query optimizing. Added with the entryproperties caching plugin,
+      this boosts performance by about 15-30%. You are also adwised
+      to use opcode-caches, if available [APC, Zend Cache, Turck, ...]
+      (garvinhicking)
+
+    * Entries can be cached by the 'entryproperties' plugins. This
+      caching interacts with other plugins: When cacheable plugins are
+      added, the cache is updated, as well as when an entry is modified.
+      When the plugin is first installed, it creates the cache for the
+      latest 15 entries; you can create a cache of all entries using
+      the admin interface. (garvinhicking)
+
+    * New CSS classes for distinction of authors within entries/comments:
+      .serendipity_entry_(author|comment)_USERNAME, applied to each
+      entry container, where USERNAME is replaced with the name of the
+      author.
+      .serendipity_entry_author_self, applied to the entry container if
+      the currently logged in user is the author of an entry
+      .serendipity_comment_author_self, applied if the commenting user-
+      name matches the owner of the entry.
+      (garvinhicking)
+
+    * Rewrote importer to use import modules and class framework
+      (tomsommer)
+
+    * New language: Traditional Chinese (Big5). Thanks to Andrew Huang!
+
+    * Recent Entries plugin: New configuration directive to not display
+      items already shown on frontpage. Thanks to Sebastian Raible!
+      (garvinhicking)
+
+    * Articles per page (default 15) can now be set within Configuration
+      (garvinhicking)
+
+    * Plugin API: Event plugins using the 'entry_display' hook to set
+      an entries page to not render (via 'clean_page') now need to use
+      the new hook 'entries_header' for their output; the 'clean_page'
+      variable still needs to be set within the hook 'entry_display'
+      though. (garvinhicking)
+
+    * Support for adding timezone offsets in configuration
+      (garvinhicking)
+
+    * Serendipity cannow be used with "JustBlogIt" extension. Just use
+      this URL:
+      http://yourblog/serendipity_admin.php?serendipity[adminModule]=entries&serendipity[adminAction]=new&serendipity[title]=%TITLE%&serendipity[body]=%TEXT%&serendipity[url]=%URL%
+      (garvinhicking)
+
+    * Plugin serendipity_event_spamblock: Added SURBL
+      (http://www.surbl.org/) Support. Will now reject any comment that
+      contains a blacklisted URL, if enabled. (nohn)
+
+    * Do not allow to view extended article when item is set to "publish"
+      but timestamp is in the future (garvinhicking)
+
+    * RSS Export orders entries in reverse ID order for easier
+      importing (garvinhicking)
+
+    * Cleaned up directory structure, created new subdirectories,
+      split up functions file. See docs/CHANGED_FILES for details if
+      you have external dependencies on removed files (like custom
+      plugins, themes, or special embedded usage) (garvinhicking)
+
+    * "Recent Entries" Plugin can now have userdefined title and only
+      show entries of a specific category (+ subcategories).
+      (garvinhicking)
+
+    * Media browser now allows to immediately upload a file from the
+      entry creation screen and use that file/image easily
+      (garvinhicking)
+
+    * exit.php redirection will emit a 301 Moved Permanently header for
+      the new location. (garvinhicking)
+
+    * Reworked plugin manager for easier plugin installation (tomsommer)
+
+    * Karma plugin works with enabled entryproperties plugin and can
+      be configured to only show Hit-statistics for an entry without
+      the voting ability (garvinhicking)
+
+    * Routine for autodetecting links within an entry will now also
+      allow images to be used as description. (garvinhicking)
+
+    * Implement plugin install() and uninstall() methods that are called
+      on installation and removal of a plugin (tomsommer)
+
+    * Improve overall rewrite path syntax (tomsommer)
+
+    * Allow the display of month, weeks and days in archive sidebar
+      (tomsommer)
+
+    * Add ability to display entries based on week (tomsommer)
+
+    * Use rewrite paths in the syndication plugin (tomsommer)
+
+    * Added import tool for Movable Type data files and WordPress
+      databases. (tadpole9)
+
+    * Syndication plugin offers to show full feed including extended
+      entry (garvinhicking)
+
+    * serendipity_event_entryproperties now supports entry caching to
+      pregenerate the full article and display that instead of
+      assigning event plugins time and again (garvinhicking)
+
+    * New plugin serendipity_event_entryproperties: You can now define
+      any property to an entry and query it. Currently implemented
+      are "sticky posts" and "private/public/members-only" entries.
+      (garvinhicking)                  [DB Layout change - > 0.8-alpha2]
+
+    * Fixed bug #1031059 - Trackbacks to a link will not be sent more
+      than once (garvinhicking)
+
+    * Added "Ping-o-Matic!" to weblogping plugin (garvinhicking)
+
+    * RSS Feed export will not contain rewritten URLs using event
+      plugins (garvinhicking)
+
+    * Updated upgrader to use MySQL as fallback when looking for
+      appropriate database updates and none was found for the selected
+      database type (tomsommer)
+
+    * Added support for Smarty Templating. (garvinhicking, tomsommer)
+
+Version 0.7.1 (December 2nd, 2004)
+------------------------------------------------------------------------
+
+    * Fixed captcha string variation on some setups by explicitly seeding
+      the randomness (garvinhicking)
+
+    * Fixed cross site scripting vulnerability. Thanks to Stefan Esser
+      for reporting this issue. (nohn, garvinhicking)
+
+    * Do not show entries of the future when entering their direct URL
+      (garvinhicking)
+
+Version 0.7 (November 8th, 2004)
+------------------------------------------------------------------------
+
+    * Fixed concatenation syntax on PostgreSQL, only used by plugin
+      "Entrylinks". (garvinhicking)
+
+    * SQLite database name was not saved properly and could get set to
+      a wrong value when updating configuration (garvinhicking)
+
+    * Better detection if Apache ErrorDocument can be used
+      (garvinhicking)
+
+    * Fixed PostgreSQL index key names (names are now unique, and
+      combined indizes on the entries text-columns are no longer set)
+      (jtate, garvinhicking)
+
+    * Fixed bug with MySQL 3.x where the category was not properly set
+      when editing (garvinhicking)
+
+    * Fixed karma plugin to not track clicks when previewing an entry
+      (garvinhicking)
+
+    * Fixed some counting problems in statistics plugin (garvinhicking)
+
+    * Fixed comment counter for deleting non-approved comments
+      (tomsommer, griffinn)
+
+Version 0.7-rc1 (October 20th, 2004)
+------------------------------------------------------------------------
+
+    * Fixed possible HTTP Response Splitting security issue. Thanks to
+      ChaoticEvil for reporting! (jannis, garvinhicking)
+
+Version 0.7-beta4 (October 14th, 2004)
+------------------------------------------------------------------------
+
+    * Bug #1016342 - Fixed RSS UTF8 decoding for remote RSS plugin.
+      (garvinhicking)
+
+    * Fixed some wrong calculations in the statistics plugin, thanks
+      to David DeLauro! (garvinhicking)
+
+    * Fixed entry count and category association bugs using SQLite
+      (garvinhicking)
+
+    * Fixed some error notices for installation with postgreSQL regarding
+      field index names (garvinhicking)
+
+    * Fixed wrong mod_rewrite rules to properly redirect to pages.
+      (garvinhicking)
+
+    * Trackback moderation support in admin panel, make captcha plugin
+      only work for comments (garvinhicking)
+
+    * Bug #1037122: BlogPDF plugin will me less strict in file inclusion
+      (garvinhicking)
+
+    * Fixed wrong entry id displayed in RSS comment feed. Thanks to
+      romulus! (garvinhicking)
+
+    * Fixed file permission checks when removing images inside media
+      manager. Thanks to Thomas from the forums! (garvinhicking)
+
+    * RSS Import: New option 'full body only', so that imported RSS
+      contents can be forced to only show up in the full body. Fixed
+      buggy substr() logic which may cause nasty splitting from entry
+      body to extended entry. (garvinhicking)
+
+    * Extend filter in commment moderation to allow the user to select
+      which types of comments he wants displayed "All", "Only approved",
+      "Need approval" (tomsommer)
+
+    * Upgraded Spam Protector event plugin. Optionally:
+      - use Captchas - images with string sequences which a
+        user has to enter before his comment is accepted.
+      - restrict captchas to entries older than X days
+      - auto-moderate comments to entries older than X days
+      - auto-moderate comments depending on their amount of
+        contained links.
+      - reject comments depending on their amount of
+        contained links.
+      - able to log rejected/moderated comments to a plaintext file
+      - fallback method for non-gdlib-enabled hosts
+      (garvinhicking)
+
+    * Fixed wrong implode() arguments for error reporting in installer
+      (garvinhicking)
+
+    * Fixed windows detection for stripping backslashes out of
+      uploaded files. Thanks to Thomas! (garvinhicking)
+
+Version 0.7-beta3 (September 21st, 2004)
+------------------------------------------------------------------------
+
+    * Bug #1031444 - Fixed postgreSQL error (for older versions of
+      pgsql) when creating categories (garvinhicking)
+
+    * Fixed wrong XHTML entities in remoterss and shoutbox plugin. Thanks
+      to Stephan van Beerschoten! (garvinhicking)
+
+    * Fixed bug #1030581: Category sidebar plugin now properly displays
+      only categories of selected author (garvinhicking)
+
+    * Fixed XML RPC API to set categories when posting via BlogJet
+      or other interfaces (garvinhicking)
+
+    * Fixed invalid standard-SQL 'CURRENT_DATE' to use a real date
+      string. Fixes Exit-Tracking with SQLite. (garvinhicking)
+
+    * Fixed footer printing wrong amount of entries when entry was
+      assigned to more than one category. Thanks to Kris/weigon for
+      helping. (garvinhicking)
+
+    * Use htmlspecialchars/strip_tags for escaping user input on comment
+      moderation/viewing. (garvinhicking)
+
+    * Fixed warning message from emoticon plugin when emoticons.inc.php
+      does not exist (garvinhicking)
+
+    * Fixed entries pagination for special cases where quickump calendar
+      was displayed on the left sidebar (garvinhicking)
+
+Version 0.7-beta2 (September 15th, 2004)
+------------------------------------------------------------------------
+
+    * Fixed entries pagination for special cases where quickump calendar
+      was displayed on the left sidebar (garvinhicking)
+
+    * Added Italian translations, thanks to Alessandro Pellizzari
+
+    * Fixed missing CSS-class for BBCode Event-Plugin (Jez Hancock)
+
+    * Fixed possible SQL injections. Thanks to aCiDBiTS!
+
+    * Fixed postgreSQL quicksearch, thanks to Mauri Sahlberg!
+
+    * Added Norwegian translations, thanks to Jo Christian
+
+    * Fixed postgreSQL bugs for viewing comment moderation panel
+      (garvinhicking)
+
+    * Fixed postgresql bug for fetching the last entry id. Will fix bug
+      with comment counter always reporting zero and trouble with
+      assigning multiple categories. (garvinhicking)
+
+    * Fixed  "no entry to display" bug when previewing entry
+      (garvinhicking)
+
+    * Fix several postgreSQL update errors. Thanks to daFool from the
+      forums! (garvinhicking)
+
+Version 0.7-beta1 (September 6th, 2004)
+------------------------------------------------------------------------
+
+    * Disable the use of popups by default (tomsommer)
+
+    * BBCode plugin can now pretty print code/php style blocks.
+      (Jez Hancock, garvinhicking)
+
+    * Threaded/Linear view of comments can be toggled by the
+      visitor. (garvinhicking, tomsommer)
+
+    * Plugin serendipity_event_spamblock: Will reject any double
+      comments, if enabled. Stub for enhancing other spam-protections
+      (kaptchas, spamassassin-integration, IP-Blacklists, whatever)
+      (garvinhicking)
+
+    * When using mod_rewrite, make use of RewriteBase for correct
+      subdirectory matching. Thanks to Martin Roell! (garvinhicking)
+
+    * Don't use the title of an entry in the RSS feed <guid></guid> tags
+      (tomsommer)
+
+    * Use '-' as separator for IDs and words in our "nice" URLs, so
+      Google and others can recognize 'a-nifty-word' as 'a nifty word'.
+      Previously this was indexed as one single word.
+      (tomsommer, garvinhicking)
+
+    * Pagination now properly works for browsing months and categories.
+      Previously paging worked through all entries and not a filter
+      by date/category. [Bug #1009715] (garvinhicking)
+
+    * Remote RSS feed can now contain a bullet image, skip blank head-
+      lines and toggle the display of the date. Thanks to Joseph Guhlin!
+      (garvinhicking)
+
+    * Karma-Plugin disallows clicking from Googlebots following java-
+      script links (garvinhicking)
+
+    * Improved link detection routine for sending trackbacks, fixes
+      problems with bbcode-transformed URLs (garvinhicking)
+
+    * Fixed missing image display for rescaling images, when file was
+      outside of parent upload directory [Bug #1007003] (garvinhicking)
+
+    * Fixed some postgreSQL-issues, thanks to Ilya A. Volynets-Evenbakh!
+
+    * Improved and fixed XHTML-Cleanup Event plugin (garvinhicking)
+
+    * Fixed .htaccess update/creation errors for shared installation
+      (garvinhicking)
+
+    * RFE #832040 - Allow for easier handling of Calendar CSS classes
+      and remove hardcoded attributes for "today" (tomsommer)
+
+    * Add detection for support of php_value directives in .htaccess
+      files (tomsommer)
+
+    * Installation will report an error, if the needed db-extension for
+      a specific database-type are not available within PHP
+      (garvinhicking)
+
+    * Added bulgariang language, thanks to Bogomil Shopov
+
+    * Fix calendar bug to not show entries available for the 1st day
+      of a month if on the first day on the next month an entry was
+      posted (garvinhicking)
+
+    * UTF-8 Encoding (for RSS-feeds) will make use of iconv-library, if
+      available (garvinhicking)
+
+    * Quicksearch no longer shows results for entries in the future
+      (garvinhicking)
+
+    * Removed {dbPrefix}css table, since it was not used for anything
+      (tomsommer)                          [DB Layout change - > 0.6.11]
+
+    * Redesign entry list (tomsommer)
+
+    * Display subtitle (usually blogname) in <title> tags (tomsommer)
+
+    * Don't embed comments, trackbacks and comment-form in entry CSS
+      class (tomsommer)
+
+    * RFE #996320: Added https-option to login sidebar-plugin
+      (garvinhicking)
+
+    * Removed full plaintext URI from trackback section and replaced it
+      with a link to that URI (tomsommer, garvinhicking)
+
+    * Several German spelling mistakes corrected (thanks to Timbalu)
+
+    * Show trackbacks on the full-entry page if popups are disabled
+      (tomsommer)
+
+    * If popups are disabled, link to the full-page entry, with comments
+      and trackbacks as page-anchors (tomsommer)
+
+    * Use DIV tags for trackback layout, just like comments (tomsommer)
+
+    * Make sure that the file/image manager can never remove the upload
+      directory, but all files in it (garvinhicking)
+
+    * Changed database key 'mime' to varchar(255) instead of varchar(15)
+      (garvinhicking)                       [DB Layout change - > 0.6.9]
+
+    * New CSS classes 'serendipity_msg_notice' and
+      'serendipity_msg_important'. (garvinhicking)
+
+    * Added a new theme, "Idea" (tadpole9)
+
+    * Changed 'View extended entry' to 'Continue reading "[title]"'
+      (tomsommer)
+
+    * Make the non-WYSIWYG link-insertion and text-formatters work in
+      the extended entry textarea (tomsommer)
+
+    * Allow authors to toggle the extended entry textarea in the entry
+      composer when using the non-WYSIWYG editor (tomsommer)
+
+    * Better handling of unsubscriptions from entries, only show message
+      if the user was indeed unsubscribed (tomsommer)
+
+    * Added ability to moderate comments and trackbacks:
+        * Moderate by email
+        * Moderate and view comments from within Authoring Suite
+        * Mass delete of comments from administration
+      (tomsommer)                           [DB Layout change - > 0.6.7]
+
+    * An entries' LastModified timestamp will get updated if a comment
+      is made to it, but only if the article is newer than 7 days.
+      Make the conditional Get RSS-feed a lot more usable because old
+      entries no longer come up again. The limit of days can be set
+      within serendipity_config.inc.php. (garvinhicking)
+
+    * Plugins can register the event-hook 'external_plugin' to spawn
+      individual content outside of the blog layout (garvinhicking)
+
+    * Fixed link insertion in non-WYSIWYG-mode for Internet Explorer
+      (garvinhicking)
+
+    * Fixed retrieving multiple stored categories for Internet Explorer
+      when editing existing entry (garvinhicking)
+
+    * Added Bitflux Livesearch Javascript as plugin
+      (serendipity_event_livesearch). It will immediately search your
+      articlebase and offer an autocomplete dropdown to the quicksearch
+      box. Users with the embedded mode need to add the call to the
+      .js file manually into their headers. (chregu, garvinhicking)
+
+    * Added new versions of mt-clean, mt-georgiablue, mt-gettysburg,
+      mt-plainjane, and mt-rusty and activated them.
+
+    * RSS Import: Allow toggling of draft/publish import, category
+      association, more description. (garvinhicking)
+
+    * Allow HTML nugget to be displayable on extended article only, over-
+      view only or both (default) (garvinhicking)
+
+    * New plugin 'serendipity_event_blogpdf'. Will export your blog
+      as PDF file. Proof-of-concept, no nice formatting, no images yet.
+      If you're using 'mod_rewrite' you need to update your .htaccess
+      file. (garvinhicking)
+
+    * Fixed bug causing the .htaccess file to never get updated when
+      changing rewrite method (tomsommer)
+
+    * Track Exits plugin: Now only uses the link id for link referral.
+      Reduces URI length and makes random exit.php calling useless for
+      spammers, as no URL is tracked, which the author didn't refer to
+      (garvinhicking, isotopp)
+
+    * Actually log the IP of users who submit comments and blogs which
+      trackback (tomsommer)
+
+    * Plugin hook 'backend_publish' now executed on entries saved as
+      draft first and after that as a public. Fixes weblogpings not sent
+      to those entries. (garvinhicking)
+
+    * Added the ability to toggle the display of the Serendipity logo and
+      text in the "Powered by" plugin (tomsommer)
+
+    * Fixed problem with booleans not checking the correct radiobuttons in
+      the plugin manager (tomsommer)
+
+    * Fixed bug #983242: Missing entity encoding for blogtitle/subtitle
+      for RSS feeds, thanks to Christian Wenz!
+
+    * Added dutch and Portuguese language. Thanks to Paul de Bruyne and
+      Ranulfo Netto!
+
+    * Multi User: Fixed bug #977695 where simple editors couldn't re-edit
+      their entries (garvinhicking)
+
+    * Auto-Trackback from serendipity will now only fetch links smaller
+      than 150kb. Use socket connections instead of URL wrappers for
+      better control. (garvinhicking)
+
+    * Fixed HTTP requests from installer and htmlvalidator plugin to
+      send "\r\n" headers instead of only "\n". IIS-Servers didn't
+      respond to the latter (garvinhicking)
+
+    * Updated plugins to show default values in plugin configuration
+      immediately. New bag property 'default' introduced to Plugin API,
+      backwards compatible. (garvinhicking)
+
+    * Remaining XHTML 1.1 issues fixed:
+      - Use <div> instead of <span> for entry's contents.
+      - Removed obsolete javascript-function for comments
+      - Removed 'align' attribute from <div> tags, replaced with new
+        CSS class 'serendipity_align'
+      - Show the pingback-link element in the HEAD area. Embedded blogs
+        need to do that on their own.
+      - New plugin 'serendipity_event_xhtmlcleanup' to correct most
+        common XHTML errors (unclosed single tags, missing 'alt'
+        attribute, unescaped ampersands)
+        (garvinhicking)
+
+    * SQLite support now works. (garvinhicking)
+
+    * Fixed Bug #963248 - Calendar cannot calculate LastRow CSS class if
+      there are more than 4 rows (tomsommer)
+
+    * Use the right HTML code for trackback-link detection when using
+      markup plugins like Text_Wiki (garvinhicking)
+
+    * Display information when sending/searching for trackbacks
+      (garvinhicking)
+
+    * Add support for MySQLi (tadpole9)
+
+    * Alphabetically sort list of plugins (tadpole9)
+
+    * Tweaks to plugin configuration design (tomsommer)
+
+    * Added small comments to serendipity_functions.inc.php on how
+      to enable the spellchecker module of the WYSIWYG editor.
+      (Suggestion by Randall)
+
+    * Plugin API: Now each sidebar plugin item will get a CSS class
+      name added to the default "serendipitySideBarContent" one, which
+      is called 'sidebar_wrap_', 'sidebar_title_', 'sidebar_content_'
+      and then the original class name of the plugin appended. I.e.:
+      'sidebar_wrap_serendipity_html_nugget_plugin'. This allows special
+      customization of any individual sidebar item. (garvinhicking)
+
+    * Finally a OPML-based blogroll importing feature added to
+      the serendipity_plugin_remoterss plugin (Richard Harrison,
+      garvinhicking)
+
+    * Simple OPML 1.0 outline feed (Richard Harrison, garvinhicking)
+
+    * Fixed variable namespace problems in Textile Event plugin
+      (Reimer Behrends, garvinhicking)
+
+    * Implemented "visitor/hits" counter for karma-plugin. Hook into
+      Statistics plugin for showing additional data of karmavotes
+      (garvinhicking)
+
+    * Fixed receiving trackbacks of an intermediate s9y CVS release,
+      which submitted wrong variables. Allow logging of incoming
+      trackbacks to a file (for developers) (garvinhicking)
+
+    * Post to multiple categories and subcategories implemented.
+      (Evan Nemerson, garvinhicking)
+
+    * Threaded comments.
+      (Evan Nemerson)                       [DB Layout change - > 0.6.5]
+
+    * Minor https fixes, when https is used as links from commenting
+      users or in referring/exit links. Fix for RPC-ping function submitting
+      double http://http:// URLs. (garvinhicking)
+
+    * New sidebar plugin "eventlinks". Displays all links to the
+      currently viewed article (only on full article view).
+      (garvinhicking)
+
+    * Plugin API: The method 'generate_content' of a sidebar plugin
+      can now return false to instruct the plugin API to NOT display
+      the sidebar. Allows optional sidebar plugins to be only shown
+      on specific parameters (garvinhicking)
+
+    * Updated upgrade.sh script for better checks (Jez Hancock)
+
+    * Fixed javascript error when submitting comments with "remember me"
+      checkbox. (garvinhicking)
+
+    * XML-RPC methods updated to includer blogger.getRecentPosts and
+      blogger.getPost (Till Adam)
+
+    * Upgraded karma-plugin to allow logging (IP/User-Agent) of votes
+     (garvinhicking)
+
+    * User manager: New user right 'publish' which controls whether a
+      user is allowed to publish entries or only drafts.
+      (garvinhicking)                        [DB Layout change -> 0.6.4]
+
+    * Added new plugin "serendipity_event_karma": Allows karma voting
+      for each article with a flexible voting period. (garvinhicking)
+
+    * Added event hook-variable for displaying an article footer.
+      Enhanced Plugin API to allow passing a second array of data to the
+      hook_event() function (backwards-compatible). Added hook for
+      embedding CSS data from within a event plugin. (garvinhicking)
+
+    * When sending trackbacks, the excerpt will now be stripped of HTML
+      code BEFORE selecting the 255 characters to be sent.
+      (garvinhicking)
+
+    * Upgraded image manager to now also accept files (pdf, doc, ...)
+      and manage/upload to/sync/browse subdirectories. Improved SQL-
+      query for fetching list of images.
+      (garvinhicking)                        [DB Layout change -> 0.6.3]
+
+    * PHP pre-4.3.0 compatibility: Define PATH_SEPARATOR if not available
+      (garvinhicking)
+
+    * Upgraded PEAR::Text_Wiki and serendipity_event_textwiki plugin.
+      Configuration options for wiki rules, options to use wiki/freelinks.
+      (Tobias Schlitt)
+
+    * Made RSS-feed compatible to sites running with UTF8-charset.
+      (garvinhicking)
+
+    * Fixed wrong proportions when resizing small images (tomsommer)
+
+    * Fixed bug #940239 - Wrong message printed when deleting a category
+      without any entries (tomsommer)
+
+    * Bugfix for serendipity_plugin_remoterss: Wrong caching.
+      (Richard Thomas Harrison)
+
+    * Added new CSS class .serendipity_comments for the comments block
+      on full article view (garvinhicking)
+
+    * Added new CSS class .serendipity_admin_filters for the redesigned
+      editing entries interface (tomsommer, garvinhicking)
+
+    * Plugin API: Introduced function 'is_event_plugin' for easier
+      integration (Jonathan Arkell)
+
+    * New event hook 'entry_display' inside of serendipity_printEntries().
+      Can be used to force entries not being shown by setting the
+      $eventData['clean_page'] variable to 'true'. (Jonathan Arkell)
+
+    * Don't show "expand"/"toggle all" buttons if there is only one section
+      availiable (tomsommer)
+
+    * Redesigned admin interface for editing entries: Adjust items per
+      page, sort order, filter mode, combined EDIT+DELETE interface into
+      one. Introduced new css classes "serendipity_admin_list_item_even"
+      and "serendipity_admin_list_item_uneven" for displaying entries.
+      Can now search for entries in admin panel, can edit entries with
+      empty titles. (garvinhicking)
+
+    * Fixed image comment manager's "center" alignment mode and use
+      image width/height from the image manager to format the <img>-Tag,
+      with regards to Lewe.
+      (garvinhicking)
+
+    * Plugin 'serendipity_event_weblogping' now takes manually defined
+      pinging service as parameter. (garvinhicking)
+
+    * Modified plugin 'serendipity_event_trackexits': New config
+      directive to deflect any links from commenting users using a
+      HTTP redirect. This destroys common search engine ranking and
+      will not benefit comment spammers. Notice that it also disables
+      the common linking to non-spammer authors, so use with caution.
+      (garvinhicking)
+
+    * New plugin 'serendipity_plugin_remoterss' - Can display a foreign
+      remote feed. Results are cached for a custom period of time.
+      Contributed by Udo Gerhards. (garvinhicking)
+
+    * Fixed Bug #941922 - strftime %e does not work on windows platform
+      (tomsommer)
+
+    * Fix template chooser plugin to reflect new location of template
+      variable (tadpole9)
+
+    * Image upload now strips all characters not suggested for filename
+      use (garvinhicking)
+
+    * Categories can now have a fixed image which is embedded for
+      every article. Can be styled via CSS (.serendipity_entryIcon).
+      Integrated with s9y image manager.
+      (Evan Nemerson, garvinhicking)         [DB Layout change -> 0.6.2]
+
+    * Published entries from the future will only be displayed on the
+      frontend when not in the future. They will get automagically
+      displayed as soon as the publish time is effectively reached.
+      #RFE 939867 (garvinhicking)
+
+    * Exit/Referrer plugin can now limit the number of elements
+      (garvinhicking)
+
+    * Added possibility to embed a comment to an image when inserting
+      it via the s9y image manager (garvinhicking)
+
+    * Added czech language (ISO-8859-2 and Win-1250), translated by
+      Josef Klimosz.
+
+    * Added french language, translated by Renaud Lavigne.
+
+    * Fixed some issues on windows servers. Patch by Richard Thomas
+      Harrison
+
+    * Improvements for multi-user interface:
+       - Configuration is stored per-user (language, WYSIWYG-preference,
+         and possibly others)
+       - passwords/usernames/E-Mail adresses can be changed
+       - introduction of userlevels (admin, chief, editor)
+       - public/private categories
+       - plugins are stored per-user. Admin-created plugins cannot be
+         removed by chiefs/users, protected plugins (HTML nuggets) can
+         only be configured by the owner or admin users
+       - manage/create users
+       - entries are stored per-user and can only be changed by the
+         author or chief/admin users. Comments can only be toggled on/
+         off and removed by the author or chief/admin users.
+       - public/private images
+       (garvinhicking)                       [DB Layout change -> 0.6.1]
+
+    * Configuration is now language-dependant. (garvinhicking)
+
+Version 0.6-pl3 (June 20th, 2004)
+------------------------------------------------------------------------
+
+    * WYSIWYG-Editor: Links were prefixed with '/' wrongly (IE only).
+      Now all entered links will be put to an absolute URL consistently.
+      Fix always inserting extended body with empty '<br />'
+      (garvinhicking)
+
+    * Fix bug during installation, which can cause an endless loop
+      of connections (tomsommer)
+
+    * Removed german blogbot pinging service, it was shut down (nohn)
+
+    * Allow pinging of blogbot.dk (tomsommer)
+
+Version 0.6-pl2 (May 24th, 2004)
+------------------------------------------------------------------------
+
+    * Fixed security vulnerability on servers with Register_Globals On.
+      (garvinhicking, gschlossnagle, tomsommer)
+
+Version 0.6-pl1 (May 15th, 2004)
+------------------------------------------------------------------------
+
+    * Fixed trackbacks not associated to the right entry id (garvinhicking)
+
+    * Fixed typo in Creative Common Plugin (Jonathan Arkell)
+
+Version 0.6 (May 12th, 2004)
+------------------------------------------------------------------------
+
+    [changes since 0.6-rc2]
+    * Creative Commons plugin bugfix (wrong 'non-commercial' case)
+      (garvinhicking)
+
+    * Fixed wrong doctype header (garvinhicking)
+
+    * Fix %e date issue on windows systems. (garvinhicking, tomsommer)
+
+    * Fix serendipity_makefilename() to replace some more foreign
+      characters (garvinhicking)
+
+    * Shoutbox plugin bugfix (errors using '%' in shouts) (garvinhicking)
+
+    * Error with non-absolute image paths in RSS feed (garvinhicking)
+
+    * Fixed installer problems timeouting (garvinhicking)
+
+    * Removed possible error message about session_start for categories
+      admin page (garvinhicking)
+
+    * Fixed postgresql limit error when browsing pages (garvinhicking)
+
+    [changes before 0.6-rc2]
+    * Image upload now strips all characters not suggested for filename
+      use (garvinhicking)
+
+    * Language Charset Header are now used throughout s9y which make it
+      completely foreign-language compatible (garvinhicking)
+
+    * German translation fix (garvinhicking)
+
+    * Upgrader kills the current session for possible changes inside
+      session data on upgrade (garvinhicking)
+
+    * Fixed wrong comparison operator - bug reported by tom, where nl2br
+      plugin has "reversed" logic. (garvinhicking)
+
+    * Fixed textile plugin not enabled by default after adding it as a
+      plugin (garvinhicking)
+
+    * Comments plugin now correctly wordwraps (garvinhicking)
+
+    * Fixed wrong HTML links for WYSIWYG-editor in Internet Explorer
+      (garvinhicking)
+
+    * Fixed htmlentites acceptance for foreign language entry titles
+      (garvinhicking)
+
+    * Relaxed dependency on WIKI plugin, if the inclusion fails.
+      (garvinhicking)
+
+    * PostgreSQL SQL update files (jtate)
+
+    * Better detection of serendipityPath variable (garvinhicking)
+
+    * Adjustable WYSIWYG-language for foreign languages (garvinhicking)
+
+    * Fixed special characters for WYSIWYG-htmlarea.css file
+      (garvinhicking)
+
+    * Fixed WYSIWYG-editing error for HTML Nugget plugin (garvinhicking)
+
+    * newline fixes inside the files (cosmetic issues) (isotopp)
+
+    * Fixed losing commenting user details when previewing a comment
+     (garvinhicking)
+
+    * Added plugin for usage of CreativeCommons (creativecommons.org)
+      license for the blog's contents (Evan Nemerson)
+
+    * Templates with an "inactive.txt" or no "info.txt" inside their
+      directory are not selectable for s9y. Usable for "work in progress"
+      templates. (garvinhicking)
+
+    * Fixed $su link for users with no URL rewriting (garvinhicking)
+
+    * Fixed invalid XML for RDF trackback:ping (garvinhicking)
+
+    * Added plugin 'serendipity_event_statistics'. Hooks into the
+      admin entry-panel. (garvinhicking)
+
+    * Do some "common XHTML-mistakes" fixing for output of RSS feeds
+      (jalcorn)
+
+    * Updated WYSIWYG-Editor (htmlarea) to latest version. Integrated
+      s9y image manager in htmlarea window. Template file 'htmlarea.css'
+      can be used to adjust the editor's look to your template.
+      (garvinhicking)
+
+    * Templates: New CSS classes for better customization
+      - 'serendipity_entry_body_folded' for the entry body on the
+         weblog index page
+      - 'serendipity_entry_body_unfolded' for the entry body on
+         article page
+      - 'serendipity_entry_extended' for the extended body on article
+         page
+      (garvinhicking)
+
+    * Image upload: Can now specify alternate file name. Renamed
+      input field to not cause confusion with COOKIE-variable
+      (garvinhicking, isotopp)
+
+    * Image manager popup-window now resizable and with scrollbars
+      (garvinhicking)
+
+    * Serendipity can now be used in shared environments and act as a
+      library for VirtualHost'ed Blogs. See README. (garvinhicking)
+
+    * Fixed installer on hosts with non-standard (80) HTTP ports
+      (garvinhicking)
+
+    * Relaxed umask/chmod file and directory creation
+      (garvinhicking)
+
+    * Abstract archives/URL locations and regex-patterns in a central
+      place for easier maintenance (zem)
+
+    * Optimized db indizes on 'entries' (zem)
+
+    * Added shoutbox plugin (Matthias Lange, garvinhicking)
+
+    * Renamed "0.5.1" to "0.6" because of changes. Updated upgrade-
+      script (garvinhicking)
+
+    * Added home-link in templates for the header/subheader
+      (garvinhicking)
+
+    * Bugfix: With mod_rewrite redirection parameters to browse pages/
+      calendar was not working in non-embedded blogs
+      (garvinhicking)
+
+    * Added many new templates (several MoveableType imitations,
+      moz-modern) (sebastianbergmann, tomsommer, garvinhicking)
+
+    * Added backwards-compatible CSS ids to admin panel for better CSS
+      customization (garvinhicking)
+
+    * Moved smilies/xml buttons to template directory (img/) to be
+      customized per-template (garvinhicking)
+
+    * Added plugin to switch themes on the frontend (Evan Nemerson,
+      garvinhicking)
+
+    * Allow (multiple) dependencies for plugin API to allow pairing of
+      event/ sidebar plugins (garvinhicking)
+
+    * Added an upgrade-script to allow for easier upgrade of an existing
+      s9y installation (tomsommer)
+
+    * Redesigned the plugin manager (tomsommer)
+
+    * Added RFE #827945 - Allow for custom selection of calendar
+      beginning on week (tomsommer)
+
+    * Markup can be applied individually from a list of available
+      transformations: BBCode, Wiki, Textile, s9y markup, Emoticons,
+      nl2br. Multiple transformations are possible. (Colin Viebrock,
+      garvinhicking)
+
+    * Allow for each language to have its own charset (tomsommer)
+
+    * Now able to preview comments. (garvinhicking)
+
+    * Fixed bug that removed admin-cookie when you didn't check the
+      "remember comment" box on submitting comments to your own blog
+      (garvinhicking)
+
+    * Conditional GET logic for RSS feeds using HTTP caching methods.
+      See README for instructions, needs database schema update
+      [db_update-0.5-0.5.1.sql] (garvinhicking)
+
+    * Small XHTML-compliance fixes. (garvinhicking)
+
+    * Image manager: Allow sorting by date/file attributes, changing
+      sort order and choosing items displayed per page (garvinhicking)
+
+    * Fixed wrong link to entry when not using any rewrite rule
+      (tomsommer & AlfaTeK)
+
+    * Changed type of DB password to 'protected' to avoid it being
+      displayed as plaintext (tomsommer)
+
+    * Added danish language file (tomsommer & Jeppe Lund)
+
+    * Added notice when using a wrong username or password to gain
+      access to admin/author suites (tomsommer)
+
+    * Added date & time translation using strftime() and setlocale()
+      (tomsommer)
+
+    * HTML Validator event plugin. Can be used to validate your entry
+      upon preview (garvinhicking)
+
+    * Create example events: mailer, weblogping, contentrewrite,
+      eventwrapper (garvinhicking)
+
+    * Created event plugin API to hook on certain serendipity actions
+      (garvinhicking)
+
+    * Redesigned image manager. (tomsommer)
+
+    * Added image syncronization with database. IMPORTANT: Click on
+      "rebuild thumbs" to re-import your file-based images! (tomsommer)
+
+    * Now able to use CommentAPI to post entries to an RSS/Atom feed,
+      like from RSS Bandit (garvinhicking)
+
+    * Renamed "sebastian's weblog" theme to "blue" (sebastianbergmann)
+
+(Older NEWS see file NEWS_OLD)
diff --git a/docs/NEWS_OLD b/docs/NEWS_OLD
new file mode 100644 (file)
index 0000000..940907e
--- /dev/null
@@ -0,0 +1,523 @@
+# $Id$
+
+(The latest changes are documented in the NEWS-file)
+
+Version 0.5-pl1 (February, 14th 2004)
+------------------------------------------------------------------------
+
+    * Fixed XHTML-invalid anchor name (garvinhicking)
+
+    * Fixed installation problems [file_get_contents, htacces
+      copy&paste] for PHP < 4.3.0 (garvinhicking)
+
+    * Fix leaking draft entries by directly entering URL or using
+      quicksearch (garvinhicking)
+
+    * Fixed output of an empty external stylesheet on admin panel
+      (garvinhicking)
+
+    * Do not output comment-type ("NORMAL") on entry view
+      (garvinhicking)
+
+    * Fixed RSS 0.91 feed (was not printing any entries) (garvinhicking)
+
+Version 0.5 (February 6th, 2004)
+------------------------------------------------------------------------
+
+    * Fixed bug not showing comment or entry admin-tools on apparently
+      static pages (garvinhicking, tomsommer)
+
+    * RSS 1.0 feed supported (garvinhicking)
+
+    * Redirection after a comment has been added to prevent users
+      refreshing a page and double-submitting. (garvinhicking)
+
+    * Fixed RSS feed to only show comments when they are associated with
+      an entry_id (garvinhicking)
+
+    * Fixed page counter to count pages depending on the entries per
+      page, and not hardcoded 15 entries (garvinhicking)
+
+    * Atom 0.3 feed supported (with xml-stylesheet display)
+      (garvinhicking)
+
+    * Fixed format of mail to not send invalid mails (garvinhicking)
+
+    * Added Yahoo! blog ping (garvinhicking)
+
+    * Format trackbacks with link to the originating blog in comments
+      plugin (garvinhicking)
+
+    * The items of the comment-RSS feeds now have their GUID per
+      comment, not per entry. This allows feedreaders to properly
+      display updated to that feed. (garvinhicking)
+
+    * Do not output our own trackbacks inside the comments plugin. Use
+      anchors on the title-link to each comment. (garvinhicking)
+
+    * Moved languages to its own folder and added available languages as
+      a dropdown in the installer (tomsommer)
+
+    * Added spanish translation (Luis Cervantes)
+
+    * Added input box to admin entry panel where you can provide an
+      entry id to be directly edited. (garvinhicking)
+
+    * Edit an entry directly from your frontend (link beside trackbacks)
+      (garvinhicking)
+
+    * Made pinging blogs configurable/changeable per-entry. Added
+      "blogg.de" to RPC-ping list (garvinhicking)
+
+    * Fixed referrer and exit tracking on PostgreSQL (jtate)
+
+    * Added support for pinging weblogs.com, blo.gs, blogrolling.com and
+      technorati.com to announce new entries. (jimwinstead &
+      sebastianbergmann)
+
+    * Added mod_rewrite rules to .htaccess templates (garvinhicking)
+
+    * Changed installer to allow selection of desired rewrite rule, if
+      any. (tomsommer)
+
+    * Used patch from Craig O'Shannessy (modified and expanded to all
+      occurences) to allow usage of s9y without mod_rewrite/
+      ErrorDocument Handlers. (garvinhicking)
+
+    * Created a clickable label for the autologin, german translation
+      (garvinhicking)
+
+    * Allow Autologin, saving login information in a cookie (tomsommer
+      & jtate)
+
+    * HTML-Nugget can now be configured to preserve textformatting.
+      Default is 'apply textformatting' to stay backwards-compatible.
+      (garvinhicking)
+
+Version 0.4 (December 12th, 2003)
+------------------------------------------------------------------------
+
+    * Fixed bug #841972 - Remove reference to leer.png (tomsommer)
+
+    * RSS2.0-feed now contains wfw:comments link for per-entry comments.
+      Is interpreted by SharpReader i.e. (garvinhicking)
+
+    * XHTML1 compatibility fixes, missing <tr> from the calendar fixed.
+      Thanks to casper/jedijab79 from the forums (garvinhicking)
+
+    * Reworked Syndication plugin to allow future embedding of new RSS-
+      fields depending with individual content.
+
+      First example is the pubDate-field for the 'channel'-context, as
+      suggested by Justin Alcorn (garvinhicking)
+
+    * Added ability to close (and re-open) comments for certain entries
+      [needs DB update!] (garvinhicking)
+
+    * Fixes for comments-plugin (for 0 comments, dateformat) (tomsommer)
+
+    * Fixes for mt-XMLRPC API (gschlossnagle)
+
+    * Fixed embed-check for more strict type comparison (garvinhicking)
+
+    * Relative links inside the RSS-feed will get converted to absolute
+      ones (garvinhicking)
+
+    * Fixed trackbacks sending HTML tags and registering unslashed text
+      in excerpt (tomsommer)
+
+    * Fix bug #816499 - Serendipity should search for `convert` binary
+      in /usr/bin (tomsommer)
+
+    * Corrected path to entries printed in the comment plugin
+      (tomsommer)
+
+Version 0.3 (October 7th, 2003)
+------------------------------------------------------------------------
+
+    * Fixed evaluation of the 'embed' variable and added a small 'HowTo'
+      to the INSTALL file (garvinhicking)
+
+    * Fixed problem with escaping single quotes during installation
+      (tomsommer)
+
+    * Fixed problem with dual-trailing slashes in paths during
+      installation (tomsommer)
+
+    * Configuration/installation will now save the current s9y version
+      to the config file... Thereby allowing upgrades at a later point
+      (tomsommer)
+
+    * Include <slash:comments> in RSS-Feed. Shows amount of comments
+      available
+
+    * Differentiate subscription mails between regular comment and
+      trackback and adjust the mail's content corresponding to this
+      (garvinhicking)
+
+    * Added verbose output for DB creation on installation, PostgreSQL
+      DB-setup fixes (jtate)
+
+    * Made XHTML-compatibility fix to radio buttons of the installer
+      (garvinhicking)
+
+    * Allow for browseing of categories (on multiple pages) and have
+      per-category RSS-feed (garvinhicking & sbergmann)
+
+    * Fixed display of category in full article (garvinhicking)
+
+    * Expand all config categories in installer when s9y is first
+      installed (garvinhicking)
+
+    * Added select-dropdown configuration directive for the plugins
+      (garvinhicking)
+
+    * Prepended language defines with a '@' to suppress error messages
+      for fallback-language (garvinhicking)
+
+    * Fixed search results not displaying all content (garvinhicking)
+
+    * Fixed some undefined indexes/constants (garvinhicking)
+
+    * Support manual editing of the publish date on articles, can be
+      disallowed via $serendipity['allowDateManipulation'] (
+      garvinhicking)
+
+    * Added SQL upgrade files from 0.2 to 0.3 (troutgirl)
+
+    * Fixed a number of bugs with language detection and display during
+      installation (tomsommer)
+
+    * Fixed bug for fetching entries on a certain date. Now s9y dies
+      with an error message if MySQL errors occur (garvinhicking)
+
+    * Display link to trackbacks on single-article view (garvinhicking)
+
+    * Enable preview to include extended body (garvinhicking)
+
+    * Display author in previewed entry (tomsommer)
+
+    * Resize images based on original image proportions, not by fixed
+      width & height (tomsommer)
+
+    * Added option to preview entries (jhermanns)
+
+    * Added ability to save drafts of entries (jhermanns)
+
+    * Fixed some links not being formatted for exit-tracking, if the
+      link appeared more than once in an entry (tomsommer)
+
+    * Added radio-button and "spacer" configuration directives for the
+      plugins (garvinhicking)
+
+    * RSS-feeds and fields can now be customized within the plugin
+      configuration (garvinhicking
+
+    * Send X-Powered-By and X-Engine mail-headers with each mail
+      Serendipity sends, for easier debugging (tomsommer)
+
+    * Added Powered-By META tag to identify Serendipity Blogs even if
+      the admin has disabled the power-by plugin (tomsommer)
+
+    * Allow for descriptions of each configuration-category (tomsommer)
+
+    * Timestamps in comments are now shown in 24-hour format (tomsommer)
+
+    * Send X-Powered-By and X-Engine mail-headers with each mail
+      Serendipity sends, for easier debugging (tomsommer)
+
+    * Trackback pings where only accepted on a POST method. Moveable
+      Type uses GET, so we now accept both. (garvinhicking)
+
+    * Fixed issue where trackbackpings were only sent to links in
+      extended entry, if one existed, discarding the standard body
+      (garvinhicking)
+
+    * Fixed issue where two users sharing same username & password would
+      not be able to log in correctly, causing errors on the admin pages
+      (tomsommer)
+
+    * Fixed issue where installation would execute SQL instructions even
+      if a table already existed, creating "ghost"-authors (tomsommer)
+
+    * Allow unsubscription of already subscribed entries (tomsommer)
+
+    * Allow subscription of blog-visitors to receive comments for an
+      entry (tomsommer)
+
+    * Restrict calendar to only browse between the dates you have
+      comments available for (garvinhicking)
+
+    * Added external plugin to display the latest comments on a sidebar
+      (experimental, garvinhicking)
+
+    * Add Link to extended entry in RSS-feed, if existing
+      (garvinhicking)
+
+    * Unified and optimized admin login functionality (tomsommer)
+
+    * Fixed trackback functionality (tomsommer)
+
+    * Send User-Agent "Serendipity/v" when trackbacking (tomsommer)
+
+    * New default theme (tomsommer)
+
+    * New config section ('Appearance') and new option to block certain
+      hosts from being put into the referer table (garvinhicking)
+
+    * Installer/configuration categories can now be folded in DHTML-
+      compatible browsers (garvinhicking, tomsommer)
+
+    * Conserve linebreaks in RSS comments. (garvinhicking)
+
+    * Allow deleting categories (moving articles to another category)
+      (garvinhicking)
+
+    * Autodetect language on installation (garvinhicking)
+
+    * RSS feeds properly utf8encoded, added <webMaster>,
+      <managingEditor>,<comments>,<category> and <generator> tag
+      (garvinhicking)
+
+    * RSS feed now contains <image> link to pixel/rss_banner.png (if
+      existing), otherwise use pixel/s9y_banner_tiny.png (garvinhicking)
+
+    * External Plugin for hotword/acronym replacements, as well as any
+      other content-rewriting plugin (garvinhicking)
+
+    * Show updated values after submit, remove config entries when a
+      plugin is removed (garvinhicking)
+
+    * Added an RSS-feed for comments to entries only (garvinhicking)
+
+    * Fixed archives to not properly show entries from the first/last
+      day of a month (garvinhicking)
+
+    * Fixed the database by separating primary key from {AUTOINCREMENT}
+      (jtate)
+
+    * Rewrote installer (tomsommer)
+
+    * Added support for postgres (jtate)
+
+    * Fixed replacement of {TEMPLATE_PATH} to be relative (tomsommer)
+
+    * Major codestyle, HTML and XHTML cleanup (garvinhicking)
+
+    * Removed lots of static non-translated text (garvinhicking)
+
+    * Remove config entries when a plugin is removed (garvinhicking)
+
+    * After plugin update, show the new values for the plugin instead
+      the old ones (garvinhicking)
+
+    * After submitting a comment, redirect back to the actual previous
+      page (tomsommer)
+
+    * Fixed inclusion of templates vs. database-CSS (tomsommer)
+
+    * Fixed CSS not being showed during installation (tomsommer)
+
+    * Cleaned up the comment-form (tomsommer)
+
+    * Fixes a bug that the last day of a month was not taken into
+      account of the archives (garvinhicking)
+
+    * Allow embeding of serendipity in your custom homepage (wrapFile
+      directive - see http://blog.supergarv.de/ for example)
+      (garvinhicking)
+
+    * Added a new file serendipity_define.js.php which can be pre-
+      included to a Java-script to set some variables (garvinhicking)
+
+    * alt tag with '' instead of "" (garvinhicking)
+
+    * Added CVS ID tags to file-headers (garvinhicking)
+
+    * Added 'Force XHTML11' config option [not used yet] (garvinhicking)
+
+    * Made direct links to each comment, actually point to the right URI
+      (tomsommer)
+
+    * Inserted htmlentities() for comments output. Was vulnerable to
+      cross-site scripting attacks (garvinhicking)
+
+    * Fixed the "categories listing" so that if there were no
+      categories, it didn't display garbage (jtate)
+
+    * XML header should be utf-8, not ISO-8859-1.  This should fix the
+      encoding problems (sterling)
+
+    * Use ISO-8859-1 Charset to display pages (tomsommer)
+
+    * serendipity_date is now an H3, serendipity_title is now an H4
+      (troutgirl)
+
+    * Import stylesheets using @import (troutgirl)
+
+    * Made "H" in 'Posted by X in Y at H' a link, like in movabletype
+      (tomsommer)
+
+    * The line trailing each entry is now adapted to the "common format"
+      'Posted by xx in xx at xx | comments (n) | trackbacks (n)'
+      (jhermanns)
+
+    * Fixed minor problem with case in generated filenames (jhermanns)
+
+    * Removed all short tags '<?=' (jtate)
+
+    * Shortened the search field a little (jhermanns)
+
+    * Updated INSTALL instructions (troutgirl)
+
+    * Solved linebreak problem in "posted by..." via CSS (mueslix)
+
+    * Changed CSS class of "View Extended Entry" and "Posted by..." to
+      serendipity_entryFooter (mueslix)
+
+    * Default template is now set in the DB during installation
+      (jhermanns)
+
+    * Moved includes out of the templates (jhermanns)
+
+    * Fixed some problems with CSS not loading a first try (tomsommer)
+
+    * Saved lots of SQL queries when fetching config variables from the
+      database (tomsommer)
+
+    * Added new template system (tomsommer)
+
+    * Enhanced the insertion of emoticons (jhermanns)
+
+    * Removed static text and made some RSS regexps case-insensitive
+      (jhermanns)
+
+    * Added link to entry in emails, sent when comments or trackbacks
+      are made (tomsommer)
+
+    * Escape potential HTML characters in <title> in RSS feeds (Joyce P
+      & gschlossnagle)
+
+    * HTML is no longer allowed in comments, all HTML is formatted to
+      plain-text (tomsommer)
+
+    * Added direct link, to an entry, in the trackback dialog
+      (tomsommer)
+
+    * Top Referrers and Exits are now click-able (tomsommer)
+
+    * Admin area now uses the same styles as the rest of the blog
+      (tomsommer)
+
+    * New layout in the installer/configuration section (tomsommer)
+
+    * Fixed bug not showing the 6th row in the calendar, if the first
+      day of the month was a Sunday (tomsommer)
+
+    * Both emails and URLs, submitted with comments, are now shown.
+      E-mails are spam-secured, and URLs are checked for validity
+      (tomsommer)
+
+    * Avoid removing static files if pregenerate is not set (Joyce P &
+      tomsommer)
+
+    * Beautified the archives (jhermanns)
+
+    * RSS 2.0 is now default type of feed (sterling)
+
+    * Submitted mails in comments are now click-able (tomsommer)
+
+    * Added support for using *.gif in Image Manager, even if PHP is
+      compiled with read-only gif (tomsommer)
+
+    * Fixing bug #720632 (exit-links in html_nuggets plugin aren't
+      counted) (tomsommer)
+
+    * We now send different notification emails if the comment is a
+      trackback. (tomsommer)
+
+    * Stripped mail from HTML tags (tomsommer)
+
+    * When viewing a single entry, page <title> becomes entry's title.
+      (jhermanns)
+
+    * Links to entries are now called /archives/id_title_of_entry.html
+      (used to be /archives/e_id.html) (jhermanns)
+
+    * Time-ranges are now accessed like this: /archives/200203.html
+      (used to be /archives/d_200203.html) (jhermanns)
+
+    * Better non-WYSIWYG editor for Mozilla and IE users (tomsommer)
+
+    * Added validation to trackback-detection (tomsommer)
+
+    * You can now delete comments and trackbacks if you are logged in
+      (tomsommer)
+
+    * New logo in "Powered By" plugin (jhermanns & tomsommer)
+
+    * Sorting Comments & trackbacks by ID (tomsommer)
+
+    * We now remember comment details in cookies if requested, and
+      delete them if wanted (tomsommer)
+
+    * Added link back to main page (tomsommer)
+
+    * Added support for deletion in blogger and metaweblog APIs
+      (gschlossnagle)
+
+    * Added lots of error-handling to image manager (tomsommer)
+
+    * We now show trackbacks in a separate window, and count them
+      separately (jhermanns)
+
+    * Superuser-login initially sends you to authoring suit now
+      (jhermanns)
+
+    * Beautified mails (tomsommer)
+
+    * In Admin-module 'Edit entries' is now called 'Authoring Suite'
+      (tomsommer)
+
+    * Improved imagick thumbnail generation (jhermanns)
+
+    * You can now delete images in image manager (tomsommer)
+
+    * Fixed lots of missing translations (jhermanns)
+
+    * Added notice if search-string is smaller than 4 chars (tomsommer)
+
+    * Link to the archives is now /archive (jhermanns)
+
+    * Disallow empty comments (tomsommer)
+
+    * Fixed broken auto-trackback discovery (gschlossnagle)
+
+    * Fixed problem with echoing of .htaccess and paths, if installation
+      fails (tomsommer)
+
+    * Added CSS to installation-screen (tomsommer)
+
+    * Fixed bug when displaying individual days by clicking on the
+      calendar (tomsommer)
+
+    * Fixed bug #719016 - (entry-title does not escape correctly)
+      (tomsommer)
+
+    * Allow the showing of *complete* archived months (tomsommer)
+
+    * Fixed typo in serendipity_getCSS_avail() mysql-query (tomsommer)
+
+    * Prevent the Admin interface to be logged as referrer when using
+      the 'Back to Blog' link (bergmann)
+
+    * Added full language support - English, German (jhermanns)
+
+    * Keep track of which blog entry was linked from or referred to
+      (bergmann)
+
+    * Regenerate the .htaccess file, if installation fails (sterling &
+      muesli)
+
+Version 0.2 (April 4th, 2003)
+------------------------------------------------------------------------
diff --git a/docs/README b/docs/README
new file mode 100644 (file)
index 0000000..f72ad62
--- /dev/null
@@ -0,0 +1,121 @@
+########################################################################
+# README                                                               #
+########################################################################
+
+For the most up-to-date information on documentation, creating styles,
+plugins and so on, please visit our Wiki on http://www.s9y.org/!
+
+########################################################################
+# NOTES FOR CONDITIONAL GET IN RSS FEEDS                               #
+########################################################################
+
+Serendipity supports an HTTP-cache compatible way of only showing items
+in an RSS feed which where modified since the last request from a
+client.
+
+Typically, an RSS reader fetches your RSS feeds (15 items, per default).
+It then remembers the timestamp when those items where fetched. By the
+time your RSS reader updates the feed (typically after 1 hour)
+Serendipity will now only serve all new or modified items since the last
+time of refresh. If no entries where updated since then, serendipity
+will only serve the 304 Header (Not Modified) and saves a lot of
+bandwidth for both client and server on periodical updates.
+
+Technically an RSS reader catches the "Last-Modified" Header of the RSS
+output as well as a special "ETag"-Header. Both are set to the last
+modification time of your article base. On the next fetch, those
+received headers are sent as "IF_MODIFIED_SINCE" (= Last-Modified) and
+"IF_NONE_MATCH" (= ETag) Headers and will affect your rss feed. This
+saves a lot of bandwidth on both client and server side.
+
+Users who have been watching your feed and where not able to catch up
+the latest articles may miss some of them, because you usually only get
+15 items per feed. In case your reader provides the IF_MODIFIED_SINCE
+header the client can now catch all items (resp. a maximum of 50
+articles to prevent abuse).
+
+If you want to permanently disable that feature (whatever the reasons
+are) you can either set a "$_REQUEST['nocache'] = true" inside your
+rss.php file (first line) or append the '&nocache=true' request variable
+to your feed so that it looks like:
+http://example.host/serendipity/rss.php?version=2.0&nocache=true.
+
+Of course, the usual feed behaviour is not affected if none of the
+caching headers are provided. So if you use syndication methods to embed
+content from a blog inside an application, just tune your application to
+either send the 'nocache'-Variable to a Serendipity blog, or to not send
+the caching headers.
+
+The syndication plugin can be configured to append that variable to your
+feed URLs from your blog.
+
+########################################################################
+# USER MANAGEMENT                                                      #
+########################################################################
+
+New users can be created by inserting them to the 'authors' table.
+
+The field 'userlevel' is a special field describing which actions a
+user may have:
+
+- Userlevel 0:   Standard editor. Cannot apply many administrative tasks
+
+- Userlevel 1:   Chief editor. Can apply some administrative tasks (like
+                 title of the blog, ...
+
+- Userlevel 255: Admin. Can change everything.
+
+Userlevels are cumulative, thus a user with level '30' can do anything
+which users of a lower level can do. Currently only the levels mentioned
+above are used.
+
+Here is a short chart of what users can do:
+
+ACTION                                               |editor|chief|admin
+-----------------------------------------------------|------|-----|-----
+Manage private plugins                               |   -     +     +
+Manage global plugins                                |   -     -     +
+Manage order of plugins                              |   -     +     +
+Manage configuration of private plugins              |   -     +     +
+Manage configuration of all protected plugins        |   -     -     +
+Manage configuration of private protected plugins    |   +     +     +
+
+Manage all categories                                |   -     +     +
+Manage public categories                             |   +     +     +
+Manage private categories                            |   +     +     +
+Manage global configuration                          |   -     -     +
+
+Manage basic configuration                           |   -     +     +
+Manage private configuration                         |   +     +     +
+
+Manage templates                                     |   -     +     +
+
+Manage 'admin' users                                 |   -     -     +
+Manage 'chief' users                                 |   -     +     +
+Manage 'editor' users                                |   -     +     +
+
+Manage private entries                               |   +     +     +
+Manage others entries                                |   -     +     +
+Manage comments/trackbacks to private entries        |   +     +     +
+Manage comments/trackbacks to others entries         |   -     +     +
+
+View/Link/Upload all pictures                        |   +     +     +
+View/Link/Upload private pictures                    |   +     +     +
+View/Link/Upload public pictures                     |   +     +     +
+
+Edit all pictures                                    |   -     +     +
+Edit public pictures                                 |   +     +     +
+Edit private pictures                                |   +     +     +
+------------------------------------------------------------------------
+
+It is advised that in shared setups only the webmaster has an admin-
+access. The users should be given a chief-login, and them theirselves
+can distribute user logins.
+
+########################################################################
+
+Serendipity Weblog - http://s9y.org
+
+Licensed under the BSD License
+
+# $Id$
diff --git a/docs/UPGRADE b/docs/UPGRADE
new file mode 100644 (file)
index 0000000..632d8b0
--- /dev/null
@@ -0,0 +1,106 @@
+########################################################################
+# UPDATING                                                             #
+########################################################################
+
+The automatic update script should find and execute any necessary
+changes to the database layout made in different s9y versions beginning
+from 0.5. The upgrader will perform its automatic actions, as soon as you
+have copied the new s9y files over your old installation and access the start
+page of your blog.
+You can speed up the process of backing up your data and copying the files by
+using the supplied "upgrade.sh" script. Be sure to edit the file and change
+the variables to your needs.
+
+Usually all DB schema upgrades in previous versions will be used. So
+when you upgrade from 0.5 to 0.7 you will get upgrades from 0.5 -> 0.6
+and 0.6 -> 0.7.
+
+However, you are always advised to look at the corresponding
+SQL update file in sql/db_update* to see which changes were made.
+
+Please bear in mind that the automatic update script is executable by
+any user visiting your blog at the time of updating. You should modify
+your .htaccess file before upgradding and include this directives:
+
+---- .htaccess
+AuthType Basic
+AuthName "Authorisation: Serendipity Upgrade IN PROGRESS"
+AuthUserFile /absolute/path/to/your/s9y/.htpasswd
+require valid-user
+----
+
+Then create a file .htpasswd using a simple 'username:cryptpasswd'
+combination. Look at http://www.advancehost.com/htpasswd.html for an
+online generator for .htpasswd files.
+
+---- .htpasswd
+s9y:s9QXoc9dcFOT2
+----
+
+This would create a user "s9y" with password "s9y" with which you'd have
+to log into your blog.
+
+A proper backup of BOTH the file system and your database is suggested.
+Whenever you made changes to the distributed files (or to the files like
+xml.gif or the smilies) you have to make sure to copy them over the
+distributed files after updating.
+
+########################################################################
+# NOTES ON UPDATING FROM 0.5/0.5.1 -> 0.6                              #
+########################################################################
+
+* [The 0.5.1 release was renamed to 0.6, but there will still be DB
+  layout changes applied which are labelled as 0.5.1 - just ignore it.
+  It's only to easy migration to CVS-Snapshot users using the
+  0.5.1-version]
+
+* The structure of the content_rewrite plugin has changed. It will get
+  rewritten automatically by the update script, but if you had output on
+  your sidebar before, you need to do this:
+
+  - Add the 'serendipity_plugin_eventwrapper' to the sidebar plugins.
+  - Configure the 'serendipity_plugin_eventwrapper' and set it to use
+    your existing 'serendpity_event_contentrewrite' plugin.
+
+* Smilies and the XML-button where moved from the '/pixel' subdirectory
+  into per-template 'img/' subdirectories. If you modified the original
+  files, you need to copy your versions inside the
+  'templates/default/img/' directory.
+
+* A home-link has been added to the page headers. For that, two new CSS
+  classes have been introduced: .homelink1 (header), .homelink2 (
+  subheader). If you have a custom template, you need to adapt to those
+  changes. To make them look like your header previously has, insert
+  this in your style.css:
+
+  a.homelink1,
+  a.homelink1:hover,
+  a.homelink1:link,
+  a.homelink1:visited,
+  #serendipity_banner h1 {
+    ... your css-definitions ...
+    text-decoration: none;
+  }
+
+  a.homelink2,
+  a.homelink2:hover,
+  a.homelink2:link,
+  a.homelink2:visited,
+  #serendipity_banner h2 {
+    ... your css-definitions ...
+    text-decoration: none;
+  }
+
+########################################################################
+# NOTES ON UPDATING FROM 0.4 -> 0.5                                    #
+########################################################################
+
+No changes where made to the database scheme in this version.
+
+########################################################################
+# NOTES ON UPDATING FROM 0.3 -> 0.4                                    #
+########################################################################
+
+Run the file 'sql/db_update_0.3_0.4_mysql.sql' or
+'sql/db_update_0.3_0.4_pgsql.sql' to update your database. Apart from
+that, just copy over the new files of the distribution.
diff --git a/docs/upgrade.sh b/docs/upgrade.sh
new file mode 100644 (file)
index 0000000..a17aa81
--- /dev/null
@@ -0,0 +1,188 @@
+#!/bin/sh
+# File: serendipity_safe_upgrade.sh
+# Author: Jez Hancock
+#
+# Description:
+# This shell script performs a backup of the serendipity MySQL database and
+# files prior to upgrading from one version to another.
+echo "This bash file is out of date and does not respect the new directory structure, templates and compiled templates. It needs to be fixed, so if you don't know how to do bash scripting, please don't use this file. Use the web-based installer instead. If you DO want to make this file work, make sure you sure know how to do it. :-)";
+exit;
+
+########################################################################
+# Configuration options start
+########################################################################
+# Change this to the IP address from which you will be updgrading the blog from
+# in a browser.  This IP address will be used in a .htaccess file to restrict
+# access during the upgrade process:
+ip=192.168.0.1
+
+# Change this to the directory containing the current serendipity web files:
+blog_dir=/usr/local/www/htdocs/serendipity
+
+# Change this to the directory containing the new serendipity web files:
+# This should be the directory containing the cvs version of s9y or the s9y
+# tarball contents:
+import_dir=/home/username/serendipity
+
+# Change this to the directory you wish your weblog files and database to be
+# backed up to.  A subdirectory 's9y.YYYYMMDD' will be created under here into
+# which a tarball will be created containing the backed up webfiles and
+# database.  
+
+# For example if your backup_dir is set to '/home/user/backup', a directory
+# called '/home/user/backup/serendipity.20040406' will be created to contain
+# the backup tarball 'serendipity_backup.tar.gz' and the backup database file
+# 'serendipity_backup.sql'.
+# Note if the backup directory already contains a backup from the current day,
+# the script will exit without doing anything.
+backup_dir=/home/username/backup
+
+# Change this to match your database user/name.  Note you will be prompted for
+# your password on the commandline.
+db_name="serendipity"
+db_user="serendipity"
+
+########################################################################
+# Configuration options end
+# You should not need to modify anything below here!
+########################################################################
+
+ok() { 
+       echo "[OK]" ; echo ""
+}
+
+nl() {
+       echo ""
+}
+
+# the date ... ymd=20040331 etc ... used in backup
+ymd=`date "+%Y%m%d"`
+
+# Our backup directory:
+backup_dir=$backup_dir/serendipity.$ymd
+
+# if the backup dir exists already, exit gracefully:
+if [ -d $backup_dir ];then
+       echo "$backup_dir already exists - exiting."
+       exit
+fi
+
+# make backup dir:
+echo "Creating backup directory:"
+nl
+echo "$backup_dir"
+mkdir $backup_dir && ok || \
+       echo "Could not create $backup_dir - exiting."
+
+# backup current weblog to a tarball in the backup dir:
+echo "Backing up weblog files from:"
+nl
+echo "$blog_dir"
+nl
+echo "to the tarball:"
+nl
+echo "$backup_dir/serendipity_backup.tar.gz"
+set `echo "$blog_dir" | sed -e 's,\(.*\)/\(.*\),\1 \2,'`
+tar zcf $backup_dir/serendipity_backup.tar.gz -C $1 $2 && ok
+
+echo "Backing up database $db_name to file:"
+nl
+echo "$backup_dir/serendipity_backup.sql"
+nl
+echo -n "MySQL user $db_user - "
+mysqldump -u$db_user -p $db_name > $backup_dir/serendipity_backup.sql \
+       && ok
+
+# make backup dir safe:
+echo "Changing perms on $backup_dir to 700"
+chmod 700 $backup_dir && ok
+
+# move current blogdir out of way:
+echo "Moving:"
+nl
+echo "$blog_dir"
+nl
+echo "to:"
+nl
+echo "$blog_dir.$ymd"
+mv $blog_dir $blog_dir.$ymd && ok
+
+# now copy in the new files:
+echo "Copying files from:"
+nl
+echo "$import_dir"
+nl
+echo "to:"
+nl
+echo "$blog_dir"
+cp -R $import_dir $blog_dir && ok
+
+# check if a .htaccess file exists in old blog dir - if so copy over:
+if [ -f "$blog_dir.$ymd/.htaccess" ]; then
+       cp $blog_dir.$ymd/.htaccess $blog_dir
+fi
+
+# allow only our ip during upgrade - remember to remove these lines 
+# after you've finished updating!:
+echo "Adding .htaccess directives to restrict browser access to blog to $ip"
+echo "during upgrade process"
+exec >> $blog_dir/.htaccess
+echo "deny from all" 
+echo "allow from $ip"
+echo 'ErrorDocument 403 "Upgrading, please check back soon!!!'
+exec > /dev/tty
+ok
+
+# copy old uploads folder over:
+if [ -d $blog_dir.$ymd/uploads ];then
+       echo "Copying old uploads folder from:"
+       nl
+       echo "$blog_dir.$ymd/uploads"
+       nl
+       echo "to:"
+       nl
+       echo "$blog_dir/uploads"
+       cp -R $blog_dir.$ymd/uploads $blog_dir/uploads && ok
+fi
+
+
+# most importantly don't forget the local config file - this is checked
+# to see whether or not your current config setup needs upgrading or
+# not:
+echo "Copying $blog_dir.$ymd/serendipity_config_local.inc.php to $blog_dir"
+cp $blog_dir.$ymd/serendipity_config_local.inc.php $blog_dir \
+       && ok
+
+echo "########################################################################"
+echo "Important!"
+echo "########################################################################"
+echo "Backup is now complete.  Continue to upgrade your serendipity"
+echo "installation by browsing to it in a web browser - you will be prompted"
+echo "with instructions from there."
+nl
+echo "After completing the upgrade via a browser, remember to remove the lines"
+echo "starting:"
+nl
+echo "deny from all"
+echo "allow from $ip"
+echo "ErrorDocument 403 ..."
+nl
+echo "from the .htaccess file:"
+nl
+echo "$blog_dir/.htaccess"
+nl
+nl
+echo "A copy of the original serendipity web folder can be found here:"
+nl
+echo "$blog_dir.$ymd"
+nl
+echo "After confirming the upgrade was successful, you can safely remove"
+echo "this directory."
+
+# This is the place to do any custom backup stuff - for example I have various
+# directory structures that I copy from my blog base directory, a few custom
+# plugins I copy, etc etc.
+# ...
+
+# Uncomment/modify the following line if you run the server:
+#chown -R www:www $blog_dir && chmod 600 $blog_dir/serendipity_config_local.inc.php
diff --git a/exit.php b/exit.php
new file mode 100644 (file)
index 0000000..e6e7f3d
--- /dev/null
+++ b/exit.php
@@ -0,0 +1,34 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+include_once 'serendipity_config.inc.php';
+
+$url      = $serendipity['baseURL'];
+
+if (isset($_GET['url_id']) && !empty($_GET['url_id']) && isset($_GET['entry_id']) && !empty($_GET['entry_id'])) {
+
+    // See if the submitted link is in our database and should be tracked
+    $links = serendipity_db_query("SELECT link FROM {$serendipity['dbPrefix']}references WHERE id = " . (int)$_GET['url_id'] . " AND entry_id = " . (int)$_GET['entry_id'], true);
+
+    if (is_array($links) && isset($links['link'])) {
+        // URL is valid. Track it.
+        $url = str_replace('&amp;', '&', $links['link']);
+        serendipity_track_url('exits', $url, $_GET['entry_id']);
+    } elseif (isset($_GET['url']) && !empty($_GET['url'])) {
+        // URL is invalid. But a URL-location was sent, so we want to redirect the user kindly.
+        $url = str_replace('&amp;', '&', base64_decode($_GET['url']));
+    }
+
+} elseif (isset($_GET['url']) && !empty($_GET['url'])) {
+    // No entry-link ID was submitted. Possibly a spammer tried to mis-use the script to get into the top-list.
+    $url = str_replace('&amp;', '&', base64_decode($_GET['url']));
+}
+
+if (serendipity_isResponseClean($url)) {
+    header('HTTP/1.0 301 Moved Permanently');
+    header('Location: ' . $url);
+}
+exit;
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/htmlarea/ChangeLog b/htmlarea/ChangeLog
new file mode 100644 (file)
index 0000000..8e18577
--- /dev/null
@@ -0,0 +1,1185 @@
+2004-02-17  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/el.js, plugins/ContextMenu/lang/el.js, plugins/TableOperations/lang/el.js:
+       updated headers
+
+       * lang/no.js: updated (thanks havardw)
+
+2004-02-09  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/EnterParagraphs/enter-paragraphs.js:
+       Plugin that enables Mozilla to create a <p> instead of <br /> at ENTER.
+       Code contributed by Adam Wright.
+
+       * htmlarea.js: code to call onKeyPress for plugins that define it
+       code that keeps single spaces as &nbsp;
+       (thanks to hipikat @ IT forums (Adam Wright))
+
+       * ChangeLog:
+       ChangeLog is acutally automatically generated so there's no point keep it in CVS
+
+2004-02-08  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: fixed possible bug
+
+       * images/ed_align_center.gif, images/ed_align_justify.gif, images/ed_align_left.gif, images/ed_align_right.gif, images/ed_blank.gif, images/ed_charmap.gif, images/ed_color_bg.gif, images/ed_color_fg.gif, images/ed_copy.gif, images/ed_custom.gif, images/ed_cut.gif, images/ed_delete.gif, images/ed_format_bold.gif, images/ed_format_italic.gif, images/ed_format_strike.gif, images/ed_format_sub.gif, images/ed_format_sup.gif, images/ed_format_underline.gif, images/ed_help.gif, images/ed_hr.gif, images/ed_html.gif, images/ed_image.gif, images/ed_indent_less.gif, images/ed_indent_more.gif, images/ed_left_to_right.gif, images/ed_link.gif, images/ed_list_bullet.gif, images/ed_list_num.gif, images/ed_paste.gif, images/ed_redo.gif, images/ed_right_to_left.gif, images/ed_save.gif, images/ed_show_border.gif, images/ed_splitcel.gif, images/ed_undo.gif, images/fullscreen_maximize.gif, images/fullscreen_minimize.gif, images/insert_table.gif, images/ed_about.gif:
+       optimized images (thanks to Alexander Kandzior and OpenCMS group)
+
+2004-02-01  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * project-config.xml: release candidate 1
+
+       * release-notes.html: updated release notes
+
+       * examples/index.html, examples/makefile.xml:
+       added examples directory index
+
+       * release-notes.html: fix
+
+2004-01-31  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * makefile.xml: ensure correct file permissions
+
+       * plugins/SpellChecker/spell-check-logic.cgi, plugins/SpellChecker/spell-check-ui.html, plugins/SpellChecker/spell-check-ui.js:
+       spell checker now reports some document information (such as total number of
+       words, number of mispelled words, number of suggestions, etc)
+
+       * htmlarea.js: removed some custom attributes
+
+       * plugins/SpellChecker/spell-check-ui.js:
+       fixed bug (frame scroll in IE)
+
+2004-01-30  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * ChangeLog, release-notes.html: updated release notes, changelog
+
+       * plugins/SpellChecker/readme-tech.html:
+       updated text about Aspell Unicode support
+
+       * plugins/SpellChecker/spell-check-style.css: - lorem ipsum
+
+       * plugins/SpellChecker/spell-check-logic.cgi: - optimization
+
+       * plugins/SpellChecker/spell-check-logic.cgi:
+       - bugfix (removed <spellchecker> tags)
+
+       * plugins/SpellChecker/spell-check-logic.cgi:
+       bleah.. this version seems to be safer; no mo' HTML::Parser; DOM rulz.
+
+       * plugins/SpellChecker/spell-check-logic.cgi:
+       seems to be better now :-\  hell knows how perl & unicode works :-/
+
+       * plugins/SpellChecker/spell-check-logic.cgi, plugins/SpellChecker/spell-check-ui.js:
+       - big performance improvement (suggestion is now passed only once for each
+         mispelled word)
+       - bugs fixed (text already corrected in Unicode is now correctly decoded)
+
+       * plugins/SpellChecker/lang/en.js: - added word "Revert"
+
+       * plugins/SpellChecker/spell-checker.js: - lorem ipsum
+       - window is a bit higher now (450px)
+
+       * plugins/SpellChecker/spell-check-ui.js:
+       - fixed IE bug ("undefined is undefined or undefined", or something..)
+       - the highlighted word will now remain in view (window scrolls if necessary)
+       - functionality for "Revert"
+       - (tried to) eliminate some of the screen blinking in Mozilla
+       - select the current dictionary on first display
+
+       * plugins/SpellChecker/spell-check-ui.html:
+       added "Revert" button (reverts the current word to the mispelled original)
+
+       * plugins/SpellChecker/spell-check-style.css: *** empty log message ***
+
+       * plugins/SpellChecker/spell-check-logic.cgi:
+       - fixed (hopefully) unicode support (by the way, it seems that Aspell _does_
+         in fact know Unicode!!)
+       - remembers the selected dictionary in a cookie
+       - removed debug code
+
+2004-01-28  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * index.html: updated main page
+
+       * release-notes.html: updated release notes
+
+       * htmlarea.js: jscrunch-safe
+
+       * popups/about.html:
+       stop tab click event so that they don't get selected
+
+       * reference.html: some parts updated
+
+       * popups/about.html, examples/2-areas.html, examples/context-menu.html, examples/core.html, examples/css.html, examples/full-page.html, examples/fully-loaded.html, examples/spell-checker.html, examples/table-operations.html, plugins/SpellChecker/readme-tech.html, ChangeLog, dialog.js, htmlarea.js, index.html, license.txt, popupwin.js, release-notes.html:
+       ChangeLog updated; copyright years/info updated
+
+2004-01-27  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js:
+       Included an workaround for a strange IE problem: IE's getElementById can
+       return a field having the _name_ attribute equal to the searched ID, even if
+       it's not having any ID at all.  This can sometimes lead to taking a
+       different field (even if it's not a textarea) as the replacement field which
+       trashes the whole layout, look, feel, and functionality :-(  Need to say it
+       again, IE SUCKS.
+
+       Thanks goes to Mike Dick for the bug report and for the patch ;-)
+
+2004-01-18  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/SpellChecker/spell-check-ui.js:
+       fixed bug (thanks Bill Sechrist for report):
+       when you "ignore"-ed the last mispelled word, no changes were applied
+
+2004-01-16  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: border: 0px on body,html in pageStyle
+
+       * popups/about.html: report userAgent in plugins tab
+
+2004-01-12  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/ru.js: updated (thanks to Yulya Shtyryakova)
+
+2004-01-03  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/ContextMenu/lang/de.js: updated
+
+2004-01-02  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/ContextMenu/lang/de.js:
+       DE translation, thanks to Martin Jaggi
+
+2003-12-22  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/ee.js: Estonian translation
+
+2003-12-05  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: word cleaner: now it actually works ;-)
+
+       * plugins/ContextMenu/lang/el.js, lang/el.js, plugins/TableOperations/lang/el.js:
+       added Greek translation (thanks to Dimitris Glezos)
+
+       * htmlarea.js:
+       call an onGenerate handler, if found on the editor object
+
+       * popups/about.html, popups/popup.js: updated about box
+
+       * plugins/SpellChecker/spell-check-ui.js: *** empty log message ***
+
+       * plugins/ContextMenu/context-menu.js:
+       open the normal insert_link dialog on modify link
+
+2003-11-28  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.css: -moz-opacity got back
+
+       * popups/about.html: *** empty log message ***
+
+       * htmlarea.js: added Word cleaner code (thanks weeezl)
+       fixed the bug concerning the url of relative link/images
+
+2003-11-24  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/CSS/css.js:
+       allows updation of parent element's class (no span).  thanks goes to Michael (pepl @ IT forums)
+
+2003-11-22  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/ContextMenu/lang/nl.js, plugins/TableOperations/lang/nl.js:
+       translation thanks to mmcw /IT forums
+
+       * lang/nl.js: updated (thanks to mmcw /IT forums)
+
+2003-11-21  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * makefile.xml: added ChangeLog to project dist
+
+       * ChangeLog: Updated ChangeLog
+
+       * examples/context-menu.html, examples/fully-loaded.html, examples/pieng.png, index.html, plugins/ContextMenu/1.pl, plugins/ContextMenu/context-menu.js, plugins/ContextMenu/lang/en.js, plugins/ContextMenu/lang/makefile.xml, plugins/ContextMenu/makefile.xml, plugins/ContextMenu/menu.css, plugins/makefile.xml:
+       Added ContextMenu plugin (work sponsored by American Bible Society)
+
+2003-11-11  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/en.js, lang/ro.js: support for the link dialog
+
+       * plugins/FullPage/popups/docprop.html, popups/popup.js:
+       support for I18N of core dialogs, added function to select a value in a <select>, all dialogs close on ESC
+
+       * htmlarea.js:
+       support for insert link popup, minor bug-fix in Mozilla (catch exception)
+
+       * examples/fully-loaded.html:
+       workaround some IE problems (it appears that it's definitely better to wait half a second before generate()-ing the editor
+
+       * popups/link.html: allow ling target, title, edit link
+
+       * plugins/TableOperations/lang/no.js, lang/no.js:
+       Norwegian translation (thanks to Svein Sando)
+
+2003-11-10  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/es.js: fixed (thanks to Jorge)
+
+2003-11-07  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/about.html:
+       changed to Unix encoding; Credits page needs to be redesigned
+
+2003-11-06  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/lt.js: Lithuanian translation, thanks to Jaroslav Satkevic
+
+2003-11-05  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/he.js: Hebrew language definition (thanks to Liron Newman)
+
+2003-11-04  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/vn.js: updated vietnamese translation, thanks to Nguyen Dinh Nam
+
+2003-11-03  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/nl.js: updated (thanks to ephemeros)
+
+       * images/ed_left_to_right.gif, images/ed_right_to_left.gif:
+       text direction icons
+
+       * htmlarea.js, lang/en.js:
+       implemented text direction support (LTR or RTL)
+       workaround for a serious bug in IE (looses selection? bleah..)
+
+2003-10-31  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * examples/2-areas.cgi, examples/2-areas.html:
+       added sample that demonstrates how to create more editors in the same page and form
+
+       * htmlarea.js:
+       - increased the initial timeout after creating the iframe
+       - apply the timeout to IE too (actually we need a better idea that will only
+         create the editor _after_ all images are loaded; it seems that IE has
+         serious problems about it: if HTMLArea is initialized while loading images,
+         the rest of images will never be loaded and functionality will miss [IE only])
+       - custom undo queue disabled by default as it's still buggy
+
+2003-10-28  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/about.html: only loaded plugins
+
+       * plugins/CSS/css.js: copyright notices updated
+
+       * examples/core.html, examples/css.html, examples/full-page.html, examples/spell-checker.html, examples/table-operations.html:
+       updated to new style (load only htmlarea.js, define _editor_lang)
+
+       * dialog.js, htmlarea.js, popups/popup.js, popupwin.js:
+       copyright notices updated
+
+       * htmlarea.js: Text "Path: " back in the status bar
+
+       * popups/fullscreen.html:
+       correctly loads all scripts and registers plugins
+
+       * plugins/SpellChecker/spell-checker.js:
+       dropped config.editorURL in favor if _editor_url
+
+       * lang/en.js:
+       - IE sucks in full screen message (not yet used but might be if users
+         complain; I'm sick of IE, that sick that I will start charging 4 times more
+         for IE compatibility; I might get a ulcer because of it... no kiddin')
+
+       * htmlarea.js: - support _editor_lang
+       - loads all required files
+       - correct loading of plugins in full-screen mode
+       - config.editorURL was permanently dropped in favor of _editor_url
+
+       * popups/fullscreen.html, htmlarea.js:
+       config.editorURL removed, better handling of _editor_url
+
+2003-10-27  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/fullscreen.html:
+       bugfix: setting the BASE tag to the caller document's URL so we have no other
+       problems like editor or button images not loading.  Ha HA! >:-)
+
+       * plugins/CSS/css.js:
+       CSS plugin drop-down boxes appear on the second toolbar line by default
+
+       * popupwin.js: added position for the opening window
+
+       * lang/en.js: Insert Image ==> Insert/Modify Image
+
+       * htmlarea.js:
+       - Insert Image command patched to allow modification of a current image, if
+         it's selected
+       - Correct handling of selection for IE (test for ControlRange object) which
+         fixes a lot of bugs (IMG elements is now present in Path, no more table
+         props failures when an IMG or floating element is selected, etc.)
+
+2003-10-25  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/insert_image.html, htmlarea.js:
+       insert image can now modify the properties of an existing image
+
+       * htmlarea.js:
+       Cut/copy/paste -- show hint of where to find information to enable it in Gecko
+
+       * examples/core.html, examples/css.html, examples/full-page.html, examples/fully-loaded.html, examples/spell-checker.html, examples/table-operations.html:
+       removed @import url(../htmlarea.css) -- HTMLArea takes care of loading the CSS by itself how
+
+       * htmlarea.js:
+       bugfix: catched some exceptions that otherwise would have led Mozilla to crash
+       removed Path text from the statusbar
+
+       * htmlarea.js:
+       call onGenerate() for plugins that implement it; added loadStyle helper for easier stylesheet loading
+
+2003-10-24  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/FullPage/test.html, examples/css.html, examples/full-page.html:
+       removed unused code
+
+       * plugins/makefile.xml, plugins/CSS/lang/makefile.xml, plugins/CSS/makefile.xml:
+       CSS plugin added to distribution
+
+       * examples/custom.css, htmlarea.js: removed default styles
+
+       * popups/about.html:
+       fixed resizable window (Moz fix only, IE worked fine)
+
+       * plugins/CSS/css.js, plugins/CSS/lang/en.js, plugins/FullPage/full-page.js, examples/css.html, examples/custom.css, examples/fully-loaded.html:
+       added the CSS plugin (sponsored by www.miro.com.au)
+
+       * htmlarea.js:
+       bugfix: sometimes getHTML failed as root.tagName was undefined (for DocumentFragment nodes)
+
+       * project-config.xml: switching to CVS snapshot releases
+
+2003-10-23  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * examples/test.cgi: moved from ../
+
+       * test.cgi: moved to examples/
+
+       * makefile.xml: added examples subdir
+
+       * examples/makefile.xml: distribute example files
+
+       * examples/full-page.html: FullPage plugin demo
+
+       * examples/fully-loaded.html: added FullPage plugin
+
+       * index.html: added link to FullPage plugin demo
+
+       * examples/core.html, examples/fully-loaded.html, examples/spell-checker.html, examples/table-operations.html, popups/fullscreen.html, index.html:
+       fixed example files, added _editor_url (REQUIREDcvs -q update -d .), fixed problems with the full-screen editor
+
+       * examples/core.html, examples/fully-loaded.html, examples/spell-checker.html, examples/table-operations.html:
+       examples previously found in ../
+
+       * example-fully-loaded.html, example-spell-checker.html, example-table-operations.html, example.html:
+       moved to examples/
+
+       * popups/about.html: minor
+
+2003-10-18  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/si.js: Slovenian translation (thanks to Tomaz Kregar)
+
+2003-10-15  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/fr.js: updated French translation (thanks to Jonathan Ernst)
+
+2003-10-07  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/FullPage/full-page.js, plugins/FullPage/img/docprop.gif, plugins/FullPage/img/makefile.xml, plugins/FullPage/lang/en.js, plugins/FullPage/lang/makefile.xml, plugins/FullPage/lang/ro.js, plugins/FullPage/makefile.xml, plugins/FullPage/popups/docprop.html, plugins/FullPage/popups/makefile.xml, plugins/FullPage/test.html, plugins/makefile.xml:
+       FullPage plugin (allows configuring document properties)
+
+       * lang/en.js: fixed typo
+
+2003-10-06  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/about.html: Released=>Compiled
+
+       * popups/about.html: plugins credits only in plugins page
+
+       * popups/popup.js: added ability to translate popup dialogs
+
+       * htmlarea.css:
+       small fix for Mozilla/XHTML mode (buttons have now correct size)
+
+       * plugins/SpellChecker/spell-checker.js, plugins/TableOperations/table-operations.js:
+       fixed plugin images paths
+
+       * htmlarea.js: fixed doctype support
+       fixed support for full page editing (did I mention that IE sucks?)
+       avoids retrieving the contenteditable tag for body (IE only)
+       fixed _colorToRgb function (returns '' for empty or null color)
+       fixed editor/plugin images paths
+
+       * popups/popup.js:
+       allow __dlg_init to resize the window to cover a certain element
+
+       * popups/fullscreen.html: save the doctype too in the new editor
+
+       * popupwin.js:
+       fixed bug: now functions correctly for absolute _editor_url
+
+2003-10-05  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js:
+       full page editing facility; better interface for plugins popup dialogs
+
+2003-10-03  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: calls the plugin update function, if supplied
+
+       * popups/insert_image.html:
+       added nice image preview (submitted by rickroot on the interactivetools
+       forums, thanks!)
+
+2003-10-02  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: implemented proprietary undo/redo system (still buggy)
+
+       * popups/about.html: no bold on tabs
+
+2003-10-01  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: undo/redo are removed only if IE and config.statusBar
+
+       * popups/about.html: larger about box
+
+       * htmlarea.js: registers the plugin instance too (where was my head?)
+
+       * htmlarea.js: registers the plugin instance too
+
+       * htmlarea.js: fixed bug: opening the help window from the right place
+
+       * htmlarea.js:
+       don't use eval to register new plugins (allows better plugin arguments handling)
+
+2003-09-29  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * project-config.xml: beta+CVS
+
+       * popups/about.html: more "space" between tabs
+
+       * popups/about.html: the coolest about box ;-)
+
+       * dialog.js, popups/insert_image.html, popups/insert_table.html, popups/popup.js, popups/select_color.html:
+       fixed popups display under IE/Win
+
+       * plugins/SpellChecker/spell-checker.js, plugins/TableOperations/table-operations.js, htmlarea.js:
+       plugins will now register information about themselves
+
+       * popups/popup.js:
+       fixed an infantile mistake ;-) (popup windows are now centered correctly in
+       Moz too)
+
+2003-09-28  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * makefile.xml: mason args not needed
+
+       * popups/about.html: better about box ;-)
+
+       * project-config.xml: version beta+
+
+       * htmlarea.js: support passing parameters to plugins
+
+       * plugins/TableOperations/lang/en.js, plugins/TableOperations/lang/ro.js, popups/about.html, lang/en.js, lang/lv.js, lang/ro.js, plugins/SpellChecker/lang/en.js, plugins/SpellChecker/lang/ro.js, plugins/SpellChecker/readme-tech.html, plugins/SpellChecker/spell-check-logic.cgi, plugins/SpellChecker/spell-check-ui.html, plugins/SpellChecker/spell-check-ui.js, plugins/SpellChecker/spell-checker.js, plugins/TableOperations/table-operations.js, release-notes.html, example-spell-checker.html, htmlarea.js, index.html, make-release.pl, reference.html:
+       updated links
+
+2003-09-27  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/fullscreen.html: dont load null scripts ;-)
+
+       * htmlarea.js: undo/redo buttons removed for IE
+
+2003-09-25  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * images/ed_save.gif, images/ed_save.png: added save icon
+
+       * plugins/SpellChecker/lang/da.js: Danish translation available
+
+2003-09-19  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/SpellChecker/lang/de.js:
+       DE translation added (thanks to broxx.com)
+
+       * plugins/TableOperations/lang/da.js:
+       danish translation provided by Steen Sønderup
+
+       * plugins/TableOperations/lang/de.js:
+       DE translation provided by broxx.com
+
+       * lang/de.js: up-to-date by broxx.com
+
+2003-09-16  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/SpellChecker/lang/hu.js:
+       added Hungarian translation for the SpellChecker plugin
+
+2003-09-15  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/hu.js, plugins/TableOperations/lang/hu.js:
+       added Hungarian translation (thanks to Miklós Somogyi)
+
+2003-09-14  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/lv.js: added Latvian translation (thanks to Janis Klavins)
+
+2003-09-02  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js:
+       added helper function for removing stuff from the configuration toolbar
+
+       * popupwin.js:
+       fixed bug that prevented TableOperation popups to show up in IE
+
+2003-08-25  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: fixed status-bar behavior (can be hidden if desired)
+
+       * lang/es.js: fixed structure
+
+2003-08-21  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popupwin.js:
+       bugfix: use _editor_url to allow the editor to be some place else
+
+2003-08-14  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/SpellChecker/lang/it.js: utf-8-ified
+
+       * lang/it.js: Italian translation updated (thanks to Fabio Rotondo)
+
+       * plugins/TableOperations/lang/it.js:
+       Italian translation, thanks to Fabio Rotondo
+
+2003-08-13  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/SpellChecker/lang/it.js:
+       Added Italian translation (thanks to Fabio Rotondo)
+
+2003-08-12  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/SpellChecker/lang/cz.js, plugins/TableOperations/lang/cz.js, lang/cz.js:
+       CZ translation
+
+       * htmlarea.js:
+       fixed bug when more HTMLAreas were present in the same <FORM> -- get each
+       one's text onsubmit. (thanks Fabio Rotondo for report and test case)
+
+2003-08-11  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * index.html: added brief installation notes
+
+2003-08-10  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * index.html, makefile.xml, release-notes.html:
+       added version/release to index.html
+
+       * lang/da.js, lang/de.js, lang/en.js, lang/es.js, lang/fi.js, lang/fr.js, lang/gb.js, lang/it.js, lang/ja-euc.js, lang/ja-jis.js, lang/ja-sjis.js, lang/ja-utf8.js, lang/makefile.xml, lang/nb.js, lang/nl.js, lang/pl.js, lang/pt_br.js, lang/ro.js, lang/ru.js, lang/se.js, lang/vn.js, plugins/SpellChecker/img/makefile.xml, plugins/SpellChecker/img/spell-check.gif, plugins/SpellChecker/lang/en.js, plugins/SpellChecker/lang/makefile.xml, plugins/SpellChecker/lang/ro.js, plugins/SpellChecker/makefile.xml, plugins/SpellChecker/readme-tech.html, plugins/SpellChecker/spell-check-logic.cgi, plugins/SpellChecker/spell-check-style.css, plugins/SpellChecker/spell-check-ui.html, plugins/SpellChecker/spell-check-ui.js, plugins/SpellChecker/spell-checker.js, plugins/TableOperations/img/cell-delete.gif, plugins/TableOperations/img/cell-insert-after.gif, plugins/TableOperations/img/cell-insert-before.gif, plugins/TableOperations/img/cell-merge.gif, plugins/TableOperations/img/cell-prop.gif, plugins/TableOperations/img/cell-split.gif, plugins/TableOperations/img/col-delete.gif, plugins/TableOperations/img/col-insert-after.gif, plugins/TableOperations/img/col-insert-before.gif, plugins/TableOperations/img/col-split.gif, plugins/TableOperations/img/makefile.xml, plugins/TableOperations/img/row-delete.gif, plugins/TableOperations/img/row-insert-above.gif, plugins/TableOperations/img/row-insert-under.gif, plugins/TableOperations/img/row-prop.gif, plugins/TableOperations/img/row-split.gif, plugins/TableOperations/img/table-prop.gif, plugins/TableOperations/lang/en.js, plugins/TableOperations/lang/fi.js, plugins/TableOperations/lang/makefile.xml, plugins/TableOperations/lang/ro.js, plugins/TableOperations/makefile.xml, plugins/TableOperations/table-operations.js, plugins/makefile.xml, popups/about.html, popups/fullscreen.html, popups/makefile.xml, example-fully-loaded.html, example-spell-checker.html, example-table-operations.html, example.html, htmlarea-lang-b5.js, htmlarea-lang-da.js, htmlarea-lang-de.js, htmlarea-lang-en.js, htmlarea-lang-es.js, htmlarea-lang-fr.js, htmlarea-lang-gb.js, htmlarea-lang-it.js, htmlarea-lang-ja-euc.js, htmlarea-lang-ja-jis.js, htmlarea-lang-ja-sjis.js, htmlarea-lang-ja-utf8.js, htmlarea-lang-nb.js, htmlarea-lang-nl.js, htmlarea-lang-pl.js, htmlarea-lang-pt_br.js, htmlarea-lang-ru.js, htmlarea-lang-se.js, htmlarea-lang-vn.js, htmlarea.css, htmlarea.js, images/ed_paste.gif, images/ed_show_border.gif, images/ed_splitcel.gif, images/makefile.xml, index.html, lang/b5.js, make-release.pl, makefile.xml, popupdiv.js, popupwin.js, project-config.xml, readme.html, reference.html, release-notes.html:
+       Merged from table-devel branch.  Development back on main trunk.
+
+       * plugins/SpellChecker/readme-tech.html: added I18N file to description
+
+       * plugins/SpellChecker/spell-check-ui.html, plugins/SpellChecker/spell-check-ui.js:
+       internationalization now supported
+
+       * plugins/TableOperations/table-operations.js:
+       fixed bug icons inside dialogs
+
+       * popups/about.html:
+       nicer dialog, + automatic version/release management
+
+       * htmlarea.js, lang/en.js, plugins/SpellChecker/lang/en.js, plugins/TableOperations/lang/en.js:
+       I18N for some messages that were left out, small IMG bug fixed, added loadPlugin static function
+
+       * example-fully-loaded.html, example-spell-checker.html, example-table-operations.html, example.html:
+       UTF-8 charset by default
+
+       * lang/ro.js, plugins/SpellChecker/lang/ro.js, plugins/TableOperations/lang/ro.js:
+       New file.
+
+       * lang/ro.js, plugins/SpellChecker/lang/ro.js, plugins/TableOperations/lang/ro.js:
+       Romanian translation (thanks to My Self)
+
+       * release-notes.html: New file.
+
+       * release-notes.html: release notes
+
+       * lang/makefile.xml, plugins/SpellChecker/img/makefile.xml, plugins/SpellChecker/lang/makefile.xml, plugins/SpellChecker/makefile.xml, plugins/TableOperations/img/makefile.xml, plugins/TableOperations/lang/makefile.xml, plugins/TableOperations/makefile.xml, plugins/makefile.xml, popups/makefile.xml:
+       New file.
+
+       * lang/makefile.xml, plugins/SpellChecker/img/makefile.xml, plugins/SpellChecker/lang/makefile.xml, plugins/SpellChecker/makefile.xml, plugins/TableOperations/img/makefile.xml, plugins/TableOperations/lang/makefile.xml, plugins/TableOperations/makefile.xml, plugins/makefile.xml, popups/makefile.xml:
+       automatic release management (a la makefile)
+
+       * images/makefile.xml, make-release.pl, makefile.xml, project-config.xml:
+       New file.
+
+       * images/makefile.xml, make-release.pl, makefile.xml, project-config.xml:
+       automatic release management (a la makefile)
+
+2003-08-03  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * lang/fi.js, plugins/TableOperations/lang/fi.js:
+       Finnish translation added (thanks bestis)
+
+       * lang/fi.js, plugins/TableOperations/lang/fi.js, index.html: New file.
+
+       * index.html: short description, copyright, links
+
+       * reference.html:
+       LAST VERSION OF THIS DOCUMENT.  IT WILL BE SOON DELETED.
+
+       * lang/b5.js, lang/da.js, lang/de.js, lang/en.js, lang/es.js, lang/fr.js, lang/gb.js, lang/it.js, lang/ja-euc.js, lang/ja-jis.js, lang/ja-sjis.js, lang/ja-utf8.js, lang/nb.js, lang/nl.js, lang/pl.js, lang/pt_br.js, lang/ru.js, lang/se.js, lang/vn.js:
+       added lang in I18N, so that we can load automatically plugin's lang file
+
+       * example-fully-loaded.html: New file.
+
+       * example-fully-loaded.html: loads all plugins
+
+       * example-spell-checker.html: removed TableOperations from this example
+
+2003-08-01  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * readme.html: documentation for 2.x is heavily outdated... removed.
+
+       * example-spell-checker.html, plugins/SpellChecker/img/spell-check.gif, plugins/SpellChecker/lang/en.js, plugins/SpellChecker/readme-tech.html, plugins/SpellChecker/spell-check-logic.cgi, plugins/SpellChecker/spell-check-style.css, plugins/SpellChecker/spell-check-ui.html, plugins/SpellChecker/spell-check-ui.js, plugins/SpellChecker/spell-checker.js:
+       New file.
+
+       * example-spell-checker.html, plugins/SpellChecker/img/spell-check.gif, plugins/SpellChecker/lang/en.js, plugins/SpellChecker/readme-tech.html, plugins/SpellChecker/spell-check-logic.cgi, plugins/SpellChecker/spell-check-style.css, plugins/SpellChecker/spell-check-ui.html, plugins/SpellChecker/spell-check-ui.js, plugins/SpellChecker/spell-checker.js:
+       added the SpellChecker plugin (sponsored by www.AmericanBible.org)
+
+       * example.html, example-table-operations.html:
+       * moved lang files to separate directory
+
+       * htmlarea-lang-en.js, htmlarea-lang-es.js, htmlarea-lang-fr.js, htmlarea-lang-gb.js, htmlarea-lang-it.js, htmlarea-lang-ja-euc.js, htmlarea-lang-ja-jis.js, htmlarea-lang-ja-sjis.js, htmlarea-lang-ja-utf8.js, htmlarea-lang-nb.js, htmlarea-lang-nl.js, htmlarea-lang-pl.js, htmlarea-lang-pt_br.js, htmlarea-lang-ru.js, htmlarea-lang-se.js, htmlarea-lang-vn.js, htmlarea-lang-b5.js, htmlarea-lang-da.js, htmlarea-lang-de.js:
+       moved to lang/
+
+       * lang/b5.js, lang/da.js, lang/de.js, lang/en.js, lang/es.js, lang/fr.js, lang/gb.js, lang/it.js, lang/ja-euc.js, lang/ja-jis.js, lang/ja-sjis.js, lang/ja-utf8.js, lang/nb.js, lang/nl.js, lang/pl.js, lang/pt_br.js, lang/ru.js, lang/se.js, lang/vn.js:
+       New file.
+
+       * lang/b5.js, lang/da.js, lang/de.js, lang/en.js, lang/es.js, lang/fr.js, lang/gb.js, lang/it.js, lang/ja-euc.js, lang/ja-jis.js, lang/ja-sjis.js, lang/ja-utf8.js, lang/nb.js, lang/nl.js, lang/pl.js, lang/pt_br.js, lang/ru.js, lang/se.js, lang/vn.js:
+       lang files separated
+
+       * htmlarea.js, htmlarea.css:
+       * added registerDropdown -- for adding custom drop-down boxes to the toolbar
+       * registerDropdown and registerButton verify for existing ID-s first (alert
+         if that's the case)
+       * support for text labels in the toolbar
+       * fixed some bugs in insertHTML (Mozilla specific)
+
+2003-07-16  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * example-table-operations.html:
+       TableOperations lang file moved to 'lang' directory
+
+       * plugins/TableOperations/lang/en.js: New file.
+
+       * plugins/TableOperations/lang/en.js, plugins/TableOperations/table-operations-lang-en.js:
+       lang files in dedicated directory [lang]
+
+       * htmlarea.js: [IE] no status bar on fullscreen editor
+
+2003-07-15  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js:
+       [IE] fixed annoying bug: displacement of the separators within the toolbar;
+            IE assigns a random image width/height, if not explicitely stated ;-)
+
+2003-07-13  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/fullscreen.html: moved plugin images to ../plugins
+       fixed bug that only applied to Moz-1.4 or newer Geckos (script.src is always
+       an absolute URL)
+
+       * htmlarea.js: restructuration concerning images
+
+       * plugins/TableOperations/table-operations.js:
+       images moved to the plugin directory
+
+       * plugins/TableOperations/img/cell-delete.gif, plugins/TableOperations/img/cell-insert-after.gif, plugins/TableOperations/img/cell-insert-before.gif, plugins/TableOperations/img/cell-merge.gif, plugins/TableOperations/img/cell-prop.gif, plugins/TableOperations/img/cell-split.gif, plugins/TableOperations/img/col-delete.gif, plugins/TableOperations/img/col-insert-after.gif, plugins/TableOperations/img/col-insert-before.gif, plugins/TableOperations/img/col-split.gif, plugins/TableOperations/img/row-delete.gif, plugins/TableOperations/img/row-insert-above.gif, plugins/TableOperations/img/row-insert-under.gif, plugins/TableOperations/img/row-prop.gif, plugins/TableOperations/img/row-split.gif, plugins/TableOperations/img/table-prop.gif:
+       New file.
+
+       * plugins/TableOperations/img/cell-delete.gif, plugins/TableOperations/img/cell-insert-after.gif, plugins/TableOperations/img/cell-insert-before.gif, plugins/TableOperations/img/cell-merge.gif, plugins/TableOperations/img/cell-prop.gif, plugins/TableOperations/img/cell-split.gif, plugins/TableOperations/img/col-delete.gif, plugins/TableOperations/img/col-insert-after.gif, plugins/TableOperations/img/col-insert-before.gif, plugins/TableOperations/img/col-split.gif, plugins/TableOperations/img/row-delete.gif, plugins/TableOperations/img/row-insert-above.gif, plugins/TableOperations/img/row-insert-under.gif, plugins/TableOperations/img/row-prop.gif, plugins/TableOperations/img/row-split.gif, plugins/TableOperations/img/table-prop.gif:
+       moved TableOperations icons here
+
+       * images/ed_splitcell.gif:
+       moved to ../plugins/TableOperations/img/cell-split.gif
+
+       * images/ed_mergecels.gif:
+       moved to ../plugins/TableOperations/img/cell-merge.gif
+
+       * images/ed_delcel.gif:
+       moved to ../plugins/TableOperations/img/cell-delete.gif
+
+       * images/ed_inscelrgt.gif:
+       moved to ../plugins/TableOperations/img/cell-insert-after.gif
+
+       * images/ed_inscellft.gif:
+       moved to ../plugins/TableOperations/img/cell-insert-before.gif
+
+       * images/ed_cellprop.gif:
+       moved to ../plugins/TableOperations/img/cell-prop.gif
+
+       * images/ed_splitcol.gif:
+       moved to ../plugins/TableOperations/img/col-split.gif
+
+       * images/ed_delcol.gif:
+       moved to ../plugins/TableOperations/img/col-delete.gif
+
+       * images/ed_insright.gif:
+       moved to ../plugins/TableOperations/img/col-insert-after.gif
+
+       * images/ed_insleft.gif:
+       moved to ../plugins/TableOperations/img/col-insert-before.gif
+
+       * images/ed_splitrow.gif:
+       moved to ../plugins/TableOperations/img/row-split.gif
+
+       * images/ed_delrow.gif:
+       moved to ../plugins/TableOperations/img/row-delete.gif
+
+       * images/ed_insunder.gif:
+       moved to ../plugins/TableOperations/img/row-insert-under.gif
+
+       * images/ed_insabove.gif:
+       moved to ../plugins/TableOperations/img/row-insert-above.gif
+
+       * images/ed_rowprop.gif:
+       moved to ../plugins/TableOperations/img/row-prop.gif
+
+       * images/ed_tableprop.gif:
+       moved to ../plugins/TableOperations/img/table-prop.gif
+
+2003-06-11  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations.js:
+       revamped code for table "border", "frame" and "rules" attributes
+
+2003-06-08  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations.js:
+       added focusEditor() calls (editor lost focus in IE after some operations)
+
+       * plugins/TableOperations/table-operations.js:
+       fixed 2 bugs (correct title in row/cell properties dialog, clear cell
+       contents when inserting new row in Internet Explorer)
+
+2003-06-02  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/fullscreen.html:
+       [IE] fixed problem that caused toolbar buttons to be unusable
+
+       * popups/fullscreen.html:
+       [IE] fixed bug when copying the click handler.  Editor is now functional in
+       fullscreen.
+
+       * plugins/TableOperations/table-operations-lang-en.js, plugins/TableOperations/table-operations.js:
+       1. Removed code that selects the table/row/cell before displaying the
+       dialog.
+
+       2. Focus back the table after closing the dialog box (was causing some
+       problems in IE).
+
+       3. Implemented merge cells for IE (user will be prompted for number of
+       cols/rows to span the current cell).
+
+       * htmlarea.js:
+       1. Display an alert if cut/copy/paste is not supported, when one of the buttons
+       is clicked.  The button will also be removed from the toolbar.
+
+       2. Fixed bug when clicking on some table/image margin in IE.
+
+2003-05-31  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations.js:
+       [IE5.5] IE5.5 doesn't support createDocumentFragment; workarounded.
+
+       * htmlarea.css: Better looking dialogs
+
+       * htmlarea.js: Fixed IE5.5 compatibility issues.
+
+       * htmlarea.js: Now IE5.5 compatible.
+
+2003-05-27  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: workaround for a horrible bug (thanks Dror!)
+
+       * htmlarea.js: oops... ;-)
+
+       * htmlarea.js: workaround for a horrible bug (thanks Dror!)
+
+2003-05-18  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations-lang-en.js:
+       added some comment notes for translators
+
+       * plugins/TableOperations/table-operations.js: bugfix:
+         - border-style changes are updated correctly in Mozilla
+         - do not show Float for td, th, tr elements
+       feature (eye-candy)
+         - added small icons on each dialog
+
+       * popupwin.js: added baseURL to the object (useful in dialogs)
+
+       * plugins/TableOperations/table-operations-lang-en.js, plugins/TableOperations/table-operations.js:
+       modified dialogs (more css-friendly, trying to avoid deprecated HTML
+       attributes).  fixed some bugs.
+
+       * htmlarea.js:
+       added oncontextmenu for status-bar elements (displays inline style)
+       fixed problem with textindicator (background-color in Mozilla)
+
+       * htmlarea.css: tables in dialogs have border-collapse: collapse
+
+       * example-table-operations.html:
+       modified example HTML (more colorful, blah blah)
+
+2003-05-14  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations.js:
+       (trying to) force redraw after table/row/cell properties dialogs close with
+       OK
+
+2003-05-13  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations-lang-en.js, plugins/TableOperations/table-operations.js, popupwin.js:
+       some fixes for IE; implemented border-collapse style properties (tables only)
+
+2003-05-12  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations-lang-en.js, plugins/TableOperations/table-operations.js, example-table-operations.html, htmlarea.css, popupwin.js:
+       improvements of the color selector button, added row properties and cell properties dialogs, fixes, etc.
+
+2003-05-08  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations.js:
+       border properties now functional
+
+       * plugins/TableOperations/table-operations-lang-en.js:
+       CSS Style -> Style [CSS]
+
+       * popupwin.js: smaller padding.. looks better.
+
+       * htmlarea.css, plugins/TableOperations/table-operations-lang-en.js, plugins/TableOperations/table-operations.js:
+       added functionality (style properties, changed BUTTON to DIV for color
+       selection widget, added border properties [not completed yed])
+
+2003-05-07  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations.js:
+       fixed small bug; added some comments
+
+2003-05-06  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js:
+       fixed small bug (user might close the select_color dialog by pressing "X"
+       button, case in which the selection is now ignored)
+
+       * htmlarea.js: debug code can sometimes be annoying -- commented out.
+
+       * htmlarea.js: bug #730593 fixed
+
+       * plugins/TableOperations/table-operations-lang-en.js, plugins/TableOperations/table-operations.js:
+       added first dialog (table properties) + other useful stuff like generic style properties that should eventually make it into a separated plugin
+
+       * popupdiv.js, popupwin.js: New file.
+
+       * popupdiv.js, popupwin.js:
+       files for handling some popup dialogs generated from JS code
+
+       * example-table-operations.html: credit modified
+
+2003-05-05  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea-lang-en.js:
+       I18N for 2 very common text-s ("ok" and "cancel")
+
+       * htmlarea.css: style for new popups
+
+       * htmlarea.js:
+       added new variable (_mdoc which keeps a reference to the document that
+       contains the HTMLArea.  it's sometimes useful (mainly in popups))
+
+2003-04-25  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations.js:
+       modified credit (bloki.com instead of zapatec.com)
+
+2003-04-24  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * plugins/TableOperations/table-operations.js:
+       fixed code to work if editor used in fullscreen
+
+       * popups/fullscreen.html:
+       added nice code that automagically loads all scripts in the parent page (opener)
+
+       * plugins/TableOperations/table-operations.js:
+       - fixes for IE (IE doesn't need the BR inside empty TD-s)
+       - when called in fullscreen mode it doesn't update the toolbar
+
+       * htmlarea.js:
+       small fix for IE (getAllAncestors sometimes returned the HTML and Document element too)
+
+2003-04-23  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/fullscreen.html: small bug fixed
+
+       * htmlarea.css:
+       changed bg for disabled buttons (this is for debug, I repeat ;-)
+
+       * htmlarea.js: - API support for external plugins
+       - support for context-enabled buttons
+       - performance improvement: cancelling updateToolbar requests if made in less
+         than 50ms -- in other words, only honor the last one
+
+       * example.html: test for context-enabled buttons
+
+       * plugins/TableOperations/table-operations.js: New file.
+
+       * plugins/TableOperations/table-operations.js:
+       added TableOperations plugin
+       several new toolbar buttons + fixes to some existent ones
+       file that demonstrate usage of the TableOperations plugin
+
+       * plugins/TableOperations/table-operations-lang-en.js: New file.
+
+       * plugins/TableOperations/table-operations-lang-en.js:
+       added TableOperations plugin
+       several new toolbar buttons + fixes to some existent ones
+       file that demonstrate usage of the TableOperations plugin
+
+       * images/ed_splitcell.gif, images/ed_splitcol.gif: New file.
+
+       * images/ed_splitcell.gif, images/ed_splitcol.gif, images/ed_splitrow.gif, images/ed_paste.gif, images/ed_insunder.gif, images/ed_mergecels.gif, images/ed_inscellft.gif, images/ed_inscelrgt.gif, images/ed_insleft.gif, images/ed_insright.gif, images/ed_insabove.gif, images/ed_delcol.gif, images/ed_delrow.gif:
+       added TableOperations plugin
+       several new toolbar buttons + fixes to some existent ones
+       file that demonstrate usage of the TableOperations plugin
+
+       * example-table-operations.html: New file.
+
+       * example-table-operations.html, images/ed_delcel.gif:
+       added TableOperations plugin
+       several new toolbar buttons + fixes to some existent ones
+       file that demonstrate usage of the TableOperations plugin
+
+2003-04-21  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: added status bar (cool B-)
+
+       * htmlarea.css: various improvements for the status bar
+
+       * example.html: minor fix (background-color instead of background)
+
+2003-04-20  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: fix: IE parsing problem
+
+       * htmlarea.css, htmlarea.js, popups/fullscreen.html: added statusbar
+
+       * images/ed_tableprop.gif: New file.
+
+       * images/ed_tableprop.gif: added images for table operations buttons
+
+       * images/ed_cellprop.gif, images/ed_delcel.gif, images/ed_delcol.gif, images/ed_delrow.gif, images/ed_insabove.gif, images/ed_inscellft.gif, images/ed_inscelrgt.gif, images/ed_insleft.gif, images/ed_insright.gif, images/ed_insunder.gif, images/ed_mergecels.gif, images/ed_paste.gif, images/ed_rowprop.gif, images/ed_show_border.gif, images/ed_splitcel.gif, images/ed_splitrow.gif:
+       New file.
+
+       * images/ed_cellprop.gif, images/ed_delcel.gif, images/ed_delcol.gif, images/ed_delrow.gif, images/ed_insabove.gif, images/ed_inscellft.gif, images/ed_inscelrgt.gif, images/ed_insleft.gif, images/ed_insright.gif, images/ed_insunder.gif, images/ed_mergecels.gif, images/ed_paste.gif, images/ed_rowprop.gif, images/ed_show_border.gif, images/ed_splitcel.gif, images/ed_splitrow.gif:
+       added images for table operations buttons
+
+       * example.html:
+       even more examples of customization, but commented out so that the example
+       page looks initially with the editor defaults
+
+       * htmlarea-lang-en.js:
+       Added tooltips for cut, copy, paste, undo, redo buttons
+
+       * htmlarea.js: new features:
+
+         - cut, copy, paste, undo, redo buttons
+         - added functions: getParentElement, getAllAncestors
+         - buttons can now be enabled/disabled function of the context (i.e. caret
+           is inside a table)
+         - iframe border removed on Mozilla (looks better)
+
+       * htmlarea.css:
+       minor fix [padding]; also contains some debugging stuff that needs to be
+       removed (disabled buttons have red background, that's because Mozilla
+       doesn't seem to support opacity any longer)
+
+2003-04-19  itools  <itools@mishoo>
+
+       * test.cgi: ..
+
+       * test.cgi: ...
+
+2003-04-15  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: added address: block-level element
+
+2003-04-02  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * popups/fullscreen.html: fixed small issue
+
+2003-03-24  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea-lang-pt_br.js: brasilian translation
+
+2003-03-19  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea-lang-nb.js: norwegian translation added
+
+       * reference.html: fixed typo
+
+2003-03-15  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js:
+       fixed bug (createlink needs UI -> true, otherwise we get a link to nowhere)
+
+2003-03-04  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea-lang-ja-euc.js, htmlarea-lang-ja-jis.js, htmlarea-lang-ja-sjis.js, htmlarea-lang-ja-utf8.js, htmlarea-lang-pl.js:
+       new translations: japanese and polish
+
+2003-03-03  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * example.html, htmlarea.js: example.html: now validates (hopefully)
+       htmlarea.js: opening help in a named window
+
+2003-03-02  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * reference.html:
+       minor fix: showing how to include the "dialog.js" file
+
+2003-02-27  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * reference.html: fixes, improvements
+       new sections on creating custom buttons
+
+       * example.html:
+       example on how to submit the form from something that's not a submit button
+
+       * htmlarea.js: added "onsubmit" handler with usual syntax.
+
+       * example.html: examples now using registerButton
+
+       * popups/fullscreen.html:
+       [fix] using now the new btnList layout; removed _textArea2
+
+       * htmlarea.js: - added helper function HTMLArea.Config.registerButton
+       - _editor_url is back
+       - fixed a problem that might disturb JS compressors ('"' character in
+       regexp)
+
+2003-02-26  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: iframe border back..
+
+       * example.html: fixes -- new btnList style
+
+       * htmlarea.js:
+       changed btnList order -- tooltip, icon, textmode, action.
+
+       * example.html: demo fix
+
+       * example.html: [minor] validity
+
+       * htmlarea.js:
+       BUG FIX: now it remembers textarea content on page reload.  Got rid of the
+                secondary textarea.
+
+       * htmlarea-lang-it.js: Italian translation -- from TeddyZ
+
+2003-02-24  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea-lang-vn.js: Vietnamese lang module
+
+2003-02-22  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js:
+       Reorganized the btnList.  Now it uses direct function calls.
+
+       * reference.html: minor: use replace() instead of replaceAll()
+
+       * htmlarea.js:
+       - fixed bug: HTMLArea.replace() needs to call generate() (thanks Dlo)
+       - adding the onsubmit handler -- check if the form is there first
+       - added onunload handler that saves the HTML content, just in case user
+         presses Back/Fwd or Refresh.
+
+       * htmlarea-lang-se.js: swedish translation
+
+2003-02-21  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea.js: done some of the changes suggested by Dlo
+       bodyStyle -> pageStyle and allows other elements' styles too
+
+       * example.html: example: how to add a custom button
+
+       * reference.html: started documentation project
+
+2003-02-20  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea-lang-da.js, htmlarea-lang-gb.js, htmlarea-lang-b5.js:
+       added new lang files
+
+2003-02-19  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * htmlarea-lang-de.js: added credits
+
+       * htmlarea-lang-nl.js: credit for redspider ;)
+
+       * htmlarea-lang-de.js: added german translation (from atk)
+
+       * htmlarea-lang-nl.js: dutch translation, from redspider
+
+       * htmlarea-lang-ru.js: RU translation (from Frol, itools forums)
+
+       * htmlarea-lang-es.js:
+       added ES translation from itools forums (thanks Luis)
+
+       * htmlarea-lang-fr.js:
+       added french translation, from Ronan (interactivetools.com forums)
+
+2003-02-17  Mihai Bazon  <mishoo@localhost.localdomain>
+
+       * images/.xvpics/ed_align_justify.gif: not needed
+
+       * htmlarea.js:
+       -- made HTMLArea constructor to work with object instead of ID (if type of
+          argument is not string)
+       -- a simpler "replaceAll" function (2 lines)
+       -- fixed a major bug that prevented IE6 to correctly retrieve the HTML (it
+          seems that it was ignoring attribute values and only displaying "")
+       -- used various techniques to reduce the code size (currently only 37K, 10K
+          less than the original editor.js code [v 2.03])
+
+       * htmlarea.js:
+       removed NodeIterator code -- was only used in one place and I found a
+       different way to accomplish that task; code smaller by about 5K
+
+       * dialog.js, images/.xvpics/ed_align_justify.gif, images/ed_about.gif, images/ed_align_center.gif, images/ed_align_justify.gif, images/ed_align_left.gif, images/ed_align_right.gif, images/ed_blank.gif, images/ed_charmap.gif, images/ed_color_bg.gif, images/ed_color_fg.gif, images/ed_copy.gif, images/ed_custom.gif, images/ed_cut.gif, images/ed_delete.gif, images/ed_format_bold.gif, images/ed_format_italic.gif, images/ed_format_strike.gif, images/ed_format_sub.gif, images/ed_format_sup.gif, images/ed_format_underline.gif, images/ed_help.gif, images/ed_hr.gif, images/ed_html.gif, images/ed_image.gif, images/ed_indent_less.gif, images/ed_indent_more.gif, images/ed_link.gif, images/ed_list_bullet.gif, images/ed_list_num.gif, images/ed_redo.gif, images/ed_undo.gif, images/fullscreen_maximize.gif, images/fullscreen_minimize.gif, images/insert_table.gif, popups/about.html, popups/blank.html, popups/custom2.html, popups/editor_help.html, popups/fullscreen.html, popups/insert_image.html, popups/insert_table.html, popups/old-fullscreen.html, popups/old_insert_image.html, popups/popup.js, popups/select_color.html:
+       New file.
+
+       * dialog.js, images/.xvpics/ed_align_justify.gif, images/ed_about.gif, images/ed_align_center.gif, images/ed_align_justify.gif, images/ed_align_left.gif, images/ed_align_right.gif, images/ed_blank.gif, images/ed_charmap.gif, images/ed_color_bg.gif, images/ed_color_fg.gif, images/ed_copy.gif, images/ed_custom.gif, images/ed_cut.gif, images/ed_delete.gif, images/ed_format_bold.gif, images/ed_format_italic.gif, images/ed_format_strike.gif, images/ed_format_sub.gif, images/ed_format_sup.gif, images/ed_format_underline.gif, images/ed_help.gif, images/ed_hr.gif, images/ed_html.gif, images/ed_image.gif, images/ed_indent_less.gif, images/ed_indent_more.gif, images/ed_link.gif, images/ed_list_bullet.gif, images/ed_list_num.gif, images/ed_redo.gif, images/ed_undo.gif, images/fullscreen_maximize.gif, images/fullscreen_minimize.gif, images/insert_table.gif, popups/about.html, popups/blank.html, popups/custom2.html, popups/editor_help.html, popups/fullscreen.html, popups/insert_image.html, popups/insert_table.html, popups/old-fullscreen.html, popups/old_insert_image.html, popups/popup.js, popups/select_color.html:
+       first moved to CVS (close to release 3.0-beta)
+
+       * htmlarea.js, test.cgi: New file.
+
+       * htmlarea.js, test.cgi: first moved to CVS (close to release 3.0-beta)
+
+       * htmlarea-lang-en.js, readme.html: New file.
+
+       * htmlarea-lang-en.js, readme.html:
+       first moved to CVS (close to release 3.0-beta)
+
+       * example.html, htmlarea.css, license.txt: New file.
+
+       * example.html, htmlarea.css, license.txt:
+       first moved to CVS (close to release 3.0-beta)
+
diff --git a/htmlarea/dialog.js b/htmlarea/dialog.js
new file mode 100644 (file)
index 0000000..8562ec4
--- /dev/null
@@ -0,0 +1,73 @@
+// htmlArea v3.0 - Copyright (c) 2003-2004 interactivetools.com, inc.
+// This copyright notice MUST stay intact for use (see license.txt).
+//
+// Portions (c) dynarch.com, 2003-2004
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon.
+//   http://dynarch.com/mishoo
+//
+// $Id: dialog.js,v 1.3 2005/01/11 15:00:34 garvinhicking Exp $
+
+// Though "Dialog" looks like an object, it isn't really an object.  Instead
+// it's just namespace for protecting global symbols.
+
+function Dialog(url, action, init) {
+       if (typeof init == "undefined") {
+               init = window;  // pass this window object by default
+       }
+       Dialog._geckoOpenModal(url, action, init);
+};
+
+Dialog._parentEvent = function(ev) {
+       setTimeout( function() { if (Dialog._modal && !Dialog._modal.closed) { Dialog._modal.focus() } }, 50);
+       if (Dialog._modal && !Dialog._modal.closed) {
+               HTMLArea._stopEvent(ev);
+       }
+};
+
+
+// should be a function, the return handler of the currently opened dialog.
+Dialog._return = null;
+
+// constant, the currently opened dialog
+Dialog._modal = null;
+
+// the dialog will read it's args from this variable
+Dialog._arguments = null;
+
+Dialog._geckoOpenModal = function(url, action, init) {
+       var dlg = window.open(url, "hadialog",
+                             "toolbar=no,menubar=no,personalbar=no,width=10,height=10," +
+                             "scrollbars=no,resizable=yes,modal=yes,dependable=yes");
+       Dialog._modal = dlg;
+       Dialog._arguments = init;
+
+       // capture some window's events
+       function capwin(w) {
+               HTMLArea._addEvent(w, "click", Dialog._parentEvent);
+               HTMLArea._addEvent(w, "mousedown", Dialog._parentEvent);
+               HTMLArea._addEvent(w, "focus", Dialog._parentEvent);
+       };
+       // release the captured events
+       function relwin(w) {
+               HTMLArea._removeEvent(w, "click", Dialog._parentEvent);
+               HTMLArea._removeEvent(w, "mousedown", Dialog._parentEvent);
+               HTMLArea._removeEvent(w, "focus", Dialog._parentEvent);
+       };
+       capwin(window);
+       // capture other frames
+       for (var i = 0; i < window.frames.length; capwin(window.frames[i++]));
+       // make up a function to be called when the Dialog ends.
+       Dialog._return = function (val) {
+               if (val && action) {
+                       action(val);
+               }
+               relwin(window);
+               // capture other frames
+               for (var i = 0; i < window.frames.length; relwin(window.frames[i++]));
+               Dialog._modal = null;
+       };
+};
diff --git a/htmlarea/examples/2-areas.html b/htmlarea/examples/2-areas.html
new file mode 100644 (file)
index 0000000..1386302
--- /dev/null
@@ -0,0 +1,158 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html>
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <title>Example with 2 HTMLAreas in the same form</title>
+    <script type="text/javascript">
+      // the _editor_url is REQUIRED!  don't forget to set it.
+      _editor_url = "../";
+      // implicit language will be "en", but let's set it for brevity
+      _editor_lang = "en";
+    </script>
+    <script type="text/javascript" src="../htmlarea.js"></script>
+    <script type="text/javascript">
+      // load the plugins that we will use
+      // loading is necessary ONLY ONCE, regardless on how many editors you create
+      // basically calling the following functions will load the plugin files as if
+      // we would have wrote script src="..." but with easier and cleaner code
+      HTMLArea.loadPlugin("TableOperations");
+      HTMLArea.loadPlugin("SpellChecker");
+      HTMLArea.loadPlugin("CSS");
+
+      // this function will get called at body.onload
+      function initDocument() {
+        // cache these values as we need to pass it for both editors
+        var css_plugin_args = {
+          combos : [
+            { label: "Syntax",
+                         // menu text       // CSS class
+              options: { "None"           : "",
+                         "Code" : "code",
+                         "String" : "string",
+                         "Comment" : "comment",
+                         "Variable name" : "variable-name",
+                         "Type" : "type",
+                         "Reference" : "reference",
+                         "Preprocessor" : "preprocessor",
+                         "Keyword" : "keyword",
+                         "Function name" : "function-name",
+                         "Html tag" : "html-tag",
+                         "Html italic" : "html-helper-italic",
+                         "Warning" : "warning",
+                         "Html bold" : "html-helper-bold"
+                       },
+              context: "pre"
+            },
+            { label: "Info",
+              options: { "None"           : "",
+                         "Quote"          : "quote",
+                         "Highlight"      : "highlight",
+                         "Deprecated"     : "deprecated"
+                       }
+            }
+          ]
+        };
+
+        //---------------------------------------------------------------------
+        // GENERAL PATTERN
+        //
+       //  1. Instantitate an editor object.
+       //  2. Register plugins (note, it's required to have them loaded).
+       //  3. Configure any other items in editor.config.
+       //  4. generate() the editor
+       //
+       // The above are steps that you use to create one editor.  Nothing new
+       // so far.  In order to create more than one editor, you just have to
+       // repeat those steps for each of one.  Of course, you can register any
+       // plugins you want (no need to register the same plugins for all
+       // editors, and to demonstrate that we'll skip the TableOperations
+       // plugin for the second editor).  Just be careful to pass different
+       // ID-s in the constructor (you don't want to _even try_ to create more
+       // editors for the same TEXTAREA element ;-)).
+       //
+       // So much for the noise, see the action below.
+       //---------------------------------------------------------------------
+
+
+        //---------------------------------------------------------------------
+        // CREATE FIRST EDITOR
+        //
+        var editor1 = new HTMLArea("text-area-1");
+
+        // plugins must be registered _per editor_.  Therefore, we register
+        // plugins for the first editor here, and we will also do this for the
+        // second editor.
+        editor1.registerPlugin(TableOperations);
+        editor1.registerPlugin(SpellChecker);
+        editor1.registerPlugin(CSS, css_plugin_args);
+
+        // custom config must be done per editor.  Here we're importing the
+        // stylesheet used by the CSS plugin.
+        editor1.config.pageStyle = "@import url(custom.css);";
+
+        // generate first editor
+        editor1.generate();
+        //---------------------------------------------------------------------
+
+
+        //---------------------------------------------------------------------
+        // CREATE SECOND EDITOR
+        //
+        var editor2 = new HTMLArea("text-area-2");
+
+        // we are using the same plugins
+        editor2.registerPlugin(TableOperations);
+        editor2.registerPlugin(SpellChecker);
+        editor2.registerPlugin(CSS, css_plugin_args);
+
+        // import the CSS plugin styles
+        editor2.config.pageStyle = "@import url(custom.css);";
+
+        // generate the second editor
+        // IMPORTANT: if we don't give it a timeout, the first editor will
+        // not function in Mozilla.  Soon I'll think about starting to
+        // implement some kind of event that will fire when the editor
+        // finished creating, then we'll be able to chain the generate()
+        // calls in an elegant way.  But right now there's no other solution
+        // than the following.
+        setTimeout(function() {
+          editor2.generate();
+        }, 500);
+        //---------------------------------------------------------------------
+      };
+    </script>
+  </head>
+
+  <body onload="initDocument()">
+    <h1>Example with 2 HTMLAreas in the same form</h1>
+
+    <form action="2-areas.cgi" method="post" target="_blank">
+
+      <input type="submit" value=" Submit " />
+      <br />
+
+      <textarea id="text-area-1" name="text1" style="width: 100%; height: 12em">
+        &lt;h3&gt;HTMLArea #1&lt;/h3&gt;
+        &lt;p&gt;This will submit a field named &lt;em&gt;text1&lt;/em&gt;.&lt;/p&gt;
+      </textarea>
+
+      <br />
+
+      <textarea id="text-area-2" name="text2" style="width: 100%; height: 12em">
+        &lt;h3&gt;Second HTMLArea&lt;/h3&gt; &lt;p&gt;&lt;em&gt;text2&lt;/em&gt; submission.  Both are
+        located in the same FORM element and the script action is
+        2-areas.cgi (see it in the examples directory)&lt;/p&gt;
+      </textarea>
+
+      <br />
+      <input type="submit" value=" Submit " />
+
+    </form>
+
+    <hr>
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Fri Oct 31 09:37:10 EET 2003 -->
+<!-- hhmts start --> Last modified: Wed Jan 28 11:10:40 EET 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
diff --git a/htmlarea/examples/context-menu.html b/htmlarea/examples/context-menu.html
new file mode 100644 (file)
index 0000000..388195b
--- /dev/null
@@ -0,0 +1,95 @@
+<html>
+  <head>
+    <title>Test of ContextMenu plugin</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <script type="text/javascript">
+      _editor_url = "../";
+      _editor_lang = "en";
+    </script>
+
+    <!-- load the main HTMLArea file -->
+    <script type="text/javascript" src="../htmlarea.js"></script>
+
+    <script type="text/javascript">
+      HTMLArea.loadPlugin("ContextMenu");
+      HTMLArea.loadPlugin("TableOperations");
+
+      function initDocument() {
+        var editor = new HTMLArea("editor");
+        editor.registerPlugin(ContextMenu);
+        editor.registerPlugin(TableOperations);
+        editor.generate();
+      }
+    </script>
+
+  </head>
+
+  <body onload="initDocument()">
+    <h1>Test of ContextMenu plugin</h1>
+
+
+<textarea id="editor" style="height: 30em; width: 100%;">
+&lt;table border="1" style="border: 1px dotted rgb(0, 102, 255); width:
+100%; background-color: rgb(255, 204, 51); background-image: none; float:
+none; text-align: left; vertical-align: top; border-collapse: collapse;"
+summary="" cellspacing="" cellpadding="" frame="box"
+rules="all"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="border: 1px solid
+rgb(255, 0, 0); background-color: rgb(0, 51, 51); background-image: none;
+text-align: left; vertical-align: top;"&gt;&lt;a
+href="http://dynarch.com/mishoo/articles.epl?art_id=430"&gt;&lt;img
+src="http://127.0.0.1/~mishoo/htmlarea/examples/pieng.png" alt="" align=""
+border="0" hspace="0" vspace="0" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;td
+style="border: 1px solid rgb(255, 0, 0); background-color: rgb(255, 255, 0);
+background-image: none; text-align: left; vertical-align: top;"&gt;The
+article linked on the left image presents a script that allows Internet
+Explorer to use PNG images.  We hope to be able to implement IE PNG support
+in HTMLArea soon.&lt;br /&gt; &lt;br /&gt; Go on, right-click everywhere and
+test our new context menus.  And be thankful to &lt;a
+href="http://www.americanbible.org/"&gt;American Bible Society&lt;/a&gt; who
+sponsored the development, &lt;a
+href="http://dynarch.com/mishoo/"&gt;mishoo&lt;/a&gt; who made it happen and
+God, Who keeps mishoo alife. ;-)&lt;br /&gt; &lt;br /&gt;&lt;span
+style="font-style: italic;"&gt;P.S.&lt;/span&gt; No animals were harmed
+while producing this movie.&lt;br /&gt;
+&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="border-style: none;
+background-color: rgb(255, 255, 51); background-image: none; text-align:
+left; vertical-align: top;"&gt;Welcome to HTMLArea, the best online
+editor.&lt;br /&gt;&lt;/td&gt;&lt;td&gt;HTMLArea is a project initiated by
+&lt;a href="http://interactivetools.com/"&gt;InteractiveTools.com&lt;/a&gt;.
+Other companies contributed largely by sponsoring the development of
+additional extensions.  Many thanks to:&lt;br /&gt; &lt;br
+style="font-family: courier new,courier,monospace;" /&gt; &lt;div
+style="margin-left: 40px;"&gt;&lt;a href="http://www.zapatec.com/"
+style="font-family: courier
+new,courier,monospace;"&gt;http://www.zapatec.com&lt;/a&gt;&lt;br
+style="font-family: courier new,courier,monospace;" /&gt; &lt;a
+href="http://www.americanbible.org/" style="font-family: courier
+new,courier,monospace;"&gt;http://www.americanbible.org&lt;/a&gt;&lt;br
+style="font-family: courier new,courier,monospace;" /&gt; &lt;a
+href="http://www.neomedia.ro/" style="font-family: courier
+new,courier,monospace;"&gt;http://www.neomedia.ro&lt;/a&gt;&lt;br
+style="font-family: courier new,courier,monospace;" /&gt; &lt;a
+href="http://www.os3.it/" style="font-family: courier
+new,courier,monospace;"&gt;http://www.os3.it&lt;/a&gt;&lt;br
+style="font-family: courier new,courier,monospace;" /&gt; &lt;a
+href="http://www.miro.com.au/" style="font-family: courier
+new,courier,monospace;"&gt;http://www.miro.com.au&lt;/a&gt;&lt;br
+style="font-family: courier new,courier,monospace;" /&gt; &lt;a
+href="http://www.thycotic.com/" style="font-family: courier
+new,courier,monospace;"&gt;http://www.thycotic.com&lt;/a&gt;&lt;br /&gt;
+&lt;/div&gt; &lt;br /&gt; and to all the posters at <a
+href="http://www.interactivetools.com/iforum/Open_Source_C3/htmlArea_v3.0_-_Alpha_Release_F14/
+">InteractiveTools</a> HTMLArea forums, whose feedback is continually
+useful in polishing HTMLArea.&lt;br /&gt; &lt;br /&gt;&lt;div
+style="text-align: right;"&gt;-- developers and maintainers of version 3,
+&lt;a href="http://dynarch.com/"&gt;dynarch.com&lt;/a&gt;.&lt;br
+/&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
+    </textarea>
+
+    <hr />
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Wed Oct  1 19:55:37 EEST 2003 -->
+<!-- hhmts start --> Last modified: Wed Jan 28 11:10:29 EET 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
diff --git a/htmlarea/examples/core.html b/htmlarea/examples/core.html
new file mode 100644 (file)
index 0000000..536be0e
--- /dev/null
@@ -0,0 +1,184 @@
+<html>
+<head>
+<title>Example of HTMLArea 3.0</title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+<!-- Configure the path to the editor.  We make it relative now, so that the
+    example ZIP file will work anywhere, but please NOTE THAT it's better to
+    have it an absolute path, such as '/htmlarea/'. -->
+<script type="text/javascript">
+  _editor_url = "../";
+  _editor_lang = "en";
+</script>
+<script type="text/javascript" src="../htmlarea.js"></script>
+
+<style type="text/css">
+html, body {
+  font-family: Verdana,sans-serif;
+  background-color: #fea;
+  color: #000;
+}
+a:link, a:visited { color: #00f; }
+a:hover { color: #048; }
+a:active { color: #f00; }
+
+textarea { background-color: #fff; border: 1px solid 00f; }
+</style>
+
+<script type="text/javascript">
+var editor = null;
+function initEditor() {
+  editor = new HTMLArea("ta");
+
+  // comment the following two lines to see how customization works
+  editor.generate();
+  return false;
+
+  var cfg = editor.config; // this is the default configuration
+  cfg.registerButton({
+    id        : "my-hilite",
+    tooltip   : "Highlight text",
+    image     : "ed_custom.gif",
+    textMode  : false,
+    action    : function(editor) {
+                  editor.surroundHTML("<span class=\"hilite\">", "</span>");
+                },
+    context   : 'table'
+  });
+
+  cfg.toolbar.push(["linebreak", "my-hilite"]); // add the new button to the toolbar
+
+  // BEGIN: code that adds a custom button
+  // uncomment it to test
+  var cfg = editor.config; // this is the default configuration
+  /*
+  cfg.registerButton({
+    id        : "my-hilite",
+    tooltip   : "Highlight text",
+    image     : "ed_custom.gif",
+    textMode  : false,
+    action    : function(editor) {
+                  editor.surroundHTML("<span class=\"hilite\">", "</span>");
+                }
+  });
+  */
+
+function clickHandler(editor, buttonId) {
+  switch (buttonId) {
+    case "my-toc":
+      editor.insertHTML("<h1>Table Of Contents</h1>");
+      break;
+    case "my-date":
+      editor.insertHTML((new Date()).toString());
+      break;
+    case "my-bold":
+      editor.execCommand("bold");
+      editor.execCommand("italic");
+      break;
+    case "my-hilite":
+      editor.surroundHTML("<span class=\"hilite\">", "</span>");
+      break;
+  }
+};
+cfg.registerButton("my-toc",  "Insert TOC", "ed_custom.gif", false, clickHandler);
+cfg.registerButton("my-date", "Insert date/time", "ed_custom.gif", false, clickHandler);
+cfg.registerButton("my-bold", "Toggle bold/italic", "ed_custom.gif", false, clickHandler);
+cfg.registerButton("my-hilite", "Hilite selection", "ed_custom.gif", false, clickHandler);
+
+cfg.registerButton("my-sample", "Class: sample", "ed_custom.gif", false,
+  function(editor) {
+    if (HTMLArea.is_ie) {
+      editor.insertHTML("<span class=\"sample\">&nbsp;&nbsp;</span>");
+      var r = editor._doc.selection.createRange();
+      r.move("character", -2);
+      r.moveEnd("character", 2);
+      r.select();
+    } else { // Gecko/W3C compliant
+      var n = editor._doc.createElement("span");
+      n.className = "sample";
+      editor.insertNodeAtSelection(n);
+      var sel = editor._iframe.contentWindow.getSelection();
+      sel.removeAllRanges();
+      var r = editor._doc.createRange();
+      r.setStart(n, 0);
+      r.setEnd(n, 0);
+      sel.addRange(r);
+    }
+  }
+);
+
+
+  /*
+  cfg.registerButton("my-hilite", "Highlight text", "ed_custom.gif", false,
+    function(editor) {
+      editor.surroundHTML('<span class="hilite">', '</span>');
+    }
+  );
+  */
+  cfg.pageStyle = "body { background-color: #efd; } .hilite { background-color: yellow; } "+
+                  ".sample { color: green; font-family: monospace; }";
+  cfg.toolbar.push(["linebreak", "my-toc", "my-date", "my-bold", "my-hilite", "my-sample"]); // add the new button to the toolbar
+  // END: code that adds a custom button
+
+  editor.generate();
+}
+function insertHTML() {
+  var html = prompt("Enter some HTML code here");
+  if (html) {
+    editor.insertHTML(html);
+  }
+}
+function highlight() {
+  editor.surroundHTML('<span style="background-color: yellow">', '</span>');
+}
+</script>
+
+</head>
+
+<!-- use <body onload="HTMLArea.replaceAll()" if you don't care about
+     customizing the editor.  It's the easiest way! :) -->
+<body onload="initEditor()">
+
+<h1>HTMLArea 3.0</h1>
+
+<p>A replacement for <code>TEXTAREA</code> elements.  &copy; <a
+href="http://interactivetools.com">InteractiveTools.com</a>, 2003-2004.</p>
+
+<form action="test.cgi" method="post" id="edit" name="edit">
+
+<textarea id="ta" name="ta" style="width:100%" rows="20" cols="80">
+  &lt;p&gt;Here is some sample text: &lt;b&gt;bold&lt;/b&gt;, &lt;i&gt;italic&lt;/i&gt;, &lt;u&gt;underline&lt;/u&gt;. &lt;/p&gt;
+  &lt;p align=center&gt;Different fonts, sizes and colors (all in bold):&lt;/p&gt;
+  &lt;p&gt;&lt;b&gt;
+   &lt;font face="arial"           size="7" color="#000066"&gt;arial&lt;/font&gt;,
+   &lt;font face="courier new"     size="6" color="#006600"&gt;courier new&lt;/font&gt;,
+   &lt;font face="georgia"         size="5" color="#006666"&gt;georgia&lt;/font&gt;,
+   &lt;font face="tahoma"          size="4" color="#660000"&gt;tahoma&lt;/font&gt;,
+   &lt;font face="times new roman" size="3" color="#660066"&gt;times new roman&lt;/font&gt;,
+   &lt;font face="verdana"         size="2" color="#666600"&gt;verdana&lt;/font&gt;,
+   &lt;font face="tahoma"          size="1" color="#666666"&gt;tahoma&lt;/font&gt;
+  &lt;/b&gt;&lt;/p&gt;
+  &lt;p&gt;Click on &lt;a href="http://www.interactivetools.com/"&gt;this link&lt;/a&gt; and then on the link button to the details ... OR ... select some text and click link to create a &lt;b&gt;new&lt;/b&gt; link.&lt;/p&gt;
+</textarea>
+
+<p />
+
+<input type="submit" name="ok" value="  submit  " />
+<input type="button" name="ins" value="  insert html  " onclick="return insertHTML();" />
+<input type="button" name="hil" value="  highlight text  " onclick="return highlight();" />
+
+<a href="javascript:mySubmit()">submit</a>
+
+<script type="text/javascript">
+function mySubmit() {
+// document.edit.save.value = "yes";
+document.edit.onsubmit(); // workaround browser bugs.
+document.edit.submit();
+};
+</script>
+
+</form>
+
+</body>
+</html>
diff --git a/htmlarea/examples/css.html b/htmlarea/examples/css.html
new file mode 100644 (file)
index 0000000..5700d63
--- /dev/null
@@ -0,0 +1,88 @@
+<html>
+  <head>
+    <title>Test of CSS plugin</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <script type="text/javascript">
+      _editor_url = "../";
+      _editor_lang = "en";
+    </script>
+
+    <!-- load the main HTMLArea files -->
+    <script type="text/javascript" src="../htmlarea.js"></script>
+
+    <script type="text/javascript">
+      HTMLArea.loadPlugin("CSS");
+
+      function initDocument() {
+        var editor = new HTMLArea("editor");
+        editor.config.pageStyle = "@import url(custom.css);";
+        editor.registerPlugin(CSS, {
+          combos : [
+            { label: "Syntax",
+                         // menu text       // CSS class
+              options: { "None"           : "",
+                         "Code" : "code",
+                         "String" : "string",
+                         "Comment" : "comment",
+                         "Variable name" : "variable-name",
+                         "Type" : "type",
+                         "Reference" : "reference",
+                         "Preprocessor" : "preprocessor",
+                         "Keyword" : "keyword",
+                         "Function name" : "function-name",
+                         "Html tag" : "html-tag",
+                         "Html italic" : "html-helper-italic",
+                         "Warning" : "warning",
+                         "Html bold" : "html-helper-bold"
+                       },
+              context: "pre"
+            },
+            { label: "Info",
+              options: { "None"           : "",
+                         "Quote"          : "quote",
+                         "Highlight"      : "highlight",
+                         "Deprecated"     : "deprecated"
+                       }
+            }
+          ]
+        });
+        editor.generate();
+      }
+    </script>
+
+  </head>
+
+  <body onload="initDocument()">
+    <h1>Test of FullPage plugin</h1>
+
+    <textarea id="editor" style="height: 30em; width: 100%;"
+>&lt;h1&gt;&lt;tt&gt;registerDropdown&lt;/tt&gt;&lt;/h1&gt;
+
+&lt;p&gt;Here's some sample code that adds a dropdown to the toolbar.  Go on, do
+        syntax highlighting on it ;-)&lt;/p&gt;
+
+&lt;pre&gt;var the_options = {
+       "Keyword"          : "keyword",
+       "Function name"    : "function-name",
+       "String"           : "string",
+       "Numeric"          : "integer",
+       "Variable name"    : "variable"
+};
+var css_class = {
+       id                 : "CSS-class",
+       tooltip            : i18n["tooltip"],
+       options            : the_options,
+       action             : function(editor) { self.onSelect(editor, this); }
+};
+cfg.registerDropdown(css_class);
+toolbar[0].unshift(["CSS-class"]);&lt;/pre&gt;
+
+&lt;p&gt;Easy, eh? ;-)&lt;/p&gt;</textarea>
+
+    <hr />
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Wed Oct  1 19:55:37 EEST 2003 -->
+<!-- hhmts start --> Last modified: Wed Jan 28 11:10:16 EET 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
diff --git a/htmlarea/examples/custom.css b/htmlarea/examples/custom.css
new file mode 100644 (file)
index 0000000..e2690df
--- /dev/null
@@ -0,0 +1,29 @@
+body { background-color: #234; color: #dd8; font-family: tahoma; font-size: 12px; }
+
+a:link, a:visited { color: #8cf; }
+a:hover { color: #ff8; }
+
+h1 { background-color: #456; color: #ff8; padding: 2px 5px; border: 1px solid; border-color: #678 #012 #012 #678; }
+
+/* syntax highlighting (used by the first combo defined for the CSS plugin) */
+
+pre { margin: 0px 1em; padding: 5px 1em; background-color: #000; border: 1px dotted #02d; border-left: 2px solid #04f; }
+.code { color: #f5deb3; }
+.string { color: #00ffff; }
+.comment { color: #8fbc8f; }
+.variable-name { color: #fa8072; }
+.type { color: #90ee90; font-weight: bold; }
+.reference { color: #ee82ee; }
+.preprocessor { color: #faf; }
+.keyword { color: #ffffff; font-weight: bold; }
+.function-name { color: #ace; }
+.html-tag { font-weight: bold; }
+.html-helper-italic { font-style: italic; }
+.warning { color: #ffa500; font-weight: bold; }
+.html-helper-bold { font-weight: bold; }
+
+/* info combo */
+
+.quote { font-style: italic; color: #ee9; }
+.highlight { background-color: yellow; color: #000; }
+.deprecated { text-decoration: line-through; color: #aaa; }
diff --git a/htmlarea/examples/full-page.html b/htmlarea/examples/full-page.html
new file mode 100644 (file)
index 0000000..0411a04
--- /dev/null
@@ -0,0 +1,77 @@
+<html>
+  <head>
+    <title>Test of FullPage plugin</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <script type="text/javascript">
+      _editor_url = "../";
+      _editor_lang = "en";
+    </script>
+
+    <!-- load the main HTMLArea files -->
+    <script type="text/javascript" src="../htmlarea.js"></script>
+
+    <script type="text/javascript">
+      HTMLArea.loadPlugin("FullPage");
+
+      function initDocument() {
+        var editor = new HTMLArea("editor");
+        editor.registerPlugin(FullPage);
+        editor.generate();
+      }
+
+      HTMLArea.onload = initDocument;
+    </script>
+
+  </head>
+
+  <body onload="HTMLArea.init()">
+    <h1>Test of FullPage plugin</h1>
+
+    <textarea id="editor" style="height: 30em; width: 100%;">
+      &lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"&gt;
+      &lt;html&gt;
+        &lt;head&gt;
+          &lt;title&gt;FullPage plugin for HTMLArea&lt;/title&gt;
+          &lt;link rel="alternate stylesheet" href="http://dynarch.com/mishoo/css/dark.css" /&gt;
+          &lt;link rel="stylesheet" href="http://dynarch.com/mishoo/css/cool-light.css" /&gt;
+        &lt;/head&gt;
+        &lt;body style="background-color: #ddddee; color: #000077;"&gt;
+          &lt;table style="width:60%; height: 90%; margin: 2% auto 1% auto;" align="center" border="0" cellpadding="0" cellspacing="0"&gt;
+            &lt;tr&gt;
+              &lt;td style="background-color: #ddeedd; border: 2px solid #002; height: 1.5em; padding: 2px; font: bold 24px Verdana;"&gt;
+                FullPage plugin
+              &lt;/td&gt;
+            &lt;/tr&gt;
+            &lt;tr&gt;
+              &lt;td style="background-color: #fff; border: 1px solid #aab; padding: 1em 3em; font: 12px Verdana;"&gt;
+                &lt;p&gt;
+                  This plugin enables one to edit a full HTML file in &lt;a
+                    href="http://dynarch.com/htmlarea/"&gt;HTMLArea&lt;/a&gt;.  This is not
+                  normally possible with just the core editor since it only
+                  retrieves the HTML inside the &lt;code&gt;body&lt;/code&gt; tag.
+                &lt;/p&gt;
+                &lt;p&gt;
+                  It provides the ability to change the &lt;code&gt;DOCTYPE&lt;/code&gt; of
+                  the document, &lt;code&gt;body&lt;/code&gt; &lt;code&gt;bgcolor&lt;/code&gt; and
+                  &lt;code&gt;fgcolor&lt;/code&gt; attributes as well as to add additional
+                  &lt;code&gt;link&lt;/code&gt;-ed stylesheets.  Cool, eh?
+                &lt;/p&gt;
+                &lt;p&gt;
+                  The development of this plugin was initiated and sponsored by
+                  &lt;a href="http://thycotic.com"&gt;Thycotic Software Ltd.&lt;/a&gt;.
+                  That's also cool, isn't it? ;-)
+                &lt;/p&gt;
+              &lt;/td&gt;
+            &lt;/tr&gt;
+          &lt;/table&gt;
+        &lt;/body&gt;
+      &lt;/html&gt;
+    </textarea>
+
+    <hr />
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Wed Oct  1 19:55:37 EEST 2003 -->
+<!-- hhmts start --> Last modified: Wed Aug 11 13:59:07 CEST 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
diff --git a/htmlarea/examples/fully-loaded.html b/htmlarea/examples/fully-loaded.html
new file mode 100644 (file)
index 0000000..6bf937b
--- /dev/null
@@ -0,0 +1,262 @@
+<html>
+<head>
+<title>Example of HTMLArea 3.0</title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+<!-- Configure the path to the editor.  We make it relative now, so that the
+    example ZIP file will work anywhere, but please NOTE THAT it's better to
+    have it an absolute path, such as '/htmlarea/'. -->
+<script type="text/javascript">
+  _editor_url = "../";
+  _editor_lang = "en";
+</script>
+
+<!-- load the main HTMLArea file, this will take care of loading the CSS and
+    other required core scripts. -->
+<script type="text/javascript" src="../htmlarea.js"></script>
+
+<!-- load the plugins -->
+<script type="text/javascript">
+      // WARNING: using this interface to load plugin
+      // will _NOT_ work if plugins do not have the language
+      // loaded by HTMLArea.
+
+      // In other words, this function generates SCRIPT tags
+      // that load the plugin and the language file, based on the
+      // global variable HTMLArea.I18N.lang (defined in the lang file,
+      // in our case "lang/en.js" loaded above).
+
+      // If this lang file is not found the plugin will fail to
+      // load correctly and NOTHING WILL WORK.
+
+      HTMLArea.loadPlugin("TableOperations");
+      HTMLArea.loadPlugin("SpellChecker");
+      HTMLArea.loadPlugin("FullPage");
+      HTMLArea.loadPlugin("CSS");
+      HTMLArea.loadPlugin("ContextMenu");
+      //HTMLArea.loadPlugin("HtmlTidy");
+      HTMLArea.loadPlugin("ListType");
+      HTMLArea.loadPlugin("CharacterMap");
+HTMLArea.loadPlugin("DynamicCSS");
+</script>
+
+<style type="text/css">
+html, body {
+  font-family: Verdana,sans-serif;
+  background-color: #fea;
+  color: #000;
+}
+a:link, a:visited { color: #00f; }
+a:hover { color: #048; }
+a:active { color: #f00; }
+
+textarea { background-color: #fff; border: 1px solid 00f; }
+</style>
+
+<script type="text/javascript">
+var editor = null;
+
+function initEditor() {
+
+  // create an editor for the "ta" textbox
+  editor = new HTMLArea("ta");
+
+  // register the FullPage plugin
+  editor.registerPlugin(FullPage);
+
+  // register the SpellChecker plugin
+  editor.registerPlugin(TableOperations);
+
+  // register the SpellChecker plugin
+  editor.registerPlugin(SpellChecker);
+  
+  // register the HtmlTidy plugin
+  //editor.registerPlugin(HtmlTidy);
+
+  // register the ListType plugin
+  editor.registerPlugin(ListType);
+
+  editor.registerPlugin(CharacterMap);
+editor.registerPlugin(DynamicCSS);
+
+  // register the CSS plugin
+  editor.registerPlugin(CSS, {
+    combos : [
+      { label: "Syntax:",
+                   // menu text       // CSS class
+        options: { "None"           : "",
+                   "Code" : "code",
+                   "String" : "string",
+                   "Comment" : "comment",
+                   "Variable name" : "variable-name",
+                   "Type" : "type",
+                   "Reference" : "reference",
+                   "Preprocessor" : "preprocessor",
+                   "Keyword" : "keyword",
+                   "Function name" : "function-name",
+                   "Html tag" : "html-tag",
+                   "Html italic" : "html-helper-italic",
+                   "Warning" : "warning",
+                   "Html bold" : "html-helper-bold"
+                 },
+        context: "pre"
+      },
+      { label: "Info:",
+        options: { "None"           : "",
+                   "Quote"          : "quote",
+                   "Highlight"      : "highlight",
+                   "Deprecated"     : "deprecated"
+                 }
+      }
+    ]
+  });
+
+  // add a contextual menu
+  editor.registerPlugin("ContextMenu");
+
+  // load the stylesheet used by our CSS plugin configuration
+  editor.config.pageStyle = "@import url(custom.css);";
+
+  editor.generate();
+  return false;
+}
+
+HTMLArea.onload = initEditor;
+
+function insertHTML() {
+  var html = prompt("Enter some HTML code here");
+  if (html) {
+    editor.insertHTML(html);
+  }
+}
+function highlight() {
+  editor.surroundHTML('<span style="background-color: yellow">', '</span>');
+}
+</script>
+
+</head>
+
+<!-- use <body onload="HTMLArea.replaceAll()" if you don't care about
+     customizing the editor.  It's the easiest way! :) -->
+<body onload="HTMLArea.init();">
+
+<h1>HTMLArea 3.0</h1>
+
+<p>A replacement for <code>TEXTAREA</code> elements.  &copy; <a
+href="http://interactivetools.com">InteractiveTools.com</a>, 2003-2004.</p>
+
+<form action="test.cgi" method="post" id="edit" name="edit">
+
+<textarea id="ta" name="ta" style="width:100%" rows="24" cols="80">
+&lt;!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN"&gt;
+&lt;html&gt;
+
+&lt;head&gt;
+&lt;title&gt;Passing parameters to JavaScript code&lt;/title&gt;
+&lt;link rel="stylesheet" href="custom.css" /&gt;
+&lt;/head&gt;
+
+&lt;body&gt;
+&lt;h1&gt;Passing parameters to JavaScript code&lt;/h1&gt;
+
+&lt;p&gt;Sometimes we need to pass parameters to some JavaScript function that we
+wrote ourselves.  But sometimes it's simply more convenient to include the
+parameter not in the function call, but in the affected HTML elements.
+Usually, all JavaScript calls affect some element, right? ;-)&lt;/p&gt;
+
+&lt;p&gt;Well, here's an original way to do it.  Or at least, I think it's
+original.&lt;/p&gt;
+
+&lt;h2&gt;But first...&lt;/h2&gt;
+
+&lt;p&gt;... an example.  Why would I need such thing?  I have a JS function that
+is called on &lt;code&gt;BODY&lt;/code&gt; &lt;code&gt;onload&lt;/code&gt; handler.  This function
+tries to retrieve the element with the ID "conttoc" and, if present, it will
+&lt;a href="toc.epl" title="Automatic TOC generation"&gt;generate an index&lt;/a&gt;.
+The problem is, this function exists in some external JavaScript library
+that it's loaded in page.  I only needed to pass the parameter from
+&lt;em&gt;one&lt;/em&gt; page.  Thus, it makes sense to pass the parameter from the HTML
+code on &lt;em&gt;that&lt;/em&gt; page, not to affect the others.&lt;/p&gt;
+
+&lt;p&gt;The first idea that came to me was to use some attribute, like "id" or
+"class".  But "id" was locked already, it &lt;em&gt;had&lt;/em&gt; to be "conttoc".  Use
+"class"?  It's not elegant.. what if I really wanted to give it a class, at
+some point?&lt;/p&gt;
+
+&lt;h2&gt;The idea&lt;/h2&gt;
+
+&lt;p&gt;So I thought: what are the HTML elements that do not affect the page
+rendering in any way?  Well, comments.  I mean, &lt;em&gt;comments&lt;/em&gt;, HTML
+comments.  You know, like &lt;code&gt;&amp;lt;!-- this is a comment --&amp;gt;&lt;/code&gt;.&lt;/p&gt;
+
+&lt;p&gt;Though comments do not normally affect the way browser renders the page,
+they are still parsed and are part of the DOM, as well as any other node.
+But this mean that we can access comments from JavaScript code, just like we
+access any other element, right?  Which means that they &lt;em&gt;can&lt;/em&gt; affect
+the way that page finally appears ;-)&lt;/p&gt;
+
+&lt;h2&gt;The code&lt;/h2&gt;
+
+&lt;p&gt;The main part was the idea.  The code is simple ;-)  Suppose we have the
+following HTML code:&lt;/p&gt;
+
+&lt;pre class="code"&gt;&lt;span class="function-name"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html-tag"&gt;div&lt;/span&gt; &lt;span class="variable-name"&gt;id=&lt;/span&gt;&lt;span class="string"&gt;&amp;quot;conttoc&amp;quot;&lt;/span&gt;&lt;span class="paren-face-match"&gt;&amp;gt;&lt;/span&gt;&lt;span class="function-name"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html-tag"&gt;/div&lt;/span&gt;&lt;span class="function-name"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
+
+&lt;p&gt;and our function checks for the presence an element having the ID
+"conttoc", and generates a table of contents into it.  Our code will also
+check if the "conttoc" element's first child is a comment node, and if so
+will parse additional parameters from there, for instance, a desired prefix
+for the links that are to be generated into it.  Why did I need it?  Because
+if the page uses a &lt;code&gt;&amp;lt;base&amp;gt;&lt;/code&gt; element to specify the default
+link prefix, then links like "#gen1" generated by the &lt;a href="toc.epl"&gt;toc
+generator&lt;/a&gt; will not point to that same page as they should, but to the
+page reffered from &lt;code&gt;&amp;lt;base&amp;gt;&lt;/code&gt;.&lt;/p&gt;
+
+&lt;p&gt;So the HTML would now look like this:&lt;/p&gt;
+
+&lt;pre class="code"&gt;&lt;span class="function-name"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html-tag"&gt;div&lt;/span&gt; &lt;span class="variable-name"&gt;id=&lt;/span&gt;&lt;span class="string"&gt;&amp;quot;conttoc&amp;quot;&lt;/span&gt;&lt;span class="function-name"&gt;&amp;gt;&lt;/span&gt;&lt;span class="comment"&gt;&amp;lt;!-- base:link/prefix.html --&amp;gt;&lt;/span&gt;&lt;span class="paren-face-match"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html-tag"&gt;/div&lt;/span&gt;&lt;span class="paren-face-match"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
+
+&lt;p&gt;And our TOC generation function does something like this:&lt;/p&gt;
+
+&lt;pre class="code"&gt;&lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;element&lt;/span&gt; = getElementById(&amp;quot;&lt;span class="string"&gt;conttoc&lt;/span&gt;&amp;quot;);
+&lt;span class="keyword"&gt;if&lt;/span&gt; (element.firstChild &amp;amp;&amp;amp; element.firstChild.nodeType == 8) {
+  &lt;span class="comment"&gt;// 8 means Node.COMMENT_NODE.  We're using numeric values
+&lt;/span&gt;  &lt;span class="comment"&gt;// because IE6 does not support constant names.
+&lt;/span&gt;  &lt;span class="keyword"&gt;var&lt;/span&gt; &lt;span class="variable-name"&gt;parameters&lt;/span&gt; = element.firstChild.data;
+  &lt;span class="comment"&gt;// at this point &amp;quot;parameters&amp;quot; contains base:link/prefix.html
+&lt;/span&gt;  &lt;span class="comment"&gt;// ...
+&lt;/span&gt;}&lt;/pre&gt;
+
+&lt;p&gt;So we retrieved the value passed to the script from the HTML code.  This
+was the goal of this article.&lt;/p&gt;
+
+&lt;hr /&gt;
+&lt;address&gt;&lt;a href="http://students.infoiasi.ro/~mishoo/"&gt;Mihai Bazon&lt;/a&gt;&lt;/address&gt;
+&lt;!-- hhmts start --&gt; Last modified on Thu Apr  3 20:34:17 2003
+&lt;!-- hhmts end --&gt;
+&lt;!-- doc-lang: English --&gt;
+&lt;/body&gt;
+&lt;/html&gt;
+</textarea>
+
+<p />
+
+<input type="submit" name="ok" value="  submit  " />
+<input type="button" name="ins" value="  insert html  " onclick="return insertHTML();" />
+<input type="button" name="hil" value="  highlight text  " onclick="return highlight();" />
+
+<a href="javascript:mySubmit()">submit</a>
+
+<script type="text/javascript">
+function mySubmit() {
+// document.edit.save.value = "yes";
+document.edit.onsubmit(); // workaround browser bugs.
+document.edit.submit();
+};
+</script>
+
+</form>
+
+</body>
+</html>
diff --git a/htmlarea/examples/index.html b/htmlarea/examples/index.html
new file mode 100644 (file)
index 0000000..e7636d7
--- /dev/null
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html> <head>
+<title>HTMLArea examples index</title>
+</head>
+
+<body>
+<h1>HTMLArea: auto-generated examples index</h1>
+
+<ul>
+% while (<*.html>) {
+% next if /^index.html$/;
+  <li>
+    <a href="<% $_ %>"><% $_ %></a>
+  </li>
+% }
+</ul>
+
+<hr />
+<address>mihai_bazon@yahoo.com</address>
+<!-- hhmts start --> Last modified: Sun Feb  1 13:30:39 EET 2004 <!-- hhmts end -->
+</body> </html>
+
+<%INIT>
+my $dir = $m->interp->comp_root;
+$dir =~ s{/+$}{}g;
+#$dir =~ s{/[^/]+$}{}g;
+$dir .= $m->current_comp->dir_path;
+chdir $dir;
+</%INIT>
diff --git a/htmlarea/examples/spell-checker.html b/htmlarea/examples/spell-checker.html
new file mode 100644 (file)
index 0000000..06c71a3
--- /dev/null
@@ -0,0 +1,132 @@
+<html>
+<head>
+<title>Example of HTMLArea 3.0</title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+<!-- Configure the path to the editor.  We make it relative now, so that the
+    example ZIP file will work anywhere, but please NOTE THAT it's better to
+    have it an absolute path, such as '/htmlarea/'. -->
+<script type="text/javascript">
+  _editor_lang = "en";
+  _editor_url = "../";
+</script>
+<!-- load the main HTMLArea files -->
+<script type="text/javascript" src="../htmlarea.js"></script>
+
+<style type="text/css">
+html, body {
+  font-family: Verdana,sans-serif;
+  background-color: #fea;
+  color: #000;
+}
+a:link, a:visited { color: #00f; }
+a:hover { color: #048; }
+a:active { color: #f00; }
+
+textarea { background-color: #fff; border: 1px solid 00f; }
+</style>
+
+<script type="text/javascript">
+HTMLArea.loadPlugin("SpellChecker");
+var editor = null;
+function initEditor() {
+  // create an editor for the "ta" textbox
+  editor = new HTMLArea("ta");
+
+  // register the SpellChecker plugin
+  editor.registerPlugin(SpellChecker);
+
+  editor.generate();
+  return false;
+}
+
+function insertHTML() {
+  var html = prompt("Enter some HTML code here");
+  if (html) {
+    editor.insertHTML(html);
+  }
+}
+function highlight() {
+  editor.surroundHTML('<span style="background-color: yellow">', '</span>');
+}
+</script>
+
+</head>
+
+<!-- use <body onload="HTMLArea.replaceAll()" if you don't care about
+     customizing the editor.  It's the easiest way! :) -->
+<body onload="initEditor()">
+
+<h1>HTMLArea 3.0</h1>
+
+<p>A replacement for <code>TEXTAREA</code> elements.  &copy; <a
+href="http://interactivetools.com">InteractiveTools.com</a>, 2003-2004.</p>
+
+<p>Plugins:
+      <tt>SpellChecker</tt> (sponsored by <a
+        href="http://americanbible.org">American Bible Society</a>).
+</p>
+
+<form action="test.cgi" method="post" id="edit" name="edit">
+
+<textarea id="ta" name="ta" style="width:100%" rows="24" cols="80">
+
+<h1>The <tt>SpellChecker</tt> plugin</h1>
+
+      <p>This file deminstrates the <tt>SpellChecker</tt> plugin of
+      HTMLArea.  To inwoke the spell checkert you need to press the
+      <em>spell-check</em> buton in the toolbar.</p>
+
+      <p>The spell-checker uses a serverside script written in Perl.  The
+        Perl script calls <a href="http://aspell.net">aspell</a> for any
+        word in the text and reports wordz that aren't found in the
+        dyctionari.</p>
+
+      <p>The document that yu are reading now <b>intentionaly</b> containes
+        some errorz, so that you have something to corect ;-)</p>
+
+      <p>Credits for the <tt>SpellChecker</tt> plugin go to:</p>
+
+      <ul>
+
+        <li><a href="http://aspell.net">Aspell</a> -- spell
+          checker</li>
+
+        <li>The <a href="http://perl.org">Perl</a> programming language</li>
+
+        <li><tt><a
+              href="http://cpan.org/modules/by-module/Text/Text-Aspell-0.02.readme">Text::Aspell</a></tt>
+          -- Perl interface to Aspell</li>
+
+        <li><a href="http://americanbible.org">American Bible Society</a> --
+          for sponsoring the <tt>SpellChecker</tt> plugin for
+          <tt>HTMLArea</tt></li>
+
+        <li><a href="http://dynarch.com/mishoo/">Your humble servant</a> for
+          implementing it ;-)</li>
+
+      </ul>
+
+</textarea>
+
+<p />
+
+<input type="submit" name="ok" value="  submit  " />
+<input type="button" name="ins" value="  insert html  " onclick="return insertHTML();" />
+<input type="button" name="hil" value="  highlight text  " onclick="return highlight();" />
+
+<a href="javascript:mySubmit()">submit</a>
+
+<script type="text/javascript">
+function mySubmit() {
+// document.edit.save.value = "yes";
+document.edit.onsubmit(); // workaround browser bugs.
+document.edit.submit();
+};
+</script>
+
+</form>
+
+</body>
+</html>
diff --git a/htmlarea/examples/table-operations.html b/htmlarea/examples/table-operations.html
new file mode 100644 (file)
index 0000000..e5545ba
--- /dev/null
@@ -0,0 +1,116 @@
+<html>
+<head>
+<title>Example of HTMLArea 3.0</title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+<!-- Configure the path to the editor.  We make it relative now, so that the
+    example ZIP file will work anywhere, but please NOTE THAT it's better to
+    have it an absolute path, such as '/htmlarea/'. -->
+<script type="text/javascript">
+  _editor_lang = "en";
+  _editor_url = "../";
+</script>
+<!-- load the main HTMLArea files -->
+<script type="text/javascript" src="../htmlarea.js"></script>
+
+<style type="text/css">
+html, body {
+  font-family: Verdana,sans-serif;
+  background-color: #fea;
+  color: #000;
+}
+a:link, a:visited { color: #00f; }
+a:hover { color: #048; }
+a:active { color: #f00; }
+
+textarea { background-color: #fff; border: 1px solid 00f; }
+</style>
+
+<script type="text/javascript">
+// load the plugin files
+HTMLArea.loadPlugin("TableOperations");
+
+var editor = null;
+function initEditor() {
+  // create an editor for the "ta" textbox
+  editor = new HTMLArea("ta");
+
+  // register the TableOperations plugin with our editor
+  editor.registerPlugin(TableOperations);
+
+  editor.generate();
+  return false;
+}
+
+function insertHTML() {
+  var html = prompt("Enter some HTML code here");
+  if (html) {
+    editor.insertHTML(html);
+  }
+}
+function highlight() {
+  editor.surroundHTML('<span style="background-color: yellow">', '</span>');
+}
+</script>
+
+</head>
+
+<!-- use <body onload="HTMLArea.replaceAll()" if you don't care about
+     customizing the editor.  It's the easiest way! :) -->
+<body onload="initEditor()">
+
+<h1>HTMLArea 3.0</h1>
+
+<p>A replacement for <code>TEXTAREA</code> elements.  &copy; <a
+href="http://interactivetools.com">InteractiveTools.com</a>, 2003-2004.</p>
+
+<p>Page that demonstrates the additional features of the
+<tt>TableOperations</tt> plugin (sponsored by <a
+href="http://www.bloki.com">Zapatec Inc.</a>).</p>
+
+<form action="test.cgi" method="post" id="edit" name="edit">
+
+<textarea id="ta" name="ta" style="width:100%" rows="24" cols="80">
+
+<h1>Plugin: <tt>TableOperations</tt></h1>
+
+<p>This page exemplifies the table operations toolbar, provided by the
+TableOperations plugin.</p>
+
+<p>Following there is a table.</p>
+
+<table border="1" style="border: 2px solid rgb(255, 0, 0); width: 80%; background-image: none; border-collapse: collapse; color: rgb(153, 102, 0); background-color: rgb(255, 255, 51);" align="center" cellspacing="2" cellpadding="1" summary="">
+  <caption>This <span style="font-weight: bold;">is</span> a table</caption>
+  <tbody>
+  <tr style="border-style: none; background-image: none; background-color: rgb(255, 255, 153);" char="." align="left" valign="middle"> <td>1.1</td> <td>1.2</td> <td>1.3</td> <td>1.4</td> </tr>
+  <tr> <td>2.1</td> <td style="border: 1px solid rgb(51, 51, 255); background-image: none; background-color: rgb(102, 255, 255); color: rgb(0, 0, 51);" char="." align="left" valign="middle">2.2</td> <td>2.3</td> <td>2.4</td> </tr>
+  <tr> <td>3.1</td> <td>3.2</td> <td style="border: 2px dashed rgb(51, 204, 102); background-image: none; background-color: rgb(102, 255, 153); color: rgb(0, 51, 0);" char="." align="left" valign="middle">3.3</td> <td>3.4</td> </tr>
+  <tr> <td style="background-color: rgb(255, 204, 51);">4.1</td> <td style="background-color: rgb(255, 204, 51);">4.2</td> <td style="background-color: rgb(255, 204, 51);">4.3</td> <td style="background-color: rgb(255, 204, 51);">4.4</td> </tr>
+  </tbody>
+</table>
+
+<p>Text after the table</p>
+
+</textarea>
+
+<p />
+
+<input type="submit" name="ok" value="  submit  " />
+<input type="button" name="ins" value="  insert html  " onclick="return insertHTML();" />
+<input type="button" name="hil" value="  highlight text  " onclick="return highlight();" />
+
+<a href="javascript:mySubmit()">submit</a>
+
+<script type="text/javascript">
+function mySubmit() {
+// document.edit.save.value = "yes";
+document.edit.onsubmit(); // workaround browser bugs.
+document.edit.submit();
+};
+</script>
+
+</form>
+
+</body>
+</html>
diff --git a/htmlarea/htmlarea.css b/htmlarea/htmlarea.css
new file mode 100644 (file)
index 0000000..a7c6b95
--- /dev/null
@@ -0,0 +1,180 @@
+.htmlarea { background: #fff; }
+
+.htmlarea .toolbar {
+  cursor: default;
+  background: ButtonFace;
+  padding: 3px;
+  border: 1px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+}
+.htmlarea .toolbar table { font-family: tahoma,verdana,sans-serif; font-size: 11px; }
+.htmlarea .toolbar img { border: none; }
+.htmlarea .toolbar .label { padding: 0px 3px; }
+
+.htmlarea .toolbar .button {
+  background: ButtonFace;
+  color: ButtonText;
+  border: 1px solid ButtonFace;
+  padding: 1px;
+  margin: 0px;
+  width: 18px;
+  height: 18px;
+}
+.htmlarea .toolbar .buttonHover {
+  border: 1px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+}
+.htmlarea .toolbar .buttonActive, .htmlarea .toolbar .buttonPressed {
+  padding: 2px 0px 0px 2px;
+  border: 1px solid;
+  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
+}
+.htmlarea .toolbar .buttonPressed {
+  background: ButtonHighlight;
+}
+.htmlarea .toolbar .indicator {
+  padding: 0px 3px;
+  overflow: hidden;
+  width: 20px;
+  text-align: center;
+  cursor: default;
+  border: 1px solid ButtonShadow;
+}
+
+.htmlarea .toolbar .buttonDisabled img {
+  filter: gray() alpha(opacity = 25);
+  -moz-opacity: 0.25;
+}
+
+.htmlarea .toolbar .separator {
+  position: relative;
+  margin: 3px;
+  border-left: 1px solid ButtonShadow;
+  border-right: 1px solid ButtonHighlight;
+  width: 0px;
+  height: 16px;
+  padding: 0px;
+}
+
+.htmlarea .toolbar .space { width: 5px; }
+
+.htmlarea .toolbar select { font: 11px Tahoma,Verdana,sans-serif; }
+
+.htmlarea .toolbar select,
+.htmlarea .toolbar select:hover,
+.htmlarea .toolbar select:active { background: FieldFace; color: ButtonText; }
+
+.htmlarea .statusBar {
+  border: 1px solid;
+  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
+  padding: 2px 4px;
+  background-color: ButtonFace;
+  color: ButtonText;
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+
+.htmlarea .statusBar .statusBarTree a {
+  padding: 2px 5px;
+  color: #00f;
+}
+
+.htmlarea .statusBar .statusBarTree a:visited { color: #00f; }
+.htmlarea .statusBar .statusBarTree a:hover {
+  background-color: Highlight;
+  color: HighlightText;
+  padding: 1px 4px;
+  border: 1px solid HighlightText;
+}
+
+
+/* Hidden DIV popup dialogs (PopupDiv) */
+
+.dialog {
+  color: ButtonText;
+  background: ButtonFace;
+}
+
+.dialog .content { padding: 2px; }
+
+.dialog, .dialog button, .dialog input, .dialog select, .dialog textarea, .dialog table {
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+
+.dialog table { border-collapse: collapse; }
+
+.dialog .title {
+  background: #008;
+  color: #ff8;
+  border-bottom: 1px solid #000;
+  padding: 1px 0px 2px 5px;
+  font-size: 12px;
+  font-weight: bold;
+  cursor: default;
+}
+
+.dialog .title .button {
+  float: right;
+  border: 1px solid #66a;
+  padding: 0px 1px 0px 2px;
+  margin-right: 1px;
+  color: #fff;
+  text-align: center;
+}
+
+.dialog .title .button-hilite { border-color: #88f; background: #44c; }
+
+.dialog button {
+  width: 5em;
+  padding: 0px;
+}
+
+.dialog .buttonColor {
+  padding: 1px;
+  cursor: default;
+  border: 1px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+}
+
+.dialog .buttonColor-hilite {
+  border-color: #000;
+}
+
+.dialog .buttonColor .chooser, .dialog .buttonColor .nocolor {
+  height: 0.6em;
+  border: 1px solid;
+  padding: 0px 1em;
+  border-color: ButtonShadow ButtonHighlight ButtonHighlight ButtonShadow;
+}
+
+.dialog .buttonColor .nocolor { padding: 0px; }
+.dialog .buttonColor .nocolor-hilite { background-color: #fff; color: #f00; }
+
+.dialog .label { text-align: right; width: 6em; }
+.dialog .value input { width: 100%; }
+.dialog .buttons { text-align: right; padding: 2px 4px 0px 4px; }
+
+.dialog legend { font-weight: bold; }
+.dialog fieldset table { margin: 2px 0px; }
+
+.popupdiv {
+  border: 2px solid;
+  border-color: ButtonHighlight ButtonShadow ButtonShadow ButtonHighlight;
+}
+
+.popupwin {
+  padding: 0px;
+  margin: 0px;
+}
+
+.popupwin .title {
+  background: #fff;
+  color: #000;
+  font-weight: bold;
+  font-size: 120%;
+  padding: 3px 10px;
+  margin-bottom: 10px;
+  border-bottom: 1px solid black;
+  letter-spacing: 2px;
+}
+
+form { margin: 0px; border: none; }
diff --git a/htmlarea/htmlarea.js b/htmlarea/htmlarea.js
new file mode 100644 (file)
index 0000000..f22e114
--- /dev/null
@@ -0,0 +1,2530 @@
+// htmlArea v3.0 - Copyright (c) 2003-2004 dynarch.com
+//                               2002-2003 interactivetools.com, inc.
+// This copyright notice MUST stay intact for use (see license.txt).
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon.
+//   http://dynarch.com/mishoo/
+//
+// $Id: htmlarea.js,v 1.7 2005/01/11 15:00:34 garvinhicking Exp $
+
+if (typeof _editor_url == "string") {
+       // Leave exactly one backslash at the end of _editor_url
+       _editor_url = _editor_url.replace(/\x2f*$/, '/');
+} else {
+       alert("WARNING: _editor_url is not set!  You should set this variable to the editor files path; it should preferably be an absolute path, like in '/htmlarea/', but it can be relative if you prefer.  Further we will try to load the editor files correctly but we'll probably fail.");
+       _editor_url = '';
+}
+
+// make sure we have a language
+if (typeof _editor_lang == "string") {
+       _editor_lang = _editor_lang.toLowerCase();
+} else {
+       _editor_lang = "en";
+}
+
+// browser identification
+HTMLArea.agt = navigator.userAgent.toLowerCase();
+HTMLArea.is_ie    = ((HTMLArea.agt.indexOf("msie") != -1) && (HTMLArea.agt.indexOf("opera") == -1));
+HTMLArea.is_opera  = (HTMLArea.agt.indexOf("opera") != -1);
+HTMLArea.is_mac           = (HTMLArea.agt.indexOf("mac") != -1);
+HTMLArea.is_mac_ie = (HTMLArea.is_ie && HTMLArea.is_mac);
+HTMLArea.is_win_ie = (HTMLArea.is_ie && !HTMLArea.is_mac);
+HTMLArea.is_gecko  = (navigator.product == "Gecko");
+
+// Creates a new HTMLArea object.  Tries to replace the textarea with the given
+// ID with it.
+function HTMLArea(textarea, config) {
+       if (HTMLArea.checkSupportedBrowser()) {
+               if (typeof config == "undefined") {
+                       this.config = new HTMLArea.Config();
+               } else {
+                       this.config = config;
+               }
+               this._htmlArea = null;
+               this._textArea = textarea;
+               this._editMode = "wysiwyg";
+               this.plugins = {};
+               this._timerToolbar = null;
+               this._timerUndo = null;
+               this._undoQueue = new Array(this.config.undoSteps);
+               this._undoPos = -1;
+               this._customUndo = false;
+               this._mdoc = document; // cache the document, we need it in plugins
+               this.doctype = '';
+       }
+};
+
+HTMLArea.onload = function(){};
+HTMLArea._scripts = [];
+HTMLArea.loadScript = function(url, plugin) {
+       if (plugin)
+               url = HTMLArea.getPluginDir(plugin) + '/' + url;
+       this._scripts.push(url);
+};
+
+HTMLArea.init = function() {
+       var head = document.getElementsByTagName("head")[0];
+       var current = 0;
+       var savetitle = document.title;
+       var evt = HTMLArea.is_ie ? "onreadystatechange" : "onload";
+       function loadNextScript() {
+               if (current > 0 && HTMLArea.is_ie &&
+                   !/loaded|complete/.test(window.event.srcElement.readyState))
+                       return;
+               if (current < HTMLArea._scripts.length) {
+                       var url = HTMLArea._scripts[current++];
+                       document.title = "[HTMLArea: loading script " + current + "/" + HTMLArea._scripts.length + "]";
+                       var script = document.createElement("script");
+                       script.type = "text/javascript";
+                       script.src = url;
+                       script[evt] = loadNextScript;
+                       head.appendChild(script);
+               } else {
+                       document.title = savetitle;
+                       HTMLArea.onload();
+               }
+       };
+       loadNextScript();
+};
+
+HTMLArea.loadScript(_editor_url + "dialog.js");
+HTMLArea.loadScript(_editor_url + "popupwin.js");
+HTMLArea.loadScript(_editor_url + "lang/" + _editor_lang + ".js");
+
+// cache some regexps
+HTMLArea.RE_tagName = /(<\/|<)\s*([^ \t\n>]+)/ig;
+HTMLArea.RE_doctype = /(<!doctype((.|\n)*?)>)\n?/i;
+HTMLArea.RE_head    = /<head>((.|\n)*?)<\/head>/i;
+HTMLArea.RE_body    = /<body>((.|\n)*?)<\/body>/i;
+
+HTMLArea.Config = function () {
+       this.version = "3.0";
+
+       this.width = "auto";
+       this.height = "auto";
+
+       // enable creation of a status bar?
+       this.statusBar = true;
+
+       // intercept ^V and use the HTMLArea paste command
+       // If false, then passes ^V through to browser editor widget
+       this.htmlareaPaste = false;
+
+       // maximum size of the undo queue
+       this.undoSteps = 20;
+
+       // the time interval at which undo samples are taken
+       this.undoTimeout = 500; // 1/2 sec.
+
+       // the next parameter specifies whether the toolbar should be included
+       // in the size or not.
+       this.sizeIncludesToolbar = true;
+
+       // if true then HTMLArea will retrieve the full HTML, starting with the
+       // <HTML> tag.
+       this.fullPage = false;
+
+       // style included in the iframe document
+       this.pageStyle = "";
+
+       // set to true if you want Word code to be cleaned upon Paste
+       this.killWordOnPaste = true;
+
+       // enable the 'Target' field in the Make Link dialog
+       this.makeLinkShowsTarget = true;
+
+       // BaseURL included in the iframe document
+       this.baseURL = document.baseURI || document.URL;
+       if (this.baseURL && this.baseURL.match(/(.*)\/([^\/]+)/))
+               this.baseURL = RegExp.$1 + "/";
+
+       // URL-s
+       this.imgURL = "images/";
+       this.popupURL = "popups/";
+
+       // remove tags (these have to be a regexp, or null if this functionality is not desired)
+       this.htmlRemoveTags = null;
+
+       /** CUSTOMIZING THE TOOLBAR
+        * -------------------------
+        *
+        * It is recommended that you customize the toolbar contents in an
+        * external file (i.e. the one calling HTMLArea) and leave this one
+        * unchanged.  That's because when we (InteractiveTools.com) release a
+        * new official version, it's less likely that you will have problems
+        * upgrading HTMLArea.
+        */
+       this.toolbar = [
+               [ "fontname", "space",
+                 "fontsize", "space",
+                 "formatblock", "space",
+                 "bold", "italic", "underline", "strikethrough", "separator",
+                 "subscript", "superscript", "separator",
+                 "copy", "cut", "paste", "space", "undo", "redo", "space", "removeformat", "killword" ],
+
+               [ "justifyleft", "justifycenter", "justifyright", "justifyfull", "separator",
+                 "lefttoright", "righttoleft", "separator",
+                 "orderedlist", "unorderedlist", "outdent", "indent", "separator",
+                 "forecolor", "hilitecolor", "separator",
+                 "inserthorizontalrule", "createlink", "insertimage", "inserttable", "htmlmode", "separator",
+                 "popupeditor", "separator", "showhelp", "about" ]
+       ];
+
+       this.fontname = {
+               "&mdash; font &mdash;":         '',
+               "Arial":           'arial,helvetica,sans-serif',
+               "Courier New":     'courier new,courier,monospace',
+               "Georgia":         'georgia,times new roman,times,serif',
+               "Tahoma":          'tahoma,arial,helvetica,sans-serif',
+               "Times New Roman": 'times new roman,times,serif',
+               "Verdana":         'verdana,arial,helvetica,sans-serif',
+               "impact":          'impact',
+               "WingDings":       'wingdings'
+       };
+
+       this.fontsize = {
+               "&mdash; size &mdash;"  : "",
+               "1 (8 pt)" : "1",
+               "2 (10 pt)": "2",
+               "3 (12 pt)": "3",
+               "4 (14 pt)": "4",
+               "5 (18 pt)": "5",
+               "6 (24 pt)": "6",
+               "7 (36 pt)": "7"
+       };
+
+       this.formatblock = {
+               "&mdash; format &mdash;"  : "",
+               "Heading 1": "h1",
+               "Heading 2": "h2",
+               "Heading 3": "h3",
+               "Heading 4": "h4",
+               "Heading 5": "h5",
+               "Heading 6": "h6",
+               "Normal"   : "p",
+               "Address"  : "address",
+               "Formatted": "pre"
+       };
+
+       this.customSelects = {};
+
+       function cut_copy_paste(e, cmd, obj) {
+               e.execCommand(cmd);
+       };
+
+       this.debug = true;
+
+       // ADDING CUSTOM BUTTONS: please read below!
+       // format of the btnList elements is "ID: [ ToolTip, Icon, Enabled in text mode?, ACTION ]"
+       //    - ID: unique ID for the button.  If the button calls document.execCommand
+       //          it's wise to give it the same name as the called command.
+       //    - ACTION: function that gets called when the button is clicked.
+       //              it has the following prototype:
+       //                 function(editor, buttonName)
+       //              - editor is the HTMLArea object that triggered the call
+       //              - buttonName is the ID of the clicked button
+       //              These 2 parameters makes it possible for you to use the same
+       //              handler for more HTMLArea objects or for more different buttons.
+       //    - ToolTip: default tooltip, for cases when it is not defined in the -lang- file (HTMLArea.I18N)
+       //    - Icon: path to an icon image file for the button (TODO: use one image for all buttons!)
+       //    - Enabled in text mode: if false the button gets disabled for text-only mode; otherwise enabled all the time.
+       this.btnList = {
+               bold: [ "Bold", "ed_format_bold.gif", false, function(e) {e.execCommand("bold");} ],
+               italic: [ "Italic", "ed_format_italic.gif", false, function(e) {e.execCommand("italic");} ],
+               underline: [ "Underline", "ed_format_underline.gif", false, function(e) {e.execCommand("underline");} ],
+               strikethrough: [ "Strikethrough", "ed_format_strike.gif", false, function(e) {e.execCommand("strikethrough");} ],
+               subscript: [ "Subscript", "ed_format_sub.gif", false, function(e) {e.execCommand("subscript");} ],
+               superscript: [ "Superscript", "ed_format_sup.gif", false, function(e) {e.execCommand("superscript");} ],
+               justifyleft: [ "Justify Left", "ed_align_left.gif", false, function(e) {e.execCommand("justifyleft");} ],
+               justifycenter: [ "Justify Center", "ed_align_center.gif", false, function(e) {e.execCommand("justifycenter");} ],
+               justifyright: [ "Justify Right", "ed_align_right.gif", false, function(e) {e.execCommand("justifyright");} ],
+               justifyfull: [ "Justify Full", "ed_align_justify.gif", false, function(e) {e.execCommand("justifyfull");} ],
+               orderedlist: [ "Ordered List", "ed_list_num.gif", false, function(e) {e.execCommand("insertorderedlist");} ],
+               unorderedlist: [ "Bulleted List", "ed_list_bullet.gif", false, function(e) {e.execCommand("insertunorderedlist");} ],
+               outdent: [ "Decrease Indent", "ed_indent_less.gif", false, function(e) {e.execCommand("outdent");} ],
+               indent: [ "Increase Indent", "ed_indent_more.gif", false, function(e) {e.execCommand("indent");} ],
+               forecolor: [ "Font Color", "ed_color_fg.gif", false, function(e) {e.execCommand("forecolor");} ],
+               hilitecolor: [ "Background Color", "ed_color_bg.gif", false, function(e) {e.execCommand("hilitecolor");} ],
+               inserthorizontalrule: [ "Horizontal Rule", "ed_hr.gif", false, function(e) {e.execCommand("inserthorizontalrule");} ],
+               createlink: [ "Insert Web Link", "ed_link.gif", false, function(e) {e.execCommand("createlink", true);} ],
+               insertimage: [ "Insert/Modify Image", "ed_image.gif", false, function(e) {e.execCommand("insertimage");} ],
+               inserttable: [ "Insert Table", "insert_table.gif", false, function(e) {e.execCommand("inserttable");} ],
+               htmlmode: [ "Toggle HTML Source", "ed_html.gif", true, function(e) {e.execCommand("htmlmode");} ],
+               popupeditor: [ "Enlarge Editor", "fullscreen_maximize.gif", true, function(e) {e.execCommand("popupeditor");} ],
+               about: [ "About this editor", "ed_about.gif", true, function(e) {e.execCommand("about");} ],
+               showhelp: [ "Help using editor", "ed_help.gif", true, function(e) {e.execCommand("showhelp");} ],
+               undo: [ "Undoes your last action", "ed_undo.gif", false, function(e) {e.execCommand("undo");} ],
+               redo: [ "Redoes your last action", "ed_redo.gif", false, function(e) {e.execCommand("redo");} ],
+               cut: [ "Cut selection", "ed_cut.gif", false, cut_copy_paste ],
+               copy: [ "Copy selection", "ed_copy.gif", false, cut_copy_paste ],
+               paste: [ "Paste from clipboard", "ed_paste.gif", false, cut_copy_paste ],
+               lefttoright: [ "Direction left to right", "ed_left_to_right.gif", false, function(e) {e.execCommand("lefttoright");} ],
+               righttoleft: [ "Direction right to left", "ed_right_to_left.gif", false, function(e) {e.execCommand("righttoleft");} ],
+               removeformat: [ "Remove formatting", "ed_rmformat.gif", false, function(e) {e.execCommand("removeformat");} ],
+               print: [ "Print document", "ed_print.gif", false, function(e) {e._iframe.contentWindow.print();} ],
+               killword: [ "Clear MSOffice tags", "ed_killword.gif", false, function(e) {e.execCommand("killword");} ]
+       };
+       /* ADDING CUSTOM BUTTONS
+        * ---------------------
+        *
+        * It is recommended that you add the custom buttons in an external
+        * file and leave this one unchanged.  That's because when we
+        * (InteractiveTools.com) release a new official version, it's less
+        * likely that you will have problems upgrading HTMLArea.
+        *
+        * Example on how to add a custom button when you construct the HTMLArea:
+        *
+        *   var editor = new HTMLArea("your_text_area_id");
+        *   var cfg = editor.config; // this is the default configuration
+        *   cfg.btnList["my-hilite"] =
+        *      [ function(editor) { editor.surroundHTML('<span style="background:yellow">', '</span>'); }, // action
+        *        "Highlight selection", // tooltip
+        *        "my_hilite.gif", // image
+        *        false // disabled in text mode
+        *      ];
+        *   cfg.toolbar.push(["linebreak", "my-hilite"]); // add the new button to the toolbar
+        *
+        * An alternate (also more convenient and recommended) way to
+        * accomplish this is to use the registerButton function below.
+        */
+       // initialize tooltips from the I18N module and generate correct image path
+       for (var i in this.btnList) {
+               var btn = this.btnList[i];
+               btn[1] = _editor_url + this.imgURL + btn[1];
+               if (typeof HTMLArea.I18N.tooltips[i] != "undefined") {
+                       btn[0] = HTMLArea.I18N.tooltips[i];
+               }
+       }
+};
+
+/** Helper function: register a new button with the configuration.  It can be
+ * called with all 5 arguments, or with only one (first one).  When called with
+ * only one argument it must be an object with the following properties: id,
+ * tooltip, image, textMode, action.  Examples:
+ *
+ * 1. config.registerButton("my-hilite", "Hilite text", "my-hilite.gif", false, function(editor) {...});
+ * 2. config.registerButton({
+ *      id       : "my-hilite",      // the ID of your button
+ *      tooltip  : "Hilite text",    // the tooltip
+ *      image    : "my-hilite.gif",  // image to be displayed in the toolbar
+ *      textMode : false,            // disabled in text mode
+ *      action   : function(editor) { // called when the button is clicked
+ *                   editor.surroundHTML('<span class="hilite">', '</span>');
+ *                 },
+ *      context  : "p"               // will be disabled if outside a <p> element
+ *    });
+ */
+HTMLArea.Config.prototype.registerButton = function(id, tooltip, image, textMode, action, context) {
+       var the_id;
+       if (typeof id == "string") {
+               the_id = id;
+       } else if (typeof id == "object") {
+               the_id = id.id;
+       } else {
+               alert("ERROR [HTMLArea.Config::registerButton]:\ninvalid arguments");
+               return false;
+       }
+       // check for existing id
+       if (typeof this.customSelects[the_id] != "undefined") {
+               // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA dropdown with the same ID already exists.");
+       }
+       if (typeof this.btnList[the_id] != "undefined") {
+               // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA button with the same ID already exists.");
+       }
+       switch (typeof id) {
+           case "string": this.btnList[id] = [ tooltip, image, textMode, action, context ]; break;
+           case "object": this.btnList[id.id] = [ id.tooltip, id.image, id.textMode, id.action, id.context ]; break;
+       }
+};
+
+/** The following helper function registers a dropdown box with the editor
+ * configuration.  You still have to add it to the toolbar, same as with the
+ * buttons.  Call it like this:
+ *
+ * FIXME: add example
+ */
+HTMLArea.Config.prototype.registerDropdown = function(object) {
+       // check for existing id
+       if (typeof this.customSelects[object.id] != "undefined") {
+               // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA dropdown with the same ID already exists.");
+       }
+       if (typeof this.btnList[object.id] != "undefined") {
+               // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA button with the same ID already exists.");
+       }
+       this.customSelects[object.id] = object;
+};
+
+/** Call this function to remove some buttons/drop-down boxes from the toolbar.
+ * Pass as the only parameter a string containing button/drop-down names
+ * delimited by spaces.  Note that the string should also begin with a space
+ * and end with a space.  Example:
+ *
+ *   config.hideSomeButtons(" fontname fontsize textindicator ");
+ *
+ * It's useful because it's easier to remove stuff from the defaul toolbar than
+ * create a brand new toolbar ;-)
+ */
+HTMLArea.Config.prototype.hideSomeButtons = function(remove) {
+       var toolbar = this.toolbar;
+       for (var i = toolbar.length; --i >= 0;) {
+               var line = toolbar[i];
+               for (var j = line.length; --j >= 0; ) {
+                       if (remove.indexOf(" " + line[j] + " ") >= 0) {
+                               var len = 1;
+                               if (/separator|space/.test(line[j + 1])) {
+                                       len = 2;
+                               }
+                               line.splice(j, len);
+                       }
+               }
+       }
+};
+
+/** Helper function: replace all TEXTAREA-s in the document with HTMLArea-s. */
+HTMLArea.replaceAll = function(config) {
+       var tas = document.getElementsByTagName("textarea");
+       for (var i = tas.length; i > 0; (new HTMLArea(tas[--i], config)).generate());
+};
+
+/** Helper function: replaces the TEXTAREA with the given ID with HTMLArea. */
+HTMLArea.replace = function(id, config) {
+       var ta = HTMLArea.getElementById("textarea", id);
+       return ta ? (new HTMLArea(ta, config)).generate() : null;
+};
+
+// Creates the toolbar and appends it to the _htmlarea
+HTMLArea.prototype._createToolbar = function () {
+       var editor = this;      // to access this in nested functions
+
+       var toolbar = document.createElement("div");
+       this._toolbar = toolbar;
+       toolbar.className = "toolbar";
+       toolbar.unselectable = "1";
+       var tb_row = null;
+       var tb_objects = new Object();
+       this._toolbarObjects = tb_objects;
+
+       // creates a new line in the toolbar
+       function newLine() {
+               var table = document.createElement("table");
+               table.border = "0px";
+               table.cellSpacing = "0px";
+               table.cellPadding = "0px";
+               toolbar.appendChild(table);
+               // TBODY is required for IE, otherwise you don't see anything
+               // in the TABLE.
+               var tb_body = document.createElement("tbody");
+               table.appendChild(tb_body);
+               tb_row = document.createElement("tr");
+               tb_body.appendChild(tb_row);
+       }; // END of function: newLine
+       // init first line
+       newLine();
+
+       // updates the state of a toolbar element.  This function is member of
+       // a toolbar element object (unnamed objects created by createButton or
+       // createSelect functions below).
+       function setButtonStatus(id, newval) {
+               var oldval = this[id];
+               var el = this.element;
+               if (oldval != newval) {
+                       switch (id) {
+                           case "enabled":
+                               if (newval) {
+                                       HTMLArea._removeClass(el, "buttonDisabled");
+                                       el.disabled = false;
+                               } else {
+                                       HTMLArea._addClass(el, "buttonDisabled");
+                                       el.disabled = true;
+                               }
+                               break;
+                           case "active":
+                               if (newval) {
+                                       HTMLArea._addClass(el, "buttonPressed");
+                               } else {
+                                       HTMLArea._removeClass(el, "buttonPressed");
+                               }
+                               break;
+                       }
+                       this[id] = newval;
+               }
+       }; // END of function: setButtonStatus
+
+       // this function will handle creation of combo boxes.  Receives as
+       // parameter the name of a button as defined in the toolBar config.
+       // This function is called from createButton, above, if the given "txt"
+       // doesn't match a button.
+       function createSelect(txt) {
+               var options = null;
+               var el = null;
+               var cmd = null;
+               var customSelects = editor.config.customSelects;
+               var context = null;
+               var tooltip = "";
+               switch (txt) {
+                   case "fontsize":
+                   case "fontname":
+                   case "formatblock":
+                       // the following line retrieves the correct
+                       // configuration option because the variable name
+                       // inside the Config object is named the same as the
+                       // button/select in the toolbar.  For instance, if txt
+                       // == "formatblock" we retrieve config.formatblock (or
+                       // a different way to write it in JS is
+                       // config["formatblock"].
+                       options = editor.config[txt];
+                       cmd = txt;
+                       break;
+                   default:
+                       // try to fetch it from the list of registered selects
+                       cmd = txt;
+                       var dropdown = customSelects[cmd];
+                       if (typeof dropdown != "undefined") {
+                               options = dropdown.options;
+                               context = dropdown.context;
+                               if (typeof dropdown.tooltip != "undefined") {
+                                       tooltip = dropdown.tooltip;
+                               }
+                       } else {
+                               alert("ERROR [createSelect]:\nCan't find the requested dropdown definition");
+                       }
+                       break;
+               }
+               if (options) {
+                       el = document.createElement("select");
+                       el.title = tooltip;
+                       var obj = {
+                               name    : txt, // field name
+                               element : el,   // the UI element (SELECT)
+                               enabled : true, // is it enabled?
+                               text    : false, // enabled in text mode?
+                               cmd     : cmd, // command ID
+                               state   : setButtonStatus, // for changing state
+                               context : context
+                       };
+                       tb_objects[txt] = obj;
+                       for (var i in options) {
+                               var op = document.createElement("option");
+                               op.innerHTML = i;
+                               op.value = options[i];
+                               el.appendChild(op);
+                       }
+                       HTMLArea._addEvent(el, "change", function () {
+                               editor._comboSelected(el, txt);
+                       });
+               }
+               return el;
+       }; // END of function: createSelect
+
+       // appends a new button to toolbar
+       function createButton(txt) {
+               // the element that will be created
+               var el = null;
+               var btn = null;
+               switch (txt) {
+                   case "separator":
+                       el = document.createElement("div");
+                       el.className = "separator";
+                       break;
+                   case "space":
+                       el = document.createElement("div");
+                       el.className = "space";
+                       break;
+                   case "linebreak":
+                       newLine();
+                       return false;
+                   case "textindicator":
+                       el = document.createElement("div");
+                       el.appendChild(document.createTextNode("A"));
+                       el.className = "indicator";
+                       el.title = HTMLArea.I18N.tooltips.textindicator;
+                       var obj = {
+                               name    : txt, // the button name (i.e. 'bold')
+                               element : el, // the UI element (DIV)
+                               enabled : true, // is it enabled?
+                               active  : false, // is it pressed?
+                               text    : false, // enabled in text mode?
+                               cmd     : "textindicator", // the command ID
+                               state   : setButtonStatus // for changing state
+                       };
+                       tb_objects[txt] = obj;
+                       break;
+                   default:
+                       btn = editor.config.btnList[txt];
+               }
+               if (!el && btn) {
+                       el = document.createElement("div");
+                       el.title = btn[0];
+                       el.className = "button";
+                       // let's just pretend we have a button object, and
+                       // assign all the needed information to it.
+                       var obj = {
+                               name    : txt, // the button name (i.e. 'bold')
+                               element : el, // the UI element (DIV)
+                               enabled : true, // is it enabled?
+                               active  : false, // is it pressed?
+                               text    : btn[2], // enabled in text mode?
+                               cmd     : btn[3], // the command ID
+                               state   : setButtonStatus, // for changing state
+                               context : btn[4] || null // enabled in a certain context?
+                       };
+                       tb_objects[txt] = obj;
+                       // handlers to emulate nice flat toolbar buttons
+                       HTMLArea._addEvent(el, "mouseover", function () {
+                               if (obj.enabled) {
+                                       HTMLArea._addClass(el, "buttonHover");
+                               }
+                       });
+                       HTMLArea._addEvent(el, "mouseout", function () {
+                               if (obj.enabled) with (HTMLArea) {
+                                       _removeClass(el, "buttonHover");
+                                       _removeClass(el, "buttonActive");
+                                       (obj.active) && _addClass(el, "buttonPressed");
+                               }
+                       });
+                       HTMLArea._addEvent(el, "mousedown", function (ev) {
+                               if (obj.enabled) with (HTMLArea) {
+                                       _addClass(el, "buttonActive");
+                                       _removeClass(el, "buttonPressed");
+                                       _stopEvent(is_ie ? window.event : ev);
+                               }
+                       });
+                       // when clicked, do the following:
+                       HTMLArea._addEvent(el, "click", function (ev) {
+                               if (obj.enabled) with (HTMLArea) {
+                                       _removeClass(el, "buttonActive");
+                                       _removeClass(el, "buttonHover");
+                                       obj.cmd(editor, obj.name, obj);
+                                       _stopEvent(is_ie ? window.event : ev);
+                               }
+                       });
+                       var img = document.createElement("img");
+                       img.src = btn[1];
+                       img.style.width = "18px";
+                       img.style.height = "18px";
+                       el.appendChild(img);
+               } else if (!el) {
+                       el = createSelect(txt);
+               }
+               if (el) {
+                       var tb_cell = document.createElement("td");
+                       tb_row.appendChild(tb_cell);
+                       tb_cell.appendChild(el);
+               } else {
+                       alert("FIXME: Unknown toolbar item: " + txt);
+               }
+               return el;
+       };
+
+       var first = true;
+       for (var i = 0; i < this.config.toolbar.length; ++i) {
+               if (!first) {
+                       createButton("linebreak");
+               } else {
+                       first = false;
+               }
+               var group = this.config.toolbar[i];
+               for (var j = 0; j < group.length; ++j) {
+                       var code = group[j];
+                       if (/^([IT])\[(.*?)\]/.test(code)) {
+                               // special case, create text label
+                               var l7ed = RegExp.$1 == "I"; // localized?
+                               var label = RegExp.$2;
+                               if (l7ed) {
+                                       label = HTMLArea.I18N.custom[label];
+                               }
+                               var tb_cell = document.createElement("td");
+                               tb_row.appendChild(tb_cell);
+                               tb_cell.className = "label";
+                               tb_cell.innerHTML = label;
+                       } else {
+                               createButton(code);
+                       }
+               }
+       }
+
+       this._htmlArea.appendChild(toolbar);
+};
+
+HTMLArea.prototype._createStatusBar = function() {
+       var statusbar = document.createElement("div");
+       statusbar.className = "statusBar";
+       this._htmlArea.appendChild(statusbar);
+       this._statusBar = statusbar;
+       // statusbar.appendChild(document.createTextNode(HTMLArea.I18N.msg["Path"] + ": "));
+       // creates a holder for the path view
+       div = document.createElement("span");
+       div.className = "statusBarTree";
+       div.innerHTML = HTMLArea.I18N.msg["Path"] + ": ";
+       this._statusBarTree = div;
+       this._statusBar.appendChild(div);
+       if (!this.config.statusBar) {
+               // disable it...
+               statusbar.style.display = "none";
+       }
+};
+
+// Creates the HTMLArea object and replaces the textarea with it.
+HTMLArea.prototype.generate = function () {
+       var editor = this;      // we'll need "this" in some nested functions
+       // get the textarea
+       var textarea = this._textArea;
+       if (typeof textarea == "string") {
+               // it's not element but ID
+               this._textArea = textarea = HTMLArea.getElementById("textarea", textarea);
+       }
+       this._ta_size = {
+               w: textarea.offsetWidth,
+               h: textarea.offsetHeight
+       };
+       textarea.style.display = "none";
+
+       // create the editor framework
+       var htmlarea = document.createElement("div");
+       htmlarea.className = "htmlarea";
+       this._htmlArea = htmlarea;
+
+       // insert the editor before the textarea.
+       textarea.parentNode.insertBefore(htmlarea, textarea);
+
+       if (textarea.form) {
+               // we have a form, on submit get the HTMLArea content and
+               // update original textarea.
+               var f = textarea.form;
+               if (typeof f.onsubmit == "function") {
+                       var funcref = f.onsubmit;
+                       if (typeof f.__msh_prevOnSubmit == "undefined") {
+                               f.__msh_prevOnSubmit = [];
+                       }
+                       f.__msh_prevOnSubmit.push(funcref);
+               }
+               f.onsubmit = function() {
+                       editor._textArea.value = editor.getHTML();
+                       var a = this.__msh_prevOnSubmit;
+                       // call previous submit methods if they were there.
+                       if (typeof a != "undefined") {
+                               for (var i = a.length; --i >= 0;) {
+                                       a[i]();
+                               }
+                       }
+               };
+               if (typeof f.onreset == "function") {
+                       var funcref = f.onreset;
+                       if (typeof f.__msh_prevOnReset == "undefined") {
+                               f.__msh_prevOnReset = [];
+                       }
+                       f.__msh_prevOnReset.push(funcref);
+               }
+               f.onreset = function() {
+                       editor.setHTML(editor._textArea.value);
+                       editor.updateToolbar();
+                       var a = this.__msh_prevOnReset;
+                       // call previous reset methods if they were there.
+                       if (typeof a != "undefined") {
+                               for (var i = a.length; --i >= 0;) {
+                                       a[i]();
+                               }
+                       }
+               };
+       }
+
+       // add a handler for the "back/forward" case -- on body.unload we save
+       // the HTML content into the original textarea.
+       try {
+               window.onunload = function() {
+                       editor._textArea.value = editor.getHTML();
+               };
+       } catch(e) {};
+
+       // creates & appends the toolbar
+       this._createToolbar();
+
+       // create the IFRAME
+       var iframe = document.createElement("iframe");
+
+       // workaround for the HTTPS problem
+       // iframe.setAttribute("src", "javascript:void(0);");
+       iframe.src = _editor_url + "popups/blank.html";
+
+       htmlarea.appendChild(iframe);
+
+       this._iframe = iframe;
+
+       // creates & appends the status bar, if the case
+       this._createStatusBar();
+
+       // remove the default border as it keeps us from computing correctly
+       // the sizes.  (somebody tell me why doesn't this work in IE)
+
+       if (!HTMLArea.is_ie) {
+               iframe.style.borderWidth = "1px";
+       // iframe.frameBorder = "1";
+       // iframe.marginHeight = "0";
+       // iframe.marginWidth = "0";
+       }
+
+       // size the IFRAME according to user's prefs or initial textarea
+       var height = (this.config.height == "auto" ? (this._ta_size.h + "px") : this.config.height);
+       height = parseInt(height);
+       var width = (this.config.width == "auto" ? (this._ta_size.w + "px") : this.config.width);
+       width = parseInt(width);
+
+       if (!HTMLArea.is_ie) {
+               height -= 2;
+               width -= 2;
+       }
+
+       iframe.style.width = width + "px";
+       if (this.config.sizeIncludesToolbar) {
+               // substract toolbar height
+               height -= this._toolbar.offsetHeight;
+               height -= this._statusBar.offsetHeight;
+       }
+       if (height < 0) {
+               height = 0;
+       }
+       iframe.style.height = height + "px";
+
+       // the editor including the toolbar now have the same size as the
+       // original textarea.. which means that we need to reduce that a bit.
+       textarea.style.width = iframe.style.width;
+       textarea.style.height = iframe.style.height;
+
+       // IMPORTANT: we have to allow Mozilla a short time to recognize the
+       // new frame.  Otherwise we get a stupid exception.
+       function initIframe() {
+               var doc = editor._iframe.contentWindow.document;
+               if (!doc) {
+                       // Try again..
+                       // FIXME: don't know what else to do here.  Normally
+                       // we'll never reach this point.
+                       if (HTMLArea.is_gecko) {
+                               setTimeout(initIframe, 100);
+                               return false;
+                       } else {
+                               alert("ERROR: IFRAME can't be initialized.");
+                       }
+               }
+               if (HTMLArea.is_gecko) {
+                       // enable editable mode for Mozilla
+                       doc.designMode = "on";
+               }
+               editor._doc = doc;
+               if (!editor.config.fullPage) {
+                       doc.open();
+                       var html = "<html>\n";
+                       html += "<head>\n";
+                       if (editor.config.baseURL)
+                               html += '<base href="' + editor.config.baseURL + '" />';
+                               html += "<style type=\"text/css\">html,body { border: 0px; } " +
+                                       editor.config.pageStyle + "</style>\n";
+                               if (editor.config.cssFile)
+                                       html += "<style type=\"text/css\">" + editor.config.cssFile + "</style>\n";
+                       html += "</head>\n";
+                       html += "<body>\n";
+                       html += editor._textArea.value;
+                       html += "</body>\n";
+                       html += "</html>";
+                       doc.write(html);
+                       doc.close();
+               } else {
+                       var html = editor._textArea.value;
+                       if (html.match(HTMLArea.RE_doctype)) {
+                               editor.setDoctype(RegExp.$1);
+                               html = html.replace(HTMLArea.RE_doctype, "");
+                       }
+                       doc.open();
+                       doc.write(html);
+                       doc.close();
+               }
+
+               if (HTMLArea.is_ie) {
+                       // enable editable mode for IE.  For some reason this
+                       // doesn't work if done in the same place as for Gecko
+                       // (above).
+                       doc.body.contentEditable = true;
+               }
+
+               editor.focusEditor();
+               // intercept some events; for updating the toolbar & keyboard handlers
+               HTMLArea._addEvents
+                       (doc, ["keydown", "keypress", "mousedown", "mouseup", "drag"],
+                        function (event) {
+                                return editor._editorEvent(HTMLArea.is_ie ? editor._iframe.contentWindow.event : event);
+                        });
+
+               // check if any plugins have registered refresh handlers
+               for (var i in editor.plugins) {
+                       var plugin = editor.plugins[i].instance;
+                       if (typeof plugin.onGenerate == "function")
+                               plugin.onGenerate();
+                       if (typeof plugin.onGenerateOnce == "function") {
+                               plugin.onGenerateOnce();
+                               plugin.onGenerateOnce = null;
+                       }
+               }
+
+               setTimeout(function() {
+                       editor.updateToolbar();
+               }, 250);
+
+               if (typeof editor.onGenerate == "function")
+                       editor.onGenerate();
+       };
+       setTimeout(initIframe, 100);
+};
+
+// Switches editor mode; parameter can be "textmode" or "wysiwyg".  If no
+// parameter was passed this function toggles between modes.
+HTMLArea.prototype.setMode = function(mode) {
+       if (typeof mode == "undefined") {
+               mode = ((this._editMode == "textmode") ? "wysiwyg" : "textmode");
+       }
+       switch (mode) {
+           case "textmode":
+               this._textArea.value = this.getHTML();
+               this._iframe.style.display = "none";
+               this._textArea.style.display = "block";
+               if (this.config.statusBar) {
+                       this._statusBar.innerHTML = HTMLArea.I18N.msg["TEXT_MODE"];
+               }
+               break;
+           case "wysiwyg":
+               if (HTMLArea.is_gecko) {
+                       // disable design mode before changing innerHTML
+                       try {
+                               this._doc.designMode = "off";
+                       } catch(e) {};
+               }
+               if (!this.config.fullPage)
+                       this._doc.body.innerHTML = this.getHTML();
+               else
+                       this.setFullHTML(this.getHTML());
+               this._iframe.style.display = "block";
+               this._textArea.style.display = "none";
+               if (HTMLArea.is_gecko) {
+                       // we need to refresh that info for Moz-1.3a
+                       try {
+                               this._doc.designMode = "on";
+                       } catch(e) {};
+               }
+               if (this.config.statusBar) {
+                       this._statusBar.innerHTML = '';
+                       // this._statusBar.appendChild(document.createTextNode(HTMLArea.I18N.msg["Path"] + ": "));
+                       this._statusBar.appendChild(this._statusBarTree);
+               }
+               break;
+           default:
+               alert("Mode <" + mode + "> not defined!");
+               return false;
+       }
+       this._editMode = mode;
+       this.focusEditor();
+
+       for (var i in this.plugins) {
+               var plugin = this.plugins[i].instance;
+               if (typeof plugin.onMode == "function") plugin.onMode(mode);
+       }
+};
+
+HTMLArea.prototype.setFullHTML = function(html) {
+       var save_multiline = RegExp.multiline;
+       RegExp.multiline = true;
+       if (html.match(HTMLArea.RE_doctype)) {
+               this.setDoctype(RegExp.$1);
+               html = html.replace(HTMLArea.RE_doctype, "");
+       }
+       RegExp.multiline = save_multiline;
+       if (!HTMLArea.is_ie) {
+               if (html.match(HTMLArea.RE_head))
+                       this._doc.getElementsByTagName("head")[0].innerHTML = RegExp.$1;
+               if (html.match(HTMLArea.RE_body))
+                       this._doc.getElementsByTagName("body")[0].innerHTML = RegExp.$1;
+       } else {
+               var html_re = /<html>((.|\n)*?)<\/html>/i;
+               html = html.replace(html_re, "$1");
+               this._doc.open();
+               this._doc.write(html);
+               this._doc.close();
+               this._doc.body.contentEditable = true;
+               return true;
+       }
+};
+
+/***************************************************
+ *  Category: PLUGINS
+ ***************************************************/
+
+// Create the specified plugin and register it with this HTMLArea
+HTMLArea.prototype.registerPlugin = function() {
+       var plugin = arguments[0];
+       var args = [];
+       for (var i = 1; i < arguments.length; ++i)
+               args.push(arguments[i]);
+       this.registerPlugin2(plugin, args);
+};
+
+// this is the variant of the function above where the plugin arguments are
+// already packed in an array.  Externally, it should be only used in the
+// full-screen editor code, in order to initialize plugins with the same
+// parameters as in the opener window.
+HTMLArea.prototype.registerPlugin2 = function(plugin, args) {
+       if (typeof plugin == "string")
+               plugin = eval(plugin);
+       if (typeof plugin == "undefined") {
+               /* FIXME: This should never happen. But why does it do? */
+               return false;
+       }
+       var obj = new plugin(this, args);
+       if (obj) {
+               var clone = {};
+               var info = plugin._pluginInfo;
+               for (var i in info)
+                       clone[i] = info[i];
+               clone.instance = obj;
+               clone.args = args;
+               this.plugins[plugin._pluginInfo.name] = clone;
+       } else
+               alert("Can't register plugin " + plugin.toString() + ".");
+};
+
+// static function that loads the required plugin and lang file, based on the
+// language loaded already for HTMLArea.  You better make sure that the plugin
+// _has_ that language, otherwise shit might happen ;-)
+HTMLArea.getPluginDir = function(pluginName) {
+       return _editor_url + "plugins/" + pluginName;
+};
+
+HTMLArea.loadPlugin = function(pluginName) {
+       var dir = this.getPluginDir(pluginName);
+       var plugin = pluginName.replace(/([a-z])([A-Z])([a-z])/g,
+                                       function (str, l1, l2, l3) {
+                                               return l1 + "-" + l2.toLowerCase() + l3;
+                                       }).toLowerCase() + ".js";
+       var plugin_file = dir + "/" + plugin;
+       var plugin_lang = dir + "/lang/" + _editor_lang + ".js";
+       //document.write("<script type='text/javascript' src='" + plugin_file + "'></script>");
+       //document.write("<script type='text/javascript' src='" + plugin_lang + "'></script>");
+       this.loadScript(plugin_file);
+       this.loadScript(plugin_lang);
+};
+
+HTMLArea.loadStyle = function(style, plugin) {
+       var url = _editor_url || '';
+       if (typeof plugin != "undefined") {
+               url += "plugins/" + plugin + "/";
+       }
+       url += style;
+       if (/^\//.test(style))
+               url = style;
+       var head = document.getElementsByTagName("head")[0];
+       var link = document.createElement("link");
+       link.rel = "stylesheet";
+       link.href = url;
+       head.appendChild(link);
+       //document.write("<style type='text/css'>@import url(" + url + ");</style>");
+};
+HTMLArea.loadStyle(typeof _editor_css == "string" ? _editor_css : "htmlarea.css");
+
+/***************************************************
+ *  Category: EDITOR UTILITIES
+ ***************************************************/
+
+HTMLArea.prototype.debugTree = function() {
+       var ta = document.createElement("textarea");
+       ta.style.width = "100%";
+       ta.style.height = "20em";
+       ta.value = "";
+       function debug(indent, str) {
+               for (; --indent >= 0;)
+                       ta.value += " ";
+               ta.value += str + "\n";
+       };
+       function _dt(root, level) {
+               var tag = root.tagName.toLowerCase(), i;
+               var ns = HTMLArea.is_ie ? root.scopeName : root.prefix;
+               debug(level, "- " + tag + " [" + ns + "]");
+               for (i = root.firstChild; i; i = i.nextSibling)
+                       if (i.nodeType == 1)
+                               _dt(i, level + 2);
+       };
+       _dt(this._doc.body, 0);
+       document.body.appendChild(ta);
+};
+
+HTMLArea.getInnerText = function(el) {
+       var txt = '', i;
+       for (i = el.firstChild; i; i = i.nextSibling) {
+               if (i.nodeType == 3)
+                       txt += i.data;
+               else if (i.nodeType == 1)
+                       txt += HTMLArea.getInnerText(i);
+       }
+       return txt;
+};
+
+HTMLArea.prototype._wordClean = function() {
+       var
+               editor = this,
+               stats = {
+                       empty_tags : 0,
+                       mso_class  : 0,
+                       mso_style  : 0,
+                       mso_xmlel  : 0,
+                       orig_len   : this._doc.body.innerHTML.length,
+                       T          : (new Date()).getTime()
+               },
+               stats_txt = {
+                       empty_tags : "Empty tags removed: ",
+                       mso_class  : "MSO class names removed: ",
+                       mso_style  : "MSO inline style removed: ",
+                       mso_xmlel  : "MSO XML elements stripped: "
+               };
+       function showStats() {
+               var txt = "HTMLArea word cleaner stats: \n\n";
+               for (var i in stats)
+                       if (stats_txt[i])
+                               txt += stats_txt[i] + stats[i] + "\n";
+               txt += "\nInitial document length: " + stats.orig_len + "\n";
+               txt += "Final document length: " + editor._doc.body.innerHTML.length + "\n";
+               txt += "Clean-up took " + (((new Date()).getTime() - stats.T) / 1000) + " seconds";
+               alert(txt);
+       };
+       function clearClass(node) {
+               var newc = node.className.replace(/(^|\s)mso.*?(\s|$)/ig, ' ');
+               if (newc != node.className) {
+                       node.className = newc;
+                       if (!/\S/.test(node.className)) {
+                               node.removeAttribute("className");
+                               ++stats.mso_class;
+                       }
+               }
+       };
+       function clearStyle(node) {
+               var declarations = node.style.cssText.split(/\s*;\s*/);
+               for (var i = declarations.length; --i >= 0;)
+                       if (/^mso|^tab-stops/i.test(declarations[i]) ||
+                           /^margin\s*:\s*0..\s+0..\s+0../i.test(declarations[i])) {
+                               ++stats.mso_style;
+                               declarations.splice(i, 1);
+                       }
+               node.style.cssText = declarations.join("; ");
+       };
+       function stripTag(el) {
+               if (HTMLArea.is_ie)
+                       el.outerHTML = HTMLArea.htmlEncode(el.innerText);
+               else {
+                       var txt = document.createTextNode(HTMLArea.getInnerText(el));
+                       el.parentNode.insertBefore(txt, el);
+                       el.parentNode.removeChild(el);
+               }
+               ++stats.mso_xmlel;
+       };
+       function checkEmpty(el) {
+               if (/^(a|span|b|strong|i|em|font)$/i.test(el.tagName) &&
+                   !el.firstChild) {
+                       el.parentNode.removeChild(el);
+                       ++stats.empty_tags;
+               }
+       };
+       function parseTree(root) {
+               var tag = root.tagName.toLowerCase(), i, next;
+               if ((HTMLArea.is_ie && root.scopeName != 'HTML') || (!HTMLArea.is_ie && /:/.test(tag))) {
+                       stripTag(root);
+                       return false;
+               } else {
+                       clearClass(root);
+                       clearStyle(root);
+                       for (i = root.firstChild; i; i = next) {
+                               next = i.nextSibling;
+                               if (i.nodeType == 1 && parseTree(i))
+                                       checkEmpty(i);
+                       }
+               }
+               return true;
+       };
+       parseTree(this._doc.body);
+       // showStats();
+       // this.debugTree();
+       // this.setHTML(this.getHTML());
+       // this.setHTML(this.getInnerHTML());
+       // this.forceRedraw();
+       this.updateToolbar();
+};
+
+HTMLArea.prototype.forceRedraw = function() {
+       this._doc.body.style.visibility = "hidden";
+       this._doc.body.style.visibility = "visible";
+       // this._doc.body.innerHTML = this.getInnerHTML();
+};
+
+// focuses the iframe window.  returns a reference to the editor document.
+HTMLArea.prototype.focusEditor = function() {
+       switch (this._editMode) {
+           // notice the try { ... } catch block to avoid some rare exceptions in FireFox
+           // (perhaps also in other Gecko browsers). Manual focus by user is required in
+        // case of an error. Somebody has an idea?
+           case "wysiwyg" : try { this._iframe.contentWindow.focus() } catch (e) {} break;
+           case "textmode": try { this._textArea.focus() } catch (e) {} break;
+           default        : alert("ERROR: mode " + this._editMode + " is not defined");
+       }
+       return this._doc;
+};
+
+// takes a snapshot of the current text (for undo)
+HTMLArea.prototype._undoTakeSnapshot = function() {
+       ++this._undoPos;
+       if (this._undoPos >= this.config.undoSteps) {
+               // remove the first element
+               this._undoQueue.shift();
+               --this._undoPos;
+       }
+       // use the fasted method (getInnerHTML);
+       var take = true;
+       var txt = this.getInnerHTML();
+       if (this._undoPos > 0)
+               take = (this._undoQueue[this._undoPos - 1] != txt);
+       if (take) {
+               this._undoQueue[this._undoPos] = txt;
+       } else {
+               this._undoPos--;
+       }
+};
+
+HTMLArea.prototype.undo = function() {
+       if (this._undoPos > 0) {
+               var txt = this._undoQueue[--this._undoPos];
+               if (txt) this.setHTML(txt);
+               else ++this._undoPos;
+       }
+};
+
+HTMLArea.prototype.redo = function() {
+       if (this._undoPos < this._undoQueue.length - 1) {
+               var txt = this._undoQueue[++this._undoPos];
+               if (txt) this.setHTML(txt);
+               else --this._undoPos;
+       }
+};
+
+// updates enabled/disable/active state of the toolbar elements
+HTMLArea.prototype.updateToolbar = function(noStatus) {
+       var doc = this._doc;
+       var text = (this._editMode == "textmode");
+       var ancestors = null;
+       if (!text) {
+               ancestors = this.getAllAncestors();
+               if (this.config.statusBar && !noStatus) {
+                       this._statusBarTree.innerHTML = HTMLArea.I18N.msg["Path"] + ": "; // clear
+                       for (var i = ancestors.length; --i >= 0;) {
+                               var el = ancestors[i];
+                               if (!el) {
+                                       // hell knows why we get here; this
+                                       // could be a classic example of why
+                                       // it's good to check for conditions
+                                       // that are impossible to happen ;-)
+                                       continue;
+                               }
+                               var a = document.createElement("a");
+                               a.href = "#";
+                               a.el = el;
+                               a.editor = this;
+                               a.onclick = function() {
+                                       this.blur();
+                                       this.editor.selectNodeContents(this.el);
+                                       this.editor.updateToolbar(true);
+                                       return false;
+                               };
+                               a.oncontextmenu = function() {
+                                       // TODO: add context menu here
+                                       this.blur();
+                                       var info = "Inline style:\n\n";
+                                       info += this.el.style.cssText.split(/;\s*/).join(";\n");
+                                       alert(info);
+                                       return false;
+                               };
+                               var txt = el.tagName.toLowerCase();
+                               a.title = el.style.cssText;
+                               if (el.id) {
+                                       txt += "#" + el.id;
+                               }
+                               if (el.className) {
+                                       txt += "." + el.className;
+                               }
+                               a.appendChild(document.createTextNode(txt));
+                               this._statusBarTree.appendChild(a);
+                               if (i != 0) {
+                                       this._statusBarTree.appendChild(document.createTextNode(String.fromCharCode(0xbb)));
+                               }
+                       }
+               }
+       }
+
+       for (var i in this._toolbarObjects) {
+               var btn = this._toolbarObjects[i];
+               var cmd = i;
+               var inContext = true;
+               if (btn.context && !text) {
+                       inContext = false;
+                       var context = btn.context;
+                       var attrs = [];
+                       if (/(.*)\[(.*?)\]/.test(context)) {
+                               context = RegExp.$1;
+                               attrs = RegExp.$2.split(",");
+                       }
+                       context = context.toLowerCase();
+                       var match = (context == "*");
+                       for (var k = 0; k < ancestors.length; ++k) {
+                               if (!ancestors[k]) {
+                                       // the impossible really happens.
+                                       continue;
+                               }
+                               if (match || (ancestors[k].tagName.toLowerCase() == context)) {
+                                       inContext = true;
+                                       for (var ka = 0; ka < attrs.length; ++ka) {
+                                               if (!eval("ancestors[k]." + attrs[ka])) {
+                                                       inContext = false;
+                                                       break;
+                                               }
+                                       }
+                                       if (inContext) {
+                                               break;
+                                       }
+                               }
+                       }
+               }
+               btn.state("enabled", (!text || btn.text) && inContext);
+               if (typeof cmd == "function") {
+                       continue;
+               }
+               // look-it-up in the custom dropdown boxes
+               var dropdown = this.config.customSelects[cmd];
+               if ((!text || btn.text) && (typeof dropdown != "undefined")) {
+                       dropdown.refresh(this);
+                       continue;
+               }
+               switch (cmd) {
+                   case "fontname":
+                   case "fontsize":
+                   case "formatblock":
+                       if (!text) try {
+                               var value = ("" + doc.queryCommandValue(cmd)).toLowerCase();
+                               if (!value) {
+                                       btn.element.selectedIndex = 0;
+                                       break;
+                               }
+                               // HACK -- retrieve the config option for this
+                               // combo box.  We rely on the fact that the
+                               // variable in config has the same name as
+                               // button name in the toolbar.
+                               var options = this.config[cmd];
+                               var k = 0;
+                               for (var j in options) {
+                                       // FIXME: the following line is scary.
+                                       if ((j.toLowerCase() == value) ||
+                                           (options[j].substr(0, value.length).toLowerCase() == value)) {
+                                               btn.element.selectedIndex = k;
+                                               throw "ok";
+                                       }
+                                       ++k;
+                               }
+                               btn.element.selectedIndex = 0;
+                       } catch(e) {};
+                       break;
+                   case "textindicator":
+                       if (!text) {
+                               try {with (btn.element.style) {
+                                       backgroundColor = HTMLArea._makeColor(
+                                               doc.queryCommandValue(HTMLArea.is_ie ? "backcolor" : "hilitecolor"));
+                                       if (/transparent/i.test(backgroundColor)) {
+                                               // Mozilla
+                                               backgroundColor = HTMLArea._makeColor(doc.queryCommandValue("backcolor"));
+                                       }
+                                       color = HTMLArea._makeColor(doc.queryCommandValue("forecolor"));
+                                       fontFamily = doc.queryCommandValue("fontname");
+                                       fontWeight = doc.queryCommandState("bold") ? "bold" : "normal";
+                                       fontStyle = doc.queryCommandState("italic") ? "italic" : "normal";
+                               }} catch (e) {
+                                       // alert(e + "\n\n" + cmd);
+                               }
+                       }
+                       break;
+                   case "htmlmode": btn.state("active", text); break;
+                   case "lefttoright":
+                   case "righttoleft":
+                       var el = this.getParentElement();
+                       while (el && !HTMLArea.isBlockElement(el))
+                               el = el.parentNode;
+                       if (el)
+                               btn.state("active", (el.style.direction == ((cmd == "righttoleft") ? "rtl" : "ltr")));
+                       break;
+                   default:
+                       cmd = cmd.replace(/(un)?orderedlist/i, "insert$1orderedlist");
+                       try {
+                               btn.state("active", (!text && doc.queryCommandState(cmd)));
+                       } catch (e) {}
+               }
+       }
+       // take undo snapshots
+       if (this._customUndo && !this._timerUndo) {
+               this._undoTakeSnapshot();
+               var editor = this;
+               this._timerUndo = setTimeout(function() {
+                       editor._timerUndo = null;
+               }, this.config.undoTimeout);
+       }
+
+       // check if any plugins have registered refresh handlers
+       for (var i in this.plugins) {
+               var plugin = this.plugins[i].instance;
+               if (typeof plugin.onUpdateToolbar == "function")
+                       plugin.onUpdateToolbar();
+       }
+};
+
+/** Returns a node after which we can insert other nodes, in the current
+ * selection.  The selection is removed.  It splits a text node, if needed.
+ */
+HTMLArea.prototype.insertNodeAtSelection = function(toBeInserted) {
+       if (!HTMLArea.is_ie) {
+               var sel = this._getSelection();
+               var range = this._createRange(sel);
+               // remove the current selection
+               sel.removeAllRanges();
+               range.deleteContents();
+               var node = range.startContainer;
+               var pos = range.startOffset;
+               switch (node.nodeType) {
+                   case 3: // Node.TEXT_NODE
+                       // we have to split it at the caret position.
+                       if (toBeInserted.nodeType == 3) {
+                               // do optimized insertion
+                               node.insertData(pos, toBeInserted.data);
+                               range = this._createRange();
+                               range.setEnd(node, pos + toBeInserted.length);
+                               range.setStart(node, pos + toBeInserted.length);
+                               sel.addRange(range);
+                       } else {
+                               node = node.splitText(pos);
+                               var selnode = toBeInserted;
+                               if (toBeInserted.nodeType == 11 /* Node.DOCUMENT_FRAGMENT_NODE */) {
+                                       selnode = selnode.firstChild;
+                               }
+                               node.parentNode.insertBefore(toBeInserted, node);
+                               this.selectNodeContents(selnode);
+                               this.updateToolbar();
+                       }
+                       break;
+                   case 1: // Node.ELEMENT_NODE
+                       var selnode = toBeInserted;
+                       if (toBeInserted.nodeType == 11 /* Node.DOCUMENT_FRAGMENT_NODE */) {
+                               selnode = selnode.firstChild;
+                       }
+                       node.insertBefore(toBeInserted, node.childNodes[pos]);
+                       this.selectNodeContents(selnode);
+                       this.updateToolbar();
+                       break;
+               }
+       } else {
+               return null;    // this function not yet used for IE <FIXME>
+       }
+};
+
+// Returns the deepest node that contains both endpoints of the selection.
+HTMLArea.prototype.getParentElement = function() {
+       var sel = this._getSelection();
+       var range = this._createRange(sel);
+       if (HTMLArea.is_ie) {
+               switch (sel.type) {
+                   case "Text":
+                   case "None":
+                       // It seems that even for selection of type "None",
+                       // there _is_ a parent element and it's value is not
+                       // only correct, but very important to us.  MSIE is
+                       // certainly the buggiest browser in the world and I
+                       // wonder, God, how can Earth stand it?
+                       return range.parentElement();
+                   case "Control":
+                       return range.item(0);
+                   default:
+                       return this._doc.body;
+               }
+       } else try {
+               var p = range.commonAncestorContainer;
+               if (!range.collapsed && range.startContainer == range.endContainer &&
+                   range.startOffset - range.endOffset <= 1 && range.startContainer.hasChildNodes())
+                       p = range.startContainer.childNodes[range.startOffset];
+               /*
+               alert(range.startContainer + ":" + range.startOffset + "\n" +
+                     range.endContainer + ":" + range.endOffset);
+               */
+               while (p.nodeType == 3) {
+                       p = p.parentNode;
+               }
+               return p;
+       } catch (e) {
+               return null;
+       }
+};
+
+// Returns an array with all the ancestor nodes of the selection.
+HTMLArea.prototype.getAllAncestors = function() {
+       var p = this.getParentElement();
+       var a = [];
+       while (p && (p.nodeType == 1) && (p.tagName.toLowerCase() != 'body')) {
+               a.push(p);
+               p = p.parentNode;
+       }
+       a.push(this._doc.body);
+       return a;
+};
+
+// Selects the contents inside the given node
+HTMLArea.prototype.selectNodeContents = function(node, pos) {
+       this.focusEditor();
+       this.forceRedraw();
+       var range;
+       var collapsed = (typeof pos != "undefined");
+       if (HTMLArea.is_ie) {
+               range = this._doc.body.createTextRange();
+               range.moveToElementText(node);
+               (collapsed) && range.collapse(pos);
+               range.select();
+       } else {
+               var sel = this._getSelection();
+               range = this._doc.createRange();
+               range.selectNodeContents(node);
+               (collapsed) && range.collapse(pos);
+               sel.removeAllRanges();
+               sel.addRange(range);
+       }
+};
+
+/** Call this function to insert HTML code at the current position.  It deletes
+ * the selection, if any.
+ */
+HTMLArea.prototype.insertHTML = function(html) {
+       var sel = this._getSelection();
+       var range = this._createRange(sel);
+       if (HTMLArea.is_ie) {
+               range.pasteHTML(html);
+       } else {
+               // construct a new document fragment with the given HTML
+               var fragment = this._doc.createDocumentFragment();
+               var div = this._doc.createElement("div");
+               div.innerHTML = html;
+               while (div.firstChild) {
+                       // the following call also removes the node from div
+                       fragment.appendChild(div.firstChild);
+               }
+               // this also removes the selection
+               var node = this.insertNodeAtSelection(fragment);
+       }
+};
+
+/**
+ *  Call this function to surround the existing HTML code in the selection with
+ *  your tags.  FIXME: buggy!  This function will be deprecated "soon".
+ */
+HTMLArea.prototype.surroundHTML = function(startTag, endTag) {
+       var html = this.getSelectedHTML();
+       // the following also deletes the selection
+       this.insertHTML(startTag + html + endTag);
+};
+
+/// Retrieve the selected block
+HTMLArea.prototype.getSelectedHTML = function() {
+       var sel = this._getSelection();
+       var range = this._createRange(sel);
+       var existing = null;
+       if (HTMLArea.is_ie) {
+               existing = range.htmlText;
+       } else {
+               existing = HTMLArea.getHTML(range.cloneContents(), false, this);
+       }
+       return existing;
+};
+
+/// Return true if we have some selection
+HTMLArea.prototype.hasSelectedText = function() {
+       // FIXME: come _on_ mishoo, you can do better than this ;-)
+       return this.getSelectedHTML() != '';
+};
+
+HTMLArea.prototype._createLink = function(link) {
+       var editor = this;
+       var outparam = null;
+       if (typeof link == "undefined") {
+               link = this.getParentElement();
+               if (link) {
+                       if (/^img$/i.test(link.tagName))
+                               link = link.parentNode;
+                       if (!/^a$/i.test(link.tagName))
+                               link = null;
+               }
+       }
+       if (!link) {
+               var sel = editor._getSelection();
+               var range = editor._createRange(sel);
+               var compare = 0;
+               if (HTMLArea.is_ie) {
+                       compare = range.compareEndPoints("StartToEnd", range);
+               } else {
+                       compare = range.compareBoundaryPoints(range.START_TO_END, range);
+               }
+               if (compare == 0) {
+                       alert("You need to select some text before creating a link");
+                       return;
+               }
+               outparam = {
+                       f_href : '',
+                       f_title : '',
+                       f_target : '',
+                       f_usetarget : editor.config.makeLinkShowsTarget
+               };
+       } else
+               outparam = {
+                       f_href   : HTMLArea.is_ie ? editor.stripBaseURL(link.href) : link.getAttribute("href"),
+                       f_title  : link.title,
+                       f_target : link.target,
+                       f_usetarget : editor.config.makeLinkShowsTarget
+               };
+       this._popupDialog("link.html", function(param) {
+               if (!param)
+                       return false;
+               var a = link;
+               if (!a) try {
+                       editor._doc.execCommand("createlink", false, param.f_href);
+                       a = editor.getParentElement();
+                       var sel = editor._getSelection();
+                       var range = editor._createRange(sel);
+                       if (!HTMLArea.is_ie) {
+                               a = range.startContainer;
+                               if (!/^a$/i.test(a.tagName)) {
+                                       a = a.nextSibling;
+                                       if (a == null)
+                                               a = range.startContainer.parentNode;
+                               }
+                       }
+               } catch(e) {}
+               else {
+                       var href = param.f_href.trim();
+                       editor.selectNodeContents(a);
+                       if (href == "") {
+                               editor._doc.execCommand("unlink", false, null);
+                               editor.updateToolbar();
+                               return false;
+                       }
+                       else {
+                               a.href = href;
+                       }
+               }
+               if (!(a && /^a$/i.test(a.tagName)))
+                       return false;
+               a.target = param.f_target.trim();
+               a.title = param.f_title.trim();
+               editor.selectNodeContents(a);
+               editor.updateToolbar();
+       }, outparam);
+};
+
+// Called when the user clicks on "InsertImage" button.  If an image is already
+// there, it will just modify it's properties.
+HTMLArea.prototype._insertImage = function(image) {
+       var editor = this;      // for nested functions
+       var outparam = null;
+       if (typeof image == "undefined") {
+               image = this.getParentElement();
+               if (image && !/^img$/i.test(image.tagName))
+                       image = null;
+       }
+       if (image) outparam = {
+               f_base   : editor.config.baseURL,
+               f_url    : HTMLArea.is_ie ? editor.stripBaseURL(image.src) : image.getAttribute("src"),
+               f_alt    : image.alt,
+               f_border : image.border,
+               f_align  : image.align,
+               f_vert   : image.vspace,
+               f_horiz  : image.hspace
+       };
+       this._popupDialog("insert_image.html", function(param) {
+               if (!param) {   // user must have pressed Cancel
+                       return false;
+               }
+               var img = image;
+               if (!img) {
+                       var sel = editor._getSelection();
+                       var range = editor._createRange(sel);
+                       editor._doc.execCommand("insertimage", false, param.f_url);
+                       if (HTMLArea.is_ie) {
+                               img = range.parentElement();
+                               // wonder if this works...
+                               if (img.tagName.toLowerCase() != "img") {
+                                       img = img.previousSibling;
+                               }
+                       } else {
+                               img = range.startContainer.previousSibling;
+                       }
+               } else {
+                       img.src = param.f_url;
+               }
+
+               for (var field in param) {
+                       var value = param[field];
+                       switch (field) {
+                           case "f_alt"    : img.alt    = value; break;
+                           case "f_border" : img.border = parseInt(value || "0"); break;
+                           case "f_align"  : img.align  = value; break;
+                           case "f_vert"   : img.vspace = parseInt(value || "0"); break;
+                           case "f_horiz"  : img.hspace = parseInt(value || "0"); break;
+                       }
+               }
+       }, outparam);
+};
+
+// Called when the user clicks the Insert Table button
+HTMLArea.prototype._insertTable = function() {
+       var sel = this._getSelection();
+       var range = this._createRange(sel);
+       var editor = this;      // for nested functions
+       this._popupDialog("insert_table.html", function(param) {
+               if (!param) {   // user must have pressed Cancel
+                       return false;
+               }
+               var doc = editor._doc;
+               // create the table element
+               var table = doc.createElement("table");
+               // assign the given arguments
+
+               for (var field in param) {
+                       var value = param[field];
+                       if (!value) {
+                               continue;
+                       }
+                       switch (field) {
+                           case "f_width"   : table.style.width = value + param["f_unit"]; break;
+                           case "f_align"   : table.align       = value; break;
+                           case "f_border"  : table.border      = parseInt(value); break;
+                           case "f_spacing" : table.cellSpacing = parseInt(value); break;
+                           case "f_padding" : table.cellPadding = parseInt(value); break;
+                       }
+               }
+               var cellwidth = 0;
+               if (param.f_fixed)
+                       cellwidth = Math.floor(100 / parseInt(param.f_cols));
+               var tbody = doc.createElement("tbody");
+               table.appendChild(tbody);
+               for (var i = 0; i < param["f_rows"]; ++i) {
+                       var tr = doc.createElement("tr");
+                       tbody.appendChild(tr);
+                       for (var j = 0; j < param["f_cols"]; ++j) {
+                               var td = doc.createElement("td");
+                               if (cellwidth)
+                                       td.style.width = cellwidth + "%";
+                               tr.appendChild(td);
+                               // Mozilla likes to see something inside the cell.
+                               (HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
+                       }
+               }
+               if (HTMLArea.is_ie) {
+                       range.pasteHTML(table.outerHTML);
+               } else {
+                       // insert the table
+                       editor.insertNodeAtSelection(table);
+               }
+               return true;
+       }, null);
+};
+
+/***************************************************
+ *  Category: EVENT HANDLERS
+ ***************************************************/
+
+// el is reference to the SELECT object
+// txt is the name of the select field, as in config.toolbar
+HTMLArea.prototype._comboSelected = function(el, txt) {
+       this.focusEditor();
+       var value = el.options[el.selectedIndex].value;
+       switch (txt) {
+           case "fontname":
+           case "fontsize": this.execCommand(txt, false, value); break;
+           case "formatblock":
+               (HTMLArea.is_ie) && (value = "<" + value + ">");
+               this.execCommand(txt, false, value);
+               break;
+           default:
+               // try to look it up in the registered dropdowns
+               var dropdown = this.config.customSelects[txt];
+               if (typeof dropdown != "undefined") {
+                       dropdown.action(this);
+               } else {
+                       alert("FIXME: combo box " + txt + " not implemented");
+               }
+       }
+};
+
+// the execCommand function (intercepts some commands and replaces them with
+// our own implementation)
+HTMLArea.prototype.execCommand = function(cmdID, UI, param) {
+       var editor = this;      // for nested functions
+       this.focusEditor();
+       cmdID = cmdID.toLowerCase();
+       if (HTMLArea.is_gecko) try { this._doc.execCommand('useCSS', false, true); } catch (e) {};
+       switch (cmdID) {
+           case "htmlmode" : this.setMode(); break;
+           case "hilitecolor":
+               (HTMLArea.is_ie) && (cmdID = "backcolor");
+           case "forecolor":
+               this._popupDialog("select_color.html", function(color) {
+                       if (color) { // selection not canceled
+                               editor._doc.execCommand(cmdID, false, "#" + color);
+                       }
+               }, HTMLArea._colorToRgb(this._doc.queryCommandValue(cmdID)));
+               break;
+           case "createlink":
+               this._createLink();
+               break;
+           case "popupeditor":
+               // this object will be passed to the newly opened window
+               HTMLArea._object = this;
+               if (HTMLArea.is_ie) {
+                       //if (confirm(HTMLArea.I18N.msg["IE-sucks-full-screen"]))
+                       {
+                               window.open(this.popupURL("fullscreen.html"), "ha_fullscreen",
+                                           "toolbar=no,location=no,directories=no,status=no,menubar=no," +
+                                           "scrollbars=no,resizable=yes,width=640,height=480");
+                       }
+               } else {
+                       window.open(this.popupURL("fullscreen.html"), "ha_fullscreen",
+                                   "toolbar=no,menubar=no,personalbar=no,width=640,height=480," +
+                                   "scrollbars=no,resizable=yes");
+               }
+               break;
+           case "undo":
+           case "redo":
+               if (this._customUndo)
+                       this[cmdID]();
+               else
+                       this._doc.execCommand(cmdID, UI, param);
+               break;
+           case "inserttable": this._insertTable(); break;
+           case "insertimage": this._insertImage(); break;
+           case "about"    : this._popupDialog("about.html", null, this); break;
+           case "showhelp" : window.open(_editor_url + "reference.html", "ha_help"); break;
+
+           case "killword": this._wordClean(); break;
+
+           case "cut":
+           case "copy":
+           case "paste":
+               try {
+                       this._doc.execCommand(cmdID, UI, param);
+                       if (this.config.killWordOnPaste)
+                               this._wordClean();
+               } catch (e) {
+                       if (HTMLArea.is_gecko) {
+                               if (typeof HTMLArea.I18N.msg["Moz-Clipboard"] == "undefined") {
+                                       HTMLArea.I18N.msg["Moz-Clipboard"] =
+                                               "Unprivileged scripts cannot access Cut/Copy/Paste programatically " +
+                                               "for security reasons.  Click OK to see a technical note at mozilla.org " +
+                                               "which shows you how to allow a script to access the clipboard.\n\n" +
+                                               "[FIXME: please translate this message in your language definition file.]";
+                               }
+                               if (confirm(HTMLArea.I18N.msg["Moz-Clipboard"]))
+                                       window.open("http://mozilla.org/editor/midasdemo/securityprefs.html");
+                       }
+               }
+               break;
+           case "lefttoright":
+           case "righttoleft":
+               var dir = (cmdID == "righttoleft") ? "rtl" : "ltr";
+               var el = this.getParentElement();
+               while (el && !HTMLArea.isBlockElement(el))
+                       el = el.parentNode;
+               if (el) {
+                       if (el.style.direction == dir)
+                               el.style.direction = "";
+                       else
+                               el.style.direction = dir;
+               }
+               break;
+           default: try { this._doc.execCommand(cmdID, UI, param); }
+               catch(e) { if (this.config.debug) { alert(e + "\n\nby execCommand(" + cmdID + ");"); } }
+       }
+       this.updateToolbar();
+       return false;
+};
+
+/** A generic event handler for things that happen in the IFRAME's document.
+ * This function also handles key bindings. */
+HTMLArea.prototype._editorEvent = function(ev) {
+       var editor = this;
+       var keyEvent = (HTMLArea.is_ie && ev.type == "keydown") || (!HTMLArea.is_ie && ev.type == "keypress");
+
+       if (keyEvent)
+               for (var i in editor.plugins) {
+                       var plugin = editor.plugins[i].instance;
+                       if (typeof plugin.onKeyPress == "function")
+                               if (plugin.onKeyPress(ev))
+                                       return false;
+               }
+       if (keyEvent && ev.ctrlKey && !ev.altKey) {
+               var sel = null;
+               var range = null;
+               var key = String.fromCharCode(HTMLArea.is_ie ? ev.keyCode : ev.charCode).toLowerCase();
+               var cmd = null;
+               var value = null;
+               switch (key) {
+                   case 'a':
+                       if (!HTMLArea.is_ie) {
+                               // KEY select all
+                               sel = this._getSelection();
+                               sel.removeAllRanges();
+                               range = this._createRange();
+                               range.selectNodeContents(this._doc.body);
+                               sel.addRange(range);
+                               HTMLArea._stopEvent(ev);
+                       }
+                       break;
+
+                       // simple key commands follow
+
+                   case 'b': cmd = "bold"; break;
+                   case 'i': cmd = "italic"; break;
+                   case 'u': cmd = "underline"; break;
+                   case 's': cmd = "strikethrough"; break;
+                   case 'l': cmd = "justifyleft"; break;
+                   case 'e': cmd = "justifycenter"; break;
+                   case 'r': cmd = "justifyright"; break;
+                   case 'j': cmd = "justifyfull"; break;
+                   case 'z': cmd = "undo"; break;
+                   case 'y': cmd = "redo"; break;
+                   case 'v': if (HTMLArea.is_ie || editor.config.htmlareaPaste) { cmd = "paste"; } break;
+                   case 'n': cmd = "formatblock"; value = HTMLArea.is_ie ? "<p>" : "p"; break;
+
+                   case '0': cmd = "killword"; break;
+
+                       // headings
+                   case '1':
+                   case '2':
+                   case '3':
+                   case '4':
+                   case '5':
+                   case '6':
+                       cmd = "formatblock";
+                       value = "h" + key;
+                       if (HTMLArea.is_ie)
+                               value = "<" + value + ">";
+                       break;
+               }
+               if (cmd) {
+                       // execute simple command
+                       this.execCommand(cmd, false, value);
+                       HTMLArea._stopEvent(ev);
+               }
+       }
+       else if (keyEvent) {
+               // other keys here
+               switch (ev.keyCode) {
+                   case 13: // KEY enter
+                       if (HTMLArea.is_gecko && !ev.shiftKey) {
+                               this.dom_checkInsertP();
+                               HTMLArea._stopEvent(ev);
+                       }
+                       break;
+                   case 8: // KEY backspace
+                   case 46: // KEY delete
+                       if (HTMLArea.is_gecko && !ev.shiftKey) {
+                               if (this.dom_checkBackspace())
+                                       HTMLArea._stopEvent(ev);
+                       } else if (HTMLArea.is_ie) {
+                               if (this.ie_checkBackspace())
+                                       HTMLArea._stopEvent(ev);
+                       }
+                       break;
+               }
+       }
+
+       // update the toolbar state after some time
+       if (editor._timerToolbar) {
+               clearTimeout(editor._timerToolbar);
+       }
+       editor._timerToolbar = setTimeout(function() {
+               editor.updateToolbar();
+               editor._timerToolbar = null;
+       }, 50);
+};
+
+HTMLArea.prototype.convertNode = function(el, newTagName) {
+       var newel = this._doc.createElement(newTagName);
+       while (el.firstChild)
+               newel.appendChild(el.firstChild);
+       return newel;
+};
+
+HTMLArea.prototype.ie_checkBackspace = function() {
+       var sel = this._getSelection();
+       var range = this._createRange(sel);
+       var r2 = range.duplicate();
+       r2.moveStart("character", -1);
+       var a = r2.parentElement();
+       if (a != range.parentElement() &&
+           /^a$/i.test(a.tagName)) {
+               r2.collapse(true);
+               r2.moveEnd("character", 1);
+               r2.pasteHTML('');
+               r2.select();
+               return true;
+       }
+};
+
+HTMLArea.prototype.dom_checkBackspace = function() {
+       var self = this;
+       setTimeout(function() {
+               var sel = self._getSelection();
+               var range = self._createRange(sel);
+               var SC = range.startContainer;
+               var SO = range.startOffset;
+               var EC = range.endContainer;
+               var EO = range.endOffset;
+               var newr = SC.nextSibling;
+               if (SC.nodeType == 3)
+                       SC = SC.parentNode;
+               if (!/\S/.test(SC.tagName)) {
+                       var p = document.createElement("p");
+                       while (SC.firstChild)
+                               p.appendChild(SC.firstChild);
+                       SC.parentNode.insertBefore(p, SC);
+                       SC.parentNode.removeChild(SC);
+                       var r = range.cloneRange();
+                       r.setStartBefore(newr);
+                       r.setEndAfter(newr);
+                       r.extractContents();
+                       sel.removeAllRanges();
+                       sel.addRange(r);
+               }
+       }, 10);
+};
+
+HTMLArea.prototype.dom_checkInsertP = function() {
+       var p = this.getAllAncestors();
+       var block = null;
+       var body = this._doc.body;
+       for (var i = 0; i < p.length; ++i)
+               if (HTMLArea.isBlockElement(p[i]) && !/body|html/i.test(p[i].tagName)) {
+                       block = p[i];
+                       break;
+               }
+       var sel = this._getSelection();
+       var range = this._createRange(sel);
+       if (!range.collapsed)
+               range.deleteContents();
+       sel.removeAllRanges();
+       var SC = range.startContainer;
+       var SO = range.startOffset;
+       var EC = range.endContainer;
+       var EO = range.endOffset;
+       //alert(SC.tagName + ":" + SO + " => " + EC.tagName + ":" + EO);
+       if (SC == EC && SC == body && !SO && !EO) {
+               p = this._doc.createTextNode(" ");
+               body.insertBefore(p, body.firstChild);
+               range.selectNodeContents(p);
+               SC = range.startContainer;
+               SO = range.startOffset;
+               EC = range.endContainer;
+               EO = range.endOffset;
+       }
+       if (!block) {
+               var r2 = range.cloneRange();
+               r2.setStartBefore(SC);
+               r2.setEndAfter(EC);
+               r2.surroundContents(block = this._doc.createElement("p"));
+               range.setEndAfter(block);
+               range.setStart(block.firstChild, SO);
+       } else range.setEndAfter(block);
+       var df = range.extractContents();
+       if (!/\S/.test(block.innerHTML))
+               block.innerHTML = "<br />";
+       p = df.firstChild;
+       if (!/\S/.test(p.innerHTML))
+               p.innerHTML = "<br />";
+       if (/^\s*<br\s*\/?>\s*$/.test(p.innerHTML) && /^h[1-6]$/i.test(p.tagName)) {
+               df.appendChild(this.convertNode(p, "p"));
+               df.removeChild(p);
+       }
+       block.parentNode.insertBefore(df, block.nextSibling);
+       range.selectNodeContents(block.nextSibling);
+       range.collapse(true);
+       sel.addRange(range);
+       this.forceRedraw();
+};
+
+// retrieve the HTML
+HTMLArea.prototype.getHTML = function() {
+       switch (this._editMode) {
+           case "wysiwyg"  :
+               if (!this.config.fullPage) {
+                       return HTMLArea.getHTML(this._doc.body, false, this);
+               } else
+                       return this.doctype + "\n" + HTMLArea.getHTML(this._doc.documentElement, true, this);
+           case "textmode" : return this._textArea.value;
+           default         : alert("Mode <" + mode + "> not defined!");
+       }
+       return false;
+};
+
+// retrieve the HTML (fastest version, but uses innerHTML)
+HTMLArea.prototype.getInnerHTML = function() {
+       switch (this._editMode) {
+           case "wysiwyg"  :
+               if (!this.config.fullPage)
+                       return this._doc.body.innerHTML;
+               else
+                       return this.doctype + "\n" + this._doc.documentElement.innerHTML;
+           case "textmode" : return this._textArea.value;
+           default         : alert("Mode <" + mode + "> not defined!");
+       }
+       return false;
+};
+
+// completely change the HTML inside
+HTMLArea.prototype.setHTML = function(html) {
+       switch (this._editMode) {
+           case "wysiwyg"  :
+               if (!this.config.fullPage)
+                       this._doc.body.innerHTML = html;
+               else
+                       // this._doc.documentElement.innerHTML = html;
+                       this._doc.body.innerHTML = html;
+               break;
+           case "textmode" : this._textArea.value = html; break;
+           default         : alert("Mode <" + mode + "> not defined!");
+       }
+       return false;
+};
+
+// sets the given doctype (useful when config.fullPage is true)
+HTMLArea.prototype.setDoctype = function(doctype) {
+       this.doctype = doctype;
+};
+
+/***************************************************
+ *  Category: UTILITY FUNCTIONS
+ ***************************************************/
+
+// variable used to pass the object to the popup editor window.
+HTMLArea._object = null;
+
+// function that returns a clone of the given object
+HTMLArea.cloneObject = function(obj) {
+       if (!obj) return null;
+       var newObj = new Object;
+
+       // check for array objects
+       if (obj.constructor.toString().indexOf("function Array(") == 1) {
+               newObj = obj.constructor();
+       }
+
+       // check for function objects (as usual, IE is fucked up)
+       if (obj.constructor.toString().indexOf("function Function(") == 1) {
+               newObj = obj; // just copy reference to it
+       } else for (var n in obj) {
+               var node = obj[n];
+               if (typeof node == 'object') { newObj[n] = HTMLArea.cloneObject(node); }
+               else                         { newObj[n] = node; }
+       }
+
+       return newObj;
+};
+
+// FIXME!!! this should return false for IE < 5.5
+HTMLArea.checkSupportedBrowser = function() {
+       if (HTMLArea.is_gecko) {
+               if (navigator.productSub < 20021201) {
+                       alert("You need at least Mozilla-1.3 Alpha.\n" +
+                             "Sorry, your Gecko is not supported.");
+                       return false;
+               }
+               if (navigator.productSub < 20030210) {
+                       alert("Mozilla < 1.3 Beta is not supported!\n" +
+                             "I'll try, though, but it might not work.");
+               }
+       }
+       return HTMLArea.is_gecko || HTMLArea.is_ie;
+};
+
+// selection & ranges
+
+// returns the current selection object
+HTMLArea.prototype._getSelection = function() {
+       if (HTMLArea.is_ie) {
+               return this._doc.selection;
+       } else {
+               return this._iframe.contentWindow.getSelection();
+       }
+};
+
+// returns a range for the current selection
+HTMLArea.prototype._createRange = function(sel) {
+       if (HTMLArea.is_ie) {
+               return sel.createRange();
+       } else {
+               this.focusEditor();
+               if (typeof sel != "undefined") {
+                       try {
+                               return sel.getRangeAt(0);
+                       } catch(e) {
+                               return this._doc.createRange();
+                       }
+               } else {
+                       return this._doc.createRange();
+               }
+       }
+};
+
+// event handling
+
+HTMLArea._addEvent = function(el, evname, func) {
+       if (HTMLArea.is_ie) {
+               el.attachEvent("on" + evname, func);
+       } else {
+               el.addEventListener(evname, func, true);
+       }
+};
+
+HTMLArea._addEvents = function(el, evs, func) {
+       for (var i = evs.length; --i >= 0;) {
+               HTMLArea._addEvent(el, evs[i], func);
+       }
+};
+
+HTMLArea._removeEvent = function(el, evname, func) {
+       if (HTMLArea.is_ie) {
+               el.detachEvent("on" + evname, func);
+       } else {
+               el.removeEventListener(evname, func, true);
+       }
+};
+
+HTMLArea._removeEvents = function(el, evs, func) {
+       for (var i = evs.length; --i >= 0;) {
+               HTMLArea._removeEvent(el, evs[i], func);
+       }
+};
+
+HTMLArea._stopEvent = function(ev) {
+       if (HTMLArea.is_ie) {
+               ev.cancelBubble = true;
+               ev.returnValue = false;
+       } else {
+               ev.preventDefault();
+               ev.stopPropagation();
+       }
+};
+
+HTMLArea._removeClass = function(el, className) {
+       if (!(el && el.className)) {
+               return;
+       }
+       var cls = el.className.split(" ");
+       var ar = new Array();
+       for (var i = cls.length; i > 0;) {
+               if (cls[--i] != className) {
+                       ar[ar.length] = cls[i];
+               }
+       }
+       el.className = ar.join(" ");
+};
+
+HTMLArea._addClass = function(el, className) {
+       // remove the class first, if already there
+       HTMLArea._removeClass(el, className);
+       el.className += " " + className;
+};
+
+HTMLArea._hasClass = function(el, className) {
+       if (!(el && el.className)) {
+               return false;
+       }
+       var cls = el.className.split(" ");
+       for (var i = cls.length; i > 0;) {
+               if (cls[--i] == className) {
+                       return true;
+               }
+       }
+       return false;
+};
+
+HTMLArea._blockTags = " body form textarea fieldset ul ol dl li div " +
+"p h1 h2 h3 h4 h5 h6 quote pre table thead " +
+"tbody tfoot tr td iframe address ";
+HTMLArea.isBlockElement = function(el) {
+       return el && el.nodeType == 1 && (HTMLArea._blockTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);
+};
+
+HTMLArea._closingTags = " head script style div span tr td tbody table em strong b i code cite dfn abbr acronym font a title ";
+HTMLArea.needsClosingTag = function(el) {
+       return el && el.nodeType == 1 && (HTMLArea._closingTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);
+};
+
+// performs HTML encoding of some given string
+HTMLArea.htmlEncode = function(str) {
+       // we don't need regexp for that, but.. so be it for now.
+       str = str.replace(/&/ig, "&amp;");
+       str = str.replace(/</ig, "&lt;");
+       str = str.replace(/>/ig, "&gt;");
+       str = str.replace(/\x22/ig, "&quot;");
+       // \x22 means '"' -- we use hex reprezentation so that we don't disturb
+       // JS compressors (well, at least mine fails.. ;)
+       return str;
+};
+
+// Retrieves the HTML code from the given node.         This is a replacement for
+// getting innerHTML, using standard DOM calls.
+// Wrapper catch a Mozilla-Exception with non well formed html source code
+HTMLArea.getHTML = function(root, outputRoot, editor){
+    try{
+        return HTMLArea.getHTMLWrapper(root,outputRoot,editor);
+    }
+    catch(e){
+        alert('Your Document is not well formed. Check JavaScript console for details.');
+        return editor._iframe.contentWindow.document.body.innerHTML;
+    }
+}
+
+HTMLArea.getHTMLWrapper = function(root, outputRoot, editor) {
+       var html = "";
+       switch (root.nodeType) {
+           case 1: // Node.ELEMENT_NODE
+           case 11: // Node.DOCUMENT_FRAGMENT_NODE
+               var closed;
+               var i;
+               var root_tag = (root.nodeType == 1) ? root.tagName.toLowerCase() : '';
+               if (root_tag == 'br' && !root.nextSibling)
+                       break;
+               if (outputRoot)
+                       outputRoot = !(editor.config.htmlRemoveTags && editor.config.htmlRemoveTags.test(root_tag));
+               if (HTMLArea.is_ie && root_tag == "head") {
+                       if (outputRoot)
+                               html += "<head>";
+                       // lowercasize
+                       var save_multiline = RegExp.multiline;
+                       RegExp.multiline = true;
+                       var txt = root.innerHTML.replace(HTMLArea.RE_tagName, function(str, p1, p2) {
+                               return p1 + p2.toLowerCase();
+                       });
+                       RegExp.multiline = save_multiline;
+                       html += txt;
+                       if (outputRoot)
+                               html += "</head>";
+                       break;
+               } else if (outputRoot) {
+                       closed = (!(root.hasChildNodes() || HTMLArea.needsClosingTag(root)));
+                       html = "<" + root.tagName.toLowerCase();
+                       var attrs = root.attributes;
+                       for (i = 0; i < attrs.length; ++i) {
+                               var a = attrs.item(i);
+                               if (!a.specified) {
+                                       continue;
+                               }
+                               var name = a.nodeName.toLowerCase();
+                               if (/_moz_editor_bogus_node/.test(name)) {
+                                       html = "";
+                                       break;
+                               }
+                               if (/_moz|contenteditable|_msh/.test(name)) {
+                                       // avoid certain attributes
+                                       continue;
+                               }
+                               var value;
+                               if (name != "style") {
+                                       // IE5.5 reports 25 when cellSpacing is
+                                       // 1; other values might be doomed too.
+                                       // For this reason we extract the
+                                       // values directly from the root node.
+                                       // I'm starting to HATE JavaScript
+                                       // development.  Browser differences
+                                       // suck.
+                                       //
+                                       // Using Gecko the values of href and src are converted to absolute links
+                                       // unless we get them using nodeValue()
+                                       if (typeof root[a.nodeName] != "undefined" && name != "href" && name != "src" && !/^on/.test(name)) {
+                                               value = root[a.nodeName];
+                                       } else {
+                                               value = a.nodeValue;
+                                               // IE seems not willing to return the original values - it converts to absolute
+                                               // links using a.nodeValue, a.value, a.stringValue, root.getAttribute("href")
+                                               // So we have to strip the baseurl manually :-/
+                                               if (HTMLArea.is_ie && (name == "href" || name == "src")) {
+                                                       value = editor.stripBaseURL(value);
+                                               }
+                                       }
+                               } else { // IE fails to put style in attributes list
+                                       // FIXME: cssText reported by IE is UPPERCASE
+                                       value = root.style.cssText;
+                               }
+                               if (/(_moz|^$)/.test(value)) {
+                                       // Mozilla reports some special tags
+                                       // here; we don't need them.
+                                       continue;
+                               }
+                               html += " " + name + '="' + value + '"';
+                       }
+                       if (html != "") {
+                               html += closed ? " />" : ">";
+                       }
+               }
+               for (i = root.firstChild; i; i = i.nextSibling) {
+                       html += HTMLArea.getHTMLWrapper(i, true, editor);
+               }
+               if (outputRoot && !closed) {
+                       html += "</" + root.tagName.toLowerCase() + ">";
+               }
+               break;
+           case 3: // Node.TEXT_NODE
+               // If a text node is alone in an element and all spaces, replace it with an non breaking one
+               // This partially undoes the damage done by moz, which translates '&nbsp;'s into spaces in the data element
+               /* if ( !root.previousSibling && !root.nextSibling && root.data.match(/^\s*$/i) ) html = '&nbsp;';
+                  else */
+               html = /^script|style$/i.test(root.parentNode.tagName) ? root.data : HTMLArea.htmlEncode(root.data);
+               break;
+           case 4: // Node.CDATA_SECTION_NODE
+               // FIXME: it seems we never get here, but I believe we should..
+               //        maybe a browser problem?--CDATA sections are converted to plain text nodes and normalized
+               // CDATA sections should go "as is" without further encoding
+               html = "<![CDATA[" + root.data + "]]>";
+               break;
+           case 8: // Node.COMMENT_NODE
+               html = "<!--" + root.data + "-->";
+               break;          // skip comments, for now.
+       }
+       return html;
+};
+
+HTMLArea.prototype.stripBaseURL = function(string) {
+       var baseurl = this.config.baseURL;
+       // strip to last directory in case baseurl points to a file
+       baseurl = baseurl.replace(/[^\/]+$/, '');
+       _baseurl = baseurl;
+       var basere = new RegExp(baseurl);
+       string = string.replace(basere, this.config.baseURL);
+
+       // strip host-part of URL which is added by MSIE to links relative to server root
+       baseurl = baseurl.replace(/^(https?:\/\/[^\/]+)(.*)$/, '$1');
+       basere = new RegExp(baseurl);
+       return string.replace(basere, baseurl);
+};
+
+String.prototype.trim = function() {
+       return this.replace(/^\s+/, '').replace(/\s+$/, '');
+};
+
+// creates a rgb-style color from a number
+HTMLArea._makeColor = function(v) {
+       if (typeof v != "number") {
+               // already in rgb (hopefully); IE doesn't get here.
+               return v;
+       }
+       // IE sends number; convert to rgb.
+       var r = v & 0xFF;
+       var g = (v >> 8) & 0xFF;
+       var b = (v >> 16) & 0xFF;
+       return "rgb(" + r + "," + g + "," + b + ")";
+};
+
+// returns hexadecimal color representation from a number or a rgb-style color.
+HTMLArea._colorToRgb = function(v) {
+       if (!v)
+               return '';
+
+       // returns the hex representation of one byte (2 digits)
+       function hex(d) {
+               return (d < 16) ? ("0" + d.toString(16)) : d.toString(16);
+       };
+
+       if (typeof v == "number") {
+               // we're talking to IE here
+               var r = v & 0xFF;
+               var g = (v >> 8) & 0xFF;
+               var b = (v >> 16) & 0xFF;
+               return "#" + hex(r) + hex(g) + hex(b);
+       }
+
+       if (v.substr(0, 3) == "rgb") {
+               // in rgb(...) form -- Mozilla
+               var re = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/;
+               if (v.match(re)) {
+                       var r = parseInt(RegExp.$1);
+                       var g = parseInt(RegExp.$2);
+                       var b = parseInt(RegExp.$3);
+                       return "#" + hex(r) + hex(g) + hex(b);
+               }
+               // doesn't match RE?!  maybe uses percentages or float numbers
+               // -- FIXME: not yet implemented.
+               return null;
+       }
+
+       if (v.substr(0, 1) == "#") {
+               // already hex rgb (hopefully :D )
+               return v;
+       }
+
+       // if everything else fails ;)
+       return null;
+};
+
+// modal dialogs for Mozilla (for IE we're using the showModalDialog() call).
+
+// receives an URL to the popup dialog and a function that receives one value;
+// this function will get called after the dialog is closed, with the return
+// value of the dialog.
+HTMLArea.prototype._popupDialog = function(url, action, init) {
+       Dialog(this.popupURL(url), action, init);
+};
+
+// paths
+
+HTMLArea.prototype.imgURL = function(file, plugin) {
+       if (typeof plugin == "undefined")
+               return _editor_url + file;
+       else
+               return _editor_url + "plugins/" + plugin + "/img/" + file;
+};
+
+HTMLArea.prototype.popupURL = function(file) {
+       var url = "";
+       if (file.match(/^plugin:\/\/(.*?)\/(.*)/)) {
+               var plugin = RegExp.$1;
+               var popup = RegExp.$2;
+               if (!/\.html$/.test(popup))
+                       popup += ".html";
+               url = _editor_url + "plugins/" + plugin + "/popups/" + popup;
+       } else
+               url = _editor_url + this.config.popupURL + file;
+       return url;
+};
+
+/**
+ * FIX: Internet Explorer returns an item having the _name_ equal to the given
+ * id, even if it's not having any id.  This way it can return a different form
+ * field even if it's not a textarea.  This workarounds the problem by
+ * specifically looking to search only elements having a certain tag name.
+ */
+HTMLArea.getElementById = function(tag, id) {
+       var el, i, objs = document.getElementsByTagName(tag);
+       for (i = objs.length; --i >= 0 && (el = objs[i]);)
+               if (el.id == id)
+                       return el;
+       return null;
+};
+
+
+
+// EOF
+// Local variables: //
+// c-basic-offset:8 //
+// indent-tabs-mode:t //
+// End: //
diff --git a/htmlarea/images/ed_about.gif b/htmlarea/images/ed_about.gif
new file mode 100644 (file)
index 0000000..f0a338b
Binary files /dev/null and b/htmlarea/images/ed_about.gif differ
diff --git a/htmlarea/images/ed_align_center.gif b/htmlarea/images/ed_align_center.gif
new file mode 100644 (file)
index 0000000..9505db2
Binary files /dev/null and b/htmlarea/images/ed_align_center.gif differ
diff --git a/htmlarea/images/ed_align_justify.gif b/htmlarea/images/ed_align_justify.gif
new file mode 100644 (file)
index 0000000..29cf731
Binary files /dev/null and b/htmlarea/images/ed_align_justify.gif differ
diff --git a/htmlarea/images/ed_align_left.gif b/htmlarea/images/ed_align_left.gif
new file mode 100644 (file)
index 0000000..d0356d4
Binary files /dev/null and b/htmlarea/images/ed_align_left.gif differ
diff --git a/htmlarea/images/ed_align_right.gif b/htmlarea/images/ed_align_right.gif
new file mode 100644 (file)
index 0000000..b9f7a96
Binary files /dev/null and b/htmlarea/images/ed_align_right.gif differ
diff --git a/htmlarea/images/ed_blank.gif b/htmlarea/images/ed_blank.gif
new file mode 100644 (file)
index 0000000..1ea396b
Binary files /dev/null and b/htmlarea/images/ed_blank.gif differ
diff --git a/htmlarea/images/ed_charmap.gif b/htmlarea/images/ed_charmap.gif
new file mode 100644 (file)
index 0000000..9fac54d
Binary files /dev/null and b/htmlarea/images/ed_charmap.gif differ
diff --git a/htmlarea/images/ed_color_bg.gif b/htmlarea/images/ed_color_bg.gif
new file mode 100644 (file)
index 0000000..8b464c9
Binary files /dev/null and b/htmlarea/images/ed_color_bg.gif differ
diff --git a/htmlarea/images/ed_color_fg.gif b/htmlarea/images/ed_color_fg.gif
new file mode 100644 (file)
index 0000000..44af9c4
Binary files /dev/null and b/htmlarea/images/ed_color_fg.gif differ
diff --git a/htmlarea/images/ed_copy.gif b/htmlarea/images/ed_copy.gif
new file mode 100644 (file)
index 0000000..975740a
Binary files /dev/null and b/htmlarea/images/ed_copy.gif differ
diff --git a/htmlarea/images/ed_custom.gif b/htmlarea/images/ed_custom.gif
new file mode 100644 (file)
index 0000000..9529a52
Binary files /dev/null and b/htmlarea/images/ed_custom.gif differ
diff --git a/htmlarea/images/ed_cut.gif b/htmlarea/images/ed_cut.gif
new file mode 100644 (file)
index 0000000..2066038
Binary files /dev/null and b/htmlarea/images/ed_cut.gif differ
diff --git a/htmlarea/images/ed_delete.gif b/htmlarea/images/ed_delete.gif
new file mode 100644 (file)
index 0000000..3c3df5b
Binary files /dev/null and b/htmlarea/images/ed_delete.gif differ
diff --git a/htmlarea/images/ed_format_bold.gif b/htmlarea/images/ed_format_bold.gif
new file mode 100644 (file)
index 0000000..c6291f0
Binary files /dev/null and b/htmlarea/images/ed_format_bold.gif differ
diff --git a/htmlarea/images/ed_format_italic.gif b/htmlarea/images/ed_format_italic.gif
new file mode 100644 (file)
index 0000000..7bb67aa
Binary files /dev/null and b/htmlarea/images/ed_format_italic.gif differ
diff --git a/htmlarea/images/ed_format_strike.gif b/htmlarea/images/ed_format_strike.gif
new file mode 100644 (file)
index 0000000..0e00304
Binary files /dev/null and b/htmlarea/images/ed_format_strike.gif differ
diff --git a/htmlarea/images/ed_format_sub.gif b/htmlarea/images/ed_format_sub.gif
new file mode 100644 (file)
index 0000000..effcf57
Binary files /dev/null and b/htmlarea/images/ed_format_sub.gif differ
diff --git a/htmlarea/images/ed_format_sup.gif b/htmlarea/images/ed_format_sup.gif
new file mode 100644 (file)
index 0000000..1b6f401
Binary files /dev/null and b/htmlarea/images/ed_format_sup.gif differ
diff --git a/htmlarea/images/ed_format_underline.gif b/htmlarea/images/ed_format_underline.gif
new file mode 100644 (file)
index 0000000..ef8c19e
Binary files /dev/null and b/htmlarea/images/ed_format_underline.gif differ
diff --git a/htmlarea/images/ed_help.gif b/htmlarea/images/ed_help.gif
new file mode 100644 (file)
index 0000000..06c2256
Binary files /dev/null and b/htmlarea/images/ed_help.gif differ
diff --git a/htmlarea/images/ed_hr.gif b/htmlarea/images/ed_hr.gif
new file mode 100644 (file)
index 0000000..9f6e5e8
Binary files /dev/null and b/htmlarea/images/ed_hr.gif differ
diff --git a/htmlarea/images/ed_html.gif b/htmlarea/images/ed_html.gif
new file mode 100644 (file)
index 0000000..807f084
Binary files /dev/null and b/htmlarea/images/ed_html.gif differ
diff --git a/htmlarea/images/ed_image.gif b/htmlarea/images/ed_image.gif
new file mode 100644 (file)
index 0000000..9d2bff1
Binary files /dev/null and b/htmlarea/images/ed_image.gif differ
diff --git a/htmlarea/images/ed_indent_less.gif b/htmlarea/images/ed_indent_less.gif
new file mode 100644 (file)
index 0000000..f320b3e
Binary files /dev/null and b/htmlarea/images/ed_indent_less.gif differ
diff --git a/htmlarea/images/ed_indent_more.gif b/htmlarea/images/ed_indent_more.gif
new file mode 100644 (file)
index 0000000..a67139d
Binary files /dev/null and b/htmlarea/images/ed_indent_more.gif differ
diff --git a/htmlarea/images/ed_killword.gif b/htmlarea/images/ed_killword.gif
new file mode 100644 (file)
index 0000000..d44e951
Binary files /dev/null and b/htmlarea/images/ed_killword.gif differ
diff --git a/htmlarea/images/ed_left_to_right.gif b/htmlarea/images/ed_left_to_right.gif
new file mode 100644 (file)
index 0000000..9edfa63
Binary files /dev/null and b/htmlarea/images/ed_left_to_right.gif differ
diff --git a/htmlarea/images/ed_link.gif b/htmlarea/images/ed_link.gif
new file mode 100644 (file)
index 0000000..76e568b
Binary files /dev/null and b/htmlarea/images/ed_link.gif differ
diff --git a/htmlarea/images/ed_list_bullet.gif b/htmlarea/images/ed_list_bullet.gif
new file mode 100644 (file)
index 0000000..caedfd2
Binary files /dev/null and b/htmlarea/images/ed_list_bullet.gif differ
diff --git a/htmlarea/images/ed_list_num.gif b/htmlarea/images/ed_list_num.gif
new file mode 100644 (file)
index 0000000..427839d
Binary files /dev/null and b/htmlarea/images/ed_list_num.gif differ
diff --git a/htmlarea/images/ed_paste.gif b/htmlarea/images/ed_paste.gif
new file mode 100644 (file)
index 0000000..13e2324
Binary files /dev/null and b/htmlarea/images/ed_paste.gif differ
diff --git a/htmlarea/images/ed_print.gif b/htmlarea/images/ed_print.gif
new file mode 100644 (file)
index 0000000..f5bd102
Binary files /dev/null and b/htmlarea/images/ed_print.gif differ
diff --git a/htmlarea/images/ed_redo.gif b/htmlarea/images/ed_redo.gif
new file mode 100644 (file)
index 0000000..2bc002a
Binary files /dev/null and b/htmlarea/images/ed_redo.gif differ
diff --git a/htmlarea/images/ed_right_to_left.gif b/htmlarea/images/ed_right_to_left.gif
new file mode 100644 (file)
index 0000000..231f183
Binary files /dev/null and b/htmlarea/images/ed_right_to_left.gif differ
diff --git a/htmlarea/images/ed_rmformat.gif b/htmlarea/images/ed_rmformat.gif
new file mode 100644 (file)
index 0000000..5d8ce2d
Binary files /dev/null and b/htmlarea/images/ed_rmformat.gif differ
diff --git a/htmlarea/images/ed_s9yimage.gif b/htmlarea/images/ed_s9yimage.gif
new file mode 100644 (file)
index 0000000..09aa37d
Binary files /dev/null and b/htmlarea/images/ed_s9yimage.gif differ
diff --git a/htmlarea/images/ed_save.gif b/htmlarea/images/ed_save.gif
new file mode 100644 (file)
index 0000000..df3aaab
Binary files /dev/null and b/htmlarea/images/ed_save.gif differ
diff --git a/htmlarea/images/ed_save.png b/htmlarea/images/ed_save.png
new file mode 100644 (file)
index 0000000..881fe5d
Binary files /dev/null and b/htmlarea/images/ed_save.png differ
diff --git a/htmlarea/images/ed_show_border.gif b/htmlarea/images/ed_show_border.gif
new file mode 100644 (file)
index 0000000..9e3fdd2
Binary files /dev/null and b/htmlarea/images/ed_show_border.gif differ
diff --git a/htmlarea/images/ed_splitcel.gif b/htmlarea/images/ed_splitcel.gif
new file mode 100644 (file)
index 0000000..a619d8a
Binary files /dev/null and b/htmlarea/images/ed_splitcel.gif differ
diff --git a/htmlarea/images/ed_undo.gif b/htmlarea/images/ed_undo.gif
new file mode 100644 (file)
index 0000000..f90faad
Binary files /dev/null and b/htmlarea/images/ed_undo.gif differ
diff --git a/htmlarea/images/fullscreen_maximize.gif b/htmlarea/images/fullscreen_maximize.gif
new file mode 100644 (file)
index 0000000..07620bc
Binary files /dev/null and b/htmlarea/images/fullscreen_maximize.gif differ
diff --git a/htmlarea/images/fullscreen_minimize.gif b/htmlarea/images/fullscreen_minimize.gif
new file mode 100644 (file)
index 0000000..09c0383
Binary files /dev/null and b/htmlarea/images/fullscreen_minimize.gif differ
diff --git a/htmlarea/images/insert_table.gif b/htmlarea/images/insert_table.gif
new file mode 100644 (file)
index 0000000..027f7c8
Binary files /dev/null and b/htmlarea/images/insert_table.gif differ
diff --git a/htmlarea/index.html b/htmlarea/index.html
new file mode 100644 (file)
index 0000000..2e69dc4
--- /dev/null
@@ -0,0 +1,210 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN">
+<html>
+  <head>
+    <title>HTMLArea -- the free, customizable online editor</title>
+
+    <style type="text/css">
+      html, body { font-family: georgia,"times new roman",serif; background-color: #fff; color: #000; }
+      .label { text-align: right; padding-right: 0.3em; }
+      .bline { border-bottom: 1px solid #aaa; }
+    </style>
+  </head>
+
+  <body>
+    <div style="float: right; border: 1px solid #aaa; background-color: #eee; padding: 3px; margin-left: 10px; margin-bottom: 10px;">
+      <table cellspacing="0" cellpadding="0" border="0">
+        <tr>
+          <td class="label">Version:</td><td><% $version %></td>
+        </tr>
+        <tr>
+          <td class="label">Release:</td><td><% $release %> (<a href="release-notes.html">release notes</a>)</td>
+        </tr>
+        <tr>
+          <td class="label bline">Compiled at:</td><td class="bline"><% $time %></td>
+        </tr>
+        <tr>
+          <td class="label">SourceForge page:</td><td><a href="http://sf.net/projects/itools-htmlarea/">http://sf.net/projects/itools-htmlarea/</a></td>
+      </table>
+    </div>
+    <h1>HTMLArea -- the free<br/>customizable online editor</h1>
+
+    <p>
+      HTMLArea is a free, customizable online editor.  It works inside your
+      browser.  It uses a non-standard feature implemented in Internet
+      Explorer 5.5 or better for Windows and Mozilla 1.3 or better (any
+      platform), therefore it will only work in one of these browsers.
+    </p>
+
+    <p>
+      HTMLArea is copyright <a
+      href="http://interactivetools.com">InteractiveTools.com</a> and <a
+      href="http://dynarch.com">Dynarch.com</a> and it is
+      released under a BSD-style license.  HTMLArea is created and developed
+      upto version 2.03 by InteractiveTools.com.  Version 3.0 developed by
+      <a href="http://dynarch.com/mishoo/">Mihai Bazon</a> for
+      InteractiveTools.  It contains code sponsored by third-party companies as well.
+      Please see our About Box for details about who sponsored what plugins.
+    </p>
+
+    <h2><a href="examples/">Online demos</a></h2>
+
+    <ul>
+
+      <li><a href="examples/core.html">HTMLArea standard</a> -- contains the core
+        editor.</li>
+
+      <li><a href="examples/table-operations.html">HTMLArea + tables</a> --
+        loads the <tt>TableOperations</tt> plugin which provides some extra
+        editing features for tables.</li>
+
+      <li><a href="examples/spell-checker.html">HTMLArea + spell checher</a>
+        -- loads the <tt>SpellChecker</tt> plugin which provides what its
+        name says: a spell checker.  This one requires additional support on
+        the server-side.</li>
+
+      <li><a href="examples/full-page.html">HTMLArea Full HTML Editor</a> --
+        loads the <tt>FullPage</tt> plugin which allows you to edit a full
+        HTML page, including &lt;title&gt;, &lt;!DOCTYPE...&gt; and some
+        other options.</li>
+
+      <li><a href="examples/context-menu.html">HTMLArea with Context
+          Menu</a> -- this plugin provides a nice and useful context menu.</li>
+
+      <li><a href="examples/fully-loaded.html">HTMLArea fully loaded</a> --
+        all of the above. ;-)</li>
+
+    </ul>
+
+    <h2>Installation</h2>
+
+    <p>
+      Installation is (or should be) easy.  You need to unpack the ZIP file
+      in a directory accessible through your webserver.  Supposing you
+      unpack in your <tt>DocumentRoot</tt> and your <tt>DocumentRoot</tt> is
+      <tt>/var/www/html</tt> as in a standard RedHat installation, you need
+      to acomplish the following steps: (the example is for a Unix-like
+      operating system)
+    </p>
+
+    <pre style="margin-left: 2em"
+>
+cd /var/www/html
+unzip /path/to/archive/<% $basename %>.zip
+mv <% $basename %> htmlarea
+find htmlarea/ -type f -exec chmod 644 {} \;
+find htmlarea/ -type d -exec chmod 755 {} \;
+find htmlarea/ -name "*.cgi" -exec chmod 755 {} \;</pre>
+
+    <p>
+      <strong>Notes.</strong> You may chose to symlink "htmlarea" to "<%
+      $basename %>", in which case your server needs to be configured to
+      "<tt>FollowSymLinks</tt>".  You need to make sure that *.cgi files are
+      interpreted as CGI scripts.  If you want to use the SpellChecker
+      plugin you need to have a recent version of Perl installed (I
+      recommend 5.8.0) on the server, and the module Text::Aspell, available
+      from CPAN.  More info in "<a
+      href="plugins/SpellChecker/readme-tech.html">plugins/SpellChecker/readme-tech.html</a>".
+    </p>
+
+    <p>About how to setup your pages to use the editor, please read the
+      [outdated yet generally valid] <a
+        href="reference.html">documentation</a>.</p>
+
+    <h2>Status and links</h2>
+
+    <p>HTMLArea has reached version 3.0.  As of this version, it
+      supports:</p>
+
+    <ul>
+
+      <li>Customizable toolbar</li>
+
+      <li>Easy internationalization</li>
+
+      <li>Plugin-based infrastructure</li>
+
+      <li>Delivers W3-compliant HTML (with few exceptions)</li>
+
+      <li>Has a subset of Microsoft Word's keyboard shortcuts</li>
+
+      <li>Full-screen editor</li>
+
+      <li>Advanced table operations (by external plugin
+        "TableOperations")</li>
+
+      <li>Spell checker (by external plugin "SpellChecker")</li>
+
+      <li>probably more... ;-)</li>
+
+    </ul>
+
+    <p>We have a <a
+    href="http://sourceforge.net/projects/itools-htmlarea/">project page</a>
+    at <a href="http://sourceforge.net">SourceForge.net</a>.  There you can
+    also find out <a href="http://sourceforge.net/cvs/?group_id=69750">how
+    to retrieve the code from CVS</a>, or you can <a
+    href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/itools-htmlarea">browse
+    the CVS online</a>.  We also have a <a
+    href="http://sourceforge.net/tracker/?atid=525656&group_id=69750&func=browse">bug
+    system</a>, a <a
+    href="http://sourceforge.net/tracker/?atid=525658&group_id=69750&func=browse">patch
+    tracking system</a> and a <a
+    href="http://sourceforge.net/tracker/?atid=525659&group_id=69750&func=browse">feature
+    request page</a>.</p>
+
+    <p>We invite you to say everything you want about HTMLArea <a
+    href="http://www.interactivetools.com/forum/gforum.cgi?forum=14;">on the
+    forums</a> at InteractiveTools.com.  There you should also find the
+    latest news.</p>
+
+    <p>Sometimes I post news about the latest developments on <a
+    href="http://dynarch.com/mishoo/">my personal homepage</a>.</p>
+
+    <h2>"It doesn't work, what's wrong?"</h2>
+
+    <p>If it doesn't work, you have several options:</p>
+
+    <ul>
+
+      <li>Post a message to the forum.  Describe your problem in as much
+      detail as possible.  Include errors you might find in the JavaScript
+      console (if you are a Mozilla user), or errors displayed by IE (though
+      they're most of the times useless).</li>
+
+      <li>If you're positive that you discovered a bug in HTMLArea then feel
+      free to fill a bug report in our bug system.  If you have the time you
+      should check to see if a similar bug was reported or not; it might be
+      fixed already in the CVS ;-) If you're positive that a similar bug was
+      not yet reported, do fill a bug report and please include as much
+      detail as possible, such as your browser, OS, errors from JavaScript
+      console, etc.</li>
+
+      <li>If you want a new feature to be implemented, post it on the
+      features request and someone will hopefully take care of it.</li>
+
+    </ul>
+
+    <p>You can <a href="mailto:mihai_bazon@yahoo.com">contact me directly</a>
+    <em>only</em> if you want to pay me for implementing custom features to
+    HTMLArea.  If you want to sponsor these features (that is, allow them to
+    get back into the public HTMLArea distribution) I'll be cheaper. ;-)</p>
+
+    <hr />
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Sun Aug  3 14:11:26 EEST 2003 -->
+<!-- hhmts start --> Last modified: Wed Jul 14 13:20:53 CEST 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
+
+<%ARGS>
+  $project => 'HTMLArea'
+  $version => '3.0'
+  $release => 'rc1'
+  $basename => 'HTMLArea-3.0-rc1'
+</%ARGS>
+
+<%INIT>;
+use POSIX qw(strftime);
+my $time = strftime '%b %e, %Y [%H:%M] GMT', gmtime;
+</%INIT>
diff --git a/htmlarea/lang/b5.js b/htmlarea/lang/b5.js
new file mode 100644 (file)
index 0000000..248c40a
--- /dev/null
@@ -0,0 +1,36 @@
+// I18N constants -- Chinese Big-5
+// by Dave Lo -- dlo@interactivetools.com
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "b5",
+
+       tooltips: {
+               bold:           "²ÊÅé",
+               italic:         "±×Åé",
+               underline:      "©³½u",
+               strikethrough:  "§R°£½u",
+               subscript:      "¤U¼Ð",
+               superscript:    "¤W¼Ð",
+               justifyleft:    "¦ì¸m¾a¥ª",
+               justifycenter:  "¦ì¸m©~¤¤",
+               justifyright:   "¦ì¸m¾a¥k",
+               justifyfull:    "¦ì¸m¥ª¥k¥­µ¥",
+               orderedlist:    "¶¶§Ç²M³æ",
+               unorderedlist:  "µL§Ç²M³æ",
+               outdent:        "´î¤p¦æ«eªÅ¥Õ",
+               indent:         "¥[¼e¦æ«eªÅ¥Õ",
+               forecolor:      "¤å¦rÃC¦â",
+               backcolor:      "­I´ºÃC¦â",
+               horizontalrule: "¤ô¥­½u",
+               createlink:     "´¡¤J³sµ²",
+               insertimage:    "´¡¤J¹Ï§Î",
+               inserttable:    "´¡¤Jªí®æ",
+               htmlmode:       "¤Á´«HTML­ì©l½X",
+               popupeditor:    "©ñ¤j",
+               about:          "Ãö©ó HTMLArea",
+               help:           "»¡©ú",
+               textindicator:  "¦rÅé¨Ò¤l"
+       }
+};
diff --git a/htmlarea/lang/ch.js b/htmlarea/lang/ch.js
new file mode 100644 (file)
index 0000000..19fbb99
--- /dev/null
@@ -0,0 +1,83 @@
+// I18N constants
+
+// LANG: "ch", ENCODING: UTF-8
+// Samuel Stone, http://stonemicro.com/
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ch",
+
+       tooltips: {
+               bold:           "粗體",
+               italic:         "斜體",
+               underline:      "底線",
+               strikethrough:  "刪線",
+               subscript:      "下標",
+               superscript:    "上標",
+               justifyleft:    "靠左",
+               justifycenter:  "居中",
+               justifyright:   "靠右",
+               justifyfull:    "整齊",
+               orderedlist:    "順序清單",
+               unorderedlist:  "無序清單",
+               outdent:        "伸排",
+               indent:         "縮排",
+               forecolor:      "文字顏色",
+               backcolor:      "背景顏色",
+               horizontalrule: "水平線",
+               createlink:     "插入連結",
+               insertimage:    "插入圖像",
+               inserttable:    "插入表格",
+               htmlmode:       "切換HTML原始碼",
+               popupeditor:    "伸出編輯系統",
+               about:          "關於 HTMLArea",
+               help:           "說明",
+               textindicator:  "字體例子",
+               undo:           "回原",
+               redo:           "重来",
+               cut:            "剪制选项",
+               copy:           "复制选项",
+               paste:          "贴上",
+               lefttoright:    "从左到右",
+               righttoleft:    "从右到左"
+       },
+
+       buttons: {
+               "ok":           "好",
+               "cancel":       "取消"
+       },
+
+       msg: {
+               "Path":         "途徑",
+               "TEXT_MODE":    "你在用純字編輯方式.  用 [<>] 按鈕轉回 所見即所得 編輯方式.",
+
+               "IE-sucks-full-screen" :
+               // translate here
+               "整頁式在Internet Explorer 上常出問題, " +
+               "因為這是 Internet Explorer 的無名問題,我們無法解決。" +
+               "你可能看見一些垃圾,或遇到其他問題。" +
+               "我們已警告了你. 如果要轉到 正頁式 請按 好.",
+
+               "Moz-Clipboard" :
+               "Unprivileged scripts cannot access Cut/Copy/Paste programatically " +
+               "for security reasons.  Click OK to see a technical note at mozilla.org " +
+               "which shows you how to allow a script to access the clipboard."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "取消",
+               "Insert/Modify Link"                                : "插入/改寫連結",
+               "New window (_blank)"                               : "新窗户(_blank)",
+               "None (use implicit)"                               : "無(use implicit)",
+               "OK"                                                : "好",
+               "Other"                                             : "其他",
+               "Same frame (_self)"                                : "本匡 (_self)",
+               "Target:"                                           : "目標匡:",
+               "Title (tooltip):"                                  : "主題 (tooltip):",
+               "Top frame (_top)"                                  : "上匡 (_top)",
+               "URL:"                                              : "網址:",
+               "You must enter the URL where this link points to"  : "你必須輸入你要连结的網址"
+       }
+};
diff --git a/htmlarea/lang/cz.js b/htmlarea/lang/cz.js
new file mode 100644 (file)
index 0000000..91f6595
--- /dev/null
@@ -0,0 +1,63 @@
+// I18N constants
+
+// LANG: "cz", ENCODING: UTF-8 | ISO-8859-2
+// Author: Jiri Löw, <jirilow@jirilow.com>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "cz",
+
+       tooltips: {
+               bold:           "Tučně",
+               italic:         "Kurzíva",
+               underline:      "Podtržení",
+               strikethrough:  "Přeškrtnutí",
+               subscript:      "Dolní index",
+               superscript:    "Horní index",
+               justifyleft:    "Zarovnat doleva",
+               justifycenter:  "Na střed",
+               justifyright:   "Zarovnat doprava",
+               justifyfull:    "Zarovnat do stran",
+               orderedlist:    "Seznam",
+               unorderedlist:  "Odrážky",
+               outdent:        "Předsadit",
+               indent:         "Odsadit",
+               forecolor:      "Barva písma",
+               hilitecolor:    "Barva pozadí",
+               horizontalrule: "Vodorovná čára",
+               createlink:     "Vložit odkaz",
+               insertimage:    "Vložit obrázek",
+               inserttable:    "Vložit tabulku",
+               htmlmode:       "Přepnout HTML",
+               popupeditor:    "Nové okno editoru",
+               about:          "O této aplikaci",
+               showhelp:       "Nápověda aplikace",
+               textindicator:  "Zvolený styl",
+               undo:           "Vrátí poslední akci",
+               redo:           "Opakuje poslední akci",
+               cut:            "Vyjmout",
+               copy:           "Kopírovat",
+               paste:          "Vložit"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Zrušit"
+       },
+
+       msg: {
+               "Path":         "Cesta",
+               "TEXT_MODE":    "Jste v TEXTOVÉM REŽIMU.  Použijte tlačítko [<>] pro přepnutí do WYSIWIG."
+       }
+};
diff --git a/htmlarea/lang/da.js b/htmlarea/lang/da.js
new file mode 100644 (file)
index 0000000..86dc617
--- /dev/null
@@ -0,0 +1,38 @@
+// danish version for htmlArea v3.0 - Alpha Release
+// - translated by rene<rene@laerke.net>
+// term´s and licenses are equal to htmlarea!
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "da",
+
+       tooltips: {
+               bold:           "Fed",
+               italic:         "Kursiv",
+               underline:      "Understregning",
+               strikethrough:  "Overstregning ",
+               subscript:      "Sænket skrift",
+               superscript:    "Hævet skrift",
+               justifyleft:    "Venstrejuster",
+               justifycenter:  "Centrer",
+               justifyright:   "Højrejuster",
+               justifyfull:    "Lige margener",
+               orderedlist:    "Opstilling med tal",
+               unorderedlist:  "Opstilling med punkttegn",
+               outdent:        "Formindsk indrykning",
+               indent:         "Forøg indrykning",
+               forecolor:      "Skriftfarve",
+               backcolor:      "Baggrundsfarve",
+               horizontalrule: "Horisontal linie",
+               createlink:     "Indsæt hyperlink",
+               insertimage:    "Indsæt billede",
+               inserttable:    "Indsæt tabel",
+               htmlmode:       "HTML visning",
+               popupeditor:    "Vis editor i popup",
+               about:          "Om htmlarea",
+               help:           "Hjælp",
+               textindicator:  "Anvendt stil"
+       }
+};
diff --git a/htmlarea/lang/de.js b/htmlarea/lang/de.js
new file mode 100644 (file)
index 0000000..8b4474b
--- /dev/null
@@ -0,0 +1,80 @@
+// I18N constants
+
+// LANG: "de", ENCODING: ISO-8859-1 for the german umlaut!
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "de",
+
+       tooltips: {
+               bold:           "Fett",
+               italic:         "Kursiv",
+               underline:      "Unterstrichen",
+               strikethrough:  "Durchgestrichen",
+               subscript:      "Hochgestellt",
+               superscript:    "Tiefgestellt",
+        justifyleft:            "Linksbündig",
+        justifycenter:          "Zentriert",
+        justifyright:           "Rechtsbündig",
+               justifyfull:    "Blocksatz",
+        orderedlist:      "Nummerierung",
+        unorderedlist:    "Aufzählungszeichen",
+               outdent:        "Einzug verkleinern",
+        indent:                 "Einzug vergrößern",
+        forecolor:              "Schriftfarbe",
+        backcolor:              "Hindergrundfarbe",
+        hilitecolor:            "Hintergrundfarbe",
+               horizontalrule: "Horizontale Linie",
+        inserthorizontalrule:   "Horizontale Linie",
+        createlink:             "Hyperlink einfügen",
+        insertimage:            "Bild einfügen",
+        inserttable:            "Tabelle einfügen",
+               htmlmode:       "HTML Modus",
+               popupeditor:    "Editor im Popup öffnen",
+        about:                  "Über htmlarea",
+        help:                   "Hilfe",
+               showhelp:       "Hilfe",
+        textindicator:          "Derzeitiger Stil",
+        undo:                   "Rückgängig",
+               redo:           "Wiederholen",
+               cut:            "Ausschneiden",
+               copy:           "Kopieren",
+        paste:                  "Einfügen aus der Zwischenablage",
+        lefttoright:            "Textrichtung von Links nach Rechts",
+        righttoleft:            "Textrichtung von Rechts nach Links",
+        removeformat:            "Formatierung entfernen"
+       },
+  
+ buttons: {
+               "ok":           "OK",
+               "cancel":       "Abbrechen"
+       },
+
+       msg: {
+               "Path":         "Pfad",
+        "TEXT_MODE":            "Sie sind im Text-Modus. Benutzen Sie den [<>] Knopf um in den visuellen Modus (WYSIWIG) zu gelangen.",
+
+        "Moz-Clipboard" :
+        "Aus Sicherheitsgründen dürfen Skripte normalerweise nicht programmtechnisch auf " +
+        "Ausschneiden/Kopieren/Einfügen zugreifen. Bitte klicken Sie OK um die technische " +
+        "Erläuterung auf mozilla.org zu öffnen, in der erklärt wird, wie einem Skript Zugriff " +
+        "gewährt werden kann."
+    },
+    
+    dialogs: {
+        "OK":                   "OK",
+        "Cancel":               "Abbrechen",
+        "Insert/Modify Link":   "Verknüpfung hinzufügen/ändern",
+        "None (use implicit)":  "k.A. (implizit)",
+        "New window (_blank)":  "Neues Fenster (_blank)",
+        "Same frame (_self)":   "Selber Rahmen (_self)",
+        "Top frame (_top)":     "Oberster Rahmen (_top)",
+        "Other":                "Anderes",
+        "Target:":              "Ziel:",
+        "Title (tooltip):":     "Titel (Tooltip):",
+        "URL:":                 "URL:",
+        "You must enter the URL where this link points to": "Sie müssen eine Ziel-URL angeben für die Verknüpfung angeben"
+       }
+};
diff --git a/htmlarea/lang/ee.js b/htmlarea/lang/ee.js
new file mode 100644 (file)
index 0000000..91a29c4
--- /dev/null
@@ -0,0 +1,63 @@
+// I18N constants
+
+// LANG: "ee", ENCODING: UTF-8 | ISO-8859-1
+// Author: Martin Raie, <albertvill@hot.ee>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ee",
+
+       tooltips: {
+               bold:           "Paks",
+               italic:         "Kursiiv",
+               underline:      "Allakriipsutatud",
+               strikethrough:  "Läbikriipsutatud",
+               subscript:      "Allindeks",
+               superscript:    "Ülaindeks",
+               justifyleft:    "Joonda vasakule",
+               justifycenter:  "Joonda keskele",
+               justifyright:   "Joonda paremale",
+               justifyfull:    "Rööpjoonda",
+               orderedlist:    "Nummerdus",
+               unorderedlist:  "Täpploend",
+               outdent:        "Vähenda taanet",
+               indent:         "Suurenda taanet",
+               forecolor:      "Fondi värv",
+               hilitecolor:    "Tausta värv",
+               inserthorizontalrule: "Horisontaaljoon",
+               createlink:     "Lisa viit",
+               insertimage:    "Lisa pilt",
+               inserttable:    "Lisa tabel",
+               htmlmode:       "HTML/tavaline vaade",
+               popupeditor:    "Suurenda toimeti aken",
+               about:          "Teave toimeti kohta",
+               showhelp:       "Spikker",
+               textindicator:  "Kirjastiil",
+               undo:           "Võta tagasi",
+               redo:           "Tee uuesti",
+               cut:            "Lõika",
+               copy:           "Kopeeri",
+               paste:          "Kleebi"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Loobu"
+       },
+
+       msg: {
+               "Path":         "Path",
+               "TEXT_MODE":    "Sa oled tekstireziimis.  Kasuta nuppu [<>] lülitamaks tagasi WYSIWIG reziimi."
+       }
+};
diff --git a/htmlarea/lang/el.js b/htmlarea/lang/el.js
new file mode 100644 (file)
index 0000000..b7c5a27
--- /dev/null
@@ -0,0 +1,75 @@
+// I18N constants
+
+// LANG: "el", ENCODING: UTF-8 | ISO-8859-7
+// Author: Dimitris Glezos, dimitris@glezos.com
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "el",
+
+       tooltips: {
+               bold:           "Έντονα",
+               italic:         "Πλάγια",
+               underline:      "Υπογραμμισμένα",
+               strikethrough:  "Διαγραμμένα",
+               subscript:      "Δείκτης",
+               superscript:    "Δείκτης",
+               justifyleft:    "Στοίχιση Αριστερά",
+               justifycenter:  "Στοίχιση Κέντρο",
+               justifyright:   "Στοίχιση Δεξιά",
+               justifyfull:    "Πλήρης Στοίχιση",
+               orderedlist:    "Αρίθμηση",
+               unorderedlist:  "Κουκκίδες",
+               outdent:        "Μείωση Εσοχής",
+               indent:         "Αύξηση Εσοχής",
+               forecolor:      "Χρώμα Γραμματοσειράς",
+               hilitecolor:    "Χρώμα Φόντου",
+               horizontalrule: "Οριζόντια Γραμμή",
+               createlink:     "Εισαγωγή Συνδέσμου",
+               insertimage:    "Εισαγωγή/Τροποποίηση Εικόνας",
+               inserttable:    "Εισαγωγή Πίνακα",
+               htmlmode:       "Εναλλαγή σε/από HTML",
+               popupeditor:    "Μεγένθυνση επεξεργαστή",
+               about:          "Πληροφορίες",
+               showhelp:       "Βοήθεια",
+               textindicator:  "Παρών στυλ",
+               undo:           "Αναίρεση τελευταίας ενέργειας",
+               redo:           "Επαναφορά από αναίρεση",
+               cut:            "Αποκοπή",
+               copy:           "Αντιγραφή",
+               paste:          "Επικόλληση",
+        lefttoright:    "Κατεύθυνση αριστερά προς δεξιά",
+        righttoleft:    "Κατεύθυνση από δεξιά προς τα αριστερά"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Ακύρωση"
+       },
+
+       msg: {
+               "Path":         "Διαδρομή",
+               "TEXT_MODE":    "Είστε σε TEXT MODE.  Χρησιμοποιήστε το κουμπί [<>] για να επανέρθετε στο WYSIWIG.",
+
+       "IE-sucks-full-screen": "Η κατάσταση πλήρης οθόνης έχει προβλήματα με τον Internet Explorer, " +
+                                                               "λόγω σφαλμάτων στον ίδιο τον browser.  Αν το σύστημα σας είναι Windows 9x " +
+                                                               "μπορεί και να χρειαστείτε reboot. Αν είστε σίγουροι, πατήστε ΟΚ."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "Ακύρωση",
+               "Insert/Modify Link"                                : "Εισαγωγή/Τροποποίηση σύνδεσμου",
+               "New window (_blank)"                               : "Νέο παράθυρο (_blank)",
+               "None (use implicit)"                               : "Κανένα (χρήση απόλυτου)",
+               "OK"                                                : "Εντάξει",
+               "Other"                                             : "Αλλο",
+               "Same frame (_self)"                                : "Ίδιο frame (_self)",
+               "Target:"                                           : "Target:",
+               "Title (tooltip):"                                  : "Τίτλος (tooltip):",
+               "Top frame (_top)"                                  : "Πάνω frame (_top)",
+               "URL:"                                              : "URL:",
+               "You must enter the URL where this link points to"  : "Πρέπει να εισάγετε το URL που οδηγεί αυτός ο σύνδεσμος"
+       }
+};
diff --git a/htmlarea/lang/en.js b/htmlarea/lang/en.js
new file mode 100644 (file)
index 0000000..3e4021c
--- /dev/null
@@ -0,0 +1,147 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "en",
+
+       tooltips: {
+               bold:           "Bold",
+               italic:         "Italic",
+               underline:      "Underline",
+               strikethrough:  "Strikethrough",
+               subscript:      "Subscript",
+               superscript:    "Superscript",
+               justifyleft:    "Justify Left",
+               justifycenter:  "Justify Center",
+               justifyright:   "Justify Right",
+               justifyfull:    "Justify Full",
+               orderedlist:    "Ordered List",
+               unorderedlist:  "Bulleted List",
+               outdent:        "Decrease Indent",
+               indent:         "Increase Indent",
+               forecolor:      "Font Color",
+               hilitecolor:    "Background Color",
+               horizontalrule: "Horizontal Rule",
+               createlink:     "Insert Web Link",
+               insertimage:    "Insert/Modify Image",
+               inserttable:    "Insert Table",
+               htmlmode:       "Toggle HTML Source",
+               popupeditor:    "Enlarge Editor",
+               about:          "About this editor",
+               showhelp:       "Help using editor",
+               textindicator:  "Current style",
+               undo:           "Undoes your last action",
+               redo:           "Redoes your last action",
+               cut:            "Cut selection",
+               copy:           "Copy selection",
+               paste:          "Paste from clipboard",
+               lefttoright:    "Direction left to right",
+               righttoleft:    "Direction right to left",
+               removeformat:   "Remove formatting",
+               print:          "Print document",
+               killword:       "Clear MSOffice tags"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Cancel"
+       },
+
+       msg: {
+               "Path":         "Path",
+               "TEXT_MODE":    "You are in TEXT MODE.  Use the [<>] button to switch back to WYSIWYG.",
+
+               "IE-sucks-full-screen" :
+               // translate here
+               "The full screen mode is known to cause problems with Internet Explorer, " +
+               "due to browser bugs that we weren't able to workaround.  You might experience garbage " +
+               "display, lack of editor functions and/or random browser crashes.  If your system is Windows 9x " +
+               "it's very likely that you'll get a 'General Protection Fault' and need to reboot.\n\n" +
+               "You have been warned.  Please press OK if you still want to try the full screen editor.",
+
+               "Moz-Clipboard" :
+               "Unprivileged scripts cannot access Cut/Copy/Paste programatically " +
+               "for security reasons.  Click OK to see a technical note at mozilla.org " +
+               "which shows you how to allow a script to access the clipboard."
+       },
+
+       dialogs: {
+               // Common
+               "OK"                                                : "OK",
+               "Cancel"                                            : "Cancel",
+
+               "Alignment:"                                        : "Alignment:",
+               "Not set"                                           : "Not set",
+               "Left"                                              : "Left",
+               "Right"                                             : "Right",
+               "Texttop"                                           : "Texttop",
+               "Absmiddle"                                         : "Absmiddle",
+               "Baseline"                                          : "Baseline",
+               "Absbottom"                                         : "Absbottom",
+               "Bottom"                                            : "Bottom",
+               "Middle"                                            : "Middle",
+               "Top"                                               : "Top",
+
+               "Layout"                                            : "Layout",
+               "Spacing"                                           : "Spacing",
+               "Horizontal:"                                       : "Horizontal:",
+               "Horizontal padding"                                : "Horizontal padding",
+               "Vertical:"                                         : "Vertical:",
+               "Vertical padding"                                  : "Vertical padding",
+               "Border thickness:"                                 : "Border thickness:",
+               "Leave empty for no border"                         : "Leave empty for no border",
+
+               // Insert Link
+               "Insert/Modify Link"                                : "Insert/Modify Link",
+               "None (use implicit)"                               : "None (use implicit)",
+               "New window (_blank)"                               : "New window (_blank)",
+               "Same frame (_self)"                                : "Same frame (_self)",
+               "Top frame (_top)"                                  : "Top frame (_top)",
+               "Other"                                             : "Other",
+               "Target:"                                           : "Target:",
+               "Title (tooltip):"                                  : "Title (tooltip):",
+               "URL:"                                              : "URL:",
+               "You must enter the URL where this link points to"  : "You must enter the URL where this link points to",
+               // Insert Table
+               "Insert Table"                                      : "Insert Table",
+               "Rows:"                                             : "Rows:",
+               "Number of rows"                                    : "Number of rows",
+               "Cols:"                                             : "Cols:",
+               "Number of columns"                                 : "Number of columns",
+               "Width:"                                            : "Width:",
+               "Width of the table"                                : "Width of the table",
+               "Percent"                                           : "Percent",
+               "Pixels"                                            : "Pixels",
+               "Em"                                                : "Em",
+               "Width unit"                                        : "Width unit",
+               "Positioning of this table"                         : "Positioning of this table",
+               "Cell spacing:"                                     : "Cell spacing:",
+               "Space between adjacent cells"                      : "Space between adjacent cells",
+               "Cell padding:"                                     : "Cell padding:",
+               "Space between content and border in cell"          : "Space between content and border in cell",
+               // Insert Image
+               "Insert Image"                                      : "Insert Image",
+               "Image URL:"                                        : "Image URL:",
+               "Enter the image URL here"                          : "Enter the image URL here",
+               "Preview"                                           : "Preview",
+               "Preview the image in a new window"                 : "Preview the image in a new window",
+               "Alternate text:"                                   : "Alternate text:",
+               "For browsers that don't support images"            : "For browsers that don't support images",
+               "Positioning of this image"                         : "Positioning of this image",
+               "Image Preview:"                                    : "Image Preview:"
+       }
+};
diff --git a/htmlarea/lang/es.js b/htmlarea/lang/es.js
new file mode 100644 (file)
index 0000000..5a1e86f
--- /dev/null
@@ -0,0 +1,51 @@
+// I18N constants
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "es",
+
+       tooltips: {
+               bold:           "Negrita",
+               italic:         "Cursiva",
+               underline:      "Subrayado",
+               strikethrough:  "Tachado",
+               subscript:      "Subíndice",
+               superscript:    "Superíndice",
+               justifyleft:    "Alinear a la Izquierda",
+               justifycenter:  "Centrar",
+               justifyright:   "Alinear a la Derecha",
+               justifyfull:    "Justificar",
+               orderedlist:    "Lista Ordenada",
+               unorderedlist:  "Lista No Ordenada",
+               outdent:        "Aumentar Sangría",
+               indent:         "Disminuir Sangría",
+               forecolor:      "Color del Texto",
+               hilitecolor:    "Color del Fondo",
+               inserthorizontalrule: "Línea Horizontal",
+               createlink:     "Insertar Enlace",
+               insertimage:    "Insertar Imagen",
+               inserttable:    "Insertar Tabla",
+               htmlmode:       "Ver Documento en HTML",
+               popupeditor:    "Ampliar Editor",
+               about:          "Acerca del Editor",
+               showhelp:       "Ayuda",
+               textindicator:  "Estilo Actual",
+               undo:           "Deshacer",
+               redo:           "Rehacer",
+               cut:            "Cortar selección",
+               copy:           "Copiar selección",
+               paste:          "Pegar desde el portapapeles"
+       },
+
+       buttons: {
+               "ok":           "Aceptar",
+               "cancel":       "Cancelar"
+       },
+
+       msg: {
+               "Path":         "Ruta",
+               "TEXT_MODE":    "Esta en modo TEXTO. Use el boton [<>] para cambiar a WYSIWIG",
+       }
+};
diff --git a/htmlarea/lang/fi.js b/htmlarea/lang/fi.js
new file mode 100644 (file)
index 0000000..2e18ea1
--- /dev/null
@@ -0,0 +1,46 @@
+// I18N constants
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "en",
+
+       tooltips: {
+               bold:                   "Lihavoitu",
+               italic:                 "Kursivoitu",
+               underline:              "Alleviivattu",
+               strikethrough:          "Yliviivattu",
+               subscript:              "Alaindeksi",
+               superscript:            "Yläindeksi",
+               justifyleft:            "Tasaa vasemmat reunat",
+               justifycenter:          "Keskitä",
+               justifyright:           "Tasaa oikeat reunat",
+               justifyfull:            "Tasaa molemmat reunat",
+               orderedlist:    "Numerointi",
+               unorderedlist:  "Luettelomerkit",
+               outdent:                "Lisää sisennystä",
+               indent:                 "Pienennä sisennystä",
+               forecolor:              "Fontin väri",
+               hilitecolor:            "Taustaväri",
+               inserthorizontalrule:   "Vaakaviiva",
+               createlink:             "Lisää Linkki",
+               insertimage:            "Lisää Kuva",
+               inserttable:            "Lisää Taulu",
+               htmlmode:               "HTML Lähdekoodi vs WYSIWYG",
+               popupeditor:            "Suurenna Editori",
+               about:                  "Tietoja Editorista",
+               showhelp:               "Näytä Ohje",
+               textindicator:          "Nykyinen tyyli",
+               undo:                   "Peruuta viimeinen toiminto",
+               redo:                   "Palauta viimeinen toiminto",
+               cut:                    "Leikkaa maalattu",
+               copy:                   "Kopioi maalattu",
+               paste:                  "Liitä leikepyödältä"
+       },
+
+       buttons: {
+               "ok":                   "Hyväksy",
+               "cancel":               "Peruuta"
+       }
+};
diff --git a/htmlarea/lang/fr.js b/htmlarea/lang/fr.js
new file mode 100644 (file)
index 0000000..e307c81
--- /dev/null
@@ -0,0 +1,97 @@
+// I18N constants
+
+// LANG: "fr", ENCODING: UTF-8 | ISO-8859-1
+// Author: Simon Richard, s.rich@sympatico.ca
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+// All technical terms used in this document are the ones approved
+// by the Office québécois de la langue française.
+// Tous les termes techniques utilisés dans ce document sont ceux
+// approuvés par l'Office québécois de la langue française.
+// http://www.oqlf.gouv.qc.ca/
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "fr",
+
+       tooltips: {
+               bold:           "Gras",
+               italic:         "Italique",
+               underline:      "Souligné",
+               strikethrough:  "Barré",
+               subscript:      "Indice",
+               superscript:    "Exposant",
+               justifyleft:    "Aligné à gauche",
+               justifycenter:  "Centré",
+               justifyright:   "Aligné à droite",
+               justifyfull:    "Justifier",
+               orderedlist:    "Numérotation",
+               unorderedlist:  "Puces",
+               outdent:        "Diminuer le retrait",
+               indent:         "Augmenter le retrait",
+               forecolor:      "Couleur de police",
+               hilitecolor:    "Surlignage",
+               horizontalrule: "Ligne horizontale",
+               createlink:     "Insérer un hyperlien",
+               insertimage:    "Insérer/Modifier une image",
+               inserttable:    "Insérer un tableau",
+               htmlmode:       "Passer au code source",
+               popupeditor:    "Agrandir l'éditeur",
+               about:          "À propos de cet éditeur",
+               showhelp:       "Aide sur l'éditeur",
+               textindicator:  "Style courant",
+               undo:           "Annuler la dernière action",
+               redo:           "Répéter la dernière action",
+               cut:            "Couper la sélection",
+               copy:           "Copier la sélection",
+               paste:          "Coller depuis le presse-papier",
+               lefttoright:    "Direction de gauche à droite",
+               righttoleft:    "Direction de droite à gauche"
+       },
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Annuler"
+       },
+
+       msg: {
+               "Path":         "Chemin",
+               "TEXT_MODE":    "Vous êtes en MODE TEXTE.  Appuyez sur le bouton [<>] pour retourner au mode tel-tel.",
+
+               "IE-sucks-full-screen" :
+               // translate here
+               "Le mode plein écran peut causer des problèmes sous Internet Explorer, " +
+               "ceci dû à des bogues du navigateur qui ont été impossible à contourner.  " +
+               "Les différents symptômes peuvent être un affichage déficient, le manque de " +
+               "fonctions dans l'éditeur et/ou pannes aléatoires du navigateur.  Si votre " +
+               "système est Windows 9x, il est possible que vous subissiez une erreur de type " +
+               "«General Protection Fault» et que vous ayez à redémarrer votre ordinateur." +
+               "\n\nConsidérez-vous comme ayant été avisé.  Appuyez sur OK si vous désirez tout " +
+               "de même essayer le mode plein écran de l'éditeur."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "Annuler",
+               "Insert/Modify Link"                                : "Insérer/Modifier Lien",
+               "New window (_blank)"                               : "Nouvelle fenêtre (_blank)",
+               "None (use implicit)"                               : "Aucun (par défaut)",
+               "OK"                                                : "OK",
+               "Other"                                             : "Autre",
+               "Same frame (_self)"                                : "Même cadre (_self)",
+               "Target:"                                           : "Cible:",
+               "Title (tooltip):"                                  : "Titre (infobulle):",
+               "Top frame (_top)"                                  : "Cadre du haut (_top)",
+               "URL:"                                              : "Adresse Web:",
+               "You must enter the URL where this link points to"  : "Vous devez entrer l'adresse Web du lien"
+       }
+};
diff --git a/htmlarea/lang/gb.js b/htmlarea/lang/gb.js
new file mode 100644 (file)
index 0000000..049087f
--- /dev/null
@@ -0,0 +1,36 @@
+// I18N constants -- Chinese GB
+// by Dave Lo -- dlo@interactivetools.com
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "gb",
+
+       tooltips: {
+               bold:           "´ÖÌå",
+               italic:         "бÌå",
+               underline:      "µ×Ïß",
+               strikethrough:  "ɾ³ýÏß",
+               subscript:      "ϱê",
+               superscript:    "Éϱê",
+               justifyleft:    "λÖÿ¿×ó",
+               justifycenter:  "λÖþÓÖÐ",
+               justifyright:   "λÖÿ¿ÓÒ",
+               justifyfull:    "λÖÃ×óÓÒÆ½µÈ",
+               orderedlist:    "˳ÐòÇåµ¥",
+               unorderedlist:  "ÎÞÐòÇåµ¥",
+               outdent:        "¼õСÐÐǰ¿Õ°×",
+               indent:         "¼Ó¿íÐÐǰ¿Õ°×",
+               forecolor:      "ÎÄ×ÖÑÕÉ«",
+               backcolor:      "±³¾°ÑÕÉ«",
+               horizontalrule: "ˮƽÏß",
+               createlink:     "²åÈëÁ¬½á",
+               insertimage:    "²åÈëͼÐÎ",
+               inserttable:    "²åÈë±í¸ñ",
+               htmlmode:       "Çл»HTMLԭʼÂë",
+               popupeditor:    "·Å´ó",
+               about:          "¹Øì¶ HTMLArea",
+               help:           "˵Ã÷",
+               textindicator:  "×ÖÌåÀý×Ó"
+       }
+};
diff --git a/htmlarea/lang/he.js b/htmlarea/lang/he.js
new file mode 100644 (file)
index 0000000..5d87b78
--- /dev/null
@@ -0,0 +1,89 @@
+// I18N constants
+
+// LANG: "he", ENCODING: UTF-8
+// Author: Liron Newman, http://www.eesh.net, <plastish at ultinet dot org>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "he",
+
+       tooltips: {
+               bold:           "מודגש",
+               italic:         "נטוי",
+               underline:      "קו תחתי",
+               strikethrough:  "קו אמצע",
+               subscript:      "כתב עילי",
+               superscript:    "כתב תחתי",
+               justifyleft:    " ישור לשמאל",
+               justifycenter:  "ישור למרכז",
+               justifyright:   "ישור לימין",
+               justifyfull:    "ישור לשורה מלאה",
+               orderedlist:    "רשימה ממוספרת",
+               unorderedlist:  "רשימה לא ממוספרת",
+               outdent:        "הקטן כניסה",
+               indent:         "הגדל כניסה",
+               forecolor:      "צבע גופן",
+               hilitecolor:    "צבע רקע",
+               horizontalrule: "קו אנכי",
+               createlink:     "הכנס היפר-קישור",
+               insertimage:    "הכנס/שנה תמונה",
+               inserttable:    "הכנס טבלה",
+               htmlmode:       "שנה מצב קוד HTML",
+               popupeditor:    "הגדל את העורך",
+               about:          "אודות עורך זה",
+               showhelp:       "עזרה לשימוש בעורך",
+               textindicator:  "סגנון נוכחי",
+               undo:           "מבטל את פעולתך האחרונה",
+               redo:           "מבצע מחדש את הפעולה האחרונה שביטלת",
+               cut:            "גזור בחירה",
+               copy:           "העתק בחירה",
+               paste:          "הדבק מהלוח",
+               lefttoright:    "כיוון משמאל לימין",
+               righttoleft:    "כיוון מימין לשמאל"
+       },
+
+       buttons: {
+               "ok":           "אישור",
+               "cancel":       "ביטול"
+       },
+
+       msg: {
+               "Path":         "נתיב עיצוב",
+               "TEXT_MODE":    "אתה במצב טקסט נקי (קוד). השתמש בכפתור [<>] כדי לחזור למצב WYSIWYG (תצוגת עיצוב).",
+
+               "IE-sucks-full-screen" :
+               // translate here
+               "מצב מסך מלא יוצר בעיות בדפדפן Internet Explorer, " +
+               "עקב באגים בדפדפן לא יכולנו לפתור את זה.  את/ה עלול/ה לחוות תצוגת זבל,  " +
+               "בעיות בתפקוד העורך ו/או קריסה של הדפדפן.  אם המערכת שלך היא Windows 9x " +
+               "סביר להניח שתקבל/י 'General Protection Fault' ותאלצ/י לאתחל את המחשב.\n\n" +
+               "ראה/י הוזהרת.  אנא לחץ/י אישור אם את/ה עדיין רוצה לנסות את העורך במסך מלא."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "ביטול",
+               "Insert/Modify Link"                                : "הוסף/שנה קישור",
+               "New window (_blank)"                               : "חלון חדש (_blank)",
+               "None (use implicit)"                               : "ללא (השתמש ב-frame הקיים)",
+               "OK"                                                : "OK",
+               "Other"                                             : "אחר",
+               "Same frame (_self)"                                : "אותו frame (_self)",
+               "Target:"                                           : "יעד:",
+               "Title (tooltip):"                                  : "כותרת (tooltip):",
+               "Top frame (_top)"                                  : "Frame עליון (_top)",
+               "URL:"                                              : "URL:",
+               "You must enter the URL where this link points to"  : "חובה לכתוב URL שאליו קישור זה מצביע"
+
+       }
+};
diff --git a/htmlarea/lang/hu.js b/htmlarea/lang/hu.js
new file mode 100644 (file)
index 0000000..2c549eb
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants
+
+// LANG: "hu", ENCODING: UTF-8
+// Author: Miklós Somogyi, <somogyine@vnet.hu>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "hu",
+
+       tooltips: {
+               bold:           "Félkövér",
+               italic:         "Dőlt",
+               underline:      "Aláhúzott",
+               strikethrough:  "Áthúzott",
+               subscript:      "Alsó index",
+               superscript:    "Felső index",
+               justifyleft:    "Balra zárt",
+               justifycenter:  "Középre zárt",
+               justifyright:   "Jobbra zárt",
+               justifyfull:    "Sorkizárt",
+               orderedlist:    "Számozott lista",
+               unorderedlist:  "Számozatlan lista",
+               outdent:        "Behúzás csökkentése",
+               indent:         "Behúzás növelése",
+               forecolor:      "Karakterszín",
+               hilitecolor:    "Háttérszín",
+               horizontalrule: "Elválasztó vonal",
+               createlink:     "Hiperhivatkozás beszúrása",
+               insertimage:    "Kép beszúrása",
+               inserttable:    "Táblázat beszúrása",
+               htmlmode:       "HTML forrás be/ki",
+               popupeditor:    "Szerkesztő külön ablakban",
+               about:          "Névjegy",
+               showhelp:       "Súgó",
+               textindicator:  "Aktuális stílus",
+               undo:           "Visszavonás",
+               redo:           "Újra végrehajtás",
+               cut:            "Kivágás",
+               copy:           "Másolás",
+               paste:          "Beillesztés",
+               lefttoright:    "Irány balról jobbra",
+               righttoleft:    "Irány jobbról balra"
+       },
+
+       buttons: {
+               "ok":           "Rendben",
+               "cancel":       "Mégsem"
+       },
+
+       msg: {
+               "Path":         "Hierarchia",
+               "TEXT_MODE":    "Forrás mód. Visszaváltás [<>] gomb",
+
+               "IE-sucks-full-screen" :
+               // translate here
+               "A teljesképrenyős szerkesztés hibát okozhat Internet Explorer használata esetén, " +
+               "ez a böngésző a hibája, amit nem tudunk kikerülni. Szemetet észlelhet a képrenyőn, " +
+               "illetve néhány funkció hiányozhat és/vagy véletlenszerűen lefagyhat a böngésző. " +
+               "Windows 9x operaciós futtatása esetén elég valószínű, hogy 'General Protection Fault' " +
+               "hibát okoz és újra kell indítania a számítógépet.\n\n" +
+               "Figyelmeztettük.  Kérjük nyomja meg a Rendben gombot, ha mégis szeretné megnyitni a " +
+               "szerkesztőt külön ablakban."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "Mégsem",
+               "Insert/Modify Link"                                : "Hivatkozás Beszúrása/Módosítása",
+               "New window (_blank)"                               : "Új ablak (_blank)",
+               "None (use implicit)"                               : "Nincs (use implicit)",
+               "OK"                                                : "OK",
+               "Other"                                             : "Más",
+               "Same frame (_self)"                                : "Ugyanabba a keretbe (_self)",
+               "Target:"                                           : "Cél:",
+               "Title (tooltip):"                                  : "Cím (tooltip):",
+               "Top frame (_top)"                                  : "Felső keret (_top)",
+               "URL:"                                              : "URL:",
+               "You must enter the URL where this link points to"  : "Be kell írnia az URL-t, ahova a hivatkozás mutasson"
+       }
+};
diff --git a/htmlarea/lang/it.js b/htmlarea/lang/it.js
new file mode 100644 (file)
index 0000000..3215dcf
--- /dev/null
@@ -0,0 +1,79 @@
+// I18N constants
+
+// LANG: "it", ENCODING: UTF-8 | ISO-8859-1
+// Author: Fabio Rotondo <fabio@rotondo.it>
+// Update for 3.0 rc1: Giovanni Premuda <gpremuda@softwerk.it>
+
+HTMLArea.I18N = {
+
+        // the following should be the filename without .js extension
+        // it will be used for automatically load plugin language.
+        lang: "it",
+
+        tooltips: {
+                bold:           "Grassetto",
+                italic:         "Corsivo",
+                underline:      "Sottolineato",
+                strikethrough:  "Barrato",
+                subscript:      "Pedice",
+                superscript:    "Apice",
+                justifyleft:    "Allinea a sinistra",
+                justifycenter:  "Allinea in centro",
+                justifyright:   "Allinea a destra",
+                justifyfull:    "Giustifica",
+                insertorderedlist:    "Lista ordinata",
+                insertunorderedlist:  "Lista puntata",
+                outdent:        "Decrementa indentazione",
+                indent:         "Incrementa indentazione",
+                forecolor:      "Colore del carattere",
+                hilitecolor:    "Colore di sfondo",
+                inserthorizontalrule: "Linea orizzontale",
+                createlink:     "Inserisci un link",
+                insertimage:    "Inserisci un'immagine",
+                inserttable:    "Inserisci una tabella",
+                htmlmode:       "Visualizzazione HTML",
+                popupeditor:    "Editor a pieno schermo",
+                about:          "Info sull'editor",
+                showhelp:       "Aiuto sull'editor",
+                textindicator:  "Stile corrente",
+                undo:           "Annulla",
+                redo:           "Ripristina",
+                cut:            "Taglia",
+                copy:           "Copia",
+                paste:          "Incolla",
+                lefttoright:    "Scrivi da sinistra a destra",
+                righttoleft:    "Scrivi da destra a sinistra"
+        },
+
+        buttons: {
+                "ok":           "OK",
+                "cancel":       "Annulla"
+        },
+
+        msg: {
+                "Path":         "Percorso",
+                "TEXT_MODE":    "Sei in MODALITA' TESTO. Usa il bottone [<>] per tornare alla modalità WYSIWYG.",
+                "IE-sucks-full-screen" :
+                // translate here
+                "The full screen mode is known to cause problems with Internet Explorer, " +
+                "due to browser bugs that we weren't able to workaround.  You might experience garbage " +
+                "display, lack of editor functions and/or random browser crashes.  If your system is Windows 9x " +
+                "it's very likely that you'll get a 'General Protection Fault' and need to reboot.\n\n" +
+                "You have been warned.  Please press OK if you still want to try the full screen editor."
+        },
+
+        dialogs: {
+                "Annulla"                                            : "Cancel",
+                "Inserisci/modifica Link"                                : "Insert/Modify Link",
+                "Nuova finestra (_blank)"                               : "New window (_blank)",
+                "Nessuno (usa predefinito)"                               : "None (use implicit)",
+                "OK"                                                : "OK",
+                "Altro"                                             : "Other",
+                "Stessa finestra (_self)"                                : "Same frame (_self)",
+                "Target:"                                           : "Target:",
+                "Title (suggerimento):"                                  : "Title (tooltip):",
+                "Frame principale (_top)"                                  : "Top frame (_top)",
+                "URL:"                                              : "URL:",
+                "You must enter the URL where this link points to"  : "Devi inserire un indirizzo per questo link"
+        }
+};
diff --git a/htmlarea/lang/ja-euc.js b/htmlarea/lang/ja-euc.js
new file mode 100644 (file)
index 0000000..87574e8
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants -- Japanese EUC
+// by Manabu Onoue -- tmocsys@tmocsys.com
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ja-euc",
+
+       tooltips: {
+               bold:           "ÂÀ»ú",
+               italic:         "¼ÐÂÎ",
+               underline:      "²¼Àþ",
+               strikethrough:  "ÂǤÁ¾Ã¤·Àþ",
+               subscript:      "²¼ÉÕ¤­Åº¤¨»ú",
+               superscript:    "¾åÉÕ¤­Åº¤¨»ú",
+               justifyleft:    "º¸´ó¤»",
+               justifycenter:  "Ãæ±û´ó¤»",
+               justifyright:   "±¦´ó¤»",
+               justifyfull:    "¶ÑÅù³äÉÕ",
+               orderedlist:    "ÈÖ¹æÉÕ¤­²Õ¾ò½ñ¤­",
+               unorderedlist:  "µ­¹æÉÕ¤­²Õ¾ò½ñ¤­",
+               outdent:        "¥¤¥ó¥Ç¥ó¥È²ò½ü",
+               indent:         "¥¤¥ó¥Ç¥ó¥ÈÀßÄê",
+               forecolor:      "ʸ»ú¿§",
+               backcolor:      "ÇØ·Ê¿§",
+               horizontalrule: "¿åÊ¿Àþ",
+               createlink:     "¥ê¥ó¥¯ºîÀ®",
+               insertimage:    "²èÁüÁÞÆþ",
+               inserttable:    "¥Æ¡¼¥Ö¥ëÁÞÆþ",
+               htmlmode:       "HTMLɽ¼¨ÀÚÂØ",
+               popupeditor:    "¥¨¥Ç¥£¥¿³ÈÂç",
+               about:          "¥Ð¡¼¥¸¥ç¥ó¾ðÊó",
+               help:           "¥Ø¥ë¥×",
+               textindicator:  "¸½ºß¤Î¥¹¥¿¥¤¥ë"
+       }
+};
diff --git a/htmlarea/lang/ja-jis.js b/htmlarea/lang/ja-jis.js
new file mode 100644 (file)
index 0000000..49e5a3b
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants -- Japanese JIS
+// by Manabu Onoue -- tmocsys@tmocsys.com
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ja-jis",
+
+       tooltips: {
+               bold:           "\e$BB@;z\e(B",
+               italic:         "\e$B<PBN\e(B",
+               underline:      "\e$B2<@~\e(B",
+               strikethrough:  "\e$BBG$A>C$7@~\e(B",
+               subscript:      "\e$B2<IU$-E:$(;z\e(B",
+               superscript:    "\e$B>eIU$-E:$(;z\e(B",
+               justifyleft:    "\e$B:84s$;\e(B",
+               justifycenter:  "\e$BCf1{4s$;\e(B",
+               justifyright:   "\e$B1&4s$;\e(B",
+               justifyfull:    "\e$B6QEy3dIU\e(B",
+               orderedlist:    "\e$BHV9fIU$-2U>r=q$-\e(B",
+               unorderedlist:  "\e$B5-9fIU$-2U>r=q$-\e(B",
+               outdent:        "\e$B%$%s%G%s%H2r=|\e(B",
+               indent:         "\e$B%$%s%G%s%H@_Dj\e(B",
+               forecolor:      "\e$BJ8;z?'\e(B",
+               backcolor:      "\e$BGX7J?'\e(B",
+               horizontalrule: "\e$B?eJ?@~\e(B",
+               createlink:     "\e$B%j%s%/:n@.\e(B",
+               insertimage:    "\e$B2hA|A^F~\e(B",
+               inserttable:    "\e$B%F!<%V%kA^F~\e(B",
+               htmlmode:       "HTML\e$BI=<(@ZBX\e(B",
+               popupeditor:    "\e$B%(%G%#%?3HBg\e(B",
+               about:          "\e$B%P!<%8%g%s>pJs\e(B",
+               help:           "\e$B%X%k%W\e(B",
+               textindicator:  "\e$B8=:_$N%9%?%$%k\e(B"
+       }
+};
diff --git a/htmlarea/lang/ja-sjis.js b/htmlarea/lang/ja-sjis.js
new file mode 100644 (file)
index 0000000..9124529
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants -- Japanese Shift-JIS
+// by Manabu Onoue -- tmocsys@tmocsys.com
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ja-sjis",
+
+       tooltips: {
+               bold:           "\91¾\8e\9a",
+               italic:         "\8eÎ\91Ì",
+               underline:      "\89º\90ü",
+               strikethrough:  "\91Å\82¿\8fÁ\82µ\90ü",
+               subscript:      "\89º\95t\82«\93Y\82¦\8e\9a",
+               superscript:    "\8fã\95t\82«\93Y\82¦\8e\9a",
+               justifyleft:    "\8d\8añ\82¹",
+               justifycenter:  "\92\86\89\9b\8añ\82¹",
+               justifyright:   "\89E\8añ\82¹",
+               justifyfull:    "\8bÏ\93\99\8a\84\95t",
+               orderedlist:    "\94Ô\8d\86\95t\82«\89Ó\8fð\8f\91\82«",
+               unorderedlist:  "\8bL\8d\86\95t\82«\89Ó\8fð\8f\91\82«",
+               outdent:        "\83C\83\93\83f\83\93\83g\89ð\8f\9c",
+               indent:         "\83C\83\93\83f\83\93\83g\90Ý\92è",
+               forecolor:      "\95\8e\9a\90F",
+               backcolor:      "\94w\8ci\90F",
+               horizontalrule: "\90\85\95½\90ü",
+               createlink:     "\83\8a\83\93\83N\8dì\90¬",
+               insertimage:    "\89æ\91\9c\91}\93ü",
+               inserttable:    "\83e\81[\83u\83\8b\91}\93ü",
+               htmlmode:       "HTML\95\\8e¦\90Ø\91Ö",
+               popupeditor:    "\83G\83f\83B\83^\8ag\91å",
+               about:          "\83o\81[\83W\83\87\83\93\8fî\95ñ",
+               help:           "\83w\83\8b\83v",
+               textindicator:  "\8c»\8dÝ\82Ì\83X\83^\83C\83\8b"
+       }
+};
diff --git a/htmlarea/lang/ja-utf8.js b/htmlarea/lang/ja-utf8.js
new file mode 100644 (file)
index 0000000..f351fac
--- /dev/null
@@ -0,0 +1,37 @@
+// I18N constants -- Japanese UTF-8
+// by Manabu Onoue -- tmocsys@tmocsys.com
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "ja-utf8",
+
+       tooltips: {
+               bold:           "太字",
+               italic:         "斜体",
+               underline:      "下線",
+               strikethrough:  "打ち消し線",
+               subscript:      "下付き添え字",
+               superscript:    "上付き添え字",
+               justifyleft:    "左寄せ",
+               justifycenter:  "中央寄せ",
+               justifyright:   "右寄せ",
+               justifyfull:    "均等割付",
+               orderedlist:    "番号付き箇条書き",
+               unorderedlist:  "記号付き箇条書き",
+               outdent:        "インデント解除",
+               indent:         "インデント設定",
+               forecolor:      "文字色",
+               backcolor:      "背景色",
+               horizontalrule: "水平線",
+               createlink:     "リンク作成",
+               insertimage:    "画像挿入",
+               inserttable:    "テーブル挿入",
+               htmlmode:       "HTML表示切替",
+               popupeditor:    "エディタ拡大",
+               about:          "バージョン情報",
+               help:           "ヘルプ",
+               textindicator:  "現在のスタイル"
+       }
+};
diff --git a/htmlarea/lang/lt.js b/htmlarea/lang/lt.js
new file mode 100644 (file)
index 0000000..2b08929
--- /dev/null
@@ -0,0 +1,77 @@
+// I18N constants
+
+// LANG: "lt", ENCODING: UTF-8
+// Author: Jaroslav Šatkevič, <jaro@akl.lt>
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "en",
+
+       tooltips: {
+               bold:           "Paryškinti",
+               italic:         "Kursyvas",
+               underline:      "Pabraukti",
+               strikethrough:  "Perbraukti",
+               subscript:      "Apatinis indeksas",
+               superscript:    "Viršutinis indeksas",
+               justifyleft:    "Lygiavimas pagal kairę",
+               justifycenter:  "Lygiavimas pagal centrą",
+               justifyright:   "Lygiavimas pagal dešinę",
+               justifyfull:    "Lygiuoti pastraipą",
+               orderedlist:    "Numeruotas sąrašas",
+               unorderedlist:  "Suženklintas sąrašas",
+               outdent:        "Sumažinti paraštę",
+               indent:         "Padidinti paraštę",
+               forecolor:      "Šrifto spalva",
+               hilitecolor:    "Fono spalva",
+               horizontalrule: "Horizontali linija",
+               createlink:     "Įterpti nuorodą",
+               insertimage:    "Įterpti paveiksliuką",
+               inserttable:    "Įterpti lentelę",
+               htmlmode:       "Perjungti į HTML/WYSIWYG",
+               popupeditor:    "Išplėstas redagavimo ekranas/Enlarge Editor",
+               about:          "Apie redaktorių",
+               showhelp:       "Pagalba naudojant redaktorių",
+               textindicator:  "Dabartinis stilius",
+               undo:           "Atšaukia paskutini jūsų veiksmą",
+               redo:           "Pakartoja paskutinį atšauktą jūsų veiksmą",
+               cut:            "Iškirpti",
+               copy:           "Kopijuoti",
+               paste:          "Įterpti"
+},
+
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Atšaukti"
+       },
+
+       msg: {
+               "Path":         "Kelias",
+               "TEXT_MODE":    "Jūs esete teksto režime.  Naudokite [<>] mygtuką grįžimui į WYSIWYG.",
+
+               "IE-sucks-full-screen" :
+               // translate here
+               "The full screen mode is known to cause problems with Internet Explorer, " +
+               "due to browser bugs that we weren't able to workaround.  You might experience garbage " +
+               "display, lack of editor functions and/or random browser crashes.  If your system is Windows 9x " +
+               "it's very likely that you'll get a 'General Protection Fault' and need to reboot.\n\n" +
+               "You have been warned.  Please press OK if you still want to try the full screen editor."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "Atšaukti",
+               "Insert/Modify Link"                                : "Idėti/Modifikuoti",
+               "New window (_blank)"                               : "Naujas langas (_blank)",
+               "None (use implicit)"                               : "None (use implicit)",
+               "OK"                                                : "OK",
+               "Other"                                             : "Kitas",
+               "Same frame (_self)"                                : "Same frame (_self)",
+               "Target:"                                           : "Target:",
+               "Title (tooltip):"                                  : "Pavadinimas (tooltip):",
+               "Top frame (_top)"                                  : "Top frame (_top)",
+               "URL:"                                              : "URL:",
+               "You must enter the URL where this link points to"  : "Jus privalote nurodyti URL į kuri rodo šitą nuoroda"
+       }
+};
diff --git a/htmlarea/lang/lv.js b/htmlarea/lang/lv.js
new file mode 100644 (file)
index 0000000..8cdfb5d
--- /dev/null
@@ -0,0 +1,55 @@
+// I18N constants
+
+// LANG: "lv", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+// Translated by: Janis Klavins, <janis.klavins@devia.lv>
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "lv",
+
+       tooltips: {
+               bold:           "Trekniem burtiem",
+               italic:         "Kursîvâ",
+               underline:      "Pasvîtrots",
+               strikethrough:  "Pârsvîtrots",
+               subscript:      "Novietot zem rindas",
+               superscript:    "Novietot virs rindas",
+               justifyleft:    "Izlîdzinât pa kreisi",
+               justifycenter:  "Izlîdzinât centrâ",
+               justifyright:   "Izlîdzinât pa labi",
+               justifyfull:    "Izlîdzinât pa visu lapu",
+               orderedlist:    "Numurçts saraksts",
+               unorderedlist:  "Saraksts",
+               outdent:        "Samazinât atkâpi",
+               indent:         "Palielinât atkâpi",
+               forecolor:      "Burtu krâsa",
+               hilitecolor:    "Fona krâsa",
+               horizontalrule: "Horizontâla atdalîtâjsvîtra",
+               createlink:     "Ievietot hipersaiti",
+               insertimage:    "Ievietot attçlu",
+               inserttable:    "Ievietot tabulu",
+               htmlmode:       "Skatît HTML kodu",
+               popupeditor:    "Palielinât Rediìçtâju",
+               about:          "Par ðo rediìçtâju",
+               showhelp:       "Rediìçtâja palîgs",
+               textindicator:  "Patreizçjais stils",
+               undo:           "Atcelt pçdçjo darbîbu",
+               redo:           "Atkârtot pçdçjo darbîbu",
+               cut:            "Izgriezt iezîmçto",
+               copy:           "Kopçt iezîmçto",
+               paste:          "Ievietot iezîmçto"
+       },
+
+       buttons: {
+               "ok":           "Labi",
+               "cancel":       "Atcelt"
+       },
+
+       msg: {
+               "Path":         "Ceïð",
+               "TEXT_MODE":    "Jûs patlaban darbojaties TEKSTA REÞÎMÂ. Lai pârietu atpakaï uz GRAFISKO REÞÎMU (WYSIWIG), lietojiet [<>] pogu."
+       }
+};
diff --git a/htmlarea/lang/nb.js b/htmlarea/lang/nb.js
new file mode 100644 (file)
index 0000000..4b95b8c
--- /dev/null
@@ -0,0 +1,36 @@
+// I18N constants
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "nb",
+
+       tooltips: {
+               bold:           "Fet",
+               italic:         "Kursiv",
+               underline:      "Understreket",
+               strikethrough:  "Gjennomstreket",
+               subscript:      "Senket",
+               superscript:    "Hevet",
+               justifyleft:    "Venstrejuster",
+               justifycenter:  "Midtjuster",
+               justifyright:   "Høyrejuster",
+               justifyfull:    "Blokkjuster",
+               orderedlist:    "Nummerert liste",
+               unorderedlist:  "Punktmerket liste",
+               outdent:        "Øke innrykk",
+               indent:         "Reduser innrykk",
+               forecolor:      "Skriftfarge",
+               backcolor:      "Bakgrunnsfarge",
+               horizontalrule: "Horisontal linje",
+               createlink:     "Sett inn lenke",
+               insertimage:    "Sett inn bilde",
+               inserttable:    "Sett inn tabell",
+               htmlmode:       "Vis HTML kode",
+               popupeditor:    "Forstørr redigeringsvindu",
+               about:          "Om..",
+               help:           "Hjelp",
+               textindicator:  "Gjeldende stil"
+       }
+};
diff --git a/htmlarea/lang/nl.js b/htmlarea/lang/nl.js
new file mode 100644 (file)
index 0000000..aa2229a
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants
+
+// LANG: "nl", ENCODING: UTF-8 | ISO-8859-1
+// Author: Michel Weegeerink (info@mmc-shop.nl), http://mmc-shop.nl
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "nl",
+
+       tooltips: {
+               bold:                                   "Vet",
+               italic:                                 "Cursief",
+               underline:                              "Onderstrepen",
+               strikethrough:                  "Doorhalen",
+               subscript:                              "Subscript",
+               superscript:                    "Superscript",
+               justifyleft:                    "Links uitlijnen",
+               justifycenter:                  "Centreren",
+               justifyright:                   "Rechts uitlijnen",
+               justifyfull:                    "Uitvullen",
+               orderedlist:            "Nummering",
+               unorderedlist:  "Opsommingstekens",
+               outdent:                                "Inspringing verkleinen",
+               indent:                                 "Inspringing vergroten",
+               forecolor:                              "Tekstkleur",
+               hilitecolor:                    "Achtergrondkleur",
+               inserthorizontalrule:   "Horizontale lijn",
+               createlink:                             "Hyperlink invoegen/aanpassen",
+               insertimage:                    "Afbeelding invoegen/aanpassen",
+               inserttable:                    "Tabel invoegen",
+               htmlmode:                               "HTML broncode",
+               popupeditor:                    "Vergroot Editor",
+               about:                                  "Over deze editor",
+               showhelp:                               "HTMLArea help",
+               textindicator:                  "Huidige stijl",
+               undo:                                   "Ongedaan maken",
+               redo:                                   "Herhalen",
+               cut:                                    "Knippen",
+               copy:                                   "Kopiëren",
+               paste:                                  "Plakken",
+               lefttoright:                    "Tekstrichting links naar rechts",
+               righttoleft:                    "Tekstrichting rechts naar links"
+       },
+
+       buttons: {
+               "ok":                                   "OK",
+               "cancel":                               "Annuleren"
+       },
+
+       msg: {
+               "Path":                                 "Pad",
+               "TEXT_MODE":                    "Je bent in TEKST-mode. Gebruik de [<>] knop om terug te keren naar WYSIWYG-mode.",
+      
+               "IE-sucks-full-screen" :
+               // translate here
+               "Fullscreen-mode veroorzaakt problemen met Internet Explorer door bugs in de webbrowser " +
+               "die we niet kunnen omzeilen. Hierdoor kunnen de volgende effecten optreden: verknoeide teksten, " +
+               "een verlies aan editor-functionaliteit en/of willekeurig vastlopen van de webbrowser. " +
+               "Als u Windows 95 of 98 gebruikt, is het zeer waarschijnlijk dat u een algemene beschermingsfout " +
+               "('General Protection Fault') krijgt en de computer opnieuw zal moeten opstarten.\n\n" +
+               "U bent gewaarschuwd. Druk OK als u toch nog de Fullscreen-editor wil gebruiken."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "Annuleren",
+               "Insert/Modify Link"                                : "Hyperlink invoegen/aanpassen",
+               "New window (_blank)"                               : "Nieuw venster (_blank)",
+               "None (use implicit)"                               : "Geen",
+               "OK"                                                : "OK",
+               "Other"                                             : "Ander",
+               "Same frame (_self)"                                : "Zelfde frame (_self)",
+               "Target:"                                           : "Doel:",
+               "Title (tooltip):"                                  : "Titel (tooltip):",
+               "Top frame (_top)"                                  : "Bovenste frame (_top)",
+               "URL:"                                              : "URL:",
+               "You must enter the URL where this link points to"  : "Geef de URL in waar de link naar verwijst"
+       }
+};
+
diff --git a/htmlarea/lang/no.js b/htmlarea/lang/no.js
new file mode 100644 (file)
index 0000000..814d64c
--- /dev/null
@@ -0,0 +1,79 @@
+// Norwegian version for htmlArea v3.0 - pre1
+// - translated by ses<ses@online.no>
+// Additional translations by Håvard Wigtil <havardw@extend.no>
+// term´s and licenses are equal to htmlarea!
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "no",
+
+       tooltips: {
+               bold:                 "Fet",
+               italic:               "Kursiv",
+               underline:            "Understreket",
+               strikethrough:        "Gjennomstreket",
+               subscript:            "Nedsenket",
+               superscript:          "Opphøyet",
+               justifyleft:          "Venstrejuster",
+               justifycenter:        "Midtjuster",
+               justifyright:         "Høyrejuster",
+               justifyfull:          "Blokkjuster",
+               orderedlist:    "Nummerert liste",
+               unorderedlist:  "Punktliste",
+               outdent:              "Reduser innrykk",
+               indent:               "Øke innrykk",
+               forecolor:            "Tekstfarge",
+               hilitecolor:          "Bakgrundsfarge",
+               inserthorizontalrule: "Vannrett linje",
+               createlink:           "Lag lenke",
+               insertimage:          "Sett inn bilde",
+               inserttable:          "Sett inn tabell",
+               htmlmode:             "Vis kildekode",
+               popupeditor:          "Vis i eget vindu",
+               about:                "Om denne editor",
+               showhelp:             "Hjelp",
+               textindicator:        "Nåværende stil",
+                undo:                 "Angrer siste redigering",
+               redo:                 "Gjør om siste angring",
+               cut:                  "Klipp ut område",
+               copy:                 "Kopier område",
+               paste:                "Lim inn",
+               lefttoright:          "Fra venstre mot høyre",
+               righttoleft:          "Fra høyre mot venstre"
+       },
+    
+       buttons: {
+               "ok":           "OK",
+               "cancel":       "Avbryt"
+       },
+
+       msg: {
+               "Path":         "Tekstvelger",
+               "TEXT_MODE":    "Du er i tekstmodus  Klikk på [<>] for å gå tilbake til WYSIWIG.",
+                "IE-sucks-full-screen" :
+               // translate here
+                "Visning i eget vindu har kjente problemer med Internet Explorer, " + 
+                "på grunn av problemer med denne nettleseren. Mulige problemer er et uryddig " + 
+                "skjermbilde, manglende editorfunksjoner og/eller at nettleseren crasher. Hvis du bruker Windows 95 eller Windows 98 " +
+                "er det også muligheter for at Windows will crashe.\n\n" +
+                "Trykk 'OK' hvis du vil bruke visning i eget vindu på tross av denne advarselen."
+       },
+
+       dialogs: {
+               "Cancel"                                            : "Avbryt",
+               "Insert/Modify Link"                                : "Rediger lenke",
+               "New window (_blank)"                               : "Eget vindu (_blank)",
+               "None (use implicit)"                               : "Ingen (bruk standardinnstilling)",
+               "OK"                                                : "OK",
+               "Other"                                             : "Annen",
+               "Same frame (_self)"                                : "Samme ramme (_self)",
+               "Target:"                                           : "Mål:",
+               "Title (tooltip):"                                  : "Tittel (tooltip):",
+               "Top frame (_top)"                                  : "Toppramme (_top)",
+               "URL:"                                              : "Adresse:",
+               "You must enter the URL where this link points to"  : "Du må skrive inn en adresse som denne lenken skal peke til"
+       }
+};
+
diff --git a/htmlarea/lang/pl.js b/htmlarea/lang/pl.js
new file mode 100644 (file)
index 0000000..80015c4
--- /dev/null
@@ -0,0 +1,36 @@
+// I18N constants\r
+\r
+HTMLArea.I18N = {\r
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "pl",
+
+       tooltips: {\r
+               bold:           "Pogrubienie",\r
+               italic:         "Pochylenie",\r
+               underline:      "Podkre\9clenie",\r
+               strikethrough:  "Przekre\9clenie",\r
+               subscript:      "Indeks dolny",\r
+               superscript:    "Indeks górny",\r
+               justifyleft:    "Wyrównaj do lewej",\r
+               justifycenter:  "Wy\9crodkuj",\r
+               justifyright:   "Wyrównaj do prawej",\r
+               justifyfull:    "Wyjustuj",\r
+               orderedlist:    "Numerowanie",\r
+               unorderedlist:  "Wypunktowanie",\r
+               outdent:        "Zmniejsz wciêcie",\r
+               indent:         "Zwiêksz wciêcie",\r
+               forecolor:      "Kolor czcionki",\r
+               backcolor:      "Kolor t³a",\r
+               horizontalrule: "Linia pozioma",\r
+               createlink:     "Wstaw adres sieci Web",\r
+               insertimage:    "Wstaw obraz",\r
+               inserttable:    "Wstaw tabelê",\r
+               htmlmode:       "Edycja WYSIWYG/w \9fródle strony",\r
+               popupeditor:    "Pe³ny ekran",\r
+               about:          "Informacje o tym edytorze",\r
+               help:           "Pomoc",\r
+               textindicator:  "Obecny styl"\r
+       }\r
+};\r
diff --git a/htmlarea/license.txt b/htmlarea/license.txt
new file mode 100644 (file)
index 0000000..32ac404
--- /dev/null
@@ -0,0 +1,30 @@
+htmlArea License (based on BSD license)
+Copyright (c) 2002-2004, interactivetools.com, inc.
+Copyright (c) 2003-2004 dynarch.com
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1) Redistributions of source code must retain the above copyright notice,
+   this list of conditions and the following disclaimer.
+
+2) Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3) Neither the name of interactivetools.com, inc. nor the names of its
+   contributors may be used to endorse or promote products derived from this
+   software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/htmlarea/plugins/CSS/css.js b/htmlarea/plugins/CSS/css.js
new file mode 100644 (file)
index 0000000..dabcf1d
--- /dev/null
@@ -0,0 +1,116 @@
+// Simple CSS (className) plugin for the editor
+// Sponsored by http://www.miro.com.au
+// Implementation by Mihai Bazon, http://dynarch.com/mishoo.
+//
+// (c) dynarch.com 2003
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+//
+// $Id: css.js,v 1.2 2005/01/11 15:00:54 garvinhicking Exp $
+
+function CSS(editor, params) {
+       this.editor = editor;
+       var cfg = editor.config;
+       var toolbar = cfg.toolbar;
+       var self = this;
+       var i18n = CSS.I18N;
+       var plugin_config = params[0];
+       var combos = plugin_config.combos;
+
+       var first = true;
+       for (var i = combos.length; --i >= 0;) {
+               var combo = combos[i];
+               var id = "CSS-class" + i;
+               var css_class = {
+                       id         : id,
+                       options    : combo.options,
+                       action     : function(editor) { self.onSelect(editor, this, combo.context, combo.updatecontextclass); },
+                       refresh    : function(editor) { self.updateValue(editor, this); },
+                       context    : combo.context
+               };
+               cfg.registerDropdown(css_class);
+
+               // prepend to the toolbar
+               toolbar[1].splice(0, 0, first ? "separator" : "space");
+               toolbar[1].splice(0, 0, id);
+               if (combo.label)
+                       toolbar[1].splice(0, 0, "T[" + combo.label + "]");
+               first = false;
+       }
+};
+
+CSS._pluginInfo = {
+       name          : "CSS",
+       version       : "1.0",
+       developer     : "Mihai Bazon",
+       developer_url : "http://dynarch.com/mishoo/",
+       c_owner       : "Mihai Bazon",
+       sponsor       : "Miro International",
+       sponsor_url   : "http://www.miro.com.au",
+       license       : "htmlArea"
+};
+
+CSS.prototype.onSelect = function(editor, obj, context, updatecontextclass) {
+       var tbobj = editor._toolbarObjects[obj.id];
+       var index = tbobj.element.selectedIndex;
+       var className = tbobj.element.value;
+
+       // retrieve parent element of the selection
+       var parent = editor.getParentElement();
+       var surround = true;
+
+       var is_span = (parent && parent.tagName.toLowerCase() == "span");
+       var update_parent = (context && updatecontextclass && parent && parent.tagName.toLowerCase() == context);
+
+       if (update_parent) {
+               parent.className = className;
+               editor.updateToolbar();
+               return;
+       }
+
+       if (is_span && index == 0 && !/\S/.test(parent.style.cssText)) {
+               while (parent.firstChild) {
+                       parent.parentNode.insertBefore(parent.firstChild, parent);
+               }
+               parent.parentNode.removeChild(parent);
+               editor.updateToolbar();
+               return;
+       }
+
+       if (is_span) {
+               // maybe we could simply change the class of the parent node?
+               if (parent.childNodes.length == 1) {
+                       parent.className = className;
+                       surround = false;
+                       // in this case we should handle the toolbar updation
+                       // ourselves.
+                       editor.updateToolbar();
+               }
+       }
+
+       // Other possibilities could be checked but require a lot of code.  We
+       // can't afford to do that now.
+       if (surround) {
+               // shit happens ;-) most of the time.  this method works, but
+               // it's dangerous when selection spans multiple block-level
+               // elements.
+               editor.surroundHTML("<span class='" + className + "'>", "</span>");
+       }
+};
+
+CSS.prototype.updateValue = function(editor, obj) {
+       var select = editor._toolbarObjects[obj.id].element;
+       var parent = editor.getParentElement();
+       if (typeof parent.className != "undefined" && /\S/.test(parent.className)) {
+               var options = select.options;
+               var value = parent.className;
+               for (var i = options.length; --i >= 0;) {
+                       var option = options[i];
+                       if (value == option.value) {
+                               select.selectedIndex = i;
+                               return;
+                       }
+               }
+       }
+       select.selectedIndex = 0;
+};
diff --git a/htmlarea/plugins/CSS/lang/en.js b/htmlarea/plugins/CSS/lang/en.js
new file mode 100644 (file)
index 0000000..7ffba00
--- /dev/null
@@ -0,0 +1,2 @@
+// none yet; this file is a stub.
+CSS.I18N = {};
diff --git a/htmlarea/plugins/ContextMenu/context-menu.js b/htmlarea/plugins/ContextMenu/context-menu.js
new file mode 100644 (file)
index 0000000..f42c753
--- /dev/null
@@ -0,0 +1,445 @@
+// Context Menu Plugin for HTMLArea-3.0
+// Sponsored by www.americanbible.org
+// Implementation by Mihai Bazon, http://dynarch.com/mishoo/
+//
+// (c) dynarch.com 2003.
+// Distributed under the same terms as HTMLArea itself.
+// This notice MUST stay intact for use (see license.txt).
+//
+// $Id: context-menu.js,v 1.2 2005/01/11 15:00:55 garvinhicking Exp $
+
+HTMLArea.loadStyle("menu.css", "ContextMenu");
+
+function ContextMenu(editor) {
+       this.editor = editor;
+};
+
+ContextMenu._pluginInfo = {
+       name          : "ContextMenu",
+       version       : "1.0",
+       developer     : "Mihai Bazon",
+       developer_url : "http://dynarch.com/mishoo/",
+       c_owner       : "dynarch.com",
+       sponsor       : "American Bible Society",
+       sponsor_url   : "http://www.americanbible.org",
+       license       : "htmlArea"
+};
+
+ContextMenu.prototype.onGenerate = function() {
+       var self = this;
+       var doc = this.editordoc = this.editor._iframe.contentWindow.document;
+       HTMLArea._addEvents(doc, ["contextmenu"],
+                           function (event) {
+                                   return self.popupMenu(HTMLArea.is_ie ? self.editor._iframe.contentWindow.event : event);
+                           });
+       this.currentMenu = null;
+};
+
+ContextMenu.prototype.getContextMenu = function(target) {
+       var self = this;
+       var editor = this.editor;
+       var config = editor.config;
+       var menu = [];
+       var tbo = this.editor.plugins.TableOperations;
+       if (tbo) tbo = tbo.instance;
+       var i18n = ContextMenu.I18N;
+
+       var selection = editor.hasSelectedText();
+       if (selection)
+               menu.push([ i18n["Cut"], function() { editor.execCommand("cut"); }, null, config.btnList["cut"][1] ],
+                         [ i18n["Copy"], function() { editor.execCommand("copy"); }, null, config.btnList["copy"][1] ]);
+       menu.push([ i18n["Paste"], function() { editor.execCommand("paste"); }, null, config.btnList["paste"][1] ]);
+
+       var currentTarget = target;
+       var elmenus = [];
+
+       var link = null;
+       var table = null;
+       var tr = null;
+       var td = null;
+       var img = null;
+
+       function tableOperation(opcode) {
+               tbo.buttonPress(editor, opcode);
+       };
+
+       function insertPara(after) {
+               var el = currentTarget;
+               var par = el.parentNode;
+               var p = editor._doc.createElement("p");
+               p.appendChild(editor._doc.createElement("br"));
+               par.insertBefore(p, after ? el.nextSibling : el);
+               var sel = editor._getSelection();
+               var range = editor._createRange(sel);
+               if (!HTMLArea.is_ie) {
+                       sel.removeAllRanges();
+                       range.selectNodeContents(p);
+                       range.collapse(true);
+                       sel.addRange(range);
+               } else {
+                       range.moveToElementText(p);
+                       range.collapse(true);
+                       range.select();
+               }
+       };
+
+       for (; target; target = target.parentNode) {
+               var tag = target.tagName;
+               if (!tag)
+                       continue;
+               tag = tag.toLowerCase();
+               switch (tag) {
+                   case "img":
+                       img = target;
+                       elmenus.push(null,
+                                    [ i18n["Image Properties"],
+                                      function() {
+                                              editor._insertImage(img);
+                                      },
+                                      i18n["Show the image properties dialog"],
+                                      config.btnList["insertimage"][1] ]
+                               );
+                       break;
+                   case "a":
+                       link = target;
+                       elmenus.push(null,
+                                    [ i18n["Modify Link"],
+                                      function() { editor.execCommand("createlink", true); },
+                                      i18n["Current URL is"] + ': ' + link.href,
+                                      config.btnList["createlink"][1] ],
+
+                                    [ i18n["Check Link"],
+                                      function() { window.open(link.href); },
+                                      i18n["Opens this link in a new window"] ],
+
+                                    [ i18n["Remove Link"],
+                                      function() {
+                                              if (confirm(i18n["Please confirm that you want to unlink this element."] + "\n" +
+                                                          i18n["Link points to:"] + " " + link.href)) {
+                                                      while (link.firstChild)
+                                                              link.parentNode.insertBefore(link.firstChild, link);
+                                                      link.parentNode.removeChild(link);
+                                              }
+                                      },
+                                      i18n["Unlink the current element"] ]
+                               );
+                       break;
+                   case "td":
+                       td = target;
+                       if (!tbo) break;
+                       elmenus.push(null,
+                                    [ i18n["Cell Properties"],
+                                      function() { tableOperation("TO-cell-prop"); },
+                                      i18n["Show the Table Cell Properties dialog"],
+                                      config.btnList["TO-cell-prop"][1] ]
+                               );
+                       break;
+                   case "tr":
+                       tr = target;
+                       if (!tbo) break;
+                       elmenus.push(null,
+                                    [ i18n["Row Properties"],
+                                      function() { tableOperation("TO-row-prop"); },
+                                      i18n["Show the Table Row Properties dialog"],
+                                      config.btnList["TO-row-prop"][1] ],
+
+                                    [ i18n["Insert Row Before"],
+                                      function() { tableOperation("TO-row-insert-above"); },
+                                      i18n["Insert a new row before the current one"],
+                                      config.btnList["TO-row-insert-above"][1] ],
+
+                                    [ i18n["Insert Row After"],
+                                      function() { tableOperation("TO-row-insert-under"); },
+                                      i18n["Insert a new row after the current one"],
+                                      config.btnList["TO-row-insert-under"][1] ],
+
+                                    [ i18n["Delete Row"],
+                                      function() { tableOperation("TO-row-delete"); },
+                                      i18n["Delete the current row"],
+                                      config.btnList["TO-row-delete"][1] ]
+                               );
+                       break;
+                   case "table":
+                       table = target;
+                       if (!tbo) break;
+                       elmenus.push(null,
+                                    [ i18n["Table Properties"],
+                                      function() { tableOperation("TO-table-prop"); },
+                                      i18n["Show the Table Properties dialog"],
+                                      config.btnList["TO-table-prop"][1] ],
+
+                                    [ i18n["Insert Column Before"],
+                                      function() { tableOperation("TO-col-insert-before"); },
+                                      i18n["Insert a new column before the current one"],
+                                      config.btnList["TO-col-insert-before"][1] ],
+
+                                    [ i18n["Insert Column After"],
+                                      function() { tableOperation("TO-col-insert-after"); },
+                                      i18n["Insert a new column after the current one"],
+                                      config.btnList["TO-col-insert-after"][1] ],
+
+                                    [ i18n["Delete Column"],
+                                      function() { tableOperation("TO-col-delete"); },
+                                      i18n["Delete the current column"],
+                                      config.btnList["TO-col-delete"][1] ]
+                               );
+                       break;
+                   case "body":
+                       elmenus.push(null,
+                                    [ i18n["Justify Left"],
+                                      function() { editor.execCommand("justifyleft"); }, null,
+                                      config.btnList["justifyleft"][1] ],
+                                    [ i18n["Justify Center"],
+                                      function() { editor.execCommand("justifycenter"); }, null,
+                                      config.btnList["justifycenter"][1] ],
+                                    [ i18n["Justify Right"],
+                                      function() { editor.execCommand("justifyright"); }, null,
+                                      config.btnList["justifyright"][1] ],
+                                    [ i18n["Justify Full"],
+                                      function() { editor.execCommand("justifyfull"); }, null,
+                                      config.btnList["justifyfull"][1] ]
+                               );
+                       break;
+               }
+       }
+
+       if (selection && !link)
+               menu.push(null, [ i18n["Make link"],
+                                 function() { editor.execCommand("createlink", true); },
+                                 i18n["Create a link"],
+                                 config.btnList["createlink"][1] ]);
+
+       for (var i = 0; i < elmenus.length; ++i)
+               menu.push(elmenus[i]);
+
+       if (!/html|body/i.test(currentTarget.tagName))
+               menu.push(null,
+                         [ i18n["Remove the"] + " &lt;" + currentTarget.tagName + "&gt; " + i18n["Element"],
+                           function() {
+                                   if (confirm(i18n["Please confirm that you want to remove this element:"] + " " +
+                                               currentTarget.tagName)) {
+                                           var el = currentTarget;
+                                           var p = el.parentNode;
+                                           p.removeChild(el);
+                                           if (HTMLArea.is_gecko) {
+                                                   if (p.tagName.toLowerCase() == "td" && !p.hasChildNodes())
+                                                           p.appendChild(editor._doc.createElement("br"));
+                                                   editor.forceRedraw();
+                                                   editor.focusEditor();
+                                                   editor.updateToolbar();
+                                                   if (table) {
+                                                           var save_collapse = table.style.borderCollapse;
+                                                           table.style.borderCollapse = "collapse";
+                                                           table.style.borderCollapse = "separate";
+                                                           table.style.borderCollapse = save_collapse;
+                                                   }
+                                           }
+                                   }
+                           },
+                           i18n["Remove this node from the document"] ],
+                         [ i18n["Insert paragraph before"],
+                           function() { insertPara(false); },
+                           i18n["Insert a paragraph before the current node"] ],
+                         [ i18n["Insert paragraph after"],
+                           function() { insertPara(true); },
+                           i18n["Insert a paragraph after the current node"] ]
+                         );
+       return menu;
+};
+
+ContextMenu.prototype.popupMenu = function(ev) {
+       var self = this;
+       var i18n = ContextMenu.I18N;
+       if (this.currentMenu)
+               this.currentMenu.parentNode.removeChild(this.currentMenu);
+       function getPos(el) {
+               var r = { x: el.offsetLeft, y: el.offsetTop };
+               if (el.offsetParent) {
+                       var tmp = getPos(el.offsetParent);
+                       r.x += tmp.x;
+                       r.y += tmp.y;
+               }
+               return r;
+       };
+       function documentClick(ev) {
+               ev || (ev = window.event);
+               if (!self.currentMenu) {
+                       alert(i18n["How did you get here? (Please report!)"]);
+                       return false;
+               }
+               var el = HTMLArea.is_ie ? ev.srcElement : ev.target;
+               for (; el != null && el != self.currentMenu; el = el.parentNode);
+               if (el == null)
+                       self.closeMenu();
+               //HTMLArea._stopEvent(ev);
+               //return false;
+       };
+       var keys = [];
+       function keyPress(ev) {
+               ev || (ev = window.event);
+               HTMLArea._stopEvent(ev);
+               if (ev.keyCode == 27) {
+                       self.closeMenu();
+                       return false;
+               }
+               var key = String.fromCharCode(HTMLArea.is_ie ? ev.keyCode : ev.charCode).toLowerCase();
+               for (var i = keys.length; --i >= 0;) {
+                       var k = keys[i];
+                       if (k[0].toLowerCase() == key)
+                               k[1].__msh.activate();
+               }
+       };
+       self.closeMenu = function() {
+               self.currentMenu.parentNode.removeChild(self.currentMenu);
+               self.currentMenu = null;
+               HTMLArea._removeEvent(document, "mousedown", documentClick);
+               HTMLArea._removeEvent(self.editordoc, "mousedown", documentClick);
+               if (keys.length > 0)
+                       HTMLArea._removeEvent(self.editordoc, "keypress", keyPress);
+               if (HTMLArea.is_ie)
+                       self.iePopup.hide();
+       };
+       var target = HTMLArea.is_ie ? ev.srcElement : ev.target;
+       var ifpos = getPos(self.editor._iframe);
+       var x = ev.clientX + ifpos.x;
+       var y = ev.clientY + ifpos.y;
+
+       var div;
+       var doc;
+       if (!HTMLArea.is_ie) {
+               doc = document;
+       } else {
+               // IE stinks
+               var popup = this.iePopup = window.createPopup();
+               doc = popup.document;
+               doc.open();
+               doc.write("<html><head><style type='text/css'>@import url(" + _editor_url + "plugins/ContextMenu/menu.css); html, body { padding: 0px; margin: 0px; overflow: hidden; border: 0px; }</style></head><body unselectable='yes'></body></html>");
+               doc.close();
+       }
+       div = doc.createElement("div");
+       if (HTMLArea.is_ie)
+               div.unselectable = "on";
+       div.oncontextmenu = function() { return false; };
+       div.className = "htmlarea-context-menu";
+       if (!HTMLArea.is_ie)
+               div.style.left = div.style.top = "0px";
+       doc.body.appendChild(div);
+
+       var table = doc.createElement("table");
+       div.appendChild(table);
+       table.cellSpacing = 0;
+       table.cellPadding = 0;
+       var parent = doc.createElement("tbody");
+       table.appendChild(parent);
+
+       var options = this.getContextMenu(target);
+       for (var i = 0; i < options.length; ++i) {
+               var option = options[i];
+               var item = doc.createElement("tr");
+               parent.appendChild(item);
+               if (HTMLArea.is_ie)
+                       item.unselectable = "on";
+               else item.onmousedown = function(ev) {
+                       HTMLArea._stopEvent(ev);
+                       return false;
+               };
+               if (!option) {
+                       item.className = "separator";
+                       var td = doc.createElement("td");
+                       td.className = "icon";
+                       var IE_IS_A_FUCKING_SHIT = '>';
+                       if (HTMLArea.is_ie) {
+                               td.unselectable = "on";
+                               IE_IS_A_FUCKING_SHIT = " unselectable='on' style='height=1px'>&nbsp;";
+                       }
+                       td.innerHTML = "<div" + IE_IS_A_FUCKING_SHIT + "</div>";
+                       var td1 = td.cloneNode(true);
+                       td1.className = "label";
+                       item.appendChild(td);
+                       item.appendChild(td1);
+               } else {
+                       var label = option[0];
+                       item.className = "item";
+                       item.__msh = {
+                               item: item,
+                               label: label,
+                               action: option[1],
+                               tooltip: option[2] || null,
+                               icon: option[3] || null,
+                               activate: function() {
+                                       self.closeMenu();
+                                       self.editor.focusEditor();
+                                       this.action();
+                               }
+                       };
+                       label = label.replace(/_([a-zA-Z0-9])/, "<u>$1</u>");
+                       if (label != option[0])
+                               keys.push([ RegExp.$1, item ]);
+                       label = label.replace(/__/, "_");
+                       var td1 = doc.createElement("td");
+                       if (HTMLArea.is_ie)
+                               td1.unselectable = "on";
+                       item.appendChild(td1);
+                       td1.className = "icon";
+                       if (item.__msh.icon)
+                               td1.innerHTML = "<img align='middle' src='" + item.__msh.icon + "' />";
+                       var td2 = doc.createElement("td");
+                       if (HTMLArea.is_ie)
+                               td2.unselectable = "on";
+                       item.appendChild(td2);
+                       td2.className = "label";
+                       td2.innerHTML = label;
+                       item.onmouseover = function() {
+                               this.className += " hover";
+                               self.editor._statusBarTree.innerHTML = this.__msh.tooltip || '&nbsp;';
+                       };
+                       item.onmouseout = function() { this.className = "item"; };
+                       item.oncontextmenu = function(ev) {
+                               this.__msh.activate();
+                               if (!HTMLArea.is_ie)
+                                       HTMLArea._stopEvent(ev);
+                               return false;
+                       };
+                       item.onmouseup = function(ev) {
+                               var timeStamp = (new Date()).getTime();
+                               if (timeStamp - self.timeStamp > 500)
+                                       this.__msh.activate();
+                               if (!HTMLArea.is_ie)
+                                       HTMLArea._stopEvent(ev);
+                               return false;
+                       };
+                       //if (typeof option[2] == "string")
+                       //item.title = option[2];
+               }
+       }
+
+       if (!HTMLArea.is_ie) {
+               var dx = x + div.offsetWidth - window.innerWidth + 4;
+               var dy = y + div.offsetHeight - window.innerHeight + 4;
+               if (dx > 0) x -= dx;
+               if (dy > 0) y -= dy;
+               div.style.left = x + "px";
+               div.style.top = y + "px";
+       } else {
+               // determine the size (did I mention that IE stinks?)
+               var foobar = document.createElement("div");
+               foobar.className = "htmlarea-context-menu";
+               foobar.innerHTML = div.innerHTML;
+               document.body.appendChild(foobar);
+               var w = foobar.offsetWidth;
+               var h = foobar.offsetHeight;
+               document.body.removeChild(foobar);
+               this.iePopup.show(ev.screenX, ev.screenY, w, h);
+       }
+
+       this.currentMenu = div;
+       this.timeStamp = (new Date()).getTime();
+
+       HTMLArea._addEvent(document, "mousedown", documentClick);
+       HTMLArea._addEvent(this.editordoc, "mousedown", documentClick);
+       if (keys.length > 0)
+               HTMLArea._addEvent(this.editordoc, "keypress", keyPress);
+
+       HTMLArea._stopEvent(ev);
+       return false;
+};
diff --git a/htmlarea/plugins/ContextMenu/lang/de.js b/htmlarea/plugins/ContextMenu/lang/de.js
new file mode 100644 (file)
index 0000000..e9f1fed
--- /dev/null
@@ -0,0 +1,59 @@
+// I18N constants
+
+// LANG: "de", ENCODING: UTF-8 | ISO-8859-1
+
+// translated: <]{MJ}[>  i@student.ethz.ch
+
+
+ContextMenu.I18N = {
+       // Items that appear in menu.  Please note that an underscore (_)
+       // character in the translation (right column) will cause the following
+       // letter to become underlined and be shortcut for that menu option.
+
+       "Cut"                                                   : "Ausschneiden",
+       "Copy"                                                  : "Kopieren",
+       "Paste"                                                 : "Einfügen",
+       "Image Properties"                                      : "_Bild Einstellungen...",
+       "Modify Link"                                           : "_Link ändern...",
+       "Check Link"                                            : "Link testen...",
+       "Remove Link"                                           : "Link entfernen...",
+       "Cell Properties"                                       : "Z_ellen Einstellungen...",
+       "Row Properties"                                        : "Ze_ilen Einstellungen...",
+       "Insert Row Before"                                     : "Zeile einfügen v_or Position",
+       "Insert Row After"                                      : "Zeile einfügen n_ach Position",
+       "Delete Row"                                            : "Zeile löschen",
+       "Table Properties"                                      : "_Tabellen Einstellungen...",
+       "Insert Column Before"                                  : "Spalte einfügen vo_r Position",
+       "Insert Column After"                                   : "Spalte einfügen na_ch Position",
+       "Delete Column"                                         : "Spalte löschen",
+       "Justify Left"                                          : "Links ausrichten",
+       "Justify Center"                                        : "Zentriert",
+       "Justify Right"                                         : "Rechts ausrichten",
+       "Justify Full"                                          : "Blocksatz",
+       "Make link"                                             : "Lin_k erstellen...",
+       "Remove the"                                            : "",
+       "Element"                                               : "Element entfernen...",
+
+       // Other labels (tooltips and alert/confirm box messages)
+
+       "Please confirm that you want to remove this element:"  : "Wollen sie dieses Element wirklich entfernen ?",
+       "Remove this node from the document"                    : "Dieses Element aus dem Dokument entfernen",
+       "How did you get here? (Please report!)"                : "How did you get here? (Please report!)",
+       "Show the image properties dialog"                      : "Fenster für die Bild-Einstellungen anzeigen",
+       "Modify URL"                                            : "URL ändern",
+       "Current URL is"                                        : "Aktuelle URL ist",
+       "Opens this link in a new window"                       : "Diesen Link in neuem Fenster öffnen",
+       "Please confirm that you want to unlink this element."  : "Wollen sie diesen Link wirklich entfernen ?",
+       "Link points to:"                                       : "Link zeigt auf:",
+       "Unlink the current element"                            : "Link auf Element entfernen",
+       "Show the Table Cell Properties dialog"                 : "Zellen-Einstellungen anzeigen",
+       "Show the Table Row Properties dialog"                  : "Zeilen-Einstellungen anzeigen",
+       "Insert a new row before the current one"               : "Zeile einfügen vor der aktuellen Position",
+       "Insert a new row after the current one"                : "Zeile einfügen nach der aktuellen Position",
+       "Delete the current row"                                : "Zeile löschen",
+       "Show the Table Properties dialog"                      : "Show the Table Properties dialog",
+       "Insert a new column before the current one"            : "Spalte einfügen vor der aktuellen Position",
+       "Insert a new column after the current one"             : "Spalte einfügen nach der aktuellen Position",
+       "Delete the current column"                             : "Spalte löschen",
+       "Create a link"                                         : "Link erstellen"
+};
diff --git a/htmlarea/plugins/ContextMenu/lang/el.js b/htmlarea/plugins/ContextMenu/lang/el.js
new file mode 100644 (file)
index 0000000..68bbaf2
--- /dev/null
@@ -0,0 +1,57 @@
+// I18N constants
+
+// LANG: "el", ENCODING: UTF-8 | ISO-8859-7
+// Author: Dimitris Glezos, dimitris@glezos.com
+
+ContextMenu.I18N = {
+       // Items that appear in menu.  Please note that an underscore (_)
+       // character in the translation (right column) will cause the following
+       // letter to become underlined and be shortcut for that menu option.
+
+       "Cut"                                                   : "Αποκοπή",
+       "Copy"                                                  : "Αντιγραφή",
+       "Paste"                                                 : "Επικόλληση",
+       "Image Properties"                                      : "Ιδιότητες Εικόνας...",
+       "Modify Link"                                           : "Τροποποίηση συνδέσμου...",
+       "Check Link"                                            : "Έλεγχος συνδέσμων...",
+       "Remove Link"                                           : "Διαγραφή συνδέσμου...",
+       "Cell Properties"                                       : "Ιδιότητες κελιού...",
+       "Row Properties"                                        : "Ιδιότητες γραμμής...",
+       "Insert Row Before"                                     : "Εισαγωγή γραμμής πριν",
+       "Insert Row After"                                      : "Εισαγωγή γραμμής μετά",
+       "Delete Row"                                            : "Διαγραφή γραμμής",
+       "Table Properties"                                      : "Ιδιότητες πίνακα...",
+       "Insert Column Before"                                  : "Εισαγωγή στήλης πριν",
+       "Insert Column After"                                   : "Εισαγωγή στήλης μετά",
+       "Delete Column"                                         : "Διαγραφή στήλης",
+       "Justify Left"                                          : "Στοίχηση Αριστερά",
+       "Justify Center"                                        : "Στοίχηση Κέντρο",
+       "Justify Right"                                         : "Στοίχηση Δεξιά",
+       "Justify Full"                                          : "Πλήρης Στοίχηση",
+       "Make link"                                             : "Δημιουργία συνδέσμου...",
+       "Remove the"                                            : "Αφαίρεση",
+       "Element"                                               : "στοιχείου...",
+
+       // Other labels (tooltips and alert/confirm box messages)
+
+       "Please confirm that you want to remove this element:"  : "Είστε βέβαιος πως θέλετε να αφαιρέσετε το στοιχείο ",
+       "Remove this node from the document"                    : "Αφαίρεση αυτού του κόμβου από το έγγραφο",
+       "How did you get here? (Please report!)"                : "Πώς ήρθατε μέχρι εδώ; (Παρακαλούμε αναφέρετε το!)",
+       "Show the image properties dialog"                      : "Εμφάνιση διαλόγου με τις Ιδιότητες εικόνας",
+       "Modify URL"                                            : "Τροποποίηση URL",
+       "Current URL is"                                        : "Το τρέχων URL είναι",
+       "Opens this link in a new window"                       : "Ανοίγει αυτό τον σύνδεσμο σε ένα νέο παράθυρο",
+       "Please confirm that you want to unlink this element."  : "Είστε βέβαιος πως θέλετε να αφαιρέσετε τον σύνδεσμο από αυτό το στοιχείο:",
+       "Link points to:"                                       : "Ο σύνδεμος οδηγεί εδώ:",
+       "Unlink the current element"                            : "Αφαίρεση συνδέσμου από το παρών στοιχείο",
+       "Show the Table Cell Properties dialog"                 : "Εμφάνιση διαλόγου με τις Ιδιότητες κελιού Πίνακα",
+       "Show the Table Row Properties dialog"                  : "Εμφάνιση διαλόγου με τις Ιδιότητες γραμμής Πίνακα",
+       "Insert a new row before the current one"               : "Εισαγωγή μιας νέας γραμμής πριν την επιλεγμένη",
+       "Insert a new row after the current one"                : "Εισαγωγή μιας νέας γραμμής μετά την επιλεγμένη",
+       "Delete the current row"                                : "Διαγραφή επιλεγμένης γραμμής",
+       "Show the Table Properties dialog"                      : "Εμφάνιση διαλόγου με τις Ιδιότητες Πίνακα",
+       "Insert a new column before the current one"            : "Εισαγωγή νέας στήλης πριν την επιλεγμένη",
+       "Insert a new column after the current one"             : "Εισαγωγή νέας στήλης μετά την επιλεγμένη",
+       "Delete the current column"                             : "Διαγραφή επιλεγμένης στήλης",
+       "Create a link"                                         : "Δημιουργία συνδέσμου"
+};
diff --git a/htmlarea/plugins/ContextMenu/lang/en.js b/htmlarea/plugins/ContextMenu/lang/en.js
new file mode 100644 (file)
index 0000000..98b3572
--- /dev/null
@@ -0,0 +1,70 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+ContextMenu.I18N = {
+       // Items that appear in menu.  Please note that an underscore (_)
+       // character in the translation (right column) will cause the following
+       // letter to become underlined and be shortcut for that menu option.
+
+       "Cut"                                                   : "Cut",
+       "Copy"                                                  : "Copy",
+       "Paste"                                                 : "Paste",
+       "Image Properties"                                      : "_Image Properties...",
+       "Modify Link"                                           : "_Modify Link...",
+       "Check Link"                                            : "Chec_k Link...",
+       "Remove Link"                                           : "_Remove Link...",
+       "Cell Properties"                                       : "C_ell Properties...",
+       "Row Properties"                                        : "Ro_w Properties...",
+       "Insert Row Before"                                     : "I_nsert Row Before",
+       "Insert Row After"                                      : "In_sert Row After",
+       "Delete Row"                                            : "_Delete Row",
+       "Table Properties"                                      : "_Table Properties...",
+       "Insert Column Before"                                  : "Insert _Column Before",
+       "Insert Column After"                                   : "Insert C_olumn After",
+       "Delete Column"                                         : "De_lete Column",
+       "Justify Left"                                          : "Justify Left",
+       "Justify Center"                                        : "Justify Center",
+       "Justify Right"                                         : "Justify Right",
+       "Justify Full"                                          : "Justify Full",
+       "Make link"                                             : "Make lin_k...",
+       "Remove the"                                            : "Remove the",
+       "Element"                                               : "Element...",
+       "Insert paragraph before"                               : "Insert paragraph before",
+       "Insert paragraph after"                                : "Insert paragraph after",
+
+       // Other labels (tooltips and alert/confirm box messages)
+
+       "Please confirm that you want to remove this element:"  : "Please confirm that you want to remove this element:",
+       "Remove this node from the document"                    : "Remove this node from the document",
+       "How did you get here? (Please report!)"                : "How did you get here? (Please report!)",
+       "Show the image properties dialog"                      : "Show the image properties dialog",
+       "Modify URL"                                            : "Modify URL",
+       "Current URL is"                                        : "Current URL is",
+       "Opens this link in a new window"                       : "Opens this link in a new window",
+       "Please confirm that you want to unlink this element."  : "Please confirm that you want to unlink this element.",
+       "Link points to:"                                       : "Link points to:",
+       "Unlink the current element"                            : "Unlink the current element",
+       "Show the Table Cell Properties dialog"                 : "Show the Table Cell Properties dialog",
+       "Show the Table Row Properties dialog"                  : "Show the Table Row Properties dialog",
+       "Insert a new row before the current one"               : "Insert a new row before the current one",
+       "Insert a new row after the current one"                : "Insert a new row after the current one",
+       "Delete the current row"                                : "Delete the current row",
+       "Show the Table Properties dialog"                      : "Show the Table Properties dialog",
+       "Insert a new column before the current one"            : "Insert a new column before the current one",
+       "Insert a new column after the current one"             : "Insert a new column after the current one",
+       "Delete the current column"                             : "Delete the current column",
+       "Create a link"                                         : "Create a link",
+       "Insert a paragraph before the current node"            : "Insert a paragraph before the current node",
+       "Insert a paragraph after the current node"             : "Insert a paragraph after the current node"
+};
diff --git a/htmlarea/plugins/ContextMenu/lang/nl.js b/htmlarea/plugins/ContextMenu/lang/nl.js
new file mode 100644 (file)
index 0000000..a91e1f5
--- /dev/null
@@ -0,0 +1,66 @@
+// I18N constants
+
+// LANG: "nl", ENCODING: UTF-8 | ISO-8859-1
+// Author: Michel Weegeerink (info@mmc-shop.nl), http://mmc-shop.nl
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+ContextMenu.I18N = {
+       // Items that appear in menu.  Please note that an underscore (_)
+       // character in the translation (right column) will cause the following
+       // letter to become underlined and be shortcut for that menu option.
+
+       "Cut"                                                   : "Knippen",
+       "Copy"                                                  : "Kopiëren",
+       "Paste"                                                 : "Plakken",
+       "Image Properties"                                      : "Eigenschappen afbeelding...",
+       "Modify Link"                                           : "Hyperlin_k aanpassen...",
+       "Check Link"                                            : "Controleer hyperlin_k...",
+       "Remove Link"                                           : "Ve_rwijder hyperlink...",
+       "Cell Properties"                                       : "C_eleigenschappen...",
+       "Row Properties"                                        : "Rijeigenscha_ppen...",
+       "Insert Row Before"                                     : "Rij invoegen boven",
+       "Insert Row After"                                      : "Rij invoegen onder",
+       "Delete Row"                                            : "Rij _verwijderen",
+       "Table Properties"                                      : "_Tabeleigenschappen...",
+       "Insert Column Before"                                  : "Kolom invoegen voor",
+       "Insert Column After"                                   : "Kolom invoegen na",
+       "Delete Column"                                         : "Kolom verwijderen",
+       "Justify Left"                                          : "Links uitlijnen",
+       "Justify Center"                                        : "Centreren",
+       "Justify Right"                                         : "Rechts uitlijnen",
+       "Justify Full"                                          : "Uitvullen",
+       "Make link"                                             : "Maak hyperlin_k...",
+       "Remove the"                                            : "Verwijder het",
+       "Element"                                               : "element...",
+
+       // Other labels (tooltips and alert/confirm box messages)
+
+       "Please confirm that you want to remove this element:"  : "Is het werkelijk de bedoeling dit element te verwijderen:",
+       "Remove this node from the document"                    : "Verwijder dit punt van het document",
+       "How did you get here? (Please report!)"                : "Hoe kwam je hier? (A.U.B. doorgeven!)",
+       "Show the image properties dialog"                      : "Laat het afbeeldingseigenschappen dialog zien",
+       "Modify URL"                                            : "Aanpassen URL",
+       "Current URL is"                                        : "Huidig URL is",
+       "Opens this link in a new window"                       : "Opend deze hyperlink in een nieuw venster",
+       "Please confirm that you want to unlink this element."  : "Is het werkelijk de bedoeling dit element te unlinken.",
+       "Link points to:"                                       : "Hyperlink verwijst naar:",
+       "Unlink the current element"                            : "Unlink het huidige element",
+       "Show the Table Cell Properties dialog"                 : "Laat de tabel celeigenschappen dialog zien",
+       "Show the Table Row Properties dialog"                  : "Laat de tabel rijeigenschappen dialog zien",
+       "Insert a new row before the current one"               : "Voeg een nieuwe rij in boven de huidige",
+       "Insert a new row after the current one"                : "Voeg een nieuwe rij in onder de huidige",
+       "Delete the current row"                                : "Verwijder de huidige rij",
+       "Show the Table Properties dialog"                      : "Laat de tabel eigenschappen dialog zien",
+       "Insert a new column before the current one"            : "Voeg een nieuwe kolom in voor de huidige",
+       "Insert a new column after the current one"             : "Voeg een nieuwe kolom in na de huidige",
+       "Delete the current column"                             : "Verwijder de huidige kolom",
+       "Create a link"                                         : "Maak een hyperlink"
+};
diff --git a/htmlarea/plugins/ContextMenu/menu.css b/htmlarea/plugins/ContextMenu/menu.css
new file mode 100644 (file)
index 0000000..35b17a8
--- /dev/null
@@ -0,0 +1,65 @@
+/* styles for the ContextMenu /HTMLArea */
+/* The ContextMenu plugin is (c) dynarch.com 2003. */
+/* Distributed under the same terms as HTMLArea itself */
+
+div.htmlarea-context-menu {
+  position: absolute;
+  border: 1px solid #aca899;
+  padding: 2px;
+  background-color: #fff;
+  color: #000;
+  cursor: default;
+  z-index: 1000;
+}
+
+div.htmlarea-context-menu table {
+  font: 11px tahoma,verdana,sans-serif;
+  border-collapse: collapse;
+}
+
+div.htmlarea-context-menu tr.item td.icon img {
+  width: 18px;
+  height: 18px;
+}
+
+div.htmlarea-context-menu tr.item td.icon {
+  padding: 0px 3px;
+  height: 18px;
+  background-color: #cdf;
+}
+
+div.htmlarea-context-menu tr.item td.label {
+  padding: 1px 10px 1px 3px;
+}
+
+div.htmlarea-context-menu tr.separator td {
+  padding: 2px 0px;
+}
+
+div.htmlarea-context-menu tr.separator td div {
+  border-top: 1px solid #aca899;
+  overflow: hidden;
+  position: relative;
+}
+
+div.htmlarea-context-menu tr.separator td.icon {
+  background-color: #cdf;
+}
+
+div.htmlarea-context-menu tr.separator td.icon div {
+/*  margin-left: 3px; */
+  border-color: #fff;
+}
+
+div.htmlarea-context-menu tr.separator td.label div {
+  margin-right: 3px;
+}
+
+div.htmlarea-context-menu tr.item.hover {
+  background-color: #316ac5;
+  color: #fff;
+}
+
+div.htmlarea-context-menu tr.item.hover td.icon {
+  background-color: #619af5;
+}
diff --git a/htmlarea/plugins/FullPage/full-page.js b/htmlarea/plugins/FullPage/full-page.js
new file mode 100644 (file)
index 0000000..3376e2d
--- /dev/null
@@ -0,0 +1,177 @@
+// FullPage Plugin for HTMLArea-3.0
+// Implementation by Mihai Bazon.  Sponsored by http://thycotic.com
+//
+// htmlArea v3.0 - Copyright (c) 2002 interactivetools.com, inc.
+// This notice MUST stay intact for use (see license.txt).
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon for InteractiveTools.
+//   http://dynarch.com/mishoo
+//
+// $Id: full-page.js,v 1.2 2005/01/11 15:00:57 garvinhicking Exp $
+
+function FullPage(editor) {
+       this.editor = editor;
+
+       var cfg = editor.config;
+       cfg.fullPage = true;
+       var tt = FullPage.I18N;
+       var self = this;
+
+       cfg.registerButton("FP-docprop", tt["Document properties"], editor.imgURL("docprop.gif", "FullPage"), false,
+                          function(editor, id) {
+                                  self.buttonPress(editor, id);
+                          });
+
+       // add a new line in the toolbar
+       cfg.toolbar[0].splice(0, 0, "separator");
+       cfg.toolbar[0].splice(0, 0, "FP-docprop");
+};
+
+FullPage._pluginInfo = {
+       name          : "FullPage",
+       version       : "1.0",
+       developer     : "Mihai Bazon",
+       developer_url : "http://dynarch.com/mishoo/",
+       c_owner       : "Mihai Bazon",
+       sponsor       : "Thycotic Software Ltd.",
+       sponsor_url   : "http://thycotic.com",
+       license       : "htmlArea"
+};
+
+FullPage.prototype.buttonPress = function(editor, id) {
+       var self = this;
+       switch (id) {
+           case "FP-docprop":
+               var doc = editor._doc;
+               var links = doc.getElementsByTagName("link");
+               var style1 = '';
+               var style2 = '';
+               var charset = '';
+               for (var i = links.length; --i >= 0;) {
+                       var link = links[i];
+                       if (/stylesheet/i.test(link.rel)) {
+                               if (/alternate/i.test(link.rel))
+                                       style2 = link.href;
+                               else
+                                       style1 = link.href;
+                       }
+               }
+               var metas = doc.getElementsByTagName("meta");
+               for (var i = metas.length; --i >= 0;) {
+                       var meta = metas[i];
+                       if (/content-type/i.test(meta.httpEquiv)) {
+                               r = /^text\/html; *charset=(.*)$/i.exec(meta.content);
+                               charset = r[1];
+                       }
+               }
+               var title = doc.getElementsByTagName("title")[0];
+               title = title ? title.innerHTML : '';
+               var init = {
+                       f_doctype      : editor.doctype,
+                       f_title        : title,
+                       f_body_bgcolor : HTMLArea._colorToRgb(doc.body.style.backgroundColor),
+                       f_body_fgcolor : HTMLArea._colorToRgb(doc.body.style.color),
+                       f_base_style   : style1,
+                       f_alt_style    : style2,
+                       f_charset      : charset,
+                       editor         : editor
+               };
+               editor._popupDialog("plugin://FullPage/docprop", function(params) {
+                       self.setDocProp(params);
+               }, init);
+               break;
+       }
+};
+
+FullPage.prototype.setDocProp = function(params) {
+       var txt = "";
+       var doc = this.editor._doc;
+       var head = doc.getElementsByTagName("head")[0];
+       var links = doc.getElementsByTagName("link");
+       var metas = doc.getElementsByTagName("meta");
+       var style1 = null;
+       var style2 = null;
+       var charset = null;
+       var charset_meta = null;
+       for (var i = links.length; --i >= 0;) {
+               var link = links[i];
+               if (/stylesheet/i.test(link.rel)) {
+                       if (/alternate/i.test(link.rel))
+                               style2 = link;
+                       else
+                               style1 = link;
+               }
+       }
+       for (var i = metas.length; --i >= 0;) {
+               var meta = metas[i];
+               if (/content-type/i.test(meta.httpEquiv)) {
+                       r = /^text\/html; *charset=(.*)$/i.exec(meta.content);
+                       charset = r[1];
+                       charset_meta = meta;
+               }
+       }
+       function createLink(alt) {
+               var link = doc.createElement("link");
+               link.rel = alt ? "alternate stylesheet" : "stylesheet";
+               head.appendChild(link);
+               return link;
+       };
+       function createMeta(name, content) {
+               var meta = doc.createElement("meta");
+               meta.httpEquiv = name;
+               meta.content = content;
+               head.appendChild(meta);
+               return meta;
+       };
+
+       if (!style1 && params.f_base_style)
+               style1 = createLink(false);
+       if (params.f_base_style)
+               style1.href = params.f_base_style;
+       else if (style1)
+               head.removeChild(style1);
+
+       if (!style2 && params.f_alt_style)
+               style2 = createLink(true);
+       if (params.f_alt_style)
+               style2.href = params.f_alt_style;
+       else if (style2)
+               head.removeChild(style2);
+
+       if (charset_meta) {
+               head.removeChild(charset_meta);
+               charset_meta = null;
+       }
+       if (!charset_meta && params.f_charset)
+               charset_meta = createMeta("Content-Type", "text/html; charset="+params.f_charset);
+
+       for (var i in params) {
+               var val = params[i];
+               switch (i) {
+                   case "f_title":
+                       var title = doc.getElementsByTagName("title")[0];
+                       if (!title) {
+                               title = doc.createElement("title");
+                               head.appendChild(title);
+                       } else while (node = title.lastChild)
+                               title.removeChild(node);
+                       if (!HTMLArea.is_ie)
+                               title.appendChild(doc.createTextNode(val));
+                       else
+                               doc.title = val;
+                       break;
+                   case "f_doctype":
+                       this.editor.setDoctype(val);
+                       break;
+                   case "f_body_bgcolor":
+                       doc.body.style.backgroundColor = val;
+                       break;
+                   case "f_body_fgcolor":
+                       doc.body.style.color = val;
+                       break;
+               }
+       }
+};
diff --git a/htmlarea/plugins/FullPage/img/docprop.gif b/htmlarea/plugins/FullPage/img/docprop.gif
new file mode 100644 (file)
index 0000000..2ceb082
Binary files /dev/null and b/htmlarea/plugins/FullPage/img/docprop.gif differ
diff --git a/htmlarea/plugins/FullPage/lang/en.js b/htmlarea/plugins/FullPage/lang/en.js
new file mode 100644 (file)
index 0000000..50b6823
--- /dev/null
@@ -0,0 +1,25 @@
+// I18N for the FullPage plugin
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+FullPage.I18N = {
+       "Alternate style-sheet:":               "Alternate style-sheet:",
+       "Background color:":                    "Background color:",
+       "Cancel":                               "Cancel",
+       "DOCTYPE:":                             "DOCTYPE:",
+       "Document properties":                  "Document properties",
+       "Document title:":                      "Document title:",
+       "OK":                                   "OK",
+       "Primary style-sheet:":                 "Primary style-sheet:",
+       "Text color:":                          "Text color:"
+};
diff --git a/htmlarea/plugins/FullPage/lang/ro.js b/htmlarea/plugins/FullPage/lang/ro.js
new file mode 100644 (file)
index 0000000..f43c8e1
--- /dev/null
@@ -0,0 +1,25 @@
+// I18N for the FullPage plugin
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+FullPage.I18N = {
+       "Alternate style-sheet:":               "Template CSS alternativ:",
+       "Background color:":                    "Culoare de fundal:",
+       "Cancel":                               "Renunţă",
+       "DOCTYPE:":                             "DOCTYPE:",
+       "Document properties":                  "Proprietăţile documentului",
+       "Document title:":                      "Titlul documentului:",
+       "OK":                                   "Acceptă",
+       "Primary style-sheet:":                 "Template CSS principal:",
+       "Text color:":                          "Culoare text:"
+};
diff --git a/htmlarea/plugins/FullPage/popups/docprop.html b/htmlarea/plugins/FullPage/popups/docprop.html
new file mode 100644 (file)
index 0000000..eab9a9c
--- /dev/null
@@ -0,0 +1,143 @@
+<html>
+
+<head>
+  <title>Document properties</title>
+
+<script type="text/javascript" src="../../../popups/popup.js"></script>
+
+<script type="text/javascript">
+
+FullPage = window.opener.FullPage; // load the FullPage plugin and lang file ;-)
+window.resizeTo(400, 100);
+
+  var accepted = {
+      f_doctype       : true,
+      f_title         : true,
+      f_body_bgcolor  : true,
+      f_body_fgcolor  : true,
+      f_base_style    : true,
+      f_alt_style     : true,
+      f_charset       : true
+  };
+
+var editor = null;
+function Init() {
+  __dlg_translate(FullPage.I18N);
+  __dlg_init();
+  var params = window.dialogArguments;
+  for (var i in params) {
+      if (i in accepted) {
+        var el = document.getElementById(i);
+        el.value = params[i];
+      }
+  }
+  editor = params.editor;
+  document.getElementById("f_title").focus();
+  document.getElementById("f_title").select();
+};
+
+function onOK() {
+  var required = {
+  };
+  for (var i in required) {
+    var el = document.getElementById(i);
+    if (!el.value) {
+      alert(required[i]);
+      el.focus();
+      return false;
+    }
+  }
+
+  var param = {};
+  for (var i in accepted) {
+    var el = document.getElementById(i);
+    param[i] = el.value;
+  }
+  __dlg_close(param);
+  return false;
+};
+
+function onCancel() {
+  __dlg_close(null);
+  return false;
+};
+
+</script>
+
+<style type="text/css">
+html, body {
+  background: ButtonFace;
+  color: ButtonText;
+  font: 11px Tahoma,Verdana,sans-serif;
+  margin: 0px;
+  padding: 0px;
+}
+body { padding: 5px; }
+table {
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }
+button { width: 70px; }
+table .label { text-align: right; width: 12em; }
+
+.title { background: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px;
+border-bottom: 1px solid black; letter-spacing: 2px;
+}
+
+#buttons {
+      margin-top: 1em; border-top: 1px solid #999;
+      padding: 2px; text-align: right;
+}
+</style>
+
+  </head>
+
+  <body onload="Init()">
+
+    <div class="title"><span>Document properties</span></div>
+
+    <table style="width: 100%">
+      <tr>
+        <td class="label"><span>Document title:</span></td>
+        <td><input type="text" id="f_title" style="width: 100%" /></td>
+      </tr>
+      <tr>
+        <td class="label"><span>DOCTYPE:</span></td>
+        <td><input type="text" id="f_doctype" style="width: 100%" /></td>
+      </tr>
+      <tr>
+        <td class="label"><span>Primary style-sheet:</span></td>
+        <td><input type="text" id="f_base_style" style="width: 100%" /></td>
+      </tr>
+      <tr>
+        <td class="label"><span>Alternate style-sheet:</span></td>
+        <td><input type="text" id="f_alt_style" style="width: 100%" /></td>
+      </tr>
+      <tr>
+        <td class="label"><span>Background color:</span></td>
+        <td><input type="text" id="f_body_bgcolor" size="7" /></td>
+      </tr>
+      <tr>
+        <td class="label"><span>Text color:</span></td>
+        <td><input type="text" id="f_body_fgcolor" size="7" /></td>
+      </tr>
+      <tr>
+        <td class="label"><span>Character set:</span></td>
+        <td><select id="f_charset">
+          <option value=""></option>
+          <option value="utf-8">UTF-8 (recommended)</option>
+          <option value="windows-1251">cyrillic (WINDOWS-1251)</option>
+          <option value="koi8-r">cyrillic (KOI8-R)</option>
+          <option value="iso-8859-5">cyrillic (ISO-8859-5)</option>
+          <option value="iso-8859-1">western (ISO-8859-1)</option>
+        </select></td>
+      </tr>
+    </table>
+
+    <div id="buttons">
+      <button type="button" name="ok" onclick="return onOK();"><span>OK</span></button>
+      <button type="button" name="cancel" onclick="return onCancel();"><span>Cancel</span></button>
+    </div>
+
+  </body>
+</html>
diff --git a/htmlarea/plugins/FullPage/test.html b/htmlarea/plugins/FullPage/test.html
new file mode 100644 (file)
index 0000000..ad4be93
--- /dev/null
@@ -0,0 +1,89 @@
+<html>
+  <head>
+    <title>Test of FullPage plugin</title>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <script type="text/javascript">
+      _editor_url = "../../";
+    </script>
+
+    <!-- load the main HTMLArea files -->
+    <script type="text/javascript" src="../../htmlarea.js"></script>
+    <script type="text/javascript" src="../../lang/en.js"></script>
+    <script type="text/javascript" src="../../dialog.js"></script>
+
+    <!-- <script type="text/javascript" src="popupdiv.js"></script> -->
+    <script type="text/javascript" src="../../popupwin.js"></script>
+
+    <script type="text/javascript">
+      HTMLArea.loadPlugin("TableOperations");
+      HTMLArea.loadPlugin("SpellChecker");
+      HTMLArea.loadPlugin("FullPage");
+
+      function initDocument() {
+        var editor = new HTMLArea("editor");
+        editor.registerPlugin(TableOperations);
+        editor.registerPlugin(SpellChecker);
+        editor.registerPlugin(FullPage);
+        editor.generate();
+      }
+    </script>
+
+    <style type="text/css">
+      @import url(../../htmlarea.css);
+    </style>
+
+  </head>
+
+  <body onload="initDocument()">
+    <h1>Test of FullPage plugin</h1>
+
+    <textarea id="editor" style="height: 30em; width: 100%;">
+      &lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"&gt;
+      &lt;html&gt;
+        &lt;head&gt;
+          &lt;title&gt;FullPage plugin for HTMLArea&lt;/title&gt;
+          &lt;link rel="alternate stylesheet" href="http://dynarch.com/mishoo/css/dark.css" /&gt;
+          &lt;link rel="stylesheet" href="http://dynarch.com/mishoo/css/cool-light.css" /&gt;
+        &lt;/head&gt;
+        &lt;body style="background-color: #ddddee; color: #000077;"&gt;
+          &lt;table style="width:60%; height: 90%; margin: 2% auto 1% auto;" align="center" border="0" cellpadding="0" cellspacing="0"&gt;
+            &lt;tr&gt;
+              &lt;td style="background-color: #ddeedd; border: 2px solid #002; height: 1.5em; padding: 2px; font: bold 24px Verdana;"&gt;
+                FullPage plugin
+              &lt;/td&gt;
+            &lt;/tr&gt;
+            &lt;tr&gt;
+              &lt;td style="background-color: #fff; border: 1px solid #aab; padding: 1em 3em; font: 12px Verdana;"&gt;
+                &lt;p&gt;
+                  This plugin enables one to edit a full HTML file in &lt;a
+                    href="http://dynarch.com/htmlarea/"&gt;HTMLArea&lt;/a&gt;.  This is not
+                  normally possible with just the core editor since it only
+                  retrieves the HTML inside the &lt;code&gt;body&lt;/code&gt; tag.
+                &lt;/p&gt;
+                &lt;p&gt;
+                  It provides the ability to change the &lt;code&gt;DOCTYPE&lt;/code&gt; of
+                  the document, &lt;code&gt;body&lt;/code&gt; &lt;code&gt;bgcolor&lt;/code&gt; and
+                  &lt;code&gt;fgcolor&lt;/code&gt; attributes as well as to add additional
+                  &lt;code&gt;link&lt;/code&gt;-ed stylesheets.  Cool, eh?
+                &lt;/p&gt;
+                &lt;p&gt;
+                  The development of this plugin was initiated and sponsored by
+                  &lt;a href="http://thycotic.com"&gt;Thycotic Software Ltd.&lt;/a&gt;.
+                  That's also cool, isn't it? ;-)
+                &lt;/p&gt;
+              &lt;/td&gt;
+            &lt;/tr&gt;
+          &lt;/table&gt;
+        &lt;/body&gt;
+      &lt;/html&gt;
+    </textarea>
+
+    <hr />
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Wed Oct  1 19:55:37 EEST 2003 -->
+<!-- hhmts start -->
+Last modified on Sat Oct 25 01:06:59 2003
+<!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
diff --git a/htmlarea/plugins/TableOperations/img/cell-delete.gif b/htmlarea/plugins/TableOperations/img/cell-delete.gif
new file mode 100644 (file)
index 0000000..df9594f
Binary files /dev/null and b/htmlarea/plugins/TableOperations/img/cell-delete.gif differ
diff --git a/htmlarea/plugins/TableOperations/img/cell-insert-after.gif b/htmlarea/plugins/TableOperations/img/cell-insert-after.gif
new file mode 100644 (file)
index 0000000..6ff2154
Binary files /dev/null and b/htmlarea/plugins/TableOperations/img/cell-insert-after.gif differ
diff --git a/htmlarea/plugins/TableOperations/img/cell-insert-before.gif b/htmlarea/plugins/TableOperations/img/cell-insert-before.gif
new file mode 100644 (file)
index 0000000..632b315
Binary files /dev/null and b/htmlarea/plugins/TableOperations/img/cell-insert-before.gif differ
diff --git a/htmlarea/plugins/TableOperations/img/cell-merge.gif b/htmlarea/plugins/TableOperations/img/cell-merge.gif
new file mode 100644 (file)
index 0000000..35e4af1
Binary files /dev/null and b/htmlarea/plugins/TableOperations/img/cell-merge.gif differ
diff --git a/htmlarea/plugins/TableOperations/img/cell-prop.gif b/htmlarea/plugins/TableOperations/img/cell-prop.gif
new file mode 100644 (file)
index 0000000..2f71bae
Binary files /dev/null and b/htmlarea/plugins/TableOperations/img/cell-prop.gif differ
diff --git a/htmlarea/plugins/TableOperations/img/cell-split.gif b/htmlarea/plugins/TableOperations/img/cell-split.gif
new file mode 100644 (file)
index 0000000..8bd011e
Binary files /dev/null and b/htmlarea/plugins/TableOperations/img/cell-split.gif differ
diff --git a/htmlarea/plugins/TableOperations/img/col-delete.gif b/htmlarea/plugins/TableOperations/img/col-delete.gif
new file mode 100644 (file)
index 0000000..565afdc
Binary files /dev/null and b/htmlarea/plugins/TableOperations/img/col-delete.gif differ
diff --git a/htmlarea/plugins/TableOperations/img/col-insert-after.gif b/htmlarea/plugins/TableOperations/img/col-insert-after.gif
new file mode 100644 (file)
index 0000000..648e54f
Binary files /dev/null and b/htmlarea/plugins/TableOperations/img/col-insert-after.gif differ
diff --git a/htmlarea/plugins/TableOperations/img/col-insert-before.gif b/htmlarea/plugins/TableOperations/img/col-insert-before.gif
new file mode 100644 (file)
index 0000000..9be8a6e
Binary files /dev/null and b/htmlarea/plugins/TableOperations/img/col-insert-before.gif differ
diff --git a/htmlarea/plugins/TableOperations/img/col-split.gif b/htmlarea/plugins/TableOperations/img/col-split.gif
new file mode 100644 (file)
index 0000000..83f21d1
Binary files /dev/null and b/htmlarea/plugins/TableOperations/img/col-split.gif differ
diff --git a/htmlarea/plugins/TableOperations/img/row-delete.gif b/htmlarea/plugins/TableOperations/img/row-delete.gif
new file mode 100644 (file)
index 0000000..e649d9f
Binary files /dev/null and b/htmlarea/plugins/TableOperations/img/row-delete.gif differ
diff --git a/htmlarea/plugins/TableOperations/img/row-insert-above.gif b/htmlarea/plugins/TableOperations/img/row-insert-above.gif
new file mode 100644 (file)
index 0000000..e39c948
Binary files /dev/null and b/htmlarea/plugins/TableOperations/img/row-insert-above.gif differ
diff --git a/htmlarea/plugins/TableOperations/img/row-insert-under.gif b/htmlarea/plugins/TableOperations/img/row-insert-under.gif
new file mode 100644 (file)
index 0000000..2005358
Binary files /dev/null and b/htmlarea/plugins/TableOperations/img/row-insert-under.gif differ
diff --git a/htmlarea/plugins/TableOperations/img/row-prop.gif b/htmlarea/plugins/TableOperations/img/row-prop.gif
new file mode 100644 (file)
index 0000000..7639725
Binary files /dev/null and b/htmlarea/plugins/TableOperations/img/row-prop.gif differ
diff --git a/htmlarea/plugins/TableOperations/img/row-split.gif b/htmlarea/plugins/TableOperations/img/row-split.gif
new file mode 100644 (file)
index 0000000..0df4697
Binary files /dev/null and b/htmlarea/plugins/TableOperations/img/row-split.gif differ
diff --git a/htmlarea/plugins/TableOperations/img/table-prop.gif b/htmlarea/plugins/TableOperations/img/table-prop.gif
new file mode 100644 (file)
index 0000000..e15a4a4
Binary files /dev/null and b/htmlarea/plugins/TableOperations/img/table-prop.gif differ
diff --git a/htmlarea/plugins/TableOperations/lang/cz.js b/htmlarea/plugins/TableOperations/lang/cz.js
new file mode 100644 (file)
index 0000000..d407dae
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants
+
+// LANG: "cz", ENCODING: UTF-8 | ISO-8859-2
+// Author: Jiri Löw, <jirilow@jirilow.com>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+TableOperations.I18N = {
+       "Align":                                          "Zarovnání",
+       "All four sides":                                 "Všechny čtyři strany",
+       "Background":                                     "Pozadí",
+       "Baseline":                                       "Základní linka",
+       "Border":                                         "Obrys",
+       "Borders":                                        "Obrysy",
+       "Bottom":                                         "Dolů",
+       "CSS Style":                                      "Kaskádové styly (CSS)",
+       "Caption":                                        "Titulek",
+       "Cell Properties":                                "Vlastnosti buňky",
+       "Center":                                         "Na střed",
+       "Char":                                           "Znak",
+       "Collapsed borders":                              "Stlačené okraje",
+       "Color":                                          "Barva",
+       "Description":                                    "Popis",
+       "FG Color":                                       "Barva popředí",
+       "Float":                                          "Obtékání",
+       "Frames":                                         "Rámečky",
+       "Height":                                         "Výška",
+       "How many columns would you like to merge?":      "Kolik sloupců si přejete spojit?",
+       "How many rows would you like to merge?":         "Kolik řádků si přejete spojit?",
+       "Image URL":                                      "Adresa obrázku",
+       "Justify":                                        "Do stran",
+       "Layout":                                         "Rozložení",
+       "Left":                                           "Vlevo",
+       "Margin":                                         "Okraj",
+       "Middle":                                         "Na střed",
+       "No rules":                                       "Žádné čáry",
+       "No sides":                                       "Žádné strany",
+       "None":                                           "Žádné",
+       "Padding":                                        "Odsazování",
+       "Please click into some cell":                    "Prosím klikněte do některé buňky",
+       "Right":                                          "Vpravo",
+       "Row Properties":                                 "Vlastnosti řádku",
+       "Rules will appear between all rows and columns": "Čáry mezi všemi řádky i sloupci",
+       "Rules will appear between columns only":         "Čáry pouze mezi sloupci",
+       "Rules will appear between rows only":            "Čáry pouze mezi řádky",
+       "Rules":                                          "Čáry",
+       "Spacing and padding":                            "Mezery a odsazování",
+       "Spacing":                                        "Mezery",
+       "Summary":                                        "Shrnutí",
+       "TO-cell-delete":                                 "Smazat buňku",
+       "TO-cell-insert-after":                           "Vložit buňku za",
+       "TO-cell-insert-before":                          "Vložit buňku před",
+       "TO-cell-merge":                                  "Spojit buňky",
+       "TO-cell-prop":                                   "Vlastnosti buňky",
+       "TO-cell-split":                                  "Rozdělit buňku",
+       "TO-col-delete":                                  "Smazat sloupec",
+       "TO-col-insert-after":                            "Vložit sloupec za",
+       "TO-col-insert-before":                           "Vložit sloupec před",
+       "TO-col-split":                                   "Rozdělit sloupec",
+       "TO-row-delete":                                  "Smazat řádek",
+       "TO-row-insert-above":                            "Smazat řádek nad",
+       "TO-row-insert-under":                            "Smazat řádek pod",
+       "TO-row-prop":                                    "Vlastnosti řádku",
+       "TO-row-split":                                   "Rozdělit řádek",
+       "TO-table-prop":                                  "Vlastnosti tabulky",
+       "Table Properties":                               "Vlastnosti tabulky",
+       "Text align":                                     "Zarovnání textu",
+       "The bottom side only":                           "Pouze spodní strana",
+       "The left-hand side only":                        "Pouze levá strana",
+       "The right and left sides only":                  "Pouze levá a pravá strana",
+       "The right-hand side only":                       "Pouze pravá strana",
+       "The top and bottom sides only":                  "Pouze horní a dolní strana",
+       "The top side only":                              "Pouze horní strana",
+       "Top":                                            "Nahoru",     
+       "Unset color":                                    "Zrušit barvu",
+       "Vertical align":                                 "Svislé zarovnání",
+       "Width":                                          "Šířka",
+       "not-del-last-cell":                              "HTMLArea zbaběle odmítá smazat poslední buňku v řádku.",
+       "not-del-last-col":                               "HTMLArea zbaběle odmítá smazat poslední sloupec v tabulce.",
+       "not-del-last-row":                               "HTMLArea zbaběle odmítá smazat poslední řádek v tabulce.",
+       "percent":                                        "procent",
+       "pixels":                                         "pixelů"
+};
diff --git a/htmlarea/plugins/TableOperations/lang/da.js b/htmlarea/plugins/TableOperations/lang/da.js
new file mode 100644 (file)
index 0000000..08a6f1b
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants
+
+// LANG: "da", ENCODING: UTF-8 | ISO-8859-1
+// Author: Steen Sønderup, <steen@soenderup.com>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+TableOperations.I18N = {
+       "Align":                                                                                        "Placer",
+       "All four sides":                                                                       "Alle fire sider",
+       "Background":                                                                           "Baggrund",
+       "Baseline":                                                                                     "Bundlinie",
+       "Border":                                                                                       "Kant",
+       "Borders":                                                                                      "Kanter",
+       "Bottom":                                                                                       "Bund",
+       "CSS Style":                                                                            "Stil [CSS]",
+       "Caption":                                                                                      "Titel",
+       "Cell Properties":                                                                      "Celle egenskaber",
+       "Center":                                                                                       "Centrer",
+       "Char":                                                                                         "Plads",
+       "Collapsed borders":                                                            "Sammensmelt rammer",
+       "Color":                                                                                        "Farve",
+       "Description":                                                                          "Beskrivelse",
+       "FG Color":                                                                                     "Font farve",
+       "Float":                                                                                        "Justering",
+       "Frames":                                                                                       "Udvendig",
+       "Height":                                                                                       "Højde",
+       "How many columns would you like to merge?":            "Hvor mange kollonner vil du samle?",
+       "How many rows would you like to merge?":                       "Hvor mange rækker vil du samle?",
+       "Image URL":                                                                            "Billede URL",
+       "Justify":                                                                                      "Lige margener",
+       "Layout":                                                                                       "Opsætning",
+       "Left":                                                                                         "Venstre",
+       "Margin":                                                                                       "Margen",
+       "Middle":                                                                                       "Centrer",
+       "No rules":                                                                                     "Ingen rammer",
+       "No sides":                                                                                     "Ingen sider",
+       "None":                                                                                         "Ingen",
+       "Padding":                                                                                      "Margen",
+       "Please click into some cell":                                          "Klik på en celle",
+       "Right":                                                                                        "Højre",
+       "Row Properties":                                                                       "Række egenskaber",
+       "Rules will appear between all rows and columns":       "Rammer mellem rækker og kolonner",
+       "Rules will appear between columns only":                       "Kun rammer mellem kolonner",
+       "Rules will appear between rows only":                          "Kun rammer mellem rækker",
+       "Rules":                                                                                        "Invendig",
+       "Spacing and padding":                                                          "Afstand og margen",
+       "Spacing":                                                                                      "Afstand",
+       "Summary":                                                                                      "Beskrivelse",
+       "TO-cell-delete":                                                                       "Slet celle",
+       "TO-cell-insert-after":                                                         "Indsæt celle efter",
+       "TO-cell-insert-before":                                                        "Indsæt celle før",
+       "TO-cell-merge":                                                                        "Sammensæt celler",
+       "TO-cell-prop":                                                                         "Celle egenskaber",
+       "TO-cell-split":                                                                        "Opdel celle",
+       "TO-col-delete":                                                                        "Slet kollonne",
+       "TO-col-insert-after":                                                          "Indsæt kolonne efter",
+       "TO-col-insert-before":                                                         "Indsæt kolonne før",
+       "TO-col-split":                                                                         "Opdel kolonne",
+       "TO-row-delete":                                                                        "Slet række",
+       "TO-row-insert-above":                                                          "Indsæt række før",
+       "TO-row-insert-under":                                                          "Indsæt række efter",
+       "TO-row-prop":                                                                          "Række egenskaber",
+       "TO-row-split":                                                                         "Opdel række",
+       "TO-table-prop":                                                                        "Tabel egenskaber",
+       "Table Properties":                                                                     "Tabel egenskaber",
+       "Text align":                                                                           "Tekst",
+       "The bottom side only":                                                         "Kun i bunden",
+       "The left-hand side only":                                                      "Kun i højre side",
+       "The right and left sides only":                                        "Kun i siderne",
+       "The right-hand side only":                                                     "Kun i venstre side",
+       "The top and bottom sides only":                                        "Kun i top og bund",
+       "The top side only":                                                            "Kun i toppen",
+       "Top":                                                                                          "Top",  
+       "Unset color":                                                                          "Farve ikke valgt",
+       "Vertical align":                                                                       "Vertikal placering",
+       "Width":                                                                                        "Bredde",
+       "not-del-last-cell":                                                            "Du kan ikke slette den sidste celle i en række.",
+       "not-del-last-col":                                                                     "Du kan ikke slette den sidste kolonne i en tabel.",
+       "not-del-last-row":                                                                     "Du kan ikke slette den sidste række i en tabel.",
+       "percent":                                                                                      "procent",
+       "pixels":                                                                                       "pixel"
+};
diff --git a/htmlarea/plugins/TableOperations/lang/de.js b/htmlarea/plugins/TableOperations/lang/de.js
new file mode 100644 (file)
index 0000000..1128cff
--- /dev/null
@@ -0,0 +1,81 @@
+// I18N constants
+
+// LANG: "de", ENCODING: UTF-8 | ISO-8859-1
+// Author: broxx, <broxx@broxx.com>
+
+TableOperations.I18N = {
+       "Align":                                          "Ausrichten",
+       "All four sides":                                 "Alle 4 Seiten",
+       "Background":                                     "Hintergrund",
+       "Baseline":                                       "Basislinie",
+       "Border":                                         "Rand",
+       "Borders":                                        "Raender",
+       "Bottom":                                         "Unten",
+       "CSS Style":                                      "Style [CSS]",
+       "Caption":                                        "Ueberschrift",
+       "Cell Properties":                                "Zellen",
+       "Center":                                         "Zentrieren",
+       "Char":                                           "Zeichen",
+       "Collapsed borders":                              "Collapsed borders",
+       "Color":                                          "Farbe",
+       "Description":                                    "Beschreibung",
+       "FG Color":                                       "FG Farbe",
+       "Float":                                          "Ausrichtung",
+       "Frames":                                         "Rahmen",
+       "Height":                                         "Hoehe",
+       "How many columns would you like to merge?":      "Wieviele Spalten willst du verbinden?",
+       "How many rows would you like to merge?":         "Wieviele Zeilen willst du verbinden?",
+       "Image URL":                                      "Bild URL",
+       "Justify":                                        "Justieren",
+       "Layout":                                         "Layout",
+       "Left":                                           "Links",
+       "Margin":                                         "Rand",
+       "Middle":                                         "Mitte",
+       "No rules":                                       "Keine Balken",
+       "No sides":                                       "Keine Seiten",
+       "None":                                           "Keine",
+       "Padding":                                        "Auffuellung",
+       "Please click into some cell":                    "Waehle eine Zelle",
+       "Right":                                          "Rechts",
+       "Row Properties":                                 "Reihen",
+       "Rules will appear between all rows and columns": "Balken zwischen Reihen und Spalten",
+       "Rules will appear between columns only":         "Balken zwischen Spalten",
+       "Rules will appear between rows only":            "Balken zwischen Reihen",
+       "Rules":                                          "Balken",
+       "Spacing and padding":                            "Abstaende",
+       "Spacing":                                        "Abstand",
+       "Summary":                                        "Zusammenfassung",
+       "TO-cell-delete":                                 "Zelle loeschen",
+       "TO-cell-insert-after":                           "Zelle einfuegen nach",
+       "TO-cell-insert-before":                          "Zelle einfuegen bevor",
+       "TO-cell-merge":                                  "Zellen zusammenfuegen",
+       "TO-cell-prop":                                   "Zelleinstellungen",
+       "TO-cell-split":                                  "Zellen aufteilen",
+       "TO-col-delete":                                  "Spalte loeschen",
+       "TO-col-insert-after":                            "Spalte einfuegen nach",
+       "TO-col-insert-before":                           "Spalte einfuegen bevor",
+       "TO-col-split":                                   "Spalte aufteilen",
+       "TO-row-delete":                                  "Reihe loeschen",
+       "TO-row-insert-above":                            "Reihe einfuegen vor",
+       "TO-row-insert-under":                            "Reihe einfuegen nach",
+       "TO-row-prop":                                    "Reiheneinstellungen",
+       "TO-row-split":                                   "Reihen aufteilen",
+       "TO-table-prop":                                  "Tabelle",
+       "Table Properties":                               "Tabelle",
+       "Text align":                                     "Ausrichtung",
+       "The bottom side only":                           "Nur untere Seite",
+       "The left-hand side only":                        "Nur linke Seite",
+       "The right and left sides only":                  "Nur linke und rechte Seite",
+       "The right-hand side only":                       "Nur rechte Seite",
+       "The top and bottom sides only":                  "Nur obere und untere Seite",
+       "The top side only":                              "Nur obere Seite",
+       "Top":                                            "Oben",       
+       "Unset color":                                    "Farbe",
+       "Vertical align":                                 "Ausrichtung",
+       "Width":                                          "Breite",
+       "not-del-last-cell":                              "Letzte Zelle in dieser Reihe!",
+       "not-del-last-col":                               "Letzte Spalte in dieser Tabelle!",
+       "not-del-last-row":                               "Letzte Reihe in dieser Tabelle",
+       "percent":                                        "%",
+       "pixels":                                         "pixels"
+};
diff --git a/htmlarea/plugins/TableOperations/lang/el.js b/htmlarea/plugins/TableOperations/lang/el.js
new file mode 100644 (file)
index 0000000..06bae5c
--- /dev/null
@@ -0,0 +1,81 @@
+// I18N constants
+
+// LANG: "el", ENCODING: UTF-8 | ISO-8859-7
+// Author: Dimitris Glezos, dimitris@glezos.com
+
+TableOperations.I18N = {
+       "Align":                                          "Στοίχηση",
+       "All four sides":                                 "Και οι 4 πλευρές",
+       "Background":                                     "Φόντο",
+       "Baseline":                                       "Baseline",
+       "Border":                                         "Περίγραμμα",
+       "Borders":                                        "Περιγράμματα",
+       "Bottom":                                         "Κάτω μέρος",
+       "CSS Style":                                      "Στυλ [CSS]",
+       "Caption":                                        "Λεζάντα",
+       "Cell Properties":                                "Ιδιότητες Κελιού",
+       "Center":                                         "Κέντρο",
+       "Char":                                           "Χαρακτήρας",
+       "Collapsed borders":                              "Συμπτυγμένα περιγράμματα",
+       "Color":                                          "Χρώμα",
+       "Description":                                    "Περιγραφή",
+       "FG Color":                                       "Χρώμα αντικειμένων",
+       "Float":                                          "Float",
+       "Frames":                                         "Frames",
+       "Height":                                         "Ύψος",
+       "How many columns would you like to merge?":      "Πόσες στήλες θέλετε να ενώσετε;",
+       "How many rows would you like to merge?":         "Πόσες γραμμές θέλετε να ενώσετε;",
+       "Image URL":                                      "URL εικόνας",
+       "Justify":                                        "Πλήρης στοίχηση",
+       "Layout":                                         "Διάταξη",
+       "Left":                                           "Αριστερά",
+       "Margin":                                         "Περιθώριο",
+       "Middle":                                         "Κέντρο",
+       "No rules":                                       "Χωρίς Γραμμές",
+       "No sides":                                       "No sides",
+       "None":                                           "Τίποτα",
+       "Padding":                                        "Εσοχή",
+       "Please click into some cell":                    "Κάντε κλικ μέσα σε κάποιο κελί",
+       "Right":                                          "Δεξιά",
+       "Row Properties":                                 "Ιδιότητες Γραμμής",
+       "Rules will appear between all rows and columns": "Γραμμές θα εμφανίζονται μεταξύ όλων των γραμμών και στηλών",
+       "Rules will appear between columns only":         "Γραμμές θα εμφανίζονται μόνο μεταξύ στηλών",
+       "Rules will appear between rows only":            "Γραμμές θα εμφανίζονται μόνο μεταξύ γραμμών",
+       "Rules":                                          "Γραμμές",
+       "Spacing and padding":                            "Αποστάσεις και εσοχές",
+       "Spacing":                                        "Αποστάσεις",
+       "Summary":                                        "Σύνοψη",
+       "TO-cell-delete":                                 "Διαγραφή κελιού",
+       "TO-cell-insert-after":                           "Εισαγωγή κελιού μετά",
+       "TO-cell-insert-before":                          "Εισαγωγή κελιού πριν",
+       "TO-cell-merge":                                  "Συγχώνευση κελιών",
+       "TO-cell-prop":                                   "Ιδιότητες κελιού",
+       "TO-cell-split":                                  "Διαίρεση κελιού",
+       "TO-col-delete":                                  "Διαγραφή στήλης",
+       "TO-col-insert-after":                            "Εισαγωγή στήλης μετά",
+       "TO-col-insert-before":                           "Εισαγωγή στήλης πριν",
+       "TO-col-split":                                   "Διαίρεση στήλης",
+       "TO-row-delete":                                  "Διαγραφή γραμμής",
+       "TO-row-insert-above":                            "Εισαγωγή γραμμής μετά",
+       "TO-row-insert-under":                            "Εισαγωγή γραμμής πριν",
+       "TO-row-prop":                                    "Ιδιότητες γραμμής",
+       "TO-row-split":                                   "Διαίρεση γραμμής",
+       "TO-table-prop":                                  "Ιδιότητες πίνακα",
+       "Table Properties":                               "Ιδιότητες πίνακα",
+       "Text align":                                     "Στοίχηση κειμένου",
+       "The bottom side only":                           "Η κάτω πλευρά μόνο",
+       "The left-hand side only":                        "Η αριστερή πλευρά μόνο",
+       "The right and left sides only":                  "Οι δεξιές και αριστερές πλευρές μόνο",
+       "The right-hand side only":                       "Η δεξιά πλευρά μόνο",
+       "The top and bottom sides only":                  "Οι πάνω και κάτω πλευρές μόνο",
+       "The top side only":                              "Η πάνω πλευρά μόνο",
+       "Top":                                            "Πάνω",   
+       "Unset color":                                    "Αναίρεση χρώματος",
+       "Vertical align":                                 "Κατακόρυφη στοίχηση",
+       "Width":                                          "Πλάτος",
+       "not-del-last-cell":                              "Δεν μπορεί να διαγραφεί το τελευταίο κελί σε μια γραμμή.",
+       "not-del-last-col":                               "Δεν μπορεί να διαγραφεί η τελευταία στήλη σε ένα πίνακα.",
+       "not-del-last-row":                               "Δεν μπορεί να διαγραφεί η τελευταία γραμμή σε ένα πίνακα.",
+       "percent":                                        "τοις εκατόν",
+       "pixels":                                         "pixels"
+};
diff --git a/htmlarea/plugins/TableOperations/lang/en.js b/htmlarea/plugins/TableOperations/lang/en.js
new file mode 100644 (file)
index 0000000..7168e09
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+TableOperations.I18N = {
+       "Align":                                          "Align",
+       "All four sides":                                 "All four sides",
+       "Background":                                     "Background",
+       "Baseline":                                       "Baseline",
+       "Border":                                         "Border",
+       "Borders":                                        "Borders",
+       "Bottom":                                         "Bottom",
+       "CSS Style":                                      "Style [CSS]",
+       "Caption":                                        "Caption",
+       "Cell Properties":                                "Cell Properties",
+       "Center":                                         "Center",
+       "Char":                                           "Char",
+       "Collapsed borders":                              "Collapsed borders",
+       "Color":                                          "Color",
+       "Description":                                    "Description",
+       "FG Color":                                       "FG Color",
+       "Float":                                          "Float",
+       "Frames":                                         "Frames",
+       "Height":                                         "Height",
+       "How many columns would you like to merge?":      "How many columns would you like to merge?",
+       "How many rows would you like to merge?":         "How many rows would you like to merge?",
+       "Image URL":                                      "Image URL",
+       "Justify":                                        "Justify",
+       "Layout":                                         "Layout",
+       "Left":                                           "Left",
+       "Margin":                                         "Margin",
+       "Middle":                                         "Middle",
+       "No rules":                                       "No rules",
+       "No sides":                                       "No sides",
+       "None":                                           "None",
+       "Padding":                                        "Padding",
+       "Please click into some cell":                    "Please click into some cell",
+       "Right":                                          "Right",
+       "Row Properties":                                 "Row Properties",
+       "Rules will appear between all rows and columns": "Rules will appear between all rows and columns",
+       "Rules will appear between columns only":         "Rules will appear between columns only",
+       "Rules will appear between rows only":            "Rules will appear between rows only",
+       "Rules":                                          "Rules",
+       "Spacing and padding":                            "Spacing and padding",
+       "Spacing":                                        "Spacing",
+       "Summary":                                        "Summary",
+       "TO-cell-delete":                                 "Delete cell",
+       "TO-cell-insert-after":                           "Insert cell after",
+       "TO-cell-insert-before":                          "Insert cell before",
+       "TO-cell-merge":                                  "Merge cells",
+       "TO-cell-prop":                                   "Cell properties",
+       "TO-cell-split":                                  "Split cell",
+       "TO-col-delete":                                  "Delete column",
+       "TO-col-insert-after":                            "Insert column after",
+       "TO-col-insert-before":                           "Insert column before",
+       "TO-col-split":                                   "Split column",
+       "TO-row-delete":                                  "Delete row",
+       "TO-row-insert-above":                            "Insert row before",
+       "TO-row-insert-under":                            "Insert row after",
+       "TO-row-prop":                                    "Row properties",
+       "TO-row-split":                                   "Split row",
+       "TO-table-prop":                                  "Table properties",
+       "Table Properties":                               "Table Properties",
+       "Text align":                                     "Text align",
+       "The bottom side only":                           "The bottom side only",
+       "The left-hand side only":                        "The left-hand side only",
+       "The right and left sides only":                  "The right and left sides only",
+       "The right-hand side only":                       "The right-hand side only",
+       "The top and bottom sides only":                  "The top and bottom sides only",
+       "The top side only":                              "The top side only",
+       "Top":                                            "Top",        
+       "Unset color":                                    "Unset color",
+       "Vertical align":                                 "Vertical align",
+       "Width":                                          "Width",
+       "not-del-last-cell":                              "HTMLArea cowardly refuses to delete the last cell in row.",
+       "not-del-last-col":                               "HTMLArea cowardly refuses to delete the last column in table.",
+       "not-del-last-row":                               "HTMLArea cowardly refuses to delete the last row in table.",
+       "percent":                                        "percent",
+       "pixels":                                         "pixels"
+};
diff --git a/htmlarea/plugins/TableOperations/lang/fi.js b/htmlarea/plugins/TableOperations/lang/fi.js
new file mode 100644 (file)
index 0000000..891f168
--- /dev/null
@@ -0,0 +1,66 @@
+TableOperations.I18N = {
+       "Align":                                          "Kohdistus",
+       "All four sides":                                 "Kaikki neljä sivua",
+       "Background":                                     "Tausta",
+       "Baseline":                                       "Takaraja",
+       "Border":                                         "Reuna",
+       "Borders":                                        "Reunat",
+       "Bottom":                                         "Alle",
+       "CSS Style":                                      "Tyyli [CSS]",
+       "Caption":                                        "Otsikko",
+       "Cell Properties":                                "Solun asetukset",
+       "Center":                                         "Keskelle",
+       "Char":                                           "Merkki",
+       "Collapsed borders":                              "Luhistetut reunat",
+       "Color":                                          "Väri",
+       "Description":                                    "Kuvaus",
+       "FG Color":                                       "FG Väri",
+       "Frames":                                         "Kehykset",
+       "Image URL":                                      "Kuvan osoite",
+       "Layout":                                         "Sommittelu",
+       "Left":                                           "Vasen",
+       "Margin":                                         "Marginaali",
+       "Middle":                                         "Keskelle",
+       "No rules":                                       "Ei viivoja",
+       "No sides":                                       "Ei sivuja",
+       "Padding":                                        "Palstantäyte",
+       "Right":                                          "Oikea",
+       "Row Properties":                                 "Rivin asetukset",
+       "Rules will appear between all rows and columns": "Viivat jokaisen rivin ja sarakkeen välillä",
+       "Rules will appear between columns only":         "Viivat ainoastaan sarakkeiden välillä",
+       "Rules will appear between rows only":            "Viivat ainoastaan rivien välillä",
+       "Rules":                                          "Viivat",
+       "Spacing":                                        "Palstatila",
+       "Summary":                                        "Yhteenveto",
+       "TO-cell-delete":                                 "Poista solu",
+       "TO-cell-insert-after":                           "Lisää solu perään",
+       "TO-cell-insert-before":                          "Lisää solu ennen",
+       "TO-cell-merge":                                  "Yhdistä solut",
+       "TO-cell-prop":                                   "Solun asetukset",
+       "TO-cell-split":                                  "Jaa solu",
+       "TO-col-delete":                                  "Poista sarake",
+       "TO-col-insert-after":                            "Lisää sarake perään",
+       "TO-col-insert-before":                           "Lisää sarake ennen",
+       "TO-col-split":                                   "Jaa sarake",
+       "TO-row-delete":                                  "Poista rivi",
+       "TO-row-insert-above":                            "Lisää rivi yläpuolelle",
+       "TO-row-insert-under":                            "Lisää rivi alapuolelle",
+       "TO-row-prop":                                    "Rivin asetukset",
+       "TO-row-split":                                   "Jaa rivi",
+       "TO-table-prop":                                  "Taulukon asetukset",
+       "Top":                                            "Ylös",       
+       "Table Properties":                               "Taulukon asetukset",
+       "The bottom side only":                           "Ainoastaan alapuolelle",
+       "The left-hand side only":                        "Ainoastaan vasenreuna",
+       "The right and left sides only":                  "Oikea- ja vasenreuna",
+       "The right-hand side only":                       "Ainoastaan oikeareuna",
+       "The top and bottom sides only":                  "Ylä- ja alapuoli.",
+       "The top side only":                              "Ainoastaan yläpuoli",
+       "Vertical align":                                 "Vertikaali kohdistus",
+       "Width":                                          "Leveys",
+       "not-del-last-cell":                              "Ei voida poistaa viimeistä solua rivistä.",
+       "not-del-last-col":                               "Ei voida poistaa viimeistä saraketta taulusta.",
+       "not-del-last-row":                               "Ei voida poistaa viimeistä riviä taulusta.",
+       "percent":                                        "prosenttia",
+       "pixels":                                         "pikseliä"
+};
diff --git a/htmlarea/plugins/TableOperations/lang/hu.js b/htmlarea/plugins/TableOperations/lang/hu.js
new file mode 100644 (file)
index 0000000..828aec1
--- /dev/null
@@ -0,0 +1,63 @@
+// I18N constants
+
+// LANG: "hu", ENCODING: UTF-8
+// Author: Miklós Somogyi, <somogyine@vnet.hu>
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+HTMLArea.I18N = {
+
+       // the following should be the filename without .js extension
+       // it will be used for automatically load plugin language.
+       lang: "hu",
+
+       tooltips: {
+               bold:           "Félkövér",
+               italic:         "Dőlt",
+               underline:      "Aláhúzott",
+               strikethrough:  "Áthúzott",
+               subscript:      "Alsó index",
+               superscript:    "Felső index",
+               justifyleft:    "Balra zárt",
+               justifycenter:  "Középre zárt",
+               justifyright:   "Jobbra zárt",
+               justifyfull:    "Sorkizárt",
+               orderedlist:    "Számozott lista",
+               unorderedlist:  "Számozatlan lista",
+               outdent:        "Behúzás csökkentése",
+               indent:         "Behúzás növelése",
+               forecolor:      "Karakterszín",
+               hilitecolor:    "Háttérszín",
+               horizontalrule: "Elválasztó vonal",
+               createlink:     "Hiperhivatkozás beszúrása",
+               insertimage:    "Kép beszúrása",
+               inserttable:    "Táblázat beszúrása",
+               htmlmode:       "HTML forrás be/ki",
+               popupeditor:    "Szerkesztő külön ablakban",
+               about:          "Névjegy",
+               showhelp:       "Súgó",
+               textindicator:  "Aktuális stílus",
+               undo:           "Visszavonás",
+               redo:           "Újra végrehajtás",
+               cut:            "Kivágás",
+               copy:           "Másolás",
+               paste:          "Beillesztés"
+       },
+
+       buttons: {
+               "ok":           "Rendben",
+               "cancel":       "Mégsem"
+       },
+
+       msg: {
+               "Path":         "Hierarchia",
+               "TEXT_MODE":    "Forrás mód. Visszaváltás [<>] gomb"
+       }
+};
diff --git a/htmlarea/plugins/TableOperations/lang/it.js b/htmlarea/plugins/TableOperations/lang/it.js
new file mode 100644 (file)
index 0000000..ccbdc94
--- /dev/null
@@ -0,0 +1,81 @@
+// I18N constants
+
+// LANG: "it", ENCODING: UTF-8 | ISO-8859-1
+// Author: Fabio Rotondo <fabio@rotondo.it>
+
+TableOperations.I18N = {
+       "Align":                                          "Allinea",
+       "All four sides":                                 "Tutti e quattro i lati",
+       "Background":                                     "Sfondo",
+       "Baseline":                                       "Allineamento",
+       "Border":                                         "Bordo",
+       "Borders":                                        "Bordi",
+       "Bottom":                                         "Basso",
+       "CSS Style":                                      "Stile [CSS]",
+       "Caption":                                        "Titolo",
+       "Cell Properties":                                "Proprietà della Cella",
+       "Center":                                         "Centra",
+       "Char":                                           "Carattere",
+       "Collapsed borders":                              "Bordi chiusi",
+       "Color":                                          "Colore",
+       "Description":                                    "Descrizione",
+       "FG Color":                                       "Colore Principale",
+       "Float":                                          "Fluttuante",
+       "Frames":                                         "Frames",
+       "Height":                                         "Altezza",
+       "How many columns would you like to merge?":      "Quante colonne vuoi unire?",
+       "How many rows would you like to merge?":         "Quante righe vuoi unire?",
+       "Image URL":                                      "URL dell'Immagine",
+       "Justify":                                        "Justifica",
+       "Layout":                                         "Layout",
+       "Left":                                           "Sinistra",
+       "Margin":                                         "Margine",
+       "Middle":                                         "Centrale",
+       "No rules":                                       "Nessun righello",
+       "No sides":                                       "Nessun lato",
+       "None":                                           "Nulla",
+       "Padding":                                        "Padding",
+       "Please click into some cell":                    "Per favore, clicca in una cella",
+       "Right":                                          "Destra",
+       "Row Properties":                                 "Proprietà della Riga",
+       "Rules will appear between all rows and columns": "Le linee appariranno tra tutte le righe e colonne",
+       "Rules will appear between columns only":         "Le linee appariranno solo tra le colonne",
+       "Rules will appear between rows only":            "Le linee appariranno solo tra le righe",
+       "Rules":                                          "Linee",
+       "Spacing and padding":                            "Spaziatura e Padding",
+       "Spacing":                                        "Spaziatura",
+       "Summary":                                        "Sommario",
+       "TO-cell-delete":                                 "Cancella cella",
+       "TO-cell-insert-after":                           "Inserisci cella dopo",
+       "TO-cell-insert-before":                          "Inserisci cella prima",
+       "TO-cell-merge":                                  "Unisci celle",
+       "TO-cell-prop":                                   "Proprietà della cella",
+       "TO-cell-split":                                  "Dividi cella",
+       "TO-col-delete":                                  "Cancella colonna",
+       "TO-col-insert-after":                            "Inserisci colonna dopo",
+       "TO-col-insert-before":                           "Inserisci colonna prima",
+       "TO-col-split":                                   "Dividi colonna",
+       "TO-row-delete":                                  "Cancella riga",
+       "TO-row-insert-above":                            "Inserisci riga prima",
+       "TO-row-insert-under":                            "Inserisci riga dopo",
+       "TO-row-prop":                                    "Proprietà della riga",
+       "TO-row-split":                                   "Dividi riga",
+       "TO-table-prop":                                  "Proprietà della Tabella",
+       "Table Properties":                               "Proprietà della Tabella",
+       "Text align":                                     "Allineamento del Testo",
+       "The bottom side only":                           "Solo la parte inferiore",
+       "The left-hand side only":                        "Solo la parte sinistra",
+       "The right and left sides only":                  "Solo destra e sinistra",
+       "The right-hand side only":                       "Solo la parte destra",
+       "The top and bottom sides only":                  "Solo sopra e sotto",
+       "The top side only":                              "Solo la parte sopra",
+       "Top":                                            "Alto",       
+       "Unset color":                                    "Rimuovi colore",
+       "Vertical align":                                 "Allineamento verticale",
+       "Width":                                          "Larghezza",
+       "not-del-last-cell":                              "HTMLArea si rifiuta codardamente di cancellare l'ultima cella nella riga.",
+       "not-del-last-col":                               "HTMLArea si rifiuta codardamente di cancellare l'ultima colonna nella tabella.",
+       "not-del-last-row":                               "HTMLArea si rifiuta codardamente di cancellare l'ultima riga nella tabella.",
+       "percent":                                        "percento",
+       "pixels":                                         "pixels"
+};
diff --git a/htmlarea/plugins/TableOperations/lang/nl.js b/htmlarea/plugins/TableOperations/lang/nl.js
new file mode 100644 (file)
index 0000000..ce9eb30
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants
+
+// LANG: "nl", ENCODING: UTF-8 | ISO-8859-1
+// Author: Michel Weegeerink (info@mmc-shop.nl), http://mmc-shop.nl
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+TableOperations.I18N = {
+       "Align":                                                                                        "Uitlijning",
+       "All four sides":                                                                       "Alle 4 zijden",
+       "Background":                                                                           "Achtergrond",
+       "Baseline":                                                                                     "Basis",
+       "Border":                                                                                       "Rand",
+       "Borders":                                                                                      "Randen",
+       "Bottom":                                                                                       "Onder",
+       "CSS Style":                                                                            "CSS Style",
+       "Caption":                                                                                      "Opmerking",
+       "Cell Properties":                                                                      "Celeigenschappen",
+       "Center":                                                                                       "Centreren",
+       "Char":                                                                                         "Karakter",
+       "Collapsed borders":                                                            "Geen randen",
+       "Color":                                                                                        "Kleur",
+       "Description":                                                                          "Omschrijving",
+       "FG Color":                                                                                     "Voorgrond",
+       "Float":                                                                                        "Zwevend",
+       "Frames":                                                                                       "Frames",
+       "Height":                                                                                       "Hoogte",
+       "How many columns would you like to merge?":            "Hoeveel kolommen wilt u samenvoegen?",
+       "How many rows would you like to merge?":                       "Hoeveel rijen wilt u samenvoegen?",
+       "Image URL":                                                                            "Afbeelding URL",
+       "Justify":                                                                                      "Uitvullen",
+       "Layout":                                                                                       "Opmaak",
+       "Left":                                                                                         "Links",
+       "Margin":                                                                                       "Marge",
+       "Middle":                                                                                       "Midden",
+       "No rules":                                                                                     "Geen regels",
+       "No sides":                                                                                     "Geen zijlijnen",
+       "None":                                                                                         "Geen",
+       "Padding":                                                                                      "Celmarge",
+       "Please click into some cell":                                          "Klik in een cel a.u.b.",
+       "Right":                                                                                        "Rechts",
+       "Row Properties":                                                                       "Rijeigenschappen",
+       "Rules will appear between all rows and columns":       "Regels verschijnen tussen alle rijen en kolommen",
+       "Rules will appear between columns only":                       "Regels verschijnen enkel tussen de kolommen",
+       "Rules will appear between rows only":                          "Regels verschijnen enkel tussen de rijen",
+       "Rules":                                                                                        "Regels",
+       "Spacing and padding":                                  "Celmarge en afstand tussen cellen",
+       "Spacing":                                                                                      "marge",
+       "Summary":                                                                                      "Overzicht",
+       "TO-cell-delete":                                                                       "Cel verwijderen",
+       "TO-cell-insert-after":                                                         "Voeg cel toe achter",
+       "TO-cell-insert-before":                                                        "Voeg cel toe voor",
+       "TO-cell-merge":                                                                        "Cellen samenvoegen",
+       "TO-cell-prop":                                                                         "Celeigenschappen",
+       "TO-cell-split":                                                                        "Cel splitsen",
+       "TO-col-delete":                                                                        "Kolom verwijderen",
+       "TO-col-insert-after":                                                          "Kolom invoegen achter",
+       "TO-col-insert-before":                                                         "Kolom invoegen voor",
+       "TO-col-split":                                                                         "Kolom splitsen",
+       "TO-row-delete":                                                                        "Rij verwijderen",
+       "TO-row-insert-above":                                                          "Rij invoegen boven",
+       "TO-row-insert-under":                                                          "Rij invoegen onder",
+       "TO-row-prop":                                                                          "Rij eigenschappen",
+       "TO-row-split":                                                                         "Rij splitsen",
+       "TO-table-prop":                                                                        "Tabel eigenschappen",
+       "Table Properties":                                                                     "Tabel eigenschappen",
+       "Text align":                                           "Text uitlijning",
+       "The bottom side only":                                                         "Enkel aan de onderkant",
+       "The left-hand side only":                                                      "Enkel aan de linkerkant",
+       "The right and left sides only":                                        "Enkel aan de linker en rechterkant",
+       "The right-hand side only":                                                     "Enkel aan de rechterkant",
+       "The top and bottom sides only":                                        "Enkel aan de bovenen onderkant",
+       "The top side only":                                                            "Enkel aan de bovenkant",
+       "Top":                                                                                          "Boven",
+       "Unset color":                                                                          "Wis kleur",
+       "Vertical align":                                                                       "Vertikale uitlijning",
+       "Width":                                                                                        "Breedte",
+       "not-del-last-cell":                                                            "HTMLArea kan de laatste cel in deze tabel niet verwijderen.",
+       "not-del-last-col":                                                                     "HTMLArea kan de laatste kolom in deze tabel niet verwijderen.",
+       "not-del-last-row":                                                                     "HTMLArea kan de laatste rij in deze tabel niet verwijderen.",
+       "percent":                                                                                      "procent",
+       "pixels":                                                                                       "pixels"
+};
diff --git a/htmlarea/plugins/TableOperations/lang/no.js b/htmlarea/plugins/TableOperations/lang/no.js
new file mode 100644 (file)
index 0000000..91fc5e5
--- /dev/null
@@ -0,0 +1,91 @@
+// I18N constants
+
+// LANG: "en", ENCODING: UTF-8 | ISO-8859-1
+// Author: Mihai Bazon, <mihai_bazon@yahoo.com>
+// translated into Norwegia: ses@online.no  11.11.03
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+TableOperations.I18N = {
+       "Align":                                                "Juster",
+       "All four sides":                               "Alle fire sider",
+       "Background":                                   "Bakgrund",
+       "Baseline":                     "Grunnlinje",
+       "Border":                                               "Kantlinje",
+       "Borders":                                              "Kantlinjer",
+       "Bottom":                       "Bunn",
+       "CSS Style":                                    "Stil [CSS]",
+       "Caption":                                              "Overskrift",
+       "Cell Properties":              "Celleegenskaper",
+       "Center":                                               "Sentrer",
+       "Char":                         "Tegn",
+       "Collapsed borders":            "Fjern kantlinjer",
+       "Color":                                                "Farge",
+       "Description":                                  "Beskrivelse",
+       "FG Color":                                             "FG farge",
+       "Float":                        "Flytende",
+       "Frames":                                               "rammer",
+       "Height":                       "Høyde",
+       "How many columns would you like to merge?":      "Hvor mange kolonner vil du slå sammen?",
+       "How many rows would you like to merge?":         "Hvor mange rader vil du slå sammen?",
+       "Image URL":                                    "Bildets URL",
+       "Justify":                      "Juster",
+       "Layout":                                               "Layout",
+       "Left":                                                 "Venstre",
+       "Margin":                       "Marg",
+       "Middle":                       "Midten",
+       "No rules":                                             "Ingen linjal",
+       "No sides":                                             "Ingen sider",
+       "None":                         "Ingen",
+       "Padding":                                              "Luft",
+       "Please click into some cell":  "Klikk i en eller annen celle",
+       "Right":                                                "Høyre",
+       "Row Properties":               "Egenskaper for rad",
+       "Rules will appear between all rows and columns": "Linjer vil synes mellom alle rader og kolonner",
+       "Rules will appear between columns only":         "Linjer vil synes kun mellom kolonner",
+       "Rules will appear between rows only":            "Linjer vil synes kun mellom rader",
+       "Rules":                                                "Linjer",
+       "Spacing and padding":          "Luft",
+       "Spacing":                                              "Luft",
+       "Summary":                                              "Sammendrag",
+       "TO-cell-delete":                               "Slett celle",
+       "TO-cell-insert-after":                 "Sett inn celle etter",
+       "TO-cell-insert-before":                "Sett inn celle foran",
+       "TO-cell-merge":                                "Slå sammen celler",
+       "TO-cell-prop":                                 "Egenskaper for celle",
+       "TO-cell-split":                                "Del celle",
+       "TO-col-delete":                                "Slett kolonne",
+       "TO-col-insert-after":                  "Skyt inn kolonne etter",
+       "TO-col-insert-before":                 "Skyt inn kolonne før",
+       "TO-col-split":                                 "Del kolonne",
+       "TO-row-delete":                                "Slett rad",
+       "TO-row-insert-above":                  "Skyt inn rad foran",
+       "TO-row-insert-under":                  "Skyt inn rad etter",
+       "TO-row-prop":                                  "Egenskaper for rad",
+       "TO-row-split":                                 "Del rad",
+       "TO-table-prop":                                "Tabellegenskaper",
+       "Table Properties":                             "Tabellegenskaper",
+       "Text align":                   "Juster tekst",
+       "The bottom side only":                 "Bunnen kun",
+       "The left-hand side only":              "Venstresiden kun",
+       "The right and left sides only":        "Høyre- og venstresiden kun",
+       "The right-hand side only":                     "Høyresiden kun",
+       "The top and bottom sides only":        "The top and bottom sides only",
+       "The top side only":                            "Overkanten kun",
+       "Top":                          "Overkant",     
+       "Unset color":                  "Ikke-bestemt farge",
+       "Vertical align":               "Vertikal justering",
+       "Width":                                                "Bredde",
+       "not-del-last-cell":                    "HTMLArea nekter å slette siste cellen i tabellen.",
+       "not-del-last-col":                             "HTMLArea nekter å slette siste kolonnen i tabellen.",
+       "not-del-last-row":                             "HTMLArea nekter å slette siste raden i tabellen.",
+       "percent":                                              "prosent",
+       "pixels":                                               "billedpunkter"
+};
diff --git a/htmlarea/plugins/TableOperations/lang/ro.js b/htmlarea/plugins/TableOperations/lang/ro.js
new file mode 100644 (file)
index 0000000..a008f21
--- /dev/null
@@ -0,0 +1,90 @@
+// I18N constants
+
+// LANG: "ro", ENCODING: UTF-8
+// Author: Mihai Bazon, http://dynarch.com/mishoo
+
+// FOR TRANSLATORS:
+//
+//   1. PLEASE PUT YOUR CONTACT INFO IN THE ABOVE LINE
+//      (at least a valid email address)
+//
+//   2. PLEASE TRY TO USE UTF-8 FOR ENCODING;
+//      (if this is not possible, please include a comment
+//       that states what encoding is necessary.)
+
+TableOperations.I18N = {
+       "Align":                                          "Aliniere",
+       "All four sides":                                 "Toate părţile",
+       "Background":                                     "Fundal",
+       "Baseline":                                       "Baseline",
+       "Border":                                         "Chenar",
+       "Borders":                                        "Chenare",
+       "Bottom":                                         "Jos",
+       "CSS Style":                                      "Stil [CSS]",
+       "Caption":                                        "Titlu de tabel",
+       "Cell Properties":                                "Proprietăţile celulei",
+       "Center":                                         "Centru",
+       "Char":                                           "Caracter",
+       "Collapsed borders":                              "Chenare asimilate",
+       "Color":                                          "Culoare",
+       "Description":                                    "Descriere",
+       "FG Color":                                       "Culoare text",
+       "Float":                                          "Poziţie",
+       "Frames":                                         "Chenare",
+       "Height":                                         "Înălţimea",
+       "How many columns would you like to merge?":      "Câte coloane vrei să uneşti?",
+       "How many rows would you like to merge?":         "Câte linii vrei să uneşti?",
+       "Image URL":                                      "URL-ul imaginii",
+       "Justify":                                        "Justify",
+       "Layout":                                         "Aranjament",
+       "Left":                                           "Stânga",
+       "Margin":                                         "Margine",
+       "Middle":                                         "Mijloc",
+       "No rules":                                       "Fără linii",
+       "No sides":                                       "Fără părţi",
+       "None":                                           "Nimic",
+       "Padding":                                        "Spaţiere",
+       "Please click into some cell":                    "Vă rog să daţi click într-o celulă",
+       "Right":                                          "Dreapta",
+       "Row Properties":                                 "Proprietăţile liniei",
+       "Rules will appear between all rows and columns": "Vor apărea linii între toate rândurile şi coloanele",
+       "Rules will appear between columns only":         "Vor apărea doar linii verticale",
+       "Rules will appear between rows only":            "Vor apărea doar linii orizontale",
+       "Rules":                                          "Linii",
+       "Spacing and padding":                            "Spaţierea",
+       "Spacing":                                        "Între celule",
+       "Summary":                                        "Sumar",
+       "TO-cell-delete":                                 "Şterge celula",
+       "TO-cell-insert-after":                           "Inserează o celulă la dreapta",
+       "TO-cell-insert-before":                          "Inserează o celulă la stânga",
+       "TO-cell-merge":                                  "Uneşte celulele",
+       "TO-cell-prop":                                   "Proprietăţile celulei",
+       "TO-cell-split":                                  "Împarte celula",
+       "TO-col-delete":                                  "Şterge coloana",
+       "TO-col-insert-after":                            "Inserează o coloană la dreapta",
+       "TO-col-insert-before":                           "Inserează o coloană la stânga",
+       "TO-col-split":                                   "Împarte coloana",
+       "TO-row-delete":                                  "Şterge rândul",
+       "TO-row-insert-above":                            "Inserează un rând înainte",
+       "TO-row-insert-under":                            "Inserează un rând după",
+       "TO-row-prop":                                    "Proprietăţile rândului",
+       "TO-row-split":                                   "Împarte rândul",
+       "TO-table-prop":                                  "Proprietăţile tabelei",
+       "Table Properties":                               "Proprietăţile tabelei",
+       "Text align":                                     "Aliniere",
+       "The bottom side only":                           "Doar partea de jos",
+       "The left-hand side only":                        "Doar partea din stânga",
+       "The right and left sides only":                  "Partea din stânga şi cea din dreapta",
+       "The right-hand side only":                       "Doar partea din dreapta",
+       "The top and bottom sides only":                  "Partea de sus si cea de jos",
+       "The top side only":                              "Doar partea de sus",
+       "Top":                                            "Sus",        
+       "Unset color":                                    "Dezactivează culoarea",
+       "Vertical align":                                 "Aliniere pe verticală",
+       "Width":                                          "Lăţime",
+       "not-del-last-cell":                              "HTMLArea refuză cu laşitate să şteargă ultima celulă din rând.",
+       "not-del-last-col":                               "HTMLArea refuză cu laşitate să şteargă ultima coloamă din tabela.",
+       "not-del-last-row":                               "HTMLArea refuză cu laşitate să şteargă ultimul rând din tabela.",
+       "percent":                                        "procente",
+       "pixels":                                         "pixeli"
+};
diff --git a/htmlarea/plugins/TableOperations/table-operations.js b/htmlarea/plugins/TableOperations/table-operations.js
new file mode 100644 (file)
index 0000000..9aa17ce
--- /dev/null
@@ -0,0 +1,1160 @@
+// Table Operations Plugin for HTMLArea-3.0
+// Implementation by Mihai Bazon.  Sponsored by http://www.bloki.com
+//
+// htmlArea v3.0 - Copyright (c) 2002 interactivetools.com, inc.
+// This notice MUST stay intact for use (see license.txt).
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon for InteractiveTools.
+//   http://dynarch.com/mishoo
+//
+// $Id: table-operations.js,v 1.2 2005/01/11 15:00:58 garvinhicking Exp $
+
+// Object that will encapsulate all the table operations provided by
+// HTMLArea-3.0 (except "insert table" which is included in the main file)
+function TableOperations(editor) {
+       this.editor = editor;
+
+       var cfg = editor.config;
+       var tt = TableOperations.I18N;
+       var bl = TableOperations.btnList;
+       var self = this;
+
+       // register the toolbar buttons provided by this plugin
+       var toolbar = ["linebreak"];
+       for (var i = 0; i < bl.length; ++i) {
+               var btn = bl[i];
+               if (!btn) {
+                       toolbar.push("separator");
+               } else {
+                       var id = "TO-" + btn[0];
+                       cfg.registerButton(id, tt[id], editor.imgURL(btn[0] + ".gif", "TableOperations"), false,
+                                          function(editor, id) {
+                                                  // dispatch button press event
+                                                  self.buttonPress(editor, id);
+                                          }, btn[1]);
+                       toolbar.push(id);
+               }
+       }
+
+       // add a new line in the toolbar
+       cfg.toolbar.push(toolbar);
+};
+
+TableOperations._pluginInfo = {
+       name          : "TableOperations",
+       version       : "1.0",
+       developer     : "Mihai Bazon",
+       developer_url : "http://dynarch.com/mishoo/",
+       c_owner       : "Mihai Bazon",
+       sponsor       : "Zapatec Inc.",
+       sponsor_url   : "http://www.bloki.com",
+       license       : "htmlArea"
+};
+
+/************************
+ * UTILITIES
+ ************************/
+
+// retrieves the closest element having the specified tagName in the list of
+// ancestors of the current selection/caret.
+TableOperations.prototype.getClosest = function(tagName) {
+       var editor = this.editor;
+       var ancestors = editor.getAllAncestors();
+       var ret = null;
+       tagName = ("" + tagName).toLowerCase();
+       for (var i = 0; i < ancestors.length; ++i) {
+               var el = ancestors[i];
+               if (el.tagName.toLowerCase() == tagName) {
+                       ret = el;
+                       break;
+               }
+       }
+       return ret;
+};
+
+// this function requires the file PopupDiv/PopupWin to be loaded from browser
+TableOperations.prototype.dialogTableProperties = function() {
+       var i18n = TableOperations.I18N;
+       // retrieve existing values
+       var table = this.getClosest("table");
+       // this.editor.selectNodeContents(table);
+       // this.editor.updateToolbar();
+
+       var dialog = new PopupWin(this.editor, i18n["Table Properties"], function(dialog, params) {
+               TableOperations.processStyle(params, table);
+               for (var i in params) {
+                       var val = params[i];
+                       switch (i) {
+                           case "f_caption":
+                               if (/\S/.test(val)) {
+                                       // contains non white-space characters
+                                       var caption = table.getElementsByTagName("caption")[0];
+                                       if (!caption) {
+                                               caption = dialog.editor._doc.createElement("caption");
+                                               table.insertBefore(caption, table.firstChild);
+                                       }
+                                       caption.innerHTML = val;
+                               } else {
+                                       // search for caption and delete it if found
+                                       var caption = table.getElementsByTagName("caption")[0];
+                                       if (caption) {
+                                               caption.parentNode.removeChild(caption);
+                                       }
+                               }
+                               break;
+                           case "f_summary":
+                               table.summary = val;
+                               break;
+                           case "f_width":
+                               table.style.width = ("" + val) + params.f_unit;
+                               break;
+                           case "f_align":
+                               table.align = val;
+                               break;
+                           case "f_spacing":
+                               table.cellSpacing = val;
+                               break;
+                           case "f_padding":
+                               table.cellPadding = val;
+                               break;
+                           case "f_borders":
+                               table.border = val;
+                               break;
+                           case "f_frames":
+                               table.frame = val;
+                               break;
+                           case "f_rules":
+                               table.rules = val;
+                               break;
+                       }
+               }
+               // various workarounds to refresh the table display (Gecko,
+               // what's going on?! do not disappoint me!)
+               dialog.editor.forceRedraw();
+               dialog.editor.focusEditor();
+               dialog.editor.updateToolbar();
+               var save_collapse = table.style.borderCollapse;
+               table.style.borderCollapse = "collapse";
+               table.style.borderCollapse = "separate";
+               table.style.borderCollapse = save_collapse;
+       },
+
+       // this function gets called when the dialog needs to be initialized
+       function (dialog) {
+
+               var f_caption = "";
+               var capel = table.getElementsByTagName("caption")[0];
+               if (capel) {
+                       f_caption = capel.innerHTML;
+               }
+               var f_summary = table.summary;
+               var f_width = parseInt(table.style.width);
+               isNaN(f_width) && (f_width = "");
+               var f_unit = /%/.test(table.style.width) ? 'percent' : 'pixels';
+               var f_align = table.align;
+               var f_spacing = table.cellSpacing;
+               var f_padding = table.cellPadding;
+               var f_borders = table.border;
+               var f_frames = table.frame;
+               var f_rules = table.rules;
+
+               function selected(val) {
+                       return val ? " selected" : "";
+               };
+
+               // dialog contents
+               dialog.content.style.width = "400px";
+               dialog.content.innerHTML = " \
+<div class='title'\
+ style='background: url(" + dialog.baseURL + dialog.editor.imgURL("table-prop.gif", "TableOperations") + ") #fff 98% 50% no-repeat'>" + i18n["Table Properties"] + "\
+</div> \
+<table style='width:100%'> \
+  <tr> \
+    <td> \
+      <fieldset><legend>" + i18n["Description"] + "</legend> \
+       <table style='width:100%'> \
+        <tr> \
+          <td class='label'>" + i18n["Caption"] + ":</td> \
+          <td class='value'><input type='text' name='f_caption' value='" + f_caption + "'/></td> \
+        </tr><tr> \
+          <td class='label'>" + i18n["Summary"] + ":</td> \
+          <td class='value'><input type='text' name='f_summary' value='" + f_summary + "'/></td> \
+        </tr> \
+       </table> \
+      </fieldset> \
+    </td> \
+  </tr> \
+  <tr><td id='--HA-layout'></td></tr> \
+  <tr> \
+    <td> \
+      <fieldset><legend>" + i18n["Spacing and padding"] + "</legend> \
+       <table style='width:100%'> \
+"+//        <tr> \
+//           <td class='label'>" + i18n["Width"] + ":</td> \
+//           <td><input type='text' name='f_width' value='" + f_width + "' size='5' /> \
+//             <select name='f_unit'> \
+//               <option value='%'" + selected(f_unit == "percent") + ">" + i18n["percent"] + "</option> \
+//               <option value='px'" + selected(f_unit == "pixels") + ">" + i18n["pixels"] + "</option> \
+//             </select> &nbsp;&nbsp;" + i18n["Align"] + ": \
+//             <select name='f_align'> \
+//               <option value='left'" + selected(f_align == "left") + ">" + i18n["Left"] + "</option> \
+//               <option value='center'" + selected(f_align == "center") + ">" + i18n["Center"] + "</option> \
+//               <option value='right'" + selected(f_align == "right") + ">" + i18n["Right"] + "</option> \
+//             </select> \
+//           </td> \
+//         </tr> \
+"        <tr> \
+          <td class='label'>" + i18n["Spacing"] + ":</td> \
+          <td><input type='text' name='f_spacing' size='5' value='" + f_spacing + "' /> &nbsp;" + i18n["Padding"] + ":\
+            <input type='text' name='f_padding' size='5' value='" + f_padding + "' /> &nbsp;&nbsp;" + i18n["pixels"] + "\
+          </td> \
+        </tr> \
+       </table> \
+      </fieldset> \
+    </td> \
+  </tr> \
+  <tr> \
+    <td> \
+      <fieldset><legend>Frame and borders</legend> \
+        <table width='100%'> \
+          <tr> \
+            <td class='label'>" + i18n["Borders"] + ":</td> \
+            <td><input name='f_borders' type='text' size='5' value='" + f_borders + "' /> &nbsp;&nbsp;" + i18n["pixels"] + "</td> \
+          </tr> \
+          <tr> \
+            <td class='label'>" + i18n["Frames"] + ":</td> \
+            <td> \
+              <select name='f_frames'> \
+                <option value='void'" + selected(f_frames == "void") + ">" + i18n["No sides"] + "</option> \
+                <option value='above'" + selected(f_frames == "above") + ">" + i18n["The top side only"] + "</option> \
+                <option value='below'" + selected(f_frames == "below") + ">" + i18n["The bottom side only"] + "</option> \
+                <option value='hsides'" + selected(f_frames == "hsides") + ">" + i18n["The top and bottom sides only"] + "</option> \
+                <option value='vsides'" + selected(f_frames == "vsides") + ">" + i18n["The right and left sides only"] + "</option> \
+                <option value='lhs'" + selected(f_frames == "lhs") + ">" + i18n["The left-hand side only"] + "</option> \
+                <option value='rhs'" + selected(f_frames == "rhs") + ">" + i18n["The right-hand side only"] + "</option> \
+                <option value='box'" + selected(f_frames == "box") + ">" + i18n["All four sides"] + "</option> \
+              </select> \
+            </td> \
+          </tr> \
+          <tr> \
+            <td class='label'>" + i18n["Rules"] + ":</td> \
+            <td> \
+              <select name='f_rules'> \
+                <option value='none'" + selected(f_rules == "none") + ">" + i18n["No rules"] + "</option> \
+                <option value='rows'" + selected(f_rules == "rows") + ">" + i18n["Rules will appear between rows only"] + "</option> \
+                <option value='cols'" + selected(f_rules == "cols") + ">" + i18n["Rules will appear between columns only"] + "</option> \
+                <option value='all'" + selected(f_rules == "all") + ">" + i18n["Rules will appear between all rows and columns"] + "</option> \
+              </select> \
+            </td> \
+          </tr> \
+        </table> \
+      </fieldset> \
+    </td> \
+  </tr> \
+  <tr> \
+    <td id='--HA-style'></td> \
+  </tr> \
+</table> \
+";
+               var st_prop = TableOperations.createStyleFieldset(dialog.doc, dialog.editor, table);
+               var p = dialog.doc.getElementById("--HA-style");
+               p.appendChild(st_prop);
+               var st_layout = TableOperations.createStyleLayoutFieldset(dialog.doc, dialog.editor, table);
+               p = dialog.doc.getElementById("--HA-layout");
+               p.appendChild(st_layout);
+               dialog.modal = true;
+               dialog.addButtons("ok", "cancel");
+               dialog.showAtElement(dialog.editor._iframe, "c");
+       });
+};
+
+// this function requires the file PopupDiv/PopupWin to be loaded from browser
+TableOperations.prototype.dialogRowCellProperties = function(cell) {
+       var i18n = TableOperations.I18N;
+       // retrieve existing values
+       var element = this.getClosest(cell ? "td" : "tr");
+       var table = this.getClosest("table");
+       // this.editor.selectNodeContents(element);
+       // this.editor.updateToolbar();
+
+       var dialog = new PopupWin(this.editor, i18n[cell ? "Cell Properties" : "Row Properties"], function(dialog, params) {
+               TableOperations.processStyle(params, element);
+               for (var i in params) {
+                       var val = params[i];
+                       switch (i) {
+                           case "f_align":
+                               element.align = val;
+                               break;
+                           case "f_char":
+                               element.ch = val;
+                               break;
+                           case "f_valign":
+                               element.vAlign = val;
+                               break;
+                       }
+               }
+               // various workarounds to refresh the table display (Gecko,
+               // what's going on?! do not disappoint me!)
+               dialog.editor.forceRedraw();
+               dialog.editor.focusEditor();
+               dialog.editor.updateToolbar();
+               var save_collapse = table.style.borderCollapse;
+               table.style.borderCollapse = "collapse";
+               table.style.borderCollapse = "separate";
+               table.style.borderCollapse = save_collapse;
+       },
+
+       // this function gets called when the dialog needs to be initialized
+       function (dialog) {
+
+               var f_align = element.align;
+               var f_valign = element.vAlign;
+               var f_char = element.ch;
+
+               function selected(val) {
+                       return val ? " selected" : "";
+               };
+
+               // dialog contents
+               dialog.content.style.width = "400px";
+               dialog.content.innerHTML = " \
+<div class='title'\
+ style='background: url(" + dialog.baseURL + dialog.editor.imgURL(cell ? "cell-prop.gif" : "row-prop.gif", "TableOperations") + ") #fff 98% 50% no-repeat'>" + i18n[cell ? "Cell Properties" : "Row Properties"] + "</div> \
+<table style='width:100%'> \
+  <tr> \
+    <td id='--HA-layout'> \
+"+//      <fieldset><legend>" + i18n["Layout"] + "</legend> \
+//        <table style='width:100%'> \
+//         <tr> \
+//           <td class='label'>" + i18n["Align"] + ":</td> \
+//           <td> \
+//             <select name='f_align'> \
+//               <option value='left'" + selected(f_align == "left") + ">" + i18n["Left"] + "</option> \
+//               <option value='center'" + selected(f_align == "center") + ">" + i18n["Center"] + "</option> \
+//               <option value='right'" + selected(f_align == "right") + ">" + i18n["Right"] + "</option> \
+//               <option value='char'" + selected(f_align == "char") + ">" + i18n["Char"] + "</option> \
+//             </select> \
+//             &nbsp;&nbsp;" + i18n["Char"] + ": \
+//             <input type='text' style='font-family: monospace; text-align: center' name='f_char' size='1' value='" + f_char + "' /> \
+//           </td> \
+//         </tr><tr> \
+//           <td class='label'>" + i18n["Vertical align"] + ":</td> \
+//           <td> \
+//             <select name='f_valign'> \
+//               <option value='top'" + selected(f_valign == "top") + ">" + i18n["Top"] + "</option> \
+//               <option value='middle'" + selected(f_valign == "middle") + ">" + i18n["Middle"] + "</option> \
+//               <option value='bottom'" + selected(f_valign == "bottom") + ">" + i18n["Bottom"] + "</option> \
+//               <option value='baseline'" + selected(f_valign == "baseline") + ">" + i18n["Baseline"] + "</option> \
+//             </select> \
+//           </td> \
+//         </tr> \
+//        </table> \
+//       </fieldset> \
+"    </td> \
+  </tr> \
+  <tr> \
+    <td id='--HA-style'></td> \
+  </tr> \
+</table> \
+";
+               var st_prop = TableOperations.createStyleFieldset(dialog.doc, dialog.editor, element);
+               var p = dialog.doc.getElementById("--HA-style");
+               p.appendChild(st_prop);
+               var st_layout = TableOperations.createStyleLayoutFieldset(dialog.doc, dialog.editor, element);
+               p = dialog.doc.getElementById("--HA-layout");
+               p.appendChild(st_layout);
+               dialog.modal = true;
+               dialog.addButtons("ok", "cancel");
+               dialog.showAtElement(dialog.editor._iframe, "c");
+       });
+};
+
+// this function gets called when some button from the TableOperations toolbar
+// was pressed.
+TableOperations.prototype.buttonPress = function(editor, button_id) {
+       this.editor = editor;
+       var mozbr = HTMLArea.is_gecko ? "<br />" : "";
+       var i18n = TableOperations.I18N;
+
+       // helper function that clears the content in a table row
+       function clearRow(tr) {
+               var tds = tr.getElementsByTagName("td");
+               for (var i = tds.length; --i >= 0;) {
+                       var td = tds[i];
+                       td.rowSpan = 1;
+                       td.innerHTML = mozbr;
+               }
+       };
+
+       function splitRow(td) {
+               var n = parseInt("" + td.rowSpan);
+               var nc = parseInt("" + td.colSpan);
+               td.rowSpan = 1;
+               tr = td.parentNode;
+               var itr = tr.rowIndex;
+               var trs = tr.parentNode.rows;
+               var index = td.cellIndex;
+               while (--n > 0) {
+                       tr = trs[++itr];
+                       var otd = editor._doc.createElement("td");
+                       otd.colSpan = td.colSpan;
+                       otd.innerHTML = mozbr;
+                       tr.insertBefore(otd, tr.cells[index]);
+               }
+               editor.forceRedraw();
+               editor.updateToolbar();
+       };
+
+       function splitCol(td) {
+               var nc = parseInt("" + td.colSpan);
+               td.colSpan = 1;
+               tr = td.parentNode;
+               var ref = td.nextSibling;
+               while (--nc > 0) {
+                       var otd = editor._doc.createElement("td");
+                       otd.rowSpan = td.rowSpan;
+                       otd.innerHTML = mozbr;
+                       tr.insertBefore(otd, ref);
+               }
+               editor.forceRedraw();
+               editor.updateToolbar();
+       };
+
+       function splitCell(td) {
+               var nc = parseInt("" + td.colSpan);
+               splitCol(td);
+               var items = td.parentNode.cells;
+               var index = td.cellIndex;
+               while (nc-- > 0) {
+                       splitRow(items[index++]);
+               }
+       };
+
+       function selectNextNode(el) {
+               var node = el.nextSibling;
+               while (node && node.nodeType != 1) {
+                       node = node.nextSibling;
+               }
+               if (!node) {
+                       node = el.previousSibling;
+                       while (node && node.nodeType != 1) {
+                               node = node.previousSibling;
+                       }
+               }
+               if (!node) {
+                       node = el.parentNode;
+               }
+               editor.selectNodeContents(node);
+       };
+
+       switch (button_id) {
+               // ROWS
+
+           case "TO-row-insert-above":
+           case "TO-row-insert-under":
+               var tr = this.getClosest("tr");
+               if (!tr) {
+                       break;
+               }
+               var otr = tr.cloneNode(true);
+               clearRow(otr);
+               tr.parentNode.insertBefore(otr, /under/.test(button_id) ? tr.nextSibling : tr);
+               editor.forceRedraw();
+               editor.focusEditor();
+               break;
+           case "TO-row-delete":
+               var tr = this.getClosest("tr");
+               if (!tr) {
+                       break;
+               }
+               var par = tr.parentNode;
+               if (par.rows.length == 1) {
+                       alert(i18n["not-del-last-row"]);
+                       break;
+               }
+               // set the caret first to a position that doesn't
+               // disappear.
+               selectNextNode(tr);
+               par.removeChild(tr);
+               editor.forceRedraw();
+               editor.focusEditor();
+               editor.updateToolbar();
+               break;
+           case "TO-row-split":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               splitRow(td);
+               break;
+
+               // COLUMNS
+
+           case "TO-col-insert-before":
+           case "TO-col-insert-after":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               var rows = td.parentNode.parentNode.rows;
+               var index = td.cellIndex;
+               for (var i = rows.length; --i >= 0;) {
+                       var tr = rows[i];
+                       var ref = tr.cells[index + (/after/.test(button_id) ? 1 : 0)];
+                       var otd = editor._doc.createElement("td");
+                       otd.innerHTML = mozbr;
+                       tr.insertBefore(otd, ref);
+               }
+               editor.focusEditor();
+               break;
+           case "TO-col-split":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               splitCol(td);
+               break;
+           case "TO-col-delete":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               var index = td.cellIndex;
+               if (td.parentNode.cells.length == 1) {
+                       alert(i18n["not-del-last-col"]);
+                       break;
+               }
+               // set the caret first to a position that doesn't disappear
+               selectNextNode(td);
+               var rows = td.parentNode.parentNode.rows;
+               for (var i = rows.length; --i >= 0;) {
+                       var tr = rows[i];
+                       tr.removeChild(tr.cells[index]);
+               }
+               editor.forceRedraw();
+               editor.focusEditor();
+               editor.updateToolbar();
+               break;
+
+               // CELLS
+
+           case "TO-cell-split":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               splitCell(td);
+               break;
+           case "TO-cell-insert-before":
+           case "TO-cell-insert-after":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               var tr = td.parentNode;
+               var otd = editor._doc.createElement("td");
+               otd.innerHTML = mozbr;
+               tr.insertBefore(otd, /after/.test(button_id) ? td.nextSibling : td);
+               editor.forceRedraw();
+               editor.focusEditor();
+               break;
+           case "TO-cell-delete":
+               var td = this.getClosest("td");
+               if (!td) {
+                       break;
+               }
+               if (td.parentNode.cells.length == 1) {
+                       alert(i18n["not-del-last-cell"]);
+                       break;
+               }
+               // set the caret first to a position that doesn't disappear
+               selectNextNode(td);
+               td.parentNode.removeChild(td);
+               editor.forceRedraw();
+               editor.updateToolbar();
+               break;
+           case "TO-cell-merge":
+               // !! FIXME: Mozilla specific !!
+               var sel = editor._getSelection();
+               var range, i = 0;
+               var rows = [];
+               var row = null;
+               var cells = null;
+               if (!HTMLArea.is_ie) {
+                       try {
+                               while (range = sel.getRangeAt(i++)) {
+                                       var td = range.startContainer.childNodes[range.startOffset];
+                                       if (td.parentNode != row) {
+                                               row = td.parentNode;
+                                               (cells) && rows.push(cells);
+                                               cells = [];
+                                       }
+                                       cells.push(td);
+                               }
+                       } catch(e) {/* finished walking through selection */}
+                       rows.push(cells);
+               } else {
+                       // Internet Explorer "browser"
+                       var td = this.getClosest("td");
+                       if (!td) {
+                               alert(i18n["Please click into some cell"]);
+                               break;
+                       }
+                       var tr = td.parentElement;
+                       var no_cols = prompt(i18n["How many columns would you like to merge?"], 2);
+                       if (!no_cols) {
+                               // cancelled
+                               break;
+                       }
+                       var no_rows = prompt(i18n["How many rows would you like to merge?"], 2);
+                       if (!no_rows) {
+                               // cancelled
+                               break;
+                       }
+                       var cell_index = td.cellIndex;
+                       while (no_rows-- > 0) {
+                               td = tr.cells[cell_index];
+                               cells = [td];
+                               for (var i = 1; i < no_cols; ++i) {
+                                       td = td.nextSibling;
+                                       if (!td) {
+                                               break;
+                                       }
+                                       cells.push(td);
+                               }
+                               rows.push(cells);
+                               tr = tr.nextSibling;
+                               if (!tr) {
+                                       break;
+                               }
+                       }
+               }
+               var HTML = "";
+               for (i = 0; i < rows.length; ++i) {
+                       // i && (HTML += "<br />");
+                       var cells = rows[i];
+                       for (var j = 0; j < cells.length; ++j) {
+                               // j && (HTML += "&nbsp;");
+                               var cell = cells[j];
+                               HTML += cell.innerHTML;
+                               (i || j) && (cell.parentNode.removeChild(cell));
+                       }
+               }
+               var td = rows[0][0];
+               td.innerHTML = HTML;
+               td.rowSpan = rows.length;
+               td.colSpan = rows[0].length;
+               editor.selectNodeContents(td);
+               editor.forceRedraw();
+               editor.focusEditor();
+               break;
+
+               // PROPERTIES
+
+           case "TO-table-prop":
+               this.dialogTableProperties();
+               break;
+
+           case "TO-row-prop":
+               this.dialogRowCellProperties(false);
+               break;
+
+           case "TO-cell-prop":
+               this.dialogRowCellProperties(true);
+               break;
+
+           default:
+               alert("Button [" + button_id + "] not yet implemented");
+       }
+};
+
+// the list of buttons added by this plugin
+TableOperations.btnList = [
+       // table properties button
+       ["table-prop",       "table"],
+       null,                   // separator
+
+       // ROWS
+       ["row-prop",         "tr"],
+       ["row-insert-above", "tr"],
+       ["row-insert-under", "tr"],
+       ["row-delete",       "tr"],
+       ["row-split",        "td[rowSpan!=1]"],
+       null,
+
+       // COLS
+       ["col-insert-before", "td"],
+       ["col-insert-after",  "td"],
+       ["col-delete",        "td"],
+       ["col-split",         "td[colSpan!=1]"],
+       null,
+
+       // CELLS
+       ["cell-prop",          "td"],
+       ["cell-insert-before", "td"],
+       ["cell-insert-after",  "td"],
+       ["cell-delete",        "td"],
+       ["cell-merge",         "tr"],
+       ["cell-split",         "td[colSpan!=1,rowSpan!=1]"]
+       ];
+
+
+
+//// GENERIC CODE [style of any element; this should be moved into a separate
+//// file as it'll be very useful]
+//// BEGIN GENERIC CODE -----------------------------------------------------
+
+TableOperations.getLength = function(value) {
+       var len = parseInt(value);
+       if (isNaN(len)) {
+               len = "";
+       }
+       return len;
+};
+
+// Applies the style found in "params" to the given element.
+TableOperations.processStyle = function(params, element) {
+       var style = element.style;
+       for (var i in params) {
+               var val = params[i];
+               switch (i) {
+                   case "f_st_backgroundColor":
+                       style.backgroundColor = val;
+                       break;
+                   case "f_st_color":
+                       style.color = val;
+                       break;
+                   case "f_st_backgroundImage":
+                       if (/\S/.test(val)) {
+                               style.backgroundImage = "url(" + val + ")";
+                       } else {
+                               style.backgroundImage = "none";
+                       }
+                       break;
+                   case "f_st_borderWidth":
+                       style.borderWidth = val;
+                       break;
+                   case "f_st_borderStyle":
+                       style.borderStyle = val;
+                       break;
+                   case "f_st_borderColor":
+                       style.borderColor = val;
+                       break;
+                   case "f_st_borderCollapse":
+                       style.borderCollapse = val ? "collapse" : "";
+                       break;
+                   case "f_st_width":
+                       if (/\S/.test(val)) {
+                               style.width = val + params["f_st_widthUnit"];
+                       } else {
+                               style.width = "";
+                       }
+                       break;
+                   case "f_st_height":
+                       if (/\S/.test(val)) {
+                               style.height = val + params["f_st_heightUnit"];
+                       } else {
+                               style.height = "";
+                       }
+                       break;
+                   case "f_st_textAlign":
+                       if (val == "char") {
+                               var ch = params["f_st_textAlignChar"];
+                               if (ch == '"') {
+                                       ch = '\\"';
+                               }
+                               style.textAlign = '"' + ch + '"';
+                       } else {
+                               style.textAlign = val;
+                       }
+                       break;
+                   case "f_st_verticalAlign":
+                       style.verticalAlign = val;
+                       break;
+                   case "f_st_float":
+                       style.cssFloat = val;
+                       break;
+//                 case "f_st_margin":
+//                     style.margin = val + "px";
+//                     break;
+//                 case "f_st_padding":
+//                     style.padding = val + "px";
+//                     break;
+               }
+       }
+};
+
+// Returns an HTML element for a widget that allows color selection.  That is,
+// a button that contains the given color, if any, and when pressed will popup
+// the sooner-or-later-to-be-rewritten select_color.html dialog allowing user
+// to select some color.  If a color is selected, an input field with the name
+// "f_st_"+name will be updated with the color value in #123456 format.
+TableOperations.createColorButton = function(doc, editor, color, name) {
+       if (!color) {
+               color = "";
+       } else if (!/#/.test(color)) {
+               color = HTMLArea._colorToRgb(color);
+       }
+
+       var df = doc.createElement("span");
+       var field = doc.createElement("input");
+       field.type = "hidden";
+       df.appendChild(field);
+       field.name = "f_st_" + name;
+       field.value = color;
+       var button = doc.createElement("span");
+       button.className = "buttonColor";
+       df.appendChild(button);
+       var span = doc.createElement("span");
+       span.className = "chooser";
+       // span.innerHTML = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
+       span.style.backgroundColor = color;
+       button.appendChild(span);
+       button.onmouseover = function() { if (!this.disabled) { this.className += " buttonColor-hilite"; }};
+       button.onmouseout = function() { if (!this.disabled) { this.className = "buttonColor"; }};
+       span.onclick = function() {
+               if (this.parentNode.disabled) {
+                       return false;
+               }
+               editor._popupDialog("select_color.html", function(color) {
+                       if (color) {
+                               span.style.backgroundColor = "#" + color;
+                               field.value = "#" + color;
+                       }
+               }, color);
+       };
+       var span2 = doc.createElement("span");
+       span2.innerHTML = "&#x00d7;";
+       span2.className = "nocolor";
+       span2.title = TableOperations.I18N["Unset color"];
+       button.appendChild(span2);
+       span2.onmouseover = function() { if (!this.parentNode.disabled) { this.className += " nocolor-hilite"; }};
+       span2.onmouseout = function() { if (!this.parentNode.disabled) { this.className = "nocolor"; }};
+       span2.onclick = function() {
+               span.style.backgroundColor = "";
+               field.value = "";
+       };
+       return df;
+};
+
+TableOperations.createStyleLayoutFieldset = function(doc, editor, el) {
+       var i18n = TableOperations.I18N;
+       var fieldset = doc.createElement("fieldset");
+       var legend = doc.createElement("legend");
+       fieldset.appendChild(legend);
+       legend.innerHTML = i18n["Layout"];
+       var table = doc.createElement("table");
+       fieldset.appendChild(table);
+       table.style.width = "100%";
+       var tbody = doc.createElement("tbody");
+       table.appendChild(tbody);
+
+       var tagname = el.tagName.toLowerCase();
+       var tr, td, input, select, option, options, i;
+
+       if (tagname != "td" && tagname != "tr" && tagname != "th") {
+               tr = doc.createElement("tr");
+               tbody.appendChild(tr);
+               td = doc.createElement("td");
+               td.className = "label";
+               tr.appendChild(td);
+               td.innerHTML = i18n["Float"] + ":";
+               td = doc.createElement("td");
+               tr.appendChild(td);
+               select = doc.createElement("select");
+               td.appendChild(select);
+               select.name = "f_st_float";
+               options = ["None", "Left", "Right"];
+               for (var i = 0; i < options.length; ++i) {
+                       var Val = options[i];
+                       var val = options[i].toLowerCase();
+                       option = doc.createElement("option");
+                       option.innerHTML = i18n[Val];
+                       option.value = val;
+                       option.selected = (("" + el.style.cssFloat).toLowerCase() == val);
+                       select.appendChild(option);
+               }
+       }
+
+       tr = doc.createElement("tr");
+       tbody.appendChild(tr);
+       td = doc.createElement("td");
+       td.className = "label";
+       tr.appendChild(td);
+       td.innerHTML = i18n["Width"] + ":";
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       input = doc.createElement("input");
+       input.type = "text";
+       input.value = TableOperations.getLength(el.style.width);
+       input.size = "5";
+       input.name = "f_st_width";
+       input.style.marginRight = "0.5em";
+       td.appendChild(input);
+       select = doc.createElement("select");
+       select.name = "f_st_widthUnit";
+       option = doc.createElement("option");
+       option.innerHTML = i18n["percent"];
+       option.value = "%";
+       option.selected = /%/.test(el.style.width);
+       select.appendChild(option);
+       option = doc.createElement("option");
+       option.innerHTML = i18n["pixels"];
+       option.value = "px";
+       option.selected = /px/.test(el.style.width);
+       select.appendChild(option);
+       td.appendChild(select);
+
+       select.style.marginRight = "0.5em";
+       td.appendChild(doc.createTextNode(i18n["Text align"] + ":"));
+       select = doc.createElement("select");
+       select.style.marginLeft = select.style.marginRight = "0.5em";
+       td.appendChild(select);
+       select.name = "f_st_textAlign";
+       options = ["Left", "Center", "Right", "Justify"];
+       if (tagname == "td") {
+               options.push("Char");
+       }
+       input = doc.createElement("input");
+       input.name = "f_st_textAlignChar";
+       input.size = "1";
+       input.style.fontFamily = "monospace";
+       td.appendChild(input);
+       for (var i = 0; i < options.length; ++i) {
+               var Val = options[i];
+               var val = Val.toLowerCase();
+               option = doc.createElement("option");
+               option.value = val;
+               option.innerHTML = i18n[Val];
+               option.selected = (el.style.textAlign.toLowerCase() == val);
+               select.appendChild(option);
+       }
+       function setCharVisibility(value) {
+               input.style.visibility = value ? "visible" : "hidden";
+               if (value) {
+                       input.focus();
+                       input.select();
+               }
+       };
+       select.onchange = function() { setCharVisibility(this.value == "char"); };
+       setCharVisibility(select.value == "char");
+
+       tr = doc.createElement("tr");
+       tbody.appendChild(tr);
+       td = doc.createElement("td");
+       td.className = "label";
+       tr.appendChild(td);
+       td.innerHTML = i18n["Height"] + ":";
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       input = doc.createElement("input");
+       input.type = "text";
+       input.value = TableOperations.getLength(el.style.height);
+       input.size = "5";
+       input.name = "f_st_height";
+       input.style.marginRight = "0.5em";
+       td.appendChild(input);
+       select = doc.createElement("select");
+       select.name = "f_st_heightUnit";
+       option = doc.createElement("option");
+       option.innerHTML = i18n["percent"];
+       option.value = "%";
+       option.selected = /%/.test(el.style.height);
+       select.appendChild(option);
+       option = doc.createElement("option");
+       option.innerHTML = i18n["pixels"];
+       option.value = "px";
+       option.selected = /px/.test(el.style.height);
+       select.appendChild(option);
+       td.appendChild(select);
+
+       select.style.marginRight = "0.5em";
+       td.appendChild(doc.createTextNode(i18n["Vertical align"] + ":"));
+       select = doc.createElement("select");
+       select.name = "f_st_verticalAlign";
+       select.style.marginLeft = "0.5em";
+       td.appendChild(select);
+       options = ["Top", "Middle", "Bottom", "Baseline"];
+       for (var i = 0; i < options.length; ++i) {
+               var Val = options[i];
+               var val = Val.toLowerCase();
+               option = doc.createElement("option");
+               option.value = val;
+               option.innerHTML = i18n[Val];
+               option.selected = (el.style.verticalAlign.toLowerCase() == val);
+               select.appendChild(option);
+       }
+
+       return fieldset;
+};
+
+// Returns an HTML element containing the style attributes for the given
+// element.  This can be easily embedded into any dialog; the functionality is
+// also provided.
+TableOperations.createStyleFieldset = function(doc, editor, el) {
+       var i18n = TableOperations.I18N;
+       var fieldset = doc.createElement("fieldset");
+       var legend = doc.createElement("legend");
+       fieldset.appendChild(legend);
+       legend.innerHTML = i18n["CSS Style"];
+       var table = doc.createElement("table");
+       fieldset.appendChild(table);
+       table.style.width = "100%";
+       var tbody = doc.createElement("tbody");
+       table.appendChild(tbody);
+
+       var tr, td, input, select, option, options, i;
+
+       tr = doc.createElement("tr");
+       tbody.appendChild(tr);
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       td.className = "label";
+       td.innerHTML = i18n["Background"] + ":";
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       var df = TableOperations.createColorButton(doc, editor, el.style.backgroundColor, "backgroundColor");
+       df.firstChild.nextSibling.style.marginRight = "0.5em";
+       td.appendChild(df);
+       td.appendChild(doc.createTextNode(i18n["Image URL"] + ": "));
+       input = doc.createElement("input");
+       input.type = "text";
+       input.name = "f_st_backgroundImage";
+       if (el.style.backgroundImage.match(/url\(\s*(.*?)\s*\)/)) {
+               input.value = RegExp.$1;
+       }
+       // input.style.width = "100%";
+       td.appendChild(input);
+
+       tr = doc.createElement("tr");
+       tbody.appendChild(tr);
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       td.className = "label";
+       td.innerHTML = i18n["FG Color"] + ":";
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       td.appendChild(TableOperations.createColorButton(doc, editor, el.style.color, "color"));
+
+       // for better alignment we include an invisible field.
+       input = doc.createElement("input");
+       input.style.visibility = "hidden";
+       input.type = "text";
+       td.appendChild(input);
+
+       tr = doc.createElement("tr");
+       tbody.appendChild(tr);
+       td = doc.createElement("td");
+       tr.appendChild(td);
+       td.className = "label";
+       td.innerHTML = i18n["Border"] + ":";
+       td = doc.createElement("td");
+       tr.appendChild(td);
+
+       var colorButton = TableOperations.createColorButton(doc, editor, el.style.borderColor, "borderColor");
+       var btn = colorButton.firstChild.nextSibling;
+       td.appendChild(colorButton);
+       // borderFields.push(btn);
+       btn.style.marginRight = "0.5em";
+
+       select = doc.createElement("select");
+       var borderFields = [];
+       td.appendChild(select);
+       select.name = "f_st_borderStyle";
+       options = ["none", "dotted", "dashed", "solid", "double", "groove", "ridge", "inset", "outset"];
+       var currentBorderStyle = el.style.borderStyle;
+       // Gecko reports "solid solid solid solid" for "border-style: solid".
+       // That is, "top right bottom left" -- we only consider the first
+       // value.
+       (currentBorderStyle.match(/([^\s]*)\s/)) && (currentBorderStyle = RegExp.$1);
+       for (var i in options) {
+               var val = options[i];
+               option = doc.createElement("option");
+               option.value = val;
+               option.innerHTML = val;
+               (val == currentBorderStyle) && (option.selected = true);
+               select.appendChild(option);
+       }
+       select.style.marginRight = "0.5em";
+       function setBorderFieldsStatus(value) {
+               for (var i = 0; i < borderFields.length; ++i) {
+                       var el = borderFields[i];
+                       el.style.visibility = value ? "hidden" : "visible";
+                       if (!value && (el.tagName.toLowerCase() == "input")) {
+                               el.focus();
+                               el.select();
+                       }
+               }
+       };
+       select.onchange = function() { setBorderFieldsStatus(this.value == "none"); };
+
+       input = doc.createElement("input");
+       borderFields.push(input);
+       input.type = "text";
+       input.name = "f_st_borderWidth";
+       input.value = TableOperations.getLength(el.style.borderWidth);
+       input.size = "5";
+       td.appendChild(input);
+       input.style.marginRight = "0.5em";
+       var span = doc.createElement("span");
+       span.innerHTML = i18n["pixels"];
+       td.appendChild(span);
+       borderFields.push(span);
+
+       setBorderFieldsStatus(select.value == "none");
+
+       if (el.tagName.toLowerCase() == "table") {
+               // the border-collapse style is only for tables
+               tr = doc.createElement("tr");
+               tbody.appendChild(tr);
+               td = doc.createElement("td");
+               td.className = "label";
+               tr.appendChild(td);
+               input = doc.createElement("input");
+               input.type = "checkbox";
+               input.name = "f_st_borderCollapse";
+               input.id = "f_st_borderCollapse";
+               var val = (/collapse/i.test(el.style.borderCollapse));
+               input.checked = val ? 1 : 0;
+               td.appendChild(input);
+
+               td = doc.createElement("td");
+               tr.appendChild(td);
+               var label = doc.createElement("label");
+               label.htmlFor = "f_st_borderCollapse";
+               label.innerHTML = i18n["Collapsed borders"];
+               td.appendChild(label);
+       }
+
+//     tr = doc.createElement("tr");
+//     tbody.appendChild(tr);
+//     td = doc.createElement("td");
+//     td.className = "label";
+//     tr.appendChild(td);
+//     td.innerHTML = i18n["Margin"] + ":";
+//     td = doc.createElement("td");
+//     tr.appendChild(td);
+//     input = doc.createElement("input");
+//     input.type = "text";
+//     input.size = "5";
+//     input.name = "f_st_margin";
+//     td.appendChild(input);
+//     input.style.marginRight = "0.5em";
+//     td.appendChild(doc.createTextNode(i18n["Padding"] + ":"));
+
+//     input = doc.createElement("input");
+//     input.type = "text";
+//     input.size = "5";
+//     input.name = "f_st_padding";
+//     td.appendChild(input);
+//     input.style.marginLeft = "0.5em";
+//     input.style.marginRight = "0.5em";
+//     td.appendChild(doc.createTextNode(i18n["pixels"]));
+
+       return fieldset;
+};
+
+//// END GENERIC CODE -------------------------------------------------------
diff --git a/htmlarea/popupdiv.js b/htmlarea/popupdiv.js
new file mode 100644 (file)
index 0000000..c2f8d3b
--- /dev/null
@@ -0,0 +1,369 @@
+/** This file is derived from PopupDiv, developed by Mihai Bazon for
+ * SamWare.net.  Modifications were needed to make it usable in HTMLArea.
+ * HTMLArea is a free WYSIWYG online HTML editor from InteractiveTools.com.
+ *
+ * This file does not function standalone.  It is dependent of global functions
+ * defined in HTMLArea-3.0 (htmlarea.js).
+ *
+ * Please see file htmlarea.js for further details.
+ **/
+
+var is_ie = ( (navigator.userAgent.toLowerCase().indexOf("msie") != -1) &&
+             (navigator.userAgent.toLowerCase().indexOf("opera") == -1) );
+var is_compat = (document.compatMode == "BackCompat");
+
+function PopupDiv(editor, titleText, handler, initFunction) {
+       var self = this;
+
+       this.editor = editor;
+       this.doc = editor._mdoc;
+       this.handler = handler;
+
+       var el = this.doc.createElement("div");
+       el.className = "content";
+
+       var popup = this.doc.createElement("div");
+       popup.className = "dialog popupdiv";
+       this.element = popup;
+       var s = popup.style;
+       s.position = "absolute";
+       s.left = "0px";
+       s.top = "0px";
+
+       var title = this.doc.createElement("div");
+       title.className = "title";
+       this.title = title;
+       popup.appendChild(title);
+
+       HTMLArea._addEvent(title, "mousedown", function(ev) {
+               self._dragStart(is_ie ? window.event : ev);
+       });
+
+       var button = this.doc.createElement("div");
+       button.className = "button";
+       title.appendChild(button);
+       button.innerHTML = "&#x00d7;";
+       title.appendChild(this.doc.createTextNode(titleText));
+       this.titleText = titleText;
+
+       button.onmouseover = function() {
+               this.className += " button-hilite";
+       };
+       button.onmouseout = function() {
+               this.className = this.className.replace(/\s*button-hilite\s*/g, " ");
+       };
+       button.onclick = function() {
+               this.className = this.className.replace(/\s*button-hilite\s*/g, " ");
+               self.close();
+       };
+
+       popup.appendChild(el);
+       this.content = el;
+
+       this.doc.body.appendChild(popup);
+
+       this.dragging = false;
+       this.onShow = null;
+       this.onClose = null;
+       this.modal = false;
+
+       initFunction(this);
+};
+
+PopupDiv.currentPopup = null;
+
+PopupDiv.prototype.showAtElement = function(el, mode) {
+       this.defaultSize();
+       var pos, ew, eh;
+       var popup = this.element;
+       popup.style.display = "block";
+       var w = popup.offsetWidth;
+       var h = popup.offsetHeight;
+       popup.style.display = "none";
+       if (el != window) {
+               pos = PopupDiv.getAbsolutePos(el);
+               ew = el.offsetWidth;
+               eh = el.offsetHeight;
+       } else {
+               pos = {x:0, y:0};
+               var size = PopupDiv.getWindowSize();
+               ew = size.x;
+               eh = size.y;
+       }
+       var FX = false, FY = false;
+       if (mode.indexOf("l") != -1) {
+               pos.x -= w;
+               FX = true;
+       }
+       if (mode.indexOf("r") != -1) {
+               pos.x += ew;
+               FX = true;
+       }
+       if (mode.indexOf("t") != -1) {
+               pos.y -= h;
+               FY = true;
+       }
+       if (mode.indexOf("b") != -1) {
+               pos.y += eh;
+               FY = true;
+       }
+       if (mode.indexOf("c") != -1) {
+               FX || (pos.x += Math.round((ew - w) / 2));
+               FY || (pos.y += Math.round((eh - h) / 2));
+       }
+       this.showAt(pos.x, pos.y);
+};
+
+PopupDiv.prototype.defaultSize = function() {
+       var s = this.element.style;
+       var cs = this.element.currentStyle;
+       var addX = (is_ie && is_compat) ? (parseInt(cs.borderLeftWidth) +
+                                          parseInt(cs.borderRightWidth) +
+                                          parseInt(cs.paddingLeft) +
+                                          parseInt(cs.paddingRight)) : 0;
+       var addY = (is_ie && is_compat) ? (parseInt(cs.borderTopWidth) +
+                                          parseInt(cs.borderBottomWidth) +
+                                          parseInt(cs.paddingTop) +
+                                          parseInt(cs.paddingBottom)) : 0;
+       s.display = "block";
+       s.width = (this.content.offsetWidth + addX) + "px";
+       s.height = (this.content.offsetHeight + this.title.offsetHeight) + "px";
+       s.display = "none";
+};
+
+PopupDiv.prototype.showAt = function(x, y) {
+       this.defaultSize();
+       var s = this.element.style;
+       s.display = "block";
+       s.left = x + "px";
+       s.top = y + "px";
+       this.hideShowCovered();
+
+       PopupDiv.currentPopup = this;
+       HTMLArea._addEvents(this.doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
+       HTMLArea._addEvents(this.editor._doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
+       if (is_ie && this.modal) {
+               this.doc.body.setCapture(false);
+               this.doc.body.onlosecapture = function() {
+                       (PopupDiv.currentPopup) && (this.doc.body.setCapture(false));
+               };
+       }
+       window.event && HTMLArea._stopEvent(window.event);
+
+       if (typeof this.onShow == "function") {
+               this.onShow();
+       } else if (typeof this.onShow == "string") {
+               eval(this.onShow);
+       }
+
+       var field = this.element.getElementsByTagName("input")[0];
+       if (!field) {
+               field = this.element.getElementsByTagName("select")[0];
+       }
+       if (!field) {
+               field = this.element.getElementsByTagName("textarea")[0];
+       }
+       if (field) {
+               field.focus();
+       }
+};
+
+PopupDiv.prototype.close = function() {
+       this.element.style.display = "none";
+       PopupDiv.currentPopup = null;
+       this.hideShowCovered();
+       HTMLArea._removeEvents(this.doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
+       HTMLArea._removeEvents(this.editor._doc.body, ["mousedown", "click"], PopupDiv.checkPopup);
+       is_ie && this.modal && this.doc.body.releaseCapture();
+       if (typeof this.onClose == "function") {
+               this.onClose();
+       } else if (typeof this.onClose == "string") {
+               eval(this.onClose);
+       }
+       this.element.parentNode.removeChild(this.element);
+};
+
+PopupDiv.prototype.getForm = function() {
+       var forms = this.content.getElementsByTagName("form");
+       return (forms.length > 0) ? forms[0] : null;
+};
+
+PopupDiv.prototype.callHandler = function() {
+       var tags = ["input", "textarea", "select"];
+       var params = new Object();
+       for (var ti = tags.length; --ti >= 0;) {
+               var tag = tags[ti];
+               var els = this.content.getElementsByTagName(tag);
+               for (var j = 0; j < els.length; ++j) {
+                       var el = els[j];
+                       params[el.name] = el.value;
+               }
+       }
+       this.handler(this, params);
+       return false;
+};
+
+PopupDiv.getAbsolutePos = function(el) {
+       var r = { x: el.offsetLeft, y: el.offsetTop };
+       if (el.offsetParent) {
+               var tmp = PopupDiv.getAbsolutePos(el.offsetParent);
+               r.x += tmp.x;
+               r.y += tmp.y;
+       }
+       return r;
+};
+
+PopupDiv.getWindowSize = function() {
+       if (window.innerHeight) {
+               return { y: window.innerHeight, x: window.innerWidth };
+       }
+       if (this.doc.body.clientHeight) {
+               return { y: this.doc.body.clientHeight, x: this.doc.body.clientWidth };
+       }
+       return { y: this.doc.documentElement.clientHeight, x: this.doc.documentElement.clientWidth };
+};
+
+PopupDiv.prototype.hideShowCovered = function () {
+       var self = this;
+       function isContained(el) {
+               while (el) {
+                       if (el == self.element) {
+                               return true;
+                       }
+                       el = el.parentNode;
+               }
+               return false;
+       };
+       var tags = new Array("applet", "select");
+       var el = this.element;
+
+       var p = PopupDiv.getAbsolutePos(el);
+       var EX1 = p.x;
+       var EX2 = el.offsetWidth + EX1;
+       var EY1 = p.y;
+       var EY2 = el.offsetHeight + EY1;
+
+       if (el.style.display == "none") {
+               EX1 = EX2 = EY1 = EY2 = 0;
+       }
+
+       for (var k = tags.length; k > 0; ) {
+               var ar = this.doc.getElementsByTagName(tags[--k]);
+               var cc = null;
+
+               for (var i = ar.length; i > 0;) {
+                       cc = ar[--i];
+                       if (isContained(cc)) {
+                               cc.style.visibility = "visible";
+                               continue;
+                       }
+
+                       p = PopupDiv.getAbsolutePos(cc);
+                       var CX1 = p.x;
+                       var CX2 = cc.offsetWidth + CX1;
+                       var CY1 = p.y;
+                       var CY2 = cc.offsetHeight + CY1;
+
+                       if ((CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) {
+                               cc.style.visibility = "visible";
+                       } else {
+                               cc.style.visibility = "hidden";
+                       }
+               }
+       }
+};
+
+PopupDiv.prototype._dragStart = function (ev) {
+       if (this.dragging) {
+               return false;
+       }
+       this.dragging = true;
+       PopupDiv.currentPopup = this;
+       var posX = ev.clientX;
+       var posY = ev.clientY;
+       if (is_ie) {
+               posY += this.doc.body.scrollTop;
+               posX += this.doc.body.scrollLeft;
+       } else {
+               posY += window.scrollY;
+               posX += window.scrollX;
+       }
+       var st = this.element.style;
+       this.xOffs = posX - parseInt(st.left);
+       this.yOffs = posY - parseInt(st.top);
+       HTMLArea._addEvent(this.doc, "mousemove", PopupDiv.dragIt);
+       HTMLArea._addEvent(this.doc, "mouseover", HTMLArea._stopEvent);
+       HTMLArea._addEvent(this.doc, "mouseup", PopupDiv.dragEnd);
+       HTMLArea._stopEvent(ev);
+};
+
+PopupDiv.dragIt = function (ev) {
+       var popup = PopupDiv.currentPopup;
+       if (!(popup && popup.dragging)) {
+               return false;
+       }
+       is_ie && (ev = window.event);
+       var posX = ev.clientX;
+       var posY = ev.clientY;
+       if (is_ie) {
+               posY += this.doc.body.scrollTop;
+               posX += this.doc.body.scrollLeft;
+       } else {
+               posY += window.scrollY;
+               posX += window.scrollX;
+       }
+       popup.hideShowCovered();
+       var st = popup.element.style;
+       st.left = (posX - popup.xOffs) + "px";
+       st.top = (posY - popup.yOffs) + "px";
+       HTMLArea._stopEvent(ev);
+};
+
+PopupDiv.dragEnd = function () {
+       var popup = PopupDiv.currentPopup;
+       if (!popup) {
+               return false;
+       }
+       popup.dragging = false;
+       HTMLArea._removeEvent(popup.doc, "mouseup", PopupDiv.dragEnd);
+       HTMLArea._removeEvent(popup.doc, "mouseover", HTMLArea._stopEvent);
+       HTMLArea._removeEvent(popup.doc, "mousemove", PopupDiv.dragIt);
+       popup.hideShowCovered();
+};
+
+PopupDiv.checkPopup = function (ev) {
+       is_ie && (ev = window.event);
+       var el = is_ie ? ev.srcElement : ev.target;
+       var cp = PopupDiv.currentPopup;
+       for (; (el != null) && (el != cp.element); el = el.parentNode);
+       if (el == null) {
+               cp.modal || ev.type == "mouseover" || cp.close();
+               HTMLArea._stopEvent(ev);
+       }
+};
+
+PopupDiv.prototype.addButtons = function() {
+       var self = this;
+       var div = this.doc.createElement("div");
+       this.content.appendChild(div);
+       div.className = "buttons";
+       for (var i = 0; i < arguments.length; ++i) {
+               var btn = arguments[i];
+               var button = this.doc.createElement("button");
+               div.appendChild(button);
+               button.innerHTML = HTMLArea.I18N.buttons[btn];
+               switch (btn) {
+                   case "ok":
+                       button.onclick = function() {
+                               self.callHandler();
+                               self.close();
+                       };
+                       break;
+                   case "cancel":
+                       button.onclick = function() {
+                               self.close();
+                       };
+                       break;
+               }
+       }
+};
diff --git a/htmlarea/popups/about.html b/htmlarea/popups/about.html
new file mode 100644 (file)
index 0000000..ee70b6f
--- /dev/null
@@ -0,0 +1,392 @@
+<!--
+
+(c) dynarch.com, 2003-2004
+Author: Mihai Bazon, http://dynarch.com/mishoo
+Distributed as part of HTMLArea 3.0
+
+"You are not expected to understand this...  I don't neither."
+
+                      (from The Linux Kernel Source Code,
+                            ./arch/x86_64/ia32/ptrace.c:90)
+
+;-)
+
+-->
+
+<html style="height: 100%">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>About HTMLArea</title>
+<script type="text/javascript" src="popup.js"></script>
+<script type="text/javascript">
+window.resizeTo(450, 250);
+var TABS = [];
+var CURRENT_TAB = 0;
+var CONTENT_HEIGHT_DIFF = 0;
+var CONTENT_WIDTH_DIFF = 0;
+function selectTab(idx) {
+  var ct = TABS[CURRENT_TAB];
+  ct.className = ct.className.replace(/\s*tab-current\s*/, ' ');
+  ct = TABS[CURRENT_TAB = idx];
+  ct.className += ' tab-current';
+  for (var i = TABS.length; --i >= 0;) {
+    var area = document.getElementById("tab-area-" + i);
+    if (CURRENT_TAB == i) {
+      area.style.display = "block";
+    } else {
+      area.style.display = "none";
+    }
+  }
+  document.body.style.visibility = "hidden";
+  document.body.style.visibility = "visible";
+  document.cookie = "HTMLAREA-ABOUT-TAB=" + idx;
+}
+var editor = null;
+function initDocument() {
+  editor = window.dialogArguments;
+  HTMLArea = window.opener.HTMLArea;
+
+  var plugins = document.getElementById("plugins");
+  var j = 0;
+  var html = "<table width='99%' cellpadding='0' style='margin-top: 1em; collapse-borders: collapse; border: 1px solid #8b8;'>" +
+         "<thead><tr>" +
+         "<td>Name</td>" +
+         "<td>Developer</td>" +
+         "<td>Sponsored by</td>" +
+         "<td>License<sup>*</sup></td>" +
+         "</tr></thead><tbody>";
+  for (var i in editor.plugins) {
+    var info = editor.plugins[i];
+    html += "<tr><td>" + info.name + " v" + info.version + "</td>" + 
+            "<td><a href='" + info.developer_url + "' target='_blank' title='Visit developer website'>" +
+           info.developer + "</a></td>" +
+           "<td><a href='" + info.sponsor_url + "' target='_blank' title='Visit sponsor website'>" +
+           info.sponsor + "</a></td>" +
+           "<td>" + info.license + "</td></tr>";
+    ++j;
+  }
+
+  if (j) {
+          html += "</tbody></table>" +
+                 "<p><sup>*</sup> License \"htmlArea\" means that the plugin is distributed under the same terms " +
+                 "as HTMLArea itself.  Such plugins are likely to be those included in the official " +
+                 "HTMLArea distribution</p>";
+         plugins.innerHTML = "<p>The following plugins have been loaded.</p>" + html;
+  } else {
+         plugins.innerHTML = "<p>No plugins have been loaded</p>";
+  }
+
+  plugins.innerHTML += "<p>User agent reports:<br/>" + navigator.userAgent + "</p>";
+
+  var content = document.getElementById("content");
+  if (window.innerHeight) {
+    CONTENT_HEIGHT_DIFF = window.innerHeight - 250;
+    CONTENT_WIDTH_DIFF = window.innerWidth - content.offsetWidth;
+  } else {
+    CONTENT_HEIGHT_DIFF = document.body.offsetHeight - 250;
+    CONTENT_WIDTH_DIFF = document.body.offsetWidth - 400;
+  }
+  window.onresize();
+  var bar = document.getElementById("tabbar");
+  j = 0;
+  for (var i = bar.firstChild; i; i = i.nextSibling) {
+    TABS.push(i);
+    i.__msh_tab = j;
+    i.onmousedown = function(ev) { selectTab(this.__msh_tab); HTMLArea._stopEvent(ev || window.event); };
+    var area = document.getElementById("tab-area-" + j);
+    if (/tab-current/.test(i.className)) {
+      CURRENT_TAB = j;
+      area.style.display = "block";
+    } else {
+      area.style.display = "none";
+    }
+    ++j;
+  }
+  if (document.cookie.match(/HTMLAREA-ABOUT-TAB=([0-9]+)/))
+    selectTab(RegExp.$1);
+}
+window.onresize = function() {
+  var content = document.getElementById("content");
+  if (window.innerHeight) {
+    content.style.height = (window.innerHeight - CONTENT_HEIGHT_DIFF) + "px";
+    content.style.width = (window.innerWidth - CONTENT_WIDTH_DIFF) + "px";
+  } else {
+    content.style.height = (document.body.offsetHeight - CONTENT_HEIGHT_DIFF) + "px";
+    //content.style.width = (document.body.offsetWidth - CONTENT_WIDTH_DIFF) + "px";
+  }
+}
+</script>
+<style>
+  html,body,textarea,table { font-family: tahoma,verdana,arial; font-size: 11px;
+padding: 0px; margin: 0px; }
+  tt { font-size: 120%; }
+  body { padding: 0px; background: #cea; color: 000; }
+  a:link, a:visited { color: #00f; }
+  a:hover { color: #f00; }
+  a:active { color: #f80; }
+  button { font: 11px tahoma,verdana,sans-serif; background-color: #cea;
+      border-width: 1px; }
+
+  p { margin: 0.5em 0px; }
+
+  h1 { font: bold 130% georgia,"times new roman",serif; margin: 0px; border-bottom: 1px solid #6a6; }
+  h2 { font: bold 110% georgia,"times new roman",serif; margin: 0.7em 0px; }
+
+  thead {
+    font-weight: bold;
+    background-color: #dfb;
+  }
+
+  .logo, .logo-hover {
+    white-space: nowrap;
+    background-color: #8f4; color: #040; padding: 3px; border-bottom: 1px solid #555;
+    height: 5em;
+  }
+  .logo .brand, .logo-hover .brand {
+    margin-left: 0.5em; margin-right: 0.5em; padding-bottom: 0.1em;
+    font-family: impact,'arial black',arial,sans-serif; font-size: 28px;
+    border-bottom: 1px solid #595; text-align: center;
+    cursor: pointer;
+  }
+  .logo-hover {
+    background-color: #fff;
+  }
+  .logo-hover .brand {
+    color: #800;
+    border-color: #04f;
+  }
+  .logo .letter, .logo-hover .letter { position: relative; font-family: monospace; }
+  .logo .letter1 { top: 0.1em; }
+  .logo .letter2 { top: 0.05em; }
+  .logo .letter3 { top: -0.05em; }
+  .logo .letter4 { top: -0.1em; }
+
+  .logo-hover .letter1 { top: -0.1em; }
+  .logo-hover .letter2 { top: -0.05em; }
+  .logo-hover .letter3 { top: 0.05em; }
+  .logo-hover .letter4 { top: 0.1em; }
+  .logo .version, .logo-hover .version { font-family: georgia,"times new roman",serif; }
+  .logo .release {
+    font-size: 90%; margin-bottom: 1em;
+    text-align: center; color: #484;
+  }
+  .logo .visit { display: none; }
+  .logo-hover .release { display: none; }
+  .logo-hover .visit {
+    font-size: 90%; margin-bottom: 1em;
+    text-align: center; color: #448;
+  }
+  .buttons {
+    text-align: right; padding: 3px; background-color: #8f4;
+    border-top: 1px solid #555;
+  }
+  #tabbar {
+    position: relative;
+    left: 10px;
+  }
+  .tab {
+    color: #454;
+    cursor: pointer;
+    margin-left: -5px;
+    float: left; position: relative;
+    border: 1px solid #555;
+    top: -3px; left: -2px;
+    padding: 2px 10px 3px 10px;
+    border-top: none; background-color: #9b7;
+    -moz-border-radius: 0px 0px 4px 4px;
+    z-index: 0;
+  }
+  .tab-current {
+    color: #000;
+    top: -4px;
+    background-color: #cea;
+    padding: 3px 10px 4px 10px;
+    z-index: 10;
+  }
+  table.sponsors { border-top: 1px solid #aca; }
+  table.sponsors td {
+    border-bottom: 1px solid #aca; vertical-align: top;
+  }
+  table.sponsors tr td { padding: 2px 0px; }
+  table.sponsors tr td.sponsor { text-align: right; padding-right: 0.3em; white-space: nowrap; }
+  li, ol, ul { margin-top: 0px; margin-bottom: 0px; }
+</style></head>
+<body onload="__dlg_init(); initDocument();"
+><table cellspacing="0" cellpadding="0" style="border-collapse: collapse;
+      width: 100%; height: 100%;">
+
+<tr style="height: 1em"><td id="tdheader">
+
+<div class="logo">
+<div class="brand"
+onmouseover="this.parentNode.className='logo-hover';"
+onmouseout="this.parentNode.className='logo';"
+onclick="window.open('http://dynarch.com/htmlarea/');">
+<span class="letter letter1">&lt;H</span><span
+class="letter letter2">T</span><span
+class="letter letter3">M</span><span
+class="letter letter4">L</span>Area <span class="letter">/&gt;</span>
+<span class="version"><% $version.$release %></span></div>
+<div class="release">Compiled on <% $time %></div>
+<div class="visit">Go to http://dynarch.com/htmlarea/ [latest milestone release]</div>
+</div>
+
+</td></tr>
+<tr><td id="tdcontent" style="padding: 0.5em;">
+
+<div style="overflow: auto; height: 250px;" id="content">
+<div id="tab-areas">
+
+<div id="tab-area-0">
+
+  <h1>HTMLArea</h1>
+  
+  <p>A free WYSIWYG editor replacement for <tt>&lt;textarea&gt;</tt> fields.<br />
+  For Mozilla 1.3+ (any platform) or Internet Explorer 5.5+ (Windows).
+  </p>
+
+  <p style="text-align: center"
+  >&copy; 2002-2004 <a href="http://interactivetools.com" target="_blank">interactivetools.com</a>, inc.<br />
+  &copy; 2003-2004 <a href="http://dynarch.com" target="_blank">dynarch.com</a> LLC.<br />
+  All Rights Reserved.</p>
+
+  <h2>Project resources</h2>
+
+  <ul>
+  <li><a href="http://sourceforge.net/projects/itools-htmlarea/" target="_blank"
+  >Project page</a> (@ sourceforge.net)</li>
+  <li><a href="http://sourceforge.net/cvs/?group_id=69750" target="_blank"
+  >Anonymous CVS access</a> (@ sourceforge.net)</li>
+  <li><a href="http://sourceforge.net/tracker/?atid=525656&group_id=69750&func=browse" target="_blank"
+  >Bug system</a> (@ sourceforge.net)</li>
+  <li><a href="http://www.interactivetools.com/forum/gforum.cgi?forum=14;" target="_blank"
+  >Forum</a> (@ interactivetools.com)</li>
+  <li><a href="http://www.dynarch.com/htmlarea/" target="_blank"
+  >Last public release</a> (@ dynarch.com)</li>
+  </ul>
+
+  <p>
+  For download section please see the <a href="http://sourceforge.net/projects/itools-htmlarea/" target="_blank"
+  >project page @ SourceForge</a>.
+  </p>
+
+<p style="margin-top: 1em; text-align: center;">Version 3.0 developed and maintained by <a
+href="http://dynarch.com/mishoo/" title="http://dynarch.com/mishoo/" target="_blank">Mihai Bazon</a> / <a
+href="http://dynarch.com" title="http://dynarch.com/" target="_blank">dynarch.com</a></p>
+
+</div>
+
+<div id="tab-area-1">
+<h1>Thank you</h1>
+
+  <p>
+  <a href="http://dynarch.com" target="_blank">dynarch.com</a> would like to thank the following
+  companies/persons for their <em>donations</em> to support development of HTMLArea (listed alphabetically):
+  </p>
+
+  <ul>
+    <li><a href="http://www.computerlove.co.uk" target="_blank">Code Computer Love Ltd.</a> (UK)</li>
+    <li><a href="http://www.neomedia.ro" target="_blank">Neomedia</a> (Romania)</li>
+    <li><a href="http://www.os3.it" target="_blank">OS3</a> (Italy)</li>
+    <li><a href="http://www.softwerk.net" target="_blank">SoftWerk</a> (Italy)</li>
+  </ul>
+
+  <p>Also many thanks to all people at InteractiveTools.com
+  <a href="http://www.interactivetools.com/forum/gforum.cgi?forum=14;">HTMLArea forums</a> for
+  contributing translations, feedback, bug reports and fixes.</p>
+
+  <p>
+  Last but not least, this project wouldn't have existed without
+  <a href="http://interactivetools.com" target="_blank">InteractiveTools.com</a>.
+  </p>
+
+</div>
+
+<div id="tab-area-2">
+<h1>htmlArea License (based on BSD license)</h1>
+
+<p style="text-align: center">© 2002-2004, interactivetools.com, inc.<br />
+  © 2003-2004 dynarch.com LLC<br />
+  All rights reserved.</p>
+
+<p>
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+</p>
+
+<ol>
+<li>
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+</li>
+
+<li>
+Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+</li>
+
+<li>
+Neither the name of interactivetools.com, inc. nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+</li>
+</ol>
+
+<p>
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+</p>
+
+</div>
+
+<div id="tab-area-3">
+<h1>Plugins</h1>
+<div id="plugins">
+</div>
+</div>
+
+</div></div>
+
+
+</tr></td>
+<tr style="height: 1em"><td id="tdfooter">
+
+
+<div class="buttons">
+<div id="tabbar"
+><div class="tab tab-current"
+>About</div><div class="tab"
+>Thanks</div><div class="tab"
+>License</div><div class="tab"
+>Plugins</div></div>
+<button type="button" onclick="__dlg_close(null);">I agree it's cool</button>
+</div>
+
+</td></tr></table>
+
+</body></html>
+
+<%ARGS>
+  $version => '3.0'
+  $release => 'beta+'
+  $basename => 'HTMLArea-3.0-beta'
+</%ARGS>
+
+<%INIT>;
+if ($release =~ /\S/) {
+    $release = ' <span style="position: relative; top: -0.6em; font-size: 50%; font-weight: normal">[ rev. '.$release.' ]</span>';
+}
+
+use POSIX qw(strftime);
+my $time = strftime '%b %e, %Y %H:%M GMT', gmtime;
+</%INIT>
diff --git a/htmlarea/popups/blank.html b/htmlarea/popups/blank.html
new file mode 100644 (file)
index 0000000..5b1b16d
--- /dev/null
@@ -0,0 +1,2 @@
+<html>\r
+</html>
\ No newline at end of file
diff --git a/htmlarea/popups/custom2.html b/htmlarea/popups/custom2.html
new file mode 100644 (file)
index 0000000..04314a0
--- /dev/null
@@ -0,0 +1,35 @@
+<html style="width:300px; Height: 60px;">\r
+ <head>\r
+  <title>Select Phrase</title>\r
+<script language="javascript">\r
+\r
+var myTitle = window.dialogArguments;\r
+document.title = myTitle;\r
+\r
+\r
+function returnSelected() {\r
+  var idx  = document.all.textPulldown.selectedIndex;\r
+  var text = document.all.textPulldown[idx].text;\r
+\r
+  window.returnValue = text;          // set return value\r
+  window.close();                     // close dialog\r
+}\r
+\r
+</script>\r
+</head>\r
+<body bgcolor="#FFFFFF" topmargin=15 leftmargin=0>\r
+\r
+<form method=get onSubmit="Set(document.all.ColorHex.value); return false;">\r
+<div align=center>\r
+\r
+<select name="textPulldown">\r
+<option>The quick brown</option>\r
+<option>fox jumps over</option>\r
+<option>the lazy dog.</option>\r
+</select>\r
+\r
+<input type="button" value=" Go " onClick="returnSelected()">\r
+\r
+</div>\r
+</form>\r
+</body></html>
\ No newline at end of file
diff --git a/htmlarea/popups/editor_help.html b/htmlarea/popups/editor_help.html
new file mode 100644 (file)
index 0000000..b455369
--- /dev/null
@@ -0,0 +1,16 @@
+<html>\r
+ <head>\r
+  <title>Editor Help</title>\r
+  <style>\r
+    body, td, p, div { font-family: arial; font-size: x-small; }\r
+  </style>\r
+ </head>\r
+<body>\r
+\r
+<h2>Editor Help<hr></h2>\r
+\r
+Todo...\r
+\r
+\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/htmlarea/popups/fullscreen.html b/htmlarea/popups/fullscreen.html
new file mode 100644 (file)
index 0000000..a4b7fff
--- /dev/null
@@ -0,0 +1,139 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html>\r
+  <head>\r
+    <title>Fullscreen HTMLArea</title>\r
+    <script type="text/javascript">\r
+      _editor_url = window.opener._editor_url || '../';\r
+      _editor_lang = window.opener._editor_lang;\r
+      _editor_css = window.opener._editor_css;\r
+      var BASE = window.opener.document.baseURI || window.opener.document.URL;\r
+      var head = document.getElementsByTagName("head")[0];\r
+      var base = document.createElement("base");\r
+      base.href = BASE;\r
+      head.appendChild(base);\r
+    </script>\r
+\r
+    <script type="text/javascript">\r
+        document.write('<scr' + 'ipt type="text/javascript" src="' + _editor_url + 'htmlarea.js"></scr' + 'ipt>');\r
+    </script>\r
+    <script type="text/javascript">\r
+       // load HTMLArea scripts that are present in the opener frame\r
+       var scripts = window.opener.HTMLArea._scripts;\r
+       for (var i = 3; i < scripts.length; ++i) {\r
+           //document.write("<scr" + "ipt type='text/javascript' src='" + scripts[i] + "'></scr" + "ipt>");\r
+           HTMLArea.loadScript(scripts[i]);\r
+        }\r
+    </script>\r
+\r
+    <!-- browser takes a coffee break here -->\r
+    <script type="text/javascript">\r
+var parent_object  = null;\r
+var editor        = null;      // to be initialized later [ function init() ]\r
+\r
+/* ---------------------------------------------------------------------- *\\r
+   Function    : \r
+   Description : \r
+\* ---------------------------------------------------------------------- */\r
+\r
+function _CloseOnEsc(ev) {\r
+       ev || (ev = window.event) || (ev = editor._iframe.contentWindow.event);\r
+       if (ev.keyCode == 27) {\r
+               // update_parent();\r
+               window.close();\r
+               return;\r
+       }\r
+}\r
+\r
+/* ---------------------------------------------------------------------- *\\r
+   Function    : resize_editor\r
+   Description : resize the editor when the user resizes the popup\r
+\* ---------------------------------------------------------------------- */\r
+\r
+function resize_editor() {  // resize editor to fix window\r
+       var newHeight;\r
+       if (document.all) {\r
+               // IE\r
+               newHeight = document.body.offsetHeight - editor._toolbar.offsetHeight;\r
+               if (newHeight < 0) { newHeight = 0; }\r
+       } else {\r
+               // Gecko\r
+               newHeight = window.innerHeight - editor._toolbar.offsetHeight;\r
+       }\r
+       if (editor.config.statusBar) {\r
+               newHeight -= editor._statusBar.offsetHeight;\r
+       }\r
+       editor._textArea.style.height = editor._iframe.style.height = newHeight - (HTMLArea.is_gecko ? 8 : 0) + "px";\r
+}\r
+\r
+/* ---------------------------------------------------------------------- *\\r
+   Function    : init\r
+   Description : run this code on page load\r
+\* ---------------------------------------------------------------------- */\r
+\r
+function init() {\r
+       parent_object      = opener.HTMLArea._object;\r
+       var config         = HTMLArea.cloneObject( parent_object.config );\r
+       config.width       = "100%";\r
+       config.height      = "auto";\r
+\r
+       // change maximize button to minimize button\r
+       config.btnList["popupeditor"] = [ 'Minimize Editor', _editor_url + 'images/fullscreen_minimize.gif', true,\r
+                                         function() { window.close(); } ];\r
+\r
+       // generate editor and resize it\r
+       editor = new HTMLArea("editor", config);\r
+\r
+       // register the plugins, if any\r
+       for (var i in parent_object.plugins) {\r
+               var plugin = parent_object.plugins[i];\r
+               try {\r
+                       eval(plugin.name);\r
+                       editor.registerPlugin2(plugin.name, plugin.args);\r
+               } catch(e) {};\r
+       }\r
+       // and restore the original toolbar\r
+        config.toolbar = parent_object.config.toolbar;\r
+       editor.generate();\r
+       editor._iframe.style.width = "100%";\r
+       editor._textArea.style.width = "100%";\r
+       resize_editor();\r
+\r
+       editor.doctype = parent_object.doctype;\r
+\r
+       // set child window contents and event handlers, after a small delay\r
+       setTimeout(function() {\r
+                          editor.setHTML(parent_object.getInnerHTML());\r
+\r
+                          // switch mode if needed\r
+                          if (parent_object._mode == "textmode") { editor.setMode("textmode"); }\r
+\r
+                          // continuously update parent editor window\r
+                          setInterval(update_parent, 500);\r
+\r
+                          // setup event handlers\r
+                          document.body.onkeypress = _CloseOnEsc;\r
+                          editor._doc.body.onkeypress = _CloseOnEsc;\r
+                          editor._textArea.onkeypress = _CloseOnEsc;\r
+                          window.onresize = resize_editor;\r
+                  }, 333);                      // give it some time to meet the new frame\r
+}\r
+\r
+/* ---------------------------------------------------------------------- *\\r
+   Function    : update_parent\r
+   Description : update parent window editor field with contents from child window\r
+   \* ---------------------------------------------------------------------- */\r
+\r
+function update_parent() {\r
+       // use the fast version\r
+       parent_object.setHTML(editor.getInnerHTML());\r
+}\r
+\r
+    </script>\r
+    <style type="text/css"> html, body { height: 100%; margin: 0px; border: 0px; background-color: buttonface; } </style>\r
+  </head>\r
+  <body scroll="no" onload="HTMLArea.onload = init; HTMLArea.init();" onunload="update_parent()">\r
+    <form style="margin: 0px; border: 1px solid; border-color: threedshadow threedhighlight threedhighlight threedshadow;">\r
+      <textarea name="editor" id="editor" style="width:100%; height:300px">&nbsp;</textarea>\r
+    </form>\r
+  </body>\r
+</html>\r
diff --git a/htmlarea/popups/insert_image.html b/htmlarea/popups/insert_image.html
new file mode 100644 (file)
index 0000000..4b9eb75
--- /dev/null
@@ -0,0 +1,191 @@
+<html>\r
+\r
+<head>\r
+  <title>Insert Image</title>\r
+\r
+<script type="text/javascript" src="popup.js"></script>\r
+\r
+<script type="text/javascript">\r
+\r
+window.resizeTo(400, 100);\r
+\r
+function Init() {\r
+  __dlg_init();\r
+  var param = window.dialogArguments;\r
+  if (param) {\r
+      document.getElementById("f_url").value = param["f_url"];\r
+      document.getElementById("f_alt").value = param["f_alt"];\r
+      document.getElementById("f_border").value = param["f_border"];\r
+      document.getElementById("f_align").value = param["f_align"];\r
+      document.getElementById("f_vert").value = param["f_vert"];\r
+      document.getElementById("f_horiz").value = param["f_horiz"];\r
+      window.ipreview.location.replace(param.f_url);\r
+  }\r
+  document.getElementById("f_url").focus();\r
+};\r
+\r
+function onOK() {\r
+  var required = {\r
+    "f_url": "You must enter the URL"\r
+  };\r
+  for (var i in required) {\r
+    var el = document.getElementById(i);\r
+    if (!el.value) {\r
+      alert(required[i]);\r
+      el.focus();\r
+      return false;\r
+    }\r
+  }\r
+  // pass data back to the calling window\r
+  var fields = ["f_url", "f_alt", "f_align", "f_border",\r
+                "f_horiz", "f_vert"];\r
+  var param = new Object();\r
+  for (var i in fields) {\r
+    var id = fields[i];\r
+    var el = document.getElementById(id);\r
+    param[id] = el.value;\r
+  }\r
+  __dlg_close(param);\r
+  return false;\r
+};\r
+\r
+function onCancel() {\r
+  __dlg_close(null);\r
+  return false;\r
+};\r
+\r
+function onPreview() {\r
+  var f_url = document.getElementById("f_url");\r
+  var url = f_url.value;\r
+  if (!url) {\r
+    alert("You have to enter an URL first");\r
+    f_url.focus();\r
+    return false;\r
+  }\r
+  window.ipreview.location.replace(url);\r
+  return false;\r
+};\r
+</script>\r
+\r
+<style type="text/css">\r
+html, body {\r
+  background: ButtonFace;\r
+  color: ButtonText;\r
+  font: 11px Tahoma,Verdana,sans-serif;\r
+  margin: 0px;\r
+  padding: 0px;\r
+}\r
+body { padding: 5px; }\r
+table {\r
+  font: 11px Tahoma,Verdana,sans-serif;\r
+}\r
+form p {\r
+  margin-top: 5px;\r
+  margin-bottom: 5px;\r
+}\r
+.fl { width: 9em; float: left; padding: 2px 5px; text-align: right; }\r
+.fr { width: 6em; float: left; padding: 2px 5px; text-align: right; }\r
+fieldset { padding: 0px 10px 5px 5px; }\r
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }\r
+button { width: 70px; }\r
+.space { padding: 2px; }\r
+\r
+.title { background: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px;\r
+border-bottom: 1px solid black; letter-spacing: 2px;\r
+}\r
+form { padding: 0px; margin: 0px; }\r
+</style>\r
+\r
+</head>\r
+\r
+<body onload="Init()">\r
+\r
+<div class="title">Insert Image</div>\r
+<!--- new stuff --->\r
+<form action="" method="get">\r
+<table border="0" width="100%" style="padding: 0px; margin: 0px">\r
+  <tbody>\r
+\r
+  <tr>\r
+    <td style="width: 7em; text-align: right">Image URL:</td>\r
+    <td><input type="text" name="url" id="f_url" style="width:75%"\r
+      title="Enter the image URL here" />\r
+      <button name="preview" onclick="return onPreview();"\r
+      title="Preview the image in a new window">Preview</button>\r
+    </td>\r
+  </tr>\r
+  <tr>\r
+    <td style="width: 7em; text-align: right">Alternate text:</td>\r
+    <td><input type="text" name="alt" id="f_alt" style="width:100%"\r
+      title="For browsers that don't support images" /></td>\r
+  </tr>\r
+\r
+  </tbody>\r
+</table>\r
+\r
+<p />\r
+\r
+<fieldset style="float: left; margin-left: 5px;">\r
+<legend>Layout</legend>\r
+\r
+<div class="space"></div>\r
+\r
+<div class="fl">Alignment:</div>\r
+<select size="1" name="align" id="f_align"\r
+  title="Positioning of this image">\r
+  <option value=""                             >Not set</option>\r
+  <option value="left"                         >Left</option>\r
+  <option value="right"                        >Right</option>\r
+  <option value="texttop"                      >Texttop</option>\r
+  <option value="absmiddle"                    >Absmiddle</option>\r
+  <option value="baseline" selected="1"        >Baseline</option>\r
+  <option value="absbottom"                    >Absbottom</option>\r
+  <option value="bottom"                       >Bottom</option>\r
+  <option value="middle"                       >Middle</option>\r
+  <option value="top"                          >Top</option>\r
+</select>\r
+\r
+<p />\r
+\r
+<div class="fl">Border thickness:</div>\r
+<input type="text" name="border" id="f_border" size="5"\r
+title="Leave empty for no border" />\r
+\r
+<div class="space"></div>\r
+\r
+</fieldset>\r
+\r
+<fieldset style="float:right; margin-right: 5px;">\r
+<legend>Spacing</legend>\r
+\r
+<div class="space"></div>\r
+\r
+<div class="fr">Horizontal:</div>\r
+<input type="text" name="horiz" id="f_horiz" size="5"\r
+title="Horizontal padding" />\r
+\r
+<p />\r
+\r
+<div class="fr">Vertical:</div>\r
+<input type="text" name="vert" id="f_vert" size="5"\r
+title="Vertical padding" />\r
+\r
+<div class="space"></div>\r
+\r
+</fieldset>\r
+<br clear="all" />\r
+<table width="100%" style="margin-bottom: 0.2em">\r
+ <tr>\r
+  <td valign="bottom">\r
+    Image Preview:<br />\r
+    <iframe name="ipreview" id="ipreview" frameborder="0" style="border : 1px solid gray;" height="200" width="300" src=""></iframe>\r
+  </td>\r
+  <td valign="bottom" style="text-align: right">\r
+    <button type="button" name="ok" onclick="return onOK();">OK</button><br>\r
+    <button type="button" name="cancel" onclick="return onCancel();">Cancel</button>\r
+  </td>\r
+ </tr>\r
+</table>\r
+</form>\r
+</body>\r
+</html>\r
diff --git a/htmlarea/popups/insert_table.html b/htmlarea/popups/insert_table.html
new file mode 100644 (file)
index 0000000..05db221
--- /dev/null
@@ -0,0 +1,175 @@
+<html>
+
+<head>
+  <title>Insert Table</title>
+
+<script type="text/javascript" src="popup.js"></script>
+
+<script type="text/javascript">
+
+window.resizeTo(400, 100);
+
+function Init() {
+  i18n = window.opener.HTMLArea.I18N.dialogs; // load the HTMLArea plugin and lang file
+  __dlg_translate(i18n);
+  __dlg_init();
+  document.getElementById("f_rows").focus();
+};
+
+function onOK() {
+  var required = {
+    "f_rows": "You must enter a number of rows",
+    "f_cols": "You must enter a number of columns"
+  };
+  for (var i in required) {
+    var el = document.getElementById(i);
+    if (!el.value) {
+      alert(required[i]);
+      el.focus();
+      return false;
+    }
+  }
+  var fields = ["f_rows", "f_cols", "f_width", "f_unit", "f_fixed",
+                "f_align", "f_border", "f_spacing", "f_padding"];
+  var param = new Object();
+  for (var i in fields) {
+    var id = fields[i];
+    var el = document.getElementById(id);
+    param[id] = (el.type == "checkbox") ? el.checked : el.value;
+  }
+  __dlg_close(param);
+  return false;
+};
+
+function onCancel() {
+  __dlg_close(null);
+  return false;
+};
+
+</script>
+
+<style type="text/css">
+html, body {
+  background: ButtonFace;
+  color: ButtonText;
+  font: 11px Tahoma,Verdana,sans-serif;
+  margin: 0px;
+  padding: 0px;
+}
+body { padding: 5px; }
+table {
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+form p {
+  margin-top: 5px;
+  margin-bottom: 5px;
+}
+.fl { width: 9em; float: left; padding: 2px 5px; text-align: right; }
+.fr { width: 7em; float: left; padding: 2px 5px; text-align: right; }
+fieldset { padding: 0px 10px 5px 5px; }
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }
+button { width: 70px; }
+.space { padding: 2px; }
+
+.title { background: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px;
+border-bottom: 1px solid black; letter-spacing: 2px;
+}
+form { padding: 0px; margin: 0px; }
+</style>
+
+</head>
+
+<body onload="Init()">
+
+<div class="title">Insert Table</div>
+
+<form action="" method="get">
+<table border="0" style="padding: 0px; margin: 0px">
+  <tbody>
+
+  <tr>
+    <td style="width: 4em; text-align: right">Rows:</td>
+    <td><input type="text" name="rows" id="f_rows" size="5" title="Number of rows" value="2" /></td>
+    <td style="width: 4em; text-align: right">Width:</td>
+    <td><input type="text" name="width" id="f_width" size="5" title="Width of the table" value="100" /></td>
+    <td><select size="1" name="unit" id="f_unit" title="Width unit">
+      <option value="%" selected="1"  >Percent</option>
+      <option value="px"              >Pixels</option>
+      <option value="em"              >Em</option>
+    </select></td>
+  </tr>
+  <tr>
+    <td style="width: 4em; text-align: right">Cols:</td>
+    <td><input type="text" name="cols" id="f_cols" size="5" title="Number of columns" value="4" /></td>
+    <td style="text-align: right"><input type="checkbox" checked="checked" name="fixed" id="f_fixed" /></td>
+    <td colspan="2"><label for="f_fixed"
+    >Fixed width columns</label></td>
+  </tr>
+  </tbody>
+</table>
+
+<p />
+
+<fieldset style="float: left; margin-left: 5px;">
+<legend>Layout</legend>
+
+<div class="space"></div>
+
+<div class="fl">Alignment:</div>
+<select size="1" name="align" id="f_align"
+  title="Positioning of this table">
+  <option value="" selected="1"                >Not set</option>
+  <option value="left"                         >Left</option>
+  <option value="right"                        >Right</option>
+  <option value="texttop"                      >Texttop</option>
+  <option value="absmiddle"                    >Absmiddle</option>
+  <option value="baseline"                     >Baseline</option>
+  <option value="absbottom"                    >Absbottom</option>
+  <option value="bottom"                       >Bottom</option>
+  <option value="middle"                       >Middle</option>
+  <option value="top"                          >Top</option>
+</select>
+
+<p />
+
+<div class="fl">Border thickness:</div>
+<input type="text" name="border" id="f_border" size="5" value="1"
+title="Leave empty for no border" />
+<!--
+<p />
+
+<div class="fl">Collapse borders:</div>
+<input type="checkbox" name="collapse" id="f_collapse" />
+-->
+<div class="space"></div>
+
+</fieldset>
+
+<fieldset style="float:right; margin-right: 5px;">
+<legend>Spacing</legend>
+
+<div class="space"></div>
+
+<div class="fr">Cell spacing:</div>
+<input type="text" name="spacing" id="f_spacing" size="5" value="1"
+title="Space between adjacent cells" />
+
+<p />
+
+<div class="fr">Cell padding:</div>
+<input type="text" name="padding" id="f_padding" size="5" value="1"
+title="Space between content and border in cell" />
+
+<div class="space"></div>
+
+</fieldset>
+
+<div style="margin-top: 85px; border-top: 1px solid #999; padding: 2px; text-align: right;">
+<button type="button" name="ok" onclick="return onOK();">OK</button>
+<button type="button" name="cancel" onclick="return onCancel();">Cancel</button>
+</div>
+
+</form>
+
+</body>
+</html>
diff --git a/htmlarea/popups/link.html b/htmlarea/popups/link.html
new file mode 100644 (file)
index 0000000..72b0111
--- /dev/null
@@ -0,0 +1,155 @@
+<html>
+
+<head>
+  <title>Insert/Modify Link</title>
+  <script type="text/javascript" src="popup.js"></script>
+  <script type="text/javascript">
+    window.resizeTo(400, 200);
+
+I18N = window.opener.HTMLArea.I18N.dialogs;
+
+function i18n(str) {
+  return (I18N[str] || str);
+};
+
+function onTargetChanged() {
+  var f = document.getElementById("f_other_target");
+  if (this.value == "_other") {
+    f.style.visibility = "visible";
+    f.select();
+    f.focus();
+  } else f.style.visibility = "hidden";
+};
+
+function Init() {
+  __dlg_translate(I18N);
+  __dlg_init();
+  var param = window.dialogArguments;
+  var target_select = document.getElementById("f_target");
+  var use_target = true;
+  if (param) {
+    if ( typeof param["f_usetarget"] != "undefined" ) {
+      use_target = param["f_usetarget"];
+    }
+    if ( typeof param["f_href"] != "undefined" ) {
+      document.getElementById("f_href").value = param["f_href"];
+      document.getElementById("f_title").value = param["f_title"];
+      comboSelectValue(target_select, param["f_target"]);
+      if (target_select.value != param.f_target) {
+        var opt = document.createElement("option");
+        opt.value = param.f_target;
+        opt.innerHTML = opt.value;
+        target_select.appendChild(opt);
+        opt.selected = true;
+      }
+    }
+  }
+  if (! use_target) {
+    document.getElementById("f_target_label").style.visibility = "hidden";
+    document.getElementById("f_target").style.visibility = "hidden";
+    document.getElementById("f_target_other").style.visibility = "hidden";
+  }
+  var opt = document.createElement("option");
+  opt.value = "_other";
+  opt.innerHTML = i18n("Other");
+  target_select.appendChild(opt);
+  target_select.onchange = onTargetChanged;
+  document.getElementById("f_href").focus();
+  document.getElementById("f_href").select();
+};
+
+function onOK() {
+  var required = {
+    // f_href shouldn't be required or otherwise removing the link by entering an empty\r
+    // url isn't possible anymore.\r
+    // "f_href": i18n("You must enter the URL where this link points to")\r
+  };
+  for (var i in required) {
+    var el = document.getElementById(i);
+    if (!el.value) {
+      alert(required[i]);
+      el.focus();
+      return false;
+    }
+  }
+  // pass data back to the calling window
+  var fields = ["f_href", "f_title", "f_target" ];
+  var param = new Object();
+  for (var i in fields) {
+    var id = fields[i];
+    var el = document.getElementById(id);
+    param[id] = el.value;
+  }
+  if (param.f_target == "_other")
+    param.f_target = document.getElementById("f_other_target").value;
+  __dlg_close(param);
+  return false;
+};
+
+function onCancel() {
+  __dlg_close(null);
+  return false;
+};
+
+</script>
+
+<style type="text/css">
+html, body {
+  background: ButtonFace;
+  color: ButtonText;
+  font: 11px Tahoma,Verdana,sans-serif;
+  margin: 0px;
+  padding: 0px;
+}
+body { padding: 5px; }
+table {
+  font: 11px Tahoma,Verdana,sans-serif;
+}
+select, input, button { font: 11px Tahoma,Verdana,sans-serif; }
+button { width: 70px; }
+table .label { text-align: right; width: 8em; }
+
+.title { background: #ddf; color: #000; font-weight: bold; font-size: 120%; padding: 3px 10px; margin-bottom: 10px;
+border-bottom: 1px solid black; letter-spacing: 2px;
+}
+
+#buttons {
+      margin-top: 1em; border-top: 1px solid #999;
+      padding: 2px; text-align: right;
+}
+</style>
+
+</head>
+
+<body onload="Init()">
+<div class="title">Insert/Modify Link</div>
+<form>
+<table border="0" style="width: 100%;">
+  <tr>
+    <td class="label">URL:</td>
+    <td><input type="text" id="f_href" style="width: 100%" /></td>
+  </tr>
+  <tr>
+    <td class="label">Title (tooltip):</td>
+    <td><input type="text" id="f_title" style="width: 100%" /></td>
+  </tr>
+  <tr>
+    <td class="label"><span id="f_target_label">Target:</span></td>
+    <td><select id="f_target">
+      <option value="">None (use implicit)</option>
+      <option value="_blank">New window (_blank)</option>
+      <option value="_self">Same frame (_self)</option>
+      <option value="_top">Top frame (_top)</option>
+    </select>
+    <input type="text" name="f_other_target" id="f_other_target" size="10" style="visibility: hidden" />
+    </td>
+  </tr>
+</table>
+
+<div id="buttons">
+  <button type="submit" name="ok" onclick="return onOK();">OK</button>
+  <button type="button" name="cancel" onclick="return onCancel();">Cancel</button>
+</div>
+</form>
+</body>
+</html>
diff --git a/htmlarea/popups/old-fullscreen.html b/htmlarea/popups/old-fullscreen.html
new file mode 100644 (file)
index 0000000..0e133ae
--- /dev/null
@@ -0,0 +1,131 @@
+<html>\r
+<head><title>Fullscreen Editor</title>\r
+<style type="text/css"> body { margin: 0px; border: 0px; background-color: buttonface; } </style>\r
+\r
+<script>\r
+\r
+// if we pass the "window" object as a argument and then set opener to\r
+// equal that we can refer to dialogWindows and popupWindows the same way\r
+if (window.dialogArguments) { opener = window.dialogArguments; }\r
+\r
+var _editor_url = "../";\r
+document.write('<scr'+'ipt src="' +_editor_url+ 'editor.js" language="Javascript1.2"></scr'+'ipt>');\r
+\r
+var parent_objname = location.search.substring(1,location.search.length);  // parent editor objname\r
+var parent_config  = opener.document.all[parent_objname].config;\r
+\r
+var config         = cloneObject( parent_config );\r
+var objname        = 'editor'; // name of this editor\r
+\r
+//  DOMViewerObj = config;\r
+//  DOMViewerName = 'config';\r
+//  window.open('/innerHTML/domviewer.htm');  \r
+\r
+/* ---------------------------------------------------------------------- *\\r
+  Function    : \r
+  Description : \r
+\* ---------------------------------------------------------------------- */\r
+\r
+function _CloseOnEsc() {\r
+  if (event.keyCode == 27) {\r
+    update_parent();\r
+    window.close();\r
+    return;\r
+  }\r
+}\r
+\r
+/* ---------------------------------------------------------------------- *\\r
+  Function    : cloneObject\r
+  Description : copy an object by value instead of by reference\r
+  Usage       : var newObj = cloneObject(oldObj);\r
+\* ---------------------------------------------------------------------- */\r
+\r
+function cloneObject(obj) {\r
+  var newObj          = new Object; \r
+\r
+  // check for array objects\r
+  if (obj.constructor.toString().indexOf('function Array(') == 1) {\r
+    newObj = obj.constructor();\r
+  }\r
+\r
+  for (var n in obj) {\r
+    var node = obj[n];\r
+    if (typeof node == 'object') { newObj[n] = cloneObject(node); }\r
+    else                         { newObj[n] = node; }\r
+  }\r
+  \r
+  return newObj;\r
+}\r
+\r
+/* ---------------------------------------------------------------------- *\\r
+  Function    : resize_editor\r
+  Description : resize the editor when the user resizes the popup\r
+\* ---------------------------------------------------------------------- */\r
+\r
+function resize_editor() {  // resize editor to fix window\r
+  var editor = document.all['_editor_editor'];\r
+\r
+  newWidth  = document.body.offsetWidth;\r
+  newHeight = document.body.offsetHeight - editor.offsetTop;\r
+\r
+  if (newWidth < 0) { newWidth = 0; }\r
+  if (newHeight < 0) { newHeight = 0; }\r
+\r
+  editor.style.width  = newWidth;\r
+  editor.style.height = newHeight;\r
+}\r
+\r
+/* ---------------------------------------------------------------------- *\\r
+  Function    : init\r
+  Description : run this code on page load\r
+\* ---------------------------------------------------------------------- */\r
+\r
+function init() {\r
+  // change maximize button to minimize button\r
+  config.btnList["popupeditor"] = ['popupeditor', 'Minimize Editor',  'update_parent(); window.close();', 'fullscreen_minimize.gif'];\r
+\r
+  // set htmlmode button to refer to THIS editor\r
+  config.btnList["htmlmode"]    = ['HtmlMode',    'View HTML Source', 'editor_setmode(\'editor\')',  'ed_html.gif'];\r
+\r
+  // change image url to be relative to current path\r
+  config.imgURL = "../images/";\r
+  \r
+  // generate editor and resize it\r
+  editor_generate('editor', config);\r
+  resize_editor();\r
+\r
+  // switch mode if needed\r
+  if (parent_config.mode == 'textedit') { editor_setmode(objname, 'textedit'); }\r
+\r
+  // set child window contents\r
+  var parentHTML = opener.editor_getHTML(parent_objname);\r
+  editor_setHTML(objname, parentHTML);\r
+\r
+  // continuously update parent editor window\r
+  window.setInterval(update_parent, 333);\r
+\r
+  // setup event handlers\r
+  document.body.onkeypress = _CloseOnEsc;\r
+  window.onresize = resize_editor;\r
+}\r
+\r
+/* ---------------------------------------------------------------------- *\\r
+  Function    : update_parent\r
+  Description : update parent window editor field with contents from child window\r
+\* ---------------------------------------------------------------------- */\r
+\r
+function update_parent() {\r
+  var childHTML = editor_getHTML(objname);\r
+  opener.editor_setHTML(parent_objname, childHTML);\r
+}\r
+\r
+\r
+</script>\r
+</head>\r
+<body scroll="no" onload="init()" onunload="update_parent()">\r
+\r
+<div style="margin: 0 0 0 0; border-width: 1; border-style: solid; border-color: threedshadow threedhighlight threedhighlight threedshadow; "></div>\r
+\r
+<textarea name="editor" style="width:100%; height:300px"></textarea><br>\r
+\r
+</body></html>
\ No newline at end of file
diff --git a/htmlarea/popups/old_insert_image.html b/htmlarea/popups/old_insert_image.html
new file mode 100644 (file)
index 0000000..3edcd3e
--- /dev/null
@@ -0,0 +1,206 @@
+<!-- based on insimage.dlg -->\r
+\r
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD W3 HTML 3.2//EN">\r
+<HTML  id=dlgImage STYLE="width: 432px; height: 194px; ">\r
+<HEAD>\r
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">\r
+<meta http-equiv="MSThemeCompatible" content="Yes">\r
+<TITLE>Insert Image</TITLE>\r
+<style>\r
+  html, body, button, div, input, select, fieldset { font-family: MS Shell Dlg; font-size: 8pt; position: absolute; };\r
+</style>\r
+<SCRIPT defer>\r
+\r
+function _CloseOnEsc() {\r
+  if (event.keyCode == 27) { window.close(); return; }\r
+}\r
+\r
+function _getTextRange(elm) {\r
+  var r = elm.parentTextEdit.createTextRange();\r
+  r.moveToElementText(elm);\r
+  return r;\r
+}\r
+\r
+window.onerror = HandleError\r
+\r
+function HandleError(message, url, line) {\r
+  var str = "An error has occurred in this dialog." + "\n\n"\r
+  + "Error: " + line + "\n" + message;\r
+  alert(str);\r
+  window.close();\r
+  return true;\r
+}\r
+\r
+function Init() {\r
+  var elmSelectedImage;\r
+  var htmlSelectionControl = "Control";\r
+  var globalDoc = window.dialogArguments;\r
+  var grngMaster = globalDoc.selection.createRange();\r
+  \r
+  // event handlers  \r
+  document.body.onkeypress = _CloseOnEsc;\r
+  btnOK.onclick = new Function("btnOKClick()");\r
+\r
+  txtFileName.fImageLoaded = false;\r
+  txtFileName.intImageWidth = 0;\r
+  txtFileName.intImageHeight = 0;\r
+\r
+  if (globalDoc.selection.type == htmlSelectionControl) {\r
+    if (grngMaster.length == 1) {\r
+      elmSelectedImage = grngMaster.item(0);\r
+      if (elmSelectedImage.tagName == "IMG") {\r
+        txtFileName.fImageLoaded = true;\r
+        if (elmSelectedImage.src) {\r
+          txtFileName.value          = elmSelectedImage.src.replace(/^[^*]*(\*\*\*)/, "$1");  // fix placeholder src values that editor converted to abs paths\r
+          txtFileName.intImageHeight = elmSelectedImage.height;\r
+          txtFileName.intImageWidth  = elmSelectedImage.width;\r
+          txtVertical.value          = elmSelectedImage.vspace;\r
+          txtHorizontal.value        = elmSelectedImage.hspace;\r
+          txtBorder.value            = elmSelectedImage.border;\r
+          txtAltText.value           = elmSelectedImage.alt;\r
+          selAlignment.value         = elmSelectedImage.align;\r
+        }\r
+      }\r
+    }\r
+  }\r
+  txtFileName.value = txtFileName.value || "http://";\r
+  txtFileName.focus();\r
+}\r
+\r
+function _isValidNumber(txtBox) {\r
+  var val = parseInt(txtBox);\r
+  if (isNaN(val) || val < 0 || val > 999) { return false; }\r
+  return true;\r
+}\r
+\r
+function btnOKClick() {\r
+  var elmImage;\r
+  var intAlignment;\r
+  var htmlSelectionControl = "Control";\r
+  var globalDoc = window.dialogArguments;\r
+  var grngMaster = globalDoc.selection.createRange();\r
+  \r
+  // error checking\r
+\r
+  if (!txtFileName.value || txtFileName.value == "http://") { \r
+    alert("Image URL must be specified.");\r
+    txtFileName.focus();\r
+    return;\r
+  }\r
+  if (txtHorizontal.value && !_isValidNumber(txtHorizontal.value)) {\r
+    alert("Horizontal spacing must be a number between 0 and 999.");\r
+    txtHorizontal.focus();\r
+    return;\r
+  }\r
+  if (txtBorder.value && !_isValidNumber(txtBorder.value)) {\r
+    alert("Border thickness must be a number between 0 and 999.");\r
+    txtBorder.focus();\r
+    return;\r
+  }\r
+  if (txtVertical.value && !_isValidNumber(txtVertical.value)) {\r
+    alert("Vertical spacing must be a number between 0 and 999.");\r
+    txtVertical.focus();\r
+    return;\r
+  }\r
+\r
+  // delete selected content and replace with image\r
+  if (globalDoc.selection.type == htmlSelectionControl && !txtFileName.fImageLoaded) {\r
+    grngMaster.execCommand('Delete');\r
+    grngMaster = globalDoc.selection.createRange();\r
+  }\r
+    \r
+  idstr = "\" id=\"556e697175657e537472696e67";     // new image creation ID\r
+  if (!txtFileName.fImageLoaded) {\r
+    grngMaster.execCommand("InsertImage", false, idstr);\r
+    elmImage = globalDoc.all['556e697175657e537472696e67'];\r
+    elmImage.removeAttribute("id");\r
+    elmImage.removeAttribute("src");\r
+    grngMaster.moveStart("character", -1);\r
+  } else {\r
+    elmImage = grngMaster.item(0);\r
+    if (elmImage.src != txtFileName.value) {\r
+      grngMaster.execCommand('Delete');\r
+      grngMaster = globalDoc.selection.createRange();\r
+      grngMaster.execCommand("InsertImage", false, idstr);\r
+      elmImage = globalDoc.all['556e697175657e537472696e67'];\r
+      elmImage.removeAttribute("id");\r
+      elmImage.removeAttribute("src");\r
+      grngMaster.moveStart("character", -1);\r
+      txtFileName.fImageLoaded = false;\r
+    }\r
+    grngMaster = _getTextRange(elmImage);\r
+  }\r
+\r
+  if (txtFileName.fImageLoaded) {\r
+    elmImage.style.width = txtFileName.intImageWidth;\r
+    elmImage.style.height = txtFileName.intImageHeight;\r
+  }\r
+\r
+  if (txtFileName.value.length > 2040) {\r
+    txtFileName.value = txtFileName.value.substring(0,2040);\r
+  }\r
+  \r
+  elmImage.src = txtFileName.value;\r
+  \r
+  if (txtHorizontal.value != "") { elmImage.hspace = parseInt(txtHorizontal.value); }\r
+  else                           { elmImage.hspace = 0; }\r
+\r
+  if (txtVertical.value != "") { elmImage.vspace = parseInt(txtVertical.value); }\r
+  else                         { elmImage.vspace = 0; }\r
+  \r
+  elmImage.alt = txtAltText.value;\r
+\r
+  if (txtBorder.value != "") { elmImage.border = parseInt(txtBorder.value); }\r
+  else                       { elmImage.border = 0; }\r
+\r
+  elmImage.align = selAlignment.value;\r
+  grngMaster.collapse(false);\r
+  grngMaster.select();\r
+  window.close();\r
+}\r
+</SCRIPT>\r
+</HEAD>\r
+<BODY id=bdy onload="Init()" style="background: threedface; color: windowtext;" scroll=no>\r
+\r
+<DIV id=divFileName style="left: 0.98em; top: 1.2168em; width: 7em; height: 1.2168em; ">Image URL:</DIV>\r
+<INPUT ID=txtFileName type=text style="left: 8.54em; top: 1.0647em; width: 21.5em;height: 2.1294em; " tabIndex=10 onfocus="select()">\r
+\r
+<DIV id=divAltText style="left: 0.98em; top: 4.1067em; width: 6.58em; height: 1.2168em; ">Alternate Text:</DIV>\r
+<INPUT type=text ID=txtAltText tabIndex=15 style="left: 8.54em; top: 3.8025em; width: 21.5em; height: 2.1294em; " onfocus="select()">\r
+\r
+<FIELDSET id=fldLayout style="left: .9em; top: 7.1em; width: 17.08em; height: 7.6em;">\r
+<LEGEND id=lgdLayout>Layout</LEGEND>\r
+</FIELDSET>\r
+\r
+<FIELDSET id=fldSpacing style="left: 18.9em; top: 7.1em; width: 11em; height: 7.6em;">\r
+<LEGEND id=lgdSpacing>Spacing</LEGEND>\r
+</FIELDSET>\r
+\r
+<DIV id=divAlign style="left: 1.82em; top: 9.126em; width: 4.76em; height: 1.2168em; ">Alignment:</DIV>\r
+<SELECT size=1 ID=selAlignment tabIndex=20 style="left: 10.36em; top: 8.8218em; width: 6.72em; height: 1.2168em; ">\r
+<OPTION id=optNotSet value=""> Not set </OPTION>\r
+<OPTION id=optLeft value=left> Left </OPTION>\r
+<OPTION id=optRight value=right> Right </OPTION>\r
+<OPTION id=optTexttop value=textTop> Texttop </OPTION>\r
+<OPTION id=optAbsMiddle value=absMiddle> Absmiddle </OPTION>\r
+<OPTION id=optBaseline value=baseline SELECTED> Baseline </OPTION>\r
+<OPTION id=optAbsBottom value=absBottom> Absbottom </OPTION>\r
+<OPTION id=optBottom value=bottom> Bottom </OPTION>\r
+<OPTION id=optMiddle value=middle> Middle </OPTION>\r
+<OPTION id=optTop value=top> Top </OPTION>\r
+</SELECT>\r
+\r
+<DIV id=divHoriz style="left: 19.88em; top: 9.126em; width: 4.76em; height: 1.2168em; ">Horizontal:</DIV>\r
+<INPUT ID=txtHorizontal style="left: 24.92em; top: 8.8218em; width: 4.2em; height: 2.1294em; ime-mode: disabled;" type=text size=3 maxlength=3 value="" tabIndex=25 onfocus="select()">\r
+\r
+<DIV id=divBorder style="left: 1.82em; top: 12.0159em; width: 8.12em; height: 1.2168em; ">Border Thickness:</DIV>\r
+<INPUT ID=txtBorder style="left: 10.36em; top: 11.5596em; width: 6.72em; height: 2.1294em; ime-mode: disabled;" type=text size=3 maxlength=3 value="" tabIndex=21 onfocus="select()">\r
+\r
+<DIV id=divVert style="left: 19.88em; top: 12.0159em; width: 3.64em; height: 1.2168em; ">Vertical:</DIV>\r
+<INPUT ID=txtVertical style="left: 24.92em; top: 11.5596em; width: 4.2em; height: 2.1294em; ime-mode: disabled;" type=text size=3 maxlength=3 value="" tabIndex=30 onfocus="select()">\r
+\r
+<BUTTON ID=btnOK style="left: 31.36em; top: 1.0647em; width: 7em; height: 2.2em; " type=submit tabIndex=40>OK</BUTTON>\r
+<BUTTON ID=btnCancel style="left: 31.36em; top: 3.6504em; width: 7em; height: 2.2em; " type=reset tabIndex=45 onClick="window.close();">Cancel</BUTTON>\r
+\r
+</BODY>\r
+</HTML>
\ No newline at end of file
diff --git a/htmlarea/popups/popup.js b/htmlarea/popups/popup.js
new file mode 100644 (file)
index 0000000..9876266
--- /dev/null
@@ -0,0 +1,114 @@
+// htmlArea v3.0 - Copyright (c) 2002, 2003 interactivetools.com, inc.
+// This copyright notice MUST stay intact for use (see license.txt).
+//
+// Portions (c) dynarch.com, 2003
+//
+// A free WYSIWYG editor replacement for <textarea> fields.
+// For full source code and docs, visit http://www.interactivetools.com/
+//
+// Version 3.0 developed by Mihai Bazon.
+//   http://dynarch.com/mishoo
+//
+// $Id: popup.js,v 1.3 2005/01/11 15:01:01 garvinhicking Exp $
+
+function getAbsolutePos(el) {
+       var r = { x: el.offsetLeft, y: el.offsetTop };
+       if (el.offsetParent) {
+               var tmp = getAbsolutePos(el.offsetParent);
+               r.x += tmp.x;
+               r.y += tmp.y;
+       }
+       return r;
+};
+
+function comboSelectValue(c, val) {
+       var ops = c.getElementsByTagName("option");
+       for (var i = ops.length; --i >= 0;) {
+               var op = ops[i];
+               op.selected = (op.value == val);
+       }
+       c.value = val;
+};
+
+function __dlg_onclose() {
+       opener.Dialog._return(null);
+};
+
+function __dlg_init(bottom) {
+       var body = document.body;
+       var body_height = 0;
+       if (typeof bottom == "undefined") {
+               var div = document.createElement("div");
+               body.appendChild(div);
+               var pos = getAbsolutePos(div);
+               body_height = pos.y;
+       } else {
+               var pos = getAbsolutePos(bottom);
+               body_height = pos.y + bottom.offsetHeight;
+       }
+       window.dialogArguments = opener.Dialog._arguments;
+       if (!document.all) {
+               window.sizeToContent();
+               window.sizeToContent(); // for reasons beyond understanding,
+                                       // only if we call it twice we get the
+                                       // correct size.
+               window.addEventListener("unload", __dlg_onclose, true);
+               window.innerWidth = body.offsetWidth + 5;
+               window.innerHeight = body_height + 2;
+               // center on parent
+               var x = opener.screenX + (opener.outerWidth - window.outerWidth) / 2;
+               var y = opener.screenY + (opener.outerHeight - window.outerHeight) / 2;
+               window.moveTo(x, y);
+       } else {
+               // window.dialogHeight = body.offsetHeight + 50 + "px";
+               // window.dialogWidth = body.offsetWidth + "px";
+               window.resizeTo(body.offsetWidth, body_height);
+               var ch = body.clientHeight;
+               var cw = body.clientWidth;
+               window.resizeBy(body.offsetWidth - cw, body_height - ch);
+               var W = body.offsetWidth;
+               var H = 2 * body_height - ch;
+               var x = (screen.availWidth - W) / 2;
+               var y = (screen.availHeight - H) / 2;
+               window.moveTo(x, y);
+       }
+       document.body.onkeypress = __dlg_close_on_esc;
+};
+
+function __dlg_translate(i18n) {
+       var types = ["input", "select", "legend", "span", "option", "td", "button", "div"];
+       for (var type = 0; type < types.length; ++type) {
+               var spans = document.getElementsByTagName(types[type]);
+               for (var i = spans.length; --i >= 0;) {
+                       var span = spans[i];
+                       if (span.firstChild && span.firstChild.data) {
+                               var txt = i18n[span.firstChild.data];
+                               if (txt)
+                                       span.firstChild.data = txt;
+                       }
+                        if (span.title) {
+                               var txt = i18n[span.title];
+                               if (txt)
+                                       span.title = txt;
+                        }
+               }
+       }
+       var txt = i18n[document.title];
+       if (txt)
+               document.title = txt;
+};
+
+// closes the dialog and passes the return info upper.
+function __dlg_close(val) {
+       opener.Dialog._return(val);
+       window.close();
+};
+
+function __dlg_close_on_esc(ev) {
+       ev || (ev = window.event);
+       if (ev.keyCode == 27) {
+               window.close();
+               return false;
+       }
+       return true;
+};
diff --git a/htmlarea/popups/select_color.html b/htmlarea/popups/select_color.html
new file mode 100644 (file)
index 0000000..c9df112
--- /dev/null
@@ -0,0 +1,347 @@
+<!-- note: this version of the color picker is optimized for IE 5.5+ only -->\r
+\r
+<html><head><title>Select Color</title>\r
+\r
+<script type="text/javascript" src="popup.js"></script>\r
+\r
+<script type="text/javascript">\r
+\r
+window.resizeTo(240, 182);\r
+function _CloseOnEsc() {\r
+  if (event.keyCode == 27) { window.close(); return; }\r
+}\r
+\r
+function Init() {                                                       // run on page load\r
+  __dlg_init();    // <!-- this can be found in popup.js -->\r
+  document.body.onkeypress = _CloseOnEsc;\r
+\r
+  var color = window.dialogArguments;\r
+  color = ValidateColor(color) || '000000';\r
+  View(color);                                                          // set default color\r
+}\r
+\r
+function View(color) {                  // preview color\r
+  document.getElementById("ColorPreview").style.backgroundColor = '#' + color;\r
+  document.getElementById("ColorHex").value = '#' + color;\r
+}\r
+\r
+function Set(string) {                   // select color\r
+  var color = ValidateColor(string);\r
+  if (color == null) { alert("Invalid color code: " + string); }        // invalid color\r
+  else {                                                                // valid color\r
+    View(color);                          // show selected color\r
+    __dlg_close(color);\r
+  }\r
+}\r
+\r
+function ValidateColor(string) {                // return valid color code\r
+  string = string || '';\r
+  string = string + "";\r
+  string = string.toUpperCase();\r
+  var chars = '0123456789ABCDEF';\r
+  var out   = '';\r
+\r
+  for (var i=0; i<string.length; i++) {             // remove invalid color chars\r
+    var schar = string.charAt(i);\r
+    if (chars.indexOf(schar) != -1) { out += schar; }\r
+  }\r
+\r
+  if (out.length != 6) { return null; }            // check length\r
+  return out;\r
+}\r
+\r
+</script>\r
+</head>\r
+<body style="background:ButtonFace; margin:0px; padding:0px" onload="Init()">\r
+\r
+<form method="get" style="margin:0px; padding:0px" onSubmit="Set(document.getElementById('ColorHex').value); return false;">\r
+<table border="0px" cellspacing="0px" cellpadding="4" width="100%">\r
+ <tr>\r
+  <td style="background:buttonface" valign=center><div style="background-color: #000000; padding: 1; height: 21px; width: 50px"><div id="ColorPreview" style="height: 100%; width: 100%"></div></div></td>\r
+  <td style="background:buttonface" valign=center><input type="text" name="ColorHex"\r
+    id="ColorHex" value="" size=15 style="font-size: 12px"></td>\r
+  <td style="background:buttonface" width=100%></td>\r
+ </tr>\r
+</table>\r
+</form>\r
+\r
+<table border="0" cellspacing="1px" cellpadding="0px" width="100%" bgcolor="#000000" style="cursor: hand;">\r
+<tr>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#003300 onMouseOver=View('003300') onClick=Set('003300') height="10px" width="10px"></td>\r
+<td bgcolor=#006600 onMouseOver=View('006600') onClick=Set('006600') height="10px" width="10px"></td>\r
+<td bgcolor=#009900 onMouseOver=View('009900') onClick=Set('009900') height="10px" width="10px"></td>\r
+<td bgcolor=#00CC00 onMouseOver=View('00CC00') onClick=Set('00CC00') height="10px" width="10px"></td>\r
+<td bgcolor=#00FF00 onMouseOver=View('00FF00') onClick=Set('00FF00') height="10px" width="10px"></td>\r
+<td bgcolor=#330000 onMouseOver=View('330000') onClick=Set('330000') height="10px" width="10px"></td>\r
+<td bgcolor=#333300 onMouseOver=View('333300') onClick=Set('333300') height="10px" width="10px"></td>\r
+<td bgcolor=#336600 onMouseOver=View('336600') onClick=Set('336600') height="10px" width="10px"></td>\r
+<td bgcolor=#339900 onMouseOver=View('339900') onClick=Set('339900') height="10px" width="10px"></td>\r
+<td bgcolor=#33CC00 onMouseOver=View('33CC00') onClick=Set('33CC00') height="10px" width="10px"></td>\r
+<td bgcolor=#33FF00 onMouseOver=View('33FF00') onClick=Set('33FF00') height="10px" width="10px"></td>\r
+<td bgcolor=#660000 onMouseOver=View('660000') onClick=Set('660000') height="10px" width="10px"></td>\r
+<td bgcolor=#663300 onMouseOver=View('663300') onClick=Set('663300') height="10px" width="10px"></td>\r
+<td bgcolor=#666600 onMouseOver=View('666600') onClick=Set('666600') height="10px" width="10px"></td>\r
+<td bgcolor=#669900 onMouseOver=View('669900') onClick=Set('669900') height="10px" width="10px"></td>\r
+<td bgcolor=#66CC00 onMouseOver=View('66CC00') onClick=Set('66CC00') height="10px" width="10px"></td>\r
+<td bgcolor=#66FF00 onMouseOver=View('66FF00') onClick=Set('66FF00') height="10px" width="10px"></td>\r
+</tr>\r
+<tr>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#333333 onMouseOver=View('333333') onClick=Set('333333') height="10px" width="10px"></td>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#000033 onMouseOver=View('000033') onClick=Set('000033') height="10px" width="10px"></td>\r
+<td bgcolor=#003333 onMouseOver=View('003333') onClick=Set('003333') height="10px" width="10px"></td>\r
+<td bgcolor=#006633 onMouseOver=View('006633') onClick=Set('006633') height="10px" width="10px"></td>\r
+<td bgcolor=#009933 onMouseOver=View('009933') onClick=Set('009933') height="10px" width="10px"></td>\r
+<td bgcolor=#00CC33 onMouseOver=View('00CC33') onClick=Set('00CC33') height="10px" width="10px"></td>\r
+<td bgcolor=#00FF33 onMouseOver=View('00FF33') onClick=Set('00FF33') height="10px" width="10px"></td>\r
+<td bgcolor=#330033 onMouseOver=View('330033') onClick=Set('330033') height="10px" width="10px"></td>\r
+<td bgcolor=#333333 onMouseOver=View('333333') onClick=Set('333333') height="10px" width="10px"></td>\r
+<td bgcolor=#336633 onMouseOver=View('336633') onClick=Set('336633') height="10px" width="10px"></td>\r
+<td bgcolor=#339933 onMouseOver=View('339933') onClick=Set('339933') height="10px" width="10px"></td>\r
+<td bgcolor=#33CC33 onMouseOver=View('33CC33') onClick=Set('33CC33') height="10px" width="10px"></td>\r
+<td bgcolor=#33FF33 onMouseOver=View('33FF33') onClick=Set('33FF33') height="10px" width="10px"></td>\r
+<td bgcolor=#660033 onMouseOver=View('660033') onClick=Set('660033') height="10px" width="10px"></td>\r
+<td bgcolor=#663333 onMouseOver=View('663333') onClick=Set('663333') height="10px" width="10px"></td>\r
+<td bgcolor=#666633 onMouseOver=View('666633') onClick=Set('666633') height="10px" width="10px"></td>\r
+<td bgcolor=#669933 onMouseOver=View('669933') onClick=Set('669933') height="10px" width="10px"></td>\r
+<td bgcolor=#66CC33 onMouseOver=View('66CC33') onClick=Set('66CC33') height="10px" width="10px"></td>\r
+<td bgcolor=#66FF33 onMouseOver=View('66FF33') onClick=Set('66FF33') height="10px" width="10px"></td>\r
+</tr>\r
+<tr>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#666666 onMouseOver=View('666666') onClick=Set('666666') height="10px" width="10px"></td>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#000066 onMouseOver=View('000066') onClick=Set('000066') height="10px" width="10px"></td>\r
+<td bgcolor=#003366 onMouseOver=View('003366') onClick=Set('003366') height="10px" width="10px"></td>\r
+<td bgcolor=#006666 onMouseOver=View('006666') onClick=Set('006666') height="10px" width="10px"></td>\r
+<td bgcolor=#009966 onMouseOver=View('009966') onClick=Set('009966') height="10px" width="10px"></td>\r
+<td bgcolor=#00CC66 onMouseOver=View('00CC66') onClick=Set('00CC66') height="10px" width="10px"></td>\r
+<td bgcolor=#00FF66 onMouseOver=View('00FF66') onClick=Set('00FF66') height="10px" width="10px"></td>\r
+<td bgcolor=#330066 onMouseOver=View('330066') onClick=Set('330066') height="10px" width="10px"></td>\r
+<td bgcolor=#333366 onMouseOver=View('333366') onClick=Set('333366') height="10px" width="10px"></td>\r
+<td bgcolor=#336666 onMouseOver=View('336666') onClick=Set('336666') height="10px" width="10px"></td>\r
+<td bgcolor=#339966 onMouseOver=View('339966') onClick=Set('339966') height="10px" width="10px"></td>\r
+<td bgcolor=#33CC66 onMouseOver=View('33CC66') onClick=Set('33CC66') height="10px" width="10px"></td>\r
+<td bgcolor=#33FF66 onMouseOver=View('33FF66') onClick=Set('33FF66') height="10px" width="10px"></td>\r
+<td bgcolor=#660066 onMouseOver=View('660066') onClick=Set('660066') height="10px" width="10px"></td>\r
+<td bgcolor=#663366 onMouseOver=View('663366') onClick=Set('663366') height="10px" width="10px"></td>\r
+<td bgcolor=#666666 onMouseOver=View('666666') onClick=Set('666666') height="10px" width="10px"></td>\r
+<td bgcolor=#669966 onMouseOver=View('669966') onClick=Set('669966') height="10px" width="10px"></td>\r
+<td bgcolor=#66CC66 onMouseOver=View('66CC66') onClick=Set('66CC66') height="10px" width="10px"></td>\r
+<td bgcolor=#66FF66 onMouseOver=View('66FF66') onClick=Set('66FF66') height="10px" width="10px"></td>\r
+</tr>\r
+<tr>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#999999 onMouseOver=View('999999') onClick=Set('999999') height="10px" width="10px"></td>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#000099 onMouseOver=View('000099') onClick=Set('000099') height="10px" width="10px"></td>\r
+<td bgcolor=#003399 onMouseOver=View('003399') onClick=Set('003399') height="10px" width="10px"></td>\r
+<td bgcolor=#006699 onMouseOver=View('006699') onClick=Set('006699') height="10px" width="10px"></td>\r
+<td bgcolor=#009999 onMouseOver=View('009999') onClick=Set('009999') height="10px" width="10px"></td>\r
+<td bgcolor=#00CC99 onMouseOver=View('00CC99') onClick=Set('00CC99') height="10px" width="10px"></td>\r
+<td bgcolor=#00FF99 onMouseOver=View('00FF99') onClick=Set('00FF99') height="10px" width="10px"></td>\r
+<td bgcolor=#330099 onMouseOver=View('330099') onClick=Set('330099') height="10px" width="10px"></td>\r
+<td bgcolor=#333399 onMouseOver=View('333399') onClick=Set('333399') height="10px" width="10px"></td>\r
+<td bgcolor=#336699 onMouseOver=View('336699') onClick=Set('336699') height="10px" width="10px"></td>\r
+<td bgcolor=#339999 onMouseOver=View('339999') onClick=Set('339999') height="10px" width="10px"></td>\r
+<td bgcolor=#33CC99 onMouseOver=View('33CC99') onClick=Set('33CC99') height="10px" width="10px"></td>\r
+<td bgcolor=#33FF99 onMouseOver=View('33FF99') onClick=Set('33FF99') height="10px" width="10px"></td>\r
+<td bgcolor=#660099 onMouseOver=View('660099') onClick=Set('660099') height="10px" width="10px"></td>\r
+<td bgcolor=#663399 onMouseOver=View('663399') onClick=Set('663399') height="10px" width="10px"></td>\r
+<td bgcolor=#666699 onMouseOver=View('666699') onClick=Set('666699') height="10px" width="10px"></td>\r
+<td bgcolor=#669999 onMouseOver=View('669999') onClick=Set('669999') height="10px" width="10px"></td>\r
+<td bgcolor=#66CC99 onMouseOver=View('66CC99') onClick=Set('66CC99') height="10px" width="10px"></td>\r
+<td bgcolor=#66FF99 onMouseOver=View('66FF99') onClick=Set('66FF99') height="10px" width="10px"></td>\r
+</tr>\r
+<tr>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#CCCCCC onMouseOver=View('CCCCCC') onClick=Set('CCCCCC') height="10px" width="10px"></td>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#0000CC onMouseOver=View('0000CC') onClick=Set('0000CC') height="10px" width="10px"></td>\r
+<td bgcolor=#0033CC onMouseOver=View('0033CC') onClick=Set('0033CC') height="10px" width="10px"></td>\r
+<td bgcolor=#0066CC onMouseOver=View('0066CC') onClick=Set('0066CC') height="10px" width="10px"></td>\r
+<td bgcolor=#0099CC onMouseOver=View('0099CC') onClick=Set('0099CC') height="10px" width="10px"></td>\r
+<td bgcolor=#00CCCC onMouseOver=View('00CCCC') onClick=Set('00CCCC') height="10px" width="10px"></td>\r
+<td bgcolor=#00FFCC onMouseOver=View('00FFCC') onClick=Set('00FFCC') height="10px" width="10px"></td>\r
+<td bgcolor=#3300CC onMouseOver=View('3300CC') onClick=Set('3300CC') height="10px" width="10px"></td>\r
+<td bgcolor=#3333CC onMouseOver=View('3333CC') onClick=Set('3333CC') height="10px" width="10px"></td>\r
+<td bgcolor=#3366CC onMouseOver=View('3366CC') onClick=Set('3366CC') height="10px" width="10px"></td>\r
+<td bgcolor=#3399CC onMouseOver=View('3399CC') onClick=Set('3399CC') height="10px" width="10px"></td>\r
+<td bgcolor=#33CCCC onMouseOver=View('33CCCC') onClick=Set('33CCCC') height="10px" width="10px"></td>\r
+<td bgcolor=#33FFCC onMouseOver=View('33FFCC') onClick=Set('33FFCC') height="10px" width="10px"></td>\r
+<td bgcolor=#6600CC onMouseOver=View('6600CC') onClick=Set('6600CC') height="10px" width="10px"></td>\r
+<td bgcolor=#6633CC onMouseOver=View('6633CC') onClick=Set('6633CC') height="10px" width="10px"></td>\r
+<td bgcolor=#6666CC onMouseOver=View('6666CC') onClick=Set('6666CC') height="10px" width="10px"></td>\r
+<td bgcolor=#6699CC onMouseOver=View('6699CC') onClick=Set('6699CC') height="10px" width="10px"></td>\r
+<td bgcolor=#66CCCC onMouseOver=View('66CCCC') onClick=Set('66CCCC') height="10px" width="10px"></td>\r
+<td bgcolor=#66FFCC onMouseOver=View('66FFCC') onClick=Set('66FFCC') height="10px" width="10px"></td>\r
+</tr>\r
+<tr>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#FFFFFF onMouseOver=View('FFFFFF') onClick=Set('FFFFFF') height="10px" width="10px"></td>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#0000FF onMouseOver=View('0000FF') onClick=Set('0000FF') height="10px" width="10px"></td>\r
+<td bgcolor=#0033FF onMouseOver=View('0033FF') onClick=Set('0033FF') height="10px" width="10px"></td>\r
+<td bgcolor=#0066FF onMouseOver=View('0066FF') onClick=Set('0066FF') height="10px" width="10px"></td>\r
+<td bgcolor=#0099FF onMouseOver=View('0099FF') onClick=Set('0099FF') height="10px" width="10px"></td>\r
+<td bgcolor=#00CCFF onMouseOver=View('00CCFF') onClick=Set('00CCFF') height="10px" width="10px"></td>\r
+<td bgcolor=#00FFFF onMouseOver=View('00FFFF') onClick=Set('00FFFF') height="10px" width="10px"></td>\r
+<td bgcolor=#3300FF onMouseOver=View('3300FF') onClick=Set('3300FF') height="10px" width="10px"></td>\r
+<td bgcolor=#3333FF onMouseOver=View('3333FF') onClick=Set('3333FF') height="10px" width="10px"></td>\r
+<td bgcolor=#3366FF onMouseOver=View('3366FF') onClick=Set('3366FF') height="10px" width="10px"></td>\r
+<td bgcolor=#3399FF onMouseOver=View('3399FF') onClick=Set('3399FF') height="10px" width="10px"></td>\r
+<td bgcolor=#33CCFF onMouseOver=View('33CCFF') onClick=Set('33CCFF') height="10px" width="10px"></td>\r
+<td bgcolor=#33FFFF onMouseOver=View('33FFFF') onClick=Set('33FFFF') height="10px" width="10px"></td>\r
+<td bgcolor=#6600FF onMouseOver=View('6600FF') onClick=Set('6600FF') height="10px" width="10px"></td>\r
+<td bgcolor=#6633FF onMouseOver=View('6633FF') onClick=Set('6633FF') height="10px" width="10px"></td>\r
+<td bgcolor=#6666FF onMouseOver=View('6666FF') onClick=Set('6666FF') height="10px" width="10px"></td>\r
+<td bgcolor=#6699FF onMouseOver=View('6699FF') onClick=Set('6699FF') height="10px" width="10px"></td>\r
+<td bgcolor=#66CCFF onMouseOver=View('66CCFF') onClick=Set('66CCFF') height="10px" width="10px"></td>\r
+<td bgcolor=#66FFFF onMouseOver=View('66FFFF') onClick=Set('66FFFF') height="10px" width="10px"></td>\r
+</tr>\r
+<tr>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#FF0000 onMouseOver=View('FF0000') onClick=Set('FF0000') height="10px" width="10px"></td>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#990000 onMouseOver=View('990000') onClick=Set('990000') height="10px" width="10px"></td>\r
+<td bgcolor=#993300 onMouseOver=View('993300') onClick=Set('993300') height="10px" width="10px"></td>\r
+<td bgcolor=#996600 onMouseOver=View('996600') onClick=Set('996600') height="10px" width="10px"></td>\r
+<td bgcolor=#999900 onMouseOver=View('999900') onClick=Set('999900') height="10px" width="10px"></td>\r
+<td bgcolor=#99CC00 onMouseOver=View('99CC00') onClick=Set('99CC00') height="10px" width="10px"></td>\r
+<td bgcolor=#99FF00 onMouseOver=View('99FF00') onClick=Set('99FF00') height="10px" width="10px"></td>\r
+<td bgcolor=#CC0000 onMouseOver=View('CC0000') onClick=Set('CC0000') height="10px" width="10px"></td>\r
+<td bgcolor=#CC3300 onMouseOver=View('CC3300') onClick=Set('CC3300') height="10px" width="10px"></td>\r
+<td bgcolor=#CC6600 onMouseOver=View('CC6600') onClick=Set('CC6600') height="10px" width="10px"></td>\r
+<td bgcolor=#CC9900 onMouseOver=View('CC9900') onClick=Set('CC9900') height="10px" width="10px"></td>\r
+<td bgcolor=#CCCC00 onMouseOver=View('CCCC00') onClick=Set('CCCC00') height="10px" width="10px"></td>\r
+<td bgcolor=#CCFF00 onMouseOver=View('CCFF00') onClick=Set('CCFF00') height="10px" width="10px"></td>\r
+<td bgcolor=#FF0000 onMouseOver=View('FF0000') onClick=Set('FF0000') height="10px" width="10px"></td>\r
+<td bgcolor=#FF3300 onMouseOver=View('FF3300') onClick=Set('FF3300') height="10px" width="10px"></td>\r
+<td bgcolor=#FF6600 onMouseOver=View('FF6600') onClick=Set('FF6600') height="10px" width="10px"></td>\r
+<td bgcolor=#FF9900 onMouseOver=View('FF9900') onClick=Set('FF9900') height="10px" width="10px"></td>\r
+<td bgcolor=#FFCC00 onMouseOver=View('FFCC00') onClick=Set('FFCC00') height="10px" width="10px"></td>\r
+<td bgcolor=#FFFF00 onMouseOver=View('FFFF00') onClick=Set('FFFF00') height="10px" width="10px"></td>\r
+</tr>\r
+<tr>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#00FF00 onMouseOver=View('00FF00') onClick=Set('00FF00') height="10px" width="10px"></td>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#990033 onMouseOver=View('990033') onClick=Set('990033') height="10px" width="10px"></td>\r
+<td bgcolor=#993333 onMouseOver=View('993333') onClick=Set('993333') height="10px" width="10px"></td>\r
+<td bgcolor=#996633 onMouseOver=View('996633') onClick=Set('996633') height="10px" width="10px"></td>\r
+<td bgcolor=#999933 onMouseOver=View('999933') onClick=Set('999933') height="10px" width="10px"></td>\r
+<td bgcolor=#99CC33 onMouseOver=View('99CC33') onClick=Set('99CC33') height="10px" width="10px"></td>\r
+<td bgcolor=#99FF33 onMouseOver=View('99FF33') onClick=Set('99FF33') height="10px" width="10px"></td>\r
+<td bgcolor=#CC0033 onMouseOver=View('CC0033') onClick=Set('CC0033') height="10px" width="10px"></td>\r
+<td bgcolor=#CC3333 onMouseOver=View('CC3333') onClick=Set('CC3333') height="10px" width="10px"></td>\r
+<td bgcolor=#CC6633 onMouseOver=View('CC6633') onClick=Set('CC6633') height="10px" width="10px"></td>\r
+<td bgcolor=#CC9933 onMouseOver=View('CC9933') onClick=Set('CC9933') height="10px" width="10px"></td>\r
+<td bgcolor=#CCCC33 onMouseOver=View('CCCC33') onClick=Set('CCCC33') height="10px" width="10px"></td>\r
+<td bgcolor=#CCFF33 onMouseOver=View('CCFF33') onClick=Set('CCFF33') height="10px" width="10px"></td>\r
+<td bgcolor=#FF0033 onMouseOver=View('FF0033') onClick=Set('FF0033') height="10px" width="10px"></td>\r
+<td bgcolor=#FF3333 onMouseOver=View('FF3333') onClick=Set('FF3333') height="10px" width="10px"></td>\r
+<td bgcolor=#FF6633 onMouseOver=View('FF6633') onClick=Set('FF6633') height="10px" width="10px"></td>\r
+<td bgcolor=#FF9933 onMouseOver=View('FF9933') onClick=Set('FF9933') height="10px" width="10px"></td>\r
+<td bgcolor=#FFCC33 onMouseOver=View('FFCC33') onClick=Set('FFCC33') height="10px" width="10px"></td>\r
+<td bgcolor=#FFFF33 onMouseOver=View('FFFF33') onClick=Set('FFFF33') height="10px" width="10px"></td>\r
+</tr>\r
+<tr>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#0000FF onMouseOver=View('0000FF') onClick=Set('0000FF') height="10px" width="10px"></td>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#990066 onMouseOver=View('990066') onClick=Set('990066') height="10px" width="10px"></td>\r
+<td bgcolor=#993366 onMouseOver=View('993366') onClick=Set('993366') height="10px" width="10px"></td>\r
+<td bgcolor=#996666 onMouseOver=View('996666') onClick=Set('996666') height="10px" width="10px"></td>\r
+<td bgcolor=#999966 onMouseOver=View('999966') onClick=Set('999966') height="10px" width="10px"></td>\r
+<td bgcolor=#99CC66 onMouseOver=View('99CC66') onClick=Set('99CC66') height="10px" width="10px"></td>\r
+<td bgcolor=#99FF66 onMouseOver=View('99FF66') onClick=Set('99FF66') height="10px" width="10px"></td>\r
+<td bgcolor=#CC0066 onMouseOver=View('CC0066') onClick=Set('CC0066') height="10px" width="10px"></td>\r
+<td bgcolor=#CC3366 onMouseOver=View('CC3366') onClick=Set('CC3366') height="10px" width="10px"></td>\r
+<td bgcolor=#CC6666 onMouseOver=View('CC6666') onClick=Set('CC6666') height="10px" width="10px"></td>\r
+<td bgcolor=#CC9966 onMouseOver=View('CC9966') onClick=Set('CC9966') height="10px" width="10px"></td>\r
+<td bgcolor=#CCCC66 onMouseOver=View('CCCC66') onClick=Set('CCCC66') height="10px" width="10px"></td>\r
+<td bgcolor=#CCFF66 onMouseOver=View('CCFF66') onClick=Set('CCFF66') height="10px" width="10px"></td>\r
+<td bgcolor=#FF0066 onMouseOver=View('FF0066') onClick=Set('FF0066') height="10px" width="10px"></td>\r
+<td bgcolor=#FF3366 onMouseOver=View('FF3366') onClick=Set('FF3366') height="10px" width="10px"></td>\r
+<td bgcolor=#FF6666 onMouseOver=View('FF6666') onClick=Set('FF6666') height="10px" width="10px"></td>\r
+<td bgcolor=#FF9966 onMouseOver=View('FF9966') onClick=Set('FF9966') height="10px" width="10px"></td>\r
+<td bgcolor=#FFCC66 onMouseOver=View('FFCC66') onClick=Set('FFCC66') height="10px" width="10px"></td>\r
+<td bgcolor=#FFFF66 onMouseOver=View('FFFF66') onClick=Set('FFFF66') height="10px" width="10px"></td>\r
+</tr>\r
+<tr>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#FFFF00 onMouseOver=View('FFFF00') onClick=Set('FFFF00') height="10px" width="10px"></td>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#990099 onMouseOver=View('990099') onClick=Set('990099') height="10px" width="10px"></td>\r
+<td bgcolor=#993399 onMouseOver=View('993399') onClick=Set('993399') height="10px" width="10px"></td>\r
+<td bgcolor=#996699 onMouseOver=View('996699') onClick=Set('996699') height="10px" width="10px"></td>\r
+<td bgcolor=#999999 onMouseOver=View('999999') onClick=Set('999999') height="10px" width="10px"></td>\r
+<td bgcolor=#99CC99 onMouseOver=View('99CC99') onClick=Set('99CC99') height="10px" width="10px"></td>\r
+<td bgcolor=#99FF99 onMouseOver=View('99FF99') onClick=Set('99FF99') height="10px" width="10px"></td>\r
+<td bgcolor=#CC0099 onMouseOver=View('CC0099') onClick=Set('CC0099') height="10px" width="10px"></td>\r
+<td bgcolor=#CC3399 onMouseOver=View('CC3399') onClick=Set('CC3399') height="10px" width="10px"></td>\r
+<td bgcolor=#CC6699 onMouseOver=View('CC6699') onClick=Set('CC6699') height="10px" width="10px"></td>\r
+<td bgcolor=#CC9999 onMouseOver=View('CC9999') onClick=Set('CC9999') height="10px" width="10px"></td>\r
+<td bgcolor=#CCCC99 onMouseOver=View('CCCC99') onClick=Set('CCCC99') height="10px" width="10px"></td>\r
+<td bgcolor=#CCFF99 onMouseOver=View('CCFF99') onClick=Set('CCFF99') height="10px" width="10px"></td>\r
+<td bgcolor=#FF0099 onMouseOver=View('FF0099') onClick=Set('FF0099') height="10px" width="10px"></td>\r
+<td bgcolor=#FF3399 onMouseOver=View('FF3399') onClick=Set('FF3399') height="10px" width="10px"></td>\r
+<td bgcolor=#FF6699 onMouseOver=View('FF6699') onClick=Set('FF6699') height="10px" width="10px"></td>\r
+<td bgcolor=#FF9999 onMouseOver=View('FF9999') onClick=Set('FF9999') height="10px" width="10px"></td>\r
+<td bgcolor=#FFCC99 onMouseOver=View('FFCC99') onClick=Set('FFCC99') height="10px" width="10px"></td>\r
+<td bgcolor=#FFFF99 onMouseOver=View('FFFF99') onClick=Set('FFFF99') height="10px" width="10px"></td>\r
+</tr>\r
+<tr>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#00FFFF onMouseOver=View('00FFFF') onClick=Set('00FFFF') height="10px" width="10px"></td>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#9900CC onMouseOver=View('9900CC') onClick=Set('9900CC') height="10px" width="10px"></td>\r
+<td bgcolor=#9933CC onMouseOver=View('9933CC') onClick=Set('9933CC') height="10px" width="10px"></td>\r
+<td bgcolor=#9966CC onMouseOver=View('9966CC') onClick=Set('9966CC') height="10px" width="10px"></td>\r
+<td bgcolor=#9999CC onMouseOver=View('9999CC') onClick=Set('9999CC') height="10px" width="10px"></td>\r
+<td bgcolor=#99CCCC onMouseOver=View('99CCCC') onClick=Set('99CCCC') height="10px" width="10px"></td>\r
+<td bgcolor=#99FFCC onMouseOver=View('99FFCC') onClick=Set('99FFCC') height="10px" width="10px"></td>\r
+<td bgcolor=#CC00CC onMouseOver=View('CC00CC') onClick=Set('CC00CC') height="10px" width="10px"></td>\r
+<td bgcolor=#CC33CC onMouseOver=View('CC33CC') onClick=Set('CC33CC') height="10px" width="10px"></td>\r
+<td bgcolor=#CC66CC onMouseOver=View('CC66CC') onClick=Set('CC66CC') height="10px" width="10px"></td>\r
+<td bgcolor=#CC99CC onMouseOver=View('CC99CC') onClick=Set('CC99CC') height="10px" width="10px"></td>\r
+<td bgcolor=#CCCCCC onMouseOver=View('CCCCCC') onClick=Set('CCCCCC') height="10px" width="10px"></td>\r
+<td bgcolor=#CCFFCC onMouseOver=View('CCFFCC') onClick=Set('CCFFCC') height="10px" width="10px"></td>\r
+<td bgcolor=#FF00CC onMouseOver=View('FF00CC') onClick=Set('FF00CC') height="10px" width="10px"></td>\r
+<td bgcolor=#FF33CC onMouseOver=View('FF33CC') onClick=Set('FF33CC') height="10px" width="10px"></td>\r
+<td bgcolor=#FF66CC onMouseOver=View('FF66CC') onClick=Set('FF66CC') height="10px" width="10px"></td>\r
+<td bgcolor=#FF99CC onMouseOver=View('FF99CC') onClick=Set('FF99CC') height="10px" width="10px"></td>\r
+<td bgcolor=#FFCCCC onMouseOver=View('FFCCCC') onClick=Set('FFCCCC') height="10px" width="10px"></td>\r
+<td bgcolor=#FFFFCC onMouseOver=View('FFFFCC') onClick=Set('FFFFCC') height="10px" width="10px"></td>\r
+</tr>\r
+<tr>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#FF00FF onMouseOver=View('FF00FF') onClick=Set('FF00FF') height="10px" width="10px"></td>\r
+<td bgcolor=#000000 onMouseOver=View('000000') onClick=Set('000000') height="10px" width="10px"></td>\r
+<td bgcolor=#9900FF onMouseOver=View('9900FF') onClick=Set('9900FF') height="10px" width="10px"></td>\r
+<td bgcolor=#9933FF onMouseOver=View('9933FF') onClick=Set('9933FF') height="10px" width="10px"></td>\r
+<td bgcolor=#9966FF onMouseOver=View('9966FF') onClick=Set('9966FF') height="10px" width="10px"></td>\r
+<td bgcolor=#9999FF onMouseOver=View('9999FF') onClick=Set('9999FF') height="10px" width="10px"></td>\r
+<td bgcolor=#99CCFF onMouseOver=View('99CCFF') onClick=Set('99CCFF') height="10px" width="10px"></td>\r
+<td bgcolor=#99FFFF onMouseOver=View('99FFFF') onClick=Set('99FFFF') height="10px" width="10px"></td>\r
+<td bgcolor=#CC00FF onMouseOver=View('CC00FF') onClick=Set('CC00FF') height="10px" width="10px"></td>\r
+<td bgcolor=#CC33FF onMouseOver=View('CC33FF') onClick=Set('CC33FF') height="10px" width="10px"></td>\r
+<td bgcolor=#CC66FF onMouseOver=View('CC66FF') onClick=Set('CC66FF') height="10px" width="10px"></td>\r
+<td bgcolor=#CC99FF onMouseOver=View('CC99FF') onClick=Set('CC99FF') height="10px" width="10px"></td>\r
+<td bgcolor=#CCCCFF onMouseOver=View('CCCCFF') onClick=Set('CCCCFF') height="10px" width="10px"></td>\r
+<td bgcolor=#CCFFFF onMouseOver=View('CCFFFF') onClick=Set('CCFFFF') height="10px" width="10px"></td>\r
+<td bgcolor=#FF00FF onMouseOver=View('FF00FF') onClick=Set('FF00FF') height="10px" width="10px"></td>\r
+<td bgcolor=#FF33FF onMouseOver=View('FF33FF') onClick=Set('FF33FF') height="10px" width="10px"></td>\r
+<td bgcolor=#FF66FF onMouseOver=View('FF66FF') onClick=Set('FF66FF') height="10px" width="10px"></td>\r
+<td bgcolor=#FF99FF onMouseOver=View('FF99FF') onClick=Set('FF99FF') height="10px" width="10px"></td>\r
+<td bgcolor=#FFCCFF onMouseOver=View('FFCCFF') onClick=Set('FFCCFF') height="10px" width="10px"></td>\r
+<td bgcolor=#FFFFFF onMouseOver=View('FFFFFF') onClick=Set('FFFFFF') height="10px" width="10px"></td>\r
+</tr>\r
+</table>\r
+\r
+</body></html>\r
diff --git a/htmlarea/popupwin.js b/htmlarea/popupwin.js
new file mode 100644 (file)
index 0000000..701d0ac
--- /dev/null
@@ -0,0 +1,139 @@
+// (c) dynarch.com 2003-2004
+// Distributed under the same terms as HTMLArea itself.
+
+function PopupWin(editor, title, handler, initFunction) {
+       this.editor = editor;
+       this.handler = handler;
+       var dlg = window.open("", "__ha_dialog",
+                             "toolbar=no,menubar=no,personalbar=no,width=600,height=600,left=20,top=40" +
+                             "scrollbars=no,resizable=no");
+       this.window = dlg;
+       var doc = dlg.document;
+       this.doc = doc;
+       var self = this;
+
+       var base = document.baseURI || document.URL;
+       if (base && base.match(/(.*)\/([^\/]+)/)) {
+               base = RegExp.$1 + "/";
+       }
+       if (typeof _editor_url != "undefined" && !/^\//.test(_editor_url) && !/http:\/\//.test(_editor_url)) {
+               // _editor_url doesn't start with '/' which means it's relative
+               // FIXME: there's a problem here, it could be http:// which
+               // doesn't start with slash but it's not relative either.
+               base += _editor_url;
+       } else
+               base = _editor_url;
+       if (!/\/$/.test(base)) {
+               // base does not end in slash, add it now
+               base += '/';
+       }
+       this.baseURL = base;
+
+       doc.open();
+       var html = "<html><head><title>" + title + "</title>\n";
+       // html += "<base href='" + base + "htmlarea.js' />\n";
+       html += "<style type='text/css'>@import url(" + base + "htmlarea.css);</style></head>\n";
+       html += "<body class='dialog popupwin' id='--HA-body'></body></html>";
+       doc.write(html);
+       doc.close();
+
+       // sometimes I Hate Mozilla... ;-(
+       function init2() {
+               var body = doc.body;
+               if (!body) {
+                       setTimeout(init2, 25);
+                       return false;
+               }
+               dlg.title = title;
+               doc.documentElement.style.padding = "0px";
+               doc.documentElement.style.margin = "0px";
+               var content = doc.createElement("div");
+               content.className = "content";
+               self.content = content;
+               body.appendChild(content);
+               self.element = body;
+               initFunction(self);
+               dlg.focus();
+       };
+       init2();
+};
+
+PopupWin.prototype.callHandler = function() {
+       var tags = ["input", "textarea", "select"];
+       var params = new Object();
+       for (var ti = tags.length; --ti >= 0;) {
+               var tag = tags[ti];
+               var els = this.content.getElementsByTagName(tag);
+               for (var j = 0; j < els.length; ++j) {
+                       var el = els[j];
+                       var val = el.value;
+                       if (el.tagName.toLowerCase() == "input") {
+                               if (el.type == "checkbox") {
+                                       val = el.checked;
+                               }
+                       }
+                       params[el.name] = val;
+               }
+       }
+       this.handler(this, params);
+       return false;
+};
+
+PopupWin.prototype.close = function() {
+       this.window.close();
+};
+
+PopupWin.prototype.addButtons = function() {
+       var self = this;
+       var div = this.doc.createElement("div");
+       this.content.appendChild(div);
+       div.className = "buttons";
+       for (var i = 0; i < arguments.length; ++i) {
+               var btn = arguments[i];
+               var button = this.doc.createElement("button");
+               div.appendChild(button);
+               button.innerHTML = HTMLArea.I18N.buttons[btn];
+               switch (btn) {
+                   case "ok":
+                       button.onclick = function() {
+                               self.callHandler();
+                               self.close();
+                               return false;
+                       };
+                       break;
+                   case "cancel":
+                       button.onclick = function() {
+                               self.close();
+                               return false;
+                       };
+                       break;
+               }
+       }
+};
+
+PopupWin.prototype.showAtElement = function() {
+       var self = this;
+       // Mozilla needs some time to realize what's goin' on..
+       setTimeout(function() {
+               var w = self.content.offsetWidth + 4;
+               var h = self.content.offsetHeight + 4;
+               // size to content -- that's fuckin' buggy in all fuckin' browsers!!!
+               // so that we set a larger size for the dialog window and then center
+               // the element inside... phuck!
+
+               // center...
+               var el = self.content;
+               var s = el.style;
+               // s.width = el.offsetWidth + "px";
+               // s.height = el.offsetHeight + "px";
+               s.position = "absolute";
+               s.left = (w - el.offsetWidth) / 2 + "px";
+               s.top = (h - el.offsetHeight) / 2 + "px";
+               if (HTMLArea.is_gecko) {
+                       self.window.innerWidth = w;
+                       self.window.innerHeight = h;
+               } else {
+                       self.window.resizeTo(w + 8, h + 35);
+               }
+       }, 25);
+};
diff --git a/htmlarea/reference.html b/htmlarea/reference.html
new file mode 100644 (file)
index 0000000..0760a73
--- /dev/null
@@ -0,0 +1,523 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN">
+<html> <head>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+<title>HTMLArea-3.0 Reference</title>
+
+<style type="text/css">
+  @import url(htmlarea.css);
+  body { font: 14px verdana,sans-serif; background: #fff; color: #000; }
+  h1, h2 { font-family:tahoma,sans-serif; }
+  h1 { border-bottom: 2px solid #000; }
+  h2 { border-bottom: 1px solid #aaa; }
+  h3, h4 { margin-bottom: 0px; font-family: Georgia,serif; font-style: italic; }
+  h4 { font-size: 90%; margin-left: 1em; }
+  acronym { border-bottom: 1px dotted #063; color: #063; }
+  p { margin-left: 2em; margin-top: 0.3em; }
+  li p { margin-left: 0px; }
+  .abstract { padding: 5px; margin: 0px 10em; font-size: 90%; border: 1px dashed #aaa; background: #eee;}
+  li { margin-left: 2em; }
+  em { color: #042; }
+  a { color: #00f; }
+  a:hover { color: #f00; }
+  a:active { color: #f80; }
+  span.browser { font-weight: bold; color: #864; }
+  .fixme { font-size: 20px; font-weight: bold; color: red; background: #fab;
+padding: 5px; text-align: center; }
+  .code {
+   background: #e4efff; padding: 5px; border: 1px dashed #abc; margin-left: 2em; margin-right: 2em;
+   font-family: fixed,"lucidux mono","andale mono","courier new",monospace;
+  }
+  .note, .warning { font-weight: bold; color: #0a0; font-variant: small-caps; }
+  .warning { color: #a00; }
+
+.string {
+  color: #06c;
+} /* font-lock-string-face */
+.comment {
+  color: #840;
+} /* font-lock-comment-face */
+.variable-name {
+  color: #000;
+} /* font-lock-variable-name-face */
+.type {
+  color: #008;
+  font-weight: bold;
+} /* font-lock-type-face */
+.reference {
+  color: #048;
+} /* font-lock-reference-face */
+.preprocessor {
+  color: #808;
+} /* font-lock-preprocessor-face */
+.keyword {
+  color: #00f;
+  font-weight: bold;
+} /* font-lock-keyword-face */
+.function-name {
+  color: #044;
+} /* font-lock-function-name-face */
+.html-tag {
+  font-weight: bold;
+} /* html-tag-face */
+.html-helper-italic {
+  font-style: italic;
+} /* html-helper-italic-face */
+.html-helper-bold {
+  font-weight: bold;
+} /* html-helper-bold-face */
+
+</style>
+
+<script type="text/javascript">
+  _editor_url = './';
+  _editor_lang = 'en';
+</script>
+<script type="text/javascript" src="htmlarea.js"></script>
+<script type="text/javascript" src="dialog.js"></script>
+<script tyle="text/javascript" src="lang/en.js"></script>
+
+</head>
+
+<body onload="HTMLArea.replace('TA')">
+
+
+<h1>HTMLArea-3.0 Documentation</h1>
+
+<div class="abstract" style="color: red; font-weight: bold">
+
+      This documentation contains valid information, but is outdated in the
+      terms that it does not covers all the features of HTMLArea.  A new
+      documentation project will be started, based on LaTeX.
+
+</div>
+
+
+<h2>Introduction</h2>
+
+<h3>What is HTMLArea?</h3>
+
+<p>HTMLArea is a free <acronym title="What You See Is What You Get"
+>WYSIWYG</acronym> editor replacement for <code>&lt;textarea&gt;</code>
+fields.  By adding a few simple lines of JavaScript code to your web page
+you can replace a regular textarea with a rich text editor that lets your
+users do the following:</p>
+
+<ul>
+  <li>Format text to be bold, italicized, or underlined.</li>
+  <li>Change the face, size, style and color.</li>
+  <li>Left, center, or right-justify paragraphs.</li>
+  <li>Make bulleted or numbered lists.</li>
+  <li>Indent or un-indent paragraphs.</li>
+  <li>Insert a horizontal line.</li>
+  <li>Insert hyperlinks and images.</li>
+  <li>View the raw HTML source of what they're editing.</li>
+  <li>and much more...</li>
+</ul>
+
+<p>Some of the interesting features of HTMLArea that set's it apart from
+other web based WYSIWYG editors are as follows:</p>
+
+<ul>
+  <li>It's lightweight, fast loading and can transform a regular textarea
+  into a rich-text editor with a single line of JavaScript.</li>
+  <li>Generates clean, valid HTML.</li>
+  <li>It degrades gracefully to older or non-supported browsers
+  (they get the original textarea field).</li>
+  <li>It's free and can be incorporated into any free or commercial
+  program.</li>
+  <li>It works with any server-side languages (ASP, PHP, Perl, Java,
+  etc).</li>
+  <li>It's written in JavaScript and can be easily viewed, modified or
+  extended.</li>
+  <li>It remembers entered content when a user navigates away and then hits
+  "back" in their browser.</li>
+  <li>Since it replaces existing textareas it doesn't require a lot of code
+  to add it to your pages (just one line).</li>
+  <li>Did we mention it was free? ;-)</li>
+</ul>
+
+<h3>Is it really free?  What's the catch?</h3>
+
+<p>Yes! It's really free. You can use it, modify it, distribute it with your
+software, or do just about anything you like with it.</p>
+
+<h3>What are the browser requirements?</h3>
+
+<p>HTMLArea requires <span class="browser"><a
+href="http://www.microsoft.com/ie">Internet Explorer</a> &gt;= 5.5</span>
+(Windows only), or <span class="browser"><a
+href="http://mozilla.org">Mozilla</a> &gt;= 1.3-Beta</span> on any platform.
+Any browser based on <a href="http://mozilla.org/newlayout">Gecko</a> will
+also work, provided that Gecko version is at least the one included in
+Mozilla-1.3-Beta (for example, <a
+href="http://galeon.sf.net">Galeon-1.2.8</a>).  However, it degrades
+gracefully to other browsers. They will get a regular textarea field
+instead of a WYSIWYG editor.</p>
+
+<h3>Can I see an example of what it looks like?</h3>
+
+<p>Just make sure you're using one of the browsers mentioned above and see
+below.</p>
+
+<form onsubmit="return false;">
+<textarea id="TA" style="width: 100%; height: 15em;">
+<p>Here is some sample text in textarea that's been transformed with <font
+color="#0000CC"><b>HTMLArea</b></font>.<br />
+You can make things <b>bold</b>, <i>italic</i>, <u>underline</u>.  You can change the
+<font size="3">size</font> and <b><font color="#0000CC">c</font><font color="#00CC00">o</font><font color="#00CCCC">l</font><font color="#CC0000">o</font><font color="#CC00CC">r</font><font color="#CCCC00">s</font><font color="#CCCCCC">!</font></b>
+And lots more...</p>
+
+<p align="center"><font size="4" color="#ff0000"><b><u>Try HTMLArea
+today!</u></b></font><br /></p>
+</textarea>
+</form>
+
+<h3>Where can I find out more info, download the latest version and talk to
+other HTMLArea users?</h3>
+
+<p>You can find out more about HTMLArea and download the latest version on
+the <a href="http://dynarch.com/htmlarea/">HTMLArea
+homepage</a> and you can talk to other HTMLArea users and post any comments
+or suggestions you have in the <a
+href="http://www.interactivetools.com/iforum/Open_Source_C3/htmlArea_v3.0_-_Alpha_Release_F14/"
+>HTMLArea forum</a>.</p>
+
+<h2>Keyboard shortcuts</h2>
+
+<p>The editor provides the following key combinations:</p>
+
+<ul>
+  <li>CTRL-A -- select all</li>
+  <li>CTRL-B -- bold</li>
+  <li>CTRL-I -- italic</li>
+  <li>CTRL-U -- underline</li>
+  <li>CTRL-S -- strikethrough</li>
+  <li>CTRL-L -- justify left</li>
+  <li>CTRL-E -- justify center</li>
+  <li>CTRL-R -- justify right</li>
+  <li>CTRL-J -- justify full</li>
+  <li>CTRL-1 .. CTRL-6 -- headings (&lt;h1&gt; .. &lt;h6&gt;)</li>
+  <li>CTRL-0 (zero) -- clean content pasted from Word</li>
+</ul>
+
+<h2>Installation</h2>
+
+<h3>How do I add HTMLArea to my web page?</h3>
+
+<p>It's easy.  First you need to upload HTMLArea files to your website.
+Just follow these steps.</p>
+
+<ol>
+  <li>Download the latest version from the <a
+  href="http://www.interactivetools.com/products/htmlarea/">htmlArea
+  homepage</a>.</li>
+  <li>Unzip the files onto your local computer (making sure to maintain the
+  directory structure contained in the zip).</li>
+  <li>Create a new folder on your website called /htmlarea/ (make sure it's
+  NOT inside the cgi-bin).</li>
+  <li>Transfer all the HTMLArea files from your local computer into the
+  /htmlarea/ folder on your website.</li>
+  <li>Open the example page /htmlarea/examples/core.html with your browser to make
+  sure everything works.</li>
+</ol>
+
+<p>Once htmlArea is on your website all you need to do is add some
+JavaScript to any pages that you want to add WYSIWYG editors to.  Here's how
+to do that.</p>
+
+<ol>
+
+  <li>Define some global variables.  "_editor_url" has to be the absolute
+  URL where HTMLArea resides within your
+  website; as we discussed, this would be “/htmlarea/”.  "_editor_lang" must
+  be the language code in which you want HTMLArea to appear.  This defaults
+  to "en" (English); for a list of supported languages, please look into
+  the "lang" subdirectory in the distribution.
+  <pre class="code"
+  ><span class="function-name">&lt;</span><span class="html-tag">script</span> <span class="variable-name">type=</span><span class="string">&quot;text/javascript&quot;</span><span class="function-name">&gt;</span>
+   _editor_url = <span class="string">&quot;/htmlarea/&quot;</span>;
+   _editor_lang = <span class="string">&quot;en&quot;</span>;
+<span class="function-name">&lt;</span><span class="html-tag">/script</span><span class="function-name">&gt;</span></pre>
+
+  <li>Include the "htmlarea.js" script:
+  <pre class="code"
+  ><span class="function-name">&lt;</span><span class="html-tag">script</span> <span class="variable-name">type=</span><span class="string">&quot;text/javascript&quot;</span> <span class="variable-name">src=</span><span class="string">&quot;/htmlarea/htmlarea.js&quot;</span><span class="function-name">&gt;</span><span class="paren-face-match">&lt;</span><span class="html-tag">/script</span><span class="paren-face-match">&gt;</span></pre>
+  </li>
+
+  <li><p>If you want to change all your &lt;textarea&gt;-s into
+  HTMLArea-s then you can use the simplest way to create HTMLArea:</p>
+  <pre class="code"
+  ><span class="function-name">&lt;</span><span class="html-tag">script</span> <span class="variable-name">type=</span><span class="string">&quot;text/javascript&quot;</span> <span class="variable-name">defer=</span><span class="string">&quot;1&quot;</span><span class="function-name">&gt;</span>
+    HTMLArea.replaceAll<span class="function-name">()</span>;
+<span class="paren-face-match">&lt;</span><span class="html-tag">/script</span><span class="paren-face-match">&gt;</span></pre>
+  <p><span class="note">Note:</span> you can also add the
+  <code>HTMLArea.replaceAll()</code> code to the <code>onload</code>
+  event handler for the <code>body</code> element, if you find it more appropriate.</p>
+
+  <p>A different approach, if you have more than one textarea and only want
+  to change one of them, is to use <code>HTMLArea.replace("id")</code> --
+  pass the <code>id</code> of your textarea.  Do not use the
+  <code>name</code> attribute anymore, it's not a standard solution!</p>
+
+</ol>
+
+<p>This section applies to HTMLArea-3.0 release candidate 1 or later; prior
+to this version, one needed to include more files; however, now HTMLArea is
+able to include other files too (such as stylesheet, language definition
+file, etc.) so you only need to define the editor path and load
+"htmlarea.js".  Nice, eh? ;-)</p>
+
+<h3>I want to change the editor settings, how do I do that?</h3>
+
+<p>While it's true that all you need is one line of JavaScript to create an
+htmlArea WYSIWYG editor, you can also specify more config settings in the
+code to control how the editor works and looks.  Here's an example of some of
+the available settings:</p>
+
+<pre class="code"
+><span class="keyword">var</span> <span class="variable-name">config</span> = <span class="keyword">new</span> HTMLArea.Config(); <span class="comment">// create a new configuration object
+</span>                                    <span class="comment">// having all the default values
+</span>config.width = '<span class="string">90%</span>';
+config.height = '<span class="string">200px</span>';
+
+<span class="comment">// the following sets a style for the page body (black text on yellow page)
+// and makes all paragraphs be bold by default
+</span>config.pageStyle =
+  '<span class="string">body { background-color: yellow; color: black; font-family: verdana,sans-serif } </span>' +
+  '<span class="string">p { font-width: bold; } </span>';
+
+<span class="comment">// the following replaces the textarea with the given id with a new
+// HTMLArea object having the specified configuration
+</span>HTMLArea.replace('<span class="string">id</span>', config);</pre>
+
+<p><span class="warning">Important:</span> It's recommended that you add
+custom features and configuration to a separate file.  This will ensure you
+that when we release a new official version of HTMLArea you'll have less
+trouble upgrading it.</p>
+
+<h3>How do I customize the toolbar?</h3>
+
+<p>Using the configuration object introduced above allows you to completely
+control what the toolbar contains.  Following is an example of a one-line,
+customized toolbar, much simpler than the default one:</p>
+
+<pre class="code"
+><span class="keyword">var</span> <span class="variable-name">config</span> = <span class="keyword">new</span> HTMLArea.Config();
+config.toolbar = [
+  ['<span class="string">fontname</span>', '<span class="string">space</span>',
+   '<span class="string">fontsize</span>', '<span class="string">space</span>',
+   '<span class="string">formatblock</span>', '<span class="string">space</span>',
+   '<span class="string">bold</span>', '<span class="string">italic</span>', '<span class="string">underline</span>']
+];
+HTMLArea.replace('<span class="string">id</span>', config);</pre>
+
+<p>The toolbar is an Array of Array objects.  Each array in the toolbar
+defines a new line.  The default toolbar looks like this:</p>
+
+<pre class="code"
+>config.toolbar = [
+[ &quot;<span class="string">fontname</span>&quot;, &quot;<span class="string">space</span>&quot;,
+  &quot;<span class="string">fontsize</span>&quot;, &quot;<span class="string">space</span>&quot;,
+  &quot;<span class="string">formatblock</span>&quot;, &quot;<span class="string">space</span>&quot;,
+  &quot;<span class="string">bold</span>&quot;, &quot;<span class="string">italic</span>&quot;, &quot;<span class="string">underline</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">strikethrough</span>&quot;, &quot;<span class="string">subscript</span>&quot;, &quot;<span class="string">superscript</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">copy</span>&quot;, &quot;<span class="string">cut</span>&quot;, &quot;<span class="string">paste</span>&quot;, &quot;<span class="string">space</span>&quot;, &quot;<span class="string">undo</span>&quot;, &quot;<span class="string">redo</span>&quot; ],
+               
+[ &quot;<span class="string">justifyleft</span>&quot;, &quot;<span class="string">justifycenter</span>&quot;, &quot;<span class="string">justifyright</span>&quot;, &quot;<span class="string">justifyfull</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">insertorderedlist</span>&quot;, &quot;<span class="string">insertunorderedlist</span>&quot;, &quot;<span class="string">outdent</span>&quot;, &quot;<span class="string">indent</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">forecolor</span>&quot;, &quot;<span class="string">hilitecolor</span>&quot;, &quot;<span class="string">textindicator</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">inserthorizontalrule</span>&quot;, &quot;<span class="string">createlink</span>&quot;, &quot;<span class="string">insertimage</span>&quot;, &quot;<span class="string">inserttable</span>&quot;, &quot;<span class="string">htmlmode</span>&quot;, &quot;<span class="string">separator</span>&quot;,
+  &quot;<span class="string">popupeditor</span>&quot;, &quot;<span class="string">separator</span>&quot;, &quot;<span class="string">showhelp</span>&quot;, &quot;<span class="string">about</span>&quot; ]
+];</pre>
+
+<p>Except three strings, all others in the examples above need to be defined
+in the <code>config.btnList</code> object (detailed a bit later in this
+document).  The three exceptions are: 'space', 'separator' and 'linebreak'.
+These three have the following meaning, and need not be present in
+<code>btnList</code>:</p>
+
+<ul>
+  <li>'space' -- Inserts a space of 5 pixels (the width is configurable by external
+  <acronym title="Cascading Style Sheets">CSS</acronym>) at the current
+  position in the toolbar.</li>
+  <li>'separator' -- Inserts a small vertical separator, for visually grouping related
+  buttons.</li>
+  <li>'linebreak' -- Starts a new line in the toolbar.  Subsequent controls will be
+  inserted on the new line.</li>
+</ul>
+
+<p><span class="warning">Important:</span> It's recommended that you add
+custom features and configuration to a separate file.  This will ensure you
+that when we release a new official version of HTMLArea you'll have less
+trouble upgrading it.</p>
+
+<h3>How do I create custom buttons?</h3>
+
+<p>By design, the toolbar is easily extensible.  For adding a custom button
+one needs to follow two steps.</p>
+
+<h4 id="regbtn">1. Register the button in <code>config.btnList</code>.</h4>
+
+<p>For each button in the toolbar, HTMLArea needs to know the following
+information:</p>
+<ul>
+  <li>a name for it (we call it the ID of the button);</li>
+  <li>the path to an image to be displayed in the toolbar;</li>
+  <li>a tooltip for it;</li>
+  <li>whether the button is enabled or not in text mode;</li>
+  <li>what to do when the button is clicked;</li>
+</ul>
+<p>You need to provide all this information for registering a new button
+too.  The button ID can be any string identifier and it's used when
+defining the toolbar, as you saw above.  We recommend starting
+it with "my-" so that it won't clash with the standard ID-s (those from
+the default toolbar).</p>
+
+<p class="note">Register button example #1</p>
+
+<pre class="code"
+><span class="comment">// get a default configuration
+</span><span class="keyword">var</span> <span class="variable-name">config</span> = <span class="keyword">new</span> HTMLArea.Config();
+<span class="comment">// register the new button using Config.registerButton.
+// parameters:        button ID,   tooltip,          image,           textMode,
+</span>config.registerButton(&quot;<span class="string">my-hilite</span>&quot;, &quot;<span class="string">Highlight text</span>&quot;, &quot;<span class="string">my-hilite.gif</span>&quot;, <span class="keyword">false</span>,
+<span class="comment">// function that gets called when the button is clicked
+</span>  <span class="keyword">function</span>(editor, id) {
+    editor.surroundHTML('<span class="string">&lt;span class=&quot;hilite&quot;&gt;</span>', '<span class="string">&lt;/span&gt;</span>');
+  }
+);</pre>
+
+<p>An alternate way of calling registerButton is exemplified above.  Though
+the code might be a little bit larger, using this form makes your code more
+maintainable.  It doesn't even needs comments as it's pretty clear.</p>
+
+<p class="note">Register button example #2</p>
+
+<pre class="code"
+><span class="keyword">var</span> <span class="variable-name">config</span> = <span class="keyword">new</span> HTMLArea.Config();
+config.registerButton({
+  id        : &quot;<span class="string">my-hilite</span>&quot;,
+  tooltip   : &quot;<span class="string">Highlight text</span>&quot;,
+  image     : &quot;<span class="string">my-hilite.gif</span>&quot;,
+  textMode  : <span class="keyword">false</span>,
+  action    : <span class="keyword">function</span>(editor, id) {
+                editor.surroundHTML('<span class="string">&lt;span class=&quot;hilite&quot;&gt;</span>', '<span class="string">&lt;/span&gt;</span>');
+              }
+});</pre>
+
+<p>You might notice that the "action" function receives two parameters:
+<b>editor</b> and <b>id</b>.  In the examples above we only used the
+<b>editor</b> parameter.  But it could be helpful for you to understand
+both:</p>
+
+<ul>
+  <li><b>editor</b> is a reference to the HTMLArea object.  Since our entire
+  code now has an <acronym title="Object Oriented Programming">OOP</acronym>-like
+  design, you need to have a reference to
+  the editor object in order to do things with it.  In previous versions of
+  HTMLArea, in order to identify the object an ID was used -- the ID of the
+  HTML element.  In this version ID-s are no longer necessary.</li>
+
+  <li><b>id</b> is the button ID.  Wondering why is this useful?  Well, you
+  could use the same handler function (presuming that it's not an anonymous
+  function like in the examples above) for more buttons.  You can <a
+  href="#btnex">see an example</a> a bit later in this document.</li>
+</ul>
+
+<h4>2. Inserting it into the toolbar</h4>
+
+<p>At this step you need to specify where in the toolbar to insert the
+button, or just create the whole toolbar again as you saw in the previous
+section.  You use the button ID, as shown in the examples of customizing the
+toolbar in the previous section.</p>
+
+<p>For the sake of completion, following there are another examples.</p>
+
+<p class="note">Append your button to the default toolbar</p>
+
+<pre class="code"
+>config.toolbar.push([ &quot;<span class="string">my-hilite</span>&quot; ]);</pre>
+
+<p class="note">Customized toolbar</p>
+
+<pre class="code"
+>config.toolbar = [
+  ['<span class="string">fontname</span>', '<span class="string">space</span>',
+   '<span class="string">fontsize</span>', '<span class="string">space</span>',
+   '<span class="string">formatblock</span>', '<span class="string">space</span>',
+   '<span class="string">separator</span>', '<span class="string">my-hilite</span>', '<span class="string">separator</span>', '<span class="string">space</span>', <span class="comment">// here's your button
+</span>   '<span class="string">bold</span>', '<span class="string">italic</span>', '<span class="string">underline</span>', '<span class="string">space</span>']
+];</pre>
+
+<p><span class="note">Note:</span> in the example above our new button is
+between two vertical separators.  But this is by no means required.  You can
+put it wherever you like.  Once registered in the btnList (<a
+href="#regbtn">step 1</a>) your custom button behaves just like a default
+button.</p>
+
+<p><span class="warning">Important:</span> It's recommended that you add
+custom features and configuration to a separate file.  This will ensure you
+that when we release a new official version of HTMLArea you'll have less
+trouble upgrading it.</p>
+
+<h4 id="btnex">A complete example</h4>
+
+<p>Please note that it is by no means necessary to include the following
+code into the htmlarea.js file.  On the contrary, it might not work there.
+The configuration system is designed such that you can always customize the
+editor <em>from outside files</em>, thus keeping the htmlarea.js file
+intact.  This will make it easy for you to upgrade your HTMLArea when we
+release a new official version.  OK, I promise it's the last time I said
+this. ;)</p>
+
+<pre class="code"
+><span class="comment">// All our custom buttons will call this function when clicked.
+// We use the <b>buttonId</b> parameter to determine what button
+// triggered the call.
+</span><span class="keyword">function</span> <span class="function-name">clickHandler</span>(editor, buttonId) {
+  <span class="keyword">switch</span> (buttonId) {
+    <span class="keyword">case</span> &quot;<span class="string">my-toc</span>&quot;:
+      editor.insertHTML(&quot;<span class="string">&lt;h1&gt;Table Of Contents&lt;/h1&gt;</span>&quot;);
+      <span class="keyword">break</span>;
+    <span class="keyword">case</span> &quot;<span class="string">my-date</span>&quot;:
+      editor.insertHTML((<span class="keyword">new</span> Date()).toString());
+      <span class="keyword">break</span>;
+    <span class="keyword">case</span> &quot;<span class="string">my-bold</span>&quot;:
+      editor.execCommand(&quot;<span class="string">bold</span>&quot;);
+      editor.execCommand(&quot;<span class="string">italic</span>&quot;);
+      <span class="keyword">break</span>;
+    <span class="keyword">case</span> &quot;<span class="string">my-hilite</span>&quot;:
+      editor.surroundHTML(&quot;<span class="string">&lt;span class=\&quot;hilite\&quot;&gt;</span>&quot;, &quot;<span class="string">&lt;/span&gt;</span>&quot;);
+      <span class="keyword">break</span>;
+  }
+};
+
+<span class="comment">// Create a new configuration object
+</span><span class="keyword">var</span> <span class="variable-name">config</span> = <span class="keyword">new</span> HTMLArea.Config();
+
+<span class="comment">// Register our custom buttons
+</span>config.registerButton(&quot;<span class="string">my-toc</span>&quot;,  &quot;<span class="string">Insert TOC</span>&quot;, &quot;<span class="string">my-toc.gif</span>&quot;, <span class="keyword">false</span>, clickHandler);
+config.registerButton(&quot;<span class="string">my-date</span>&quot;, &quot;<span class="string">Insert date/time</span>&quot;, &quot;<span class="string">my-date.gif</span>&quot;, <span class="keyword">false</span>, clickHandler);
+config.registerButton(&quot;<span class="string">my-bold</span>&quot;, &quot;<span class="string">Toggle bold/italic</span>&quot;, &quot;<span class="string">my-bold.gif</span>&quot;, <span class="keyword">false</span>, clickHandler);
+config.registerButton(&quot;<span class="string">my-hilite</span>&quot;, &quot;<span class="string">Hilite selection</span>&quot;, &quot;<span class="string">my-hilite.gif</span>&quot;, <span class="keyword">false</span>, clickHandler);
+
+<span class="comment">// Append the buttons to the default toolbar
+</span>config.toolbar.push([&quot;<span class="string">linebreak</span>&quot;, &quot;<span class="string">my-toc</span>&quot;, &quot;<span class="string">my-date</span>&quot;, &quot;<span class="string">my-bold</span>&quot;, &quot;<span class="string">my-hilite</span>&quot;]);
+
+<span class="comment">// Replace an existing textarea with an HTMLArea object having the above config.
+</span>HTMLArea.replace(&quot;<span class="string">textAreaID</span>&quot;, config);</pre>
+
+
+<hr />
+<address>&copy; <a href="http://interactivetools.com" title="Visit our website"
+>InteractiveTools.com</a> 2002-2004.
+<br />
+© <a href="http://dynarch.com">dynarch.com</a> 2003-2004<br />
+HTMLArea v3.0 developed by <a
+href="http://dynarch.com/mishoo/">Mihai Bazon</a>.
+<br />
+Documentation written by Mihai Bazon.
+</address>
+<!-- hhmts start --> Last modified: Wed Jan 28 12:18:23 EET 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+</body> </html>
diff --git a/htmlarea/release-notes.html b/htmlarea/release-notes.html
new file mode 100644 (file)
index 0000000..f6b1266
--- /dev/null
@@ -0,0 +1,209 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 3.2//EN">
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <title><% $basename %> release notes</title>
+    <style>
+      .fixme { color: red; }
+    </style>
+  </head>
+
+  <body>
+
+    <h1><% $basename %> release notes</h1>
+
+    <p>This release was compiled on <% $time %>.</p>
+
+    <h2>3.0-rc1</h2>
+
+    <p>Changes since 3.0-Beta:</p>
+
+    <ul>
+      <li>
+        <b>New plugins</b>
+        <ul>
+          <li>
+            ContextMenu plugin (provides a nice context menu with common
+            operations, including table ops, link ops, etc.)
+          </li>
+          <li>
+            CSS plugin (provides an easy way to insert/change CSS classes)
+          </li>
+          <li>
+            FullPage plugin (allows HTMLArea to edit a whole HTML file,
+            not only the content within &lt;body&gt;.)
+          </li>
+        </ul>
+      </li>
+      <li>
+        <b>Changes in the SpellChecker plugin</b>
+        <ul>
+          <li>
+            Many bugfixes: now it works ;-)  Fully Unicode-safe.
+          </li>
+          <li>
+            Speed and bandwidth optimization: reports the list of
+            suggestions only once for each mispelled word; this helps
+            in cases where you have, for instance, the word “HTMLArea”
+            in 10 places all over the document; the list of
+            suggestions for it--which is kind of huge--will only be
+            included <em>once</em>.
+          </li>
+          <li>
+            User interface improvements: the highlighted word will
+            remain in view; in cases where it's normally outside, the
+            window will be scrolled to it.
+          </li>
+          <li>
+            Added a "Revert" button for those that change their minds ;-)
+          </li>
+          <li>
+            Added a "Info" button which reports information about the
+            document, retrieved by the server-side spell checker:
+            total number of words, total number of mispelled words,
+            number of suggestions made, spell check time, etc.  More
+            can be easily added.  <span class="fixme">FIXME: this part
+            is not yet internationalized.</span>
+          </li>
+          <li>
+            The server-side spell checker now uses XML::DOM instead of
+            HTML::Parser, which means that it will be unable to parse
+            “tag-soup” HTML.  It needs valid code.  Usually HTMLArea
+            generates valid code, but on rare occasions it might fail
+            and the spell checker will report a gross error message.
+            This gonna have to be fixed, but instead of making the
+            spell checker accept invalid HTML I prefer to make
+            HTMLArea generate valid code, so changes are to be done in
+            other places ;-)
+          </li>
+        </ul>
+      </li>
+      <li>
+        <b>Changes in the core editor</b>
+        <ul>
+          <li>
+            Easier to setup: you only need to load
+            <tt>htmlarea.js</tt>; other scripts will be loaded
+            automatically.  <a href="reference.html">Documentation</a>
+            and <a href="examples/">examples</a> updated.
+          </li>
+          <li>
+            Better plugin support (they register information about
+            themselves with the editor; can register event handlers for
+            the editor, etc.)
+          </li>
+          <li>
+            New about box; check it out, it's cool ;-)
+          </li>
+          <li>
+            Word cleaner (can be enabled to automatically kill Word crap
+            on paste (see Config.killWordOnPaste); otherwise accessible by
+            pressing CTRL-0 in the editor; a toolbar button will come up
+            soon)
+          </li>
+          <li>
+            Image preview in "insert image" dialog.  Also allows
+            modification of current image, if selected.
+          </li>
+          <li>
+            New "insert link" dialog, allows target and title
+            specification, allows editing links.
+          </li>
+          <li>
+            Implemented support for text direction (left-to-right or
+            right-to-left).
+          </li>
+          <li>
+            Lots of bug fixes!  ... and more, I guess ;-) an
+            automatically generated <a href="ChangeLog">change log</a>
+            is now available.
+          </li>
+        </ul>
+      </li>
+    </ul>
+
+    <p>I don't have the power to go through the <a
+href="http://sourceforge.net/tracker/?atid=525656&group_id=69750&func=browse">bug
+system</a> at SourceForge
+    now.  Some of the bugs reported there may be fixed; I'll update
+    their status, some other time.  If you reported bugs there and now
+    find them to be fixed, please let me know.</p>
+
+    <h2>3.0-Beta</h2>
+
+    <p>Changes since 3.0-Alpha:</p>
+
+    <ul>
+
+      <li>Performance improvements.</li>
+
+      <li>Many bugs fixed.</li>
+
+      <li>Plugin infrastructure.</li>
+
+      <li>TableOperations plugin.</li>
+
+      <li>SpellChecker plugin.</li>
+
+      <li>Status bar.</li>
+
+      <li>API for registering custom buttons and drop-down boxes in the
+        toolbar.</li>
+
+      <li>Toolbar can contain text labels.</li>
+
+      <li>Cut, copy, paste, undo, redo buttons.</li>
+
+    </ul>
+<%doc>
+    <h2>Rationale for Beta</h2>
+
+    <p>Why was this released as "Beta"?  The code is quite stable and it
+    didn't deserve a "Beta" qualification.  However, there are some things
+    left to do for the real 3.0 version.  These things will not affect the
+    API to work with HTMLArea, in other words, you can install the Beta
+    right now and then install the final release without modifying your
+    code.  That's if you don't modify HTMLArea itself.  ;-)</p>
+
+    <h2>To-Do before 3.0 final</h2>
+
+    <ol>
+
+      <li>We should use a single popup interface.  Currently there are two:
+      dialog.js and popupwin.js; dialog.js emulates modal dialogs, which
+      sucks when you want to open "select-color" from another popup and not
+      from the editor itself.  Very buggy in IE.  We should probably use only
+      modeless dialogs (that is, popupwin.js).</li>
+
+      <li>Internationalization for the SpellChecker plugin.</li>
+
+      <li>Internationalization for the TableOperations plugin.</li>
+
+      <li>People who sent translations are invited to re-iterate through
+        their work and make it up-to-date with lang/en.js which is the main
+        lang file for HTMLArea-3.0.  Some things have changed but not all
+        translations are updated.</li>
+
+      <li><strong>Documentation</strong>.</li>
+
+    </ol>
+</%doc>
+    <hr />
+    <address><a href="http://dynarch.com/mishoo/">Mihai Bazon</a></address>
+<!-- Created: Sun Aug  3 16:55:08 EEST 2003 -->
+<!-- hhmts start --> Last modified: Wed Mar 31 19:18:26 EEST 2004 <!-- hhmts end -->
+<!-- doc-lang: English -->
+  </body>
+</html>
+
+<%ARGS>
+  $project => 'HTMLArea'
+  $version => '3.0'
+  $release => 'rc1'
+  $basename => 'HTMLArea-3.0-rc1'
+</%ARGS>
+
+<%INIT>;
+use POSIX qw(strftime);
+my $time = strftime '%b %e, %Y [%H:%M] GMT', gmtime;
+</%INIT>
diff --git a/include/admin/category.inc.php b/include/admin/category.inc.php
new file mode 100644 (file)
index 0000000..f81f3c2
--- /dev/null
@@ -0,0 +1,246 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+if (IN_serendipity !== true) {
+    die ("Don't hack!");
+}
+
+$admin_category = ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF ? "AND (authorid = 0 OR authorid = " . (int)$serendipity['authorid'] . ")" : '');
+
+/* Add a new category */
+if (isset($_POST['SAVE'])) {
+    $name     = $serendipity['POST']['cat']['name'];
+    $desc     = $serendipity['POST']['cat']['description'];
+    $authorid = (isset($serendipity['POST']['cat']['all_authors']) && $serendipity['POST']['cat']['all_authors'] == 'true') ? 0 : $serendipity['authorid'];
+    $icon     = $serendipity['POST']['cat']['icon'];
+    $parentid = (isset($serendipity['POST']['cat']['parent_cat']) && is_numeric($serendipity['POST']['cat']['parent_cat'])) ? $serendipity['POST']['cat']['parent_cat'] : 0;
+
+    if ($serendipity['GET']['adminAction'] == 'new') {
+        if ($parentid != 0) {
+            // TODO: This doesn't seem to work as expected, serendipity_rebuildCategoryTree(); is still needed! Only activate this optimization function when it's really working :)
+            // TODO: This works if only one subcategory exists.  Otherwise, the first query will return an array.
+            /*
+            $res = serendipity_db_query("SELECT category_right FROM {$serendipity['dbPrefix']}category WHERE parentid={$parentid}");
+            serendipity_db_query("UPDATE {$serendipity['dbPrefix']}category SET category_left=category_left+2, category_right=category_right+2 WHERE category_right>{$res}");
+            */
+        }
+
+        /* Check to see if a category with the same name, already exist */
+        $sql = serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}category
+                                        WHERE category_name = '". serendipity_db_escape_string($name) ."'", true);
+        if ( $sql ) {
+            echo '<div class="serendipityAdminMsgError">'. sprintf(CATEGORY_ALREADY_EXIST, htmlspecialchars($name)) .'</div>';
+        } else {
+            $query = "INSERT INTO {$serendipity['dbPrefix']}category
+                            (category_name, category_description, authorid, category_icon, parentid, category_left, category_right)
+                        VALUES ('". serendipity_db_escape_string($name) ."', '". serendipity_db_escape_string($desc) ."', ". (int)$authorid .", '". serendipity_db_escape_string($icon) ."', ". (int)$parentid .", 0, 0)";
+            serendipity_db_query($query);
+            echo '<div class="serendipityAdminMsgSuccess">'. CATEGORY_SAVED .'</div>';
+        }
+
+
+    } elseif ($serendipity['GET']['adminAction'] == 'edit') {
+            /* Check to see if a category with the same name, already exist */
+            $sql = serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}category
+                                                WHERE category_name = '". serendipity_db_escape_string($name) ."'
+                                                    AND categoryid <> ". (int)$serendipity['GET']['cid'], true);
+            if ( $sql ) {
+                echo '<div class="serendipityAdminMsgError">'. sprintf(CATEGORY_ALREADY_EXIST, htmlspecialchars($name)) .'</div>';
+            } else {
+                /* Check to make sure parent is not a child of self */
+                $r = serendipity_db_query("SELECT categoryid FROM {$serendipity['dbPrefix']}category c
+                                                WHERE c.categoryid = ". (int)$parentid ."
+                                                    AND c.category_left BETWEEN " . implode(' AND ', serendipity_fetchCategoryRange((int)$serendipity['GET']['cid'])));
+                if ( is_array($r) ) {
+                    $r = serendipity_db_query("SELECT category_name FROM {$serendipity['dbPrefix']}category
+                                                        WHERE categoryid = ". (int)$parentid);
+                    echo sprintf(ALREADY_SUBCATEGORY, htmlspecialchars($r[0]['category_name']), htmlspecialchars($name));
+                } else {
+                    $query = "UPDATE {$serendipity['dbPrefix']}category
+                                    SET category_name = '". serendipity_db_escape_string($name) ."',
+                                        category_description = '". serendipity_db_escape_string($desc) ."',
+                                        authorid = ". (int)$authorid .",
+                                        category_icon = '". serendipity_db_escape_string($icon) ."',
+                                        parentid = ". (int)$parentid ."
+                                    WHERE categoryid = ". (int)$serendipity['GET']['cid'] ."
+                                        $admin_category";
+                    serendipity_db_query($query);
+                    echo '<div class="serendipityAdminMsgSuccess">'. CATEGORY_SAVED .'</div>';
+                }
+            }
+    }
+
+    serendipity_rebuildCategoryTree();
+    $serendipity['GET']['adminAction'] = 'view';
+}
+
+/* Delete a category */
+if ($serendipity['GET']['adminAction'] == 'doDelete') {
+    if ($serendipity['GET']['cid'] != 0) {
+        $remaining_cat = (int)$serendipity['POST']['cat']['remaining_catid'];
+        $category_range = implode(' AND ', serendipity_fetchCategoryRange((int)$serendipity['GET']['cid']));
+        if ($serendipity['dbType'] == 'postgres' || $serendipity['dbType'] == 'sqlite') {
+            $query = "UPDATE {$serendipity['dbPrefix']}entrycat
+                        SET categoryid={$remaining_cat} WHERE entryid IN
+                        (
+                          SELECT DISTINCT(e.id) FROM {$serendipity['dbPrefix']}entries e,
+                          {$serendipity['dbPrefix']}category c,
+                          {$serendipity['dbPrefix']}entrycat ec
+                          WHERE e.id=ec.entryid AND c.categoryid=ec.categoryid
+                          AND c.category_left BETWEEN {$category_range} {$admin_category}
+                        )";
+        } else {
+            $query = "UPDATE {$serendipity['dbPrefix']}entries e,
+                        {$serendipity['dbPrefix']}entrycat ec,
+                        {$serendipity['dbPrefix']}category c
+                      SET ec.categoryid={$remaining_cat}
+                        WHERE e.id = ec.entryid
+                          AND c.categoryid = ec.categoryid
+                          AND c.category_left BETWEEN {$category_range}
+                          {$admin_category}";
+        }
+        if ( serendipity_db_query($query) ) {
+            if ( serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}category WHERE category_left BETWEEN {$category_range} {$admin_category}") ) {
+                echo '<div class="serendipityAdminMsgSuccess">'. ($remaining_cat ? sprintf(CATEGORY_DELETED_ARTICLES_MOVED, (int)$serendipity['GET']['cid'], $remaining_cat) : sprintf(CATEGORY_DELETED,(int)$serendipity['GET']['cid'])) .'</div>';
+                $serendipity['GET']['adminAction'] = 'view';
+            }
+        }
+    } else {
+        echo '<div class="serendipityAdminMsgError">'. INVALID_CATEGORY .'</div>';
+    }
+}
+?>
+
+<?php
+    if ( $serendipity['GET']['adminAction'] == 'delete' ) {
+        if ($serendipity['serendipityUserlevel'] >= USERLEVEL_CHIEF || $serendipity['authorid'] == $this_cat['authorid'] || $this_cat['authorid'] == '0') {
+?>
+        <form method="POST" name="serendipityCategory" action="?serendipity[adminModule]=category&amp;serendipity[adminAction]=doDelete&amp;serendipity[cid]=<?php echo $serendipity['GET']['cid'] ?>">
+            <br />
+            <?php echo CATEGORY_REMAINING ?>:
+            <select name="serendipity[cat][remaining_catid]">
+                <option value="0">- <?php echo NO_CATEGORY ?> -</option>
+<?php
+    $cats = serendipity_fetchCategories('all');
+    /* TODO, show dropdown as nested categories */
+    foreach ($cats as $cat_data) {
+        if ($cat_data['categoryid'] != $serendipity['GET']['cid'] && ($serendipity['serendipityUserlevel'] >= USERLEVEL_ADMIN || $cat_data['authorid'] == '0' || $cat_data['authorid'] == $serendipity['authorid'])) {
+            echo '<option value="' . $cat_data['categoryid'] . '">' . htmlspecialchars($cat_data['category_name']) . '</option>' . "\n";
+        }
+    }
+?>
+            </select>
+            <input type="submit" name="REMOVE" value="<?php echo GO ?>" class="serendipityPrettyButton">
+        </form>
+<?php
+        }
+    }
+?>
+
+
+
+<?php if ( $serendipity['GET']['adminAction'] == 'edit' || $serendipity['GET']['adminAction'] == 'new' ) {
+        if ( $serendipity['GET']['adminAction'] == 'edit' ) {
+            $this_cat = serendipity_fetchCategoryInfo($serendipity['GET']['cid']);
+            echo '<strong>'. sprintf(EDIT_THIS_CAT, htmlspecialchars($this_cat['category_name'])) .'</strong>';
+            $save = SAVE;
+        } else {
+            echo '<strong>'. CREATE_NEW_CAT .'</strong>';
+            $save = CREATE;
+        }
+?>
+<form method="POST" name="serendipityCategory">
+<table cellpadding="5" width="100%">
+    <tr>
+        <td><?php echo NAME; ?></td>
+        <td><input type="text" name="serendipity[cat][name]" value="<?php echo isset($this_cat['category_name']) ? htmlspecialchars($this_cat['category_name']) : ''; ?>" /></td>
+        <td rowspan="5" align="center" valign="middle" width="200" style="border: 1px solid #ccc"><img src="<?php echo isset($this_cat['category_icon']) ? $this_cat['category_icon'] : '' ?>" id="imagepreview" <?php echo empty($this_cat['category_icon']) ? 'style="display: none"' : '' ?>></td>
+    </tr>
+
+    <tr>
+        <td><?php echo DESCRIPTION; ?></td>
+        <td><input type="text" name="serendipity[cat][description]" value="<?php echo isset($this_cat['category_description']) ? htmlspecialchars($this_cat['category_description']) : ''; ?>" /></td>
+    </tr>
+
+    <tr>
+        <td><?php echo IMAGE; ?></td>
+        <td>
+            <script type="text/javascript" language="JavaScript" src="serendipity_editor.js"></script>
+            <input type="text" id="img_icon" name="serendipity[cat][icon]" value="<?php echo isset($this_cat['category_icon']) ? htmlspecialchars($this_cat['category_icon']) : ''; ?>" onchange="document.getElementById('imagepreview').src = this.value; document.getElementById('imagepreview').style.display = '';" />
+            <script type="text/javascript" language="JavaScript">document.write('<input type="button" name="insImage" value="<?php echo IMAGE ; ?>" onclick="window.open(\'serendipity_admin_image_selector.php?serendipity[htmltarget]=img_icon&amp;serendipity[filename_only]=true\', \'ImageSel\', \'width=800,height=600,toolbar=no,scrollbars=1,scrollbars,resize=1,resizable=1\');" class="serendipityPrettyButton" />');</script><!-- noscript>FIXXME: Emit a warning if JS is disabled</noscript -->
+        </td>
+    </tr>
+
+    <tr>
+        <td><label for="all_authors"><?php echo ALL_AUTHORS; ?></label></td>
+        <td><input id="all_authors" type="checkbox" name="serendipity[cat][all_authors]" value="true" <?php echo (!is_array($this_cat) || (isset($this_cat['authorid']) && $this_cat['authorid'] == '0')) ? 'checked="checked"' : ''; ?> /></td>
+    </tr>
+    <tr>
+        <td><label for="parent_cat"><?php echo PARENT_CATEGORY; ?></label></td>
+        <td>
+            <select id="parent_cat" name="serendipity[cat][parent_cat]">
+                <option value="0"<?php if ( (int)$serendipity['GET']['cid'] == 0 ) echo ' selected="selected"'; ?>>[ <?php echo NO_CATEGORY; ?> ]</option>
+<?php
+        $categories = serendipity_fetchCategories('all');
+        $categories = serendipity_walkRecursive($categories, 'categoryid', 'parentid', VIEWMODE_THREADED);
+        foreach ( $categories as $cat ) {
+            /* We can't be our own parent, the universe will collapse */
+            if ( $cat['categoryid'] == $serendipity['GET']['cid'] ) {
+                continue;
+            }
+            echo '<option value="'. $cat['categoryid'] .'"'. ($this_cat['parentid'] == $cat['categoryid'] ? ' selected="selected"' : '') .'>'. str_repeat('&nbsp;', $cat['depth']) . $cat['category_name'] .'</option>' . "\n";
+        }
+?>
+            </select>
+        </td>
+    </tr>
+</table>
+    <div><input type="submit" name="SAVE" value="<?php echo $save; ?>" class="serendipityPrettyButton" /></div>
+</form>
+<?php } ?>
+
+
+
+
+<?php
+if ( $serendipity['GET']['adminAction'] == 'view' ) {
+    if (empty($admin_category)) {
+        $cats = serendipity_fetchCategories('all');
+    } else {
+        $cats = serendipity_fetchCategories();
+    }
+
+    if ( is_array($cats) && sizeof($cats) > 0 ) {
+        echo CATEGORY_INDEX .':';
+    } else {
+        echo '<div align="center">- '. NO_CATEGORIES .' -</div>';
+    }
+?>
+<br /><br />
+<table cellspacing="0" cellpadding="4" width="100%" border=0>
+<?php
+            if ( is_array($cats) ) {
+                $categories = serendipity_walkRecursive($cats, 'categoryid', 'parentid', VIEWMODE_THREADED);
+                foreach ( $categories as $category ) {
+?>
+            <tr>
+                <td width="16"><a href="?serendipity[adminModule]=category&amp;serendipity[adminAction]=edit&amp;serendipity[cid]=<?php echo $category['categoryid'] ?>"><img src="<?php echo serendipity_getTemplateFile('admin/img/edit.png') ?>" border="0" alt="<?php echo EDIT ?>" /></a></td>
+                <td width="16"><a href="?serendipity[adminModule]=category&amp;serendipity[adminAction]=delete&amp;serendipity[cid]=<?php echo $category['categoryid'] ?>"><img src="<?php echo serendipity_getTemplateFile('admin/img/delete.png') ?>" border="0" alt="<?php echo DELETE ?>" /></a></td>
+                <td width="16"><?php if ( !empty($category['category_icon']) ) {?><img src="<?php echo serendipity_getTemplateFile('admin/img/thumbnail.png') ?>" alt="" /><?php } else echo '&nbsp;' ?></td>
+                <td width="300" style="padding-left: <?php echo ($category['depth']*15)+20 ?>px"><img src="<?php echo serendipity_getTemplateFile('admin/img/folder.png') ?>" style="vertical-align: bottom;"> <?php echo htmlspecialchars($category['category_name']) ?></td>
+                <td><?php echo htmlspecialchars($category['category_description']) ?></td>
+                <td align="right"><?php echo ($category['authorid'] == '0' ? ALL_AUTHORS : $category['realname']); ?></td>
+            </tr>
+<?php           }
+            } ?>
+            <tr>
+                <td colspan="6" align="right">
+                    <a href="?serendipity[adminModule]=category&serendipity[adminAction]=new" class="serendipityPrettyButton"><?php echo CREATE_NEW_CAT ?></a>
+                </td>
+            </tr>
+</table>
+<?php } ?>
+<?php
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/comments.inc.php b/include/admin/comments.inc.php
new file mode 100644 (file)
index 0000000..d71545d
--- /dev/null
@@ -0,0 +1,370 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+if (IN_serendipity !== true) {
+    die ("Don't hack!");
+}
+
+$commentsPerPage = (!empty($serendipity['GET']['filter']['perpage']) ? $serendipity['GET']['filter']['perpage'] : 10);
+$summaryLength = 200;
+
+if ( $serendipity['POST']['formAction'] == 'multiDelete' && sizeof($serendipity['POST']['delete']) != 0 ) {
+    foreach ( $serendipity['POST']['delete'] as $k => $v ) {
+        serendipity_deleteComment($k, $v);
+        echo DONE . ': '. sprintf(COMMENT_DELETED, $k) . '<br />';
+    }
+    return true;
+}
+
+
+/* We are asked to save the edited comment, and we are not in preview mode */
+if ( isset($serendipity['GET']['adminAction']) && $serendipity['GET']['adminAction'] == 'doEdit' && !isset($serendipity['POST']['preview']) ) {
+    $sql = "UPDATE {$serendipity['dbPrefix']}comments
+                    SET
+                        author    = '" . serendipity_db_escape_string($serendipity['POST']['name'])    . "',
+                        email     = '" . serendipity_db_escape_string($serendipity['POST']['email'])   . "',
+                        url       = '" . serendipity_db_escape_string($serendipity['POST']['url'])     . "',
+                        parent_id = '" . serendipity_db_escape_string($serendipity['POST']['replyTo']) . "',
+                        body      = '" . serendipity_db_escape_string($serendipity['POST']['comment']) . "'
+            WHERE id = " . (int)$serendipity['GET']['id'] . " AND
+                  entry_id = " . (int)$serendipity['POST']['entry_id'];
+    serendipity_db_query($sql);
+    echo COMMENT_EDITED;
+    return true;
+}
+
+
+/* We approve a comment */
+if ( isset($serendipity['GET']['adminAction']) && $serendipity['GET']['adminAction'] == 'approve' ) {
+    $sql = "SELECT c.*, e.title, a.email as authoremail, a.mail_comments
+            FROM {$serendipity['dbPrefix']}comments c
+            LEFT JOIN {$serendipity['dbPrefix']}entries e ON (e.id = c.entry_id)
+            LEFT JOIN {$serendipity['dbPrefix']}authors a ON (e.authorid = a.authorid)
+            WHERE c.id = " . (int)$serendipity['GET']['id']  ." AND status = 'pending'";
+    $rs  = serendipity_db_query($sql, true);
+
+    if ($rs === false) {
+        echo ERROR .': '. sprintf(COMMENT_ALREADY_APPROVED, $serendipity['GET']['id']);
+        return true;
+    }
+
+    serendipity_approveComment($serendipity['GET']['id'], $rs['entry_id']);
+    echo DONE . ': '. sprintf(COMMENT_APPROVED, $serendipity['GET']['id']);
+    return true;
+}
+
+/* We are asked to delete a comment */
+if ( isset($serendipity['GET']['adminAction']) && $serendipity['GET']['adminAction'] == 'delete' ) {
+    serendipity_deleteComment($serendipity['GET']['id'], $serendipity['GET']['entry_id']);
+    echo DONE . ': '. sprintf(COMMENT_DELETED, $serendipity['GET']['id']);
+    return true;
+}
+
+/* We are either in edit mode, or preview mode */
+if ( isset($serendipity['GET']['adminAction']) && $serendipity['GET']['adminAction'] == 'edit' || isset($serendipity['POST']['preview'])) {
+
+    $serendipity['smarty_raw_mode'] = true; // Force output of Smarty stuff in the backend
+    serendipity_smarty_init();
+
+    /* If we are not in preview, we need data from our database */
+    if (!isset($serendipity['POST']['preview']) ) {
+        $comment = serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}comments WHERE id = ". (int)$serendipity['GET']['id']);
+        $data['name']       = $comment[0]['author'];
+        $data['email']      = $comment[0]['email'];
+        $data['url']        = $comment[0]['url'];
+        $data['replyTo']    = $comment[0]['parent_id'];
+        $data['comment']    = $comment[0]['body'];
+
+    /* If we are in preview, we get data from our form */
+    } elseif ( isset($serendipity['POST']['preview']) ) {
+        $data['name']       = $serendipity['POST']['name'];
+        $data['email']      = $serendipity['POST']['email'];
+        $data['url']        = $serendipity['POST']['url'];
+        $data['replyTo']    = $serendipity['POST']['replyTo'];
+        $data['comment']    = $serendipity['POST']['comment'];
+        $pc_data = array(
+                array(
+                  'email'     => $serendipity['POST']['email'],
+                  'author'    => $serendipity['POST']['name'],
+                  'body'      => $serendipity['POST']['comment'],
+                  'url'       => $serendipity['POST']['url'],
+                  'timestamp' => time()
+                )
+              );
+
+        serendipity_printComments($pc_data);
+        $serendipity['smarty']->display(serendipity_getTemplateFile('comments.tpl', 'serendipityPath'));
+    }
+
+    serendipity_displayCommentForm(
+      $serendipity['GET']['entry_id'],
+      '?serendipity[action]=admin&amp;serendipity[adminModule]=comments&amp;serendipity[adminAction]=doEdit&amp;serendipity[id]=' . $serendipity['GET']['id'] . '&amp;serendipity[entry_id]=' . $serendipity['GET']['entry_id'],
+      NULL,
+      $data,
+      false,
+      false
+    );
+
+    $serendipity['smarty']->display(serendipity_getTemplateFile('commentform.tpl', 'serendipityPath'));
+
+    return true;
+}
+
+/* Searchable fields */
+$filters = array('author', 'email', 'ip', 'url', 'body', 'referer');
+
+/* Compress the filters into an "AND" SQL query, and a querystring */
+foreach ( $filters as $filter ) {
+    $and          .= (!empty($serendipity['GET']['filter'][$filter]) ? "AND c.". $filter ." LIKE '%". serendipity_db_escape_string($serendipity['GET']['filter'][$filter]) ."%'" : "");
+    $searchString .= (!empty($serendipity['GET']['filter'][$filter]) ? "&amp;serendipity[filter][". $filter ."]=". $serendipity['GET']['filter'][$filter] : "");
+}
+
+if ($serendipity['GET']['filter']['show'] == 'approved') {
+    $and          .= "AND status = 'approved'";
+    $searchString .= "&amp;serendipity[filter][show]=approved";
+} elseif ($serendipity['GET']['filter']['show'] == 'pending') {
+    $and           .= "AND status = 'pending'";
+    $searchString .= "&amp;serendipity[filter][show]=pending";
+} else {
+    $serendipity['GET']['filter']['show'] = 'all';
+}
+
+if ($serendipity['GET']['filter']['type'] == 'TRACKBACK') {
+    $c_type = 'TRACKBACK';
+    $searchString .= "&amp;serendipity[filter][type]=TRACKBACK";
+} else {
+    $c_type = 'NORMAL';
+}
+
+/* Paging */
+$sql = serendipity_db_query("SELECT COUNT(*) AS total FROM {$serendipity['dbPrefix']}comments c WHERE c.type = '$c_type' ". $and, true);
+
+$totalComments = $sql['total'];
+$pages = ($commentsPerPage == COMMENTS_FILTER_ALL ? 1 : ceil($totalComments/(int)$commentsPerPage));
+$page = (int)$serendipity['GET']['page'];
+if ( $page == 0 || $page > $pages ) {
+    $page = 1;
+}
+
+$linkPrevious = 'serendipity_admin.php?serendipity[adminModule]=comments&amp;serendipity[page]='. ($page-1) . $searchString;
+$linkNext = 'serendipity_admin.php?serendipity[adminModule]=comments&amp;serendipity[page]='. ($page+1) . $searchString;
+
+if ($commentsPerPage == COMMENTS_FILTER_ALL) {
+    $limit = '';
+}else {
+    $limit = serendipity_db_limit_sql(serendipity_db_limit(($page-1)*(int)$commentsPerPage, (int)$commentsPerPage));
+}
+
+$sql = serendipity_db_query("SELECT c.*, e.title FROM {$serendipity['dbPrefix']}comments c
+                                LEFT JOIN {$serendipity['dbPrefix']}entries e ON (e.id = c.entry_id)
+                                WHERE type = '$c_type'
+                                ". $and ."
+                                " . (($serendipity['serendipityUserlevel'] != USERLEVEL_ADMIN) ? 'AND e.authorid = ' . (int)$serendipity['authorid'] : '') . "
+                                ORDER BY c.id DESC $limit");
+?>
+<script type="text/javascript">
+function toggle(id) {
+    if ( document.getElementById(id + '_full').style.display == '' ) {
+        document.getElementById(id + '_full').style.display='none';
+        document.getElementById(id + '_summary').style.display='';
+        document.getElementById(id + '_text').innerHTML = '<?php echo VIEW ?>';
+    } else {
+        document.getElementById(id + '_full').style.display='';
+        document.getElementById(id + '_summary').style.display='none';
+        document.getElementById(id + '_text').innerHTML = '<?php echo HIDE ?>';
+    }
+    return false;
+}
+function invertSelection() {
+    var f = document.formMultiDelete;
+    for (var i = 0; i < f.elements.length; i++) {
+        if( f.elements[i].type == 'checkbox' ) {
+            f.elements[i].checked = !(f.elements[i].checked);
+            f.elements[i].onclick();
+        }
+    }
+}
+function highlightComment(id, checkvalue) {
+    var comment = document.getElementById(id);
+    if (checkvalue) {
+        comment.style.borderColor = '#FF0000';
+        comment.style.borderWidth = 2;
+    } else {
+        comment.style.borderColor = '';
+        comment.style.borderWidth = '';
+    }
+}
+</script>
+<form action="" method="GET" style="margin: 0">
+<input type="hidden" name="serendipity[adminModule]" value="comments" />
+<input type="hidden" name="serendipity[page]" value="<?php echo $page ?>" />
+<table class="serendipity_admin_filters" width="100%">
+    <tr>
+        <td colspan="6" class="serendipity_admin_filters_headline"><strong><?php echo FILTERS ?></strong> - <?php echo FIND_COMMENTS ?></td>
+    </tr>
+    <tr>
+        <td><?php echo AUTHOR ?>:</td>
+        <td><input type="text" name="serendipity[filter][author]" size="15" value="<?php echo $serendipity['GET']['filter']['author'] ?>" /></td>
+        <td><?php echo EMAIL ?>:</td>
+        <td><input type="text" name="serendipity[filter][email]" size="15" value="<?php echo $serendipity['GET']['filter']['email'] ?>" /></td>
+        <td><?php echo URL ?>:</td>
+        <td><input type="text" name="serendipity[filter][url]" size="15" value="<?php echo $serendipity['GET']['filter']['url'] ?>" /></td>
+    </tr>
+    <tr>
+        <td>IP:</td>
+        <td><input type="text" name="serendipity[filter][ip]" size="15" value="<?php echo $serendipity['GET']['filter']['ip'] ?>" /></td>
+        <td><?php echo CONTENT ?>:</td>
+        <td><input type="text" name="serendipity[filter][body]" size="15" value="<?php echo $serendipity['GET']['filter']['body'] ?>" /></td>
+        <td><?php echo REFERER ?>:</td>
+        <td><input type="text" name="serendipity[filter][referer]" size="15" value="<?php echo $serendipity['GET']['filter']['referer'] ?>" /></td>
+    </tr>
+    <tr>
+        <td><?php echo COMMENTS; ?>:</td>
+        <td><select name="serendipity[filter][perpage]">
+        <?php 
+            $filter_vals = array(10, 20, 50, COMMENTS_FILTER_ALL);
+            foreach($filter_vals AS $filter_val) { ?>
+            <option value="<?php echo $filter_val; ?>" <?php echo ($commentsPerPage == $filter_val ? ' selected="selected"' : ''); ?>><?php echo $filter_val; ?></option>
+        <?php
+            }
+        ?>
+            </select></td>
+        <td><?php echo COMMENTS_FILTER_SHOW ?>:</td>
+        <td><select name="serendipity[filter][show]">
+                <option value="all"<?php if ( $serendipity['GET']['filter']['show'] == 'all' ) echo ' selected="selected"' ?>><?php echo COMMENTS_FILTER_ALL ?></option>
+                <option value="approved"<?php if ( $serendipity['GET']['filter']['show'] == 'approved' ) echo ' selected="selected"' ?>><?php echo COMMENTS_FILTER_APPROVED_ONLY ?></option>
+                <option value="pending"<?php if ( $serendipity['GET']['filter']['show'] == 'pending' ) echo ' selected="selected"' ?>><?php echo COMMENTS_FILTER_NEED_APPROVAL ?></option>
+            </select></td>
+        <td><?php echo TYPE; ?></td>
+        <td><select name="serendipity[filter][type]">
+                <option value="NORMAL"<?php if ($c_type == 'NORMAL') echo ' selected="selected"' ?>><?php echo COMMENTS; ?></option>
+                <option value="TRACKBACK"<?php if ($c_type == 'TRACKBACK') echo ' selected="selected"' ?>><?php echo TRACKBACKS; ?></option>
+            </select></td>
+    </tr>
+    <tr>
+        <td colspan="6" align="right"><input type="submit" name="submit" value=" - <?php echo GO ?> - " class="serendipityPrettyButton" /></td>
+    </tr>
+</table>
+</form>
+<?php
+    if (!is_array($sql)) {
+        echo '<div align="center">- '. NO_COMMENTS .' -</div>';
+    } else {
+?>
+<form action="" method="POST" name="formMultiDelete" id="formMultiDelete">
+<input type="hidden" name="serendipity[formAction]" value="multiDelete" />
+<table width="100%" cellpadding="3" border="0" cellspacing="0">
+<tr>
+    <td align="center">
+        <table width="100%" cellspacing="5" cellpadding="0" border="0">
+            <tr>
+                <td>
+                <?php if ( $page != 1 && $page <= $pages ) { ?>
+                    <a href="<?php echo $linkPrevious; ?>" class="serendipityIconLink"><img src="<?php echo serendipity_getTemplateFile('admin/img/previous.png') ?>" /><?php echo PREVIOUS ?></a>
+                <?php } ?>
+                </td>
+                <td align="center"><?php printf(PAGE_BROWSE_COMMENTS, $page, $pages, $totalComments); ?></td>
+                <td align="right">
+                <?php if ( $page != $pages ) { ?>
+                    <a href="<?php echo $linkNext; ?>" class="serendipityIconLinkRight"><?php echo NEXT ?><img src="<?php echo serendipity_getTemplateFile('admin/img/next.png') ?>" /></a>
+                <?php } ?>
+                </td>
+            </tr>
+        </table>
+    </td>
+</tr>
+<?php
+
+$i = 0;
+foreach ($sql as $rs) {
+    $i++;
+    if (empty($rs['author'])) {
+        $rs['author'] = ANONYMOUS;
+    }
+
+    $fullBody = nl2br(strip_tags($rs['body']));
+    $summary = serendipity_mb('substr', $fullBody, 0, $summaryLength);
+
+    if (strlen($fullBody) > strlen($summary) ) {
+        $summary .= ' ...';
+    }
+
+    $class = 'serendipity_admin_list_item_' . (($i % 2 == 0 ) ? 'even' : 'uneven');
+    $header_class = ($rs['status'] == 'pending' ? 'serendipityAdminMsgNote' : '');
+?>
+<tr>
+    <td class="<?php echo $header_class; ?>"><a name="c<?php echo $rs['id'] ?>"></a>
+        <?php echo ($rs['type'] == 'NORMAL' ? COMMENT : TRACKBACK) . ' #'. $rs['id'] .', '. IN_REPLY_TO .' <strong>'. $rs['title'] .'</strong>, '. ON . ' ' . serendipity_mb('ucfirst', serendipity_strftime('%b %e %Y, %H:%M', $rs['timestamp']))?>
+    </td>
+</tr>
+<tr>
+    <td class="serendipity_admin_list_item <?php echo $class ?>" id="comment_<?php echo $rs['id'] ?>">
+        <table width="100%" cellspacing="0" cellpadding="3" border="0">
+            <tr>
+                <td rowspan="3" width="20" align="center"><input type="checkbox" name="serendipity[delete][<?php echo $rs['id'] ?>]" value="<?php echo $rs['entry_id'] ?>" onclick="highlightComment('comment_<?php echo $rs['id'] ?>', this.checked)" tabindex="<?php echo $i ?>" /></td>
+                <td width="40%"><strong><?php echo AUTHOR ?></strong>: <?php echo htmlspecialchars($rs['author']) ?></td>
+                <td><strong><?php echo EMAIL ?></strong>:
+                    <?php
+                        if ( empty($rs['email']) ) {
+                            echo 'N/A';
+                        } else {
+                    ?>
+                            <a href="mailto:<?php echo htmlspecialchars($rs['email']) ?>"><?php echo htmlspecialchars($rs['email']) ?></a>
+                    <?php } ?></td>
+            </tr>
+            <tr>
+                <td width="40%"><strong>IP</strong>:
+                    <?php
+                        if ( empty($rs['ip']) ) {
+                            echo '0.0.0.0';
+                        } else {
+                            echo htmlspecialchars($rs['ip']);
+                        }
+                    ?></td>
+                <td><strong><?php echo URL; ?></strong>:
+                    <?php
+                        if ( empty($rs['url']) ) {
+                            echo 'N/A';
+                        } else {
+                    ?>
+                            <a href="<?php echo htmlspecialchars($rs['url']) ?>" target="_blank"><?php echo htmlspecialchars($rs['url']) ?></a>
+                    <?php } ?></td>
+            </tr>
+            <tr>
+                <td width="40%">&nbsp;</td>
+                <td><strong><?php echo REFERER; ?></strong>:
+                    <?php
+                        if ( empty($rs['referer']) ) {
+                            echo 'N/A';
+                        } else {
+                    ?>
+                          <a href="<?php echo htmlspecialchars($rs['referer']) ?>" title="<?php echo htmlspecialchars($rs['referer']) ?>"><?php echo htmlspecialchars(serendipity_truncateString($rs['referer'],30)) ?></a>
+                    <?php } ?></td>
+            <tr>
+                <td style="border-top: 1px solid #CCCCCC; border-bottom: 1px solid #CCCCCC" colspan="3">
+                    <div id="<?php echo $rs['id'] ?>_summary"><?php echo $summary ?></div>
+                    <div id="<?php echo $rs['id'] ?>_full" style="display: none"><?php echo $fullBody ?></div>
+                </td>
+            </tr>
+        </table>
+<?php if ($rs['status'] == 'pending') { ?>
+          <a href="?serendipity[action]=admin&amp;serendipity[adminModule]=comments&amp;serendipity[adminAction]=approve&amp;serendipity[id]=<?php echo $rs['id'] ?>" class="serendipityIconLink" title="<?php echo APPROVE; ?>"><img src="<?php echo serendipity_getTemplateFile('admin/img/accept.png'); ?>" alt="<?php echo APPROVE ?>" /><?php echo APPROVE ?></a>
+<?php } ?>
+<?php if (strlen($fullBody) > strlen($summary) ) { ?>
+          <a href="#c<?php echo $rs['id'] ?>" onclick="toggle(<?php echo $rs['id'] ?>); return false;" title="<?php echo VIEW; ?>" class="serendipityIconLink"><img src="<?php echo serendipity_getTemplateFile('admin/img/zoom.png'); ?>" alt="<?php echo VIEW; ?>" /><span id="<?php echo $rs['id'] ?>_text"><?php echo VIEW ?></span></a>
+<?php } ?>
+          <a href="?serendipity[action]=admin&amp;serendipity[adminModule]=comments&amp;serendipity[adminAction]=edit&amp;serendipity[id]=<?php echo $rs['id'] ?>&amp;serendipity[entry_id]=<?php echo $rs['entry_id'] ?>" title="<?php echo EDIT; ?>" class="serendipityIconLink"><img src="<?php echo serendipity_getTemplateFile('admin/img/edit.png'); ?>" alt="<?php echo EDIT; ?>" /><?php echo EDIT ?></a>
+          <a href="?serendipity[action]=admin&amp;serendipity[adminModule]=comments&amp;serendipity[adminAction]=delete&amp;serendipity[id]=<?php echo $rs['id'] ?>&amp;serendipity[entry_id]=<?php echo $rs['entry_id'] ?>" onclick="return confirm('<?php echo sprintf(COMMENT_DELETE_CONFIRM, $rs['id'], htmlspecialchars($rs['author'])) ?>')" title="<?php echo DELETE ?>" class="serendipityIconLink"><img src="<?php echo serendipity_getTemplateFile('admin/img/delete.png'); ?>" alt="<?php echo DELETE; ?>" /><?php echo DELETE ?></a>
+    </td>
+</tr>
+<tr>
+    <td><hr noshade="noshade"></td>
+</tr>
+<?php } ?>
+<tr>
+    <td><input type="button" name="toggle" value="<?php echo INVERT_SELECTIONS ?>" onclick="invertSelection()" class="serendipityPrettyButton" /> <input type="submit" name="toggle" value="<?php echo DELETE_SELECTED_COMMENTS ?>" onclick="return confirm('<?php echo COMMENTS_DELETE_CONFIRM ?>')" tabindex="<?php echo ($i+1) ?>" class="serendipityPrettyButton" /></td>
+</tr>
+</table>
+</form>
+<?php } ?>
diff --git a/include/admin/configuration.inc.php b/include/admin/configuration.inc.php
new file mode 100644 (file)
index 0000000..c6953de
--- /dev/null
@@ -0,0 +1,44 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+umask(0000);
+$umask = 0775;
+@define('IN_installer', true);
+
+if (!isset($_POST['installAction'])) {
+    $_POST['installAction'] = '';
+}
+
+switch ($_POST['installAction']) {
+    case 'check':
+        $oldRewrite = $serendipity['rewrite']; // We save the rewrite method, because we run a check after $serendipity has been updated
+        $res = serendipity_updateConfiguration();
+        if (is_array($res)) {
+            echo DIAGNOSTIC_ERROR;
+            echo '<span class="serendipityAdminMsgError">- ' . implode('<br />', $res) . '</span><br /><br />';
+        } else {
+            /* If we have new rewrite rules, then install them */
+            if (isset($_POST['rewrite']) && $serendipity['serendipityUserlevel'] >= USERLEVEL_ADMIN && $oldRewrite != $_POST['rewrite']) {
+                printf(ATTEMPT_WRITE_FILE, $serendipity['serendipityPath'] . '.htaccess');
+                $res = serendipity_installFiles($serendipity['serendipityPath']);
+                if (is_array($res)) {
+                    echo implode('<br />', $res);
+                } else {
+                    echo DONE . '<br />';
+                }
+            }
+            echo '<br /><div class="serendipityAdminMsgSuccess">'. WRITTEN_N_SAVED .'</div>';
+        }
+
+        break;
+
+    default:
+        $from = &$serendipity;
+        $t = serendipity_parseTemplate(S9Y_CONFIG_TEMPLATE);
+        serendipity_printConfigTemplate($t, $from, false, true);
+        break;
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/entries.inc.php b/include/admin/entries.inc.php
new file mode 100644 (file)
index 0000000..01b8f90
--- /dev/null
@@ -0,0 +1,405 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+if (IN_serendipity !== true) {
+    die ("Don't hack!");
+}
+
+$sort_order = array('timestamp'     => DATE,
+                    'isdraft'       => PUBLISH . '/' . DRAFT,
+                    'a.realname'    => AUTHOR,
+                    'category_name' => CATEGORY,
+                    'last_modified' => LAST_UPDATED,
+                    'title'         => TITLE);
+$per_page = array('12', '16', '50', '100');
+
+
+// A little helper we don't want in _functions.inc.php
+function serendipity_drawList() {
+    global $serendipity, $sort_order, $per_page;
+
+    $perPage = (!empty($serendipity['GET']['sort']['perPage']) ? $serendipity['GET']['sort']['perPage'] : $per_page[0]);
+    $page    = (int)$serendipity['GET']['page'];
+    $offSet  = $perPage*$page;
+
+    if (empty($serendipity['GET']['sort']['ordermode']) || $serendipity['GET']['sort']['ordermode'] != 'ASC') {
+        $serendipity['GET']['sort']['ordermode'] = 'DESC';
+    }
+
+    if (!empty($serendipity['GET']['sort']['order']) && !empty($sort_order[$serendipity['GET']['sort']['order']])) {
+        $orderby = serendipity_db_escape_string($serendipity['GET']['sort']['order'] . ' ' . $serendipity['GET']['sort']['ordermode']);
+    } else {
+        $orderby = 'timestamp ' . serendipity_db_escape_string($serendipity['GET']['sort']['ordermode']);
+    }
+
+    $filter = array();
+    if (!empty($serendipity['GET']['filter']['author'])) {
+        $filter[] = "e.authorid = '" . serendipity_db_escape_string($serendipity['GET']['filter']['author']) . "'";
+    }
+
+    if (!empty($serendipity['GET']['filter']['category'])) {
+        $filter[] = "ec.categoryid = '" . serendipity_db_escape_string($serendipity['GET']['filter']['category']) . "'";
+    }
+
+    if (!empty($serendipity['GET']['filter']['body'])) {
+        if ($serendipity['dbType'] == 'mysql') {
+            $filter[] = "MATCH (title,body,extended) AGAINST ('" . serendipity_db_escape_string($serendipity['GET']['filter']['body']) . "')";
+            $full     = true;
+        }
+    }
+
+    $filter_sql = implode(' AND ', $filter);
+
+    // Fetch the entries
+    $entries = serendipity_fetchEntries(
+                 false,
+                 false,
+                 serendipity_db_limit(
+                   $offSet,
+                   $perPage
+                 ),
+                 true,
+                 false,
+                 $orderby,
+                 $filter_sql
+               );
+?>
+<form action="?" method="get">
+<div class="serendipity_admin_list">
+    <input type="hidden" name="serendipity[action]"      value="admin"      />
+    <input type="hidden" name="serendipity[adminModule]" value="entries"    />
+    <input type="hidden" name="serendipity[adminAction]" value="editSelect" />
+    <table width="100%" class="serendipity_admin_filters">
+        <tr>
+            <td class="serendipity_admin_filters_headline" colspan="6"><strong><?php echo FILTERS ?></strong> - <?php echo FIND_ENTRIES ?></td>
+        </tr>
+        <tr>
+            <td width="80"><?php echo AUTHOR ?></td>
+            <td>
+                <select name="serendipity[filter][author]">
+                    <option value="">--</option>
+<?php
+                    $users = serendipity_fetchUsers();
+                    if (is_array($users)) {
+                        foreach ($users AS $user) {
+                            echo '<option value="' . $user['authorid'] . '" ' . (isset($serendipity['GET']['filter']['author']) && $serendipity['GET']['filter']['author'] == $user['authorid'] ? 'selected="selected"' : '') . '>' . $user['realname'] . '</option>' . "\n";
+                        }
+                    }
+?>              </select>
+            </td>
+            <td width="80"><?php echo CATEGORY ?></td>
+            <td>
+                <select name="serendipity[filter][category]">
+                    <option value="">--</option>
+<?php
+                    $categories = serendipity_fetchCategories();
+                    $categories = serendipity_walkRecursive($categories, 'categoryid', 'parentid', VIEWMODE_THREADED);
+                    foreach ( $categories as $cat ) {
+                        echo '<option value="'. $cat['categoryid'] .'"'. ($serendipity['GET']['filter']['category'] == $cat['categoryid'] ? ' selected="selected"' : '') .'>'. str_repeat('&nbsp;', $cat['depth']) . $cat['category_name'] .'</option>' . "\n";
+                    }
+?>              </select>
+            </td>
+            <td width="80"><?php echo CONTENT ?></td>
+            <td><input size="10" type="text" name="serendipity[filter][body]" value="<?php echo (isset($serendipity['GET']['filter']['body']) ? htmlspecialchars($serendipity['GET']['filter']['body']) : '') ?>" /></td>
+        </tr>
+        <tr>
+            <td class="serendipity_admin_filters_headline" colspan="6"><strong><?php echo SORT_ORDER ?></strong></td>
+        </tr>
+        <tr>
+            <td><?php echo SORT_BY ?></td>
+            <td>
+                <select name="serendipity[sort][order]">
+<?php
+    foreach($sort_order as $so_key => $so_val) {
+        echo '<option value="' . $so_key . '" ' . (isset($serendipity['GET']['sort']['order']) && $serendipity['GET']['sort']['order'] == $so_key ? 'selected="selected"': '') . '>' . $so_val . '</option>' . "\n";
+    }
+?>              </select>
+            </td>
+            <td><?php echo SORT_ORDER ?></td>
+            <td>
+                <select name="serendipity[sort][ordermode]">
+                    <option value="DESC" <?php echo (isset($serendipity['GET']['sort']['ordermode']) && $serendipity['GET']['sort']['ordermode'] == 'DESC' ? 'selected="selected"' : '') ?>><?php echo SORT_ORDER_DESC ?></option>
+                    <option value="ASC" <?php echo (isset($serendipity['GET']['sort']['ordermode']) && $serendipity['GET']['sort']['ordermode'] == 'ASC'  ? 'selected="selected"' : '') ?>><?php echo SORT_ORDER_ASC ?></option>
+                </select>
+            </td>
+            <td><?php echo ENTRIES_PER_PAGE ?></td>
+            <td>
+                <select name="serendipity[sort][perPage]">
+<?php
+    foreach($per_page AS $per_page_nr) {
+       echo '<option value="' . $per_page_nr . '"   ' . (isset($serendipity['GET']['sort']['perPage']) && $serendipity['GET']['sort']['perPage'] == $per_page_nr ? 'selected="selected"' : '') . '>' . $per_page_nr . '</option>' . "\n";
+    }
+
+?>
+                </select>
+            </td>
+        </tr>
+        <tr>
+            <td align="right" colspan="6"><input type="submit" name="go" value="<?php echo GO ?>" class="serendipityPrettyButton" /></td>
+        </tr>
+    </table>
+    <table class="serendipity_admin_list" cellpadding="5" width="100%">
+<?php
+    if (is_array($entries)) {
+        $count = count($entries);
+        $qString = '?serendipity[adminModule]=entries&amp;serendipity[adminAction]=editSelect';
+        foreach ((array)$serendipity['GET']['sort'] as $k => $v) {
+            $qString .= '&amp;serendipity[sort]['. $k .']='. $v;
+        }
+        foreach ((array)$serendipity['GET']['filter'] as $k => $v) {
+            $qString .= '&amp;serendipity[filter]['. $k .']='. $v;
+        }
+        $linkPrevious = $qString . '&amp;serendipity[page]=' . ($page-1);
+        $linkNext     = $qString . '&amp;serendipity[page]=' . ($page+1);
+?>
+        <tr>
+            <td>
+                <?php if ($offSet > 0) { ?>
+                    <a href="<?php echo $linkPrevious ?>" class="serendipityIconLink"><img src="<?php echo serendipity_getTemplateFile('admin/img/previous.png') ?>" /><?php echo PREVIOUS ?></a>
+                <?php } ?>
+            </td>
+            <td align="right">
+                <?php if ($count == $perPage) { ?>
+                    <a href="<?php echo $linkNext ?>" class="serendipityIconLinkRight"><?php echo NEXT ?><img src="<?php echo serendipity_getTemplateFile('admin/img/next.png') ?>" /></a>
+                <?php } ?>
+            </td>
+        </tr>
+    </table>
+<?php
+        // Print the entries
+        $rows = 0;
+        foreach ( $entries as $entry ) {
+            $rows++;
+            // Find out if the entry has been modified later than 30 minutes after creation
+            if ($entry['timestamp'] <= ($entry['last_modified'] - 60*30)) {
+                $lm = '<a href="#" title="' . LAST_UPDATED . ': ' . serendipity_formatTime(DATE_FORMAT_SHORT, $entry['last_modified']) . '" onclick="alert(this.title)"><img src="'. serendipity_getTemplateFile('admin/img/clock.png') .'" alt="*" style="border: 0px none ; vertical-align: bottom;" /></a>';
+            } else {
+                $lm = '';
+            }
+
+            if (!$serendipity['showFutureEntries'] && $entry['timestamp'] >= serendipity_serverOffsetHour()) {
+                $entry_pre = '<a href="#" title="' . ENTRY_PUBLISHED_FUTURE . '" onclick="alert(this.title)"><img src="'. serendipity_getTemplateFile('admin/img/clock_future.png') .'" alt="*" style="border: 0px none ; vertical-align: bottom;" /></a> ';
+            } else {
+                $entry_pre = '';
+            }
+
+            if ($entry['isdraft'] == 'true') {
+                $entry_pre .= ' ' . DRAFT . ': ';
+            }
+?>
+            <div class="serendipity_admin_list_item serendipity_admin_list_item_<?php echo ($rows % 2 ? 'even' : 'uneven'); ?>">
+                <table width="100%" cellspacing="0" cellpadding="3">
+                    <tr>
+                        <td>
+                            <strong><?php echo $entry_pre; ?><a href="?serendipity[action]=admin&amp;serendipity[adminModule]=entries&amp;serendipity[adminAction]=edit&amp;serendipity[id]=<?php echo $entry['id']; ?>" title="#<?php echo $entry['id']; ?>"><?php echo serendipity_truncateString($entry['title'],50) ?></a></strong>
+                        </td>
+                        <td align="right">
+                            <?php echo serendipity_formatTime(DATE_FORMAT_SHORT, $entry['timestamp']) . ' ' .$lm; ?>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td>
+                            <?php
+                echo POSTED_BY . ' ' . $entry['author'];
+                if (count($entry['categories'])) {
+                    echo ' ' . IN . ' ';
+                    $cats = array();
+                    foreach ($entry['categories'] as $cat) {
+                        $cats[] = '<a href="' . $serendipity['serendipityHTTPPath'] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '') . 'categories/' . $cat['categoryid'] . '_' . serendipity_makeFilename($cat['category_name']) . '">' . $cat['category_name'] . '</a>';
+                    }
+                    echo implode(', ', $cats);
+                }
+                ?>
+
+                        </td>
+                        <td align="right">
+                            <a href="?serendipity[action]=admin&amp;serendipity[adminModule]=entries&amp;serendipity[adminAction]=edit&amp;serendipity[id]=<?php echo $entry['id']; ?>" title="<?php echo EDIT . ' #' . $entry['id']; ?>" class="serendipityIconLink"><img src="<?php echo serendipity_getTemplateFile('admin/img/edit.png'); ?>" alt="<?php echo EDIT; ?>" /><?php echo EDIT ?></a>
+                            <a href="?serendipity[action]=admin&amp;serendipity[adminModule]=entries&amp;serendipity[adminAction]=delete&amp;serendipity[id]=<?php echo $entry['id']; ?>" title="<?php echo DELETE . ' #' . $entry['id']; ?>" class="serendipityIconLink"><img src="<?php echo serendipity_getTemplateFile('admin/img/delete.png'); ?>" alt="<?php echo DELETE; ?>" /><?php echo DELETE ?></a>
+                        </td>
+                    </tr>
+                </table>
+        </div>
+<?php
+        } // end entries output
+?>
+
+        <div class="serendipity_admin_list_item serendipity_admin_list_item_<?php echo (($rows+1) % 2 ? 'even' : 'uneven'); ?>">
+            <table width="100%" cellspacing="0" cellpadding="3">
+                    <tr>
+                        <td>
+                            <?php echo EDIT_ENTRY ?>: #<input type="text" size="3" name="serendipity[id]" /> <input type="submit" name="serendipity[editSubmit]" value="<?php echo GO ?>" class="serendipityPrettyButton" />
+                        </td>
+                    </tr>
+            </table>
+        </div>
+ <?php
+    } else {
+        // We've got nothing
+?>
+        <div align="center">- <?php echo NO_ENTRIES_TO_PRINT ?> -</div>
+<?php
+    }
+?>
+</div>
+</form>
+<?php
+} // End function serendipity_drawList()
+
+if (!empty($serendipity['GET']['editSubmit'])) {
+    $serendipity['GET']['adminAction'] = 'edit';
+}
+
+switch($serendipity['GET']['adminAction']) {
+    case 'save':
+        $entry = array(
+                   'id'                 => $serendipity['POST']['id'],
+                   'title'              => $serendipity['POST']['title'],
+                   'timestamp'          => $serendipity['POST']['timestamp'],
+                   'body'               => $serendipity['POST']['body'],
+                   'extended'           => $serendipity['POST']['extended'],
+                   'categories'         => $serendipity['POST']['categories'],
+                   'isdraft'            => $serendipity['POST']['isdraft'],
+                   'allow_comments'     => $serendipity['POST']['allow_comments'],
+                   'moderate_comments'  => $serendipity['POST']['moderate_comments'],
+                   'exflag'             => (!empty($serendipity['POST']['extended']) ? true : false)
+        );
+
+        if ($entry['allow_comments'] != 'true' && $entry['allow_comments'] !== true) {
+            $entry['allow_comments'] = 'false';
+        }
+
+        if ($entry['moderate_comments'] != 'true' && $entry['moderate_comments'] !== true) {
+            $entry['moderate_comments'] = 'false';
+        }
+
+        // Check if the user changed the timestamp.
+        if (isset($serendipity['allowDateManipulation']) && $serendipity['allowDateManipulation'] && isset($serendipity['POST']['new_timestamp']) && $serendipity['POST']['new_timestamp'] != date(DATE_FORMAT_2, $serendipity['POST']['chk_timestamp'])) {
+            // The user changed the timestamp, now set the DB-timestamp to the user's date
+            $entry['timestamp'] = strtotime($serendipity['POST']['new_timestamp']);
+
+            if ($entry['timestamp'] == -1) {
+                echo DATE_INVALID . '<br />';
+                // The date given by the user is not convertable. Reset the timestamp.
+                $entry['timestamp'] = $serendipity['POST']['timestamp'];
+            }
+        }
+
+        // Save server timezone in database always, so substract the offset we added for display; otherwise it would be added time and again
+        if (!empty($entry['timestamp'])) {
+            $entry['timestamp'] = serendipity_serverOffsetHour($entry['timestamp'], true);
+        }
+
+        // Save the entry, or just display a preview
+        if ($serendipity['POST']['preview'] != 'true') {
+            /* We don't need an iframe to save a draft */
+            if ( $serendipity['POST']['isdraft'] == 'true' ) {
+                echo '<div class="serendipityAdminMsgSuccess">' . IFRAME_SAVE_DRAFT . '</div><br />';
+                serendipity_updertEntry($entry);
+            } else {
+                if ($serendipity['use_iframe']) {
+                    echo '<div class="serendipityAdminMsgSuccess">' . IFRAME_SAVE . '</div><br />';
+                    serendipity_iframe_create('save', $entry);
+                } else {
+                    serendipity_iframe($entry, 'save');
+                }
+            }
+        } else {
+            // Only display the preview
+            $serendipity['hidefooter'] = true;
+            if (!is_numeric($entry['timestamp'])) {
+                $entry['timestamp']  = time();
+            }
+
+            if (!isset($entry['trackbacks']) || !$entry['trackbacks']) {
+                $entry['trackbacks'] = 0;
+            }
+
+            if (!isset($entry['comments']) || !$entry['comments']) {
+                $entry['comments']   = 0;
+            }
+
+            if (!isset($entry['realname']) || !$entry['realname']) {
+                $entry['realname']   = $serendipity['serendipityUser'];
+            }
+
+            $categories = (array)$entry['categories'];
+            $entry['categories'] = array();
+            foreach ($categories as $catid) {
+                $entry['categories'][] = serendipity_fetchCategoryInfo($catid);
+            }
+
+            if (isset($entry['id'])) {
+                $serendipity['GET']['id'] = $entry['id'];
+            } else {
+                $serendipity['GET']['id'] = 1;
+            }
+
+            if ($serendipity['use_iframe']) {
+                echo '<div class="serendipityAdminMsgSuccess">' . IFRAME_PREVIEW . '</div><br />';
+                serendipity_iframe_create('preview', $entry);
+            } else {
+                serendipity_iframe($entry, 'preview');
+            }
+        }
+
+        // serendipity_updertEntry sets this global variable to store the entry id. Couldn't pass this
+        // by reference or as return value because it affects too many places inside our API and dependant
+        // function calls.
+        if (!empty($serendipity['lastSavedEntry'])) {
+            $entry['id'] = $serendipity['lastSavedEntry'];
+        }
+
+        serendipity_printEntryForm(
+            '?',
+            array(
+              'serendipity[action]'      => 'admin',
+              'serendipity[adminModule]' => 'entries',
+              'serendipity[adminAction]' => 'save',
+              'serendipity[timestamp]'   => $entry['timestamp']
+            ),
+
+            $entry
+        );
+
+        break;
+
+    case 'editSelect':
+        serendipity_drawList();
+        break;
+
+    case 'delete':
+        $newLoc = '?serendipity[action]=admin&amp;serendipity[adminModule]=entries&amp;serendipity[adminAction]=doDelete&amp;serendipity[id]=' . $serendipity['GET']['id'];
+        printf(DELETE_SURE, $serendipity['GET']['id']);
+?>
+<br />
+<br />
+<div>
+    <a href="<?php echo $_SERVER["HTTP_REFERER"]; ?>" class="serendipityPrettyButton"><?php echo NOT_REALLY; ?></a>
+    <?php echo str_repeat('&nbsp;', 10); ?>
+    <a href="<?php echo $newLoc; ?>" class="serendipityPrettyButton"><?php echo DUMP_IT; ?></a>
+</div>
+<?php
+        break;
+
+    case 'doDelete':
+        serendipity_deleteEntry($serendipity['GET']['id']);
+        printf(RIP_ENTRY, $serendipity['GET']['id']);
+        break;
+
+    case 'edit':
+        $entry = serendipity_fetchEntry('id', $serendipity['GET']['id'], 1, 1);
+
+    default:
+        serendipity_printEntryForm(
+            '?',
+            array(
+            'serendipity[action]'      => 'admin',
+            'serendipity[adminModule]' => 'entries',
+            'serendipity[adminAction]' => 'save'
+            ),
+            (isset($entry) ? $entry : array())
+        );
+}
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/entries_overview.inc.php b/include/admin/entries_overview.inc.php
new file mode 100644 (file)
index 0000000..b9a593f
--- /dev/null
@@ -0,0 +1,12 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+if (IN_serendipity !== true) {
+    die ('Don\'t hack!');
+}
+
+echo WELCOME_BACK . ' ' . $_SESSION['serendipityUser'];
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/export.inc.php b/include/admin/export.inc.php
new file mode 100644 (file)
index 0000000..fd5af16
--- /dev/null
@@ -0,0 +1,15 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+if (IN_serendipity !== true) {
+    die ("Don't hack!");
+}
+
+?>
+  <div>
+    <a href="<?php echo $serendipity['baseURL'] ?>rss.php?version=2.0&all=1" class="serendipityPrettyButton"><?php echo EXPORT_FEED; ?></a>
+  </div>
+<?php
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/images.inc.php b/include/admin/images.inc.php
new file mode 100644 (file)
index 0000000..12e57d1
--- /dev/null
@@ -0,0 +1,546 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+if (IN_serendipity !== true) {
+    die ("Don't hack!");
+}
+
+switch ($serendipity['GET']['adminAction']) {
+    case 'sync':
+        set_time_limit(0);
+        ignore_user_abort();
+
+        echo '<p><b>' . SYNCING . '</b><br /><br />';
+        flush();
+
+        $i = serendipity_syncThumbs();
+        printf(SYNC_DONE, $i);
+
+        echo '<p><b>' . RESIZING . '</b><br /><br />';
+        flush();
+
+        $i = serendipity_generateThumbs();
+        printf(RESIZE_DONE, $i);
+
+        break;
+
+    case 'DoDelete':
+        $file   = $serendipity['GET']['fname'];
+        serendipity_deleteImage($serendipity['GET']['fid']);
+        break;
+
+    case 'delete':
+        $file     = serendipity_fetchImageFromDatabase($serendipity['GET']['fid']);
+
+        if ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF && $file['authorid'] != '0' && $file['authorid'] != $serendipity['authorid']) {
+            return;
+        }
+
+        $abortLoc = $serendipity['serendipityHTTPPath'] . 'serendipity_admin.php?serendipity[adminModule]=images';
+        $newLoc   = $abortLoc . '&serendipity[adminAction]=DoDelete&serendipity[fid]=' . $serendipity['GET']['fid'];
+
+        printf(ABOUT_TO_DELETE_FILE, $file['name'] .'.'. $file['extension']);
+?>
+    <form method="get" name="delete_image">
+        <div>
+              <a href="<?php echo $newLoc; ?>" class="serendipityPrettyButton"><?php echo DUMP_IT ?></a>
+              &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+              <a href="<?php echo $abortLoc; ?>" class="serendipityPrettyButton"><?php echo ABORT_NOW ?></a>
+        </div>
+    </form>
+<?php
+        break;
+
+    case 'rename':
+        $file = serendipity_fetchImageFromDatabase($serendipity['GET']['fid']);
+        $serendipity['GET']['newname'] = serendipity_uploadSecure($serendipity['GET']['newname']);
+
+        if ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF && $file['authorid'] != '0' && $file['authorid'] != $serendipity['authorid']) {
+            return;
+        }
+
+        if ($file['hotlink']) {
+            serendipity_updateImageInDatabase(array('name' => $serendipity['GET']['newname']), $serendipity['GET']['fid']);
+        } else {
+            $newfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $serendipity['GET']['newname'] . '.' . $file['extension'];
+            $oldfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . '.'. $file['extension'];
+            if ($serendipity['GET']['newname'] != '' && file_exists($oldfile) && !file_exists($newfile)) {
+                // Rename file
+                rename($oldfile, $newfile);
+
+                // Rename thumbnail
+                rename($serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . '.' . $file['thumbnail_name'] . '.' .  $file['extension'],
+                       $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $serendipity['GET']['newname'] . '.' . $serendipity['thumbSuffix'] . '.' . $file['extension']);
+
+                serendipity_updateImageInDatabase(array('thumbnail_name' => $serendipity['thumbSuffix'], 'name' => $serendipity['GET']['newname']), $serendipity['GET']['fid']);
+                // Forward user to overview (we don't want the user's back button to rename things again)
+            } else {
+                if (!file_exists($oldfile)) {
+                    echo ERROR_FILE_NOT_EXISTS;
+                } elseif (file_exists($newfile)) {
+                    echo ERROR_FILE_EXISTS;
+                } else {
+                    echo ERROR_SOMETHING;
+                }
+    ?>
+        <br />
+        <input type="button" onclick="history.go(-1);" value="<?php echo BACK; ?>" class="serendipityPrettyButton" />
+    <?php
+                break;
+            }
+        }
+
+        // if we successfully rename
+    ?>
+        <script language="javascript" type="text/javascript">
+            location.href="?serendipity[adminModule]=images";
+        </script>
+        <noscript>
+            <a href="?serendipity[adminModule]=images"><?php echo DONE ?></a>
+        </noscript>
+    <?php
+        break;
+
+    case 'add':
+?>
+    <b><?php echo ADDING_IMAGE; ?></b>
+    <br /><br />
+<?php
+
+    $authorid = (isset($serendipity['POST']['all_authors']) && $serendipity['POST']['all_authors'] == 'true') ? '0' : $serendipity['authorid'];
+
+    // First find out whether to fetch a file or accept an upload
+    if ($serendipity['POST']['imageurl'] != '' && $serendipity['POST']['imageurl'] != 'http://') {
+        if (!empty($serendipity['POST']['target_filename'])) {
+            $tfile   = $serendipity['POST']['target_filename'];
+        } else {
+            $tfile   = basename($serendipity['POST']['imageurl']);
+        }
+
+        if ($serendipity['serendipityUserlevel'] < USERLEVEL_ADMIN && preg_match('@\.(php[34]?|[ps]html?)$@i', $tfile)) {
+            printf(ERROR_FILE_FORBIDDEN, $tfile);
+            break;
+        }
+
+        $tfile = serendipity_uploadSecure($tfile);
+        $serendipity['POST']['target_directory'] = serendipity_uploadSecure($serendipity['POST']['target_directory'], true);
+        $target = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $serendipity['POST']['target_directory'] . $tfile;
+
+        if (file_exists($target)) {
+            echo '(' . $target . ') ' . ERROR_FILE_EXISTS_ALREADY;
+        } else {
+            require_once S9Y_INCLUDE_PATH . 'bundled-libs/HTTP/Request.php';
+            $req = &new HTTP_Request($serendipity['POST']['imageurl']);
+            // Try to get the URL
+
+            if (PEAR::isError($req->sendRequest()) || $req->getResponseCode() != '200') {
+                printf(REMOTE_FILE_NOT_FOUND, $serendipity['POST']['imageurl']);
+            } else {
+                // Fetch file
+                $fContent = $req->getResponseBody();
+
+                if ($serendipity['POST']['imageimporttype'] == 'hotlink') {
+                    $tempfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . '/hotlink_' . time();
+                    $fp = fopen($tempfile, 'w');
+                    fwrite($fp, $fContent);
+                    fclose($fp);
+                      
+                    $image_id = @serendipity_insertHotlinkedImageInDatabase($tfile, $serendipity['POST']['imageurl'], $authorid, null, $tempfile);
+                    printf(HOTLINK_DONE. '<br />', $serendipity['POST']['imageurl'], $tfile);
+                } else {
+                    $fp = fopen($target, 'w');
+                    fwrite($fp, $fContent);
+                    fclose($fp);
+
+                    printf(FILE_FETCHED . '<br />', $serendipity['POST']['imageurl'], $tfile);
+
+                    // Create thumbnail
+                    if ( $created_thumbnail = serendipity_makeThumbnail($tfile, $serendipity['POST']['target_directory']) ) {
+                        echo THUMB_CREATED_DONE . '<br />';
+                    }
+                    // Insert into database
+                    $image_id = serendipity_insertImageInDatabase($tfile, $serendipity['POST']['target_directory'], $authorid);
+                }
+            }
+        }
+    } else {
+        if (!empty($serendipity['POST']['target_filename'])) {
+            $tfile   = $serendipity['POST']['target_filename'];
+        } else {
+            $tfile   = $_FILES['userfile']['name'];
+        }
+
+        if ($serendipity['serendipityUserlevel'] < USERLEVEL_ADMIN && preg_match('@\.(php[34]?|[ps]html?)$@i', $tfile)) {
+            printf(ERROR_FILE_FORBIDDEN, $tfile);
+            break;
+        }
+
+        $tfile = serendipity_uploadSecure($tfile);
+        $serendipity['POST']['target_directory'] = serendipity_uploadSecure($serendipity['POST']['target_directory'], true);
+        $target = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $serendipity['POST']['target_directory'] . $tfile;
+
+        if (file_exists($target)) {
+            echo '(' . $target . ') ' . ERROR_FILE_EXISTS_ALREADY;
+        } else {
+            // Accept file
+            if (move_uploaded_file($_FILES['userfile']['tmp_name'], $target)) {
+                printf(FILE_UPLOADED . '<br />', $_FILES['userfile']['name'], $target);
+                @umask(0000);
+                @chmod($target, 0664);
+
+                // Create thumbnail
+                if ( $created_thumbnail = serendipity_makeThumbnail($tfile, $serendipity['POST']['target_directory']) ) {
+                    echo THUMB_CREATED_DONE . '<br />';
+                }
+                // Insert into database
+                $image_id = serendipity_insertImageInDatabase($tfile, $serendipity['POST']['target_directory'], $authorid);
+            } else {
+                echo ERROR_UNKNOWN_NOUPLOAD . '<br />';
+            }
+        }
+    }
+    break;
+
+
+    case 'directoryDoDelete':
+        if ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF) {
+            return;
+        }
+
+        $new_dir = serendipity_uploadSecure($serendipity['GET']['dir'], true);
+        if (is_dir($serendipity['serendipityPath'] . $serendipity['uploadPath'] . $new_dir)) {
+            if (!is_writable($serendipity['serendipityPath'] . $serendipity['uploadPath'] . $new_dir)) {
+                printf(DIRECTORY_WRITE_ERROR, $new_dir);
+            } else {
+                // Directory exists and is writable. Now dive within subdirectories and kill 'em all.
+                serendipity_killPath($serendipity['serendipityPath'] . $serendipity['uploadPath'], $new_dir, (isset($serendipity['POST']['nuke']) ? true : false));
+            }
+        } else {
+            printf(ERROR_NO_DIRECTORY, $new_dir);
+        }
+
+        break;
+    case 'directoryDelete':
+        if ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF) {
+            return;
+        }
+?>
+
+    <strong><?php echo DELETE_DIRECTORY ?></strong><br />
+    <?php echo DELETE_DIRECTORY_DESC ?>
+    <br />
+    <br />
+    <form method="POST" action="?serendipity[adminModule]=images&serendipity[adminAction]=directoryDoDelete&amp;serendipity[dir]=<?php echo $serendipity['GET']['dir'] ?>">
+    <table cellpadding="5">
+        <tr>
+            <td width="100"><strong><?php echo NAME ?></strong></td>
+            <td><?php echo basename($serendipity['GET']['dir']) ?></td>
+        </tr>
+        <tr>
+            <td colspan="2"><input type="checkbox" name="serendipity[nuke]" value="true" style="margin: 0"> <?php echo FORCE_DELETE ?></td>
+        </tr>
+    </table>
+    <br />
+    <br />
+    <div align="center">
+        <?php echo sprintf(CONFIRM_DELETE_DIRECTORY, $serendipity['GET']['dir']) ?><br />
+        <input name="SAVE" value="<?php echo DELETE_DIRECTORY ?>" class="serendipityPrettyButton" type="submit">
+    </div>
+    </form>
+
+<?php
+        break;
+
+
+    case 'directoryDoCreate':
+        if ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF) {
+            return;
+        }
+
+        $new_dir = serendipity_uploadSecure($serendipity['POST']['parent'] . '/' . $serendipity['POST']['name'], true);
+        $new_dir = str_replace('..', '', $new_dir);
+
+        /* TODO: check if directory already exist */
+        if (@mkdir($serendipity['serendipityPath'] . $serendipity['uploadPath'] . $new_dir)) {
+            printf(DIRECTORY_CREATED, $serendipity['POST']['name']);
+            @umask(0000);
+            @chmod($serendipity['serendipityPath'] . $serendipity['uploadPath'] . $new_dir, 0777);
+        } else {
+            printf(DIRECTORY_WRITE_ERROR, $new_dir);
+        }
+
+
+
+        break;
+
+
+    case 'directoryCreate':
+        if ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF) {
+            return;
+        }
+?>
+    <strong><?php echo CREATE_DIRECTORY ?></strong><br />
+    <?php echo CREATE_DIRECTORY_DESC ?>
+    <br />
+    <br />
+    <form method="POST" action="?serendipity[adminModule]=images&serendipity[adminAction]=directoryDoCreate">
+    <table cellpadding="5">
+        <tr>
+            <td><?php echo NAME ?></td>
+            <td><input type="text" name="serendipity[name]" value="" /></td>
+        </tr>
+        <tr>
+            <td><?php echo PARENT_DIRECTORY ?></td>
+            <td><select name="serendipity[parent]">
+                    <option value=""><?php echo BASE_DIRECTORY ?></option>
+                <?php foreach ( serendipity_traversePath($serendipity['serendipityPath'] . $serendipity['uploadPath']) as $folder ) { ?>
+                    <option value="<?php echo $folder['relpath'] ?>"><?php echo str_repeat('&nbsp;', $folder['depth']*2) . ' '. $folder['name'] ?></option>
+                <?php } ?>
+                </select>
+            </td>
+        </tr>
+    </table>
+    <div><input name="SAVE" value="<?php echo CREATE_DIRECTORY ?>" class="serendipityPrettyButton" type="submit"></div>
+    </form>
+<?php
+        break;
+
+    case 'directorySelect':
+        if ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF) {
+            return;
+        }
+
+?>
+    <br />
+    <?php echo DIRECTORIES_AVAILABLE; ?>
+    <br />
+    <table border="0" cellspacing="0" cellpadding="4" width="100%">
+        <tr>
+            <td colspan="2"><strong><?php echo BASE_DIRECTORY ?></strong></td>
+        </tr>
+        <?php foreach ( serendipity_traversePath($serendipity['serendipityPath'] . $serendipity['uploadPath']) as $folder ) { ?>
+        <tr>
+            <td width="16"><a href="?serendipity[adminModule]=images&amp;serendipity[adminAction]=directoryDelete&amp;serendipity[dir]=<?php echo urlencode($folder['relpath']) ?>"><img src="<?php echo serendipity_getTemplateFile('admin/img/delete.png') ?>" alt="<?php echo DELETE ?>" border="0"></a></td>
+            <td style="padding-left: <?php echo $folder['depth']*10 ?>"><?php echo $folder['name'] ?></td>
+        </tr>
+        <?php } ?>
+    </table>
+    <br />
+    <div><a href="?serendipity[adminModule]=images&serendipity[adminAction]=directoryCreate" class="serendipityPrettyButton"><?php echo CREATE_NEW_DIRECTORY ?></a></div>
+
+<?php
+        break;
+
+    case 'addSelect':
+?>
+    <?php echo ADD_MEDIA_BLAHBLAH; ?>
+
+    <script type="text/javascript">
+    function getfilename(field, value) {
+        re = /^.+[\/\\]+?(.+)$/;
+        document.getElementById(field).value = value.replace(re, "$1");
+    }
+    </script>
+
+    <form action="?" method="POST" id="uploadform" enctype="multipart/form-data">
+        <div>
+            <input type="hidden" name="MAX_FILE_SIZE"            value="3000000" />
+            <input type="hidden" name="serendipity[action]"      value="admin" />
+            <input type="hidden" name="serendipity[adminModule]" value="images" />
+            <input type="hidden" name="serendipity[adminAction]" value="add" />
+<?php
+        if (isset($image_selector_addvars) && is_array($image_selector_addvars)) {
+            // These variables may come frmo serendipity_admin_image_selector.php to show embedded upload form
+            foreach($image_selector_addvars AS $imgsel_key => $imgsel_val) {
+                echo '          <input type="hidden" name="serendipity[' . htmlspecialchars($imgsel_key) . ']" value="' . htmlspecialchars($imgsel_val) . '" />' . "\n";
+            }
+        }
+?>
+            <table>
+                <tr>
+                    <td nowrap="nowrap"><?php echo ENTER_MEDIA_URL; ?></td>
+                    <td><input type="text" name="serendipity[imageurl]" onblur="getfilename('target_filename', this.value);" onchange="getfilename('target_filename', this.value);" onkeyup="getfilename('target_filename', this.value);" value="" size="40" /></td>
+                </tr>
+                <tr>
+                    <td nowrap="nowrap"><?php echo ENTER_MEDIA_URL_METHOD; ?></td>
+                    <td>
+                        <select name="serendipity[imageimporttype]">
+                            <option value="image"><?php echo FETCH_METHOD_IMAGE; ?></option>
+                            <option value="hotlink"><?php echo FETCH_METHOD_HOTLINK; ?></option>
+                        </select>
+                    </td>
+                </tr>
+
+                <tr>
+                    <td align="center" colspan="2"><b> - <?php echo WORD_OR; ?> - </b></td>
+                </tr>
+
+                <tr>
+                    <td nowrap='nowrap'><?php echo ENTER_MEDIA_UPLOAD; ?></td>
+                    <td><input name="userfile" onchange="getfilename('target_filename', this.value);" onblur="getfilename('target_filename', this.value);" onkeyup="getfilename('target_filename', this.value);" type="file" /></td>
+                </tr>
+
+                <tr>
+                    <td align="center" colspan="2"><br /></td>
+                </tr>
+
+                <tr>
+                    <td><?php echo SAVE_FILE_AS; ?></td>
+                    <td><input type="text" id="target_filename" name="serendipity[target_filename]" value="" size="40" /></td>
+                </tr>
+
+                <tr>
+                    <td><?php echo STORE_IN_DIRECTORY; ?></td>
+                    <td>
+                        <select name="serendipity[target_directory]">
+                        <option value=""><?php echo BASE_DIRECTORY; ?></option>
+                        <?php foreach (serendipity_traversePath($serendipity['serendipityPath'] . $serendipity['uploadPath']) as $folder) { ?>
+                        <option <?php echo ($serendipity['GET']['only_path'] == $folder['relpath']) ? 'selected="selected"' : '' ?> value="<?php echo $folder['relpath'] ?>"><?php echo str_repeat('&nbsp;', $folder['depth']*2) . ' '. $folder['name'] ?></option>
+                        <?php } ?>
+                        </select>
+                    </td>
+                </tr>
+
+                <tr>
+                    <td align="right" colspan="2"><input type="checkbox" name="serendipity[all_authors]" value="true" checked="checked" id="all_authors" /><label for="all_authors"><?php echo ALL_AUTHORS; ?></label> <input type="submit" value="<?php echo GO; ?>" class="serendipityPrettyButton" /></td>
+                </tr>
+            </table>
+        </div>
+        <div><?php echo ADD_MEDIA_BLAHBLAH_NOTE; ?></div>
+    </form>
+<?php
+    break;
+
+    case 'rotateCW':
+        if ( serendipity_rotateImg($serendipity['GET']['fid'], -90) ) {
+?>
+        <script language="javascript" type="text/javascript">
+            location.href="<?php echo $_SERVER['HTTP_REFERER'] ?>";
+        </script>
+       <noscript><a href="<?php echo $_SERVER['HTTP_REFERER'] ?>"><?php echo DONE ?></a></noscript>
+<?php
+        }
+    break;
+
+    case 'rotateCCW':
+        if ( serendipity_rotateImg($serendipity['GET']['fid'], 90) ) {
+?>
+        <script language="javascript" type="text/javascript">
+            location.href="<?php echo $_SERVER['HTTP_REFERER'] ?>";
+        </script>
+       <noscript><a href="<?php echo $_SERVER['HTTP_REFERER'] ?>"><?php echo DONE ?></a></noscript>
+<?php
+        }
+    break;
+
+    case 'scale':
+        $file = serendipity_fetchImageFromDatabase($serendipity['GET']['fid']);
+
+        if ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF && $file['authorid'] != '0' && $file['authorid'] != $serendipity['authorid']) {
+            return;
+        }
+
+        printf(
+          SCALING_IMAGE . '<br />',
+
+          $file['path'] . $file['name'] .'.'. $file['extension'],
+          $serendipity['GET']['width'],
+          $serendipity['GET']['height']
+        );
+
+        echo serendipity_scaleImg($serendipity['GET']['fid'], $serendipity['GET']['width'], $serendipity['GET']['height']) . '<br />';
+        echo DONE . '<br />';
+        // Forward user to overview (we don't want the user's back button to rename things again)
+?>
+    <script language="javascript" type="text/javascript">
+       // location.href="?serendipity[adminModule]=images";
+    </script>
+    <noscript><a href="<?php echo $_SERVER['HTTP_REFERER'] ?>"><?php echo DONE ?></a></noscript>
+<?php
+        break;
+
+    case 'scaleSelect':
+        $file = serendipity_fetchImageFromDatabase($serendipity['GET']['fid']);
+
+        if ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF && $file['authorid'] != '0' && $file['authorid'] != $serendipity['authorid']) {
+            return;
+        }
+
+        $s = getimagesize($serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] .'.'. $file['extension']);
+?>
+    <script type="text/javascript" language="javascript">
+    <!--
+        function rescale(dim, newval) {
+            var originalWidth  = <?php echo $s[0]; ?>;
+            var originalHeight = <?php echo $s[1]; ?>;
+            var ratio          = originalHeight/originalWidth;
+            var trans          = new Array();
+            trans['width']     = new Array('serendipity[height]', ratio);
+            trans['height']    = new Array('serendipity[width]', 1/ratio);
+
+            if (document.serendipityScaleForm.elements['auto'].checked == true) {
+                document.serendipityScaleForm.elements[trans[dim][0]].value=Math.round(trans[dim][1]*newval);
+            }
+
+            document.getElementsByName('serendipityScaleImg')[0].style.width =
+              document.serendipityScaleForm.elements['serendipity[width]'].value+'px';
+
+            document.getElementsByName('serendipityScaleImg')[0].style.height =
+              document.serendipityScaleForm.elements['serendipity[height]'].value+'px';
+        }
+    //-->
+    </script>
+<?php
+
+        printf(RESIZE_BLAHBLAH, $serendipity['GET']['fname']);
+        printf(ORIGINAL_SIZE, $s[0],$s[1]);
+        echo HERE_YOU_CAN_ENTER_BLAHBLAH;
+?>
+    <form name="serendipityScaleForm" action="?" method="GET">
+        <div>
+            <?php echo NEWSIZE; ?>
+
+            <input type="hidden" name="serendipity[adminModule]" value="images" />
+            <input type="hidden" name="serendipity[adminAction]" value="scale" />
+            <input type="hidden" name="serendipity[fid]"         value="<?php echo $serendipity["GET"]["fid"]; ?>" />
+
+            <input type="text" size="4" name="serendipity[width]"   onchange="rescale('width' , value);" value="<?php echo $s[0]; ?>" />x
+            <input type="text" size="4" name="serendipity[height]"  onchange="rescale('height', value);" value="<?php echo $s[1]; ?>" />
+            <br />
+
+            <?php echo KEEP_PROPORTIONS; ?>:
+            <!-- <input type='button' value='preview'>-->
+            <input type="checkbox" name="auto"  checked="checked" /><br />
+            <input type="button"   name="scale" value="<?php echo IMAGE_RESIZE; ?>" onclick="if (confirm('<?php echo REALLY_SCALE_IMAGE; ?>')) document.serendipityScaleForm.submit();" class="serendipityPrettyButton" />
+        </div>
+    </form>
+
+    <img src="<?php echo $serendipity['uploadHTTPPath'] . $file['path'] . $file['name'] .'.'. $file['extension'] ; ?>" name="serendipityScaleImg" style="width: <?php echo $s[0]; ?>px; height: <?php echo $s[1]; ?>px;" alt="" />
+<?php
+        break;
+
+    default:
+?>
+<script type="text/javascript" language="javascript">
+    <!--
+        function rename(id, fname) {
+            if(newname = prompt('<?php echo ENTER_NEW_NAME; ?>' + fname, fname)) {
+                location.href='?serendipity[adminModule]=images&serendipity[adminAction]=rename&serendipity[fid]='+ escape(id) + '&serendipity[newname]='+ escape(newname);
+            }
+        }
+    //-->
+    </script>
+
+
+<?php
+        serendipity_displayImageList(
+          isset($serendipity['GET']['page'])   ? $serendipity['GET']['page']   : 1,
+          2,
+          true
+        );
+
+        break;
+}
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/import.inc.php b/include/admin/import.inc.php
new file mode 100644 (file)
index 0000000..1a96a65
--- /dev/null
@@ -0,0 +1,187 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+if (IN_serendipity !== true) {
+    die ("Don't hack!");
+}
+if ( $serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF ) {
+    return;
+}
+
+/* This won't do anything if safe-mode is ON, but let's try anyway since importing could take a while */
+@set_time_limit(0);
+
+/* For later use */
+class Serendipity_Import {
+    var $trans_table = '';
+
+    function getImportNotes() { return ""; }
+
+    function getCharsets($utf8_default = true) {
+        $charsets = array();
+        
+        if (!$utf8_default) {
+            $charsets['native'] = LANG_CHARSET;
+        }
+
+        if (LANG_CHARSET != 'UTF-8') {
+            $charsets['UTF-8'] = 'UTF-8';
+        }
+
+        if (LANG_CHARSET != 'ISO-8859-1') {
+            $charset['ISO-8859-1'] = 'ISO-8859-1';
+        }
+        
+        if ($utf8_default) {
+            $charsets['native'] = LANG_CHARSET;
+        }
+        
+        return $charsets;
+    }
+
+    function decode($string) {
+        switch($this->data['charset']) {
+            case 'native':
+                return $string;
+
+            case 'ISO-8859-1':
+                if (function_exists('iconv')) {
+                    return iconv('ISO-8859-1', LANG_CHARSET, $string);
+                } elseif (function_exists('recode')) {
+                    return recode('iso-8859-1..' . LANG_CHARSET, $string);
+                } else {
+                    return $string;
+                }
+            
+            case 'UTF-8':
+            default:
+                return utf8_decode($string);
+        }
+    }
+
+    function strtr($data) {
+        return strtr($this->decode($data), $this->trans_table);
+    }
+
+    function strtrRecursive($data) {
+        foreach ($data as $key => $val) {
+            if (is_array($val)) {
+                $data[$key] = $this->strtrRecursive($val);
+            } else {
+                $data[$key] = $this->strtr($val);
+            }
+        }
+
+        return $data;
+    }
+    
+    function getTransTable() {
+        if (!serendipity_db_bool($this->data['use_strtr'])) {
+            $this->trans_table = array();
+            return true;
+        }
+
+        // We need to convert interesting characters to HTML entities, except for those with special relevance to HTML.
+        $this->trans_table = get_html_translation_table(HTML_ENTITIES);
+        foreach (get_html_translation_table(HTML_SPECIALCHARS) as $char => $encoded) {
+            if (isset($this->trans_table[$char])) {
+                unset($this->trans_table[$char]);
+            }
+        }
+    }
+}
+
+if ( isset($serendipity['GET']['importFrom']) ) {
+
+    /* Include the importer */
+    $class = @require_once(S9Y_INCLUDE_PATH . 'include/admin/importers/'. basename($serendipity['GET']['importFrom']) .'.inc.php');
+    if ( !class_exists($class) ) {
+        die('FAILURE: Unable to require import module, possible syntax error?');
+    }
+
+    /* Init the importer with form data */
+    $importer = new $class($serendipity['POST']['import']);
+
+    /* Yes sir, we are importing if we have valid data */
+    if ( $importer->validateData() ) {
+        echo IMPORT_STARTING . '<br />';
+
+        /* import() MUST return (bool)true, otherwise we assume it failed */
+        if ( ($result = $importer->import()) !== true ) {
+            echo IMPORT_FAILED .': '. $result . '<br />';
+        } else {
+            echo IMPORT_DONE . '<br />';
+        }
+
+
+    /* Apprently we do not have valid data, ask for some */
+    } else {
+?>
+
+<?php echo IMPORT_PLEASE_ENTER ?>:<br />
+<br />
+<form action="" method="POST" enctype="multipart/form-data">
+  <table cellpadding="3" cellspacing="2">
+    <?php foreach ( $importer->getInputFields() as $field ) { ?>
+    <tr>
+      <td><?php echo $field['text'] ?></td>
+      <td><?php serendipity_guessInput($field['type'], 'serendipity[import]['. $field['name'] .']', (isset($serendipity['POST']['import'][$field['name']]) ? $serendipity['POST']['import'][$field['name']] : $field['default']), $field['default']) ?></td>
+    </tr>
+    <?php } ?>
+    <?php if ($notes = $importer->getImportNotes()){ ?>
+    <tr>
+      <td colspan="2">
+        <b><?php echo IMPORT_NOTES; ?></b><br />
+        <?php echo $notes ?>
+      </td>
+    </tr>
+    <?php } ?>
+    <tr>
+      <td colspan="2" align="right"><input type="submit" value="<?php echo IMPORT_NOW ?>" class="serendipityPrettyButton"></td>
+    </tr>
+  </table>
+</form>
+<?php
+    }
+
+} else {
+
+    $importpath = S9Y_INCLUDE_PATH . 'include/admin/importers/';
+    $dir        = opendir($importpath);
+    $list       = array();
+    while (($file = readdir($dir)) !== false ) {
+        if (!is_file($importpath . $file)) {
+            continue;
+        }
+
+        $class = include_once($importpath . $file);
+        if ( class_exists($class) ) {
+            $tmpClass = new $class(array());
+            $list[substr($file, 0, strpos($file, '.'))] = $tmpClass->info['software'];
+            unset($tmpClass);
+        }
+    }
+    closedir($dir);
+    ksort($list);
+?>
+<?php echo IMPORT_WELCOME ?>.<br />
+<?php echo IMPORT_WHAT_CAN ?>. <br />
+<br />
+<?php echo IMPORT_SELECT ?>:<br />
+<br />
+<form action="" method="GET">
+  <input type="hidden" name="serendipity[adminModule]" value="import">
+  <strong><?php echo IMPORT_WEBLOG_APP ?>: </strong>
+  <select name="serendipity[importFrom]">
+    <?php foreach ($list as $v=>$k) { ?>
+    <option value="<?php echo $v ?>"><?php echo $k ?></option>
+    <?php } ?>
+  </select>
+  <input type="submit" value="<?php echo GO ?>" class="serendipityPrettyButton">
+</form>
+<?php
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/importers/b2evolution.inc.php b/include/admin/importers/b2evolution.inc.php
new file mode 100644 (file)
index 0000000..5328a19
--- /dev/null
@@ -0,0 +1,297 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+/*****************************************************************
+ *  b2evolution  Importer,   by Garvin Hicking *
+ * ****************************************************************/
+
+class Serendipity_Import_b2evolution extends Serendipity_Import {
+    var $info        = array('software' => 'b2Evolution 0.9.0.11 Paris');
+    var $data        = array();
+    var $inputFields = array();
+    var $categories  = array();
+
+    function getImportNotes() {
+        return '';
+    }
+
+    function Serendipity_Import_b2evolution($data) {
+        $this->data = $data;
+        $this->inputFields = array(array('text' => INSTALL_DBHOST,
+                                         'type' => 'input',
+                                         'name' => 'host'),
+
+                                   array('text' => INSTALL_DBUSER,
+                                         'type' => 'input',
+                                         'name' => 'user'),
+
+                                   array('text' => INSTALL_DBPASS,
+                                         'type' => 'protected',
+                                         'name' => 'pass'),
+
+                                   array('text' => INSTALL_DBNAME,
+                                         'type' => 'input',
+                                         'name' => 'name'),
+
+                                   array('text'    => CHARSET,
+                                         'type'    => 'list',
+                                         'name'    => 'charset',
+                                         'value'   => 'UTF-8',
+                                         'default' => $this->getCharsets(true)),
+
+                                   array('text'    => CONVERT_HTMLENTITIES,
+                                         'type'    => 'bool',
+                                         'name'    => 'use_strtr',
+                                         'default' => 'true'),
+
+                                   array('text'    => ACTIVATE_AUTODISCOVERY,
+                                         'type'    => 'bool',
+                                         'name'    => 'autodiscovery',
+                                         'default' => 'false')
+                            );
+    }
+
+    function validateData() {
+        return sizeof($this->data);
+    }
+
+    function getInputFields() {
+        return $this->inputFields;
+    }
+
+    function import() {
+        global $serendipity;
+
+        // Save this so we can return it to its original value at the end of this method.
+        $noautodiscovery = isset($serendipity['noautodiscovery']) ? $serendipity['noautodiscovery'] : false;
+
+        if ($this->data['autodiscovery'] == 'false') {
+            $serendipity['noautodiscovery'] = 1;
+        }
+
+        $this->getTransTable();
+
+        $users = array();
+        $entries = array();
+
+        if (!extension_loaded('mysql')) {
+            return MYSQL_REQUIRED;
+        }
+
+        $b2db = @mysql_connect($this->data['host'], $this->data['user'], $this->data['pass']);
+        if (!$b2db) {
+            return sprintf(COULDNT_CONNECT, $this->data['host']);
+        }
+
+        if (!@mysql_select_db($this->data['name'])) {
+            return sprintf(COULDNT_SELECT_DB, mysql_error($b2db));
+        }
+
+        /* Users */
+        $res = @mysql_query("SELECT ID         AS ID,
+                                    user_login AS user_login,
+                                    user_pass  AS user_pass,
+                                    user_email AS user_email,
+                                    user_level AS user_level,
+                                    user_url   AS user_url
+                               FROM evo_users", $b2db);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_USER_INFO, mysql_error($b2db));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res); $x < $max_x ; $x++ ) {
+            $users[$x] = mysql_fetch_assoc($res);
+
+            $data = array('right_publish' => ($users[$x]['user_level'] >= 2) ? 1 : 0,
+                          'realname'      => $users[$x]['user_login'],
+                          'username'      => $users[$x]['user_login'],
+                          'email'         => $users[$x]['user_email'],
+                          'password'      => $users[$x]['user_pass']); // MD5 compatible
+
+            if ( $users[$x]['user_level'] <= 2 ) {
+                $data['userlevel'] = USERLEVEL_EDITOR;
+            } elseif ($users[$x]['user_level'] <= 9) {
+                $data['userlevel'] = USERLEVEL_CHIEF;
+            } else {
+                $data['userlevel'] = USERLEVEL_ADMIN;
+            }
+
+            if ($serendipity['serendipityUserlevel'] < $data['userlevel']) {
+                $data['userlevel'] = $serendipity['serendipityUserlevel'];
+            }
+
+            serendipity_db_insert('authors', $this->strtrRecursive($data));
+            $users[$x]['authorid'] = serendipity_db_insert_id('authors', 'authorid');
+        }
+
+        /* Categories */
+        if (!$this->importCategories(null)) {
+            return sprintf(COULDNT_SELECT_CATEGORY_INFO, mysql_error($b2db));
+        }
+        serendipity_rebuildCategoryTree();
+
+        /* Entries */
+        $res = @mysql_query("SELECT * FROM evo_posts ORDER BY ID;", $b2db);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_ENTRY_INFO, mysql_error($b2db));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++ ) {
+            $entries[$x] = mysql_fetch_assoc($res);
+
+            $entry = array('title'          => $this->decode($entries[$x]['post_title']),
+                           'isdraft'        => ($entries[$x]['post_status'] == 'published') ? 'false' : 'true',
+                           'allow_comments' => ($entries[$x]['post_comments'] == 'open' ) ? 'true' : 'false',
+                           'timestamp'      => strtotime($entries[$x]['post_issue_date']),
+                           'body'           => $this->strtr($entries[$x]['post_content']));
+
+            $entry['authorid'] = '';
+            $entry['author']   = '';
+            foreach ($users as $user) {
+                if ($user['ID'] == $entries[$x]['post_author']) {
+                    $entry['authorid'] = $user['authorid'];
+                    $entry['author']   = $user['user_login'];
+                    break;
+                }
+            }
+
+            if (!is_int($entries[$x]['entryid'] = serendipity_updertEntry($entry))) {
+                return $entries[$x]['entryid'];
+            }
+
+            /* Entry/category */
+            foreach ($this->categories as $category) {
+                if ($category['cat_ID'] == $entries[$x]['post_category'] ) {
+                    $data = array('entryid'    => $entries[$x]['entryid'],
+                                  'categoryid' => $category['categoryid']);
+                    serendipity_db_insert('entrycat', $this->strtrRecursive($data));
+                    break;
+                }
+            }
+        }
+
+        /* Even more category stuff */
+        $res = @mysql_query("SELECT * FROM evo_postcats;", $b2db);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_CATEGORY_INFO, mysql_error($b2db));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++ ) {
+            $entrycat = mysql_fetch_assoc($res);
+
+            $entryid = 0;
+            $categoryid = 0;
+            foreach($entries AS $entry) {
+                if ($entry['ID'] == $entrycat['postcat_post_ID']) {
+                    $entryid = $entry['entryid'];
+                    break;
+                }
+            }
+
+            foreach($this->categories AS $category) {
+                if ($category['cat_ID'] == $entrycat['postcat_cat_ID']) {
+                    $categoryid = $category['categoryid'];
+                }
+            }
+
+            if ($entryid > 0 && $categoryid > 0) {
+                $data = array('entryid'    => $entryid,
+                              'categoryid' => $categoryid);
+                serendipity_db_insert('entrycat', $this->strtrRecursive($data));
+            }
+        }
+
+        /* Comments */
+        $res = @mysql_query("SELECT * FROM evo_comments;", $b2db);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_COMMENT_INFO, mysql_error($b2db));
+        }
+
+        while ($a = mysql_fetch_assoc($res)) {
+            foreach ($entries as $entry) {
+                if ($entry['ID'] == $a['comment_post_ID'] ) {
+                    $author = '';
+                    $mail     = '';
+                    $url      = '';
+                    if (!empty($a['comment_author_ID'])) {
+                        foreach($users AS $user) {
+                            if ($user['ID'] == $a['comment_author_ID']) {
+                                $author = $user['user_login'];
+                                $mail = $user['user_email'];
+                                $url  = $user['user_url'];
+                                break;
+                            }
+                        }
+                    }
+
+                    if (empty($author) && empty($mail)) {
+                        $author = $a['comment_author'];
+                        $mail = $a['comment_author_email'];
+                        $url = $a['comment_author_url'];
+                    }
+
+                    $comment = array('entry_id ' => $entry['entryid'],
+                                     'parent_id' => 0,
+                                     'timestamp' => strtotime($a['comment_date']),
+                                     'author'    => $author,
+                                     'email'     => $mail,
+                                     'url'       => $url,
+                                     'ip'        => $a['comment_author_IP'],
+                                     'status'    => ($a['comment_status'] == 'published' ? 'approved' : 'pending'),
+                                     'body'      => $a['comment_content'],
+                                     'subscribed'=> 'false',
+                                     'type'      => 'NORMAL');
+
+                    serendipity_db_insert('comments', $this->strtrRecursive($comment));
+                    if ($a['comment_status'] == 'published') {
+                        $cid = serendipity_db_insert_id('comments', 'id');
+                        serendipity_approveComment($cid, $entry['entryid'], true);
+                    }
+                }
+            }
+        }
+
+        $serendipity['noautodiscovery'] = $noautodiscovery;
+
+        // That was fun.
+        return true;
+    }
+
+    function importCategories($parentid = 0, $new_parentid = 0) {
+        if (is_null($parentid)) {
+            $where = 'WHERE ISNULL(cat_parent_ID)';
+        } else {
+            $where = "WHERE cat_parent_ID = '" . mysql_escape_string($parentid) . "'";
+        }
+
+        $res = mysql_query("SELECT * FROM evo_categories
+                                     " . $where);
+        if (!$res) {
+            echo mysql_error();
+            return false;
+        }
+
+        // Get all the info we need
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++) {
+            $row = mysql_fetch_assoc($res);
+            $cat = array('category_name'        => $row['cat_name'],
+                         'category_description' => $row['cat_description'],
+                         'parentid'             => (int)$new_parentid,
+                         'category_left'        => 0,
+                         'category_right'       => 0);
+
+            serendipity_db_insert('category', $this->strtrRecursive($cat));
+            $row['categoryid']  = serendipity_db_insert_id('category', 'categoryid');
+            $this->categories[] = $row;
+            $this->importCategories($row['cat_ID'], $row['categoryid']);
+        }
+
+        return true;
+    }
+}
+
+return 'Serendipity_Import_b2evolution';
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/importers/bblog.inc.php b/include/admin/importers/bblog.inc.php
new file mode 100644 (file)
index 0000000..cd458cf
--- /dev/null
@@ -0,0 +1,233 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+/*****************************************************************
+ *  bblog  Importer,    by Garvin Hicking *
+ * ****************************************************************/
+
+class Serendipity_Import_bblog extends Serendipity_Import {
+    var $info        = array('software' => 'bBlog 0.7.4');
+    var $data        = array();
+    var $inputFields = array();
+    var $categories  = array();
+
+    function Serendipity_Import_bblog($data) {
+        $this->data = $data;
+        $this->inputFields = array(array('text' => INSTALL_DBHOST,
+                                         'type' => 'input',
+                                         'name' => 'host'),
+
+                                   array('text' => INSTALL_DBUSER,
+                                         'type' => 'input',
+                                         'name' => 'user'),
+
+                                   array('text' => INSTALL_DBPASS,
+                                         'type' => 'protected',
+                                         'name' => 'pass'),
+
+                                   array('text' => INSTALL_DBNAME,
+                                         'type' => 'input',
+                                         'name' => 'name'),
+
+                                   array('text' => INSTALL_DBPREFIX,
+                                         'type' => 'input',
+                                         'name' => 'prefix',
+                                         'default' => 'bB_'),
+
+                                   array('text'    => CHARSET,
+                                         'type'    => 'list',
+                                         'name'    => 'charset',
+                                         'value'   => 'native',
+                                         'default' => $this->getCharsets()),
+
+                                   array('text'    => CONVERT_HTMLENTITIES,
+                                         'type'    => 'bool',
+                                         'name'    => 'use_strtr',
+                                         'default' => 'true'),
+
+                                   array('text'    => ACTIVATE_AUTODISCOVERY,
+                                         'type'    => 'bool',
+                                         'name'    => 'autodiscovery',
+                                         'default' => 'false')
+                            );
+    }
+
+    function validateData() {
+        return sizeof($this->data);
+    }
+
+    function getInputFields() {
+        return $this->inputFields;
+    }
+
+    function import() {
+        global $serendipity;
+
+        // Save this so we can return it to its original value at the end of this method.
+        $noautodiscovery = isset($serendipity['noautodiscovery']) ? $serendipity['noautodiscovery'] : false;
+
+        if ($this->data['autodiscovery'] == 'false') {
+            $serendipity['noautodiscovery'] = 1;
+        }
+
+        $this->getTransTable();
+
+        $this->data['prefix'] = serendipity_db_escape_string($this->data['prefix']);
+        $users = array();
+        $entries = array();
+
+        if (!extension_loaded('mysql')) {
+            return MYSQL_REQUIRED;
+        }
+
+        $bblogdb = @mysql_connect($this->data['host'], $this->data['user'], $this->data['pass']);
+        if (!$bblogdb) {
+            return sprintf(COULDNT_CONNECT, $this->data['host']);
+        }
+
+        if (!@mysql_select_db($this->data['name'])) {
+            return sprintf(COULDNT_SELECT_DB, mysql_error($bblogdb));
+        }
+
+        /* Users */
+        $res = @mysql_query("SELECT id         AS ID,
+                                    password   AS pw,
+                                    nickname   AS user_login,
+                                    email      AS user_email,
+                                    url        AS user_url
+                               FROM {$this->data['prefix']}authors", $bblogdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_USER_INFO, mysql_error($bblogdb));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res); $x < $max_x ; $x++ ) {
+            $users[$x] = mysql_fetch_assoc($res);
+
+            $data = array('right_publish' => 1,
+                          'username'      => $users[$x]['user_login'],
+                          'email'         => $users[$x]['user_email'],
+                          'userlevel'     => USERLEVEL_ADMIN,
+                          'password'      => md5($users[$x]['pw'])); // Wicked. This is the first blog I've seen storing cleartext passwords :-D
+
+            if ($serendipity['serendipityUserlevel'] < $data['userlevel']) {
+                $data['userlevel'] = $serendipity['serendipityUserlevel'];
+            }
+
+            serendipity_db_insert('authors', $this->strtrRecursive($data));
+            echo mysql_error();
+            $users[$x]['authorid'] = serendipity_db_insert_id('authors', 'authorid');
+        }
+
+        /* Categories */
+        $res = @mysql_query("SELECT * FROM {$this->data['prefix']}sections", $bblogdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_CATEGORY_INFO, mysql_error($bblogdb));
+        }
+
+        // Get all the info we need
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++) {
+            $row = mysql_fetch_assoc($res);
+            $cat = array('category_name'        => $row['nicename'],
+                         'category_description' => $row['nicename'],
+                         'parentid'             => 0,
+                         'category_left'        => 0,
+                         'category_right'       => 0);
+
+            serendipity_db_insert('category', $this->strtrRecursive($cat));
+            $row['categoryid']  = serendipity_db_insert_id('category', 'categoryid');
+            $this->categories[] = $row;
+        }
+
+        serendipity_rebuildCategoryTree();
+
+        /* Entries */
+        $res = @mysql_query("SELECT * FROM {$this->data['prefix']}posts ORDER BY postid;", $bblogdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_ENTRY_INFO, mysql_error($bblogdb));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++ ) {
+            $entries[$x] = mysql_fetch_assoc($res);
+
+            $entry = array('title'          => $this->decode($entries[$x]['title']),
+                           'isdraft'        => ($entries[$x]['status'] == 'live') ? 'false' : 'true',
+                           'allow_comments' => ($entries[$x]['allowcomments'] == 'allow' ) ? 'true' : 'false',
+                           'timestamp'      => $entries[$x]['posttime'],
+                           'body'           => $this->strtr($entries[$x]['body']),
+                           'extended'       => '',
+                           );
+
+            $entry['authorid'] = '';
+            $entry['author']   = '';
+            foreach ($users as $user) {
+                if ($user['ID'] == $entries[$x]['author']) {
+                    $entry['authorid'] = $user['authorid'];
+                    $entry['author']   = $user['user_login'];
+                    break;
+                }
+            }
+
+            if (!is_int($entries[$x]['entryid'] = serendipity_updertEntry($entry))) {
+                return $entries[$x]['entryid'];
+            }
+
+            $sections = explode(':', $entries[$x]['sections']);
+            foreach($sections AS $section) {
+                if (empty($section)) {
+                    continue;
+                }
+
+                foreach($this->categories AS $category) {
+                    if ($category['sectionid'] == $section) {
+                        $categoryid = $category['categoryid'];
+                    }
+                }
+
+                if ($categoryid > 0) {
+                    $data = array('entryid'    => $entries[$x]['entryid'],
+                                  'categoryid' => $categoryid);
+                    serendipity_db_insert('entrycat', $this->strtrRecursive($data));
+                }
+            }
+        }
+
+        /* Comments */
+        $res = @mysql_query("SELECT * FROM {$this->data['prefix']}comments WHERE type = 'comment';", $bblogdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_COMMENT_INFO, mysql_error($bblogdb));
+        }
+
+        while ($a = mysql_fetch_assoc($res)) {
+            foreach ($entries as $entry) {
+                if ($entry['postid'] == $a['postid'] ) {
+                    $comment = array('entry_id ' => $entry['entryid'],
+                                     'parent_id' => 0,
+                                     'timestamp' => $a['posttime'],
+                                     'author'    => $a['postername'],
+                                     'email'     => $a['posteremail'],
+                                     'url'       => $a['posterwebsite'],
+                                     'ip'        => $a['ip'],
+                                     'status'    => 'approved',
+                                     'body'      => $a['commenttext'],
+                                     'subscribed'=> 'false',
+                                     'type'      => 'NORMAL');
+
+                    serendipity_db_insert('comments', $this->strtrRecursive($comment));
+                    $cid = serendipity_db_insert_id('comments', 'id');
+                    serendipity_approveComment($cid, $entry['entryid'], true);
+                }
+            }
+        }
+
+        $serendipity['noautodiscovery'] = $noautodiscovery;
+
+        // That was fun.
+        return true;
+    }
+}
+
+return 'Serendipity_Import_bblog';
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/importers/bmachine.inc.php b/include/admin/importers/bmachine.inc.php
new file mode 100644 (file)
index 0000000..7d05cc1
--- /dev/null
@@ -0,0 +1,255 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+/*****************************************************************
+ *  bmachine  Importer,   by Garvin Hicking *
+ * ****************************************************************/
+
+class Serendipity_Import_bmachine extends Serendipity_Import {
+    var $info        = array('software' => 'boastMachine 3.0');
+    var $data        = array();
+    var $inputFields = array();
+    var $categories  = array();
+
+    function getImportNotes() {
+        return '';
+    }
+
+    function Serendipity_Import_bmachine($data) {
+        $this->data = $data;
+        $this->inputFields = array(array('text' => INSTALL_DBHOST,
+                                         'type' => 'input',
+                                         'name' => 'host'),
+
+                                   array('text' => INSTALL_DBUSER,
+                                         'type' => 'input',
+                                         'name' => 'user'),
+
+                                   array('text' => INSTALL_DBPASS,
+                                         'type' => 'protected',
+                                         'name' => 'pass'),
+
+                                   array('text' => INSTALL_DBNAME,
+                                         'type' => 'input',
+                                         'name' => 'name'),
+
+                                   array('text'    => CHARSET,
+                                         'type'    => 'list',
+                                         'name'    => 'charset',
+                                         'value'   => 'native',
+                                         'default' => $this->getCharsets()),
+
+                                   array('text'    => CONVERT_HTMLENTITIES,
+                                         'type'    => 'bool',
+                                         'name'    => 'use_strtr',
+                                         'default' => 'true'),
+
+                                   array('text'    => ACTIVATE_AUTODISCOVERY,
+                                         'type'    => 'bool',
+                                         'name'    => 'autodiscovery',
+                                         'default' => 'false')
+                            );
+    }
+
+    function validateData() {
+        return sizeof($this->data);
+    }
+
+    function getInputFields() {
+        return $this->inputFields;
+    }
+
+    function import() {
+        global $serendipity;
+
+        // Save this so we can return it to its original value at the end of this method.
+        $noautodiscovery = isset($serendipity['noautodiscovery']) ? $serendipity['noautodiscovery'] : false;
+
+        if ($this->data['autodiscovery'] == 'false') {
+            $serendipity['noautodiscovery'] = 1;
+        }
+
+        $this->getTransTable();
+
+        $users = array();
+        $entries = array();
+
+        if (!extension_loaded('mysql')) {
+            return MYSQL_REQUIRED;
+        }
+
+        $txpdb = @mysql_connect($this->data['host'], $this->data['user'], $this->data['pass']);
+        if (!$txpdb) {
+            return sprintf(COULDNT_CONNECT, $this->data['host']);
+        }
+
+        if (!@mysql_select_db($this->data['name'])) {
+            return sprintf(COULDNT_SELECT_DB, mysql_error($txpdb));
+        }
+
+        /* Users */
+        $res = @mysql_query("SELECT id         AS ID,
+                                    user_login AS user_login,
+                                    user_pass  AS user_pass,
+                                    user_email AS user_email,
+                                    level      AS user_level,
+                                    user_url   AS user_url
+                               FROM bmc_users", $txpdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_USER_INFO, mysql_error($txpdb));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res); $x < $max_x ; $x++ ) {
+            $users[$x] = mysql_fetch_assoc($res);
+
+            $data = array('right_publish' => ($users[$x]['user_level'] >= 2) ? 1 : 0,
+                          'realname'      => $users[$x]['user_login'],
+                          'username'      => $users[$x]['user_login'],
+                          'email'         => $users[$x]['user_email'],
+                          'password'      => $users[$x]['user_pass']); // MD5 compatible
+
+            if ( $users[$x]['user_level'] <= 2 ) {
+                $data['userlevel'] = USERLEVEL_EDITOR;
+            } elseif ($users[$x]['user_level'] == 3) {
+                $data['userlevel'] = USERLEVEL_CHIEF;
+            } else {
+                $data['userlevel'] = USERLEVEL_ADMIN;
+            }
+
+            if ($serendipity['serendipityUserlevel'] < $data['userlevel']) {
+                $data['userlevel'] = $serendipity['serendipityUserlevel'];
+            }
+
+            serendipity_db_insert('authors', $this->strtrRecursive($data));
+            $users[$x]['authorid'] = serendipity_db_insert_id('authors', 'authorid');
+        }
+
+        /* Categories */
+        $res = @mysql_query("SELECT id       AS cat_ID,
+                                    cat_name AS cat_name,
+                                    cat_info AS category_description
+                               FROM bmc_cats ORDER BY id;", $txpdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_CATEGORY_INFO, mysql_error($txpdb));
+        }
+
+        // Get all the info we need
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++) {
+            $categories[] = mysql_fetch_assoc($res);
+        }
+
+        // Insert all categories as top level (we need to know everyone's ID before we can represent the hierarchy).
+        for ($x=0, $max_x = sizeof($categories) ; $x < $max_x ; $x++ ) {
+            $cat = array('category_name'        => $categories[$x]['cat_name'],
+                         'category_description' => $categories[$x]['category_description'],
+                         'parentid'             => 0, // <---
+                         'category_left'        => 0,
+                         'category_right'       => 0);
+
+            serendipity_db_insert('category', $this->strtrRecursive($cat));
+            $categories[$x]['categoryid'] = serendipity_db_insert_id('category', 'categoryid');
+        }
+
+        serendipity_rebuildCategoryTree();
+
+        /* Entries */
+        $res = @mysql_query("SELECT * FROM bmc_posts ORDER BY id;", $txpdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_ENTRY_INFO, mysql_error($txpdb));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++ ) {
+            $entries[$x] = mysql_fetch_assoc($res);
+
+            $entry = array('title'          => $this->decode($entries[$x]['title']),
+                           'isdraft'        => ($entries[$x]['status'] == '1') ? 'false' : 'true',
+                           'allow_comments' => ($entries[$x]['m_cmt'] == '1' ) ? 'true' : 'false',
+                           'timestamp'      => $entries[$x]['date'],
+                           'extended'       => $this->strtr($entries[$x]['data']),
+                           'body'           => $this->strtr($entries[$x]['summary']));
+
+            $entry['authorid'] = '';
+            $entry['author']   = '';
+            foreach ($users as $user) {
+                if ($user['ID'] == $entries[$x]['author']) {
+                    $entry['authorid'] = $user['authorid'];
+                    $entry['author']   = $user['user_login'];
+                    break;
+                }
+            }
+
+            if (!is_int($entries[$x]['entryid'] = serendipity_updertEntry($entry))) {
+                return $entries[$x]['entryid'];
+            }
+
+            /* Entry/category */
+            foreach ($this->categories as $category) {
+                if ($category['cat_ID'] == $entries[$x]['cat'] ) {
+                    $data = array('entryid'    => $entries[$x]['entryid'],
+                                  'categoryid' => $category['categoryid']);
+                    serendipity_db_insert('entrycat', $this->strtrRecursive($data));
+                    break;
+                }
+            }
+        }
+
+        /* Comments */
+        $res = @mysql_query("SELECT * FROM bmc_comments;", $txpdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_COMMENT_INFO, mysql_error($txpdb));
+        }
+
+        while ($a = mysql_fetch_assoc($res)) {
+            foreach ($entries as $entry) {
+                if ($entry['id'] == $a['post'] ) {
+                    $author   = '';
+                    $mail     = '';
+                    $url      = '';
+                    if (!empty($a['author'])) {
+                        foreach($users AS $user) {
+                            if ($user['ID'] == $a['author']) {
+                                $author = $user['user_login'];
+                                $mail = $user['user_email'];
+                                $url  = $user['user_url'];
+                                break;
+                            }
+                        }
+                    }
+
+                    if (empty($author) && empty($mail)) {
+                        $author = $a['auth_name'];
+                        $mail = $a['auth_email'];
+                        $url = $a['auth_url'];
+                    }
+
+                    $comment = array('entry_id ' => $entry['entryid'],
+                                     'parent_id' => 0,
+                                     'timestamp' => $a['date'],
+                                     'author'    => $author,
+                                     'email'     => $mail,
+                                     'url'       => $url,
+                                     'ip'        => $a['auth_ip'],
+                                     'status'    => 'approved',
+                                     'body'      => $a['data'],
+                                     'subscribed'=> 'false',
+                                     'type'      => 'NORMAL');
+
+                    serendipity_db_insert('comments', $this->strtrRecursive($comment));
+                    $cid = serendipity_db_insert_id('comments', 'id');
+                    serendipity_approveComment($cid, $entry['entryid'], true);
+                }
+            }
+        }
+
+        $serendipity['noautodiscovery'] = $noautodiscovery;
+
+        // That was fun.
+        return true;
+    }
+}
+
+return 'Serendipity_Import_bmachine';
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/importers/geeklog.inc.php b/include/admin/importers/geeklog.inc.php
new file mode 100644 (file)
index 0000000..b4f6603
--- /dev/null
@@ -0,0 +1,245 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+/*****************************************************************
+ *  geeklog  Importer,    by Garvin Hicking *
+ * ****************************************************************/
+
+class Serendipity_Import_geeklog extends Serendipity_Import {
+    var $info        = array('software' => 'Geeklog 1.3.11');
+    var $data        = array();
+    var $inputFields = array();
+    var $categories  = array();
+
+    function getImportNotes() {
+        return 'GeekLog has a granular control over access privileges which cannot be migrated to Serendipity. All Users will be migrated as Superusers, you may need to set them to editor or chief users manually after import.';
+    }
+
+    function Serendipity_Import_geeklog($data) {
+        $this->data = $data;
+        $this->inputFields = array(array('text' => INSTALL_DBHOST,
+                                         'type' => 'input',
+                                         'name' => 'host'),
+
+                                   array('text' => INSTALL_DBUSER,
+                                         'type' => 'input',
+                                         'name' => 'user'),
+
+                                   array('text' => INSTALL_DBPASS,
+                                         'type' => 'protected',
+                                         'name' => 'pass'),
+
+                                   array('text' => INSTALL_DBNAME,
+                                         'type' => 'input',
+                                         'name' => 'name'),
+
+                                   array('text' => INSTALL_DBPREFIX,
+                                         'type' => 'input',
+                                         'name' => 'prefix',
+                                         'default' => 'gl_'),
+
+                                   array('text'    => CHARSET,
+                                         'type'    => 'list',
+                                         'name'    => 'charset',
+                                         'value'   => 'native',
+                                         'default' => $this->getCharsets()),
+
+                                   array('text'    => CONVERT_HTMLENTITIES,
+                                         'type'    => 'bool',
+                                         'name'    => 'use_strtr',
+                                         'default' => 'true'),
+
+                                   array('text'    => ACTIVATE_AUTODISCOVERY,
+                                         'type'    => 'bool',
+                                         'name'    => 'autodiscovery',
+                                         'default' => 'false')
+                            );
+    }
+
+    function validateData() {
+        return sizeof($this->data);
+    }
+
+    function getInputFields() {
+        return $this->inputFields;
+    }
+
+    function import() {
+        global $serendipity;
+
+        // Save this so we can return it to its original value at the end of this method.
+        $noautodiscovery = isset($serendipity['noautodiscovery']) ? $serendipity['noautodiscovery'] : false;
+
+        if ($this->data['autodiscovery'] == 'false') {
+            $serendipity['noautodiscovery'] = 1;
+        }
+
+        $this->getTransTable();
+
+        $this->data['prefix'] = serendipity_db_escape_string($this->data['prefix']);
+        $users = array();
+        $entries = array();
+
+        if (!extension_loaded('mysql')) {
+            return MYSQL_REQUIRED;
+        }
+
+        $gdb = @mysql_connect($this->data['host'], $this->data['user'], $this->data['pass']);
+        if (!$gdb) {
+            return sprintf(COULDNT_CONNECT, $this->data['host']);
+        }
+
+        if (!@mysql_select_db($this->data['name'])) {
+            return sprintf(COULDNT_SELECT_DB, mysql_error($gdb));
+        }
+
+        /* Users */
+        $res = @mysql_query("SELECT uid        AS ID,
+                                    username   AS user_login,
+                                    passwd     AS user_pass,
+                                    email      AS user_email,
+                                    homepage   AS user_url
+                               FROM {$this->data['prefix']}users", $gdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_USER_INFO, mysql_error($gdb));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res); $x < $max_x ; $x++ ) {
+            $users[$x] = mysql_fetch_assoc($res);
+
+            $data = array('right_publish' => 1,
+                          'realname'      => $users[$x]['user_login'],
+                          'username'      => $users[$x]['user_login'],
+                          'email'         => $users[$x]['user_email'],
+                          'userlevel'     => USERLEVEL_ADMIN,
+                          'password'      => $users[$x]['user_pass']); // MD5 compatible
+
+            if ($serendipity['serendipityUserlevel'] < $data['userlevel']) {
+                $data['userlevel'] = $serendipity['serendipityUserlevel'];
+            }
+
+            serendipity_db_insert('authors', $this->strtrRecursive($data));
+            echo mysql_error();
+            $users[$x]['authorid'] = serendipity_db_insert_id('authors', 'authorid');
+        }
+
+        /* Categories */
+        $res = @mysql_query("SELECT tid AS cat_ID, topic AS cat_name, topic AS category_description FROM {$this->data['prefix']}topics ORDER BY tid;", $gdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_CATEGORY_INFO, mysql_error($gdb));
+        }
+
+        // Get all the info we need
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++) {
+            $categories[] = mysql_fetch_assoc($res);
+        }
+
+        // Insert all categories as top level (we need to know everyone's ID before we can represent the hierarchy).
+        for ($x=0, $max_x = sizeof($categories) ; $x < $max_x ; $x++ ) {
+            $cat = array('category_name'        => $categories[$x]['cat_name'],
+                         'category_description' => $categories[$x]['category_description'],
+                         'parentid'             => 0, // <---
+                         'category_left'        => 0,
+                         'category_right'       => 0);
+
+            serendipity_db_insert('category', $this->strtrRecursive($cat));
+            $categories[$x]['categoryid'] = serendipity_db_insert_id('category', 'categoryid');
+        }
+
+        serendipity_rebuildCategoryTree();
+
+        /* Entries */
+        $res = @mysql_query("SELECT * FROM {$this->data['prefix']}stories ORDER BY sid;", $gdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_ENTRY_INFO, mysql_error($gdb));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++ ) {
+            $entries[$x] = mysql_fetch_assoc($res);
+
+            $entry = array('title'          => $this->decode($entries[$x]['title']),
+                           'isdraft'        => ($entries[$x]['draft_flag'] == '0') ? 'false' : 'true',
+                           'allow_comments' => ($entries[$x]['comments'] == '1' ) ? 'true' : 'false',
+                           'timestamp'      => strtotime($entries[$x]['date']),
+                           'body'           => $this->strtr($entries[$x]['introtext']),
+                           'extended'       => $this->strtr($entries[$x]['bodytext']),
+                           );
+
+            $entry['authorid'] = '';
+            $entry['author']   = '';
+            foreach ($users as $user) {
+                if ($user['ID'] == $entries[$x]['uid']) {
+                    $entry['authorid'] = $user['authorid'];
+                    $entry['author']   = $user['user_login'];
+                    break;
+                }
+            }
+
+            if (!is_int($entries[$x]['entryid'] = serendipity_updertEntry($entry))) {
+                return $entries[$x]['entryid'];
+            }
+
+            /* Entry/category */
+            foreach ($categories as $category) {
+                if ($category['cat_ID'] == $entries[$x]['tid'] ) {
+                    $data = array('entryid'    => $entries[$x]['entryid'],
+                                  'categoryid' => $category['categoryid']);
+                    serendipity_db_insert('entrycat', $this->strtrRecursive($data));
+                    break;
+                }
+            }
+        }
+
+        /* Comments */
+        $res = @mysql_query("SELECT * FROM {$this->data['prefix']}comments;", $gdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_COMMENT_INFO, mysql_error($gdb));
+        }
+
+        while ($a = mysql_fetch_assoc($res)) {
+            foreach ($entries as $entry) {
+                if ($entry['sid'] == $a['sid'] ) {
+                    $author   = '';
+                    $mail     = '';
+                    $url      = '';
+
+                    foreach($users AS $user) {
+                        if ($user['ID'] == $a['uid']) {
+                            $author = $user['user_login'];
+                            $mail = $user['user_email'];
+                            $url  = $user['user_url'];
+                            break;
+                        }
+                    }
+
+                    $comment = array('entry_id ' => $entry['entryid'],
+                                     'parent_id' => 0,
+                                     'timestamp' => strtotime($a['date']),
+                                     'author'    => $author,
+                                     'email'     => $mail,
+                                     'url'       => $url,
+                                     'ip'        => $a['ip'],
+                                     'status'    => 'approved',
+                                     'body'      => $a['comment'],
+                                     'subscribed'=> 'false',
+                                     'type'      => 'NORMAL');
+
+                    serendipity_db_insert('comments', $this->strtrRecursive($comment));
+                    $cid = serendipity_db_insert_id('comments', 'id');
+                    serendipity_approveComment($cid, $entry['entryid'], true);
+                }
+            }
+        }
+
+        $serendipity['noautodiscovery'] = $noautodiscovery;
+
+        // That was fun.
+        return true;
+    }
+}
+
+return 'Serendipity_Import_geeklog';
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/importers/generic.inc.php b/include/admin/importers/generic.inc.php
new file mode 100644 (file)
index 0000000..55a4a77
--- /dev/null
@@ -0,0 +1,147 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+require_once 'bundled-libs/Onyx/RSS.php';
+
+class Serendipity_Import_Generic extends Serendipity_Import {
+    var $info        = array('software' => IMPORT_GENERIC_RSS);
+    var $data        = array();
+    var $inputFields = array();
+
+    function Serendipity_Import_Generic($data) {
+        $this->data = $data;
+        $this->inputFields = array(array('text'    => RSS . ' ' . URL,
+                                         'type'    => 'input',
+                                         'name'    => 'url'),
+
+                                   array('text'    => STATUS,
+                                         'type'    => 'list',
+                                         'name'    => 'type',
+                                         'value'   => 'publish',
+                                         'default' => array('draft' => DRAFT, 'publish' => PUBLISH)),
+
+                                   array('text'    => RSS_IMPORT_CATEGORY,
+                                         'type'    => 'list',
+                                         'name'    => 'category',
+                                         'value'   => 0,
+                                         'default' => $this->_getCategoryList()),
+
+                                   array('text'    => CHARSET,
+                                         'type'    => 'list',
+                                         'name'    => 'charset',
+                                         'value'   => 'UTF-8',
+                                         'default' => $this->getCharsets()),
+
+                                    array('text'   => RSS_IMPORT_BODYONLY,
+                                         'type'    => 'bool',
+                                         'name'    => 'bodyonly',
+                                         'value'   => 'false'));
+    }
+
+    function validateData() {
+        return sizeof($this->data);
+    }
+
+    function getInputFields() {
+        return $this->inputFields;
+    }
+
+    function _getCategoryList() {
+        $res = serendipity_fetchCategories('all');
+        $ret = array(0 => NO_CATEGORY);
+        if (is_array($res)) {
+            foreach ($res as $v) {
+                $ret[$v['categoryid']] = $v['category_name'];
+            }
+        }
+        return $ret;
+    }
+
+    function buildEntry($item, &$entry) {
+        global $serendipity;
+
+        $entry    = array();
+        $bodyonly = serendipity_get_bool($this->data['bodyonly']);
+
+        if ($item['description']) {
+            $entry['body'] = $this->decode($item['description']);
+        }
+
+        if ($item['content:encoded']) {
+            if (!isset($entry['body']) || $bodyonly) {
+                $data = &$entry['body'];
+            } else {
+                $data = &$entry['extended'];
+            }
+
+            // See if the 'description' element is a substring of the 'content:encoded' part. If it is,
+            // we will only fetch the full 'content:encoded' part. If it's not a substring, we append
+            // the 'content:encoded' part to either body or extended entry (respecting the 'bodyonly'
+            // switch). We substract 4 letters because of possible '...' additions to an entry.
+            $testbody = substr(trim(strip_tags($entry['body'])), 0, -4);
+            if ($testbody != substr(trim(strip_tags($item['content:encoded'])), 0, strlen($testbody))) {
+                $data .= $this->decode($item['content:encoded']);
+            } else {
+                $data = $this->decode($item['content:encoded']);
+            }
+        }
+
+        $entry['title'] = $this->decode($item['title']);
+        $entry['timestamp'] = $this->decode(strtotime(isset($item['pubdate']) ? $item['pubdate'] : $item['dc:date']));
+        if ($entry['timestamp'] == -1) {
+            // strtotime does not seem to parse ISO 8601 dates
+            if (preg_match('@^([0-9]{4})\-([0-9]{2})\-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})\-([0-9]{2}):([0-9]{2})$@', isset($item['pubdate']) ? $item['pubdate'] : $item['dc:date'], $timematch)) {
+                $entry['timestamp'] = mktime($timematch[4] - $timematch[7], $timematch[5] - $timematch[8], $timematch[6], $timematch[3], $timematch[2], $timematch[1]);
+            } else {
+                $entry['timestamp'] = time();
+            }
+        }
+
+        if ($this->data['type'] == 'draft') {
+            $entry['isdraft'] = 'true';
+        } else {
+            $entry['isdraft'] = 'false';
+        }
+
+        if (!empty($item['category'])) {
+            $cat = serendipity_fetchCategoryInfo(0, trim($this->decode($item['category'])));
+            if (is_array($cat) && isset($cat['categoryid'])) {
+                $entry['categories'][] = $cat['categoryid'];
+            }
+        }
+
+        if (!is_array($entry['categories'])) {
+            $entry['categories'][] = $this->data['category'];
+        }
+
+        if (!isset($entry['extended'])) {
+            $entry['extended'] = '';
+        }
+
+        $entry['allow_comments'] = true;
+
+        return true;
+    }
+
+    function import() {
+        global $serendipity;
+
+        $c = &new Onyx_RSS();
+        $c->parse($this->data['url']);
+
+        $serendipity['noautodiscovery'] = 1;
+        while ($item = $c->getNextItem()) {
+            if ($this->buildEntry($item, $entry)) {
+                serendipity_updertEntry($entry);
+            }
+        }
+
+        return true;
+    }
+}
+
+return 'Serendipity_Import_Generic';
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/importers/movabletype.inc.php b/include/admin/importers/movabletype.inc.php
new file mode 100644 (file)
index 0000000..719c29b
--- /dev/null
@@ -0,0 +1,219 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+/*****************************************************************
+ *                MovableType Importer, by Evan Nemerson         *
+ *****************************************************************/
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('IMPORTER_MT_WARN_PLUGIN',     'Bitte installieren Sie das Plugin "%s"');
+        @define('IMPORTER_MT_NOTE', 'Falls Sie weiter machen, ohne die Plugins zu installieren, werden möglicherweise Zeilenumbrüche falsch importiert (verdoppelt oder entfernt)');
+        break;
+
+    case 'en':
+    default:
+        @define('IMPORTER_MT_WARN_PLUGIN',     'Please install the plugin "%s"');
+        @define('IMPORTER_MT_NOTE', 'If you continue without installing those plugins, line breaks may be incorrectly imported (doubled or removed)');
+        break;
+}
+
+class Serendipity_Import_MovableType extends Serendipity_Import {
+    var $info        = array('software' => 'MovableType');
+    var $data        = array();
+    var $inputFields = array();
+
+    function Serendipity_Import_MovableType($data) {
+        $this->data = $data;
+        $this->inputFields = array(array('text'    => MT_DATA_FILE,
+                                         'type'    => 'file',
+                                         'name'    => 'mt_dat'),
+
+                                   array('text'    => FORCE,
+                                         'type'    => 'bool',
+                                         'name'    => 'mt_force',
+                                         'default' => 'true'),
+
+                                   array('text'    => ACTIVATE_AUTODISCOVERY,
+                                         'type'    => 'bool',
+                                         'name'    => 'autodiscovery',
+                                         'default' => 'false')
+                            );
+    }
+
+    function getImportNotes(){
+        $notes = array();
+        if (!class_exists('serendipity_event_nl2br')){
+            $notes[] = sprintf(IMPORTER_MT_WARN_PLUGIN, 'serendipity_event_nl2br');
+        }
+        if (!class_exists('serendipity_event_entryproperties')){
+            $notes[] = sprintf(IMPORTER_MT_WARN_PLUGIN, 'serendipity_event_entryproperties');
+        }
+        if (count($notes) > 0){
+            return '<ul><li>'.implode('</li><li>', $notes).'</li></ul>'.IMPORTER_MT_NOTE;
+        }
+    }
+    function validateData() {
+        return sizeof($this->data);
+    }
+
+    function getInputFields() {
+        return $this->inputFields;
+    }
+
+    function doEntryWork(&$mt_entry, &$tasks){
+        $entry = array();
+        $entry['categories'] = array();
+        $entryprops = array();
+
+        foreach($mt_entry as $name => $data){
+            switch($name){
+            case 'AUTHOR':
+                    if ( !isset($authors[$data]) ) {
+                        $au_inf = serendipity_fetchAuthor($data);
+                        if ( !is_array($au_inf) ) {
+                            $tasks[] = sprintf(CREATE_AUTHOR, htmlspecialchars($data));
+                            $au_inf = serendipity_fetchAuthor($serendipity['authorid']);
+                        }
+                        $authors[$data] = $au_inf[0];
+                    }
+                    $entry['authorid'] = $authors[$data]['authorid'];
+                    $entry['author'] = $authors[$data]['username'];
+                    break;
+                case 'TITLE':
+                    $entry['title'] = $data;
+                    break;
+                case 'STATUS':
+                    $entry['isdraft'] = ($data == 'Publish') ? 'false' : 'true';
+                    break;
+                case 'ALLOW COMMENTS':
+                    $entry['allow_comments'] = ($data == '1') ? 'true' : 'false';
+                    break;
+                case 'DATE':
+                    $entry['timestamp'] = strtotime($data);
+                    if ( $entry['timestamp'] == 0 ) {
+                        $entry['timestamp'] = time();
+                    }
+                    break;
+                case 'BODY':
+                    $entry['body'] = $data;
+                    break;
+                case 'EXTENDED BODY':
+                    $entry['extended'] = $data;
+                    break;
+                case 'CONVERT BREAKS':
+                    $entryprops['nl2br'] = ($data == '1') ? true : false;
+                    break;
+                case 'PRIMARY CATEGORY':
+                case 'CATEGORY':
+                      $cat_found = false;
+                      if ( is_array($this->categories) ) {
+                          for ( $y=0 ; $y<sizeof($this->categories) ; $y++ ) {
+                              if ( $this->categories[$y]['category_name'] == $data ) {
+                                  $cat_found = true;
+                                  break;
+                              }
+                          }
+                          if ( $cat_found){
+                              if (!in_array($this->categories[$y]['categoryid'], $entry['categories']) ) {
+                                  //$entries[$n]['categories'][] = $categories[$y]['categoryid'];
+                                  $entry['categories'][] = $this->categories[$y]['categoryid'];
+                              }
+                          }else {
+                              $tasks[] = sprintf(CREATE_CATEGORY, htmlspecialchars($data));
+                          }
+                      }
+                      break;
+            }
+        }
+        $entry['props'] = $entryprops;
+        return $entry;
+    }
+
+    function import() {
+        global $serendipity;
+
+        $force    = ($this->data['force'] == 'true');
+
+        if ($this->data['autodiscovery'] == 'false') {
+            $serendipity['noautodiscovery'] = 1;
+        }
+
+        // Rewritten to parse the file line by line. Can save quite some
+        // memory on large blogs
+        //$contents   = file_get_contents($_FILES['serendipity']['tmp_name']['import']['mt_dat']);
+
+        $authors    = array();
+        $this->categories = serendipity_fetchCategories();
+        $tasks      = array();
+
+        $entries = array();
+
+        $fh = fopen($_FILES['serendipity']['tmp_name']['import']['mt_dat'], 'r');
+
+        $n = 0;
+
+        $entry = array();
+        $el    = "";
+        $skip  = false;
+        while (!feof($fh)){
+            $line = fgets($fh, 8192);
+            if ($skip && (!preg_match('/^--------/', $line)))
+                continue;
+            if (preg_match('/^--------/', $line)){
+                // We found the end marker of the current entry. Add to
+            // entries-Array
+                $entries[] = $this->doEntryWork($entry, $tasks);
+                $entry = array();
+                $skip = false;
+            }elseif (preg_match('/^-----/', $line)){
+                if (empty($el)){
+                    $line = fgets($fh, 8192);
+                    if (preg_match('/^([A-Z]+):/', $line, $matches)){
+                        if ($matches[1] == 'COMMENT'){
+                            // todo: really handle comments.
+                           $skip = true;
+                        }else{
+                           $el = $matches[1];
+                        }
+                    }
+                }else{
+                    $el = "";
+                }
+           }else{
+               if (empty($el) ){
+                   if (preg_match('/^([A-Z ]+): (.*)$/', $line, $matches)){
+                       $entry[$matches[1]] = $matches[2];
+                   }
+               }else{
+                   $entry[$el] .= $line;
+               }
+           }
+
+        }
+        fclose($fh);
+
+        if ( !sizeof($tasks) || $force == true ) {
+            serendipity_db_begin_transaction();
+            foreach ( $entries as $entry ) {
+                $entryprops = $entry['props'];
+                unset($entry['props']);
+                if ( !is_int($r = serendipity_updertEntry($entry)) ) {
+                    echo '<div class="serendipityAdminMsgError">' . $r . '</div>';
+                }else{
+                    $entry['id'] = $r;
+                    // Let the plugins do some additional stuff. Here it's used with
+                    // event_entryproperties in mind to setup the nl2br-stuff
+                    serendipity_plugin_api::hook_event('backend_import_entry', $entry, $entryprops);
+                }
+            }
+            serendipity_db_end_transaction(true);
+            return true;
+        }else {
+            return '<ul><li>'.implode('</li><li>', array_unique($tasks)).'</li></ul>';
+        }
+    }
+}
+return 'Serendipity_Import_MovableType';
+?>
diff --git a/include/admin/importers/nucleus.inc.php b/include/admin/importers/nucleus.inc.php
new file mode 100644 (file)
index 0000000..7dce7ac
--- /dev/null
@@ -0,0 +1,244 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+/*****************************************************************
+ *  Nucleus  Importer, by Garvin Hicking *
+ * ****************************************************************/
+
+class Serendipity_Import_Nucleus extends Serendipity_Import {
+    var $info        = array('software' => 'Nucleus');
+    var $data        = array();
+    var $inputFields = array();
+
+
+    function Serendipity_Import_Nucleus($data) {
+        $this->data = $data;
+        $this->inputFields = array(array('text' => INSTALL_DBHOST,
+                                         'type' => 'input',
+                                         'name' => 'host'),
+
+                                   array('text' => INSTALL_DBUSER,
+                                         'type' => 'input',
+                                         'name' => 'user'),
+
+                                   array('text' => INSTALL_DBPASS,
+                                         'type' => 'protected',
+                                         'name' => 'pass'),
+
+                                   array('text' => INSTALL_DBNAME,
+                                         'type' => 'input',
+                                         'name' => 'name'),
+
+                                   array('text' => INSTALL_DBPREFIX,
+                                         'type' => 'input',
+                                         'name' => 'prefix',
+                                         'default' => 'nucleus_'),
+
+                                   array('text'    => CHARSET,
+                                         'type'    => 'list',
+                                         'name'    => 'charset',
+                                         'value'   => 'native',
+                                         'default' => $this->getCharsets()),
+
+                                   array('text'    => CONVERT_HTMLENTITIES,
+                                         'type'    => 'bool',
+                                         'name'    => 'use_strtr',
+                                         'default' => 'true'),
+
+                                   array('text'    => ACTIVATE_AUTODISCOVERY,
+                                         'type'    => 'bool',
+                                         'name'    => 'autodiscovery',
+                                         'default' => 'false')
+                            );
+    }
+
+    function validateData() {
+        return sizeof($this->data);
+    }
+
+    function getInputFields() {
+        return $this->inputFields;
+    }
+
+    function import() {
+        global $serendipity;
+
+        // Save this so we can return it to its original value at the end of this method.
+        $noautodiscovery = isset($serendipity['noautodiscovery']) ? $serendipity['noautodiscovery'] : false;
+
+        if ($this->data['autodiscovery'] == 'false') {
+            $serendipity['noautodiscovery'] = 1;
+        }
+        
+        $this->getTransTable();
+
+        $this->data['prefix'] = serendipity_db_escape_string($this->data['prefix']);
+        $users = array();
+        $categories = array();
+        $entries = array();
+
+        if (!extension_loaded('mysql')) {
+            return MYSQL_REQUIRED;;
+        }
+
+        $nucdb = @mysql_connect($this->data['host'], $this->data['user'], $this->data['pass']);
+        if (!$nucdb) {
+            return sprintf(COULDNT_CONNECT, $this->data['host']);
+        }
+
+        if (!@mysql_select_db($this->data['name'])) {
+            return sprintf(COULDNT_SELECT_DB, mysql_error($nucdb));
+        }
+
+        /* Users */
+        $res = @mysql_query("SELECT mnumber AS ID, mname AS user_login, mpassword AS user_pass, memail AS user_email, madmin AS user_level FROM {$this->data['prefix']}member;", $nucdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_USER_INFO, mysql_error($nucdb));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res); $x < $max_x ; $x++ ) {
+            $users[$x] = mysql_fetch_assoc($res);
+
+            $data = array('right_publish' => ($users[$x]['user_level'] >= 1) ? 1 : 0,
+                          'realname'      => $users[$x]['user_login'],
+                          'username'      => $users[$x]['user_login'],
+                          'email'         => $users[$x]['user_email'],
+                          'password'      => $users[$x]['user_pass']); // Nucleus uses md5, too.
+
+            if ( $users[$x]['user_level'] < 1 ) {
+                $data['userlevel'] = USERLEVEL_EDITOR;
+            } else {
+                $data['userlevel'] = USERLEVEL_ADMIN;
+            }
+
+            if ($serendipity['serendipityUserlevel'] < $data['userlevel']) {
+                $data['userlevel'] = $serendipity['serendipityUserlevel'];
+            }
+
+            serendipity_db_insert('authors', $this->strtrRecursive($data));
+            $users[$x]['authorid'] = serendipity_db_insert_id('authors', 'authorid');
+        }
+
+        /* Categories */
+        $res = @mysql_query("SELECT catid AS cat_ID, cname AS cat_name, cdesc AS category_description FROM {$this->data['prefix']}category ORDER BY catid;", $nucdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_CATEGORY_INFO, mysql_error($nucdb));
+        }
+
+        // Get all the info we need
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++) {
+            $categories[] = mysql_fetch_assoc($res);
+        }
+
+        // Insert all categories as top level (we need to know everyone's ID before we can represent the hierarchy).
+        for ($x=0, $max_x = sizeof($categories) ; $x < $max_x ; $x++ ) {
+            $cat = array('category_name'        => $categories[$x]['cat_name'],
+                         'category_description' => $categories[$x]['category_description'],
+                         'parentid'             => 0, // <---
+                         'category_left'        => 0,
+                         'category_right'       => 0);
+
+            serendipity_db_insert('category', $this->strtrRecursive($cat));
+            $categories[$x]['categoryid'] = serendipity_db_insert_id('category', 'categoryid');
+        }
+
+        serendipity_rebuildCategoryTree();
+
+        /* Entries */
+        $res = @mysql_query("SELECT * FROM {$this->data['prefix']}item ORDER BY itime;", $nucdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_ENTRY_INFO, mysql_error($nucdb));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++ ) {
+            $entries[$x] = mysql_fetch_assoc($res);
+
+            $entry = array('title'          => $this->decode($entries[$x]['ititle']),
+                           'isdraft'        => ($entries[$x]['idraft'] != '1') ? 'false' : 'true',
+                           'allow_comments' => ($entries[$x]['iclosed'] == '1' ) ? 'false' : 'true',
+                           'timestamp'      => strtotime($entries[$x]['itime']),
+                           'extended'       => $this->strtr($entries[$x]['imore']),
+                           'body'           => $this->strtr($entries[$x]['ibody']));
+
+            $entry['authorid'] = '';
+            $entry['author']   = '';
+            foreach ($users as $user) {
+                if ($user['ID'] == $entries[$x]['iauthor']) {
+                    $entry['authorid'] = $user['authorid'];
+                    $entry['author']   = $user['realname'];
+                    break;
+                }
+            }
+
+            if (!is_int($entries[$x]['entryid'] = serendipity_updertEntry($entry))) {
+                return $entries[$x]['entryid'];
+            }
+
+            /* Entry/category */
+            foreach ($categories as $category) {
+                if ($category['cat_ID'] == $entries[$x]['icat'] ) {
+                    $data = array('entryid'    => $entries[$x]['entryid'],
+                                  'categoryid' => $category['categoryid']);
+                    serendipity_db_insert('entrycat', $this->strtrRecursive($data));
+                    break;
+                }
+            }
+        }
+
+        /* Comments */
+        $res = @mysql_query("SELECT * FROM {$this->data['prefix']}comment;", $nucdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_COMMENT_INFO, mysql_error($nucdb));
+        }
+
+        while ($a = mysql_fetch_assoc($res)) {
+            foreach ($entries as $entry) {
+                if ($entry['inumber'] == $a['citem'] ) {
+                    $author   = '';
+                    $mail     = '';
+                    if (!empty($a['cmember'])) {
+                        foreach($users AS $user) {
+                            if ($user['ID'] == $a['cmember']) {
+                                $author = $user['user_login'];
+                                $mail = $user['user_email'];
+                                break;
+                            }
+                        }
+                    }
+
+                    if (empty($author) && empty($mail)) {
+                        $author = $a['cuser'];
+                        $mail = $a['cmail'];
+                    }
+
+                    $comment = array('entry_id ' => $entry['entryid'],
+                                     'parent_id' => 0,
+                                     'timestamp' => strtotime($a['ctime']),
+                                     'author'    => $author,
+                                     'email'     => $mail,
+                                     'url'       => $a['chost'],
+                                     'ip'        => $a['cip'],
+                                     'status'    => 'approved',
+                                     'body'      => $a['cbody'],
+                                     'subscribed'=> 'false',
+                                     'type'      => 'NORMAL');
+
+                    serendipity_db_insert('comments', $this->strtrRecursive($comment));
+                    $cid = serendipity_db_insert_id('comments', 'id');
+                    serendipity_approveComment($cid, $entry['entryid'], true);
+                }
+            }
+        }
+
+        $serendipity['noautodiscovery'] = $noautodiscovery;
+
+        // That was fun.
+        return true;
+    }
+}
+
+return 'Serendipity_Import_Nucleus';
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/importers/phpbb.inc.php b/include/admin/importers/phpbb.inc.php
new file mode 100644 (file)
index 0000000..6604451
--- /dev/null
@@ -0,0 +1,308 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+/*****************************************************************
+ *  phpbb  Importer,     by Garvin Hicking *
+ * ****************************************************************/
+
+class Serendipity_Import_phpbb extends Serendipity_Import {
+    var $info        = array('software' => 'phpBB');
+    var $data        = array();
+    var $inputFields = array();
+    var $categories  = array();
+
+    function Serendipity_Import_phpbb($data) {
+        $this->data = $data;
+        $this->inputFields = array(array('text' => INSTALL_DBHOST,
+                                         'type' => 'input',
+                                         'name' => 'host'),
+
+                                   array('text' => INSTALL_DBUSER,
+                                         'type' => 'input',
+                                         'name' => 'user'),
+
+                                   array('text' => INSTALL_DBPASS,
+                                         'type' => 'protected',
+                                         'name' => 'pass'),
+
+                                   array('text' => INSTALL_DBNAME,
+                                         'type' => 'input',
+                                         'name' => 'name'),
+
+                                   array('text' => INSTALL_DBPREFIX,
+                                         'type' => 'input',
+                                         'name' => 'prefix',
+                                         'default' => 'phpbb_'),
+
+                                   array('text'    => CHARSET,
+                                         'type'    => 'list',
+                                         'name'    => 'charset',
+                                         'value'   => 'native',
+                                         'default' => $this->getCharsets(false)),
+
+                                   array('text'    => CONVERT_HTMLENTITIES,
+                                         'type'    => 'bool',
+                                         'name'    => 'use_strtr',
+                                         'default' => 'true'),
+
+                                   array('text'    => ACTIVATE_AUTODISCOVERY,
+                                         'type'    => 'bool',
+                                         'name'    => 'autodiscovery',
+                                         'default' => 'false')
+                            );
+    }
+
+    function validateData() {
+        return sizeof($this->data);
+    }
+
+    function getInputFields() {
+        return $this->inputFields;
+    }
+
+    function import() {
+        global $serendipity;
+
+        // Save this so we can return it to its original value at the end of this method.
+        $noautodiscovery = isset($serendipity['noautodiscovery']) ? $serendipity['noautodiscovery'] : false;
+
+        if ($this->data['autodiscovery'] == 'false') {
+            $serendipity['noautodiscovery'] = 1;
+        }
+
+        $this->getTransTable();
+
+        $this->data['prefix'] = serendipity_db_escape_string($this->data['prefix']);
+        $users = array();
+        $entries = array();
+
+        if (!extension_loaded('mysql')) {
+            return MYSQL_REQUIRED;
+        }
+
+        $gdb = @mysql_connect($this->data['host'], $this->data['user'], $this->data['pass']);
+        if (!$gdb) {
+            return sprintf(COULDNT_CONNECT, $this->data['host']);
+        }
+
+        if (!@mysql_select_db($this->data['name'])) {
+            return sprintf(COULDNT_SELECT_DB, mysql_error($gdb));
+        }
+
+        /* Users */
+        $res = @mysql_query("SELECT user_id       AS ID,
+                                    username      AS user_login,
+                                    user_password AS user_pass,
+                                    user_email    AS user_email,
+                                    user_website  AS user_url,
+                                    user_level
+                               FROM {$this->data['prefix']}users
+                              WHERE user_active = 1", $gdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_USER_INFO, mysql_error($gdb));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res); $x < $max_x ; $x++ ) {
+            $users[$x] = mysql_fetch_assoc($res);
+
+            $data = array('right_publish' => 1,
+                          'realname'      => $users[$x]['user_login'],
+                          'username'      => $users[$x]['user_login'],
+                          'email'         => $users[$x]['user_email'],
+                          'userlevel'     => ($users[$x]['user_level'] == 0 ? USERLEVEL_EDITOR : USERLEVEL_ADMIN),
+                          'password'      => $users[$x]['user_pass']); // MD5 compatible
+
+            if ($serendipity['serendipityUserlevel'] < $data['userlevel']) {
+                $data['userlevel'] = $serendipity['serendipityUserlevel'];
+            }
+
+            serendipity_db_insert('authors', $this->strtrRecursive($data));
+            echo mysql_error();
+            $users[$x]['authorid'] = serendipity_db_insert_id('authors', 'authorid');
+        }
+
+        /* Categories */
+        $res = @mysql_query("SELECT cat_id AS cat_ID, 
+                                    cat_title AS cat_name 
+                               FROM {$this->data['prefix']}categories", $gdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_CATEGORY_INFO, mysql_error($gdb));
+        }
+
+        // Get all the info we need
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++) {
+            $parent_categories[] = mysql_fetch_assoc($res);
+        }
+
+        for ($x=0, $max_x = sizeof($parent_categories) ; $x < $max_x ; $x++ ) {
+            $cat = array('category_name'        => $parent_categories[$x]['cat_name'],
+                         'category_description' => '',
+                         'parentid'             => 0, // <---
+                         'category_left'        => 0,
+                         'category_right'       => 0);
+
+            serendipity_db_insert('category', $this->strtrRecursive($cat));
+            $parent_categories[$x]['categoryid'] = serendipity_db_insert_id('category', 'categoryid');
+        }
+
+        /* Categories */
+        $res = @mysql_query("SELECT forum_id AS cat_ID,
+                                    cat_id   AS parent_cat_id, 
+                                    forum_name AS cat_name, 
+                                    forum_desc AS category_description 
+                               FROM {$this->data['prefix']}forums ORDER BY forum_order;", $gdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_CATEGORY_INFO, mysql_error($gdb));
+        }
+
+        // Get all the info we need
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++) {
+            $categories[] = mysql_fetch_assoc($res);
+        }
+
+        // Insert all categories as top level (we need to know everyone's ID before we can represent the hierarchy).
+        for ($x=0, $max_x = sizeof($categories) ; $x < $max_x ; $x++ ) {
+            $pcatid = 0;
+            foreach($parent_categories AS $pcat) {
+                if ($pcat['cat_ID'] == $categories[$x]['parent_cat_id']) {
+                    $pcatid = $pcat['cat_ID'];
+                    break;
+                }
+            }
+
+            $cat = array('category_name'        => $categories[$x]['cat_name'],
+                         'category_description' => $categories[$x]['category_description'],
+                         'parentid'             => $pcatid, // <---
+                         'category_left'        => 0,
+                         'category_right'       => 0);
+
+            serendipity_db_insert('category', $this->strtrRecursive($cat));
+            $categories[$x]['categoryid'] = serendipity_db_insert_id('category', 'categoryid');
+        }
+
+        serendipity_rebuildCategoryTree();
+
+        /* Entries */
+        $res = @mysql_query("SELECT t.topic_title, 
+                                    t.topic_poster,
+                                    t.forum_id,
+                                    p.post_time,
+                                    pt.post_subject,
+                                    pt.post_text,
+                                    count(p.topic_id) AS ccount,
+                                    p.topic_id,
+                                    MIN(p.post_id) AS post_id
+                               FROM {$this->data['prefix']}topics AS t
+                    LEFT OUTER JOIN {$this->data['prefix']}posts  AS p
+                                 ON t.topic_id = p.topic_id
+                    LEFT OUTER JOIN {$this->data['prefix']}posts_text  AS pt
+                                 ON pt.post_id = p.post_id
+                           GROUP BY p.topic_id
+                           ", $gdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_ENTRY_INFO, mysql_error($gdb));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++ ) {
+            $entries[$x] = mysql_fetch_assoc($res);
+
+            $entry = array('title'          => $this->decode($entries[$x]['post_subject']),
+                           'isdraft'        => 'false',
+                           'allow_comments' => 'true',
+                           'timestamp'      => $entries[$x]['post_time'],
+                           'body'           => $this->strtr($entries[$x]['post_text']),
+                           'extended'       => ''
+                           );
+
+            $entry['authorid'] = '';
+            $entry['author']   = '';
+            foreach ($users as $user) {
+                if ($user['ID'] == $entries[$x]['topic_poster']) {
+                    $entry['authorid'] = $user['authorid'];
+                    $entry['author']   = $user['user_login'];
+                    break;
+                }
+            }
+
+            if (!is_int($entries[$x]['entryid'] = serendipity_updertEntry($entry))) {
+                return $entries[$x]['entryid'];
+            }
+
+            /* Entry/category */
+            foreach ($categories as $category) {
+                if ($category['cat_ID'] == $entries[$x]['forum_id'] ) {
+                    $data = array('entryid'    => $entries[$x]['entryid'],
+                                  'categoryid' => $category['categoryid']);
+                    serendipity_db_insert('entrycat', $this->strtrRecursive($data));
+                    break;
+                }
+            }
+            
+            /* Comments */
+            $topic_id = $entries[$x]['topic_id'];
+            $c_res = @mysql_query("SELECT t.topic_title, 
+                                        t.topic_poster,
+                                        p.poster_id,
+                                        t.forum_id,
+                                        p.post_time,
+                                        pt.post_subject,
+                                        pt.post_text,
+                                        pt.post_id
+                                   FROM {$this->data['prefix']}topics AS t
+                        LEFT OUTER JOIN {$this->data['prefix']}posts  AS p
+                                     ON t.topic_id = p.topic_id
+                        LEFT OUTER JOIN {$this->data['prefix']}posts_text  AS pt
+                                     ON pt.post_id = p.post_id
+                                  WHERE p.topic_id = {$topic_id} 
+                               ", $gdb);
+            if (!$c_res) {
+                return sprintf(COULDNT_SELECT_COMMENT_INFO, mysql_error($gdb));
+            }
+    
+            while ($a = mysql_fetch_assoc($c_res)) {
+                if ($a['post_id'] == $entries[$x]['post_id']) {
+                    continue;
+                }
+                $author   = '';
+                $mail     = '';
+                $url      = '';
+
+                foreach($users AS $user) {
+                    if ($user['ID'] == $a['poster_id']) {
+                        $author = $user['user_login'];
+                        $mail   = $user['user_email'];
+                        $url    = $user['user_url'];
+                        break;
+                    }
+                }
+
+                $comment = array('entry_id ' => $entries[$x]['entryid'],
+                                 'parent_id' => 0,
+                                 'timestamp' => $a['post_time'],
+                                 'author'    => $author,
+                                 'email'     => $mail,
+                                 'url'       => $url,
+                                 'ip'        => '',
+                                 'status'    => 'approved',
+                                 'body'      => $a['post_text'],
+                                 'subscribed'=> 'false',
+                                 'type'      => 'NORMAL');
+
+                serendipity_db_insert('comments', $this->strtrRecursive($comment));
+                $cid = serendipity_db_insert_id('comments', 'id');
+                serendipity_approveComment($cid, $entries[$x]['entryid'], true);
+            }
+        }
+
+        $serendipity['noautodiscovery'] = $noautodiscovery;
+
+        // That was fun.
+        return true;
+    }
+}
+
+return 'Serendipity_Import_phpbb';
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/importers/pmachine.inc.php b/include/admin/importers/pmachine.inc.php
new file mode 100644 (file)
index 0000000..25acc59
--- /dev/null
@@ -0,0 +1,252 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+/*****************************************************************
+ *  pMachine  Importer,  by Garvin Hicking *
+ * ****************************************************************/
+
+class Serendipity_Import_pMachine extends Serendipity_Import {
+    var $info        = array('software' => 'pMachine Pro 2.4');
+    var $data        = array();
+    var $inputFields = array();
+
+
+    function Serendipity_Import_pMachine($data) {
+        $this->data = $data;
+        $this->inputFields = array(array('text' => INSTALL_DBHOST,
+                                         'type' => 'input',
+                                         'name' => 'host'),
+
+                                   array('text' => INSTALL_DBUSER,
+                                         'type' => 'input',
+                                         'name' => 'user'),
+
+                                   array('text' => INSTALL_DBPASS,
+                                         'type' => 'protected',
+                                         'name' => 'pass'),
+
+                                   array('text' => INSTALL_DBNAME,
+                                         'type' => 'input',
+                                         'name' => 'name'),
+
+                                   array('text' => INSTALL_DBPREFIX,
+                                         'type' => 'input',
+                                         'name' => 'prefix',
+                                         'default' => 'pm_'),
+
+                                   array('text'    => CHARSET,
+                                         'type'    => 'list',
+                                         'name'    => 'charset',
+                                         'value'   => 'native',
+                                         'default' => $this->getCharsets()),
+
+                                   array('text'    => CONVERT_HTMLENTITIES,
+                                         'type'    => 'bool',
+                                         'name'    => 'use_strtr',
+                                         'default' => 'true'),
+
+                                   array('text'    => ACTIVATE_AUTODISCOVERY,
+                                         'type'    => 'bool',
+                                         'name'    => 'autodiscovery',
+                                         'default' => 'false')
+                            );
+    }
+
+    function validateData() {
+        return sizeof($this->data);
+    }
+
+    function getInputFields() {
+        return $this->inputFields;
+    }
+
+    function import() {
+        global $serendipity;
+
+        // Save this so we can return it to its original value at the end of this method.
+        $noautodiscovery = isset($serendipity['noautodiscovery']) ? $serendipity['noautodiscovery'] : false;
+
+        if ($this->data['autodiscovery'] == 'false') {
+            $serendipity['noautodiscovery'] = 1;
+        }
+
+        $this->getTransTable();
+
+        $this->data['prefix'] = serendipity_db_escape_string($this->data['prefix']);
+        $users = array();
+        $categories = array();
+        $entries = array();
+
+        if (!extension_loaded('mysql')) {
+            return MYSQL_REQUIRED;
+        }
+
+        $pmdb = @mysql_connect($this->data['host'], $this->data['user'], $this->data['pass']);
+        if (!$pmdb) {
+            return sprintf(COULDNT_CONNECT, $this->data['host']);
+        }
+
+        if (!@mysql_select_db($this->data['name'])) {
+            return sprintf(COULDNT_SELECT_DB, mysql_error($pmdb));
+        }
+
+        /* Users */
+        $res = @mysql_query("SELECT id         AS ID,
+                                    username   AS user_login,
+                                    `password` AS user_pass,
+                                    email      AS user_email,
+                                    status     AS user_level,
+                                    url        AS url
+                               FROM {$this->data['prefix']}members", $pmdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_USER_INFO, mysql_error($pmdb));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res); $x < $max_x ; $x++ ) {
+            $users[$x] = mysql_fetch_assoc($res);
+
+            $data = array('right_publish' => ($users[$x]['user_level'] >= 3) ? 1 : 0,
+                          'realname'      => $users[$x]['user_login'],
+                          'username'      => $users[$x]['user_login'],
+                          'email'         => $users[$x]['user_email'],
+                          'password'      => $users[$x]['user_pass']); // pMachine uses md5, too.
+
+            if ( $users[$x]['user_level'] < 12 ) {
+                $data['userlevel'] = USERLEVEL_EDITOR;
+            } else {
+                $data['userlevel'] = USERLEVEL_ADMIN;
+            }
+
+            if ($serendipity['serendipityUserlevel'] < $data['userlevel']) {
+                $data['userlevel'] = $serendipity['serendipityUserlevel'];
+            }
+
+            serendipity_db_insert('authors', $this->strtrRecursive($data));
+            $users[$x]['authorid'] = serendipity_db_insert_id('authors', 'authorid');
+        }
+
+        /* Categories */
+        $res = @mysql_query("SELECT id       AS cat_ID,
+                                    category AS cat_name,
+                                    category AS category_description
+                               FROM {$this->data['prefix']}categories ORDER BY id", $pmdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_CATEGORY_INFO, mysql_error($pmdb));
+        }
+
+        // Get all the info we need
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++) {
+            $categories[] = mysql_fetch_assoc($res);
+        }
+
+        // Insert all categories as top level (we need to know everyone's ID before we can represent the hierarchy).
+        for ($x=0, $max_x = sizeof($categories) ; $x < $max_x ; $x++ ) {
+            $cat = array('category_name'        => $categories[$x]['cat_name'],
+                         'category_description' => $categories[$x]['category_description'],
+                         'parentid'             => 0, // <---
+                         'category_left'        => 0,
+                         'category_right'       => 0);
+
+            serendipity_db_insert('category', $this->strtrRecursive($cat));
+            $categories[$x]['categoryid'] = serendipity_db_insert_id('category', 'categoryid');
+        }
+
+        serendipity_rebuildCategoryTree();
+
+        /* Entries */
+        $res = @mysql_query("SELECT * FROM {$this->data['prefix']}weblog ORDER BY t_stamp;", $pmdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_ENTRY_INFO, mysql_error($pmdb));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++ ) {
+            $entries[$x] = mysql_fetch_assoc($res);
+
+            $entry = array('title'          => $this->decode($entries[$x]['title']),
+                           'isdraft'        => ($entries[$x]['status'] == 'open') ? 'false' : 'true',
+                           'allow_comments' => ($entries[$x]['showcomments'] == '1' ) ? 'true' : 'false',
+                           'timestamp'      => $entries[$x]['t_stamp'],
+                           'extended'       => $this->strtr($entries[$x]['more']),
+                           'body'           => $this->strtr($entries[$x]['body']));
+
+            $entry['authorid'] = '';
+            $entry['author']   = '';
+            foreach ($users as $user) {
+                if ($user['ID'] == $entries[$x]['member_id']) {
+                    $entry['authorid'] = $user['authorid'];
+                    $entry['author']   = $user['username'];
+                    break;
+                }
+            }
+
+            if (!is_int($entries[$x]['entryid'] = serendipity_updertEntry($entry))) {
+                return $entries[$x]['entryid'];
+            }
+
+            /* Entry/category */
+            foreach ($categories as $category) {
+                if ($category['cat_ID'] == $entries[$x]['category'] ) {
+                    $data = array('entryid'    => $entries[$x]['entryid'],
+                                  'categoryid' => $category['categoryid']);
+                    serendipity_db_insert('entrycat', $this->strtrRecursive($data));
+                    break;
+                }
+            }
+        }
+
+        /* Comments */
+        $res = @mysql_query("SELECT * FROM {$this->data['prefix']}comments;", $pmdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_COMMENT_INFO, mysql_error($pmdb));
+        }
+
+        while ($a = mysql_fetch_assoc($res)) {
+            foreach ($entries as $entry) {
+                if ($entry['post_id'] == $a['post_id'] ) {
+                    $author   = '';
+                    $mail     = '';
+                    $url      = '';
+                    if (!empty($a['member_id'])) {
+                        foreach($users AS $user) {
+                            if ($user['ID'] == $a['member_id']) {
+                                $author = $user['user_login'];
+                                $mail     = $user['user_email'];
+                                $url      = $user['url'];
+                                break;
+                            }
+                        }
+                    }
+
+                    $comment = array('entry_id ' => $entry['entryid'],
+                                     'parent_id' => 0,
+                                     'timestamp' => $a['t_stamp'],
+                                     'author'    => $author,
+                                     'email'     => $mail,
+                                     'url'       => $url,
+                                     'ip'        => $a['comment_ip'],
+                                     'status'    => ($a['status'] == 'open' ? 'approved' : 'pending'),
+                                     'body'      => $a['body'],
+                                     'subscribed'=> 'false',
+                                     'type'      => 'NORMAL');
+
+                    serendipity_db_insert('comments', $this->strtrRecursive($comment));
+                    if ($a['status'] == 'open') {
+                        $cid = serendipity_db_insert_id('comments', 'id');
+                        serendipity_approveComment($cid, $entry['entryid'], true);
+                    }
+                }
+            }
+        }
+
+        $serendipity['noautodiscovery'] = $noautodiscovery;
+
+        // That was fun.
+        return true;
+    }
+}
+
+return 'Serendipity_Import_pMachine';
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/importers/sunlog.inc.php b/include/admin/importers/sunlog.inc.php
new file mode 100644 (file)
index 0000000..0e8b3b3
--- /dev/null
@@ -0,0 +1,276 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+/*****************************************************************
+ *  sunlog  Importer,    by Garvin Hicking *
+ * ****************************************************************/
+
+class Serendipity_Import_sunlog extends Serendipity_Import {
+    var $info        = array('software' => 'Sunlog 0.4.4');
+    var $data        = array();
+    var $inputFields = array();
+    var $categories  = array();
+
+    function getImportNotes() {
+        return 'Sunlog uses a crypted string to represent stored passwords. Thus, those passwords are incompatible with the MD5 hashing of Serendipity and can not be reconstructed. The passwords for all users have been set to "sunlog". <strong>You need to modify the passwords manually for each user</strong>, we are sorry for that inconvenience.<br />'
+             . '<br />'
+             . 'Sunlog has a granular control over access privileges which cannot be migrated to Serendipity. All Users will be migrated as Superusers, you may need to set them to editor or chief users manually after import.';
+    }
+
+    function Serendipity_Import_sunlog($data) {
+        $this->data = $data;
+        $this->inputFields = array(array('text' => INSTALL_DBHOST,
+                                         'type' => 'input',
+                                         'name' => 'host'),
+
+                                   array('text' => INSTALL_DBUSER,
+                                         'type' => 'input',
+                                         'name' => 'user'),
+
+                                   array('text' => INSTALL_DBPASS,
+                                         'type' => 'protected',
+                                         'name' => 'pass'),
+
+                                   array('text' => INSTALL_DBNAME,
+                                         'type' => 'input',
+                                         'name' => 'name'),
+
+                                   array('text' => INSTALL_DBPREFIX,
+                                         'type' => 'input',
+                                         'name' => 'prefix',
+                                         'default' => 'sunlog_'),
+
+                                   array('text'    => CHARSET,
+                                         'type'    => 'list',
+                                         'name'    => 'charset',
+                                         'value'   => 'native',
+                                         'default' => $this->getCharsets()),
+
+                                   array('text'    => CONVERT_HTMLENTITIES,
+                                         'type'    => 'bool',
+                                         'name'    => 'use_strtr',
+                                         'default' => 'true'),
+
+                                   array('text'    => ACTIVATE_AUTODISCOVERY,
+                                         'type'    => 'bool',
+                                         'name'    => 'autodiscovery',
+                                         'default' => 'false')
+                            );
+    }
+
+    function validateData() {
+        return sizeof($this->data);
+    }
+
+    function getInputFields() {
+        return $this->inputFields;
+    }
+
+    function import() {
+        global $serendipity;
+
+        // Save this so we can return it to its original value at the end of this method.
+        $noautodiscovery = isset($serendipity['noautodiscovery']) ? $serendipity['noautodiscovery'] : false;
+
+        if ($this->data['autodiscovery'] == 'false') {
+            $serendipity['noautodiscovery'] = 1;
+        }
+
+        $this->getTransTable();
+
+        $this->data['prefix'] = serendipity_db_escape_string($this->data['prefix']);
+        $users = array();
+        $entries = array();
+
+        if (!extension_loaded('mysql')) {
+            return MYSQL_REQUIRED;
+        }
+
+        $sunlogdb = @mysql_connect($this->data['host'], $this->data['user'], $this->data['pass']);
+        if (!$sunlogdb) {
+            return sprintf(COULDNT_CONNECT, $this->data['host']);
+        }
+
+        if (!@mysql_select_db($this->data['name'])) {
+            return sprintf(COULDNT_SELECT_DB, mysql_error($sunlogdb));
+        }
+
+        /* Users */
+        $res = @mysql_query("SELECT id         AS ID,
+                                    name       AS user_login,
+                                    email      AS user_email,
+                                    homepage   AS user_url
+                               FROM {$this->data['prefix']}users", $sunlogdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_USER_INFO, mysql_error($sunlogdb));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res); $x < $max_x ; $x++ ) {
+            $users[$x] = mysql_fetch_assoc($res);
+
+            $data = array('right_publish' => 1,
+                          'realname'      => $users[$x]['user_login'],
+                          'username'      => $users[$x]['user_login'],
+                          'email'         => $users[$x]['user_email'],
+                          'userlevel'     => USERLEVEL_ADMIN,
+                          'password'      => md5('sunlog'));
+
+            if ($serendipity['serendipityUserlevel'] < $data['userlevel']) {
+                $data['userlevel'] = $serendipity['serendipityUserlevel'];
+            }
+
+            serendipity_db_insert('authors', $this->strtrRecursive($data));
+            echo mysql_error();
+            $users[$x]['authorid'] = serendipity_db_insert_id('authors', 'authorid');
+        }
+
+        /* Categories */
+        if (!$this->importCategories(null)) {
+            return sprintf(COULDNT_SELECT_CATEGORY_INFO, mysql_error($sunlogdb));
+        }
+        serendipity_rebuildCategoryTree();
+
+        /* Entries */
+        $res = @mysql_query("SELECT * FROM {$this->data['prefix']}articles ORDER BY id;", $sunlogdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_ENTRY_INFO, mysql_error($sunlogdb));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++ ) {
+            $entries[$x] = mysql_fetch_assoc($res);
+
+            $entry = array('title'          => $this->decode($entries[$x]['title']),
+                           'isdraft'        => ($entries[$x]['draft'] == '0') ? 'false' : 'true',
+                           'allow_comments' => ($entries[$x]['c_comments'] == '1' ) ? 'true' : 'false',
+                           'timestamp'      => strtotime($entries[$x]['timestamp']),
+                           'body'           => $this->strtr($entries[$x]['lead_converted']),
+                           'extended'       => $this->strtr($entries[$x]['article_converted']),
+                           );
+
+            $entry['authorid'] = '';
+            $entry['author']   = '';
+            foreach ($users as $user) {
+                if ($user['ID'] == $entries[$x]['author']) {
+                    $entry['authorid'] = $user['authorid'];
+                    $entry['author']   = $user['user_login'];
+                    break;
+                }
+            }
+
+            if (!is_int($entries[$x]['entryid'] = serendipity_updertEntry($entry))) {
+                return $entries[$x]['entryid'];
+            }
+        }
+
+        /* Even more category stuff */
+        $res = @mysql_query("SELECT * FROM {$this->data['prefix']}transfer_c;", $sunlogdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_CATEGORY_INFO, mysql_error($sunlogdb));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++ ) {
+            $entrycat = mysql_fetch_assoc($res);
+
+            $entryid = 0;
+            $categoryid = 0;
+            foreach($entries AS $entry) {
+                if ($entry['id'] == $entrycat['article']) {
+                    $entryid = $entry['entryid'];
+                    break;
+                }
+            }
+
+            foreach($this->categories AS $category) {
+                if ($category['id'] == $entrycat['category']) {
+                    $categoryid = $category['categoryid'];
+                }
+            }
+
+            if ($entryid > 0 && $categoryid > 0) {
+                $data = array('entryid'    => $entryid,
+                              'categoryid' => $categoryid);
+                serendipity_db_insert('entrycat', $this->strtrRecursive($data));
+            }
+        }
+
+        /* Comments */
+        $res = @mysql_query("SELECT * FROM {$this->data['prefix']}c_comments;", $sunlogdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_COMMENT_INFO, mysql_error($sunlogdb));
+        }
+
+        while ($a = mysql_fetch_assoc($res)) {
+            foreach ($entries as $entry) {
+                if ($entry['id'] == $a['for_entry'] ) {
+                    $author   = '';
+                    $mail     = '';
+                    $url      = '';
+
+                    foreach($users AS $user) {
+                        if ($user['ID'] == $a['user']) {
+                            $author = $user['user_login'];
+                            $mail = $user['user_email'];
+                            $url  = $user['user_url'];
+                            break;
+                        }
+                    }
+
+                    $comment = array('entry_id ' => $entry['entryid'],
+                                     'parent_id' => 0,
+                                     'timestamp' => strtotime($a['insertdate']),
+                                     'author'    => $author,
+                                     'email'     => $mail,
+                                     'url'       => $url,
+                                     'ip'        => '',
+                                     'status'    => 'approved',
+                                     'body'      => $a['comment'],
+                                     'subscribed'=> 'false',
+                                     'type'      => 'NORMAL');
+
+                    serendipity_db_insert('comments', $this->strtrRecursive($comment));
+                    $cid = serendipity_db_insert_id('comments', 'id');
+                    serendipity_approveComment($cid, $entry['entryid'], true);
+                }
+            }
+        }
+
+        $serendipity['noautodiscovery'] = $noautodiscovery;
+
+        // That was fun.
+        return true;
+    }
+
+    function importCategories($parentid = 0, $new_parentid = 0) {
+        $where = "WHERE parent = '" . mysql_escape_string($parentid) . "'";
+
+        $res = mysql_query("SELECT * FROM {$this->data['prefix']}categories
+                                     " . $where);
+        if (!$res) {
+            echo mysql_error();
+            return false;
+        }
+
+        // Get all the info we need
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++) {
+            $row = mysql_fetch_assoc($res);
+            $cat = array('category_name'        => $row['title'],
+                         'category_description' => $row['optional_1'] . ' ' . $row['optional_2'] . ' ' . $row['optional_3'],
+                         'parentid'             => (int)$new_parentid,
+                         'category_left'        => 0,
+                         'category_right'       => 0);
+
+            serendipity_db_insert('category', $this->strtrRecursive($cat));
+            $row['categoryid']  = serendipity_db_insert_id('category', 'categoryid');
+            $this->categories[] = $row;
+            $this->importCategories($row['id'], $row['categoryid']);
+        }
+
+        return true;
+    }
+}
+
+return 'Serendipity_Import_sunlog';
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/importers/textpattern.inc.php b/include/admin/importers/textpattern.inc.php
new file mode 100644 (file)
index 0000000..d17316f
--- /dev/null
@@ -0,0 +1,251 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+/*****************************************************************
+ *  textpattern  Importer,   by Garvin Hicking *
+ * ****************************************************************/
+
+class Serendipity_Import_textpattern extends Serendipity_Import {
+    var $info        = array('software' => 'Textpattern 1.0rc1');
+    var $data        = array();
+    var $inputFields = array();
+    var $categories  = array();
+
+    function getImportNotes() {
+        return 'Textpattern uses MySQLs native PASSWORD() function to save passwords. Thus, those passwords are incompatible with the MD5 hashing of Serendipity. The passwords for all users have been set to "txp". <strong>You need to modify the passwords manually for each user</strong>, we are sorry for that inconvenience.<br />';
+    }
+
+    function Serendipity_Import_textpattern($data) {
+        $this->data = $data;
+        $this->inputFields = array(array('text' => INSTALL_DBHOST,
+                                         'type' => 'input',
+                                         'name' => 'host'),
+
+                                   array('text' => INSTALL_DBUSER,
+                                         'type' => 'input',
+                                         'name' => 'user'),
+
+                                   array('text' => INSTALL_DBPASS,
+                                         'type' => 'protected',
+                                         'name' => 'pass'),
+
+                                   array('text' => INSTALL_DBNAME,
+                                         'type' => 'input',
+                                         'name' => 'name'),
+
+                                   array('text' => INSTALL_DBPREFIX,
+                                         'type' => 'input',
+                                         'name' => 'prefix',
+                                         'default' => ''),
+
+                                   array('text'    => CHARSET,
+                                         'type'    => 'list',
+                                         'name'    => 'charset',
+                                         'value'   => 'UTF-8',
+                                         'default' => $this->getCharsets(true)),
+
+                                   array('text'    => CONVERT_HTMLENTITIES,
+                                         'type'    => 'bool',
+                                         'name'    => 'use_strtr',
+                                         'default' => 'true'),
+
+                                   array('text'    => ACTIVATE_AUTODISCOVERY,
+                                         'type'    => 'bool',
+                                         'name'    => 'autodiscovery',
+                                         'default' => 'false')
+                            );
+    }
+
+    function validateData() {
+        return sizeof($this->data);
+    }
+
+    function getInputFields() {
+        return $this->inputFields;
+    }
+
+    function import() {
+        global $serendipity;
+
+        // Save this so we can return it to its original value at the end of this method.
+        $noautodiscovery = isset($serendipity['noautodiscovery']) ? $serendipity['noautodiscovery'] : false;
+
+        if ($this->data['autodiscovery'] == 'false') {
+            $serendipity['noautodiscovery'] = 1;
+        }
+
+        $this->getTransTable();
+
+        $this->data['prefix'] = serendipity_db_escape_string($this->data['prefix']);
+        $users = array();
+        $entries = array();
+
+        if (!extension_loaded('mysql')) {
+            return MYSQL_REQUIRED;
+        }
+
+        $txpdb = @mysql_connect($this->data['host'], $this->data['user'], $this->data['pass']);
+        if (!$txpdb) {
+            return sprintf(COULDNT_CONNECT, $this->data['host']);
+        }
+
+        if (!@mysql_select_db($this->data['name'])) {
+            return sprintf(COULDNT_SELECT_DB, mysql_error($txpdb));
+        }
+
+        /* Users */
+        $res = @mysql_query("SELECT user_id    AS ID,
+                                    name       AS user_login,
+                                    `pass`     AS user_pass,
+                                    email      AS user_email,
+                                    privs      AS user_level
+                               FROM {$this->data['prefix']}txp_users", $txpdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_USER_INFO, mysql_error($txpdb));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res); $x < $max_x ; $x++ ) {
+            $users[$x] = mysql_fetch_assoc($res);
+
+            $data = array('right_publish' => ($users[$x]['user_level'] <= 4) ? 1 : 0,
+                          'realname'      => $users[$x]['user_login'],
+                          'username'      => $users[$x]['user_login'],
+                          'email'         => $users[$x]['user_email'],
+                          'password'      => md5('txp')); // blame TXP for using PASSWORD().
+
+            if ( $users[$x]['user_level'] == 1 ) {
+                $data['userlevel'] = USERLEVEL_EDITOR;
+            } elseif ($users[$x]['user_level'] == 2) {
+                $data['userlevel'] = USERLEVEL_CHIEF;
+            } else {
+                $data['userlevel'] = USERLEVEL_ADMIN;
+            }
+
+            if ($serendipity['serendipityUserlevel'] < $data['userlevel']) {
+                $data['userlevel'] = $serendipity['serendipityUserlevel'];
+            }
+
+            serendipity_db_insert('authors', $this->strtrRecursive($data));
+            $users[$x]['authorid'] = serendipity_db_insert_id('authors', 'authorid');
+        }
+
+        /* Categories */
+        if (!$this->importCategories('root')) {
+            return sprintf(COULDNT_SELECT_CATEGORY_INFO, mysql_error($txpdb));
+        }
+        serendipity_rebuildCategoryTree();
+
+        /* Entries */
+        // Notice: Textpattern doesn't honor the prefix for this table. Wicked system.
+        $res = @mysql_query("SELECT * FROM {$this->data['prefix']}textpattern ORDER BY Posted;", $txpdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_ENTRY_INFO, mysql_error($txpdb));
+        }
+
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++ ) {
+            $entries[$x] = mysql_fetch_assoc($res);
+
+            $entry = array('title'          => $this->decode($entries[$x]['Title']),
+                           'isdraft'        => ($entries[$x]['Status'] == '4') ? 'false' : 'true',
+                           'allow_comments' => ($entries[$x]['Annotate'] == '1' ) ? 'true' : 'false',
+                           'timestamp'      => strtotime($entries[$x]['Posted']),
+                           'extended'       => $this->strtr($entries[$x]['Body_html']),
+                           'body'           => $this->strtr($entries[$x]['Excerpt']));
+
+            $entry['authorid'] = '';
+            $entry['author']   = '';
+            foreach ($users as $user) {
+                if ($user['user_login'] == $entries[$x]['AuthorID']) {
+                    $entry['authorid'] = $user['authorid'];
+                    $entry['author']   = $user['user_login'];
+                    break;
+                }
+            }
+
+            if (!is_int($entries[$x]['entryid'] = serendipity_updertEntry($entry))) {
+                return $entries[$x]['entryid'];
+            }
+
+            /* Entry/category */
+            foreach ($this->categories as $category) {
+                if ($category['name'] == $entries[$x]['Category1'] || $category['name'] == $entries[$x]['Category2']) {
+                    $data = array('entryid'    => $entries[$x]['entryid'],
+                                  'categoryid' => $category['categoryid']);
+                    serendipity_db_insert('entrycat', $this->strtrRecursive($data));
+                    break;
+                }
+            }
+        }
+
+        /* Comments */
+        $res = @mysql_query("SELECT * FROM {$this->data['prefix']}txp_discuss;", $txpdb);
+        if (!$res) {
+            return sprintf(COULDNT_SELECT_COMMENT_INFO, mysql_error($txpdb));
+        }
+
+        while ($a = mysql_fetch_assoc($res)) {
+            foreach ($entries as $entry) {
+                if ($entry['ID'] == $a['parentid'] ) {
+                    $author   = $a['name'];
+                    $mail     = $a['email'];
+                    $url      = $a['web'];
+
+                    $comment = array('entry_id ' => $entry['entryid'],
+                                     'parent_id' => 0,
+                                     'timestamp' => strtotime($a['posted']),
+                                     'author'    => $author,
+                                     'email'     => $mail,
+                                     'url'       => $url,
+                                     'ip'        => $a['ip'],
+                                     'status'    => ($a['visible'] == '1' ? 'approved' : 'pending'),
+                                     'body'      => $a['message'],
+                                     'subscribed'=> 'false',
+                                     'type'      => 'NORMAL');
+
+                    serendipity_db_insert('comments', $this->strtrRecursive($comment));
+                    if ($a['visible'] == '1') {
+                        $cid = serendipity_db_insert_id('comments', 'id');
+                        serendipity_approveComment($cid, $entry['entryid'], true);
+                    }
+                }
+            }
+        }
+
+        $serendipity['noautodiscovery'] = $noautodiscovery;
+
+        // That was fun.
+        return true;
+    }
+
+    function importCategories($parentname = 'root', $parentid = 0) {
+        $res = mysql_query("SELECT * FROM {$this->data['prefix']}txp_category
+                                     WHERE parent = '" . mysql_escape_string($parentname) . "' AND type = 'article'");
+        if (!$res) {
+            echo mysql_error();
+            return false;
+        }
+
+        // Get all the info we need
+        for ($x=0, $max_x = mysql_num_rows($res) ; $x < $max_x ; $x++) {
+            $row = mysql_fetch_assoc($res);
+            $cat = array('category_name'        => $row['name'],
+                         'category_description' => $row['name'],
+                         'parentid'             => $parentid,
+                         'category_left'        => 0,
+                         'category_right'       => 0);
+
+            serendipity_db_insert('category', $this->strtrRecursive($cat));
+            $row['categoryid']  = serendipity_db_insert_id('category', 'categoryid');
+            $this->categories[] = $row;
+            $this->importCategories($row['name'], $row['categoryid']);
+        }
+
+        return true;
+    }
+}
+
+return 'Serendipity_Import_textpattern';
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/importers/wordpress.inc.php b/include/admin/importers/wordpress.inc.php
new file mode 100644 (file)
index 0000000..8661117
--- /dev/null
@@ -0,0 +1,254 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+/*****************************************************************
+ *                WordPress Importer, by Evan Nemerson           *
+ *****************************************************************/
+
+class Serendipity_Import_WordPress extends Serendipity_Import {
+    var $info        = array('software' => 'WordPress');
+    var $data        = array();
+    var $inputFields = array();
+
+
+    function Serendipity_Import_WordPress($data) {
+        $this->data = $data;
+        $this->inputFields = array(array('text' => INSTALL_DBHOST,
+                                         'type' => 'input',
+                                         'name' => 'host'),
+
+                                   array('text' => INSTALL_DBUSER,
+                                         'type' => 'input',
+                                         'name' => 'user'),
+
+                                   array('text' => INSTALL_DBPASS,
+                                         'type' => 'protected',
+                                         'name' => 'pass'),
+
+                                   array('text' => INSTALL_DBNAME,
+                                         'type' => 'input',
+                                         'name' => 'name'),
+
+                                   array('text' => INSTALL_DBPREFIX,
+                                         'type' => 'input',
+                                         'name' => 'prefix'),
+
+                                   array('text'    => CHARSET,
+                                         'type'    => 'list',
+                                         'name'    => 'charset',
+                                         'value'   => 'UTF-8',
+                                         'default' => $this->getCharsets(true)),
+
+                                   array('text'    => CONVERT_HTMLENTITIES,
+                                         'type'    => 'bool',
+                                         'name'    => 'use_strtr',
+                                         'default' => 'true'),
+
+                                   array('text'    => ACTIVATE_AUTODISCOVERY,
+                                         'type'    => 'bool',
+                                         'name'    => 'autodiscovery',
+                                         'default' => 'false')
+                            );
+    }
+
+    function validateData() {
+        return sizeof($this->data);
+    }
+
+    function getInputFields() {
+        return $this->inputFields;
+    }
+
+    function import() {
+        global $serendipity;
+
+        // Save this so we can return it to its original value at the end of this method.
+        $noautodiscovery = isset($serendipity['noautodiscovery']) ? $serendipity['noautodiscovery'] : false;
+
+        if ($this->data['autodiscovery'] == 'false') {
+            $serendipity['noautodiscovery'] = 1;
+        }
+
+        $this->getTransTable();
+
+        $this->data['prefix'] = serendipity_db_escape_string($this->data['prefix']);
+        $users = array();
+        $categories = array();
+        $entries = array();
+
+        if ( !extension_loaded('mysql') ) {
+            return MYSQL_REQUIRED;;
+        }
+
+        $wpdb = @mysql_connect($this->data['host'], $this->data['user'], $this->data['pass']);
+        if ( !$wpdb ) {
+            return sprintf(COULDNT_CONNECT, $this->data['host']);
+        }
+
+        if ( !@mysql_select_db($this->data['name']) ) {
+            return sprintf(COULDNT_SELECT_DB, mysql_error($wpdb));
+        }
+
+        /* Users */
+        $res = @mysql_query("SELECT ID, user_login, user_pass, user_email, user_level FROM {$this->data['prefix']}users;", $wpdb);
+        if ( !$res ) {
+            return sprintf(COULDNT_SELECT_USER_INFO, mysql_error($wpdb));
+        }
+
+        for ( $x=0 ; $x<mysql_num_rows($res) ; $x++ ) {
+            $users[$x] = mysql_fetch_assoc($res);
+
+            $data = array('right_publish' => ($users[$x]['user_level'] >= 1) ? 1 : 0,
+                          'realname'      => $users[$x]['user_login'],
+                          'username'      => $users[$x]['user_login'],
+                          'password'      => $users[$x]['user_pass']); // WP uses md5, too.
+
+            if ( $users[$x]['user_level'] <= 1 ) {
+                $data['userlevel'] = USERLEVEL_EDITOR;
+            } elseif ( $users[$x]['user_level'] < 5 ) {
+                $data['userlevel'] = USERLEVEL_CHIEF;
+            } else {
+                $data['userlevel'] = USERLEVEL_ADMIN;
+            }
+
+            if ($serendipity['serendipityUserlevel'] < $data['userlevel']) {
+                $data['userlevel'] = $serendipity['serendipityUserlevel'];
+            }
+
+            serendipity_db_insert('authors', $this->strtrRecursive($data));
+            $users[$x]['authorid'] = serendipity_db_insert_id('authors', 'authorid');
+        }
+
+        /* Categories */
+        $res = @mysql_query("SELECT cat_ID, cat_name, category_description, category_parent FROM {$this->data['prefix']}categories ORDER BY category_parent, cat_ID;", $wpdb);
+        if ( !$res ) {
+            return sprintf(COULDNT_SELECT_CATEGORY_INFO, mysql_error($wpdb));
+        }
+
+        // Get all the info we need
+        for ( $x=0 ; $x<mysql_num_rows($res) ; $x++ )
+            $categories[] = mysql_fetch_assoc($res);
+
+        // Insert all categories as top level (we need to know everyone's ID before we can represent the hierarchy).
+        for ( $x=0 ; $x<sizeof($categories) ; $x++ ) {
+            $cat = array('category_name'        => $categories[$x]['cat_name'],
+                         'category_description' => $categories[$x]['category_description'],
+                         'parentid'             => 0, // <---
+                         'category_left'        => 0,
+                         'category_right'       => 0);
+
+            serendipity_db_insert('category', $this->strtrRecursive($cat));
+            $categories[$x]['categoryid'] = serendipity_db_insert_id('category', 'categoryid');
+        }
+
+        // There has to be a more efficient way of doing this...
+        foreach ( $categories as $cat ) {
+            if ( $cat['category_parent'] != 0 ) {
+                // Find the parent
+                $par_id = 0;
+                foreach ( $categories as $possible_par ) {
+                    if ( $possible_par['cat_ID'] == $cat['category_parent'] ) {
+                        $par_id = $possible_par['categoryid'];
+                        break;
+                    }
+                }
+
+                if ( $par_id != 0 ) {
+                  serendipity_db_query("UPDATE {$serendipity['dbPrefix']}category SET parentid={$par_id} WHERE categoryid={$cat['categoryid']};");
+                } // else { echo "D'oh! " . random_string_of_profanity(); }
+            }
+        }
+
+        serendipity_rebuildCategoryTree();
+
+        /* Entries */
+        $res = @mysql_query("SELECT * FROM {$this->data['prefix']}posts ORDER BY post_date;", $wpdb);
+        if ( !$res ) {
+            return sprintf(COULDNT_SELECT_ENTRY_INFO, mysql_error($wpdb));
+        }
+
+        for ( $x=0 ; $x<mysql_num_rows($res) ; $x++ ) {
+            $entries[$x] = mysql_fetch_assoc($res);
+
+            $entry = array('title'          => $this->decode($entries[$x]['post_title']), // htmlentities() is called later, so we can leave this.
+                           'isdraft'        => ($entries[$x]['post_status'] == 'publish') ? 'false' : 'true',
+                           'allow_comments' => ($entries[$x]['comment_status'] == 'open' ) ? 'true' : 'false',
+                           'timestamp'      => strtotime($entries[$x]['post_date']),
+                           'body'           => $this->strtr($entries[$x]['post_content']));
+
+            foreach ( $users as $user ) {
+                if ( $user['ID'] == $entries[$x]['post_author'] ) {
+                    $entry['authorid'] = $user['authorid'];
+                    break;
+                }
+            }
+
+            if ( !is_int($entries[$x]['entryid'] = serendipity_updertEntry($entry)) ) {
+                return $entries[$x]['entryid'];
+            }
+        }
+
+        /* Entry/category */
+        $res = @mysql_query("SELECT * FROM {$this->data['prefix']}post2cat;", $wpdb);
+        if ( !$res ) {
+            return sprintf(COULDNT_SELECT_ENTRY_INFO, mysql_error($wpdb));
+        }
+
+        while ( $a = mysql_fetch_assoc($res) ) {
+            foreach ( $categories as $category ) {
+                if ( $category['cat_ID'] == $a['category_id'] ) {
+                    foreach ( $entries as $entry ) {
+                        if ( $a['post_id'] == $entry['ID'] ) {
+                            $data = array('entryid' => $entry['entryid'],
+                                          'categoryid' => $category['categoryid']);
+                            serendipity_db_insert('entrycat', $this->strtrRecursive($data));
+                            break;
+                        }
+                    }
+                    break;
+                }
+            }
+        }
+
+        /* Comments */
+        $res = @mysql_query("SELECT * FROM {$this->data['prefix']}comments;", $wpdb);
+        if ( !$res ) {
+            return sprintf(COULDNT_SELECT_COMMENT_INFO, mysql_error($wpdb));
+        }
+
+        while ( $a = mysql_fetch_assoc($res) ) {
+            foreach ( $entries as $entry ) {
+                if ( $entry['ID'] == $a['comment_post_ID'] ) {
+                    $comment = array('entry_id ' => $entry['entryid'],
+                                     'parent_id' => 0,
+                                     'timestamp' => strtotime($a['comment_date']),
+                                     'author'    => $a['comment_author'],
+                                     'email'     => $a['comment_author_email'],
+                                     'url'       => $a['comment_author_url'],
+                                     'ip'        => $a['comment_author_IP'],
+                                     'status'    => (empty($a['comment_approved']) || $a['comment_approved'] == '1') ? 'approved' : 'pending',
+                                     'subscribed'=> 'false',
+                                     'body'      => $a['comment_content'],
+                                     'type'      => 'NORMAL');
+
+                    serendipity_db_insert('comments', $this->strtrRecursive($comment));
+                    if ($comment['status'] == 'approved') {
+                        $cid = serendipity_db_insert_id('comments', 'id');
+                        serendipity_approveComment($cid, $entry['entryid'], true);
+                    }
+                }
+            }
+        }
+
+        $serendipity['noautodiscovery'] = $noautodiscovery;
+
+        // That was fun.
+        return true;
+    }
+}
+
+return 'Serendipity_Import_WordPress';
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/installer.inc.php b/include/admin/installer.inc.php
new file mode 100644 (file)
index 0000000..e454cb0
--- /dev/null
@@ -0,0 +1,456 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+umask(0000);
+$umask = 0775;
+@define('IN_installer', true);
+
+define('S9Y_I_ERROR', -1);
+define('S9Y_I_WARNING', 0);
+define('S9Y_I_SUCCESS', 1);
+$basedir = serendipity_query_default('serendipityPath', false);
+
+function serendipity_installerResultDiagnose($result, $s) {
+    global $errorCount;
+    if ( $result === S9Y_I_SUCCESS ) {
+        return '<span style="color: green; font-weight: bold">'. $s .'</span>';
+    }
+    if ( $result === S9Y_I_WARNING ) {
+        return '<span style="color: orange; font-weight: bold">'. $s .'</span>';
+    }
+    if ( $result === S9Y_I_ERROR ) {
+        $errorCount++;
+        return '<span style="color: red; font-weight: bold">'. $s .'</span>';
+    }
+}
+
+/* If register_globals is enabled and we use the dual GET/POST submission method, we will
+   receive the value of the POST-variable inside the GET-variable, which is of course unwanted.
+   Thus we transfer a new variable GETSTEP via POST and set that to an internal GET value. */
+if (!empty($serendipity['POST']['getstep']) && is_numeric($serendipity['POST']['getstep'])) {
+    $serendipity['GET']['step'] = $serendipity['POST']['getstep'];
+}
+
+/* From configuration to install */
+if ( sizeof($_POST) > 1 && $serendipity['GET']['step'] == 3 ) {
+    /* One problem, if the user chose to do an easy install, not all config vars has been transfered
+       Therefore we fetch all config vars with their default values, and merge them with our POST data */
+
+    $config = serendipity_parseTemplate(S9Y_CONFIG_TEMPLATE);
+    foreach ( $config as $category ) {
+        foreach ( $category['items'] as $item ) {
+            if ( !isset($_POST[$item['var']]) ) {
+                $_POST[$item['var']] = serendipity_query_default($item['var'], $item['default']);
+            }
+        }
+    }
+
+    if ( is_array($errors = serendipity_checkInstallation()) ) {
+        foreach ( $errors as  $error ) {
+            echo '<div class="serendipityAdminMsgError">'. $error .'</div>';
+        }
+
+        $from = $_POST;
+        /* Back to configuration, user did something wrong */
+        $serendipity['GET']['step'] = $serendipity['POST']['step'];
+    } else {
+        /* We're good, move to install process */
+        $serendipity['GET']['step'] = 3;
+    }
+}
+
+if ( (int)$serendipity['GET']['step'] == 0 ) {
+?>
+<?php echo WELCOME_TO_INSTALLATION ?>.
+<br /><?php echo FIRST_WE_TAKE_A_LOOK ?>.
+<br /><?php echo sprintf(ERRORS_ARE_DISPLAYED_IN, serendipity_installerResultDiagnose(S9Y_I_ERROR, RED), serendipity_installerResultDiagnose(S9Y_I_WARNING, YELLOW), serendipity_installerResultDiagnose(S9Y_I_SUCCESS, GREEN)); ?>.
+<br />
+<br>
+<div align="center">- <?php echo sprintf(PRE_INSTALLATION_REPORT, $serendipity['version']) ?> -</div><br />
+
+
+<?php $errorCount = 0 ?>
+<div align="center">
+<table class="serendipity_admin_list_item serendipity_admin_list_item_even" width="90%" align="center">
+    <tr>
+        <td colspan="2" style="font-weight: bold"><?php echo PHP_INSTALLATION ?></td>
+    </tr>
+    <tr>
+      <td><?php echo OPERATING_SYSTEM ?></td>
+      <td><?php echo php_uname('s') .' '. php_uname('r') .', '. php_uname('m') ?></td>
+    </tr>
+    <tr>
+      <td><?php echo WEBSERVER_SAPI ?></td>
+      <td><?php echo php_sapi_name() ?></td>
+    </tr>
+    <tr>
+        <td>PHP version >= 4.1.2</td>
+        <td width="200"><?php
+            if ( version_compare(phpversion(), '4.1.2', '>=') ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, YES .', '. phpversion());
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_ERROR, NO);
+            }
+     ?></td>
+    </tr>
+    <tr>
+        <td>Database extensions</td>
+        <td width="200"><?php
+
+            if ( sizeof(($_res = serendipity_probeInstallation('dbType'))) == 0 ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_ERROR, NONE);
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, implode(', ', $_res));
+            }
+     ?></td>
+    </tr>
+    <tr>
+        <td>Session extension</td>
+        <td width="200"><?php
+            if ( extension_loaded('session') ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, YES);
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, NO);
+            }
+     ?></td>
+    </tr>
+    <tr>
+        <td>PCRE extension</td>
+        <td width="200"><?php
+            if ( extension_loaded('pcre') ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, YES);
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, NO);
+            }
+     ?></td>
+    </tr>
+    <tr>
+        <td>GDlib extension</td>
+        <td width="200"><?php
+            if ( extension_loaded('gd') ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, YES);
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_WARNING, NO);
+            }
+     ?></td>
+    </tr>
+    <tr>
+      <td>OpenSSL extension</td>
+      <td><?php
+            if ( extension_loaded('openssl') ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, YES);
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_WARNING, NO);
+            }
+     ?></td>
+    </tr>
+    <tr>
+        <td>mbstring extension</td>
+        <td width="200"><?php
+            if ( extension_loaded('mbstring') ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, YES);
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_WARNING, NO);
+            }
+     ?></td>
+    </tr>
+    <tr>
+        <td>iconv extension</td>
+        <td width="200"><?php
+            if ( extension_loaded('iconv') ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, YES);
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_WARNING, NO);
+            }
+     ?></td>
+    </tr>
+    <tr>
+        <td>zlib extension</td>
+        <td width="200"><?php
+            if ( extension_loaded('zlib') ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, YES);
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_WARNING, NO);
+            }
+     ?></td>
+    </tr>
+    <tr>
+      <td>Imagemagick binary </td>
+      <td><?php
+            if ($binary = serendipity_query_default('convert', false)) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, $binary);
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_WARNING, NOT_FOUND);
+            }
+      ?></td>
+    </tr>
+</table>
+<br />
+<table class="serendipity_admin_list_item serendipity_admin_list_item_even" width="90%" align="center">
+    <tr>
+        <td colspan="3" style="font-weight: bold"><?PHP echo PHPINI_CONFIGURATION ?></td>
+    </tr>
+    <tr>
+      <td>&nbsp;</td>
+      <td width="150"><em><?php echo RECOMMENDED ?></em></td>
+      <td width="150"><em><?php echo ACTUAL ?></em></td>
+    </tr>
+    <tr>
+      <td>safe_mode</td>
+      <td width="150"><strong><?php echo 'OFF' ?></strong></td>
+      <td width="150"><?php
+            if ( !serendipity_ini_bool(ini_get('safe_mode')) ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, 'OFF');
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_WARNING, 'ON');
+            }
+     ?></td>
+    </tr>
+    <tr>
+        <td>register_globals</td>
+        <td width="150"><strong><?php echo 'OFF' ?></strong></td>
+        <td width="150"><?php
+            if ( serendipity_ini_bool(ini_get('register_globals')) ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_WARNING, 'ON');
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, 'OFF');
+            }
+     ?></td>
+    </tr>
+    <tr>
+        <td>magic_quotes_gpc</td>
+        <td width="150"><strong><?php echo 'OFF' ?></strong></td>
+        <td width="150"><?php
+            if ( !serendipity_ini_bool(ini_get('magic_quotes_gpc')) ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, 'OFF');
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_WARNING, 'ON');
+            }
+     ?></td>
+    </tr>
+    <tr>
+      <td>magic_quotes_runtime</td>
+      <td width="150"><strong><?php echo 'OFF' ?></strong></td>
+      <td width="150"><?php
+            if ( !serendipity_ini_bool(ini_get('magic_quotes_runtime')) ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, 'OFF');
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_ERROR, 'ON');
+            }
+     ?></td>
+    </tr>
+    <tr>
+      <td>session.use_trans_sid</td>
+      <td width="150"><strong><?php echo 'OFF' ?></strong></td>
+      <td width="150"><?php
+            if ( !serendipity_ini_bool(ini_get('session.use_trans_sid')) ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, 'OFF');
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_WARNING, 'ON');
+            }
+     ?></td>
+    </tr>
+    <tr>
+      <td>allow_url_fopen</td>
+      <td width="150"><strong><?php echo 'ON' ?></strong></td>
+      <td width="150"><?php
+            if ( serendipity_ini_bool(ini_get('allow_url_fopen')) ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, 'ON');
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_WARNING, 'OFF');
+            }
+     ?></td>
+    </tr>
+    <tr>
+      <td>file_uploads</td>
+      <td width="150"><strong><?php echo 'ON' ?></strong></td>
+      <td width="150"><?php
+            if ( serendipity_ini_bool(ini_get('file_uploads')) ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, 'ON');
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_ERROR, 'OFF');
+            }
+     ?></td>
+    </tr>
+    <tr>
+      <td>post_max_size</td>
+      <td width="150"><strong>10M</strong></td>
+      <td width="150"><?php
+            if ( serendipity_ini_bytesize(ini_get('post_max_size')) >= (10*1024*1024) ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, ini_get('post_max_size'));
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_WARNING, ini_get('post_max_size'));
+            }
+     ?></td>
+    </tr>
+    <tr>
+      <td>upload_max_filesize</td>
+      <td width="150"><strong>10M</strong></td>
+      <td width="150"><?php
+            if ( serendipity_ini_bytesize(ini_get('upload_max_filesize')) >= (10*1024*1024) ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, ini_get('upload_max_filesize'));
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_WARNING, ini_get('upload_max_filesize'));
+            }
+     ?></td>
+    </tr>
+</table>
+
+<br />
+<table class="serendipity_admin_list_item serendipity_admin_list_item_even" width="90%" align="center">
+    <tr>
+        <td colspan="2" style="font-weight: bold"><?php echo PERMISSIONS ?></td>
+    </tr>
+    <tr>
+        <td><?php echo $basedir ?></td>
+        <td width="200"><?php
+            if ( is_writable($basedir) ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, WRITABLE);
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_ERROR, NOT_WRITABLE);
+                $showWritableNote = true;
+            }
+     ?></td>
+    </tr>
+    <tr>
+        <td><?php echo $basedir . PATH_SMARTY_COMPILE?></td>
+        <td width="200"><?php
+            if ( is_writable($basedir . PATH_SMARTY_COMPILE) ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, WRITABLE);
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_ERROR, NOT_WRITABLE);
+                $showWritableNote = true;
+            }
+     ?></td>
+    </tr>
+<?php if ( is_dir($basedir .'uploads/') ) { ?>
+    <tr>
+        <td><?php echo $basedir . 'uploads/'?></td>
+        <td width="200"><?php
+            if ( is_writable($basedir . 'uploads/') ) {
+                echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, WRITABLE);
+            } else {
+                echo serendipity_installerResultDiagnose(S9Y_I_ERROR, NOT_WRITABLE);
+                $showWritableNote = true;
+            }
+     ?></td>
+    </tr>
+<?php } ?>
+<?php if (function_exists('is_executable')) { ?>
+    <tr>
+      <td>Execute Imagemagick  binary </td>
+      <td><?php
+            if ($binary = serendipity_query_default('convert', false)) {
+                if (is_executable($binary)) {
+                    echo serendipity_installerResultDiagnose(S9Y_I_SUCCESS, YES);
+                } else {
+                    echo serendipity_installerResultDiagnose(S9Y_I_WARNING, NO);
+                }
+            } else {
+                 echo serendipity_installerResultDiagnose(S9Y_I_WARNING, NOT_FOUND);
+            }
+      ?></td>
+    </tr>
+<?php } ?>
+</table>
+
+<?php if ( $showWritableNote === true ) { ?>
+    <div class="serendipityAdminMsgNote"><?php echo sprintf(PROBLEM_PERMISSIONS_HOWTO, 'chmod 1777') ?></div>
+<?php } ?>
+
+<div align="center">
+<?php if ( $errorCount > 0 ) { ?>
+    <div class="serendipityAdminMsgError"><?php echo PROBLEM_DIAGNOSTIC ?></div>
+    <h2><a href="serendipity_admin.php"><?php echo RECHECK_INSTALLATION ?></a></h2>
+<?php } else { ?>
+    <?php echo SELECT_INSTALLATION_TYPE ?>:
+    <h2><a href="?serendipity[step]=2a"><?php echo SIMPLE_INSTALLATION ?></a> - <a href="?serendipity[step]=2b"><?php echo EXPERT_INSTALLATION ?></a></h2>
+    <?php } ?>
+</div>
+</div>
+
+<?php } elseif ( $serendipity['GET']['step'] == '2a' ) { ?>
+<form action="?" method="post">
+    <input type="hidden" name="serendipity[step]" value="<?php echo $serendipity['GET']['step'] ?>">
+    <input type="hidden" name="serendipity[getstep]" value="3">
+<?php
+    $config = serendipity_parseTemplate(S9Y_CONFIG_TEMPLATE, null, array('simpleInstall'));
+    serendipity_printConfigTemplate($config, $from, true, false, false);
+?>
+    <div align="center"><input name="submit" type="submit" value="<?php echo COMPLETE_INSTALLATION ?>" class="serendipityPrettyButton"></div>
+</form>
+
+<?php } elseif ( $serendipity['GET']['step'] == '2b' ) { ?>
+<form action="?" method="post">
+    <input type="hidden" name="serendipity[step]" value="<?php echo $serendipity['GET']['step'] ?>">
+    <input type="hidden" name="serendipity[getstep]" value="3">
+<?php
+    $config = serendipity_parseTemplate(S9Y_CONFIG_TEMPLATE);
+    serendipity_printConfigTemplate($config, $from, true, false, false);
+?>
+    <div align="center"><input name="submit" type="submit" value="<?php echo COMPLETE_INSTALLATION ?>" class="serendipityPrettyButton"></div>
+</form>
+
+<?php } elseif ( (int)$serendipity['GET']['step'] == 3 ) { ?>
+<?php
+
+    $serendipity['dbPrefix'] = $_POST['dbPrefix'];
+
+    echo CHECK_DATABASE_EXISTS .'...';
+    $t = serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}authors", false, 'both', false, false, false, true);
+    if ( is_array($t) ) {
+        echo ' <strong>'. THEY_DO .'</strong>, '. WONT_INSTALL_DB_AGAIN;
+        echo '<br />';
+        echo '<br />';
+    } else {
+        echo ' <strong>'. THEY_DONT .'</strong>';
+        echo '<br />';
+
+        echo CREATE_DATABASE;
+        serendipity_installDatabase();
+        echo ' <strong>' . DONE . '</strong><br />';
+
+        echo sprintf(CREATING_PRIMARY_AUTHOR, $_POST['user']) .'...';
+        $authorid = serendipity_addAuthor($_POST['user'], $_POST['pass'], $_POST['realname'], $_POST['email'], USERLEVEL_ADMIN);
+        $mail_comments =  (serendipity_db_bool($_POST['want_mail']) ? 1 : 0);
+        serendipity_set_user_var('mail_comments', $mail_comments, $authorid);
+        serendipity_set_user_var('mail_trackbacks', $mail_comments, $authorid);
+        serendipity_set_user_var('right_publish', 1, $authorid);
+
+
+        echo ' <strong>' . DONE . '</strong><br />';
+
+        echo SETTING_DEFAULT_TEMPLATE .'... ';
+        serendipity_set_config_var('template', $serendipity['defaultTemplate']);
+        echo ' <strong>' . DONE . '</strong><br />';
+
+        echo INSTALLING_DEFAULT_PLUGINS .'... ';
+        include_once S9Y_INCLUDE_PATH . 'include/plugin_api.inc.php';
+        serendipity_plugin_api::register_default_plugins();
+        echo ' <strong>' . DONE . '</strong><br />';
+
+    }
+
+    echo sprintf(ATTEMPT_WRITE_FILE, '.htaccess') . '... ';
+    $errors = serendipity_installFiles($basedir);
+    if ( $errors === true ) {
+         echo ' <strong>' . DONE . '</strong><br />';
+    } else {
+        echo ' <strong>' . FAILED . '</strong><br />';
+        foreach ( $errors as $error ) {
+            echo '<div class="serendipityAdminMsgError">'. $error .'</div>';
+        }
+    }
+
+    if ( serendipity_updateConfiguration() ) {
+        echo '<div class="serendipityAdminMsgSuccess">'. SERENDIPITY_INSTALLED .'</div>';
+        echo '<div align="center" style="font-size: large"><a href="'. $_POST['serendipityHTTPPath'] .'">'. VISIT_BLOG_HERE .'</a></div>';
+        echo '<div align="center">'. THANK_YOU_FOR_CHOOSING .'</div>';
+    } else {
+        echo '<div class="serendipityAdminMsgSuccess">'. ERROR_DETECTED_IN_INSTALL .'</div>';
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/overview.inc.php b/include/admin/overview.inc.php
new file mode 100644 (file)
index 0000000..bcc32a1
--- /dev/null
@@ -0,0 +1,18 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+if (IN_serendipity !== true) {
+    die ("Don't hack!");
+}
+
+$user = serendipity_fetchAuthor($serendipity['authorid']);
+?>
+
+<?php echo WELCOME_BACK ?> <?php echo $user[0]['realname'] ?>.
+
+<?php serendipity_plugin_api::hook_event('backend_frontpage_display', $serendipity); ?>
+
+<?php
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/personal.inc.php b/include/admin/personal.inc.php
new file mode 100644 (file)
index 0000000..dfe1d20
--- /dev/null
@@ -0,0 +1,46 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+if (IN_serendipity !== true) {
+    die ("Don't hack!");
+}
+
+$from = array();
+
+if ( $serendipity['GET']['adminAction'] == 'save' ) {
+    $config = serendipity_parseTemplate(S9Y_CONFIG_USERTEMPLATE);
+    if ((int)$_POST['userlevel'] > $serendipity['serendipityUserlevel']) {
+        echo '<div class="serendipityAdminMsgError">' . CREATE_NOT_AUTHORIZED_USERLEVEL . '</div>';
+    } else {
+        foreach($config as $category) {
+            foreach ($category['items'] as $item) {
+                if ( serendipity_checkConfigItemFlags($item, 'local') ) {
+                    serendipity_set_user_var($item['var'], $_POST[$item['var']], $serendipity['authorid'], true);
+                }
+
+                if ( serendipity_checkConfigItemFlags($item, 'configuration') ) {
+                    serendipity_set_config_var($item['var'], $_POST[$item['var']], $serendipity['authorid']);
+                }
+            }
+        }
+        $from = $_POST;
+?>
+    <div class="serendipityAdminMsgSuccess"><?php echo sprintf(MODIFIED_USER, $_POST['realname']) ?></div>
+<?php }
+} ?>
+
+<form action="?serendipity[adminModule]=personal&amp;serendipity[adminAction]=save" method="post">
+<?php
+$template   = serendipity_parseTemplate(S9Y_CONFIG_USERTEMPLATE);
+$user       = serendipity_fetchUsers($serendipity['authorid']);
+$from       = $user[0];
+unset($from['password']);
+serendipity_printConfigTemplate($template, $from, true, false);
+?>
+    <div align="right"><input type="submit" name="SAVE"   value="<?php echo SAVE; ?>" /></div>
+</form>
+
+<?php
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/plugins.inc.php b/include/admin/plugins.inc.php
new file mode 100644 (file)
index 0000000..6b19ecb
--- /dev/null
@@ -0,0 +1,711 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+if (IN_serendipity !== true) {
+    die ('Don\'t hack!');
+}
+
+if ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF) {
+    return;
+}
+
+include_once S9Y_INCLUDE_PATH . 'include/plugin_api.inc.php';
+include_once S9Y_INCLUDE_PATH . 'include/plugin_internal.inc.php';
+
+function serendipity_pluginListSort($x, $y) {
+    return strnatcasecmp($x['name'] . ' - ' . $x['desc'], $y['name'] . ' - ' . $y['desc']);
+}
+
+function show_plugins($event_only = false)
+{
+    global $serendipity;
+?>
+    <form action="?serendipity[adminModule]=plugins" method="post">
+        <table border="0" cellpadding="5" cellspacing="0" width="100%">
+            <tr>
+                <td colspan="2">&nbsp;</td>
+                <td><strong><?php echo TITLE; ?></strong></td>
+                <td><strong><?php echo PERMISSIONS; ?></strong></td>
+<?php
+    if (!$event_only) {
+?>
+                <td colspan="3" align="center"><strong><?php echo PLACEMENT; ?></strong></td>
+<?php
+    } else {
+?>
+                <td colspan="2">&nbsp;</dd>
+<?php } ?>
+            </tr>
+<?php
+    $sort_order = 0;
+    $errors     = array();
+
+    /* Block display the plugins per placement location. */
+    if ($event_only) {
+        $plugin_placements = array('event');
+    } else {
+        $plugin_placements = array('left', 'right', 'hide');
+    }
+
+    foreach ($plugin_placements as $plugin_placement) {
+        $plugins = serendipity_plugin_api::enum_plugins($plugin_placement);
+
+        if (!is_array($plugins)) {
+            continue;
+        }
+
+        $sort_idx = 0;
+        foreach ($plugins as $plugin_data) {
+            $plugin =& serendipity_plugin_api::load_plugin($plugin_data['name'], $plugin_data['authorid']);
+            $key    = urlencode($plugin_data['name']);
+            $is_plugin_owner    = ($plugin_data['authorid'] == $serendipity['authorid'] || $serendipity['serendipityUserlevel'] >= USERLEVEL_ADMIN);
+            $is_plugin_editable = ($is_plugin_owner || $plugin_data['authorid'] == '0');
+
+            if (!is_object($plugin)) {
+                $name = ERROR . ': ' . $plugin_data['name'];
+                $desc = ERROR . '!';
+            } else {
+                /* query for its name, description and configuration data */
+
+                $bag = new serendipity_property_bag;
+                $plugin->introspect($bag);
+
+                $name  = htmlspecialchars($bag->get('name'));
+                $desc  = htmlspecialchars($bag->get('description'));
+
+                $title = serendipity_plugin_api::get_plugin_title($plugin, '[' . $name . ']');
+
+                if ($bag->is_set('configuration') && ($plugin->protected === FALSE || $plugin_data['authorid'] == '0' || $plugin_data['authorid'] == $serendipity['authorid'] || $serendipity['serendipityUserlevel'] >= USERLEVEL_ADMIN)) {
+                    $can_configure = true;
+                } else {
+                    $can_configure = false;
+                }
+            }
+
+            if ($event_only) {
+                $place = '<input type="hidden" name="serendipity[placement][' . $plugin_data['name'] . ']" value="event" />';
+                $event_only_uri = '&amp;serendipity[event_plugin]=true';
+            } else {
+                $place = placement_box('serendipity[placement][' . $plugin_data['name'] . ']', $plugin_data['placement'], $is_plugin_editable);
+                $event_only_uri = '';
+            }
+
+            /* Only display UP/DOWN links if there's somewhere for the plugin to go */
+            if ($sort_idx == 0) {
+                $moveup   = '&nbsp;';
+            } else {
+                $moveup   = '<a href="?serendipity[adminModule]=plugins&amp;submit=move+up&amp;serendipity[plugin_to_move]=' . $key . $event_only_uri . '" style="border: 0"><img src="' . serendipity_getTemplateFile('admin/img/uparrow.png') .'" height="16" width="16" border="0" alt="' . UP . '" /></a>';
+            }
+
+            if ($sort_idx == (count($plugins)-1)) {
+                $movedown = '&nbsp;';
+            } else {
+                $movedown = ($moveup != '' ? '&nbsp;' : '') . '<a href="?serendipity[adminModule]=plugins&amp;submit=move+down&serendipity[plugin_to_move]=' . $key . $event_only_uri . '" style="border: 0"><img src="' . serendipity_getTemplateFile('admin/img/downarrow.png') . '" height="16" width="16" alt="'. DOWN .'" border="0" /></a>';
+            }
+?>
+            <tr>
+                <td style="border-bottom: 1px solid #000000">
+                    <div>
+                    <?php if ($is_plugin_editable) { ?>
+                        <input type="checkbox" name="serendipity[plugin_to_remove][]" value="<?php echo $plugin_data['name']; ?>" />
+                    <?php } else { ?>
+                        &nbsp;
+                    <?php } ?>
+                    </div>
+                </td>
+                <td style="border-bottom: 1px solid #000000" width="16">
+                <?php if ( $can_configure ) { ?>
+                    <a href="?serendipity[adminModule]=plugins&amp;serendipity[plugin_to_conf]=<?php echo $key ?>"><img src="<?php echo serendipity_getTemplateFile('admin/img/configure.png') ?>" style="border: 0; vertical-align: bottom;"></a>
+                <?php } else { ?>
+                    &nbsp;
+                <?php } ?>
+                </td>
+                <td style="border-bottom: 1px solid #000000"><strong>
+                <?php if ( $can_configure ) { ?>
+                    <a href="?serendipity[adminModule]=plugins&amp;serendipity[plugin_to_conf]=<?php echo $key ?>"><?php echo $title; ?></a>
+                <?php } else { ?>
+                    <?php echo $title; ?>
+                <?php } ?></strong><br />
+                    <div style="font-size: 8pt"><?php echo $desc; ?></div>
+                </td>
+                <td style="border-bottom: 1px solid #000000" nowrap="nowrap"><?php ownership($plugin_data['authorid'], $plugin_data['name'], $is_plugin_owner); ?></td>
+            <?php if ( !$event_only ) { ?>
+                <td style="border-bottom: 1px solid #000000" nowrap="nowrap"><?php echo $place ?></td>
+            <?php } ?>
+                <td style="border-bottom: 1px solid #000000"><?php echo $moveup ?></td>
+                <td style="border-bottom: 1px solid #000000"><?php echo $movedown ?></td>
+            </tr>
+<?php
+            $sort_idx++;
+        }
+    }
+?>
+        </table>
+        <br />
+        <div>
+            <input type="submit" name="REMOVE" title="<?php echo REMOVE_TICKED_PLUGINS; ?>"  value="<?php echo DELETE; ?>" class="serendipityPrettyButton" />
+            <input type="submit" name="SAVE"   title="<?php echo SAVE_CHANGES_TO_LAYOUT; ?>" value="<?php echo SAVE; ?>" class="serendipityPrettyButton" />
+        </div>
+</form>
+<?php
+}
+
+function ownership($authorid, $name, $is_plugin_owner = false) {
+    global $serendipity;
+
+    static $users = array();
+    if (empty($users)) {
+        $users = serendipity_fetchUsers();
+    }
+
+    if ($is_plugin_owner) {
+?>
+<select name="serendipity[ownership][<?php echo $name; ?>]">
+    <option value="0"><?php echo ALL_AUTHORS; ?></option>
+<?php
+    }
+
+    foreach($users AS $user) {
+        if (!$is_plugin_owner && $user['authorid'] == $authorid) {
+            $realname = htmlspecialchars($user['realname']);
+        } elseif ($is_plugin_owner) {
+?>
+    <option value="<?php echo $user['authorid']; ?>"<?php echo ($user['authorid'] == $authorid ? ' selected="selected"' : ''); ?>><?php echo htmlspecialchars($user['realname']); ?></option>
+<?php
+        }
+    }
+
+    if ($is_plugin_owner) {
+?>
+</select>
+<?php
+    } else {
+        echo (empty($username) ? ALL_AUTHORS : $username);
+    }
+}
+
+function placement_box($name, $val, $is_plugin_editable = false)
+{
+    static $opts = array(
+                    'left'  => LEFT,
+                    'right' => RIGHT,
+                    'hide'  => HIDDEN
+        );
+
+    $x = "\n<select name=\"$name\">\n";
+    foreach ($opts as $k => $v) {
+        if (!$is_plugin_editable && $k == 'hide') {
+            continue;
+        }
+
+        $x .= "    <option value=\"$k\"" . ($k == $val ? ' selected="selected"' : '') . ">$v</option>\n";
+    }
+    return $x . "</select>\n";
+}
+
+if (isset($_GET['serendipity']['plugin_to_move']) && isset($_GET['submit'])) {
+    if (isset($_GET['serendipity']['event_plugin'])) {
+        $plugins = serendipity_plugin_api::enum_plugins('event', false);
+    } else {
+        $plugins = serendipity_plugin_api::enum_plugins('event', true);
+    }
+
+    /* Renumber the sort order to be certain that one actually exists
+        Also look for the one we're going to move */
+    $idx_to_move = -1;
+    for($idx = 0; $idx < count($plugins); $idx++) {
+        $plugins[$idx]['sort_order'] = $idx;
+
+        if ($plugins[$idx]['name'] == $_GET['serendipity']['plugin_to_move']) {
+            $idx_to_move = $idx;
+        }
+    }
+
+    /* If idx_to_move is still -1 then we never found it (shouldn't happen under normal conditions)
+        Also make sure the swaping idx is around */
+    if ($idx_to_move >= 0 && (($_GET['submit'] == 'move down' && $idx_to_move < (count($plugins)-1)) || ($_GET['submit'] == 'move up' && $idx_to_move > 0))) {
+
+        /* Swap the one were moving with the one that's in the spot we're moving to */
+        $tmp = $plugins[$idx_to_move]['sort_order'];
+
+        $plugins[$idx_to_move]['sort_order'] = (int)$plugins[$idx_to_move + ($_GET['submit'] == 'move down' ? 1 : -1)]['sort_order'];
+        $plugins[$idx_to_move + ($_GET['submit'] == 'move down' ? 1 : -1)]['sort_order'] = (int)$tmp;
+
+        /* Update table */
+        foreach($plugins as $plugin) {
+            $key = serendipity_db_escape_string($plugin['name']);
+            serendipity_db_query("UPDATE {$serendipity['dbPrefix']}plugins SET sort_order = {$plugin['sort_order']} WHERE name='$key'");
+        }
+    }
+
+    /* TODO: Moving The first Right oriented plugin up,
+            or the last left oriented plugin down
+            should not be displayed to the user as an option.
+            It's a behavior which really has no meaning. */
+}
+
+if (isset($_GET['serendipity']['plugin_to_conf'])) {
+    /* configure a specific instance */
+    $plugin =& serendipity_plugin_api::load_plugin($_GET['serendipity']['plugin_to_conf']);
+
+    if (!($plugin->protected === FALSE || $plugin->serendipity_owner == '0' || $plugin->serendipity_owner == $serendipity['authorid'] || $serendipity['serendipityUserlevel'] >= USERLEVEL_ADMIN)) {
+        return;
+    }
+
+    $bag  = new serendipity_property_bag;
+    $plugin->introspect($bag);
+    $name = htmlspecialchars($bag->get('name'));
+    $desc = htmlspecialchars($bag->get('description'));
+
+    $config_names = $bag->get('configuration');
+
+    if (isset($_POST['SAVECONF'])) {
+        /* enum properties and set their values */
+
+        foreach ($config_names as $config_item) {
+            $cbag = new serendipity_property_bag;
+            if ($plugin->introspect_config_item($config_item, $cbag)) {
+                $plugin->set_config($config_item, $_POST['serendipity']['plugin'][$config_item]);
+            }
+        }
+
+        $plugin->cleanup();
+    }
+?>
+
+<?php if ( isset($_POST['SAVECONF']) ) { ?>
+    <div class="serendipityAdminMsgSuccess"><?php echo DONE .': '. sprintf(SETTINGS_SAVED_AT, serendipity_strftime('%T')); ?></div>
+<?php } ?>
+
+<form method="post" name="serendipityPluginConfigure">
+    <table cellpadding="5" style="border: 1px dashed" width="90%" align="center">
+        <tr>
+            <th width="100"><?php echo NAME; ?></th>
+            <td><?php echo $name; ?></td>
+        </tr>
+
+        <tr>
+            <th><?php echo DESCRIPTION; ?></th>
+            <td><?php echo $desc; ?></td>
+        </tr>
+    </table>
+<br />
+    <table border="0" cellspacing="0" cellpadding="3" width="100%">
+<?php
+    foreach ($config_names as $config_item) {
+        $cbag = new serendipity_property_bag;
+        $plugin->introspect_config_item($config_item, $cbag);
+
+        $cname      = htmlspecialchars($cbag->get('name'));
+        $cdesc      = htmlspecialchars($cbag->get('description'));
+        $value      = $plugin->get_config($config_item, 'unset');
+        $lang_direction = htmlspecialchars($cbag->get('lang_direction'));
+
+        if (empty($lang_direction)) {
+            $lang_direction = LANG_DIRECTION;
+        }
+
+        /* Apparently no value was set for this config item */
+        if ($value === 'unset') {
+            /* Try and the default value for the config item */
+            $value = $cbag->get('default');
+
+            /* Still, we don't have a value, try and get (bool)false - from an old plugin */
+            if ($value === '') {
+                $value = $plugin->get_config($config_item, false, true);
+            }
+        }
+        $hvalue   = (isset($_POST['serendipity']['plugin'][$config_item]) ? htmlspecialchars($_POST['serendipity']['plugin'][$config_item]) : htmlspecialchars($value));
+        $radio    = array();
+        $select   = array();
+        $per_row  = null;
+
+        switch ($cbag->get('type')) {
+            case 'seperator':
+?>
+        <tr>
+            <td colspan="2"><hr noshade="noshade" size="1" /></td>
+        </tr>
+<?php
+                break;
+
+            case 'select':
+                $select = $cbag->get('select_values');
+?>
+        <tr>
+            <td style="border-bottom: 1px solid #000000; vertical-align: top"><strong><?php echo $cname; ?></strong>
+<?php
+    if ($cdesc != '') {
+?>
+                <br><span  style="color: #5E7A94; font-size: 8pt;">&nbsp;<?php echo $cdesc; ?></span>
+<?php } ?>
+            </td>
+            <td style="border-bottom: 1px solid #000000; vertical-align: middle" width="250">
+                <div>
+                    <select class="direction_<?php echo $lang_direction; ?>" name="serendipity[plugin][<?php echo $config_item; ?>]">
+<?php
+                foreach($select AS $select_value => $select_desc) {
+                    $id = htmlspecialchars($config_item . $select_value);
+?>
+                        <option value="<?php echo $select_value; ?>" <?php echo ($select_value == $hvalue ? 'selected="selected"' : ''); ?> title="<?php echo htmlspecialchars($select_desc); ?>" />
+                            <?php echo htmlspecialchars($select_desc); ?>
+                        </option>
+<?php
+                }
+?>
+                    </select>
+                </div>
+            </td>
+        </tr>
+<?php
+                break;
+
+            case 'tristate':
+                $per_row = 3;
+                $radio['value'][] = 'default';
+                $radio['desc'][]  = USE_DEFAULT;
+
+            case 'boolean':
+                $radio['value'][] = 'true';
+                $radio['desc'][]  = YES;
+
+                $radio['value'][] = 'false';
+                $radio['desc'][]  = NO;
+
+           case 'radio':
+                if (!count($radio) > 0) {
+                    $radio = $cbag->get('radio');
+                }
+
+                if (empty($per_row)) {
+                    $per_row = $cbag->get('radio_per_row');
+                    if (empty($per_row)) {
+                        $per_row = 2;
+                    }
+                }
+?>
+        <tr>
+            <td style="border-bottom: 1px solid #000000; vertical-align: top"><strong><?php echo $cname; ?></strong>
+<?php
+                if ($cdesc != '') {
+?>
+                <br /><span  style="color: #5E7A94; font-size: 8pt;">&nbsp;<?php echo $cdesc; ?></span>
+<?php
+                }
+?>
+            </td>
+            <td style="border-bottom: 1px solid #000000; vertical-align: middle;" width="250">
+<?php
+                $counter = 0;
+                foreach($radio['value'] AS $radio_index => $radio_value) {
+                    $id = htmlspecialchars($config_item . $radio_value);
+                    $counter++;
+                    $checked = "";
+
+                    if ($radio_value == 'true' && ($hvalue === '1' || $hvalue === 'true')) {
+                        $checked = " checked";
+                    } elseif ($radio_value == 'false' && ($hvalue === '' || $hvalue === 'false')) {
+                        $checked = " checked";
+                    } elseif ($radio_value == $hvalue) {
+                        $checked = " checked";
+                    }
+
+                    if ($counter == 1) {
+?>
+                <div>
+<?php
+                    }
+?>
+                    <input class="direction_<?php echo $lang_direction; ?>" type="radio" id="serendipity_plugin_<?php echo $id; ?>" name="serendipity[plugin][<?php echo $config_item; ?>]" value="<?php echo $radio_value; ?>" <?php echo $checked ?> title="<?php echo htmlspecialchars($radio['desc'][$radio_index]); ?>" />
+                        <label for="serendipity_plugin_<?php echo $id; ?>"><?php echo htmlspecialchars($radio['desc'][$radio_index]); ?></label>
+<?php
+                    if ($counter == $per_row) {
+                        $counter = 0;
+?>
+                </div>
+<?php
+                    }
+                }
+?>
+            </td>
+        </tr>
+<?php
+                break;
+
+            case 'string':
+?>
+        <tr>
+            <td style="border-bottom: 1px solid #000000">
+                    <strong><?php echo $cname; ?></strong>
+                    <br><span style="color: #5E7A94; font-size: 8pt;">&nbsp;<?php echo $cdesc; ?></span>
+            </td>
+            <td style="border-bottom: 1px solid #000000" width="250">
+                <div>
+                    <input class="direction_<?php echo $lang_direction; ?>" type="text" name="serendipity[plugin][<?php echo $config_item; ?>]" value="<?php echo $hvalue; ?>" size="30" />
+                </div>
+            </td>
+        </tr>
+<?php
+                break;
+
+            case 'html':
+            case 'text':
+?>
+        <tr>
+            <td colspan="2"><strong><?php echo $cname; ?></strong>
+                &nbsp;<span style="color: #5E7A94; font-size: 8pt;">&nbsp;<?php echo $cdesc; ?></span>
+            </td>
+        </tr>
+
+        <tr>
+            <td colspan="2">
+                <div>
+                    <textarea class="direction_<?php echo $lang_direction; ?>" style="width: 100%" id="nugget" name="serendipity[plugin][<?php echo $config_item; ?>]" rows="20" cols="80"><?php echo $hvalue; ?></textarea>
+                </div>
+            </td>
+        </tr>
+<?php
+                if ($cbag->get('type') == 'html') {
+                    serendipity_emit_htmlarea_code('nugget', 'nugget');
+                }
+                break;
+
+            case 'content':
+                ?><tr><td colspan="2"><?php echo $cbag->get('default'); ?></td></tr><?php
+                break;
+
+            case 'hidden':
+                ?><tr><td colspan="2"><input class="direction_<?php echo $lang_direction; ?>" type="hidden" name="serendipity[plugin][<?php echo $config_item; ?>]" value="<?php echo $cbag->get('value'); ?>" /></td></tr><?php
+                break;
+        }
+    }
+?>
+    </table>
+<br />
+    <div style="padding-left: 20px">
+        <input type="submit" name="SAVECONF" value="<?php echo SAVE; ?>" class="serendipityPrettyButton" />
+    </div>
+<?php
+    if (method_exists($plugin, 'example') ) {
+?>
+    <div>
+        <?php echo $plugin->example() ?>
+    </div>
+<?php
+    }
+?>
+    </div>
+</form>
+<?php
+
+} elseif ( $serendipity['GET']['adminAction'] == 'addnew' ) {
+?>
+<?php if ( $serendipity['GET']['type'] == 'event' ) { ?>
+    <h2><?php echo EVENT_PLUGINS ?></h2>
+<?php } else { ?>
+    <h2><?php echo SIDEBAR_PLUGINS ?></h2>
+<?php } ?>
+<?php echo SELECT_A_PLUGIN_TO_ADD; ?>
+<br />
+<br />
+<?php
+    $foreignPlugins = array();
+    serendipity_plugin_api::hook_event('backend_plugins_fetchlist', $foreignPlugins);
+?>
+<table cellspacing="0" cellpadding="0" border="0" width="100%">
+    <tr>
+        <td><strong>Plugin</strong></td>
+        <td width="100" align="center"><strong>Action</strong></td>
+    </tr>
+<?php
+    if (count($foreignPlugins) > 0) {
+        $pluginstack = $foreignPlugins['pluginstack'];
+        $errorstack  = $foreignPlugins['errorstack'];
+    } else {
+        $plugins = serendipity_plugin_api::get_installed_plugins();
+
+        $errorstack = $pluginstack = array();
+        $classes = serendipity_plugin_api::enum_plugin_classes(($serendipity['GET']['type'] == 'event'));
+        foreach ($classes as $class_data) {
+            $plugin =& serendipity_plugin_api::load_plugin($class_data['name'], null, $class_data['pluginPath']);
+            if (is_object($plugin)) {
+                $bag = new serendipity_property_bag;
+                $plugin->introspect($bag);
+                $pluginstack[] = array('plugin_class'   => $class_data['name'],
+                                       'class_name'     => get_class($plugin),
+                                       'name'           => $bag->get('name'),
+                                       'desc'           => $bag->get('description'),
+                                       'installable'    => !($bag->get('stackable') === false && in_array($class_data['name'], $plugins)),
+                                       'author'         => $bag->get('author'),
+                                       'version'        => $bag->get('version'),
+                                       'requirements'   => $bag->get('requirements'),
+                                       'website'        => $bag->get('website'),
+                                       'pluginPath'     => $class_data['pluginPath']);
+            } else {
+                $errorstack[] = $class_data['name'];
+            }
+        }
+    }
+
+    usort($pluginstack, 'serendipity_pluginListSort');
+    foreach($errorstack as $e_idx => $e_name) {
+        echo ERROR . ': ' . $e_name . '<br />';
+    }
+?>
+<?php
+    foreach ($pluginstack as $plug) {
+        $jsLine = " onmouseout=\"document.getElementById('serendipity_plugin_". $plug['class_name'] ."').className='';\"";
+        $jsLine .= " onmouseover=\"document.getElementById('serendipity_plugin_". $plug['class_name'] ."').className='serendipity_admin_list_item_uneven';\"";
+
+        $pluginInfo = $notice = array();
+        if (!empty($plug['author'])) {
+            $pluginInfo[] = AUTHOR  . ': ' . $plug['author'];
+        }
+
+        if (!empty($plug['version'])) {
+            $pluginInfo[] = VERSION  . ': ' . $plug['version'];
+        }
+
+        if (!empty($plug['upgrade_version'])) {
+            $pluginInfo[] = sprintf(UPGRADE_TO_VERSION, $plug['upgrade_version']);
+        }
+
+        if (!isset($plug['customURI'])) {
+            $plug['customURI'] = '';
+        }
+
+        if ( !empty($plug['requirements']['serendipity']) && version_compare($plug['requirements']['serendipity'], serendipity_getCoreVersion($serendipity['version']), '>') ) {
+            $notice['requirements_failures'][] = 's9y ' . $plug['requirements']['serendipity'];
+        }
+
+        if ( !empty($plug['requirements']['serendipity']) && version_compare($plug['requirements']['php'], phpversion(), '>') ) {
+            $notice['requirements_failures'][] = 'PHP ' . $plug['requirements']['php'];
+        }
+
+        /* Enable after Smarty 2.6.7 upgrade.
+         * TODO: How can we get current Smarty version here? $smarty is not created!
+        if ( !empty($plug['requirements']['smarty']) && version_compare($plug['requirements']['smarty'], '2.6.7', '>') ) {
+            $notice['requirements_failures'][] = 'Smarty: ' . $plug['requirements']['smarty'];
+        }
+        */
+
+        if (count($notice['requirements_failures']) > 0) {
+            $plug['requirements_fail'] = true;
+        }
+
+?>
+    <tr id="serendipity_plugin_<?php echo $plug['class_name']; ?>">
+        <td colspan="2" <?php echo $jsLine ?>>
+            <table width="100%" cellpadding="3" cellspacing="0" border="0">
+                <tr>
+                    <td><strong><?php echo $plug['name'] ?></strong></td>
+                    <td width="100" align="center" valign="middle" rowspan="3">
+                        <?php if ( $plug['requirements_fail'] == true ) { ?>
+                            <span style="color: #cccccc"><?php printf(UNMET_REQUIREMENTS, implode(', ', $notice['requirements_failures'])); ?></span>
+                        <?php } elseif ( $plug['upgradable'] == true ) { ?>
+                            <a href="?serendipity[adminModule]=plugins&amp;serendipity[pluginPath]=<?php echo $plug['pluginPath']; ?>&amp;serendipity[install_plugin]=<?php echo $plug['plugin_class'] . $plug['customURI'] ?>"><img src="<?php echo serendipity_getTemplateFile('admin/img/upgrade_now.png') ?>" title="<?php echo UPGRADE ?>" alt="<?php echo UPGRADE ?>" border="0"></a>
+                        <?php } elseif ($plug['installable'] == true) { ?>
+                            <a href="?serendipity[adminModule]=plugins&amp;serendipity[pluginPath]=<?php echo $plug['pluginPath']; ?>&amp;serendipity[install_plugin]=<?php echo $plug['plugin_class'] . $plug['customURI'] ?>"><img src="<?php echo serendipity_getTemplateFile('admin/img/install_now.png') ?>" title="<?php echo INSTALL ?>" alt="<?php echo INSTALL ?>" border="0"></a>
+                        <?php } else { ?>
+                            <span style="color: #cccccc"><?php echo ALREADY_INSTALLED ?></span>
+                        <?php } ?>
+                    </td>
+                </tr>
+                <tr>
+                    <td style="padding-left: 10px"><?php echo $plug['desc'] ?></td>
+                </tr>
+<?php if (count($pluginInfo) > 0) { ?>
+                <tr>
+                    <td style="padding-left: 10px; font-size: x-small"><?php echo implode('; ', $pluginInfo); ?></td>
+                </tr>
+<?php } ?>
+            </table>
+        </td>
+    </tr>
+<?php
+    }
+?>
+</table>
+
+<?php
+} else {
+    /* show general plugin list */
+
+    if (isset($_POST['SAVE']) && isset($_POST['serendipity']['placement'])) {
+        foreach ($_POST['serendipity']['placement'] as $plugin_name => $placement) {
+            serendipity_plugin_api::update_plugin_placement(
+                addslashes($plugin_name),
+                addslashes($placement)
+            );
+
+            serendipity_plugin_api::update_plugin_owner(
+                addslashes($plugin_name),
+                addslashes($_POST['serendipity']['ownership'][$plugin_name])
+            );
+        }
+    }
+
+    if (isset($serendipity['GET']['install_plugin'])) {
+        $authorid = $serendipity['authorid'];
+        if ($serendipity['serendipityUserlevel'] >= USERLEVEL_ADMIN) {
+            $authorid = '0';
+        }
+
+        $fetchplugin_data = array('GET'     => &$serendipity['GET'],
+                                  'install' => true);
+        serendipity_plugin_api::hook_event('backend_plugins_fetchplugin', $fetchplugin_data);
+
+        if ($fetchplugin_data['install']) {
+            $inst = serendipity_plugin_api::create_plugin_instance($serendipity['GET']['install_plugin'], null, (serendipity_plugin_api::is_event_plugin($serendipity['GET']['install_plugin']) ? 'event': 'right'), $authorid, serendipity_db_escape_string($serendipity['GET']['pluginPath']));
+
+            /* Load the new plugin */
+            $plugin = &serendipity_plugin_api::load_plugin($inst);
+            $bag  = new serendipity_property_bag;
+            $plugin->introspect($bag);
+
+            if ($bag->is_set('configuration')) {
+                /* Only play with the plugin if there is something to play with */
+                echo '<script type="text/javascript">location.href = \'' . $serendipity['baseurl'] . '?serendipity[adminModule]=plugins&serendipity[plugin_to_conf]=' . $inst . '\';</script>';
+                die();
+            } else {
+                /* If no config is available, redirect to plugin overview, because we do not want that a user can install the plugin a second time via accidental browser refresh */
+                echo '<script type="text/javascript">location.href = \'' . $serendipity['baseurl'] . '?serendipity[adminModule]=plugins\';</script>';
+                die();
+            }
+        }
+    }
+
+    if (isset($_POST['REMOVE'])) {
+        if (is_array($_POST['serendipity']['plugin_to_remove'])) { 
+            foreach ($_POST['serendipity']['plugin_to_remove'] as $key) {
+                $plugin =& serendipity_plugin_api::load_plugin($key);
+    
+                if ($plugin->serendipity_owner == '0' || $plugin->serendipity_owner == $serendipity['authorid'] || $serendipity['serendipityUserlevel'] >= USERLEVEL_ADMIN) {
+                    serendipity_plugin_api::remove_plugin_instance($key);
+                }
+            }
+        }
+    }
+?>
+    <?php echo BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS ?>
+    <br />
+    <br />
+
+    <h3><?php echo SIDEBAR_PLUGINS ?></h3>
+    <a href="?serendipity[adminModule]=plugins&amp;serendipity[adminAction]=addnew" class="serendipityIconLink"><img src="<?php echo serendipity_getTemplateFile('admin/img/install.png') ?>" style="border: 0px none ; vertical-align: middle; display: inline;" alt=""><?php echo sprintf(CLICK_HERE_TO_INSTALL_PLUGIN, SIDEBAR_PLUGIN) ?></a>
+    <?php serendipity_plugin_api::hook_event('backend_plugins_sidebar_header', $serendipity); ?>
+    <?php show_plugins(false); ?>
+
+    <br />
+    <br />
+
+    <h3><?php echo EVENT_PLUGINS ?></h3>
+    <a href="?serendipity[adminModule]=plugins&amp;serendipity[adminAction]=addnew&amp;serendipity[type]=event" class="serendipityIconLink"><img src="<?php echo serendipity_getTemplateFile('admin/img/install.png') ?>" style="border: 0px none ; vertical-align: middle; display: inline;" alt=""><?php echo sprintf(CLICK_HERE_TO_INSTALL_PLUGIN, EVENT_PLUGIN) ?></a>
+    <?php serendipity_plugin_api::hook_event('backend_plugins_event_header', $serendipity); ?>
+    <?php show_plugins(true); ?>
+
+<?php
+}
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/templates.inc.php b/include/admin/templates.inc.php
new file mode 100644 (file)
index 0000000..2587edd
--- /dev/null
@@ -0,0 +1,91 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+if (IN_serendipity !== true) {
+    die ("Don't hack!");
+}
+
+if ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF) {
+    return;
+}
+
+if ($serendipity['GET']['adminAction'] == 'install' ) {
+    $themeInfo = serendipity_fetchTemplateInfo($serendipity['GET']['theme']);
+
+    serendipity_set_config_var('template', $serendipity['GET']['theme']);
+    serendipity_set_config_var('template_engine', isset($themeInfo['engine']) ? $themeInfo['engine'] : 'default');
+
+    echo '<div class="serendipityAdminMsgSuccess">'. sprintf(TEMPLATE_SET, $serendipity['GET']['theme']) .'</div>';
+}
+?>
+
+<?php
+    if ( @file_exists($serendipity['serendipityPath'] . $serendipity['templatePath'] . $serendipity['template'] .'/layout.php') ) {
+        echo '<div class="serendipityAdminMsgNote">'. WARNING_TEMPLATE_DEPRECATED .'</div>';
+    }
+?>
+
+
+<?php echo SELECT_TEMPLATE; ?>
+<?php
+    $i = 0;
+    foreach (serendipity_fetchTemplates() as $theme) {
+        $i++;
+        $info = serendipity_fetchTemplateInfo($theme);
+
+        /* Sorry, but we don't display engines */
+        if ( strtolower($info['engine']) == 'yes' ) {
+            continue;
+        }
+
+
+        if (file_exists($serendipity['serendipityPath'] . $serendipity['templatePath'] . $theme . '/preview.png')) {
+            $preview = '<img src="' . $serendipity['templatePath'] . $theme . '/preview.png" width="100" style="border: 1px #000000 solid" />';
+        } else {
+            $preview = '&nbsp;';
+        }
+
+        $unmetRequirements = array();
+        if ( isset($info['require serendipity']) && version_compare($info['require serendipity'], serendipity_getCoreVersion($serendipity['version']), '>') ) {
+            $unmetRequirements[] = 'Serendipity '. $info['require serendipity'];
+        }
+
+        /* TODO: Smarty versioncheck */
+
+        $class = (($i % 2) ? 'even' : 'uneven');
+
+?>
+<div class="serendipity_admin_list_item serendipity_admin_list_item_<?php echo $class ?>">
+    <table width="100%" id="serendipity_theme_<?php echo $theme; ?>">
+        <tr>
+            <td colspan="2"><strong><?php echo $info['name']; ?></strong></td>
+            <td valign="middle" align="center" width="70" rowspan="2">
+<?php
+    if ( $serendipity['template'] != $theme ) {
+        if ( !sizeof($unmetRequirements) ) {
+?>
+            <a href="?serendipity[adminModule]=templates&amp;serendipity[adminAction]=install&amp;serendipity[theme]=<?php echo $theme ?>"><img src="<?php echo serendipity_getTemplateFile('admin/img/install_now.png') ?>" alt="<?php echo SET_AS_TEMPLATE ?>" title="<?php echo SET_AS_TEMPLATE ?>" border="0" /></a>
+<?php   } else { ?>
+        <span style="color: #cccccc"><?php echo sprintf(UNMET_REQUIREMENTS, implode(', ', $unmetRequirements)); ?></span>
+<?php
+        }
+    } ?>
+            </td>
+        </tr>
+
+        <tr>
+            <td width="100" style="padding-left: 10px"><?php echo $preview; ?></td>
+            <td valign="top">
+                <?php echo AUTHOR;       ?>: <?php echo $info['author'];?><br />
+                <?php echo LAST_UPDATED; ?>: <?php echo $info['date'];  ?>
+            </td>
+        </tr>
+    </table>
+</div>
+<?php
+    }
+?>
+<?php
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/admin/upgrader.inc.php b/include/admin/upgrader.inc.php
new file mode 100644 (file)
index 0000000..ede20b1
--- /dev/null
@@ -0,0 +1,336 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+require_once(S9Y_INCLUDE_PATH . 'include/functions_installer.inc.php');
+require_once(S9Y_INCLUDE_PATH . 'include/functions_upgrader.inc.php');
+
+define('S9Y_U_ERROR', -1);
+define('S9Y_U_WARNING', 0);
+define('S9Y_U_SUCCESS', 1);
+
+function serendipity_upgraderResultDiagnose($result, $s) {
+    global $errorCount;
+
+    if ( $result === S9Y_U_SUCCESS ) {
+        return '<span style="color: green; font-weight: bold">'. $s .'</span>';
+    }
+
+    if ( $result === S9Y_U_WARNING ) {
+        return '<span style="color: orange; font-weight: bold">'. $s .'</span>';
+    }
+
+    if ( $result === S9Y_U_ERROR ) {
+        $errorCount++;
+        return '<span style="color: red; font-weight: bold">'. $s .'</span>';
+    }
+}
+
+// Setting this value to 'FALSE' is recommended only for SHARED BLOG INSTALLATIONS. This enforces all shared blogs with a common
+// codebase to only allow upgrading, no bypassing and thus causing instabilities.
+// This variable can also be set as $serendipity['UpgraderShowAbort'] inside serendipity_config_local.inc.php to prevent
+// your setting being changed when updating serendipity in first place.
+$showAbort  = (isset($serendipity['UpgraderShowAbort']) ? $serendipity['UpgraderShowAbort'] : true);
+
+$abortLoc   = $serendipity['serendipityHTTPPath'] . 'serendipity_admin.php?serendipity[action]=ignore';
+$upgradeLoc = $serendipity['serendipityHTTPPath'] . 'serendipity_admin.php?serendipity[action]=upgrade';
+
+/* Functions which needs to be run if installed version is equal or lower */
+$tasks = array(array('version'   => '0.5.1',
+                     'function'  => 'serendipity_syncThumbs',
+                     'title'     => 'Image Sync',
+                     'desc'      => 'Version 0.5.1 introduces image sync with the database'. "\n" .
+                                    'With your permission I would like to perform the image sync'),
+
+               array('version'   => '0.6.5',
+                     'function'  => 'serendipity_rebuildCategoryTree',
+                     'title'     => 'Nested subcategories, post to multiple categories',
+                     'desc'      => 'This update will update the categories table of your database and update the relations from entries to categories.'. "\n" .
+                                    'This is a possibly dangerous task to perform, so <strong style="color: red">make sure you have a backup of your database!</strong>'),
+
+               array('version'   => '0.6.8',
+                     'function'  => 'serendipity_installFiles',
+                     'title'     => 'Update of .htaccess file',
+                     'desc'      => 'Changes were made to the .htaccess file, you need to regenerate it'),
+
+               array('version'   => '0.6.10',
+                     'functon'   => 'serendipity_installFiles',
+                     'title'     => 'Update of .htaccess file',
+                     'desc'      => 'Changes were made to the .htaccess file, you need to regenerate it'),
+
+               array('version'   => '0.6.12',
+                     'function'  => 'serendipity_installFiles',
+                     'title'     => 'Update of .htaccess file',
+                     'desc'      => 'Changes were made to the .htaccess file, you need to regenerate it'),
+
+               array('version'   => '0.8-alpha3',
+                     'function'  => 'serendipity_removeFiles',
+                     'title'     => 'Removal of obsolete files',
+                     'arguments' => array($obsolete_files),
+                     'desc'      => 'The directory structure has been reworked. The following files will be moved to a folder called "backup". If you made manual changes to those files, be sure to read the file docs/CHANGED_FILES to re-implement your changes.<br /><div style="font-size: x-small; margin: 15px">' . implode(', ', $obsolete_files) . '</div>'),
+
+               array('version'   => '0.8-alpha4',
+                     'function'  => 'serendipity_removeFiles',
+                     'title'     => 'Removal of serendipity_entries.php',
+                     'arguments' => array(array('serendipity_entries.php')),
+                     'desc'      => 'In order to implement the new administration, we have to remove the leftovers'),
+
+               array('version'   => '0.8-alpha4',
+                     'function'  => 'serendipity_installFiles',
+                     'title'     => 'Update of .htaccess file',
+                     'desc'      => 'In order to implement the new administration, changes were made to the .htaccess file, you need to regenerate it'),
+
+               array('version'   => '0.8-alpha7',
+                     'function'  => 'serendipity_removeObsoleteVars',
+                     'title'     => 'Removal of obsolete configuration variables',
+                     'desc'      => 'Because of the new configuration parsing methods, some database variables are now only stored in serendipity_config_local.inc.php. Those obsolete variables will be removed from the database'),
+
+               array('version'   => '0.8-alpha8',
+                     'function'  => array('serendipity_plugin_api', 'create_plugin_instance'),
+                     'arguments' => array('serendipity_event_browsercompatibility', null, 'event'),
+                     'title'     => 'Plugin for Browser Compatibility',
+                     'desc'      => 'Includes some CSS-behaviours and other functions to maximize browser compatibility'),
+
+               array('version'   => '0.8-alpha9',
+                     'function'  => 'serendipity_installFiles',
+                     'title'     => 'Update of .htaccess file',
+                     'desc'      => 'In order to implement author views, changes were made to the .htaccess file, you need to regenerate it'),
+
+               array('version'   => '0.8-alpha11',
+                     'function'  => 'serendipity_installFiles',
+                     'title'     => 'Update of .htaccess file',
+                     'desc'      => 'In order to implement URL rewrite improvement, changes were made to the .htaccess file, you need to regenerate it'),
+
+               array('version'   => '0.8-alpha12',
+                     'type'      => 'TEMPLATE_NOTICE',
+                     'function'  => '',
+                     'title'     => '<b>TEMPLATE_NOTICE:</b> The template file "entries.tpl" has changed.',
+                     'desc'      => 'Authors can now have longer real names instead of only their loginnames. Those new fields need to be displayed in your Template, if you manually created one. Following variables were changes:
+                                     <b>{$entry.username}</b> =&gt; <b>{$entry.author}</b>
+                                     <b>{$entry.link_username}</b> =&gt; <b>{$entry.link_author}</b>
+                                     Those variables have been replaced in all bundled templates and those in our additional_themes repository.
+                                     ' . serendipity_upgraderResultDiagnose(S9Y_U_WARNING, 'Manual user interaction is required! This can NOT be done automatically!')),
+
+               array('version'   => '0.8-beta3',
+                     'function'  => 'serendipity_fixPlugins',
+                     'arguments' => array('markup_column_names'),
+                     'title'     => 'Configuration options of markup plugins',
+                     'desc'      => 'Because of the latest multilingual improvements in Serendipity, the database key names for certain configuration directives only found in markup plugins need to be renamed.<br />'
+                                    . 'This will be automatically handled by Serendipity for all internally bundled and external plugins. If you are using the external plugins "GeShi" and "Markdown", please make sure you will upgrade to their latest versions!<br />'
+                                    . 'We also advise that you check the plugin configuration of all your markup plugins (like emoticate, nl2br, s9ymarkup, bbcode) and see if the settings you made are all properly migrated.'),
+
+               array('version'   => '0.8-beta5',
+                     'function'  => 'serendipity_smarty_purge',
+                     'title'     => 'Clear Smarty compiled templates',
+                     'desc'      => 'Smarty has been upgraded to its latest stable version, and we therefore need to purge all compiled templates and cache'),
+);
+
+/* Fetch SQL files which needs to be run */
+$dir      = opendir(S9Y_INCLUDE_PATH . 'sql/');
+$tmpfiles = array();
+while (($file = readdir($dir)) !== false ) {
+    if (preg_match('@db_update_(.*)_(.*)_(.*).sql@', $file, $res)) {
+        list(, $verFrom, $verTo, $dbType) = $res;
+        if (version_compare($verFrom, $serendipity['versionInstalled']) >= 0) {
+            $tmpFiles[$verFrom][$dbType] = $file;
+        }
+    }
+}
+
+$sqlfiles = array();
+if (is_array($tmpFiles)) {
+    foreach ($tmpFiles as $version => $db) {
+        if (array_key_exists($serendipity['dbType'], $db) === false ) {
+            $sqlfiles[$version] = $db['mysql'];
+        } else {
+            $sqlfiles[$version] = $db[$serendipity['dbType']];
+        }
+    }
+}
+
+@uksort($sqlfiles, "strnatcasecmp");
+
+if ($serendipity['GET']['action'] == 'ignore') {
+    /* Todo: Don't know what to put here? */
+
+} elseif ($serendipity['GET']['action'] == 'upgrade') {
+
+    $errors = array();
+
+    /* Install SQL files */
+    foreach ($sqlfiles as $sqlfile) {
+        $sql = file_get_contents(S9Y_INCLUDE_PATH .'sql/'. $sqlfile);
+        $sql = str_replace('{PREFIX}', $serendipity['dbPrefix'], $sql);
+        preg_match_all("@(.*);@iUs", $sql, $res);
+        foreach ($res[0] as $sql) {
+            $r = serendipity_db_schema_import($sql);
+            if (is_string($r)) {
+                $errors[] = trim($r);
+            }
+        }
+    }
+
+    /* Call functions */
+    foreach ($tasks as $task) {
+        if (!empty($task['function']) && version_compare($serendipity['versionInstalled'], $task['version'], '<') ) {
+            if (is_callable($task['function'])) {
+                echo sprintf('Calling %s ...<br />', (is_array($task['function']) ? $task['function'][0] . '::'. $task['function'][1] : $task['function']));;
+
+                if (empty($task['arguments'])) {
+                    call_user_func($task['function']);
+                } else {
+                    call_user_func_array($task['function'], $task['arguments']);
+                }
+            } else {
+                $errors[] = 'Unable to call '. $task['function'];
+            }
+        }
+    }
+
+    if (sizeof($errors)) {
+        echo DIAGNOSTIC_ERROR . '<br /><br />';
+        echo '<span class="serendipityAdminMsgError">- ' . implode('<br />', $errors) . '</span><br /><br />';
+    }
+
+    /* I don't care what you told me, I will always nuke Smarty cache */
+    serendipity_smarty_purge();
+
+}
+
+if (($showAbort && $serendipity['GET']['action'] == 'ignore') || $serendipity['GET']['action'] == 'upgrade') {
+    $privateVariables = array();
+    if (isset($serendipity['UpgraderShowAbort'])) {
+        $privateVariables['UpgraderShowAbort'] = $serendipity['UpgraderShowAbort'];
+    }
+
+    $r = serendipity_updateLocalConfig(
+           $serendipity['dbName'],
+           $serendipity['dbPrefix'],
+           $serendipity['dbHost'],
+           $serendipity['dbUser'],
+           $serendipity['dbPass'],
+           $serendipity['dbType'],
+           $serendipity['dbPersistent'],
+           $privateVariables
+    );
+
+    if ($serendipity['GET']['action'] == 'ignore') {
+        echo SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED;
+    } elseif ($serendipity['GET']['action'] == 'upgrade') {
+        printf('<div class="serendipityAdminMsgSuccess">'. SERENDIPITY_UPGRADER_NOW_UPGRADED .'</div>', $serendipity['version']);
+    }
+    echo '<br />';
+    printf('<div align="center">'. SERENDIPITY_UPGRADER_RETURN_HERE .'</div>', '<a href="'. $serendipity['serendipityHTTPPath'] .'">', '</a>');
+    $_SESSION['serendipityAuthedUser'] = false;
+    @session_destroy();
+} else {
+    echo '<h2>' . SERENDIPITY_UPGRADER_WELCOME . '</h2>';
+    printf(SERENDIPITY_UPGRADER_PURPOSE . '<br />', $serendipity['versionInstalled']);
+    printf(SERENDIPITY_UPGRADER_WHY . '.', $serendipity['version']);
+    echo '<br />' . FIRST_WE_TAKE_A_LOOK  . '.';
+?>
+<br /><br />
+<div align="center"><?php printf(ERRORS_ARE_DISPLAYED_IN, serendipity_upgraderResultDiagnose(S9Y_U_ERROR, RED), serendipity_upgraderResultDiagnose(S9Y_U_WARNING, YELLOW), serendipity_upgraderResultDiagnose(S9Y_U_SUCCESS, GREEN)); ?>.<br />
+<?php
+    $errorCount = 0;
+    $showWritableNote = false;
+    $basedir = $serendipity['serendipityPath'];
+?>
+<div align="center">
+<table class="serendipity_admin_list_item serendipity_admin_list_item_even" width="90%" align="center">
+    <tr>
+        <td colspan="2" style="font-weight: bold"><?php echo PERMISSIONS ?></td>
+    </tr>
+    <tr>
+        <td><?php echo $basedir ?></td>
+        <td width="200"><?php
+            if ( is_writable($basedir) ) {
+                echo serendipity_upgraderResultDiagnose(S9Y_U_SUCCESS, WRITABLE);
+            } else {
+                echo serendipity_upgraderResultDiagnose(S9Y_U_ERROR, NOT_WRITABLE);
+                $showWritableNote = true;
+            }
+     ?></td>
+    </tr>
+    <tr>
+        <td><?php echo $basedir . PATH_SMARTY_COMPILE?></td>
+        <td width="200"><?php
+            if ( is_writable($basedir . PATH_SMARTY_COMPILE) ) {
+                echo serendipity_upgraderResultDiagnose(S9Y_U_SUCCESS, WRITABLE);
+            } else {
+                echo serendipity_upgraderResultDiagnose(S9Y_U_ERROR, NOT_WRITABLE);
+                $showWritableNote = true;
+            }
+     ?></td>
+    </tr>
+<?php if (is_dir($basedir . $serendipity['uploadHTTPPath'])) { ?>
+    <tr>
+        <td><?php echo $basedir . $serendipity['uploadHTTPPath']; ?></td>
+        <td width="200"><?php
+            if (is_writable($basedir . $serendipity['uploadHTTPPath'])) {
+                echo serendipity_upgraderResultDiagnose(S9Y_U_SUCCESS, WRITABLE);
+            } else {
+                echo serendipity_upgraderResultDiagnose(S9Y_U_ERROR, NOT_WRITABLE);
+                $showWritableNote = true;
+            }
+     ?></td>
+    </tr>
+<?php } ?>
+</table>
+</div>
+<?php if ($showWritableNote === true) { ?>
+    <div class="serendipityAdminMsgNote"><?php echo sprintf(PROBLEM_PERMISSIONS_HOWTO, 'chmod 1777') ?></div>
+<?php }
+
+    if ($errorCount > 0) { ?>
+    <div align="center">
+        <div class="serendipityAdminMsgError"><?php echo PROBLEM_DIAGNOSTIC ?></div>
+        <h2><a href="serendipity_admin.php"><?php echo RECHECK_INSTALLATION ?></a></h2>
+    </div>
+<?php }
+?>
+</div>
+
+<?php
+    if ($errorCount < 1) {
+        if (sizeof($sqlfiles) > 0) { ?>
+    <br />
+    <h3><?php printf(SERENDIPITY_UPGRADER_DATABASE_UPDATES, $serendipity['dbType']) ?>:</h3>
+<?php echo SERENDIPITY_UPGRADER_FOUND_SQL_FILES ?>:<br />
+<?php
+            foreach ($sqlfiles as $sqlfile) {
+                echo '<div style="padding-left: 5px"><strong>'. $sqlfile .'</strong></div>';
+            }
+        }
+?>
+    <br />
+
+    <h3><?php echo SERENDIPITY_UPGRADER_VERSION_SPECIFIC ?>:</h3>
+<?php
+        $taskCount = 0;
+
+        foreach ( $tasks as $task ) {
+            if (version_compare($serendipity['versionInstalled'], $task['version'], '<'))  {
+                echo '<div><strong>'. $task['version'] .' - '. $task['title'] .'</strong></div>';
+                echo '<div style="padding-left: 5px">'. nl2br($task['desc']) .'</div><br />';
+                $taskCount++;
+            }
+        }
+
+        if ($taskCount == 0) {
+            echo SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC;
+        }
+?>
+
+    <br /><br />
+    <hr noshade="noshade">
+<?php if ($taskCount > 0 || sizeof($sqlfiles) > 0) { ?>
+        <strong><?php echo SERENDIPITY_UPGRADER_PROCEED_QUESTION ?></strong>
+        <br /><br /><a href="<?php echo $upgradeLoc; ?>" class="serendipityPrettyButton"><?php echo SERENDIPITY_UPGRADER_PROCEED_DOIT ?></a> <?php if ($showAbort) { ?><a href="<?php echo $abortLoc; ?>" class="serendipityPrettyButton"><?php echo SERENDIPITY_UPGRADER_PROCEED_ABORT ?></a><?php } ?>
+<?php } else { ?>
+        <strong><?php echo SERENDIPITY_UPGRADER_NO_UPGRADES ?></strong>
+        <br /><br /><a href="<?php echo $abortLoc; ?>" class="serendipityPrettyButton"><?php echo SERENDIPITY_UPGRADER_CONSIDER_DONE ?></a>
+<?php }
+    }
+}
+?>
diff --git a/include/admin/users.inc.php b/include/admin/users.inc.php
new file mode 100644 (file)
index 0000000..a72300b
--- /dev/null
@@ -0,0 +1,190 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+if (IN_serendipity !== true) {
+    die ('Don\'t hack!');
+}
+
+if ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF) {
+    return;
+}
+
+require_once(S9Y_INCLUDE_PATH . 'include/functions_installer.inc.php');
+
+/* Delete a user */
+if (isset($_POST['DELETE_YES'])) {
+    $user = serendipity_fetchUsers($serendipity['POST']['user']);
+    if ($user[0]['userlevel'] >= $serendipity['serendipityUserlevel'] && $serendipity['serendipityUserlevel'] < USERLEVEL_ADMIN) {
+        echo '<div class="serendipityAdminMsgError">' . CREATE_NOT_AUTHORIZED . '</div>';
+    } elseif ($_POST['userlevel'] > $serendipity['serendipityUserlevel']) {
+        echo '<div class="serendipityAdminMsgError">' . CREATE_NOT_AUTHORIZED_USERLEVEL . '</div>';
+    } else {
+        serendipity_deleteAuthor($user[0]['authorid']);
+        printf('<div class="serendipityAdminMsgSuccess">' . DELETED_USER . '</div>', $serendipity['POST']['user'], $user[0]['realname']);
+    }
+}
+
+
+/* Save new user */
+if (isset($_POST['SAVE_NEW'])) {
+    if ($_POST['userlevel'] >= $serendipity['serendipityUserlevel'] && $serendipity['serendipityUserlevel'] < USERLEVEL_ADMIN) {
+        echo '<div class="serendipityAdminMsgError">' . CREATE_NOT_AUTHORIZED . '</div>';
+    } else {
+        $serendipity['POST']['user'] = serendipity_addAuthor($_POST['username'], $_POST['pass'], $_POST['realname'], $_POST['email'], $_POST['userlevel']);
+
+        /* Save all the properties */
+        $config = serendipity_parseTemplate(S9Y_CONFIG_USERTEMPLATE);
+        foreach($config as $category) {
+            foreach ($category['items'] as $item) {
+                if ( serendipity_checkConfigItemFlags($item, 'local') ) {
+                    serendipity_set_user_var($item['var'], $_POST[$item['var']], $serendipity['POST']['user'], ($serendipity['authorid'] == $serendipity['POST']['authorid'] ? true : false));
+                }
+                if ( serendipity_checkConfigItemFlags($item, 'configuration') ) {
+                    serendipity_set_config_var($item['var'], $_POST[$item['var']], $serendipity['POST']['user']);
+                }
+            }
+        }
+
+        printf('<div class="serendipityAdminMsgSuccess">' . CREATED_USER . '</div>', '#' . $serendipity['POST']['user'] . ', ' . $_POST['realname']);
+    }
+}
+
+
+/* Edit a user */
+if (isset($_POST['SAVE_EDIT'])) {
+    $user = serendipity_fetchUsers($serendipity['POST']['authorid']);
+    if ($user[0]['userlevel'] >= $serendipity['serendipityUserlevel'] && $serendipity['serendipityUserlevel'] < USERLEVEL_ADMIN) {
+        echo '<div class="serendipityAdminMsgError">' . CREATE_NOT_AUTHORIZED . '</div>';
+    } elseif ($_POST['userlevel'] > $serendipity['serendipityUserlevel']) {
+        echo '<div class="serendipityAdminMsgError">' . CREATE_NOT_AUTHORIZED_USERLEVEL . '</div>';
+    } else {
+        $config = serendipity_parseTemplate(S9Y_CONFIG_USERTEMPLATE);
+        foreach($config as $category) {
+            foreach ($category['items'] as $item) {
+                if ( serendipity_checkConfigItemFlags($item, 'local') ) {
+                    serendipity_set_user_var($item['var'], $_POST[$item['var']], $serendipity['POST']['user'], ($serendipity['authorid'] == $serendipity['POST']['authorid'] ? true : false));
+                }
+                if ( serendipity_checkConfigItemFlags($item, 'configuration') ) {
+                    serendipity_set_config_var($item['var'], $_POST[$item['var']], $serendipity['POST']['user']);
+                }
+            }
+        }
+        printf('<div class="serendipityAdminMsgSuccess">' . MODIFIED_USER . '</div>', $_POST['realname']);
+    }
+}
+
+if ( $serendipity['GET']['adminAction'] != 'delete' ) {
+?>
+    <table width="100%">
+        <tr>
+            <td><strong><?php echo USER; ?></strong></td>
+            <td width="100" align="center"><strong><?php echo USER_LEVEL ?></strong></td>
+            <td width="200">&nbsp;</td>
+        </tr>
+        <tr>
+            <td colspan="3">
+<?php
+$users = serendipity_fetchUsers();
+$i = 0;
+foreach($users as $user) {
+    if ($user['userlevel'] < $serendipity['serendipityUserlevel'] || $user['authorid'] == $serendipity['authorid'] || $serendipity['serendipityUserlevel'] >= USERLEVEL_ADMIN ) {
+
+    if ( $user['userlevel'] >= USERLEVEL_ADMIN ) {
+        $img = serendipity_getTemplateFile('admin/img/user_admin.png');
+    } elseif ( $user['userlevel'] >= USERLEVEL_CHIEF ) {
+        $img = serendipity_getTemplateFile('admin/img/user_chief.png');
+    } else {
+        $img = serendipity_getTemplateFile('admin/img/user_editor.png');
+    }
+?>
+<div class="serendipity_admin_list_item serendipity_admin_list_item_<?php echo ($i++ % 2) ? 'even' : 'uneven' ?>">
+<table width="100%">
+    <tr>
+<?php /* TODO: Add username to list once tom figures out how to fix uneven rowstyles */ ?>
+        <td><img src="<?php echo $img ?>" alt="" style="border: 0px none ; vertical-align: bottom; display: inline;" /> <?php echo htmlspecialchars($user['realname']); ?></td>
+        <td width="100" align="center"><?php echo $user['userlevel']; ?></td>
+        <td width="200" align="right"> [<a href="?serendipity[adminModule]=users&amp;serendipity[adminAction]=edit&amp;serendipity[userid]=<?php echo $user['authorid'] ?>"><?php echo EDIT ?></a>]
+                                     - [<a href="?serendipity[adminModule]=users&amp;serendipity[adminAction]=delete&amp;serendipity[userid]=<?php echo $user['authorid'] ?>"><?php echo DELETE ?></a>]</td>
+    </tr>
+</table>
+</div>
+<?php
+    }
+}
+?>
+            </tr>
+        </tr>
+<?php if ( !isset($_POST['NEW']) ) { ?>
+        <tr>
+            <td colspan="3" align="right">
+                <form action="?serendipity[adminModule]=users" method="post">
+                    <input type="submit" name="NEW"   value="<?php echo CREATE_NEW_USER; ?>" class="serendipityPrettyButton" />
+                </form>
+            </td>
+        </tr>
+<?php } ?>
+    </table>
+
+<?php
+}
+
+
+if ($serendipity['GET']['adminAction'] == 'edit' || isset($_POST['NEW'])) {
+?>
+<br />
+<br />
+<hr noshade="noshade">
+<form action="?serendipity[adminModule]=users" method="post">
+    <div>
+    <h3>
+<?php
+if ($serendipity['GET']['adminAction'] == 'edit') {
+    $user = serendipity_fetchUsers($serendipity['GET']['userid']);
+    if ($user[0]['userlevel'] >= $serendipity['serendipityUserlevel'] && $user[0]['authorid'] != $serendipity['authorid'] && $serendipity['serendipityUserlevel'] < USERLEVEL_ADMIN) {
+        echo '<strong>' . CREATE_NOT_AUTHORIZED . '</strong><br />';
+        echo EDIT;
+        $from = array();
+    } else {
+        echo EDIT;
+        $from = &$user[0];
+        unset($from['password']);
+        echo '<input type="hidden" name="serendipity[user]" value="' . $from['authorid'] . '" />';
+    }
+} else {
+    echo CREATE;
+    $from = array();
+}
+?>
+    </h3>
+
+<?php
+$config = serendipity_parseTemplate(S9Y_CONFIG_USERTEMPLATE);
+serendipity_printConfigTemplate($config, $from, true, false);
+
+if ($serendipity['GET']['adminAction'] == 'edit') { ?>
+        <input type="submit" name="SAVE_EDIT"   value="<?php echo SAVE; ?>" class="serendipityPrettyButton" />
+<?php } else { ?>
+        <input type="submit" name="SAVE_NEW" value="<?php echo CREATE_NEW_USER; ?>" class="serendipityPrettyButton" />
+<?php } ?>
+
+    </div>
+</form>
+<?php
+} elseif ($serendipity['GET']['adminAction'] == 'delete') {
+    $user = serendipity_fetchUsers($serendipity['GET']['userid']);
+?>
+<form action="?serendipity[adminModule]=users" method="post">
+    <div>
+    <?php printf(DELETE_USER, $serendipity['GET']['userid'], $user[0]['realname']); ?>
+        <br /><br />
+        <input type="hidden" name="serendipity[user]" value="<?php echo $serendipity['GET']['userid']; ?>" />
+        <input type="submit" name="DELETE_YES" value="<?php echo DUMP_IT; ?>" class="serendipityPrettyButton" />
+        <input type="submit" name="NO" value="<?php echo NOT_REALLY; ?>" class="serendipityPrettyButton" />
+    </div>
+</form>
+<?php
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/compat.inc.php b/include/compat.inc.php
new file mode 100644 (file)
index 0000000..b9ee22a
--- /dev/null
@@ -0,0 +1,173 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+$serendipity = array();
+@ini_set('magic_quotes_runtime', 'off');
+
+if (!defined('PATH_SEPARATOR')) {
+    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+        define('PATH_SEPARATOR', ';');
+    } else {
+        define('PATH_SEPARATOR', ':');
+    }
+}
+
+if (!defined('DIRECTORY_SEPARATOR')) {
+    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+        define('DIRECTORY_SEPARATOR', '\\');
+    } else {
+        define('DIRECTORY_SEPARATOR', '/');
+    }
+}
+
+if (!function_exists('file_get_contents')) {
+    function file_get_contents($filename, $use_include_path = 0) {
+        $file = fopen($filename, 'rb', $use_include_path);
+        $data = '';
+        if ($file) {
+            while (!feof($file)) {
+                $data .= fread($file, 4096);
+            }
+            fclose($file);
+        }
+
+        return $data;
+    }
+}
+
+if (!isset($_REQUEST)) {
+    $_REQUEST = &$HTTP_REQUEST_VARS;
+}
+if (!isset($_POST)) {
+    $_POST = &$HTTP_POST_VARS;
+}
+
+if (!isset($_GET)) {
+    $_GET = &$HTTP_GET_VARS;
+}
+
+if (!isset($_SESSION)) {
+    $_SESSION = &$HTTP_SESSION_VARS;
+}
+
+if (!isset($_COOKIE)) {
+    $_COOKIE = &$HTTP_COOKIE_VARS;
+}
+
+if (!isset($_SERVER)) {
+    $_SERVER = &$HTTP_SERVER_VARS;
+}
+
+/*
+ *  Avoid magic_quotes_gpc issues
+ *  courtesy of iliaa@php.net
+ */
+function serendipity_strip_quotes(&$var)
+{
+    if (is_array($var)) {
+        foreach ($var as $k => $v) {
+            if (is_array($v)) {
+                array_walk($var[$k], 'serendipity_strip_quotes');
+            } else {
+                $var[$k] = stripslashes($v);
+            }
+        }
+    } else {
+        $var = stripslashes($var);
+    }
+}
+
+if (ini_get('magic_quotes_gpc')) {
+    if (@count($_REQUEST)) {
+        array_walk($_REQUEST, 'serendipity_strip_quotes');
+    }
+
+    if (@count($_GET)) {
+        array_walk($_GET,     'serendipity_strip_quotes');
+    }
+
+    if (@count($_POST)) {
+        array_walk($_POST,    'serendipity_strip_quotes');
+    }
+
+    if (@count($_COOKIE)) {
+        array_walk($_COOKIE, 'serendipity_strip_quotes');
+    }
+
+    if (@count($_FILES) && strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
+        array_walk($_FILES,   'serendipity_strip_quotes');
+    }
+}
+
+
+// Merge get and post into the serendipity array
+$serendipity['GET']    = &$_GET['serendipity'];
+$serendipity['POST']   = &$_POST['serendipity'];
+$serendipity['COOKIE'] = &$_COOKIE['serendipity'];
+
+// Some security issues
+if (isset($serendipity['GET']['searchTerm'])) {
+    $serendipity['GET']['searchTerm'] = htmlspecialchars(strip_tags($serendipity['GET']['searchTerm']));
+}
+
+function serendipity_get_bool($item) {
+    static $translation = array('true'  => true,
+                                'false' => false);
+
+    if (isset($translation[$item])) {
+        return $translation[$item];
+    } else {
+        return $item;
+    }
+}
+
+// Needs to be included here so that it's globally available also when installing
+function serendipity_detectLang($use_include = false) {
+    global $serendipity;
+
+    $supported_languages = array_keys($serendipity['languages']);
+    $possible_languages = explode(',', (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : ''));
+    if (is_array($possible_languages)) {
+        foreach($possible_languages as $index => $lang) {
+            $preferred_language = strtolower(preg_replace('@^([^\-_;]*)_?.*$@', '\1', $lang));
+            if (in_array($preferred_language, $supported_languages)) {
+                if ($use_include) {
+                    @include_once(S9Y_INCLUDE_PATH . 'lang/serendipity_lang_' . $preferred_language . '.inc.php');
+                    $serendipity['autolang'] = $preferred_language;
+                }
+                return $preferred_language;
+            } // endif
+        } // endforeach
+    } // endif
+
+    return $serendipity['lang'];
+}
+
+function serendipity_getCoreVersion($version) {
+    return preg_replace('@^([0-9\.]+).*$@', '\1', $version);
+}
+
+function serendipity_die($html) {
+    die(
+        '<html>
+            <head>
+                <meta http-equiv="Content-Type" content="text/html; charset=' . LANG_CHARSET . '">
+            </head>
+            <body>' . $html . '</body>
+        </html>');
+}
+
+/*
+ *  Some defaults for our config vars.
+ *  They are likely to be overwritten later in the code
+ */
+$serendipity['templatePath'] = 'templates/';
+if (!isset($serendipity['serendipityPath'])) {
+    $serendipity['serendipityPath'] = (defined('S9Y_INCLUDE_PATH') ? S9Y_INCLUDE_PATH : './');
+}
+
+$serendipity['indexFile'] = 'index.php';
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/db/db.inc.php b/include/db/db.inc.php
new file mode 100644 (file)
index 0000000..6ef09e4
--- /dev/null
@@ -0,0 +1,94 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+
+if (@include_once(S9Y_INCLUDE_PATH . "include/db/{$serendipity['dbType']}.inc.php")) {
+    @define('S9Y_DB_INCLUDED', TRUE);
+}
+
+function serendipity_db_update($table, $keys, $values)
+{
+    global $serendipity;
+
+    $set = '';
+
+    foreach ($values as $k => $v) {
+        if (strlen($set))
+            $set .= ', ';
+        $set .= $k . '=\'' . serendipity_db_escape_string($v) . '\'';
+    }
+
+    $where = '';
+    foreach ($keys as $k => $v) {
+        if (strlen($where))
+            $where .= ' AND ';
+        $where .= $k . '=\'' . serendipity_db_escape_string($v) . '\'';
+    }
+
+    if (strlen($where)) {
+        $where = " WHERE $where";
+    }
+
+    return serendipity_db_query("UPDATE {$serendipity['dbPrefix']}$table SET $set $where");
+}
+
+function serendipity_db_insert($table, $values)
+{
+    global $serendipity;
+
+    $names = implode(',', array_keys($values));
+
+    $vals = '';
+    foreach ($values as $k => $v) {
+        if (strlen($vals))
+            $vals .= ', ';
+        $vals .= '\'' . serendipity_db_escape_string($v) . '\'';
+    }
+
+    return serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}$table ($names) values ($vals)");
+}
+
+function serendipity_db_bool ($val)
+{
+    if(($val === true) || ($val == 'true') || ($val == 't') || ($val == '1'))
+        return true;
+    #elseif (($val === false || $val == 'false' || $val == 'f'))
+    else
+        return false;
+}
+
+function serendipity_db_get_interval($val, $ival = 900) {
+    global $serendipity;
+
+    switch($serendipity['dbType']) {
+        case 'sqlite':
+            $interval = $ival;
+            $ts       = time();
+            break;
+
+        case 'postgres':
+            $interval = "interval '$ival'";
+            $ts       = 'NOW()';
+            break;
+
+        case 'mysql':
+        case 'mysqli':
+        default:
+            $interval = $ival;
+            $ts       = 'NOW()';
+            break;
+    }
+    
+    switch($val) {
+        case 'interval':
+            return $interval;
+        
+        default:
+        case 'ts':
+            return $ts;
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/db/mysql.inc.php b/include/db/mysql.inc.php
new file mode 100644 (file)
index 0000000..51dc47b
--- /dev/null
@@ -0,0 +1,200 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+function serendipity_db_begin_transaction(){
+    serendipity_db_query('start transaction');
+}
+
+function serendipity_db_end_transaction($commit){
+    if ($commit){
+        serendipity_db_query('commit');
+    }else{
+        serendipity_db_query('rollback');
+    }
+}
+
+/* Issues a query to the underlying database;
+ * returns:
+ *   false if there was an error,
+ *   true if the query succeeded but did not generate any rows
+ *   array of field values if it returned a single row and $single is true
+ *   array of array of field values if it returned row(s)
+ */
+function &serendipity_db_query($sql, $single = false, $result_type = "both", $reportErr = false, $assocKey = false, $assocVal = false, $expectError = false) {
+    global $serendipity;
+    static $type_map = array(
+                         'assoc' => MYSQL_ASSOC,
+                         'num'   => MYSQL_NUM,
+                         'both'  => MYSQL_BOTH
+    );
+
+    // highlight_string(var_export($sql, 1));
+
+    if ($expectError) {
+        $c = @mysql_query($sql, $serendipity['dbConn']);
+    } else {
+        $c = mysql_query($sql, $serendipity['dbConn']);
+    }
+
+    if (!$expectError && mysql_error($serendipity['dbConn']) != '') {
+        return '<pre>' . $sql . '</pre> / ' . mysql_error($serendipity['dbConn']);
+    }
+
+    if (!$c) {
+        if (!$expectError && !$serendipity['production']) {
+            print '<pre>' . $sql . '</pre> / ' . mysql_error($serendipity['dbConn']);
+            if (function_exists('debug_backtrace') && $reportErr == true) {
+                highlight_string(var_export(debug_backtrace(), 1));
+            }
+        }
+
+        return false;
+    }
+    if ($c === true) {
+        return true;
+    }
+
+    $result_type = $type_map[$result_type];
+
+    switch(mysql_num_rows($c)) {
+        case 0:
+            if ($single) {
+                return false;
+            }
+            return true;
+        case 1:
+            if ($single) {
+                return mysql_fetch_array($c, $result_type);
+            }
+        default:
+            if ($single) {
+                return mysql_fetch_array($c, $result_type);
+            }
+
+            $rows = array();
+            while (($row = mysql_fetch_array($c, $result_type))) {
+                if (!empty($assocKey) && !empty($assocVal)) {
+                    // You can fetch a key-associated array via the two function parameters assocKey and assocVal
+                    $rows[$row[$assocKey]] = $row[$assocVal];
+                } else {
+                    $rows[] = $row;
+                }
+            }
+            return $rows;
+    }
+}
+
+function serendipity_db_insert_id() {
+    global $serendipity;
+
+    return mysql_insert_id($serendipity['dbConn']);
+}
+
+function serendipity_db_affected_rows() {
+    global $serendipity;
+
+    return mysql_affected_rows($serendipity['dbConn']);
+}
+
+function serendipity_db_updated_rows() {
+    global $serendipity;
+
+    preg_match(
+        "/^[^0-9]+([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+)/",
+        mysql_info(),
+        $arr);
+        // mysql_affected_rows returns 0 if rows were matched but not changed.
+        // mysql_info returns rows matched AND rows changed
+        return $arr[2];
+}
+
+function serendipity_db_matched_rows() {
+    global $serendipity;
+
+    preg_match(
+        "/^[^0-9]+([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+)/",
+        mysql_info(),
+        $arr);
+        // mysql_affected_rows returns 0 if rows were matched but not changed.
+        // mysql_info returns rows matched AND rows changed
+        return $arr[1];
+}
+
+function serendipity_db_escape_string($string) {
+    return mysql_escape_string($string);
+}
+
+function serendipity_db_limit($start, $offset) {
+    return $start . ', ' . $offset;
+}
+
+function serendipity_db_limit_sql($limitstring) {
+    return ' LIMIT ' . $limitstring;
+}
+
+function serendipity_db_connect() {
+    global $serendipity;
+
+    if (isset($serendipity['dbConn'])) {
+        return $serendipity['dbConn'];
+    }
+
+    if (isset($serendipity['dbPersistent']) && $serendipity['dbPersistent']) {
+        $function = 'mysql_pconnect';
+    } else {
+        $function = 'mysql_connect';
+    }
+
+    $serendipity['dbConn'] = $function($serendipity['dbHost'], $serendipity['dbUser'], $serendipity['dbPass']);
+    mysql_select_db($serendipity['dbName']);
+    return $serendipity['dbConn'];
+}
+
+function serendipity_db_schema_import($query) {
+    static $search  = array('{AUTOINCREMENT}', '{PRIMARY}',
+        '{UNSIGNED}', '{FULLTEXT}', '{FULLTEXT_MYSQL}', '{BOOLEAN}');
+    static $replace = array('int(11) not null auto_increment', 'primary key',
+        'unsigned'  , 'FULLTEXT', 'FULLTEXT', 'enum (\'true\', \'false\') NOT NULL default \'true\'');
+
+    $query = trim(str_replace($search, $replace, $query));
+    if ($query{0} == '@') {
+        // Errors are expected to happen (like duplicate index creation)
+        return serendipity_db_query(substr($query, 1), false, 'both', false, false, false, true);
+    } else {
+        return serendipity_db_query($query);
+    }
+}
+
+/* probes the usability of the DB during installation */
+function serendipity_db_probe($hash, &$errs) {
+    global $serendipity;
+
+    if (!function_exists('mysql_connect')) {
+        $errs[] = 'No mySQL extension found. Please check your webserver installation or contact your systems administrator regarding this problem.';
+        return false;
+    }
+
+    if (!($c = @mysql_connect($hash['dbHost'], $hash['dbUser'], $hash['dbPass']))) {
+        $errs[] = 'Could not connect to database; check your settings.';
+        $errs[] = 'The mySQL error was: ' . mysql_error();
+        return false;
+    }
+
+    $serendipity['dbConn'] = $c;
+
+    if (!@mysql_select_db($hash['dbName'])) {
+        $errs[] = 'The database you specified does not exist.';
+        $errs[] = 'The mySQL error was: ' . mysql_error();
+        return false;
+    }
+
+    return true;
+}
+
+function serendipity_db_concat($string) {
+    return 'concat(' . $string . ')';
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/db/mysqli.inc.php b/include/db/mysqli.inc.php
new file mode 100644 (file)
index 0000000..f3549b3
--- /dev/null
@@ -0,0 +1,196 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+function serendipity_db_begin_transaction(){
+    serendipity_db_query('start transaction');
+}
+
+function serendipity_db_end_transaction($commit){
+    if ($commit){
+        serendipity_db_query('commit');
+    }else{
+        serendipity_db_query('rollback');
+    }
+}
+
+/* Issues a query to the underlying database;
+ * returns:
+ *   false if there was an error,
+ *   true if the query succeeded but did not generate any rows
+ *   array of field values if it returned a single row and $single is true
+ *   array of array of field values if it returned row(s)
+ */
+function &serendipity_db_query($sql, $single = false, $result_type = "both", $reportErr = false, $assocKey = false, $assocVal = false, $expectError = false) {
+    global $serendipity;
+    $type_map = array('assoc' => MYSQLI_ASSOC, 'num' => MYSQLI_NUM, 'both' => MYSQLI_BOTH);
+
+    if ($expectError) {
+        $c = @mysqli_query($serendipity['dbConn'], $sql);
+    } else {
+        $c = mysqli_query($serendipity['dbConn'], $sql);
+    }
+
+    if (!$expectError && mysqli_error($serendipity['dbConn']) != '') {
+        return mysqli_error($serendipity['dbConn']);
+    }
+
+    if (!$c) {
+        if (!$expectError && !$serendipity['production']) {
+            print mysqli_error($serendipity['dbConn']);
+            if (function_exists('debug_backtrace') && $reportErr == true) {
+                highlight_string(var_export(debug_backtrace(), 1));
+            }
+        }
+
+        return false;
+    }
+
+    if ($c === true) {
+        return true;
+    }
+
+    $result_type = $type_map[$result_type];
+
+    switch(mysqli_num_rows($c)) {
+        case 0:
+            if ($single) {
+                return false;
+            }
+            return true;
+        case 1:
+            if ($single) {
+                return mysqli_fetch_array($c, $result_type);
+            }
+        default:
+            if ($single) {
+                return mysqli_fetch_array($c, $result_type);
+            }
+
+            $rows = array();
+            while ($row = mysqli_fetch_array($c, $result_type)) {
+                if (!empty($assocKey) && !empty($assocVal)) {
+                    // You can fetch a key-associated array via the two function parameters assocKey and assocVal
+                    $rows[$row[$assocKey]] = $row[$assocVal];
+                } else {
+                    $rows[] = $row;
+                }
+            }
+            return $rows;
+    }
+}
+
+
+function serendipity_db_insert_id() {
+    global $serendipity;
+    return mysqli_insert_id($serendipity['dbConn']);
+}
+
+function serendipity_db_affected_rows() {
+    global $serendipity;
+    return mysqli_affected_rows($serendipity['dbConn']);
+}
+
+function serendipity_db_updated_rows() {
+    global $serendipity;
+
+    preg_match(
+        "/^[^0-9]+([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+)/",
+        mysqli_info(),
+        $arr);
+        // mysqli_affected_rows returns 0 if rows were matched but not changed.
+        // mysqli_info returns rows matched
+        return $arr[1];
+}
+
+function serendipity_db_matched_rows() {
+    global $serendipity;
+
+    preg_match(
+        "/^[^0-9]+([0-9]+)[^0-9]+([0-9]+)[^0-9]+([0-9]+)/",
+        mysqli_info(),
+        $arr);
+        // mysqli_affected_rows returns 0 if rows were matched but not changed.
+        // mysqli_info returns rows matched
+        return $arr[0];
+}
+
+function serendipity_db_escape_string($string) {
+    global $serendipity;
+    return mysqli_escape_string($serendipity['dbConn'], $string);
+}
+
+function serendipity_db_limit($start, $offset) {
+    return $start . ', ' . $offset;
+}
+
+function serendipity_db_limit_sql($limitstring) {
+    return ' LIMIT ' . $limitstring;
+}
+
+function serendipity_db_connect() {
+    global $serendipity;
+
+    if (isset($serendipity['dbConn'])) {
+        return $serendipity['dbConn'];
+    }
+
+    if (isset($serendipity['dbPersistent']) && $serendipity['dbPersistent']) {
+        $function = 'mysqli_pconnect';
+    } else {
+        $function = 'mysqli_connect';
+    }
+
+    $serendipity['dbConn'] = $function($serendipity['dbHost'], $serendipity['dbUser'], $serendipity['dbPass']);
+    mysqli_select_db($serendipity['dbConn'], $serendipity['dbName']);
+
+    return $serendipity['dbConn'];
+}
+
+function serendipity_db_schema_import($query) {
+    static $search  = array('{AUTOINCREMENT}', '{PRIMARY}',
+        '{UNSIGNED}', '{FULLTEXT}', '{FULLTEXT_MYSQL}', '{BOOLEAN}');
+    static $replace = array('int(11) not null auto_increment', 'primary key',
+        'unsigned'  , 'FULLTEXT', 'FULLTEXT', 'enum (\'true\', \'false\') NOT NULL default \'true\'');
+
+    $query = trim(str_replace($search, $replace, $query));
+    if ($query{0} == '@') {
+        // Errors are expected to happen (like duplicate index creation)
+        return serendipity_db_query(substr($query, 1), false, 'both', false, false, false, true);
+    } else {
+        return serendipity_db_query($query);
+    }
+}
+
+/* probes the usability of the DB during installation */
+function serendipity_db_probe($hash, &$errs) {
+    global $serendipity;
+
+    if (!function_exists('mysqli_connect')) {
+        $errs[] = 'No mySQLi extension found. Please check your webserver installation or contact your systems administrator regarding this problem.';
+        return false;
+    }
+
+    if (!($c = @mysqli_connect($hash['dbHost'], $hash['dbUser'], $hash['dbPass']))) {
+        $errs[] = 'Could not connect to database; check your settings.';
+        $errs[] = 'The mySQL error was: ' . mysqli_connect_error();
+        return false;
+    }
+
+    $serendipity['dbConn'] = $c;
+
+    if ( !@mysqli_select_db($c, $hash['dbName']) ) {
+        $errs[] = 'The database you specified does not exist.';
+        $errs[] = 'The mySQL error was: ' . mysqli_error($c);
+        return false;
+    }
+
+    return true;
+}
+
+function serendipity_db_concat($string) {
+    return 'concat(' . $string . ')';
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/db/postgres.inc.php b/include/db/postgres.inc.php
new file mode 100644 (file)
index 0000000..b68fb0b
--- /dev/null
@@ -0,0 +1,208 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+function serendipity_db_begin_transaction(){
+    serendipity_db_query('begin work');
+}
+
+function serendipity_db_end_transaction($commit){
+    if ($commit){
+        serendipity_db_query('commit');
+    }else{
+        serendipity_db_query('rollback');
+    }
+}
+
+function serendipity_db_connect() {
+    global $serendipity;
+
+    if (isset($serendipity['dbPersistent']) && $serendipity['dbPersistent']) {
+        $function = 'pg_pconnect';
+    } else {
+        $function = 'pg_connect';
+    }
+
+    $serendipity['dbConn'] = $function(
+                               sprintf(
+                                 '%sdbname=%s user=%s password=%s',
+                                 strlen($serendipity['dbHost']) ? ('host=' . $serendipity['dbHost'] . ' ') : '',
+                                 $serendipity['dbName'],
+                                 $serendipity['dbUser'],
+                                 $serendipity['dbPass']
+                               )
+                             );
+
+    return $serendipity['dbConn'];
+}
+
+function serendipity_db_escape_string($string) {
+    return pg_escape_string($string);
+}
+
+function serendipity_db_limit($start, $offset) {
+    return $offset . ', ' . $start;
+}
+
+function serendipity_db_limit_sql($limitstring) {
+    $limit_split = split(',', $limitstring);
+    if (count($limit_split) > 1) {
+        $limit = ' LIMIT ' . $limit_split[0] . ' OFFSET ' . $limit_split[1];
+    } else {
+        $limit = ' LIMIT ' . $limit_split[0];
+    }
+    return $limit;
+}
+
+function serendipity_db_affected_rows() {
+    global $serendipity;
+    return pg_affected_rows($serendipity['dbLastResult']);
+}
+
+function serendipity_db_updated_rows() {
+    global $serendipity;
+    // it is unknown whether pg_affected_rows returns number of rows
+    //  UPDATED or MATCHED on an UPDATE statement.
+    return pg_affected_rows($serendipity['dbLastResult']);
+}
+
+function serendipity_db_matched_rows() {
+    global $serendipity;
+    // it is unknown whether pg_affected_rows returns number of rows
+    //  UPDATED or MATCHED on an UPDATE statement.
+    return pg_affected_rows($serendipity['dbLastResult']);
+}
+
+function serendipity_db_insert_id($table = '', $id = '') {
+    global $serendipity;
+    if (empty($table) || empty($id)) {
+        // BC - will/should never be called with empty parameters!
+        return pg_last_oid($serendipity['dbLastResult']);
+    } else {
+        $query = "SELECT currval('{$serendipity['dbPrefix']}{$table}_{$id}_seq'::text) AS {$id}";
+        $res   = pg_query($serendipity['dbConn'], $query);
+        if (pg_num_rows($res)) {
+            $insert_id = pg_fetch_array($res, 0, PGSQL_ASSOC);
+            return $insert_id[$id];
+        } else {
+            return pg_last_oid($serendipity['dbLastResult']); // BC - should not happen!
+        }
+    }
+}
+
+function &serendipity_db_query($sql, $single = false, $result_type = "both", $reportErr = false, $assocKey = false, $assocVal = false, $expectError = false) {
+    global $serendipity;
+    static $type_map = array(
+                         'assoc' => PGSQL_ASSOC,
+                         'num'   => PGSQL_NUM,
+                         'both'  => PGSQL_BOTH
+    );
+
+    if (!isset($serendipity['dbPgsqlOIDS'])) {
+        $serendipity['dbPgsqlOIDS'] = true;
+        @serendipity_db_query('SET default_with_oids = true', true, 'both', false, false, false, true);
+    }
+
+    if (!$expectError && ($reportErr || !$serendipity['production'])) {
+        $serendipity['dbLastResult'] = pg_query($serendipity['dbConn'], $sql);
+    } else {
+        $serendipity['dbLastResult'] = @pg_query($serendipity['dbConn'], $sql);
+    }
+
+    if (!$serendipity['dbLastResult']) {
+        if (!$expectError && !$serendipity['production']) {
+            print "Error in $sql<br/>\n";
+            print pg_last_error($serendipity['dbConn']) . "<BR/>\n";
+            if (function_exists('debug_backtrace')) {
+                highlight_string(var_export(debug_backtrace(), 1));
+            }
+            print "<br><code>$sql</code>\n";
+        }
+        return false;
+    }
+
+    if ($serendipity['dbLastResult'] === true) {
+        return true;
+    }
+
+    $result_type = $type_map[$result_type];
+
+    $n = pg_num_rows($serendipity['dbLastResult']);
+
+    switch ($n) {
+        case 0:
+            if ($single) {
+                return false;
+            }
+            return true;
+        case 1:
+            if ($single) {
+                return pg_fetch_array($serendipity['dbLastResult'], 0, $result_type);
+            }
+        default:
+            $rows = array();
+            for ($i = 0; $i < $n; $i++) {
+                if (!empty($assocKey) && !empty($assocVal)) {
+                    // You can fetch a key-associated array via the two function parameters assocKey and assocVal
+                    $row = pg_fetch_array($serendipity['dbLastResult'], $i, $result_type);
+                    $rows[$row[$assocKey]] = $row[$assocVal];
+                } else {
+                    $rows[] = pg_fetch_array($serendipity['dbLastResult'], $i, $result_type);
+                }
+            }
+            return $rows;
+    }
+}
+
+function serendipity_db_schema_import($query) {
+    static $search  = array('{AUTOINCREMENT}', '{PRIMARY}', '{UNSIGNED}',
+        '{FULLTEXT}', '{BOOLEAN}', 'int(1)', 'int(10)', 'int(11)', 'int(4)');
+    static $replace = array('SERIAL', 'primary key', '', '', 'BOOLEAN NOT NULL', 'int2',
+        'int4', 'int4', 'int4');
+
+    if (stristr($query, '{FULLTEXT_MYSQL}')) {
+        return true;
+    }
+
+    $query = trim(str_replace($search, $replace, $query));
+    if ($query{0} == '@') {
+        // Errors are expected to happen (like duplicate index creation)
+        return serendipity_db_query(substr($query, 1), false, 'both', false, false, false, true);
+    } else {
+        return serendipity_db_query($query);
+    }
+}
+
+function serendipity_db_probe($hash, &$errs) {
+    global $serendipity;
+
+    if (!function_exists('pg_connect')) {
+        $errs[] = 'No PostgreSQL extension found. Please check your webserver installation or contact your systems administrator regarding this problem.';
+        return false;
+    }
+
+    $serendipity['dbConn'] = pg_connect(
+                               sprintf(
+                                 '%sdbname=%s user=%s password=%s',
+
+                                 strlen($hash['dbHost']) ? ('host=' . $hash['dbHost'] . ' ') : '',
+                                 $hash['dbName'],
+                                 $hash['dbUser'],
+                                 $hash['dbPass']
+                               )
+                             );
+
+    if (!$serendipity['dbConn']) {
+        $errs[] = 'Could not connect to database; check your settings.';
+        return false;
+    }
+
+    return true;
+}
+
+function serendipity_db_concat($string) {
+    return '(' . str_replace(', ', '||', $string) . ')';
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/db/sqlite.inc.php b/include/db/sqlite.inc.php
new file mode 100644 (file)
index 0000000..009d12f
--- /dev/null
@@ -0,0 +1,218 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+if (!function_exists('sqlite_open')) {
+    @dl('sqlite.so');
+    @dl('sqlite.dll');
+}
+
+function serendipity_db_begin_transaction(){
+    serendipity_db_query('begin transaction');
+}
+
+function serendipity_db_end_transaction($commit){
+    if ($commit){
+        serendipity_db_query('commit transaction');
+    }else{
+        serendipity_db_query('rollback transaction');
+    }
+}
+
+function serendipity_db_connect()
+{
+    global $serendipity;
+
+    if (isset($serendipity['dbConn'])) {
+        return $serendipity['dbConn'];
+    }
+
+    if (isset($serendipity['dbPersistent']) && $serendipity['dbPersistent']) {
+        $function = 'sqlite_popen';
+    } else {
+        $function = 'sqlite_open';
+    }
+
+
+    $serendipity['dbConn'] = $function($serendipity['serendipityPath'] . $serendipity['dbName'] . '.db');
+
+    return $serendipity['dbConn'];
+}
+
+function serendipity_db_escape_string($string)
+{
+    static $search  = array("\x00", '%',   "'",   '\"');
+    static $replace = array('%00',  '%25', "''", '\\\"');
+
+    return str_replace($search, $replace, $string);
+}
+
+function serendipity_db_affected_rows()
+{
+    global $serendipity;
+
+    return sqlite_changes($serendipity['dbConn']);
+}
+
+function serendipity_db_updated_rows()
+{
+    global $serendipity;
+    // It is unknown whether sqllite returns rows MATCHED or rows UPDATED
+    return sqlite_changes($serendipity['dbConn']);
+}
+
+function serendipity_db_matched_rows()
+{
+    global $serendipity;
+    // It is unknown whether sqllite returns rows MATCHED or rows UPDATED
+    return sqlite_changes($serendipity['dbConn']);
+}
+
+function serendipity_db_insert_id()
+{
+    global $serendipity;
+
+    return sqlite_last_insert_rowid($serendipity['dbConn']);
+}
+
+function serendipity_db_sqlite_fetch_array($res, $type = SQLITE_BOTH)
+{
+    static $search  = array('%00',  '%25');
+    static $replace = array("\x00", '%');
+
+    $row = sqlite_fetch_array($res, $type);
+    if (!is_array($row)) {
+        return $row;
+    }
+
+    /* strip any slashes, correct fieldname */
+    foreach ($row as $i => $v) {
+        // TODO: If a query of the format 'SELECT a.id, b.text FROM table' is used,
+        //       the sqlite extension will give us key indizes 'a.id' and 'b.text'
+        //       instead of just 'id' and 'text' like in mysql/postgresql extension.
+        //       To fix that, we use a preg-regex; but that is quite performance costy.
+        //       Either we always need to use 'SELECT a.id AS id, b.text AS text' in query,
+        //       or the sqlite extension may get fixed. :-)
+        $row[preg_replace('@^.+\.(.*)@', '\1', $i)] = str_replace($search, $replace, $v);
+    }
+
+    return $row;
+}
+
+function &serendipity_db_query($sql, $single = false, $result_type = "both", $reportErr = true, $assocKey = false, $assocVal = false, $expectError = false)
+{
+    global $serendipity;
+    static $type_map = array(
+                         'assoc' => SQLITE_ASSOC,
+                         'num'   => SQLITE_NUM,
+                         'both'  => SQLITE_BOTH
+    );
+
+    static $debug = false;
+
+    if ($debug) $fp = @fopen('sqlite.log', 'a');
+
+    if ($reportErr && !$expectError) {
+        $res = sqlite_query($sql, $serendipity['dbConn']);
+    } else {
+        $res = @sqlite_query($sql, $serendipity['dbConn']);
+    }
+
+    if (!$res) {
+        if (!$expectError && !$serendipity['production']) {
+            var_dump($res);
+            var_dump($sql);
+            return "problem with query";
+        }
+        if ($debug) fwrite($fp, '[' . date('d.m.Y H:i') . '] [ERROR] SQLITE QUERY: ' . $sql . "\n\n");
+
+        return false;
+    } elseif ($debug) {
+        fwrite($fp, '[' . date('d.m.Y H:i') . '] SQLITE QUERY: ' . $sql . "\n\n");
+    }
+
+    if ($res === true) {
+        return true;
+    }
+
+    if (sqlite_num_rows($res) == 0) {
+        if ($single) {
+            return false;
+        }
+        return true;
+    } else {
+        $rows = array();
+
+        while (($row = serendipity_db_sqlite_fetch_array($res, $type_map[$result_type]))) {
+            if (!empty($assocKey) && !empty($assocVal)) {
+                // You can fetch a key-associated array via the two function parameters assocKey and assocVal
+                $rows[$row[$assocKey]] = $row[$assocVal];
+            } else {
+                $rows[] = $row;
+            }
+        }
+
+        if ($debug) fwrite($fp, '[' . date('d.m.Y H:i') . '] SQLITE RESULT: ' . print_r($rows, true). "\n\n");
+        if ($debug) fclose($fp);
+
+        if ($single && count($rows) == 1) {
+            return $rows[0];
+        }
+
+        return $rows;
+    }
+}
+
+function serendipity_db_probe($hash, &$errs)
+{
+    global $serendipity;
+
+    $dbName = (isset($hash['sqlitedbName']) ? $hash['sqlitedbName'] : $hash['dbName']);
+
+    if (!function_exists('sqlite_open')) {
+        $errs[] = 'SQLite extension not installed. Run "pear install sqlite" on your webserver or contact your systems administrator regarding this problem.';
+        return false;
+    }
+
+    $serendipity['dbConn'] = sqlite_open($serendipity['serendipityPath'] . $dbName . '.db');
+
+    if ($serendipity['dbConn']) {
+        return true;
+    }
+
+    $errs[] = "Unable to open \"{$serendipity['serendipityPath']}$dbName.db\" - check permissions (directory needs to be writeable for webserver)!";
+    return false;
+}
+
+function serendipity_db_schema_import($query)
+{
+    static $search  = array('{AUTOINCREMENT}', '{PRIMARY}', '{UNSIGNED}', '{FULLTEXT}', '{BOOLEAN}');
+    static $replace = array('INTEGER', 'PRIMARY KEY', '', '', 'BOOLEAN NOT NULL');
+
+    if (stristr($query, '{FULLTEXT_MYSQL}')) {
+        return true;
+    }
+
+    $query = trim(str_replace($search, $replace, $query));
+    if ($query{0} == '@') {
+        // Errors are expected to happen (like duplicate index creation)
+        return serendipity_db_query(substr($query, 1), false, 'both', false, false, false, true);
+    } else {
+        return serendipity_db_query($query);
+    }
+}
+
+function serendipity_db_limit($start, $offset) {
+    return $start . ', ' . $offset;
+}
+
+function serendipity_db_limit_sql($limitstring) {
+    return ' LIMIT ' . $limitstring;
+}
+
+function serendipity_db_concat($string) {
+    return 'concat(' . $string . ')';
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/functions.inc.php b/include/functions.inc.php
new file mode 100644 (file)
index 0000000..30c270e
--- /dev/null
@@ -0,0 +1,681 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+$serendipity['imageList'] = array();
+include_once(S9Y_INCLUDE_PATH . "include/db/db.inc.php");
+include_once(S9Y_INCLUDE_PATH . "include/compat.inc.php");
+include_once(S9Y_INCLUDE_PATH . "include/functions_config.inc.php");
+include_once(S9Y_INCLUDE_PATH . "bundled-libs/XML/RPC.php");
+include_once(S9Y_INCLUDE_PATH . "include/plugin_api.inc.php");
+include_once(S9Y_INCLUDE_PATH . "include/functions_images.inc.php");
+include_once(S9Y_INCLUDE_PATH . "include/functions_installer.inc.php");
+include_once(S9Y_INCLUDE_PATH . "include/functions_entries.inc.php");
+include_once(S9Y_INCLUDE_PATH . "include/functions_comments.inc.php");
+include_once(S9Y_INCLUDE_PATH . "include/functions_trackbacks.inc.php");
+include_once(S9Y_INCLUDE_PATH . "include/functions_smarty.inc.php");
+
+function serendipity_truncateString($s, $len) {
+    if ( strlen($s) > ($len+3) ) {
+        $s = serendipity_mb('substr', $s, 0, $len) . '...';
+    }
+    return $s;
+}
+
+function serendipity_gzCompression() {
+    global $serendipity;
+    if (isset($serendipity['useGzip']) && serendipity_db_bool($serendipity['useGzip']) && function_exists('ob_gzhandler') && extension_loaded('zlib') && serendipity_ini_bool(ini_get('zlib.output_compression')) == false) {
+        ob_start("ob_gzhandler");
+    }
+}
+
+function serendipity_serverOffsetHour($timestamp = null, $negative = false) {
+    global $serendipity;
+
+    if ($timestamp == null) {
+        $timestamp = time();
+    }
+
+    if (empty($serendipity['serverOffsetHours']) || !is_numeric($serendipity['serverOffsetHours']) || $serendipity['serverOffsetHours'] == 0) {
+        return $timestamp;
+    } else {
+        return $timestamp + (($negative ? -$serendipity['serverOffsetHours'] : $serendipity['serverOffsetHours']) * 60 * 60);
+    }
+}
+
+function serendipity_strftime($format, $timestamp = null, $useOffset = true) {
+    if ($timestamp == null) {
+        $timestamp = serendipity_serverOffsetHour();
+    } elseif ($useOffset) {
+        $timestamp = serendipity_serverOffsetHour($timestamp);
+    }
+
+    return strftime($format, $timestamp);
+}
+
+function serendipity_formatTime($format, $time, $useOffset = true) {
+    static $cache;
+    if (!isset($cache)) {
+        $cache = array();
+    }
+
+    if (!isset($cache[$format])) {
+        $cache[$format] = $format;
+        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+            $cache[$format] = str_replace('%e', '%d', $cache[$format]);
+        }
+    }
+    return serendipity_mb('ucfirst', serendipity_strftime($cache[$format], (int)$time, $useOffset));
+}
+
+function serendipity_fetchTemplates() {
+    global $serendipity;
+    $dir = opendir($serendipity['serendipityPath'] . $serendipity['templatePath']);
+    while (($file = readdir($dir)) !== false) {
+        if (is_dir($serendipity['serendipityPath'] . $serendipity['templatePath'] . $file) && !ereg('^(\.|CVS)', $file) && !file_exists($serendipity['serendipityPath'] . $serendipity['templatePath'] . $file . '/inactive.txt') && file_exists($serendipity['serendipityPath'] . $serendipity['templatePath'] . $file . '/info.txt')) {
+            $rv[] = $file;
+        }
+    }
+    natcasesort($rv);
+    return $rv;
+}
+
+function serendipity_fetchTemplateInfo($theme) {
+    global $serendipity;
+
+    $lines = @file($serendipity['serendipityPath'] . $serendipity['templatePath'] . $theme . '/info.txt');
+    if ( !$lines ) {
+        return array();
+    }
+
+    for($x=0; $x<count($lines); $x++) {
+        $j = preg_split('/([^\:]+)\:/', $lines[$x], -1, PREG_SPLIT_DELIM_CAPTURE);
+        if ($j[2]) {
+            $currSec = $j[1];
+            $data[strtolower($currSec)][] = trim($j[2]);
+        } else {
+            $data[strtolower($currSec)][] = trim($j[0]);
+        }
+    }
+
+    foreach ($data as $k => $v) {
+        $data[$k] = implode("\n", $v);
+    }
+
+    return $data;
+}
+
+function serendipity_walkRecursive($ary, $child_name = 'id', $parent_name = 'parent_id', $parentid = 0, $depth = 0) {
+    global $serendipity;
+    static $_resArray;
+
+    if ( sizeof($ary) == 0 ) {
+        return array();
+    }
+
+    if ($parentid === VIEWMODE_THREADED) {
+        $parentid = 0;
+    }
+
+    if ( $depth == 0 ) {
+        $_resArray = array();
+    }
+
+    foreach ($ary as $data) {
+        if ($parentid === VIEWMODE_LINEAR || !isset($data[$parent_name]) || $data[$parent_name] == $parentid) {
+            $data['depth'] = $depth;
+            $_resArray[] = $data;
+            if ($data[$child_name] && $parentid !== VIEWMODE_LINEAR ) {
+                serendipity_walkRecursive($ary, $child_name, $parent_name, $data[$child_name], ($depth+1));
+            }
+        }
+    }
+
+    /* We are inside a recusive child, and we need to break out */
+    if ($depth !== 0) {
+        return true;
+    }
+
+    return $_resArray;
+}
+
+function serendipity_fetchUsers($user = '') {
+    global $serendipity;
+
+    $where = '';
+    if (!empty($user)) {
+        $where = "WHERE authorid = '" . (int)$user ."'";
+    }
+
+    $querystring = "SELECT * FROM {$serendipity['dbPrefix']}authors $where ORDER BY realname ASC";
+
+    return serendipity_db_query($querystring);
+}
+
+
+function serendipity_sendMail($to, $subject, $message, $fromMail, $headers = NULL, $fromName = NULL) {
+    global $serendipity;
+
+    if ( !is_null($headers) && !is_array($headers) ) {
+        trigger_error(__FUNCTION__ . ': $headers must be either an array or null', E_USER_ERROR);
+    }
+
+    if ( is_null($fromName) ) {
+        $fromName = $serendipity['blogTitle'];
+    }
+    
+    if ( is_null($fromMail) ) {
+        $fromMail = $to;
+    }
+    
+    // Fix special characters
+    $fromName = str_replace(array('"'), array("'"), $fromName);
+    
+    /* Prefix all mail with weblog title */
+    $subject = '['. $serendipity['blogTitle'] . '] '.  $subject;
+
+    /* Append signature to every mail */
+    $message .= "\n" . sprintf(SIGNATURE, $serendipity['blogTitle']);
+
+
+    /* Check for mb_* function, and use it to encode headers etc. */
+    if ( function_exists('mb_encode_mimeheader') ) {
+        // Funky mb_encode_mimeheader function insertes linebreaks after 74 chars.
+        // Most MTA I've personally spoken with told me they don't like this at all. ;)
+        // Regards to Mark Kronsbein for finding this issue!
+        $subject = str_replace(array("\n", "\r"), array('', ''), mb_encode_mimeheader($subject, LANG_CHARSET));
+        $fromName = str_replace(array("\n", "\r"), array('', ''), mb_encode_mimeheader($fromName, LANG_CHARSET));
+    }
+
+
+    /* Always add these headers */
+    $headers[] = 'From: "'. $fromName .'" <'. $fromMail .'>';
+    $headers[] = 'X-Mailer: Serendipity/'. $serendipity['version'];
+    $headers[] = 'X-Engine: PHP/'. phpversion();
+    $headers[] = 'Message-ID: <'. md5(microtime() . uniqid(time())) .'@'. $_SERVER['HTTP_HOST'] .'>';
+    $headers[] = 'MIME-Version: 1.0';
+    $headers[] = 'Content-Type: text/plain; charset="' . LANG_CHARSET .'"';
+
+    return mail($to, $subject, $message, implode("\n", $headers));
+}
+
+function serendipity_makeFilename($str) {
+    static $from = array(
+                     ' ',
+
+                     'Ä',
+                     'ä',
+
+                     'Ö',
+                     'ö',
+
+                     'Ü',
+                     'ü',
+
+                     'ß',
+
+                     'é',
+                     'è',
+                     'ê',
+
+                     'í',
+                     'ì',
+                     'î',
+
+                     'á',
+                     'à',
+                     'â',
+                     'å',
+
+                     'ó',
+                     'ò',
+                     'ô',
+                     'õ',
+
+                     'ú',
+                     'ù',
+                     'û',
+
+                     'ç',
+                     'Ç',
+
+                     'ñ',
+
+                     'ý');
+
+    static $to   = array(
+                     '-',
+
+                     'AE',
+                     'ae',
+
+                     'OE',
+                     'oe',
+
+                     'UE',
+                     'ue',
+
+                     'ss',
+
+                     'e',
+                     'e',
+                     'e',
+
+                     'i',
+                     'i',
+                     'i',
+
+                     'a',
+                     'a',
+                     'a',
+                     'a',
+
+                     'o',
+                     'o',
+                     'o',
+                     'o',
+
+                     'u',
+                     'u',
+                     'u',
+
+                     'c',
+                     'C',
+
+                     'n',
+
+                     'y');
+
+    // Replace international chars not detected by every locale
+    $str = str_replace($from, $to, $str);
+
+    // Nuke chars not allowed in our URI
+    $str = preg_replace('#[^' . PAT_FILENAME . ']#i', '', $str);
+
+    // Remove consecutive separators
+    $str = preg_replace('#'. $to[0] .'{2,}#s', $to[0], $str);
+
+    // Remove excess separators
+    $str = trim($str, $to[0]);
+
+    return $str;
+}
+
+function serendipity_fetchReferences($id) {
+    global $serendipity;
+
+    $query = "SELECT name,link FROM {$serendipity['dbPrefix']}references WHERE entry_id = '" . (int)$id . "'";
+
+    return serendipity_db_query($query);
+}
+
+
+function serendipity_utf8_encode($string) {
+    if (strtolower(LANG_CHARSET) != 'utf-8') {
+        if (function_exists('iconv')) {
+            return iconv(LANG_CHARSET, 'UTF-8', $string);
+        } else {
+            return utf8_encode($string);
+        }
+    } else {
+        return $string;
+    }
+}
+
+function serendipity_rss_getguid($entry, $comments = false) {
+    $guid = serendipity_archiveURL((isset($entry['entryid']) && $entry['entryid'] != '' ? $entry['entryid'] : $entry['id']), 'guid');
+    if ($comments == true) {
+        $guid .= '#c' . $entry['commentid'];
+    }
+
+    return $guid;
+}
+
+// jbalcorn: starter function to clean up xhtml for atom feed.  Add things to this as we find common
+//      mistakes, unless someone finds a better way to do this.
+//      DONE:
+//          since someone encoded all the urls, we can now assume any amp followed by
+//              whitespace or a HTML tag (i.e. &<br /> )should be
+//              encoded and most not with a space are intentional
+//      TODO:
+//          check ALL ampersands, find out if it's a valid code, and encode if not
+function xhtml_cleanup($html) {
+    static $p = array(
+        '/\&([\s\<])/',       // ampersand followed by whitespace or tag
+        '/\&$/',              // ampersand at end of body
+        '/<(br|hr|img)([^\/>]*)>/i',    // unclosed br tag - attributes included
+        '/\&nbsp;/'
+    );
+
+    static $r = array(
+        '&amp;\1',
+        '&amp;',
+        '<\1\2 />',
+        '&#160;'
+    );
+
+    return preg_replace($p, $r, $html);
+}
+
+/* Uses logic to figure out how the URI should look, based on current rewrite rule */
+function serendipity_rewriteURL($path, $key='baseURL') {
+    global $serendipity;
+    return $serendipity[$key] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '') . $path;
+}
+
+function serendipity_makePermalink($format, $data) {
+    static $keys = array('%id%', '%title%');
+    $replacements = array((int)$data['id'], serendipity_makeFilename($data['title']));
+    return str_replace($keys, $replacements, $format);
+}
+
+function serendipity_makePermalinkRegex($format) {
+    static $keys        = array('%id%', '%title%');
+    static $regexValues = array('([0-9]+)', '[0-9a-z\.\_!;,\+\-]+');
+    return str_replace($keys, $regexValues, preg_quote($format));
+}
+
+function serendipity_archiveURL($id, $title, $key = 'baseURL', $checkrewrite = true) {
+    $path = PATH_ARCHIVES . '/' . serendipity_makePermalink(PERM_ARCHIVES, array('id'=>$id, 'title' => $title));
+    if ( $checkrewrite ) {
+        $path = serendipity_rewriteURL($path, $key);
+    }
+    return $path;
+}
+
+function serendipity_archiveDateUrl($range, $summary=false, $key='baseURL') {
+    return serendipity_rewriteURL(PATH_ARCHIVES . '/' . $range . ($summary ? '/summary' : '') . '.html', $key);
+}
+
+function serendipity_fetchAuthor($author) {
+    global $serendipity;
+
+    return serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}authors WHERE " . (is_numeric($author) ? "authorid={$author};" : "username='" . serendipity_db_escape_string($author) . "';"));
+}
+
+/**
+* Split up a filename
+**/
+function serendipity_parseFileName($file) {
+    $x = explode('.', $file);
+    $suf = array_pop($x);
+    $f   = @implode('.', $x);
+    return array($f, $suf);
+}
+
+function serendipity_track_referrer($entry = 0) {
+    global $serendipity;
+
+    if (isset($_SERVER['HTTP_REFERER'])) {
+        if (stristr($_SERVER['HTTP_REFERER'], $serendipity['baseURL']) !== false) {
+            return;
+        }
+
+        if (!isset($serendipity['_blockReferer']) || !is_array($serendipity['_blockReferer'])) {
+            // Only generate an array once per call
+            $serendipity['_blockReferer'] = array();
+            $serendipity['_blockReferer'] = @explode(';', $serendipity['blockReferer']);
+        }
+
+        $url_parts  = parse_url($_SERVER['HTTP_REFERER']);
+        $host_parts = explode('.', $url_parts['host']);
+        if (!$url_parts['host'] ||
+            strstr($url_parts['host'], $_SERVER['SERVER_NAME'])) {
+            return;
+        }
+
+        foreach($serendipity['_blockReferer'] AS $idx => $hostname) {
+            if (@strstr($url_parts['host'], $hostname)) {
+                return;
+            }
+        }
+
+        if (rand(0, 100) < 1) {
+            serendipity_track_referrer_gc();
+        }
+
+        $ts       = serendipity_db_get_interval('ts');
+        $interval = serendipity_db_get_interval('interval', 900); 
+
+        $suppressq = "SELECT count(1)
+                      FROM $serendipity[dbPrefix]suppress
+                      WHERE ip = '" . serendipity_db_escape_string($_SERVER['REMOTE_ADDR']) . "'
+                      AND scheme = '" . serendipity_db_escape_string($url_parts['scheme']) . "'
+                      AND port = '" . serendipity_db_escape_string($url_parts['port']) . "'
+                      AND host = '" . serendipity_db_escape_string($url_parts['host']) . "'
+                      AND path = '" . serendipity_db_escape_string($url_parts['path']) . "'
+                      AND query = '" . serendipity_db_escape_string($url_parts['query']) . "'
+                      AND last > $ts - $interval";
+
+        $suppressp = "DELETE FROM $serendipity[dbPrefix]suppress
+                      WHERE ip = '" . serendipity_db_escape_string($_SERVER['REMOTE_ADDR']) . "'
+                      AND scheme = '" . serendipity_db_escape_string($url_parts['scheme']) . "'
+                      AND host = '" . serendipity_db_escape_string($url_parts['host']) . "'
+                      AND port = '" . serendipity_db_escape_string($url_parts['port']) . "'
+                      AND query = '" . serendipity_db_escape_string($url_parts['query']) . "'
+                      AND path = '" . serendipity_db_escape_string($url_parts['path']) . "'";
+        $suppressu = "INSERT INTO $serendipity[dbPrefix]suppress
+                      (ip, last, scheme, host, port, path, query)
+                      VALUES (
+                      '" . serendipity_db_escape_string($_SERVER['REMOTE_ADDR']) . "',
+                      $ts,
+                      '" . serendipity_db_escape_string($url_parts['scheme']) . "',
+                      '" . serendipity_db_escape_string($url_parts['host']) . "',
+                      '" . serendipity_db_escape_string($url_parts['port']) . "',
+                      '" . serendipity_db_escape_string($url_parts['path']) . "',
+                      '" . serendipity_db_escape_string($url_parts['query']) . "'
+                      )";
+
+        $count = serendipity_db_query($suppressq, true);
+
+        if ($count[0] == 0) {
+            serendipity_db_query($suppressu);
+            return;
+        }
+
+        serendipity_db_query($suppressp);
+        serendipity_db_query($suppressu);
+
+        serendipity_track_url('referrers', $_SERVER['HTTP_REFERER'], $entry);
+    }
+}
+
+function serendipity_track_referrer_gc() {
+    global $serendipity;
+
+    $ts       = serendipity_db_get_interval('ts');
+    $interval = serendipity_db_get_interval('interval', 900); 
+    $gc = "DELETE FROM $serendipity[dbPrefix]suppress WHERE last <= $ts - $interval";
+    serendipity_db_query($gc);
+}
+
+function serendipity_track_url($list, $url, $entry_id = 0) {
+    global $serendipity;
+
+    $url_parts = parse_url($url);
+
+    serendipity_db_query(
+      @sprintf(
+        "UPDATE %s%s
+            SET count = count + 1
+          WHERE scheme = '%s'
+            AND host   = '%s'
+            AND port   = '%s'
+            AND path   = '%s'
+            AND query  = '%s'
+            AND day    = '%s'
+            %s",
+
+        $serendipity['dbPrefix'],
+        $list,
+        serendipity_db_escape_string($url_parts['scheme']),
+        serendipity_db_escape_string($url_parts['host']),
+        serendipity_db_escape_string($url_parts['port']),
+        serendipity_db_escape_string($url_parts['path']),
+        serendipity_db_escape_string($url_parts['query']),
+        date('Y-m-d'),
+        ($entry_id != 0) ? "AND entry_id = '". (int)$entry_id ."'" : ''
+      )
+    );
+
+    if (serendipity_db_affected_rows() == 0) {
+        serendipity_db_query(
+          sprintf(
+            "INSERT INTO %s%s
+                    (entry_id, day, count, scheme, host, port, path, query)
+             VALUES (%d, '%s', 1, '%s', '%s', '%s', '%s', '%s')",
+
+            $serendipity['dbPrefix'],
+            $list,
+            (int)$entry_id,
+            date('Y-m-d'),
+            serendipity_db_escape_string($url_parts['scheme']),
+            serendipity_db_escape_string($url_parts['host']),
+            serendipity_db_escape_string($url_parts['port']),
+            serendipity_db_escape_string($url_parts['path']),
+            serendipity_db_escape_string($url_parts['query'])
+          )
+        );
+    }
+}
+
+function serendipity_displayTopReferrers($limit = 10, $use_links = true) {
+    serendipity_displayTopUrlList('referrers', $limit, $use_links);
+}
+
+function serendipity_displayTopExits($limit = 10, $use_links = true) {
+    serendipity_displayTopUrlList('exits', $limit, $use_links);
+}
+
+function serendipity_displayTopUrlList($list, $limit, $use_links = true) {
+    global $serendipity;
+
+    if ($limit){
+        $limit = serendipity_db_limit_sql($limit);
+    }
+
+    /* HACK */
+    if (preg_match('/^mysqli?/', $serendipity['dbType'])) {
+        /* Nonportable SQL due to MySQL date functions,
+         * but produces rolling 7 day totals, which is more
+         * interesting
+         */
+        $query = "SELECT scheme, host, SUM(count) AS total
+                  FROM {$serendipity['dbPrefix']}$list
+                  WHERE day > date_sub(current_date, interval 7 day)
+                  GROUP BY host
+                  ORDER BY total DESC, host
+                  $limit";
+    } else {
+        /* Portable version of the same query */
+        $query = "SELECT scheme, host, SUM(count) AS total
+                  FROM {$serendipity['dbPrefix']}$list
+                  GROUP BY scheme, host
+                  ORDER BY total DESC, host
+                  $limit";
+    }
+
+    $rows = serendipity_db_query($query);
+    echo "<span class='serendipityReferer'>";
+    if (is_array($rows)) {
+        foreach ($rows as $row) {
+            if ($use_links) {
+                printf(
+                    '<a href="%1$s://%2$s" title="%2$s" >%2$s</a> (%3$s)<br />',
+                    $row['scheme'],
+                    $row['host'],
+                    $row['total']
+                );
+            } else {
+                printf(
+                    '%1$s (%2$s)<br />',
+                    $row['host'],
+                    $row['total']
+                );
+            }
+        }
+    }
+    echo "</span>";
+}
+
+function serendipity_xhtml_target($target) {
+    global $serendipity;
+
+    if ($serendipity['enablePopup'] != true)
+        return "";
+
+    if ($serendipity['XHTML11']) {
+        return ' onclick="window.open(this.href, \'target' . time() . '\'); return false;" ';
+    } else {
+        return ' target="' . $target . '" ';
+    }
+}
+
+function serendipity_discover_rss($name, $ext) {
+    static $default = '2.0';
+
+    /* Detect type */
+    if ( $name == 'comments' ) {
+        $type = 'comments';
+    } else {
+        $type = 'content';
+    }
+
+    /* Detect version */
+    if ( $name == 'atom' || $ext == 'atom' ) {
+        $ver = 'atom0.3';
+    } elseif ( $name == 'opml' || $ext == 'opml' ) {
+        $ver = 'opml1.0';
+    } elseif ( $ext == 'rss' ) {
+        $ver = '0.91';
+    } elseif ( $ext == 'rss1' ) {
+        $ver = '1.0';
+    } else {
+        $ver = $default;
+    }
+
+    return array($ver, $type);
+}
+
+function serendipity_isResponseClean($d) {
+    return (strpos($d, "\r") === false && strpos($d, "\n") === false);
+}
+
+function serendipity_currentURL() {
+    global $serendipity;
+
+    // All that URL getting humpty-dumpty is necessary to allow a user to change the template in the
+    // articles view. POSTing data to that page only works with mod_rewrite and not the ErrorDocument
+    // redirection, so we need to generate the ErrorDocument-URI here.
+
+    $uri = parse_url($_SERVER['REQUEST_URI']);
+    $qst = '';
+    if (!empty($uri['query'])) {
+        $qst = '&amp;' . str_replace('&', '&amp;', $uri['query']);
+    }
+    $uri['path'] = str_replace($serendipity['serendipityHTTPPath'], '', $uri['path']);
+    $url = $serendipity['serendipityHTTPPath'] . $serendipity['indexFile'] . '?' . $uri['path'] . $qst;
+    $url = str_replace($serendipity['indexFile'] . '&amp;', '', $url); // Kill possible looped repitions which could occur
+
+    return $url;
+}
+
+function serendipity_getUriArguments($uri, $wildcard = false) {
+global $serendipity;
+
+    /* Explode the path into sections, to later be able to check for arguments and add our own */
+    preg_match('/^'. preg_quote($serendipity['serendipityHTTPPath'], '/') . '(' . preg_quote($serendipity['indexFile'], '/') . '\?\/)?(' . ($wildcard ? '.+' : '[a-z0-9\-*\/%\+]+') . ')/i', $uri, $_res);
+    if (strlen($_res[2]) != 0) {
+        $args = explode('/', $_res[2]);
+        if ($args[0] == 'index') {
+            unset($args[0]);
+        }
+        return $args;
+    } else {
+        return array();
+    }
+}
+
+define("serendipity_FUNCTIONS_LOADED", true);
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/functions_comments.inc.php b/include/functions_comments.inc.php
new file mode 100644 (file)
index 0000000..7b3be7d
--- /dev/null
@@ -0,0 +1,486 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+function serendipity_rememberComment() {
+    global $serendipity;
+
+    if (isset($serendipity['POST']['remember'])) {
+        serendipity_rememberCommentDetails(
+          array(
+            'url'      => $serendipity['POST']['url'],
+            'name'     => $serendipity['POST']['name'],
+            'email'    => $serendipity['POST']['email'],
+            'remember' => 'checked="checked"'
+          )
+        );
+    } elseif (isset($serendipity['POST']['comment'])) {
+        serendipity_forgetCommentDetails(array('url', 'name', 'email', 'remember'));
+    }
+}
+
+function serendipity_rememberCommentDetails($details) {
+    global $serendipity;
+
+    foreach ($details as $n => $v) {
+        serendipity_setCookie($n, $v);
+    }
+}
+
+function serendipity_forgetCommentDetails($keys) {
+    global $serendipity;
+    if (!$serendipity['COOKIE']) {
+        return;
+    }
+
+    foreach ($keys AS $n) {
+        serendipity_deleteCookie($n);
+    }
+}
+
+function serendipity_displayCommentForm($id, $url = '', $comments = NULL, $data = NULL, $showToolbar = true, $moderate_comments = true, $entry = null) {
+    global $serendipity;
+
+    if ($comments == NULL) {
+        $comments = serendipity_fetchComments($id);
+    }
+
+    $serendipity['smarty']->assign(
+      array(
+        'commentform_action'         => $url,
+        'commentform_id'             => $id,
+        'commentform_name'           => isset($data['name'])     ? $data['name']       : (isset($serendipity['COOKIE']['name'])     ? $serendipity['COOKIE']['name']     : ''),
+        'commentform_email'          => isset($data['email'])    ? $data['email']      : (isset($serendipity['COOKIE']['email'])    ? $serendipity['COOKIE']['email']    : ''),
+        'commentform_url'            => isset($data['url'])      ? $data['url']        : (isset($serendipity['COOKIE']['url'])      ? $serendipity['COOKIE']['url']      : ''),
+        'commentform_remember'       => isset($data['remember']) ? 'checked="checked"' : (isset($serendipity['COOKIE']['remember']) ? $serendipity['COOKIE']['remember'] : ''),
+        'commentform_replyTo'        => serendipity_generateCommentList($id, $comments, ((isset($data['replyTo']) && ($data['replyTo'])) ? $data['replyTo'] : 0)),
+        'commentform_subscribe'      => isset($data['subscribe']) ? 'checked="checked"' : '',
+        'commentform_data'           => isset($data['comment']) ? $data['comment'] : '',
+        'is_commentform_showToolbar' => $showToolbar,
+        'is_allowSubscriptions'      => $serendipity['allowSubscriptions'],
+        'is_moderate_comments'       => $moderate_comments,
+        'commentform_entry'          => $entry
+      )
+    );
+
+    serendipity_smarty_fetch('COMMENTFORM', 'commentform.tpl');
+}
+
+function serendipity_fetchComments($id, $limit = null, $order = '', $showAll = false) {
+    global $serendipity;
+    $and = '';
+
+    if (!empty($limit)) {
+        $limit = serendipity_db_limit_sql($limit);
+    } else {
+        $limit = '';
+    }
+
+    if (!empty($id)) {
+        $and .= " AND co.entry_id = '" . (int)$id ."'";
+    }
+
+    if (!$showAll) {
+        $and .= ' AND co.status = \'approved\'';
+    }
+
+    if ($serendipity['dbType'] == 'postgres') {
+        $group    = '';
+        $distinct = 'DISTINCT';
+    } else {
+        $group    = 'GROUP BY co.id';
+        $distinct = '';
+    }
+
+    $query = "SELECT $distinct
+                    co.id,
+                    co.entry_id, co.timestamp, co.title, co.email, co.url, co.ip, co.body, co.type, co.subscribed,
+                    co.author,
+                    e.title,
+                    e.id AS entryid,
+                    e.authorid,
+                    co.id AS commentid,
+                    co.parent_id AS parent_id
+              FROM
+                    {$serendipity['dbPrefix']}comments co
+                    LEFT JOIN {$serendipity['dbPrefix']}entries e ON (co.entry_id = e.id)
+              WHERE co.type LIKE 'NORMAL' AND co.entry_id > 0 $and
+              $group
+              ORDER BY
+                    co.id " . ($order != '' ? $order : '') . "
+                    $limit";
+
+    $comments = serendipity_db_query($query);
+
+    if (!is_array($comments)) {
+        return array();
+    }
+
+    serendipity_plugin_api::hook_event('fetchcomments', $comments);
+    return $comments;
+}
+
+function serendipity_generateCommentList($id, $comments = NULL, $selected = 0, $parent = 0, $level = 0, $indent = '') {
+    global $serendipity;
+
+    if (!is_array($comments)) {
+        if (empty($id)) {
+            $comments = array();
+        } else {
+            $comments = serendipity_fetchComments($id);
+        }
+    }
+
+    $retval = $parent ? '' : '<select id="serendipity_replyTo" name="serendipity[replyTo]"><option value="0">[ ' . TOP_LEVEL . ' ]</option>';
+    $i = 0;
+    foreach ($comments as $comment) {
+        if ($comment['parent_id'] == $parent) {
+            $i++;
+            $retval .= '<option value="' . $comment['id'] . '"'. ($selected == $comment['id'] || (isset($serendipity['POST']['replyTo']) && $comment['id'] == $serendipity['POST']['replyTo']) ? ' selected="selected"' : '') .'>' . str_repeat('&#160;', $level * 2) . '#' . $indent . $i . ': ' . (empty($comment['author']) ? ANONYMOUS : htmlspecialchars($comment['author'])) . ' ' . ON . ' ' . serendipity_mb('ucfirst', serendipity_strftime(DATE_FORMAT_SHORT, $comment['timestamp'])) . "</option>\n";
+            $retval .= serendipity_generateCommentList($id, $comments, $selected, $comment['id'], $level + 1, $indent . $i . '.');
+        }
+    }
+    $retval .= $parent ? '' : '</select>';
+
+    return $retval;
+}
+
+function serendipity_printComments($comments, $parentid = 0, $depth = 0, $trace = null) {
+    global $serendipity;
+    static $_smartyComments;
+
+    /* - $_smartyComments holds the ending smarty array.
+       - $depth is the current depth of the recurrence.
+       - $i is the position in the current depth. */
+
+    if ($parentid === VIEWMODE_THREADED) {
+        $parentid = 0;
+    }
+
+    /* Wait a second, we just got attacked by a call with level 0,
+       this must mean we've started over */
+    if ( $depth == 0 ) {
+        $_smartyComments = array();
+    }
+
+    $i = 0;
+    foreach ($comments as $comment) {
+        if ($parentid === VIEWMODE_LINEAR || !isset($comment['parent_id']) || $comment['parent_id'] == $parentid) {
+            $i++;
+
+            $comment['comment'] = htmlspecialchars(strip_tags($comment['body']));
+            $comment['url']     = strip_tags($comment['url']);
+            $comment['link_delete'] = $serendipity['baseURL'] . 'comment.php?serendipity[delete]=' . $comment['id'] . '&amp;serendipity[entry]=' . $comment['entry_id'] . '&amp;serendipity[type]=comments';
+
+            /* Fix fucked links */
+            if (!empty($comment['url']) && substr($comment['url'], 0, 7) != 'http://' && substr($comment['url'], 0, 8) != 'https://') {
+                $comment['url'] = 'http://' . $comment['url'];
+            }
+
+            serendipity_plugin_api::hook_event('frontend_display', $comment);
+
+            if (isset($comment['no_email']) && $comment['no_email']) {
+                $comment['email'] = false;
+            } elseif (!empty($comment['email'])) {
+                $comment['email'] = htmlspecialchars(str_replace('@', '[at]', $comment['email']));
+            }
+
+            $comment['body']    = $comment['comment'];
+            $comment['pos']     = $i;
+            $comment['trace']   = $trace . $i;
+            $comment['depth']   = $depth;
+            $comment['author']  = htmlspecialchars($comment['author']);
+
+            $_smartyComments[] = $comment;
+            if ($comment['id'] && $parentid !== VIEWMODE_LINEAR ) {
+                serendipity_printComments($comments, $comment['id'], ($depth+1), ($trace . $i . '.'));
+            }
+        }
+    }
+
+    /* We are inside a recusive child, and we need to break out */
+    if ($depth !== 0) {
+        return true;
+    }
+
+    $serendipity['smarty']->assign('comments', $_smartyComments);
+    unset($_smartyComments);
+
+    return serendipity_smarty_fetch('COMMENTS', 'comments.tpl');
+}
+
+function serendipity_deleteComment($id, $entry_id, $type='comments') {
+    global $serendipity;
+
+    if ($_SESSION['serendipityAuthedUser'] === true) {
+        $admin = '';
+        if ($_SESSION['serendipityUserlevel'] < USERLEVEL_CHIEF) {
+            $admin = " AND authorid = " . (int)$_SESSION['serendipityAuthorid'] ."'";
+        }
+
+        /* We have to figure out if the comment we are about to delete, is awaiting approval,
+           if so - we should *not* subtract it from the entries table */
+        $sql = serendipity_db_query("SELECT status, parent_id FROM {$serendipity['dbPrefix']}comments
+                                            WHERE entry_id = '". (int)$entry_id ."'
+                                                    AND id = '". (int)$id ."'
+                                                    $admin", true);
+
+        serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}comments
+                                    WHERE entry_id = '". (int)$entry_id ."'
+                                            AND id = '". (int)$id ."'
+                                            $admin");
+
+        if ($sql['status'] !== 'pending') {
+            serendipity_db_query("UPDATE {$serendipity['dbPrefix']}entries SET $type = $type-1 WHERE id = '". (int)$entry_id ."' $admin");
+        }
+
+        serendipity_db_query("UPDATE {$serendipity['dbPrefix']}comments SET parent_id = " . (int)$sql['parent_id'] . " WHERE parent_id = '" . (int)$id . "'");
+
+        return true;
+    } else {
+        return false;
+    }
+}
+
+function serendipity_allowCommentsToggle($entry_id, $switch = 'disable') {
+    global $serendipity;
+
+    if ($_SESSION['serendipityAuthedUser'] === true) {
+        $admin = '';
+        if ($_SESSION['serendipityUserlevel'] < USERLEVEL_CHIEF) {
+            $admin = " AND authorid = '" . (int)$_SESSION['serendipityAuthorid'] ."'";
+        }
+
+        $query = "UPDATE {$serendipity['dbPrefix']}entries SET allow_comments = '" . ($switch == 'disable' ? 'false' : 'true') . "' WHERE id = '". (int)$entry_id ."' $admin";
+        serendipity_db_query($query);
+        if (serendipity_isResponseClean($_SERVER['HTTP_REFERER'])) {
+            header('Location: '. $_SERVER['HTTP_REFERER']);
+        }
+    } else {
+        die('What are you up to? You need to be an admin to close comments');
+    }
+}
+
+function serendipity_approveComment($cid, $entry_id, $force = false) {
+    global $serendipity;
+
+    /* Get data about the comment, we need this query because this function can be called from anywhere */
+    /* This also makes sure we are either the author of the comment, or a USERLEVEL_ADMIN */
+    $sql = "SELECT c.*, e.title, a.email as authoremail, a.mail_comments, e.timestamp AS entry_timestamp, e.last_modified AS entry_last_modified
+                FROM {$serendipity['dbPrefix']}comments c
+                LEFT JOIN {$serendipity['dbPrefix']}entries e ON (e.id = c.entry_id)
+                LEFT JOIN {$serendipity['dbPrefix']}authors a ON (e.authorid = a.authorid)
+                WHERE c.id = '". (int)$cid ."'
+                    ". (($serendipity['serendipityUserlevel'] != USERLEVEL_ADMIN && $force !== true) ? "AND e.authorid = '". (int)$serendipity['authorid'] ."'" : '') ."
+                    ". (($force === true) ? "" : "AND status = 'pending'");
+    $rs  = serendipity_db_query($sql, true);
+
+    /* It's already approved, don't spam people */
+    if ( $rs === false ) {
+        return false;
+    }
+
+    $sql = "UPDATE {$serendipity['dbPrefix']}comments SET status = 'approved' WHERE id = ". (int)$cid;
+    serendipity_db_query($sql);
+
+    $field = ($rs['type'] == 'NORMAL' ? 'comments' : 'trackbacks');
+    // Check when the entry was published. If it is older than max_last_modified allows, the last_modified date of that entry
+    // will not be pushed. With this we make sure that an RSS feed will not be updated on a client's reader and marked as new
+    // only because someone made an comment to an old entry.
+    if ($rs['entry_timestamp'] > time() - $serendipity['max_last_modified']) {
+        $lm = time();
+    } else {
+        $lm = (int)$rs['entry_last_modified'];
+    }
+
+    $query = "UPDATE {$serendipity['dbPrefix']}entries SET $field=$field+1, last_modified=". $lm ." WHERE id='". (int)$entry_id ."'";
+    serendipity_db_query($query);
+
+    if ($serendipity['allowSubscriptions']) {
+        serendipity_mailSubscribers($entry_id, $rs['author'], $rs['email'], $rs['title'], $rs['authoremail']);
+    }
+    return true;
+}
+
+function serendipity_saveComment($id, $commentInfo, $type = 'NORMAL', $source = 'internal') {
+    global $serendipity;
+
+    $query = "SELECT id, allow_comments, moderate_comments, last_modified, timestamp FROM {$serendipity['dbPrefix']}entries WHERE id = '". (int)$id ."'";
+    $ca    = serendipity_db_query($query, true);
+
+    $commentInfo['type'] = $type;
+    $commentInfo['source'] = $source;
+    serendipity_plugin_api::hook_event('frontend_saveComment', $ca, $commentInfo);
+    if (!is_array($ca) || serendipity_db_bool($ca['allow_comments'])) {
+        $title         = serendipity_db_escape_string(isset($commentInfo['title']) ? $commentInfo['title'] : '');
+        $comments      = $commentInfo['comment'];
+        $ip            = serendipity_db_escape_string(isset($commentInfo['ip']) ? $commentInfo['ip'] : $_SERVER['REMOTE_ADDR']);
+        $commentsFixed = serendipity_db_escape_string($commentInfo['comment']);
+        $name          = serendipity_db_escape_string($commentInfo['name']);
+        $url           = serendipity_db_escape_string($commentInfo['url']);
+        $email         = serendipity_db_escape_string($commentInfo['email']);
+        $parentid      = (isset($commentInfo['parent_id']) && is_numeric($commentInfo['parent_id'])) ? $commentInfo['parent_id'] : 0;
+        $status        = serendipity_db_escape_string(isset($commentInfo['status']) ? $commentInfo['status'] : (serendipity_db_bool($ca['moderate_comments']) ? 'pending' : 'approved'));
+        $t             = serendipity_db_escape_string(isset($commentInfo['time']) ? $commentInfo['time'] : time());
+        $referer       = (isset($_SESSION['HTTP_REFERER']) ? serendipity_db_escape_string($_SESSION['HTTP_REFERER']) : '');
+
+        if (isset($commentInfo['subscribe'])) {
+            $subscribe = 'true';
+        } else {
+            $subscribe = 'false';
+        }
+
+        $query  = "INSERT INTO {$serendipity['dbPrefix']}comments (entry_id, parent_id, ip, author, email, url, body, type, timestamp, title, subscribed, status, referer)";
+        $query .= " VALUES ('". (int)$id ."', '$parentid', '$ip', '$name', '$email', '$url', '$commentsFixed', '$type', '$t', '$title', '$subscribe', '$status', '$referer')";
+
+        serendipity_db_query($query);
+        $cid = serendipity_db_insert_id('comments', 'id');
+
+        $query = "SELECT a.email, e.title, a.mail_comments, a.mail_trackbacks
+                 FROM {$serendipity['dbPrefix']}entries e, {$serendipity['dbPrefix']}authors a
+                 WHERE e.id  = '". (int)$id ."'
+                 AND e.authorid = a.authorid";
+        $row = serendipity_db_query($query, true); // Get info on author/entry
+
+        // Send mail to the author if he chose to receive these mails, or if the comment is awaiting moderation
+        if (serendipity_db_bool($ca['moderate_comments'])
+            || ($type == 'NORMAL' && serendipity_db_bool($row['mail_comments']))
+            || ($type == 'TRACKBACK' && serendipity_db_bool($row['mail_trackbacks']))) {
+            serendipity_sendComment($cid, $row['email'], $name, $email, $url, $id, $row['title'], $comments, $type, serendipity_db_bool($ca['moderate_comments']));
+        }
+
+        // Approve with force, if moderation is disabled
+        if (empty($ca['moderate_comments']) || serendipity_db_bool($ca['moderate_comments']) == false) {
+            serendipity_approveComment($cid, $id, true);
+        }
+        serendipity_purgeEntry($id, $t);
+        return true;
+    } else {
+        return false;
+    }
+}
+
+function serendipity_mailSubscribers($entry_id, $poster, $posterMail, $title, $fromEmail = 'none@example.com') {
+    global $serendipity;
+
+    $entryURI = serendipity_archiveURL($entry_id, $title, 'baseURL');
+    $subject =  sprintf(NEW_COMMENT_TO_SUBSCRIBED_ENTRY, $title);
+
+    $pgsql_insert = '';
+    $mysql_insert = '';
+    if ($serendipity['dbType'] == 'postgres') {
+        $pgsql_insert = 'DISTINCT ON (email)';
+    } else {
+        $mysql_insert = 'GROUP BY email';
+    }
+
+    $sql = "SELECT $pgsql_insert author, email, type
+            FROM {$serendipity['dbPrefix']}comments
+            WHERE entry_id = '". (int)$entry_id ."'
+              AND email <> '" . serendipity_db_escape_string($posterMail) . "'
+              AND subscribed = 'true' $mysql_insert";
+    $subscribers = serendipity_db_query($sql);
+
+    if (!is_array($subscribers)) {
+        return;
+    }
+
+    foreach ($subscribers as $subscriber) {
+        if ($subscriber['type'] == 'TRACKBACK') {
+            $text = sprintf(
+                      SUBSCRIPTION_TRACKBACK_MAIL,
+
+                      $subscriber['author'],
+                      $serendipity['blogTitle'],
+                      $title,
+                      $poster,
+                      $entryURI,
+                      serendipity_rewriteURL('unsubscribe/' . urlencode($subscriber['email']) . '/' . (int)$entry_id, 'baseURL')
+            );
+        } else {
+            $text = sprintf(
+                      SUBSCRIPTION_MAIL,
+
+                      $subscriber['author'],
+                      $serendipity['blogTitle'],
+                      $title,
+                      $poster,
+                      $entryURI,
+                      serendipity_rewriteURL('unsubscribe/' . urlencode($subscriber['email']) . '/' . (int)$entry_id, 'baseURL')
+            );
+        }
+
+        serendipity_sendMail($subscriber['email'], $subject, $text, $fromEmail);
+    }
+}
+
+function serendipity_cancelSubscription($email, $entry_id) {
+    global $serendipity;
+    $sql = "UPDATE {$serendipity['dbPrefix']}comments
+                SET subscribed = 'false'
+            WHERE entry_id = '". (int)$entry_id ."'
+                AND email = '" . serendipity_db_escape_string($email) . "'";
+    serendipity_db_query($sql);
+
+    return serendipity_db_affected_rows();
+}
+
+function serendipity_sendComment($comment_id, $to, $fromName, $fromEmail, $fromUrl, $id, $title, $comment, $type = 'NORMAL', $moderate_comment = false) {
+    global $serendipity;
+
+    if (empty($fromName)) {
+        $fromName = ANONYMOUS;
+    }
+
+    $entryURI = serendipity_archiveURL($id, $title, 'baseURL');
+    $path = ($type == 'TRACKBACK') ? 'trackback' : 'comment';
+    $deleteURI = serendipity_rewriteURL(PATH_DELETE . '/'. $path .'/' . $comment_id . '/'. $id .'_' . serendipity_makeFilename($title)  . '.html', 'baseURL');
+    $approveURI = serendipity_rewriteURL(PATH_APPROVE . '/'. $path .'/' . $comment_id . '/'. $id .'_' . serendipity_makeFilename($title)  . '.html', 'baseURL');
+
+    if ($type == 'TRACKBACK') {
+
+        /******************* TRACKBACKS *******************/
+        $subject =  ($moderate_comment ? '[' . REQUIRES_REVIEW . '] ' : '') . NEW_TRACKBACK_TO . ' ' . $title;
+        $text = sprintf(A_NEW_TRACKBACK_BLAHBLAH, $title)
+              . "\n"
+              . "\n" . REQUIRES_REVIEW          . ': ' . (($moderate_comment) ? YES : NO) . (isset($serendipity['moderate_reason']) ? ' (' . $serendipity['moderate_reason'] . ')' : '')
+              . "\n" . LINK_TO_ENTRY            . ': ' . $entryURI
+              . "\n" . 'Weblog ' . NAME         . ': ' . stripslashes($fromName)
+              . "\n" . LINK_TO_REMOTE_ENTRY     . ': ' . $fromUrl
+              . "\n"
+              . "\n" . EXCERPT . ':'
+              . "\n" . strip_tags($comment)
+              . "\n"
+              . "\n" . '----'
+              . "\n" . YOU_HAVE_THESE_OPTIONS
+              . (($moderate_comment) ? "\n" . str_repeat(' ', 2) . THIS_TRACKBACK_NEEDS_REVIEW : '')
+              . "\n" . str_repeat(' ', 3) . str_pad(VIEW_ENTRY,  15) . ' -- '. $entryURI
+              . "\n" . str_repeat(' ', 3) . str_pad(DELETE_TRACKBACK,  15) . ' -- '. $deleteURI
+              . (($moderate_comment) ? "\n" . str_repeat(' ', 3) . str_pad(APPROVE_TRACKBACK, 15) . ' -- '. $approveURI : '');
+
+    } else {
+
+        /******************* COMMENTS *********************/
+        $subject = ($moderate_comment ? '[' . REQUIRES_REVIEW . '] ' : '') . NEW_COMMENT_TO . ' ' . $title;
+        $text = sprintf(A_NEW_COMMENT_BLAHBLAH, $serendipity['blogTitle'], $title)
+              . "\n" . LINK_TO_ENTRY . ': ' . $entryURI
+              . "\n"
+              . "\n" . REQUIRES_REVIEW         . ': ' . (($moderate_comment) ? YES : NO) . (isset($serendipity['moderate_reason']) ? ' (' . $serendipity['moderate_reason'] . ')' : '')
+              . "\n" . USER . ' ' . IP_ADDRESS . ': ' . $_SERVER['REMOTE_ADDR']
+              . "\n" . USER . ' ' . NAME       . ': ' . $fromName
+              . "\n" . USER . ' ' . EMAIL      . ': ' . $fromEmail
+              . "\n" . USER . ' ' . HOMEPAGE   . ': ' . $fromUrl
+              . "\n"
+              . "\n" . COMMENTS                . ': '
+              . "\n" . strip_tags($comment)
+              . "\n"
+              . "\n" . '----'
+              . "\n" . YOU_HAVE_THESE_OPTIONS
+              . (($moderate_comment) ? "\n" . str_repeat(' ', 2) . THIS_COMMENT_NEEDS_REVIEW : '')
+              . "\n" . str_repeat(' ', 3) . str_pad(VIEW_COMMENT,  15) . ' -- '. $entryURI .'#c'. $comment_id
+              . "\n" . str_repeat(' ', 3) . str_pad(DELETE_COMMENT,  15) . ' -- '. $deleteURI
+              . (($moderate_comment) ? "\n" . str_repeat(' ', 3) . str_pad(APPROVE_COMMENT, 15) . ' -- '. $approveURI : '');
+    }
+
+    return serendipity_sendMail($to, $subject, $text, $fromEmail);
+}
diff --git a/include/functions_config.inc.php b/include/functions_config.inc.php
new file mode 100644 (file)
index 0000000..7d353d2
--- /dev/null
@@ -0,0 +1,490 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+function serendipity_addAuthor($username, $password, $realname, $email, $userlevel=0) {
+    global $serendipity;
+    $password = md5($password);
+    $query = "INSERT INTO {$serendipity['dbPrefix']}authors (username, password, realname, email, userlevel)
+                        VALUES  ('" . serendipity_db_escape_string($username) . "',
+                                 '" . serendipity_db_escape_String($password) . "',
+                                 '" . serendipity_db_escape_String($realname) . "',
+                                 '" . serendipity_db_escape_String($email) . "',
+                                 '" . serendipity_db_escape_String($userlevel) . "')";
+    serendipity_db_query($query);
+    return serendipity_db_insert_id('authors', 'authorid');
+}
+
+function serendipity_deleteAuthor($authorid) {
+    global $serendipity;
+    serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}authors WHERE authorid=" . (int)$authorid ." and userlevel <= ". (int)$serendipity['serendipityUserlevel']);
+    return true;
+}
+
+function serendipity_remove_config_var($name, $authorid = 0) {
+    global $serendipity;
+    serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}config where name='" . serendipity_db_escape_string($name) . "' AND authorid = " . (int)$authorid);
+}
+
+function serendipity_set_config_var($name, $val, $authorid = 0) {
+    global $serendipity;
+
+    serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}config where name='" . serendipity_db_escape_string($name) . "' AND authorid = " . (int)$authorid);
+    $r = serendipity_db_insert('config', array('name' => $name, 'value' => $val, 'authorid' => $authorid));
+    $serendipity[$name] = $val;
+    if (is_string($r)) {
+        echo $r;
+    }
+}
+
+function serendipity_get_config_var($name, $defval = false, $empty = false) {
+    global $serendipity;
+    if (isset($serendipity[$name])) {
+        if ($empty && gettype($serendipity[$name]) == 'string' && $serendipity[$name] === '') {
+            return $defval;
+        } else {
+            return $serendipity[$name];
+        }
+    } else {
+        return $defval;
+    }
+}
+
+function serendipity_get_user_config_var($name, $authorid, $default = '') {
+    global $serendipity;
+
+    $author_sql = '';
+    if (!empty($authorid)) {
+        $author_sql = "authorid = " . (int)$authorid . " AND ";
+    }
+
+    $r = serendipity_db_query("SELECT value FROM {$serendipity['dbPrefix']}config WHERE $author_sql name = '" . $name . "' LIMIT 1", true);
+
+    if (is_array($r)) {
+        return $r[0];
+    } else {
+        return $default;
+    }
+}
+
+function serendipity_get_user_var($name, $authorid, $default) {
+    global $serendipity;
+
+    $r = serendipity_db_query("SELECT $name FROM {$serendipity['dbPrefix']}authors WHERE authorid = " . (int)$authorid, true);
+
+    if (is_array($r)) {
+        return $r[0];
+    } else {
+        return $default;
+    }
+}
+
+function serendipity_set_user_var($name, $val, $authorid, $copy_to_s9y = true) {
+    global $serendipity;
+
+    // When inserting a DB value, this array maps the new values to the corresponding s9y variables
+    static $user_map_array = array(
+        'username'  => 'serendipityUser',
+        'email'     => 'serendipityEmail',
+        'userlevel' => 'serendipityUserlevel'
+    );
+
+    // Special case for inserting a password
+    switch($name) {
+        case 'password':
+            if (empty($val)) {
+                return;
+            }
+
+            $val = md5($val);
+            $copy_to_s9y = false;
+            break;
+
+        case 'right_publish':
+        case 'mail_comments':
+        case 'mail_trackbacks':
+            $val = (serendipity_db_bool($val) ? 1 : '0');
+            break;
+    }
+
+    serendipity_db_query("UPDATE {$serendipity['dbPrefix']}authors SET $name = '" . serendipity_db_escape_string($val) . "' WHERE authorid = " . (int)$authorid);
+
+    if ($copy_to_s9y) {
+        if (isset($user_map_array[$name])) {
+            $key = $user_map_array[$name];
+        } else {
+            $key = 'serendipity' . ucfirst($name);
+        }
+
+        $_SESSION[$key] = $serendipity[$key] = $val;
+    }
+}
+
+function serendipity_getTemplateFile($file, $key = 'serendipityHTTPPath') {
+    global $serendipity;
+
+    $directories = array();
+
+    $directories[] = isset($serendipity['template']) ? $serendipity['template'] . '/' : '';
+    if ( isset($serendipity['template_engine']) ) {
+         $directories[] = $serendipity['template_engine'] . '/';
+    }
+    $directories[] = $serendipity['defaultTemplate'] .'/';
+    $directories[] = 'default/';
+
+    foreach ($directories as $directory) {
+        $templateFile = $serendipity['templatePath'] . $directory . $file;
+
+        if (file_exists($serendipity['serendipityPath'] . $templateFile)) {
+            return $serendipity[$key] . $templateFile;
+        }
+    }
+    return false;
+}
+
+function serendipity_load_configuration($author = null) {
+    global $serendipity;
+
+    if (!empty($author)) {
+        // Replace default configuration directives with user-relevant data
+        $rows = serendipity_db_query("SELECT name,value
+                                        FROM {$serendipity['dbPrefix']}config
+                                        WHERE authorid = '". (int)$author ."'");
+    } else {
+        // Only get default variables, user-independent (frontend)
+        $rows = serendipity_db_query("SELECT name,value
+                                        FROM {$serendipity['dbPrefix']}config
+                                        WHERE authorid = 0");
+    }
+
+    if (is_array($rows)) {
+        foreach ($rows as $row) {
+            // Convert 'true' and 'false' into booleans
+            $serendipity[$row['name']] = serendipity_get_bool($row['value']);
+        }
+    }
+}
+
+function serendipity_logout() {
+    $_SESSION['serendipityAuthedUser'] = false;
+    @session_destroy();
+    serendipity_deleteCookie('author_information');
+}
+
+function serendipity_login($use_external = true) {
+    global $serendipity;
+
+    if (serendipity_authenticate_author('', '', false, $use_external)) {
+        #The session has this data already
+        #we previously just checked the value of $_SESSION['serendipityAuthedUser'] but
+        #we need the authorid still, so call serendipity_authenticate_author with blank
+        #params
+        return true;
+    }
+
+    if (serendipity_authenticate_author($serendipity['POST']['user'], $serendipity['POST']['pass'], false, $use_external)) {
+        if (empty($serendipity['POST']['auto'])) {
+            serendipity_deleteCookie('author_information');
+            return false;
+        } else {
+            $package = serialize(array('username' => $serendipity['POST']['user'],
+                                       'password' => $serendipity['POST']['pass']));
+            serendipity_setCookie('author_information', base64_encode($package));
+            return true;
+        }
+    } elseif ( isset($serendipity['COOKIE']['author_information']) ) {
+        $cookie = unserialize(base64_decode($serendipity['COOKIE']['author_information']));
+        if (serendipity_authenticate_author($cookie['username'], $cookie['password'], $use_external)) {
+            return true;
+        } else {
+            serendipity_deleteCookie('author_information');
+            return false;
+        }
+    }
+}
+
+function serendipity_userLoggedIn() {
+    if ($_SESSION['serendipityAuthedUser'] === true && IS_installed) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+function serendipity_restoreVar(&$source, &$target) {
+    global $serendipity;
+
+    if (isset($source) && !isset($target)) {
+        $target = $source;
+        return true;
+    }
+
+    return false;
+}
+
+function serendipity_JSsetCookie($name, $value) {
+    $name  = str_replace('"', '\"', $name);
+    $value = str_replace('"', '\"', $value);
+
+    echo '<script type="text/javascript">SetCookie("' . $name . '", "' . $value . '")</script>' . "\n";
+}
+
+function serendipity_setCookie($name,$value) {
+    global $serendipity;
+
+    setcookie("serendipity[$name]", $value, time()+60*60*24*30, $serendipity['serendipityHTTPPath']);
+    $_COOKIE[$name] = $value;
+    $serendipity['COOKIE'][$name] = $value;
+}
+
+function serendipity_deleteCookie($name) {
+    global $serendipity;
+
+    setcookie("serendipity[$name]", '', time()-4000);
+    unset($_COOKIE[$name]);
+    unset($serendipity['COOKIE'][$name]);
+}
+
+function serendipity_authenticate_author($username = '', $password = '', $is_md5 = false, $use_external = true) {
+    global $serendipity;
+
+    if (isset($_SESSION['serendipityUser']) && isset($_SESSION['serendipityPassword']) && isset($_SESSION['serendipityAuthedUser']) && $_SESSION['serendipityAuthedUser'] == true) {
+        $username = $_SESSION['serendipityUser'];
+        $password = $_SESSION['serendipityPassword'];
+        // For safety reasons when multiple blogs are installed on the same host, we need to check the current author each time to not let him log into a different blog with the same sessiondata
+        $is_md5 = true;
+    }
+
+    if ($username != '') {
+        if ($use_external) {
+            serendipity_plugin_api::hook_event('backend_auth', $is_md5, array('username' => $username, 'password' => $password));
+        }
+
+        if ($is_md5 === false && !empty($password)) {
+            $password = md5($password);
+        }
+
+        $query = "SELECT DISTINCT
+                    email, authorid, userlevel, right_publish
+                  FROM
+                    $serendipity[dbPrefix]authors
+                  WHERE
+                    username   = '" . serendipity_db_escape_string($username) . "'
+                  AND password = '" . serendipity_db_escape_string($password) . "'";
+        $row = serendipity_db_query($query, true, 'assoc');
+
+        if (is_array($row)) {
+            $_SESSION['serendipityUser']        = $serendipity['serendipityUser']         = $username;
+            $_SESSION['serendipityPassword']    = $serendipity['serendipityPassword']     = $password;
+            $_SESSION['serendipityEmail']       = $serendipity['serendipityEmail']        = $row['email'];
+            $_SESSION['serendipityAuthorid']    = $serendipity['authorid']                = $row['authorid'];
+            $_SESSION['serendipityUserlevel']   = $serendipity['serendipityUserlevel']    = $row['userlevel'];
+            $_SESSION['serendipityAuthedUser']  = $serendipity['serendipityAuthedUser']   = true;
+            $_SESSION['serendipityRightPublish']= $serendipity['serendipityRightPublish'] = $row['right_publish'];
+            serendipity_load_configuration($serendipity['authorid']);
+            return true;
+        } else {
+            $_SESSION['serendipityAuthedUser'] = false;
+            @session_destroy();
+        }
+    }
+
+    return false;
+}
+
+function serendipity_is_iframe() {
+    global $serendipity;
+
+    if ($serendipity['GET']['is_iframe'] && is_array($_SESSION['save_entry'])) {
+        // An iframe may NOT contain <html> and </html> tags, that's why we emit different headers here than on serendipity_admin.php
+?>
+    <head>
+        <title><?php echo SERENDIPITY_ADMIN_SUITE; ?></title>
+        <meta http-equiv="Content-Type" content="text/html; charset=<?php echo LANG_CHARSET; ?>" />
+        <link rel="stylesheet" type="text/css" href="<?php echo (isset($serendipity['serendipityHTTPPath']) ? $serendipity['serendipityHTTPPath'] : ''); ?>serendipity.css.php" />
+        <script type="text/javascript">
+           window.onload = function() {
+             parent.document.getElementById('serendipity_iframe').style.height = document.getElementById('mainpane').offsetHeight
+                                                                               + parseInt(document.getElementById('mainpane').style.marginTop)
+                                                                               + parseInt(document.getElementById('mainpane').style.marginBottom)
+                                                                               + 'px';
+             parent.document.getElementById('serendipity_iframe').scrolling    = 'no';
+             parent.document.getElementById('serendipity_iframe').style.border = 0;
+           }
+        </script>
+    </head>
+
+    <body style="padding: 0px; margin: 0px;">
+        <div id="mainpane" style="padding: 0px; margin: 5px auto 5px auto; width: 98%;">
+            <div id="content" style="padding: 5px; margin: 0px;">
+<?php
+        // We need to restore GET/POST variables to that depending plugins inside the iframe
+        // can still fetch all that variables; and we also tighten security by not allowing
+        // to pass any different GET/POST variables to our iframe.
+        $iframe_mode         = $serendipity['GET']['iframe_mode'];
+        $serendipity['POST'] = &$_SESSION['save_entry_POST'];
+        $serendipity['GET']  = &$_SESSION['save_entry_POST']; // GET-Vars are the same as POST to ensure compatibility.
+        ignore_user_abort(true);
+        serendipity_iframe($_SESSION['save_entry'], $iframe_mode);
+?>
+            </div>
+        </div>
+    </body>
+<?php
+        return true;
+    }
+    return false;
+}
+
+function serendipity_iframe(&$entry, $mode = null) {
+    global $serendipity;
+
+    if (empty($mode) || !is_array($entry)) {
+        return false;
+    }
+
+    switch ($mode) {
+        case 'save':
+            echo '<div style="float: left; height: 75px"></div>';
+            $res = serendipity_updertEntry($entry);
+
+            if (is_string($res)) {
+                echo '<div class="serendipity_msg_error">' . ERROR . ': <b>' . $res . '</b></div>';
+            } else {
+                if (!empty($serendipity['lastSavedEntry'])) {
+                    // Last saved entry must be propagated to entry form so that if the user re-edits it,
+                    // it needs to be stored with the new ID.
+                    echo '<script type="text/javascript">parent.document.forms[\'serendipityEntry\'][\'serendipity[id]\'].value = "' . $serendipity['lastSavedEntry'] . '";</script>';
+                }
+                echo '<div class="serendipityAdminMsgSuccess">' . ENTRY_SAVED . '</div>';
+            }
+            echo '<br style="clear: both" />';
+
+            return true;
+            break;
+
+        case 'preview':
+            echo '<div style="float: left; height: 225px"></div>';
+            $serendipity['smarty_raw_mode'] = true; // Force output of Smarty stuff in the backend
+            serendipity_smarty_init();
+            $serendipity['smarty']->assign('is_preview',  true);
+
+            serendipity_printEntries(array($entry), ($entry['extended'] != '' ? 1 : 0), true);
+            echo '<br style="clear: both" />';
+
+            return true;
+            break;
+    }
+
+    return false;
+}
+
+function serendipity_iframe_create($mode, &$entry) {
+    global $serendipity;
+
+    if (!empty($serendipity['POST']['no_save'])) {
+        return true;
+    }
+
+    $_SESSION['save_entry']      = $entry;
+    $_SESSION['save_entry_POST'] = $serendipity['POST'];
+
+    $attr = '';
+    switch($mode) {
+        case 'save':
+            $attr = ' height="100" ';
+            break;
+
+        case 'preview':
+            $attr = ' height="300" ';
+            break;
+    }
+
+    echo '<iframe src="serendipity_admin.php?serendipity[is_iframe]=true&amp;serendipity[iframe_mode]=' . $mode . '" id="serendipity_iframe" name="serendipity_iframe" ' . $attr . ' width="100%" frameborder="0" marginwidth="0" marginheight="0" scrolling="auto" title="Serendipity">'
+         . IFRAME_WARNING
+         . '</iframe><br /><br />';
+}
+
+function serendipity_probeInstallation($item) {
+    global $serendipity;
+    $res = NULL;
+
+    switch ( $item ) {
+        case 'dbType' :
+            $res =  array();
+            if (extension_loaded('mysql')) {
+                $res['mysql'] = 'MySQL';
+            }
+            if (extension_loaded('pgsql')) {
+                $res['postgres'] = 'PostgreSQL';
+            }
+            if (extension_loaded('mysqli')) {
+                $res['mysqli'] = 'MySQLi';
+            }
+            if (extension_loaded('sqlite')) {
+                $res['sqlite'] = 'SQLite';
+            }
+            break;
+
+        case 'rewrite' :
+            $res = array();
+            $res['none'] = 'Disable URL Rewriting';
+            $res['errordocs'] = 'Use Apache errorhandling';
+            if( !function_exists('apache_get_modules') || in_array('mod_rewrite', apache_get_modules()) ) {
+                $res['rewrite'] = 'Use Apache mod_rewrite';
+            }
+            break;
+    }
+
+    return $res;
+}
+
+function serendipity_header($header) {
+    if (!headers_sent()) {
+        header($header);
+    }
+}
+
+/* TODO:
+  This previously was handled inside a plugin with an event hook, but caching
+  the event plugins that early in sequence created trouble with plugins not
+  having loaded the right language.
+  Find a way to let plugins hook into that sequence :-) */
+function serendipity_getSessionLanguage() {
+    global $serendipity;
+
+    if ($_SESSION['serendipityAuthedUser']) {
+        serendipity_header('X-Serendipity-InterfaceLangSource: Database');
+        return $serendipity['lang'];
+    }
+
+    if (isset($_REQUEST['user_language']) && (!empty($serendipity['languages'][$_REQUEST['user_language']])) && !headers_sent()) {
+        serendipity_setCookie('serendipityLanguage', $_REQUEST['user_language']);
+    }
+
+    if (isset($serendipity['COOKIE']['serendipityLanguage'])) {
+        serendipity_header('X-Serendipity-InterfaceLangSource: Cookie');
+        $lang = $serendipity['COOKIE']['serendipityLanguage'];
+    } elseif (!empty($serendipity['languages'][$serendipity['GET']['lang_selected']])) {
+        serendipity_header('X-Serendipity-InterfaceLangSource: GET');
+        $lang = $serendipity['GET']['lang_selected'];
+    } elseif (serendipity_db_bool($serendipity['lang_content_negotiation'])) {
+        serendipity_header('X-Serendipity-InterfaceLangSource: Content-Negotiation');
+        $lang = serendipity_detectLang();
+    }
+
+    if (!isset($lang) || !isset($serendipity['languages'][$lang])) {
+        $lang = $serendipity['lang'];
+    }
+
+    serendipity_header('X-Serendipity-InterfaceLang: ' . $lang);
+
+    if ($lang != $serendipity['lang']) {
+        $serendipity['content_lang'] = $lang;
+    }
+
+    return $lang;
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/functions_entries.inc.php b/include/functions_entries.inc.php
new file mode 100644 (file)
index 0000000..5c9f133
--- /dev/null
@@ -0,0 +1,1666 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+function serendipity_fetchCategoryRange($categoryid) {
+    global $serendipity;
+
+    $res = serendipity_db_query("SELECT category_left, category_right FROM {$serendipity['dbPrefix']}category WHERE categoryid='". (int)$categoryid ."'");
+    if (!is_array($res) || !isset($res[0]['category_left']) || !isset($res[0]['category_right'])) {
+        $res = array(array('category_left' => 0, 'category_right' => 0));
+    }
+
+    return array('category_left' => $res[0]['category_left'], 'category_right' => $res[0]['category_right']);
+}
+
+function serendipity_fetchCategoryInfo($categoryid, $categoryname = '') {
+    global $serendipity;
+
+    if (!empty($categoryname)) {
+        $query = "SELECT
+                         c.authorid,
+                         c.categoryid,
+                         c.category_name,
+                         c.category_description,
+                         c.category_icon,
+                         c.parentid
+                    FROM {$serendipity['dbPrefix']}category AS c
+                   WHERE category_name = '" . serendipity_db_escape_string($categoryname) . "'";
+
+        $ret = serendipity_db_query($query);
+        return $ret[0];
+    } else if (is_numeric($categoryid)) {
+        $query = "SELECT
+                         c.authorid,
+                         c.categoryid,
+                         c.category_name,
+                         c.category_description,
+                         c.category_icon,
+                         c.parentid
+                    FROM {$serendipity['dbPrefix']}category AS c
+                   WHERE categoryid = {$categoryid}";
+
+        $ret = serendipity_db_query($query);
+        return $ret[0];
+    }
+}
+
+function serendipity_fetchEntryCategories($entryid) {
+  global $serendipity;
+
+    if (is_numeric($entryid)) {
+        $query = "SELECT
+                         c.categoryid,
+                         c.category_name,
+                         c.category_description,
+                         c.category_icon,
+                         c.parentid
+                    FROM {$serendipity['dbPrefix']}category AS c
+              INNER JOIN {$serendipity['dbPrefix']}entrycat AS ec
+                      ON ec.categoryid = c.categoryid
+                   WHERE ec.entryid = {$entryid}";
+
+        $cat = serendipity_db_query($query);
+        if (!is_array($cat)) {
+            return array();
+        } else {
+            return $cat;
+        }
+    }
+}
+
+
+/**
+* Give it a range in YYYYMMDD format to gather the desired entries
+* (For february 2002 you would pass 200202 for all entries withing
+* two timestamps you would pass array(timestamp1,timestamp2)
+**/
+function serendipity_fetchEntries($range = null, $full = true, $limit = '', $fetchDrafts = false, $modified_since = false, $orderby = 'timestamp DESC', $filter_sql = '', $noCache = false, $noSticky = false) {
+    global $serendipity;
+
+    $cond = array();
+    $cond['orderby'] = $orderby;
+    if (isset($serendipity['short_archives']) && $serendipity['short_archives']) {
+        // In the short listing of all titles for a month, we don't want to have a limit applied. And we don't need/want toe
+        // full article body (consumes memory)
+        $limit   = '';
+        $full    = false;
+    }
+
+    if ($full === true) {
+        $noCache = true; // So no entryproperties related to body/extended caching will be loaded
+        $body = ', e.body, e.extended';
+    } else {
+        $body = '';
+    }
+
+    if ($fetchDrafts === false) {
+        $drafts = "isdraft = 'false'";
+    }
+
+    if ($limit != '') {
+        $serendipity['fetchLimit'] = $limit;
+    }
+
+    /* Attempt to grab range from $serendipity, if $range is not an array or null */
+    if (!is_array($range) && !is_null($range) && isset($serendipity['range'])) {
+        $range = $serendipity['range'];
+    }
+
+    if (is_numeric($range)) {
+        $year  = (int)substr($range, 0, 4);
+        $month = (int)substr($range, 4, 2);
+        $day   = (int)substr($range, 6, 2);
+
+        $startts = serendipity_serverOffsetHour(mktime(0, 0, 0, $month, ($day == 0 ? 1 : $day), $year), true);
+
+        if ($day == 0) {
+            $month++;
+        } else {
+            $day++;
+        }
+
+        $endts = serendipity_serverOffsetHour(mktime(0, 0, 0, $month, ($day == 0 ? 1 : $day), $year), true);
+
+        $cond['and'] = " WHERE timestamp >= $startts AND timestamp <= $endts";
+    } elseif (is_array($range) && count($range)==2) {
+        $startts = serendipity_serverOffsetHour((int)$range[0], true);
+        $endts   = serendipity_serverOffsetHour((int)$range[1], true);
+        $cond['and'] = " WHERE timestamp >= $startts AND timestamp <= $endts";
+    } else {
+        if ($modified_since) {
+            $unix_modified = strtotime($modified_since);
+            if ($unix_modified != -1) {
+                $cond['and'] = ' WHERE last_modified >= ' . (int)$unix_modified;
+                if (!empty($limit)) {
+                    $limit = ($limit > $serendipity['max_fetch_limit'] ? $limit : $serendipity['max_fetch_limit']);
+                }
+                $cond['orderby'] = 'last_modified DESC';
+            }
+        }
+    }
+
+    if (!empty($drafts)) {
+        if (!empty($cond['and'])) {
+            $cond['and'] .= " AND $drafts";
+        } else {
+            $cond['and'] = "WHERE $drafts";
+        }
+    }
+
+    if (isset($serendipity['GET']['viewAuthor'])) {
+        $cond['and'] .= " AND e.authorid = ". (int)$serendipity['GET']['viewAuthor'];
+    }
+
+
+    if (isset($serendipity['GET']['category'])) {
+        $categoryid  = (int)$serendipity['GET']['category'];
+
+        if ($categoryid != 0) {
+            if (!empty($cond['and'])) {
+                $cond['and'] .= " AND c.category_left BETWEEN " . implode(' AND ', serendipity_fetchCategoryRange($categoryid));
+            } else {
+                $cond['and'] = "WHERE c.category_left BETWEEN " . implode(' AND ', serendipity_fetchCategoryRange($categoryid));
+            }
+        }
+    }
+
+    if (!empty($limit)) {
+        if (isset($serendipity['GET']['page']) && $serendipity['GET']['page'] > 1 && !strstr($limit, ',')) {
+            $limit = serendipity_db_limit(($serendipity['GET']['page']-1) * $limit, $limit);
+        }
+
+        $limit = serendipity_db_limit_sql($limit);
+    }
+
+    if (isset($serendipity['GET']['adminModule']) && $serendipity['GET']['adminModule'] == 'entries' && $serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF) {
+        if (!empty($cond['and'])) {
+            $cond['and'] .= " AND e.authorid = '" . $serendipity['authorid'] . "'";
+        } else {
+            $cond['and'] = "WHERE e.authorid = '" . $serendipity['authorid'] . "'";
+        }
+    }
+
+    if (!isset($serendipity['GET']['adminModule']) && !serendipity_db_bool($serendipity['showFutureEntries'])) {
+        if (!empty($cond['and'])) {
+            $cond['and'] .= " AND e.timestamp <= '" . time() . "'";
+        } else {
+            $cond['and'] = "WHERE e.timestamp <= '" . time() . "'";
+        }
+    }
+
+    if (!empty($filter_sql)) {
+        if (!empty($cond['and'])) {
+            $cond['and'] .= ' AND ' . $filter_sql;
+        } else {
+            $cond['and'] = 'WHERE ' . $filter_sql;
+        }
+    }
+
+    serendipity_plugin_api::hook_event('frontend_fetchentries', $cond, array('noCache' => $noCache, 'noSticky' => $noSticky));
+
+    if ($serendipity['dbType'] == 'postgres') {
+        $group    = '';
+        $distinct = 'DISTINCT';
+    } else {
+        $group    = 'GROUP BY e.id';
+        $distinct = '';
+    }
+
+    // Store the unique query condition for entries for later reference, like getting the total article count.
+    $serendipity['fullCountQuery'] = "
+                FROM
+                    {$serendipity['dbPrefix']}entries AS e
+                    LEFT JOIN {$serendipity['dbPrefix']}authors a
+                        ON e.authorid = a.authorid
+                    LEFT JOIN {$serendipity['dbPrefix']}entrycat ec
+                        ON e.id = ec.entryid
+                    LEFT JOIN {$serendipity['dbPrefix']}category c
+                        ON ec.categoryid = c.categoryid
+                    {$cond['joins']}
+                    {$cond['and']}";
+
+    $query = "SELECT $distinct
+                    {$cond['addkey']}
+
+                    e.id,
+                    e.title,
+                    e.timestamp,
+                    e.comments,
+                    e.exflag,
+                    e.authorid,
+                    e.trackbacks,
+                    e.isdraft,
+                    e.allow_comments,
+                    e.last_modified,
+
+                    a.realname AS author,
+                    a.email
+
+                    $body
+                    {$serendipity['fullCountQuery']}
+                    $group
+                    ORDER BY {$cond['orderby']}
+                    $limit";
+
+    $ret = serendipity_db_query($query);
+
+    if (is_string($ret)) {
+        die("Query failed: $ret");
+    }
+
+    if (is_array($ret)) {
+        // The article's query LIMIT operates on a flattened entries layer so that
+        // an article having 5 associated categories won't count as 5 entries.
+        // But to store the expanded list of categories, we need to send a new
+        // query once for all entries we have just fetched.
+        // First code for this was sending 15 queries for 15 fetched entries,
+        // this is now limited to just one query per fetched articles group
+
+        $search_ids = array(); // An array to hold all ids of the entry we want to fetch.
+        $assoc_ids  = array(); // A temporary key association container to not have to loop through the return array once again.
+
+        foreach($ret AS $i => $entry) {
+            $search_ids[]            = $entry['id'];
+            $ret[$i]['categories']   = array();        // make sure every article gets its category association
+            $assoc_ids[$entry['id']] = $i;             // store temporary reference
+        }
+
+        serendipity_plugin_api::hook_event('frontend_entryproperties', $ret, $assoc_ids);
+
+        $query = "SELECT
+                         ec.entryid,
+                         c.categoryid,
+                         c.category_name,
+                         c.category_description,
+                         c.category_icon,
+                         c.parentid
+                    FROM {$serendipity['dbPrefix']}category AS c
+               LEFT JOIN {$serendipity['dbPrefix']}entrycat AS ec
+                      ON ec.categoryid = c.categoryid
+                   WHERE ec.entryid IN (" . implode(', ', $search_ids) . ")";
+
+        $search_ret = serendipity_db_query($query);
+
+        if (is_array($search_ret)) {
+            foreach($search_ret AS $i => $entry) {
+                $ret[$assoc_ids[$entry['entryid']]]['categories'][] = $entry;
+            }
+        }
+    }
+
+    return $ret;
+}
+
+/**
+* Fetches a specific entry
+**/
+function serendipity_fetchEntry($key, $val, $full = true, $fetchDrafts = 'false') {
+    global $serendipity;
+
+    $cond = array();
+    $cond['and'] = " "; // intentional dummy string to attach dummy AND parts to the WHERE clauses
+
+    if ($fetchDrafts == 'false') {
+        $cond['and'] = " AND e.isdraft = 'false' " . (!serendipity_db_bool($serendipity['showFutureEntries']) ? " AND e.timestamp <= " . time() : '');
+    }
+
+    if (isset($serendipity['GET']['adminModule']) && $serendipity['GET']['adminModule'] == 'entries' && $serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF) {
+        $cond['and'] = " AND e.authorid = '" . $serendipity['authorid'] . "'";
+    }
+
+    serendipity_plugin_api::hook_event('frontend_fetchentry', $cond, array('noSticky' => true));
+
+    $querystring = "SELECT
+                            *,
+                            a.realname AS author,
+                            a.email
+                      FROM
+                            {$serendipity['dbPrefix']}entries e
+                 LEFT JOIN  {$serendipity['dbPrefix']}authors a
+                        ON  e.authorid = a.authorid
+                            {$cond['joins']}
+                     WHERE
+                            e.$key LIKE '" . serendipity_db_escape_string($val) . "'
+                            {$cond['and']}
+                     LIMIT  1";
+
+    $ret = serendipity_db_query($querystring, true);
+    if (is_array($ret)) {
+        $ret['categories'] = serendipity_fetchEntryCategories($ret['id']);
+        $ret['properties'] = serendipity_fetchEntryProperties($ret['id']);
+    }
+
+    return $ret;
+}
+
+function serendipity_fetchEntryProperties($id) {
+    global $serendipity;
+
+    $parts = array();
+    serendipity_plugin_api::hook_event('frontend_entryproperties_query', $parts);
+
+    $properties = serendipity_db_query("SELECT property, value FROM {$serendipity['dbPrefix']}entryproperties WHERE entryid = " . (int)$id . " " . $parts['and']);
+    if (!is_array($properties)) {
+        $properties = array();
+    }
+
+    $property = array();
+    foreach($properties AS $idx => $row) {
+        $property[$row['property']] = $row['value'];
+    }
+
+    return $property;
+}
+
+/**
+* Fetches a users categories
+**/
+function serendipity_fetchCategories($authorid = null, $name = '') {
+    global $serendipity;
+
+    if (!isset($authorid) || $authorid === null) {
+        $authorid = ((isset($serendipity['authorid']) && !empty($serendipity['GET']['adminModule'])) ? $serendipity['authorid'] : 1);
+    }
+
+    if ($serendipity['serendipityUserlevel'] == USERLEVEL_ADMIN) {
+        $authorid = 'all';
+    }
+
+    if ($authorid != 'all' && is_numeric($authorid)) {
+        $where = " WHERE ((c.authorid = $authorid OR c.authorid = 0) " . (!empty($serendipity['serendipityUserlevel']) ? " OR a.userlevel < {$serendipity['serendipityUserlevel']}" : '') . ')';
+    } else {
+        $where = '';
+    }
+
+    if (!empty($name)) {
+        if ($where == '') {
+            $where = ' WHERE ';
+        } else {
+            $where = ' AND ';
+        }
+
+        $where .= " c.category_name = '" . serendipity_db_escape_string($name) . "'";
+    }
+
+    $querystring = "SELECT
+                           c.*,
+                           a.username,
+                           a.realname
+                      FROM {$serendipity['dbPrefix']}category AS c
+           LEFT OUTER JOIN {$serendipity['dbPrefix']}authors AS a
+                        ON c.authorid = a.authorid $where
+                  ORDER BY category_name";
+    return serendipity_db_query($querystring);
+}
+
+function serendipity_rebuildCategoryTree($parent = 0, $left = 0) {
+    // Based on http://www.sitepoint.com/article/hierarchical-data-database/1
+    global $serendipity;
+    $right = $left + 1;
+
+    $result = serendipity_db_query("SELECT categoryid FROM {$serendipity['dbPrefix']}category WHERE parentid = '" . (int)$parent . "'");
+    if ( is_array($result) ) {
+        foreach ( $result as $category ) {
+            $right = serendipity_rebuildCategoryTree($category['categoryid'], $right);
+        }
+    }
+    if ( $parent > 0 ) {
+        serendipity_db_query("UPDATE {$serendipity['dbPrefix']}category SET category_left='{$left}', category_right='{$right}' WHERE categoryid='{$parent}'");
+    }
+
+    return $right + 1;
+}
+
+/**
+* Give it a raw searchstring, it'll search
+**/
+function serendipity_searchEntries($term, $limit = '') {
+    global $serendipity;
+
+    if ($limit == '') {
+        $limit = $serendipity['fetchLimit'];
+    }
+
+    if (isset($serendipity['GET']['page']) && $serendipity['GET']['page'] > 1 && !strstr($limit, ',')) {
+        $limit = serendipity_db_limit(($serendipity['GET']['page']-1) * $limit, $limit);
+    }
+
+    $limit = serendipity_db_limit_sql($limit);
+
+    $term = serendipity_db_escape_string($term);
+    if ($serendipity['dbType'] == 'postgres') {
+        $group     = '';
+        $distinct  = 'DISTINCT';
+        $find_part = "(title~'$term' OR body~'$term' OR extended~'$term')";
+    } elseif ($serendipity['dbType'] == 'sqlite') {
+        // Very extensive SQLite search. There currently seems no other way to perform fulltext search in SQLite
+        // But it's better than no search at all :-D
+        $group     = 'GROUP BY e.id';
+        $distinct  = '';
+        $term      = serendipity_mb('strtolower', $term);
+        $find_part = "(lower(title) LIKE '%$term%' OR lower(body) LIKE '%$term%' OR lower(extended) LIKE '%$term%')";
+    } else {
+        $group     = 'GROUP BY e.id';
+        $distinct  = '';
+        $find_part = "MATCH(title,body,extended) AGAINST('$term')";
+    }
+
+    $cond = array();
+    $cond['and'] = " AND isdraft = 'false' " . (!serendipity_db_bool($serendipity['showFutureEntries']) ? " AND timestamp <= " . time() : '');
+    serendipity_plugin_api::hook_event('frontend_fetchentries', $cond);
+
+    $serendipity['fullCountQuery'] = "
+                      FROM
+                            {$serendipity['dbPrefix']}entries e
+                 LEFT JOIN  {$serendipity['dbPrefix']}authors a
+                        ON  e.authorid = a.authorid
+                 LEFT JOIN  {$serendipity['dbPrefix']}entrycat ec
+                        ON  e.id = ec.entryid
+                            {$cond['joins']}
+                     WHERE
+                            $find_part
+                            {$cond['and']}";
+
+    $querystring = "SELECT $distinct
+                            e.id,
+                            e.authorid,
+                            a.realname AS author,
+                            a.email,
+                            ec.categoryid,
+                            e.timestamp,
+                            e.comments,
+                            e.title,
+                            e.body,
+                            e.extended,
+                            e.trackbacks,
+                            e.exflag
+                    {$serendipity['fullCountQuery']}
+                    $group
+                  ORDER BY  timestamp DESC
+                    $limit";
+
+    $search = serendipity_db_query($querystring);
+    return $search;
+}
+
+function serendipity_printEntryFooter() {
+    global $serendipity;
+
+    $totalEntries = serendipity_getTotalEntries();
+    $totalPages   = ceil($totalEntries / $serendipity['fetchLimit']);
+
+    if (!isset($serendipity['GET']['page'])) {
+        $serendipity['GET']['page'] = 1;
+    }
+
+    if ($totalPages <= 0 ) {
+        $totalPages = 1;
+    }
+
+    if ($serendipity['GET']['page'] > 1) {
+        $uriArguments = $serendipity['uriArguments'];
+        $uriArguments[] = 'P'. ($serendipity['GET']['page'] - 1);
+        $serendipity['smarty']->assign('footer_prev_page', serendipity_rewriteURL(implode('/', $uriArguments) .'.html'));
+    }
+
+    $serendipity['smarty']->assign('footer_info', sprintf(PAGE_BROWSE_ENTRIES, (int)$serendipity['GET']['page'], $totalPages, $totalEntries));
+
+    if ($serendipity['GET']['page'] < $totalPages) {
+        $uriArguments = $serendipity['uriArguments'];
+        $uriArguments[] = 'P'. ($serendipity['GET']['page'] + 1);
+        $serendipity['smarty']->assign('footer_next_page', serendipity_rewriteURL(implode('/', $uriArguments) .'.html'));
+    }
+}
+
+function serendipity_getTotalEntries() {
+    global $serendipity;
+
+    // The unique query condition was built previously in serendipity_fetchEntries()
+    if ($serendipity['dbType'] == 'sqlite') {
+        $querystring  = "SELECT count(e.id) {$serendipity['fullCountQuery']} GROUP BY e.id";
+    } else {
+        $querystring  = "SELECT count(distinct e.id) {$serendipity['fullCountQuery']}";
+    }
+
+    $query = serendipity_db_query($querystring);
+
+    if (is_array($query) && isset($query[0])) {
+        if ($serendipity['dbType'] == 'sqlite') {
+            return count($query);
+        } else {
+            return $query[0][0];
+        }
+    }
+
+    return 0;
+}
+
+/**
+* Prints the entries you fetched with serendipity_fetchEntries/searchEntries in HTML.
+**/
+function serendipity_printEntries($entries, $extended = 0, $preview = false) {
+    global $serendipity;
+
+    $addData = array('extended' => $extended, 'preview' => $preview);
+    serendipity_plugin_api::hook_event('entry_display', $entries, $addData);
+
+    if (isset($entries['clean_page']) && $entries['clean_page'] === true) {
+        $serendipity['smarty']->assign('plugin_clean_page', true);
+        serendipity_smarty_fetch('ENTRIES', 'entries.tpl', true);
+        return; // no display of this item
+    }
+
+    // We shouldn't return here, because we want Smarty to handle the output
+    if (!is_array($entries) || $entries[0] == false || !isset($entries[0]['timestamp'])) {
+        $entries = array();
+    }
+
+    $dategroup = array();
+    for ($x = 0, $num_entries = count($entries); $x < $num_entries; $x++) {
+        if (!empty($entries[$x]['properties']['ep_is_sticky']) && serendipity_db_bool($entries[$x]['properties']['ep_is_sticky'])) {
+            $entries[$x]['is_sticky'] = true;
+            $key = 'sticky';
+        } else {
+            $key = date('Ymd', serendipity_serverOffsetHour($entries[$x]['timestamp']));
+        }
+
+        if (!empty($entries[$x]['properties']['ep_cache_body'])) {
+            $entries[$x]['body']      = &$entries[$x]['properties']['ep_cache_body'];
+            $entries[$x]['is_cached'] = true;
+        }
+
+        if (!empty($entries[$x]['properties']['ep_cache_extended'])) {
+            $entries[$x]['extended']  = &$entries[$x]['properties']['ep_cache_extended'];
+            $entries[$x]['is_cached'] = true;
+        }
+
+        $dategroup[$key]['date']        = $entries[$x]['timestamp'];
+        $dategroup[$key]['is_sticky']   = (isset($entries[$x]['is_sticky']) && serendipity_db_bool($entries[$x]['is_sticky']) ? true : false);
+        $dategroup[$key]['entries'][]   = &$entries[$x];
+    }
+
+    foreach($dategroup as $properties) {
+        foreach($properties['entries'] as $x => $_entry) {
+            $entry = &$properties['entries'][$x]; // PHP4 Compat
+            serendipity_plugin_api::hook_event('frontend_display', $entry);
+
+            $entry['link']      = serendipity_archiveURL($entry['id'], $entry['title'], 'serendipityHTTPPath');
+            $entry['commURL']   = serendipity_archiveURL($entry['id'], $entry['title'], 'baseURL', false);
+            $entry['rdf_ident'] = serendipity_archiveURL($entry['id'], $entry['title'], 'baseURL');
+            $entry['title']     = htmlspecialchars($entry['title']);
+
+            $entry['link_allow_comments']    = $serendipity['baseURL'] . 'comment.php?serendipity[switch]=enable&amp;serendipity[entry]=' . $entry['id'];
+            $entry['link_deny_comments']     = $serendipity['baseURL'] . 'comment.php?serendipity[switch]=disable&amp;serendipity[entry]=' . $entry['id'];
+            $entry['allow_comments']         = serendipity_db_bool($entry['allow_comments']);
+            $entry['moderate_comments']      = serendipity_db_bool($entry['moderate_comments']);
+            $entry['viewmode']               = ($serendipity['GET']['cview'] == VIEWMODE_LINEAR ? VIEWMODE_LINEAR : VIEWMODE_THREADED);
+            $entry['link_popup_comments']    = $serendipity['serendipityHTTPPath'] .'comment.php?serendipity[entry_id]='. $entry['id'] .'&amp;serendipity[type]=comments';
+            $entry['link_popup_trackbacks']  = $serendipity['serendipityHTTPPath'] .'comment.php?serendipity[entry_id]='. $entry['id'] .'&amp;serendipity[type]=trackbacks';
+            $entry['link_edit']              = $serendipity['baseURL'] .'serendipity_admin.php?serendipity[action]=admin&amp;serendipity[adminModule]=entries&amp;serendipity[adminAction]=edit&amp;serendipity[id]='. $entry['id'];
+            $entry['link_trackback']         = $serendipity['baseURL'] .'comment.php?type=trackback&amp;entry_id='. $entry['id'];
+            $entry['link_rdf']               = serendipity_rewriteURL(PATH_FEEDS . '/ei_'. $entry['id'] .'.rdf');
+            $entry['link_viewmode_threaded'] = $serendipity['serendipityHTTPPath'] . $serendipity['indexFile'] .'?url='. $entry['commURL'] .'&amp;serendipity[cview]='. VIEWMODE_THREADED;
+            $entry['link_viewmode_linear']   = $serendipity['serendipityHTTPPath'] . $serendipity['indexFile'] .'?url='. $entry['commURL'] .'&amp;serendipity[cview]='. VIEWMODE_LINEAR;
+            $entry['link_author']            = serendipity_rewriteURL(PATH_AUTHORS .'/'. serendipity_makePermalink(PERM_AUTHORS, array('id' => $entry['authorid'], 'title' => $entry['author'])));
+
+            if (is_array($entry['categories'])) {
+                foreach ($entry['categories'] as $k => $v) {
+                    $entry['categories'][$k]['category_link'] =  serendipity_rewriteURL(PATH_CATEGORIES . '/' . serendipity_makePermalink(PERM_CATEGORIES, array('id' => $entry['categories'][$k]['categoryid'], 'title' => $entry['categories'][$k]['category_name'])));
+                }
+            }
+
+            if (strlen($entry['extended'])) {
+                $entry['has_extended']      = true;
+            }
+
+            if (isset($entry['exflag']) && $entry['exflag'] && ($extended || $preview)) {
+                $entry['is_extended']       = true;
+            }
+
+            if (serendipity_db_bool($entry['allow_comments']) || !isset($entry['allow_comments']) || $entry['comments'] > 0) {
+                $entry['has_comments']      = true;
+                $entry['label_comments']    = $entry['comments'] == 1 ? COMMENT : COMMENTS;
+            }
+
+            if (serendipity_db_bool($entry['allow_comments']) || !isset($entry['allow_comments']) || $entry['trackbacks'] > 0) {
+                $entry['has_trackbacks']    = true;
+                $entry['label_trackbacks']  = $entry['trackbacks'] == 1 ? TRACKBACK : TRACKBACKS;
+            }
+
+            if ($_SESSION['serendipityAuthedUser'] === true && ($_SESSION['serendipityUserlevel'] >= USERLEVEL_CHIEF || $_SESSION['serendipityAuthorid'] == $entry['authorid'])) {
+                $entry['is_entry_owner']    = true;
+            }
+
+            $entry['display_dat'] = '';
+            serendipity_plugin_api::hook_event('frontend_display:html:per_entry', $entry);
+            $entry['plugin_display_dat'] =& $entry['display_dat'];
+
+            if ($preview) {
+                ob_start();
+                serendipity_plugin_api::hook_event('backend_preview', $entry);
+                $entry['backend_preview'] = ob_get_contents();
+                ob_end_clean();
+            }
+
+            /* IF WE ARE DISPLAYING A FULL ENTRY */
+            if (isset($serendipity['GET']['id'])) {
+                $serendipity['smarty']->assign(
+                    array(
+                        'comments_messagestack' => (isset($serendipity['messagestack']['comments']) ? (array)$serendipity['messagestack']['comments'] : array()),
+                        'is_comment_added'      => (isset($serendipity['GET']['csuccess']) && $serendipity['GET']['csuccess'] == 'true' ? true: false),
+                        'is_comment_moderate'   => (isset($serendipity['GET']['csuccess']) && $serendipity['GET']['csuccess'] == 'moderate' ? true: false)
+                    )
+                );
+
+                serendipity_displayCommentForm(
+                    $entry['id'],
+                    $serendipity['serendipityHTTPPath'] . $serendipity['indexFile'] . '?url=' . $entry['commURL'],
+                    true,
+                    $serendipity['POST'],
+                    true,
+                    serendipity_db_bool($entry['moderate_comments']),
+                    $entry
+                );
+            } // END FULL ENTRY LOGIC
+        } // end foreach-loop (entries)
+    } // end foreach-loop (dates)
+
+    if (!isset($serendipity['GET']['id']) &&
+            (!isset($serendipity['hidefooter']) || $serendipity['hidefooter'] == false) &&
+            ($num_entries <= $serendipity['fetchLimit'])) {
+        serendipity_printEntryFooter();
+    }
+
+    $serendipity['smarty']->assign('entries', $dategroup);
+    unset($entries, $dategroup);
+
+    if (isset($serendipity['short_archives']) && $serendipity['short_archives']) {
+        serendipity_smarty_fetch('ENTRIES', 'entries_summary.tpl', true);
+    } else {
+        serendipity_smarty_fetch('ENTRIES', 'entries.tpl', true);
+    }
+
+} // end function serendipity_printEntries
+
+function serendipity_printEntries_rss($entries, $version, $comments = false, $fullFeed = false, $showMail = true) {
+    global $serendipity;
+
+    if (is_array($entries)) {
+        foreach ($entries as $entry) {
+            $id   = (isset($entry['entryid']) && !empty($entry['entryid']) ? $entry['entryid'] : $entry['id']);
+            $guid = serendipity_rss_getguid($entry, $comments);
+            $entryLink = serendipity_archiveURL($id, $entry['title']);
+            if ($comments == true) {
+                // Display username as part of the title for easier feed-readability
+                $entry['title'] = $entry['author'] . ': ' . $entry['title'];
+            }
+
+            // Embed a link to extended entry, if existing
+            if ($fullFeed) {
+                $entry['body'] .= ' ' . $entry['extended'];
+            } elseif ($entry['exflag']) {
+                $ext = '<br /><a href="' . $guid . '#extended">' . sprintf(VIEW_EXTENDED_ENTRY, htmlspecialchars($entry['title'])) . '</a>';
+            } else {
+                $ext = '';
+            }
+
+            serendipity_plugin_api::hook_event('frontend_display', $entry);
+            // Do some relative -> absolute URI replacing magic. Replaces all HREF/SRC (<a>, <img>, ...) references to only the serendipitypath with the full baseURL URI
+            // garvin: Could impose some problems. Closely watch this one.
+            $entry['body'] = preg_replace('@(href|src)=("|\')(' . preg_quote($serendipity['serendipityHTTPPath']) . ')(.*)("|\')(.*)>@imsU', '\1=\2' . $serendipity['baseURL'] . '\4\2\6>', $entry['body']);
+            // jbalcorn: clean up body for XML compliance as best we can.
+            $entry['body'] = xhtml_cleanup($entry['body']);
+
+            // extract author information
+            if ((isset($entry['no_email']) && $entry['no_email']) || !$showMail) {
+                $entry['email'] = 'nospam@example.com'; // RSS Feeds need an E-Mail address!
+            } elseif (empty($entry['email'])) {
+                $query = "select email FROM {$serendipity['dbPrefix']}authors WHERE authorid = '". serendipity_db_escape_string($entry['authorid']) ."'";
+                $results = serendipity_db_query($query);
+                $entry['email'] = $results[0]['email'];
+            }
+
+            if (!is_array($entry['categories'])) {
+                $entry['categories'] = array(0 => array('category_name' => $entry['category_name']));
+            }
+
+            if ($version == 'atom0.3') {
+                /*********** ATOM 0.3 FEED *************/
+?>
+<entry>
+    <link href="<?php echo $entryLink; ?>" rel="alternate" title="<?php echo serendipity_utf8_encode(htmlspecialchars($entry['title'])); ?>" type="text/html" />
+    <author>
+        <name><?php echo serendipity_utf8_encode(htmlspecialchars($entry['author'])); ?></name>
+        <email><?php echo serendipity_utf8_encode(htmlspecialchars($entry['email'])); ?></email>
+    </author>
+
+    <issued><?php echo gmdate('Y-m-d\TH:i:s\Z', serendipity_serverOffsetHour($entry['timestamp'])); ?></issued>
+    <created><?php echo gmdate('Y-m-d\TH:i:s\Z', serendipity_serverOffsetHour($entry['timestamp'])); ?></created>
+    <modified><?php echo gmdate('Y-m-d\TH:i:s\Z', serendipity_serverOffsetHour($entry['last_modified'])); ?></modified>
+    <wfw:comment><?php echo $serendipity['baseURL']; ?>wfwcomment.php?cid=<?php echo $id; ?></wfw:comment>
+
+<?php
+                    if ($comments === false) {
+?>
+    <slash:comments><?php echo $entry['comments']; ?></slash:comments>
+    <wfw:commentRss><?php echo $serendipity['baseURL']; ?>rss.php?version=<?php echo $version; ?>&amp;type=comments&amp;cid=<?php echo $id; ?></wfw:commentRss>
+<?php
+                    }
+?>
+
+    <id><?php echo $guid; ?></id>
+    <title mode="escaped" type="text/html"><?php echo serendipity_utf8_encode(htmlspecialchars($entry['title'])); ?></title>
+    <content type="application/xhtml+xml" xml:base="<?php echo $serendipity['baseURL']; ?>">
+        <div xmlns="http://www.w3.org/1999/xhtml">
+<?php
+                    echo serendipity_utf8_encode($entry['body'].$ext);
+?>
+        </div>
+    </content>
+</entry>
+<?php
+            } elseif ($version == '0.91' || $version == '2.0') {
+                /*********** BEGIN RSS 0.91/2.0 FEED *************/
+?>
+<item>
+    <title><?php echo serendipity_utf8_encode(htmlspecialchars($entry['title'])); ?></title>
+    <link><?php echo $entryLink; ?></link>
+<?php
+                /*********** END RSS 0.91/2.0 FEED *************/
+
+                if ($version == '2.0') {
+                    /*********** RSS 2.0 FEED EXTRAS *************/
+                    foreach ($entry['categories'] AS $idx => $cat) {
+                        ?><category><?php echo serendipity_utf8_encode(htmlspecialchars($cat['category_name'])); ?></category><?php
+                    }
+?>
+    <comments><?php echo $entryLink; ?>#comments</comments>
+    <wfw:comment><?php echo $serendipity['baseURL']; ?>wfwcomment.php?cid=<?php echo $id; ?></wfw:comment>
+<?php
+                    if ($comments === false) {
+?>
+    <slash:comments><?php echo $entry['comments']; ?></slash:comments>
+    <wfw:commentRss><?php echo $serendipity['baseURL']; ?>rss.php?version=<?php echo $version; ?>&amp;type=comments&amp;cid=<?php echo $id; ?></wfw:commentRss>
+<?php
+                    }
+?>
+    <author><?php echo serendipity_utf8_encode(htmlspecialchars($entry['email'])) . ' (' . serendipity_utf8_encode(htmlspecialchars($entry['author'])) . ')'; ?></author>
+    <content:encoded>
+<?php
+                    echo serendipity_utf8_encode(htmlspecialchars($entry['body'].$ext));
+?>
+    </content:encoded>
+    <pubDate><?php echo date('r', serendipity_serverOffsetHour($entry['timestamp'])); ?></pubDate>
+    <guid isPermaLink="false"><?php echo $guid; ?></guid>
+    <?php
+      $entry['display_dat'] = '';
+      serendipity_plugin_api::hook_event('frontend_display:rss-2.0:per_entry', $entry);
+      echo $entry['display_dat'];
+    ?>
+</item>
+<?php
+                    /*********** END 2.0 FEED EXTRAS *************/
+                } else {
+                    /*********** BEGIN RSS 0.91 FEED EXTRAS *************/
+?>
+    <description>
+        <?php echo serendipity_utf8_encode(htmlspecialchars($entry['body'] . $ext)); ?>
+    </description>
+</item>
+<?php
+                    /*********** END RSS 0.91 FEED EXTRAS *************/
+                }
+            } else if ($version == '1.0') {
+                $categories = array();
+                foreach ($entry['categories'] AS $idx => $cat) {
+                    $categories[] = $cat['category_name'];
+                }
+
+?>
+<item rdf:about="<?php echo $guid; ?>">
+    <title><?php echo serendipity_utf8_encode(htmlspecialchars($entry['title'])); ?></title>
+    <link><?php echo $entryLink; ?></link>
+    <description>
+<?php
+                echo serendipity_utf8_encode(htmlspecialchars($entry['body'].$ext));
+?>
+    </description>
+    <?php
+      $entry['display_dat'] = '';
+      serendipity_plugin_api::hook_event('frontend_display:rss-1.0:per_entry', $entry);
+      echo $entry['display_dat'];
+    ?>
+    <dc:publisher><?php echo serendipity_utf8_encode(htmlspecialchars($serendipity['blogTitle'])); ?></dc:publisher>
+    <dc:creator><?php echo serendipity_utf8_encode(htmlspecialchars($entry['email'])) . ' (' . serendipity_utf8_encode(htmlspecialchars($entry['author'])) . ')'; ?></dc:creator>
+    <dc:subject><?php echo serendipity_utf8_encode(htmlspecialchars(implode(', ', $categories))); ?></dc:subject>
+    <dc:date><?php echo date('Y-m-d\TH:i:s\Z', serendipity_serverOffsetHour($entry['timestamp'])); ?></dc:date>
+    <wfw:comment><?php echo $serendipity['baseURL']; ?>wfwcomment.php?cid=<?php echo $id; ?></wfw:comment>
+<?php
+                    if ($comments === false) {
+?>
+    <slash:comments><?php echo $entry['comments']; ?></slash:comments>
+    <wfw:commentRss><?php echo $serendipity['baseURL']; ?>rss.php?version=<?php echo $version; ?>&amp;type=comments&amp;cid=<?php echo $id; ?></wfw:commentRss>
+<?php
+                    }
+?>
+</item>
+<?php
+            } elseif ($version == 'opml1.0') {
+?>
+    <outline text="<?php echo serendipity_utf8_encode(htmlspecialchars($entry['title'])); ?>" type="url" htmlUrl="<?php echo $entryLink; ?>" urlHTTP="<?php echo $entryLink; ?>" />
+<?php
+            }
+        }
+    }
+}
+
+
+/**
+/**
+ * purge a statically pregenerated entry
+ */
+function serendipity_purgeEntry($id, $timestamp = null) {
+    global $serendipity;
+
+    // If pregenerate is not set, short circuit all this logic
+    // and remove nothing.
+    if(!isset($serendipity['pregenerate'])) {
+        return;
+    }
+
+    if (isset($timestamp)) {
+        $dated = date('Ymd', serendipity_serverOffsetHour($timestamp));
+        $datem = date('Ym',  serendipity_serverOffsetHour($timestamp));
+
+        @unlink("{$serendipity['serendipityPath']}/".PATH_ARCHIVES."/{$dated}.html");
+        @unlink("{$serendipity['serendipityPath']}/".PATH_ARCHIVES."/{$datem}.html");
+    }
+
+    // Fixme (the _* part) !
+    @unlink("{$serendipity['serendipityPath']}/".PATH_ARCHIVES."/{$id}_*.html");
+    @unlink("{$serendipity['serendipityPath']}/".PATH_FEEDS."/index.rss");
+    @unlink("{$serendipity['serendipityPath']}/".PATH_FEEDS."/index.rss2");
+    @unlink("{$serendipity['serendipityPath']}/index.html");
+}
+
+/**
+* Inserts a new entry into the database or updates an existing
+**/
+function serendipity_updertEntry($entry) {
+    global $serendipity;
+
+    $errors = array();
+    serendipity_plugin_api::hook_event('backend_entry_updertEntry', $errors, $entry);
+    if (count($errors) > 0) {
+        // Return error message(s)
+        return implode("\n", $errors);
+    }
+
+    serendipity_plugin_api::hook_event('backend_entry_presave', $entry);
+
+    $categories = $entry['categories'];
+    unset($entry['categories']);
+
+    $newEntry = 0;
+    $exflag = 0;
+
+    if (!is_numeric($entry['timestamp'])) {
+        $entry['timestamp'] = time();
+    }
+
+    if (!isset($entry['last_modified']) || !is_numeric($entry['last_modified'])) {
+        $entry['last_modified'] = time();
+    }
+
+    /* WYSIWYG-editor inserts empty ' ' for extended body; this is reversed here */
+    if (isset($entry['extended']) && trim($entry['extended']) == '') {
+        $entry['extended'] = '';
+    }
+
+    if (strlen($entry['extended'])) {
+        $exflag = 1;
+    }
+
+    $entry['exflag']   = $exflag;
+
+    if (!is_numeric($entry['id'])) {
+        /* we need to insert */
+
+        unset($entry['id']);
+        $entry['comments'] = 0;
+
+        // New entries need an author
+        $entry['author']   = $serendipity['user'];
+        if (!isset($entry['authorid']) || empty($entry['authorid'])) {
+            $entry['authorid'] = $serendipity['authorid'];
+        }
+
+        if (!$_SESSION['serendipityRightPublish']) {
+            $entry['isdraft'] = 'true';
+        }
+
+        if(!isset($entry['allow_comments'])){
+            $entry['allow_comments']='false';
+        }
+        if(!isset($entry['moderate_comments'])){
+            $entry['moderate_comments']='false';
+        }
+
+        $res = serendipity_db_insert('entries', $entry);
+
+        if ($res) {
+            $entry['id'] = $serendipity['lastSavedEntry'] = serendipity_db_insert_id('entries', 'id');
+            if (is_array($categories)) {
+                foreach ($categories as $cat) {
+                  if (is_numeric($cat))
+                      serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}entrycat (entryid, categoryid) VALUES ({$entry['id']}, {$cat})");
+                }
+            }
+        }
+        else {
+            //Some error message here
+            return ENTRIES_NOT_SUCCESSFULLY_INSERTED;
+        }
+        $newEntry    = 1;
+    } else {
+        /* we need to update */
+
+        // Get settings from entry if already in DB, which should not be alterable with POST methods
+        $_entry            = serendipity_fetchEntry('id', $entry['id'], 1, 1);
+        $entry['authorid'] = $_entry['authorid'];
+
+        if (isset($serendipity['GET']['adminModule']) && $serendipity['GET']['adminModule'] == 'entries' && $serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF && $entry['authorid'] != $serendipity['authorid']) {
+            // Only chiefs and admins can change other's entry. Else update fails.
+            return;
+        }
+
+        if (!$_SESSION['serendipityRightPublish']) {
+            unset($entry['isdraft']);
+        }
+
+        if (is_array($categories)) {
+            serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}entrycat WHERE entryid={$entry['id']}");
+            foreach ($categories as $cat) {
+                serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}entrycat (entryid, categoryid) VALUES ({$entry['id']}, {$cat})");
+            }
+        }
+
+        $res = serendipity_db_update('entries', array('id' => $entry['id']), $entry);
+        $newEntry = 0;
+    }
+
+    if (is_string($res)) {
+        return $res;
+    }
+
+    if ($entry['isdraft'] == 'false') {
+        serendipity_plugin_api::hook_event('frontend_display', $entry, array('no_scramble' => true));
+        serendipity_handle_references($entry['id'], $serendipity['blogTitle'], $entry['title'], $entry['body'] . $entry['extended'], $newEntry);
+    }
+
+    serendipity_purgeEntry($entry['id'], $entry['timestamp']);
+
+    // Send publish tags if either a new article has been inserted from scratch, or if the entry was previously
+    // stored as draft and is now published
+    if ($entry['isdraft'] == 'false' && ($newEntry || $_entry['isdraft'] == 'true')) {
+        serendipity_plugin_api::hook_event('backend_publish', $entry, $newEntry);
+    } else {
+        serendipity_plugin_api::hook_event('backend_save', $entry, $newEntry);
+    }
+
+    return (int)$entry['id'];
+}
+
+/**
+* Deletes an entry and everything that belongs to it (comments, etc...) from
+* the database
+**/
+function serendipity_deleteEntry($id) {
+    global $serendipity;
+
+    if (!is_numeric($id)) {
+        return false;
+    }
+
+    // Purge the daily/monthly entries so they can be rebuilt
+    $result = serendipity_db_query("SELECT timestamp, authorid FROM {$serendipity['dbPrefix']}entries WHERE id = '". (int)$id ."'", true);
+
+    if ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF && $result[1] != $serendipity['authorid']) {
+        // Only admins and chief users can delete entries which do not belong to the author
+        return;
+    }
+
+    serendipity_purgeEntry($id, $result[0]);
+
+    serendipity_db_query("DELETE FROM {$serendipity["dbPrefix"]}entries WHERE id=$id");
+    serendipity_db_query("DELETE FROM {$serendipity["dbPrefix"]}entrycat WHERE entryid=$id");
+    serendipity_db_query("DELETE FROM {$serendipity["dbPrefix"]}entryproperties WHERE entryid=$id");
+    serendipity_db_query("DELETE FROM {$serendipity["dbPrefix"]}comments WHERE entry_id=$id");
+    serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}references WHERE entry_id='$id'");
+}
+
+/**
+* Print a list of categories
+*
+* Prints a list of categories for use in forms, the sidebar, or whereever...
+* @param array  An array of categories, typically gathered by serendipity_fetchCategories()
+* @param array  Select
+* @param int    Type
+* @param int    ID
+* @param int    Level
+* @param string Tells the function, whether or not to display the XML button for each category.
+*               If empty, no links to the xml feeds will be displayed; If you want to, you can
+*               pass an image here (this setting is only used, when type==3).
+* @see serendipity_fetchCategories()
+*/
+function serendipity_generateCategoryList($cats, $select = array(0), $type = 0, $id = 0, $level = 0, $xmlImg = '') {
+    global $serendipity;
+
+    if ( !is_array($cats) || !count($cats) )
+        return;
+
+    $ret = '';
+    foreach ($cats as $cat) {
+        if ($cat['parentid'] == $id) {
+            switch ($type) {
+                case 0:
+                    $ret .= str_repeat('&nbsp;', $level * 2).'&bull;&nbsp;<span id="catItem_' . $cat['categoryid'] . '"' . (($cat['categoryid'] && in_array($cat['categoryid'], $select)) ? ' selected="selected"' : '') . '><a href="?serendipity[adminModule]=category&amp;serendipity[cat][catid]=' . $cat['categoryid'] . '">' . (!empty($cat['category_icon']) ? '<img style="vertical-align: middle;" src="' . $cat['category_icon'] . '" border="0" alt="' . $cat['category_name'] . '"/> ' : '') . htmlspecialchars($cat['category_name']) . (!empty($cat['category_description']) ? ' - ' . htmlspecialchars($cat['category_description']) : '') . '</a></span><br/>' . "\n";
+                    break;
+                case 1:
+                case 2:
+                   $ret .= '<option value="' . $cat['categoryid'] . '"' . (($cat['categoryid'] && in_array($cat['categoryid'], $select)) ? ' selected="selected"' : '') . '>';
+                   $ret .= str_repeat('&nbsp;', $level * 2) . htmlspecialchars($cat['category_name']) . ($type == 1 && !empty($cat['category_description']) ? (' - ' . htmlspecialchars($cat['category_description'])) : '');
+                   $ret .= '</option>';
+                   break;
+                case 3:
+                    $category_id = serendipity_makeFilename($cat['category_name']);
+                    if (!empty($xmlImg)) {
+                        $ret .= sprintf(
+                          '<div style="padding-bottom: 2px;">' .
+                          '<a href="%s" title="%s"><img alt="xml" src="%s" style="vertical-align: bottom; display: inline; border: 0px" /></a>&#160;%s' .
+                          '<a href="%s" title="%s">%s</a>' .
+                          '</div>',
+                          $serendipity['serendipityHTTPPath'] . 'rss.php?category=' . $cat['categoryid'] . '_' . $category_id,
+                          htmlspecialchars($cat['category_description']),
+                          $xmlImg,
+                          str_repeat('&#160;', $level * 3),
+                          serendipity_rewriteURL(PATH_CATEGORIES . '/' . serendipity_makePermalink(PERM_CATEGORIES, array('id' => $cat['categoryid'], 'title' =>  $category_id)), 'serendipityHTTPPath'),
+                          htmlspecialchars($cat['category_description']),
+                          htmlspecialchars($cat['category_name']));
+                    } else {
+                        $ret .= sprintf(
+                          '%s<a href="%s" title="%s">%s</a><br />',
+                          str_repeat('&#160;', $level * 3),
+                          serendipity_rewriteURL(PATH_CATEGORIES . '/' . serendipity_makePermalink(PERM_CATEGORIES, array('id' => $cat['categoryid'], 'title' => $category_id)), 'serendipityHTTPPath'),
+                          htmlspecialchars($cat['category_description']),
+                          htmlspecialchars($cat['category_name']));
+                    }
+                    break;
+                case 4:
+                    $ret .= $cat['categoryid'] . '|||' . str_repeat(' ', $level * 2) . $cat['category_name'] . '@@@';
+                    break;
+            }
+            $ret .= serendipity_generateCategoryList($cats, $select, $type, $cat['categoryid'], $level + 1, $xmlImg);
+        }
+    }
+    return $ret;
+}
+
+/**
+* Prints a form to enter new diary entries
+**/
+function serendipity_printEntryForm($targetURL, $hiddens = array(), $entry = array(), $errMsg = "") {
+    global $serendipity;
+
+    $serendipity['EditorBrowsers'] = '(IE|Mozilla)';
+
+    $draftD = '';
+    $draftP = '';
+    $categoryselector_expanded = false;
+
+    serendipity_plugin_api::hook_event('backend_entryform', $entry);
+
+    if ( (isset($entry['isdraft']) && $entry['isdraft'] == 'true') ||
+         (!isset($entry['isdraft']) && $serendipity['publishDefault'] == 'draft') ) {
+        $draftD = ' selected="selected"';
+    } else {
+        $draftP = ' selected="selected"';
+    }
+
+    if (isset($entry['moderate_comments']) && (serendipity_db_bool($entry['moderate_comments']))) {
+        $moderate_comments = ' checked="checked"';
+    } elseif (!isset($entry['moderate_comments']) && ($serendipity['moderateCommentsDefault'] == 'true' || $serendipity['moderateCommentsDefault'] === true)) {
+        // This is the default on creation of a new entry and depends on the "moderateCommentsDefault" variable of the configuration.
+        $moderate_comments = ' checked="checked"';
+    } else {
+        $moderate_comments = '';
+    }
+
+
+    if (isset($entry['allow_comments']) && (serendipity_db_bool($entry['allow_comments']))) {
+        $allow_comments = ' checked="checked"';
+    } elseif ((!isset($entry['allow_comments']) || $entry['allow_comments'] !== 'false') && (!isset($serendipity['allowCommentsDefault']) || $serendipity['allowCommentsDefault'] == 'true' || $serendipity['allowCommentsDefault'] === true)) {
+        // This is the default on creation of a new entry and depends on the "allowCommentsDefault" variable of the configuration.
+        $allow_comments = ' checked="checked"';
+    } else {
+        $allow_comments = '';
+    }
+
+    // Fix category list. If the entryForm is displayed after a POST request, the additional category information is lost.
+    if (is_array($entry['categories']) && !is_array($entry['categories'][0])) {
+        $categories = (array)$entry['categories'];
+        $entry['categories'] = array();
+        foreach ($categories as $catid) {
+            $entry['categories'][] = serendipity_fetchCategoryInfo($catid);
+        }
+    }
+
+    $n = "\n";
+    $cat_list = '<select id="categoryselector" name="serendipity[categories][]" style="vertical-align: middle;" multiple="multiple">' . $n;
+    $cat_list .= '    <option value="0">[' . NO_CATEGORY . ']</option>' . $n;
+    $selected = array();
+    if (is_array($entry['categories'])) {
+        if (count($entry['categories']) > 1) {
+            $categoryselector_expanded = true;
+        }
+
+        foreach ($entry['categories'] as $cat) {
+            $selected[] = $cat['categoryid'];
+        }
+    }
+
+    if (count($selected) > 1 ||
+          (isset($serendipity['POST']['categories']) && is_array($serendipity['POST']['categories']) && sizeof($serendipity['POST']['categories']) > 1)) {
+        $categoryselector_expanded = true;
+    }
+
+    if (is_array($cats = serendipity_fetchCategories())) {
+        $cats = serendipity_walkRecursive($cats, 'categoryid', 'parentid', VIEWMODE_THREADED);
+        foreach ( $cats as $cat ) {
+            $cat_list .= '<option value="'. $cat['categoryid'] .'"'. (in_array($cat['categoryid'], $selected) ? ' selected="selected"' : '') .'>'. str_repeat('&nbsp;', $cat['depth']) . $cat['category_name'] .'</option>' . "\n";
+        }
+    }
+    $cat_list .= '</select>' . $n;
+
+    if (!empty($serendipity['GET']['title'])) {
+        $entry['title'] = utf8_decode(urldecode($serendipity['GET']['title']));
+    }
+
+    if (!empty($serendipity['GET']['body'])) {
+        $entry['body'] = utf8_decode(urldecode($serendipity['GET']['body']));
+    }
+
+    if (!empty($serendipity['GET']['url'])) {
+        $entry['body'] .= "\n" . '<br /><a href="' . htmlspecialchars(utf8_decode(urldecode($serendipity['GET']['url']))) . '">' . $entry['title'] . '</a>';
+    }
+
+    $hidden = '';
+    foreach($hiddens as $key => $value) {
+        $hidden .= '        <input type="hidden" name="' . $key . '" value="' . $value . '" />' . $n;
+    }
+    $hidden .= '        <input type="hidden" id="entryid" name="serendipity[id]" value="' . (isset($entry['id']) ? $entry['id'] : '') . '" />' . $n;
+    $hidden .= '        <input type="hidden" name="serendipity[timestamp]" value="' . (isset($entry['timestamp']) ? serendipity_serverOffsetHour($entry['timestamp']) : serendipity_serverOffsetHour(time())) . '" />' . $n;
+    $hidden .= '        <input type="hidden" name="serendipity[preview]" value="false" />';
+
+    if (!empty($errMsg)) {
+?>
+        <div class="serendipityAdminMsgError"><?php echo $errMsg; ?></div>
+<?php } ?>
+        <form action="<?php echo $targetURL; ?>" method="post" <?php echo ($serendipity['XHTML11'] ? 'id' : 'name'); ?>="serendipityEntry" style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px">
+        <?php echo $hidden; ?>
+
+        <table class="serendipityEntryEdit" border="0" width="100%">
+            <tr>
+                <td>
+                   <b><?php echo TITLE; ?>:</b>
+                </td>
+                <td colspan="2">
+                    <table width="100%" cellspacing="0" cellpadding="0" border="0">
+                        <tr>
+                            <td><input type="text" id="entryTitle" name="serendipity[title]" value="<?php echo isset($entry['title']) ? htmlspecialchars($entry['title']) : ''; ?>" size="60" /></td>
+                            <td align="right">
+                                <select name="serendipity[isdraft]">
+                                    <?php if ($_SESSION['serendipityRightPublish']) { ?><option  value="false" <?php echo $draftP; ?>><?php echo PUBLISH; ?></option><?php } ?>
+                                    <option  value="true"  <?php echo $draftD; ?>><?php echo DRAFT; ?></option>
+                                </select>
+                            </td>
+                        </tr>
+                    </table>
+                </td>
+            </tr>
+            <tr>
+<?php
+        if (isset($serendipity['allowDateManipulation']) && $serendipity['allowDateManipulation']) {
+?>
+                <td>
+                    <b><?php echo DATE; ?>:</b>
+                </td>
+                <td>
+                    <input type="hidden" name="serendipity[chk_timestamp]" value="<?php echo serendipity_serverOffsetHour(isset($entry['timestamp']) && $entry['timestamp'] > 0 ? $entry['timestamp'] : time()); ?>" />
+                    <input type="text" name="serendipity[new_timestamp]" id="serendipityNewTimestamp" value="<?php echo date(DATE_FORMAT_2, serendipity_serverOffsetHour(isset($entry['timestamp']) && $entry['timestamp'] > 0 ? $entry['timestamp'] : time())); ?>" />
+                    <a href="#" onclick="document.getElementById('serendipityNewTimestamp').value = '<?php echo date(DATE_FORMAT_2, serendipity_serverOffsetHour(time())) ?>'; return false;" title="<?php echo RESET_DATE_DESC ?>"><img src="<?php echo serendipity_getTemplateFile('admin/img/clock.png') ?>" border="0"  style="vertical-align: text-top;" alt="<?php echo RESET_DATE ?>" /></a>
+                </td>
+                <td align="right">
+<?php
+        } else {
+?>
+                <td align="right" colspan="3">
+<?php
+        }
+?>
+                    <a style="border:0; text-decoration: none" href="#" onclick="showItem('categoryselector'); return false" title="<?php echo TOGGLE_OPTION; ?>"><img src="<?php echo serendipity_getTemplateFile('img/plus.png') ?>" id="option_categoryselector" style="border: 20px" alt="" border="0" /></a> <b><?php echo CATEGORY; ?>:</b> <?php echo $cat_list ; ?>
+                    <script type="text/javascript" language="JavaScript">
+
+                    function toggle_extended(setCookie) {
+                        var textarea = document.getElementById('serendipity[extended]');
+                        var button   = document.getElementById('option_extended');
+                        var tools    = document.getElementById('tools_extended');
+                        if ( textarea.style.display == 'none' ) {
+                            textarea.style.display = '';
+                            tools.style.display = '';
+                            button.src = '<?php echo serendipity_getTemplateFile('img/minus.png') ?>';
+                            if (setCookie == true) {
+                                document.cookie = 'serendipity[toggle_extended]=true;';
+                            }
+                        } else {
+                            textarea.style.display = 'none';
+                            tools.style.display = 'none';
+                            button.src = '<?php echo serendipity_getTemplateFile('img/plus.png') ?>';
+                            if (setCookie == true) {
+                                document.cookie = 'serendipity[toggle_extended]=;';
+                            }
+                        }
+                    }
+
+                    var selector_toggle  = new Array();
+                    var selector_store   = new Array();
+                    var selector_restore = new Array();
+
+                    function showItem(id) {
+                        var selected = 0;
+                        if (document.getElementById) {
+                            el = document.getElementById(id);
+                            if (selector_toggle[id] && selector_toggle[id] == 'off') {
+                                selector_restore[id] = new Array();
+                                if (selector_store[id] > 0) {
+                                    el.size = selector_store[id];
+                                } else {
+                                    el.size = 1
+                                }
+
+                                selector_toggle[id] = 'on';
+
+                                /* Show a normal dropdown */
+                                if (el.multiple) {
+                                    el.multiple = false;
+                                }
+
+                                /* Hack to make sure that when the single dropdown is shown, don't have multiple selections */
+                                last = 0;
+                                for (i=0; i< el.options.length; i++) {
+                                    if (el.options[i].selected == true) selected++;
+
+                                    if (selected > 1) {
+                                        /* If there is more than one selected, we reset all those to false
+                                           This is because otherwise the label will say 'No Category', but the categories will still be selected */
+                                        for (j=0; j < el.options.length; j++) {
+                                            /* Save selection in array to later restore them */
+                                            if (el.options[j].selected == true) {
+                                                el.options[j].selected = false;
+                                                selector_restore[id][j] = 'on';
+                                                last = j;
+                                            } else {
+                                                selector_restore[id][j] = false;
+                                            }
+                                        }
+
+                                        el.selectedIndex = last;
+                                        break;
+                                    }
+                                }
+
+                                if (el.selectedIndex == -1) el.selectedIndex = 0;
+
+                                document.getElementById('option_' + id).src = '<?php echo serendipity_getTemplateFile('img/plus.png') ?>';
+                            } else {
+                                selector_store[id] = el.size;
+                                el.size = <?php echo count($cats)+1; ?>;
+                                selector_toggle[id] = 'off';
+
+                                /* Show multiple items */
+                                el.multiple = true;
+
+                                /* Restore previously selected items? */
+                                for (i = 0; i < el.options.length; i++) {
+                                    if (selector_restore && selector_restore[id] && selector_restore[id][i] && selector_restore[id][i] == 'on') {
+                                        val = el.options[i].value;
+                                        if (el.options[i].selected != true) {
+                                            el.options[i].selected = true;
+                                            // [TODO] IE Bug: Don't ask me why, but this restoring only works in Internet Explorer if you put this:
+                                            // alert('it doesnt matter what, just the alert is important');
+                                        }
+                                    }
+                                }
+
+                                document.getElementById('option_' + id).src = '<?php echo serendipity_getTemplateFile('img/minus.png') ?>';
+                            }
+                        }
+                    }
+
+                    function checkSave() {
+<?php
+    $void = null;
+    serendipity_plugin_api::hook_event('backend_entry_checkSave', $void);
+?>
+                        return true;
+                    }
+
+                    selector_toggle['categoryselector'] = '<?php echo ($categoryselector_expanded ? 'on' : 'off'); ?>';
+                    showItem('categoryselector');
+                    </script>
+                    </td>
+            </tr>
+            <tr>
+<?php
+    if (!$serendipity['wysiwyg']) {
+?>
+                <td colspan="2"><b><?php echo ENTRY_BODY; ?></b></td>
+                <td align="right">
+<?php
+        /* Since the user has WYSIWYG editor disabled, we want to check if we should use the "better" non-WYSIWYG editor */
+        if (!$serendipity['wysiwyg'] && eregi($serendipity['EditorBrowsers'], $_SERVER['HTTP_USER_AGENT']) ) {
+?>
+                  <script type="text/javascript" language="JavaScript">
+                        document.write('<input type="button" class="serendipityPrettyButton" name="insI" value="I" accesskey="i" style="font-style: italic" onclick="wrapSelection(document.forms[\'serendipityEntry\'][\'serendipity[body]\'],\'<i>\',\'</i>\')" />');
+                        document.write('<input type="button" class="serendipityPrettyButton" name="insB" value="B" accesskey="i" style="font-weight: bold" onclick="wrapSelection(document.forms[\'serendipityEntry\'][\'serendipity[body]\'],\'<b>\',\'</b>\')" />');
+                        document.write('<input type="button" class="serendipityPrettyButton" name="insU" value="U" accesskey="u" style="text-decoration: underline;" onclick="wrapSelection(document.forms[\'serendipityEntry\'][\'serendipity[body]\'],\'<u>\',\'</u>\')" />');
+                        document.write('<input type="button" class="serendipityPrettyButton" name="insQ" value="<?php echo QUOTE ?>" accesskey="q" style="font-style: italic" onclick="wrapSelection(document.forms[\'serendipityEntry\'][\'serendipity[body]\'],\'<blockquote>\',\'</blockquote>\')" />');
+                        document.write('<input type="button" class="serendipityPrettyButton" name="insJ" value="img" accesskey="j" onclick="wrapInsImage(document.forms[\'serendipityEntry\'][\'serendipity[body]\'])" />');
+                        document.write('<input type="button" class="serendipityPrettyButton" name="insImage" value="<?php echo MEDIA; ?>" style="" onclick="window.open(\'serendipity_admin_image_selector.php?serendipity[textarea]=body\', \'ImageSel\', \'width=800,height=600,toolbar=no,scrollbars=1,scrollbars,resize=1,resizable=1\');" />');
+                        document.write('<input type="button" class="serendipityPrettyButton" name="insU" value="URL" accesskey="l" style="color: blue; text-decoration: underline;" onclick="wrapSelectionWithLink(document.forms[\'serendipityEntry\'][\'serendipity[body]\'])" />');
+                  </script>
+<?php
+        /* Do the "old" non-WYSIWYG editor */
+        } elseif (!$serendipity['wysiwyg']) { ?>
+                  <script type="text/javascript" language="JavaScript">
+                        document.write('<input type="button" class="serendipityPrettyButton" value=" B " onclick="serendipity_insBasic(document.forms[\'serendipityEntry\'][\'serendipity[body]\'], \'b\')">');
+                        document.write('<input type="button" class="serendipityPrettyButton" value=" U " onclick="serendipity_insBasic(document.forms[\'serendipityEntry\'][\'serendipity[body]\'], \'u\')">');
+                        document.write('<input type="button" class="serendipityPrettyButton" value=" I " onclick="serendipity_insBasic(document.forms[\'serendipityEntry\'][\'serendipity[body]\'], \'i\')">');
+                        document.write('<input type="button" class="serendipityPrettyButton" value="<img>" onclick="serendipity_insImage(document.forms[\'serendipityEntry\'][\'serendipity[body]\'])">');
+                        document.write('<input type="button" class="serendipityPrettyButton" value="<?php echo MEDIA; ?>" onclick="window.open(\'serendipity_admin_image_selector.php?serendipity[textarea]=body\', \'ImageSel\', \'width=800,height=600,toolbar=no\');">');
+                        document.write('<input type="button" class="serendipityPrettyButton" value="Link" onclick="serendipity_insLink(document.forms[\'serendipityEntry\'][\'serendipity[body]\'])">');
+                </script>
+<?php   }
+
+        serendipity_plugin_api::hook_event('backend_entry_toolbar_body', $entry);
+    } else {
+?>
+            <td colspan="2"><b><?php echo ENTRY_BODY; ?></b></td>
+            <td><?php serendipity_plugin_api::hook_event('backend_entry_toolbar_body', $entry); ?>
+
+<?php } ?>
+                </td>
+            </tr>
+
+            <tr>
+                <td colspan="3">
+                    <textarea style="width: 100%" name="serendipity[body]" id="serendipity[body]" cols="80" rows="20"><?php echo isset($entry['body']) ? htmlspecialchars($entry['body']) : ''; ?></textarea>
+                </td>
+            </tr>
+
+            <tr>
+                <td colspan="3">
+                    <table width="100%" cellpadding="0" cellspacing="0">
+                        <tr>
+                            <td align="left" width="70%">
+                                <input id="checkbox_allow_comments" type="checkbox" name="serendipity[allow_comments]" value="true" <?php echo $allow_comments; ?> /><label for="checkbox_allow_comments"><?php echo COMMENTS_ENABLE; ?></label><br />
+                                <input id="checkbox_moderate_comments" type="checkbox" name="serendipity[moderate_comments]" value="true" <?php echo $moderate_comments; ?> /><label for="checkbox_moderate_comments"><?php echo COMMENTS_MODERATE; ?></label>
+                            </td>
+                            <td align="right" rowspan="2" valign="middle" width="30%">
+                                <input accesskey="p" type="submit" value="- <?php echo PREVIEW; ?> -" class="serendipityPrettyButton"  style="width: 150px" onclick="document.forms['serendipityEntry'].elements['serendipity[preview]'].value='true';" /><br />
+                                <input accesskey="s" type="submit" onclick="return checkSave();" value="- <?php echo SAVE; ?> -" class="serendipityPrettyButton" style="width: 150px" />
+                            </td>
+                        </tr>
+                    </table>
+                    <br />
+                </td>
+            </tr>
+
+            <tr>
+                <td colspan="2">
+<?php if (!$serendipity['wysiwyg']) { ?>
+                    <a style="border:0; text-decoration: none" href="#" onclick="toggle_extended(true); return false;" title="<?php echo TOGGLE_OPTION; ?>"><img src="<?php echo serendipity_getTemplateFile('img/plus.png') ?>" id="option_extended" alt="+/-" border="0" /></a>
+<?php } ?> <b><?php echo EXTENDED_BODY; ?></b></td>
+                <td align="right">
+                <?php
+if (!$serendipity['wysiwyg']) {
+?>
+                    <div id="tools_extended" style="display: none">
+<?php
+        /* Since the user has WYSIWYG editor disabled, we want to check if we should use the "better" non-WYSIWYG editor */
+        if (eregi($serendipity['EditorBrowsers'], $_SERVER['HTTP_USER_AGENT']) ) {
+?>
+                        <input type="button" class="serendipityPrettyButton" name="insI" value="I" accesskey="i" style="font-style: italic" onclick="wrapSelection(document.forms['serendipityEntry']['serendipity[extended]'],'<i>','</i>')" />
+                        <input type="button" class="serendipityPrettyButton" name="insB" value="B" accesskey="i" style="font-weight: bold" onclick="wrapSelection(document.forms['serendipityEntry']['serendipity[extended]'],'<b>','</b>')" />
+                        <input type="button" class="serendipityPrettyButton" name="insU" value="U" accesskey="u" style="text-decoration: underline;" onclick="wrapSelection(document.forms['serendipityEntry']['serendipity[extended]'],'<u>','</u>')" />
+                        <input type="button" class="serendipityPrettyButton" name="insQ" value="<?php echo QUOTE ?>" accesskey="q" style="font-style: italic" onclick="wrapSelection(document.forms['serendipityEntry']['serendipity[extended]'],'<blockquote>','</blockquote>')" />
+                        <input type="button" class="serendipityPrettyButton" name="insJ" value="img" accesskey="j" onclick="wrapInsImage(document.forms['serendipityEntry']['serendipity[extended]'])" />
+                        <input type="button" class="serendipityPrettyButton" name="insImage" value="<?php echo MEDIA; ?>" onclick="window.open('serendipity_admin_image_selector.php?serendipity[textarea]=extended', 'ImageSel', 'width=800,height=600,toolbar=no,scrollbars=1,scrollbars,resize=1,resizable=1');" />
+                        <input type="button" class="serendipityPrettyButton" name="insU" value="URL" accesskey="l" style="color: blue; text-decoration: underline;" onclick="wrapSelectionWithLink(document.forms['serendipityEntry']['serendipity[extended]'])" />
+<?php
+        /* Do the "old" non-WYSIWYG editor */
+        } else { ?>
+                        <input type="button" class="serendipityPrettyButton" value=" B " onclick="serendipity_insBasic(document.forms['serendipityEntry']['serendipity[extended]'], 'b')">
+                        <input type="button" class="serendipityPrettyButton" value=" U " onclick="serendipity_insBasic(document.forms['serendipityEntry']['serendipity[extended]'], 'u')">
+                        <input type="button" class="serendipityPrettyButton" value=" I " onclick="serendipity_insBasic(document.forms['serendipityEntry']['serendipity[extended]'], 'i')">
+                        <input type="button" class="serendipityPrettyButton" value="<img>" onclick="serendipity_insImage(document.forms['serendipityEntry']['serendipity[extended]'])">
+                        <input type="button" class="serendipityPrettyButton" value="<?php echo MEDIA; ?>" onclick="window.open('serendipity_admin_image_selector.php?serendipity[textarea]=extended', 'ImageSel', 'width=800,height=600,toolbar=no');">
+                        <input type="button" class="serendipityPrettyButton" value="Link" onclick="serendipity_insLink(document.forms['serendipityEntry']['serendipity[extended]'])">
+<?php
+        }
+
+        serendipity_plugin_api::hook_event('backend_entry_toolbar_extended', $entry);
+?>
+                    </div>
+<?php } else {
+        serendipity_plugin_api::hook_event('backend_entry_toolbar_extended', $entry);
+} ?>
+               </td>
+            </tr>
+
+            <tr>
+                <td colspan="3">
+                    <textarea style="width: 100%;" name="serendipity[extended]" id="serendipity[extended]" cols="80" rows="20"><?php echo isset($entry['extended']) ? htmlspecialchars($entry['extended']) : ''; ?></textarea>
+<?php if (!$serendipity['wysiwyg']) { ?>
+                    <script type="text/javascript" language="JavaScript">
+                       toggle_extended();
+                    </script>
+<?php } ?>
+                </td>
+            </tr>
+
+            <tr>
+                <td colspan="3">
+                    <br />
+                    <fieldset>
+                        <legend><b><?php echo ADVANCED_OPTIONS; ?></b></legend>
+<?php
+    serendipity_plugin_api::hook_event('backend_display', $entry);
+?>
+                    </fieldset>
+                </td>
+            </tr>
+        </table>
+    </form>
+<?php
+    if ((!empty($entry['extended']) || !empty($serendipity['COOKIE']['toggle_extended'])) && !$serendipity['wysiwyg']) {
+?>
+    <script type="text/javascript" language="JavaScript">
+        toggle_extended();
+    </script>
+<?php } ?>
+<?php
+    if ($serendipity['wysiwyg']) {
+        serendipity_emit_htmlarea_code('serendipity[body]', 'body');
+        serendipity_emit_htmlarea_code('serendipity[extended]', 'extended');
+    }
+
+    echo '    <script type="text/javascript" language="JavaScript" src="serendipity_define.js.php"></script>';
+    echo '    <script type="text/javascript" language="JavaScript" src="serendipity_editor.js"></script>';
+}
+
+function serendipity_emit_htmlarea_code($item, $jsname) {
+    static $init = false;
+    global $serendipity;
+
+    if (isset ($serendipity['wysiwyg']) && $serendipity['wysiwyg']) {
+
+        if (!$init) {
+?>
+    <script type="text/javascript">
+        _editor_url = "<?php echo $serendipity['serendipityHTTPPath'] . 'htmlarea/'; ?>";
+        _editor_lang = "<?php echo WYSIWYG_LANG; ?>";
+        var editorref = '';
+    </script>
+    <script type="text/javascript" src="htmlarea/htmlarea.js"></script>
+    <script type="text/javascript" src="htmlarea/lang/<?php echo WYSIWYG_LANG; ?>.js"></script>
+    <script type="text/javascript" src="htmlarea/dialog.js"></script>
+    <style  type="text/css">@import url(htmlarea/htmlarea.css);</style>
+<?php
+        }
+
+    $csscode = str_replace(
+                 array(
+                   "\n",
+                   "'",
+                   "\r"
+                 ),
+
+                 array(
+                   '\n',
+                   "\'",
+                   ""
+                 ),
+
+                 file_get_contents(serendipity_getTemplateFile('htmlarea.css', 'serendipityPath'))
+    );
+?>
+    <script type="text/javascript">
+    // IF you want to enable HTMLArea's spellchecker, download the SpellChecker plugin from the HTMLArea homepage
+    // (http://www.sourceforge.net/projects/itools-htmlarea) and uncomment the lines suffixed with ' // [SPELLCHECK]'
+    // Note that the SpellChecker is a CGI-based application which needs setup in your Apache host ("Options +CGIExec")
+    // Thanks to Randall for pointing this out!
+
+    // HTMLArea.loadPlugin("SpellChecker"); // [SPELLCHECK]
+    var editor<?php echo $jsname; ?> = null; var config<?php echo $jsname; ?> = null;
+    function Spawn<?php echo $jsname; ?>() {
+        var editor<?php echo $jsname; ?>    = new HTMLArea("<?php echo $item; ?>");
+        var config<?php echo $jsname; ?>    = editor<?php echo $jsname; ?>.config;
+        config<?php echo $jsname; ?>.registerButton('image_selector', '<?PHP echo MANAGE_IMAGES; ?>', 'htmlarea/images/ed_s9yimage.gif', false,
+            function(editor, id) {
+                window.open('serendipity_admin_image_selector.php?serendipity[textarea]=<?php echo $jsname; ?>', 'ImageSel', 'width=800,height=600,toolbar=no,scrollbars=1,scrollbars,resize=1,resizable=1');
+                editorref = editor<?php echo $jsname; ?>;
+            }
+        );
+        config<?php echo $jsname; ?>.toolbar.push([ "image_selector"]);
+        config<?php echo $jsname; ?>.cssFile = '<?php echo $csscode; ?>';
+        config<?php echo $jsname; ?>.toolbar = [
+            [ "fontname", "space",
+              "fontsize", "space",
+              "formatblock", "space",
+              "bold", "italic", "underline", "strikethrough", "separator",
+              "subscript", "superscript", "separator",
+              "copy", "cut", "paste", "space", "undo", "redo" ],
+
+            [ "justifyleft", "justifycenter", "justifyright", "justifyfull", "separator",
+              "lefttoright", "righttoleft", "separator",
+              "orderedlist", "unorderedlist", "outdent", "indent", "separator",
+              "forecolor", "hilitecolor", "separator",
+              "inserthorizontalrule", "createlink", "insertimage", "image_selector", "inserttable", "htmlmode", "separator",
+              "popupeditor", "separator", "showhelp", "about" ]
+        ];
+        // editor<?php echo $jsname; ?>.registerPlugin(SpellChecker);  // [SPELLCHECK]
+        editor<?php echo $jsname; ?>.generate();
+        editor<?php echo $jsname; ?>._textArea.className = 'serendipity_entry';
+    }
+    </script>
+<?php
+    }
+
+    $init = true;
+}
+
+function serendipity_updateEntryCategories($postid, $categories) {
+    global $serendipity;
+
+    if (!$postid || !$categories) {
+        return;
+    }
+
+    $query = "DELETE FROM $serendipity[dbPrefix]entrycat WHERE entryid = " . (int)$postid;
+    serendipity_db_query($query);
+
+    if (!is_array($categories)) {
+        $categories = array(0 => $categories);
+    }
+
+    foreach($categories AS $idx => $cat) {
+        $query = "INSERT INTO $serendipity[dbPrefix]entrycat (categoryid, entryid) VALUES (" . (int)$cat . ", " . (int)$postid . ")";
+        serendipity_db_query($query);
+    }
+}
+
+function serendipity_printArchives() {
+    global $serendipity;
+
+    $f = serendipity_db_query("SELECT timestamp FROM {$serendipity['dbPrefix']}entries ORDER BY timestamp ASC LIMIT 1");
+    $lastYear   = date('Y', serendipity_serverOffsetHour($f[0][0]));
+    $lastMonth  = date('m', serendipity_serverOffsetHour($f[0][0]));
+    $thisYear   = date('Y', serendipity_serverOffsetHour());
+    $thisMonth  = date('m', serendipity_serverOffsetHour());
+    $max        = 0;
+
+    $output = array();
+    for ($y = $thisYear; $y >= $lastYear; $y--) {
+        $output[$y]['year'] = $y;
+        for ($m = 12; $m >= 1; $m--) {
+
+            /* If the month we are checking are in the future, we drop it */
+            if ($m > $thisMonth && $y == $thisYear) {
+                continue;
+            }
+
+            /* If the month is lower than the lowest month containing entries, we're done */
+            if ($m < $lastMonth && $y <= $lastYear) {
+                break;
+            }
+
+            $s = serendipity_serverOffsetHour(mktime(0, 0, 0, $m, 1, $y), true);
+            $e = serendipity_serverOffsetHour(mktime(23, 59, 59, $m, date('t', $s), $y), true);
+            $entries = serendipity_db_query("SELECT count(id) FROM {$serendipity['dbPrefix']}entries
+                                                       WHERE isdraft = 'false'
+                                                           AND timestamp >= $s
+                                                           AND timestamp <= $e
+                                                           " . (!serendipity_db_bool($serendipity['showFutureEntries']) ? " AND timestamp <= " . time() : ''));
+            $entry_count = $entries[0][0];
+
+            /* A silly hack to get the maximum amount of entries per month */
+            if ($entry_count > $max) {
+                $max = $entry_count;
+            }
+
+            $data = array();
+            $data['entry_count']    = $entry_count;
+            $data['link']           = serendipity_archiveDateUrl($y . '/'. sprintf('%02s', $m));
+            $data['link_summary']   = serendipity_archiveDateUrl($y . '/'. sprintf('%02s', $m), true);
+            $data['date']           = $s;
+            $output[$y]['months'][] = $data;
+        }
+    }
+    $serendipity['smarty']->assign(array('archives' => $output,
+                                         'max_entries' => $max));
+
+    serendipity_smarty_fetch('ARCHIVES', 'entries_archives.tpl', true);
+}
+
diff --git a/include/functions_images.inc.php b/include/functions_images.inc.php
new file mode 100644 (file)
index 0000000..222a111
--- /dev/null
@@ -0,0 +1,1289 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+/**
+* Get a list of images
+**/
+function serendipity_fetchImagesFromDatabase($start=0, $limit=0, &$total, $order = false, $ordermode = false, $directory = '', $filename = '') {
+    global $serendipity;
+
+    $orderfields = serendipity_getImageFields();
+    if (empty($order) || !isset($orderfields[$order])) {
+        $order = 'date';
+    }
+
+    if (empty($ordermode) || ($ordermode != 'DESC' && $ordermode != 'ASC')) {
+        $ordermode = 'DESC';
+    }
+
+    if ($limit != 0) {
+        $limitsql = serendipity_db_limit_sql(serendipity_db_limit($start, $limit));
+    }
+
+    if (!empty($directory)) {
+        $directorysql = ' WHERE path LIKE \'' . serendipity_db_escape_string($directory) . '%\' ';
+    }
+
+    if (!empty($filename)) {
+        if (empty($directorysql)) {
+            $directorysql = " WHERE  name like '%" . serendipity_db_escape_string($filename) . "%'";
+        } else {
+            $directorysql .= " AND   name like '%" . serendipity_db_escape_string($filename) . "%'";
+        }
+    }
+
+    $query = "SELECT i.*, a.realname AS authorname FROM {$serendipity['dbPrefix']}images AS i LEFT OUTER JOIN {$serendipity['dbPrefix']}authors AS a ON i.authorid = a.authorid $directorysql ORDER BY $order $ordermode $limitsql";
+    $rs = serendipity_db_query($query, false, 'assoc');
+    if (!is_array($rs)) {
+        return array();
+    }
+
+    $total_query = "SELECT count(i.id) FROM {$serendipity['dbPrefix']}images AS i LEFT OUTER JOIN {$serendipity['dbPrefix']}authors AS a on i.authorid = a.authorid";
+    $total_rs = serendipity_db_query($total_query, true, 'num');
+    if (is_array($total_rs)) {
+        $total = $total_rs[0];
+    }
+
+    return $rs;
+}
+
+function serendipity_fetchImageFromDatabase($id) {
+    global $serendipity;
+    $rs = serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}images WHERE id = ". (int)$id, true, 'assoc');
+    return $rs;
+}
+
+function serendipity_updateImageInDatabase($updates, $id) {
+    global $serendipity;
+
+    $admin = '';
+    if ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF) {
+        $admin = ' AND (authorid = ' . $serendipity['authorid'] . ' OR authorid = 0)';
+    }
+
+    $i=0;
+    if (sizeof($updates) > 0) {
+        foreach ($updates as $k => $v) {
+            $q[] = $k ." = '" . serendipity_db_escape_string($v) . "'";
+        }
+        serendipity_db_query("UPDATE {$serendipity['dbPrefix']}images SET ". implode($q, ',') ." WHERE id = " . (int)$id . " $admin");
+        $i++;
+    }
+    return $i;
+}
+
+function serendipity_deleteImage($id) {
+    global $serendipity;
+    $file   = serendipity_fetchImageFromDatabase($id);
+    $dFile  = $file['path'] . $file['name'] .'.'. $file['extension'];
+    $dThumb = $file['path'] . $file['name'] .'.'. $file['thumbnail_name'] .'.'. $file['extension'];
+
+    $admin = '';
+    if ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF && $file['authorid'] != '0' && $file['authorid'] != $serendipity['authorid']) {
+        // A non-admin user may not delete private files from other users.
+        return;
+    }
+
+    if (!$file['hotlink']) {
+        if (file_exists($serendipity['serendipityPath'] . $serendipity['uploadPath'] . $dFile)) {
+            if (@unlink($serendipity['serendipityPath'] . $serendipity['uploadPath'] . $dFile)) {
+                printf(DELETE_FILE . '<br />', $dFile);
+            } else {
+                printf(DELETE_FILE_FAIL . '<br />', $dFile);
+            }
+
+            if (@unlink($serendipity['serendipityPath'] . $serendipity['uploadPath'] . $dThumb)) {
+                printf(DELETE_THUMBNAIL . '<br />', $dThumb);
+            }
+        } else {
+            printf(FILE_NOT_FOUND . '<br />', $dFile);
+        }
+    } else {
+        printf(DELETE_HOTLINK_FILE . '<br />', $file['name']);
+    }
+
+    serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}images WHERE id = ". (int)$id);
+
+}
+
+/**
+* Get a list of images
+**/
+function serendipity_fetchImages($group = false, $start = 0, $end = 20, $images = '', $odir = '') {
+    global $serendipity;
+
+    // Open directory
+    $basedir = $serendipity['serendipityPath'] . $serendipity['uploadPath'];
+    $images = array();
+    if ($dir = @opendir($basedir . $odir)) {
+        while(false !== ($f = readdir($dir))) {
+            if ($f != '.' && $f != '..' && strpos($f, $serendipity['thumbSuffix']) === false) {
+                $cdir = ($odir != '' ? $odir . '/' : '');
+                if (is_dir($basedir . $odir . '/' . $f)) {
+                    $temp = serendipity_fetchImages($group, $start, $end, $images, $cdir . $f);
+                    foreach($temp AS $tkey => $tval) {
+                        array_push($images, $tval);
+                    }
+                } else {
+                    array_push($images, $cdir . $f);
+                }
+            }
+        }
+    }
+    natsort($images);
+
+    /* BC */
+    $serendipity['imageList'] = $images;
+    return $images;
+}
+
+function serendipity_insertHotlinkedImageInDatabase($filename, $url, $authorid = 0, $time = NULL, $tempfile = NULL) {
+    global $serendipity;
+
+    if (is_null($time)) {
+        $time = time();
+    }
+
+    list($filebase, $extension) = serendipity_parseFileName($filename);
+
+    if ($tempfile && file_exists($tempfile)) {
+        $filesize = @filesize($tempfile);
+        $fdim     = @serendipity_getimagesize($tempfile, '', $extension);
+        $width    = $fdim[0];
+        $height   = $fdim[1];
+        $mime     = $fdim['mime'];
+        @unlink($tempfile);
+    }
+
+    $query = sprintf(
+      "INSERT INTO {$serendipity['dbPrefix']}images (
+                    name,
+                    date,
+                    authorid,
+                    extension,
+                    mime,
+                    size,
+                    dimensions_width,
+                    dimensions_height,
+                    path,
+                    hotlink
+                   ) VALUES (
+                    '%s',
+                    %s,
+                    %s,
+                    '%s',
+                    '%s',
+                    %s,
+                    %s,
+                    %s,
+                    '%s',
+                    1
+                   )",
+      serendipity_db_escape_string($filebase),
+      (int)$time,
+      (int)$authorid,
+      serendipity_db_escape_string($extension),
+      serendipity_db_escape_string($mime),
+      (int)$filesize,
+      (int)$width,
+      (int)$height,
+      serendipity_db_escape_string($url)
+    );
+
+    $sql = serendipity_db_query($query);
+    if (is_string($sql)) {
+        echo $query . '<br />';
+        echo $sql . '<br />';
+    }
+
+    $image_id = serendipity_db_insert_id('images', 'id');
+    if ($image_id > 0) {
+        return $image_id;
+    }
+
+    return 0;
+}
+
+function serendipity_insertImageInDatabase($filename, $directory, $authorid = 0, $time = NULL) {
+    global $serendipity;
+
+    if ( is_null($time) ) {
+        $time = time();
+    }
+
+    $filepath = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $directory . $filename;
+    $filesize = @filesize($filepath);
+
+    list($filebase, $extension) = serendipity_parseFileName($filename);
+
+    $thumbpath = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $directory . $filebase . '.'. $serendipity['thumbSuffix'] . '.'. $extension;
+    $thumbnail = (file_exists($thumbpath) ? $serendipity['thumbSuffix'] : '');
+
+    $fdim = @serendipity_getimagesize($filepath, '', $extension);
+    $width = $fdim[0];
+    $height = $fdim[1];
+    $mime = $fdim['mime'];
+
+
+    $query = sprintf(
+      "INSERT INTO {$serendipity['dbPrefix']}images (
+                    name,
+                    extension,
+                    mime,
+                    size,
+                    dimensions_width,
+                    dimensions_height,
+                    thumbnail_name,
+                    date,
+                    authorid,
+                    path
+                   ) VALUES (
+                    '%s',
+                    '%s',
+                    '%s',
+                    %s,
+                    %s,
+                    %s,
+                    '%s',
+                    %s,
+                    %s,
+                    '%s'
+                   )",
+      serendipity_db_escape_string($filebase),
+      serendipity_db_escape_string($extension),
+      serendipity_db_escape_string($mime),
+      (int)$filesize,
+      (int)$width,
+      (int)$height,
+      serendipity_db_escape_string($thumbnail),
+      (int)$time,
+      (int)$authorid,
+      serendipity_db_escape_string($directory)
+    );
+
+    $sql = serendipity_db_query($query);
+    if (is_string($sql)) {
+        echo $query . '<br />';
+        echo $sql . '<br />';
+    }
+
+    $image_id = serendipity_db_insert_id('images', 'id');
+    if ($image_id > 0) {
+        return $image_id;
+    }
+
+    return 0;
+}
+
+
+/**
+* Generate a thumbnail
+**/
+function serendipity_makeThumbnail($file, $directory = '', $size = false) {
+    global $serendipity;
+
+    if ($size === false) {
+        $size = $serendipity['thumbSize'];
+    }
+
+    $t       = serendipity_parseFileName($file);
+    $f       = $t[0];
+    $suf     = $t[1];
+
+
+    $infile  = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $directory . $file;
+    $outfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $directory . $f . '.' . $serendipity['thumbSuffix'] . '.' . $suf;
+
+    $fdim    = @serendipity_getimagesize($infile, '', $suf);
+    if (isset($fdim['noimage'])) {
+        $r = array(0, 0);
+    } else {
+        if ($serendipity['magick'] !== true) {
+            $r = serendipity_resize_image_gd($infile, $outfile, $size);
+        } else {
+            $r = array($size, $size);
+            $newSize = $size . 'x' . $size;
+            if ($ft_mime != 'application/pdf') {
+               $cmd     = escapeshellcmd($serendipity['convert']) . ' -antialias -scale '. serendipity_escapeshellarg($newSize) .' '. serendipity_escapeshellarg($infile) .' '. serendipity_escapeshellarg($outfile);
+            } else {
+               $cmd     = escapeshellcmd($serendipity['convert']) . ' -antialias -flatten -scale '. serendipity_escapeshellarg($newSize) .' '. serendipity_escapeshellarg($infile) .' '. serendipity_escapeshellarg($outfile .'.png');
+            }
+            exec($cmd, $output, $result);
+            if ( $result != 0 ) {
+                echo '<div class="serendipityAdminMsgError">'. sprintf(IMAGICK_EXEC_ERROR, $cmd, $output[0], $result) .'</div>';
+                $r = false; // return failure
+            }
+            unset($output, $result);
+        }
+    }
+
+    return $r;
+}
+
+/**
+*  Scale an image (ignoring proportions)
+**/
+function serendipity_scaleImg($id, $width, $height) {
+    global $serendipity;
+
+    $file = serendipity_fetchImageFromDatabase($id);
+
+    $admin = '';
+    if ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF && $file['authorid'] != '0' && $file['authorid'] != $serendipity['authorid']) {
+        return;
+    }
+
+    $infile = $outfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . '.' . $file['extension'];
+
+    if ($serendipity['magick'] !== true) {
+        serendipity_resize_image_gd($infile, $outfile, $width, $height);
+    } else {
+        $cmd = escapeshellcmd($serendipity['convert']) . ' -scale ' .  serendipity_escapeshellarg($width . 'x' . $height) . ' ' . serendipity_escapeshellarg($infile) . ' ' . serendipity_escapeshellarg($outfile);
+        exec($cmd, $output, $result);
+        if ( $result != 0 ) {
+            echo '<div class="serendipityAdminMsgError">'. sprintf(IMAGICK_EXEC_ERROR, $cmd, $output[0], $result) .'</div>';
+        }
+        unset($output, $result);
+    }
+
+    serendipity_updateImageInDatabase(array('dimensions_width' => $width, 'dimensions_height' => $height), $id);
+    return true;
+}
+
+/**
+ * Rotate an Image
+ **/
+function serendipity_rotateImg($id, $degrees) {
+    global $serendipity;
+
+    $file = serendipity_fetchImageFromDatabase($id);
+
+    $admin = '';
+    if ($serendipity['serendipityUserlevel'] < USERLEVEL_CHIEF && $file['authorid'] != '0' && $file['authorid'] != $serendipity['authorid']) {
+        // A non-admin user may not delete private files from other users.
+        return false;
+    }
+
+    $infile = $outfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . '.' . $file['extension'];
+    $infileThumb = $outfileThumb = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . '.' . $file['thumbnail_name'] . '.'. $file['extension'];
+
+    if ($serendipity['magick'] !== true) {
+        serendipity_rotate_image_gd($infile, $outfile, $degrees);
+        serendipity_rotate_image_gd($infileThumb, $outfileThumb, $degrees);
+    } else {
+        /* Why can't we just all agree on the rotation direction? */
+        $degrees = (360 - $degrees);
+
+        /* Resize main image */
+        $cmd = escapeshellcmd($serendipity['convert']) . ' -rotate ' . serendipity_escapeshellarg($degrees) . ' ' . serendipity_escapeshellarg($infile) . ' ' . serendipity_escapeshellarg($outfile);
+        exec($cmd, $output, $result);
+        if ( $result != 0 ) {
+            echo '<div class="serendipityAdminMsgError">'. sprintf(IMAGICK_EXEC_ERROR, $cmd, $output[0], $result) .'</div>';
+        }
+        unset($output, $result);
+
+        /* Resize thumbnail */
+        $cmd = escapeshellcmd($serendipity['convert']) . ' -rotate ' . serendipity_escapeshellarg($degrees) . ' ' . serendipity_escapeshellarg($infileThumb) . ' ' . serendipity_escapeshellarg($outfileThumb);
+        exec($cmd, $output, $result);
+        if ( $result != 0 ) {
+            echo '<div class="serendipityAdminMsgError">'. sprintf(IMAGICK_EXEC_ERROR, $cmd, $output[0], $result) .'</div>';
+        }
+        unset($output, $result);
+
+    }
+
+    $fdim = @getimagesize($outfile);
+
+    serendipity_updateImageInDatabase(array('dimensions_width' => $fdim[0], 'dimensions_height' => $fdim[1]), $id);
+
+    return true;
+}
+
+
+/**
+* Creates thumbnails for all images in the upload dir
+**/
+function serendipity_generateThumbs() {
+    global $serendipity;
+
+    $i=0;
+    $serendipity['imageList'] = serendipity_fetchImagesFromDatabase(0, 0, $total);
+
+    foreach ($serendipity['imageList'] as $k => $file) {
+        $is_image = serendipity_isImage($file);
+
+        if ($is_image && !$file['hotlink']) {
+            $update   = false;
+            $filename = $file['path'] . $file['name'] .'.'. $file['extension'];
+            $ffull    = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $filename;
+
+            if (!file_exists($ffull)) {
+                serendipity_deleteImage($file['id']);
+                continue;
+            }
+
+            if (empty($file['thumbnail_name'])) {
+                $file['thumbnail_name'] = $serendipity['thumbSuffix'];
+            }
+
+            $oldThumb = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . '.' . $file['thumbnail_name'] . '.' . $file['extension'];
+            $newThumb = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . '.' . $serendipity['thumbSuffix'] . '.' . $file['extension'];
+            $fdim = @getimagesize($ffull);
+
+            if (!file_exists($oldThumb) && !file_exists($newThumb) && ($fdim[0] > $serendipity['thumbSize'] || $fdim[1] > $serendipity['thumbSize'])) {
+                $returnsize = serendipity_makeThumbnail($file['name'] . '.' . $file['extension'], $file['path']);
+                if ($returnsize !== false ) {
+                    printf(RESIZE_BLAHBLAH, $filename . ': ' . $returnsize[0] . 'x' . $returnsize[1]);
+                    if (!file_exists($newThumb)) {
+                        printf('<span class="serendipityAdminMsgError">' . THUMBNAIL_FAILED_COPY . '</span><br />', $filename);
+                    } else {
+                        $update = true;
+                    }
+                }
+            } elseif (!file_exists($oldThumb) && !file_exists($newThumb) && $fdim[0] <= $serendipity['thumbSize'] && $fdim[1] <= $serendipity['thumbSize']) {
+                $res = @copy($ffull, $newThumb);
+                if (@$res === true) {
+                    printf(THUMBNAIL_USING_OWN . '<br />', $filename);
+                    $update = true;
+                } else {
+                    printf('<span class="serendipityAdminMsgError">' . THUMBNAIL_FAILED_COPY . '</span><br />', $filename);
+                }
+            }
+
+            if ($update) {
+                $i++;
+                $updates = array('thumbnail_name' => $serendipity['thumbSuffix']);
+                serendipity_updateImageInDatabase($updates, $file['id']);
+            }
+        } else {
+            // Currently, non-image files have no thumbnail.
+        }
+    }
+
+    return $i;
+}
+
+function serendipity_guessMime($extension) {
+    $mime = '';
+    switch (strtolower($extension)) {
+        case 'jpg':
+        case 'jpeg':
+            $mime = 'image/jpeg';
+        break;
+
+        case 'aiff':
+        case 'aif':
+            $mime = 'audio/x-aiff';
+            break;
+
+        case 'gif':
+            $mime = 'image/gif';
+        break;
+
+        case 'png':
+            $mime = 'image/png';
+        break;
+
+        case 'pdf':
+            $mime = 'application/pdf';
+            break;
+
+        case 'doc':
+            $mime = 'application/msword';
+            break;
+
+        case 'rtf':
+            $mime = 'application/rtf';
+            break;
+
+        case 'wav':
+        case 'wave':
+            $mime = 'audio/x-wav';
+            break;
+
+        case 'mp2':
+        case 'mpg':
+        case 'mpeg':
+            $mime = 'video/x-mpeg';
+            break;
+
+        case 'avi':
+            $mime = 'video/x-msvideo';
+            break;
+
+        case 'mp3':
+            $mime = 'audio/x-mpeg3';
+            break;
+
+        case 'xlm':
+        case 'xlb':
+        case 'xll':
+        case 'xla':
+        case 'xlw':
+        case 'xlc':
+        case 'xls':
+        case 'xlt':
+            $mime = 'application/vnd.ms-excel';
+            break;
+
+        case 'ppt':
+        case 'pps':
+            $mime = 'application/vnd.ms-powerpoint';
+            break;
+
+        case 'html':
+        case 'htm':
+            $mime = 'text/html';
+            break;
+
+        case 'xsl':
+        case 'xslt':
+        case 'xml':
+        case 'wsdl':
+        case 'xsd':
+            $mime = 'text/xml';
+            break;
+
+        case 'zip':
+            $mime = 'application/zip';
+            break;
+
+        case 'tar':
+            $mime = 'application/x-tar';
+            break;
+
+        case 'tgz':
+        case 'gz':
+            $mime = 'application/x-gzip';
+            break;
+
+        case 'swf':
+            $mime = 'application/x-shockwave-flash';
+            break;
+
+        case 'rm':
+        case 'ra':
+        case 'ram':
+            $mime = 'application/vnd.rn-realaudio';
+            break;
+
+        case 'exe':
+            $mime = 'application/octet-stream';
+            break;
+
+        case 'mov':
+        case 'qt':
+            $mime = 'video/x-quicktime';
+            break;
+
+        case 'midi':
+        case 'mid':
+            $mime = 'audio/x-midi';
+            break;
+
+        case 'txt':
+            $mime = 'text/plain';
+            break;
+
+        case 'qcp':
+            $mime = 'audio/vnd.qcelp';
+            break;
+
+        case 'emf':
+            $mime = 'image/x-emf';
+            break;
+
+        case 'wmf':
+            $mime = 'image/x-wmf';
+            break;
+
+        case 'snd':
+            $mime = 'audio/basic';
+            break;
+
+        case 'pmd':
+            $mime = 'application/x-pmd';
+            break;
+
+        case 'wbmp':
+            $mime = 'image/vnd.wap.wbmp';
+            break;
+
+        case 'gcd':
+            $mime = 'text/x-pcs-gcd';
+            break;
+
+        case 'mms':
+            $mime = 'application/vnd.wap.mms-message';
+            break;
+
+        case 'ogg':
+        case 'ogm':
+            $mime = 'application/ogg';
+            break;
+
+        case 'rv':
+            $mime = 'video/vnd.rn-realvideo';
+            break;
+
+        case 'wmv':
+            $mime = 'video/x-ms-wmv';
+            break;
+
+        case 'wma':
+            $mime = 'audio/x-ms-wma';
+            break;
+
+        case 'qcp':
+            $mime = 'audio/vnd.qcelp';
+            break;
+
+        case 'jad':
+            $mime = 'text/vnd.sun.j2me.app-descriptor';
+            break;
+
+        case '3g2':
+        case '3gp':
+            $mime = 'video/3gpp';
+            break;
+
+        case 'jar':
+            $mime = 'application/java-archive';
+
+        default:
+            $mime = 'application/octet-stream';
+            break;
+    }
+
+    return $mime;
+}
+
+/**
+* Creates thumbnails for all images in the upload dir
+**/
+function serendipity_syncThumbs() {
+    global $serendipity;
+
+    $i=0;
+    $files = serendipity_fetchImages();
+
+    $fcount = count($files);
+    for ($x = 0; $x < $fcount; $x++) {
+        $update = $q = array();
+        $f      = serendipity_parseFileName($files[$x]);
+        if (empty($f[1]) || $f[1] == $files[$x]) {
+            // No extension means bad file most probably. Skip it.
+            printf(SKIPPING_FILE_EXTENSION . '<br />', $files[$x]);
+            continue;
+        }
+
+        $ffull   = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $files[$x];
+        $fthumb  = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $f[0] . '.' . $serendipity['thumbSuffix'] . '.' . $f[1];
+        $fbase   = basename($f[0]);
+        $fdir    = dirname($f[0]) . '/';
+        if ($fdir == './') {
+            $fdir = '';
+        }
+
+        if (!is_readable($ffull) || filesize($ffull) == 0) {
+            printf(SKIPPING_FILE_UNREADABLE . '<br />', $files[$x]);
+            continue;
+        }
+
+        $ft_mime = serendipity_guessMime($f[1]);
+        $fdim    = serendipity_getimagesize($ffull, $ft_mime);
+
+        $rs = serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}images
+                                            WHERE name = '" . serendipity_db_escape_string($fbase) . "'
+                                              " . ($fdir != '' ? "AND path = '" . serendipity_db_escape_string($fdir) . "'" : '') . "
+                                              AND mime = '" . serendipity_db_escape_string($fdim['mime']) . "'", true, 'assoc');
+        if (is_array($rs)) {
+            $update    = array();
+            $checkfile = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $rs['path'] . $rs['name'] . '.' . $rs['thumbnail_name'] . '.' . $rs['extension'];
+            if (isset($fdim[0]) && $rs['dimensions_width'] != $fdim[0]) {
+                $update['dimensions_width'] = $fdim[0];
+            }
+
+            if (isset($fdim[1]) && $rs['dimensions_height'] != $fdim[1]) {
+                $update['dimensions_height'] = $fdim[1];
+            }
+
+            if ($rs['size'] != filesize($ffull)) {
+                $update['size'] = filesize($ffull);
+            }
+
+            if (!file_exists($checkfile) && file_exists($fthumb)) {
+                $update['thumbnail_name'] = $serendipity['thumbSuffix'];
+            }
+
+            /* Do the database update, if needed */
+            if (sizeof($update) != 0) {
+                printf(FOUND_FILE . '<br />', $files[$x]);
+                serendipity_updateImageInDatabase($update, $rs['id']);
+                $i++;
+            }
+        } else {
+            printf(FOUND_FILE . '<br />', $files[$x]);
+            serendipity_insertImageInDatabase($fbase . '.' . $f[1], $fdir, 0, filemtime($ffull));
+            $i++;
+        }
+    }
+    return $i;
+}
+
+function serendipity_functions_gd($infilename) {
+    if (!function_exists('imagecopyresampled')) {
+        return false;
+    }
+
+    $func = array();
+    $inf  = pathinfo(strtolower($infilename));
+    switch ($inf['extension']) {
+    case 'gif':
+        $func['load'] = 'imagecreatefromgif';
+        $func['save'] = 'imagegif';
+        break;
+
+    case 'jpeg':
+    case 'jpg':
+    case 'jfif':
+        $func['load'] = 'imagecreatefromjpeg';
+        $func['save'] = 'imagejpeg';
+        break;
+
+    case 'png':
+        $func['load'] = 'imagecreatefrompng';
+        $func['save'] = 'imagepng';
+        break;
+
+    default:
+        return false;
+    }
+
+    /* If our loader does not exist, we are doomed */
+    if (!function_exists($func['load'])) {
+        return false;
+    }
+
+    /* If the save function does not exist (i.e. read-only GIF), we want to output it as PNG */
+    if (!function_exists($func['save'])) {
+        if (function_exists('imagepng')) {
+            $func['save'] = 'imagepng';
+        } else {
+            return false;
+        }
+    }
+
+    return $func;
+}
+
+function serendipity_rotate_image_gd($infilename, $outfilename, $degrees)
+{
+    $func = serendipity_functions_gd($infilename);
+    if (!is_array($func)) {
+        return false;
+    }
+
+    $in        = $func['load']($infilename);
+
+    $out       = imagerotate($in, $degrees, 0);
+    $func['save']($out, $outfilename);
+
+    $newwidth  = imagesx($out);
+    $newheight = imagesy($out);
+
+    $out       = null;
+    $in        = null;
+
+    return array($newwidth, $newheight);
+}
+
+
+function serendipity_resize_image_gd($infilename, $outfilename, $newwidth, $newheight=null)
+{
+    $func = serendipity_functions_gd($infilename);
+    if (!is_array($func)) {
+        return false;
+    }
+
+    $in = $func['load']($infilename);
+    $width = imagesx($in);
+    $height = imagesy($in);
+
+    if (is_null($newheight)) {
+        $newsizes = serendipity_calculate_aspect_size($width, $height, $newwidth);
+        $newwidth = $newsizes[0];
+        $newheight = $newsizes[1];
+    }
+
+    $out = imagecreatetruecolor($newwidth, $newheight);
+
+    /* Attempt to copy transparency information, this really only works for PNG */
+    if (function_exists('imagesavealpha')) {
+        imagealphablending($out, false);
+        imagesavealpha($out, true);
+    }
+
+    imagecopyresampled($out, $in, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
+    $func['save']($out, $outfilename, 100);
+    $out = null;
+    $in  = null;
+
+    return array($newwidth, $newheight);
+}
+
+function serendipity_calculate_aspect_size($width, $height, $newwidth) {
+
+    // calculate aspect ratio
+    $div_width  = $width  / $newwidth;
+    $div_height = $height / $newwidth;
+
+    if ($div_width <= 1 && $div_height <= 1) {
+        // do not scale small images where both sides are smaller than the thumbnail dimensions
+        $newheight = $height;
+        $newwidth  = $width;
+    } elseif ($div_width >= $div_height) {
+        // max width - calculate height, keep width as scaling base
+        $newheight = round($height / $div_width);
+        // make sure the height is at least 1 pixel for extreme images
+        $newheight = ($newheight >= 1 ? $newheight : 1);
+    } else {
+        // max height - calculate width, keep height as scaling base
+        $newheight = $newwidth;
+        $newwidth  = round($width / $div_height);
+        // make sure the width is at least 1 pixel for extreme images
+        $newwidth  = ($newwidth >= 1 ? $newwidth : 1);
+    }
+
+    return array($newwidth, $newheight);
+}
+
+function serendipity_displayImageList($page = 0, $lineBreak = NULL, $manage = false, $url = NULL, $show_upload = false) {
+    global $serendipity;
+    $sort_row_interval = array(8, 16, 50, 100);
+    $sortParams        = array('perpage', 'order', 'ordermode');
+    $importParams      = array('adminModule', 'htmltarget', 'filename_only', 'textarea', 'subpage');
+    $extraParems       = '';
+    $filterParams      = array('only_path', 'only_filename');
+
+    foreach($importParams AS $importParam) {
+        if (isset($serendipity['GET'][$importParam])) {
+            $extraParems .= 'serendipity[' . $importParam . ']='. $serendipity['GET'][$importParam] .'&amp;';
+        }
+    }
+
+    foreach($sortParams AS $sortParam) {
+        serendipity_restoreVar($serendipity['COOKIE']['sortorder_' . $sortParam], $serendipity['GET']['sortorder'][$sortParam]);
+        serendipity_JSsetCookie('sortorder_' . $sortParam, $serendipity['GET']['sortorder'][$sortParam]);
+        $extraParems .= 'serendipity[sortorder]['. $sortParam .']='. $serendipity['GET']['sortorder'][$sortParam] .'&amp;';
+    }
+
+    foreach($filterParams AS $filterParam) {
+        serendipity_restoreVar($serendipity['COOKIE'][$filterParam], $serendipity['GET'][$filterParam]);
+        serendipity_JSsetCookie($filterParam, $serendipity['GET'][$filterParam]);
+        if (!empty($serendipity['GET'][$filterParam])) {
+            $extraParems .= 'serendipity[' . $filterParam . ']='. $serendipity['GET'][$filterParam] .'&amp;';
+        }
+    }
+
+    $serendipity['GET']['only_path']     = serendipity_uploadSecure($serendipity['GET']['only_path'], true);
+    $serendipity['GET']['only_filename'] = str_replace(array('*', '?'), array('%', '_'), $serendipity['GET']['only_filename']);
+
+    $perPage = (!empty($serendipity['GET']['sortorder']['perpage']) ? $serendipity['GET']['sortorder']['perpage'] : $sort_row_interval[0]);
+    $start   = ($page-1) * $perPage;
+
+    $serendipity['imageList'] = serendipity_fetchImagesFromDatabase(
+                                  $start,
+                                  $perPage,
+                                  $totalImages, // Passed by ref
+                                  (isset($serendipity['GET']['sortorder']['order']) ? $serendipity['GET']['sortorder']['order'] : false),
+                                  (isset($serendipity['GET']['sortorder']['ordermode']) ? $serendipity['GET']['sortorder']['ordermode'] : false),
+                                  (isset($serendipity['GET']['only_path']) ? $serendipity['GET']['only_path'] : ''),
+                                  (isset($serendipity['GET']['only_filename']) ? $serendipity['GET']['only_filename'] : '')
+    );
+
+    $pages         = ceil($totalImages / $perPage);
+    $linkPrevious  = '?' . $extraParems . 'serendipity[page]=' . ($page-1);
+    $linkNext      = '?' . $extraParems . 'serendipity[page]=' . ($page+1);
+    $sort_order    = serendipity_getImageFields();
+    $paths         = serendipity_traversePath($serendipity['serendipityPath'] . $serendipity['uploadPath']);
+
+    if (is_null($lineBreak)) {
+        $lineBreak = floor(750 / ($serendipity['thumbSize'] + 20));
+    }
+?>
+<form style="display: inline; margin: 0px; padding: 0px;" method="get" action="?">
+<?php
+    foreach($serendipity['GET'] AS $g_key => $g_val) {
+        if ( !is_array($g_val) && $g_key != 'page' ) {
+            echo '<input type="hidden" name="serendipity[' . $g_key . ']" value="' . htmlspecialchars($g_val) . '" />';
+        }
+    }
+?>
+    <table class="serendipity_admin_filters" width="100%">
+        <tr>
+            <td class="serendipity_admin_filters_headline" colspan="6"><strong><?php echo FILTERS ?></strong> - <?php echo FIND_MEDIA ?></td>
+        </tr>
+        <tr>
+            <td><?php echo FILTER_DIRECTORY ?></td>
+            <td><select name="serendipity[only_path]">
+                    <option value=""><?php echo ALL_DIRECTORIES ?></option>
+                    <?php foreach ( $paths as $folder ) { ?>
+                    <option <?php echo ($serendipity['GET']['only_path'] == $folder['relpath']) ? 'selected="selected"' : '' ?> value="<?php echo $folder['relpath'] ?>"><?php echo str_repeat('&nbsp;', $folder['depth']*2) . ' '. $folder['name'] ?></option>
+                    <?php } ?>
+                </select>
+            </td>
+            <td><?php echo SORT_ORDER_NAME ?></td>
+            <td colspan="3"><input type="text" name="serendipity[only_filename]" value="<?php echo htmlspecialchars($serendipity['GET']['only_filename']); ?>" /></td>
+        </tr>
+        <tr>
+            <td class="serendipity_admin_filters_headline" colspan="6"><strong><?php echo SORT_ORDER ?></strong></td>
+        </tr>
+        <tr>
+            <td><?php echo SORT_BY ?></td>
+            <td><select name="serendipity[sortorder][order]">
+<?php
+        foreach($sort_order AS $so_key => $so_val) {
+            echo '<option value="' . $so_key . '" ' . (isset($serendipity['GET']['sortorder']['order']) && $serendipity['GET']['sortorder']['order'] == $so_key ? 'selected="selected"' : '') . '>' . $so_val . '</option>';
+        }
+?>              </select>
+</td>
+            <td><?php echo SORT_ORDER ?></td>
+            <td><select name="serendipity[sortorder][ordermode]">
+                    <option value="DESC" <?php echo (isset($serendipity['GET']['sortorder']['ordermode']) && $serendipity['GET']['sortorder']['ordermode'] == 'DESC' ? 'selected="selected"' : '') ?>><?php echo SORT_ORDER_DESC ?></option>
+                    <option value="ASC"  <?php echo (isset($serendipity['GET']['sortorder']['ordermode']) && $serendipity['GET']['sortorder']['ordermode'] == 'ASC'  ? 'selected="selected"' : '') ?>><?php echo SORT_ORDER_ASC  ?></option>
+                </select>
+            </td>
+            <td><?php echo FILES_PER_PAGE ?></td>
+            <td><select name="serendipity[sortorder][perpage]">
+<?php
+        foreach($sort_row_interval AS $so_val) {
+            echo '<option value="' . $so_val . '" ' . ($perPage == $so_val ? 'selected="selected"' : '') . '>' . $so_val . '</option>';
+        }
+?>              </select>
+            </td>
+        </tr>
+        <tr>
+            <td align="right" colspan="6">
+<?php
+        if ($show_upload) {
+?>
+                <input type="button" value="<?php echo htmlspecialchars(ADD_MEDIA); ?>" onclick="location.href='<?php echo $url; ?>&amp;serendipity[adminAction]=addSelect'; return false" class="serendipityPrettyButton" />
+<?php
+        }
+?>
+                <input type="submit" name="go" value=" - <?php echo GO ?> - " class="serendipityPrettyButton" />
+            </td>
+        </tr>
+</table>
+</form>
+<?php if ( sizeof($serendipity['imageList']) == 0 ) { ?>
+    <div align="center">- <?php echo NO_IMAGES_FOUND ?> -</div>
+<?php } else { ?>
+<table border="0" width="100%">
+    <tr>
+        <td colspan="<?php echo floor($lineBreak); ?>">
+            <table width="100%">
+                <tr>
+                    <td>
+                    <?php if ( $page != 1 && $page <= $pages ) { ?>
+                        <a href="<?php echo $linkPrevious ?>" class="serendipityIconLink"><img src="<?php echo serendipity_getTemplateFile('admin/img/previous.png') ?>" /><?php echo PREVIOUS ?></a>
+                    <?php } ?></td>
+                    <td align="right">
+                    <?php if ($page != $pages ) { ?>
+                        <a href="<?php echo $linkNext ?>" class="serendipityIconLinkRight"><?php echo NEXT ?><img src="<?php echo serendipity_getTemplateFile('admin/img/next.png') ?>" /></a>
+                    <?php } ?></td>
+                </tr>
+            </table>
+        </td>
+    </tr>
+    <tr>
+<?php
+        $x = 0;
+        foreach ($serendipity['imageList'] as $k => $file) {
+            ++$x; $preview = '';
+            $img = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . '.' . $file['thumbnail_name'] . '.' . $file['extension'];
+            $i = @getimagesize($img);
+            $file['imgsrc'] = $serendipity['uploadHTTPPath'] . $file['path'] . $file['name'] . '.' . $file['thumbnail_name'] . '.' . $file['extension'];
+            $is_image = serendipity_isImage($file);
+
+            /* If it is an image, and the thumbnail exists */
+            if ($is_image && file_exists($img)) {
+                $preview .= '<img src="' . $file['imgsrc'] . '" border="0" title="' . $file['path'] . $file['name'] . '" alt="'. $file['name'] . '" />';
+                if ($url) {
+                    $preview = '<a href="'. $url .'&amp;serendipity[image]='. $file['id'] .'">'. $preview .'</a>';
+                }
+            } elseif ($is_image && $file['hotlink']) {
+                $sizes = serendipity_calculate_aspect_size($file['dimensions_width'], $file['dimensions_height'], $serendipity['thumbSize']);
+                $preview .= '<img src="' . $file['path'] . '" width="' . $sizes[0] . '" height="' . $sizes[1] . '" border="0" title="' . $file['path'] . '" alt="'. $file['name'] . '" />';
+                if ($url) {
+                    $preview = '<a href="'. $url .'&amp;serendipity[image]='. $file['id'] .'">'. $preview .'</a>';
+                }
+            /* If it's not an image, or the thumbnail does not exist */
+            } else {
+                $preview .= '<img src="'. serendipity_getTemplateFile('admin/img/mime_unknown.png') .'" title="' . $file['path'] . $file['name'] . ' (' . $file['mime'] . ')" alt="'. $file['mime'] .'" /><br /><span style="font-weight: bold; font-size: 8pt">- ' . (($file['hotlink']) ? MEDIA_HOTLINKED : $file['mime']) .' -</span>';
+                if ($url) {
+                    $preview .= '<br /><a href="' . $url . '&amp;serendipity[image]=' . $file['id'] . '">' . $file['name'] . '.' . $file['extension'] . '</a>';
+                }
+                $preview .= '</div>';
+            }
+
+?>
+                <td nowrap="nowrap" align="center" valign="<?php echo $manage ? 'top' : 'middle' ?>" width="<?php echo round(1/$lineBreak*100) ?>%" class="serendipity_admin_list_item serendipity_admin_list_item_<?php echo (($i % 2) ? 'even' : 'uneven') ?>">
+<?php
+if ( !$manage ) {
+    echo $preview;
+} else { ?>
+                    <table width="100%" border="0" cellspacing="0" cellpadding="3">
+                        <tr>
+                            <td valign="top" width="16" rowspan="3">
+<?php
+                if ($serendipity['authorid'] == $file['authorid'] || $file['authorid'] == '0' || $serendipity['serendipityUserlevel'] >= USERLEVEL_CHIEF) {
+                    $popupWidth = ($is_image ? ($file['dimensions_width'] + 20) : 600);
+                    $popupHeight = ($is_image ? ($file['dimensions_height'] + 20) : 500);
+?>
+                            <img class="serendipityImageButton" title="<?php echo MEDIA_FULLSIZE; ?>" alt="<?php echo MEDIA_FULLSIZE; ?>" src="<?php echo serendipity_getTemplateFile('admin/img/big_zoom.png') ?>"   border="0" onclick="F1 = window.open('<?php echo ($file['hotlink'] ? $file['path'] : $serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $file['path'] . $file['name'] . '.'. $file['extension']); ?>','Zoom','height=<?php echo $popupHeight; ?>,width=<?php echo $popupWidth; ?>,top='+ (screen.height-<?php echo $popupHeight ?>)/2 +',left='+ (screen.width-<?php echo $popupWidth ?>)/2 +',toolbar=no,menubar=no,location=no,resize=1,resizable=1<?php echo ($is_image ? '' : ',scrollbars=yes'); ?>');" /><br />
+                            <img class="serendipityImageButton" title="<?php echo MEDIA_RENAME; ?>" alt="<?php echo MEDIA_RENAME; ?>" src="<?php echo serendipity_getTemplateFile('admin/img/big_rename.png') ?>" border="0" onclick="rename('<?php echo $file['id']; ?>', '<?php echo addslashes($file['name']); ?>')" /><br />
+                            <?php if ($is_image && !$file['hotlink']) { ?><img class="serendipityImageButton" title="<?php echo IMAGE_RESIZE; ?>"   alt="<?php echo IMAGE_RESIZE; ?>"   src="<?php echo serendipity_getTemplateFile('admin/img/big_resize.png') ?>" border="0" onclick="location.href='?serendipity[adminModule]=images&amp;serendipity[adminAction]=scaleSelect&amp;serendipity[fid]=<?php echo $file['id']; ?>';" /><br /><?php } ?>
+                            <?php if ($is_image && !$file['hotlink']) { ?><a href="?serendipity[adminModule]=images&amp;serendipity[adminAction]=rotateCCW&amp;serendipity[fid]=<?php echo $file['id']; ?>"><img class="serendipityImageButton" title="<?php echo IMAGE_ROTATE_LEFT; ?>" alt="<?php echo IMAGE_ROTATE_LEFT; ?>" src="<?php echo serendipity_getTemplateFile('admin/img/big_rotate_ccw.png') ?>" border="0" /><br /><?php } ?>
+                            <?php if ($is_image && !$file['hotlink']) { ?><a href="?serendipity[adminModule]=images&amp;serendipity[adminAction]=rotateCW&amp;serendipity[fid]=<?php echo $file['id']; ?>"><img class="serendipityImageButton" title="<?php echo IMAGE_ROTATE_RIGHT; ?>" alt="<?php echo IMAGE_ROTATE_RIGHT; ?>" src="<?php echo serendipity_getTemplateFile('admin/img/big_rotate_cw.png') ?>" border="0" /><br /><?php } ?>
+                            <a href="?serendipity[adminModule]=images&amp;serendipity[adminAction]=delete&amp;serendipity[fid]=<?php echo $file['id']; ?>"><img class="serendipityImageButton" title="<?php echo MEDIA_DELETE; ?>"   alt="<?php echo MEDIA_DELETE; ?>"   src="<?php echo serendipity_getTemplateFile('admin/img/big_delete.png') ?>" border="0" /><br />
+<?php
+                }
+?>
+                            </td>
+                            <td height="10" align="left" style="font-weight: bold; font-size: 8pt"><?php echo $file['name'] . '.' . $file['extension']; ?></td>
+                            <td height="10" align="right" style="font-size: 8pt"><?php echo ($file['authorid'] == '0' ? ALL_AUTHORS : $file['authorname']); ?></td>
+                        </tr>
+                        <tr>
+                            <td align="center" colspan="2"><?php echo $preview ?></td>
+                        </tr>
+                        <tr>
+                            <td colspan="2" height="10" align="center" style="font-size: 8pt">
+<?php
+                if ($is_image && !$file['hotlink']) {
+                    echo ORIGINAL_SHORT . ': ' . $file['dimensions_width'] . 'x' . $file['dimensions_height'] .', ';
+                    echo THUMBNAIL_SHORT . ': ' . $i[0] . 'x' . $i[1];
+                } elseif ($file['hotlink']) {
+                    echo wordwrap($file['path'], 45, '<br />', 1);
+                } else {
+                    echo SORT_ORDER_SIZE . ': ' . number_format(round($file['size']/1024, 2), NUMBER_FORMAT_DECIMALS, NUMBER_FORMAT_DECPOINT, NUMBER_FORMAT_THOUSANDS) . 'kb';
+                }
+?>
+                            </td>
+                        </tr>
+                    </table>
+<?php } ?>
+        </td>
+<?php
+        // Newline?
+        if ($x % $lineBreak == 0) {
+?>
+    </tr>
+    <tr>
+<?php
+        }
+    }
+?>
+    </tr>
+</table>
+<?php
+}
+} // End serendipity_displayImageList()
+
+function serendipity_isImage(&$file) {
+    $file['displaymime'] = $file['mime'];
+
+    // File is PDF -> Thumb is PNG
+    if ($file['mime'] == 'application/pdf') {
+        $file['imgsrc']     .= '.png';
+        $file['displaymime'] = 'image/png';
+    }
+
+    return (0 === strpos(strtolower($file['displaymime']), 'image/'));
+}
+
+function serendipity_killPath($basedir, $directory = '', $forceDelete = false) {
+    static $n = "<br />\n";
+    static $serious = true;
+
+    if ($handle = @opendir($basedir . $directory)) {
+        while (false !== ($file = @readdir($handle))) {
+            if ($file != '.' && $file != '..') {
+                if (is_dir($basedir . $directory . $file)) {
+                    serendipity_killPath($basedir, $directory . $file . '/', $forceDelete);
+                } else {
+                    $filestack[$file] = $directory . $file;
+                }
+            }
+        }
+        @closedir($handle);
+
+        printf(CHECKING_DIRECTORY . "<br />\n", $directory);
+
+        // No, we just don't kill files the easy way. We sort them out properly from the database
+        // and preserve files not entered therein.
+        $files = serendipity_fetchImagesFromDatabase(0, 0, $total, false, false, $directory);
+        if (is_array($files)) {
+            echo "<ul>\n";
+            foreach($files AS $f => $file) {
+                echo "<li>\n";
+                if ($serious) {
+                    serendipity_deleteImage($file['id']);
+                } else {
+                    echo $file['name'] . '.' . $file['extension'];
+                }
+                echo "</li>\n";
+
+                unset($filestack[$file['name'] . '.' . $file['extension']]);
+                unset($filestack[$file['name'] . '.' . $file['thumbnail_name'] . '.' . $file['extension']]);
+            }
+            echo "</ul>\n";
+        }
+
+        if (count($filestack) > 0) {
+            if ($forceDelete) {
+                echo "<ul>\n";
+                foreach($filestack AS $f => $file) {
+                    if ($serious && @unlink($basedir . $file)) {
+                        printf('<li>' . DELETING_FILE . $n . DONE . "</li>\n", $file);
+                    } else {
+                        printf('<li>' . DELETING_FILE . $n . ERROR . "</li>\n", $file);
+                    }
+                }
+                echo "</ul>\n";
+            } else {
+                echo ERROR_DIRECTORY_NOT_EMPTY . $n;
+                echo "<ul>\n";
+                foreach($filestack AS $f => $file) {
+                    echo '<li>' . $file . "</li>\n";
+                }
+                echo "</ul>\n";
+            }
+        }
+
+        echo '<strong>';
+        if ($serious && !empty($directory) && !preg_match('@^.?/?$@', $directory) && @rmdir($basedir . $directory)) {
+            printf(DIRECTORY_DELETE_SUCCESS . $n, $directory);
+        } else {
+            printf(DIRECTORY_DELETE_FAILED . $n, $directory);
+        }
+        echo '</strong>';
+    }
+
+    return true;
+}
+
+
+function serendipity_traversePath($basedir, $dir='', $onlyDirs=true, $pattern = NULL, $depth = 1) {
+
+
+    $dh = @opendir($basedir . '/' . $dir);
+    if ( !$dh ) {
+        return false;
+    }
+
+    $files = array();
+    while (($file = @readdir($dh)) !== false) {
+        if ( $file != '.' && $file != '..' ) {
+            if ( $onlyDirs === false || ($onlyDirs === true && is_dir($basedir . '/' . $dir . '/' . $file)) ) {
+                if ( is_null($pattern) || preg_match($pattern, $file) ) {
+                    $files[] = array(
+                        'name'    => $file,
+                        'depth'   => $depth,
+                        'relpath' => ltrim(str_replace('\\', '/', $dir) . basename($file) . '/', '/')
+                    );
+                }
+            }
+            if ( is_dir($basedir . '/' . $dir . '/' . $file) ) {
+                $files = array_merge($files, serendipity_traversePath($basedir, $dir . '/' . basename($file) . '/', $onlyDirs, $pattern, ($depth+1)));
+            }
+        }
+    }
+
+    fclose($dh);
+    return $files;
+}
+
+
+function serendipity_deletePath($dir) {
+    $d = dir($dir);
+    if ($d) {
+        while ($f = $d->read() ){
+            if ($f != '.' && $f != '..') {
+                if (is_dir($dir . $f)){
+                    serendipity_deletePath($dir . $f . '/');
+                    rmdir($dir . $f);
+                }
+
+                if (is_file($dir . $f)) {
+                    unlink($dir . $f);
+                }
+            }
+        }
+
+        $d->close();
+    }
+}
+
+function serendipity_uploadSecure($var, $strip_paths = true) {
+    $var = preg_replace('@[^0-9a-z\._/-]@i', '', $var);
+    if ($strip_paths) {
+        $var = preg_replace('@(\.+[/\\\\]+)@', '/', $var);
+    }
+
+    $var = preg_replace('@^(/+)@', '', $var);
+
+    return $var;
+}
+
+function serendipity_getimagesize($file, $ft_mime = '', $suf = '') {
+    if (empty($ft_mime) && !empty($suf)) {
+        $ft_mime = serendipity_guessMime($suf);
+    }
+
+    if ($ft_mime == 'application/pdf') {
+       $fdim = array(1000,1000,24, '', 'bits'=> 24, 'channels' => '3', 'mime' => 'application/pdf');
+    }
+
+    $fdim = @getimagesize($file);
+
+    if (is_array($fdim)) {
+        if (empty($fdim['mime'])) {
+            $fdim['mime'] = $ft_mime;
+        }
+
+        if ($fdim['mime'] == 'image/vnd.wap.wbmp' && $ft_mime == 'video/x-quicktime') {
+            // PHP Versions prior to 4.3.9 reported .mov files wrongly as WAP. Fix this and mark the file as 'non-image' with 0x0 dimensions
+            $fdim['mime'] = $ft_mime;
+        }
+    } else {
+        // The file is no image. Return a fake array so that files are inserted (but without a thumb)
+        $fdim = array(
+            0         => 0,
+            1         => 0,
+            'mime'    => $ft_mime,
+            'noimage' => true
+        );
+    }
+
+    return $fdim;
+}
+
+function serendipity_getImageFields() {
+    return array(
+        'date'              => SORT_ORDER_DATE,
+        'name'              => SORT_ORDER_NAME,
+        'authorid'          => AUTHOR,
+        'extension'         => SORT_ORDER_EXTENSION,
+        'size'              => SORT_ORDER_SIZE,
+        'dimensions_width'  => SORT_ORDER_WIDTH,
+        'dimensions_height' => SORT_ORDER_HEIGHT
+    );
+}
+
+function serendipity_escapeshellarg($string) {
+    return escapeshellarg(str_replace('%', '', $string));
+}
+?>
diff --git a/include/functions_installer.inc.php b/include/functions_installer.inc.php
new file mode 100644 (file)
index 0000000..baaa970
--- /dev/null
@@ -0,0 +1,869 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+
+function serendipity_ini_bool($var) {
+    return ($var === 'on' || $var == '1');
+}
+
+function serendipity_ini_bytesize($val) {
+    if ( $val == '' )
+        return 0;
+
+    switch(substr($val, -1)) {
+        case 'k':
+        case 'K':
+            return (int) $val * 1024;
+            break;
+        case 'm':
+        case 'M':
+            return (int) $val * 1048576;
+            break;
+        default:
+            return $val;
+   }
+}
+
+function serendipity_updateLocalConfig($dbName, $dbPrefix, $dbHost, $dbUser, $dbPass, $dbType, $dbPersistent, $privateVariables = null) {
+    global $serendipity;
+    umask(0000);
+
+    $file = 'serendipity_config_local.inc.php';
+    $path = $serendipity['serendipityPath'];
+
+    $oldconfig = @file_get_contents($path . $file);
+    $configfp  = fopen($path . $file, 'w');
+
+    if (!is_resource($configfp)) {
+        $errs[] = sprintf(FILE_WRITE_ERROR, $file);
+        $errs[] = sprintf(DIRECTORY_RUN_CMD, 'chown -R www:www', $path) . ' (' . WWW_USER . ')';
+        $errs[] = sprintf(DIRECTORY_RUN_CMD, 'chmod 770'       , $path);
+        $errs[] = BROWSER_RELOAD;
+
+        return $errs;
+    }
+
+    if (isset($_POST['sqlitedbName']) && !empty($_POST['sqlitedbName'])) {
+        $dbName = $_POST['sqlitedbName'];
+    }
+
+    $file_start    = "<?php\n"
+                   . "\t/*\n"
+                   . "\t  Serendipity configuration file\n";
+    $file_mark     = "\n\t// End of Serendipity configuration file"
+                   . "\n\t// You can place your own special variables after here:\n";
+    $file_end      = "\n?>\n";
+    $file_personal = '';
+
+    preg_match('@' . preg_quote($file_start) . '.*' . preg_quote($file_mark) . '(.+)' . preg_quote($file_end) . '@imsU', $oldconfig, $match);
+    if (!empty($match[1])) {
+        $file_personal = $match[1];
+    }
+
+    fwrite($configfp, $file_start);
+
+    fwrite($configfp, "\t  Written on ". date('r') ."\n");
+    fwrite($configfp, "\t*/\n\n");
+
+    fwrite($configfp, "\t\$serendipity['versionInstalled']  = '{$serendipity['version']}';\n");
+    fwrite($configfp, "\t\$serendipity['dbName']            = '{$dbName}';\n");
+    fwrite($configfp, "\t\$serendipity['dbPrefix']          = '{$dbPrefix}';\n");
+    fwrite($configfp, "\t\$serendipity['dbHost']            = '{$dbHost}';\n");
+    fwrite($configfp, "\t\$serendipity['dbUser']            = '{$dbUser}';\n");
+    fwrite($configfp, "\t\$serendipity['dbPass']            = '{$dbPass}';\n");
+    fwrite($configfp, "\t\$serendipity['dbType']            = '{$dbType}';\n");
+    fwrite($configfp, "\t\$serendipity['dbPersistent']      = ". (serendipity_db_bool($dbPersistent) ? 'true' : 'false') .";\n");
+
+    if (is_array($privateVariables) && count($privateVariables) > 0) {
+        foreach($privateVariables AS $p_idx => $p_val) {
+            fwrite($configfp, "\t\$serendipity['{$p_idx}']  = '{$p_val}';\n");
+        }
+    }
+
+    fwrite($configfp, $file_mark .  $file_personal . $file_end);
+
+    fclose($configfp);
+
+    @chmod($path . $file, 0700);
+    return true;
+}
+
+/**
+* Creates the needed tables - beware, they will be empty and need to be stuffed with
+* default templates and such...
+*/
+function serendipity_installDatabase() {
+  global $serendipity;
+  $queries = serendipity_parse_sql_tables(S9Y_INCLUDE_PATH . 'sql/db.sql');
+  $queries = str_replace('{PREFIX}', $serendipity['dbPrefix'], $queries);
+
+  foreach ($queries as $query) {
+      serendipity_db_schema_import($query);
+  }
+}
+
+function serendipity_query_default($optname, $default, $usertemplate = false, $type = 'string') {
+    global $serendipity;
+
+    /* I won't tell you the password, it's MD5 anyway, you can't do anything with it */
+    if ($type == 'protected' && IS_installed === true) {
+        return '';
+    }
+
+    switch ($optname) {
+
+        case 'dbType' :
+            if (extension_loaded('mysqli')) {
+                $type = 'mysqli';
+            }
+            if (extension_loaded('pgsql')) {
+                $type = 'postgres';
+            }
+            if (extension_loaded('mysql')) {
+                $type = 'mysql';
+            }
+            return $type;
+
+        case 'serendipityPath':
+            $test_path1 = $_SERVER['DOCUMENT_ROOT'] . rtrim(dirname($_SERVER['PHP_SELF']), '/') . '/';
+            $test_path2 = serendipity_getRealDir(__FILE__);
+            if (file_exists($test_path1 . 'serendipity_admin.php')) {
+                return $test_path1;
+            } else {
+                return $test_path2;
+            }
+
+        case 'serendipityHTTPPath':
+            return rtrim(dirname($_SERVER['PHP_SELF']), '/') .'/';
+
+        case 'baseURL':
+            $ssl  = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on';
+            $port = $_SERVER['SERVER_PORT'];
+
+            return sprintf('http%s://%s%s%s',
+
+                            $ssl ? 's' : '',
+                            preg_replace('@^([^:]+):?.*$@', '\1', $_SERVER['HTTP_HOST']),
+                            (($ssl && $port != 443) || (!$ssl && $port != 80)) ? (':' . $port) : '',
+                            rtrim(dirname($_SERVER['PHP_SELF']), '/') .'/'
+                   );
+
+        case 'convert':
+            $path = array();
+
+            $path[] = ini_get('safe_mode_exec_dir');
+
+            if (isset($_SERVER['PATH'])) {
+                $path = array_merge($path, explode(':', $_SERVER['PATH']));
+            }
+
+            /* add some other possible locations to the path while we are at it,
+             * as these are not always included in the apache path */
+            $path[] = '/usr/X11R6/bin';
+            $path[] = '/usr/bin';
+            $path[] = '/usr/local/bin';
+
+            foreach ($path as $dir) {
+                if ((function_exists('is_executable') && @is_executable($dir . '/convert')) || @is_file($dir . '/convert')) {
+                    return $dir . '/convert';
+                }
+            }
+            return $default;
+
+        case 'rewrite':
+            return serendipity_check_rewrite($default);
+
+        default:
+            if ($usertemplate) {
+                return serendipity_get_user_var($optname, $serendipity['authorid'], $default);
+            }
+
+            return $default;
+    }
+}
+
+function serendipity_parseTemplate($filename, $areas = null, $onlyFlags=null) {
+    global $serendipity;
+
+    $userlevel = $serendipity['serendipityUserlevel'];
+
+    if ( !IS_installed ) {
+        $userlevel = USERLEVEL_ADMIN;
+    }
+
+    $config = @include($filename);
+
+    foreach ( $config as $n => $category ) {
+        /* If $areas is an array, we filter out those categories, not within the array */
+        if ( is_array($areas) && !in_array($n, $areas) ) {
+            unset($config[$n]);
+            continue;
+        }
+
+        foreach ( $category['items'] as $i => $item ) {
+            $items = &$config[$n]['items'][$i];
+            if (!isset($items['userlevel']) || !is_numeric($items['userlevel'])) {
+                $items['userlevel'] = USERLEVEL_ADMIN;
+            }
+
+            if ($userlevel < $items['userlevel']) {
+                unset($config[$n]['items'][$i]);
+                continue;
+            }
+
+            if (!isset($items['flags']) || !is_array($items['flags'])) {
+                $items['flags'] = array();
+            }
+
+            if ( is_array($onlyFlags) ) {
+                foreach ( $onlyFlags as $onlyFlag ) {
+                    if ( !in_array($onlyFlag, $items['flags']) ) {
+                        unset($config[$n]['items'][$i]);
+                        continue;
+                    }
+                }
+            }
+        }
+
+        if (sizeof($config[$n]['items']) < 1) {
+            unset($config[$n]);
+        }
+    }
+
+    return $config;
+}
+
+function serendipity_replaceEmbeddedConfigVars ($s) {
+    return str_replace(
+                  array(
+                    '%clock%'
+                  ),
+
+                  array(
+                    date('H:i')
+                  ),
+
+                  $s);
+}
+
+function serendipity_guessInput($type, $name, $value='', $default='') {
+    global $serendipity;
+
+    switch ($type) {
+        case 'bool' :
+            $value = serendipity_get_bool($value);
+            echo '<input id="radio_cfg_' . $name . '_yes" type="radio" name="' . $name . '" value="true" ';
+            echo (($value == true) ? 'checked="checked"' : ''). ' /><label for="radio_cfg_' . $name . '_yes"> ' . YES . '</label>&nbsp;';
+            echo '<input id="radio_cfg_' . $name . '_no" type="radio" name="' . $name . '" value="false" ';
+            echo (($value == true) ? '' : 'checked="checked"'). ' /><label for="radio_cfg_' . $name . '_no"> ' . NO . '</label>';
+            break;
+
+        case 'protected' :
+            echo '<input type="password" size="30" name="' . $name . '" value="' . htmlspecialchars($value) . '" />';
+            break;
+
+        case 'list' :
+            echo '<select name="'. $name .'">';
+            foreach ((array)$default as $k=>$v) {
+                printf('<option value="%s"%s>%s</option>'. "\n",
+                      $k,
+                      (($k == $value) ? ' selected="selected"' : ''),
+                      $v);
+            }
+            echo '</select>';
+            break;
+        case 'file' :
+            echo '<input type="file" size="30" name="' . $name . '" />';
+            break;
+        default :
+            echo '<input type="text" size="30" name="' . $name . '" value="' . htmlspecialchars($value) . '" />';
+            break;
+    }
+}
+
+function serendipity_printConfigTemplate($config, $from = false, $noForm = false, $folded = true, $allowToggle = true) {
+    global $serendipity;
+    if (!isset($serendipity['XHTML11'])) {
+        $serendipity['XHTML11'] = FALSE;
+    }
+    if ( $allowToggle ) {
+?>
+<script type="text/javascript" language="JavaScript">
+function showConfig(id) {
+    if (document.getElementById) {
+        el = document.getElementById(id);
+        if (el.style.display == 'none') {
+            document.getElementById('option' + id).src = '<?php echo serendipity_getTemplateFile('img/minus.png') ?>';
+            el.style.display = '';
+        } else {
+            document.getElementById('option' + id).src = '<?php echo serendipity_getTemplateFile('img/plus.png') ?>';
+            el.style.display = 'none';
+        }
+    }
+}
+
+var state='<?php echo ($folded === true ? '' : 'none'); ?>';
+function showConfigAll(count) {
+    if (document.getElementById) {
+        for (i = 1; i <= count; i++) {
+            document.getElementById('el' + i).style.display = state;
+            document.getElementById('optionel' + i).src = (state == '' ? '<?php echo serendipity_getTemplateFile('img/minus.png') ?>' : '<?php echo serendipity_getTemplateFile('img/plus.png') ?>');
+        }
+
+        if (state == '') {
+            document.getElementById('optionall').src = '<?php echo serendipity_getTemplateFile('img/minus.png') ?>';
+            state = 'none';
+        } else {
+            document.getElementById('optionall').src = '<?php echo serendipity_getTemplateFile('img/plus.png') ?>';
+            state = '';
+        }
+    }
+}
+</script>
+
+<?php
+    }
+
+    if (!$noForm) {
+?>
+<form action="?" method="POST">
+    <div>
+        <input type="hidden" name="serendipity[adminModule]" value="installer" />
+        <input type="hidden" name="installAction" value="check" />
+        <br />
+<?php   }
+    if (sizeof($config) > 1 && $allowToggle) { ?>
+        <div align="right">
+            <a style="border:0; text-decoration: none" href="#" onClick="showConfigAll(<?php echo sizeof($config); ?>)" title="<?php echo TOGGLE_ALL; ?>"><img src="<?php echo serendipity_getTemplateFile('img/'. ($folded === true ? 'plus' : 'minus') .'.png') ?>" id="optionall" alt="+/-" border="0" />&nbsp;<?php echo TOGGLE_ALL; ?></a></a><br />
+        </div>
+<?php
+    }
+    $el_count = 0;
+    foreach ($config as $category) {
+        $el_count++;
+?>
+        <table width="100%" cellspacing="2">
+<?php
+        if (sizeof($config) > 1) {
+?>
+            <tr>
+                <th align="left" colspan="2" style="padding-left: 15px;">
+<?php if ( $allowToggle ) { ?>
+                    <a style="border:0; text-decoration: none;" href="#" onClick="showConfig('el<?php echo $el_count; ?>'); return false" title="<?php echo TOGGLE_OPTION; ?>"><img src="<?php echo serendipity_getTemplateFile('img/'. ($folded === true ? 'plus' : 'minus') .'.png') ?>" id="optionel<?php echo $el_count; ?>" alt="+/-" border="0" />&nbsp;<?php echo $category['title']; ?></a>
+<?php } else { ?>
+                    <?php echo $category['title']; ?>
+<?php } ?>
+                </th>
+            </tr>
+<?php   } ?>
+            <tr>
+                <td>
+                    <table width="100%" cellspacing="0" cellpadding="3" id="el<?php echo $el_count; ?>">
+                        <tr>
+                            <td style="padding-left: 20px;" colspan="2">
+                                <?php echo $category['description'] ?>
+                            </td>
+                        </tr>
+
+<?php
+        foreach ( $category['items'] as $item ) {
+
+            $value = $from[$item['var']];
+
+            /* Calculate value if we are not installed, how clever :) */
+            if ($from == false) {
+                $value = serendipity_query_default($item['var'], $item['default']);
+            }
+
+            /* Check for installOnly flag */
+            if ( in_array('installOnly', $item['flags']) && IS_installed === true ) {
+                continue;
+            }
+
+            if ( in_array('hideValue', $item['flags']) ) {
+                $value = '';
+            }
+
+            if (in_array('config', $item['flags']) && isset($from['authorid'])) {
+                $value = serendipity_get_user_config_var($item['var'], $from['authorid'], $item['default']);
+            }
+
+            if (in_array('parseDescription', $item['flags'])) {
+                $item['description'] = serendipity_replaceEmbeddedConfigVars($item['description']);
+            }
+
+            if (in_array('probeDefault', $item['flags'])) {
+                $item['default'] = serendipity_probeInstallation($item['var']);
+            }
+?>
+                        <tr>
+                            <td style="border-bottom: 1px #000000 solid" align="left" valign="top" width="75%">
+                                <strong><?php echo $item['title']; ?></strong>
+                                <br />
+                                <span style="color: #5E7A94; font-size: 8pt;"><?php echo $item['description']; ?></span>
+                            </td>
+                            <td style="border-bottom: 1px #000000 solid; font-size: 8pt" align="left" valign="middle" width="25%">
+                                <?php echo ($serendipity['XHTML11'] ? '<span style="white-space: nowrap">' : '<nobr>'); ?><?php echo serendipity_guessInput($item['type'], $item['var'], $value, $item['default']); ?><?php echo ($serendipity['XHTML11'] ? '</span>' : '</nobr>'); ?>
+                            </td>
+                        </tr>
+<?php
+        }
+?>
+                    </table><br /><br />
+                </td>
+            </tr>
+        </table>
+<?php
+    }
+
+    if ($folded && $allowToggle) {
+        echo '<script type="text/javascript" language="JavaScript">';
+        for ($i = 1; $i <= $el_count; $i++) {
+            echo 'document.getElementById("el' . $i . '").style.display = "none";' . "\n";
+        }
+        echo '</script>';
+    }
+
+    if (!$noForm) {
+?>
+        <input type="submit" value="<?php echo CHECK_N_SAVE; ?>" class="serendipityPrettyButton" />
+    </div>
+</form>
+<?php
+    }
+}
+
+function serendipity_parse_sql_tables($filename) {
+    $in_table = 0;
+    $queries = array();
+
+    $fp = fopen($filename, 'r', 1);
+    if ($fp) {
+        while (!@feof($fp)) {
+            $line = trim(fgets($fp, 4096));
+            if ($in_table) {
+                $def .= $line;
+                if (preg_match('/^\)\s*(type\=\S+)?\s*\;$/i', $line)) {
+                    $in_table = 0;
+                    array_push($queries, $def);
+                }
+            } else {
+                if (preg_match('#^create table \{PREFIX\}\S+\s*\(#i', $line)) {
+                    $in_table = 1;
+                    $def = $line;
+                }
+
+                if (preg_match('#^create\s*(\{fulltext\}|unique|\{fulltext_mysql\})?\s*index#i', $line)) {
+                    array_push($queries, $line);
+                }
+            }
+        }
+        fclose($fp);
+    }
+
+    return $queries;
+}
+
+function serendipity_checkInstallation() {
+    global $serendipity, $umask;
+
+    $errs = array();
+
+    // Check dirs
+    if (!is_dir($_POST['serendipityPath'])) {
+        $errs[] = sprintf(DIRECTORY_NON_EXISTANT, $_POST['serendipityPath']);
+    }
+    elseif (!is_writable($_POST['serendipityPath']) ) {
+        $errs[] = sprintf(DIRECTORY_WRITE_ERROR, $_POST['serendipityPath']);
+    }
+    elseif (!is_dir($_POST['serendipityPath'] . $_POST['uploadPath'] ) && @mkdir($_POST['serendipityPath'] . $_POST['uploadPath'], $umask) !== true) {
+        $errs[] = sprintf(DIRECTORY_CREATE_ERROR, $_POST['serendipityPath'] . $_POST['uploadPath']);
+    }
+    elseif (!is_writable($_POST['serendipityPath'] . $_POST['uploadPath'])) {
+        $errs[] = sprintf(DIRECTORY_WRITE_ERROR, $_POST['serendipityPath'] . $_POST['uploadPath']);
+        $errs[] = sprintf(DIRECTORY_RUN_CMD    , 'chmod go+rws', $_POST['serendipityPath'] . $_POST['uploadPath']);
+    }
+
+    // Attempt to create the template compile directory, it might already be there, but we just want to be sure
+    if (!is_dir($_POST['serendipityPath'] . PATH_SMARTY_COMPILE) && @mkdir($_POST['serendipityPath'] . PATH_SMARTY_COMPILE, $umask) !== true) {
+        $errs[] = sprintf(DIRECTORY_CREATE_ERROR, $_POST['serendipityPath'] . PATH_ARCHIVES);
+        $errs[] = sprintf(DIRECTORY_RUN_CMD     , 'mkdir'      , $_POST['serendipityPath'] . PATH_SMARTY_COMPILE);
+        $errs[] = sprintf(DIRECTORY_RUN_CMD     , 'chmod go+rwx', $_POST['serendipityPath'] . PATH_SMARTY_COMPILE);
+    } elseif (is_dir($_POST['serendipityPath'] . PATH_SMARTY_COMPILE) && !is_writeable($_POST['serendipityPath'] . PATH_SMARTY_COMPILE) && @chmod($_POST['serendipityPath'] . PATH_SMARTY_COMPILE, $umask) !== true) {
+        $errs[] = sprintf(DIRECTORY_RUN_CMD     , 'chmod go+rwx', $_POST['serendipityPath'] . PATH_SMARTY_COMPILE);
+    }
+
+    // Attempt to create the archives directory
+    if (!is_dir($_POST['serendipityPath'] . PATH_ARCHIVES) && @mkdir($_POST['serendipityPath'] . PATH_ARCHIVES, $umask) !== true) {
+        $errs[] = sprintf(DIRECTORY_CREATE_ERROR, $_POST['serendipityPath'] . PATH_ARCHIVES);
+        $errs[] = sprintf(DIRECTORY_RUN_CMD     , 'mkdir'      , $_POST['serendipityPath'] . PATH_ARCHIVES);
+        $errs[] = sprintf(DIRECTORY_RUN_CMD     , 'chmod go+rwx', $_POST['serendipityPath'] . PATH_ARCHIVES);
+    }
+
+    // Check imagick
+    if ($_POST['magick'] == 'true' && function_exists('is_executable') && !@is_executable($_POST['convert'])) {
+        $errs[] = sprintf(CANT_EXECUTE_BINARY, 'convert imagemagick');
+    }
+
+    if ($_POST['dbType'] == 'sqlite') {
+        // We don't want that our SQLite db file can be guessed from other applications on a server
+        // and have access to our's. So we randomize the SQLite dbname.
+        $_POST['sqlitedbName'] = $_POST['dbName'] . '_' . md5(time());
+    }
+
+    if (empty($_POST['dbPrefix']) && empty($serendipity['dbPrefix'])) {
+        $errs[] = sprintf(EMPTY_SETTING, INSTALL_DBPREFIX);
+    }
+
+    $serendipity['dbType'] = $_POST['dbType'];
+    // Probe database
+    // (do it after the dir stuff, as we need to be able to create the sqlite database)
+    @include_once($_POST['serendipityPath'] . 'include/db/db.inc.php');
+    // For shared installations, probe the file on include path
+    @include_once(S9Y_INCLUDE_PATH . 'include/db/db.inc.php');
+
+    if (S9Y_DB_INCLUDED) {
+        serendipity_db_probe($_POST, $errs);
+    }
+
+    return (count($errs) > 0 ? $errs : '');
+}
+
+function serendipity_installFiles($serendipity_core = '') {
+    global $serendipity;
+
+    // This variable is transmitted from serendipity_admin_installer. If an empty variable is used,
+    // this means that serendipity_installFiles() was called from the auto-updater facility.
+    if (empty($serendipity_core)) {
+        $serendipity_core = $serendipity['serendipityPath'];
+    }
+
+    $htaccess = @file_get_contents($serendipity_core . '.htaccess');
+
+    // Let this function be callable outside installation and let it use existing settings.
+    $import = array('rewrite', 'serendipityHTTPPath', 'indexFile');
+    foreach($import AS $key) {
+        if (empty($_POST[$key]) && isset($serendipity[$key])) {
+            $$key = $serendipity[$key];
+        } else {
+            $$key = $_POST[$key];
+        }
+    }
+
+    if (php_sapi_name() == 'cgi' || php_sapi_name() == 'cgi-fcgi') {
+        $htaccess_cgi = '_cgi';
+    } else {
+        $htaccess_cgi = '';
+    }
+
+
+    /* Detect comptability with php_value directives */
+    if ($htaccess_cgi == '') {
+        $response = '';
+        $serendipity_root = dirname($_SERVER['PHP_SELF']) . '/';
+        $serendipity_host = preg_replace('@^([^:]+):?.*$@', '\1', $_SERVER['HTTP_HOST']);
+
+        $old_htaccess = @file_get_contents($serendipity_core . '.htaccess');
+        $fp = @fopen($serendipity_core . '.htaccess', 'w');
+        if ($fp) {
+            fwrite($fp, 'php_value register_globals off'. "\n" .'php_value session.use_trans_sid 0');
+            fclose($fp);
+
+            $sock = @fsockopen($serendipity_host, $_SERVER['SERVER_PORT'], $errorno, $errorstring, 10);
+            if ($sock) {
+                fputs($sock, "GET {$serendipityHTTPPath} HTTP/1.0\r\n");
+                fputs($sock, "Host: $serendipity_host\r\n");
+                fputs($sock, "User-Agent: Serendipity/{$serendipity['version']}\r\n");
+                fputs($sock, "Connection: close\r\n\r\n");
+
+                while (!feof($sock) && strlen($response) < 4096) {
+                    $response .= fgets($sock, 400);
+                }
+                fclose($sock);
+            }
+
+            /* If we get HTTP 500 Internal Server Error, we have to use the .cgi template */
+            if (preg_match('@^HTTP/\d\.\d 500@', $response)) {
+                $htaccess_cgi = '_cgi';
+            }
+
+            if (!empty($old_htaccess)) {
+                $fp = @fopen($serendipity_core . '.htaccess', 'w');
+                fwrite($fp, $old_htaccess);
+                fclose($fp);
+            } else {
+                @unlink($serendipity_core . '.htaccess');
+            }
+        }
+    }
+
+
+    if ($rewrite == 'rewrite') {
+        $template = 'htaccess' . $htaccess_cgi . '_rewrite.tpl';
+    } elseif ($rewrite == 'errordocs') {
+        $template = 'htaccess' . $htaccess_cgi . '_errordocs.tpl';
+    } else {
+        $template = 'htaccess' . $htaccess_cgi . '_normal.tpl';
+    }
+
+    if (!($a = file(S9Y_INCLUDE_PATH . 'include/tpl/' . $template, 1))) {
+        $errs[] = ERROR_TEMPLATE_FILE;
+    }
+
+    $content = str_replace(
+                 array(
+                   '{PREFIX}',
+                   '{indexFile}',
+                   '{PAT_UNSUBSCRIBE}', '{PATH_UNSUBSCRIBE}',
+                   '{PAT_ARCHIVES}', '{PATH_ARCHIVES}',
+                   '{PAT_FEEDS}', '{PATH_FEEDS}',
+                   '{PAT_FEED}',
+                   '{PAT_ADMIN}', '{PATH_ADMIN}',
+                   '{PAT_ENTRIES}', '{PATH_ENTRIES}',
+                   '{PAT_ARCHIVE}', '{PATH_ARCHIVE}',
+                   '{PAT_CATEGORIES}', '{PATH_CATEGORIES}',
+                   '{PAT_PLUGIN}', '{PATH_PLUGIN}',
+                   '{PAT_DELETE}', '{PATH_DELETE}',
+                   '{PAT_APPROVE}', '{PATH_APPROVE}',
+                   '{PAT_SEARCH}', '{PATH_SEARCH}',
+                   '{PAT_CSS}',
+                   '{PAT_AUTHORS}', '{PATH_AUTHORS}'
+                 ),
+
+                 array(
+                   $serendipityHTTPPath,
+                   $indexFile,
+                   trim(PAT_UNSUBSCRIBE, '@/i'), PATH_UNSUBSCRIBE,
+                   trim(PAT_ARCHIVES, '@/i'), PATH_ARCHIVES,
+                   trim(PAT_FEEDS, '@/i'), PATH_FEEDS,
+                   trim(PAT_FEED, '@/i'),
+                   trim(PAT_ADMIN, '@/i'), PATH_ADMIN,
+                   trim(PAT_ENTRIES, '@/i'), PATH_ENTRIES,
+                   trim(PAT_ARCHIVE, '@/i'), PATH_ARCHIVE,
+                   trim(PAT_CATEGORIES, '@/i'), PATH_CATEGORIES,
+                   trim(PAT_PLUGIN, '@/i'), PATH_PLUGIN,
+                   trim(PAT_DELETE, '@/i'), PATH_DELETE,
+                   trim(PAT_APPROVE, '@/i'), PATH_APPROVE,
+                   trim(PAT_SEARCH, '@/i'), PATH_SEARCH,
+                   trim(PAT_CSS, '@/i'),
+                   trim(PAT_AUTHORS, '@/i'), PATH_AUTHORS
+                 ),
+
+                 implode('', $a)
+              );
+
+    $fp = @fopen($serendipity_core . '.htaccess', 'w');
+    if (!$fp) {
+        $errs[] = sprintf(FILE_WRITE_ERROR, $serendipity_core . '.htaccess') . ' ' . FILE_CREATE_YOURSELF;
+        $errs[] = sprintf(COPY_CODE_BELOW , $serendipity_core . '.htaccess', 'serendipity', htmlspecialchars($content));
+        return $errs;
+    } else {
+        // Check if an old htaccess file existed and try to preserve its contents. Otherwise completely wipe the file.
+        if ($htaccess != '' && preg_match('@^(.*)#\s+BEGIN\s+s9y.*#\s+END\s+s9y(.*)$@isU', $htaccess, $match)) {
+            // Code outside from s9y-code was found.
+            fwrite($fp, $match[1] . $content . $match[2]);
+        } else {
+            fwrite($fp, $content);
+        }
+        fclose($fp);
+        return true;
+    }
+
+}
+
+/* Takes the item data from a config var, and checks the flags against the current area */
+function serendipity_checkConfigItemFlags(&$item, $area) {
+
+    if ( in_array('nosave', $item['flags']) ) {
+        return false;
+    }
+
+    if ( in_array('local', $item['flags']) && $area == 'configuration' ) {
+        return false;
+    }
+
+    if ( in_array('config', $item['flags']) && $area == 'local' ) {
+        return false;
+    }
+
+    return true;
+}
+
+function serendipity_updateConfiguration() {
+    global $serendipity, $umask;
+
+    // Save all basic config variables to the database
+    $config = serendipity_parseTemplate(S9Y_CONFIG_TEMPLATE);
+
+    if (isset($_POST['sqlitedbName']) && !empty($_POST['sqlitedbName'])) {
+        $_POST['dbName'] = $_POST['sqlitedbName'];
+    }
+
+    // Password can be hidden in re-configuring, but we need to store old password
+    if (empty($_POST['dbPass']) && !empty($serendipity['dbPass'])) {
+        $_POST['dbPass'] = $serendipity['dbPass'];
+    }
+
+    foreach($config as $category) {
+        foreach ( $category['items'] as $item ) {
+
+            /* Don't save trash */
+            if ( !serendipity_checkConfigItemFlags($item, 'configuration') ) {
+                continue;
+            }
+
+            if (!isset($item['userlevel'])) {
+                $item['userlevel'] = USERLEVEL_ADMIN;
+            }
+
+            if ( $serendipity['serendipityUserlevel'] >= $item['userlevel'] || IS_installed === false ) {
+                $authorid = 0;
+            } else {
+                $authorid = $serendipity['authorid'];
+            }
+
+            serendipity_set_config_var($item['var'], $_POST[$item['var']], $authorid);
+        }
+    }
+
+    if (IS_installed === false || $serendipity['serendipityUserlevel'] >= USERLEVEL_ADMIN) {
+        return serendipity_updateLocalConfig($_POST['dbName'],
+                                             $_POST['dbPrefix'],
+                                             $_POST['dbHost'],
+                                             $_POST['dbUser'],
+                                             $_POST['dbPass'],
+                                             $_POST['dbType'],
+                                             $_POST['dbPersistent']);
+    } else {
+        return true;
+    }
+}
+
+function serendipity_httpCoreDir() {
+    if (!empty($_SERVER['SCRIPT_FILENAME']) && substr(php_sapi_name(), 0, 3) != 'cgi') {
+        return dirname($_SERVER['SCRIPT_FILENAME']) . '/';
+    }
+
+    return $_SERVER['DOCUMENT_ROOT'] . dirname($_SERVER['PHP_SELF']) . '/';
+}
+
+function serendipity_removeFiles($files = null) {
+    global $serendipity, $errors;
+
+    if (!is_array($files)) {
+        return;
+    }
+
+    $backupdir = S9Y_INCLUDE_PATH . 'backup';
+    if (!is_dir($backupdir)) {
+        @mkdir($backupdir, 0777);
+        if (!is_dir($backupdir)) {
+            $errors[] = sprintf(DIRECTORY_CREATE_ERROR, $backupdir);
+            return false;
+        }
+    }
+
+    if (!is_writable($backupdir)) {
+        $errors[] = sprintf(DIRECTORY_WRITE_ERROR, $backupdir);
+        return false;
+    }
+
+    foreach($files AS $file) {
+        $source   = S9Y_INCLUDE_PATH . $file;
+        $sanefile = str_replace('/', '_', $file);
+        $target   = $backupdir . '/' . $sanefile;
+
+        if (!file_exists($source)) {
+            continue;
+        }
+
+        if (file_exists($target)) {
+            $target = $backupdir . '/' . time() . '.' . $sanefile; // Backupped file already exists. Append with timestamp as name.
+        }
+
+        if (!is_writable($source)) {
+            $errors[] = sprintf(FILE_WRITE_ERROR, $source) . '<br />';
+        } else {
+            rename($source, $target);
+        }
+    }
+}
+
+function serendipity_getRealDir($file) {
+    $dir = str_replace( "\\", "/", dirname($file));
+    $base = preg_replace('@/include$@', '', $dir) . '/';
+    return $base;
+}
+
+function serendipity_check_rewrite($default) {
+    global $serendipity;
+
+    if (IS_installed == true) {
+        return $default;
+    }
+
+    $serendipity_root = dirname($_SERVER['PHP_SELF']) . '/';
+    $serendipity_core = serendipity_httpCoreDir();
+    $old_htaccess     = @file_get_contents($serendipity_core . '.htaccess');
+    $fp               = @fopen($serendipity_core . '.htaccess', 'w');
+    $serendipity_host = preg_replace('@^([^:]+):?.*$@', '\1', $_SERVER['HTTP_HOST']);
+
+    if (!$fp) {
+        printf(HTACCESS_ERROR,
+          '<b>chmod go+rwx ' . getcwd() . '/</b>'
+        );
+        return $default;
+    } else {
+        fwrite($fp, 'ErrorDocument 404 ' . $serendipity_root . 'index.php');
+        fclose($fp);
+
+        // Do a request on a nonexistant file to see, if our htaccess allows ErrorDocument
+        $sock = @fsockopen($serendipity_host, $_SERVER['SERVER_PORT'], $errorno, $errorstring, 10);
+        $response = '';
+
+        if ($sock) {
+            fputs($sock, "GET {$_SERVER['PHP_SELF']}nonexistant HTTP/1.0\r\n");
+            fputs($sock, "Host: $serendipity_host\r\n");
+            fputs($sock, "User-Agent: Serendipity/{$serendipity['version']}\r\n");
+            fputs($sock, "Connection: close\r\n\r\n");
+
+            while (!feof($sock) && strlen($response) < 4096) {
+                $response .= fgets($sock, 400);
+            }
+            fclose($sock);
+        }
+
+        if (preg_match('@^HTTP/\d\.\d 200@', $response) && preg_match('@X\-Blog: Serendipity@', $response)) {
+            $default = 'errordocs';
+        } else {
+            $default = 'none';
+        }
+
+        if (!empty($old_htaccess)) {
+            $fp = @fopen($serendipity_core . '.htaccess', 'w');
+            fwrite($fp, $old_htaccess);
+            fclose($fp);
+        } else {
+            @unlink($serendipity_core . '.htaccess');
+        }
+
+        return $default;
+    }
+}
+
+function serendipity_removeObsoleteVars() {
+global $serendipity;
+
+    $config = serendipity_parseTemplate(S9Y_CONFIG_TEMPLATE);
+    foreach($config as $category) {
+        foreach($category['items'] as $item) {
+            /* Remove trash */
+            if (!serendipity_checkConfigItemFlags($item, 'remove')) {
+                serendipity_remove_config_var($item['var'], 0);
+            }
+        }
+    }
+}
+
+?>
diff --git a/include/functions_smarty.inc.php b/include/functions_smarty.inc.php
new file mode 100644 (file)
index 0000000..3ac2fc0
--- /dev/null
@@ -0,0 +1,243 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+function &serendipity_smarty_fetch($block, $file, $echo = false) {
+    global $serendipity;
+
+    $output = $serendipity['smarty']->fetch('file:'. serendipity_getTemplateFile($file, 'serendipityPath'), null, null, ($echo === true && $serendipity['smarty_raw_mode']));
+    $serendipity['smarty']->assign($block, $output);
+
+    return $output;
+}
+
+function serendipity_emptyPrefix($string, $prefix = ': ') {
+    return (!empty($string) ? $prefix . htmlspecialchars($string) : '');
+}
+
+function serendipity_smarty_showPlugin($params, &$smarty) {
+    global $serendipity;
+
+    if (!isset($params['class']) && !isset($params['id'])) {
+        $smarty->trigger_error(__FUNCTION__ .": missing 'class' or 'id' parameter");
+        return;
+    }
+
+    if (!isset($params['side'])) {
+        $params['side'] = '*';
+    }
+
+    if (!isset($params['negate'])) {
+        $params['negate'] = null;
+    }
+
+    return serendipity_plugin_api::generate_plugins($params['side'], null, $params['negate'], $params['class'], $params['id']);
+}
+
+function serendipity_smarty_hookPlugin($params, &$smarty) {
+    global $serendipity;
+    static $hookable = array('frontend_header',
+                             'entries_header',
+                             'entries_footer',
+                             'frontend_comment');
+
+    if (!isset($params['hook'])) {
+        $smarty->trigger_error(__FUNCTION__ .": missing 'hook' parameter");
+        return;
+    }
+
+    if (!in_array($params['hook'], $hookable) && $params['hookAll'] != 'true') {
+        $smarty->trigger_error(__FUNCTION__ .": illegal hook '". $params['hook'] ."'");
+        return;
+    }
+
+    if (!isset($params['data'])) {
+        $params['data'] = &$serendipity;
+    }
+
+    if (!isset($params['addData'])) {
+        $params['addData'] = null;
+    }
+
+    serendipity_plugin_api::hook_event($params['hook'], $params['data'], $params['addData']);
+}
+
+
+function serendipity_smarty_printSidebar($params, &$smarty) {
+    if ( !isset($params['side']) ) {
+        $smarty->trigger_error(__FUNCTION__ .": missing 'side' parameter");
+        return;
+    }
+    return serendipity_plugin_api::generate_plugins($params['side']);
+}
+
+function serendipity_smarty_getFile($params, &$smarty) {
+    if ( !isset($params['file']) ) {
+        $smarty->trigger_error(__FUNCTION__ .": missing 'file' parameter");
+        return;
+    }
+    return serendipity_getTemplateFile($params['file']);
+}
+
+
+function serendipity_smarty_formatTime($timestamp, $format, $useOffset = true) {
+    if (defined($format)) {
+        return serendipity_formatTime(constant($format), $timestamp, $useOffset);
+    } else {
+        return serendipity_formatTime($format, $timestamp, $useOffset);
+    }
+}
+
+function &serendipity_smarty_printComments($params, &$smarty) {
+    global $serendipity;
+
+    if (!isset($params['entry'])) {
+        $smarty->trigger_error(__FUNCTION__ .": missing 'entry' parameter");
+        return;
+    }
+
+    if (!isset($params['mode'])) {
+        $params['mode'] = VIEWMODE_THREADED;
+    }
+
+    $comments = serendipity_fetchComments($params['entry']);
+
+    if (!empty($serendipity['POST']['preview'])) {
+        $comments[] =
+            array(
+                    'email'     => $serendipity['POST']['email'],
+                    'author'    => $serendipity['POST']['name'],
+                    'body'      => $serendipity['POST']['comment'],
+                    'url'       => $serendipity['POST']['url'],
+                    'parent_id' => $serendipity['POST']['replyTo'],
+                    'timestamp' => time()
+            );
+    }
+
+    return serendipity_printComments($comments, $params['mode']);
+}
+
+function serendipity_smarty_printTrackbacks($params, &$smarty) {
+    if ( !isset($params['entry']) ) {
+        $smarty->trigger_error(__FUNCTION__ .": missing 'entry' parameter");
+        return;
+    }
+
+    return serendipity_printTrackbacks(serendipity_fetchTrackbacks($params['entry']));
+}
+
+function serendipity_smarty_init() {
+    global $serendipity;
+
+    if (!isset($serendipity['smarty'])) {
+        @define('SMARTY_DIR', S9Y_INCLUDE_PATH . 'bundled-libs/Smarty/libs/');
+        require_once SMARTY_DIR . 'Smarty.class.php';
+        $serendipity['smarty'] = new Smarty;
+        if ($serendipity['production'] === 'debug') {
+            $serendipity['smarty']->force_compile   = true;
+            $serendipity['smarty']->debugging       = true;
+        }
+        $serendipity['smarty']->template_dir  = $serendipity['serendipityPath'] . $serendipity['templatePath'] . $serendipity['template'];
+        $serendipity['smarty']->compile_dir   = $serendipity['serendipityPath'] . PATH_SMARTY_COMPILE;
+        $serendipity['smarty']->config_dir    = &$serendipity['smarty']->template_dir;
+        $serendipity['smarty']->secure_dir    = array($serendipity['serendipityPath'] . $serendipity['templatePath']);
+        $serendipity['smarty']->security_settings['MODIFIER_FUNCS'] = array('sprintf', 'sizeof', 'count', 'rand');
+        $serendipity['smarty']->security      = true;
+        $serendipity['smarty']->use_sub_dirs  = false;
+        $serendipity['smarty']->compile_check = true;
+        $serendipity['smarty']->compile_id    = &$serendipity['template'];
+
+        $serendipity['smarty']->register_modifier('makeFilename', 'serendipity_makeFilename');
+        $serendipity['smarty']->register_modifier('xhtml_target', 'serendipity_xhtml_target');
+        $serendipity['smarty']->register_modifier('emptyPrefix', 'serendipity_emptyPrefix');
+        $serendipity['smarty']->register_modifier('formatTime', 'serendipity_smarty_formatTime');
+        $serendipity['smarty']->register_function('serendipity_printSidebar', 'serendipity_smarty_printSidebar');
+        $serendipity['smarty']->register_function('serendipity_hookPlugin', 'serendipity_smarty_hookPlugin');
+        $serendipity['smarty']->register_function('serendipity_showPlugin', 'serendipity_smarty_showPlugin');
+        $serendipity['smarty']->register_function('serendipity_getFile', 'serendipity_smarty_getFile');
+        $serendipity['smarty']->register_function('serendipity_printComments', 'serendipity_smarty_printComments');
+        $serendipity['smarty']->register_function('serendipity_printTrackbacks', 'serendipity_smarty_printTrackbacks');
+    }
+
+    if (!isset($serendipity['smarty_raw_mode'])) {
+        if (file_exists($serendipity['smarty']->template_dir . '/layout.php') && $serendipity['template'] != 'default') {
+            $serendipity['smarty_raw_mode'] = true;
+        } else {
+            $serendipity['smarty_raw_mode'] = false;
+        }
+    }
+
+    if (!isset($serendipity['smarty_file'])) {
+        $serendipity['smarty_file'] = 'index.tpl';
+    }
+
+    $serendipity['smarty']->assign(
+        array(
+            'head_charset'              => LANG_CHARSET,
+            'head_version'              => $serendipity['version'],
+            'head_title'                => $serendipity['head_title'],
+            'head_subtitle'             => $serendipity['head_subtitle'],
+            'head_link_stylesheet'      => serendipity_rewriteURL('serendipity.css'),
+
+            'CONST'                     => get_defined_constants(),
+
+            'is_xhtml'                  => $serendipity['XHTML11'],
+            'use_popups'                => $serendipity['enablePopup'],
+            'is_embedded'               => (!$serendipity['embed'] || $serendipity['embed'] === 'false' || $serendipity['embed'] === false) ? false : true,
+            'is_raw_mode'               => $serendipity['smarty_raw_mode'],
+
+            'entry_id'                  => (isset($serendipity['GET']['id']) && is_numeric($serendipity['GET']['id'])) ? $serendipity['GET']['id'] : false,
+            'is_single_entry'           => (isset($serendipity['GET']['id']) && is_numeric($serendipity['GET']['id'])),
+
+            'blogTitle'                 => htmlspecialchars($serendipity['blogTitle']),
+            'blogSubTitle'              => (!empty($serendipity['blogSubTitle']) ? htmlspecialchars($serendipity['blogSubTitle']) : ''),
+            'blogDescription'           => htmlspecialchars($serendipity['blogDescription']),
+
+            'serendipityHTTPPath'       => $serendipity['serendipityHTTPPath'],
+            'serendipityBaseURL'        => $serendipity['baseURL'],
+            'serendipityRewritePrefix'  => $serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '',
+            'serendipityIndexFile'      => $serendipity['indexFile'],
+            'serendipityVersion'        => $serendipity['version'],
+
+            'dateRange'                 => (!empty($serendipity['range']) ? $serendipity['range'] : array())
+        )
+    );
+
+    return true;
+}
+
+/* Nukes all Smarty compiled templates and cache */
+function serendipity_smarty_purge() {
+    global $serendipity;
+
+    /* Attempt to init Smarty, brrr */
+    serendipity_smarty_init();
+
+    $files = serendipity_traversePath($serendipity['smarty']->compile_dir, '', false, '/.+\.tpl\.php$/');
+
+    if ( !is_array($files) ) {
+        return false;
+    }
+
+    foreach ( $files as $file ) {
+        @unlink($serendipity['smarty']->compile_dir . DIRECTORY_SEPARATOR . $file['name']);
+    }
+}
+
+/* Function can be called from foreign applications. ob_start() needs to
+  have been called before, and will be parsed into Smarty here */
+function serendipity_smarty_shutdown($serendipity_directory = '') {
+global $serendipity;
+
+    $cwd = getcwd();
+    chdir($serendipity_directory);
+    $raw_data = ob_get_contents();
+    ob_end_clean();
+    $serendipity['smarty']->assign('content_message', $raw_data);
+
+    serendipity_smarty_fetch('CONTENT', 'content.tpl');
+    if (empty($serendipity['smarty_file'])) {
+        $serendipity['smarty_file'] = '404.tpl';
+    }
+    $serendipity['smarty']->display(serendipity_getTemplateFile($serendipity['smarty_file'], 'serendipityPath'));
+}
diff --git a/include/functions_trackbacks.inc.php b/include/functions_trackbacks.inc.php
new file mode 100644 (file)
index 0000000..d6c0518
--- /dev/null
@@ -0,0 +1,384 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+function serendipity_fetchTrackbacks($id, $limit = null, $showAll = false) {
+    global $serendipity;
+
+    if (!$showAll) {
+        $and = "AND status = 'approved'";
+    }
+
+    $query = "SELECT * FROM {$serendipity['dbPrefix']}comments WHERE entry_id = '". (int)$id ."' AND type = 'TRACKBACK' $and ORDER BY id";
+    if (isset($limit)) {
+        $limit  = serendipity_db_limit_sql($limit);
+        $query .= " $limit";
+    }
+
+    $comments = serendipity_db_query($query);
+    if (!is_array($comments)) {
+        return array();
+    }
+
+    return $comments;
+}
+
+function serendipity_printTrackbacks($trackbacks) {
+    global $serendipity;
+
+    $serendipity['smarty']->assign('trackbacks', $trackbacks);
+
+    return serendipity_smarty_fetch('TRACKBACKS', 'trackbacks.tpl');
+}
+
+/**
+ * validate trackback response
+ */
+function serendipity_trackback_is_success($resp) {
+    if (preg_match('@<error>(\d+)</error>@', $resp, $matches)) {
+        if ((int) $matches[1] === 0) {
+            return true;
+        } else {
+            if (preg_match('@<message>([^<]+)</message>@', $resp, $matches)) {
+                return $matches[1];
+            }
+            else {
+                return 'unknown error';
+            }
+        }
+    }
+    return true;
+}
+
+function serendipity_pingback_autodiscover($loc, $body) {
+    if (!empty($_SERVER['X-PINGBACK'])) {
+        $pingback = $_SERVER['X-PINGBACK'];
+    } elseif (preg_match('@<link rel="pingback" href="([^"]+)" ?/?>@i', $body, $matches)) {
+        $pingback = $matches[1];
+    } else {
+        return;
+    }
+
+    // xml-rpc hack
+    $query = "
+<?xml version=\"1.0\"?>
+<methodCall>
+  <methodName>pingback.ping</methodName>
+  <params>
+    <param>
+      <name>sourceURI</name>
+      <value><string>{$serendipity['baseURL']}</string></value>
+    </param>
+      <name>targetURI</name>
+      <value><string>$loc</string></value>
+    </param>
+  </params>
+</methodCall>";
+        _serendipity_send($pingback, $query);
+        return;
+}
+
+/**
+ * Send a trackback ping
+ */
+function _serendipity_send($loc, $data) {
+    global $serendipity;
+
+    $target = parse_url($loc);
+    if ($target['query'] != '') {
+        $target['query'] = '?' . str_replace('&amp;', '&', $target['query']);
+    }
+
+    if (!is_numeric($target['port'])) {
+       $target['port'] = 80;
+    }
+
+    $sock = @fsockopen($target['host'], $target['port']);
+    if (!is_resource($sock)) {
+        return "Couldn't connect to $loc";
+    }
+
+    $headers = "POST {$target['path']}{$target['query']} HTTP/1.1\r\n";
+    $headers .= "Host: {$target['host']}\r\n";
+    $headers .= "User-Agent: Serendipity/{$serendipity['version']}\r\n";
+    $headers .= "Content-Type: application/x-www-form-urlencoded; charset=" . LANG_CHARSET . "\r\n";
+    $headers .= "Content-Length: " . strlen($data) . "\r\n";
+    $headers .= "Connection: close\r\n";
+    $headers .= "\r\n";
+    $headers .= $data;
+
+    fwrite($sock, $headers);
+
+    $res = '';
+    while (!feof($sock)) {
+        $res .= fgets($sock, 1024);
+    }
+
+    fclose($sock);
+    return $res;
+}
+
+function serendipity_trackback_autodiscover($res, $loc, $url, $author, $title, $text) {
+    if (!preg_match('@trackback:ping(\s*rdf:resource)?\s*=\s*["\'](https?:[^"\']+)["\']@i', $res, $matches)) {
+        echo '<div>&#8226; ' . sprintf(TRACKBACK_FAILED, TRACKBACK_NOT_FOUND) . '</div>';
+        return false;
+    }
+
+    $trackURI = trim($matches[2]);
+
+    if (preg_match('@dc:identifier\s*=\s*["\'](https?:[^\'"]+)["\']@i', $res, $test)) {
+        if ($loc != $test[1]) {
+            echo '<div>&#8226; ' . sprintf(TRACKBACK_FAILED, TRACKBACK_URI_MISMATCH) . '</div>';
+            return false;
+        }
+    }
+
+    $data = 'url='        . rawurlencode($url)
+          . '&title='     . rawurlencode($title)
+          . '&blog_name=' . rawurlencode($author)
+          . '&excerpt='   . rawurlencode(strip_tags($text));
+
+    printf(TRACKBACK_SENDING, htmlspecialchars($trackURI));
+    flush();
+
+    $response = serendipity_trackback_is_success(_serendipity_send($trackURI, $data));
+
+    if ($response === true) {
+        echo '<div>&#8226; ' . TRACKBACK_SENT .'</div>';
+    } else {
+        echo '<div>&#8226; ' . sprintf(TRACKBACK_FAILED, $response) . '</div>';
+    }
+
+    return $response;
+}
+
+function serendipity_reference_autodiscover($loc, $url, $author, $title, $text) {
+global $serendipity;
+    $timeout   = 30;
+
+    $u = parse_url($loc);
+
+    if ($u['scheme'] != 'http' && $u['scheme'] != 'https') {
+        return;
+    } elseif ($u['scheme'] == 'https' && !extension_loaded('openssl')) {
+        return; // Trackbacks to HTTPS URLs can only be performed with openssl activated
+    }
+
+    echo '<div>&#8226; '. sprintf(TRACKBACK_CHECKING, $loc) .'</div>';
+    flush();
+
+    if (empty($u['port'])) {
+        $u['port'] = 80;
+        $port      = '';
+    } else {
+        $port      = ':' . $u['port'];
+    }
+
+    if (!empty($u['query'])) {
+        $u['path'] .= '?' . $u['query'];
+    }
+
+    $parsed_loc = $u['scheme'] . '://' . $u['host'] . $port . $u['path'];
+    $res = '';
+
+    $fp  = @fsockopen($u['host'], $u['port'], $err, $timeout);
+    if (!$fp) {
+        echo '<div>&#8226; ' . sprintf(TRACKBACK_COULD_NOT_CONNECT, $u['host'], $u['port']) .'</div>';
+        return;
+    } else {
+        fputs($fp, "GET {$u['path']} HTTP/1.0\r\n");
+        fputs($fp, "Host: {$u['host']}\r\n");
+        fputs($fp, "User-Agent: Serendipity/{$serendipity['version']}\r\n");
+        fputs($fp, "Connection: close\r\n\r\n");
+
+        while ($fp && !feof($fp) && strlen($res) < $serendipity['trackback_filelimit']) {
+            $res .= fgets($fp, 4096);
+        }
+        fclose($fp);
+
+        if (strlen($res) >= $serendipity['trackback_filelimit']) {
+            echo '<div>&#8226; ' . sprintf(TRACKBACK_SIZE, $serendipity['trackback_filelimit']) .'</div>';
+            return;
+        }
+    }
+
+    if (strlen($res) != 0) {
+        serendipity_trackback_autodiscover($res, $parsed_loc, $url, $author, $title, $text);
+        serendipity_pingback_autodiscover($loc, $res);
+    } else {
+        echo '<div>&#8226; ' . TRACKBACK_NO_DATA . '</div>';
+    }
+    echo '<hr noshade="noshade" />';
+}
+
+/**
+ *
+ */
+function add_trackback ($id, $title, $url, $name, $excerpt) {
+    global $serendipity;
+
+    // We can't accept a trackback if we don't get any URL
+    // This is a protocol rule.
+    if ( empty($url) ) {
+        return 0;
+    }
+
+    // If title is not provided, the value for url will be set as the title
+    // This is a protocol rule.
+    if ( empty($title) ) {
+        $title = $url;
+    }
+    $comment['title']   = $title;
+    $comment['url']     = $url;
+    $comment['name']    = $name;
+    $comment['comment'] = $excerpt;
+
+    serendipity_saveComment($id, $comment, 'TRACKBACK');
+
+    return 1;
+}
+
+function add_pingback ($id, $postdata) {
+    global $serendipity;
+
+    if(preg_match('@<methodcall>\s*<methodName>\s*pingback.ping\s*</methodName>\s*<params>\s*<param>\s*<value>\s*<string>([^<])*</string>\s*</value>\s*</param>\s*<param>\s*<value>\s*<string>([^<])*</string>\s*</value>\s*</param>\s*</params>\s*</methodCall>@i', $postdata, $matches)) {
+        $remote             = $matches[1];
+        $local              = $matches[2];
+        $comment['title']   = '';
+        $comment['url']     = $remote;
+        $comment['comment'] = '';
+        $comment['name']    = '';
+
+        serendipity_saveComment($id, $comment, 'PINGBACK');
+        return 1;
+    }
+    return 0;
+}
+
+/**
+ * Cut text
+ */
+function serendipity_trackback_excerpt($text) {
+    return substr(strip_tags($text), 0, 255);
+}
+
+function report_trackback_success () {
+print '<?xml version="1.0" encoding="iso-8859-1"?>' . "\n";
+print <<<SUCCESS
+<response>
+    <error>0</error>
+</response>
+SUCCESS;
+}
+
+function report_trackback_failure () {
+print '<?xml version="1.0" encoding="iso-8859-1"?>' . "\n";
+print <<<FAILURE
+<response>
+    <error>1</error>
+    <message>Danger Will Robinson, trackback failed.</message>
+</response>
+FAILURE;
+}
+
+function report_pingback_success () {
+print '<?xml version="1.0"?>' . "\n";
+print <<<SUCCESS
+<methodResponse>
+   <params>
+      <param>
+         <value><string>success</string></value>
+         </param>
+      </params>
+   </methodResponse>
+SUCCESS;
+}
+
+function report_pingback_failure () {
+print '<?xml version="1.0"?>' . "\n";
+print <<<FAILURE
+<methodResponse>
+    <fault>
+    <value><i4>0</i4></value>
+    </fault>
+</methodResponse>
+FAILURE;
+}
+
+/**
+ * search through link body, and automatically send a trackback ping.
+ */
+function serendipity_handle_references($id, $author, $title, $text) {
+    global $serendipity;
+
+    if (!preg_match_all('@<a[^>]+?href\s*=\s*["\']?([^\'" >]+?)[ \'"][^>]*>(.+?)</a>@i', $text, $matches)) {
+        return;
+    }
+
+    // remove full matches
+    array_shift($matches);
+
+    // Make trackback URL
+    $url = serendipity_archiveURL($id, $title, 'baseURL');
+
+    // Add URL references
+    $locations = $matches[0];
+    $names     = $matches[1];
+
+    $tmpid = serendipity_db_escape_string($id);
+
+    $checked_locations = array();
+    serendipity_plugin_api::hook_event('backend_trackbacks', $locations);
+    for ($i = 0, $j = count($locations); $i < $j; ++$i) {
+        if ($locations[$i][0] == '/') {
+            $locations[$i] = 'http' . (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off' ? 's' : '') . '://' . $_SERVER['HTTP_HOST'] . $locations[$i];
+        }
+
+        if (isset($checked_locations[$locations[$i]])) {
+            continue;
+        }
+
+        if (preg_match_all('@<img[^>]+?alt=["\']?([^\'">]+?)[\'"][^>]+?>@i', $names[$i], $img_alt)) {
+            if (is_array($img_alt) && is_array($img_alt[0])) {
+                foreach($img_alt[0] as $alt_idx => $alt_img) {
+                    // Replace all <img>s within a link with their respective ALT tag, so that references
+                    // can be stored with a title.
+                    $names[$i] = str_replace($alt_img, $img_alt[1][$alt_idx], $names[$i]);
+                }
+            }
+        }
+
+        $query = "SELECT COUNT(id) FROM {$serendipity['dbPrefix']}references
+                                  WHERE entry_id = '". (int)$tmpid ."'
+                                    AND link = '" . serendipity_db_escape_string($locations[$i]) . "'";
+
+        $row = serendipity_db_query($query, true, 'num');
+        if ($row[0] > 0) {
+            continue;
+        }
+
+        if (!isset($serendipity['noautodiscovery']) || !$serendipity['noautodiscovery']) {
+            serendipity_reference_autodiscover($locations[$i], $url, $author, $title, serendipity_trackback_excerpt($text));
+            $checked_locations[$locations[$i]] = true; // Store trackbacked link so that no further trackbacks will be sent to the same link
+        }
+    }
+    serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}references WHERE entry_id='" . (int)$tmpid . "'");
+
+    for ($i = 0; $i < $j; ++$i) {
+        $query = "INSERT INTO {$serendipity['dbPrefix']}references (entry_id, name, link) VALUES(";
+        $query .= "'" . (int)$tmpid . "', '" . serendipity_db_escape_string(strip_tags($names[$i])) . "', '";
+        $query .= serendipity_db_escape_string($locations[$i]) . "')";
+
+        serendipity_db_query($query);
+    }
+
+    // Add citations
+    preg_match_all('@<cite[^>]*>([^<]+)</cite>@i', $text, $matches);
+
+    foreach ($matches[1] as $citation) {
+        $query = "INSERT INTO {$serendipity['dbPrefix']}references (entry_id, name) VALUES(";
+        $query .= "'" . (int)$tmpid . "', '" . serendipity_db_escape_string($citation) . "')";
+
+        serendipity_db_query($query);
+    }
+}
diff --git a/include/functions_upgrader.inc.php b/include/functions_upgrader.inc.php
new file mode 100644 (file)
index 0000000..cf95f17
--- /dev/null
@@ -0,0 +1,113 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+/* A list of files which got obsoleted in 0.8 */
+$obsolete_files = array(
+    'serendipity.inc.php',
+    'serendipity_layout.inc.php',
+    'serendipity_layout_table.inc.php',
+    'serendipity_entries_overview.inc.php',
+    'serendipity_rss_exchange.inc.php',
+    'serendipity_admin_category.inc.php',
+    'serendipity_admin_comments.inc.php',
+    'serendipity_admin_entries.inc.php',
+    'serendipity_admin_images.inc.php',
+    'serendipity_admin_installer.inc.php',
+    'serendipity_admin_interop.inc.php',
+    'serendipity_admin_overview.inc.php',
+    'serendipity_admin_plugins.inc.php',
+    'serendipity_admin_templates.inc.php',
+    'serendipity_admin_upgrader.inc.php',
+    'serendipity_admin_users.inc.php',
+    'compat.php',
+    'serendipity_functions_config.inc.php',
+    'serendipity_functions_images.inc.php',
+    'serendipity_functions_installer.inc.php',
+    'serendipity_genpage.inc.php',
+    'serendipity_lang.inc.php',
+    'serendipity_plugin_api.php',
+    'serendipity_sidebar_items.php',
+    'serendipity_db.inc.php',
+    'serendipity_db_mysql.inc.php',
+    'serendipity_db_mysqli.inc.php',
+    'serendipity_db_postgres.inc.php',
+    'serendipity_db_sqlite.inc.php',
+    'htaccess.cgi.errordocs.tpl',
+    'htaccess.cgi.normal.tpl',
+    'htaccess.cgi.rewrite.tpl',
+    'htaccess.errordocs.tpl',
+    'htaccess.normal.tpl',
+    'htaccess.rewrite.tpl',
+    'serendipity_config_local.tpl',
+    'serendipity_config_user.tpl',
+    'INSTALL',
+    'LICENSE',
+    'NEWS',
+    'README',
+    'TODO',
+    'upgrade.sh',
+    'templates/default/layout.php'
+);
+
+function serendipity_fixPlugins($case) {
+    global $serendipity;
+
+    switch($case) {
+        case 'markup_column_names':
+            $affected_plugins = array(
+                'serendipity_event_bbcode',
+                'serendipity_event_contentrewrite',
+                'serendipity_event_emoticate',
+                'serendipity_event_geshi',
+                'serendipity_event_nl2br',
+                'serendipity_event_textwiki',
+                'serendipity_event_trackexits',
+                'serendipity_event_xhtmlcleanup',
+                'serendipity_event_markdown',
+                'serendipity_event_s9ymarkup',
+                'serendipity_event_searchhighlight',
+                'serendipity_event_textile'
+            );
+            
+            $elements = array(
+                'ENTRY_BODY',
+                'EXTENDED_BODY',
+                'COMMENT',
+                'HTML_NUGGET'
+            );
+
+            $where = array();
+            foreach($affected_plugins AS $plugin) {
+                $where[] = "name LIKE '$plugin:%'";
+            }
+
+            $rows = serendipity_db_query("SELECT name, value, authorid 
+                                            FROM {$serendipity['dbPrefix']}config  
+                                           WHERE " . implode(' OR ', $where));
+            if (!is_array($rows)) {
+                return false;
+            }
+            
+            foreach($rows AS $row) {
+                if (preg_match('@^(serendipity_event_.+):([a-z0-9]+)/(.+)@i', $row['name'], $plugin_data)) {
+                    foreach($elements AS $element) {
+                        if ($plugin_data[3] != constant($element)) {
+                            continue;
+                        }
+                        
+                        $new = $plugin_data[1] . ':' . $plugin_data[2] . '/' . $element;
+                        serendipity_db_query("UPDATE {$serendipity['dbPrefix']}config
+                                                 SET name     = '$new'
+                                               WHERE name     = '{$row['name']}' 
+                                                 AND value    = '{$row['value']}'
+                                                 AND authorid = '{$row['authorid']}'");
+                    }
+                }
+            }
+
+            return true;
+            break;
+    }
+}
+?>
diff --git a/include/genpage.inc.php b/include/genpage.inc.php
new file mode 100644 (file)
index 0000000..7ccfacc
--- /dev/null
@@ -0,0 +1,72 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+include_once('serendipity_config.inc.php');
+include_once(S9Y_INCLUDE_PATH . 'include/plugin_api.inc.php');
+include_once(S9Y_INCLUDE_PATH . 'include/plugin_internal.inc.php');
+
+serendipity_plugin_api::hook_event('genpage', $uri);
+serendipity_smarty_init();
+
+// For advanced usage, we allow template authors to create a file 'config.inc.php' where they can
+// setup custom smarty variables, modifiers etc. to use in their templates.
+@include_once $serendipity['smarty']->template_dir . '/config.inc.php';
+
+$serendipity['smarty']->assign(
+    array(
+        'leftSidebarElements'       => serendipity_plugin_api::count_plugins('left'),
+        'rightSidebarElements'      => serendipity_plugin_api::count_plugins('right')
+    )
+);
+
+if ($serendipity['smarty_raw_mode']) {
+    /* For BC reasons, we have to ask for layout.php */
+    @include_once(serendipity_getTemplateFile('layout.php', 'serendipityPath'));
+} else {
+    switch ($serendipity['GET']['action']) {
+        // User wants to read the diary
+        case 'read':
+            if (isset($serendipity['GET']['id'])) {
+                serendipity_printEntries(array(serendipity_fetchEntry('id', $serendipity['GET']['id'])), 1);
+            } else {
+                serendipity_printEntries(serendipity_fetchEntries($serendipity['range'], true, $serendipity['fetchLimit']));
+            }
+            break;
+
+        // User searches
+        case 'search':
+            $r = serendipity_searchEntries($serendipity['GET']['searchTerm']);
+            if (strlen($serendipity['GET']['searchTerm']) <= 3) {
+                $serendipity['smarty']->assign('content_message', SEARCH_TOO_SHORT);
+                break;
+            }
+
+            if (is_string($r) && $r !== true) {
+                $serendipity['smarty']->assign('content_message', sprintf(SEARCH_ERROR, $serendipity['dbPrefix'], $r));
+                break;
+            } elseif ($r === true) {
+                $serendipity['smarty']->assign('content_message', sprintf(NO_ENTRIES_BLAHBLAH, $serendipity['GET']['searchTerm']));
+                break;
+            }
+
+            $serendipity['smarty']->assign('content_message', sprintf(YOUR_SEARCH_RETURNED_BLAHBLAH, $serendipity['GET']['searchTerm'], count($r)));
+            serendipity_printEntries($r);
+            break;
+
+        // Show the archive
+        case 'archives':
+            serendipity_printArchives();
+            break;
+
+        // Welcome screen or whatever
+        default:
+            serendipity_printEntries(serendipity_fetchEntries(null, true, $serendipity['fetchLimit']));
+            break;
+    }
+
+    serendipity_smarty_fetch('CONTENT', 'content.tpl');
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/lang.inc.php b/include/lang.inc.php
new file mode 100644 (file)
index 0000000..908d454
--- /dev/null
@@ -0,0 +1,81 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+if (!defined('serendipity_LANG_LOADED') || serendipity_LANG_LOADED !== true) {
+    // Try and include preferred language from the configurated setting
+    if (@include(S9Y_INCLUDE_PATH . 'lang/serendipity_lang_'. $serendipity['lang'] .'.inc.php') ) {
+        // Only here can we truely say the language is loaded
+        define('serendipity_LANG_LOADED', true);
+    } elseif (IS_installed === false || (defined('IS_up2date') && IS_up2date === false)) {   /* -- Auto-Guess -- */
+        // If no config file is loaded, language includes are not available.
+        // Now include one. Try to auto-guess the language by looking up the HTTP_ACCEPT_LANGUAGE.
+        serendipity_detectLang(true);
+    }  //endif
+
+    // Do fallback to english
+    if ((defined('serendipity_LANG_LOADED') && serendipity_LANG_LOADED === true) || IS_installed === false || (defined('IS_up2date') && IS_up2date === false)) {
+        @include_once(S9Y_INCLUDE_PATH . 'lang/serendipity_lang_en.inc.php');
+    }
+}
+
+if (!defined('serendipity_MB_LOADED') && defined('serendipity_LANG_LOADED')) {
+    // Needs to be included here because we need access to constant LANG_CHARSET definied in languages (not available for compat.inc.php)
+
+    if (function_exists('mb_language')) {
+        @mb_language($serendipity['lang']);
+    }
+    
+    if (function_exists('mb_internal_encoding')) {
+        @mb_internal_encoding(LANG_CHARSET);
+    }
+
+    // Multibyte string functions wrapper:
+    // strlen(), strpos(), strrpos(), strtolower(), strtoupper(), substr(), ucfirst()
+    function serendipity_mb() {
+        static $mbstring = null;
+
+        if (is_null($mbstring)) {
+            $mbstring = (extension_loaded('mbstring') ? 1 : 0);
+            if ($mbstring === 1) {
+                if (function_exists('mb_strtoupper')) {
+                    $mbstring = 2;
+                }
+            }
+        }
+
+        $args = func_get_args();
+        $func = $args[0];
+        unset($args[0]);
+
+        switch($func) {
+            case 'ucfirst':
+                // there's no mb_ucfirst, so emulate it
+                if ($mbstring === 2) {
+                    return mb_strtoupper(mb_substr($args[1], 0, 1)) . mb_substr($args[1], 1);
+                } else {
+                    return ucfirst($args[1]);
+                }
+
+            case 'strtolower':
+            case 'strtoupper':
+                if ($mbstring === 2) {
+                    return call_user_func_array('mb_' . $func, $args);
+                } else {
+                    return call_user_func_array($func, $args);
+                }
+
+            default:
+                if ($mbstring) {
+                    return call_user_func_array('mb_' . $func, $args);
+                } else {
+                    return call_user_func_array($func, $args);
+                }
+        }
+    }
+
+    define('serendipity_MB_LOADED', true);
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/plugin_api.inc.php b/include/plugin_api.inc.php
new file mode 100644 (file)
index 0000000..9b66da4
--- /dev/null
@@ -0,0 +1,838 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+if (IN_serendipity !== true) {
+    die ('Don\'t hack!');
+}
+
+include_once S9Y_INCLUDE_PATH . 'include/functions.inc.php';
+
+/* This file defines the plugin API for serendipity.
+ * By extending these classes, you can add your own code
+ * to appear in the sidebar(s) of serendipity.
+ *
+ *
+ * The system defines a number of built-in plugins; these are
+ * identified by @class_name.
+ *
+ * Third-party plugins are identified by the name of the folder into
+ * which they were uploaded (so there is no @ sign at the start of
+ * their class name.
+ *
+ * The user creates instances of plugins; an instance is assigned
+ * an identifier like this:
+ *   classname:uniqid()
+ *
+ * The user can configure instances of plugins.
+ */
+
+class serendipity_plugin_api {
+    function register_default_plugins()
+    {
+        /* Register default sidebar plugins, order matters */
+        serendipity_plugin_api::create_plugin_instance('@serendipity_calendar_plugin');
+        serendipity_plugin_api::create_plugin_instance('@serendipity_quicksearch_plugin');
+        serendipity_plugin_api::create_plugin_instance('@serendipity_archives_plugin');
+        serendipity_plugin_api::create_plugin_instance('@serendipity_categories_plugin');
+        serendipity_plugin_api::create_plugin_instance('@serendipity_syndication_plugin');
+        serendipity_plugin_api::create_plugin_instance('@serendipity_superuser_plugin');
+        serendipity_plugin_api::create_plugin_instance('@serendipity_plug_plugin');
+
+        /* Register default event plugins */
+        serendipity_plugin_api::create_plugin_instance('serendipity_event_s9ymarkup', null, 'event');
+        serendipity_plugin_api::create_plugin_instance('serendipity_event_emoticate', null, 'event');
+        serendipity_plugin_api::create_plugin_instance('serendipity_event_nl2br', null, 'event');
+        serendipity_plugin_api::create_plugin_instance('serendipity_event_browsercompatibility', null, 'event');
+        serendipity_plugin_api::create_plugin_instance('serendipity_event_spamblock', null, 'event');
+    }
+
+    /* Create an instance of a plugin.
+     * $plugin_class_id is of the form:
+     *    @class_name        for a built-in plugin
+     * or
+     *    plugin_dir_name    for a third-party plugin
+     * returns the instance identifier for the newly created plugin.
+     *
+     * TO BE IMPLEMENTED:
+     * If $copy_from_instance is not null, and identifies another plugin
+     * of the same class, then the persistent state will be copied.
+     * This allows the user to clone a plugin.
+     */
+    function create_plugin_instance($plugin_class_id, $copy_from_instance = null, $default_placement = 'right', $authorid = '0', $pluginPath = '')
+    {
+        global $serendipity;
+
+        $id = md5(uniqid(''));
+
+        $key = $plugin_class_id . ':' . $id;
+
+        // Secure Plugin path. No leading slashes, no backslashes, no "up" directories
+        $pluginPath = preg_replace('@^(/)@', '', $pluginPath);
+        $pluginPath = str_replace(array('..', "\\"), array('', '/'), serendipity_db_escape_string($pluginPath));
+
+        $rs = serendipity_db_query("SELECT MAX(sort_order) as sort_order_max FROM {$serendipity['dbPrefix']}plugins WHERE placement = '$default_placement'", true, 'num');
+
+        if (is_array($rs)) {
+            $nextidx = intval($rs[0]+1);
+        } else {
+            $nextidx = 0;
+        }
+
+        serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}plugins (name, sort_order, placement, authorid, path) values ('$key', $nextidx, '$default_placement', '$authorid', '$pluginPath')");
+        serendipity_plugin_api::hook_event('backend_plugins_new_instance', $key, array('default_placement' => $default_placement));
+
+        /* Check for multiple dependencies */
+        $plugin =& serendipity_plugin_api::load_plugin($key, $authorid, $pluginPath);
+        if (is_object($plugin)) {
+            $bag    = new serendipity_property_bag;
+            $plugin->introspect($bag);
+            serendipity_plugin_api::get_event_plugins(false, true); // Refresh static list of plugins to allow execution of added plugin
+            $plugin->register_dependencies(false, $authorid);
+            $plugin->install();
+        } else {
+            echo ERROR . ': ' . $key . ' (' . $pluginPath . ')<br />';
+        }
+
+        return $key;
+    }
+
+    function remove_plugin_instance($plugin_instance_id)
+    {
+        global $serendipity;
+
+        $plugin =& serendipity_plugin_api::load_plugin($plugin_instance_id);
+        if (is_object($plugin)) {
+            $bag    = new serendipity_property_bag;
+            $plugin->introspect($bag);
+            $plugin->uninstall($bag);
+        }
+
+        serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}plugins where name='$plugin_instance_id'");
+
+        if (is_object($plugin)) {
+            $plugin->register_dependencies(true);
+        }
+
+        serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}config  where name LIKE '$plugin_instance_id/%'");
+    }
+
+    function remove_plugin_value($plugin_instance_id, $where)
+    {
+        global $serendipity;
+        $where_sql = array();
+        foreach($where AS $key) {
+            $where_sql[] = "(name LIKE '{$plugin_instance_id}/{$key}_%' AND value = '')";
+        }
+
+        $query = "DELETE FROM  {$serendipity['dbPrefix']}config
+                                    WHERE  " . implode(' OR ', $where_sql);
+
+        serendipity_db_query($query);
+    }
+
+    /* Retrieves a list of available plugins */
+    function &enum_plugin_classes($event_only = false)
+    {
+        global $serendipity;
+
+        $classes = array();
+
+        /* built-in classes first */
+        $cls = get_declared_classes();
+        foreach ($cls as $class_name) {
+            if (strncmp($class_name, 'serendipity_', 6)) {
+                continue;
+            }
+
+            $p = get_parent_class($class_name);
+            while ($p != 'serendipity_plugin' && $p != 'serendipity_event' && $p !== false) {
+                $p = get_parent_class($p);
+            }
+
+            if ($p == 'serendipity_plugin' && $class_name != 'serendipity_event' && (!$event_only || is_null($event_only))) {
+                $classes[$class_name] = array('name'       => '@' . $class_name,
+                                              'pluginPath' => '');
+            } elseif ($p == 'serendipity_event' && $class_name != 'serendipity_event' && ($event_only || is_null($event_only))) {
+                $classes[$class_name] = array('name'       => '@' . $class_name,
+                                              'pluginPath' => '');
+            }
+        }
+
+        /* GLOBAL third-party classes next */
+        $ppath = serendipity_getRealDir(__FILE__) . 'plugins';
+        serendipity_plugin_api::traverse_plugin_dir($ppath, $classes, $event_only);
+
+        /* LOCAL third-party classes next */
+        $local_ppath = $serendipity['serendipityPath'] . 'plugins';
+        if ($ppath != $local_ppath) {
+            serendipity_plugin_api::traverse_plugin_dir($local_ppath, $classes, $event_only);
+        }
+
+        return $classes;
+    }
+
+    function traverse_plugin_dir($ppath, &$classes, $event_only, $maindir = '') {
+        $d = @opendir($ppath);
+        if ($d) {
+            while (($f = readdir($d)) !== false) {
+                if ($f{0} == '.' || $f == 'CVS' || !is_dir($ppath . '/' . $f)) {
+                    continue;
+                }
+
+                $subd = opendir($ppath . '/' . $f);
+                if (!$subd) {
+                    continue;
+                }
+
+                // Instead of only looking for directories, search for files within subdirectories
+                while (($subf = readdir($subd)) !== false) {
+                    if ($subf{0} == '.' || $subf == 'CVS') {
+                        continue;
+                    }
+
+                    if (is_dir($ppath . '/' . $f . '/' . $subf) && $maindir != $ppath . '/' . $f) {
+                        // Search for another level of subdirectories
+                        serendipity_plugin_api::traverse_plugin_dir($ppath . '/' . $f, $classes, $event_only, $f . '/');
+                    }
+
+                    if (!preg_match('@^[^_]+_(event|plugin)_.+\.php$@i', $subf)) {
+                        continue;
+                    }
+
+                    // If an external plugin/event already exists as internal, remove the internal reference because its redundant
+                    if (isset($classes['@' . $subf])) {
+                        unset($classes['@' . $subf]);
+                    }
+
+                    // A local plugin will be preferred over general plugins [used when calling this function the second time]
+                    if (isset($classes[$subf])) {
+                        unset($classes[$subf]);
+                    }
+
+                    if (!is_null($event_only) && $event_only && !serendipity_plugin_api::is_event_plugin($subf)) {
+                        continue;
+                    }
+
+                    if (!is_null($event_only) && !$event_only && serendipity_plugin_api::is_event_plugin($subf)) {
+                        continue;
+                    }
+
+                    $class_name = str_replace('.php', '', $subf);
+                    $classes[$class_name] = array('name'       => $class_name,
+                                                  'pluginPath' => $maindir . $f);
+                }
+            }
+        }
+    }
+
+    function get_installed_plugins($filter = '*') {
+        $plugins = serendipity_plugin_api::enum_plugins($filter);
+        $res = array();
+        foreach ( (array)$plugins as $plugin ) {
+            list($class_name) = explode(':', $plugin['name']);
+            if ($class_name{0} == '@') {
+                $class_name = substr($class_name, 1);
+            }
+            $res[] = $class_name;
+        }
+        return $res;
+    }
+
+    /* Retrieves a list of plugin instances */
+    function enum_plugins($filter = '*', $negate = false, $classname = null, $id = null)
+    {
+        global $serendipity;
+
+        $sql   = "SELECT * from {$serendipity['dbPrefix']}plugins ";
+        $where = array();
+
+        if ($filter !== '*') {
+            if ($negate) {
+                $where[] = " placement != '" . serendipity_db_escape_string($filter) . "' ";
+            } else {
+                $where[] = " placement =  '" . serendipity_db_escape_string($filter) . "' ";
+            }
+        }
+        
+        if (!empty($classname)) {
+            $where[] = " (name LIKE '@" . serendipity_db_escape_string($classname) . "%' OR name LIKE '" . serendipity_db_escape_string($classname) . "%') ";
+        }
+        
+        if (!empty($id)) {
+            $where[] = " name = '" . serendipity_db_escape_string($id) . "' ";
+        }
+        
+        if (count($where) > 0) {
+            $sql .= ' WHERE ' . implode(' AND ', $where);
+        }
+
+        $sql .= ' ORDER BY placement, sort_order';
+
+        return serendipity_db_query($sql);
+    }
+
+    /* Retrieves a list of plugin instances */
+    function count_plugins($filter = '*', $negate = false)
+    {
+        global $serendipity;
+
+        $sql = "SELECT COUNT(placement) AS count from {$serendipity['dbPrefix']}plugins ";
+
+        if ($filter !== '*') {
+            if ($negate) {
+                $sql .= "WHERE placement != '$filter' ";
+            } else {
+                $sql .= "WHERE placement='$filter' ";
+            }
+        }
+
+        $count = serendipity_db_query($sql, true);
+        if (is_array($count) && isset($count[0])) {
+            return (int)$count[0];
+        }
+
+        return 0;
+    }
+
+    /* Creates an instance of a named plugin */
+    function &load_plugin($instance_id, $authorid = null, $pluginPath = '')
+    {
+        global $serendipity;
+
+        $instance = explode(':', $instance_id);
+        $name     = $instance[0];
+
+        if ($name{0} == '@') {
+            $class_name = substr($name, 1);
+        } else {
+            /* plugin from the plugins/ dir */
+            if (!class_exists($name)) {
+                if (empty($pluginPath)) {
+                    $sql = "SELECT path from {$serendipity['dbPrefix']}plugins WHERE name = '" . $instance_id . "'";
+                    $plugdata = serendipity_db_query($sql, true, 'both', false, false, false, true);
+                    if (is_array($plugdata) && isset($plugdata[0])) {
+                        $pluginPath = $plugdata[0];
+                    }
+
+                    if (empty($pluginPath)) {
+                        $pluginPath = $name;
+                    }
+                }
+
+                // First try the local path, and then (if existing) a shared library repository ...
+                if (file_exists($serendipity['serendipityPath'] . 'plugins/' . $pluginPath . '/' . $name . '.php')) {
+                    include $serendipity['serendipityPath'] . 'plugins/' . $pluginPath . '/' . $name . '.php';
+                } elseif (file_exists(S9Y_INCLUDE_PATH . 'plugins/' . $pluginPath . '/' . $name . '.php')) {
+                    include S9Y_INCLUDE_PATH . 'plugins/' . $pluginPath . '/' . $name . '.php';
+                }
+
+                if (!class_exists($name)) {
+                    return false;
+                }
+            }
+
+            $class_name =& $name;
+        }
+
+        $p =& new $class_name($instance_id);
+        if (!is_null($authorid)) {
+            $p->serendipity_owner = $authorid;
+        } else {
+            $sql = "SELECT authorid from {$serendipity['dbPrefix']}plugins WHERE name = '" . $instance_id . "'";
+            $owner = serendipity_db_query($sql, true);
+            if (is_array($owner) && isset($owner[0])) {
+                $p->serendipity_owner = $owner[0];
+            }
+        }
+
+        return $p;
+    }
+
+    function update_plugin_placement($name, $placement, $order=null)
+    {
+        global $serendipity;
+
+        $admin = '';
+        if ($serendipity['serendipityUserlevel'] < USERLEVEL_ADMIN && $placement == 'hidden') {
+            // Only administrators can set plugins to 'hidden' if they are not the owners.
+            $admin = " AND (authorid = 0 OR authorid = {$serendipity['authorid']})";
+        }
+
+        $sql = "UPDATE {$serendipity['dbPrefix']}plugins set placement='$placement' ";
+
+        if ($order !== null) {
+            $sql .= ", sort_order=$order ";
+        }
+
+        $sql .= "WHERE name='$name' $admin";
+
+        return serendipity_db_query($sql);
+    }
+
+    function update_plugin_owner($name, $authorid)
+    {
+        global $serendipity;
+
+        if (empty($authorid) && $authorid != '0') {
+            return;
+        }
+
+        $admin = '';
+        if ($serendipity['serendipityUserlevel'] < USERLEVEL_ADMIN) {
+            $admin = " AND (authorid = 0 OR authorid = {$serendipity['authorid']})";
+        }
+
+        $sql = "UPDATE {$serendipity['dbPrefix']}plugins SET authorid='$authorid' WHERE name='$name' $admin";
+
+        return serendipity_db_query($sql);
+    }
+
+    function generate_plugins($side, $tag = '', $negate = false, $class = null, $id = null)
+    {
+        global $serendipity;
+
+        /* $tag parameter is deprecated and used in Smarty templates instead. Only use it in function
+         * header for layout.php BC.
+         */
+
+        $plugins = serendipity_plugin_api::enum_plugins($side, $negate, $class, $id);
+
+        if (!is_array($plugins)) {
+            return;
+        }
+        
+        if (!isset($serendipity['smarty'])) {
+            $serendipity['smarty_raw_mode'] = true;
+            serendipity_smarty_init();
+        }
+
+        $pluginData = array();
+        foreach ($plugins as $plugin_data) {
+            $plugin =& serendipity_plugin_api::load_plugin($plugin_data['name'], $plugin_data['authorid'], $plugin_data['path']);
+            if (is_object($plugin)) {
+                $class  = get_class($plugin);
+                $title  = '';
+
+                /* TODO: make generate_content NOT echo its output */
+                ob_start();
+                $show_plugin = $plugin->generate_content($title);
+                $content = ob_get_contents();
+                ob_end_clean();
+
+                if ($show_plugin !== FALSE) {
+                    $pluginData[] = array('side'    => $side,
+                                          'class'   => $class,
+                                          'title'   => $title,
+                                          'content' => $content);
+                }
+            } elseif ($show_plugin !== FALSE) {
+                    $pluginData[] = array('side'          => $side,
+                                          'title'         => ERROR,
+                                          'content'       => sprintf(INCLUDE_ERROR, $plugin_data['name']));
+            }
+        }
+
+        $serendipity['smarty']->assign(
+            array(
+                'plugindata' => $pluginData,
+                'pluginside' => ucfirst($side)
+            )
+        );
+
+
+        return serendipity_smarty_fetch('sidebar_'. $side, 'sidebar.tpl', true);
+    }
+
+    function get_plugin_title(&$plugin, $default_title = '')
+    {
+        global $serendipity;
+
+        // Generate plugin output. Make sure that by probing the plugin, no events are actually called. After that,
+        // restore setting of 'no_events'.
+
+        if (!is_null($plugin->title)) {
+            // Preferred way of fetching a plugins title
+            $title = &$plugin->title;
+        } else {
+            $ne = (isset($serendipity['no_events']) && $serendipity['no_events'] ? TRUE : FALSE);
+            $serendipity['no_events'] = TRUE;
+            ob_start();
+            $plugin->generate_content($title);
+            ob_end_clean();
+            $serendipity['no_events'] = $ne;
+        }
+
+        if (strlen(trim($title)) == 0) {
+            if (!empty($default_title)) {
+                $title = $default_title;
+            } else {
+                $title = $plugin->instance;
+            }
+        }
+
+        return $title;
+    }
+
+    /* conditional to see if the named plugin is an event plugin
+        Refactoring: decompose conditional */
+    function is_event_plugin($name) {
+        return (strstr($name, '_event_'));
+    }
+
+    function &get_event_plugins($getInstance = false, $refresh = false) {
+        static $event_plugins;
+
+        if (!$refresh && isset($event_plugins) && is_array($event_plugins)) {
+            if ($getInstance) {
+                if (isset($event_plugins[$getInstance]['p'])) {
+                    return $event_plugins[$getInstance]['p'];
+                }
+                return false;
+            }
+            return $event_plugins;
+        }
+
+        $plugins = serendipity_plugin_api::enum_plugins('event');
+
+        if (!is_array($plugins)) {
+            return false;
+        }
+
+        $event_plugins = array();
+        foreach($plugins AS $plugin_data) {
+            if ($event_plugins[$plugin_data['name']]['p'] = &serendipity_plugin_api::load_plugin($plugin_data['name'], $plugin_data['authorid'], $plugin_data['path'])) {
+                /* query for its name, description and configuration data */
+                $event_plugins[$plugin_data['name']]['b'] = new serendipity_property_bag;
+                $event_plugins[$plugin_data['name']]['p']->introspect($event_plugins[$plugin_data['name']]['b']);
+                $event_plugins[$plugin_data['name']]['t'] = serendipity_plugin_api::get_plugin_title($event_plugins[$plugin_data['name']]['p']);
+            } else {
+                unset($event_plugins[$plugin_data['name']]); // Unset failed plugins
+            }
+        }
+
+        if ($getInstance) {
+            if (isset($event_plugins[$getInstance]['p'])) {
+                return $event_plugins[$getInstance]['p'];
+            }
+            return false;
+        }
+
+        return $event_plugins;
+    }
+
+    function hook_event($event_name, &$eventData, $addData = null) {
+        global $serendipity;
+
+        // Can be bypassed globally by setting $serendipity['no_events'] = TRUE;
+        if (isset($serendipity['no_events']) && $serendipity['no_events'] == true) {
+            return false;
+        }
+        
+        $plugins = serendipity_plugin_api::get_event_plugins();
+        
+        if (is_array($plugins)) {
+            // foreach() operates on copies of values, but we want to operate on references, so we use while()
+            @reset($plugins);
+            while(list($plugin, $plugin_data) = each($plugins)) {
+                $bag = &$plugin_data['b'];
+                if (array_key_exists($event_name, $bag->get('event_hooks'))) {
+                    // Check for cachable events.
+                    if (isset($eventData['is_cached']) && $eventData['is_cached'] && array_key_exists($event_name, (array)$bag->get('cachable_events'))) {
+                        continue;
+                    }
+
+                    $plugin_data['p']->event_hook($event_name, $bag, $eventData, $addData);
+                }
+            }
+        }
+
+        return true;
+    }
+
+    function exists($instance_id) {
+        global $serendipity;
+
+        if (!strstr($instance_id, ':')) {
+            $instance_id .= ':';
+        }
+
+        $existing = serendipity_db_query("SELECT name FROM {$serendipity['dbPrefix']}plugins WHERE name LIKE '%$instance_id%'");
+
+        if (is_array($existing) && !empty($existing[0][0])) {
+            return $existing[0][0];
+        }
+
+        return false;
+    }
+
+    function &autodetect_instance($plugin_name, $authorid, $is_event_plugin = false) {
+        if ($is_event_plugin) {
+            $side = 'event';
+        } else {
+            $side = 'right';
+        }
+
+        $classes = serendipity_plugin_api::enum_plugin_classes(null);
+        if (isset($classes[$plugin_name])) {
+            return serendipity_plugin_api::create_plugin_instance($plugin_name, null, $side, $authorid, $classes[$plugin_name]['pluginPath']);
+        } else {
+            return false;
+        }
+    }
+}
+
+/* holds a bunch of properties; since serendipity 0.8 only one value per key is allowed [was never really useful] */
+class serendipity_property_bag {
+    var $properties = array();
+    var $name       = null;
+
+    function add($name, $value)
+    {
+        $this->properties[$name] = $value;
+    }
+
+    function &get($name)
+    {
+        return $this->properties[$name];
+    }
+
+    function is_set($name)
+    {
+        if (isset($this->properties[$name])) {
+            return true;
+        }
+
+        return false;
+    }
+}
+
+class serendipity_plugin {
+    var $instance      = null;
+    var $protected     = false;
+    var $wrap_class    = 'serendipitySideBarItem';
+    var $title_class   = 'serendipitySideBarTitle';
+    var $content_class = 'serendipitySideBarContent';
+    var $title         = null;
+
+    /* Be sure to call this method from your derived classes constructors,
+     * otherwise your config data will not be stored or retrieved correctly
+     */
+
+    function serendipity_plugin($instance)
+    {
+        $this->instance = $instance;
+    }
+
+    /* Called by Serendipity when the plugin is first installed.
+     * Can be used to install database tables etc.
+     */
+    function install()
+    {
+        return true;
+    }
+
+    /* Called by Serendipity when the plugin is removed/uninstalled.
+     * Can be used to drop installed database tables etc.
+     */
+    function uninstall(&$propbag)
+    {
+        return true;
+    }
+
+    /* Called by serendipity when it wants to display information
+     * about your plugin.
+     * You need to override this method in your child class.
+     */
+    function introspect(&$propbag)
+    {
+        $propbag->add('copyright', 'MIT License');
+        $propbag->add('name'     , get_class($this));
+
+        // $propbag->add(
+        //   'configuration',
+        //   array(
+        //     'text field',
+        //     'foo bar'
+        //   )
+        // );
+
+        $this->protected = FALSE; // If set to TRUE, only allows the owner of the plugin to modify its configuration
+
+        return true;
+    }
+
+    /* Called by serendipity when it wants to display the configuration
+     * editor for your plugin.
+     * $name is the name of a configuration item you added in
+     * your instrospect method.
+     * You need to fill the property bag with appropriate items
+     * that describe the type and value(s) for that particular
+     * configuration option.
+     * You need to override this method in your child class if
+     * you have configuration options.
+     */
+    function introspect_config_item($name, &$propbag)
+    {
+        return false;
+    }
+
+    /* Called by serendipity when it wants your plugin to display itself.
+     * You need to set $title to be whatever text you want want to
+     * appear in the item caption space.
+     * Simply echo/print your content to the output; serendipity will
+     * capture it and make things work.
+     * You need to override this method in your child class.
+     */
+    function generate_content(&$title)
+    {
+        $title = 'Sample!';
+        echo     'This is a sample!';
+    }
+
+    /* Fetches a configuration value for this plugin */
+    function get_config($name, $defaultvalue = null, $empty = true)
+    {
+        $_res = serendipity_get_config_var($this->instance . '/' . $name, $defaultvalue, $empty);
+
+        if (is_null($_res)) {
+            // A protected plugin by a specific owner may not have its values stored in $serendipity
+            // because of the special authorid. To display such contents, we need to fetch it
+            // seperately from the DB.
+            $_res = serendipity_get_user_config_var($this->instance . '/' . $name, null, $defaultvalue);
+        }
+
+        if (is_null($_res)) {
+            $cbag = new serendipity_property_bag;
+            $this->introspect_config_item($name, $cbag);
+            $_res = $cbag->get('default');
+            unset($cbag);
+        }
+
+        return $_res;
+    }
+
+    function set_config($name, $value)
+    {
+        $name = $this->instance . '/' . $name;
+
+        return serendipity_set_config_var($name, $value);
+    }
+
+    /* Called by serendipity after insertion of a config item. If you want to kick out certain
+     * elements based on contents, create the corresponding function here.
+     */
+    function cleanup()
+    {
+        // Cleanup. Remove all empty configs on SAVECONF-Submit.
+        // serendipity_plugin_api::remove_plugin_value($this->instance, array('title', 'description'));
+        return true;
+    }
+
+    function register_dependencies($remove = false, $authorid = '0')
+    {
+        global $serendipity;
+
+        if (isset($this->dependencies) && is_array($this->dependencies)) {
+
+            if ($remove) {
+                $dependencies = @explode(';', $this->get_config('dependencies'));
+                $modes        = @explode(';', $this->get_config('dependency_modes'));
+
+                if (!empty($dependencies) && is_array($dependencies)) {
+                    foreach($dependencies AS $idx => $dependency) {
+                        if ($modes[$idx] == 'remove' && serendipity_plugin_api::exists($dependency)) {
+                            serendipity_plugin_api::remove_plugin_instance($dependency);
+                        }
+                    }
+                }
+            } else {
+                $keys  = array();
+                $modes = array();
+                foreach($this->dependencies AS $dependency => $mode) {
+                    $exists = serendipity_plugin_api::exists($dependency);
+                    if (!$exists) {
+                        if (serendipity_plugin_api::is_event_plugin($dependency)) {
+                            $keys[] = serendipity_plugin_api::autodetect_instance($dependency, $authorid, true);
+                        } else {
+                            $keys[] = serendipity_plugin_api::autodetect_instance($dependency, $authorid, false);
+                        }
+                    } else {
+                        $keys[] = $exists;
+                    }
+
+                    $modes[] = $mode;
+                }
+
+                $this->set_config('dependencies',     implode(';', $keys));
+                $this->set_config('dependency_modes', implode(';', $modes));
+            }
+        }
+
+        return true;
+    }
+}
+
+class serendipity_event extends serendipity_plugin {
+    /* Events can be called on several occasions when s9y performs an action.
+     * One or multiple plugin can be registered for each of those hooks.
+     */
+
+    /* Be sure to call this method from your derived classes constructors,
+     * otherwise your config data will not be stored or retrieved correctly
+     */
+
+    function serendipity_event($instance)
+    {
+        $this->instance = $instance;
+    }
+
+    function &getFieldReference($fieldname = 'body', &$eventData) {
+        // Get a reference to a content field (body/extended) of
+        // $entries input data. This is a unifying function because
+        // several plugins are using similar fields.
+
+        if (is_array($eventData) && isset($eventData[0]) && is_array($eventData[0]['properties'])) {
+            if (!empty($eventData[0]['properties']['ep_cache_' . $fieldname])) {
+
+                // It may happen that there is no extended entry to concatenate to. In that case,
+                // create a dummy extended entry.
+                if (!isset($eventData[0]['properties']['ep_cache_' . $fieldname])) {
+                    $eventData[0]['properties']['ep_cache_' . $fieldname] = '';
+                }
+
+                $key = &$eventData[0]['properties']['ep_cache_' . $fieldname];
+            } else {
+                $key = &$eventData[0][$fieldname];
+            }
+        } elseif (is_array($eventData) && is_array($eventData['properties'])) {
+            if (!empty($eventData['properties']['ep_cache_' . $fieldname])) {
+                $key = &$eventData['properties']['ep_cache_' . $fieldname];
+            } else {
+                $key = &$eventData[$fieldname];
+            }
+        } elseif (isset($eventData[0][$fieldname])) {
+            $key = &$eventData[0][$fieldname];
+        } else {
+            $key = '';
+        }
+
+        return $key;
+    }
+
+    function event_hook($event, &$bag, &$eventData, $addData = null) {
+        // Define event hooks here, if you want you plugin to execute those instead of being a sidebar item.
+        // Look at external plugins 'serendipity_event_mailer' or 'serendipity_event_weblogping' for usage.
+        // Currently available events:
+        //   backend_publish [after insertion of a new article in your s9y-backend]
+        //   backend_display [after displaying an article in your s9y-backend]
+        //   frontend_display [before displaying an article in your s9y-frontend]
+        //   frontend_comment [after displaying the "enter comment" dialog]
+        return true;
+    }
+}
+
+include_once S9Y_INCLUDE_PATH . 'include/plugin_internal.inc.php';
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/plugin_internal.inc.php b/include/plugin_internal.inc.php
new file mode 100644 (file)
index 0000000..2c4ca7c
--- /dev/null
@@ -0,0 +1,1012 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+class serendipity_calendar_plugin extends serendipity_plugin {
+    var $title = CALENDAR;
+
+    function introspect(&$propbag)
+    {
+        $propbag->add('name',        CALENDAR);
+        $propbag->add('description', QUICKJUMP_CALENDAR);
+        $propbag->add('configuration', array('beginningOfWeek'));
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Serendipity Team');
+        $propbag->add('version',       '1.0');
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'beginningOfWeek':
+                $options = array();
+                for ( $i = 1; $i <= 7; $i++ ) {
+                    $options[] = serendipity_formatTime('%A', mktime(0,0,0,3,$i-1,2004));
+                }
+
+                $propbag->add('type',        'select');
+                $propbag->add('select_values', $options);
+                $propbag->add('name',        CALENDAR_BEGINNING_OF_WEEK);
+                $propbag->add('description', CALENDAR_BOW_DESC);
+                $propbag->add('default',     1);
+                break;
+
+            default:
+                return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title)
+    {
+        global $serendipity;
+
+        $title = $this->title;
+
+        // Usage of serendipity_serverOffsetHour is as follow:
+        // * Whenever a date to display needs to be set, apply the timezone offset
+        // * Whenever we USE the date anywhere in the database, subtract the timezone offset
+        // * Whenever we DISPLAY the date, we do not apply additional timezone addition to it.
+
+        if (!isset($serendipity['GET']['calendarZoom'])) {
+            if (!isset($serendipity['range'])) {
+                $serendipity['GET']['calendarZoom'] = serendipity_serverOffsetHour(time());
+            } else {
+                $serendipity['GET']['calendarZoom'] = serendipity_serverOffsetHour($serendipity['range'][0]);
+            }
+        }
+
+
+        $month = date('m', serendipity_serverOffsetHour($serendipity['GET']['calendarZoom'], true));
+        $year  = date('Y', serendipity_serverOffsetHour($serendipity['GET']['calendarZoom'], true));
+
+        $bow = (int)$this->get_config('beginningOfWeek', 1);
+        // Check for faulty input, is so - run the default
+        if ($bow > 6) {
+            $bow = 1;
+        }
+
+        // Catch faulty month
+        $month = (int)$month;
+        if ($month < 1) {
+            $month = 1;
+        }
+
+        // How many days does the month have?
+        $ts              = strtotime($year . '-' . sprintf('%02d', $month) . '-01');
+        $now             = serendipity_serverOffsetHour(time(), true);
+        $nrOfDays        = date('t', $ts);
+        $firstDayWeekDay = date('w', $ts);
+
+        // Calculate the first day of the week, based on the beginning of the week ($bow)
+        if ($bow > $firstDayWeekDay) {
+            $firstDayWeekDay = $firstDayWeekDay + 7 - $bow;
+        } elseif ( $bow < $firstDayWeekDay ) {
+            $firstDayWeekDay = $firstDayWeekDay - $bow;
+        } else {
+            $firstDayWeekDay = 0;
+        }
+
+        // Calculate the number of next/previous month
+        if ($month > 1) {
+            $previousMonth = $month-1;
+            $previousYear  = $year;
+        } else {
+            $previousMonth = 12;
+            $previousYear  = $year-1;
+        }
+
+        if ($month < 12) {
+            $nextMonth = $month+1;
+            $nextYear  = $year;
+        } else {
+            $nextMonth = 1;
+            $nextYear  = $year+1;
+        }
+
+        $endts = mktime(0, 0, 0, $month + 1, 1, $year);
+
+        // Get first and last entry
+        $minmax = serendipity_db_query("SELECT MAX(timestamp) AS max, MIN(timestamp) AS min FROM {$serendipity['dbPrefix']}entries");
+        if (!is_array($minmax) || !is_array($minmax[0]) || $minmax[0]['min'] < 1 || $minmax[0]['max'] < 1) {
+            // If no entry is available yet, allow scrolling a year back and forth
+            $minmax = array(
+                        '0' => array(
+                                 'min' => mktime(0, 0, 0, 1, 1, date('Y', $now) - 1),
+                                 'max' => mktime(0, 0, 0, 1, 1, date('Y', $now) + 1)
+                               )
+                            );
+        }
+
+        // Find out about diary entries
+        $add_query   = '';
+        $base_query  = '';
+        $cond = array();
+        $cond['and']     = "WHERE e.timestamp  >= " . serendipity_serverOffsetHour($ts, true) . "
+                              AND e.timestamp  <= " . serendipity_serverOffsetHour($endts, true) . "
+                                  " . (!serendipity_db_bool($serendipity['showFutureEntries']) ? " AND e.timestamp  <= " . time() : '') . "
+                              AND e.isdraft     = 'false'";
+
+        serendipity_plugin_api::hook_event('frontend_fetchentries', $cond, array('noCache' => false, 'noSticky' => false));
+
+        if (isset($serendipity['GET']['category'])) {
+            $categoryid  = serendipity_db_escape_string($serendipity['GET']['category']);
+
+            if (is_numeric($categoryid)) {
+                $base_query   = 'C' . $categoryid;
+                $add_query    = '/' . $base_query;
+                $querystring = "SELECT timestamp
+                                  FROM {$serendipity['dbPrefix']}category c,
+                                       {$serendipity['dbPrefix']}entrycat ec,
+                                       {$serendipity['dbPrefix']}entries e
+                                       {$cond['joins']}
+                                       {$cond['and']}
+                                   AND e.id          = ec.entryid
+                                   AND c.categoryid  = ec.categoryid
+                                   AND c.category_left BETWEEN " . implode(' AND ', serendipity_fetchCategoryRange($categoryid));
+            }
+        }
+
+        if (!isset($querystring)) {
+            $querystring = "SELECT id, timestamp
+                              FROM {$serendipity['dbPrefix']}entries e
+                              {$cond['joins']}
+                              {$cond['and']}";
+        }
+
+        $rows = serendipity_db_query($querystring);
+
+        $activeDays = array();
+        if (is_array($rows)) {
+            foreach ($rows as $row) {
+                $row['timestamp'] = serendipity_serverOffsetHour($row['timestamp']);
+                $activeDays[date('j', $row['timestamp'])] = $row['timestamp'];
+            }
+        }
+
+        // Print the calendar
+        $currDay     = 1;
+        $nrOfRows    = ceil(($nrOfDays+$firstDayWeekDay)/7);
+        $today_day   = date('j', $now);
+        $today_month = date('m', $now);
+        $today_year  = date('Y', $now);
+        for ($x = 0; $x < 6; $x++) {
+            // Break out if we are out of days
+            if ($currDay > $nrOfDays) {
+                break;
+            }
+            // Prepare row
+            for ($y = 0; $y < 7; $y++) {
+                $cellProps = array();
+                $printDay = '';
+                $link = '';
+
+                if ($x == 0) {
+                    $cellProps['FirstRow'] = 1;
+                }
+                if ($y == 0) {
+                    $cellProps['FirstInRow'] = 1;
+                }
+                if ($y == 6) {
+                    $cellProps['LastInRow'] = 1;
+                }
+                if ($x == $nrOfRows-1) {
+                    $cellProps['LastRow'] = 1;
+                }
+
+                // If it's not a blank day, we print the day
+                if (($x > 0 || $y >= $firstDayWeekDay) && $currDay <= $nrOfDays) {
+                    $printDay = $currDay;
+                    if ($today_year == $year && $today_month == $month && $today_day == $currDay) {
+                        $cellProps['Today'] = 1;
+                    }
+                    if (isset($activeDays[$currDay]) && $activeDays[$currDay] > 1) {
+                        $cellProps['Active'] = 1;
+                        $cellProps['Link']   = serendipity_archiveDateUrl(sprintf('%4d/%02d/%02d', $year, $month, $currDay) . $add_query );
+                    }
+                    $currDay++;
+                }
+                $smartyRows[$x]['days'][] = array('name' => $printDay,
+                                                  'properties' => $cellProps,
+                                                  'classes' => implode(' ', array_keys($cellProps)));
+            } // end for
+        } // end for
+
+        $serendipity['smarty']->assign('plugin_calendar_weeks', $smartyRows);
+
+
+        $dow = array();
+        for ($i = 1; $i <= 7; $i++) {
+            $dow[] = array('date' => mktime(0, 0, 0, 3, $bow + $i - 1, 2004));
+        }
+        $serendipity['smarty']->assign('plugin_calendar_dow', $dow);
+
+        $serendipity['smarty']->assign('plugin_calendar_head', array('month_date'   => $ts,
+                                                                     'uri_previous' => serendipity_archiveDateUrl(sprintf('%04d/%02d', $previousYear, $previousMonth). $add_query),
+                                                                     'uri_month'    => serendipity_archiveDateUrl(sprintf('%04d/%02d', $year, $month)),
+                                                                     'uri_next'     => serendipity_archiveDateUrl(sprintf('%04d/%02d',$nextYear, $nextMonth) . $add_query),
+                                                                     'minScroll'    => $minmax[0]['min'],
+                                                                     'maxScroll'    => $minmax[0]['max']));
+        echo serendipity_smarty_fetch('CALENDAR', 'plugin_calendar.tpl');
+    } // end function
+} // end class
+
+class serendipity_quicksearch_plugin extends serendipity_plugin {
+    var $title = QUICKSEARCH;
+
+    function introspect(&$propbag)
+    {
+        $propbag->add('name',          QUICKSEARCH);
+        $propbag->add('description',   SEARCH_FOR_ENTRY);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Serendipity Team');
+        $propbag->add('version',       '1.0');
+    }
+
+    function generate_content(&$title)
+    {
+        global $serendipity;
+
+        $title = $this->title;
+?>
+<form id="searchform" action="<?php echo $serendipity['serendipityHTTPPath'] . $serendipity['indexFile']; ?>" method="get">
+    <div>
+        <input type="hidden"  name="serendipity[action]" value="search" />
+        <input alt="<?php echo QUICKSEARCH; ?>" type="text"   id="serendipityQuickSearchTermField" name="serendipity[searchTerm]" size="13" />
+    </div>
+    <div id="LSResult" style="display: none;"><div id="LSShadow"></div></div>
+</form>
+<?php
+        serendipity_plugin_api::hook_event('quicksearch_plugin', $serendipity);
+    }
+}
+
+class serendipity_archives_plugin extends serendipity_plugin {
+    var $title = ARCHIVES;
+
+    function introspect(&$propbag)
+    {
+        $propbag->add('name',          ARCHIVES);
+        $propbag->add('description',   BROWSE_ARCHIVES);
+        $propbag->add('stackable',     true);
+        $propbag->add('author',        'Serendipity Team');
+        $propbag->add('version',       '1.0');
+        $propbag->add('configuration', array('frequency', 'count'));
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'count' :
+                $propbag->add('type', 'string');
+                $propbag->add('name', ARCHIVE_COUNT);
+                $propbag->add('description', ARCHIVE_COUNT_DESC);
+                $propbag->add('default', 3);
+                break;
+
+            case 'frequency' :
+                $propbag->add('type', 'select');
+                $propbag->add('name', ARCHIVE_FREQUENCY);
+                $propbag->add('select_values', array('months' => MONTHS, 'weeks' => WEEKS, 'days' => DAYS));
+                $propbag->add('description', ARCHIVE_FREQUENCY_DESC);
+                $propbag->add('default', 'months');
+                break;
+            default:
+                return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title)
+    {
+        global $serendipity;
+
+        $title = $this->title;
+
+        $ts = mktime(0, 0, 0);
+
+        for($x = 0; $x < $this->get_config('count', 3); $x++) {
+
+            switch($this->get_config('frequency', 'months')) {
+                case 'months' :
+                    $linkStamp = date('Y/m', $ts);
+                    $ts_title = serendipity_formatTime("%B %Y", $ts, false);
+                    $ts = mktime(0, 0, 0, date('m', $ts)-1, 1, date('Y', $ts)); // Must be last in 'case' statement
+                    break;
+                case 'weeks' :
+                    $linkStamp = date('Y/\WW', $ts);
+                    $ts_title = WEEK . ' '. date('W, Y', $ts);
+                    $ts = mktime(0, 0, 0, date('m', $ts), date('d', $ts)-7, date('Y', $ts));
+                    break;
+                case 'days' :
+                    $linkStamp = date('Y/m/d', $ts);
+                    $ts_title = serendipity_formatTime("%B %e. %Y", $ts, false);
+                    $ts = mktime(0, 0, 0, date('m', $ts), date('d', $ts)-1, date('Y', $ts)); // Must be last in 'case' statement
+                    break;
+            }
+            $link = serendipity_rewriteURL(PATH_ARCHIVES.'/' . $linkStamp . '.html', 'serendipityHTTPPath');
+
+            echo '<a href="' . $link . '" title="' . $ts_title . '">' . $ts_title . '</a><br />' . "\n";
+
+        }
+
+        echo '<a href="'. $serendipity['serendipityHTTPPath'] .'">' . RECENT . '</a><br />' . "\n";
+        echo '<a href="'. serendipity_rewriteURL(PATH_ARCHIVE) .'">' . OLDER . '</a>'. "\n";
+    }
+}
+
+class serendipity_topreferrers_plugin extends serendipity_plugin {
+    var $title = TOP_REFERRER;
+
+    function introspect(&$propbag)
+    {
+        $propbag->add('name',          TOP_REFERRER);
+        $propbag->add('description',   SHOWS_TOP_SITES);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Serendipity Team');
+        $propbag->add('version',       '1.0');
+        $propbag->add('configuration', array('limit', 'use_links'));
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'limit':
+                $propbag->add('type',        'string');
+                $propbag->add('name',        LIMIT_TO_NUMBER);
+                $propbag->add('description', LIMIT_TO_NUMBER);
+                $propbag->add('default',     10);
+                break;
+
+            case 'use_links':
+                $propbag->add('type',        'tristate');
+                $propbag->add('name',        INSTALL_TOP_AS_LINKS);
+                $propbag->add('description', INSTALL_TOP_AS_LINKS_DESC);
+                $propbag->add('default',     false);
+                break;
+
+            default:
+                return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title)
+    {
+        global $serendipity;
+
+        $title = $this->title;
+
+        // get local configuration (default, true, false)
+        $use_links = $this->get_config('use_links', 'default');
+        // get global configuration (true, false)
+        $global_use_link = serendipity_get_config_var('top_as_links', false, true);
+
+        // if local configuration say to use global default, do so
+        if ($use_links == 'default') {
+            $use_links = serendipity_db_bool($global_use_link);
+        } else {
+            $use_links = serendipity_db_bool($use_links);
+        }
+
+        echo serendipity_displayTopReferrers($this->get_config('limit', 10), $use_links);
+    }
+}
+
+class serendipity_topexits_plugin extends serendipity_plugin {
+    var $title = TOP_EXITS;
+
+    function introspect(&$propbag)
+    {
+        $propbag->add('name',          TOP_EXITS);
+        $propbag->add('description',   SHOWS_TOP_EXIT);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Serendipity Team');
+        $propbag->add('version',       '1.0');
+        $propbag->add('configuration', array('limit', 'use_links'));
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'limit':
+                $propbag->add('type',        'string');
+                $propbag->add('name',        LIMIT_TO_NUMBER);
+                $propbag->add('description', LIMIT_TO_NUMBER);
+                $propbag->add('default',     10);
+                break;
+
+            case 'use_links':
+                $propbag->add('type',        'tristate');
+                $propbag->add('name',        INSTALL_TOP_AS_LINKS);
+                $propbag->add('description', INSTALL_TOP_AS_LINKS_DESC);
+                $propbag->add('default',     true);
+                break;
+
+            default:
+                return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title)
+    {
+        global $serendipity;
+
+        $title = $this->title;
+
+        // get local configuration (default, true, false)
+        $use_links = $this->get_config('use_links', 'default');
+        // get global configuration (true, false)
+        $global_use_link = serendipity_get_config_var('top_as_links', false, true);
+
+        // if local configuration say to use global default, do so
+        if ($use_links == 'default') {
+            $use_links = serendipity_db_bool($global_use_link);
+        } else {
+            $use_links = serendipity_db_bool($use_links);
+        }
+
+        echo serendipity_displayTopExits($this->get_config('limit', 10), $use_links);
+    }
+}
+
+class serendipity_syndication_plugin extends serendipity_plugin {
+    var $title = SYNDICATE_THIS_BLOG;
+
+    function introspect(&$propbag)
+    {
+        $propbag->add('name',          SYNDICATION);
+        $propbag->add('description',   SHOWS_RSS_BLAHBLAH);
+        $propbag->add('stackable',     true);
+        $propbag->add('author',        'Serendipity Team');
+        $propbag->add('version',       '1.0');
+        $propbag->add('configuration', array(
+                                        'fullfeed',
+                                        'show_0.91',
+                                        'show_1.0',
+                                        'show_2.0',
+                                        'show_2.0c',
+                                        'show_atom0.3',
+                                        'show_opml1.0',
+                                        'seperator',
+                                        'show_mail',
+                                        'field_managingEditor',
+                                        'field_webMaster',
+                                        'field_ttl',
+                                        'field_pubDate',
+                                        'seperator',
+                                        'bannerURL',
+                                        'bannerWidth',
+                                        'bannerHeight',
+                                       )
+        );
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'fullfeed':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        SYNDICATION_PLUGIN_FULLFEED);
+                $propbag->add('description', '');
+                $propbag->add('default',     false);
+                break;
+
+            case 'show_0.91':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        SYNDICATION_PLUGIN_091);
+                $propbag->add('description', '');
+                $propbag->add('default',     'true');
+                break;
+
+            case 'show_1.0':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        SYNDICATION_PLUGIN_10);
+                $propbag->add('description', '');
+                $propbag->add('default',     'true');
+                break;
+
+            case 'show_2.0':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        SYNDICATION_PLUGIN_20);
+                $propbag->add('description', '');
+                $propbag->add('default',     'true');
+                break;
+
+            case 'show_2.0c':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        SYNDICATION_PLUGIN_20c);
+                $propbag->add('description', '');
+                $propbag->add('default',     'true');
+                break;
+
+            case 'show_atom0.3':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        SYNDICATION_PLUGIN_ATOM03);
+                $propbag->add('description', '');
+                $propbag->add('default',     'true');
+                break;
+
+            case 'show_opml1.0':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        sprintf(SYNDICATION_PLUGIN_GENERIC_FEED, 'OPML 1.0'));
+                $propbag->add('description', '');
+                $propbag->add('default',     'false');
+                break;
+
+            case 'seperator':
+                $propbag->add('type',        'seperator');
+                break;
+
+            case 'show_mail':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        SYNDICATION_PLUGIN_SHOW_MAIL);
+                $propbag->add('description', '');
+                $propbag->add('default',     'true');
+                break;
+
+            case 'field_managingEditor':
+                $propbag->add('type',        'string');
+                $propbag->add('name',        SYNDICATION_PLUGIN_MANAGINGEDITOR);
+                $propbag->add('description', SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC);
+                $propbag->add('default',     '');
+                break;
+
+            case 'field_webMaster':
+                $propbag->add('type',        'string');
+                $propbag->add('name',        SYNDICATION_PLUGIN_WEBMASTER);
+                $propbag->add('description', SYNDICATION_PLUGIN_WEBMASTER_DESC);
+                $propbag->add('default',     '');
+                break;
+
+            case 'field_ttl':
+                $propbag->add('type',        'string');
+                $propbag->add('name',        SYNDICATION_PLUGIN_TTL);
+                $propbag->add('description', SYNDICATION_PLUGIN_TTL_DESC);
+                $propbag->add('default',     '');
+                break;
+
+            case 'field_pubDate':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        SYNDICATION_PLUGIN_PUBDATE);
+                $propbag->add('description', SYNDICATION_PLUGIN_PUBDATE_DESC);
+                $propbag->add('default',     '');
+                break;
+
+            case 'bannerURL':
+                $propbag->add('type',        'string');
+                $propbag->add('name',        SYNDICATION_PLUGIN_BANNERURL);
+                $propbag->add('description', SYNDICATION_PLUGIN_BANNERURL_DESC);
+                $propbag->add('default',     '');
+                break;
+
+            case 'bannerWidth':
+                $propbag->add('type',        'string');
+                $propbag->add('name',        SYNDICATION_PLUGIN_BANNERWIDTH);
+                $propbag->add('description', SYNDICATION_PLUGIN_BANNERWIDTH_DESC);
+                $propbag->add('default',     '');
+                break;
+
+            case 'bannerHeight':
+                $propbag->add('type',        'string');
+                $propbag->add('name',        SYNDICATION_PLUGIN_BANNERHEIGHT);
+                $propbag->add('description', SYNDICATION_PLUGIN_BANNERHEIGHT_DESC);
+                $propbag->add('default',     '');
+                break;
+
+            default:
+                return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title)
+    {
+        global $serendipity;
+
+        $title = $this->title;
+
+        if (serendipity_db_bool($this->get_config('show_0.91', true))) {
+?>
+        <div style="padding-bottom: 2px;">
+            <a href="<?php echo serendipity_rewriteURL(PATH_FEEDS .'/index.rss', 'serendipityHTTPPath') ?>"><img src="<?php echo serendipity_getTemplateFile('img/xml.gif'); ?>" alt="XML" style="border: 0px" /></a>
+            <a href="<?php echo serendipity_rewriteURL(PATH_FEEDS .'/index.rss', 'serendipityHTTPPath') ?>">RSS 0.91 feed</a>
+        </div>
+<?php
+        }
+
+        if (serendipity_db_bool($this->get_config('show_1.0', true))) {
+?>
+        <div style="padding-bottom: 2px;">
+            <a href="<?php echo serendipity_rewriteURL(PATH_FEEDS .'/index.rss1', 'serendipityHTTPPath') ?>"><img src="<?php echo serendipity_getTemplateFile('img/xml.gif'); ?>" alt="XML" style="border: 0px" /></a>
+            <a href="<?php echo serendipity_rewriteURL(PATH_FEEDS .'/index.rss1', 'serendipityHTTPPath') ?>">RSS 1.0 feed</a>
+        </div>
+<?php
+        }
+
+        if (serendipity_db_bool($this->get_config('show_2.0', true))) {
+?>
+        <div style="padding-bottom: 2px;">
+            <a href="<?php echo serendipity_rewriteURL(PATH_FEEDS .'/index.rss2', 'serendipityHTTPPath') ?>"><img src="<?php echo serendipity_getTemplateFile('img/xml.gif'); ?>" alt="XML" style="border: 0px" /></a>
+            <a href="<?php echo serendipity_rewriteURL(PATH_FEEDS .'/index.rss2', 'serendipityHTTPPath') ?>">RSS 2.0 feed</a>
+        </div>
+<?php
+        }
+
+        if (serendipity_db_bool($this->get_config('show_atom0.3', true))) {
+?>
+        <div style="padding-bottom: 2px;">
+            <a href="<?php echo serendipity_rewriteURL(PATH_FEEDS .'/atom.xml', 'serendipityHTTPPath') ?>"><img src="<?php echo serendipity_getTemplateFile('img/xml.gif'); ?>" alt="ATOM/XML" style="border: 0px" /></a>
+            <a href="<?php echo serendipity_rewriteURL(PATH_FEEDS .'/atom.xml', 'serendipityHTTPPath') ?>">ATOM 0.3 feed</a>
+        </div>
+<?php
+        }
+
+        if (serendipity_db_bool($this->get_config('show_2.0c', true))) {
+?>
+        <div style="padding-bottom: 2px;">
+            <a href="<?php echo serendipity_rewriteURL(PATH_FEEDS .'/comments.rss2', 'serendipityHTTPPath') ?>"><img src="<?php echo serendipity_getTemplateFile('img/xml.gif'); ?>" alt="XML" style="border: 0px" /></a>
+            <a href="<?php echo serendipity_rewriteURL(PATH_FEEDS .'/comments.rss2', 'serendipityHTTPPath') ?>"><?php echo ($serendipity['XHTML11'] ? '<span style="white-space: nowrap">' : '<nobr>'); ?>RSS 2.0 <?php echo COMMENTS; ?><?php echo ($serendipity['XHTML11'] ? '</span>' : '</nobr>'); ?></a>
+        </div>
+<?php
+        }
+
+        if (serendipity_db_bool($this->get_config('show_opml1.0', false))) {
+?>
+        <div style="padding-bottom: 2px;">
+            <a href="<?php echo serendipity_rewriteURL(PATH_FEEDS .'/opml.xml', 'serendipityHTTPPath') ?>"><img src="<?php echo serendipity_getTemplateFile('img/xml.gif'); ?>" alt="XML" style="border: 0px" /></a>
+            <a href="<?php echo serendipity_rewriteURL(PATH_FEEDS .'/opml.xml', 'serendipityHTTPPath') ?>">OPML 1.0 feed</a>
+        </div>
+<?php
+        }
+    }
+
+    function generate_rss_fields(&$title, &$description, &$entries) {
+        global $serendipity;
+        // Check for a logo to use for an RSS feed. Can either be set by configuring the
+        // syndication plugin OR by just placing a rss_banner.png file in the template directory.
+        // If both is not set, we will display our happy own branding. :-)
+
+        $bag    = new serendipity_property_bag;
+        $this->introspect($bag);
+        $additional_fields = array();
+
+        if ($this->get_config('bannerURL') != '') {
+            $img   = $this->get_config('bannerURL');
+            $w     = $this->get_config('bannerWidth');
+            $h     = $this->get_config('bannerHeight');
+        } elseif (($banner = serendipity_getTemplateFile('img/rss_banner.png', 'serendipityPath'))) {
+            $img = serendipity_getTemplateFile('img/rss_banner.png', 'baseURL');
+            $i = getimagesize($banner);
+            $w = $i[0];
+            $h = $i[1];
+        } else {
+            $img = serendipity_getTemplateFile('img/s9y_banner_small.png', 'baseURL');
+            $w = 100;
+            $h = 21;
+        }
+
+        $additional_fields['image'] = <<<IMAGE
+<image>
+        <url>$img</url>
+        <title>RSS: $title - $description</title>
+        <link>{$serendipity['baseURL']}</link>
+        <width>$w</width>
+        <height>$h</height>
+    </image>
+IMAGE;
+
+        $additional_fields['image_rss1.0_channel'] = '<image rdf:resource="' . $img . '" />';
+        $additional_fields['image_rss1.0_rdf'] = <<<IMAGE
+<image rdf:about="$img">
+        <url>$img</url>
+        <title>RSS: $title - $description</title>
+        <link>{$serendipity['baseURL']}</link>
+        <width>$w</width>
+        <height>$h</height>
+    </image>
+IMAGE;
+
+        // Now, if set, stitch together any fields that have been configured in the syndication plugin.
+        // First, do some sanity checks
+        $additional_fields['channel'] = '';
+        foreach($bag->get('configuration') AS $bag_index => $bag_value) {
+            if (preg_match('|^field_(.*)$|', $bag_value, $match)) {
+                $bag_content = $this->get_config($bag_value);
+
+                switch($match[1]) {
+                    case 'pubDate':
+                        if ($bag_content != 'false') {
+                            $bag_content = gmdate('D, d M Y H:i:s \G\M\T', serendipity_serverOffsetHour($entries[0]['last_modified']));
+                        } else {
+                            $bag_content = '';
+                        }
+                        break;
+
+                    // Each new RSS-field which needs rewrite of its content should get its own case here.
+
+                    default:
+                        break;
+                }
+
+                if ($bag_content != '') {
+                    $additional_fields['channel'] .= '<' . $match[1] . '>' . $bag_content . '</' . $match[1] . '>' . "\n";
+                }
+
+            }
+        }
+
+        return $additional_fields;
+    }
+}
+
+class serendipity_superuser_plugin extends serendipity_plugin {
+    var $title = SUPERUSER;
+
+    function introspect(&$propbag)
+    {
+        $propbag->add('name',          SUPERUSER);
+        $propbag->add('description',   ALLOWS_YOU_BLAHBLAH);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Serendipity Team');
+        $propbag->add('version',       '1.0');
+        $propbag->add('configuration', array('https'));
+    }
+
+    function generate_content(&$title)
+    {
+        global $serendipity;
+
+        $title = $this->title;
+        if ($this->get_config('https', 'false') == 'true') {
+            $base = str_replace('http://', 'https://', $serendipity['baseURL']);
+        } else {
+            $base = $serendipity['serendipityHTTPPath'];
+        }
+
+        $link = $base . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] .'?/' : '') . PATH_ADMIN;
+        $text = (($_SESSION['serendipityAuthedUser'] === true) ? SUPERUSER_OPEN_ADMIN : SUPERUSER_OPEN_LOGIN);
+        echo '<a href="' . $link . '" title="'. $text .'">'. $text .'</a>';
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'https':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        PLUGIN_SUPERUSER_HTTPS);
+                $propbag->add('description', PLUGIN_SUPERUSER_HTTPS_DESC);
+                $propbag->add('default',     'false');
+                break;
+
+            default:
+                return false;
+        }
+        return true;
+    }
+}
+
+class serendipity_plug_plugin extends serendipity_plugin {
+    var $title = POWERED_BY;
+
+    function introspect(&$propbag)
+    {
+        $propbag->add('name',          POWERED_BY);
+        $propbag->add('description',   ADVERTISES_BLAHBLAH);
+        $propbag->add('stackable',     true);
+        $propbag->add('author',        'Serendipity Team');
+        $propbag->add('version',       '1.0');
+        $propbag->add('configuration', array(
+                                        'image',
+                                        'text'));
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'image':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        POWERED_BY_SHOW_IMAGE);
+                $propbag->add('description', POWERED_BY_SHOW_IMAGE_DESC);
+                $propbag->add('default',     'true');
+                break;
+
+            case 'text':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        POWERED_BY_SHOW_TEXT);
+                $propbag->add('description', POWERED_BY_SHOW_TEXT_DESC);
+                $propbag->add('default',     'false');
+                break;
+            default:
+                return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title)
+    {
+        global $serendipity;
+
+        $title = $this->title;
+?>
+<div class="serendipityPlug">
+<?php if ( $this->get_config('image', 'true') == 'true' ) { ?>
+    <a title="<?php echo $title ?> Serendipity" href="http://www.s9y.org/"><img src="<?php echo serendipity_getTemplateFile('img/s9y_banner_small.png') ?>" alt="Serendipity PHP Weblog" style="border: 0px" /></a>
+<?php } ?>
+<?php if ( $this->get_config('text', 'false') == 'true' ) { ?>
+    <div>
+        <a title="<?php echo $title ?> Serendipity" href="http://www.s9y.org/">Serendipity PHP Weblog</a>
+    </div>
+<?php } ?>
+</div>
+<?php
+    }
+}
+
+class serendipity_html_nugget_plugin extends serendipity_plugin {
+    var $title = HTML_NUGGET;
+
+    function introspect(&$propbag)
+    {
+        $this->title = $this->get_config('title', $this->title);
+        $propbag->add('name',          HTML_NUGGET);
+        $propbag->add('description',   HOLDS_A_BLAHBLAH);
+        $propbag->add('stackable',     true);
+        $propbag->add('author',        'Serendipity Team');
+        $propbag->add('version',       '1.0');
+        $propbag->add('configuration', array(
+                                        'title',
+                                        'content',
+                                        'markup',
+                                        'show_where'
+                                       )
+        );
+
+        $this->protected = TRUE; // If set to TRUE, only allows the owner of the plugin to modify its configuration
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'title':
+                $propbag->add('type',        'string');
+                $propbag->add('name',        TITLE);
+                $propbag->add('description', TITLE_FOR_NUGGET);
+                $propbag->add('default',     '');
+                break;
+
+            case 'content':
+                $propbag->add('type',        'html');
+                $propbag->add('name',        CONTENT);
+                $propbag->add('description', THE_NUGGET);
+                $propbag->add('default',     '');
+                break;
+
+            case 'markup':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        DO_MARKUP);
+                $propbag->add('description', DO_MARKUP_DESCRIPTION);
+                $propbag->add('default',     'true');
+                break;
+
+            case 'show_where':
+                $select = array('extended' => PLUGIN_ITEM_DISPLAY_EXTENDED, 'overview' => PLUGIN_ITEM_DISPLAY_OVERVIEW, 'both' => PLUGIN_ITEM_DISPLAY_BOTH);
+                $propbag->add('type',        'select');
+                $propbag->add('select_values', $select);
+                $propbag->add('name',        PLUGIN_ITEM_DISPLAY);
+                $propbag->add('description', '');
+                $propbag->add('default',     'both');
+                break;
+
+            default:
+                return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title)
+    {
+        global $serendipity;
+
+        $title = $this->get_config('title');
+        $show_where = $this->get_config('show_where', 'both');
+
+        if ($show_where == 'extended' && (!isset($serendipity['GET']['id']) || !is_numeric($serendipity['GET']['id']))) {
+            return false;
+        } else if ($show_where == 'overview' && isset($serendipity['GET']['id']) && is_numeric($serendipity['GET']['id'])) {
+            return false;
+        }
+
+        if ($this->get_config('markup', 'true') == 'true') {
+            $entry = array('html_nugget' => $this->get_config('content'));
+            serendipity_plugin_api::hook_event('frontend_display', $entry);
+            echo $entry['html_nugget'];
+        } else {
+            echo $this->get_config('content');
+        }
+    }
+}
+
+class serendipity_categories_plugin extends serendipity_plugin {
+    var $title = CATEGORIES;
+
+    function introspect(&$propbag) {
+        global $serendipity;
+
+        $propbag->add('name',        CATEGORIES);
+        $propbag->add('description', CATEGORY_PLUGIN_DESC);
+        $propbag->add('stackable',     true);
+        $propbag->add('author',        'Serendipity Team');
+        $propbag->add('version',       '1.0');
+        $propbag->add('configuration', array('authorid', 'image'));
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        global $serendipity;
+        switch($name) {
+            case 'authorid':
+                $row_authors = serendipity_db_query("SELECT realname, authorid FROM {$serendipity['dbPrefix']}authors");
+                $authors     = array('all' => ALL_AUTHORS);
+                if (is_array($row_authors)) {
+                    foreach($row_authors as $row) {
+                        $authors[$row['authorid']] = $row['realname'];
+                    }
+                }
+
+                $propbag->add('type',         'select');
+                $propbag->add('name',         CATEGORIES_TO_FETCH);
+                $propbag->add('description',  CATEGORIES_TO_FETCH_DESC);
+                $propbag->add('select_values', $authors);
+                $propbag->add('default',     'all');
+                break;
+
+            case 'image':
+                $propbag->add('type',         'string');
+                $propbag->add('name',         XML_IMAGE_TO_DISPLAY);
+                $propbag->add('description',  XML_IMAGE_TO_DISPLAY_DESC);
+                $propbag->add('default',     serendipity_getTemplateFile('img/xml.gif'));
+                break;
+
+            default:
+                return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title) {
+        global $serendipity;
+
+        $which_category = $this->get_config('authorid');
+        $categories = serendipity_fetchCategories(empty($which_category) ? 'all' : $which_category);
+        $title = $this->title;
+        $html       = '';
+        $image = $this->get_config('image', serendipity_getTemplateFile('img/xml.gif'));
+        $image = (($image == "'none'" || $image == 'none') ? '' : $image);
+        if (is_array($categories) && count($categories)) {
+            $categories = serendipity_walkRecursive($categories, 'categoryid', 'parentid', VIEWMODE_THREADED);
+            foreach ( $categories as $cat ) {
+                $html .= '<div style="padding-bottom: 2px;">';
+                if ( !empty($image) ) {
+                    $html .= '<a href="'. serendipity_rewriteURL(PATH_FEEDS .'/'. PATH_CATEGORIES .'/'. serendipity_makePermalink(PERM_FEEDS_CATEGORIES, array('id' => $cat['categoryid'], 'title' => $cat['category_name']))) .'"><img src="'. $image .'" alt="XML" style="border: 0px" /></a> ';
+                }
+                $html .= '<a href="'. serendipity_rewriteURL(PATH_CATEGORIES . '/' . serendipity_makePermalink(PERM_CATEGORIES, array('id' => $cat['categoryid'], 'title' => $cat['category_name'])), 'serendipityHTTPPath') .'" title="'. $cat['category_name'] .'" style="padding-left: '. $cat['depth']*6 .'px">'. $cat['category_name'] .'</a>';
+                $html .= '</div>' . "\n";
+            }
+        }
+
+        $html .= sprintf(
+            '<br /><a href="%s" title="%s">%s</a>',
+
+            $serendipity['serendipityHTTPPath'] . $serendipity['indexFile'],
+            ALL_CATEGORIES,
+            ALL_CATEGORIES
+        );
+
+        print $html;
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/include/tpl/config_local.inc.php b/include/tpl/config_local.inc.php
new file mode 100644 (file)
index 0000000..b10878f
--- /dev/null
@@ -0,0 +1,297 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+    // Here be dragons and NO application logic!
+
+    $res = array();
+    $res['database'] =
+             array('title'       => INSTALL_CAT_DB,
+                   'description' => INSTALL_CAT_DB_DESC,
+                   'items' => array(array('var'         => 'dbType',
+                                          'title'       => INSTALL_DBTYPE,
+                                          'description' => INSTALL_DBTYPE_DESC,
+                                          'type'        => 'list',
+                                          'default'     => array(),
+                                          'flags'       => array('nosave', 'simpleInstall', 'probeDefault')),
+
+                                    array('var'         => 'dbHost',
+                                          'title'       => INSTALL_DBHOST,
+                                          'description' => INSTALL_DBHOST_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'localhost',
+                                          'flags'       => array('nosave', 'simpleInstall')),
+
+                                    array('var'         => 'dbUser',
+                                          'title'       => INSTALL_DBUSER,
+                                          'description' => INSTALL_DBUSER_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'serendipity',
+                                          'flags'       => array('nosave', 'simpleInstall')),
+
+                                    array('var'         => 'dbPass',
+                                          'title'       => INSTALL_DBPASS,
+                                          'description' => INSTALL_DBPASS_DESC,
+                                          'type'        => 'protected',
+                                          'default'     => '',
+                                          'flags'       => array('nosave', 'hideValue', 'simpleInstall')),
+
+                                    array('var'         => 'dbName',
+                                          'title'       => INSTALL_DBNAME,
+                                          'description' => INSTALL_DBNAME_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'serendipity',
+                                          'flags'       => array('nosave', 'simpleInstall')),
+
+                                    array('var'         => 'dbPrefix',
+                                          'title'       => INSTALL_DBPREFIX,
+                                          'description' => INSTALL_DBPREFIX_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'serendipity_',
+                                          'flags'       => array('nosave')),
+
+                                    array('var'         => 'dbPersistent',
+                                          'title'       => INSTALL_DBPERSISTENT,
+                                          'description' => INSTALL_DBPERSISTENT_DESC,
+                                          'type'        => 'bool',
+                                          'default'     => false,
+                                          'flags'       => array('nosave'))
+                                ));
+
+    $res['paths'] =
+             array('title'          => INSTALL_CAT_PATHS,
+                   'description'    => INSTALL_CAT_PATHS_DESC,
+                   'items' => array(array('var'         => 'serendipityPath',
+                                          'title'       => INSTALL_FULLPATH,
+                                          'description' => INSTALL_FULLPATH_DESC,
+                                          'type'        => 'string',
+                                          'default'     => '/webroot/serendipity/'),
+
+                                    array('var'         => 'uploadPath',
+                                          'title'       => INSTALL_UPLOADPATH,
+                                          'description' => INSTALL_UPLOADPATH_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'uploads/'),
+
+                                    array('var'         => 'serendipityHTTPPath',
+                                          'title'       => INSTALL_RELPATH,
+                                          'description' => INSTALL_RELPATH_DESC,
+                                          'type'        => 'string',
+                                          'default'     => '/serendipity/'),
+
+                                    array('var'         => 'templatePath',
+                                          'title'       => INSTALL_RELTEMPLPATH,
+                                          'description' => INSTALL_RELTEMPLPATH_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'templates/'),
+
+                                    array('var'         => 'uploadHTTPPath',
+                                          'title'       => INSTALL_RELUPLOADPATH,
+                                          'description' => INSTALL_RELUPLOADPATH_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'uploads/'),
+
+                                    array('var'         => 'baseURL',
+                                          'title'       => INSTALL_URL,
+                                          'description' => INSTALL_URL_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'http://www.example.com/serendipity/'),
+
+                                    array('var'         => 'autodetect_baseURL',
+                                          'title'       => INSTALL_AUTODETECT_URL,
+                                          'description' => INSTALL_AUTODETECT_URL_DESC,
+                                          'type'        => 'bool',
+                                          'default'     => false),
+
+                                    array('var'         => 'indexFile',
+                                          'title'       => INSTALL_INDEXFILE,
+                                          'description' => INSTALL_INDEXFILE_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'index.php'),
+                                ));
+
+
+    $res['settings'] =
+             array('title'          => INSTALL_CAT_SETTINGS,
+                   'description'    => INSTALL_CAT_SETTINGS_DESC,
+                   'items' => array(array('var'         => 'user',
+                                          'title'       => INSTALL_USERNAME,
+                                          'description' => INSTALL_USERNAME_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'John Doe',
+                                          'flags'       => array('installOnly', 'local', 'simpleInstall')),
+
+                                    array('var'         => 'pass',
+                                          'title'       => INSTALL_PASSWORD,
+                                          'description' => INSTALL_PASSWORD_DESC,
+                                          'type'        => 'protected',
+                                          'default'     => 'john',
+                                          'flags'       => array('installOnly', 'local', 'simpleInstall')),
+
+                                    array('var'         => 'realname',
+                                          'title'       => USERCONF_REALNAME,
+                                          'description' => USERCONF_REALNAME_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'John Doe',
+                                          'flags'       => array('installOnly', 'local', 'simpleInstall')),
+
+                                    array('var'         => 'email',
+                                          'title'       => INSTALL_EMAIL,
+                                          'description' => INSTALL_EMAIL_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'john@example.com',
+                                          'flags'       => array('installOnly', 'local', 'simpleInstall')),
+
+                                    array('var'         => 'want_mail',
+                                          'title'       => INSTALL_SENDMAIL,
+                                          'description' => INSTALL_SENDMAIL_DESC,
+                                          'type'        => 'bool',
+                                          'default'     => true,
+                                          'flags'       => array('installOnly', 'local')),
+
+                                    array('var'         => 'allowSubscriptions',
+                                          'title'       => INSTALL_SUBSCRIBE,
+                                          'description' => INSTALL_SUBSCRIBE_DESC,
+                                          'type'        => 'bool',
+                                          'default'     => true),
+
+                                    array('var'         => 'blogTitle',
+                                          'title'       => INSTALL_BLOGNAME,
+                                          'description' => INSTALL_BLOGNAME_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'John Doe\'s personal blog',
+                                          'userlevel'   => USERLEVEL_CHIEF,
+                                          'flags'       => array('simpleInstall')),
+
+                                    array('var'         => 'blogDescription',
+                                          'title'       => INSTALL_BLOGDESC,
+                                          'description' => INSTALL_BLOGDESC_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'My little place on the web...',
+                                          'userlevel'   => USERLEVEL_CHIEF,
+                                          'flags'       => array('simpleInstall')),
+
+                                    array('var'         => 'lang',
+                                          'title'       => INSTALL_LANG,
+                                          'description' => INSTALL_LANG_DESC,
+                                          'type'        => 'list',
+                                          'default'     => $serendipity['languages'],
+                                          'flags'       => array('simpleInstall')),
+
+                                    array('var'         => 'lang_content_negotiation',
+                                          'title'       => AUTOLANG,
+                                          'description' => AUTOLANG_DESC,
+                                          'type'        => 'bool',
+                                          'default'     => false,
+                                          'userlevel'   => USERLEVEL_CHIEF),
+                            ));
+
+    $res['display'] =
+             array('title'          => INSTALL_CAT_DISPLAY,
+                   'description'    => INSTALL_CAT_DISPLAY_DESC,
+                   'items' => array(array('var'         => 'fetchLimit',
+                                          'title'       => INSTALL_FETCHLIMIT,
+                                          'description' => INSTALL_FETCHLIMIT_DESC,
+                                          'type'        => 'int',
+                                          'default'     => 15,
+                                          'userlevel'   => USERLEVEL_CHIEF),
+
+                                    array('var'         => 'useGzip',
+                                          'title'       => INSTALL_USEGZIP,
+                                          'description' => INSTALL_USEGZIP_DESC,
+                                          'type'        => 'bool',
+                                          'default'     => true),
+
+                                    array('var'         => 'wysiwyg',
+                                          'title'       => INSTALL_WYSIWYG,
+                                          'description' => INSTALL_WYSIWYG_DESC,
+                                          'type'        => 'bool',
+                                          'default'     => false,
+                                          'userlevel'   => USERLEVEL_CHIEF,
+                                          'flags'       => array('simpleInstall')),
+
+                                    array('var'         => 'XHTML11',
+                                          'title'       => INSTALL_XHTML11,
+                                          'description' => INSTALL_XHTML11_DESC,
+                                          'type'        => 'bool',
+                                          'default'     => false),
+
+                                    array('var'         => 'enablePopup',
+                                          'title'       => INSTALL_POPUP,
+                                          'description' => INSTALL_POPUP_DESC,
+                                          'type'        => 'bool',
+                                          'default'     => false,
+                                          'userlevel'   => USERLEVEL_CHIEF),
+
+                                    array('var'         => 'embed',
+                                          'title'       => INSTALL_EMBED,
+                                          'description' => INSTALL_EMBED_DESC,
+                                          'type'        => 'bool',
+                                          'default'     => 'false'),
+
+                                    array('var'         => 'top_as_links',
+                                          'title'       => INSTALL_SHOW_EXTERNAL_LINKS,
+                                          'description' => INSTALL_SHOW_EXTERNAL_LINKS_DESC,
+                                          'type'        => 'bool',
+                                          'default'     => false),
+
+                                    array('var'         => 'blockReferer',
+                                          'title'       => INSTALL_BLOCKREF,
+                                          'description' => INSTALL_BLOCKREF_DESC,
+                                          'type'        => 'string',
+                                          'default'     => ';',
+                                          'userlevel'   => USERLEVEL_CHIEF),
+
+                                    array('var'         => 'rewrite',
+                                          'title'       => INSTALL_REWRITE,
+                                          'description' => INSTALL_REWRITE_DESC,
+                                          'type'        => 'list',
+                                          'default'     => array(),
+                                          'flags'       => array('probeDefault')),
+
+                                    array('var'         => 'serverOffsetHours',
+                                          'title'       => INSTALL_OFFSET,
+                                          'description' => INSTALL_OFFSET_DESC,
+                                          'type'        => 'int',
+                                          'default'     => 0,
+                                          'userlevel'   => USERLEVEL_CHIEF,
+                                          'flags'       => array('parseDescription')),
+
+                                    array('var'         => 'showFutureEntries',
+                                          'title'       => INSTALL_SHOWFUTURE,
+                                          'description' => INSTALL_SHOWFUTURE_DESC,
+                                          'type'        => 'bool',
+                                          'default'     => false,
+                                          'userlevel'   => USERLEVEL_CHIEF),
+                            ));
+
+    $res['imagehandling'] =
+             array('title' => INSTALL_CAT_IMAGECONV,
+                   'description' => INSTALL_CAT_IMAGECONV_DESC,
+                   'items' => array(array('var'         => 'magick',
+                                          'title'       => INSTALL_IMAGEMAGICK,
+                                          'description' => INSTALL_IMAGEMAGICK_DESC,
+                                          'type'        => 'bool',
+                                          'default'     => false),
+
+                                    array('var'         => 'convert',
+                                          'title'       => INSTALL_IMAGEMAGICKPATH,
+                                          'description' => INSTALL_IMAGEMAGICKPATH_DESC,
+                                          'type'        => 'string',
+                                          'default'     => '/usr/local/bin/convert'),
+
+                                    array('var'         => 'thumbSuffix',
+                                          'title'       => INSTALL_THUMBSUFFIX,
+                                          'description' => INSTALL_THUMBSUFFIX_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'serendipityThumb'),
+
+                                    array('var'         => 'thumbSize',
+                                          'title'       => INSTALL_THUMBWIDTH,
+                                          'description' => INSTALL_THUMBWIDTH_DESC,
+                                          'type'        => 'int',
+                                          'default'     => 110),
+                            ));
+
+    return $res;
+?>
diff --git a/include/tpl/config_personal.inc.php b/include/tpl/config_personal.inc.php
new file mode 100644 (file)
index 0000000..26f4f15
--- /dev/null
@@ -0,0 +1,114 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+// Here be dragons and NO application logic!
+
+    $res = array();
+    $res['personal'] =
+             array('title' => USERCONF_CAT_PERSONAL,
+                   'description' => USERCONF_CAT_PERSONAL_DESC,
+                   'items' => array(array('var'         => 'username',
+                                          'title'       => USERCONF_USERNAME,
+                                          'description' => USERCONF_USERNAME_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'johndoe',
+                                          'userlevel'   => USERLEVEL_EDITOR),
+
+                                    array('var'         => 'password',
+                                          'title'       => USERCONF_PASSWORD,
+                                          'description' => USERCONF_PASSWORD_DESC,
+                                          'type'        => 'protected',
+                                          'default'     => '',
+                                          'userlevel'   => USERLEVEL_EDITOR),
+
+                                    array('var'         => 'realname',
+                                          'title'       => USERCONF_REALNAME,
+                                          'description' => USERCONF_REALNAME_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'John Doe',
+                                          'userlevel'   => USERLEVEL_EDITOR),
+
+                                    array('var'         => 'userlevel',
+                                          'title'       => USERCONF_USERLEVEL,
+                                          'description' => USERCONF_USERLEVEL_DESC,
+                                          'type'        => 'list',
+                                          'default'     => $serendipity['permissionLevels'],
+                                          'userlevel'   => USERLEVEL_CHIEF),
+
+                                    array('var'         => 'email',
+                                          'title'       => USERCONF_EMAIL,
+                                          'description' => USERCONF_EMAIL_DESC,
+                                          'type'        => 'string',
+                                          'default'     => 'john@example.com',
+                                          'userlevel'   => USERLEVEL_EDITOR),
+
+                                    array('var'         => 'lang',
+                                          'title'       => INSTALL_LANG,
+                                          'description' => INSTALL_LANG_DESC,
+                                          'type'        => 'list',
+                                          'default'     => $serendipity['languages'],
+                                          'userlevel'   => USERLEVEL_EDITOR,
+                                          'flags'       => array('config')),
+
+                                    array('var'         => 'wysiwyg',
+                                          'title'       => INSTALL_WYSIWYG,
+                                          'description' => INSTALL_WYSIWYG_DESC,
+                                          'type'        => 'bool',
+                                          'default'     => false,
+                                          'userlevel'   => USERLEVEL_EDITOR,
+                                          'flags'       => array('config')),
+
+                                    array('var'         => 'mail_comments',
+                                          'title'       => USERCONF_SENDCOMMENTS,
+                                          'description' => USERCONF_SENDCOMMENTS_DESC,
+                                          'type'        => 'bool',
+                                          'default'     => true,
+                                          'userlevel'   => USERLEVEL_EDITOR),
+
+                                    array('var'         => 'mail_trackbacks',
+                                          'title'       => USERCONF_SENDTRACKBACKS,
+                                          'description' => USERCONF_SENDTRACKBACKS_DESC,
+                                          'type'        => 'bool',
+                                          'default'     => true,
+                                          'userlevel'   => USERLEVEL_EDITOR),
+
+                                    array('var'         => 'right_publish',
+                                          'title'       => USERCONF_ALLOWPUBLISH,
+                                          'description' => USERCONF_ALLOWPUBLISH_DESC,
+                                          'type'        => 'bool',
+                                          'default'     => true,
+                                          'userlevel'   => USERLEVEL_CHIEF),
+                            ));
+
+    $res['defaults'] =
+             array('title' => USERCONF_CAT_DEFAULT_NEW_ENTRY,
+                   'description' => '',
+                   'items' => array(
+                                    array('var'         => 'moderateCommentsDefault',
+                                          'title'       => COMMENTS_MODERATE,
+                                          'description' => '',
+                                          'type'        => 'bool',
+                                          'default'     => false,
+                                          'userlevel'   => USERLEVEL_EDITOR,
+                                          'flags'       => array('config')),
+
+                                    array('var'         => 'allowCommentsDefault',
+                                          'title'       => COMMENTS_ENABLE,
+                                          'description' => '',
+                                          'type'        => 'bool',
+                                          'default'     => true,
+                                          'userlevel'   => USERLEVEL_EDITOR,
+                                          'flags'       => array('config')),
+
+                                    array('var'         => 'publishDefault',
+                                          'title'       => NEW_ENTRY,
+                                          'description' => '',
+                                          'type'        => 'list',
+                                          'default'     => array('publish' => PUBLISH, 'draft' => DRAFT),
+                                          'userlevel'   => USERLEVEL_EDITOR,
+                                          'flags'       => array('config')),
+                            ));
+
+    return $res;
+?>
diff --git a/include/tpl/htaccess_cgi_errordocs.tpl b/include/tpl/htaccess_cgi_errordocs.tpl
new file mode 100644 (file)
index 0000000..c69a7d1
--- /dev/null
@@ -0,0 +1,21 @@
+# BEGIN s9y
+ErrorDocument 404 {PREFIX}{indexFile}
+DirectoryIndex {PREFIX}{indexFile}
+
+<Files *.tpl>
+    deny from all
+</Files>
+
+<Files *.sql>
+    deny from all
+</Files>
+
+<Files *.inc.php>
+    deny from all
+</Files>
+
+<Files *.db>
+    deny from all
+</Files>
+
+# END s9y
diff --git a/include/tpl/htaccess_cgi_normal.tpl b/include/tpl/htaccess_cgi_normal.tpl
new file mode 100644 (file)
index 0000000..85a6a75
--- /dev/null
@@ -0,0 +1,19 @@
+# BEGIN s9y
+DirectoryIndex {PREFIX}{indexFile}
+<Files *.tpl>
+    deny from all
+</Files>
+
+<Files *.sql>
+    deny from all
+</Files>
+
+<Files *.inc.php>
+    deny from all
+</Files>
+
+<Files *.db>
+    deny from all
+</Files>
+
+# END s9y
diff --git a/include/tpl/htaccess_cgi_rewrite.tpl b/include/tpl/htaccess_cgi_rewrite.tpl
new file mode 100644 (file)
index 0000000..b9c4429
--- /dev/null
@@ -0,0 +1,41 @@
+# BEGIN s9y
+ErrorDocument 404 {PREFIX}{indexFile}
+DirectoryIndex {PREFIX}{indexFile}
+
+RewriteEngine On
+RewriteBase {PREFIX}
+RewriteRule ^{PAT_ARCHIVES} {indexFile}?url=/{PATH_ARCHIVES}/$1.html [L,QSA]
+RewriteRule ^([0-9]+)[_\-][0-9a-z_\-]*\.html {indexFile}?url=$1-article.html [L,NC,QSA]
+RewriteRule ^{PAT_FEEDS}/(.*) {indexFile}?url=/{PATH_FEEDS}/$1 [L,QSA]
+RewriteRule ^{PAT_UNSUBSCRIBE} {indexFile}?url=/{PATH_UNSUBSCRIBE}/$1/$2 [L,QSA]
+RewriteRule ^{PAT_APPROVE} {indexFile}?url={PATH_APPROVE}/$1/$2/$3 [L,QSA]
+RewriteRule ^{PAT_DELETE} {indexFile}?url={PATH_DELETE}/$1/$2/$3 [L,QSA]
+RewriteRule ^{PAT_ADMIN} {indexFile}?url={PATH_ADMIN}/ [L,QSA]
+RewriteRule ^{PAT_ARCHIVE} {indexFile}?url=/{PATH_ARCHIVE} [L,QSA]
+RewriteRule ^{PAT_CATEGORIES} {indexFile}?url=/{PATH_CATEGORIES}/$1 [L,QSA]
+RewriteRule ^{PAT_FEED} rss.php?file=$1&ext=$2
+RewriteRule ^{PAT_PLUGIN} {indexFile}?url=plugin/$1 [L,QSA]
+RewriteRule ^{PAT_SEARCH} {indexFile}?url=/{PATH_SEARCH}/$1 [L,QSA]
+RewriteRule ^{PAT_CSS} {indexFile}?url=/$1 [L,QSA]
+RewriteRule ^{PAT_AUTHORS} {indexFile}?url=/{PATH_AUTHORS}/$1 [L,QSA]
+RewriteRule ^index\.(html?|php.?) {indexFile}?url=index.html [L,QSA]
+RewriteRule ^htmlarea/(.*) htmlarea/$1 [L,QSA]
+RewriteRule (.*\.html?) {indexFile}?url=/$1 [L,QSA]
+
+<Files *.tpl>
+    deny from all
+</Files>
+
+<Files *.sql>
+    deny from all
+</Files>
+
+<Files *.inc.php>
+    deny from all
+</Files>
+
+<Files *.db>
+    deny from all
+</Files>
+
+# END s9y
diff --git a/include/tpl/htaccess_errordocs.tpl b/include/tpl/htaccess_errordocs.tpl
new file mode 100644 (file)
index 0000000..7477fb3
--- /dev/null
@@ -0,0 +1,23 @@
+# BEGIN s9y
+ErrorDocument 404 {PREFIX}{indexFile}
+DirectoryIndex {PREFIX}{indexFile}
+php_value session.use_trans_sid 0
+php_value register_globals off
+
+<Files *.tpl>
+    deny from all
+</Files>
+
+<Files *.sql>
+    deny from all
+</Files>
+
+<Files *.inc.php>
+    deny from all
+</Files>
+
+<Files *.db>
+    deny from all
+</Files>
+
+# END s9y
diff --git a/include/tpl/htaccess_normal.tpl b/include/tpl/htaccess_normal.tpl
new file mode 100644 (file)
index 0000000..73c3a94
--- /dev/null
@@ -0,0 +1,21 @@
+# BEGIN s9y
+DirectoryIndex {PREFIX}{indexFile}
+php_value session.use_trans_sid 0
+php_value register_globals off
+<Files *.tpl>
+    deny from all
+</Files>
+
+<Files *.sql>
+    deny from all
+</Files>
+
+<Files *.inc.php>
+    deny from all
+</Files>
+
+<Files *.db>
+    deny from all
+</Files>
+
+# END s9y
diff --git a/include/tpl/htaccess_rewrite.tpl b/include/tpl/htaccess_rewrite.tpl
new file mode 100644 (file)
index 0000000..26ea1e4
--- /dev/null
@@ -0,0 +1,43 @@
+# BEGIN s9y
+ErrorDocument 404 {PREFIX}{indexFile}
+DirectoryIndex {PREFIX}{indexFile}
+php_value session.use_trans_sid 0
+php_value register_globals off
+
+RewriteEngine On
+RewriteBase {PREFIX}
+RewriteRule ^{PAT_ARCHIVES} {indexFile}?url=/{PATH_ARCHIVES}/$1.html [L,QSA]
+RewriteRule ^([0-9]+)[_\-][0-9a-z_\-]*\.html {indexFile}?url=$1-article.html [L,NC,QSA]
+RewriteRule ^{PAT_FEEDS}/(.*) {indexFile}?url=/{PATH_FEEDS}/$1 [L,QSA]
+RewriteRule ^{PAT_UNSUBSCRIBE} {indexFile}?url=/{PATH_UNSUBSCRIBE}/$1/$2 [L,QSA]
+RewriteRule ^{PAT_APPROVE} {indexFile}?url={PATH_APPROVE}/$1/$2/$3 [L,QSA]
+RewriteRule ^{PAT_DELETE} {indexFile}?url={PATH_DELETE}/$1/$2/$3 [L,QSA]
+RewriteRule ^{PAT_ADMIN} {indexFile}?url={PATH_ADMIN}/ [L,QSA]
+RewriteRule ^{PAT_ARCHIVE} {indexFile}?url=/{PATH_ARCHIVE} [L,QSA]
+RewriteRule ^{PAT_CATEGORIES} {indexFile}?url=/{PATH_CATEGORIES}/$1 [L,QSA]
+RewriteRule ^{PAT_FEED} rss.php?file=$1&ext=$2
+RewriteRule ^{PAT_PLUGIN} {indexFile}?url=plugin/$1 [L,QSA]
+RewriteRule ^{PAT_SEARCH} {indexFile}?url=/{PATH_SEARCH}/$1 [L,QSA]
+RewriteRule ^{PAT_CSS} {indexFile}?url=/$1 [L,QSA]
+RewriteRule ^{PAT_AUTHORS} {indexFile}?url=/{PATH_AUTHORS}/$1 [L,QSA]
+RewriteRule ^index\.(html?|php.?) {indexFile}?url=index.html [L,QSA]
+RewriteRule ^htmlarea/(.*) htmlarea/$1 [L,QSA]
+RewriteRule (.*\.html?) {indexFile}?url=/$1 [L,QSA]
+
+<Files *.tpl>
+    deny from all
+</Files>
+
+<Files *.sql>
+    deny from all
+</Files>
+
+<Files *.inc.php>
+    deny from all
+</Files>
+
+<Files *.db>
+    deny from all
+</Files>
+
+# END s9y
diff --git a/index.php b/index.php
new file mode 100644 (file)
index 0000000..9b6c3a2
--- /dev/null
+++ b/index.php
@@ -0,0 +1,312 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+$global_debug = false;
+if ($global_debug) {
+    #apd_set_pprof_trace();
+
+    function microtime_float() {
+        list($usec, $sec) = explode(" ", microtime());
+        return ((float)$usec + (float)$sec);
+    }
+
+    $time_start = microtime_float();
+}
+
+// We need to set this to return a 200 since we use .htaccess ErrorDocument
+// rules to handle archives.
+header('HTTP/1.0 200');
+header('X-Blog: Serendipity'); // Used for installer detection
+
+// Session are needed to also remember an autologin user on the frontend
+ob_start();
+include_once('serendipity_config.inc.php');
+header('Content-Type: text/html; charset='. LANG_CHARSET);
+
+$track_referer = true;
+$uri = $_SERVER['REQUEST_URI'];
+
+$serendipity['uriArguments'] = serendipity_getUriArguments($uri);
+
+if (isset($_SERVER['HTTP_REFERER']) && empty($_SESSION['HTTP_REFERER'])) {
+    $_SESSION['HTTP_REFERER'] = $_SERVER['HTTP_REFERER'];
+}
+
+if (preg_match(PAT_UNSUBSCRIBE, $uri, $res)) {
+    if (serendipity_cancelSubscription(urldecode($res[1]), $res[2])) {
+        define('DATA_UNSUBSCRIBED', urldecode($res[1]));
+    }
+
+    $uri = '/' . PATH_UNSUBSCRIBE . '/' . $res[2] . '-untitled.html';
+}
+
+if (preg_match(PAT_DELETE, $uri, $res) && $serendipity['serendipityAuthedUser'] === true) {
+    if ($res[1] == 'comment' && serendipity_deleteComment($res[2], $res[3], 'comments')) {
+        define('DATA_COMMENT_DELETED', $res[2]);
+    } elseif ( $res[1] == 'trackback' && serendipity_deleteComment($res[2], $res[3], 'trackbacks') ) {
+        define('DATA_TRACKBACK_DELETED', $res[2]);
+    }
+}
+
+if (preg_match(PAT_APPROVE, $uri, $res) && $serendipity['serendipityAuthedUser'] === true) {
+    if ($res[1] == 'comment' && serendipity_approveComment($res[2], $res[3])) {
+        define('DATA_COMMENT_APPROVED', $res[2]);
+    } elseif ($res[1] == 'trackback' && serendipity_approveComment($res[2], $res[3])) {
+        define('DATA_TRACKBACK_APPROVED', $res[2]);
+    }
+}
+
+
+if (preg_match(PAT_ARCHIVES, $uri, $matches) || isset($serendipity['GET']['range']) && is_numeric($serendipity['GET']['range'])) {
+    $_args = $serendipity['uriArguments'];
+
+    /* Attempt to locate hidden variables within the URI */
+    foreach ($_args as $k => $v){
+        if ($v == PATH_ARCHIVES) {
+            continue;
+        }
+        if ($v{0} == 'C') { /* category */
+            $serendipity['GET']['category'] = substr($v, 1);
+            unset($_args[$k]);
+        } elseif ($v{0} == 'W') { /* Week */
+            $week = substr($v, 1);
+            unset($_args[$k]);
+        } elseif ($v == 'summary') { /* Summary */
+            $serendipity['short_archives'] = true;
+            unset($_args[$k]);
+        } elseif ($v{0} == 'P') { /* Page */
+            $serendipity['GET']['page'] = substr($v, 1);
+            unset($_args[$k]);
+            unset($serendipity['uriArguments'][$k]);
+        }
+    }
+
+    /* We must always *assume* that Year, Month and Day are the first 3 arguments */
+    list(,$year, $month, $day) = $_args;
+
+    $serendipity['GET']['action']     = 'read';
+    $serendipity['GET']['hidefooter'] = true;
+
+    if ( !isset($year) ) {
+        $year = date('Y');
+        $month = date('m');
+        $day = date('j');
+        $serendipity['GET']['action']     = null;
+        $serendipity['GET']['hidefooter'] = null;
+    }
+
+    if ($week) {
+        $tm = strtotime('+ '. ($week-2) .' WEEKS monday', mktime(0, 0, 0, 1, 1, $year));
+        $ts = mktime(0, 0, 0, date('m', $tm), date('j', $tm), $year);
+        $te = mktime(23, 59, 59, date('m', $tm), date('j', $tm)+7, $year);
+        $date = serendipity_formatTime(WEEK .' '. $week .', %Y', $ts, false);
+    } else {
+        if ($day) {
+            $ts = mktime(0, 0, 0, $month, $day, $year);
+            $te = mktime(23, 59, 59, $month, $day, $year);
+            $date = serendipity_formatTime(DATE_FORMAT_ENTRY, $ts, false);
+        } else {
+            $ts = mktime(0, 0, 0, $month, 1, $year);
+            $te = mktime(23, 59, 59, $month, date('t', $ts), $year);
+            $date = serendipity_formatTime('%B %Y', $ts, $false);
+        }
+    }
+
+    $serendipity['range'] = array($ts, $te);
+
+    if ($serendipity['GET']['action'] == 'read') {
+        $serendipity['head_subtitle'] = sprintf(ENTRIES_FOR, $date);
+    }
+
+    ob_start();
+    include_once(S9Y_INCLUDE_PATH . 'include/genpage.inc.php');
+    $data = ob_get_contents();
+    ob_end_clean();
+
+    if (isset($serendipity['pregenerate']) && $serendipity['pregenerate']) {
+        $fp = fopen('./'.PATH_ARCHIVES.'/' . $matches[1], 'w');
+        fwrite($fp, $data);
+        fclose($fp);
+    }
+
+    echo $data;
+} else if (preg_match(PAT_COMMENTSUB, $uri, $matches)) {
+    serendipity_rememberComment();
+
+    if (!empty($serendipity['POST']['submit'])) {
+        $comment['url']       = $serendipity['POST']['url'];
+        $comment['comment']   = trim($serendipity['POST']['comment']);
+        $comment['name']      = $serendipity['POST']['name'];
+        $comment['email']     = $serendipity['POST']['email'];
+        $comment['subscribe'] = $serendipity['POST']['subscribe'];
+        $comment['parent_id'] = $serendipity['POST']['replyTo'];
+        if (!empty($comment['comment'])) {
+            if (serendipity_saveComment($serendipity['POST']['entry_id'], $comment, 'NORMAL')) {
+                $sc_url = $_SERVER['REQUEST_URI'] . (strstr($_SERVER['REQUEST_URI'], '?') ? '&' : '?') . 'serendipity[csuccess]=' . $serendipity['csuccess'];
+                if (serendipity_isResponseClean($sc_url)) {
+                    header('Location: ' . $sc_url);
+                }
+                exit;
+            } else {
+                $serendipity['messagestack']['comments'][] = COMMENT_NOT_ADDED;
+            }
+        } else {
+                $serendipity['messagestack']['comments'][] = sprintf(EMPTY_COMMENT, '', '');
+        }
+    }
+
+    $id = (int)$matches[1];
+
+    serendipity_track_referrer($id);
+    $track_referer = false;
+
+    $_GET['serendipity']['action'] = 'read';
+    $_GET['serendipity']['id']     = $id;
+
+    $title = serendipity_db_query("SELECT title FROM {$serendipity['dbPrefix']}entries WHERE id=$id", true);
+    $serendipity['head_title']    = $title[0];
+    $serendipity['head_subtitle'] = $serendipity['blogTitle'];
+
+    ob_start();
+    include_once(S9Y_INCLUDE_PATH . 'include/genpage.inc.php');
+    $data = ob_get_contents();
+    ob_end_clean();
+
+    if (isset($serendipity['pregenerate']) && $serendipity['pregenerate']) {
+        $fp = fopen($serendipity['serendipityPath'] . PATH_ARCHIVES.'/' . $id, 'w');
+        fwrite($fp, $data);
+        fclose($fp);
+    }
+    print $data;
+} elseif (preg_match(PAT_FEEDS, $uri)) {
+    header('Content-Type: text/html; charset=utf-8');
+
+    if (preg_match('@/(index|atom|rss|comments|opml)\.(rss[0-9]?|rdf|rss|xml|atom)$@', $uri, $matches)) {
+        list($_GET['version'], $_GET['type']) = serendipity_discover_rss($matches[1], $matches[2]);
+    }
+
+    if (preg_match(PAT_FEEDS_CATEGORIES, $uri, $matches)) {
+        $_GET['category'] = $matches[1];
+    }
+
+    ob_start();
+    include_once(S9Y_INCLUDE_PATH . 'rss.php');
+    $data = ob_get_contents();
+    ob_end_clean();
+
+    if ($serendipity['pregenerate']) {
+        $fp = fopen($serendipity['serendipityPath'] . PATH_FEEDS.'/index.' . $matches[1], 'w');
+        fwrite($fp, $data);
+        fclose($fp);
+    }
+
+    serendipity_gzCompression();
+
+    print $data;
+    exit;
+} else if (preg_match(PAT_ADMIN, $uri)) {
+    header("Location: {$serendipity['serendipityHTTPPath']}serendipity_admin.php");
+    exit;
+} else if (preg_match(PAT_ARCHIVE, $uri)) {
+    $serendipity['GET']['action'] = 'archives';
+    include_once(S9Y_INCLUDE_PATH . 'include/genpage.inc.php');
+} else if (preg_match(PAT_PLUGIN, $uri, $matches)) {
+    serendipity_plugin_api::hook_event('external_plugin', $matches[1]);
+    exit;
+} else if (preg_match(PAT_CATEGORIES, $uri, $matches)) {
+    $_args = $serendipity['uriArguments'];
+
+    /* Attempt to locate hidden variables within the URI */
+    foreach ($_args as $k => $v){
+        if ($v == PATH_CATEGORIES) {
+            continue;
+        }
+        if ($v{0} == 'P') { /* Page */
+            $serendipity['GET']['page'] = substr($v, 1);
+            unset($_args[$k]);
+            unset($serendipity['uriArguments'][$k]);
+        }
+    }
+
+    $serendipity['GET']['category'] = $matches[1];
+    $serendipity['GET']['action'] = 'read';
+    $cInfo = serendipity_fetchCategoryInfo($serendipity['GET']['category']);
+    $serendipity['head_title']    = $cInfo['category_name'];
+    $serendipity['head_subtitle'] = $serendipity['blogTitle'];
+
+    include_once(S9Y_INCLUDE_PATH . 'include/genpage.inc.php');
+} else if (preg_match(PAT_AUTHORS, $uri, $matches)) {
+    $serendipity['GET']['viewAuthor'] = $matches[1];
+    $serendipity['GET']['action'] = 'read';
+
+    $uInfo = serendipity_fetchUsers($serendipity['GET']['viewAuthor']);
+    $serendipity['head_title']    = sprintf(ENTRIES_BY, $uInfo[0]['realname']);
+    $serendipity['head_subtitle'] = $serendipity['blogTitle'];
+
+    include_once(S9Y_INCLUDE_PATH . 'include/genpage.inc.php');
+} else if (preg_match(PAT_SEARCH, $uri, $matches)) {
+    $_args = $serendipity['uriArguments'];
+
+    /* Attempt to locate hidden variables within the URI */
+    $search = array();
+    foreach ($_args as $k => $v){
+        if ($v == PATH_SEARCH) {
+            continue;
+        }
+
+        if ($v{0} == 'P') { /* Page */
+            $serendipity['GET']['page'] = substr($v, 1);
+            unset($_args[$k]);
+            unset($serendipity['uriArguments'][$k]);
+        } else {
+            $search[] = $v;
+        }
+    }
+
+    $serendipity['GET']['action']     = 'search';
+    $serendipity['GET']['searchTerm'] = urldecode(htmlspecialchars(strip_tags(implode(' ', $search))));
+    include_once(S9Y_INCLUDE_PATH . 'include/genpage.inc.php');
+} elseif (preg_match(PAT_CSS, $uri, $matches)) {
+    $css_mode = $matches[1];
+    include_once(S9Y_INCLUDE_PATH . 'serendipity.css.php');
+    exit;
+} else if (preg_match('@/(index(\.php|\.html)?)|'. preg_quote($serendipity['indexFile']) .'@', $uri) ||
+           preg_match('@^/' . preg_quote(trim($serendipity['serendipityHTTPPath'], '/')) . '/?(\?.*)?$@', $uri)) {
+
+    if ($serendipity['GET']['action'] == 'search') {
+        $serendipity['uriArguments'] = array(PATH_SEARCH, urlencode($serendipity['GET']['searchTerm']));
+    } else {
+        $serendipity['uriArguments'][] = PATH_ARCHIVES;
+    }
+
+    include_once(S9Y_INCLUDE_PATH . 'include/genpage.inc.php');
+} else {
+    header('HTTP/1.0 404 Not found');
+    include_once(S9Y_INCLUDE_PATH . 'include/genpage.inc.php');
+    // printf('<div class="serendipity_msg_important">' . DOCUMENT_NOT_FOUND . '</div>', $uri);
+}
+
+if ($track_referer) {
+    serendipity_track_referrer();
+}
+
+$raw_data = ob_get_contents();
+ob_end_clean();
+$serendipity['smarty']->assign('raw_data', $raw_data);
+if (empty($serendipity['smarty_file'])) {
+    $serendipity['smarty_file'] = '404.tpl';
+}
+
+serendipity_gzCompression();
+
+$serendipity['smarty']->display(serendipity_getTemplateFile($serendipity['smarty_file'], 'serendipityPath'));
+
+if ($global_debug) {
+    /* TODO: Remove (hide) this debug */
+    echo '<div id="s9y_debug" style="text-align: center; color: red; font-size: 10pt; font-weight: bold; padding: 10px">Page delivered in '. round(microtime_float()-$time_start,6) .' seconds, '. sizeof(get_included_files()) .' files included</div>';
+    echo '</div>';
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/lang/serendipity_lang_bg.inc.php b/lang/serendipity_lang_bg.inc.php
new file mode 100644 (file)
index 0000000..4ab01b5
--- /dev/null
@@ -0,0 +1,655 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Translation (c) 2004 Bogomil Shopov <bogomil@spisanie.com>
+# http://www.purplerain.org/nb/
+
+@define('LANG_CHARSET', 'windows-1251');
+@define('DATE_LOCALES', 'bulgarian, bg, bg_BG');
+@define('DATE_FORMAT_ENTRY', '%A, %B %e. %Y');
+@define('WYSIWYG_LANG', 'en');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Serendipity Àäìèíèñòðàöèÿ');
+@define('HAVE_TO_BE_LOGGED_ON', 'Òðÿáâà äà âçëåçåòå çà äà âèäèòå òàçè ñòðàíèöà:');
+@define('WRONG_USERNAME_OR_PASSWORD', 'Âúâåëè ñòå ãðåøíî èìå èëè ïàðîëà');
+@define('APPEARANCE', 'Appearance');
+@define('MANAGE_STYLES', 'Ïðîìÿíà íà ñòèëà');
+@define('CONFIGURE_PLUGINS', 'Êîíôèãóðàöèÿ íà äîïúëíèòåëíèòå ìîäóëè');
+@define('CONFIGURATION', 'Êîíôèãóðàöèÿ');
+@define('BACK_TO_BLOG', 'Îáðàòíî êúì áëîã-à');
+@define('LOGIN', 'Âõîä');
+@define('LOGOUT', 'Èçõîä');
+@define('LOGGEDOUT', 'Âèå èçëÿçîõòå.');
+@define('CREATE', 'Ñúçäàé');
+@define('SAVE', 'Çàïàçè');
+@define('NAME', 'Èìå');
+@define('CREATE_NEW_CAT', 'Ñúçäàâàíå íà íîâà êàòåãîðèÿ');
+@define('I_WANT_THUMB', 'Èñêàì äà ïîëçâàì òúìáíåéëè â ìîåòî ñúäúðæàíèå.');
+@define('I_WANT_BIG_IMAGE', 'Èñêàì äà ïîëçâà ãîëÿìà êàðòèíêà â ìîåòî ñúäúðæàíèå');
+@define('I_WANT_NO_LINK', ' Èñêàì äà áóäå ïîêàçàíî êàòî êàðòèíêà');
+@define('I_WANT_IT_TO_LINK', 'Èñêàì äà áúäå ïîêàçàíî êàòî êàòî ëèíê êúì òîçè àäðåñ:');
+@define('BACK', 'Íàçàä');
+@define('FORWARD', 'Íàïðåä');
+@define('ANONYMOUS', 'Àíîíèìåí');
+@define('NEW_TRACKBACK_TO', 'Íîâî ïðîñëåäÿâàíå íà');
+@define('NEW_COMMENT_TO', 'Íîâ êîìåíòàð ïúáëèêóâàí îò');
+@define('RECENT', 'Ñåãàøíè...');
+@define('OLDER', 'Ïðåäèøíè...');
+@define('DONE', 'Ãîòîâî');
+@define('WELCOME_BACK', 'Äîáðå äîøúë îòíîâî,');
+@define('TITLE', 'Çàãëàâèå');
+@define('DESCRIPTION', 'Îïèñàíèå');
+@define('PLACEMENT', 'Ïîëîæåíèå');
+@define('DELETE', 'Èçòðèâàíå');
+@define('SAVE', 'Çàïàçâàíå');
+@define('UP', 'Íàãîðå');
+@define('DOWN', 'Íàäîëó');
+@define('ENTRIES', 'Ñúäúðæàíèå:');
+@define('NEW_ENTRY', 'Íîâî');
+@define('EDIT_ENTRIES', 'Ðåäàêöèÿ íà ñúäúðæàíèå');
+@define('CATEGORIES', 'Êàòåãîðèè');
+@define('WARNING_THIS_BLAHBLAH', "Âíèìàíèå!!!:\\n Âúçìîæíî å îïåðàöèÿòà äà ïðîäúëæè ìíîãî âðåìå, àêî èìà ìíîãî èçîáðàæåíèÿ.");
+@define('CREATE_THUMBS', 'Íàïðàâè òúìáíåéëè îòíîâî');
+@define('MANAGE_IMAGES', 'Ðåäàêöèÿ íà èçîáðàæåíèÿòà');
+@define('NAME', 'Èìå');
+@define('EMAIL', 'Email');
+@define('HOMEPAGE', 'Ñòðàíèöà â èíòåðíåò');
+@define('COMMENT', 'Êîìåíòàð');
+@define('REMEMBER_INFO', 'Äà çàïîìíÿ ëè äàííèòå? ');
+@define('SUBMIT_COMMENT', 'Âúâåäè êîìåíòàð');
+@define('NO_ENTRIES_TO_PRINT', 'Íÿìà äàííè çà ðàçïå÷àòâàíå');
+@define('COMMENTS', 'Êîìåíòàðè');
+@define('ADD_COMMENT', 'Äîáàâè êîìåíòàð');
+@define('NO_COMMENTS', 'Íÿìà êîìåíòàðè');
+@define('POSTED_BY', 'Ïóáëèêóâàíî îò');
+@define('ON', 'íà');
+@define('A_NEW_COMMENT_BLAHBLAH', 'Íîâ êîìåíòàð áåøå ïóáëèêóâàí íà áëîã-à âè "%s", è å îçàãëàâåí : "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'Íîâî ïðîñëåäÿâàíå å íàïðàâåíî "%s".');
+@define('NO_CATEGORY', 'Íÿìà êàòåãîðèÿ');
+@define('ENTRY_BODY', 'Âúâåäåòå ñúîáùåíèå');
+@define('EXTENDED_BODY', 'Äîïúëíèòåëíî ñúîáùåíèå');
+@define('CATEGORY', 'Êàòåãîðèÿ:');
+@define('EDIT', 'Ðåäàêöèÿ');
+@define('NO_ENTRIES_BLAHBLAH', 'Íàìà íàìåðåíè ðåçóëòàòè çà %s' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'Òúðñåíåòî çà  %s âúðíà %s ðåçóëòàòè:');
+@define('SEARCH_TOO_SHORT', 'Âúâåäåòå ìèíèìóì 3 çíàêà â ïîëåòî çà òúðñåíå');
+@define('IMAGE', 'Èçîáðàæåíèå');
+@define('ERROR_FILE_NOT_EXISTS', 'Ãðåøêà: Ñòàðîòî èìå íå ñúùåñòâóâà!');
+@define('ERROR_FILE_EXISTS', 'Ãðåøêà: Íîâîòî èìå âå÷å ñå èçïîëçâà, èçáåðåòå äðóãî!');
+@define('ERROR_SOMETHING', 'Ãðåøêà: Íåùî å ñãðåøåíî.');
+@define('ADDING_IMAGE', 'Äîáàâÿíå íà èçîáðàæåíèå...');
+@define('THUMB_CREATED_DONE', 'Òúìáíåéëà å ãîòîâ.');
+@define('ERROR_FILE_EXISTS_ALREADY', 'Ãðåøêà: Òîçè ôàéë âå÷å ñúøåñòâóâà!');
+@define('GO', 'Äàâàé!');
+@define('NEWSIZE', 'Íîâ ðàçìåð: ');
+@define('RESIZE_BLAHBLAH', '<b>Íîâè ðàçìåðè %s</b><p>');
+@define('ORIGINAL_SIZE', 'Îðèãèíàëíè ðàçìåðè: <i>%sx%s</i> pixel');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>Òóê ìîæåòå äà ïîñî÷èòå íîåèòå ðàçìåðè íà èçîáðàæåíèÿòà. Àêî èñêàòå  äà çàïàçèòå ïðîïîðöèèòå èì,âúâåäåòå ñàìî åäíà ñòîéíîñò è íàòèñíåòå áóòîíà TAB. Àâòîìàòè÷íî ùå ñå ïðåñìåòíå ïðîïîðöèÿòà');
+@define('QUICKSEARCH', 'Òúðñåíå');
+@define('SEARCH_FOR_ENTRY', 'Òúðñè ');
+@define('ARCHIVES', 'Àðõèâ');
+@define('BROWSE_ARCHIVES', 'Íàìåðè ñúîáøåíèÿ ïî ìåñåö');
+@define('TOP_REFERRER', 'Òîï ðåôåðåíòè');
+@define('SHOWS_TOP_SITES', 'Ïîêàçâà êîé å èìà âðúçêà êúì ñàéòà âè');
+@define('TOP_EXITS', 'Òîï èçõîäíè ëèíêîâå');
+@define('SHOWS_TOP_EXIT', 'Ïîêàçâà, íà êîè ëèíêîâå íàé-ìíîãî ñå å êëèêàëî îò ñàéòà âè');
+@define('SYNDICATION', 'Ñèíõðîíèçàöèÿ');
+@define('SHOWS_RSS_BLAHBLAH', 'Ïîêàæè RSS ëèíêîâå');
+@define('ADVERTISES_BLAHBLAH', 'Ðåêëàìèðàé ïðîèçõîäà íà ñâîÿ áëîã');
+@define('HTML_NUGGET', 'HTML Ïîëå');
+@define('HOLDS_A_BLAHBLAH', 'Äîáàâè  HTML ïîëå â ñâîÿ ñàéò');
+@define('TITLE_FOR_NUGGET', 'Çàãëàâèå íà ïîëåòî');
+@define('THE_NUGGET', 'Ñúäúðæàíèå íà ïîëåòî');
+@define('SYNDICATE_THIS_BLOG', 'Âçåìè íîâèíè îò òîçè áëîã');
+@define('YOU_CHOSE', 'Âèå èçáðàõòå %s');
+@define('IMAGE_SIZE', 'Ãîëåìèíà íà êàðòèíêàòà');
+@define('IMAGE_AS_A_LINK', 'Âúâåæäàíå íà êàðòèíêàòà');
+@define('POWERED_BY', 'Íàïðàâåí îò');
+@define('TRACKBACKS', 'Ïðîñëåäÿâàíèÿ');
+@define('TRACKBACK', 'Ïðîñëåäÿâàíå');
+@define('NO_TRACKBACKS', 'íÿìà ïðîñëåäÿâàíèÿ');
+@define('TOPICS_OF', 'Çàãëàâèÿ íà');
+@define('VIEW_FULL', 'ïîêàæè öÿëàòà');
+@define('VIEW_TOPICS', 'ïîêàæè çàãëàâèÿòà');
+@define('AT', 'íà');
+@define('SET_AS_TEMPLATE', 'Íåêà äà áúäå òåìïëåéò');
+@define('VIEW_EXTENDED_ENTRY', 'Âèæ öÿëîòî ñúäúðæàíèå');
+@define('IN', 'â');
+@define('EXCERPT', 'Excerpt');
+@define('TRACKED', 'Ïðîñëåäåíè');
+@define('LINK_TO_ENTRY', 'Link to entry');
+@define('LINK_TO_REMOTE_ENTRY', 'Âðúçêà êúì âúíøíî ñúäúðæàíèå');
+@define('IP_ADDRESS', 'IP-àäðåñ');
+@define('USER', 'Ïîòðåáèòåë');
+@define('THUMBNAIL_USING_OWN', 'Èçïîëçâàéòå %s êàòî òúìáíåéë, çàøîòî è ñåãà å ñ ìàëêè ðàçìåðè.');
+@define('THUMBNAIL_FAILED_COPY', 'Èñêàòå äà èçïîëçâàòåe %s êàòî òóìáíåéë, íî íå ñòàâà. Íå ìîãà äà ãî êîïèðàì!');
+@define('AUTHOR', 'Àâòîðr');
+@define('LAST_UPDATED', 'Ïîñëåäíî ïðîìåíåí');
+@define('TRACKBACK_SPECIFIC', 'Ïðîñëåäè îïðåäåëåí URI çà òîâà ñúäúðæàíèå');
+@define('DIRECT_LINK', 'Äèðåêòåí ëèíê êúì òîâà ñúäúðæàíèå');
+@define('COMMENT_ADDED', 'Êîìåíòàðà Âè áåøå äîáàâåí óñïåøíî. ');
+@define('COMMENT_ADDED_CLICK', 'êëèêíåòå %s òóê çà äà ñå âúðíåòå%s êúì êîìåíòàðà, è òóê %s çà äà çàòâîðèòåe%s òîçè ïðîçîðåö.');
+@define('COMMENT_NOT_ADDED', 'Íå ìîæåòå äà äîáàâèòå êîìåíòàð, çàøîòî ñà çàáðàíåíè êîìåíòàðèòå êúì òîâà ñúäúðæàíèå.');
+@define('COMMENT_NOT_ADDED_CLICK', 'Êëèêíåòå %s òóê çà äà ñå âúðíåòå%s êúì êîìåíòàðà, è òóê %s çà äà çàòâîðèòåe%s òîçè ïðîçîðåö.');
+@define('COMMENTS_DISABLE', 'Çàáðàíåòå êîìåíòàðèòå êúì òàçè ñòàòèÿ');
+@define('COMMENTS_ENABLE', 'Ðàçðåøåòå êîìåíòàðèòå êúì òàçè ñòàòèÿ');
+@define('COMMENTS_CLOSED', 'Àâòîðà å çàáðàíèë êîìåíòàðèòå êúì ñòàòèÿòà');
+@define('EMPTY_COMMENT', 'Êîìåíòàðúò Âè íå ñúäúðæà íèùî, ìîëÿ âúðíåòå ñå%s %s è ïðîáâàéòå îòíîâî');
+@define('ENTRIES_FOR', 'Ñúäúðæàíèå çà %s');
+@define('DOCUMENT_NOT_FOUND', 'Äîêóìåíòà %s íå å íàìåðåí.');
+@define('USERNAME', 'Ïîòðåáèòåë');
+@define('PASSWORD', 'Ïàðîëà');
+@define('AUTOMATIC_LOGIN', 'Çàïàçè èíôîðìàöèÿòà.');
+@define('SERENDIPITY_INSTALLATION', 'Serendipity èíñòàëèðàíå');
+@define('LEFT', 'ëÿâî');
+@define('RIGHT', 'äÿñíî');
+@define('HIDDEN', 'ñêðèòî');
+@define('REMOVE_TICKED_PLUGINS', 'Ìàõíè îòáåëÿçàíèòå ìîäóëè');
+@define('SAVE_CHANGES_TO_LAYOUT', 'Ñúõðàíè ïðîìåíèòå');
+@define('COMMENTS_FROM', 'Êîìåíòàðè îò');
+@define('ERROR', 'Ãðåøêà');
+@define('ENTRY_SAVED', 'Çàïàçåíî å');
+@define('DELETE_SURE', 'Ñèãóðåí ëè ñòå,÷å èñêàòå äà èçòðèåòå #%s çàâèíàãè?');
+@define('NOT_REALLY', 'Íå ñúâñåì...');
+@define('DUMP_IT', 'Äàâàé it!');
+@define('RIP_ENTRY', 'Ïî÷åâàé â ìèð, íîìåð  #%s');
+@define('CATEGORY_DELETED', 'ÊÀòåãîðèÿòà #%s å èçòðèòà. Ñòàòèèòå ñà ïðåìåñòåíè êúì êàòåãîðèÿ #%s');
+@define('INVALID_CATEGORY', 'Íÿìà êàòåãîðèÿ çà èçòðèâàíå');
+@define('CATEGORY_SAVED', 'ÊÀòåãîðèÿòà å çàïàçåíà');
+@define('SELECT_TEMPLATE', 'ÈÇáåðåòå âúíøíèÿ âèä íà áëîã-à ñè');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'Ñúäúðæàíèåòî íå áåïå ïóáëèêóâàíî!');
+@define('YES', 'Äà');
+@define('NO', 'Íå');
+@define('CHECK_N_SAVE', 'Èçáåðè  &amp; Çàïàçè');
+@define('DIRECTORY_WRITE_ERROR', 'Íå ìîãà äà ïèøà â ïàïêà: %s. Ïðîâåðè äàëè ìîæå äà ñå ïèøå òàì.');
+@define('DIRECTORY_CREATE_ERROR', 'Ïàïêàòà  %s íå ñúøåñòâóâà è íå ìîæå äà áúäå ñúçäàäåíà.Ñúçäàéòå ÿ ðú÷íî !!!');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; èçïúëíåòå òàçè êîìàíäà: <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', 'Íå ìîãà äà èçïúëíÿ òîâà %s ');
+@define('FILE_WRITE_ERROR', 'Íå ìîãà äà ïèøà â òîçè ôàéë %s.');
+@define('FILE_CREATE_YOURSELF', 'Ìîëÿ ñúçäàéòå ôàéëà ñàìè è ïðîâåðåòå äàëè ìîæå äà ñå ïèøå â íåãî');
+@define('COPY_CODE_BELOW', '<br />* Ñàìî êîïèðàéòå êîäà è ãî ñëîæåòå â  %s â ïàïêà %s <b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Ïðîìåíåòå www íà ïîòðåáèòåë apache äà ñå èçïóëíÿâà êàòî nobody.');
+@define('BROWSER_RELOAD', 'Êàòî íàïðàâèòå òîâà, íàòèñíåòå "reload" áóòîíà.');
+@define('DIAGNOSTIC_ERROR', 'Çàñÿêîõìå íÿêîëêî ãðåøêè ïðè âúâåäåíàòà èíôîðìàöèÿ îò Âàñ:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity îøå íå å èíñòàëèðàíà. ìîëÿ êëèíåòå íà òîçè  <a href="%s">ëèíê</a>.');
+@define('INCLUDE_ERROR', 'serendipity ãðåøêà: íå ìîãà äà âìúêíà òîçè ôàéë %s - èçëèçàì.');
+@define('DATABASE_ERROR', 'serendipity ãðåøêà: íå ìîãà äà ñå ñâúðæà ñ áàçàòà äàííè - èçëèçàì.');
+@define('CREATE_DATABASE', 'Ñúçäàâàì áàçàòà äàííè...');
+@define('ATTEMPT_WRITE_FILE', 'Ïðîáâàì äà ïèøà âúâ ôàéë %s ...');
+@define('WRITTEN_N_SAVED', 'Êîíôèãóðàöèÿòà å çàïèñàíà');
+@define('IMAGE_ALIGNMENT', 'Ïîëîæåíèå íà èçîáðàæåíèåòî');
+@define('ENTER_NEW_NAME', 'Âúâåäåòå èìå çà: ');
+@define('RESIZING', 'Ïðîìåíÿíå íà ðàçìåðèòå');
+@define('RESIZE_DONE', 'Ãîòîâî (ïðîìåíåíè %s êàðòèíêè).');
+@define('SYNCING', 'Ñèíõðîíèçèðàíå íà áàçàòà äàííè ñ ïàïêàòà ñ êàðòèíêèòå');
+@define('SYNC_DONE', 'Ãîòîâî (ñèíõðîíèçèðàíè %s êàðòèíêè).');
+@define('DELETE_IMAGE_FAIL' , 'Íå ìîãà äà èçòðèÿ èçîáðàæåíèå <b>%s</b>');
+@define('DELETE_THUMBNAIL', 'Èçòðèâàíå íà òúìáíåéë <b>%s</b>');
+@define('FILE_NOT_FOUND', 'Íå ìîãà äà íàìåðÿ ôàéëà <b>%s</b>, ìîæå áè âå÷å å èçòðèò?');
+@define('ABORT_NOW', 'Ñïðåòå äåéñòâèåòî ñåãà');
+@define('REMOTE_FILE_NOT_FOUND', 'Ôàéëà íå å íàìåðåí íà îòäàëå÷åíèÿ ñúðâúð, ñèãóðåí ëè ñòå ÷ð àäðåñà: <b>%s</b> å âåðåí?');
+@define('FILE_FETCHED', '%s èçòåãëåí êàòî %s');
+@define('FILE_UPLOADED', 'Ôàéëà %s å óñïåøíî êà÷åí êàòî %s');
+@define('WORD_OR', 'Èëè');
+@define('SCALING_IMAGE', 'Ïðîìåíÿì %s äî %s x %s px');
+@define('KEEP_PROPORTIONS', 'Çàïàçåòå ïðîìîðöèèòå');
+@define('REALLY_SCALE_IMAGE', 'Ñèãóðíè ëè ñòå? Íàìà âðúøàíå íàçàä!');
+@define('TOGGLE_ALL', 'Ïîêàæè âñè÷êè');
+@define('TOGGLE_OPTION', 'Toggle');
+@define('SUBSCRIBE_TO_THIS_ENTRY', 'Çàïèøåòå ñå çà òîçè ìàòåðèàë');
+@define('UNSUBSCRIBE_OK', "%s å îòèñàí îò òîçè ìàòåðèàë");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'Íîâ êîìåíòàð: "%s"');
+@define('SUBSCRIPTION_MAIL', "Çäðàâåé %s,\n\nÍîâ êîìåíòàð å íàïðàâåí ïî ìàòåðèàëà êîéòî ñëåäèòå \"%s\", îçàãëàâåí \"%s\"\nÈìåòî íà òîçè, êîéòî å ïóáëèêóâàë å: %s\n\nÌîæåòå äà íàìåðèòå ñúäúðæàíèåòî òóê: %s\n\nÌîæåòå äà ñå îòïèøåòå, êëèêâàéêè íà òîçè ëèíê %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "Çäðàâåé %s,\n\nÍîâ êîìåíòàð å íàïðàâåí ïî ìàòåðèàëà êîéòî ñëåäèòå \"%s\", îçàãëàâåí \"%s\"\nÈìåòî íà òîçè, êîéòî å ïóáëèêóâàë å: %s\n\nÌîæåòå äà íàìåðèòå ñúäúðæàíèåòî òóê: %s\n\nÌîæåòå äà ñå îòïèøåòå, êëèêâàéêè íà òîçè ëèíê %s\n");
+@define('SIGNATURE', "\n-- \n%s is íàïðàâåí îò Serendipity.\nÍàé-äîáðèÿò áëîã.\nÌîæåòå äà ñè ãî ñâàëèòå îò òóê <http://s9y.org> .");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91 ');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0 ');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0 ');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 êîìåíòàðè');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'Ïîëå "managingEditor"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  'Ïîëå "webMaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'Êàðòèíêà çà RSS êàíàëà');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', 'Äúëæèíà íà êàðòèíêàòà');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'Âèñî÷èíà íà êàðòèíêàòà');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  'E-Mail àäðåñà íà óåá ìàéñòîðà (empty: hidden) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', 'E-Mail àäðåñà íà òîçè êîéòî ïèøå ñúäúðæàíèå. (empty: hidden) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'URL í àêàðòèíêà(GIF/JPEG/PNG) (empty: serendipity-logo)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'â ïèêñåëè, ìàêñ. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'â ïèêñåëè, ìàêñ. 400');
+@define('SYNDICATION_PLUGIN_TTL', 'Ïîëå "ttl" (time-to-live)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'Ñëåä êîëêî ìèíóòè áëîãà Âè äà áúäå êåøèðàí (empty: hidden) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'Ïîëå "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', 'Òðÿáâà ëè äà èìà è ïîëå "pubDate"?');
+@define('CONTENT', 'Ñúäúðæàíèå');
+@define('TYPE', 'Tèï');
+@define('DRAFT', 'Draft');
+@define('PUBLISH', 'Ïóáëèêóâàé');
+@define('PREVIEW', 'Ïðåãëåäàé');
+@define('DATE', 'Data');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', 'Âíèìàíèå: Ïîñî÷åíàòà äàòà íå å âàëèäíàd. Òðÿáâà äà å â ñëåäíèÿ ôîðìàò YYYY-MM-DD HH:MM ');
+@define('CATEGORY_PLUGIN_DESC', 'Ïîêàçè ñïèñúêà íà êàòåãîðèèòå.');
+@define('ALL_AUTHORS', 'Âñè÷êè àâòîðè');
+@define('CATEGORIES_TO_FETCH', 'Êàòåãîðèè çà èçâëè÷àíå');
+@define('CATEGORIES_TO_FETCH_DESC', 'Èçâëå÷è êàòåãîðèèòå çà âñåêè àâòîð?');
+@define('PREVIOUS_PAGE', 'ïðåäèøíà ñòðàíèöà');
+@define('NEXT_PAGE', 'ñëåäâàøà ñòðàíèöà');
+@define('ALL_CATEGORIES', 'Âñè÷êè êàòåãîðèè');
+@define('DO_MARKUP', 'Ïðåìèíè êúì òðàíñôîðìàöèÿ');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'Ôîðìàòèðàíå íà äàòàòà');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'Ôîðìàòà íà äàòàòà íà ñúäúðæàíèåòî å íàïðàâåíî ïîñðåäñòâîì ôóíêöèÿòà íà PHP strftime() (Default: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'Íå ìîãà äà îòâîðÿ ôàéëà ñ òåìïëåéòèòå, ìîëÿ ñâàëåòå ñè ïîñëåäíàòà âåðñèÿ íà serendipity!');
+@define('ADVANCED_OPTIONS', 'Advanced âúçìîæíîñòè');
+@define('EDIT_ENTRY', 'Ðåäàêòèðàé');
+@define('HTACCESS_ERROR', 'Çà äà ïðîâåðè ñúðâúðà âè, serendipity òðÿáâà äà ìîæå äà ïèøå âúâ ôàéëà ".htaccess". Òîâà íå å âúçìîæíî,ìîëÿ ïðîìåíåòå ïðàâàòà çà ïèñàíå âúðõó òîçè ôàéë ì åòî òàêà <br />&nbsp;&nbsp;%s<br /> è ïðåçàðåäåòå ñòðàíèöàòà.');
+@define('SIDEBAR_PLUGINS', 'Ñòðàíè÷íè ìîäóëè');
+@define('EVENT_PLUGINS', 'Ìîäóëè çà ñúáèòèÿ');
+@define('SORT_ORDER', 'Ñîðòèðàíå ïî');
+@define('SORT_ORDER_NAME', 'Èìå íà ôàéë');
+@define('SORT_ORDER_EXTENSION', 'Ðàçøèðåíèå');
+@define('SORT_ORDER_SIZE', 'Ãîëåìèíà íà ôàéëà');
+@define('SORT_ORDER_WIDTH', 'Äúëæèíà íà èçîáðàæåíèåòî');
+@define('SORT_ORDER_HEIGHT', 'Âèñî÷èíà íà èçîáðàæåíèåòî');
+@define('SORT_ORDER_DATE', 'Äàòà íà êà÷âàíå');
+@define('SORT_ORDER_ASC', 'Íàìàëÿâàù');
+@define('SORT_ORDER_DESC', 'Óâåëè÷àâàø');
+@define('THUMBNAIL_SHORT', 'Òóìáíåéë');
+@define('ORIGINAL_SHORT', 'Îðèãèíàëåí.');
+@define('APPLY_MARKUP_TO', 'Ïðèëîæè äåéñòâèåòî íà %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'Íà÷àëî íà ñåäìèöàòà');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity ðàçáðà ,÷å âàïàòà êîíôèãèðàöèÿ å çà âåðñèÿ %s, ìîëÿ âçåìåòå íîâà âåðñèÿ îò òóê: <a href="%s">Click here</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'Çäðàâåéòå, è äîáðå äîøëè â ïðîãðàìàòà çà àêòóàëèçàöèÿ.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', 'Àç ñúì òóê çà äà àêòóàëèçèðàì Serendipity %s.');
+@define('SERENDIPITY_UPGRADER_WHY', 'Âèå âèæäàòå òîâà ñúîáùåíèå çàùîòî òîêó ùî èíñòàëèðàõòå Serendipity %s, íî íÿìàòå îùå àêòóàëèçàöèÿ íà áàçàòà äàííè');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'Àêòóàëèçàöèÿ íà áàçàòà äàííè (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'Íàìåðèõìå ñëåäíèòå .sql ôàéëîâå, êîéòî Âèå òðÿáâà äà èçïúëíèòå çà äà ìîæå èíñòàëàöèÿòà äà ïðîäúëæè');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  'ñïåöèôè÷íè îïåðàöèè çà òàçè âåðñèÿ');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', 'Íÿìà íàìåðåíè òàêèâà');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', 'Èñêàòå ëè äà ïðåäïðèåìåòå òèçå äåéñòâèÿ?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'Íå, ùå ñè ãè íàïðàâÿ ðú÷íî');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'Äà');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'Èçãëåæäà íÿìà íóæäà îò àêòóàëèçàöèÿ íà âåðñèÿòà');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', 'Serendipity å àêòóàëèçèðàí');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'Âèå ïðåíåáðåãíàõòå àêòóàëèçàöèîííàòà ïðîãðàìà , ìîëÿ óâåðåòå ñå ÷å èìàòå âñè÷êè ïðîìåíè ïðåäè äà ïðèñòúïèòå êúì ðàáîòà');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'Serendipity ñåãà âå÷å å âåðñèÿ %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', 'Ìîæåòå äà ñå âúðíåòå êúì áëîãà Âè êàòî êëèêíåòå  %sòóê%s');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'No Trackback sent: Could not open connection to %s on port %d'); // Translate
+@define('MEDIA', 'Media'); // Translate
+@define('MEDIA_LIBRARY', 'Media library'); // Translate
+@define('ADD_MEDIA', 'Add media'); // Translate
+@define('ENTER_MEDIA_URL', 'Enter an URL of a file to fetch:'); // Translate
+@define('ENTER_MEDIA_UPLOAD', 'Select a file you wish to upload:'); // Translate
+@define('SAVE_FILE_AS', 'Save the file as:'); // Translate
+@define('STORE_IN_DIRECTORY', 'Store inside the following directory: '); // Translate
+@define('MEDIA_RENAME', 'Rename this file'); // Translate
+@define('IMAGE_RESIZE', 'Resize this image'); // Translate
+@define('MEDIA_DELETE', 'Delete this file'); // Translate
+@define('FILES_PER_PAGE', 'Files per page'); // Translate
+@define('CLICK_FILE_TO_INSERT', 'Click the file you want to insert:'); // Translate
+@define('SELECT_FILE', 'Select file to insert'); // Translate
+@define('MEDIA_FULLSIZE', 'Fullsize'); // Translate
+@define('CALENDAR_BOW_DESC', 'The day of the week that should be considered the beginning of the week. Default is Monday'); // Translate
+@define('SUPERUSER', 'Blog Administration'); // Translate
+@define('ALLOWS_YOU_BLAHBLAH', 'Provides a link in the sidebar to your blog administration'); // Translate
+@define('CALENDAR', 'Calendar'); // Translate
+@define('QUICKJUMP_CALENDAR', 'A calendar to navigate in your blog'); // Translate
+@define('SUPERUSER_OPEN_ADMIN', 'Open administration'); // Translate
+@define('SUPERUSER_OPEN_LOGIN', 'Open login screen'); // Translate
+@define('INVERT_SELECTIONS', 'Invert Selections'); // Translate
+@define('COMMENTS_DELETE_CONFIRM', 'Are you sure you wish to delete the selected comments?'); // Translate
+@define('COMMENT_DELETE_CONFIRM', 'Are you sure you wish to delete comment #%d, written by %s?'); // Translate
+@define('DELETE_SELECTED_COMMENTS', 'Delete selected comments'); // Translate
+@define('VIEW_COMMENT', 'View comment'); // Translate
+@define('VIEW_ENTRY', 'View entry'); // Translate
+@define('DELETE_FILE', 'Deleted the file entitled <b>%s</b>'); // Translate
+@define('ABOUT_TO_DELETE_FILE', 'You are about to delete <b>%s</b><br />If you are using this file in some of your entries, it will cause dead links or images<br />Are you sure you wish to proceed?<br /><br />'); // Translate
+@define('TRACKBACK_SENDING', 'Sending trackback to URI %s...'); // Translate
+@define('TRACKBACK_SENT', 'Trackback successful'); // Translate
+@define('TRACKBACK_FAILED', 'Trackback failed: %s'); // Translate
+@define('TRACKBACK_NOT_FOUND', 'No trackback-URI found.'); // Translate
+@define('TRACKBACK_URI_MISMATCH', 'The autodiscovered trackback URI does not match our target URI.'); // Translate
+@define('TRACKBACK_CHECKING', 'Checking <u>%s</u> for possible trackbacks...'); // Translate
+@define('TRACKBACK_NO_DATA', 'Target contained no data'); // Translate
+@define('TRACKBACK_SIZE', 'Target URI exceeded maximum filesize of %s bytes.'); // Translate
+@define('VIEWMODE_THREADED', 'Switch to threaded view'); // Translate
+@define('COMMENTS_VIEWMODE_THREADED', 'Threaded'); // Translate
+@define('COMMENTS_VIEWMODE_LINEAR', 'Linear'); // Translate
+@define('DISPLAY_COMMENTS_AS', 'Display comments as'); // Translate
+@define('DATE_FORMAT_SHORT', '%Y-%m-%d %H:%M'); // Translate
+@define('NUMBER_FORMAT_DECIMALS', '2'); // Translate
+@define('NUMBER_FORMAT_DECPOINT', '.'); // Translate
+@define('NUMBER_FORMAT_THOUSANDS', ','); // Translate
+@define('ERROR_UNKNOWN_NOUPLOAD', 'Unknown error occured, file not uploaded. Maybe your filesize is larger than the maximum size allowed by your server installation. Check with your ISP or edit your php.ini file to allow larger file size uploads.'); // Translate
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Category #%s deleted. Old articles moved to category #%s'); // Translate
+@define('USE_DEFAULT', 'Default'); // Translate
+@define('PAGE_BROWSE_ENTRIES', 'Page %s of %s, totalling %s entries'); // Translate
+@define('MANAGE_USERS', 'Manage users'); // Translate
+@define('CREATE_NEW_USER', 'Create new user'); // Translate
+@define('CREATE_NOT_AUTHORIZED', 'You cannot modify users with the same userlevel as yourself'); // Translate
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'You cannot create users with a higher userlevel than yourself'); // Translate
+@define('CREATED_USER', 'A new user %s has been created'); // Translate
+@define('MODIFIED_USER', 'The properties of user %s have been changed'); // Translate
+@define('USER_LEVEL', 'Userlevel'); // Translate
+@define('DELETE_USER', 'You are about to delete user #%d %s. Are you serious? This will disallow showing any entries written by him on the frontend.'); // Translate
+@define('DELETED_USER', 'User #%d %s deleted.'); // Translate
+@define('LIMIT_TO_NUMBER', 'How many items should be displayed?'); // Translate
+@define('ENTRIES_PER_PAGE', 'entries per page'); // Translate
+@define('XML_IMAGE_TO_DISPLAY', 'XML Button'); // Translate
+@define('DIRECTORIES_AVAILABLE', 'In the list of available subdirectories you can click on any directory name to create a new directory within that structure.'); // Translate
+@define('ALL_DIRECTORIES', 'all directories'); // Translate
+@define('MANAGE_DIRECTORIES', 'Manage directories'); // Translate
+@define('DIRECTORY_CREATED', 'Directory <strong>%s</strong> has been created.'); // Translate
+@define('PARENT_DIRECTORY', 'Parent directory'); // Translate
+@define('CONFIRM_DELETE_DIRECTORY', 'Are you sure you want to remove all the contents of directory %s?'); // Translate
+@define('ERROR_NO_DIRECTORY', 'Error: Directory %s does not exist'); // Translate
+@define('CHECKING_DIRECTORY', 'Checking files in directory %s'); // Translate
+@define('DELETING_FILE', 'Deleting file %s...'); // Translate
+@define('ERROR_DIRECTORY_NOT_EMPTY', 'Could not remove non-empty directory. Check the "force deletion" checkbox if you want to remove those files as well, and then submit again. Existing files are:'); // Translate
+@define('DIRECTORY_DELETE_FAILED', 'Deletion of directory %s failed. Check permissions or messages above.'); // Translate
+@define('DIRECTORY_DELETE_SUCCESS', 'Directory %s successfully deleted.'); // Translate
+@define('SKIPPING_FILE_EXTENSION', 'Skipping file: Missing extension on %s.'); // Translate
+@define('SKIPPING_FILE_UNREADABLE', 'Skipping file: %s not readable.'); // Translate
+@define('FOUND_FILE', 'Found new/modified file: %s.'); // Translate
+@define('ALREADY_SUBCATEGORY', '%s is a already a subcategory of %s.'); // Translate
+@define('PARENT_CATEGORY', 'Parent category'); // Translate
+@define('IN_REPLY_TO', 'In reply to'); // Translate
+@define('TOP_LEVEL', 'Top level'); // Translate
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s feed'); // Translate
+@define('PERMISSIONS', 'Permissions'); // Translate
+@define('SETTINGS_SAVED_AT', 'The new settings have been saved at %s'); // Translate
+@define('INSTALL_CAT_DB', 'Database settings'); // Translate
+@define('INSTALL_CAT_DB_DESC', 'Here you can enter all your database information. Serendipity needs this to be able to function'); // Translate
+@define('INSTALL_DBTYPE', 'Database type'); // Translate
+@define('INSTALL_DBTYPE_DESC', 'Database type'); // Translate
+@define('INSTALL_DBHOST', 'Database host'); // Translate
+@define('INSTALL_DBHOST_DESC', 'The hostname for your database server'); // Translate
+@define('INSTALL_DBUSER', 'Database user'); // Translate
+@define('INSTALL_DBUSER_DESC', 'The username used to connect to your database'); // Translate
+@define('INSTALL_DBPASS', 'Database password'); // Translate
+@define('INSTALL_DBPASS_DESC', 'The password matching the above username'); // Translate
+@define('INSTALL_DBNAME', 'Database name'); // Translate
+@define('INSTALL_DBNAME_DESC', 'The name of your database'); // Translate
+@define('INSTALL_DBPREFIX', 'Database table prefix'); // Translate
+@define('INSTALL_DBPREFIX_DESC', 'Prefix for the table names, i.e. serendipity_'); // Translate
+@define('INSTALL_CAT_PATHS', 'Paths'); // Translate
+@define('INSTALL_CAT_PATHS_DESC', 'Various paths to different essential folders and files. Don\'t forget trailing slashes for directories!'); // Translate
+@define('INSTALL_FULLPATH', 'Full path'); // Translate
+@define('INSTALL_FULLPATH_DESC', 'The full and absolute path to your serendipity installation'); // Translate
+@define('INSTALL_UPLOADPATH', 'Upload path'); // Translate
+@define('INSTALL_UPLOADPATH_DESC', 'All uploads will go here, relative to the \'Full path\' - typically \'uploads/\''); // Translate
+@define('INSTALL_RELPATH', 'Relative path'); // Translate
+@define('INSTALL_RELPATH_DESC', 'Path to serendipity for your browser, typically \'/serendipity/\''); // Translate
+@define('INSTALL_RELTEMPLPATH', 'Relative template path'); // Translate
+@define('INSTALL_RELTEMPLPATH_DESC', 'The path to the folder containing your templates - Relative to the \'relative path\''); // Translate
+@define('INSTALL_RELUPLOADPATH', 'Relative upload path'); // Translate
+@define('INSTALL_RELUPLOADPATH_DESC', 'Path to your uploads for browsers - Relative to the \'relative path\''); // Translate
+@define('INSTALL_URL', 'URL to blog'); // Translate
+@define('INSTALL_URL_DESC', 'Base URL to your serendipity installation'); // Translate
+@define('INSTALL_INDEXFILE', 'Index file'); // Translate
+@define('INSTALL_INDEXFILE_DESC', 'The name of your serendipity index file'); // Translate
+@define('INSTALL_CAT_SETTINGS', 'General settings'); // Translate
+@define('INSTALL_CAT_SETTINGS_DESC', 'Customize how Serendipity behaves'); // Translate
+@define('INSTALL_USERNAME', 'Admin username'); // Translate
+@define('INSTALL_USERNAME_DESC', 'Username for admin login'); // Translate
+@define('INSTALL_PASSWORD', 'Admin password'); // Translate
+@define('INSTALL_PASSWORD_DESC', 'Password for admin login'); // Translate
+@define('INSTALL_EMAIL', 'Admin email'); // Translate
+@define('INSTALL_EMAIL_DESC', 'Email for the blog administrator'); // Translate
+@define('INSTALL_SENDMAIL', 'Send mails to admin?'); // Translate
+@define('INSTALL_SENDMAIL_DESC', 'Do you want to receive emails when comments are posted to your entries?'); // Translate
+@define('INSTALL_SUBSCRIBE', 'Allow users to subscribe to entries?'); // Translate
+@define('INSTALL_SUBSCRIBE_DESC', 'Allow users to subscribe to an entry and thereby receive a mail when new comments are made to that entry'); // Translate
+@define('INSTALL_BLOGNAME', 'Blog name'); // Translate
+@define('INSTALL_BLOGNAME_DESC', 'The title of your blog'); // Translate
+@define('INSTALL_BLOGDESC', 'Blog description'); // Translate
+@define('INSTALL_BLOGDESC_DESC', 'Description of your blog'); // Translate
+@define('INSTALL_LANG', 'Language'); // Translate
+@define('INSTALL_LANG_DESC', 'Select the language for your blog'); // Translate
+@define('INSTALL_CAT_DISPLAY', 'Appearance and options'); // Translate
+@define('INSTALL_CAT_DISPLAY_DESC', 'Customize how Serendipity looks and feels'); // Translate
+@define('INSTALL_WYSIWYG', 'Use WYSIWYG editor'); // Translate
+@define('INSTALL_WYSIWYG_DESC', 'Do you want to use the WYSIWYG editor? (Works on IE5+, partially in Mozilla 1.3+)'); // Translate
+@define('INSTALL_POPUP', 'Enable use of popup windows'); // Translate
+@define('INSTALL_POPUP_DESC', 'Do you want to use popup windows for comments, trackbacks et al?'); // Translate
+@define('INSTALL_EMBED', 'Is serendipity embedded?'); // Translate
+@define('INSTALL_EMBED_DESC', 'If you want to embed serendipity within a regular page, set to true to discard any headers and just print the contents. You can make use of the indexFile option to use a wrapper class where you put your normal webpage headers. See the README file for more information!'); // Translate
+@define('INSTALL_TOP_AS_LINKS', 'Show Top Exits/Referrers as links?'); // Translate
+@define('INSTALL_TOP_AS_LINKS_DESC', '"no": Exits and Referrers are shown as plain text to prevent google spam. "yes": Exits and Referrers are shown as hyperlinks. "default": Use setting from global configuration (recommended).'); // Translate
+@define('INSTALL_BLOCKREF', 'Blocked Referers'); // Translate
+@define('INSTALL_BLOCKREF_DESC', 'Are there any special hosts you want not to show up in the referers list? Separate the list of hostnames with \';\' and note that the host is blocked by substring matches!'); // Translate
+@define('INSTALL_REWRITE', 'URL Rewriting'); // Translate
+@define('INSTALL_REWRITE_DESC', 'Select which rules you wish to use when generating URLs. Enabling rewrite rules will make pretty URLs for your blog and make it better indexable for spiders like google. The webserver needs to support either mod_rewrite or "AllowOverride All" for your serendipity dir. The default setting is auto-detected'); // Translate
+@define('INSTALL_CAT_IMAGECONV', 'Imageconversion Settings'); // Translate
+@define('INSTALL_CAT_IMAGECONV_DESC', 'Enter general information about how serendipity should handle Images'); // Translate
+@define('INSTALL_IMAGEMAGICK', 'Use Imagemagick'); // Translate
+@define('INSTALL_IMAGEMAGICK_DESC', 'Do you have image magick installed and want to use it to resize images?'); // Translate
+@define('INSTALL_IMAGEMAGICKPATH', 'Path to convert binary'); // Translate
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'Full path & name of your image magick convert binary'); // Translate
+@define('INSTALL_THUMBSUFFIX', 'Thumbnail suffix'); // Translate
+@define('INSTALL_THUMBSUFFIX_DESC', 'Thumbnails will be named with the following format: original.[suffix].ext'); // Translate
+@define('INSTALL_THUMBWIDTH', 'Thumbnail dimensions'); // Translate
+@define('INSTALL_THUMBWIDTH_DESC', 'Static maximum width of auto-generated thumbnails'); // Translate
+@define('USERCONF_CAT_PERSONAL', 'Your personal details'); // Translate
+@define('USERCONF_CAT_PERSONAL_DESC', 'Change your personal details'); // Translate
+@define('USERCONF_USERNAME', 'Your username'); // Translate
+@define('USERCONF_USERNAME_DESC', 'The username you use to log in to the blog'); // Translate
+@define('USERCONF_PASSWORD', 'Your password'); // Translate
+@define('USERCONF_PASSWORD_DESC', 'The password you wish to use to log in to the blog'); // Translate
+@define('USERCONF_EMAIL', 'Your e-mail address'); // Translate
+@define('USERCONF_EMAIL_DESC', 'Your personal e-mail address'); // Translate
+@define('USERCONF_SENDCOMMENTS', 'Send comment announcements?'); // Translate
+@define('USERCONF_SENDCOMMENTS_DESC', 'Do you want to receive emails when comments are posted to your entries?'); // Translate
+@define('USERCONF_SENDTRACKBACKS', 'Send trackback announcements?'); // Translate
+@define('USERCONF_SENDTRACKBACKS_DESC', 'Do you want to receive emails when trackbacks are posted to your entries?'); // Translate
+@define('USERCONF_ALLOWPUBLISH', 'Rights: Publishing entries?'); // Translate
+@define('USERCONF_ALLOWPUBLISH_DESC', 'Is this user allowed to publish entries?'); // Translate
+@define('SUCCESS', 'Success'); // Translate
+@define('POWERED_BY_SHOW_TEXT', 'Show "Serendipity" as text'); // Translate
+@define('POWERED_BY_SHOW_TEXT_DESC', 'Will display "Serendipity Weblog" as text'); // Translate
+@define('POWERED_BY_SHOW_IMAGE', 'Show "Serendipity" with a logo'); // Translate
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Displays the Serendipity logo'); // Translate
+@define('PLUGIN_ITEM_DISPLAY', 'Where should the item be displayed?'); // Translate
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'Extended entry only'); // Translate
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'Overview page only'); // Translate
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'All times'); // Translate
+@define('RSS_IMPORT_CATEGORY', 'Use this category for non-matching imported entries'); // Translate
+@define('COMMENTS_WILL_BE_MODERATED', 'Submitted comments will be subject to moderation before being displayed.'); // Translate
+@define('YOU_HAVE_THESE_OPTIONS', 'You have the following options available:'); // Translate
+@define('THIS_COMMENT_NEEDS_REVIEW', 'Warning: This comment needs approval before it will be displayed'); // Translate
+@define('DELETE_COMMENT', 'Delete comment'); // Translate
+@define('APPROVE_COMMENT', 'Approve comment'); // Translate
+@define('REQUIRES_REVIEW', 'Requires review'); // Translate
+@define('COMMENT_APPROVED', 'Comment #%s has successfully been approved'); // Translate
+@define('COMMENT_DELETED', 'Comment #%s has successfully been deleted'); // Translate
+@define('COMMENTS_MODERATE', 'Comments & trackbacks to this entry requires moderation'); // Translate
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'Warning: This trackback needs approval before it will be displayed'); // Translate
+@define('DELETE_TRACKBACK', 'Delete trackback'); // Translate
+@define('APPROVE_TRACKBACK', 'Approve trackback'); // Translate
+@define('TRACKBACK_APPROVED', 'Trackback #%s has successfully been approved'); // Translate
+@define('TRACKBACK_DELETED', 'Trackback #%s has successfully been deleted'); // Translate
+@define('VIEW', 'View'); // Translate
+@define('COMMENT_ALREADY_APPROVED', 'Comment #%s appears to already have been approved'); // Translate
+@define('COMMENT_EDITED', 'The selected comment has been edited'); // Translate
+@define('HIDE', 'Hide'); // Translate
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'This link is not meant to be clicked. It contains the trackback URI for this entry. You can use this URI to send ping- & trackbacks from your own blog to this entry. To copy the link, right click and select "Copy Shortcut" in Internet Explorer or "Copy Link Location" in Mozilla.'); // Translate
+@define('PLUGIN_SUPERUSER_HTTPS', 'Use https for login'); // Translate
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'Lets the login-link point to a https-location. Your webserver needs to support this!'); // Translate
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'Make external links clickable?'); // Translate
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"no": Unchecked external links (Top Exits, Top Referrers, User comments) are not shown/shown as plain text where applicable to prevent google spam (recommended). "yes": Unchecked external links are shown as hyperlinks. Can be overridden within sidebar plugin configuration!'); // Translate
+@define('PAGE_BROWSE_COMMENTS', 'Page %s of %s, totalling %s comments'); // Translate
+@define('FILTERS', 'Filters'); // Translate
+@define('FIND_ENTRIES', 'Find entries'); // Translate
+@define('FIND_COMMENTS', 'Find comments'); // Translate
+@define('FIND_MEDIA', 'Find media'); // Translate
+@define('FILTER_DIRECTORY', 'Directory'); // Translate
+@define('SORT_BY', 'Sort by'); // Translate
+@define('ADD_MEDIA_BLAHBLAH', '<b>Add a file to your media repository:</b><p>Here you can upload mediafiles, or tell me to fetch them from somewhere in the web! If you don\'t have an appropriate image, <a href="http://images.google.com" target="_blank">search for images on google</a> matching your thoughts, the results are often useful and funny :)<p><b>Select method:</b><br>'); // Translate
+@define('XML_IMAGE_TO_DISPLAY_DESC', 'Links to XML Feeds will be displayed by this image. Leave empty for default, enter \'none\' to disable.'); // Translate
+@define('COMMENTS_FILTER_SHOW', 'Show'); // Translate
+@define('COMMENTS_FILTER_ALL', 'All'); // Translate
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'Only approved'); // Translate
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'Pending approval'); // Translate
+@define('RSS_IMPORT_BODYONLY', 'Put all imported text in the "body" section and do not split up into "extended entry" section.'); // Translate
+@define('SYNDICATION_PLUGIN_FULLFEED', 'Show full articles with extended body inside RSS feed'); // Translate
+@define('MT_DATA_FILE', 'Movable Type data file'); // Translate
+@define('FORCE', 'Force'); // Translate
+@define('CREATE_AUTHOR', 'Create author \'%s\'.'); // Translate
+@define('CREATE_CATEGORY', 'Create category \'%s\'.'); // Translate
+@define('MYSQL_REQUIRED', 'You must have the MySQL extension in order to perform this action.'); // Translate
+@define('COULDNT_CONNECT', 'Could not connect to MySQL database: %s.'); // Translate
+@define('COULDNT_SELECT_DB', 'Could not select database: %s.'); // Translate
+@define('COULDNT_SELECT_USER_INFO', 'Could not select user information: %s.'); // Translate
+@define('COULDNT_SELECT_CATEGORY_INFO', 'Could not select category information: %s.'); // Translate
+@define('COULDNT_SELECT_ENTRY_INFO', 'Could not select entry information: %s.'); // Translate
+@define('COULDNT_SELECT_COMMENT_INFO', 'Could not select comment information: %s.'); // Translate
+@define('WEEK', 'Week'); // Translate
+@define('WEEKS', 'Weeks'); // Translate
+@define('MONTHS', 'Months'); // Translate
+@define('DAYS', 'Days'); // Translate
+@define('ARCHIVE_FREQUENCY', 'Calendar item frequency'); // Translate
+@define('ARCHIVE_FREQUENCY_DESC', 'The calendar interval to use between each item in the list'); // Translate
+@define('ARCHIVE_COUNT', 'Number of items in the list'); // Translate
+@define('ARCHIVE_COUNT_DESC', 'The total number of months, weeks or days to display'); // Translate
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'Below is a list of installed plugins'); // Translate
+@define('SIDEBAR_PLUGIN', 'sidebar plugin'); // Translate
+@define('EVENT_PLUGIN', 'event plugin'); // Translate
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'Click here to install a new %s'); // Translate
+@define('VERSION', 'version'); // Translate
+@define('INSTALL', 'Install'); // Translate
+@define('ALREADY_INSTALLED', 'Already installed'); // Translate
+@define('SELECT_A_PLUGIN_TO_ADD', 'Select the plugin which you wish to install'); // Translate
+@define('INSTALL_OFFSET', 'Server time Offset'); // Translate
+@define('STICKY_POSTINGS', 'Sticky Postings'); // Translate
+@define('INSTALL_FETCHLIMIT', 'Entries to display on frontpage'); // Translate
+@define('INSTALL_FETCHLIMIT_DESC', 'Number of entries to display for each page on the frontend'); // Translate
+@define('IMPORT_ENTRIES', 'Import data'); // Translate
+@define('EXPORT_ENTRIES', 'Export entries'); // Translate
+@define('IMPORT_WELCOME', 'Welcome to the Serendipity import utility'); // Translate
+@define('IMPORT_WHAT_CAN', 'Here you can import entries from other weblog software applications'); // Translate
+@define('IMPORT_SELECT', 'Please select the software you wish to import from'); // Translate
+@define('IMPORT_PLEASE_ENTER', 'Please enter the data as requested below'); // Translate
+@define('IMPORT_NOW', 'Import now!'); // Translate
+@define('IMPORT_STARTING', 'Starting import procedure...'); // Translate
+@define('IMPORT_FAILED', 'Import failed'); // Translate
+@define('IMPORT_DONE', 'Import successfully completed'); // Translate
+@define('IMPORT_WEBLOG_APP', 'Weblog application'); // Translate
+@define('EXPORT_FEED', 'Export full RSS feed'); // Translate
+@define('STATUS', 'Status after import'); // Translate
+@define('IMPORT_GENERIC_RSS', 'Generic RSS import'); // Translate
+@define('ACTIVATE_AUTODISCOVERY', 'Send Trackbacks to links found in the entry'); // Translate
+@define('WELCOME_TO_ADMIN', 'Welcome to the Serendipity Administration Suite.'); // Translate
+@define('PLEASE_ENTER_CREDENTIALS', 'Please enter your credentials below.'); // Translate
+@define('ADMIN_FOOTER_POWERED_BY', 'Powered by Serendipity %s and PHP %s'); // Translate
+@define('INSTALL_USEGZIP', 'Use gzip compressed pages'); // Translate
+@define('INSTALL_USEGZIP_DESC', 'To speed up delivery of pages, we can compress the pages we send to the visitor, given that his browser supports this. This is recommended'); // Translate
+@define('INSTALL_SHOWFUTURE', 'Show future entries'); // Translate
+@define('INSTALL_SHOWFUTURE_DESC', 'If enabled, this will show all entries in the future on your blog. Default is to hide those entries and only show them if the publish date has arrived.'); // Translate
+@define('INSTALL_DBPERSISTENT', 'Use persistent connections'); // Translate
+@define('INSTALL_DBPERSISTENT_DESC', 'Enable the usage of persistent database connections, read more <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">here</a>. This is normally not recommended'); // Translate
+@define('NO_IMAGES_FOUND', 'No images found'); // Translate
+@define('PERSONAL_SETTINGS', 'Personal Settings'); // Translate
+@define('REFERER', 'Referer'); // Translate
+@define('NOT_FOUND', 'Not found'); // Translate
+@define('NOT_WRITABLE', 'Not writable'); // Translate
+@define('WRITABLE', 'Writable'); // Translate
+@define('PROBLEM_DIAGNOSTIC', 'Due to a problematic diagnostic, you cannot continue with the installation before the above errors are fixed'); // Translate
+@define('SELECT_INSTALLATION_TYPE', 'Select which installation type you wish to use'); // Translate
+@define('WELCOME_TO_INSTALLATION', 'Welcome to the Serendipity Installation'); // Translate
+@define('FIRST_WE_TAKE_A_LOOK', 'First we will take a look at your current setup and attempt to diagnose any compatibility problems'); // Translate
+@define('ERRORS_ARE_DISPLAYED_IN', 'Errors are displayed in %s, recommendations in %s and success in %s'); // Translate
+@define('RED', 'red'); // Translate
+@define('YELLOW', 'yellow'); // Translate
+@define('GREEN', 'green'); // Translate
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s pre-installation report'); // Translate
+@define('RECOMMENDED', 'Recommended'); // Translate
+@define('ACTUAL', 'Actual'); // Translate
+@define('PHPINI_CONFIGURATION', 'php.ini configuration'); // Translate
+@define('PHP_INSTALLATION', 'PHP installation'); // Translate
+@define('THEY_DO', 'they do'); // Translate
+@define('THEY_DONT', 'they don\'t'); // Translate
+@define('SIMPLE_INSTALLATION', 'Simple installation'); // Translate
+@define('EXPERT_INSTALLATION', 'Expert installation'); // Translate
+@define('COMPLETE_INSTALLATION', 'Complete installation'); // Translate
+@define('WONT_INSTALL_DB_AGAIN', 'won\'t install the database again'); // Translate
+@define('CHECK_DATABASE_EXISTS', 'Checking to see if the database and tables already exists'); // Translate
+@define('CREATING_PRIMARY_AUTHOR', 'Creating primary author \'%s\''); // Translate
+@define('SETTING_DEFAULT_TEMPLATE', 'Setting default template'); // Translate
+@define('INSTALLING_DEFAULT_PLUGINS', 'Installing default plugins'); // Translate
+@define('SERENDIPITY_INSTALLED', 'Serendipity has been successfully installed'); // Translate
+@define('VISIT_BLOG_HERE', 'Visit your new blog here'); // Translate
+@define('THANK_YOU_FOR_CHOOSING', 'Thank you for choosing Serendipity'); // Translate
+@define('ERROR_DETECTED_IN_INSTALL', 'An error was detected in the installation'); // Translate
+@define('OPERATING_SYSTEM', 'Operating system'); // Translate
+@define('WEBSERVER_SAPI', 'Webserver SAPI'); // Translate
+@define('IMAGE_ROTATE_LEFT', 'Rotate image 90 degrees counter-clockwise'); // Translate
+@define('IMAGE_ROTATE_RIGHT', 'Rotate image 90 degrees clockwise'); // Translate
+@define('TEMPLATE_SET', '\'%s\' has been set as your active template'); // Translate
+@define('SEARCH_ERROR', 'The search function did not work as expected. Notice for the administrator of this blog: This may happen because of missing index keys in your database. On MySQL systems your database user account needs to be privileged to execute this query: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> The specific error returned by the database was: <pre>%s</pre>'); // Translate
+@define('EDIT_THIS_CAT', 'Editing "%s"'); // Translate
+@define('CATEGORY_REMAINING', 'Delete this category and move its entries to this category'); // Translate
+@define('CATEGORY_INDEX', 'Below is a list of categories available to your entries'); // Translate
+@define('NO_CATEGORIES', 'No categories'); // Translate
+@define('RESET_DATE', 'Reset date'); // Translate
+@define('RESET_DATE_DESC', 'Click here to reset the date to the current time'); // Translate
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Permissions can be set by running shell command: `<em>%s</em>` on the failed directory, or by setting this using an FTP program'); // Translate
+@define('WARNING_TEMPLATE_DEPRECATED', 'Warning: Your current template is using a deprecated template method, you are advised to update if possible'); // Translate
+@define('ENTRY_PUBLISHED_FUTURE', 'This entry is not yet published.'); // Translate
+@define('ENTRIES_BY', 'Entries by %s'); // Translate
+@define('PREVIOUS', 'Previous'); // Translate
+@define('NEXT', 'Next'); // Translate
+@define('APPROVE', 'Approve'); // Translate
+@define('DO_MARKUP_DESCRIPTION', 'Apply markup transformations to the text (smilies, shortcut markups via *, /, _, ...). Disabling this will preserve any HTML-code in the text.'); // Translate
+@define('CATEGORY_ALREADY_EXIST', 'A category with the name "%s" already exist'); // Translate
+@define('IMPORT_NOTES', 'Note:'); // Translate
+@define('ERROR_FILE_FORBIDDEN', 'You are not allowed to upload files with active content'); // Translate
+@define('ADMIN', 'Administration'); // Re-Translate
+@define('ADMIN_FRONTPAGE', 'Frontpage'); // Translate
+@define('QUOTE', 'Quote'); // Translate
+@define('IFRAME_SAVE', 'Serendipity is now saving your entry, creating trackbacks and performing possible XML-RPC calls. This may take a while..'); // Translate
+@define('IFRAME_SAVE_DRAFT', 'A draft of this entry has been saved'); // Translate
+@define('IFRAME_PREVIEW', 'Serendipity is now creating the preview of your entry...'); // Translate
+@define('IFRAME_WARNING', 'Your browser does not support the concept of iframes. Please open your serendipity_config.inc.php file and set $serendipity[\'use_iframe\'] variable to FALSE.'); // Translate
+@define('NONE', 'none');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Default settings for new entries'); // Translate
+@define('UPGRADE', 'Upgrade'); // Translate
+@define('UPGRADE_TO_VERSION', 'Upgrade to version %s'); // Translate
+@define('DELETE_DIRECTORY', 'Delete directory'); // Translate
+@define('DELETE_DIRECTORY_DESC', 'You are about to delete the contents of a directory that contains media files, possibly files used in some of your entries.'); // Translate
+@define('FORCE_DELETE', 'Delete ALL files in this directory, including those not known by Serendipity'); // Translate
+@define('CREATE_DIRECTORY', 'Create directory'); // Translate
+@define('CREATE_NEW_DIRECTORY', 'Create new directory'); // Translate
+@define('CREATE_DIRECTORY_DESC', 'Here you can create a new directory to place media files in. Choose the name for your new directory and select an optional parent directory to place it in.'); // Translate
+@define('BASE_DIRECTORY', 'Base directory'); // Translate
+@define('USERLEVEL_EDITOR_DESC', 'Standard editor'); // Translate
+@define('USERLEVEL_CHIEF_DESC', 'Chief editor'); // Translate
+@define('USERLEVEL_ADMIN_DESC', 'Administrator'); // Translate
+@define('USERCONF_USERLEVEL', 'Access level'); // Translate
+@define('USERCONF_USERLEVEL_DESC', 'This level is used to determine what kind of access this user has to the blog'); // Translate
+@define('USER_SELF_INFO', 'Logged in as %s (%s)'); // Translate
+@define('ADMIN_ENTRIES', 'Entries'); // Translate
+@define('RECHECK_INSTALLATION', 'Recheck installation'); // Translate
+@define('IMAGICK_EXEC_ERROR', 'Unable to execute: "%s", error: %s, return var: %d'); // Translate
+@define('INSTALL_OFFSET_DESC', 'Enter the amount of hours between the date of your webserver (current: %clock%) and your desired time zone'); // Translate
+@define('UNMET_REQUIREMENTS', 'Requirements failed: %s'); // Translate
+@define('CHARSET', 'Charset');
+@define('AUTOLANG', 'Use visitor\'s browser language as default');
+@define('AUTOLANG_DESC', 'If enabled, this will use the visitor\'s browser language setting to determine the default language of your entry and interface language.');
+@define('INSTALL_AUTODETECT_URL', 'Autodetect used HTTP-Host'); // Translate
+@define('INSTALL_AUTODETECT_URL_DESC', 'If set to "true", Serendipity will ensure that the HTTP Host which was used by your visitor is used as your BaseURL setting. Enabling this will let you be able to use multiple domain names for your Serendipity Blog, and use the domain for all follow-up links which the user used to access your blog.'); // Translate
+@define('CONVERT_HTMLENTITIES', 'Try to auto-convert HTML entities?');
+@define('EMPTY_SETTING', 'You did not specify a valid value for "%s"!');
+@define('USERCONF_REALNAME', 'Real name'); // Translate
+@define('USERCONF_REALNAME_DESC', 'The full name of the author. This is the name seen by readers'); // Translate
+@define('HOTLINK_DONE', 'File hotlinked.<br />Done.'); // Translate
+@define('ENTER_MEDIA_URL_METHOD', 'Fetch method:'); // Translate
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Note: If you choose to hotlink to server, make sure you have permission to hotlink to the designated website, or the website is yours. Hotlink allows you to use off-site images without storing them locally.'); // Translate
+@define('MEDIA_HOTLINKED', 'hotlinked'); // Translate
+@define('FETCH_METHOD_IMAGE', 'Download image to your server'); // Translate
+@define('FETCH_METHOD_HOTLINK', 'Hotlink to server'); // Translate
+@define('DELETE_HOTLINK_FILE', 'Deleted the hotlinked file entitled <b>%s</b>'); // Translate
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Show E-Mail addresses?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_cn.inc.php b/lang/serendipity_lang_cn.inc.php
new file mode 100644 (file)
index 0000000..4a618c7
--- /dev/null
@@ -0,0 +1,669 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+@define('LANG_CHARSET', 'UTF-8');
+@define('DATE_LOCALES', 'cn, zh, zh_CN.UTF-8');
+@define('DATE_FORMAT_ENTRY', '%A, %B %e. %Y');
+@define('DATE_FORMAT_SHORT', '%Y-%m-%d %H:%M');
+@define('WYSIWYG_LANG', 'en');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', '.');
+@define('NUMBER_FORMAT_THOUSANDS', ',');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Serendipity 管理套件');
+@define('HAVE_TO_BE_LOGGED_ON', '请先登入');
+@define('WRONG_USERNAME_OR_PASSWORD', '您输入了错误的帐号或密码');
+@define('APPEARANCE', '外观配置');
+@define('MANAGE_STYLES', '布景管理');
+@define('CONFIGURE_PLUGINS', '设定外挂');
+@define('CONFIGURATION', '管理设定');
+@define('BACK_TO_BLOG', '回到日记首页');
+@define('LOGIN', '登入');
+@define('LOGOUT', '登出');
+@define('LOGGEDOUT', '登出.');
+@define('CREATE', '建立');
+@define('SAVE', '储存');
+@define('NAME', '名称');
+@define('CREATE_NEW_CAT', '新增类别');
+@define('I_WANT_THUMB', '我要在文章内使用缩图.');
+@define('I_WANT_BIG_IMAGE', '我要在文章内使用大型图片.');
+@define('I_WANT_NO_LINK', ' 我要它以图片显示');
+@define('I_WANT_IT_TO_LINK', '我要它以连结显示这个 URL:');
+@define('BACK', '返回');
+@define('FORWARD', '前进');
+@define('ANONYMOUS', '匿名');
+@define('NEW_TRACKBACK_TO', '新的引用到');
+@define('NEW_COMMENT_TO', '新的回响到');
+@define('RECENT', '新文库...');
+@define('OLDER', '旧文库...');
+@define('DONE', '完成');
+@define('WELCOME_BACK', '欢迎回来,');
+@define('TITLE', '标题');
+@define('DESCRIPTION', '简介');
+@define('PLACEMENT', '位址');
+@define('DELETE', '删除');
+@define('SAVE', '储存');
+@define('UP', '上');
+@define('DOWN', '下');
+@define('ENTRIES', '文章');
+@define('NEW_ENTRY', '新增文章');
+@define('EDIT_ENTRIES', '编辑文章');
+@define('CATEGORIES', '类别');
+@define('WARNING_THIS_BLAHBLAH', "警告:\\n这个可能需要长时间如果有很多不是缩图的图片.");
+@define('CREATE_THUMBS', '重建缩图');
+@define('MANAGE_IMAGES', '管理图片');
+@define('NAME', '名称');
+@define('EMAIL', 'Email');
+@define('HOMEPAGE', '网址');
+@define('COMMENT', '回响');
+@define('REMEMBER_INFO', '记住资料? ');
+@define('SUBMIT_COMMENT', '传送回响');
+@define('NO_ENTRIES_TO_PRINT', '没有文章可以显示');
+@define('COMMENTS', '回响');
+@define('ADD_COMMENT', '新增回响');
+@define('NO_COMMENTS', '没有回响');
+@define('POSTED_BY', '作者');
+@define('ON', '在');
+@define('A_NEW_COMMENT_BLAHBLAH', '新回响已发表到您的日记 "%s", 在这个文章里面 "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', '您的日记文章 "%s" 已有了新的引用.');
+@define('NO_CATEGORY', '没有类别');
+@define('ENTRY_BODY', '文章主内容');
+@define('EXTENDED_BODY', '文章副内容');
+@define('CATEGORY', '类别');
+@define('EDIT', '编辑');
+@define('NO_ENTRIES_BLAHBLAH', '找不到此查询 %s 的文章' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', '您搜寻的 %s 显示了 %s 结果:');
+@define('SEARCH_TOO_SHORT', '您搜寻的文字必须多於 3 个字词');
+@define('IMAGE', '图片');
+@define('ERROR_FILE_NOT_EXISTS', '错误: 档案不存在!');
+@define('ERROR_FILE_EXISTS', '错误: 档案名称已被使用, 请重新输入!');
+@define('ERROR_SOMETHING', '错误: 有错误.');
+@define('ADDING_IMAGE', '新增图片...');
+@define('THUMB_CREATED_DONE', '缩图建立.<br>完成.');
+@define('ERROR_FILE_EXISTS_ALREADY', '错误: 档案已存在!');
+@define('ERROR_UNKNOWN_NOUPLOAD', '未知的错误发生, 档案还没上传. 也许你的档案大於限制的大小. 请询问您的 ISP 或修改您的 php.ini 档.');
+@define('GO', '继续!');
+@define('NEWSIZE', '新大小: ');
+@define('RESIZE_BLAHBLAH', '<b>重设大小 %s</b><p>');
+@define('ORIGINAL_SIZE', '原有的大小: <i>%sx%s</i> 像素');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>在这里您可以修改图片大小. 如果您要修改成相同的图片比例, 您只需要输入一个数值然后按 TAB -- 系统会自动帮您计算比例以免出错</p>');
+@define('QUICKJUMP_CALENDAR', '日历快速跳跃');
+@define('QUICKSEARCH', '快速搜寻');
+@define('SEARCH_FOR_ENTRY', '搜寻文章');
+@define('ARCHIVES', '保存文库');
+@define('BROWSE_ARCHIVES', '以月份浏览保存文库');
+@define('TOP_REFERRER', '主要来源');
+@define('SHOWS_TOP_SITES', '显示连结到您的日记的网站');
+@define('TOP_EXITS', '主要出源');
+@define('SHOWS_TOP_EXIT', '显示您的日记的主要出源');
+@define('SYNDICATION', '文章同步');
+@define('SHOWS_RSS_BLAHBLAH', '显示 RSS 同步连结');
+@define('ADVERTISES_BLAHBLAH', '宣传您的网路日记');
+@define('HTML_NUGGET', 'HTML 讯息');
+@define('HOLDS_A_BLAHBLAH', '显示 HTML 讯息到侧列');
+@define('TITLE_FOR_NUGGET', '讯息的标题');
+@define('THE_NUGGET', 'HTML 讯息!');
+@define('SYNDICATE_THIS_BLOG', '同步这个日记');
+@define('YOU_CHOSE', '您选择 %s');
+@define('IMAGE_SIZE', '图片大小');
+@define('IMAGE_AS_A_LINK', '输入图片');
+@define('POWERED_BY', 'Powered by');
+@define('TRACKBACKS', '引用');
+@define('TRACKBACK', '引用');
+@define('NO_TRACKBACKS', '没有引用');
+@define('TOPICS_OF', '主题');
+@define('VIEW_FULL', '浏览全部');
+@define('VIEW_TOPICS', '浏览主题');
+@define('AT', '在');
+@define('SET_AS_TEMPLATE', '使用布景');
+@define('IN', '在');
+@define('EXCERPT', '摘要');
+@define('TRACKED', '引用');
+@define('LINK_TO_ENTRY', '连结到文章');
+@define('LINK_TO_REMOTE_ENTRY', '连结到远端文章');
+@define('IP_ADDRESS', 'IP 位址');
+@define('USER', '作者');
+@define('THUMBNAIL_USING_OWN', '使用 %s 当它的缩图尺寸因为图片已经很小了.');
+@define('THUMBNAIL_FAILED_COPY', '使用 %s 当它的缩图, 但是无法复制!');
+@define('AUTHOR', '发表者');
+@define('LAST_UPDATED', '最后更新');
+@define('TRACKBACK_SPECIFIC', '引用此文章特定的 URI (网址)');
+@define('DIRECT_LINK', '直接的文章连结');
+@define('COMMENT_ADDED', '您的回响已成功增入. ');
+@define('COMMENT_ADDED_CLICK', '点 %s这里返回%s 到回响, 和点 %s这里关闭%s 这个视窗.');
+@define('COMMENT_NOT_ADDED', '您的回响不能增入因为此篇文章不允许回响. ');
+@define('COMMENT_NOT_ADDED_CLICK', '点 %s这里返回%s 到回响, 和点 %s这里关闭%s 这个视窗.');
+@define('COMMENTS_DISABLE', '不允许回响到这篇文章');
+@define('COMMENTS_ENABLE', '允许回响到这篇文章');
+@define('COMMENTS_CLOSED', '作者不允许回响到这篇文章');
+@define('EMPTY_COMMENT', '您的回响没有任何讯息, 请 %s返回%s 重试');
+@define('ENTRIES_FOR', '文章给 %s');
+@define('DOCUMENT_NOT_FOUND', '找不到此篇文件 %s.');
+@define('USERNAME', '帐号');
+@define('PASSWORD', '密码');
+@define('AUTOMATIC_LOGIN', '自动登入');
+@define('SERENDIPITY_INSTALLATION', 'Serendipity 安装程式');
+@define('LEFT', '左');
+@define('RIGHT', '右');
+@define('HIDDEN', '隐藏');
+@define('REMOVE_TICKED_PLUGINS', '移除勾选的外挂');
+@define('SAVE_CHANGES_TO_LAYOUT', '储存外观配置');
+@define('COMMENTS_FROM', '回响来源');
+@define('ERROR', '错误');
+@define('ENTRY_SAVED', '您的文章已储存');
+@define('DELETE_SURE', '确定要删除 #%s 吗?');
+@define('NOT_REALLY', '算了...');
+@define('DUMP_IT', '删除吧!');
+@define('RIP_ENTRY', 'R.I.P. 文章 #%s');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', '类别 #%s 已删除. 旧文章已被移动到类别 #%s');
+@define('CATEGORY_DELETED', '类别 #%s 已删除.');
+@define('INVALID_CATEGORY', '没有提供删除的类别');
+@define('CATEGORY_SAVED', '类别已储存');
+@define('SELECT_TEMPLATE', '请选择网路日记的布景');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', '没有完成增入文章!');
+@define('MT_DATA_FILE', 'Movable Type 资料档');
+@define('FORCE', '强制');
+@define('CREATE_AUTHOR', '新增作者 \'%s\'.');
+@define('CREATE_CATEGORY', '新增类别 \'%s\'.');
+@define('MYSQL_REQUIRED', '您必须要有 MySQL 的扩充功能才能执行这个动作.');
+@define('COULDNT_CONNECT', '不能联结到 MySQL 资料库: %s.');
+@define('COULDNT_SELECT_DB', '不能选择资料库: %s.');
+@define('COULDNT_SELECT_USER_INFO', '不能选择使用者的资料: %s.');
+@define('COULDNT_SELECT_CATEGORY_INFO', '不能选择类别的资料: %s.');
+@define('COULDNT_SELECT_ENTRY_INFO', '不能选择文章的资料: %s.');
+@define('COULDNT_SELECT_COMMENT_INFO', '不能选择回响的资料: %s.');
+@define('YES', '是');
+@define('NO', '否');
+@define('USE_DEFAULT', '预设');
+@define('CHECK_N_SAVE', '储存');
+@define('DIRECTORY_WRITE_ERROR', '不能读写档案夹 %s. 请检查权限.');
+@define('DIRECTORY_CREATE_ERROR', '档案夹 %s 不存在也无法建立. 请自己建立这个档案夹');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; run <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', '无法执行 %s 资源档案');
+@define('FILE_WRITE_ERROR', '无法读写档案 %s.');
+@define('FILE_CREATE_YOURSELF', '请自己建立这个档案或检查权限');
+@define('COPY_CODE_BELOW', '<br />* 请复制下面的代码然后放入 %s 到您的 %s 档案夹:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', '请改变 www 到使用者的 Apache (i.e. nobody).');
+@define('BROWSER_RELOAD', '完成之后, 重新刷新您的浏览器.');
+@define('DIAGNOSTIC_ERROR', '系统侦测到一些错误:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity 还没安装完成. 请按 <a href="%s">安装</a>.');
+@define('INCLUDE_ERROR', 'serendipity 错误: 无法包括 %s - 退出.');
+@define('DATABASE_ERROR', 'serendipity 错误: 无法连结到资料库 - 退出.');
+@define('CHECK_DATABASE_EXISTS', '检查资料库是否存在. 如果您看到资料库查询错误, 请不用管它...');
+@define('CREATE_DATABASE', '建立预设资料库设定...');
+@define('ATTEMPT_WRITE_FILE', '读写 %s 档案...');
+@define('SERENDIPITY_INSTALLED', '%sSerendipity 已安装完成.%s 请记得您的密码: "%s", 您的帐号是 "%s".%s您现在可以到新建立的 <a href="%s">网路日记</a>');
+@define('WRITTEN_N_SAVED', '储存完毕');
+@define('IMAGE_ALIGNMENT', '图片对齐');
+@define('ENTER_NEW_NAME', '输入新名称给: ');
+@define('RESIZING', '重设大小');
+@define('RESIZE_DONE', '完成 (重设 %s 个图片).');
+@define('SYNCING', '进行资料库和图片档案夹同步化');
+@define('SYNC_DONE', '完成 (同步了 %s 个图片).');
+@define('FILE_NOT_FOUND', '找不到档案名称 <b>%s</b>, 也许已经被删除了?');
+@define('ABORT_NOW', '放弃');
+@define('REMOTE_FILE_NOT_FOUND', '档案不在远端主机内, 您确定这个 URL: <b>%s</b> 是正确的吗?');
+@define('FILE_FETCHED', '%s 取回为 %s');
+@define('FILE_UPLOADED', '档案 %s 上传为 %s');
+@define('WORD_OR', '或');
+@define('SCALING_IMAGE', '缩放 %s 到 %s x %s px');
+@define('KEEP_PROPORTIONS', '维持比例');
+@define('REALLY_SCALE_IMAGE', '确定要缩放图片吗? 这个动作不能复原!');
+@define('TOGGLE_ALL', '切换展开');
+@define('TOGGLE_OPTION', '切换选项');
+@define('SUBSCRIBE_TO_THIS_ENTRY', '订阅这篇文章');
+@define('UNSUBSCRIBE_OK', "%s 已取消订阅这篇文章");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', '新回响到订阅的文章 "%s"');
+@define('SUBSCRIPTION_MAIL', "您好 %s,\n\n您订阅的文章有了新的回响在 \"%s\", 标题是 \"%s\"\n回响的发表者是: %s\n\n您可以在这找到此文章: %s\n\n您可以点这个连结取消订阅: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "您好 %s,\n\n您订阅的文章有了新的引用在 \"%s\", 标题是 \"%s\"\n引用的作者是: %s\n\n您可以在这找到此文章: %s\n\n您可以点这个连结取消订阅: %s\n");
+@define('SIGNATURE', "\n-- \n%s is powered by Serendipity.\nThe best blog around, you can use it too.\nCheck out <http://s9y.org> to find out how.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91 feed');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0 feed');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0 feed');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 comments');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3 feed');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', '栏位 "managingEditor"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  '栏位 "webMaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'RSS feed 的图片');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', '图片宽度');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', '图片高度');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  '管理员的电子邮件, 如果有. (空白: 隐藏) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', '作者的电子邮件, 如果有. (空白: 隐藏) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', '图片的位址 URL, 以 GIF/JPEG/PNG 格式, 如果有. (空白: serendipity-logo)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', '像素, 最大. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', '像素, 最大. 400');
+@define('SYNDICATION_PLUGIN_TTL', '栏位 "ttl" (time-to-live)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', '过几分钟后您的文章不会被外来的网站或程式储存到快取记忆里 (空白: 隐藏) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', '栏位 "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', '"pubDate"-栏位需要内嵌到RSS-频道, 以显示最后文章的日期吗?');
+@define('CONTENT', '内容');
+@define('TYPE', '类型');
+@define('DRAFT', '草稿');
+@define('PUBLISH', '公开');
+@define('PREVIEW', '预览');
+@define('DATE', '日期');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', '警告: 您提供的日期不正确. 它必须是 YYYY-MM-DD HH:MM 格式.');
+@define('CATEGORY_PLUGIN_DESC', '显示类别清单.');
+@define('ALL_AUTHORS', '全部作者');
+@define('CATEGORIES_TO_FETCH', '显示类别');
+@define('CATEGORIES_TO_FETCH_DESC', '显示哪位作者的类别?');
+@define('PAGE_BROWSE_ENTRIES', '页数 %s 共 %s, 总共 %s 篇文章');
+@define('PREVIOUS_PAGE', '上一页');
+@define('NEXT_PAGE', '下一页');
+@define('ALL_CATEGORIES', '全部类别');
+@define('DO_MARKUP', '执行标记转换');
+@define('GENERAL_PLUGIN_DATEFORMAT', '日期格式化');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', '文章的日期格式, 使用 PHP 的 strftime() 变数. (预设: "%s")');
+@define('ERROR_TEMPLATE_FILE', '无法开启布景档案, 请更新 serendipity!');
+@define('ADVANCED_OPTIONS', '进阶选项');
+@define('EDIT_ENTRY', '编辑文章');
+@define('HTACCESS_ERROR', '要检查您的主机安装设定, serendipity 需要读写档案 ".htaccess". 但是因为权限错误, 没有办法为您检查. 请改变档案权限像这样: <br />&nbsp;&nbsp;%s<br />然后重新刷新这个网页.');
+@define('SIDEBAR_PLUGINS', '侧列外挂');
+@define('EVENT_PLUGINS', '事件外挂');
+@define('SORT_ORDER', '排序');
+@define('SORT_ORDER_NAME', '档案名称');
+@define('SORT_ORDER_EXTENSION', '副档名');
+@define('SORT_ORDER_SIZE', '档案大小');
+@define('SORT_ORDER_WIDTH', '图片宽度');
+@define('SORT_ORDER_HEIGHT', '图片长度');
+@define('SORT_ORDER_DATE', '上传日期');
+@define('SORT_ORDER_ASC', '递增排序');
+@define('SORT_ORDER_DESC', '递减排序');
+@define('THUMBNAIL_SHORT', '缩图');
+@define('ORIGINAL_SHORT', '原始');
+@define('APPLY_MARKUP_TO', '套用标记到 %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', '一周的第一天');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity 侦测到您的配置版本是 %s, 但是 Serendipity 本身的安装版本是 %s, 请更新您的程式版本! <a href="%s">更新</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', '您好, 欢迎来到 Serendipity 的更新系统.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', '更新系统会帮您更新到 Serendipity 版本 %s.');
+@define('SERENDIPITY_UPGRADER_WHY', '您看到这个讯息是因为您安装了 Serendipity 版本 %s, 但是您没有更新资料库');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', '资料库更新 (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', '系统找到以下的 .sql 档, 那些档案必须先执行才能继续安装 Serendipity');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  '特定的版本任务');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', '没有特定的版本任务');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', '确定要执行上面的任务吗?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', '我自己执行');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', '请帮我执行');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', '您不需要进行任何更新');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', '假装 Serendipity 更新完成吧');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', '您略过了更新任务, 请确定资料库已安装完成, 和其他的任务安装无误');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', '您的 Serendipity 以更新至版本 %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', '您可以点 %s这里%s 返回日记首页');
+@define('MANAGE_USERS', '管理作者');
+@define('CREATE_NEW_USER', '新增作者');
+@define('CREATE_NOT_AUTHORIZED', '您不能修改跟您相同权限的作者');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', '您不能新增比您高权限的作者');
+@define('CREATED_USER', '新作者 %s 已经新增');
+@define('MODIFIED_USER', '作者 %s 的资料已经更改');
+@define('USER_LEVEL', '作者权限');
+@define('DELETE_USER', '您要删除这个作者 #%d %s. 确定吗? 这会在主页隐藏他所写的任何文章.');
+@define('DELETED_USER', '作者 #%d %s 已被删除.');
+@define('LIMIT_TO_NUMBER', '要显示多少项目?');
+@define('ENTRIES_PER_PAGE', '每页显示的文章');
+@define('XML_IMAGE_TO_DISPLAY', 'XML 按钮');
+@define('XML_IMAGE_TO_DISPLAY_DESC','连结到 XML Feeds 的都会用这个图片表示. 不填写将会使用预设的图片, 或输入 \'none\' 关闭这个功能.');
+
+@define('DIRECTORIES_AVAILABLE', '您可以在子目录内点任何目录来建立新的目录.');
+@define('ALL_DIRECTORIES', '全部目绿');
+@define('MANAGE_DIRECTORIES', '管理目录');
+@define('DIRECTORY_CREATED', '目录 <strong>%s</strong> 已经新增.');
+@define('PARENT_DIRECTORY', '母目录');
+@define('CONFIRM_DELETE_DIRECTORY', '确定要删除这个目录内的全部内容吗 %s?');
+@define('ERROR_NO_DIRECTORY', '错误: 目录 %s 不存在');
+@define('CHECKING_DIRECTORY', '检查此目录的档案 %s');
+@define('DELETING_FILE', '删除档案 %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', '不能移除未清空的目录. 勾选 "强制删除" 核取方块如果您要移除这些档案, 然后在继续. 存在的档案是:');
+@define('DIRECTORY_DELETE_FAILED', '不能删除目录 %s. 请检查权限或看上面的讯息.');
+@define('DIRECTORY_DELETE_SUCCESS', '目录 %s 成功删除.');
+@define('SKIPPING_FILE_EXTENSION', '略过档案: 没有 %s 的副档名.');
+@define('SKIPPING_FILE_UNREADABLE', '略过档案: %s 不能读取.');
+@define('FOUND_FILE', '找到 新/修改 过的档案: %s.');
+@define('ALREADY_SUBCATEGORY', '%s 已经是此类别的子类别 %s.');
+@define('PARENT_CATEGORY', '母类别');
+@define('IN_REPLY_TO', '回覆到');
+@define('TOP_LEVEL', '最高层');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s feed');
+@define('PERMISSIONS', '权限');
+@define('SETTINGS_SAVED_AT', '新设定已经被储存到 %s');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', '资料库设定');
+@define('INSTALL_CAT_DB_DESC', '您可以在这输入全部的资料库资料. Serendipity 需要这些资料才能正常运作');
+@define('INSTALL_DBTYPE', '资料库类型');
+@define('INSTALL_DBTYPE_DESC', '资料库类型');
+@define('INSTALL_DBHOST', '资料库主机');
+@define('INSTALL_DBHOST_DESC', '资料库主机名称');
+@define('INSTALL_DBUSER', '资料库帐号');
+@define('INSTALL_DBUSER_DESC', '登入资料库的帐号');
+@define('INSTALL_DBPASS', '资料库密码');
+@define('INSTALL_DBPASS_DESC', '您的资料库密码');
+@define('INSTALL_DBNAME', '资料库名称');
+@define('INSTALL_DBNAME_DESC', '资料库名称');
+@define('INSTALL_DBPREFIX', '资料表前置名称');
+@define('INSTALL_DBPREFIX_DESC', '资料表的前置名称, 例如 serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', '路径设定');
+@define('INSTALL_CAT_PATHS_DESC', '给档案夹的路径. 不要忘了最后的斜线!');
+@define('INSTALL_FULLPATH', '完全路径');
+@define('INSTALL_FULLPATH_DESC', '您的 Serendipity 安装的完全路径和绝对路径');
+@define('INSTALL_UPLOADPATH', '上传路径');
+@define('INSTALL_UPLOADPATH_DESC', '全部的上传档案会存到这里, 以 \'完全路径\' 表示的相对路径 - 例如 \'uploads/\'');
+@define('INSTALL_RELPATH', '相对路径');
+@define('INSTALL_RELPATH_DESC', '给浏览器的路径, 例如 \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', '相对的布景路径');
+@define('INSTALL_RELTEMPLPATH_DESC', '您放布景的路径 - 以 \'相对路径\' 表示的相对路径');
+@define('INSTALL_RELUPLOADPATH', '相对的上传路径');
+@define('INSTALL_RELUPLOADPATH_DESC', '给浏览器上传档案的路径 - 以 \'相对路径\' 表示的相对路径');
+@define('INSTALL_URL', '网路日记 URL');
+@define('INSTALL_URL_DESC', '您的 Serendipity 安装的基本 URL');
+@define('INSTALL_INDEXFILE', 'Index 档案');
+@define('INSTALL_INDEXFILE_DESC', 'Serendipity 的 index 档案');
+
+/* Generel settings */
+@define('INSTALL_CAT_SETTINGS', '一般设定');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Serendipity 的一般设定');
+@define('INSTALL_USERNAME', '管理员帐号');
+@define('INSTALL_USERNAME_DESC', '管理员的登入名称');
+@define('INSTALL_PASSWORD', '管理员密码');
+@define('INSTALL_PASSWORD_DESC', '管理员的登入密码');
+@define('INSTALL_EMAIL', '电子邮件');
+@define('INSTALL_EMAIL_DESC', '管理员的电子邮件');
+@define('INSTALL_SENDMAIL', '寄送电子邮件给管理员?');
+@define('INSTALL_SENDMAIL_DESC', '当有人发布回响到您的文章时要收到电子邮件通知吗?');
+@define('INSTALL_SUBSCRIBE', '允许使用者订阅文章?');
+@define('INSTALL_SUBSCRIBE_DESC', '您可以允许使用者收到电子邮件通知, 当有回响发布时她们会收到通知.');
+@define('INSTALL_BLOGNAME', '日记名称');
+@define('INSTALL_BLOGNAME_DESC', '您的日记标题');
+@define('INSTALL_BLOGDESC', '日记简介');
+@define('INSTALL_BLOGDESC_DESC', '介绍您的日记');
+@define('INSTALL_LANG', '语系');
+@define('INSTALL_LANG_DESC', '您日记使用的语系');
+
+/* Appearance and options */
+@define('INSTALL_CAT_DISPLAY', '外观及选项设定');
+@define('INSTALL_CAT_DISPLAY_DESC', '让您设定 Serendipity 的外观和其他设定');
+@define('INSTALL_WYSIWYG', '使用 WYSIWYG 编辑器');
+@define('INSTALL_WYSIWYG_DESC', '您要使用 WYSIWYG 编辑器吗? (可在 IE5+ 使用, 某些部分可使用於 Mozilla 1.3+)');
+@define('INSTALL_XHTML11', '强制符合 XHTML 1.1 要求');
+@define('INSTALL_XHTML11_DESC', '您可以让您的日记强制符合 XHTML 1.1 的要求 (对旧的浏览器可能会有 后台/前台 的问题)');
+@define('INSTALL_POPUP', '使用弹出视窗');
+@define('INSTALL_POPUP_DESC', '您要在回响, 引用等地方使用弹出视窗吗?');
+@define('INSTALL_EMBED', '使用内嵌功能?');
+@define('INSTALL_EMBED_DESC', '如果你要将 Serendipity 以内嵌的方式放到网页内, 选择 是 会让您舍弃任何标题然后只显示日记内容. 您可以用 indexFile 设定来使用包装函式类别以便您放入网页标题. 详情请查询 README 档案!');
+@define('INSTALL_TOP_AS_LINKS', '以连结显示 主要出源/主要来源?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"否": 出源和来源将用文字显示以避免 google 的广告. "是": 出源和来源将用连结显示. "预设": 用全区里面的设定 (建议).');
+@define('INSTALL_BLOCKREF', '阻挡来源');
+@define('INSTALL_BLOCKREF_DESC', '有任何特殊的主机您不想在来源里显示吗? 用 \';\' 来分开主机名称, 注意主机是以子字串方式阻挡!');
+@define('INSTALL_REWRITE', 'URL Rewriting');
+@define('INSTALL_REWRITE_DESC', '请选择您想用的 URL Rewriting 方式. 开启 rewrite 规则会以比较清楚的方式显示 URL, 以便搜寻网站能正确的登入您的文章. 您的主机必须支援 mod_rewrite 或 "AllowOverride All" 到您的 Serendipity 档案夹. 预设的设定是系统自动帮您侦测的');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', '图片转换设定');
+@define('INSTALL_CAT_IMAGECONV_DESC', '请设定 Serendipity 设定图片转换的方式');
+@define('INSTALL_IMAGEMAGICK', '使用 Imagemagick');
+@define('INSTALL_IMAGEMAGICK_DESC', '如果有安装 image magick, 您要用它来改变图片大小吗?');
+@define('INSTALL_IMAGEMAGICKPATH', '转换程式路径');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'image magick 转换程式的完全路径和名称');
+@define('INSTALL_THUMBSUFFIX', '缩图后置字元');
+@define('INSTALL_THUMBSUFFIX_DESC', '缩图会以下面的格式重新命名: original.[后置字元].ext');
+@define('INSTALL_THUMBWIDTH', '缩图尺度');
+@define('INSTALL_THUMBWIDTH_DESC', '自动建立缩图的最大宽度');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', '个人资料设定');
+@define('USERCONF_CAT_PERSONAL_DESC', '改变您的个人资料');
+@define('USERCONF_USERNAME', '您的帐号');
+@define('USERCONF_USERNAME_DESC', '您登入网路日记的名称');
+@define('USERCONF_PASSWORD', '您的密码');
+@define('USERCONF_PASSWORD_DESC', '您登入网路日记的密码');
+@define('USERCONF_EMAIL', '您的电子邮件');
+@define('USERCONF_EMAIL_DESC', '您使用的电子邮件');
+@define('USERCONF_SENDCOMMENTS', '寄送回响通知?');
+@define('USERCONF_SENDCOMMENTS_DESC', '当有新回响到您的文章时要通知您吗?');
+@define('USERCONF_SENDTRACKBACKS', '寄送引用通知?');
+@define('USERCONF_SENDTRACKBACKS_DESC', '当有新引用到您的文章时要通知您吗?');
+@define('USERCONF_ALLOWPUBLISH', '权限: 可发布文章?');
+@define('USERCONF_ALLOWPUBLISH_DESC', '允许这位作者发布文章吗?');
+@define('SUCCESS', '完成');
+@define('POWERED_BY_SHOW_TEXT', '以文字显示 "Serendipity"');
+@define('POWERED_BY_SHOW_TEXT_DESC', '将用文字显示 "Serendipity Weblog"');
+@define('POWERED_BY_SHOW_IMAGE', '以 logo 显示 "Serendipity"');
+@define('POWERED_BY_SHOW_IMAGE_DESC', '显示 Serendipity 的 logo');
+@define('PLUGIN_ITEM_DISPLAY', '该项目的显示位址?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', '只在副内容显示');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', '只在概观内显示');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', '永远显示');
+
+@define('COMMENTS_WILL_BE_MODERATED', '发布的回响将需要管理员的审核.');
+@define('YOU_HAVE_THESE_OPTIONS', '您有以下选择:');
+@define('THIS_COMMENT_NEEDS_REVIEW', '警告: 这个回响须审核才会显示');
+@define('DELETE_COMMENT', '删除回响');
+@define('APPROVE_COMMENT', '认可回响');
+@define('REQUIRES_REVIEW', '需要审核');
+@define('COMMENT_APPROVED', '回响 #%s 已经通过审核');
+@define('COMMENT_DELETED', '回响 #%s 已经成功删除');
+@define('COMMENTS_MODERATE', '回响和引用到这个文章需要管理员的审核');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', '警告: 这个引用需要管理员的审核才会显示');
+@define('DELETE_TRACKBACK', '删除引用');
+@define('APPROVE_TRACKBACK', '认可引用');
+@define('TRACKBACK_APPROVED', '引用 #%s 已经通过审核');
+@define('TRACKBACK_DELETED', '引用 #%s 已经成功删除');
+@define('VIEW', '浏览');
+@define('COMMENT_ALREADY_APPROVED', '回响 #%s 已经通过审核');
+@define('COMMENT_EDITED', '文章已被编辑');
+@define('HIDE', '隐藏');
+@define('VIEW_EXTENDED_ENTRY', '继续阅读 "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', '这个连结不是用来点的. 它包含了这个文章的引用 URI. 您可以从您的日记内用这个 URI 来传送 ping 和引用到这个文章. 如果要复制这个连结, 在连结上点右键然后选择 "复制连结" (IE) 或 "复制连结位址" (Mozilla).');
+@define('PLUGIN_SUPERUSER_HTTPS', '用 https 登入');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', '让登入连结连到 https 网址. 您的主机必须支援这项功能!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', '让外来连结以连结显示?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"否": 外来连结 (主要出源, 主要来源, 回响) 都不会以文字显示以避免 google 广告 (建议使用). "是": 外来连结将以超连结的方式显示. 可以在侧列外挂盖过此设定!');
+@define('PAGE_BROWSE_COMMENTS', '页数 %s 共 %s, 总共 %s 个回响');
+@define('FILTERS', '过滤');
+@define('FIND_ENTRIES', '搜寻文章');
+@define('FIND_COMMENTS', '搜寻回响');
+@define('FIND_MEDIA', '搜寻媒体');
+@define('FILTER_DIRECTORY', '目录');
+@define('SORT_BY', '排序');
+@define('TRACKBACK_COULD_NOT_CONNECT', '没有送出引用: 无法开启线路到 %s 用连接埠 %d');
+@define('MEDIA', '媒体');
+@define('MEDIA_LIBRARY', '媒体存库');
+@define('ADD_MEDIA', '新增媒体');
+@define('ENTER_MEDIA_URL', '请输入档案的 URL:');
+@define('ENTER_MEDIA_UPLOAD', '请选择要上传的档案:');
+@define('SAVE_FILE_AS', '储存档案:');
+@define('STORE_IN_DIRECTORY', '储存到以下目录: ');
+@define('ADD_MEDIA_BLAHBLAH', '<b>新增档案到媒体存库:</b><p>您可以在这上传媒体档, 或告诉系统到哪寻找! 如果您没有想要的图片, 您可以到 <a href="http://images.google.com" target="_blank">google寻找图片</a>.<p><b>选择方式:</b><br>');
+@define('MEDIA_RENAME', '更改档案名称');
+@define('IMAGE_RESIZE', '更改图片尺寸');
+@define('MEDIA_DELETE', '删除这个档案');
+@define('FILES_PER_PAGE', '每页显示的档案数');
+@define('CLICK_FILE_TO_INSERT', '点选您要输入的档案:');
+@define('SELECT_FILE', '选择要输入的档案');
+@define('MEDIA_FULLSIZE', '完整尺寸');
+@define('CALENDAR_BOW_DESC', '一个礼拜的第一天. 预设是星期一');
+@define('SUPERUSER', '日记管理');
+@define('ALLOWS_YOU_BLAHBLAH', '在侧列提供连结到日记管理');
+@define('CALENDAR', '日历');
+@define('SUPERUSER_OPEN_ADMIN', '开启管理页面');
+@define('SUPERUSER_OPEN_LOGIN', '开启登入页面');
+@define('INVERT_SELECTIONS', '颠倒勾选');
+@define('COMMENTS_DELETE_CONFIRM', '确定要删除勾选的回响吗?');
+@define('COMMENT_DELETE_CONFIRM', '确定要删除回响 #%d, 发布者是 %s?');
+@define('DELETE_SELECTED_COMMENTS', '删除勾选的回响');
+@define('VIEW_COMMENT', '浏览回响');
+@define('VIEW_ENTRY', '浏览文章');
+@define('DELETE_FILE_FAIL' , '无法删除档案 <b>%s</b>');
+@define('DELETE_THUMBNAIL', '删除了图片缩图 <b>%s</b>');
+@define('DELETE_FILE', '删除了档案 <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', '您将删除档案 <b>%s</b><br />如果您有在其他的文章内使用这个档案, 那个连结或图片将会无效<br />确定要继续吗?<br /><br />');
+@define('TRACKBACK_SENDING', '传送引用到 URI %s...');
+@define('TRACKBACK_SENT', '引用完成');
+@define('TRACKBACK_FAILED', '引用错误: %s');
+@define('TRACKBACK_NOT_FOUND', '找不到引用的URI.');
+@define('TRACKBACK_URI_MISMATCH', '自动搜寻的引用跟引用目标不相同.');
+@define('TRACKBACK_CHECKING', '搜寻 <u>%s</u> 的引用...');
+@define('TRACKBACK_NO_DATA', '目标没有任何资料');
+@define('TRACKBACK_SIZE', '目标 URI 超出了允许的 %s bytes 档案大小.');
+@define('COMMENTS_VIEWMODE_THREADED', '分线程');
+@define('COMMENTS_VIEWMODE_LINEAR', '直线程');
+@define('DISPLAY_COMMENTS_AS', '回响显示方式');
+@define('COMMENTS_FILTER_SHOW', '显示');
+@define('COMMENTS_FILTER_ALL', '全部');
+@define('COMMENTS_FILTER_APPROVED_ONLY', '显示审核回响');
+@define('COMMENTS_FILTER_NEED_APPROVAL', '显示等待审核');
+@define('RSS_IMPORT_BODYONLY', '将输入的文字放到主内容, 将不拆开过长的文章到副内容地区.');
+@define('SYNDICATION_PLUGIN_FULLFEED', '在 RSS feed 里显示全部的文章');
+@define('WEEK', '周');
+@define('WEEKS', '周');
+@define('MONTHS', '月');
+@define('DAYS', '日');
+@define('ARCHIVE_FREQUENCY', '保存文库的项目频率');
+@define('ARCHIVE_FREQUENCY_DESC', '保存文库使用的项目清单间隔');
+@define('ARCHIVE_COUNT', '保存文库的项目数');
+@define('ARCHIVE_COUNT_DESC', '显示的月, 周, 或日');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', '下面是安装好的外挂');
+@define('SIDEBAR_PLUGIN', '侧列外挂');
+@define('EVENT_PLUGIN', '事件外挂');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', '点这里安装新 %s');
+@define('VERSION', '版本');
+@define('INSTALL', '安装');
+@define('ALREADY_INSTALLED', '已经安装');
+@define('SELECT_A_PLUGIN_TO_ADD', '请选择要安装的外挂');
+@define('RSS_IMPORT_CATEGORY', '用这个类别给不相同的输入文章');
+
+@define('INSTALL_OFFSET', 'Server time Offset'); // Translate
+@define('STICKY_POSTINGS', 'Sticky Postings'); // Translate
+@define('INSTALL_FETCHLIMIT', 'Entries to display on frontpage'); // Translate
+@define('INSTALL_FETCHLIMIT_DESC', 'Number of entries to display for each page on the frontend'); // Translate
+@define('IMPORT_ENTRIES', 'Import data'); // Translate
+@define('EXPORT_ENTRIES', 'Export entries'); // Translate
+@define('IMPORT_WELCOME', 'Welcome to the Serendipity import utility'); // Translate
+@define('IMPORT_WHAT_CAN', 'Here you can import entries from other weblog software applications'); // Translate
+@define('IMPORT_SELECT', 'Please select the software you wish to import from'); // Translate
+@define('IMPORT_PLEASE_ENTER', 'Please enter the data as requested below'); // Translate
+@define('IMPORT_NOW', 'Import now!'); // Translate
+@define('IMPORT_STARTING', 'Starting import procedure...'); // Translate
+@define('IMPORT_FAILED', 'Import failed'); // Translate
+@define('IMPORT_DONE', 'Import successfully completed'); // Translate
+@define('IMPORT_WEBLOG_APP', 'Weblog application'); // Translate
+@define('EXPORT_FEED', 'Export full RSS feed'); // Translate
+@define('STATUS', 'Status after import'); // Translate
+@define('IMPORT_GENERIC_RSS', 'Generic RSS import'); // Translate
+@define('ACTIVATE_AUTODISCOVERY', 'Send Trackbacks to links found in the entry'); // Translate
+@define('WELCOME_TO_ADMIN', 'Welcome to the Serendipity Administration Suite.'); // Translate
+@define('PLEASE_ENTER_CREDENTIALS', 'Please enter your credentials below.'); // Translate
+@define('ADMIN_FOOTER_POWERED_BY', 'Powered by Serendipity %s and PHP %s'); // Translate
+@define('INSTALL_USEGZIP', 'Use gzip compressed pages'); // Translate
+@define('INSTALL_USEGZIP_DESC', 'To speed up delivery of pages, we can compress the pages we send to the visitor, given that his browser supports this. This is recommended'); // Translate
+@define('INSTALL_SHOWFUTURE', 'Show future entries'); // Translate
+@define('INSTALL_SHOWFUTURE_DESC', 'If enabled, this will show all entries in the future on your blog. Default is to hide those entries and only show them if the publish date has arrived.'); // Translate
+@define('INSTALL_DBPERSISTENT', 'Use persistent connections'); // Translate
+@define('INSTALL_DBPERSISTENT_DESC', 'Enable the usage of persistent database connections, read more <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">here</a>. This is normally not recommended'); // Translate
+@define('NO_IMAGES_FOUND', 'No images found'); // Translate
+@define('PERSONAL_SETTINGS', 'Personal Settings'); // Translate
+@define('REFERER', 'Referer'); // Translate
+@define('NOT_FOUND', 'Not found'); // Translate
+@define('NOT_WRITABLE', 'Not writable'); // Translate
+@define('WRITABLE', 'Writable'); // Translate
+@define('PROBLEM_DIAGNOSTIC', 'Due to a problematic diagnostic, you cannot continue with the installation before the above errors are fixed'); // Translate
+@define('SELECT_INSTALLATION_TYPE', 'Select which installation type you wish to use'); // Translate
+@define('WELCOME_TO_INSTALLATION', 'Welcome to the Serendipity Installation'); // Translate
+@define('FIRST_WE_TAKE_A_LOOK', 'First we will take a look at your current setup and attempt to diagnose any compatibility problems'); // Translate
+@define('ERRORS_ARE_DISPLAYED_IN', 'Errors are displayed in %s, recommendations in %s and success in %s'); // Translate
+@define('RED', 'red'); // Translate
+@define('YELLOW', 'yellow'); // Translate
+@define('GREEN', 'green'); // Translate
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s pre-installation report'); // Translate
+@define('RECOMMENDED', 'Recommended'); // Translate
+@define('ACTUAL', 'Actual'); // Translate
+@define('PHPINI_CONFIGURATION', 'php.ini configuration'); // Translate
+@define('PHP_INSTALLATION', 'PHP installation'); // Translate
+@define('THEY_DO', 'they do'); // Translate
+@define('THEY_DONT', 'they don\'t'); // Translate
+@define('SIMPLE_INSTALLATION', 'Simple installation'); // Translate
+@define('EXPERT_INSTALLATION', 'Expert installation'); // Translate
+@define('COMPLETE_INSTALLATION', 'Complete installation'); // Translate
+@define('WONT_INSTALL_DB_AGAIN', 'won\'t install the database again'); // Translate
+@define('CHECK_DATABASE_EXISTS', 'Checking to see if the database and tables already exists'); // Translate
+@define('CREATING_PRIMARY_AUTHOR', 'Creating primary author \'%s\''); // Translate
+@define('SETTING_DEFAULT_TEMPLATE', 'Setting default template'); // Translate
+@define('INSTALLING_DEFAULT_PLUGINS', 'Installing default plugins'); // Translate
+@define('SERENDIPITY_INSTALLED', 'Serendipity has been successfully installed'); // Translate
+@define('VISIT_BLOG_HERE', 'Visit your new blog here'); // Translate
+@define('THANK_YOU_FOR_CHOOSING', 'Thank you for choosing Serendipity'); // Translate
+@define('ERROR_DETECTED_IN_INSTALL', 'An error was detected in the installation'); // Translate
+@define('OPERATING_SYSTEM', 'Operating system'); // Translate
+@define('WEBSERVER_SAPI', 'Webserver SAPI'); // Translate
+@define('TEMPLATE_SET', '\'%s\' has been set as your active template'); // Translate
+@define('SEARCH_ERROR', 'The search function did not work as expected. Notice for the administrator of this blog: This may happen because of missing index keys in your database. On MySQL systems your database user account needs to be privileged to execute this query: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> The specific error returned by the database was: <pre>%s</pre>'); // Translate
+@define('EDIT_THIS_CAT', 'Editing "%s"'); // Translate
+@define('CATEGORY_REMAINING', 'Delete this category and move its entries to this category'); // Translate
+@define('CATEGORY_INDEX', 'Below is a list of categories available to your entries'); // Translate
+@define('NO_CATEGORIES', 'No categories'); // Translate
+@define('RESET_DATE', 'Reset date'); // Translate
+@define('RESET_DATE_DESC', 'Click here to reset the date to the current time'); // Translate
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Permissions can be set by running shell command: `<em>%s</em>` on the failed directory, or by setting this using an FTP program'); // Translate
+@define('WARNING_TEMPLATE_DEPRECATED', 'Warning: Your current template is using a deprecated template method, you are advised to update if possible'); // Translate
+@define('ENTRY_PUBLISHED_FUTURE', 'This entry is not yet published.'); // Translate
+@define('ENTRIES_BY', 'Entries by %s'); // Translate
+@define('PREVIOUS', 'Previous'); // Translate
+@define('NEXT', 'Next'); // Translate
+@define('APPROVE', 'Approve'); // Translate
+@define('DO_MARKUP_DESCRIPTION', 'Apply markup transformations to the text (smilies, shortcut markups via *, /, _, ...). Disabling this will preserve any HTML-code in the text.'); // Translate
+@define('CATEGORY_ALREADY_EXIST', 'A category with the name "%s" already exist'); // Translate
+@define('IMPORT_NOTES', 'Note:'); // Translate
+@define('ERROR_FILE_FORBIDDEN', 'You are not allowed to upload files with active content'); // Translate
+@define('ADMIN', 'Administration'); // Re-Translate
+@define('ADMIN_FRONTPAGE', 'Frontpage'); // Translate
+@define('QUOTE', 'Quote'); // Translate
+@define('IFRAME_SAVE', 'Serendipity is now saving your entry, creating trackbacks and performing possible XML-RPC calls. This may take a while..'); // Translate
+@define('IFRAME_SAVE_DRAFT', 'A draft of this entry has been saved'); // Translate
+@define('IFRAME_PREVIEW', 'Serendipity is now creating the preview of your entry...'); // Translate
+@define('IFRAME_WARNING', 'Your browser does not support the concept of iframes. Please open your serendipity_config.inc.php file and set $serendipity[\'use_iframe\'] variable to FALSE.'); // Translate
+@define('NONE', 'none');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Default settings for new entries'); // Translate
+@define('UPGRADE', 'Upgrade'); // Translate
+@define('UPGRADE_TO_VERSION', 'Upgrade to version %s'); // Translate
+@define('DELETE_DIRECTORY', 'Delete directory'); // Translate
+@define('DELETE_DIRECTORY_DESC', 'You are about to delete the contents of a directory that contains media files, possibly files used in some of your entries.'); // Translate
+@define('FORCE_DELETE', 'Delete ALL files in this directory, including those not known by Serendipity'); // Translate
+@define('CREATE_DIRECTORY', 'Create directory'); // Translate
+@define('CREATE_NEW_DIRECTORY', 'Create new directory'); // Translate
+@define('CREATE_DIRECTORY_DESC', 'Here you can create a new directory to place media files in. Choose the name for your new directory and select an optional parent directory to place it in.'); // Translate
+@define('BASE_DIRECTORY', 'Base directory'); // Translate
+@define('USERLEVEL_EDITOR_DESC', 'Standard editor'); // Translate
+@define('USERLEVEL_CHIEF_DESC', 'Chief editor'); // Translate
+@define('USERLEVEL_ADMIN_DESC', 'Administrator'); // Translate
+@define('USERCONF_USERLEVEL', 'Access level'); // Translate
+@define('USERCONF_USERLEVEL_DESC', 'This level is used to determine what kind of access this user has to the blog'); // Translate
+@define('USER_SELF_INFO', 'Logged in as %s (%s)'); // Translate
+@define('ADMIN_ENTRIES', 'Entries'); // Translate
+@define('RECHECK_INSTALLATION', 'Recheck installation'); // Translate
+@define('IMAGICK_EXEC_ERROR', 'Unable to execute: "%s", error: %s, return var: %d'); // Translate
+@define('INSTALL_OFFSET_DESC', 'Enter the amount of hours between the date of your webserver (current: %clock%) and your desired time zone'); // Translate
+@define('UNMET_REQUIREMENTS', 'Requirements failed: %s'); // Translate
+@define('CHARSET', 'Charset');
+@define('AUTOLANG', 'Use visitor\'s browser language as default');
+@define('AUTOLANG_DESC', 'If enabled, this will use the visitor\'s browser language setting to determine the default language of your entry and interface language.');
+@define('INSTALL_AUTODETECT_URL', 'Autodetect used HTTP-Host'); // Translate
+@define('INSTALL_AUTODETECT_URL_DESC', 'If set to "true", Serendipity will ensure that the HTTP Host which was used by your visitor is used as your BaseURL setting. Enabling this will let you be able to use multiple domain names for your Serendipity Blog, and use the domain for all follow-up links which the user used to access your blog.'); // Translate
+@define('CONVERT_HTMLENTITIES', 'Try to auto-convert HTML entities?');
+@define('EMPTY_SETTING', 'You did not specify a valid value for "%s"!');
+@define('USERCONF_REALNAME', 'Real name'); // Translate
+@define('USERCONF_REALNAME_DESC', 'The full name of the author. This is the name seen by readers'); // Translate
+@define('HOTLINK_DONE', 'File hotlinked.<br />Done.'); // Translate
+@define('ENTER_MEDIA_URL_METHOD', 'Fetch method:'); // Translate
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Note: If you choose to hotlink to server, make sure you have permission to hotlink to the designated website, or the website is yours. Hotlink allows you to use off-site images without storing them locally.'); // Translate
+@define('MEDIA_HOTLINKED', 'hotlinked'); // Translate
+@define('FETCH_METHOD_IMAGE', 'Download image to your server'); // Translate
+@define('FETCH_METHOD_HOTLINK', 'Hotlink to server'); // Translate
+@define('DELETE_HOTLINK_FILE', 'Deleted the hotlinked file entitled <b>%s</b>'); // Translate
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Show E-Mail addresses?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_cs.inc.php b/lang/serendipity_lang_cs.inc.php
new file mode 100644 (file)
index 0000000..7eff04c
--- /dev/null
@@ -0,0 +1,671 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Translation (c) 2005 Josef Klimosz <ok2wo@centrum.cz>
+
+@define('LANG_CHARSET', 'windows-1250');
+@define('DATE_LOCALES', 'Czech, cs, cs_CZ.windows-1250');
+@define('DATE_FORMAT_ENTRY', '%A, %e. %B %Y');
+@define('DATE_FORMAT_SHORT', '%d/%m/%Y %H.%M');
+@define('WYSIWYG_LANG', 'cs-win');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', ',');
+@define('NUMBER_FORMAT_THOUSANDS', ' ');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Administrátorská sekce');
+@define('HAVE_TO_BE_LOGGED_ON', 'Pro zobrazení této stránky musíte být pøihlá\9aen');
+@define('WRONG_USERNAME_OR_PASSWORD', 'Zøejmì jste vlo\9eil \9apatné jméno nebo heslo!');
+@define('APPEARANCE', 'Vzhled');
+@define('MANAGE_STYLES', 'Zmìna stylu');
+@define('CONFIGURE_PLUGINS', 'Konfigurace pluginù');
+@define('CONFIGURATION', 'Konfigurace');
+@define('BACK_TO_BLOG', 'Zpìt do weblogu');
+@define('LOGIN', 'Pøihlá\9aení');
+@define('LOGOUT', 'Odhlá\9aení');
+@define('LOGGEDOUT', 'Odhlá\9aen');
+@define('CREATE', 'Vytvoøit');
+@define('SAVE', 'Ulo\9eit');
+@define('NAME', 'Jméno');
+@define('CREATE_NEW_CAT', 'Vytvoøení nové kategorie');
+@define('I_WANT_THUMB', 'Pou\9eít náhled.');
+@define('I_WANT_BIG_IMAGE', 'Pou\9eít celý obrázek.');
+@define('I_WANT_NO_LINK', ' Zobrazit jako obrázek');
+@define('I_WANT_IT_TO_LINK', 'Zobrazit jako odkaz (URL):');
+@define('BACK', 'Zpìt');
+@define('FORWARD', 'Dále');
+@define('ANONYMOUS', 'Anonym');
+@define('NEW_TRACKBACK_TO', 'Nová odezva na');
+@define('NEW_COMMENT_TO', 'Nový komentáø k');
+@define('RECENT', 'Nové...');
+@define('OLDER', 'Star\9aí...');
+@define('DONE', 'Hotovo');
+@define('WELCOME_BACK', 'Vítejte zpìt,');
+@define('TITLE', 'Titulek');
+@define('DESCRIPTION', 'Popis');
+@define('PLACEMENT', 'Umístìní');
+@define('DELETE', 'Vymazat');
+@define('SAVE', 'Ulo\9eit');
+@define('UP', 'Nahoru');
+@define('DOWN', 'Dolù');
+@define('ENTRIES', 'záznamy');
+@define('NEW_ENTRY', 'Nový záznam');
+@define('EDIT_ENTRIES', 'Editovat záznamy');
+@define('CATEGORIES', 'Kategorie');
+@define('WARNING_THIS_BLAHBLAH', "POZOR:\\nTato akce mù\9ee trvat déle pokud máte mnoho obrázkù bez náhledù.");
+@define('CREATE_THUMBS', 'Vytvoøit náhledy');
+@define('MANAGE_IMAGES', 'Správa obrázkù');
+@define('NAME', 'Jméno');
+@define('EMAIL', 'E-mail');
+@define('HOMEPAGE', 'Domácí stránka');
+@define('COMMENT', 'Komentáø');
+@define('REMEMBER_INFO', 'Zapamatovat informace? ');
+@define('SUBMIT_COMMENT', 'Odeslat komentáø');
+@define('NO_ENTRIES_TO_PRINT', '\8eádné záznamy k zobrazení');
+@define('COMMENTS', 'Komentáøe');
+@define('ADD_COMMENT', 'Pøidat komentáø');
+@define('NO_COMMENTS', '\8eádné komentáøe');
+@define('POSTED_BY', 'Vlo\9eil');
+@define('ON', 'v');
+@define('A_NEW_COMMENT_BLAHBLAH', 'Nový komentáø k weblogu "%s", k záznamu s názvem "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'Nová odezva na weblog/záznam s názvem "%s".');
+@define('NO_CATEGORY', '\8eádná kategorie');
+@define('ENTRY_BODY', 'Text záznamu');
+@define('EXTENDED_BODY', 'Roz\9aíøená textová èást');
+@define('CATEGORY', 'Kategorie');
+@define('EDIT', 'Editace');
+@define('NO_ENTRIES_BLAHBLAH', 'Nenalezen \9eádný záznam odpovídající volbì %s' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'Vyhledávání %s odpovídá %s výsledkù:');
+@define('SEARCH_TOO_SHORT', 'Výraz pro vyhledávání musí být del\9aí ne\9e 3 znaky');
+@define('IMAGE', 'Obrázek');
+@define('ERROR_FILE_NOT_EXISTS', 'Chyba: Jméno souboru neexistuje!');
+@define('ERROR_FILE_EXISTS', 'Chyba: Toto jméno souboru je u\9e pou\9eito, zvolte jiné!');
+@define('ERROR_SOMETHING', 'Chyba: Nìco je \9apatnì.');
+@define('ADDING_IMAGE', 'Pøidání obrázku...');
+@define('THUMB_CREATED_DONE', 'Náhled je vytvoøen.<br>Hotovo.');
+@define('ERROR_FILE_EXISTS_ALREADY', 'Chyba: Soubor u\9e ve va\9aem poèítaèi existuje!');
+@define('GO', 'Provést!');
+@define('NEWSIZE', 'Nový rozmìr: ');
+@define('RESIZE_BLAHBLAH', '<b>Zmìnit rozmìr %s</b><p>');
+@define('ORIGINAL_SIZE', 'Pùvodní rozmìr: <i>%sx%s</i> pixelù');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>Zde mù\9eete zadat nový rozmìr obrázku. Pokud chcete zachovat proporce, zadejte jen jednu hodnotu a stisknìte klávesu TAB, nový rozmìr bude dopoèítán automaticky:');
+@define('QUICKJUMP_CALENDAR', 'Vyhledávací kalendáø');
+@define('QUICKSEARCH', 'Rychlé hledání');
+@define('SEARCH_FOR_ENTRY', 'Hledání záznamu');
+@define('ARCHIVES', 'Archivy');
+@define('BROWSE_ARCHIVES', 'Prohlí\9eení mìsíèních archivù');
+@define('TOP_REFERRER', 'Top odbìratelé');
+@define('SHOWS_TOP_SITES', 'Nejèastìj\9aí pøipojení k tomuto weblogu');
+@define('TOP_EXITS', 'Top výstupy');
+@define('SHOWS_TOP_EXIT', 'Nejèastìj\9aí výstupy z tohoto weblogu');
+@define('SYNDICATION', 'Spolupráce');
+@define('SHOWS_RSS_BLAHBLAH', 'Sdílené RSS linky');
+@define('ADVERTISES_BLAHBLAH', 'Reklama na tvùrce systému va\9aeho weblogu');
+@define('HTML_NUGGET', 'Vlo\9eený HTML kód');
+@define('HOLDS_A_BLAHBLAH', 'Vlo\9eení HTML kódu do postranního sloupce');
+@define('TITLE_FOR_NUGGET', 'Název HTML kódu');
+@define('THE_NUGGET', 'Vlo\9eený HTML');
+@define('SYNDICATE_THIS_BLOG', 'Sdílení weblogu');
+@define('YOU_CHOSE', 'Vybral jste %s');
+@define('IMAGE_SIZE', 'Obrázek o rozmìru');
+@define('IMAGE_AS_A_LINK', 'Vlo\9eení obrázku');
+@define('POWERED_BY', 'Vytvoøeno pomocí');
+@define('SUPERUSER', 'Superu\9eivatel');
+@define('TRACKBACKS', 'Odezvy');
+@define('TRACKBACK', 'Odezva');
+@define('NO_TRACKBACKS', '\8eádné odezvy');
+@define('TOPICS_OF', 'Téma');
+@define('VIEW_FULL', 'Zobrazit v\9ae');
+@define('VIEW_TOPICS', 'Zobrazit téma');
+@define('AT', 'v');
+@define('SET_AS_TEMPLATE', 'Nastavit jako vzor');
+@define('IN', 've');
+@define('EXCERPT', 'Výpis');
+@define('TRACKED', 'Sledován');
+@define('LINK_TO_ENTRY', 'Odkaz na záznam');
+@define('LINK_TO_REMOTE_ENTRY', 'Odkaz na externí záznam');
+@define('IP_ADDRESS', 'IP adresa');
+@define('USER', 'U\9eivatel');
+@define('THUMBNAIL_USING_OWN', '%s je pou\9eit jako vlastní náhled, proto\9ee je pøíli\9a malý.');
+@define('THUMBNAIL_FAILED_COPY', '%s nelze pou\9eít jako vlastní náhled, nebo\9d jej nelze zkopírovat!');
+@define('AUTHOR', 'Autor');
+@define('LAST_UPDATED', 'Naposled zmìnìno');
+@define('TRACKBACK_SPECIFIC', 'Odezva ze specifického URI na tento záznam');
+@define('DIRECT_LINK', 'Pøímý odkaz na tento záznam');
+@define('COMMENT_ADDED', 'Vá\9a komentáø byl úspì\9anì pøidán.');
+@define('COMMENT_ADDED_CLICK', 'Kliknìte %ssem%s pro návrat ke komentáøùm nebo %ssem%s pro zavøení okna.');
+@define('COMMENT_NOT_ADDED', 'Vá\9a komentáø nebyl pøidán, proto\9ee  k tomuto záznamu nejsou komentáøe umo\9enìny. %sVra\9dte se%s zpìt ke komentáøùm nebo %szavøete%s toto okno.');
+@define('COMMENT_NOT_ADDED_CLICK', 'Kliknìte %ssem%s pro návrat ke komentáøùm nebo %ssem%s pro zavøení okna.');
+@define('COMMENTS_DISABLE', 'Neumo\9enit pøidávání komentáøù');
+@define('COMMENTS_ENABLE', 'Umo\9enit pøidávání komentáøù');
+@define('COMMENTS_CLOSED', 'Autor neumo\9enil pøidávat komentáøe');
+@define('EMPTY_COMMENT', 'Vá\9a komentáø nic neobsahuje, %svra\9dte se%s a zkuste to znovu');
+@define('ENTRIES_FOR', 'Záznamy: %s');
+@define('DOCUMENT_NOT_FOUND', 'Dokument %s nebyl nalezen.');
+@define('USERNAME', 'Jméno (pøezdívka)');
+@define('PASSWORD', 'Heslo');
+@define('AUTOMATIC_LOGIN', 'Ulo\9eit informace');
+@define('SERENDIPITY_INSTALLATION', 'Instalace Serendipity');
+@define('LEFT', 'vlevo');
+@define('RIGHT', 'vpravo');
+@define('HIDDEN', 'skrytý');
+@define('REMOVE_TICKED_PLUGINS', 'Odstranit oznaèené pluginy');
+@define('SAVE_CHANGES_TO_LAYOUT', 'Ulo\9eit zmìny layoutu');
+@define('COMMENTS_FROM', 'Komentáøe od');
+@define('ERROR', 'Chyba');
+@define('ENTRY_SAVED', 'Záznam ulo\9een');
+@define('DELETE_SURE', 'Urèitì chcete vymazat #%s natrvalo?');
+@define('NOT_REALLY', 'Nechci...');
+@define('DUMP_IT', 'Vymazat!');
+@define('RIP_ENTRY', 'Zru\9aen záznam #%s');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Kategorie #%s byla zru\9aena. Star\9aí záznamy byly pøemístìny do #%s');
+@define('CATEGORY_DELETED', 'Kategorie #%s byla zru~Zena.');
+@define('INVALID_CATEGORY', '\8eádná kategorie nebyla urèena k vymazání');
+@define('CATEGORY_SAVED', 'Kategorie ulo\9eena');
+@define('SELECT_TEMPLATE', 'Vyberte vzor pro vá\9a web');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'Záznamy nebyly vlo\9eeny úspì\9anì!');
+@define('YES', 'Ano');
+@define('NO', 'Ne');
+@define('USE_DEFAULT', 'Default');
+@define('CHECK_N_SAVE', 'Provìøit a ulo\9eit');
+@define('DIRECTORY_WRITE_ERROR', 'Nelze zapisovat do adresáøe %s - provìøte oprávnìní.');
+@define('DIRECTORY_CREATE_ERROR', 'Adresáø %s neexistuje a nemohl být vytvoøen. Vytvoøte adresáø manuálnì.');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; spustit <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', 'Nelze spustit binární soubor %s.');
+@define('FILE_WRITE_ERROR', 'Nelze zapisovat do souboru %s.');
+@define('FILE_CREATE_YOURSELF', 'Vytvoøte soubor pøímo nebo provìøte oprávnìní');
+@define('COPY_CODE_BELOW', '<br />* Zkopírujte kód uvedený ní\9ee a umístìte jej do %s ve va\9aem %s adresáøi:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Zmìòte www na u\9eivatele, který je urèen v Apache (na pø. nobody).');
+@define('BROWSER_RELOAD', 'Po dokonèení stisknìte tlaèítko obnovení stránky ve va\9aem prohlí\9eeèi.');
+@define('DIAGNOSTIC_ERROR', 'Diagnostika detekovala nìjaké chyby ve vkládaných informacích:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity je\9atì není nainstalován. <a href="%s">Instalujte</a> jej nyní.');
+@define('INCLUDE_ERROR', 'chyba serendipity: nelze vlo\9eit %s - ukonèeno.');
+@define('DATABASE_ERROR', 'chyba serendipity: nelze se spojit s databází - ukonèeno.');
+@define('CREATE_DATABASE', 'Vytvoøení základní databáze...');
+@define('ATTEMPT_WRITE_FILE', 'Pokus ulo\9eit soubor %s...');
+@define('WRITTEN_N_SAVED', 'Konfigurace byla zapsána a ulo\9eena');
+@define('IMAGE_ALIGNMENT', 'Úprava obrázku');
+@define('ENTER_NEW_NAME', 'Nový název: ');
+@define('RESIZING', 'Zmìna rozmìrù');
+@define('RESIZE_DONE', 'Hotovo (upraven rozmìr %s obrázkù).');
+@define('SYNCING', 'Synchronizace databáze s adresáøem obrázkù');
+@define('SYNC_DONE', 'Hotovo (synchronizováno %s obrázkù).');
+@define('DELETE_IMAGE_FAIL' , 'Nelze vymazat obrázek <b>%s</b>');
+@define('DELETE_THUMBNAIL', 'Vymazán náhled obrázku s názvem <b>%s</b>');
+@define('FILE_NOT_FOUND', 'Nelze nalézt soubor s názvem <b>%s</b>, mo\9ená je opravdu vymazán?');
+@define('ABORT_NOW', 'Zru\9ait');
+@define('REMOTE_FILE_NOT_FOUND', 'Soubor nebyl na vzdáleném serveru nalezen, jste si jist \9ee URL: <b>%s</b> je správné?');
+@define('FILE_FETCHED', '%s nalezen');
+@define('FILE_UPLOADED', 'Soubor %s je úspì\9anì nahrán.');
+@define('WORD_OR', 'nebo');
+@define('SCALING_IMAGE', 'Zmìna %s na %s x %s px');
+@define('KEEP_PROPORTIONS', 'Zachovat proporce');
+@define('REALLY_SCALE_IMAGE', 'Opravdu zmìnit rozmìr? Nelze vrátit!');
+@define('TOGGLE_ALL', 'Otevøít v\9ae');
+@define('TOGGLE_OPTION', 'Otevøít volbu');
+@define('SUBSCRIBE_TO_THIS_ENTRY', 'Pøihlásit se ke sledování komentáøù k záznamu');
+@define('UNSUBSCRIBE_OK', "%s je odhlá\9aen ze sledování komentáøù");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'Nový komentáø k pøihlá\9aenému záznamu "%s"');
+@define('SUBSCRIPTION_MAIL', "Pozor %s,\n\nA právì byl pøidán nový komentáø k záznamu, který sledujete na \"%s\", s názvem \"%s\"\nJméno odesílatele: %s\n\nZáznam najdete zde: %s\n\nMù\9eete se odhlásit zde: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "Pozor %s,\n\nA právì byla pøidána nová odezva k záznamu, který sledujete na \"%s\", s názvem \"%s\"\nJméno odesílatele: %s\n\nZáznam najdete zde: %s\n\nMù\9eete se odhlásit zde: %s\n");
+@define('SIGNATURE', "\n-- \n%s je vytvoøen pomocí Serendipity.\n Tento perfektní blogovací systém mù\9eete zdarma pou\9eívat také.\nNav\9ativte <http://s9y.org>, kde se dozvíte v\9ae potøebné.");
+@define('SYNDICATION_PLUGIN_091', 'Kanál RSS 0.91');
+@define('SYNDICATION_PLUGIN_20', 'Kanál RSS 2.0');
+@define('SYNDICATION_PLUGIN_10', 'Kanál RSS 1.0');
+@define('SYNDICATION_PLUGIN_20c', 'Komentáøe RSS 2.0');
+@define('SYNDICATION_PLUGIN_ATOM03', 'Kanál ATOM 0.3');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', 'Kanál %s');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'Pole "hlavní redaktor"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  'Pole "webmaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'Obrázek kanálu RSS');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', '\8aíøka');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'Vý\9aka');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  'E-mailová adresa webmastera, je-li k dispozici. (prázdné: skryté) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', 'E-mailová adresa hlavního redaktora, je-li k dispozici. (prázdné: skryté) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'URL obrázku ve formátu GIF/JPEG/PNG, je-li k dispozici. (prázdné: logo serendipity)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'v pixelech, max. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'v pixelech, max. 400');
+@define('SYNDICATION_PLUGIN_TTL', 'Pole "ttl" (\9eivotnost)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'Èas v minutách, po kterém by vá\9a weblog nemìl být nadále ke\9aován v cizích serverech/aplikacích (prázdné: skryté) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'Pole "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', 'Pole "pubDate"je pro kanál RSS ukryto, chcete ukázat datum posledního záznamu?');
+@define('CONTENT', 'Obsah');
+@define('TYPE', 'Typ');
+@define('DRAFT', 'Koncept');
+@define('PUBLISH', 'Publikovat');
+@define('PREVIEW', 'Ukázat');
+@define('DATE', 'Datum');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', 'Upozornìní: Datum je specifikováno \9apatnì. Pou\9eijte formát YYYY-MM-DD HH:MM.');
+@define('CATEGORY_PLUGIN_DESC', 'Seznam kategorií.');
+@define('ALL_AUTHORS', 'V\9aichni autoøi');
+@define('CATEGORIES_TO_FETCH', 'Vyhledat kategorie');
+@define('CATEGORIES_TO_FETCH_DESC', 'Vyhledat kategorie podle autorù?');
+@define('PAGE_BROWSE_ENTRIES', 'Stránka %s z %s, celkem %s záznamù');
+@define('PREVIOUS_PAGE', 'pøedchozí stránka');
+@define('NEXT_PAGE', 'dal\9aí stránka');
+@define('ALL_CATEGORIES', 'V\9aechny kategorie');
+@define('DO_MARKUP', 'Umo\9enit pøevod znaèek');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'Formátování data');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'Formát aktuálního data záznamu, pou\9eívá PHP promìnnou strftime(). (Pøednastaveno: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'Nelze otevøít vzorový soubor, updatujte Serendipity!');
+@define('ADVANCED_OPTIONS', 'Roz\9aíøené volby');
+@define('EDIT_ENTRY', 'Editovat záznam');
+@define('HTACCESS_ERROR', 'Provìøte instalaci va\9aeho webserveru, Serendipity potøebuje ulo\9eit soubor ".htaccess". To nebylo mo\9ené kvùli chybì oprávnìní. Nastavte oprávnìní jako: <br />&nbsp;&nbsp;%s<br />a znovu ulo\9ete tuto stránku.');
+@define('SIDEBAR_PLUGINS', 'Pluginy pro postranní sloupce');
+@define('EVENT_PLUGINS', 'Pluginy událostí');
+@define('SORT_ORDER', 'Poøadí');
+@define('SORT_ORDER_NAME', 'Název souboru');
+@define('SORT_ORDER_EXTENSION', 'Roz\9aíøení');
+@define('SORT_ORDER_SIZE', 'Velikost');
+@define('SORT_ORDER_WIDTH', '\8aíøka obrázku');
+@define('SORT_ORDER_HEIGHT', 'Vý\9aka obrázku');
+@define('SORT_ORDER_DATE', 'Datum nahrání');
+@define('SORT_ORDER_ASC', 'Vzestupnì');
+@define('SORT_ORDER_DESC', 'Sestupnì');
+@define('THUMBNAIL_SHORT', 'Náhl.');
+@define('ORIGINAL_SHORT', 'Orig.');
+@define('APPLY_MARKUP_TO', 'Zapnout znaèkování %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'Zaèátek týdne');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity detekoval, \9ee va\9ae konfigurace je ulo\9eena ve verzi %s, ale serendipity je instalován jako verze %s, je potøeba upgrade! <a href="%s">Kliknìte zde</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'Vítá vás mana\9eer upgrade Serendipity.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', 'Pomohu vám s upgrade va\9aí instalace Serendipity %s.');
+@define('SERENDIPITY_UPGRADER_WHY', 'Tato zpráva je zobrazena proto, \9ee va\9ae instalace je Serendipity %s, ale je\9atì nebyla updatována databáze pro tuto verzi');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'Update databáze (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'Zde jsou .sql soubory, která musíte spustit pøed pokraèováním práce se Serendipity');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  'Úlohy specifické pro tuto verzi');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', '\8eádné specifické úlohy');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', 'Mohu pokraèovat v tìchto úlohách?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'Ne, spustím je manuálnì');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'Ano, pokraèujte');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'Není tøeba \9eádný upgrade');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', 'Serendipity je upgradován');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'Vynechal jste stupeò upgrade Serendipity, ujistìte se, \9ee databáze je správnì nainstalována a plánované funkce jsou spu\9atìny');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'Va\9ae instalace Serendipity je upgradována na %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', 'Kliknutím %ssem%s se vrátíte do va\9aeho weblogu');
+@define('MANAGE_USERS', 'Správa u\9eivatelù');
+@define('CREATE_NEW_USER', 'Vytvoøit nového u\9eivatele');
+@define('CREATE_NOT_AUTHORIZED', 'Nemù\9eete editovat u\9eivatele se stejnou úrovní jako je va\9ae');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'Nemù\9eete vytvoøit u\9eivatele s vy\9a\9aí úrovní ne\9e je va\9ae');
+@define('CREATED_USER', 'Nový u\9eivatel %s byl vytvoøen');
+@define('MODIFIED_USER', 'Nastavení u\9eivatele %s byla zmìnìna');
+@define('USER_LEVEL', 'Úroveò');
+@define('DELETE_USER', 'Chcete vymazat u\9eivatele #%d %s. Myslíte to vá\9enì? Tato akce znemo\9ení prohlí\9eet jím vytvoøené záznamy na hlavní stránce.');
+@define('DELETED_USER', 'U\9eivatel #%d %s je vymazán.');
+@define('LIMIT_TO_NUMBER', 'Kolik záznamù by mìlo být zobrazeno?');
+@define('ENTRIES_PER_PAGE', 'záznamù na stránku');
+@define('DIRECTORIES_AVAILABLE', 'Po kliknutí na nìkterý adresáø v seznamu mù\9eete vytvoøit dal\9aí podadresáø.');
+@define('ALL_DIRECTORIES', 'v\9aechny adresáøe');
+@define('MANAGE_DIRECTORIES', 'Práce s adresáøi');
+@define('DIRECTORY_CREATED', 'Adresáø <strong>%s</strong> byl vytvoøen.');
+@define('PARENT_DIRECTORY', 'Základní adresáø');
+@define('CONFIRM_DELETE_DIRECTORY', 'Jste si jist, \9ee chcete odstranit v\9aechen obsah adresáøe %s?');
+@define('ERROR_NO_DIRECTORY', 'Chyba: Adresáø %s neexistuje');
+@define('CHECKING_DIRECTORY', 'Kontrola souborù v adresáøi %s');
+@define('DELETING_FILE', 'Vymazání souboru %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', 'Nelze odstranit neprázdný adresáø. Zkuste zvolit "vynucené mazání", pokud potøebujete vymazat tyto soubory, a ode\9alete po\9eadavek znovu. Existující soubory jsou:');
+@define('DIRECTORY_DELETE_FAILED', 'Vymazání adresáøe %s se nepodaøilo. Zkontrolujte oprávnìní nebo ètìte zprávu vý\9ae.');
+@define('DIRECTORY_DELETE_SUCCESS', 'Adresáø %s byl úspì\9anì vymazán.');
+@define('SKIPPING_FILE_EXTENSION', 'Vynechán soubor: Chybìjící pøípona %s.');
+@define('SKIPPING_FILE_UNREADABLE', 'Vynechán soubor: %s nelze naèíst.');
+@define('FOUND_FILE', 'Zalo\9eit nový/zmìnit soubor: %s.');
+@define('PERMISSIONS', 'Oprávnìní');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', 'Databáze');
+@define('INSTALL_CAT_DB_DESC', 'Sem vlo\9ete v\9aech informace o databázi. Serendipity je potøebuje k funkci.');
+@define('INSTALL_DBTYPE', 'Typ');
+@define('INSTALL_DBTYPE_DESC', 'Typ databáze');
+@define('INSTALL_DBHOST', 'Hostitel');
+@define('INSTALL_DBHOST_DESC', 'Název hostitelského serveru');
+@define('INSTALL_DBUSER', 'U\9eivatel');
+@define('INSTALL_DBUSER_DESC', 'U\9eivatelské jméno');
+@define('INSTALL_DBPASS', 'Heslo');
+@define('INSTALL_DBPASS_DESC', 'U\9eivatelské heslo');
+@define('INSTALL_DBNAME', 'Název');
+@define('INSTALL_DBNAME_DESC', 'Název databáze');
+@define('INSTALL_DBPREFIX', 'Prefix');
+@define('INSTALL_DBPREFIX_DESC', 'Prefix pro záznamy v databázi, napø. serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', 'Cesty');
+@define('INSTALL_CAT_PATHS_DESC', 'Cesty k rùzným adresáøùm a souborùm. Nezapomeòte na ukonèovací lomítko pro adresáøe!');
+@define('INSTALL_FULLPATH', 'Úplná cesta');
+@define('INSTALL_FULLPATH_DESC', 'Úplná absolutní cesta k va\9aí instalaci Serendipity.');
+@define('INSTALL_UPLOADPATH', 'Cesta pro uploady');
+@define('INSTALL_UPLOADPATH_DESC', 'Sem budou smìrovány uploady, relativnì k \'úplné cestì\' - typicky \'uploads/\'');
+@define('INSTALL_RELPATH', 'Relativní cesta');
+@define('INSTALL_RELPATH_DESC', 'Cesta k Serendipity pro vá\9a prohlí\9eeè, typicky \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', 'Relativní cesta k template');
+@define('INSTALL_RELTEMPLPATH_DESC', 'Cesta k adresáøi, obsahujícímu vzory (templates) - relativní k \'relativní cestì\'');
+@define('INSTALL_RELUPLOADPATH', 'Relativní cesta k uploadùm');
+@define('INSTALL_RELUPLOADPATH_DESC', 'Cesta k uploadùm pro prohlí\9eeèe - relativní k \'relativní cestì\'');
+@define('INSTALL_URL', 'URL weblogu');
+@define('INSTALL_URL_DESC', 'Základní URL va\9aí instalace Serendipity');
+@define('INSTALL_INDEXFILE', 'Indexový soubor');
+@define('INSTALL_INDEXFILE_DESC', 'Název souboru pou\9eitého jako index');
+
+/* Generel settings */
+@define('INSTALL_CAT_SETTINGS', 'Základní nastavení');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Úprava správy Serendipity');
+@define('INSTALL_USERNAME', 'Jméno admina');
+@define('INSTALL_USERNAME_DESC', 'Jméno pro pøihlá\9aení admina');
+@define('INSTALL_PASSWORD', 'Heslo admina');
+@define('INSTALL_PASSWORD_DESC', 'Heslo pro pøihlá\9aení admina');
+@define('INSTALL_EMAIL', 'E-mail admina');
+@define('INSTALL_EMAIL_DESC', 'E-mail pro pøihlá\9aení admina');
+@define('INSTALL_SENDMAIL', 'Posílat e-maily adminovi?');
+@define('INSTALL_SENDMAIL_DESC', 'Chcete dostávat e-mailem zprávy o komentáøích k va\9aim záznamùm?');
+@define('INSTALL_SUBSCRIBE', 'Umo\9enit odbìr komentáøù?');
+@define('INSTALL_SUBSCRIBE_DESC', 'Umo\9enit u\9eivatelùm pøihlá\9aení k odbìru komentáøù k záznamùm');
+@define('INSTALL_BLOGNAME', 'Název');
+@define('INSTALL_BLOGNAME_DESC', 'Název va\9aeho weblogu');
+@define('INSTALL_BLOGDESC', 'Popis');
+@define('INSTALL_BLOGDESC_DESC', 'Popis weblogu');
+@define('INSTALL_LANG', 'Jazyk');
+@define('INSTALL_LANG_DESC', 'Vyberte jazyk va\9aeho weblogu');
+
+/* Appearance and options */
+@define('INSTALL_CAT_DISPLAY', 'Vzhled a volby');
+@define('INSTALL_CAT_DISPLAY_DESC', 'Úprava vzhledu a chování Serendipity');
+@define('INSTALL_WYSIWYG', 'Pou\9eívat WYSIWYG editor?');
+@define('INSTALL_WYSIWYG_DESC', 'Chcete pou\9eívat WYSIWYG editor? (Pracuje v IE5+, èásteènì v Mozille 1.3+)');
+@define('INSTALL_XHTML11', 'Vnutit kompatibilitu s XHTML 1.1?');
+@define('INSTALL_XHTML11_DESC', 'Chcete plnou kompatibilitu s XHTML 1.1? (mù\9ee zpùsobit problémy ve star\9aích prohlí\9eeèích)');
+@define('INSTALL_POPUP', 'Umo\9enit pou\9eití vyskakovacích oken');
+@define('INSTALL_POPUP_DESC', 'Chcete ve weblogu pou\9eívat vyskakovací okna pro komentáøe, odezvy a pod.?');
+@define('INSTALL_EMBED', 'Je Serendipity vlo\9eené?');
+@define('INSTALL_EMBED_DESC', 'Pokud chcete umístit weblog do va\9aich stránek, zvolte ano pro odstranìní v\9aech záhlaví, bude zobrazován jen obsah. Mù\9eete pou\9eít volitelný soubor indexFile pro obalení obsahu vlastními záhlavími a sloupci. Více informací najdete v souboru README!');
+@define('INSTALL_BLOCKREF', 'Blokovaní odbìratelé');
+@define('INSTALL_BLOCKREF_DESC', 'Chcete zamezit pøístup z urèitých adres? Seznam adres oddìlujte \';\' a pozor, adresy jsou blokovány vèetnì subadres!');
+@define('INSTALL_REWRITE', 'Pøepisování URL');
+@define('INSTALL_REWRITE_DESC', 'Urèení pravidel pro tvorbu URL. Zapnutí módu pøepisování zajistí správné URL va\9aeho weblogu a lep\9aí indexaci pro vyhledávaèe, jako je Google. Vá\9a webserver musí podporovat mod_rewrite nebo "AllowOverride All" v adresáøi pro Serendipity. Defaultní nastavení je automaticky detekováno.');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', 'Úpravy obrázkù');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'Vlo\9eení základních informací o zpùsobu zpracování obrázkù');
+@define('INSTALL_IMAGEMAGICK', 'Pou\9eívat Imagemagick?');
+@define('INSTALL_IMAGEMAGICK_DESC', 'Máte instalován Imagemagick?');
+@define('INSTALL_IMAGEMAGICKPATH', 'Cesta ke konverznímu souboru');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'Úplná cesta a název konverzního souboru Imagemagick');
+@define('INSTALL_THUMBSUFFIX', 'Sufix náhledù');
+@define('INSTALL_THUMBSUFFIX_DESC', 'Náhledy budou pojmenovány original.sufix.ext');
+@define('INSTALL_THUMBWIDTH', 'Rozmìry náhledù');
+@define('INSTALL_THUMBWIDTH_DESC', 'Pevná \9aíøka automaticky generovaných náhledù');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', 'Osobní nastavení');
+@define('USERCONF_CAT_PERSONAL_DESC', 'Nastavení va\9aeho úètu');
+@define('USERCONF_USERNAME', 'Jméno');
+@define('USERCONF_USERNAME_DESC', 'Va\9ae u\9eivatelské jméno (pøezdívka)');
+@define('USERCONF_PASSWORD', 'Heslo');
+@define('USERCONF_PASSWORD_DESC', 'Va\9ae heslo');
+@define('USERCONF_EMAIL', 'E-mailová adresa');
+@define('USERCONF_EMAIL_DESC', 'Vá\9a e-mail');
+@define('USERCONF_SENDCOMMENTS', 'Posílat zprávy o komentáøích?');
+@define('USERCONF_SENDCOMMENTS_DESC', 'Chcete dostávat zprávy o komentáøích e-mailem?');
+@define('USERCONF_SENDTRACKBACKS', 'Posílat zprávy o odezvách?');
+@define('USERCONF_SENDTRACKBACKS_DESC', 'Chcete dostávat zprávy o odezvách na záznamy e-mailem?');
+@define('USERCONF_ALLOWPUBLISH', 'Právo publikovat záznamy?');
+@define('USERCONF_ALLOWPUBLISH_DESC', 'Umo\9enit u\9eivateli publikovat záznamy');
+
+@define('ALREADY_SUBCATEGORY', '%s je opravdu subkategorie pod %s.');
+@define('PARENT_CATEGORY', 'Nadøazená kategorie');
+@define('IN_REPLY_TO', 'Odpovìï na');
+@define('TOP_LEVEL', 'Nejvy\9a\9aí úroveò');
+@define('XML_IMAGE_TO_DISPLAY', 'Znak XML');
+@define('XML_IMAGE_TO_DISPLAY_DESC','Odkazy na XML kanály budou zobrazeny s tímto znakem. Nechejte prázdné pro pùvodní nastavení, nebo zadejte \'none\' pro vypnutí.');
+@define('SUCCESS', 'Úspìch');
+
+@define('POWERED_BY_SHOW_TEXT', 'Zobrazit "Serendipity" jako text');
+@define('POWERED_BY_SHOW_TEXT_DESC', 'Vytvoøeno v "Serendipity" se zobrazí jako text');
+@define('POWERED_BY_SHOW_IMAGE', 'Zobrazit "Serendipity" s logem');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Zobrazí se logo Serendipity');
+@define('INSTALL_TOP_AS_LINKS', 'Zobrazit Top výstupy/odbìratele jako linky?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"Ne": Výstupy a adresy odbìratelù budou zobrazeny jako èistý text pro zamezení spamu, "Ano": nebo jako hyperlinky. "Default": Pou\9eít globální nastavení (doporuèeno).');
+@define('SETTINGS_SAVED_AT', 'Nové nastavení bylo ulo\9eeno v %s');
+@define('PLUGIN_ITEM_DISPLAY', 'Kde by mìla být tato polo\9eka zobrazena?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'V roz\9aíøené èásti');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'V úvodu');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'V obou èástech');
+
+@define('RSS_IMPORT_CATEGORY', 'Pou\9eít tuto kategorii pro neurèené záznamy');
+@define('ERROR_UNKNOWN_NOUPLOAD', 'Neznámá chyba, soubor nebyl nahrán. Je mo\9ené, \9ee délka souboru pøekraèuje maximum, povolené serverem. Spojte se s va\9aím ISP nebo editujte soubor php.ini a povolte vìt\9aí velikost.');
+@define('COMMENTS_WILL_BE_MODERATED', 'Odeslané komentáøe budou pøed uveøejnìním moderovány.');
+@define('YOU_HAVE_THESE_OPTIONS', 'Máte k dispozici tyto volby:');
+@define('THIS_COMMENT_NEEDS_REVIEW', 'Pozor: Tento komentáø musí být pøed uveøejnìním odsouhlasen');
+@define('DELETE_COMMENT', 'Vymazat komentáø');
+@define('APPROVE_COMMENT', 'Odsouhlasit komentáø');
+@define('REQUIRES_REVIEW', 'Vy\9eádat pøezkoumání');
+@define('COMMENT_APPROVED', 'Komentáø #%s byl odsouhlasen');
+@define('COMMENT_DELETED', 'Komentáø #%s byl vymazán');
+@define('VIEW', 'Ukázat');
+@define('COMMENT_ALREADY_APPROVED', 'Komentáø #%s se jeví jako skuteènì odsouhlasený');
+@define('COMMENT_EDITED', 'Vybraný komentáø byl editován');
+@define('HIDE', 'Skrýt');
+@define('VIEW_EXTENDED_ENTRY', 'Pokraèovat ve ètení "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'Tento odkaz není mínìn jako klikatelný. Obsahuje zpìtné URI záznamu. Tento URI mù\9eete pou\9eít k odesílání pingù a sledování odezvy na tento záznam. Odkaz zkopírujete kliknutím pravou my\9aí a volbou "Kopírovat odkaz" v Internet Exploreru nebo "Zkopírovat umístìní odkazu" v Mozille.');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'Pozor: Tato odezva musí být pøed uveøejnìním odsouhlasena');
+@define('DELETE_TRACKBACK', 'Vymazat odezvu');
+@define('APPROVE_TRACKBACK', 'Odsouhlasit odezvu');
+@define('TRACKBACK_APPROVED', 'Odezva #%s byla odsouhlasena');
+@define('TRACKBACK_DELETED', 'Odezva #%s byla vymazána');
+@define('COMMENTS_MODERATE', 'Komentáøe a odezvy k tomuto záznamu budou moderovány');
+@define('PLUGIN_SUPERUSER_HTTPS', 'Pou\9eít https pro pøihlá\9aení');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'Umo\9eòuje pou\9eít spojení https pro pøihlá\9aení. Vá\9a server to musí podporovat!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'Udìlat externí odkazy klikatelné?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"Ne": Neoznaèené externí odkazy (Top výstupy, Top odbìratelé, U\9eivatelské komentáøe) nebudou ukázány/budou ukázány jako bì\9ený text v\9aude, kde je to mo\9ené, pro omezení spamu (doporuèeno). "Ano": Neoznaèené externí odkazy budou ukázány jako hyperlinky. Toto mù\9ee být pøepsáno v konfiguraci pluginù!');
+@define('PAGE_BROWSE_COMMENTS', 'Stránka %s ze %s, celkem %s komentáøù');
+@define('FILTERS', 'Filtry');
+@define('FIND_ENTRIES', 'Hledat záznamy');
+@define('FIND_COMMENTS', 'Hledat komentáøe');
+@define('FIND_MEDIA', 'Hledat média');
+@define('FILTER_DIRECTORY', 'Adresáø');
+@define('SORT_BY', 'Seøadit podle');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'Odezva nebyla odeslána: nepodaøilo se spojení s %s na portu %d');
+@define('MEDIA', 'Média (obrázky)');
+@define('MEDIA_LIBRARY', 'Knihovna médií');
+@define('ADD_MEDIA', 'Pøidat');
+@define('ENTER_MEDIA_URL', 'Vlo\9ete URL pøidávaného souboru:');
+@define('ENTER_MEDIA_UPLOAD', 'Vyberte soubor pro nahrání:');
+@define('SAVE_FILE_AS', 'Ulo\9eit soubor jako:');
+@define('STORE_IN_DIRECTORY', 'Ulo\9eit do následujího adresáøe: ');
+@define('MEDIA_RENAME', 'Pøejmenovat soubor');
+@define('IMAGE_RESIZE', 'Zmìnit rozmìr obrázku');
+@define('MEDIA_DELETE', 'Vymazat soubor');
+@define('FILES_PER_PAGE', 'Souborù na stránku');
+@define('CLICK_FILE_TO_INSERT', 'Kliknìte na soubor, který chcete vlo\9eit:');
+@define('SELECT_FILE', 'Vyberte soubor pro vlo\9eení:');
+@define('MEDIA_FULLSIZE', 'Plný rozmìr');
+@define('CALENDAR_BOW_DESC', 'Den, urèený jako zaèátek týdne. Default je pondìlí');
+@define('ALLOWS_YOU_BLAHBLAH', 'Vlo\9eit odkaz do postranního bloku administrace weblogu');
+@define('CALENDAR', 'Kalendáø');
+@define('SUPERUSER_OPEN_ADMIN', 'Administrace');
+@define('SUPERUSER_OPEN_LOGIN', 'Pøihlá\9aení');
+@define('INVERT_SELECTIONS', 'Obrátit výbìr');
+@define('COMMENTS_DELETE_CONFIRM', 'Jste se jist vymazáním vybraných komentáøù?');
+@define('COMMENT_DELETE_CONFIRM', 'Jste si jist vymazáním komentáøe #%d, zapsaného %s?');
+@define('DELETE_SELECTED_COMMENTS', 'Vymazat vybrané komentáøe');
+@define('VIEW_COMMENT', 'Ukázat komentáø');
+@define('VIEW_ENTRY', 'Ukázat záznam');
+@define('DELETE_FILE', 'Vymazat soubor s názvem <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', 'Chcete vymazat <b>%s</b><br />Jestli\9ee pou\9eíváte tento soubor v nìjakých záznamech, zpùsobí to nepøístupnost odkazù nebo obrázkù.<br />Chcete pøesto pokraèovat?<br /><br />');
+@define('TRACKBACK_SENDING', 'Odeslání odezvy na URI %s...');
+@define('TRACKBACK_SENT', 'Odezva úspì\9aná');
+@define('TRACKBACK_FAILED', 'Odezva neúspì\9aná: %s');
+@define('TRACKBACK_NOT_FOUND', 'URI odezvy neexistuje.');
+@define('TRACKBACK_URI_MISMATCH', 'Automaticky získané URI neodpovídá va\9aemu cílovému.');
+@define('TRACKBACK_CHECKING', 'Testvání <u>%s</u> pro mo\9ené odezvy...');
+@define('TRACKBACK_NO_DATA', 'Cíl neobsahuje data');
+@define('TRACKBACK_SIZE', 'Cílové URI pøekroèilo max. velikost souboru %s bytù.');
+@define('VIEWMODE_THREADED', 'Pøepnout na vláknové zobrazení');
+@define('COMMENTS_VIEWMODE_THREADED', 'Vláknové');
+@define('COMMENTS_VIEWMODE_LINEAR', 'Lineární');
+@define('DISPLAY_COMMENTS_AS', 'Zobrazit komentáøe jako');
+@define('ADD_MEDIA_BLAHBLAH', '<b>Pøidat soubor do schránky médií:</b><p>Zde mù\9eete ukládat mediální soubory, nebo urèit, kde je získat z WEBu! Pokud nemáte odpovídající obrázek, <a href="http://images.google.com" target="_blank">hledejte na Google</a> odpovìï na va\9ai potøebu, obvykle se zadaøí :).<p><b>Vyberte metodu:</b><br>');
+@define('COMMENTS_FILTER_SHOW', 'Zobrazit');
+@define('COMMENTS_FILTER_ALL', 'V\9ae');
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'Pouze povolené');
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'Èekající na povolení');
+@define('RSS_IMPORT_BODYONLY', 'Ulo\9eit celý importovaný text do "hlavní" èásti, nerozdìlovat do "roz\9aíøené" èásti.');
+@define('SYNDICATION_PLUGIN_FULLFEED', 'Zobrazit celé èlánky vèetnì roz\9aíøené èásti v RSS kanálu');
+@define('MT_DATA_FILE', 'Soubory Movable Type');
+@define('FORCE', 'Vnutit');
+@define('CREATE_AUTHOR', 'Vytvoøit autora \'%s\'.');
+@define('CREATE_CATEGORY', 'Vytvoøit kategorii \'%s\'.');
+@define('MYSQL_REQUIRED', 'Pro provedení této akce je nutné mít databázi MySQL.');
+@define('COULDNT_CONNECT', 'Nebylo mo\9ené se spojit s databází MySQL: %s.');
+@define('COULDNT_SELECT_DB', 'Nebylo mo\9ené vybrat databázi: %s.');
+@define('COULDNT_SELECT_USER_INFO', 'Nebylo mo\9ené vybrat u\9eivatelské informace: %s.');
+@define('COULDNT_SELECT_CATEGORY_INFO', 'Nebylo mo\9ené vybrat informace o kategorii: %s.');
+@define('COULDNT_SELECT_ENTRY_INFO', 'Nebylo mo\9ené vybrat informace o záznamu: %s.');
+@define('COULDNT_SELECT_COMMENT_INFO', 'Nebylo mo\9ené vybrat informace o komentáøi: %s.');
+@define('WEEK', 'Týden');
+@define('WEEKS', 'Týdny');
+@define('MONTHS', 'Mìsíce');
+@define('DAYS', 'Dny');
+@define('ARCHIVE_FREQUENCY', 'Kalendáøní krok');
+@define('ARCHIVE_FREQUENCY_DESC', 'Kalendáøní krok mezi prvky seznamu');
+@define('ARCHIVE_COUNT', 'Poèet prvkù v seznamu');
+@define('ARCHIVE_COUNT_DESC', 'Celkový poèet zobrazených mìsícù, týdnù nebo dnù');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'Ní\9ee je seznam instalovaných pluginù');
+@define('SIDEBAR_PLUGIN', 'postranní plugin');
+@define('EVENT_PLUGIN', 'plugin události');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'Kliknìte a instalujte nový %s');
+@define('VERSION', 'verze');
+@define('INSTALL', 'Instalovat');
+@define('ALREADY_INSTALLED', 'Instalován');
+@define('SELECT_A_PLUGIN_TO_ADD', 'Vyberte plugin, který chcete instalovat');
+@define('INSTALL_OFFSET', 'Èasový posun serveru');
+@define('STICKY_POSTINGS', 'Pøilepené záznamy');
+@define('INSTALL_FETCHLIMIT', 'Záznamy zobrazené na hlavní stránce');
+@define('INSTALL_FETCHLIMIT_DESC', 'Poèet záznamù, zobrazených na hlavní stránce');
+@define('IMPORT_ENTRIES', 'Import dat');
+@define('EXPORT_ENTRIES', 'Export záznamù');
+@define('IMPORT_WELCOME', 'Vítejte v utilitì pro import dat');
+@define('IMPORT_WHAT_CAN', 'Zde mù\9eete importovat záznamy z jiných weblogù');
+@define('IMPORT_SELECT', 'Vyberte software, ze kterého chcete importovat');
+@define('IMPORT_PLEASE_ENTER', 'Vlo\9ete data po\9eadovaná ní\9ee');
+@define('IMPORT_NOW', 'Importovat!');
+@define('IMPORT_STARTING', 'Start importu...');
+@define('IMPORT_FAILED', 'Import se nezdaøil');
+@define('IMPORT_DONE', 'Import úspì\9anì dokonèen');
+@define('IMPORT_WEBLOG_APP', 'Weblogová aplikace');
+@define('EXPORT_FEED', 'Exportovat plný RSS kanál');
+@define('STATUS', 'Stav po importu');
+@define('IMPORT_GENERIC_RSS', 'Základní RSS import');
+@define('ACTIVATE_AUTODISCOVERY', 'Odeslat odezvy na odkazy obsa\9eené v záznamu');
+@define('WELCOME_TO_ADMIN', 'Vítejte v Administraèní sekci Serendipity .');
+@define('PLEASE_ENTER_CREDENTIALS', 'Vlo\9ete oprávnìní.');
+@define('ADMIN_FOOTER_POWERED_BY', 'Vytvoøeno pomocí Serendipity %s a PHP %s');
+@define('INSTALL_USEGZIP', 'Pou\9eijte kompresi gzip');
+@define('INSTALL_USEGZIP_DESC', 'Doporuèujeme pou\9eít kompresi stránek pro jejich urychlené naèítání');
+@define('INSTALL_SHOWFUTURE', 'Zobrazit budoucí záznamy');
+@define('INSTALL_SHOWFUTURE_DESC', 'Tato volba umo\9ení zobrazení budoucích záznamù blogu. Defaultnì jsou skryté a budou zobrazeny a\9e v èase jejich vydání.');
+@define('INSTALL_DBPERSISTENT', 'Pou\9eít trvalé pøipojení');
+@define('INSTALL_DBPERSISTENT_DESC', 'Umo\9enit trvalé pøipojení k databázi, více <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">zde</a>. Bì\9enì to není doporuèeno');
+@define('NO_IMAGES_FOUND', '\8eádné obrázky');
+@define('PERSONAL_SETTINGS', 'Osobní nastavení');
+@define('REFERER', 'Odbìratel');
+@define('NOT_FOUND', 'Není obsa\9een');
+@define('NOT_WRITABLE', 'Nezapisovatelný');
+@define('WRITABLE', 'Zapisovatelný');
+@define('PROBLEM_DIAGNOSTIC', 'Byly diagnostikovány problémy, tak\9ee nelze pokraèovat v instalaci, dokud nebudou odstranìny');
+@define('SELECT_INSTALLATION_TYPE', 'Vyberte typ instalace');
+@define('WELCOME_TO_INSTALLATION', 'Vítejte v instalaci Serendipity');
+@define('FIRST_WE_TAKE_A_LOOK', 'Nejdøíve se podíváme na va\9ae základní nastavení a zkusíme diagnostikovat pøípadné problémy');
+@define('ERRORS_ARE_DISPLAYED_IN', 'Chyby budou zobrazeny %s, doporuèení %s a úspìch %s');
+@define('RED', 'èervenì');
+@define('YELLOW', '\9elutì');
+@define('GREEN', 'zelenì');
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s - pøedinstalaèní zpráva');
+@define('RECOMMENDED', 'Doporuèeno');
+@define('ACTUAL', 'Aktuální');
+@define('PHPINI_CONFIGURATION', 'konfigurace php.ini');
+@define('PHP_INSTALLATION', 'Instalace PHP');
+@define('THEY_DO', 'they do');
+@define('THEY_DONT', 'they don\'t');
+@define('SIMPLE_INSTALLATION', 'Jednoduchá instalace');
+@define('EXPERT_INSTALLATION', 'Expertní instalace');
+@define('COMPLETE_INSTALLATION', 'Kompletní instalace');
+@define('WONT_INSTALL_DB_AGAIN', 'nechci znovu instalovat databázi');
+@define('CHECK_DATABASE_EXISTS', 'Kontrola, jestli databáze a tabulky opravdu existují');
+@define('CREATING_PRIMARY_AUTHOR', 'Vytvoøení hlavního autora \'%s\'');
+@define('SETTING_DEFAULT_TEMPLATE', 'Nastavení defaultního vzoru');
+@define('INSTALLING_DEFAULT_PLUGINS', 'Instalace defaultních pluginù');
+@define('SERENDIPITY_INSTALLED', 'Serendipity byl úspì\9anì nainstalován');
+@define('VISIT_BLOG_HERE', 'Zde se pøepnete do svého nového weblogu');
+@define('THANK_YOU_FOR_CHOOSING', 'Dìkujeme za volbu Serendipity');
+@define('ERROR_DETECTED_IN_INSTALL', 'Pøi instalaci byla detekována chyba');
+@define('OPERATING_SYSTEM', 'Operaèní systém');
+@define('WEBSERVER_SAPI', 'Webserver SAPI');
+@define('IMAGE_ROTATE_LEFT', 'Otoèit o 90 stupòù doleva');
+@define('IMAGE_ROTATE_RIGHT', 'Otoèit o 90 stupòù doprava');
+@define('TEMPLATE_SET', '\'%s\' byl nastaven jako defaultní vzor (template)');
+@define('SEARCH_ERROR', 'Funkce vyhledávání nepracovala podle oèekávání. Poznámka pro administrátora blogu: Mohlo to být zpùsobeno nepøítomností pøíslu\9aných indexù v databázi. U\9eivatelský úèet v databázi MySQL musí být oprávnìn vykonat tento dotaz: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> Specifická chyba vrácená databází byla: <pre>%s</pre>');
+@define('EDIT_THIS_CAT', 'Editace "%s"');
+@define('CATEGORY_REMAINING', 'Vymazat kategorii a pøemístit záznamy do kategorie');
+@define('CATEGORY_INDEX', 'Ní\9ee je seznam kategorií, které mù\9eet pou\9eít k va\9aemu záznamu');
+@define('NO_CATEGORIES', '\8eádné kategorie');
+@define('RESET_DATE', 'Resetovat datum');
+@define('RESET_DATE_DESC', 'Kliknìte a resetujte datum na aktuální');
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Oprávnìní mù\9ee být nastaveno s pou\9eitím povelu: `<em>%s</em>` v adresáøi, nebo nastavením pomocí FTP programu');
+@define('WARNING_TEMPLATE_DEPRECATED', 'Varování: Vá\9a vzor pou\9eívá nepovolenou metodu, je-li to mo\9ené, proveïte aktualizaci');
+@define('ENTRY_PUBLISHED_FUTURE', 'Tento záznam je\9atì není publikován.');
+@define('ENTRIES_BY', 'Záznamy od %s');
+@define('PREVIOUS', 'Pøedchozí');
+@define('NEXT', 'Dal\9aí');
+@define('APPROVE', 'Povolit');
+@define('DO_MARKUP_DESCRIPTION', 'Pøevést znaèky na text (smajlíky, zkratky *, /, _, ...). Vypnutí této volby zajistí ulo\9eení HTML kódù v textu.');
+@define('CATEGORY_ALREADY_EXIST', 'Kategorie nazvaná "%s" skuteènì existuje'); 
+@define('IMPORT_NOTES', 'Poznámka:'); 
+@define('ERROR_FILE_FORBIDDEN', 'Nejste oprávnìn nahrávat soubory s aktivním obsahem'); 
+@define('ADMIN', 'Administrace'); 
+@define('ADMIN_FRONTPAGE', 'Hlavní stránka'); 
+@define('QUOTE', 'Citace'); 
+@define('IFRAME_SAVE', 'Serendipity ukládá vá\9a záznam, vytváøí odezvy a zaji\9a\9duje mo\9ená XML-RPC spojení. Mù\9ee to chvíli trvat...'); 
+@define('IFRAME_SAVE_DRAFT', 'Koncept tohoto záznamu byl ulo\9een'); 
+@define('IFRAME_PREVIEW', 'Serendipity nyní vytváøí náhled va\9aeho záznamu...'); 
+@define('IFRAME_WARNING', 'Vá\9a prohlí\9eeè nepodporuje iframe. Otevøete soubor serendipity_config.inc.php a nastavte promìnnou $serendipity[\'use_iframe\'] na FALSE.'); 
+@define('NONE', 'nic');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Základní nastavení pro nové záznamy'); 
+@define('UPGRADE', 'Aktualizace'); 
+@define('UPGRADE_TO_VERSION', 'Aktualizace na verzi %s'); 
+@define('DELETE_DIRECTORY', 'Vymazat adresáø'); 
+@define('DELETE_DIRECTORY_DESC', 'Chcete vymazat obsah adresáøe, obsahující mediální soubory, které mohou být pou\9eívány ve va\9aich záznamech.'); 
+@define('FORCE_DELETE', 'Vymazat V\8aECHNY soubory v adresáøi, vèetnì tìch, které nejsou vytvoøeny pomocí Serendipity'); 
+@define('CREATE_DIRECTORY', 'Vytvoøit adresáø'); 
+@define('CREATE_NEW_DIRECTORY', 'Vytvoøit nový adresáø'); 
+@define('CREATE_DIRECTORY_DESC', 'Zde mù\9eete vytvoøit adresáø pro ukládání mediálních souborù. Zvolte název adresáøe a pøípadný nadøízený adresáø.'); 
+@define('BASE_DIRECTORY', 'Základní adresáø'); 
+@define('USERLEVEL_EDITOR_DESC', 'Autor'); 
+@define('USERLEVEL_CHIEF_DESC', 'Redaktor'); 
+@define('USERLEVEL_ADMIN_DESC', 'Administrátor'); 
+@define('USERCONF_USERLEVEL', 'Úroveò'); 
+@define('USERCONF_USERLEVEL_DESC', 'Tato úroveò urèuje práva u\9eivatele weblogu.'); 
+@define('USER_SELF_INFO', 'Pøihlá\9aen jako %s (%s)'); 
+@define('ADMIN_ENTRIES', 'Záznamy'); 
+@define('RECHECK_INSTALLATION', 'Pøekontrolovat instalaci'); 
+@define('IMAGICK_EXEC_ERROR', 'Nelze spustit: "%s", chyba: %s, vrací promìnnou: %d'); 
+@define('INSTALL_OFFSET_DESC', 'Vlo\9ete poèet hodin mezi èasem serveru (aktuálnì: %clock%) a va\9aí èasovou zónou'); 
+@define('UNMET_REQUIREMENTS', 'Nesplnìné po\9eadavky: %s'); 
+@define('CHARSET', 'Znaková sada');
+@define('AUTOLANG', 'Pou\9eít jazyk prohlí\9eeèe jako defaultní');
+@define('AUTOLANG_DESC', 'Zapnutím této volby urèíte, \9ee jazyk prohlí\9eeèe bude pøevzat jako základní pro u\9eivatelské rozhraní a pro záznamy.');
+@define('INSTALL_AUTODETECT_URL', 'Autodetekce pou\9eité HTTP hostitelské adresy'); 
+@define('INSTALL_AUTODETECT_URL_DESC', 'Pøi volbì "Ano" bude Serendipity pøedpokládat, \9ee HTTP adresa hostitele, pou\9eitá náv\9atìvníkem, je va\9ae základní nastavení URL. Zapnutí umo\9ení pou\9eívání rùzných domén k pøístupu na va\9ae stránky, a pou\9eití této jedné domény pro v\9aechny odkazy ke sledování zmìn na stránkách.'); 
+@define('CONVERT_HTMLENTITIES', 'Zkusit automatickou konverzi HTML entit?');
+@define('EMPTY_SETTING', 'Nespecifikoval jste platnou hodnotu pro "%s"!');
+@define('USERCONF_REALNAME', 'Skuteèné jméno'); 
+@define('USERCONF_REALNAME_DESC', 'Plné jméno autora. Toto jméno uvidí ètenáøi'); 
+@define('HOTLINK_DONE', 'Soubor pøipojen odkazem.<br />Hotovo.'); 
+@define('ENTER_MEDIA_URL_METHOD', 'Zpùsob pøipojení:'); 
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Poznámka: Pokud zvolíte odkaz na server, ujistìte se, \9ee máte potøebná práva, nebo \9ee jde o vá\9a web. Odkazy vám umo\9ení vyu\9eívat obrázky z jiných ne\9e místních zdrojù.'); 
+@define('MEDIA_HOTLINKED', 'odkazován'); 
+@define('FETCH_METHOD_IMAGE', 'Nahrání na server'); 
+@define('FETCH_METHOD_HOTLINK', 'Odkaz na server'); 
+@define('DELETE_HOTLINK_FILE', 'Vymazán odkazovaný soubor <b>%s</b>'); 
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Show E-Mail addresses?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_cz.inc.php b/lang/serendipity_lang_cz.inc.php
new file mode 100644 (file)
index 0000000..d1bf1a9
--- /dev/null
@@ -0,0 +1,671 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Translation (c) 2004 Josef Klimosz <ok2wo@centrum.cz>
+
+@define('LANG_CHARSET', 'ISO-8859-2');
+@define('DATE_LOCALES', 'Czech, cs, cs_CZ.ISO-8859-2');
+@define('DATE_FORMAT_ENTRY', '%A, %e. %B %Y');
+@define('DATE_FORMAT_SHORT', '%d/%m/%Y %H.%M');
+@define('WYSIWYG_LANG', 'cs-iso');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', ',');
+@define('NUMBER_FORMAT_THOUSANDS', ' ');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Administrátorská sekce');
+@define('HAVE_TO_BE_LOGGED_ON', 'Pro zobrazení této stránky musíte být pøihlá¹en');
+@define('WRONG_USERNAME_OR_PASSWORD', 'Zøejmì jste vlo¾il ¹patné jméno nebo heslo!');
+@define('APPEARANCE', 'Vzhled');
+@define('MANAGE_STYLES', 'Zmìna stylu');
+@define('CONFIGURE_PLUGINS', 'Konfigurace pluginù');
+@define('CONFIGURATION', 'Konfigurace');
+@define('BACK_TO_BLOG', 'Zpìt do weblogu');
+@define('LOGIN', 'Pøihlá¹ení');
+@define('LOGOUT', 'Odhlá¹ení');
+@define('LOGGEDOUT', 'Odhlá¹en');
+@define('CREATE', 'Vytvoøit');
+@define('SAVE', 'Ulo¾it');
+@define('NAME', 'Jméno');
+@define('CREATE_NEW_CAT', 'Vytvoøení nové kategorie');
+@define('I_WANT_THUMB', 'Pou¾ít náhled.');
+@define('I_WANT_BIG_IMAGE', 'Pou¾ít celý obrázek.');
+@define('I_WANT_NO_LINK', ' Zobrazit jako obrázek');
+@define('I_WANT_IT_TO_LINK', 'Zobrazit jako odkaz (URL):');
+@define('BACK', 'Zpìt');
+@define('FORWARD', 'Dále');
+@define('ANONYMOUS', 'Anonym');
+@define('NEW_TRACKBACK_TO', 'Nová odezva na');
+@define('NEW_COMMENT_TO', 'Nový komentáø k');
+@define('RECENT', 'Nové...');
+@define('OLDER', 'Star¹í...');
+@define('DONE', 'Hotovo');
+@define('WELCOME_BACK', 'Vítejte zpìt,');
+@define('TITLE', 'Titulek');
+@define('DESCRIPTION', 'Popis');
+@define('PLACEMENT', 'Umístìní');
+@define('DELETE', 'Vymazat');
+@define('SAVE', 'Ulo¾it');
+@define('UP', 'Nahoru');
+@define('DOWN', 'Dolù');
+@define('ENTRIES', 'záznamy');
+@define('NEW_ENTRY', 'Nový záznam');
+@define('EDIT_ENTRIES', 'Editovat záznamy');
+@define('CATEGORIES', 'Kategorie');
+@define('WARNING_THIS_BLAHBLAH', "POZOR:\\nTato akce mù¾e trvat déle pokud máte mnoho obrázkù bez náhledù.");
+@define('CREATE_THUMBS', 'Vytvoøit náhledy');
+@define('MANAGE_IMAGES', 'Správa obrázkù');
+@define('NAME', 'Jméno');
+@define('EMAIL', 'E-mail');
+@define('HOMEPAGE', 'Domácí stránka');
+@define('COMMENT', 'Komentáø');
+@define('REMEMBER_INFO', 'Zapamatovat informace? ');
+@define('SUBMIT_COMMENT', 'Odeslat komentáø');
+@define('NO_ENTRIES_TO_PRINT', '®ádné záznamy k zobrazení');
+@define('COMMENTS', 'Komentáøe');
+@define('ADD_COMMENT', 'Pøidat komentáø');
+@define('NO_COMMENTS', '®ádné komentáøe');
+@define('POSTED_BY', 'Vlo¾il');
+@define('ON', 'v');
+@define('A_NEW_COMMENT_BLAHBLAH', 'Nový komentáø k weblogu "%s", k záznamu s názvem "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'Nová odezva na weblog/záznam s názvem "%s".');
+@define('NO_CATEGORY', '®ádná kategorie');
+@define('ENTRY_BODY', 'Text záznamu');
+@define('EXTENDED_BODY', 'Roz¹íøená textová èást');
+@define('CATEGORY', 'Kategorie');
+@define('EDIT', 'Editace');
+@define('NO_ENTRIES_BLAHBLAH', 'Nenalezen ¾ádný záznam odpovídající volbì %s' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'Vyhledávání %s odpovídá %s výsledkù:');
+@define('SEARCH_TOO_SHORT', 'Výraz pro vyhledávání musí být del¹í ne¾ 3 znaky');
+@define('IMAGE', 'Obrázek');
+@define('ERROR_FILE_NOT_EXISTS', 'Chyba: Jméno souboru neexistuje!');
+@define('ERROR_FILE_EXISTS', 'Chyba: Toto jméno souboru je u¾ pou¾ito, zvolte jiné!');
+@define('ERROR_SOMETHING', 'Chyba: Nìco je ¹patnì.');
+@define('ADDING_IMAGE', 'Pøidání obrázku...');
+@define('THUMB_CREATED_DONE', 'Náhled je vytvoøen.<br>Hotovo.');
+@define('ERROR_FILE_EXISTS_ALREADY', 'Chyba: Soubor u¾ ve va¹em poèítaèi existuje!');
+@define('GO', 'Provést!');
+@define('NEWSIZE', 'Nový rozmìr: ');
+@define('RESIZE_BLAHBLAH', '<b>Zmìnit rozmìr %s</b><p>');
+@define('ORIGINAL_SIZE', 'Pùvodní rozmìr: <i>%sx%s</i> pixelù');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>Zde mù¾ete zadat nový rozmìr obrázku. Pokud chcete zachovat proporce, zadejte jen jednu hodnotu a stisknìte klávesu TAB, nový rozmìr bude dopoèítán automaticky:');
+@define('QUICKJUMP_CALENDAR', 'Vyhledávací kalendáø');
+@define('QUICKSEARCH', 'Rychlé hledání');
+@define('SEARCH_FOR_ENTRY', 'Hledání záznamu');
+@define('ARCHIVES', 'Archivy');
+@define('BROWSE_ARCHIVES', 'Prohlí¾ení mìsíèních archivù');
+@define('TOP_REFERRER', 'Top odbìratelé');
+@define('SHOWS_TOP_SITES', 'Nejèastìj¹í pøipojení k tomuto weblogu');
+@define('TOP_EXITS', 'Top výstupy');
+@define('SHOWS_TOP_EXIT', 'Nejèastìj¹í výstupy z tohoto weblogu');
+@define('SYNDICATION', 'Spolupráce');
+@define('SHOWS_RSS_BLAHBLAH', 'Sdílené RSS linky');
+@define('ADVERTISES_BLAHBLAH', 'Reklama na tvùrce systému va¹eho weblogu');
+@define('HTML_NUGGET', 'Vlo¾ený HTML kód');
+@define('HOLDS_A_BLAHBLAH', 'Vlo¾ení HTML kódu do postranního sloupce');
+@define('TITLE_FOR_NUGGET', 'Název HTML kódu');
+@define('THE_NUGGET', 'Vlo¾ený HTML');
+@define('SYNDICATE_THIS_BLOG', 'Sdílení weblogu');
+@define('YOU_CHOSE', 'Vybral jste %s');
+@define('IMAGE_SIZE', 'Obrázek o rozmìru');
+@define('IMAGE_AS_A_LINK', 'Vlo¾ení obrázku');
+@define('POWERED_BY', 'Vytvoøeno pomocí');
+@define('SUPERUSER', 'Superu¾ivatel');
+@define('TRACKBACKS', 'Odezvy');
+@define('TRACKBACK', 'Odezva');
+@define('NO_TRACKBACKS', '®ádné odezvy');
+@define('TOPICS_OF', 'Téma');
+@define('VIEW_FULL', 'Zobrazit v¹e');
+@define('VIEW_TOPICS', 'Zobrazit téma');
+@define('AT', 'v');
+@define('SET_AS_TEMPLATE', 'Nastavit jako vzor');
+@define('IN', 've');
+@define('EXCERPT', 'Výpis');
+@define('TRACKED', 'Sledován');
+@define('LINK_TO_ENTRY', 'Odkaz na záznam');
+@define('LINK_TO_REMOTE_ENTRY', 'Odkaz na externí záznam');
+@define('IP_ADDRESS', 'IP adresa');
+@define('USER', 'U¾ivatel');
+@define('THUMBNAIL_USING_OWN', '%s je pou¾it jako vlastní náhled, proto¾e je pøíli¹ malý.');
+@define('THUMBNAIL_FAILED_COPY', '%s nelze pou¾ít jako vlastní náhled, nebo» jej nelze zkopírovat!');
+@define('AUTHOR', 'Autor');
+@define('LAST_UPDATED', 'Naposled zmìnìno');
+@define('TRACKBACK_SPECIFIC', 'Odezva ze specifického URI na tento záznam');
+@define('DIRECT_LINK', 'Pøímý odkaz na tento záznam');
+@define('COMMENT_ADDED', 'Vá¹ komentáø byl úspì¹nì pøidán.');
+@define('COMMENT_ADDED_CLICK', 'Kliknìte %ssem%s pro návrat ke komentáøùm nebo %ssem%s pro zavøení okna.');
+@define('COMMENT_NOT_ADDED', 'Vá¹ komentáø nebyl pøidán, proto¾e  k tomuto záznamu nejsou komentáøe umo¾nìny. %sVra»te se%s zpìt ke komentáøùm nebo %szavøete%s toto okno.');
+@define('COMMENT_NOT_ADDED_CLICK', 'Kliknìte %ssem%s pro návrat ke komentáøùm nebo %ssem%s pro zavøení okna.');
+@define('COMMENTS_DISABLE', 'Neumo¾nit pøidávání komentáøù');
+@define('COMMENTS_ENABLE', 'Umo¾nit pøidávání komentáøù');
+@define('COMMENTS_CLOSED', 'Autor neumo¾nil pøidávat komentáøe');
+@define('EMPTY_COMMENT', 'Vá¹ komentáø nic neobsahuje, %svra»te se%s a zkuste to znovu');
+@define('ENTRIES_FOR', 'Záznamy: %s');
+@define('DOCUMENT_NOT_FOUND', 'Dokument %s nebyl nalezen.');
+@define('USERNAME', 'Jméno (pøezdívka)');
+@define('PASSWORD', 'Heslo');
+@define('AUTOMATIC_LOGIN', 'Ulo¾it informace');
+@define('SERENDIPITY_INSTALLATION', 'Instalace Serendipity');
+@define('LEFT', 'vlevo');
+@define('RIGHT', 'vpravo');
+@define('HIDDEN', 'skrytý');
+@define('REMOVE_TICKED_PLUGINS', 'Odstranit oznaèené pluginy');
+@define('SAVE_CHANGES_TO_LAYOUT', 'Ulo¾it zmìny layoutu');
+@define('COMMENTS_FROM', 'Komentáøe od');
+@define('ERROR', 'Chyba');
+@define('ENTRY_SAVED', 'Záznam ulo¾en');
+@define('DELETE_SURE', 'Urèitì chcete vymazat #%s natrvalo?');
+@define('NOT_REALLY', 'Nechci...');
+@define('DUMP_IT', 'Vymazat!');
+@define('RIP_ENTRY', 'Zru¹en záznam #%s');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Kategorie #%s byla zru¹ena. Star¹í záznamy byly pøemístìny do #%s');
+@define('CATEGORY_DELETED', 'Kategorie #%s byla zru~Zena.');
+@define('INVALID_CATEGORY', '®ádná kategorie nebyla urèena k vymazání');
+@define('CATEGORY_SAVED', 'Kategorie ulo¾ena');
+@define('SELECT_TEMPLATE', 'Vyberte vzor pro vá¹ web');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'Záznamy nebyly vlo¾eny úspì¹nì!');
+@define('YES', 'Ano');
+@define('NO', 'Ne');
+@define('USE_DEFAULT', 'Default');
+@define('CHECK_N_SAVE', 'Provìøit a ulo¾it');
+@define('DIRECTORY_WRITE_ERROR', 'Nelze zapisovat do adresáøe %s - provìøte oprávnìní.');
+@define('DIRECTORY_CREATE_ERROR', 'Adresáø %s neexistuje a nemohl být vytvoøen. Vytvoøte adresáø manuálnì.');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; spustit <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', 'Nelze spustit binární soubor %s.');
+@define('FILE_WRITE_ERROR', 'Nelze zapisovat do souboru %s.');
+@define('FILE_CREATE_YOURSELF', 'Vytvoøte soubor pøímo nebo provìøte oprávnìní');
+@define('COPY_CODE_BELOW', '<br />* Zkopírujte kód uvedený ní¾e a umístìte jej do %s ve va¹em %s adresáøi:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Zmìòte www na u¾ivatele, který je urèen v Apache (na pø. nobody).');
+@define('BROWSER_RELOAD', 'Po dokonèení stisknìte tlaèítko obnovení stránky ve va¹em prohlí¾eèi.');
+@define('DIAGNOSTIC_ERROR', 'Diagnostika detekovala nìjaké chyby ve vkládaných informacích:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity je¹tì není nainstalován. <a href="%s">Instalujte</a> jej nyní.');
+@define('INCLUDE_ERROR', 'chyba serendipity: nelze vlo¾it %s - ukonèeno.');
+@define('DATABASE_ERROR', 'chyba serendipity: nelze se spojit s databází - ukonèeno.');
+@define('CREATE_DATABASE', 'Vytvoøení základní databáze...');
+@define('ATTEMPT_WRITE_FILE', 'Pokus ulo¾it soubor %s...');
+@define('WRITTEN_N_SAVED', 'Konfigurace byla zapsána a ulo¾ena');
+@define('IMAGE_ALIGNMENT', 'Úprava obrázku');
+@define('ENTER_NEW_NAME', 'Nový název: ');
+@define('RESIZING', 'Zmìna rozmìrù');
+@define('RESIZE_DONE', 'Hotovo (upraven rozmìr %s obrázkù).');
+@define('SYNCING', 'Synchronizace databáze s adresáøem obrázkù');
+@define('SYNC_DONE', 'Hotovo (synchronizováno %s obrázkù).');
+@define('DELETE_IMAGE_FAIL' , 'Nelze vymazat obrázek <b>%s</b>');
+@define('DELETE_THUMBNAIL', 'Vymazán náhled obrázku s názvem <b>%s</b>');
+@define('FILE_NOT_FOUND', 'Nelze nalézt soubor s názvem <b>%s</b>, mo¾ná je opravdu vymazán?');
+@define('ABORT_NOW', 'Zru¹it');
+@define('REMOTE_FILE_NOT_FOUND', 'Soubor nebyl na vzdáleném serveru nalezen, jste si jist ¾e URL: <b>%s</b> je správné?');
+@define('FILE_FETCHED', '%s nalezen');
+@define('FILE_UPLOADED', 'Soubor %s je úspì¹nì nahrán.');
+@define('WORD_OR', 'nebo');
+@define('SCALING_IMAGE', 'Zmìna %s na %s x %s px');
+@define('KEEP_PROPORTIONS', 'Zachovat proporce');
+@define('REALLY_SCALE_IMAGE', 'Opravdu zmìnit rozmìr? Nelze vrátit!');
+@define('TOGGLE_ALL', 'Otevøít v¹e');
+@define('TOGGLE_OPTION', 'Otevøít volbu');
+@define('SUBSCRIBE_TO_THIS_ENTRY', 'Pøihlásit se ke sledování komentáøù k záznamu');
+@define('UNSUBSCRIBE_OK', "%s je odhlá¹en ze sledování komentáøù");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'Nový komentáø k pøihlá¹enému záznamu "%s"');
+@define('SUBSCRIPTION_MAIL', "Pozor %s,\n\nA právì byl pøidán nový komentáø k záznamu, který sledujete na \"%s\", s názvem \"%s\"\nJméno odesílatele: %s\n\nZáznam najdete zde: %s\n\nMù¾ete se odhlásit zde: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "Pozor %s,\n\nA právì byla pøidána nová odezva k záznamu, který sledujete na \"%s\", s názvem \"%s\"\nJméno odesílatele: %s\n\nZáznam najdete zde: %s\n\nMù¾ete se odhlásit zde: %s\n");
+@define('SIGNATURE', "\n-- \n%s je vytvoøen pomocí Serendipity.\n Tento perfektní blogovací systém mù¾ete zdarma pou¾ívat také.\nNav¹tivte <http://s9y.org>, kde se dozvíte v¹e potøebné.");
+@define('SYNDICATION_PLUGIN_091', 'Kanál RSS 0.91');
+@define('SYNDICATION_PLUGIN_20', 'Kanál RSS 2.0');
+@define('SYNDICATION_PLUGIN_10', 'Kanál RSS 1.0');
+@define('SYNDICATION_PLUGIN_20c', 'Komentáøe RSS 2.0');
+@define('SYNDICATION_PLUGIN_ATOM03', 'Kanál ATOM 0.3');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', 'Kanál %s');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'Pole "hlavní redaktor"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  'Pole "webmaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'Obrázek kanálu RSS');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', '©íøka');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'Vý¹ka');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  'E-mailová adresa webmastera, je-li k dispozici. (prázdné: skryté) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', 'E-mailová adresa hlavního redaktora, je-li k dispozici. (prázdné: skryté) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'URL obrázku ve formátu GIF/JPEG/PNG, je-li k dispozici. (prázdné: logo serendipity)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'v pixelech, max. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'v pixelech, max. 400');
+@define('SYNDICATION_PLUGIN_TTL', 'Pole "ttl" (¾ivotnost)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'Èas v minutách, po kterém by vá¹ weblog nemìl být nadále ke¹ován v cizích serverech/aplikacích (prázdné: skryté) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'Pole "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', 'Pole "pubDate"je pro kanál RSS ukryto, chcete ukázat datum posledního záznamu?');
+@define('CONTENT', 'Obsah');
+@define('TYPE', 'Typ');
+@define('DRAFT', 'Koncept');
+@define('PUBLISH', 'Publikovat');
+@define('PREVIEW', 'Ukázat');
+@define('DATE', 'Datum');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', 'Upozornìní: Datum je specifikováno ¹patnì. Pou¾ijte formát YYYY-MM-DD HH:MM.');
+@define('CATEGORY_PLUGIN_DESC', 'Seznam kategorií.');
+@define('ALL_AUTHORS', 'V¹ichni autoøi');
+@define('CATEGORIES_TO_FETCH', 'Vyhledat kategorie');
+@define('CATEGORIES_TO_FETCH_DESC', 'Vyhledat kategorie podle autorù?');
+@define('PAGE_BROWSE_ENTRIES', 'Stránka %s z %s, celkem %s záznamù');
+@define('PREVIOUS_PAGE', 'pøedchozí stránka');
+@define('NEXT_PAGE', 'dal¹í stránka');
+@define('ALL_CATEGORIES', 'V¹echny kategorie');
+@define('DO_MARKUP', 'Umo¾nit pøevod znaèek');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'Formátování data');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'Formát aktuálního data záznamu, pou¾ívá PHP promìnnou strftime(). (Pøednastaveno: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'Nelze otevøít vzorový soubor, updatujte Serendipity!');
+@define('ADVANCED_OPTIONS', 'Roz¹íøené volby');
+@define('EDIT_ENTRY', 'Editovat záznam');
+@define('HTACCESS_ERROR', 'Provìøte instalaci va¹eho webserveru, Serendipity potøebuje ulo¾it soubor ".htaccess". To nebylo mo¾né kvùli chybì oprávnìní. Nastavte oprávnìní jako: <br />&nbsp;&nbsp;%s<br />a znovu ulo¾te tuto stránku.');
+@define('SIDEBAR_PLUGINS', 'Pluginy pro postranní sloupce');
+@define('EVENT_PLUGINS', 'Pluginy událostí');
+@define('SORT_ORDER', 'Poøadí');
+@define('SORT_ORDER_NAME', 'Název souboru');
+@define('SORT_ORDER_EXTENSION', 'Roz¹íøení');
+@define('SORT_ORDER_SIZE', 'Velikost');
+@define('SORT_ORDER_WIDTH', '©íøka obrázku');
+@define('SORT_ORDER_HEIGHT', 'Vý¹ka obrázku');
+@define('SORT_ORDER_DATE', 'Datum nahrání');
+@define('SORT_ORDER_ASC', 'Vzestupnì');
+@define('SORT_ORDER_DESC', 'Sestupnì');
+@define('THUMBNAIL_SHORT', 'Náhl.');
+@define('ORIGINAL_SHORT', 'Orig.');
+@define('APPLY_MARKUP_TO', 'Zapnout znaèkování %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'Zaèátek týdne');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity detekoval, ¾e va¹e konfigurace je ulo¾ena ve verzi %s, ale serendipity je instalován jako verze %s, je potøeba upgrade! <a href="%s">Kliknìte zde</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'Vítá vás mana¾er upgrade Serendipity.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', 'Pomohu vám s upgrade va¹í instalace Serendipity %s.');
+@define('SERENDIPITY_UPGRADER_WHY', 'Tato zpráva je zobrazena proto, ¾e va¹e instalace je Serendipity %s, ale je¹tì nebyla updatována databáze pro tuto verzi');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'Update databáze (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'Zde jsou .sql soubory, která musíte spustit pøed pokraèováním práce se Serendipity');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  'Úlohy specifické pro tuto verzi');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', '®ádné specifické úlohy');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', 'Mohu pokraèovat v tìchto úlohách?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'Ne, spustím je manuálnì');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'Ano, pokraèujte');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'Není tøeba ¾ádný upgrade');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', 'Serendipity je upgradován');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'Vynechal jste stupeò upgrade Serendipity, ujistìte se, ¾e databáze je správnì nainstalována a plánované funkce jsou spu¹tìny');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'Va¹e instalace Serendipity je upgradována na %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', 'Kliknutím %ssem%s se vrátíte do va¹eho weblogu');
+@define('MANAGE_USERS', 'Správa u¾ivatelù');
+@define('CREATE_NEW_USER', 'Vytvoøit nového u¾ivatele');
+@define('CREATE_NOT_AUTHORIZED', 'Nemù¾ete editovat u¾ivatele se stejnou úrovní jako je va¹e');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'Nemù¾ete vytvoøit u¾ivatele s vy¹¹í úrovní ne¾ je va¹e');
+@define('CREATED_USER', 'Nový u¾ivatel %s byl vytvoøen');
+@define('MODIFIED_USER', 'Nastavení u¾ivatele %s byla zmìnìna');
+@define('USER_LEVEL', 'Úroveò');
+@define('DELETE_USER', 'Chcete vymazat u¾ivatele #%d %s. Myslíte to vá¾nì? Tato akce znemo¾ní prohlí¾et jím vytvoøené záznamy na hlavní stránce.');
+@define('DELETED_USER', 'U¾ivatel #%d %s je vymazán.');
+@define('LIMIT_TO_NUMBER', 'Kolik záznamù by mìlo být zobrazeno?');
+@define('ENTRIES_PER_PAGE', 'záznamù na stránku');
+@define('DIRECTORIES_AVAILABLE', 'Po kliknutí na nìkterý adresáø v seznamu mù¾ete vytvoøit dal¹í podadresáø.');
+@define('ALL_DIRECTORIES', 'v¹echny adresáøe');
+@define('MANAGE_DIRECTORIES', 'Práce s adresáøi');
+@define('DIRECTORY_CREATED', 'Adresáø <strong>%s</strong> byl vytvoøen.');
+@define('PARENT_DIRECTORY', 'Základní adresáø');
+@define('CONFIRM_DELETE_DIRECTORY', 'Jste si jist, ¾e chcete odstranit v¹echen obsah adresáøe %s?');
+@define('ERROR_NO_DIRECTORY', 'Chyba: Adresáø %s neexistuje');
+@define('CHECKING_DIRECTORY', 'Kontrola souborù v adresáøi %s');
+@define('DELETING_FILE', 'Vymazání souboru %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', 'Nelze odstranit neprázdný adresáø. Zkuste zvolit "vynucené mazání", pokud potøebujete vymazat tyto soubory, a ode¹lete po¾adavek znovu. Existující soubory jsou:');
+@define('DIRECTORY_DELETE_FAILED', 'Vymazání adresáøe %s se nepodaøilo. Zkontrolujte oprávnìní nebo ètìte zprávu vý¹e.');
+@define('DIRECTORY_DELETE_SUCCESS', 'Adresáø %s byl úspì¹nì vymazán.');
+@define('SKIPPING_FILE_EXTENSION', 'Vynechán soubor: Chybìjící pøípona %s.');
+@define('SKIPPING_FILE_UNREADABLE', 'Vynechán soubor: %s nelze naèíst.');
+@define('FOUND_FILE', 'Zalo¾it nový/zmìnit soubor: %s.');
+@define('PERMISSIONS', 'Oprávnìní');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', 'Databáze');
+@define('INSTALL_CAT_DB_DESC', 'Sem vlo¾te v¹ech informace o databázi. Serendipity je potøebuje k funkci.');
+@define('INSTALL_DBTYPE', 'Typ');
+@define('INSTALL_DBTYPE_DESC', 'Typ databáze');
+@define('INSTALL_DBHOST', 'Hostitel');
+@define('INSTALL_DBHOST_DESC', 'Název hostitelského serveru');
+@define('INSTALL_DBUSER', 'U¾ivatel');
+@define('INSTALL_DBUSER_DESC', 'U¾ivatelské jméno');
+@define('INSTALL_DBPASS', 'Heslo');
+@define('INSTALL_DBPASS_DESC', 'U¾ivatelské heslo');
+@define('INSTALL_DBNAME', 'Název');
+@define('INSTALL_DBNAME_DESC', 'Název databáze');
+@define('INSTALL_DBPREFIX', 'Prefix');
+@define('INSTALL_DBPREFIX_DESC', 'Prefix pro záznamy v databázi, napø. serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', 'Cesty');
+@define('INSTALL_CAT_PATHS_DESC', 'Cesty k rùzným adresáøùm a souborùm. Nezapomeòte na ukonèovací lomítko pro adresáøe!');
+@define('INSTALL_FULLPATH', 'Úplná cesta');
+@define('INSTALL_FULLPATH_DESC', 'Úplná absolutní cesta k va¹í instalaci Serendipity.');
+@define('INSTALL_UPLOADPATH', 'Cesta pro uploady');
+@define('INSTALL_UPLOADPATH_DESC', 'Sem budou smìrovány uploady, relativnì k \'úplné cestì\' - typicky \'uploads/\'');
+@define('INSTALL_RELPATH', 'Relativní cesta');
+@define('INSTALL_RELPATH_DESC', 'Cesta k Serendipity pro vá¹ prohlí¾eè, typicky \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', 'Relativní cesta k template');
+@define('INSTALL_RELTEMPLPATH_DESC', 'Cesta k adresáøi, obsahujícímu vzory (templates) - relativní k \'relativní cestì\'');
+@define('INSTALL_RELUPLOADPATH', 'Relativní cesta k uploadùm');
+@define('INSTALL_RELUPLOADPATH_DESC', 'Cesta k uploadùm pro prohlí¾eèe - relativní k \'relativní cestì\'');
+@define('INSTALL_URL', 'URL weblogu');
+@define('INSTALL_URL_DESC', 'Základní URL va¹í instalace Serendipity');
+@define('INSTALL_INDEXFILE', 'Indexový soubor');
+@define('INSTALL_INDEXFILE_DESC', 'Název souboru pou¾itého jako index');
+
+/* Generel settings */
+@define('INSTALL_CAT_SETTINGS', 'Základní nastavení');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Úprava správy Serendipity');
+@define('INSTALL_USERNAME', 'Jméno admina');
+@define('INSTALL_USERNAME_DESC', 'Jméno pro pøihlá¹ení admina');
+@define('INSTALL_PASSWORD', 'Heslo admina');
+@define('INSTALL_PASSWORD_DESC', 'Heslo pro pøihlá¹ení admina');
+@define('INSTALL_EMAIL', 'E-mail admina');
+@define('INSTALL_EMAIL_DESC', 'E-mail pro pøihlá¹ení admina');
+@define('INSTALL_SENDMAIL', 'Posílat e-maily adminovi?');
+@define('INSTALL_SENDMAIL_DESC', 'Chcete dostávat e-mailem zprávy o komentáøích k va¹im záznamùm?');
+@define('INSTALL_SUBSCRIBE', 'Umo¾nit odbìr komentáøù?');
+@define('INSTALL_SUBSCRIBE_DESC', 'Umo¾nit u¾ivatelùm pøihlá¹ení k odbìru komentáøù k záznamùm');
+@define('INSTALL_BLOGNAME', 'Název');
+@define('INSTALL_BLOGNAME_DESC', 'Název va¹eho weblogu');
+@define('INSTALL_BLOGDESC', 'Popis');
+@define('INSTALL_BLOGDESC_DESC', 'Popis weblogu');
+@define('INSTALL_LANG', 'Jazyk');
+@define('INSTALL_LANG_DESC', 'Vyberte jazyk va¹eho weblogu');
+
+/* Appearance and options */
+@define('INSTALL_CAT_DISPLAY', 'Vzhled a volby');
+@define('INSTALL_CAT_DISPLAY_DESC', 'Úprava vzhledu a chování Serendipity');
+@define('INSTALL_WYSIWYG', 'Pou¾ívat WYSIWYG editor?');
+@define('INSTALL_WYSIWYG_DESC', 'Chcete pou¾ívat WYSIWYG editor? (Pracuje v IE5+, èásteènì v Mozille 1.3+)');
+@define('INSTALL_XHTML11', 'Vnutit kompatibilitu s XHTML 1.1?');
+@define('INSTALL_XHTML11_DESC', 'Chcete plnou kompatibilitu s XHTML 1.1? (mù¾e zpùsobit problémy ve star¹ích prohlí¾eèích)');
+@define('INSTALL_POPUP', 'Umo¾nit pou¾ití vyskakovacích oken');
+@define('INSTALL_POPUP_DESC', 'Chcete ve weblogu pou¾ívat vyskakovací okna pro komentáøe, odezvy a pod.?');
+@define('INSTALL_EMBED', 'Je Serendipity vlo¾ené?');
+@define('INSTALL_EMBED_DESC', 'Pokud chcete umístit weblog do va¹ich stránek, zvolte ano pro odstranìní v¹ech záhlaví, bude zobrazován jen obsah. Mù¾ete pou¾ít volitelný soubor indexFile pro obalení obsahu vlastními záhlavími a sloupci. Více informací najdete v souboru README!');
+@define('INSTALL_BLOCKREF', 'Blokovaní odbìratelé');
+@define('INSTALL_BLOCKREF_DESC', 'Chcete zamezit pøístup z urèitých adres? Seznam adres oddìlujte \';\' a pozor, adresy jsou blokovány vèetnì subadres!');
+@define('INSTALL_REWRITE', 'Pøepisování URL');
+@define('INSTALL_REWRITE_DESC', 'Urèení pravidel pro tvorbu URL. Zapnutí módu pøepisování zajistí správné URL va¹eho weblogu a lep¹í indexaci pro vyhledávaèe, jako je Google. Vá¹ webserver musí podporovat mod_rewrite nebo "AllowOverride All" v adresáøi pro Serendipity. Defaultní nastavení je automaticky detekováno.');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', 'Úpravy obrázkù');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'Vlo¾ení základních informací o zpùsobu zpracování obrázkù');
+@define('INSTALL_IMAGEMAGICK', 'Pou¾ívat Imagemagick?');
+@define('INSTALL_IMAGEMAGICK_DESC', 'Máte instalován Imagemagick?');
+@define('INSTALL_IMAGEMAGICKPATH', 'Cesta ke konverznímu souboru');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'Úplná cesta a název konverzního souboru Imagemagick');
+@define('INSTALL_THUMBSUFFIX', 'Sufix náhledù');
+@define('INSTALL_THUMBSUFFIX_DESC', 'Náhledy budou pojmenovány original.sufix.ext');
+@define('INSTALL_THUMBWIDTH', 'Rozmìry náhledù');
+@define('INSTALL_THUMBWIDTH_DESC', 'Pevná ¹íøka automaticky generovaných náhledù');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', 'Osobní nastavení');
+@define('USERCONF_CAT_PERSONAL_DESC', 'Nastavení va¹eho úètu');
+@define('USERCONF_USERNAME', 'Jméno');
+@define('USERCONF_USERNAME_DESC', 'Va¹e u¾ivatelské jméno (pøezdívka)');
+@define('USERCONF_PASSWORD', 'Heslo');
+@define('USERCONF_PASSWORD_DESC', 'Va¹e heslo');
+@define('USERCONF_EMAIL', 'E-mailová adresa');
+@define('USERCONF_EMAIL_DESC', 'Vá¹ e-mail');
+@define('USERCONF_SENDCOMMENTS', 'Posílat zprávy o komentáøích?');
+@define('USERCONF_SENDCOMMENTS_DESC', 'Chcete dostávat zprávy o komentáøích e-mailem?');
+@define('USERCONF_SENDTRACKBACKS', 'Posílat zprávy o odezvách?');
+@define('USERCONF_SENDTRACKBACKS_DESC', 'Chcete dostávat zprávy o odezvách na záznamy e-mailem?');
+@define('USERCONF_ALLOWPUBLISH', 'Právo publikovat záznamy?');
+@define('USERCONF_ALLOWPUBLISH_DESC', 'Umo¾nit u¾ivateli publikovat záznamy');
+
+@define('ALREADY_SUBCATEGORY', '%s je opravdu subkategorie pod %s.');
+@define('PARENT_CATEGORY', 'Nadøazená kategorie');
+@define('IN_REPLY_TO', 'Odpovìï na');
+@define('TOP_LEVEL', 'Nejvy¹¹í úroveò');
+@define('XML_IMAGE_TO_DISPLAY', 'Znak XML');
+@define('XML_IMAGE_TO_DISPLAY_DESC','Odkazy na XML kanály budou zobrazeny s tímto znakem. Nechejte prázdné pro pùvodní nastavení, nebo zadejte \'none\' pro vypnutí.');
+@define('SUCCESS', 'Úspìch');
+
+@define('POWERED_BY_SHOW_TEXT', 'Zobrazit "Serendipity" jako text');
+@define('POWERED_BY_SHOW_TEXT_DESC', 'Vytvoøeno v "Serendipity" se zobrazí jako text');
+@define('POWERED_BY_SHOW_IMAGE', 'Zobrazit "Serendipity" s logem');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Zobrazí se logo Serendipity');
+@define('INSTALL_TOP_AS_LINKS', 'Zobrazit Top výstupy/odbìratele jako linky?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"Ne": Výstupy a adresy odbìratelù budou zobrazeny jako èistý text pro zamezení spamu, "Ano": nebo jako hyperlinky. "Default": Pou¾ít globální nastavení (doporuèeno).');
+@define('SETTINGS_SAVED_AT', 'Nové nastavení bylo ulo¾eno v %s');
+@define('PLUGIN_ITEM_DISPLAY', 'Kde by mìla být tato polo¾ka zobrazena?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'V roz¹íøené èásti');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'V úvodu');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'V obou èástech');
+
+@define('RSS_IMPORT_CATEGORY', 'Pou¾ít tuto kategorii pro neurèené záznamy');
+@define('ERROR_UNKNOWN_NOUPLOAD', 'Neznámá chyba, soubor nebyl nahrán. Je mo¾né, ¾e délka souboru pøekraèuje maximum, povolené serverem. Spojte se s va¹ím ISP nebo editujte soubor php.ini a povolte vìt¹í velikost.');
+@define('COMMENTS_WILL_BE_MODERATED', 'Odeslané komentáøe budou pøed uveøejnìním moderovány.');
+@define('YOU_HAVE_THESE_OPTIONS', 'Máte k dispozici tyto volby:');
+@define('THIS_COMMENT_NEEDS_REVIEW', 'Pozor: Tento komentáø musí být pøed uveøejnìním odsouhlasen');
+@define('DELETE_COMMENT', 'Vymazat komentáø');
+@define('APPROVE_COMMENT', 'Odsouhlasit komentáø');
+@define('REQUIRES_REVIEW', 'Vy¾ádat pøezkoumání');
+@define('COMMENT_APPROVED', 'Komentáø #%s byl odsouhlasen');
+@define('COMMENT_DELETED', 'Komentáø #%s byl vymazán');
+@define('VIEW', 'Ukázat');
+@define('COMMENT_ALREADY_APPROVED', 'Komentáø #%s se jeví jako skuteènì odsouhlasený');
+@define('COMMENT_EDITED', 'Vybraný komentáø byl editován');
+@define('HIDE', 'Skrýt');
+@define('VIEW_EXTENDED_ENTRY', 'Pokraèovat ve ètení "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'Tento odkaz není mínìn jako klikatelný. Obsahuje zpìtné URI záznamu. Tento URI mù¾ete pou¾ít k odesílání pingù a sledování odezvy na tento záznam. Odkaz zkopírujete kliknutím pravou my¹í a volbou "Kopírovat odkaz" v Internet Exploreru nebo "Zkopírovat umístìní odkazu" v Mozille.');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'Pozor: Tato odezva musí být pøed uveøejnìním odsouhlasena');
+@define('DELETE_TRACKBACK', 'Vymazat odezvu');
+@define('APPROVE_TRACKBACK', 'Odsouhlasit odezvu');
+@define('TRACKBACK_APPROVED', 'Odezva #%s byla odsouhlasena');
+@define('TRACKBACK_DELETED', 'Odezva #%s byla vymazána');
+@define('COMMENTS_MODERATE', 'Komentáøe a odezvy k tomuto záznamu budou moderovány');
+@define('PLUGIN_SUPERUSER_HTTPS', 'Pou¾ít https pro pøihlá¹ení');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'Umo¾òuje pou¾ít spojení https pro pøihlá¹ení. Vá¹ server to musí podporovat!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'Udìlat externí odkazy klikatelné?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"Ne": Neoznaèené externí odkazy (Top výstupy, Top odbìratelé, U¾ivatelské komentáøe) nebudou ukázány/budou ukázány jako bì¾ný text v¹ude, kde je to mo¾né, pro omezení spamu (doporuèeno). "Ano": Neoznaèené externí odkazy budou ukázány jako hyperlinky. Toto mù¾e být pøepsáno v konfiguraci pluginù!');
+@define('PAGE_BROWSE_COMMENTS', 'Stránka %s ze %s, celkem %s komentáøù');
+@define('FILTERS', 'Filtry');
+@define('FIND_ENTRIES', 'Hledat záznamy');
+@define('FIND_COMMENTS', 'Hledat komentáøe');
+@define('FIND_MEDIA', 'Hledat média');
+@define('FILTER_DIRECTORY', 'Adresáø');
+@define('SORT_BY', 'Seøadit podle');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'Odezva nebyla odeslána: nepodaøilo se spojení s %s na portu %d');
+@define('MEDIA', 'Média (obrázky)');
+@define('MEDIA_LIBRARY', 'Knihovna médií');
+@define('ADD_MEDIA', 'Pøidat');
+@define('ENTER_MEDIA_URL', 'Vlo¾te URL pøidávaného souboru:');
+@define('ENTER_MEDIA_UPLOAD', 'Vyberte soubor pro nahrání:');
+@define('SAVE_FILE_AS', 'Ulo¾it soubor jako:');
+@define('STORE_IN_DIRECTORY', 'Ulo¾it do následujího adresáøe: ');
+@define('MEDIA_RENAME', 'Pøejmenovat soubor');
+@define('IMAGE_RESIZE', 'Zmìnit rozmìr obrázku');
+@define('MEDIA_DELETE', 'Vymazat soubor');
+@define('FILES_PER_PAGE', 'Souborù na stránku');
+@define('CLICK_FILE_TO_INSERT', 'Kliknìte na soubor, který chcete vlo¾it:');
+@define('SELECT_FILE', 'Vyberte soubor pro vlo¾ení:');
+@define('MEDIA_FULLSIZE', 'Plný rozmìr');
+@define('CALENDAR_BOW_DESC', 'Den, urèený jako zaèátek týdne. Default je pondìlí');
+@define('ALLOWS_YOU_BLAHBLAH', 'Vlo¾it odkaz do postranního bloku administrace weblogu');
+@define('CALENDAR', 'Kalendáø');
+@define('SUPERUSER_OPEN_ADMIN', 'Administrace');
+@define('SUPERUSER_OPEN_LOGIN', 'Pøihlá¹ení');
+@define('INVERT_SELECTIONS', 'Obrátit výbìr');
+@define('COMMENTS_DELETE_CONFIRM', 'Jste se jist vymazáním vybraných komentáøù?');
+@define('COMMENT_DELETE_CONFIRM', 'Jste si jist vymazáním komentáøe #%d, zapsaného %s?');
+@define('DELETE_SELECTED_COMMENTS', 'Vymazat vybrané komentáøe');
+@define('VIEW_COMMENT', 'Ukázat komentáø');
+@define('VIEW_ENTRY', 'Ukázat záznam');
+@define('DELETE_FILE', 'Vymazat soubor s názvem <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', 'Chcete vymazat <b>%s</b><br />Jestli¾e pou¾íváte tento soubor v nìjakých záznamech, zpùsobí to nepøístupnost odkazù nebo obrázkù.<br />Chcete pøesto pokraèovat?<br /><br />');
+@define('TRACKBACK_SENDING', 'Odeslání odezvy na URI %s...');
+@define('TRACKBACK_SENT', 'Odezva úspì¹ná');
+@define('TRACKBACK_FAILED', 'Odezva neúspì¹ná: %s');
+@define('TRACKBACK_NOT_FOUND', 'URI odezvy neexistuje.');
+@define('TRACKBACK_URI_MISMATCH', 'Automaticky získané URI neodpovídá va¹emu cílovému.');
+@define('TRACKBACK_CHECKING', 'Testvání <u>%s</u> pro mo¾né odezvy...');
+@define('TRACKBACK_NO_DATA', 'Cíl neobsahuje data');
+@define('TRACKBACK_SIZE', 'Cílové URI pøekroèilo max. velikost souboru %s bytù.');
+@define('VIEWMODE_THREADED', 'Pøepnout na vláknové zobrazení');
+@define('COMMENTS_VIEWMODE_THREADED', 'Vláknové');
+@define('COMMENTS_VIEWMODE_LINEAR', 'Lineární');
+@define('DISPLAY_COMMENTS_AS', 'Zobrazit komentáøe jako');
+@define('ADD_MEDIA_BLAHBLAH', '<b>Pøidat soubor do schránky médií:</b><p>Zde mù¾ete ukládat mediální soubory, nebo urèit, kde je získat z WEBu! Pokud nemáte odpovídající obrázek, <a href="http://images.google.com" target="_blank">hledejte na Google</a> odpovìï na va¹i potøebu, obvykle se zadaøí :).<p><b>Vyberte metodu:</b><br>');
+@define('COMMENTS_FILTER_SHOW', 'Zobrazit');
+@define('COMMENTS_FILTER_ALL', 'V¹e');
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'Pouze povolené');
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'Èekající na povolení');
+@define('RSS_IMPORT_BODYONLY', 'Ulo¾it celý importovaný text do "hlavní" èásti, nerozdìlovat do "roz¹íøené" èásti.');
+@define('SYNDICATION_PLUGIN_FULLFEED', 'Zobrazit celé èlánky vèetnì roz¹íøené èásti v RSS kanálu');
+@define('MT_DATA_FILE', 'Soubory Movable Type');
+@define('FORCE', 'Vnutit');
+@define('CREATE_AUTHOR', 'Vytvoøit autora \'%s\'.');
+@define('CREATE_CATEGORY', 'Vytvoøit kategorii \'%s\'.');
+@define('MYSQL_REQUIRED', 'Pro provedení této akce je nutné mít databázi MySQL.');
+@define('COULDNT_CONNECT', 'Nebylo mo¾né se spojit s databází MySQL: %s.');
+@define('COULDNT_SELECT_DB', 'Nebylo mo¾né vybrat databázi: %s.');
+@define('COULDNT_SELECT_USER_INFO', 'Nebylo mo¾né vybrat u¾ivatelské informace: %s.');
+@define('COULDNT_SELECT_CATEGORY_INFO', 'Nebylo mo¾né vybrat informace o kategorii: %s.');
+@define('COULDNT_SELECT_ENTRY_INFO', 'Nebylo mo¾né vybrat informace o záznamu: %s.');
+@define('COULDNT_SELECT_COMMENT_INFO', 'Nebylo mo¾né vybrat informace o komentáøi: %s.');
+@define('WEEK', 'Týden');
+@define('WEEKS', 'Týdny');
+@define('MONTHS', 'Mìsíce');
+@define('DAYS', 'Dny');
+@define('ARCHIVE_FREQUENCY', 'Kalendáøní krok');
+@define('ARCHIVE_FREQUENCY_DESC', 'Kalendáøní krok mezi prvky seznamu');
+@define('ARCHIVE_COUNT', 'Poèet prvkù v seznamu');
+@define('ARCHIVE_COUNT_DESC', 'Celkový poèet zobrazených mìsícù, týdnù nebo dnù');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'Ní¾e je seznam instalovaných pluginù');
+@define('SIDEBAR_PLUGIN', 'postranní plugin');
+@define('EVENT_PLUGIN', 'plugin události');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'Kliknìte a instalujte nový %s');
+@define('VERSION', 'verze');
+@define('INSTALL', 'Instalovat');
+@define('ALREADY_INSTALLED', 'Instalován');
+@define('SELECT_A_PLUGIN_TO_ADD', 'Vyberte plugin, který chcete instalovat');
+@define('INSTALL_OFFSET', 'Èasový posun serveru');
+@define('STICKY_POSTINGS', 'Pøilepené záznamy');
+@define('INSTALL_FETCHLIMIT', 'Záznamy zobrazené na hlavní stránce');
+@define('INSTALL_FETCHLIMIT_DESC', 'Poèet záznamù, zobrazených na hlavní stránce');
+@define('IMPORT_ENTRIES', 'Import dat');
+@define('EXPORT_ENTRIES', 'Export záznamù');
+@define('IMPORT_WELCOME', 'Vítejte v utilitì pro import dat');
+@define('IMPORT_WHAT_CAN', 'Zde mù¾ete importovat záznamy z jiných weblogù');
+@define('IMPORT_SELECT', 'Vyberte software, ze kterého chcete importovat');
+@define('IMPORT_PLEASE_ENTER', 'Vlo¾te data po¾adovaná ní¾e');
+@define('IMPORT_NOW', 'Importovat!');
+@define('IMPORT_STARTING', 'Start importu...');
+@define('IMPORT_FAILED', 'Import se nezdaøil');
+@define('IMPORT_DONE', 'Import úspì¹nì dokonèen');
+@define('IMPORT_WEBLOG_APP', 'Weblogová aplikace');
+@define('EXPORT_FEED', 'Exportovat plný RSS kanál');
+@define('STATUS', 'Stav po importu');
+@define('IMPORT_GENERIC_RSS', 'Základní RSS import');
+@define('ACTIVATE_AUTODISCOVERY', 'Odeslat odezvy na odkazy obsa¾ené v záznamu');
+@define('WELCOME_TO_ADMIN', 'Vítejte v Administraèní sekci Serendipity .');
+@define('PLEASE_ENTER_CREDENTIALS', 'Vlo¾te oprávnìní.');
+@define('ADMIN_FOOTER_POWERED_BY', 'Vytvoøeno pomocí Serendipity %s a PHP %s');
+@define('INSTALL_USEGZIP', 'Pou¾ijte kompresi gzip');
+@define('INSTALL_USEGZIP_DESC', 'Doporuèujeme pou¾ít kompresi stránek pro jejich urychlené naèítání');
+@define('INSTALL_SHOWFUTURE', 'Zobrazit budoucí záznamy');
+@define('INSTALL_SHOWFUTURE_DESC', 'Tato volba umo¾ní zobrazení budoucích záznamù blogu. Defaultnì jsou skryté a budou zobrazeny a¾ v èase jejich vydání.');
+@define('INSTALL_DBPERSISTENT', 'Pou¾ít trvalé pøipojení');
+@define('INSTALL_DBPERSISTENT_DESC', 'Umo¾nit trvalé pøipojení k databázi, více <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">zde</a>. Bì¾nì to není doporuèeno');
+@define('NO_IMAGES_FOUND', '®ádné obrázky');
+@define('PERSONAL_SETTINGS', 'Osobní nastavení');
+@define('REFERER', 'Odbìratel');
+@define('NOT_FOUND', 'Není obsa¾en');
+@define('NOT_WRITABLE', 'Nezapisovatelný');
+@define('WRITABLE', 'Zapisovatelný');
+@define('PROBLEM_DIAGNOSTIC', 'Byly diagnostikovány problémy, tak¾e nelze pokraèovat v instalaci, dokud nebudou odstranìny');
+@define('SELECT_INSTALLATION_TYPE', 'Vyberte typ instalace');
+@define('WELCOME_TO_INSTALLATION', 'Vítejte v instalaci Serendipity');
+@define('FIRST_WE_TAKE_A_LOOK', 'Nejdøíve se podíváme na va¹e základní nastavení a zkusíme diagnostikovat pøípadné problémy');
+@define('ERRORS_ARE_DISPLAYED_IN', 'Chyby budou zobrazeny %s, doporuèení %s a úspìch %s');
+@define('RED', 'èervenì');
+@define('YELLOW', '¾lutì');
+@define('GREEN', 'zelenì');
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s - pøedinstalaèní zpráva');
+@define('RECOMMENDED', 'Doporuèeno');
+@define('ACTUAL', 'Aktuální');
+@define('PHPINI_CONFIGURATION', 'konfigurace php.ini');
+@define('PHP_INSTALLATION', 'Instalace PHP');
+@define('THEY_DO', 'they do');
+@define('THEY_DONT', 'they don\'t');
+@define('SIMPLE_INSTALLATION', 'Jednoduchá instalace');
+@define('EXPERT_INSTALLATION', 'Expertní instalace');
+@define('COMPLETE_INSTALLATION', 'Kompletní instalace');
+@define('WONT_INSTALL_DB_AGAIN', 'nechci znovu instalovat databázi');
+@define('CHECK_DATABASE_EXISTS', 'Kontrola, jestli databáze a tabulky opravdu existují');
+@define('CREATING_PRIMARY_AUTHOR', 'Vytvoøení hlavního autora \'%s\'');
+@define('SETTING_DEFAULT_TEMPLATE', 'Nastavení defaultního vzoru');
+@define('INSTALLING_DEFAULT_PLUGINS', 'Instalace defaultních pluginù');
+@define('SERENDIPITY_INSTALLED', 'Serendipity byl úspì¹nì nainstalován');
+@define('VISIT_BLOG_HERE', 'Zde se pøepnete do svého nového weblogu');
+@define('THANK_YOU_FOR_CHOOSING', 'Dìkujeme za volbu Serendipity');
+@define('ERROR_DETECTED_IN_INSTALL', 'Pøi instalaci byla detekována chyba');
+@define('OPERATING_SYSTEM', 'Operaèní systém');
+@define('WEBSERVER_SAPI', 'Webserver SAPI');
+@define('IMAGE_ROTATE_LEFT', 'Otoèit o 90 stupòù doleva');
+@define('IMAGE_ROTATE_RIGHT', 'Otoèit o 90 stupòù doprava');
+@define('TEMPLATE_SET', '\'%s\' byl nastaven jako defaultní vzor (template)');
+@define('SEARCH_ERROR', 'Funkce vyhledávání nepracovala podle oèekávání. Poznámka pro administrátora blogu: Mohlo to být zpùsobeno nepøítomností pøíslu¹ných indexù v databázi. U¾ivatelský úèet v databázi MySQL musí být oprávnìn vykonat tento dotaz: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> Specifická chyba vrácená databází byla: <pre>%s</pre>');
+@define('EDIT_THIS_CAT', 'Editace "%s"');
+@define('CATEGORY_REMAINING', 'Vymazat kategorii a pøemístit záznamy do kategorie');
+@define('CATEGORY_INDEX', 'Ní¾e je seznam kategorií, které mù¾et pou¾ít k va¹emu záznamu');
+@define('NO_CATEGORIES', '®ádné kategorie');
+@define('RESET_DATE', 'Resetovat datum');
+@define('RESET_DATE_DESC', 'Kliknìte a resetujte datum na aktuální');
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Oprávnìní mù¾e být nastaveno s pou¾itím povelu: `<em>%s</em>` v adresáøi, nebo nastavením pomocí FTP programu');
+@define('WARNING_TEMPLATE_DEPRECATED', 'Varování: Vá¹ vzor pou¾ívá nepovolenou metodu, je-li to mo¾né, proveïte aktualizaci');
+@define('ENTRY_PUBLISHED_FUTURE', 'Tento záznam je¹tì není publikován.');
+@define('ENTRIES_BY', 'Záznamy od %s');
+@define('PREVIOUS', 'Pøedchozí');
+@define('NEXT', 'Dal¹í');
+@define('APPROVE', 'Povolit');
+@define('DO_MARKUP_DESCRIPTION', 'Pøevést znaèky na text (smajlíky, zkratky *, /, _, ...). Vypnutí této volby zajistí ulo¾ení HTML kódù v textu.');
+@define('CATEGORY_ALREADY_EXIST', 'Kategorie nazvaná "%s" skuteènì existuje'); 
+@define('IMPORT_NOTES', 'Poznámka:'); 
+@define('ERROR_FILE_FORBIDDEN', 'Nejste oprávnìn nahrávat soubory s aktivním obsahem'); 
+@define('ADMIN', 'Administrace'); 
+@define('ADMIN_FRONTPAGE', 'Hlavní stránka'); 
+@define('QUOTE', 'Citace'); 
+@define('IFRAME_SAVE', 'Serendipity ukládá vá¹ záznam, vytváøí odezvy a zaji¹»uje mo¾ná XML-RPC spojení. Mù¾e to chvíli trvat...'); 
+@define('IFRAME_SAVE_DRAFT', 'Koncept tohoto záznamu byl ulo¾en'); 
+@define('IFRAME_PREVIEW', 'Serendipity nyní vytváøí náhled va¹eho záznamu...'); 
+@define('IFRAME_WARNING', 'Vá¹ prohlí¾eè nepodporuje iframe. Otevøete soubor serendipity_config.inc.php a nastavte promìnnou $serendipity[\'use_iframe\'] na FALSE.'); 
+@define('NONE', 'nic');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Základní nastavení pro nové záznamy'); 
+@define('UPGRADE', 'Aktualizace'); 
+@define('UPGRADE_TO_VERSION', 'Aktualizace na verzi %s'); 
+@define('DELETE_DIRECTORY', 'Vymazat adresáø'); 
+@define('DELETE_DIRECTORY_DESC', 'Chcete vymazat obsah adresáøe, obsahující mediální soubory, které mohou být pou¾ívány ve va¹ich záznamech.'); 
+@define('FORCE_DELETE', 'Vymazat V©ECHNY soubory v adresáøi, vèetnì tìch, které nejsou vytvoøeny pomocí Serendipity'); 
+@define('CREATE_DIRECTORY', 'Vytvoøit adresáø'); 
+@define('CREATE_NEW_DIRECTORY', 'Vytvoøit nový adresáø'); 
+@define('CREATE_DIRECTORY_DESC', 'Zde mù¾ete vytvoøit adresáø pro ukládání mediálních souborù. Zvolte název adresáøe a pøípadný nadøízený adresáø.'); 
+@define('BASE_DIRECTORY', 'Základní adresáø'); 
+@define('USERLEVEL_EDITOR_DESC', 'Autor'); 
+@define('USERLEVEL_CHIEF_DESC', 'Redaktor'); 
+@define('USERLEVEL_ADMIN_DESC', 'Administrátor'); 
+@define('USERCONF_USERLEVEL', 'Úroveò'); 
+@define('USERCONF_USERLEVEL_DESC', 'Tato úroveò urèuje práva u¾ivatele weblogu.'); 
+@define('USER_SELF_INFO', 'Pøihlá¹en jako %s (%s)'); 
+@define('ADMIN_ENTRIES', 'Záznamy'); 
+@define('RECHECK_INSTALLATION', 'Pøekontrolovat instalaci'); 
+@define('IMAGICK_EXEC_ERROR', 'Nelze spustit: "%s", chyba: %s, vrací promìnnou: %d'); 
+@define('INSTALL_OFFSET_DESC', 'Vlo¾te poèet hodin mezi èasem serveru (aktuálnì: %clock%) a va¹í èasovou zónou'); 
+@define('UNMET_REQUIREMENTS', 'Nesplnìné po¾adavky: %s'); 
+@define('CHARSET', 'Znaková sada');
+@define('AUTOLANG', 'Pou¾ít jazyk prohlí¾eèe jako defaultní');
+@define('AUTOLANG_DESC', 'Zapnutím této volby urèíte, ¾e jazyk prohlí¾eèe bude pøevzat jako základní pro u¾ivatelské rozhraní a pro záznamy.');
+@define('INSTALL_AUTODETECT_URL', 'Autodetekce pou¾ité HTTP hostitelské adresy'); 
+@define('INSTALL_AUTODETECT_URL_DESC', 'Pøi volbì "Ano" bude Serendipity pøedpokládat, ¾e HTTP adresa hostitele, pou¾itá náv¹tìvníkem, je va¹e základní nastavení URL. Zapnutí umo¾ní pou¾ívání rùzných domén k pøístupu na va¹e stránky, a pou¾ití této jedné domény pro v¹echny odkazy ke sledování zmìn na stránkách.'); 
+@define('CONVERT_HTMLENTITIES', 'Zkusit automatickou konverzi HTML entit?');
+@define('EMPTY_SETTING', 'Nespecifikoval jste platnou hodnotu pro "%s"!');
+@define('USERCONF_REALNAME', 'Skuteèné jméno'); 
+@define('USERCONF_REALNAME_DESC', 'Plné jméno autora. Toto jméno uvidí ètenáøi'); 
+@define('HOTLINK_DONE', 'Soubor pøipojen odkazem.<br />Hotovo.'); 
+@define('ENTER_MEDIA_URL_METHOD', 'Zpùsob pøipojení:'); 
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Poznámka: Pokud zvolíte odkaz na server, ujistìte se, ¾e máte potøebná práva, nebo ¾e jde o vá¹ web. Odkazy vám umo¾ní vyu¾ívat obrázky z jiných ne¾ místních zdrojù.'); 
+@define('MEDIA_HOTLINKED', 'odkazován'); 
+@define('FETCH_METHOD_IMAGE', 'Nahrání na server'); 
+@define('FETCH_METHOD_HOTLINK', 'Odkaz na server'); 
+@define('DELETE_HOTLINK_FILE', 'Vymazán odkazovaný soubor <b>%s</b>'); 
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Show E-Mail addresses?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_da.inc.php b/lang/serendipity_lang_da.inc.php
new file mode 100644 (file)
index 0000000..3288b96
--- /dev/null
@@ -0,0 +1,671 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Translation (c) by Tom Sommer, <ts@dreamcoder.dk>
+# Thanks to: Jeppe Lund, <nocture@nocture.dk>
+#            Robert Piil, <robert@piil.org>
+
+
+@define('LANG_CHARSET', 'ISO-8859-1');
+@define('DATE_LOCALES', 'danish, da, da_DK, da_DK.ISO8859-1');
+@define('DATE_FORMAT_ENTRY', '%A d. %e. %B %Y');
+@define('DATE_FORMAT_SHORT', '%d.%m.%Y %H:%M');
+@define('WYSIWYG_LANG', 'da');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Serendipity Administrationssuite');
+@define('HAVE_TO_BE_LOGGED_ON', 'Du skal være logget ind for at kunne se denne side');
+@define('WRONG_USERNAME_OR_PASSWORD', 'Du har indtastet et forkert brugernavn eller adgangskode');
+@define('APPEARANCE', 'Udseende');
+@define('MANAGE_STYLES', 'Administrer temaer');
+@define('CONFIGURE_PLUGINS', 'Konfigurerer plugins');
+@define('CONFIGURATION', 'Konfiguration');
+@define('BACK_TO_BLOG', 'Tilbage til weblog');
+@define('LOGIN', 'Login');
+@define('LOGOUT', 'Log ud');
+@define('LOGGEDOUT', 'Logget ud.');
+@define('CREATE', 'Opret');
+@define('SAVE', 'Gem');
+@define('NAME', 'Navn');
+@define('CREATE_NEW_CAT', 'Opret ny kategori');
+@define('I_WANT_THUMB', 'Jeg vil bruge minibilledet i min artikel.');
+@define('I_WANT_BIG_IMAGE', 'Jeg vil bruge det originale billede i min artikel.');
+@define('I_WANT_NO_LINK', 'Vis billedet uden link');
+@define('I_WANT_IT_TO_LINK', 'Vis billedet med link');
+@define('BACK', 'Tilbage');
+@define('FORWARD', 'Fremad');
+@define('ANONYMOUS', 'Annonym');
+@define('NEW_TRACKBACK_TO', 'Ny trackback lavet til');
+@define('NEW_COMMENT_TO', 'Ny kommentar lavet til');
+@define('RECENT', 'Nyere...');
+@define('OLDER', 'Ældre...');
+@define('DONE', 'Færdig');
+@define('WELCOME_BACK', 'Velkommen tilbage,');
+@define('TITLE', 'Titel');
+@define('DESCRIPTION', 'Beskrivelse');
+@define('PLACEMENT', 'Placering');
+@define('DELETE', 'Slet');
+@define('UP', 'OP');
+@define('DOWN', 'NED');
+@define('ENTRIES', 'artikler');
+@define('NEW_ENTRY', 'Ny artikel');
+@define('EDIT_ENTRIES', 'Rediger artikler');
+@define('CATEGORIES', 'Kategorier');
+@define('WARNING_THIS_BLAHBLAH', "ADVARSEL:\\nDette kan tage lang tid hvis der er mange billeder uden minibilleder.");
+@define('CREATE_THUMBS', 'Genopbyg minibilleder');
+@define('MANAGE_IMAGES', 'Administrer billeder');
+@define('NAME', 'Navn');
+@define('EMAIL', 'Email');
+@define('HOMEPAGE', 'Hjemmeside');
+@define('COMMENT', 'Kommentar');
+@define('REMEMBER_INFO', 'Husk oplysninger?');
+@define('SUBMIT_COMMENT', 'Tilføj kommentar');
+@define('NO_ENTRIES_TO_PRINT', 'Der er ingen artikler at vise');
+@define('COMMENTS', 'Kommentarer');
+@define('ADD_COMMENT', 'Tilføj kommentar');
+@define('NO_COMMENTS', 'Ingen kommentarer');
+@define('POSTED_BY', 'Skrevet af');
+@define('ON', 'aktiv');
+@define('A_NEW_COMMENT_BLAHBLAH', 'En ny kommentar er blevet oprettet på din blog "%s", til artiklen ved navn "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'Et nyt trackback er blevet lavet til din artikel ved navn "%s".');
+@define('NO_CATEGORY', 'Ingen kategori');
+@define('ENTRY_BODY', 'Artikel indhold');
+@define('EXTENDED_BODY', 'Udvidet indhold');
+@define('CATEGORY', 'Kategori');
+@define('EDIT', 'Rediger');
+@define('NO_ENTRIES_BLAHBLAH', 'Ingen artikler blev fundet som indeholdt %s' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'Din søgning på %s retunerede %s resultater:');
+@define('SEARCH_TOO_SHORT', 'Din søgning skal være på mere end 3 tegn');
+@define('IMAGE', 'Billede');
+@define('ERROR_FILE_NOT_EXISTS', 'Fejl: Det gamle filnavn findes ikke!');
+@define('ERROR_FILE_EXISTS', 'Fejl: Det nye filnavn bruges allerede, vælg et andet!');
+@define('ERROR_SOMETHING', 'Fejl: Der gik noget galt');
+@define('ADDING_IMAGE', 'Tilføjet billede...');
+@define('THUMB_CREATED_DONE', 'Minibillede er oprettet.<br>Done.');
+@define('ERROR_FILE_EXISTS_ALREADY', 'Fejl: Filen findes allerede på din maskine!');
+@define('GO', 'Begynd!');
+@define('NEWSIZE', 'Ny størrelse: ');
+@define('RESIZE_BLAHBLAH', '<b>Ændre størrelse på %s</b><p>');
+@define('ORIGINAL_SIZE', 'Original størrelse: <i>%sx%s</i> pixel');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>Her kan du justere billedets størrelse. Hvis du vil bevare proportionerne, skal du bare indtaste én af værdirene og trykke på TAB-tasten, jeg vil dernæst automatisk beregne den anden værdi:');
+@define('QUICKJUMP_CALENDAR', 'Hurtigkalender');
+@define('QUICKSEARCH', 'Søgning');
+@define('SEARCH_FOR_ENTRY', 'Søg efter en artikel');
+@define('ARCHIVES', 'Arkiver');
+@define('BROWSE_ARCHIVES', 'Gennemse arkiver efter måneder');
+@define('TOP_REFERRER', 'Referencer');
+@define('SHOWS_TOP_SITES', 'Viser de sites som oftest linker til din blog');
+@define('TOP_EXITS', 'Udgangssider');
+@define('SHOWS_TOP_EXIT', 'Viser de udgangssider der er klikket flest gange på');
+@define('SYNDICATION', 'Syndikering');
+@define('SHOWS_RSS_BLAHBLAH', 'Viser RSS syndikeringslinks');
+@define('ADVERTISES_BLAHBLAH', 'Reklamer for din blogs oprindelse');
+@define('HTML_NUGGET', 'HTML Nugget');
+@define('HOLDS_A_BLAHBLAH', 'Indeholder et stykke HTML i din sidebar');
+@define('TITLE_FOR_NUGGET', 'Titel på din nugget');
+@define('THE_NUGGET', 'HTML-indholdet af din nugget');
+@define('SYNDICATE_THIS_BLOG', 'Syndiker denne blog');
+@define('YOU_CHOSE', 'Du valgte %s');
+@define('IMAGE_SIZE', 'Billedestørrelse');
+@define('IMAGE_AS_A_LINK', 'Billedeindsættelse');
+@define('POWERED_BY', 'Drives af');
+@define('TRACKBACKS', 'Trackbacks');
+@define('TRACKBACK', 'Trackback');
+@define('NO_TRACKBACKS', 'Ingen Trackbacks');
+@define('TOPICS_OF', 'Emner af');
+@define('VIEW_FULL', 'Vis i fuld');
+@define('VIEW_TOPICS', 'Vis emner');
+@define('AT', 'kl');
+@define('SET_AS_TEMPLATE', 'Sæt som skabelon');
+@define('IN', 'i');
+@define('EXCERPT', 'Uddrag');
+@define('TRACKED', 'Tracked');
+@define('LINK_TO_ENTRY', 'Link til artikel');
+@define('LINK_TO_REMOTE_ENTRY', 'Link til ekstern artikel');
+@define('IP_ADDRESS', 'IP-adresse');
+@define('USER', 'Bruger');
+@define('THUMBNAIL_USING_OWN', 'Bruger %s som dets eget minibillede, fordi det allerede er så lille.');
+@define('THUMBNAIL_FAILED_COPY', 'Ville gerne have brugt %s som dets egen minibillede, men kunne ikke kopiere!');
+@define('AUTHOR', 'Forfatter');
+@define('LAST_UPDATED', 'Sidst opdateret');
+@define('TRACKBACK_SPECIFIC', 'Trackback URI til denne artikel');
+@define('DIRECT_LINK', 'Direkte link til denne artikel');
+@define('COMMENT_ADDED', 'Din kommentar blev tilføjet. ');
+@define('COMMENT_ADDED_CLICK', 'Klik %her for at gå tilbage%s til kommentarerne, og %sher for at lukke%s dette vindue.');
+@define('COMMENT_NOT_ADDED', 'Din kommentar kunne ikke tilføjes fordi kommentarer til denne artikel er blevet deaktiveret.');
+@define('COMMENT_NOT_ADDED_CLICK', 'Klik %sher for at gå tilbage%s til kommentarene, og %sher for at lukke%s dette vindue. ');
+@define('COMMENTS_DISABLE', 'Tillad ikke kommentarer til denne artikel');
+@define('COMMENTS_ENABLE', 'Tillad kommentarer til denne artikel');
+@define('COMMENTS_CLOSED', 'Forfatteren har valgt ikke at tillade kommentarer til denne artikel');
+@define('EMPTY_COMMENT', 'Din kommentar indeholdt ikke noget, gå venligst %stilbage%s og prøv igen');
+@define('ENTRIES_FOR', 'Artikler fra %s');
+@define('DOCUMENT_NOT_FOUND', 'Dokumentet %s kunne ikke findes.');
+@define('USERNAME', 'Brugernavn');
+@define('PASSWORD', 'Adgangskode');
+@define('AUTOMATIC_LOGIN', 'Gem oplysningerne');
+@define('SERENDIPITY_INSTALLATION', 'Serendipity Installation');
+@define('LEFT', 'venstre');
+@define('RIGHT', 'højre');
+@define('HIDDEN', 'skjult');
+@define('REMOVE_TICKED_PLUGINS', 'Fjern valgte plugins');
+@define('SAVE_CHANGES_TO_LAYOUT', 'Gem layout-ændringerne');
+@define('COMMENTS_FROM', 'Kommentar fra');
+@define('ERROR', 'Fejl');
+@define('ENTRY_SAVED', 'Din artikel blev gemt');
+@define('DELETE_SURE', 'Er du sikker på du vil slette #%s permanent?');
+@define('NOT_REALLY', 'Egentlig ikke...');
+@define('DUMP_IT', 'Smid den ud!');
+@define('RIP_ENTRY', 'Farvel artikel #%s');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Kategori #%s blev slettet. Gamle artikler flyttet til kategori #%s');
+@define('CATEGORY_DELETED', 'Kategori #%s blev slettet.');
+@define('INVALID_CATEGORY', 'Ingen kategori blev valgt til sletning');
+@define('CATEGORY_SAVED', 'Kategori gemt');
+@define('SELECT_TEMPLATE', 'Vælg den skabelon du ønsker at bruge til din blog');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'Der var problemer under indsættelsen af artiklerne!');
+@define('YES', 'Ja');
+@define('NO', 'Nej');
+@define('USE_DEFAULT', 'Default');
+@define('CHECK_N_SAVE', 'Check &amp; gem');
+@define('DIRECTORY_WRITE_ERROR', 'Kan ikke skrive til biblioteket %s. Check filrettighederne.');
+@define('DIRECTORY_CREATE_ERROR', 'Biblioteket %s eksisterer ikke og kunne ikke oprettes. Opret venligst biblioteket manuelt');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; Kør <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', 'Kan ikke eksekvere %s');
+@define('FILE_WRITE_ERROR', 'Kan ikke skrive til filen %s.');
+@define('FILE_CREATE_YOURSELF', 'Opret venligst filen selv og check dens rettigheder');
+@define('COPY_CODE_BELOW', '<br />* Kopier blot koden nedenunder og placer den i %s i din %s mappe:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Ændr www til den bruger som apache kører som (fx. nobody).');
+@define('BROWSER_RELOAD', 'Når du har gjort dette, så tryk på browserens "opdater" knap');
+@define('DIAGNOSTIC_ERROR', 'Vi har opdaget nogle fejl mens vi kørte nogle diagnostiker på dine indtastede informationer:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity er endnu ikke installeret. Klik <a href="%s">her for at installere</a> nu.');
+@define('INCLUDE_ERROR', 'serendipityfejl: Kunne ikke inkludere %s - Afbryder.');
+@define('DATABASE_ERROR', 'serendipityfejl: Kunne ikke oprette forbindelse til databasen - Afbryder.');
+@define('CREATE_DATABASE', 'Opretter standarddatabase setup...');
+@define('ATTEMPT_WRITE_FILE', 'Forsøger at skrive til %s ...');
+@define('WRITTEN_N_SAVED', 'Konfiguration skrevet &amp; gemt');
+@define('IMAGE_ALIGNMENT', 'Billedejustering');
+@define('ENTER_NEW_NAME', 'Indtast det nye navn for: ');
+@define('RESIZING', 'Ændre dimensioner');
+@define('RESIZE_DONE', 'Færdig (Ændrede %s billeder).');
+@define('SYNCING', 'Synkronisere databasen med billedemappen');
+@define('SYNC_DONE', 'Færdig (Synkroniserede %s billeder).');
+@define('DELETE_IMAGE_FAIL' , 'Kunne ikke slette billedet <b>%s</b>');
+@define('DELETE_THUMBNAIL', 'Slettede billedet ved navn <b>%s</b>');
+@define('FILE_NOT_FOUND', 'Kunne ikke finde filen ved navn <b>%s</b>, måske er den allerede slettet?');
+@define('ABORT_NOW', 'Afbryd nu');
+@define('REMOTE_FILE_NOT_FOUND', 'Filen kunne ikke findes på serveren, er du sikker på URLen: <b>%s</b> er korrekt?');
+@define('FILE_FETCHED', '%s hentet: %s');
+@define('FILE_UPLOADED', 'Filen %s er blevet uploadet: %s');
+@define('WORD_OR', 'eller');
+@define('SCALING_IMAGE', 'Ændre størrelsen på %s til %s x %s px');
+@define('KEEP_PROPORTIONS', 'Bevar forholdet');
+@define('REALLY_SCALE_IMAGE', 'Er du sikker på du vil ændre størrelsen på dette billede? Der er ingen vej tilbage!');
+@define('TOGGLE_ALL', 'Vis/Skjul alle');
+@define('TOGGLE_OPTION', 'Vis/Skjul denne option');
+@define('SUBSCRIBE_TO_THIS_ENTRY', 'Abonnér på denne artikel');
+@define('UNSUBSCRIBE_OK', "%s er ikke længere abonnement på denne artikel");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'Ny kommentar på abonnerede artikel "%s"');
+@define('SUBSCRIPTION_MAIL', "Hej %s,\n\nEn ny kommentar er blevet lavet til en artikel du abonnerer på hos \"%s\", ved navn \"%s\"\nNavnet på skribenten er: %s\n\nDu kan finde artiklen her: %s\n\nDu kan stoppe dit abonnement ved at klikke på dette link: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "Hej %s,\n\nEt nyt trackback er blevet lavet til en artikel du abonnerer på hos \"%s\", ved navn \"%s\"\nNavnet på skribenten er: %s\n\nDu kan finde artiklen her: %s\n\nDu kan stoppe dit abonnement ved at klikke på dette link: %s\n");
+@define('SIGNATURE', "\n-- \n%s bruger Serendipity.\nDen bedste blog på dette, du kan også bruge det.\nKig nærmere på <http://s9y.org> for at finde mere information.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91 feed');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0 feed');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0 feed');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 kommentarer');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3 feed');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s feed');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'Feltet "Hovedredaktør"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  'Feltet "webmaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'Billede til RSS feedet');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', 'Billedebredde');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'Billedehøjde');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  'Email adressen på webmasteren, hvis tilgængelig. (tom: skjult) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', 'E-mail adressen på redaktøren, hvis tilgængelig. (tom: skjult) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'URL på et billede i GIF/JPEG/PNG format, hvis tilgængeligt. (tom: serendipity-logo)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'i pixels, max. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'i pixels, max. 400');
+@define('SYNDICATION_PLUGIN_TTL', 'Feltet "ttl" (time-to-live)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'Antallet af minutter din blog skal gemmes af eksterne sider/programmer (tom: skjult) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'Feltet "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', 'Skal "pubDate"-feltet være indkapslet til en RSS-channel, for at vise datoen på den nyeste artikel?');
+@define('CONTENT', 'Indhold');
+@define('TYPE', 'Type');
+@define('DRAFT', 'Udkast');
+@define('PUBLISH', 'Udgiv');
+@define('PREVIEW', 'Vis');
+@define('DATE', 'Dato');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', 'Advarsel: Den dato du indtastede var ugyldig. Det skal indtastes i følgende format: YYYY-MM-DD HH:MM.');
+@define('CATEGORY_PLUGIN_DESC', 'Viser listen over kategorier.');
+@define('ALL_AUTHORS', 'Alle forfattere');
+@define('CATEGORIES_TO_FETCH', 'Kategorier som skal hentes');
+@define('CATEGORIES_TO_FETCH_DESC', 'Hent kategorier fra en bestemt forfatter?');
+@define('PAGE_BROWSE_ENTRIES', 'Side %s af %s, i alt %s artikler');
+@define('PREVIOUS_PAGE', 'forrige side');
+@define('NEXT_PAGE', 'næste side');
+@define('ALL_CATEGORIES', 'Alle kategorier');
+@define('DO_MARKUP', 'Udført Markup-transformation');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'Datoformat');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'Formatet på artiklens faktiske dato, brug PHPs strftime() variabler. (Standard: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'Kunne ikke åbne skabelonen, opdater Serendipity!');
+@define('ADVANCED_OPTIONS', 'Avancerede indstillinger');
+@define('EDIT_ENTRY', 'Rediger artikel');
+@define('HTACCESS_ERROR', 'For at kunne checke din lokale webserver\'s installation, skal Serendipity være i stand til at skrive til filen ".htaccess". Dette var ikke muligt pga. forkerte rettigheder. Justér rettighederne således: <br />&nbsp;&nbsp;%s<br />og genindlæs siden.');
+@define('SORT_ORDER', 'Sorter efter');
+@define('SORT_ORDER_NAME', 'Filnavn');
+@define('SORT_ORDER_EXTENSION', 'Filtype');
+@define('SORT_ORDER_SIZE', 'Filstørrelse');
+@define('SORT_ORDER_WIDTH', 'Billedebrede');
+@define('SORT_ORDER_HEIGHT', 'Billedehøjde');
+@define('SORT_ORDER_DATE', 'Upload-dato');
+@define('SORT_ORDER_ASC', 'Stigende');
+@define('SORT_ORDER_DESC', 'Faldende');
+@define('THUMBNAIL_SHORT', 'Mini');
+@define('ORIGINAL_SHORT', 'Orig.');
+@define('APPLY_MARKUP_TO', 'Formater %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'Starten på ugen');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity har opdaget at din nuværende konfiguration passer til version %s. Serendipity selv er installeret som version %s, Det er nødvendigt at opgradere! <a href="%s">Klik her!</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'Velkommen til Serendipitys opgraderingsscript.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', 'Scriptet vil hjælpe dig med at opgradere Serendipity %s.');
+@define('SERENDIPITY_UPGRADER_WHY', 'Denne meddelelse vises, fordi Serendipity er installeret med version %s, men databasen er endnu ikke opgraderet til denne version.');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'Databasen opdateringer (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'Følgende .sql-filer skal eksekveres før Serendipity igen kan fungere normalt.');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  'Versionsspecifikke opgaver');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', 'Ingen versionsspecifikke opgaver fundet');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', 'Ønsker du at ovenstående opgaver udføres?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'Nej, jeg udfører dem manuelt');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'Ja tak!');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'Det ser ud til at opgradering ikke er nødvendig.');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', 'Serendipity er opgraderet');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'Du har ignoreret en del af opgraderingen. Undersøg venligst om databasen er korrekt opdateret, og planlagte opgaver udført');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'Din Serendipity-installation er nu opgraderet til version %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', 'Du kan vende tilbage til din blog ved at klikke %sher%s');
+@define('MANAGE_USERS', 'Håndter brugerer');
+@define('CREATE_NEW_USER', 'Opret by bruger');
+@define('CREATE_NOT_AUTHORIZED', 'Du kan ikke redigere brugere med den samme brugerniveau som digselv');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'Du kan ikke oprette brugere med en højere brugerniveau end digselv');
+@define('CREATED_USER', 'En ny bruger %s er blevet oprettet');
+@define('MODIFIED_USER', 'Egenskaberne for brugeren %s er blevet ændret');
+@define('USER_LEVEL', 'brugerniveau');
+@define('DELETE_USER', 'Du er ved at slette bruger #%d %s. Er du sikker? Dette vil forbyde visningen af alle artikler skrevet af ham.');
+@define('DELETED_USER', 'Bruger #%d %s er blevet slettet.');
+@define('LIMIT_TO_NUMBER', 'Hvor mange punkter skal vises?');
+@define('ENTRIES_PER_PAGE', 'artikler per side');
+@define('PERMISSIONS', 'Rettigheder');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', 'Database indstillinger');
+@define('INSTALL_CAT_DB_DESC', 'Her kan du indtaste al din database information');
+@define('INSTALL_DBTYPE', 'Database type');
+@define('INSTALL_DBTYPE_DESC', 'Database type');
+@define('INSTALL_DBHOST', 'Database host');
+@define('INSTALL_DBHOST_DESC', 'Hostname til din database server');
+@define('INSTALL_DBUSER', 'Database bruger');
+@define('INSTALL_DBUSER_DESC', 'Brugernavnet der er brugt til at forbinde til din database');
+@define('INSTALL_DBPASS', 'Database adgangskode');
+@define('INSTALL_DBPASS_DESC', 'Adgangskoden der passer til ovenstående brugernavn');
+@define('INSTALL_DBNAME', 'Database navn');
+@define('INSTALL_DBNAME_DESC', 'Navnet på din database');
+@define('INSTALL_DBPREFIX', 'Database tabel præfix');
+@define('INSTALL_DBPREFIX_DESC', 'Præfix på tabelnavne, fx. serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', 'Stier');
+@define('INSTALL_CAT_PATHS_DESC', 'Forskellige stier til forskellige essentielle mapper og filer. Glem ikke efterfølgende slashes på biblioteker!');
+@define('INSTALL_FULLPATH', 'Fuld sti');
+@define('INSTALL_FULLPATH_DESC', 'Den fulde og absolutte sti til din serendipity installation');
+@define('INSTALL_UPLOADPATH', 'Upload sti');
+@define('INSTALL_UPLOADPATH_DESC', 'Alle uploads bliver placeret her, relativ til \'Full path\' - typisk \'uploads/\'');
+@define('INSTALL_RELPATH', 'Relativ sti');
+@define('INSTALL_RELPATH_DESC', 'Sti til Serendipity i henhold til din browser, typisk \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', 'Relativ skabelon sti');
+@define('INSTALL_RELTEMPLPATH_DESC', 'Stien til mappen der indeholder dine skabeloner - Relativ til \'relative path\'');
+@define('INSTALL_RELUPLOADPATH', 'Relativ upload sti');
+@define('INSTALL_RELUPLOADPATH_DESC', 'Sti til dine uploads i henhold til din browser - Relativ til \'relative path\'');
+@define('INSTALL_URL', 'URL til din blog');
+@define('INSTALL_URL_DESC', 'Base URL for din Serendipity installation');
+@define('INSTALL_INDEXFILE', 'Index fil');
+@define('INSTALL_INDEXFILE_DESC', 'Navnet på din Serendipity index fil');
+
+/* Generel settings */
+@define('INSTALL_CAT_SETTINGS', 'Generelle indstillinger');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Tilpas den måde Serendipity opfører sig på');
+@define('INSTALL_USERNAME', 'Admin brugernavn');
+@define('INSTALL_USERNAME_DESC', 'Brugernavn til admin login');
+@define('INSTALL_PASSWORD', 'Admin adgangskode');
+@define('INSTALL_PASSWORD_DESC', 'Adgangskode til admin login');
+@define('INSTALL_EMAIL', 'Admin email');
+@define('INSTALL_EMAIL_DESC', 'E-mail adresse på ejeren af bloggen');
+@define('INSTALL_SENDMAIL', 'Send mails til admin?');
+@define('INSTALL_SENDMAIL_DESC', 'Vil du modtage emails når kommentare er givet på dine artikler?');
+@define('INSTALL_SUBSCRIBE', 'Tillad brugere at abonnere på artikler?');
+@define('INSTALL_SUBSCRIBE_DESC', 'Tillad brugere at abonnere på en artikel og derved modtage en mail når der bliver oprettet nye kommentare på den artikel');
+@define('INSTALL_BLOGNAME', 'Navn på blog');
+@define('INSTALL_BLOGNAME_DESC', 'Titlen på din blog');
+@define('INSTALL_BLOGDESC', 'Blog beskrivelse');
+@define('INSTALL_BLOGDESC_DESC', 'Beskrivelse af din blog');
+@define('INSTALL_LANG', 'Sprog');
+@define('INSTALL_LANG_DESC', 'Vælg sproget på din blog');
+
+/* Appearance and options */
+@define('INSTALL_CAT_DISPLAY', 'Udseende og indstillinger');
+@define('INSTALL_CAT_DISPLAY_DESC', 'Tilpas hvordan Serendipity ser ud og føles');
+@define('INSTALL_WYSIWYG', 'Brug WYSIWYG editor');
+@define('INSTALL_WYSIWYG_DESC', 'Vil du benytte WYSIWYG editoren? (Virker med IE5+, delvis i Mozilla 1.3+)');
+@define('INSTALL_XHTML11', 'Gennemtving XHTML 1.1');
+@define('INSTALL_XHTML11_DESC', 'Ønsker du at gennemtvinge XHTML 1.1 overholdelse (Kan skabe problemer i 4. generations browsere)');
+@define('INSTALL_POPUP', 'Aktiver brug af popup vinduer');
+@define('INSTALL_POPUP_DESC', 'Vil du åbne kommentarer og trackbacks i et popup vindue?');
+@define('INSTALL_EMBED', 'Er Serendipity embedded?');
+@define('INSTALL_EMBED_DESC', 'Hvis du ønsker at indkapsle Serendipity inde i en normal side, aktiver da dette direktiv for at ignorere headers og kun udskrive indholdet. Du kan benytte indexFile direktivet til at lave en wrapper fil hvor du placere din normale hjemmeside headers. Konsulter README filen for mere information!');
+@define('INSTALL_TOP_AS_LINKS', 'Vis top udgangssider/referencer som links?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"Nej": Udgangs- og henvisende sider er vist som ren tekst for at undgå google spam. "Ja": Udgangs- og henvisende sider er vist som hyperlinks. "standard": Brug indstillinger fra global konfiguration (anbefalet).');
+@define('INSTALL_BLOCKREF', 'Bloker referencer');
+@define('INSTALL_BLOCKREF_DESC', 'Er der nogle specielle hosts du ikke ønsker skal vises i reference listen? Separer listen af hostnavne med \';\' og bemærk at disse er blokere med substring masker!');
+@define('INSTALL_REWRITE', 'URL Omskrivning');
+@define('INSTALL_REWRITE_DESC', 'Vælg hvilken regel du ønsker at bruge når du generere URLs Aktivering at omskrivningsregler vil gøre dine URLs flotte og gøre din side bedre at indeksere for robotter som google. Webserveren skal enten understøtte mod_rewrite eller "AllowOverride All" for dit Serendipity bibliotek. Standardindstillingen er automatisk beregnet');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', 'Billedekonverterings indstillinger');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'Generel information om hvordan Serendipity skal håndtere billeder');
+@define('INSTALL_IMAGEMAGICK', 'Brug Imagemagick');
+@define('INSTALL_IMAGEMAGICK_DESC', 'Har du image magick installeret og ønsker at bruge det til at ændre størrelse på billeder?');
+@define('INSTALL_IMAGEMAGICKPATH', 'Sti til convert binær fil');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'Fuld sti og navn på din image magick convert binær fil');
+@define('INSTALL_THUMBSUFFIX', 'Thumbnail suffiks');
+@define('INSTALL_THUMBSUFFIX_DESC', 'Thumbnails vil blive navngivet i følgende format: original.[suffix].ext');
+@define('INSTALL_THUMBWIDTH', 'Thumbnail dimensioner');
+@define('INSTALL_THUMBWIDTH_DESC', 'Statisk maximal brede på et auto-genereret thumbnail');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', 'Dine personlige detaljer');
+@define('USERCONF_CAT_PERSONAL_DESC', 'Ændre dine personlige detaljer');
+@define('USERCONF_USERNAME', 'Dit brugernavn');
+@define('USERCONF_USERNAME_DESC', 'Brugernavnet du vil bruge for at logge ind i bloggen');
+@define('USERCONF_PASSWORD', 'Dit kodeord');
+@define('USERCONF_PASSWORD_DESC', 'Kodeordet du vil bruge for at logge ind i bloggen');
+@define('USERCONF_EMAIL', 'Din email adresse');
+@define('USERCONF_EMAIL_DESC', 'Din personlige email adresse');
+@define('USERCONF_SENDCOMMENTS', 'Send beskeder om nye kommentarer?');
+@define('USERCONF_SENDCOMMENTS_DESC', 'Ønsker du at modtage en mail når nye kommentarer bliver lavet på dine artikler?');
+@define('USERCONF_SENDTRACKBACKS', 'Send beskeder om nye trackbacks?');
+@define('USERCONF_SENDTRACKBACKS_DESC', 'Ønsker du at modtage en mail når nye trackbacks bliver lavet på dine artikler?');
+@define('USERCONF_ALLOWPUBLISH', 'Tilladelse: Udgiv artikler?');
+@define('USERCONF_ALLOWPUBLISH_DESC', 'Kan denne bruger udgive artikler?');
+
+@define('DIRECTORIES_AVAILABLE', 'I listen over tilgængelige undermapper, kan du klikke på en ny mappe for at oprette en ny mappe inden for den stuktur.');
+@define('ALL_DIRECTORIES', 'alle mapper');
+@define('MANAGE_DIRECTORIES', 'Håndér mapper');
+@define('DIRECTORY_CREATED', 'Mappen <strong>%s</strong> er blevet oprettet.');
+@define('PARENT_DIRECTORY', 'Hovedmappe');
+@define('CONFIRM_DELETE_DIRECTORY', 'Er du sikker på du vil slette al indholdet af mappen %s?');
+@define('ERROR_NO_DIRECTORY', 'Fejl: Mappen %s eksistere ikke');
+@define('CHECKING_DIRECTORY', 'Checker filer i mappen %s');
+@define('DELETING_FILE', 'Sletter fil %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', 'Kunne ikke fjerne en ikke-tom mappe. Afkryds "gennemtving sletning" feltet, hvis du vil slette disse og tryk derefter på submit igen. Eksisterende filer er:');
+@define('DIRECTORY_DELETE_FAILED', 'Sletning af mappe %s mislykkedes. Check rettigheder eller ovenstående beskeder.');
+@define('DIRECTORY_DELETE_SUCCESS', 'Mappen %s er blevet slettet.');
+@define('SKIPPING_FILE_EXTENSION', 'Ignorerede filen: Manglende filtype %s.');
+@define('SKIPPING_FILE_UNREADABLE', 'Ignorere fil: %s er ikke læsbar.');
+@define('FOUND_FILE', 'Fandt ny/ændret fil: %s.');
+@define('ALREADY_SUBCATEGORY', '%s er allerede en underkategori af %s.');
+@define('PARENT_CATEGORY', 'Hovedkategori');
+@define('IN_REPLY_TO', 'Som svar på');
+@define('TOP_LEVEL', 'Topniveau');
+@define('XML_IMAGE_TO_DISPLAY', 'XML knap');
+@define('XML_IMAGE_TO_DISPLAY_DESC','Links til XML Feeds vil blive vist med dette billede. Efterlad tomt for standard, indtast \'none\' for at deaktivere.');
+@define('SUCCESS', 'Succes');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', ',');
+@define('NUMBER_FORMAT_THOUSANDS', '.');
+@define('POWERED_BY_SHOW_TEXT', 'Vis "Serendipity" som tekst');
+@define('POWERED_BY_SHOW_TEXT_DESC', 'Vil vise "Serendipity Weblog" som tekst');
+@define('POWERED_BY_SHOW_IMAGE', 'Vis "Serendipity"" som et logo');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Vis Serendipity logoet');
+@define('SETTINGS_SAVED_AT', 'De nye indstillinger er blevet gemt kl %s');
+@define('PLUGIN_ITEM_DISPLAY', 'Hvor skal enheden vises?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'Kun udvidet artikel');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'Kun i oversigten');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'Hele tiden');
+@define('RSS_IMPORT_CATEGORY', 'Brug denne kategori for kategoriløse artikler');
+@define('ERROR_UNKNOWN_NOUPLOAD', 'Der skete en ukendt fejl, filen blev ikke uploaded. Måske er din filstørrelse større end den maximale størrelse tilladt af din serveropsætning. Spørg din webudbyder eller rediger din php.ini fil for at tillade uploads af større filer.');
+@define('COMMENTS_WILL_BE_MODERATED', 'Kommentarer på denne artikel vil først blive vist såfremt de bliver godkendt.');
+@define('YOU_HAVE_THESE_OPTIONS', 'Du har følgende muligheder:');
+@define('THIS_COMMENT_NEEDS_REVIEW', 'Advarsel: Denne kommentar kræver godkendelse førend den vil blive vist');
+@define('DELETE_COMMENT', 'Slet kommentar');
+@define('APPROVE_COMMENT', 'Godkend kommentar');
+@define('REQUIRES_REVIEW', 'Kræver godkendelse');
+@define('COMMENT_APPROVED', 'Kommentar #%s er blevet godkendt');
+@define('COMMENT_DELETED', 'Kommentar #%s er blevet slettet');
+@define('VIEW', 'Vis');
+@define('COMMENT_ALREADY_APPROVED', 'Kommentar #%s ser allerede ud til at være godkendt');
+@define('COMMENT_EDITED', 'Den valgte kommentar er blevet redigeret');
+@define('HIDE', 'Skjul');
+@define('VIEW_EXTENDED_ENTRY', 'Læs resten af "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'Dette link er ikke ikke til at blive klikket. Det indeholder denne artikels trackback URI. Du kan bruge denne URI til at sende ping- & trackbacks fra din egen blog til denne artikel. For at kopiere linket, kan du højreklikke og vælge "Kopier genvej" i Internet Explorer eller "Copy Link Location" i Mozilla.');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'Advarsel: Dette trackback kræver godkendelse førend det vil blive vist');
+@define('DELETE_TRACKBACK', 'Slet trackback');
+@define('APPROVE_TRACKBACK', 'Godkend trackback');
+@define('TRACKBACK_APPROVED', 'Trackback #%s er blevet godkendt');
+@define('TRACKBACK_DELETED', 'Trackback #%s er blevet slettet');
+@define('COMMENTS_MODERATE', 'Kommentarer og trackbacks til denne artikel kræver godkendelse');
+@define('PLUGIN_SUPERUSER_HTTPS', 'Brug https til login');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'Lader loginlinket pege på en https-destination. Din webserver skal understøtte dette!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'Gør eksterne links klikbare?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"nej": Eksterne links (Top udgangsider, Top henvisninger, bruger kommentarer) er ikke vist/vist som ren tekst hvor brugbart, for at forhindre google spam (anbefales). "ja": Eksterne links er vist som hyperlinks. Kan overskrives inde i hver enkel sidebar plugin konfigurationen!');
+@define('PAGE_BROWSE_COMMENTS', 'Side %s af %s, i alt %s kommentarer');
+@define('FILTERS', 'Filtrer');
+@define('FIND_ENTRIES', 'Find artikler');
+@define('FIND_COMMENTS', 'Find kommentarer');
+@define('FIND_MEDIA', 'Find media');
+@define('FILTER_DIRECTORY', 'Bibliotek');
+@define('SORT_BY', 'Sorter efter');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'Intet trackback sendt: Kunne ikke åbne forbindelse til %s på port %d');
+@define('MEDIA', 'Media');
+@define('MEDIA_LIBRARY', 'Mediabibliotek');
+@define('ADD_MEDIA', 'Tilføj media');
+@define('ENTER_MEDIA_URL', 'Indtast en URL til filen du vil hente');
+@define('ENTER_MEDIA_UPLOAD', 'Vælg en fil du ønsker at uploade:');
+@define('SAVE_FILE_AS', 'Gem files som:');
+@define('STORE_IN_DIRECTORY', 'Gem i følgende bibliotek:');
+@define('MEDIA_RENAME', 'Omdøb denne fil');
+@define('IMAGE_RESIZE', 'Ændre størrelse på billede');
+@define('MEDIA_DELETE', 'Slet denne fil');
+@define('FILES_PER_PAGE', 'Filer per side');
+@define('CLICK_FILE_TO_INSERT', 'Klik på filen du vil indsætte:');
+@define('SELECT_FILE', 'Vælg filen du vil indsætte');
+@define('MEDIA_FULLSIZE', 'Fuld størrelse');
+@define('CALENDAR_BOW_DESC', 'Dagen i ugen der skal bruges som den første dag i ugen. Standardværdien er Mandag');
+@define('SUPERUSER', 'Blog Administration');
+@define('ALLOWS_YOU_BLAHBLAH', 'Placerer et link i sidebaren til din blog administration');
+@define('CALENDAR', 'Kalender');
+@define('SUPERUSER_OPEN_ADMIN', 'Åbn administration');
+@define('SUPERUSER_OPEN_LOGIN', 'Åbn loginskærm');
+@define('INVERT_SELECTIONS', 'Inverter valgte elementer');
+@define('COMMENTS_DELETE_CONFIRM', 'Er du sikker på du vil slette de valgte kommentarer?');
+@define('COMMENT_DELETE_CONFIRM', 'Er du sikker på du vil slette kommentar #%d, skrevet af %s?');
+@define('DELETE_SELECTED_COMMENTS', 'Slet valgte kommentarer');
+@define('VIEW_COMMENT', 'Vis kommentar');
+@define('VIEW_ENTRY', 'Vis artikel');
+@define('DELETE_FILE', 'Slettede filen ved navn <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', 'Du er ved at slette <b>%s</b><br />Hvis du benytter denne fil i nogle af dine artikler, vil det resultere i døde links eller billeder<br />Er du sikker på du vil fortsætte?<br /><br />');
+@define('TRACKBACK_SENDING', 'Sender trackback til URI %s...');
+@define('TRACKBACK_SENT', 'Trackback fuldført');
+@define('TRACKBACK_FAILED', 'Trackback fejl: %s');
+@define('TRACKBACK_NOT_FOUND', 'Ingen trackback URI fundet.');
+@define('TRACKBACK_URI_MISMATCH', 'Den automastiske trackback URI passer ikke vores egen URI.');
+@define('TRACKBACK_CHECKING', 'Checker <u>%s</u> for mulige trackbacks...');
+@define('TRACKBACK_NO_DATA', 'Modstående side indeholdte inden data');
+@define('TRACKBACK_SIZE', 'Modstående URI overskred den maximale filstørrelse på %s bytes.');
+@define('VIEWMODE_THREADED', 'Switch to threaded view');
+@define('COMMENTS_VIEWMODE_THREADED', 'Tråde');
+@define('COMMENTS_VIEWMODE_LINEAR', 'Linear');
+@define('DISPLAY_COMMENTS_AS', 'Vis kommentarer som');
+@define('SIDEBAR_PLUGINS', 'Sidebarplugins');
+@define('EVENT_PLUGINS', 'Hændelseplugins');
+@define('ADD_MEDIA_BLAHBLAH', '<b>Tilføj en fil til dit mediearkiv:</b><p>Her kan du uploade mediafiler, eller bede mig hente dem fra et sted på nette! Hvis du ikke har et passende billeder, <a href="http://images.google.com" target="_blank">prøv at søg efter billeder på google</a> der passer til dine tanker, resultatet er ofte brugbart og sjovt :)<p><b>Vælg metode:</b><br>');
+@define('COMMENTS_FILTER_SHOW', 'Vis');
+@define('COMMENTS_FILTER_ALL', 'Alle');
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'Kun godkendte');
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'Afventer godkendelse');
+@define('RSS_IMPORT_BODYONLY', 'Placer al den importeret tekst in i "artikel" delen, og ikke opdel ind i "udvidet artikel" sektionen.');
+@define('SYNDICATION_PLUGIN_FULLFEED', 'Vil hele artiklen, med udvidet del, inde i RSS feed');
+@define('MT_DATA_FILE', 'Movable Type data fil');
+@define('FORCE', 'gennemtving');
+@define('CREATE_AUTHOR', 'Opret forfatter \'%s\'.');
+@define('CREATE_CATEGORY', 'Opret kategori \'%s\'.');
+@define('MYSQL_REQUIRED', 'Du skal have MySQL udvidelsen installere førend du kan udføre denne handling.');
+@define('COULDNT_CONNECT', 'Kunne ikke forbinde til MySQL database: %s.');
+@define('COULDNT_SELECT_DB', 'Kunne ikke vælge database: %s.');
+@define('COULDNT_SELECT_USER_INFO', 'Kunne ikke finde bruger information: %s.');
+@define('COULDNT_SELECT_CATEGORY_INFO', 'Kunne ikke finde kategori information: %s.');
+@define('COULDNT_SELECT_ENTRY_INFO', 'Kunne ikke finde artikel information: %s.');
+@define('COULDNT_SELECT_COMMENT_INFO', 'Kunne ikke finde kommentar information: %s.');
+@define('WEEK', 'Uge');
+@define('WEEKS', 'Uger');
+@define('MONTHS', 'Månder');
+@define('DAYS', 'Dage');
+@define('ARCHIVE_FREQUENCY', 'Kalender frekvens');
+@define('ARCHIVE_FREQUENCY_DESC', 'Angiver intervallet imellem hvert punkt på listen');
+@define('ARCHIVE_COUNT', 'Antal punkter på listen');
+@define('ARCHIVE_COUNT_DESC', 'Det totale antal af måneder, uger eller dage at vise');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'Herunder er en liste over installerede plugins');
+@define('SIDEBAR_PLUGIN', 'sidebar plugin');
+@define('EVENT_PLUGIN', 'event plugin');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'Klik her for at installere et nyt %s');
+@define('VERSION', 'version');
+@define('INSTALL', 'Installer');
+@define('ALREADY_INSTALLED', 'Allerede installeret');
+@define('SELECT_A_PLUGIN_TO_ADD', 'Vælge det plugin du ønsker at instalelre');
+@define('INSTALL_OFFSET', 'Server tidsforskydelse');
+@define('STICKY_POSTINGS', 'Vedvarende artikler');
+@define('INSTALL_FETCHLIMIT', 'Artikler på forsiden');
+@define('INSTALL_FETCHLIMIT_DESC', 'Antallet af artikler at vise på hver side på forsiden');
+@define('IMPORT_ENTRIES', 'Importer data');
+@define('EXPORT_ENTRIES', 'Eksporter artikler');
+@define('IMPORT_WELCOME', 'Velkommen til Serendipity importværktøj');
+@define('IMPORT_WHAT_CAN', 'Her kan du importere artikler fra andre weblog software applikationer');
+@define('IMPORT_SELECT', 'Vælg venligst det software du ønsker at importere fra');
+@define('IMPORT_PLEASE_ENTER', 'Indtast venligst det påkrævede data herunder');
+@define('IMPORT_NOW', 'Importer nu!');
+@define('IMPORT_STARTING', 'Starter import procedure...');
+@define('IMPORT_FAILED', 'Importeringen fejlede');
+@define('IMPORT_DONE', 'Importering gennemført');
+@define('IMPORT_WEBLOG_APP', 'Weblog applikation');
+@define('EXPORT_FEED', 'Eksporter fuldt RSS feed');
+@define('STATUS', 'Status efter import');
+@define('IMPORT_GENERIC_RSS', 'Almindeligt RSS import');
+@define('ACTIVATE_AUTODISCOVERY', 'Send Trackbacks til links fundet i artikler');
+@define('WELCOME_TO_ADMIN', 'Velkommen til Serendipity Administrations Suiteen.');
+@define('PLEASE_ENTER_CREDENTIALS', 'Indtast venligst dine adgangsoplysninger herunder.');
+@define('ADMIN_FOOTER_POWERED_BY', 'Drives af Serendipity %s og PHP %s');
+@define('INSTALL_USEGZIP', 'Benyt gzip komprimerede sider');
+@define('INSTALL_USEGZIP_DESC', 'For at fremskynde levering af sider, kan vi komprimere siderne vi sender til den besøgende, givet at hans browser understøtter dette. Dette er anbefalet');
+@define('INSTALL_SHOWFUTURE', 'Vis fremtidige artikler');
+@define('INSTALL_SHOWFUTURE_DESC', 'Hvis aktiveret, dette vil vise alle fremtidige artikler på din blog. Som standard skjules disse artikler og vises først når udgivelsesdatoen er nået.');
+@define('INSTALL_DBPERSISTENT', 'Brug vedvarende forbindelser');
+@define('INSTALL_DBPERSISTENT_DESC', 'Aktiver brug af vedvarende database forbindelser, læs mere <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">her</a>. Dette anbefales normalt ikke');
+@define('NO_IMAGES_FOUND', 'Ingen billeder fundet');
+@define('PERSONAL_SETTINGS', 'Personlige indstillinger');
+@define('REFERER', 'Henvisende side');
+@define('NOT_FOUND', 'Ikke fundet');
+@define('NOT_WRITABLE', 'Ikke skrivbar');
+@define('WRITABLE', 'Skrivbar');
+@define('PROBLEM_DIAGNOSTIC', 'Grundet en problematisk diagnose, kan du ikke fortsætte med installationen førend ovenstående fejl er rettet');
+@define('SELECT_INSTALLATION_TYPE', 'Vælg hvilken installationstype du vil benytte');
+@define('WELCOME_TO_INSTALLATION', 'Velkommen til Serendipity Installationen');
+@define('FIRST_WE_TAKE_A_LOOK', 'Først kigger vi på dit nuværende setup og vil forsøge at diagnosere eventuelle kompatibilitetsproblemer');
+@define('ERRORS_ARE_DISPLAYED_IN', 'Fejl er vist som %s, anbefalinger som %s og succes som %s');
+@define('RED', 'rød');
+@define('YELLOW', 'gul');
+@define('GREEN', 'grøn');
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s før-installations report');
+@define('RECOMMENDED', 'Anbefalet');
+@define('ACTUAL', 'Faktisk');
+@define('PHPINI_CONFIGURATION', 'php.ini konfiguration');
+@define('PHP_INSTALLATION', 'PHP installation');
+@define('THEY_DO', 'det gør de');
+@define('THEY_DONT', 'det før de ikke');
+@define('SIMPLE_INSTALLATION', 'Simpel installation');
+@define('EXPERT_INSTALLATION', 'Expert installation');
+@define('COMPLETE_INSTALLATION', 'Fuldfør installation');
+@define('WONT_INSTALL_DB_AGAIN', 'instalerer ikke database igen');
+@define('CHECK_DATABASE_EXISTS', 'Undersøger om databasen og tabllerne allerede findes');
+@define('CREATING_PRIMARY_AUTHOR', 'Opretter primær forfatter \'%s\'');
+@define('SETTING_DEFAULT_TEMPLATE', 'Sætter standard template');
+@define('INSTALLING_DEFAULT_PLUGINS', 'Installere standard plugins');
+@define('SERENDIPITY_INSTALLED', 'Serendipity er nu installeret');
+@define('VISIT_BLOG_HERE', 'Besøg din nye blog her');
+@define('THANK_YOU_FOR_CHOOSING', 'Tak fordi du valgte Serendipity');
+@define('ERROR_DETECTED_IN_INSTALL', 'En fejl blev fundet under installationen');
+@define('OPERATING_SYSTEM', 'Operativsystem');
+@define('WEBSERVER_SAPI', 'Webserver SAPI');
+@define('IMAGE_ROTATE_LEFT', 'Roter billede 90 grader imod uret');
+@define('IMAGE_ROTATE_RIGHT', 'Roter billede 90 grader med uret');
+@define('TEMPLATE_SET', '\'%s\' has been set as your active template');
+@define('SEARCH_ERROR', 'Søgefunktionen fungere ikke som forventet. Besked til administratoren: Dette sker muligvis pga. en manglende index key i databasen. På MySQL systemer skal din bruger have rettigheder til at udføre dette query: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> Den specifikke fejl returneret af databasen, var: <pre>%s</pre>');
+@define('EDIT_THIS_CAT', ' Redigerer "%s"');
+@define('CATEGORY_REMAINING', 'Slet denne kategori og flyt dens artikler ind i denne kategori');
+@define('CATEGORY_INDEX', 'Nedenunder er en liste over kategorier der er tilgængelige for dine artikler');
+@define('NO_CATEGORIES', 'Ingen kategorier');
+@define('RESET_DATE', 'Reset dato');
+@define('RESET_DATE_DESC', 'Klik her for at resette datoen til den nuværende tid');
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Rettigheder kan gives ved at kører følgende shell kommando: `<em>%s</em>` på det fejlede bibliotek, eller ved at sætte det vha. et FTP program');
+@define('WARNING_TEMPLATE_DEPRECATED', 'Advarsel: Din nuværende template bruger en forældet template metode, vi anbefaler du opgraderer, hvis muligt');
+@define('ENTRY_PUBLISHED_FUTURE', 'Denne artikler er endnu ikke udgivet.');
+@define('ENTRIES_BY', 'Artikler skrevet af %s');
+@define('PREVIOUS', 'Forrige');
+@define('NEXT', 'Næste');
+@define('APPROVE', 'Godkend');
+@define('DO_MARKUP_DESCRIPTION', 'Tilføj markup-transformationer på teksten (smilies, shortcut markups via *, /, _, ...). Hvis du slår dette fra vil al HTML-kode i teksten blive bibeholdt.');
+@define('CATEGORY_ALREADY_EXIST', 'En kategori med navnet "%s" findes allerede');
+@define('IMPORT_NOTES', 'Note:');
+@define('ERROR_FILE_FORBIDDEN', 'Det er ikke tilladt at uploade filer med aktivt indhold');
+@define('ADMIN', 'Administration'); // Re-Translate
+@define('ADMIN_FRONTPAGE', 'Forside');
+@define('QUOTE', 'Citer');
+@define('IFRAME_SAVE', 'Serendipity gemmer nu din artikel, sender trackbacks og udfører mulige XML-RPC calls. Dette kan tage noget tid..');
+@define('IFRAME_SAVE_DRAFT', 'Et udkast af denne artikel er blevet gemt');
+@define('IFRAME_PREVIEW', 'Serendipity opretter nu et preview af din artikel...');
+@define('IFRAME_WARNING', 'Din browser understøtter ikke iframes. Åbn serendipity_config.inc.php og sæt $serendipity[\'use_iframe\'] til FALSE.');
+@define('NONE', 'ingen');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Standard indstillinger for nye artikler');
+@define('UPGRADE', 'Opgrader');
+@define('UPGRADE_TO_VERSION', 'Opgrader til v%s');
+@define('DELETE_DIRECTORY', 'Slet mappe');
+@define('DELETE_DIRECTORY_DESC', 'Du er ved at slette indholdet af en mappe der indeholder multimedia filer, muligvis filer brugt i dine artikler.');
+@define('FORCE_DELETE', 'Slet ALLE filer i denne mappe, inklusiv dem ikke kendt af Serendipity');
+@define('CREATE_DIRECTORY', 'Opret mappe');
+@define('CREATE_NEW_DIRECTORY', 'Opret ny mappe');
+@define('CREATE_DIRECTORY_DESC', 'Her kan du oprette en ny mappe til at placere dine multimedia filer i. Vælg navnet på din nye mappe, og vælg en passende mappe at oprette den i.');
+@define('BASE_DIRECTORY', 'Rodmappe');
+@define('USERLEVEL_EDITOR_DESC', 'Standard editor');
+@define('USERLEVEL_CHIEF_DESC', 'Chefeditor');
+@define('USERLEVEL_ADMIN_DESC', 'Administrator');
+@define('USERCONF_USERLEVEL', 'Adgangsniveau');
+@define('USERCONF_USERLEVEL_DESC', 'Dette niveau er brugt til at bestemme hvilken type adgang brugeren har til bloggen');
+@define('USER_SELF_INFO', 'Logget ind som %s (%s)');
+@define('ADMIN_ENTRIES', 'Artikler');
+@define('RECHECK_INSTALLATION', 'Check installation igen');
+@define('IMAGICK_EXEC_ERROR', 'Kunne ikke eksekvere: "%s", fejl: %s, return var: %d');
+@define('INSTALL_OFFSET_DESC', 'Indtast antallet af timer mellem tiden på din webserver (%clock%) og din fortrukne tidszone');
+@define('UNMET_REQUIREMENTS', 'Uopfyldt krav: %s');
+@define('CHARSET', 'Karaktersæt');
+@define('AUTOLANG', 'Brug, som standard, brugerens browser sprog');
+@define('AUTOLANG_DESC', 'Hvis aktiveret, vil brugerens browsersprog benyttes til at finde det viste sprog i dine artikler og interface.');
+@define('INSTALL_AUTODETECT_URL', 'Autoudregn brugte HTTP-Host');
+@define('INSTALL_AUTODETECT_URL_DESC', 'Hvis denne er sat til "ja", vil Serendipity sikre at den HTTP Host der var brug af din besøgende, er brugt som din BaseURL indstilling. Aktiverer du dette, kan du bruge flere domænenavne på samme Serendipity Blog.');
+@define('CONVERT_HTMLENTITIES', 'Prøv at automatisk konvertere HTML entities?');
+@define('EMPTY_SETTING', 'Du angav ikke en gyldig værdi for "%s"!');
+@define('USERCONF_REALNAME', 'Rigtigt navn');
+@define('USERCONF_REALNAME_DESC', 'Det fulde navn på fatteren. Dette er navnet set af læserne');
+@define('HOTLINK_DONE', 'Fil blev hotlinked.<br />Færdig.');
+@define('ENTER_MEDIA_URL_METHOD', 'Afhentningsmetode:');
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Bemærk: Hvis du vælger at hotlinke til en server, bør du sikre dig tilladelse til at gøre dette, eller være ejeren af serveren. Hotlink gør det muligt at bruge eksterne billeder, uden at gemme den lokalt.');
+@define('MEDIA_HOTLINKED', 'hotlinked');
+@define('FETCH_METHOD_IMAGE', 'Hent billede fra din server');
+@define('FETCH_METHOD_HOTLINK', 'Hotlink til server');
+@define('DELETE_HOTLINK_FILE', 'Slet den hotlinked fil ved navn <b>%s</b>');
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Vis E-Mail adresser?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/lang/serendipity_lang_de.inc.php b/lang/serendipity_lang_de.inc.php
new file mode 100644 (file)
index 0000000..dff9d25
--- /dev/null
@@ -0,0 +1,669 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Translation (c) Jannis Hermanns, Garvin Hicking and others
+
+@define('LANG_CHARSET', 'ISO-8859-1');
+@define('DATE_LOCALES', 'german, de_DE, de, de_DE.ISO-8859-1, de_DE@euro, de_DE.ISO8859-1');
+@define('DATE_FORMAT_ENTRY', '%A, %e. %B %Y');
+@define('DATE_FORMAT_SHORT', '%d.%m.%Y %H:%M');
+@define('WYSIWYG_LANG', 'de');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', ',');
+@define('NUMBER_FORMAT_THOUSANDS', '.');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Serendipity Verwaltungsoberfläche');
+@define('HAVE_TO_BE_LOGGED_ON', 'Sie müssen angemeldet sein, um diese Seite zu sehen');
+@define('WRONG_USERNAME_OR_PASSWORD', 'Das Passwort oder der Username war falsch. Bitte wiederholen Sie die Eingabe.');
+@define('APPEARANCE', 'Aussehen');
+@define('MANAGE_STYLES', 'Styles verwalten');
+@define('CONFIGURE_PLUGINS', 'Plugins verwalten');
+@define('CONFIGURATION', 'Konfiguration');
+@define('BACK_TO_BLOG', 'Zurück zum Blog');
+@define('LOGOUT', 'Abmelden');
+@define('LOGGEDOUT', 'Abgemeldet.');
+@define('CREATE', 'Erstellen');
+@define('SAVE', 'Speichern');
+@define('NAME', 'Name');
+@define('NEW_TRACKBACK_TO', 'Neues Trackback für');
+@define('NEW_COMMENT_TO', 'Neuer Kommentar für');
+@define('RECENT', 'Das neueste...');
+@define('OLDER', 'Älteres...');
+@define('ANONYMOUS', 'Anonym');
+@define('CREATE_NEW_CAT', 'Neue Kategorie');
+@define('I_WANT_THUMB', 'Ich möchte die Vorschau im Eintrag haben.');
+@define('I_WANT_BIG_IMAGE', 'Ich möchte das grosse Bild im Eintrag haben.');
+@define('I_WANT_NO_LINK', 'Das Bild soll kein Link sein');
+@define('I_WANT_IT_TO_LINK', 'Das Bild soll hierhin linken:');
+@define('BACK', 'Zurück');
+@define('FORWARD', 'Vorwärts');
+@define('DONE', 'Fertig');
+@define('WELCOME_BACK', 'Willkommen zurück,');
+@define('TITLE', 'Titel');
+@define('DESCRIPTION', 'Beschreibung');
+@define('PLACEMENT', 'Platzierung');
+@define('DELETE', 'Löschen');
+@define('SAVE', 'Speichern');
+@define('UP', 'HOCH');
+@define('DOWN', 'RUNTER');
+@define('ENTRIES', 'Einträge');
+@define('NEW_ENTRY', 'Neuer Eintrag');
+@define('EDIT_ENTRIES', 'Einträge bearbeiten');
+@define('CATEGORIES', 'Kategorien');
+@define('WARNING_THIS_BLAHBLAH', "ACHTUNG:\\nDas kann jetzt lange dauern, wenn für viele Bilder noch keine Vorschau existiert.");
+@define('CREATE_THUMBS', 'Vorschauen erneuern');
+@define('MANAGE_IMAGES', 'Bilder verwalten');
+@define('NAME', 'Name');
+@define('EMAIL', 'Email');
+@define('HOMEPAGE', 'Homepage');
+@define('COMMENT', 'Kommentar');
+@define('REMEMBER_INFO', 'Daten merken? ');
+@define('SUBMIT_COMMENT', 'Kommentar abschicken');
+@define('NO_ENTRIES_TO_PRINT', 'Keine Einträge vorhanden');
+@define('COMMENTS', 'Kommentare');
+@define('ADD_COMMENT', 'Kommentar schreiben');
+@define('NO_COMMENTS', 'Noch keine Kommentare');
+@define('POSTED_BY', 'Geschrieben von');
+@define('ON', 'am');
+@define('A_NEW_COMMENT_BLAHBLAH', 'Im Blog %s wurde ein neuer Kommentar zu Eintrag #%s eingetragen!');
+@define('NO_CATEGORY', 'Keine Kategorie');
+@define('ENTRY_BODY', 'Eintrag');
+@define('EXTENDED_BODY', 'Erweiterter Eintrag');
+@define('CATEGORY', 'Kategorie');
+@define('EDIT', 'Bearbeiten');
+@define('NO_ENTRIES_BLAHBLAH', 'Für die Suche %s konnte kein Eintrag gefunden werden' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'Die Suche nach %s ergab %s Treffer:');
+@define('IMAGE', 'Bild');
+@define('ERROR_FILE_NOT_EXISTS', ' Alte Datei existiert nicht!');
+@define('ERROR_FILE_EXISTS', 'Fehler: Neuer Dateiname existiert schon, bitte einen anderen wählen.');
+@define('ERROR_SOMETHING', 'Fehler: Irgend etwas stimmt nicht.');
+@define('ADDING_IMAGE', 'Bild hinzufügen...');
+@define('THUMB_CREATED_DONE', 'Vorschau erstellt.<br />Fertig.');
+@define('ERROR_FILE_EXISTS_ALREADY', 'Fehler: Diese Datei existiert schon auf dem Server!');
+@define('GO', 'Los!');
+@define('NEWSIZE', 'Neue Größe ');
+@define('RESIZE_BLAHBLAH', '<b>Größe von %s ändern</b><p>');
+@define('ORIGINAL_SIZE', 'Originalgröße: <i>%sx%s</i> Pixel');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>Hier können Sie die Bildgröße ändern. Um die Proportionen beizubehalten, einfach einen der beiden Werte eingeben, und anschließend die TAB-Taste drücken, und Sie erhalten eine Vorschau mit korrekten Proportionen.');
+@define('DATE_FORMAT_1', 'd.m.Y');
+@define('QUICKJUMP_CALENDAR', 'QuickJump Kalender');
+@define('QUICKSEARCH', 'Suche');
+@define('SEARCH_FOR_ENTRY', 'Nach Einträgen suchen');
+@define('ARCHIVES', 'Archive');
+@define('BROWSE_ARCHIVES', 'Die Archive durchstöbern');
+@define('TOP_REFERRER', 'Top Referrer');
+@define('SHOWS_TOP_SITES', 'Zeigt die Top-Seiten, die auf das Blog linken');
+@define('TOP_EXITS', 'Top Exits');
+@define('SHOWS_TOP_EXIT', 'Zeigt die Top-Exit-Links des Blogs');
+@define('SYNDICATION', 'Syndication');
+@define('SHOWS_RSS_BLAHBLAH', 'Zeigt die RSS Syndication-Links');
+@define('ADVERTISES_BLAHBLAH', 'Zeigt einen Hinweis darauf, dass Serendipity als Blog-Software verwendet wird');
+@define('HTML_NUGGET', 'HTML Klotz');
+@define('HOLDS_A_BLAHBLAH', 'Zeigt einen kleinen Klotz HTML Code in einer der Seitenleisten an');
+@define('TITLE_FOR_NUGGET', 'Titel für den Klotz');
+@define('THE_NUGGET', 'Der HTML Klotz!');
+@define('SYNDICATE_THIS_BLOG', 'Blog abonnieren');
+@define('SEARCH_TOO_SHORT', 'Bitte geben Sie einen Suchbegriff mit mehr als drei Zeichen an.');
+@define('YOU_CHOSE', 'Sie haben sich für %s entschieden');
+@define('IMAGE_SIZE', 'Bildgröße');
+@define('IMAGE_ROTATE_LEFT', 'Bild 90 Grad gegen den Uhrzeigersinn drehen');
+@define('IMAGE_ROTATE_RIGHT', 'Bild 90 Grad im Uhrzeigersinn drehen');
+@define('IMAGE_AS_A_LINK', 'Bild als Link');
+@define('POWERED_BY', 'Powered by');
+@define('TRACKBACKS', 'Trackbacks');
+@define('TRACKBACK', 'Trackback');
+@define('NO_TRACKBACKS', 'Keine Trackbacks');
+@define('TOPICS_OF', 'Themen in');
+@define('VIEW_FULL', 'ganz anzeigen');
+@define('VIEW_TOPICS', 'Überschriften anzeigen');
+@define('AT', 'um');
+@define('SET_AS_TEMPLATE', 'Als Template wählen');
+@define('IN', 'in');
+@define('EXCERPT', 'Auszug');
+@define('TRACKED', 'Aufgenommen');
+@define('LINK_TO_ENTRY', 'Link zum Eintrag');
+@define('LINK_TO_REMOTE_ENTRY', 'Link zum Remote-Eintrag');
+@define('IP_ADDRESS', 'IP-Adresse');
+@define('USER', 'Benutzer');
+@define('THUMBNAIL_USING_OWN', 'Verwende %s als Vorschaubild, da das Originalbild bereits so klein ist.');
+@define('THUMBNAIL_FAILED_COPY', 'Wollte %s als Vorschaubild verwenden, aber das Kopieren schlug fehl!');
+@define('AUTHOR', 'Author');
+@define('LAST_UPDATED', 'Zuletzt aktualisiert');
+@define('TRACKBACK_SPECIFIC', 'Trackback für spezifische URI dieses Eintrags');
+@define('DIRECT_LINK', 'Direkter Link zu diesem Eintrag');
+@define('COMMENT_ADDED', 'Kommentar wurde hinzugefügt. ');
+@define('COMMENT_ADDED_CLICK', 'Klicken Sie %shier, um zu den Kommentaren zurückzukehren%s und %shier, um das Fenster zu schließen%s.');
+@define('COMMENTS_DISABLE', 'Kommentare für diesen Eintrag nicht mehr zulassen');
+@define('COMMENTS_ENABLE', 'Kommentare für diesen Eintrag zulassen');
+@define('COMMENTS_CLOSED', 'Die Kommentarfunktion wurde vom Besitzer dieses Blogs in diesem Eintrag deaktiviert. ');
+@define('COMMENT_NOT_ADDED', 'Kommentar wurde nicht hinzugefügt, da der Eintrag geschlossen wurde.');
+@define('COMMENT_NOT_ADDED_CLICK', 'Klicken Sie %shier, um zu den Kommentaren zurückzukehren%s und %shier, um das Fenster zu schließen%s.');
+@define('EMPTY_COMMENT', 'Ihr Kommentar war leer, bitte %sgehen Sie zurück%s und versuchen es erneut');
+@define('ENTRIES_FOR', 'Einträge für %s');
+@define('DOCUMENT_NOT_FOUND', 'Das Dokument %s wurde nicht gefunden.');
+@define('USERNAME', 'Benutzername');
+@define('PASSWORD', 'Passwort');
+@define('SERENDIPITY_INSTALLATION', 'Serendipity-Installation');
+@define('LEFT', 'links');
+@define('RIGHT', 'rechts');
+@define('HIDDEN', 'versteckt');
+@define('REMOVE_TICKED_PLUGINS', 'Markierte Plugins entfernen');
+@define('SAVE_CHANGES_TO_LAYOUT', 'Änderungen am Layout speichern');
+@define('COMMENTS_FROM', 'Kommentare von');
+@define('ERROR', 'Fehler');
+@define('ENTRY_SAVED', 'Der Eintrag wurde gespeichert');
+@define('DELETE_SURE', 'Soll #%s permanent gelöscht werden?');
+@define('NOT_REALLY', 'Nicht wirklich...');
+@define('DUMP_IT', 'Hinfort damit!');
+@define('RIP_ENTRY', 'Ruhe in Frieden, #%s');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Kategorie #%s wurde gelöscht. Alte Artikel in dieser Kategorie nach %s verschoben');
+@define('CATEGORY_DELETED', 'Kategorie #%s wurde gelöscht.');
+@define('INVALID_CATEGORY', 'Es wurde keine Kategorie zum Löschen gewählt.');
+@define('CATEGORY_SAVED', 'Kategorie gespeichert');
+@define('SELECT_TEMPLATE', 'Wählen Sie das Template für das Blog');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'Einträge konnten nicht importiert werden!');
+@define('YES', 'Ja');
+@define('NO', 'Nein');
+@define('USE_DEFAULT', 'Default');
+@define('CHECK_N_SAVE', 'Testen &amp; speichern');
+@define('DIRECTORY_WRITE_ERROR', 'Keine Schreibrechte für Verzeichnis %s. Bitte korrigieren');
+@define('DIRECTORY_CREATE_ERROR', 'Verzeichnis %s existiert nicht und konnte nicht erstellt werden. Bitte legen Sie es manuell an.');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; führen Sie <i>%s %s</i> aus!');
+@define('CANT_EXECUTE_BINARY', 'Kann die \'%s\'-Datei nicht ausführen');
+@define('FILE_WRITE_ERROR', 'Datei %s kann nicht geschrieben werden.');
+@define('FILE_CREATE_YOURSELF', ' Bitte die Datei manuell anlegen oder Dateirechte korrigieren.');
+@define('COPY_CODE_BELOW', '<br />* Kopieren Sie den folgenden Code in die Datei %s des %s Verzeichnisses:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Ersetzen Sie \'www\' mit dem User, als der der Webserver läuft. (z.B. \'nobody\')');
+@define('BROWSER_RELOAD', 'Danach aktualisieren Sie bitte diese Seite im Browser');
+@define('DIAGNOSTIC_ERROR', 'Bei der Einrichtung der Installation traten einige Fehler auf:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity ist noch nicht eingerichtet. Bitte jetzt <a href="%s">installieren</a>.');
+@define('INCLUDE_ERROR', 'Serendipity Fehler: Kann Datei %s nicht einbinden - wird beendet.');
+@define('DATABASE_ERROR', 'Serendipity Fehler: Kann keine Verbindung zur Datenbank herstellen - wird beendet.');
+@define('CREATE_DATABASE', 'Richte Datenbank ein...');
+@define('ATTEMPT_WRITE_FILE', 'Probiere die Datei %s zu erstellen...');
+@define('WRITTEN_N_SAVED', 'Konfiguration geschrieben und gesichert');
+@define('IMAGE_ALIGNMENT', 'Bildausrichtung');
+@define('ENTER_NEW_NAME', 'Bitte einen neuen Namen eingeben für: ');
+@define('RESIZING', 'Anpassen der Bildgröße');
+@define('RESIZE_DONE', 'Fertig (%s Bildgrößen angepaßt).');
+@define('DELETE_IMAGE_FAIL' , 'Kann Bild namens <b>%s</b> nicht löschen');
+@define('DELETE_THUMBNAIL', 'Vorschaubilder zu <b>%s</b> gelöscht');
+@define('FILE_NOT_FOUND', 'Die Datei namens <b>%s</b> kann nicht gefunden werden, vielleicht wurde diese schon gelöscht?');
+@define('ABORT_NOW', 'Abbrechen');
+@define('REMOTE_FILE_NOT_FOUND', 'Die Datei konnte auf dem Server nicht gefunden werden. Sind Sie sicher, dass die URL <b>%s</b> korrekt ist?');
+@define('FILE_FETCHED', '%s geladen als %s');
+@define('FILE_UPLOADED', 'Datei %s erfolgreich als %s hochgeladen');
+@define('WORD_OR', 'Oder');
+@define('SCALING_IMAGE', 'Ändere Größe von %s nach %s x %s px');
+@define('KEEP_PROPORTIONS', 'Proportionen beibehalten');
+@define('REALLY_SCALE_IMAGE', 'Bildgröße wirklich verändert? Kein zurück!');
+@define('TOGGLE_ALL', 'Alle Optionen ein-/ausblenden');
+@define('TOGGLE_OPTION', 'Option ein-/ausblenden');
+@define('SUBSCRIBE_TO_THIS_ENTRY', 'Bei Aktualisierung dieser Kommentare benachrichtigen');
+@define('UNSUBSCRIBE_OK', 'Sie (%s) erhalten nun keine weiteren Benachrichtigungen mehr.');
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'Benachrichtigung zu neuem Kommentar des Eintrags "%s"');
+@define('SUBSCRIPTION_MAIL', "Hallo %s,\n\nEin neuer Kommentar wurde dem Eintrag hinzugefügt, den Sie auf \"%s\" namens \"%s\" finden.\nDer Name des Autoren ist: %s\n\nSie können den Eintrag hier finden: %s\n\nSie können diese Benachrichtung mit folgender URL kündigen: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "Hallo %s,\n\nEin neues Trackback wurde dem Eintrag hinzugefügt, den Sie auf \"%s\" namens \"%s\" finden.\nDer Name des Autoren ist: %s\n\nSie können den Eintrag hier finden: %s\n\nSie können diese Benachrichtung mit folgender URL kündigen: %s\n");
+@define('SIGNATURE', "\n-- \n%s wird betrieben mit Serendipity.\nDas allerbeste Blog, Sie können es auch nutzen.\nWie das geht, sehen Sie auf <http://s9y.org>.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91 feed');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0 feed');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0 feed');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 Kommentar');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3 feed');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'Feld "managingEditor"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  'Feld "webMaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'Bild für den RSS feed');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', 'Breite des Bildes');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'Höhe des Bildes');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  'E-Mail Adresse des Webmasters, falls vorhanden. (leer: nicht verwenden) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', 'E-Mail Adresse des verantwortlichen Editors, falls vorhanden. (leer: nicht verwenden) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'URL für ein Bild im GIF/JPEG/PNG Format, falls vorhanden. (leer: Serendipity-Logo)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'in Pixeln, max. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'in Pixeln, max. 400');
+@define('SYNDICATION_PLUGIN_TTL', 'Feld "ttl" (time-to-live)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'Anzahl der Minuten, nachdem das Blog von fremden Seiten nicht mehr gecached werden sollte (leer: nicht verwenden) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'Feld "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', 'Soll das "pubDate"-Feld für den RSS-Kanal eingebettet werden, um das Datum des letzten Eintrags zu enthalten?');
+@define('CONTENT', 'Inhalt');
+@define('TYPE', 'Typ');
+@define('DRAFT', 'Entwurf');
+@define('PUBLISH', 'Veröffentlichung');
+@define('PREVIEW', 'Vorschau');
+@define('DATE', 'Datum');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', 'Warnung: Das Datum, welches Sie für den Artikel angegeben haben ist ungültig. Es muss dem Format JJJJ-MM-TT SS:MM entsprechen.');
+@define('CATEGORY_PLUGIN_DESC', 'Zeigt eine Liste der Kategorien');
+@define('ALL_AUTHORS', 'Alle Autoren');
+@define('CATEGORIES_TO_FETCH', 'Quelle der Kategorien');
+@define('CATEGORIES_TO_FETCH_DESC', 'Kategorien welcher Autoren einbeziehen?');
+@define('PAGE_BROWSE_ENTRIES', 'Seite %s von %s, insgesamt %s Einträge');
+@define('PREVIOUS_PAGE', 'vorige Seite');
+@define('NEXT_PAGE', 'nächste Seite');
+@define('ALL_CATEGORIES', 'Alle Kategorien');
+@define('DO_MARKUP', 'Textformatierung(en) durchführen');
+@define('AUTOMATIC_LOGIN', 'Daten speichern');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'Datumsformat');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'Das Datumsformat des Eintrages, mithilfe von PHPs strftime() Variablen. (Standard: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'Die Templatedatei konnte nicht geöffnet werden, bitte die Serendipity-Version aktualisieren!');
+@define('ADVANCED_OPTIONS', 'Erweiterte Optionen');
+@define('EDIT_ENTRY', 'Eintrag bearbeiten');
+@define('HTACCESS_ERROR', 'Um die Webserverkonfiguration zu testen benötigt Serendipity die Möglichkeit, die Datei ".htaccess" zu erstellen. Dies war aufgrund von Rechteproblemen nicht möglich. Bitte passen Sie die Rechte wie folgt an: <br />&nbsp;&nbsp;%s<br />und laden Sie diese Seite neu.');
+@define('SIDEBAR_PLUGINS', 'Seitenleisten Plugins');
+@define('EVENT_PLUGINS', 'Ereignis Plugins');
+@define('SYNCING', 'Synchronisiere Datenbank mit Bilder-Ordner');
+@define('SYNC_DONE', 'Fertig (%s Bilder synchronisiert).');
+@define('SORT_ORDER', 'Sortierung');
+@define('SORT_ORDER_NAME', 'Dateiname');
+@define('SORT_ORDER_EXTENSION', 'Dateiendung');
+@define('SORT_ORDER_SIZE', 'Dateigröße');
+@define('SORT_ORDER_WIDTH', 'Bildbreite');
+@define('SORT_ORDER_HEIGHT', 'Bildhöhe');
+@define('SORT_ORDER_DATE', 'Upload-Datum');
+@define('SORT_ORDER_ASC', 'Aufsteigend');
+@define('SORT_ORDER_DESC', 'Absteigend');
+@define('THUMBNAIL_SHORT', 'Vorsch.');
+@define('ORIGINAL_SHORT', 'Orig.');
+@define('APPLY_MARKUP_TO', 'Textformatierung auf %s anwenden');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'Anfang der Woche');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity hat entdeckt, dass derzeit Version %s verwendet wird. Jedoch wurde Version %s installiert, daher müssten Sie die <a href="%s">Installation aktualisieren</a>!');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'Willkommen beim Serendipity Aktualisierungs-Agenten');
+@define('SERENDIPITY_UPGRADER_PURPOSE', 'Ich möchte Ihnen gerne beim Aktualisieren der Serendipity %s Installation helfen.');
+@define('SERENDIPITY_UPGRADER_WHY', 'Diese Seite erscheint, da gerade Serendipity %s installiert wurde, aber die Datenbank noch nicht an diese Version angepasst wurde.');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'Datenbank-Aktualisierungen (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'Die folgenden .sql Dateien wurden gefunden und müssen nun ausgeführt werden, bevor Serendipity wieder wie gewohnt funktioniert.');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  'Versionsabhängige Funktionen');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', 'Keine versionsabhängigen Funktionen gefunden');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', 'Soll ich die aufgeführten Funktionen ausführen?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'Nein, das werde ich manuell erledigen');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'Ja, bitte ausführen');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'Es müssen keine Aktualisierungen ausgeführt werden');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', 'Serendipity wurde an die neue Version angepasst');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'Sie haben den automatischen Aktualisierungsvorgang ignoriert. Bitte stellen Sie sicher, dass die Datenbank anhand der .sql Dateien aktualisiert wird und die geplanten Funktionen aufgerufen werden.');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'Die Serendipity-Installation ist nun auf die Version %s aktualisiert.');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', 'Zurück zum %sBlog%s');
+@define('MANAGE_USERS', 'Benutzerverwaltung');
+@define('CREATE_NEW_USER', 'Einen neuen Benutzer anlegen');
+@define('CREATE_NOT_AUTHORIZED', 'Sie können keine Benutzer mit demselben Userlevel wie Ihrem eigenen bearbeiten');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'Sie können keine Benutzer mit einem höheren Benutzerlevel als Ihrem anlegen');
+@define('CREATED_USER', 'Der neue Benutzer %s wurde angelegt');
+@define('MODIFIED_USER', 'Die Eigenschaften von Benutzer %s wurden geändert');
+@define('USER_LEVEL', 'Userlevel');
+@define('DELETE_USER', 'Sie wollen den Benutzer #%d %s löschen. Sind sie sicher? Dadurch werden seine Artikel nicht mehr auf der Oberfläche angezeigt.');
+@define('DELETED_USER', 'Benutzer #%d %s gelöscht.');
+@define('LIMIT_TO_NUMBER', 'Wieviele Elemente sollen angezeigt werden?');
+@define('ENTRIES_PER_PAGE', 'Artikel pro Seite');
+@define('DIRECTORIES_AVAILABLE', 'In der Liste der verfügbaren Unterverzeichnisse kann durch einen Klick auf einen Verzeichnisnamen ein neuer Ordner unterhalb des gewählten erstellt werden.');
+@define('ALL_DIRECTORIES', 'alle Verzeichnisse');
+@define('MANAGE_DIRECTORIES', 'Verzeichnisse verwalten');
+@define('DIRECTORY_CREATED', 'Verzeichnis <strong>%s</strong> wurde angelegt.');
+@define('PARENT_DIRECTORY', 'Stammverzeichnis');
+@define('CONFIRM_DELETE_DIRECTORY', 'Wirklich alle Inhalte von Verzeichnis %s löschen?');
+@define('ERROR_NO_DIRECTORY', 'Fehler: Verzeichnis %s existiert nicht.');
+@define('CHECKING_DIRECTORY', 'Prüfe Dateien im Verzeichnis %s');
+@define('DELETING_FILE', 'Lösche Datei %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', 'Konnte das Verzeichnis nicht löschen, da noch Dateien vorhanden sind. Bitte die "Alle Dateien löschen"-Auswahlbox anklicken, falls diese Dateien trotzdem gelöscht werden sollen. Die noch vorhandenen Dateien sind:');
+@define('DIRECTORY_DELETE_FAILED', 'Das Löschen des Verzeichnisses %s ist fehlgeschlagen. Bitte Verzeichnisrechte oder vorige Meldungen überprüfen.');
+@define('DIRECTORY_DELETE_SUCCESS', 'Verzeichnis %s erfolgreich gelöscht.');
+@define('SKIPPING_FILE_EXTENSION', 'Überspringe Datei: Fehlende Dateiendung von %s.');
+@define('SKIPPING_FILE_UNREADABLE', 'Überspringe Datei: %s nicht lesbar.');
+@define('FOUND_FILE', 'Neue/Geänderte Datei %s gefunden.');
+@define('ALREADY_SUBCATEGORY', '%s ist bereits eine Unterkategorie von %s.');
+@define('PARENT_CATEGORY', 'Übergeordnete Kategorie');
+@define('IN_REPLY_TO', 'Antwort zu');
+@define('TOP_LEVEL', 'Ursprung');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s feed');
+@define('PERMISSIONS', 'Rechte');
+@define('XML_IMAGE_TO_DISPLAY', 'XML-Button');
+@define('XML_IMAGE_TO_DISPLAY_DESC','Bilddatei um ein Icon für XML-Feeds darzustellen. Für das Standardbild leer lassen oder \'none\' zum deaktivieren.');
+@define('SETTINGS_SAVED_AT', 'Die neuen Einstellungen wurden um %s gespeichert.');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', 'Datenbankeinstellungen');
+@define('INSTALL_CAT_DB_DESC', 'Konfigurieren Sie hier die Datenbank. Serendipity benötigt die Daten, um lauffähig zu sein.');
+@define('INSTALL_DBTYPE', 'Datenbanktyp');
+@define('INSTALL_DBTYPE_DESC', 'Datenbanktyp');
+@define('INSTALL_DBHOST', 'Datenbank Servername');
+@define('INSTALL_DBHOST_DESC', 'Datenbank Servername');
+@define('INSTALL_DBUSER', 'Datenbank Username');
+@define('INSTALL_DBUSER_DESC', 'Datenbank Username');
+@define('INSTALL_DBPASS', 'Datenbank Passwort');
+@define('INSTALL_DBPASS_DESC', 'Datenbank Passwort');
+@define('INSTALL_DBNAME', 'Datenbankname');
+@define('INSTALL_DBNAME_DESC', 'Name der Datenbank');
+@define('INSTALL_DBPREFIX', 'Datenbank-Präfix');
+@define('INSTALL_DBPREFIX_DESC', 'Präfix für Tabellennamen, z.B. serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', 'Pfade');
+@define('INSTALL_CAT_PATHS_DESC', 'Zahlreiche Pfade zu unterschiedlichen wichtigen Verzeichnissen und Dateien. Unbedingt auf abschließenden Schrägstrich nach Pfaden achten!');
+@define('INSTALL_FULLPATH', 'Voller Pfad');
+@define('INSTALL_FULLPATH_DESC', 'Der volle und absolute Pfad zur Serendipity Installation.');
+@define('INSTALL_UPLOADPATH', 'Upload-Pfad');
+@define('INSTALL_UPLOADPATH_DESC', 'Alle Dateien werden hierhin hochgeladen. Relativ zum vollen Pfad - üblicherweise \'uploads/\'');
+@define('INSTALL_RELPATH', 'Relativer HTTP-Pfad');
+@define('INSTALL_RELPATH_DESC', 'Der HTTP-Pfad zu Serendipity für den Browser, üblicherweise \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', 'Relativer Template-Pfad');
+@define('INSTALL_RELTEMPLPATH_DESC', 'Der Pfad zum Verzeichnis, der die Templates enthält - Relativ zum HTTP-Pfad');
+@define('INSTALL_RELUPLOADPATH', 'Relativer Upload-Pfad');
+@define('INSTALL_RELUPLOADPATH_DESC', 'Der Pfad zum Uploadverzeichnis für den Browser - Relativ zum HTTP-Pfad');
+@define('INSTALL_URL', 'URL zum Blog');
+@define('INSTALL_URL_DESC', 'Stamm-URL zur Serendipity-Installation');
+@define('INSTALL_INDEXFILE', 'Index-Datei');
+@define('INSTALL_INDEXFILE_DESC', 'Welche Datei wird als Indexdatei verwendet (index.php)');
+
+/* Generel settings */
+@define('INSTALL_CAT_SETTINGS', 'Generelle Einstellungen');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Stellt die Grundeigenschaften von Serendipity ein');
+@define('INSTALL_USERNAME', 'Admin Username');
+@define('INSTALL_USERNAME_DESC', 'Username für den Administrator-Zugang');
+@define('INSTALL_PASSWORD', 'Admin Passwort');
+@define('INSTALL_PASSWORD_DESC', 'Passwort für den Administrator-Zugang');
+@define('INSTALL_EMAIL', 'Admin E-Mail');
+@define('INSTALL_EMAIL_DESC', 'E-Mail des Administrators');
+@define('INSTALL_SENDMAIL', 'Sende E-Mails zum Admin?');
+@define('INSTALL_SENDMAIL_DESC', 'Soll der Administrator E-Mails erhalten, wenn Kommentare zum Blog geschrieben werden?');
+@define('INSTALL_SUBSCRIBE', 'Abonnieren von Einträgen erlauben?');
+@define('INSTALL_SUBSCRIBE_DESC', 'Soll es den Besuchern des Blogs möglich sein, einen Eintrag zu abonnieren und so alle neuen Kommentare dazu per E-Mail erhalten?');
+@define('INSTALL_BLOGNAME', 'Blog Titel');
+@define('INSTALL_BLOGNAME_DESC', 'Der Titel des Blogs');
+@define('INSTALL_BLOGDESC', 'Blog Beschreibung');
+@define('INSTALL_BLOGDESC_DESC', 'Die Beschreibung des Blogs');
+@define('INSTALL_LANG', 'Sprache');
+@define('INSTALL_LANG_DESC', 'Wählen Sie die Sprache des Blogs');
+
+/* Appearance and options */
+@define('INSTALL_CAT_DISPLAY', 'Design und Optionen');
+@define('INSTALL_CAT_DISPLAY_DESC', 'Legt fest wie Serendipity aussieht');
+@define('INSTALL_WYSIWYG', 'Grafischen WYSIWYG-Editor verwenden');
+@define('INSTALL_WYSIWYG_DESC', 'Soll der grafische WYSIWYG-Editor verwendet werden? (Funktioniert im  IE5+, größenteils Mozilla 1.3+)');
+@define('INSTALL_XHTML11', 'XHTML1.1 Standard verwenden');
+@define('INSTALL_XHTML11_DESC', 'Soll der XHTML 1.1 Standard verwendet werden? (führt zu gültigem Code aber kann bei älteren Browsern Schwierigkeiten erzeugen)');
+@define('INSTALL_POPUP', 'Popups für Kommentare, Trackbacks usw. verwenden?');
+@define('INSTALL_POPUP_DESC', 'Sollen die Links zu den Kommentaren, Trackbacks etc. mit Popups geöffnet werden?');
+@define('INSTALL_EMBED', 'Eingebettete Nutzung von Serendipity aktivieren?');
+@define('INSTALL_EMBED_DESC', 'Falls Serendipity innerhalb einer normalen Seite eingebettet werden soll, aktivieren Sie diese Option. Serendipity stellt dann nur Inhalte dar, und Sie können sich um Header und Footer kümmern. Lesen Sie die Datei README für weitere Informationen.');
+@define('INSTALL_TOP_AS_LINKS', 'Top Exits/Referrers als Link anzeigen?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"Nein": Exit/Referer-URLs werden als Text angezeigt, um Googlespam zu verhindern. "Ja": Exit/Referer-URLs werden als Hyperlinks angezeigt. "Default": Die Einstellung aus der globalen Konfiguration wird übernommen (empfohlen).');
+@define('INSTALL_BLOCKREF', 'Geblockte Referer');
+@define('INSTALL_BLOCKREF_DESC', 'Sollen spezielle Hosts aus der Referrer-Liste gesperrt werden? Hostnamen getrennt mit ";" eingeben. Jeder Hostname wird als Teilstring überprüft, so dass "goo" sowohl "google.com" als auch "googlegroups.com" sperren würde.');
+@define('INSTALL_REWRITE', 'URL-Formung');
+@define('INSTALL_REWRITE_DESC', 'Wählen Sie die Methode zur Erzeugung der URLs. Wenn diese aktiviert werden, können sprechende Namen für jeden Artikel verwendet werden und somit besser von Suchmaschinen indiziert Der Webserver muss entweder mod_rewrite oder die "AllowOverride All"-Direktive unterstützen. Der Standardwert wird automagisch bestimmt');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', 'Bildkonvertierung');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'Wie soll Serendipity Bilder handhaben');
+@define('INSTALL_IMAGEMAGICK', 'Imagemagick zur Skalierung verwenden');
+@define('INSTALL_IMAGEMAGICK_DESC', 'Ist ImageMagick installiert? Verwendet ansonsten die GDLib.');
+@define('INSTALL_IMAGEMAGICKPATH', 'Pfad zur convert ImageMagick-Datei');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'Voller Pfad und Name zur Image-Magick Datei');
+@define('INSTALL_THUMBSUFFIX', 'Thumbnail-Endung');
+@define('INSTALL_THUMBSUFFIX_DESC', 'Thumbnails werden nach dem Schema originalname.Suffix.erweiterung benannt.');
+@define('INSTALL_THUMBWIDTH', 'Thumbnailgröße');
+@define('INSTALL_THUMBWIDTH_DESC', 'Maximale Breite/Höhe der automatisch erzeugten Thumbnails');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', 'Persönliche Einstellungen');
+@define('USERCONF_CAT_PERSONAL_DESC', 'Einstellungen des eigenen Accounts');
+@define('USERCONF_USERNAME', 'Username');
+@define('USERCONF_USERNAME_DESC', 'Ihr Username');
+@define('USERCONF_PASSWORD', 'Passwort');
+@define('USERCONF_PASSWORD_DESC', 'Ihr Passwort');
+@define('USERCONF_EMAIL', 'E-Mail');
+@define('USERCONF_EMAIL_DESC', 'Ihre E-Mail Adresse');
+@define('USERCONF_SENDCOMMENTS', 'Über Kommentare benachrichtigen?');
+@define('USERCONF_SENDCOMMENTS_DESC', 'Wollen Sie eine E-Mail erhalten, sobald ein neuer Kommentar zu Ihrem Eintrag geschrieben wurde?');
+@define('USERCONF_SENDTRACKBACKS', 'Über Trackbacks benachrichtigen?');
+@define('USERCONF_SENDTRACKBACKS_DESC', 'Wollen Sie eine E-Mail erhalten, sobald ein neues Trackback zu Ihrem Eintrag geschrieben wurde?');
+@define('USERCONF_ALLOWPUBLISH', 'Rechte: Einträge veröffentlichen?');
+@define('USERCONF_ALLOWPUBLISH_DESC', 'Darf Einträge veröffentlichen?');
+@define('SUCCESS', 'Erfolgreich beendet');
+@define('POWERED_BY_SHOW_TEXT', 'Zeige "Serendipity" als Text');
+@define('POWERED_BY_SHOW_TEXT_DESC', 'Zeigt den Text "Serendipity Blog" an');
+@define('POWERED_BY_SHOW_IMAGE', 'Zeige "Serendipity" als Logo');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Stellt das Serendipity-Logo dar');
+@define('PLUGIN_ITEM_DISPLAY', 'Wo soll dieses Plugin angezeigt werden?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'Nur Artikel-Detailansicht');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'Nur Artikelübersicht');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'Überall');
+@define('RSS_IMPORT_CATEGORY', 'Diese Kategorie für nicht zugeordnete importierte Einträge verwenden');
+@define('ERROR_UNKNOWN_NOUPLOAD', 'Ein Fehler trat beim Dateiupload auf. Vielleicht ist die Datei größer als durch die Server-Konfiguration zugelassen. Bitte mit Ihrem ISP absprechen oder die php.ini datei bearbeiten um größere Uploads zuzulassen.');
+@define('COMMENTS_WILL_BE_MODERATED', 'Kommentare werden erst nach redaktioneller Prüfung freigeschaltet.');
+@define('YOU_HAVE_THESE_OPTIONS', 'Folgende Möglichkeiten stehen zur Verfügung:');
+@define('THIS_COMMENT_NEEDS_REVIEW', 'Hinweis: Dieser Kommentar wird ohne Bewilligung nicht dargestellt');
+@define('DELETE_COMMENT', 'Kommentar löschen');
+@define('APPROVE_COMMENT', 'Kommentar bewilligen');
+@define('REQUIRES_REVIEW', 'Bewilligung notwendig');
+@define('COMMENT_APPROVED', 'Kommentar #%s wurde erfolgreich bewilligt');
+@define('COMMENT_DELETED', 'Kommentar #%s wurde erfolgreich gelöscht');
+@define('VIEW', 'Anzeigen');
+@define('COMMENT_ALREADY_APPROVED', 'Kommentar #%s wurde bereits bewilligt');
+@define('COMMENT_EDITED', 'Der gewählte Kommentare wurde bearbeitet');
+@define('HIDE', 'Ausblenden');
+@define('VIEW_EXTENDED_ENTRY', '"%s" vollständig lesen');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'Dieser Link ist nicht aktiv. Er enthält die Tracback-URI zu diesem Eintrag. Sie können diese URI benutzen um Ping- und Trackbacks von Ihrem eigenen Blog zu diesem Eintrag zu schicken. Um den Link zu kopieren, führen Sie einen Rechtsklick aus und wählen "Verknüpfung kopieren" im Internet Explorer oder "Linkadresse kopieren" in Mozilla.');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'Warnung: Dieses Trackback wird ohne Bewilligung nicht dargestellt');
+@define('DELETE_TRACKBACK', 'Trackback löschen');
+@define('APPROVE_TRACKBACK', 'Trackback bewilligen');
+@define('TRACKBACK_APPROVED', 'Trackback #%s wurde erfolgreich bewilligt');
+@define('TRACKBACK_DELETED', 'Trackback #%s wurde erfolgreich gelöscht');
+@define('COMMENTS_MODERATE', 'Kommentare und Trackbacks dieses Eintrags werden moderiert');
+@define('PLUGIN_SUPERUSER_HTTPS', 'https zum Login verwenden');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'Erstellt eine https-URL als Login-Link zum Blog. Der Webserver muss dies unterstützen!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'Externe Links klickbar?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"Nein": Ungeprüfte externe Links (Top Exits, Top Referer, Kommentare) werden unterdrückt/als Text angezeigt, um Googlespam zu verhindern (empfohlen). "Ja": Externe Links werden als Hyperlinks angezeigt. Diese Einstellung kann in den einzelnen Plugins überschrieben werden.');
+@define('PAGE_BROWSE_COMMENTS', 'Seite %s von %s, %s Kommentare insgesamt');
+@define('FILTERS', 'Filter');
+@define('FIND_ENTRIES', 'Einträge durchsuchen');
+@define('FIND_COMMENTS', 'Kommentare durchsuchen');
+@define('FIND_MEDIA', 'Mediendaten durchsuchen');
+@define('FILTER_DIRECTORY', 'Verzeichnis');
+@define('SORT_BY', 'Sortieren nach');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'Kein Trackback: Konnte Verbindung zu %s auf Port %d nicht herstellen');
+@define('MEDIA', 'Mediendatenbank');
+@define('MEDIA_LIBRARY', 'Mediendatenbank');
+@define('ADD_MEDIA', 'Mediendaten hinzufügen');
+@define('ENTER_MEDIA_URL', 'URL zum Download angeben:');
+@define('ENTER_MEDIA_UPLOAD', 'Datei zum Hochladen angeben:');
+@define('SAVE_FILE_AS', 'Datei speichern mit Name:');
+@define('STORE_IN_DIRECTORY', 'In diesem Verzeichnis ablegen: ');
+@define('MEDIA_RENAME', 'Datei umbenennen');
+@define('IMAGE_RESIZE', 'Dateiausmaße ändern');
+@define('MEDIA_DELETE', 'Datei löschen');
+@define('FILES_PER_PAGE', 'Dateien pro Seite');
+@define('CLICK_FILE_TO_INSERT', 'Auf eine Datei klicken um diese einzufügen:');
+@define('SELECT_FILE', 'Bitte wählen Sie eine Datei');
+@define('MEDIA_FULLSIZE', 'Vollbild');
+@define('CALENDAR_BOW_DESC', 'Welcher Tag gibt den Wochenanfang an? Standard ist Montag.');
+@define('SUPERUSER', 'Verwaltung des Blog');
+@define('ALLOWS_YOU_BLAHBLAH', 'Zeigt einen Link zur Verwaltung des Blogs in der Seitenleiste an');
+@define('CALENDAR', 'Kalender');
+@define('SUPERUSER_OPEN_ADMIN', 'Zur Verwaltung des Blog');
+@define('SUPERUSER_OPEN_LOGIN', 'Login zum Blog');
+@define('INVERT_SELECTIONS', 'Auswahl umkehren');
+@define('COMMENTS_DELETE_CONFIRM', 'Sollen die markierten Kommentare gelöscht werden?');
+@define('COMMENT_DELETE_CONFIRM', 'Soll das Kommentar #%d von %s wirklich gelöscht werden?');
+@define('DELETE_SELECTED_COMMENTS', 'Markierte Kommentare löschen');
+@define('VIEW_COMMENT', 'Kommentar ansehen');
+@define('VIEW_ENTRY', 'Eintrag ansehen');
+@define('DELETE_FILE', 'Datei namens <b>%s</b> gelöscht');
+@define('ABOUT_TO_DELETE_FILE', 'Sie sind dabei die Datei <b>%s</b> zu löschen.<br />Wenn Sie die Datei in einem Ihrer Einträge verwenden, wird das Löschen Lücken erzeugen.<br />Soll trotzdem fortgefahren werden?<br /><br />');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'Ein neues Trackback für den Blog-Eintrag namens "%s" wurde empfangen.');
+@define('LOGIN', 'Login');
+@define('TRACKBACK_SENDING', 'Sende Trackback zu URI %s...');
+@define('TRACKBACK_SENT', 'Trackback erfolgreich');
+@define('TRACKBACK_FAILED', 'Trackback failed: %s');
+@define('TRACKBACK_NOT_FOUND', 'Keine Trackback-URI gefunden.');
+@define('TRACKBACK_URI_MISMATCH', 'Die automatisch erkannte Trackback-URI gleicht nicht der angegebenen URI.');
+@define('TRACKBACK_CHECKING', 'Überprüfe <u>%s</u> auf mögliche Trackbacks...');
+@define('TRACKBACK_NO_DATA', 'URI enthielt keine Daten');
+@define('TRACKBACK_SIZE', 'URI ist größer als die erlaubten %s Bytes.');
+@define('VIEWMODE_THREADED', 'Als Baumstruktur anzeigen');
+@define('COMMENTS_VIEWMODE_THREADED', 'Verschachtelt');
+@define('COMMENTS_VIEWMODE_LINEAR', 'Linear');
+@define('DISPLAY_COMMENTS_AS', 'Ansicht der Kommentare: ');
+@define('ADD_MEDIA_BLAHBLAH', '<b>Bild/Datei zur Sammlung hinzufügen:</b><p>Hier können Sie eine Datei (z.B. ein Bild) hochladen, oder mitteilen, von wo es geladen werden soll! Wenn das passende Bild fehlt, einfach bei Google danach suchen. Probieren Sie mal <a href="http://images.google.de" target="_blank">Googles Bildsuche</a>, die Resultate sind oft brauchbar, aber auf jeden Fall witzig :). Aber vorsicht: Die meisten Bilder sind urheberrechtlich geschützt, also vorher fragen um Ärger zu vermeiden.<p><b>Methode wählen:</b><br>');
+@define('COMMENTS_FILTER_SHOW', 'Zeige');
+@define('COMMENTS_FILTER_ALL', 'Alle');
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'Nur bewilligte');
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'Zu bewilligende');
+@define('RSS_IMPORT_BODYONLY', 'Füge den gesamten importierten Text in das einzelne "Text"-Feld ein. Verhindert die Aufteilung in den "Erweiterten Eintrag"-Bereich.');
+@define('SYNDICATION_PLUGIN_FULLFEED', 'Volle Einträge mit erweitertem Text im RSS-Feed einbinden');
+@define('MT_DATA_FILE', 'Movable Type Datensätze');
+@define('FORCE', 'Erzwingen');
+@define('CREATE_AUTHOR', 'Erstelle Autoren \'%s\'.');
+@define('CREATE_CATEGORY', 'Erstelle Kategorie \'%s\'.');
+@define('MYSQL_REQUIRED', 'Die MySQL-Extension muss installiert sein, um diese Aktion durchzuführen.');
+@define('COULDNT_CONNECT', 'Verbindung zu MySQL-Datenbank %s fehlgeschlagen.');
+@define('COULDNT_SELECT_DB', 'Datenbank %s konnte nicht ausgewählt werden.');
+@define('COULDNT_SELECT_USER_INFO', 'Die Benutzerinformationen von %s konnten nicht gelesen werden.');
+@define('COULDNT_SELECT_CATEGORY_INFO', 'Die Kategorien von %s konnten nicht gelesen werden.');
+@define('COULDNT_SELECT_ENTRY_INFO', 'Die Einträge von %s konnten nicht gelesen werden.');
+@define('COULDNT_SELECT_COMMENT_INFO', 'Die Kommentare von %s konnten nicht gelesen werden.');
+@define('WEEK', 'Woche');
+@define('WEEKS', 'Wochen');
+@define('MONTHS', 'Monate');
+@define('DAYS', 'Tage');
+@define('ARCHIVE_FREQUENCY', 'Frequenz der Einträge des Kalenders');
+@define('ARCHIVE_FREQUENCY_DESC', 'Der Kalenderinterval, der zwischen den Einträgen verwendet werden soll');
+@define('ARCHIVE_COUNT', 'Anzahl von Einträgen im Archiv');
+@define('ARCHIVE_COUNT_DESC', 'Die Anzahl der angezeigten Monate, Wochen oder Tagen');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'Es folgt eine Liste installierter Plugins');
+@define('SIDEBAR_PLUGIN', 'Seitenleisten-Plugin');
+@define('EVENT_PLUGIN', 'Ereignis-Plugin');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'Hier klicken um %s zu installieren');
+@define('VERSION', 'version');
+@define('INSTALL', 'Installieren');
+@define('ALREADY_INSTALLED', 'Bereits installiert');
+@define('SELECT_A_PLUGIN_TO_ADD', 'Plugin zur Installation wählen');
+@define('INSTALL_OFFSET', 'Server Zeitunterschied');
+@define('STICKY_POSTINGS', 'Dauerhafte Einträge');
+@define('INSTALL_FETCHLIMIT', 'Anzahl der Artikel auf der Startseite');
+@define('INSTALL_FETCHLIMIT_DESC', 'Wieviele Artikel sollen auf jeder Seite des Blogs angezeigt werden');
+@define('IMPORT_ENTRIES', 'Daten importieren');
+@define('EXPORT_ENTRIES', 'Einträge exportieren');
+@define('IMPORT_WELCOME', 'Willkommen im Serendipity Import-Bereich');
+@define('IMPORT_WHAT_CAN', 'Hier können Daten von anderen Weblog-Installationen importiert werde');
+@define('IMPORT_SELECT', 'Bitte die Art der Software auswählen, von der die Daten importiert werden sollen');
+@define('IMPORT_PLEASE_ENTER', 'Bitte die folgenden Daten eintrage');
+@define('IMPORT_NOW', 'Jetzt importieren!');
+@define('IMPORT_STARTING', 'Starte Import-Vorgang...');
+@define('IMPORT_FAILED', 'Import fehlgeschlagen');
+@define('IMPORT_DONE', 'Import erfolgreich abgeschlossen');
+@define('IMPORT_WEBLOG_APP', 'Weblog-Software');
+@define('IMPORT_NOTES', 'Hinweis');
+@define('EXPORT_FEED', 'Vollständigen RSS-Feed exportieren');
+@define('STATUS', 'Status nach dem Importieren');
+@define('IMPORT_GENERIC_RSS', 'Allgemeiner RSS-Import');
+@define('ACTIVATE_AUTODISCOVERY', 'Trackbacks an erkannte Links im Eintrag senden');
+@define('WELCOME_TO_ADMIN', 'Willkommen zur Serendipity Administrationsoberfläche.');
+@define('PLEASE_ENTER_CREDENTIALS', 'Bitte geben Sie die Zugangsdaten ein.');
+@define('ADMIN_FOOTER_POWERED_BY', 'Betrieben mit Serendipity %s und PHP %s');
+@define('INSTALL_USEGZIP', 'GZIP Kompression verwenden');
+@define('INSTALL_USEGZIP_DESC', 'Um die Auslieferung von Seiten zu beschleunigen, können diese vorher GZIP komprimiert werden, sofern der Browser des Betrachters dies unterstützt. Diese Einstellung ist empfohlen.');
+@define('INSTALL_SHOWFUTURE', 'Zukünftige Einträge zeigen');
+@define('INSTALL_SHOWFUTURE_DESC', 'Falls aktiviert, werden Einträge deren Datum in der Zukunft liegt angezeigt. Standardmäßig werden solche Einträge versteckt und erst angezeigt, wenn das eingetragene Datum erreicht wird.');
+@define('INSTALL_DBPERSISTENT', 'Persistente Verbindungen nutzen');
+@define('INSTALL_DBPERSISTENT_DESC', 'Aktiviert die nutzung einer persistenten Datenbankverbindung. Mehr dazu in der <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">PHP-Dokumentation</a>. Üblicherweise wird diese Einstellung nicht empfohlen.');
+@define('NO_IMAGES_FOUND', 'Keine Bilder gefunden');
+@define('PERSONAL_SETTINGS', 'Eigene Einstellungen');
+@define('REFERER', 'Referer');
+@define('NOT_FOUND', 'Nicht gefunden');
+@define('WRITABLE', 'Beschreibbar');
+@define('NOT_WRITABLE', 'Nicht beschreibbar');
+@define('PROBLEM_DIAGNOSTIC', 'Da ein Fehler bei der Systemdiagnose auftrat, muss dieser erst behoben werden bevor die Installation weitergeführt werden kann.');
+@define('SELECT_INSTALLATION_TYPE', 'Bitte die Installationsart wählen');
+@define('WELCOME_TO_INSTALLATION', 'Willkommen bei der Installation von Serendipity');
+@define('FIRST_WE_TAKE_A_LOOK', 'Als Erstes wird eine Systemdiagnose durchgeführt, um etwaigen Inkompatibiläten oder fehlenden Modulen vorzubeugen.');
+@define('ERRORS_ARE_DISPLAYED_IN', 'Fehler werden in %s, Empfehlungen in %s und erfolgreiche Meldungen in %s dargestellt.');
+@define('RED', 'rot');
+@define('YELLOW', 'gelb');
+@define('GREEN', 'grün');
+@define('PRE_INSTALLATION_REPORT', 'Systemdiagnose von Serendipity v.%s');
+@define('RECOMMENDED', 'Empfohlen');
+@define('ACTUAL', 'Vorhanden');
+@define('PHPINI_CONFIGURATION', 'php.ini Konfiguration');
+@define('PHP_INSTALLATION', 'PHP Installation');
+@define('THEY_DO', 'Positiv');
+@define('THEY_DONT', 'Negativ');
+@define('SIMPLE_INSTALLATION', 'Einfache Installation');
+@define('EXPERT_INSTALLATION', 'Fortgeschrittene Installation');
+@define('COMPLETE_INSTALLATION', 'Vollständige Installation');
+@define('WONT_INSTALL_DB_AGAIN', 'werde Datenbank nicht erneut erzeugen');
+@define('CHECK_DATABASE_EXISTS', 'Prüfe ob Datenbank und Tabellen bereits bestehen');
+@define('CREATING_PRIMARY_AUTHOR', 'Erstelle Hauptbenutzer \'%s\'');
+@define('SETTING_DEFAULT_TEMPLATE', 'Setze Standard-Template');
+@define('INSTALLING_DEFAULT_PLUGINS', 'Installiere Standard-Plugins');
+@define('SERENDIPITY_INSTALLED', 'Serendipity wurde erfolgreich installiert');
+@define('VISIT_BLOG_HERE', 'Besuchen Sie Ihr neues Blog hier');
+@define('THANK_YOU_FOR_CHOOSING', 'Danke, dass Sie Serendipity gewählt haben.');
+@define('ERROR_DETECTED_IN_INSTALL', 'Bei der Installation trat ein Fehler auf');
+@define('OPERATING_SYSTEM', 'Betriebssystem');
+@define('WEBSERVER_SAPI', 'Webserver SAPI');
+@define('TEMPLATE_SET', '\'%s\' wurde als Template gewählt');
+@define('SEARCH_ERROR', 'Die Suche konnte nicht wie gewünscht ausgeführt werden. Hinweis für den Administrator dieses Blogs: Der Fehler kann durch fehlende Index-Schlüssel der Datenbank verursacht werden. Auf MySQL-Systemen muss der Datenbankbenutzer-Account in der Lage sein, Index-Schlüssel zu erstellen und folgende Abfrage auszuführen: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> Die genaue Fehlermeldung der Datenbank bei der Suche lautete: <pre>%s</pre>');
+@define('EDIT_THIS_CAT', 'Bearbeite "%s"');
+@define('CATEGORY_REMAINING', 'Diese Kategorie löschen und Einträge darin in folgende Kategorie verschieben');
+@define('CATEGORY_INDEX', 'Es folgt eine Liste von verfügbaren Kategorien');
+@define('NO_CATEGORIES', 'Keine Kategorien');
+@define('RESET_DATE', 'Datum zurücksetzen');
+@define('RESET_DATE_DESC', 'Hier klicken um das Datum auf die aktuelle Systemzeit zu setzen');
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Zugriffsrechte können durch folgenden Shell-Befehl (oder auch mittels FTP-Client) geändert werden: `<em>%s</em>` mit dem Namen des unbeschreibbaren Verzeichnisses.');
+@define('WARNING_TEMPLATE_DEPRECATED', 'Hinweis: Das aktuelle Template verwendet eine ältere Methode der HTML-Erzeugung. Falls möglich bitte das Template auf die Nutzung von Smarty optimieren.');
+@define('ENTRY_PUBLISHED_FUTURE', 'Dieser Artikel ist noch nicht veröffentlicht.');
+@define('ENTRIES_BY', 'Einträge von %s');
+@define('PREVIOUS', 'Zurück');
+@define('NEXT', 'Weiter');
+@define('APPROVE', 'Bewilligen');
+@define('DO_MARKUP_DESCRIPTION', 'Textformatierung(en) durchführen, wie z.B. Smilies, Schnellformatierung via *, /, _, ...). Dadurch wird jeglicher eingegebener HTML-Code beibehalten.');
+@define('CATEGORY_ALREADY_EXIST', 'Eine Kategorie namens "%s" besteht bereits');
+@define('ERROR_FILE_FORBIDDEN', 'Der Upload von Dateien mit aktivem Inhalt ist nicht gestattet');
+@define('ADMIN', 'Administration');
+@define('ADMIN_FRONTPAGE', 'Startseite');
+@define('QUOTE', 'Zitat');
+@define('IFRAME_SAVE', 'Serendipity speichert nun den Eintrag, erstellt etwaige Trackbacks und führt mögliche XML-RPC Aufrufe durch. Dies kann eine Weile dauern...');
+@define('IFRAME_SAVE_DRAFT', 'Der Entwurf dieses Eintrags wurde gespeichert');
+@define('IFRAME_PREVIEW', 'Serendipity erstellt die Vorschau des Eintrags...');
+@define('IFRAME_WARNING', 'Ihr Browser unterstützt keine iframes. Bitte die Datei serendipity_config.inc.php öffnen und die Variable $serendipity[\'use_iframe\'] auf FALSE setzen.');
+@define('NONE', 'keine');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Voreinstellungen für neue Einträge');
+@define('UPGRADE', 'Aktualisieren');
+@define('UPGRADE_TO_VERSION', 'Aktuelle version %s');
+@define('DELETE_DIRECTORY', 'Verzeichnis löschen');
+@define('DELETE_DIRECTORY_DESC', 'Sie sind dabei, den Inhalt eines Verzeichnisses zu löschen, in dem Dateien enthalten sind, die möglicherweise in Blog-Einträgen verwendet wurden!');
+@define('FORCE_DELETE', 'ALLE Dateien dieses Verzeichnisses löschen, inklusive der Dateien, die Serendipity nicht katalogisiert hat');
+@define('CREATE_DIRECTORY', 'Verzeichnis anlegen');
+@define('CREATE_NEW_DIRECTORY', 'Neues Verzeichnis anlegen');
+@define('CREATE_DIRECTORY_DESC', 'Hier kann ein neues Verzeichnis angelegt werden um Mediendaten zu speichern. Bitte den Namen des neuen Verzeichnisses angeben und optional ein übergeordnetes Verzeichnis auswählen.');
+@define('BASE_DIRECTORY', 'Stammverzeichnis');
+@define('USERLEVEL_EDITOR_DESC', 'Redakteur');
+@define('USERLEVEL_CHIEF_DESC', 'Chef-Redakteur');
+@define('USERLEVEL_ADMIN_DESC', 'Administrator');
+@define('USERCONF_USERLEVEL', 'Zugriffsrechte');
+@define('USERCONF_USERLEVEL_DESC', 'Zugriffsrechte bestimmen die Art und den Umfang des Zugriffes eines Benutzers auf die Funkionalitäten des Blogs');
+@define('USER_SELF_INFO', 'Angemeldet als %s (%s)');
+@define('ADMIN_ENTRIES', 'Einträge');
+@define('RECHECK_INSTALLATION', 'Installation erneut überprüfen');
+@define('IMAGICK_EXEC_ERROR', 'Konnte folgendes Programm nicht ausführen: "%s", Fehlermeldung: %s, Rückgabewert: %d');
+@define('INSTALL_OFFSET_DESC', 'Wieviele Stunden liegen zwischen der Uhrzeit des Servers (aktuell: %clock%) und der eigenen Zeitzone');
+@define('UNMET_REQUIREMENTS', 'Bedingung unerfüllt: %s');
+@define('CHARSET', 'Zeichensatz');
+@define('AUTOLANG', 'Sprache des Browsers eines Besuchers verwenden');
+@define('AUTOLANG_DESC', 'Falls aktiviert wird die im Browser des Besuchers eingestellte Sprache als Standardsprache für Einträge und die Serendipity Oberfläche benutzt.');
+@define('INSTALL_AUTODETECT_URL', 'HTTP-Hostnamen automatisch erkennen');
+@define('INSTALL_AUTODETECT_URL_DESC', 'Falls aktiviert wird Serendipity sicherstellen, dass der vom Besucher gewählte HTTP-Hostname als BaseURL variable verwendet wird. Sofern diese Option aktiviert ist, ist es möglich, mehrere Domainnamen für das Weblog zu verwenden. Alle Links werden dann mit dem HTTP-Hostnamen umgeschrieben, der vom Besucher gewählt wurde.');
+@define('CONVERT_HTMLENTITIES', 'Try to auto-convert HTML entities?');
+@define('EMPTY_SETTING', 'You did not specify a valid value for "%s"!');
+@define('USERCONF_REALNAME', 'Voller Name');
+@define('USERCONF_REALNAME_DESC', 'Der vollständige Name des Autoren. Nur dieser Name wird von Besuchern gelesen.');
+@define('HOTLINK_DONE', 'Link zur Datei erstellt.<br />Fertig.');
+@define('ENTER_MEDIA_URL_METHOD', 'Download-Methode:');
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Hinweis: Falls Sie auf eine Datei/Grafik nur verweisen wollen, stellen Sie bitte sicher, dass Sie Erlaubnis haben zu diesen Bildern zu linken, oder dass die Zielwebseite ihre ist. Dateiverweise/Links ermöglichen es eine Datei nicht selber zu speichern, sondern stattdessen nur zum Zielort zu verweisen.');
+@define('MEDIA_HOTLINKED', 'Link');
+@define('FETCH_METHOD_IMAGE', 'Bild auf diesem Server speichern');
+@define('FETCH_METHOD_HOTLINK', 'Nur zum Quellserver linken');
+@define('DELETE_HOTLINK_FILE', 'Link zu Datei namens <b>%s</b> löschen?');
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'E-Mail Adressen einbinden?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_en.inc.php b/lang/serendipity_lang_en.inc.php
new file mode 100644 (file)
index 0000000..539f42f
--- /dev/null
@@ -0,0 +1,668 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+@define('LANG_CHARSET', 'ISO-8859-1');
+@define('DATE_LOCALES', 'english, en, en_US');
+@define('DATE_FORMAT_ENTRY', '%A, %B %e. %Y');
+@define('DATE_FORMAT_SHORT', '%Y-%m-%d %H:%M');
+@define('WYSIWYG_LANG', 'en');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', '.');
+@define('NUMBER_FORMAT_THOUSANDS', ',');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Serendipity Administration Suite');
+@define('HAVE_TO_BE_LOGGED_ON', 'You have to be logged in to view this page');
+@define('WRONG_USERNAME_OR_PASSWORD', 'You appear to have entered an invalid username or password');
+@define('APPEARANCE', 'Appearance');
+@define('MANAGE_STYLES', 'Manage Styles');
+@define('CONFIGURE_PLUGINS', 'Configure Plugins');
+@define('CONFIGURATION', 'Configuration');
+@define('BACK_TO_BLOG', 'Back to Weblog');
+@define('LOGIN', 'Login');
+@define('LOGOUT', 'Logout');
+@define('LOGGEDOUT', 'Logged out.');
+@define('CREATE', 'Create');
+@define('SAVE', 'Save');
+@define('NAME', 'Name');
+@define('CREATE_NEW_CAT', 'Create New Category');
+@define('I_WANT_THUMB', 'I want to use the thumbnail in my entry.');
+@define('I_WANT_BIG_IMAGE', 'I want to use the larger image in my entry.');
+@define('I_WANT_NO_LINK', 'I want to display it as an image');
+@define('I_WANT_IT_TO_LINK', 'I want to display it as a link to this url:');
+@define('BACK', 'Back');
+@define('FORWARD', 'Forward');
+@define('ANONYMOUS', 'Anonymous');
+@define('NEW_TRACKBACK_TO', 'New trackback made to');
+@define('NEW_COMMENT_TO', 'New comment posted to');
+@define('RECENT', 'Recent...');
+@define('OLDER', 'Older...');
+@define('DONE', 'Done');
+@define('WELCOME_BACK', 'Welcome back,');
+@define('TITLE', 'Title');
+@define('DESCRIPTION', 'Description');
+@define('PLACEMENT', 'Placement');
+@define('DELETE', 'Delete');
+@define('SAVE', 'Save');
+@define('UP', 'UP');
+@define('DOWN', 'DOWN');
+@define('ENTRIES', 'entries');
+@define('NEW_ENTRY', 'New Entry');
+@define('EDIT_ENTRIES', 'Edit Entries');
+@define('CATEGORIES', 'Categories');
+@define('WARNING_THIS_BLAHBLAH', "WARNING:\\nThis may take a long time if there are many images without thumbnails.");
+@define('CREATE_THUMBS', 'Rebuild Thumbs');
+@define('MANAGE_IMAGES', 'Manage Images');
+@define('NAME', 'Name');
+@define('EMAIL', 'Email');
+@define('HOMEPAGE', 'Homepage');
+@define('COMMENT', 'Comment');
+@define('REMEMBER_INFO', 'Remember Information? ');
+@define('SUBMIT_COMMENT', 'Submit Comment');
+@define('NO_ENTRIES_TO_PRINT', 'No entries to print');
+@define('COMMENTS', 'Comments');
+@define('ADD_COMMENT', 'Add Comment');
+@define('NO_COMMENTS', 'No comments');
+@define('POSTED_BY', 'Posted by');
+@define('ON', 'on');
+@define('A_NEW_COMMENT_BLAHBLAH', 'A new comment has been posted on your blog "%s", to the entry entitled "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'A new trackback has been made to your blog-entry entitled "%s".');
+@define('NO_CATEGORY', 'No Category');
+@define('ENTRY_BODY', 'Entry Body');
+@define('EXTENDED_BODY', 'Extended Body');
+@define('CATEGORY', 'Category');
+@define('EDIT', 'Edit');
+@define('NO_ENTRIES_BLAHBLAH', 'No Entries Found for Query %s' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'Your search for %s returned %s results:');
+@define('SEARCH_TOO_SHORT', 'Your search-query must be longer than 3 characters');
+@define('IMAGE', 'Image');
+@define('ERROR_FILE_NOT_EXISTS', 'Error: Old filename does not exist!');
+@define('ERROR_FILE_EXISTS', 'Error: New filename already used, pick another!');
+@define('ERROR_SOMETHING', 'Error: Something is wrong.');
+@define('ADDING_IMAGE', 'Adding image...');
+@define('THUMB_CREATED_DONE', 'Thumbnail created.<br/>Done.');
+@define('ERROR_FILE_EXISTS_ALREADY', 'Error: File already exists on your machine!');
+@define('ERROR_UNKNOWN_NOUPLOAD', 'Unknown error occured, file not uploaded. Maybe your filesize is larger than the maximum size allowed by your server installation. Check with your ISP or edit your php.ini file to allow larger file size uploads.');
+@define('GO', 'Go!');
+@define('NEWSIZE', 'New size: ');
+@define('RESIZE_BLAHBLAH', '<b>Resize %s</b><p>');
+@define('ORIGINAL_SIZE', 'Original size: <i>%sx%s</i> pixel');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>Here, you can adjust the image size. If you want to resize the image proportionally, just enter a value in one of the two boxes and press the TAB key --  I will automatically calculate the new size so the image proportions do not get messed up</p>');
+@define('QUICKJUMP_CALENDAR', 'QuickJump Calendar');
+@define('QUICKSEARCH', 'Quicksearch');
+@define('SEARCH_FOR_ENTRY', 'Search for an entry');
+@define('ARCHIVES', 'Archives');
+@define('BROWSE_ARCHIVES', 'Browse archives by month');
+@define('TOP_REFERRER', 'Top Referrers');
+@define('SHOWS_TOP_SITES', 'Shows top sites that linked to your blogs');
+@define('TOP_EXITS', 'Top Exits');
+@define('SHOWS_TOP_EXIT', 'Shows top exit links from your blogs');
+@define('SYNDICATION', 'Syndication');
+@define('SHOWS_RSS_BLAHBLAH', 'Shows RSS syndication links');
+@define('ADVERTISES_BLAHBLAH', 'Advertises the origins of your blog');
+@define('HTML_NUGGET', 'HTML Nugget');
+@define('HOLDS_A_BLAHBLAH', 'Holds a nugget of HTML in your sidebar');
+@define('TITLE_FOR_NUGGET', 'Title for the nugget');
+@define('THE_NUGGET', 'The Nugget of HTML!');
+@define('SYNDICATE_THIS_BLOG', 'Syndicate This Blog');
+@define('YOU_CHOSE', 'You chose %s');
+@define('IMAGE_ROTATE_LEFT', 'Rotate image 90 degrees counter-clockwise');
+@define('IMAGE_ROTATE_RIGHT', 'Rotate image 90 degrees clockwise');
+@define('IMAGE_SIZE', 'Image size');
+@define('IMAGE_AS_A_LINK', 'Image insertion');
+@define('POWERED_BY', 'Powered by');
+@define('TRACKBACKS', 'Trackbacks');
+@define('TRACKBACK', 'Trackback');
+@define('NO_TRACKBACKS', 'No Trackbacks');
+@define('TOPICS_OF', 'Topics from');
+@define('VIEW_FULL', 'view full');
+@define('VIEW_TOPICS', 'view topics');
+@define('AT', 'at');
+@define('SET_AS_TEMPLATE', 'Set as template');
+@define('IN', 'in');
+@define('EXCERPT', 'Excerpt');
+@define('TRACKED', 'Tracked');
+@define('LINK_TO_ENTRY', 'Link to entry');
+@define('LINK_TO_REMOTE_ENTRY', 'Link to remote-entry');
+@define('IP_ADDRESS', 'IP-address');
+@define('USER', 'User');
+@define('THUMBNAIL_USING_OWN', 'Using %s as its own thumbnail because it is so small already.');
+@define('THUMBNAIL_FAILED_COPY', 'Wanted to use %s as its own thumbnail, but failed to copy!');
+@define('AUTHOR', 'Author');
+@define('LAST_UPDATED', 'Last Updated');
+@define('TRACKBACK_SPECIFIC', 'Trackback specific URI for this entry');
+@define('DIRECT_LINK', 'Direct link to this entry');
+@define('COMMENT_ADDED', 'Your comment was successfully added. ');
+@define('COMMENT_ADDED_CLICK', 'Click %shere to return%s to the comments, and %shere to close%s this window.');
+@define('COMMENT_NOT_ADDED', 'Your comment could not be added, because comments for this entry have been disabled. ');
+@define('COMMENT_NOT_ADDED_CLICK', 'Click %shere to return%s to the comments, and %shere to close%s this window.');
+@define('COMMENTS_DISABLE', 'Do not allow comments to this entry');
+@define('COMMENTS_ENABLE', 'Allow comments to this entry');
+@define('COMMENTS_CLOSED', 'The author does not allow comments to this entry');
+@define('EMPTY_COMMENT', 'Your comment did not contain anything, please %sgo back%s and try again');
+@define('ENTRIES_FOR', 'Entries from %s');
+@define('DOCUMENT_NOT_FOUND', 'The document %s was not found.');
+@define('USERNAME', 'Username');
+@define('PASSWORD', 'Password');
+@define('AUTOMATIC_LOGIN', 'Save information');
+@define('SERENDIPITY_INSTALLATION', 'Serendipity Installation');
+@define('LEFT', 'left');
+@define('RIGHT', 'right');
+@define('HIDDEN', 'hidden');
+@define('REMOVE_TICKED_PLUGINS', 'Remove ticked plugins');
+@define('SAVE_CHANGES_TO_LAYOUT', 'Save changes to layout');
+@define('COMMENTS_FROM', 'Comments from');
+@define('ERROR', 'Error');
+@define('ENTRY_SAVED', 'Your entry has been saved');
+@define('DELETE_SURE', 'Are you sure you want to delete #%s permanently?');
+@define('NOT_REALLY', 'No');
+@define('DUMP_IT', 'Yes');
+@define('RIP_ENTRY', 'Entry #%s deleted.');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Category #%s deleted. Old articles moved to category #%s.');
+@define('CATEGORY_DELETED', 'Category #%s deleted.');
+@define('INVALID_CATEGORY', 'No category was provided for deletion');
+@define('CATEGORY_SAVED', 'Category saved');
+@define('SELECT_TEMPLATE', 'Select the template you wish to use for your blog');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'Entries were not successfully inserted!');
+@define('MT_DATA_FILE', 'Movable Type data file');
+@define('FORCE', 'Force');
+@define('CREATE_AUTHOR', 'Create author \'%s\'.');
+@define('CREATE_CATEGORY', 'Create category \'%s\'.');
+@define('MYSQL_REQUIRED', 'You must have the MySQL extension in order to perform this action.');
+@define('COULDNT_CONNECT', 'Could not connect to MySQL database: %s.');
+@define('COULDNT_SELECT_DB', 'Could not select database: %s.');
+@define('COULDNT_SELECT_USER_INFO', 'Could not select user information: %s.');
+@define('COULDNT_SELECT_CATEGORY_INFO', 'Could not select category information: %s.');
+@define('COULDNT_SELECT_ENTRY_INFO', 'Could not select entry information: %s.');
+@define('COULDNT_SELECT_COMMENT_INFO', 'Could not select comment information: %s.');
+@define('YES', 'Yes');
+@define('NO', 'No');
+@define('USE_DEFAULT', 'Default');
+@define('CHECK_N_SAVE', 'Check &amp; save');
+@define('DIRECTORY_WRITE_ERROR', 'Cannot write to directory %s. Please check the permissions.');
+@define('DIRECTORY_CREATE_ERROR', 'Directory %s does not exist and could not be created. Please create the directory manually');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; run <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', 'Cannot execute the %s binary');
+@define('FILE_WRITE_ERROR', 'Cannot write to file %s.');
+@define('FILE_CREATE_YOURSELF', 'Please create the file yourself or check permissions');
+@define('COPY_CODE_BELOW', '<br />* Just copy the code below and place it in %s in your %s folder:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Change www to the user apache runs as (e.g. nobody).');
+@define('BROWSER_RELOAD', 'Once you have done this, hit your browser\'s "reload" button.');
+@define('DIAGNOSTIC_ERROR', 'We detected some errors while running some diagnostics on your entered information:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity is not yet installed. Please <a href="%s">install</a> it now.');
+@define('INCLUDE_ERROR', 'serendipity error: could not include %s - exiting.');
+@define('DATABASE_ERROR', 'serendipity error: unable to connect to database - exiting.');
+@define('CREATE_DATABASE', 'Creating default database setup...');
+@define('ATTEMPT_WRITE_FILE', 'Attempting to write %s file...');
+@define('WRITTEN_N_SAVED', 'Configuration written &amp; saved');
+@define('IMAGE_ALIGNMENT', 'Image alignment');
+@define('ENTER_NEW_NAME', 'Enter the new name for: ');
+@define('RESIZING', 'Resizing');
+@define('RESIZE_DONE', 'Done (resized %s images).');
+@define('SYNCING', 'Synchronizing the database with the image folder');
+@define('SYNC_DONE', 'Done (Synchronized %s images).');
+@define('FILE_NOT_FOUND', 'Unable to locate the file entitled <b>%s</b>, maybe it has already been deleted?');
+@define('ABORT_NOW', 'Abort now');
+@define('REMOTE_FILE_NOT_FOUND', 'File was not located on the remote server, are you sure the URL: <b>%s</b> is correct?');
+@define('FILE_FETCHED', '%s fetched as %s');
+@define('FILE_UPLOADED', 'File %s successfully uploaded as %s');
+@define('WORD_OR', 'Or');
+@define('SCALING_IMAGE', 'Scaling %s to %s x %s px');
+@define('KEEP_PROPORTIONS', 'Keep proportions');
+@define('REALLY_SCALE_IMAGE', 'Really scale the image? This operation cannot be undone!');
+@define('TOGGLE_ALL', 'Toggle expand all');
+@define('TOGGLE_OPTION', 'Toggle option');
+@define('SUBSCRIBE_TO_THIS_ENTRY', 'Subscribe to this entry');
+@define('UNSUBSCRIBE_OK', "%s is now unsubscribed from this entry");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'New comment to subscribed entry "%s"');
+@define('SUBSCRIPTION_MAIL', "Hello %s,\n\nA new comment was made to the entry you are monitoring on \"%s\", entitled \"%s\"\nThe name of the poster is: %s\n\nYou can find the entry here: %s\n\nYou can unsubscribe by clicking on this link: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "Hello %s,\n\nA new trackback was added to the entry you are monitoring on \"%s\", entitled \"%s\"\nThe name of the poster is: %s\n\nYou can find the entry here: %s\n\nYou can unsubscribe by clicking on this link: %s\n");
+@define('SIGNATURE', "\n-- \n%s is powered by Serendipity.\nThe best blog around, you can use it too.\nCheck out <http://s9y.org> to find out how.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91 feed');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0 feed');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0 feed');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 comments');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3 feed');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'Field "managingEditor"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  'Field "webMaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'Image for the RSS feed');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', 'Image width');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'Image height');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  'E-Mail address of the webmaster, if available. (empty: hidden) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', 'E-Mail address of the managing editor, if available. (empty: hidden) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'URL of an image in GIF/JPEG/PNG format, if available. (empty: serendipity-logo)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'in pixels, max. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'in pixels, max. 400');
+@define('SYNDICATION_PLUGIN_TTL', 'Field "ttl" (time-to-live)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'Amount of minutes after which your blog should not be cached any more by foreign sites/applications (empty: hidden) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'Field "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', 'Should the "pubDate"-field be embedded for a RSS-channel, to show the date of the latest entry?');
+@define('CONTENT', 'Content');
+@define('TYPE', 'Type');
+@define('DRAFT', 'Draft');
+@define('PUBLISH', 'Publish');
+@define('PREVIEW', 'Preview');
+@define('DATE', 'Date');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', 'Warning: The date you specified was invalid. It has to be given in YYYY-MM-DD HH:MM format.');
+@define('CATEGORY_PLUGIN_DESC', 'Shows the list of categories.');
+@define('ALL_AUTHORS', 'All authors');
+@define('CATEGORIES_TO_FETCH', 'Categories to fetch');
+@define('CATEGORIES_TO_FETCH_DESC', 'Fetch categories from which author?');
+@define('PAGE_BROWSE_ENTRIES', 'Page %s of %s, totalling %s entries');
+@define('PREVIOUS_PAGE', 'previous page');
+@define('NEXT_PAGE', 'next page');
+@define('ALL_CATEGORIES', 'All categories');
+@define('DO_MARKUP', 'Perform Markup Transformations');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'Dateformatting');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'The format of the entry\'s actual date, using PHPs strftime() variables. (Default: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'Unable to open template file, please update serendipity!');
+@define('ADVANCED_OPTIONS', 'Advanced Options');
+@define('EDIT_ENTRY', 'Edit entry');
+@define('HTACCESS_ERROR', 'To check your local webserver installation, serendipity needs to be able to write the file ".htaccess". This was not possible because of permission errors. Please adjust the permissions like this: <br />&nbsp;&nbsp;%s<br />and reload this page.');
+@define('SIDEBAR_PLUGINS', 'Sidebar Plugins');
+@define('EVENT_PLUGINS', 'Event Plugins');
+@define('SORT_ORDER', 'Sort order');
+@define('SORT_ORDER_NAME', 'Filename');
+@define('SORT_ORDER_EXTENSION', 'File extension');
+@define('SORT_ORDER_SIZE', 'Filesize');
+@define('SORT_ORDER_WIDTH', 'Image width');
+@define('SORT_ORDER_HEIGHT', 'Image height');
+@define('SORT_ORDER_DATE', 'Upload date');
+@define('SORT_ORDER_ASC', 'Ascending');
+@define('SORT_ORDER_DESC', 'Descending');
+@define('THUMBNAIL_SHORT', 'Thumb');
+@define('ORIGINAL_SHORT', 'Orig.');
+@define('APPLY_MARKUP_TO', 'Apply markup to %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'Beginning of the week');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity has detected that your currently installed Serendipity version is %s. It seems you are attempting to upgrade to version %s, so you need to <a href="%s">click here</a> to continue the upgrade process.');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'Hi, and welcome to the Serendipity upgrade agent.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', 'I am here to help you upgrade your Serendipity %s installation.');
+@define('SERENDIPITY_UPGRADER_WHY', 'You are seeing this message because you have just installed Serendipity %s, but have not yet upgraded your database installation to fit this version');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'Database updates (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'I have found the following .sql files which needs to be run before you can continue normal operation of Serendipity');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  'Version specific tasks');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', 'No version specific tasks found');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', 'Do you wish me to perform the above tasks?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'No, I will run them manually');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'Yes, please do so');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'It appears you do not need any upgrades run');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', 'Consider Serendipity upgraded');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'You have ignored the upgrade stage of Serendipity, please make sure your database is correctly installed, and scheduled functions are run');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'Your Serendipity installation is now upgraded to version %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', 'You can return to your blog by clicking %shere%s');
+@define('MANAGE_USERS', 'Manage users');
+@define('CREATE_NEW_USER', 'Create new user');
+@define('CREATE_NOT_AUTHORIZED', 'You cannot modify users with the same userlevel as yourself');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'You cannot create users with a higher userlevel than yourself');
+@define('CREATED_USER', 'A new user %s has been created');
+@define('MODIFIED_USER', 'The properties of user %s have been changed');
+@define('USER_LEVEL', 'Userlevel');
+@define('DELETE_USER', 'You are about to delete user #%d %s. Are you serious? This will disallow showing any entries written by him on the frontend.');
+@define('DELETED_USER', 'User #%d %s deleted.');
+@define('LIMIT_TO_NUMBER', 'How many items should be displayed?');
+@define('ENTRIES_PER_PAGE', 'entries per page');
+@define('XML_IMAGE_TO_DISPLAY', 'XML Button');
+@define('XML_IMAGE_TO_DISPLAY_DESC','Links to XML Feeds will be displayed by this image. Leave empty for default, enter \'none\' to disable.');
+
+@define('DIRECTORIES_AVAILABLE', 'In the list of available subdirectories you can click on any directory name to create a new directory within that structure.');
+@define('ALL_DIRECTORIES', 'all directories');
+@define('MANAGE_DIRECTORIES', 'Manage directories');
+@define('DIRECTORY_CREATED', 'Directory <strong>%s</strong> has been created.');
+@define('PARENT_DIRECTORY', 'Parent directory');
+@define('CONFIRM_DELETE_DIRECTORY', 'Are you sure you want to remove all the contents of directory %s?');
+@define('ERROR_NO_DIRECTORY', 'Error: Directory %s does not exist');
+@define('CHECKING_DIRECTORY', 'Checking files in directory %s');
+@define('DELETING_FILE', 'Deleting file %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', 'Could not remove non-empty directory. Check the "force deletion" checkbox if you want to remove those files as well, and then submit again. Existing files are:');
+@define('DIRECTORY_DELETE_FAILED', 'Deletion of directory %s failed. Check permissions or messages above.');
+@define('DIRECTORY_DELETE_SUCCESS', 'Directory %s successfully deleted.');
+@define('SKIPPING_FILE_EXTENSION', 'Skipping file: Missing extension on %s.');
+@define('SKIPPING_FILE_UNREADABLE', 'Skipping file: %s not readable.');
+@define('FOUND_FILE', 'Found new/modified file: %s.');
+@define('ALREADY_SUBCATEGORY', '%s is a already a subcategory of %s.');
+@define('PARENT_CATEGORY', 'Parent category');
+@define('IN_REPLY_TO', 'In reply to');
+@define('TOP_LEVEL', 'Top level');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s feed');
+@define('PERMISSIONS', 'Permissions');
+@define('SETTINGS_SAVED_AT', 'The new settings have been saved at %s');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', 'Database Settings');
+@define('INSTALL_CAT_DB_DESC', 'Here you can enter all your database information. Serendipity needs this to be able to function');
+@define('INSTALL_DBTYPE', 'Database type');
+@define('INSTALL_DBTYPE_DESC', 'Database type');
+@define('INSTALL_DBHOST', 'Database host');
+@define('INSTALL_DBHOST_DESC', 'The hostname for your database server');
+@define('INSTALL_DBUSER', 'Database user');
+@define('INSTALL_DBUSER_DESC', 'The username used to connect to your database');
+@define('INSTALL_DBPASS', 'Database password');
+@define('INSTALL_DBPASS_DESC', 'The password matching the above username');
+@define('INSTALL_DBNAME', 'Database name');
+@define('INSTALL_DBNAME_DESC', 'The name of your database');
+@define('INSTALL_DBPREFIX', 'Database table prefix');
+@define('INSTALL_DBPREFIX_DESC', 'Prefix for the table names, e.g. serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', 'Paths');
+@define('INSTALL_CAT_PATHS_DESC', 'Various paths to different essential folders and files. Do not forget trailing slashes for directories!');
+@define('INSTALL_FULLPATH', 'Full path');
+@define('INSTALL_FULLPATH_DESC', 'The full and absolute path to your serendipity installation');
+@define('INSTALL_UPLOADPATH', 'Upload path');
+@define('INSTALL_UPLOADPATH_DESC', 'All uploads will go here, relative to the \'Full path\' - typically \'uploads/\'');
+@define('INSTALL_RELPATH', 'Relative path');
+@define('INSTALL_RELPATH_DESC', 'Path to serendipity for your browser, typically \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', 'Relative template path');
+@define('INSTALL_RELTEMPLPATH_DESC', 'The path to the folder containing your templates - Relative to the \'relative path\'');
+@define('INSTALL_RELUPLOADPATH', 'Relative upload path');
+@define('INSTALL_RELUPLOADPATH_DESC', 'Path to your uploads for browsers - Relative to the \'relative path\'');
+@define('INSTALL_URL', 'URL to blog');
+@define('INSTALL_URL_DESC', 'Base URL to your serendipity installation');
+@define('INSTALL_INDEXFILE', 'Index file');
+@define('INSTALL_INDEXFILE_DESC', 'The name of your serendipity index file');
+
+/* GENERAL SETTINGS */
+@define('INSTALL_CAT_SETTINGS', 'General Settings');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Customize how Serendipity behaves');
+@define('INSTALL_USERNAME', 'Admin username');
+@define('INSTALL_USERNAME_DESC', 'Username for admin login');
+@define('INSTALL_PASSWORD', 'Admin password');
+@define('INSTALL_PASSWORD_DESC', 'Password for admin login');
+@define('INSTALL_EMAIL', 'Admin email');
+@define('INSTALL_EMAIL_DESC', 'Email for the blog administrator');
+@define('INSTALL_SENDMAIL', 'Send mails to admin?');
+@define('INSTALL_SENDMAIL_DESC', 'Do you want to receive emails when comments are posted to your entries?');
+@define('INSTALL_SUBSCRIBE', 'Allow users to subscribe to entries?');
+@define('INSTALL_SUBSCRIBE_DESC', 'Allow users to subscribe to an entry and thereby receive a mail when new comments are made to that entry');
+@define('INSTALL_BLOGNAME', 'Blog name');
+@define('INSTALL_BLOGNAME_DESC', 'The title of your blog');
+@define('INSTALL_BLOGDESC', 'Blog description');
+@define('INSTALL_BLOGDESC_DESC', 'Description of your blog');
+@define('INSTALL_LANG', 'Language');
+@define('INSTALL_LANG_DESC', 'Select the language for your blog');
+
+/* APPEARANCE AND OPTIONS */
+@define('INSTALL_CAT_DISPLAY', 'Appearance and Options');
+@define('INSTALL_CAT_DISPLAY_DESC', 'Customize how Serendipity looks and feels');
+@define('INSTALL_WYSIWYG', 'Use WYSIWYG editor');
+@define('INSTALL_WYSIWYG_DESC', 'Do you want to use the WYSIWYG editor? (Works on IE5+, partially in Mozilla 1.3+)');
+@define('INSTALL_XHTML11', 'Force XHTML 1.1 compliance');
+@define('INSTALL_XHTML11_DESC', 'Do you want to force XHTML 1.1 compliance (may cause problems for back-/frontend on older 4th generation browsers)');
+@define('INSTALL_POPUP', 'Enable use of popup windows');
+@define('INSTALL_POPUP_DESC', 'Do you want to use popup windows for comments, trackbacks et al?');
+@define('INSTALL_EMBED', 'Is serendipity embedded?');
+@define('INSTALL_EMBED_DESC', 'If you want to embed serendipity within a regular page, set to true to discard any headers and just print the contents. You can make use of the indexFile option to use a wrapper class where you put your normal webpage headers. See the README file for more information!');
+@define('INSTALL_TOP_AS_LINKS', 'Show Top Exits/Referrers as links?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"no": Exits and Referrers are shown as plain text to prevent google spam. "yes": Exits and Referrers are shown as hyperlinks. "default": Use setting from global configuration (recommended).');
+@define('INSTALL_BLOCKREF', 'Blocked Referers');
+@define('INSTALL_BLOCKREF_DESC', 'Are there any special hosts you want not to show up in the referers list? Separate the list of hostnames with \';\' and note that the host is blocked by substring matches!');
+@define('INSTALL_REWRITE', 'URL Rewriting');
+@define('INSTALL_REWRITE_DESC', 'Select which rules you wish to use when generating URLs. Enabling rewrite rules will make pretty URLs for your blog and make it better indexable for spiders like google. The webserver needs to support either mod_rewrite or "AllowOverride All" for your serendipity dir. The default setting is auto-detected');
+
+/* IMAGECONVERSION SETTINGS */
+@define('INSTALL_CAT_IMAGECONV', 'Image Conversion Settings');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'Enter general information about how serendipity should handle Images');
+@define('INSTALL_IMAGEMAGICK', 'Use ImageMagick');
+@define('INSTALL_IMAGEMAGICK_DESC', 'Do you have ImageMagick installed and want to use it to resize images?');
+@define('INSTALL_IMAGEMAGICKPATH', 'Path to convert binary');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'Full path & name of your ImageMagick convert binary');
+@define('INSTALL_THUMBSUFFIX', 'Thumbnail suffix');
+@define('INSTALL_THUMBSUFFIX_DESC', 'Thumbnails will be named with the following format: original.[suffix].ext');
+@define('INSTALL_THUMBWIDTH', 'Thumbnail dimensions');
+@define('INSTALL_THUMBWIDTH_DESC', 'Static maximum width of auto-generated thumbnails');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', 'Your personal details');
+@define('USERCONF_CAT_PERSONAL_DESC', 'Change your personal details');
+@define('USERCONF_USERNAME', 'Your username');
+@define('USERCONF_USERNAME_DESC', 'The username you use to log in to the blog');
+@define('USERCONF_PASSWORD', 'Your password');
+@define('USERCONF_PASSWORD_DESC', 'The password you wish to use to log in to the blog');
+@define('USERCONF_EMAIL', 'Your e-mail address');
+@define('USERCONF_EMAIL_DESC', 'Your personal e-mail address');
+@define('USERCONF_SENDCOMMENTS', 'Send comment announcements?');
+@define('USERCONF_SENDCOMMENTS_DESC', 'Do you want to receive emails when comments are posted to your entries?');
+@define('USERCONF_SENDTRACKBACKS', 'Send trackback announcements?');
+@define('USERCONF_SENDTRACKBACKS_DESC', 'Do you want to receive emails when trackbacks are posted to your entries?');
+@define('USERCONF_ALLOWPUBLISH', 'Rights: Publishing entries?');
+@define('USERCONF_ALLOWPUBLISH_DESC', 'Is this user allowed to publish entries?');
+@define('SUCCESS', 'Success');
+@define('POWERED_BY_SHOW_TEXT', 'Show "Serendipity" as text');
+@define('POWERED_BY_SHOW_TEXT_DESC', 'Will display "Serendipity Weblog" as text');
+@define('POWERED_BY_SHOW_IMAGE', 'Show "Serendipity" with a logo');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Displays the Serendipity logo');
+@define('PLUGIN_ITEM_DISPLAY', 'Where should the item be displayed?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'Extended entry only');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'Overview page only');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'All times');
+@define('RSS_IMPORT_CATEGORY', 'Use this category for non-matching imported entries');
+
+@define('COMMENTS_WILL_BE_MODERATED', 'Submitted comments will be subject to moderation before being displayed.');
+@define('YOU_HAVE_THESE_OPTIONS', 'You have the following options available:');
+@define('THIS_COMMENT_NEEDS_REVIEW', 'Warning: This comment needs approval before it will be displayed');
+@define('DELETE_COMMENT', 'Delete comment');
+@define('APPROVE_COMMENT', 'Approve comment');
+@define('REQUIRES_REVIEW', 'Requires review');
+@define('COMMENT_APPROVED', 'Comment #%s has successfully been approved');
+@define('COMMENT_DELETED', 'Comment #%s has successfully been deleted');
+@define('COMMENTS_MODERATE', 'Comments & trackbacks to this entry requires moderation');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'Warning: This trackback needs approval before it will be displayed');
+@define('DELETE_TRACKBACK', 'Delete trackback');
+@define('APPROVE_TRACKBACK', 'Approve trackback');
+@define('TRACKBACK_APPROVED', 'Trackback #%s has successfully been approved');
+@define('TRACKBACK_DELETED', 'Trackback #%s has successfully been deleted');
+@define('VIEW', 'View');
+@define('COMMENT_ALREADY_APPROVED', 'Comment #%s appears to already have been approved');
+@define('COMMENT_EDITED', 'The selected comment has been edited');
+@define('HIDE', 'Hide');
+@define('VIEW_EXTENDED_ENTRY', 'Continue reading "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'This link is not meant to be clicked. It contains the trackback URI for this entry. You can use this URI to send ping- & trackbacks from your own blog to this entry. To copy the link, right click and select "Copy Shortcut" in Internet Explorer or "Copy Link Location" in Mozilla.');
+@define('PLUGIN_SUPERUSER_HTTPS', 'Use https for login');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'Lets the login-link point to a https-location. Your webserver needs to support this!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'Make external links clickable?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"no": Unchecked external links (Top Exits, Top Referrers, User comments) are not shown/shown as plain text where applicable to prevent google spam (recommended). "yes": Unchecked external links are shown as hyperlinks. Can be overridden within sidebar plugin configuration!');
+@define('PAGE_BROWSE_COMMENTS', 'Page %s of %s, totalling %s comments');
+@define('FILTERS', 'Filters');
+@define('FIND_ENTRIES', 'Find entries');
+@define('FIND_COMMENTS', 'Find comments');
+@define('FIND_MEDIA', 'Find media');
+@define('FILTER_DIRECTORY', 'Directory');
+@define('SORT_BY', 'Sort by');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'No Trackback sent: Could not open connection to %s on port %d');
+@define('MEDIA', 'Media');
+@define('MEDIA_LIBRARY', 'Media library');
+@define('ADD_MEDIA', 'Add media');
+@define('ENTER_MEDIA_URL', 'Enter an URL of a file to fetch:');
+@define('ENTER_MEDIA_UPLOAD', 'Select a file you wish to upload:');
+@define('SAVE_FILE_AS', 'Save the file as:');
+@define('STORE_IN_DIRECTORY', 'Store inside the following directory: ');
+@define('ADD_MEDIA_BLAHBLAH', '<b>Add a file to your media repository:</b><p>Here you can upload mediafiles, or tell me to fetch them from somewhere in the web! If you do not have an appropriate image, <a href="http://images.google.com" target="_blank">search for images on google</a> matching your thoughts, the results are often useful and funny :) But be careful, most images are copyrighted, so you should ask before using them.<p><b>Select method:</b><br/>');
+@define('MEDIA_RENAME', 'Rename this file');
+@define('IMAGE_RESIZE', 'Resize this image');
+@define('MEDIA_DELETE', 'Delete this file');
+@define('FILES_PER_PAGE', 'Files per page');
+@define('CLICK_FILE_TO_INSERT', 'Click the file you want to insert:');
+@define('SELECT_FILE', 'Select file to insert');
+@define('MEDIA_FULLSIZE', 'Fullsize');
+@define('CALENDAR_BOW_DESC', 'The day of the week that should be considered the beginning of the week. Default is Monday');
+@define('SUPERUSER', 'Blog Administration');
+@define('ALLOWS_YOU_BLAHBLAH', 'Provides a link in the sidebar to your blog administration');
+@define('CALENDAR', 'Calendar');
+@define('SUPERUSER_OPEN_ADMIN', 'Open administration');
+@define('SUPERUSER_OPEN_LOGIN', 'Open login screen');
+@define('INVERT_SELECTIONS', 'Invert Selections');
+@define('COMMENTS_DELETE_CONFIRM', 'Are you sure you wish to delete the selected comments?');
+@define('COMMENT_DELETE_CONFIRM', 'Are you sure you wish to delete comment #%d, written by %s?');
+@define('DELETE_SELECTED_COMMENTS', 'Delete selected comments');
+@define('VIEW_COMMENT', 'View comment');
+@define('VIEW_ENTRY', 'View entry');
+@define('DELETE_FILE_FAIL' , 'Unable to delete file <b>%s</b>');
+@define('DELETE_THUMBNAIL', 'Deleted the image thumbnail entitled <b>%s</b>');
+@define('DELETE_FILE', 'Deleted the file entitled <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', 'You are about to delete <b>%s</b><br />If you are using this file in some of your entries, it will cause dead links or images<br />Are you sure you wish to proceed?<br /><br />');
+@define('TRACKBACK_SENDING', 'Sending trackback to URI %s...');
+@define('TRACKBACK_SENT', 'Trackback successful');
+@define('TRACKBACK_FAILED', 'Trackback failed: %s');
+@define('TRACKBACK_NOT_FOUND', 'No trackback-URI found.');
+@define('TRACKBACK_URI_MISMATCH', 'The autodiscovered trackback URI does not match our target URI.');
+@define('TRACKBACK_CHECKING', 'Checking <u>%s</u> for possible trackbacks...');
+@define('TRACKBACK_NO_DATA', 'Target contained no data');
+@define('TRACKBACK_SIZE', 'Target URI exceeded maximum filesize of %s bytes.');
+@define('COMMENTS_VIEWMODE_THREADED', 'Threaded');
+@define('COMMENTS_VIEWMODE_LINEAR', 'Linear');
+@define('DISPLAY_COMMENTS_AS', 'Display comments as');
+@define('COMMENTS_FILTER_SHOW', 'Show');
+@define('COMMENTS_FILTER_ALL', 'All');
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'Only approved');
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'Pending approval');
+@define('RSS_IMPORT_BODYONLY', 'Put all imported text in the "body" section and do not split up into "extended entry" section.');
+@define('SYNDICATION_PLUGIN_FULLFEED', 'Show full articles with extended body inside RSS feed');
+@define('WEEK', 'Week');
+@define('WEEKS', 'Weeks');
+@define('MONTHS', 'Months');
+@define('DAYS', 'Days');
+@define('ARCHIVE_FREQUENCY', 'Calendar item frequency');
+@define('ARCHIVE_FREQUENCY_DESC', 'The calendar interval to use between each item in the list');
+@define('ARCHIVE_COUNT', 'Number of items in the list');
+@define('ARCHIVE_COUNT_DESC', 'The total number of months, weeks or days to display');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'Below is a list of installed plugins');
+@define('SIDEBAR_PLUGIN', 'sidebar plugin');
+@define('EVENT_PLUGIN', 'event plugin');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'Click here to install a new %s');
+@define('VERSION', 'version');
+@define('INSTALL', 'Install');
+@define('ALREADY_INSTALLED', 'Already installed');
+@define('SELECT_A_PLUGIN_TO_ADD', 'Select the plugin which you wish to install');
+@define('INSTALL_OFFSET', 'Server time Offset');
+@define('STICKY_POSTINGS', 'Sticky Postings');
+@define('INSTALL_FETCHLIMIT', 'Entries to display on frontpage');
+@define('INSTALL_FETCHLIMIT_DESC', 'Number of entries to display for each page on the frontend');
+@define('IMPORT_ENTRIES', 'Import data');
+@define('EXPORT_ENTRIES', 'Export entries');
+@define('IMPORT_WELCOME', 'Welcome to the Serendipity import utility');
+@define('IMPORT_WHAT_CAN', 'Here you can import entries from other weblog software applications');
+@define('IMPORT_SELECT', 'Please select the software you wish to import from');
+@define('IMPORT_PLEASE_ENTER', 'Please enter the data as requested below');
+@define('IMPORT_NOW', 'Import now!');
+@define('IMPORT_STARTING', 'Starting import procedure...');
+@define('IMPORT_FAILED', 'Import failed');
+@define('IMPORT_DONE', 'Import successfully completed');
+@define('IMPORT_WEBLOG_APP', 'Weblog application');
+@define('IMPORT_NOTES', 'Note:');
+@define('EXPORT_FEED', 'Export full RSS feed');
+@define('STATUS', 'Status after import');
+@define('IMPORT_GENERIC_RSS', 'Generic RSS import');
+@define('ACTIVATE_AUTODISCOVERY', 'Send Trackbacks to links found in the entry');
+@define('WELCOME_TO_ADMIN', 'Welcome to the Serendipity Administration Suite.');
+@define('PLEASE_ENTER_CREDENTIALS', 'Please enter your credentials below.');
+@define('ADMIN_FOOTER_POWERED_BY', 'Powered by Serendipity %s and PHP %s');
+@define('INSTALL_USEGZIP', 'Use gzip compressed pages');
+@define('INSTALL_USEGZIP_DESC', 'To speed up delivery of pages, we can compress the pages we send to the visitor, given that his browser supports this. This is recommended');
+@define('INSTALL_SHOWFUTURE', 'Show future entries');
+@define('INSTALL_SHOWFUTURE_DESC', 'If enabled, this will show all entries in the future on your blog. Default is to hide those entries and only show them if the publish date has arrived.');
+@define('INSTALL_DBPERSISTENT', 'Use persistent connections');
+@define('INSTALL_DBPERSISTENT_DESC', 'Enable the usage of persistent database connections, read more <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">here</a>. This is normally not recommended');
+@define('NO_IMAGES_FOUND', 'No images found');
+@define('PERSONAL_SETTINGS', 'Personal Settings');
+@define('REFERER', 'Referer');
+@define('NOT_FOUND', 'Not found');
+@define('WRITABLE', 'Writable');
+@define('NOT_WRITABLE', 'Not writable');
+@define('PROBLEM_DIAGNOSTIC', 'Due to a problematic diagnostic, you cannot continue with the installation until the above errors are fixed');
+@define('SELECT_INSTALLATION_TYPE', 'Select which installation type you wish to use');
+@define('WELCOME_TO_INSTALLATION', 'Welcome to the Serendipity Installation');
+@define('FIRST_WE_TAKE_A_LOOK', 'First we will take a look at your current setup and attempt to diagnose any compatibility problems');
+@define('ERRORS_ARE_DISPLAYED_IN', 'Errors are displayed in %s, recommendations in %s and success in %s');
+@define('RED', 'red');
+@define('YELLOW', 'yellow');
+@define('GREEN', 'green');
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s pre-installation report');
+@define('RECOMMENDED', 'Recommended');
+@define('ACTUAL', 'Actual');
+@define('PHPINI_CONFIGURATION', 'php.ini configuration');
+@define('PHP_INSTALLATION', 'PHP installation');
+@define('THEY_DO', 'they do');
+@define('THEY_DONT', 'they do not');
+@define('SIMPLE_INSTALLATION', 'Simple installation');
+@define('EXPERT_INSTALLATION', 'Expert installation');
+@define('COMPLETE_INSTALLATION', 'Complete installation');
+@define('WONT_INSTALL_DB_AGAIN', 'will not install the database again');
+@define('CHECK_DATABASE_EXISTS', 'Checking to see if the database and tables already exists');
+@define('CREATING_PRIMARY_AUTHOR', 'Creating primary author \'%s\'');
+@define('SETTING_DEFAULT_TEMPLATE', 'Setting default template');
+@define('INSTALLING_DEFAULT_PLUGINS', 'Installing default plugins');
+@define('SERENDIPITY_INSTALLED', 'Serendipity has been successfully installed');
+@define('VISIT_BLOG_HERE', 'Visit your new blog here');
+@define('THANK_YOU_FOR_CHOOSING', 'Thank you for choosing Serendipity');
+@define('ERROR_DETECTED_IN_INSTALL', 'An error was detected in the installation');
+@define('OPERATING_SYSTEM', 'Operating system');
+@define('WEBSERVER_SAPI', 'Webserver SAPI');
+@define('TEMPLATE_SET', '\'%s\' has been set as your active template');
+@define('SEARCH_ERROR', 'The search function did not work as expected. Notice for the administrator of this blog: This may happen because of missing index keys in your database. On MySQL systems your database user account needs to be privileged to execute this query: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> The specific error returned by the database was: <pre>%s</pre>');
+@define('EDIT_THIS_CAT', 'Editing "%s"');
+@define('CATEGORY_REMAINING', 'Delete this category and move its entries to this category');
+@define('CATEGORY_INDEX', 'Below is a list of categories available to your entries');
+@define('NO_CATEGORIES', 'No categories');
+@define('RESET_DATE', 'Reset date');
+@define('RESET_DATE_DESC', 'Click here to reset the date to the current time');
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Permissions can be set by running shell command: `<em>%s</em>` on the failed directory, or by setting this using an FTP program');
+@define('WARNING_TEMPLATE_DEPRECATED', 'Warning: Your current template is using a deprecated template method, you are advised to update if possible');
+@define('ENTRY_PUBLISHED_FUTURE', 'This entry is not yet published.');
+@define('ENTRIES_BY', 'Entries by %s');
+@define('PREVIOUS', 'Previous');
+@define('NEXT', 'Next');
+@define('APPROVE', 'Approve');
+@define('DO_MARKUP_DESCRIPTION', 'Apply markup transformations to the text (smilies, shortcut markups via *, /, _, ...). Disabling this will preserve any HTML-code in the text.');
+@define('CATEGORY_ALREADY_EXIST', 'A category with the name "%s" already exist');
+@define('ERROR_FILE_FORBIDDEN', 'You are not allowed to upload files with active content');
+@define('ADMIN', 'Administration');
+@define('ADMIN_FRONTPAGE', 'Frontpage');
+@define('QUOTE', 'Quote');
+@define('IFRAME_SAVE', 'Serendipity is now saving your entry, creating trackbacks and performing possible XML-RPC calls. This may take a while..');
+@define('IFRAME_SAVE_DRAFT', 'A draft of this entry has been saved');
+@define('IFRAME_PREVIEW', 'Serendipity is now creating the preview of your entry...');
+@define('IFRAME_WARNING', 'Your browser does not support the concept of iframes. Please open your serendipity_config.inc.php file and set $serendipity[\'use_iframe\'] variable to FALSE.');
+@define('NONE', 'none');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Default settings for new entries');
+@define('UPGRADE', 'Upgrade');
+@define('UPGRADE_TO_VERSION', 'Upgrade to version %s');
+@define('DELETE_DIRECTORY', 'Delete directory');
+@define('DELETE_DIRECTORY_DESC', 'You are about to delete the contents of a directory that contains media files, possibly files used in some of your entries.');
+@define('FORCE_DELETE', 'Delete ALL files in this directory, including those not known by Serendipity');
+@define('CREATE_DIRECTORY', 'Create directory');
+@define('CREATE_NEW_DIRECTORY', 'Create new directory');
+@define('CREATE_DIRECTORY_DESC', 'Here you can create a new directory to place media files in. Choose the name for your new directory and select an optional parent directory to place it in.');
+@define('BASE_DIRECTORY', 'Base directory');
+@define('USERLEVEL_EDITOR_DESC', 'Standard editor');
+@define('USERLEVEL_CHIEF_DESC', 'Chief editor');
+@define('USERLEVEL_ADMIN_DESC', 'Administrator');
+@define('USERCONF_USERLEVEL', 'Access level');
+@define('USERCONF_USERLEVEL_DESC', 'This level is used to determine what kind of access this user has to the blog');
+@define('USER_SELF_INFO', 'Logged in as %s (%s)');
+@define('ADMIN_ENTRIES', 'Entries');
+@define('RECHECK_INSTALLATION', 'Recheck installation');
+@define('IMAGICK_EXEC_ERROR', 'Unable to execute: "%s", error: %s, return var: %d');
+@define('INSTALL_OFFSET_DESC', 'Enter the amount of hours between the date of your webserver (current: %clock%) and your desired time zone');
+@define('UNMET_REQUIREMENTS', 'Requirements failed: %s');
+@define('CHARSET', 'Charset');
+@define('AUTOLANG', 'Use visitor\'s browser language as default');
+@define('AUTOLANG_DESC', 'If enabled, this will use the visitor\'s browser language setting to determine the default language of your entry and interface language.');
+@define('INSTALL_AUTODETECT_URL', 'Autodetect used HTTP-Host');
+@define('INSTALL_AUTODETECT_URL_DESC', 'If set to "true", Serendipity will ensure that the HTTP Host which was used by your visitor is used as your BaseURL setting. Enabling this will let you be able to use multiple domain names for your Serendipity Blog, and use the domain for all follow-up links which the user used to access your blog.');
+@define('CONVERT_HTMLENTITIES', 'Try to auto-convert HTML entities?');
+@define('EMPTY_SETTING', 'You did not specify a valid value for "%s"!');
+@define('USERCONF_REALNAME', 'Real name'); // Translate
+@define('USERCONF_REALNAME_DESC', 'The full name of the author. This is the name seen by readers'); // Translate
+@define('HOTLINK_DONE', 'File hotlinked.<br />Done.'); // Translate
+@define('ENTER_MEDIA_URL_METHOD', 'Fetch method:'); // Translate
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Note: If you choose to hotlink to server, make sure you have permission to hotlink to the designated website, or the website is yours. Hotlink allows you to use off-site images without storing them locally.'); // Translate
+@define('MEDIA_HOTLINKED', 'hotlinked'); // Translate
+@define('FETCH_METHOD_IMAGE', 'Download image to your server'); // Translate
+@define('FETCH_METHOD_HOTLINK', 'Hotlink to server'); // Translate
+@define('DELETE_HOTLINK_FILE', 'Deleted the hotlinked file entitled <b>%s</b>'); // Translate
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Show E-Mail addresses?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_es.inc.php b/lang/serendipity_lang_es.inc.php
new file mode 100644 (file)
index 0000000..fb8a357
--- /dev/null
@@ -0,0 +1,673 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Translation (c) by Luis Cervantes <LuisCervantes@ono.com>,
+#                    Manuel García <lendulado@gmail.com>
+
+@define('LANG_CHARSET', 'ISO-8859-15');
+@define('DATE_LOCALES', 'spanish, sp, es, es_ES, es_ES.ISO_8859-1, es_ES.ISO8859-1, es-ES');
+@define('DATE_FORMAT_ENTRY', '%A, %e de %B del %Y');
+@define('DATE_FORMAT_SHORT', '%d.%m.%Y %H:%M');
+@define('WYSIWYG_LANG', 'es');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Suite de Administraci&oacute;n de Serendipity');
+@define('HAVE_TO_BE_LOGGED_ON', 'Debes identificarte para ver esta p&aacute;gina');
+@define('APPEARANCE', 'Apariencia');
+@define('MANAGE_STYLES', 'Gesti&oacute;n de estilos');
+@define('CONFIGURE_PLUGINS', 'Configurar extensiones');
+@define('CONFIGURATION', 'Configuraci&oacute;n');
+@define('BACK_TO_BLOG', 'Volver al weblog');
+@define('LOGOUT', 'Desconectar');
+@define('LOGGEDOUT', 'Desconectado');
+@define('CREATE_NEW_CAT', 'Crear una categor&iacute;a nueva');
+@define('CREATE', 'Crear');
+@define('SAVE', 'Guardar');
+@define('NAME', 'Nombre');
+@define('I_WANT_THUMB', 'Quiero usar la miniatura en mi entrada.');
+@define('I_WANT_BIG_IMAGE', 'Quiero usar la imagen m&aacute;s grande en mi entrada.');
+@define('I_WANT_NO_LINK', ' Quiero que aparezca como una imagen');
+@define('I_WANT_IT_TO_LINK', 'Quiero que aparezca como un enlace a esta URL:');
+@define('BACK', 'Atr&aacute;s');
+@define('FORWARD', 'Seguir');
+@define('ANONYMOUS', 'An&oacute;nimo');
+@define('NEW_TRACKBACK_TO', 'Nueva referencia hecha para');
+@define('NEW_COMMENT_TO', 'Nuevo comentario para');
+@define('RECENT', 'Recientes...');
+@define('OLDER', 'Antiguos...');
+@define('DONE', 'Hecho');
+@define('WELCOME_BACK', 'Bienvenido de nuevo,');
+@define('TITLE', 'T&iacute;tulo');
+@define('DESCRIPTION', 'Descripci&oacute;n');
+@define('PLACEMENT', 'Localizaci&oacute;n');
+@define('DELETE', 'Borrar');
+@define('SAVE', 'Guardar');
+@define('UP', 'ARRIBA');
+@define('DOWN', 'ABAJO');
+@define('ENTRIES', 'entradas');
+@define('NEW_ENTRY', 'Nueva entrada');
+@define('EDIT_ENTRIES', 'Editar entradas');
+@define('CATEGORIES', 'Categor&iacute;as');
+@define('WARNING_THIS_BLAHBLAH', "ATENCI&Oacute;N:\\nPuede tardar si hay muchas im&aacute;genes que no tienen miniatura.");
+@define('CREATE_THUMBS', 'Crear las miniaturas');
+@define('MANAGE_IMAGES', 'Gesti&oacute;n de im&aacute;genes');
+@define('NAME', 'Nombre');
+@define('EMAIL', 'Correo electr&oacute;nico');
+@define('HOMEPAGE', 'URL personal');
+@define('COMMENT', 'Comentario');
+@define('REMEMBER_INFO', '¿Recordar la informaci&oacute;n? ');
+@define('SUBMIT_COMMENT', 'Enviar comentario');
+@define('NO_ENTRIES_TO_PRINT', 'No hay entradas para mostrar');
+@define('COMMENTS', 'Comentarios');
+@define('ADD_COMMENT', 'A&ntilde;adir comentario');
+@define('NO_COMMENTS', 'No hay comentarios');
+@define('POSTED_BY', 'Publicado por');
+@define('ON', 'activado');
+@define('A_NEW_COMMENT_BLAHBLAH', 'Se ha realizado un nuevo comentario en tu blog "%s", para la entrada titulada "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'Se ha realizado una nueva referencia a la entrada titulada "%s".');
+@define('NO_CATEGORY', 'No existe la categor&iacute;a');
+@define('ENTRY_BODY', 'Texto de la entrada');
+@define('EXTENDED_BODY', 'Texto ampliado');
+@define('CATEGORY', 'Categor&iacute;a');
+@define('EDIT', 'Editar');
+@define('NO_ENTRIES_BLAHBLAH', 'No se han encontrado resultados para la b&uacute;squeda %s' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'La b&uacute;squeda para %s ha obtenido %s resultados:');
+@define('SEARCH_TOO_SHORT', 'La b&uacute;squeda debe tener tres caracteres como m&iacute;nimo ');
+@define('IMAGE', 'Imagen');
+@define('ERROR_FILE_NOT_EXISTS', 'Error: ¡El fichero antiguo no existe!');
+@define('ERROR_FILE_EXISTS', 'Error: ¡Un fichero con ese nombre ya existe, selecciona otro!');
+@define('ERROR_SOMETHING', 'Error: Algo est&aacute; mal.');
+@define('ADDING_IMAGE', 'A&ntilde;adiendo imagen...');
+@define('THUMB_CREATED_DONE', 'Miniatura creada.<br />Hecho.');
+@define('ERROR_FILE_EXISTS_ALREADY', 'Error: ¡El fichero ya existe en el sistema!');
+@define('GO', '¡Ir!');
+@define('NEWSIZE', 'Nuevo tama&ntilde;o: ');
+@define('RESIZE_BLAHBLAH', '<b>Cambiar tama&ntilde;o %s</b><p>');
+@define('ORIGINAL_SIZE', 'Tama&ntilde;o original: <i>%sx%s</i> pixel');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>Aqu&iacute; puedes ajustar el nuevo tama&ntilde;o de la imagen. Si quieres mantener las proporciones s&oacute;lo introduce uno de los valores y presiona la tecla tabulador (TAB), de esta forma se ajustar&aacute; autom&aacute;ticamente:');
+@define('DATE_FORMAT_1', 'd.m.Y');
+@define('QUICKJUMP_CALENDAR', 'Calendario r&aacute;pido');
+@define('QUICKSEARCH', 'Buscar');
+@define('SEARCH_FOR_ENTRY', 'Busca una entrada');
+@define('ARCHIVES', 'Archivos');
+@define('BROWSE_ARCHIVES', 'Navega los archivos por mes');
+@define('TOP_REFERRER', 'Sitios asociados'); 
+@define('SHOWS_TOP_SITES', 'Muestra los sitios que enlazan a tu weblog');
+@define('TOP_EXITS', 'Salidas'); 
+@define('SHOWS_TOP_EXIT', 'Muestra los enlaces de salida m&aacute;s frecuentes desde tu weblog');
+@define('SYNDICATION', 'Sindicaci&oacute;n');
+@define('SHOWS_RSS_BLAHBLAH', 'Muestra los enlaces RSS de sindicaci&oacute;n');
+@define('ADVERTISES_BLAHBLAH', 'Informa del programa en el que se basa tu weblog'); 
+@define('HTML_NUGGET', 'Fragmento de HTML');
+@define('HOLDS_A_BLAHBLAH', 'Presenta un fragmento de HTML en la barra lateral');
+@define('TITLE_FOR_NUGGET', 'T&iacute;tulo para el fragmento de HTML');
+@define('THE_NUGGET', '¡Fragmento de HTML!');
+@define('SYNDICATE_THIS_BLOG', 'Sindica este blog');
+@define('YOU_CHOSE', 'Elige %s');
+@define('IMAGE_SIZE', 'Tama&ntilde;o de la imagen');
+@define('IMAGE_AS_A_LINK', 'Inserci&oacute;n de imagen');
+@define('POWERED_BY', 'Basado en');
+@define('TRACKBACKS', 'Referencias');
+@define('TRACKBACK', 'Referencia');
+@define('NO_TRACKBACKS', 'No hay referencias');
+@define('TOPICS_OF', 'Temas de');
+@define('VIEW_FULL', 'ver completo');
+@define('VIEW_TOPICS', 'ver temas');
+@define('AT', 'a las');
+@define('SET_AS_TEMPLATE', 'Mantenlo como plantilla'); 
+@define('IN', 'en');
+@define('EXCERPT', 'Segmento'); 
+@define('TRACKED', 'Tracked'); 
+@define('LINK_TO_ENTRY', 'Enlazar a la entrada');
+@define('LINK_TO_REMOTE_ENTRY', 'Enlazar a una entrada remota');
+@define('IP_ADDRESS', 'Direcci&oacute;n IP');
+@define('USER', 'Usuario');
+@define('THUMBNAIL_USING_OWN', 'Usando %s como su miniatura debido al escaso tama&ntilde;o.');
+@define('THUMBNAIL_FAILED_COPY', 'Quer&iacute;as usar %s como tu miniatura, ¡pero ha fallado la copia!');
+@define('AUTHOR', 'Autor');
+@define('LAST_UPDATED', '&Uacute;ltima actualizaci&oacute;n');
+@define('TRACKBACK_SPECIFIC', 'URI de referencia para esta entrada');
+@define('DIRECT_LINK', 'Enlace directo a esta entrada');
+@define('COMMENT_ADDED', 'Tu comentario ha sido a&ntilde;adido correctamente. ');
+@define('COMMENT_ADDED_CLICK', 'Pulsa %saqu&iacute; para volver%s a los comentarios, y %saqu&iacute; para cerrar%s esta ventana.');
+@define('COMMENT_NOT_ADDED', 'Tu comentario no ha podido ser a&ntilde;adido, la posibilidad de a&ntilde;adir comentarios a esta entrada ha sido desactivada. ');
+@define('COMMENT_NOT_ADDED_CLICK', 'Pulsa %saqu&iacute; para volver%s a los comentarios, y %saqu&iacute; para cerrar%s esta ventana');
+@define('COMMENTS_DISABLE', 'No permitir comentarios a esta entrada');
+@define('COMMENTS_ENABLE', 'Permitir comentarios a esta entrada');
+@define('COMMENTS_CLOSED', 'El autor no permite a&ntilde;adir comentarios a esta entrada');
+@define('EMPTY_COMMENT', 'Tu comentario est&aacute; vac&iacute;o, por favor %svuelve%s e int&eacute;ntalo de nuevo');
+@define('ENTRIES_FOR', 'Entradas para %s'); 
+@define('DOCUMENT_NOT_FOUND', 'El documento %s no se encontr&oacute;.');
+@define('USERNAME', 'Nombre de usuario');
+@define('PASSWORD', 'Contrase&ntilde;a');
+@define('SERENDIPITY_INSTALLATION', 'Instalaci&oacute;n de Serendipity');
+@define('LEFT', 'Izquierda');
+@define('RIGHT', 'Derecha');
+@define('HIDDEN', 'Oculto');
+@define('REMOVE_TICKED_PLUGINS', 'Quita las extensiones seleccionadas');
+@define('SAVE_CHANGES_TO_LAYOUT', 'Guarda los cambios en el dise&ntilde;o');
+@define('COMMENTS_FROM', 'Comentarios para'); 
+@define('ERROR', 'Error');
+@define('DELETE_SURE', '¿Est&aacute;s seguro de que quieres eliminar #%s permanentemente?');
+@define('NOT_REALLY', 'No...');
+@define('DUMP_IT', 'S&iacute;');
+@define('RIP_ENTRY', 'Entrada #%s borrada.');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Categor&iacute;a #%s eliminada. Los art&iacute;culos antiguos han sido movidos a la categor&iacute;a #%s');
+@define('CATEGORY_DELETED', 'Categor&iacute;a #%s eliminada.');
+@define('INVALID_CATEGORY', 'Ninguna categor&iacute;a valida para borrar');
+@define('CATEGORY_SAVED', 'Categor&iacute;a guardada');
+@define('SELECT_TEMPLATE', 'Selecciona la plantilla que deseas utilizar en tu weblog');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', '¡No se ha podido insertar las entradas!');
+@define('YES', 'S&iacute;');
+@define('NO', 'No');
+@define('USE_DEFAULT', 'Predeterminado');
+@define('CHECK_N_SAVE', 'Revisa y guarda');
+@define('DIRECTORY_WRITE_ERROR', 'No puedes escribir en el directorio %s. Comprueba los permisos.');
+@define('DIRECTORY_CREATE_ERROR', 'El directorio %s no existe y no puede ser creado. Cr&eacute;alo manualmente.');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; ejecuta <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', 'No se puede ejecutar %s');
+@define('FILE_WRITE_ERROR', 'No se puede escribir el fichero %s.');
+@define('FILE_CREATE_YOURSELF', 'Crea el fichero tu mismo o verifica los permisos');
+@define('COPY_CODE_BELOW', '<br />* Tan solo copia el c&oacute;digo situado debajo y ponlo %s dentro %s del directorio:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Cambia www por el usuario que est&aacute; ejecutando el servidor web (p. ej. nobody).');
+@define('BROWSER_RELOAD', 'Una vez hecho esto, pulsa en tu navegador el bot&oacute;n "Recargar".');
+@define('DIAGNOSTIC_ERROR', 'Hemos detectado algunos errores mientras se ejecutaban varias comprobaciones en la informaci&oacute;n que has introducido:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity no est&aacute; instalado todav&iacute;a. Por favor <a href="%s">inst&aacute;lalo</a> ahora.');
+@define('INCLUDE_ERROR', 'Error de Serendipity: no se puede incluir %s - saliendo.');
+@define('DATABASE_ERROR', 'Error de Serendipity: no es posible conectar a la base de datos - saliendo.');
+@define('CREATE_DATABASE', 'Creando la configuraci&oacute;n predeterminada de la base de datos...');
+@define('ATTEMPT_WRITE_FILE', 'Intentando escribir el fichero %s...');
+@define('WRITTEN_N_SAVED', 'Configuraci&oacute;n realizada y guardada');
+@define('IMAGE_ALIGNMENT', 'Alineaci&oacute;n de im&aacute;genes');
+@define('ENTER_NEW_NAME', 'Introduzca el nuevo nombre para: ');
+@define('RESIZING', 'Cambiando el tama&ntilde;o');
+@define('RESIZE_DONE', 'Terminado (las im&aacute;genes %s cambiaron de tama&ntilde;o).');
+@define('DELETE_IMAGE_FAIL' , 'No se puede eliminar la imagen <b>%s</b>'); 
+@define('DELETE_THUMBNAIL', 'Eliminada la imagen miniatura llamada <b>%s</b>');
+@define('FILE_NOT_FOUND', 'No es posible encontrar el fichero con nombre <b>%s</b>, ¿es posible que lo haya borrado ya?');
+@define('ABORT_NOW', 'Salir ahora');
+@define('REMOTE_FILE_NOT_FOUND', 'El fichero no fue localizado en el servidor remoto, ¿est&aacute;s seguro de que la URL: <b>%s</b> es correcta?');
+@define('FILE_FETCHED', '%s enlazado como: %s'); 
+@define('FILE_UPLOADED', 'El fichero %s fue transferido correctamente: %s');
+@define('WORD_OR', 'O...'); 
+@define('SCALING_IMAGE', 'Escalando %s a %s x %s px');
+@define('KEEP_PROPORTIONS', 'Mantener las proporciones');
+@define('REALLY_SCALE_IMAGE', '¿Realmente deseas escalar la imagen? ¡No se podr&aacute; deshacer esta acci&oacute;n!');
+@define('TOGGLE_ALL', 'Mostrar/Ocultar todo');
+@define('TOGGLE_OPTION', 'Mostrar/Ocultar');
+@define('SUBSCRIBE_TO_THIS_ENTRY', 'Suscribirse a esta entrada');
+@define('UNSUBSCRIBE_OK', "%s ya no est&aacute; suscrito a esta entrada");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'Nuevo comentario en la entrada suscrita "%s"');
+@define('SUBSCRIPTION_MAIL', "Hola %s,\n\nHay un nuevo comentario a la entrada \"%s\", titulada \"%s\"\nEl autor es: %s\n\nPuedes encontrar la entrada aqu&iacute;: %s\n\nPuedes dejar de recibir informaci&oacute;n sobre esta entrada haciendo click aqu&iacute;: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "Hola %s,\n\nHay una nueva referencia a la entrada \"%s\", titulada \"%s\"\nEl autor es: %s\n\nPuedes encontrar la entrada aqu&iacute;: %s\n\nPuedes dejar de recibir informaci&oacute;n sobre esta entrada haciendo click aqu&iacute;: %s\n");
+@define('SIGNATURE', "\n-- \n%s est&aacute; basado en Serendipity.\nEl mejor programa para blog ;).\nVisita <http://s9y.org> y compru&eacute;balo.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91 feed');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0 feed');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0 feed');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 comentarios');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3 feed');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'Campo "managingEditor"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  'Campo "webMaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'Imagen para el feed RSS');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', 'Anchura de la imagen');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'Altura de la imagen');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC', 'Correo electr&oacute;nico del webmaster, si est&aacute; disponible. (d&eacute;jalo vac&iacute;o para no mostrarlo) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', 'Correo electr&oacute;nico del editor, si est&aacute; disponible. (d&eacute;jalo vac&iacute;o para no mostrarlo) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'URL de una imagen en formato GIF/JPEG/PNG, si est&aacute; disponible. (dej&aacute;ndolo vac&iacute;o se usara el logo de Serendipity)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'en pixels, max. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'en pixels, max. 400');
+@define('SYNDICATION_PLUGIN_TTL', 'Campo "ttl" (time-to-live)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'Cantidad de minutos, despu&eacute;s de los cuales, tu blog no ser&aacute; verificado por ning&uacute;n site o aplicaci&oacute;n externa (si lo dejas vac&iacute;o no se mostrara) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'Campo "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', '¿Deber&iacute;a el campo "pubDate" estar incluido en un canal RSS para mostrar la fecha de la &uacute;ltima entrada?');
+@define('CONTENT', 'Contenido');
+@define('TYPE', 'Tipo');
+@define('DRAFT', 'Borrador');
+@define('PUBLISH', 'Publicar');
+@define('PREVIEW', 'Previsualizaci&oacute;n');
+@define('DATE', 'Fecha');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', 'Aviso: La fecha especificada no es v&aacute;lida. Debe tener el formato AAAA-MM-DD HH:MM.');
+@define('CATEGORY_PLUGIN_DESC', 'Muestra la lista de categor&iacute;as.');
+@define('ALL_AUTHORS', 'Todos los autores');
+@define('CATEGORIES_TO_FETCH', 'Categor&iacute;as enlazadas'); 
+@define('CATEGORIES_TO_FETCH_DESC', '¿De que autor quiere enlazar las categor&iacute;as?');
+@define('PAGE_BROWSE_ENTRIES', 'P&aacute;gina %s de %s, en total %s entradas');
+@define('PREVIOUS_PAGE', 'p&aacute;gina anterior');
+@define('NEXT_PAGE', 'p&aacute;gina siguiente');
+@define('ALL_CATEGORIES', 'Todas las categor&iacute;as');
+
+/* TRANSLATE */
+@define('WRONG_USERNAME_OR_PASSWORD', 'Usuario o contrase&ntilde;a err&oacute;neo');
+@define('HTACCESS_ERROR', 'Para verificar tu instalaci&oacute;n del servidor web, serendipity deber ser capaz de escribir en el fichero ".htaccess". Esto no fue posible debido a errores de permisos. Por favor, ajusta los permisos como: <br />&nbsp;%s<br />y recarga esta p&aacute;gina.');
+@define('SIDEBAR_PLUGINS', 'Extensiones de barra lateral');
+@define('EVENT_PLUGINS', 'Extensiones de eventos');
+@define('SYNCING', 'Sincronizando la base de datos con el directorio de im&aacute;genes.');
+@define('SYNC_DONE', 'Hecho (Sincronizadas %s im&aacute;genes).');
+@define('SORT_ORDER', 'Ordenar por');
+@define('SORT_ORDER_NAME', 'Nombre de fichero');
+@define('SORT_ORDER_EXTENSION', 'Extensi&oacute;n de fichero');
+@define('SORT_ORDER_SIZE', 'Tama&ntilde;o de fichero');
+@define('SORT_ORDER_WIDTH', 'Anchura de imagen');
+@define('SORT_ORDER_HEIGHT', 'Altura de imagen');
+@define('SORT_ORDER_DATE', 'Fecha de transferencia');
+@define('SORT_ORDER_ASC', 'Ascendente');
+@define('SORT_ORDER_DESC', 'Descendente');
+@define('THUMBNAIL_SHORT', 'Miniatura');
+@define('ORIGINAL_SHORT', 'Orig.');
+@define('APPLY_MARKUP_TO', 'Aplicar marca a %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'Inicio de la semana');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Se ha detectado una discrepancia entre tu configuraci&oacute;n actual que es la versi&oacute;n %s, y la de serendipity versi&oacute;n %s, ¡necesitas actualizar! <a href="%s">Haz click aqu&iacute;</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'Hola y bienvenido al agente de actualizaci&oacute;n de Serendipity.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', 'Estoy aqu&iacute; para ayudarte a actualizar tu instalaci&oacute;n %s de Serendipity.');
+@define('SERENDIPITY_UPGRADER_WHY', 'Est&aacute;s viendo este mensaje porque has instalado Serendipity %s, pero no has actualizado la instalaci&oacute;n de la base de datos para coincidir con esta versi&oacute;n');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'Actualizaciones para la base de datos (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'He encontrado los siguientes ficheros .sql que se necesitan ejecutar antes de que puedas continuar usando normalmente Serendipity');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  'Tareas espec&iacute;ficas de la versi&oacute;n');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', 'No se ha encontrado tareas espec&iacute;ficas de la versi&oacute;n');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', '¿Quieres que realice las tareas descritas?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'No, las ejecutar&eacute; manualmente');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'S&iacute;, por favor');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'Parece que no necesitas ejecutar ninguna actualizaci&oacute;n');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', 'Considera actualizado Serendipity');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'Has ignorado el paso de actualizaci&oacute;n de Serendipity, aseg&uacute;rate que tu base de datos est&aacute; correctamente instalada y que las funciones planeadas son ejecutadas.');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'Tu instalaci&oacute;n de Serendipity se ha actualizado a la versi&oacute;n %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', 'Puedes volver a tu blog haciendo click %saqu&iacute;%s');
+@define('MANAGE_USERS', 'Gesti&oacute;n de usuarios');
+@define('CREATE_NEW_USER', 'Crear nuevo usuario');
+@define('CREATE_NOT_AUTHORIZED', 'No puedes modificar usuarios con el mismo nivel que el tuyo');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'No puedes crear usuarios con un nivel mayor que el tuyo');
+@define('CREATED_USER', 'Un nuevo usuario %s se ha creado');
+@define('MODIFIED_USER', 'Las propiedades del usuario %s se han cambiado');
+@define('USER_LEVEL', 'Nivel de usuario');
+@define('DELETE_USER', 'Est&aacute;s a punto de borrar al usuario #%d %s. ¿Est&aacute;s seguro? Esto no permitir&aacute; mostrar las entradas escritas por &eacute;l.');
+@define('DELETED_USER', 'Usuario #%d %s borrado.');
+@define('LIMIT_TO_NUMBER', '¿Cu&aacute;ntos elementos deber&iacute;an mostrarse?');
+@define('ENTRIES_PER_PAGE', 'entradas por p&aacute;gina');
+@define('DIRECTORIES_AVAILABLE', 'En la lista de subdirectorios disponibles puedes hacer click en el nombre de un directorio para crear un nuevo directorio dentro de esa estructura.');
+@define('ALL_DIRECTORIES', 'todos los directorios');
+@define('MANAGE_DIRECTORIES', 'Gesti&oacute;n de directorios');
+@define('DIRECTORY_CREATED', 'Directorio <strong>%s</strong> creado.');
+@define('PARENT_DIRECTORY', 'Directorio superior');
+@define('CONFIRM_DELETE_DIRECTORY', '¿Est&aacute;s seguro de que quieres eliminar todos los contenidos del directorio %s?');
+@define('ERROR_NO_DIRECTORY', 'Error: Directorio %s no existe');
+@define('CHECKING_DIRECTORY', 'Verificar ficheros en directorio %s');
+@define('DELETING_FILE', 'Borrando fichero %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', 'No puedo borrar un directorio con ficheros. Marca "forzar borrado" si quieres eliminar tambi&eacute;n los ficheros e int&eacute;ntalo de nuevo. Los ficheros que existen son:');
+@define('DIRECTORY_DELETE_FAILED', 'Eliminaci&oacute;n del directorio %s fallida. Revisa los permisos o los mensajes anteriores.');
+@define('DIRECTORY_DELETE_SUCCESS', 'Directorio %s eliminado exitosamente.');
+@define('SKIPPING_FILE_EXTENSION', 'Saltando fichero: falta extensi&oacute;n en %s.');
+@define('SKIPPING_FILE_UNREADABLE', 'Saltando fichero: %s no se puede leer.');
+@define('FOUND_FILE', 'Encontrado fichero nuevo/modificado: %s.');
+@define('ALREADY_SUBCATEGORY', '%s es ya una subcategor&iacute;a de %s.');
+@define('PARENT_CATEGORY', 'Categor&iacute;a superior');
+@define('IN_REPLY_TO', 'En respuesta a');
+@define('TOP_LEVEL', 'Nivel superior');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s feed');
+@define('PERMISSIONS', 'Permisos');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', 'Opciones de la base de datos');
+@define('INSTALL_CAT_DB_DESC', 'Introduce aqu&iacute; la informaci&oacute;n de tu base de datos. Serendipity la necesita para funcionar');
+@define('INSTALL_DBTYPE', 'Tipo');
+@define('INSTALL_DBTYPE_DESC', 'El tipo de gestor de la base de datos');
+@define('INSTALL_DBHOST', 'Servidor');
+@define('INSTALL_DBHOST_DESC', 'El servidor donde est&aacute; el gestor de la base de datos');
+@define('INSTALL_DBUSER', 'Usuario');
+@define('INSTALL_DBUSER_DESC', 'El usuario que conecta a la base de datos');
+@define('INSTALL_DBPASS', 'Contrase&ntilde;a');
+@define('INSTALL_DBPASS_DESC', 'La contrase&ntilde;a para el usuario');
+@define('INSTALL_DBNAME', 'Nombre');
+@define('INSTALL_DBNAME_DESC', 'El nombre de la base de datos');
+@define('INSTALL_DBPREFIX', 'Prefijo');
+@define('INSTALL_DBPREFIX_DESC', 'Prefijo para los nombres de las tablas, p. ej. serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', 'Rutas');
+@define('INSTALL_CAT_PATHS_DESC', 'Varias rutas a ficheros y directorios esenciales. ¡No olvides la barra final en los directorios!');
+@define('INSTALL_FULLPATH', 'Ruta completa');
+@define('INSTALL_FULLPATH_DESC', 'La ruta completa y absoluta a tu instalaci&oacute;n de serendipity');
+@define('INSTALL_UPLOADPATH', 'Ruta para los ficheros transferidos');
+@define('INSTALL_UPLOADPATH_DESC', 'Todos los ficheros transferidos ir&aacute;n aqu&iacute;, relativo a  \'Ruta completa\' - normalmente \'uploads/\'');
+@define('INSTALL_RELPATH', 'Ruta relativa');
+@define('INSTALL_RELPATH_DESC', 'Ruta de serendipity para tu navegador, normalmente \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', 'Ruta relativa para las plantillas');
+@define('INSTALL_RELTEMPLPATH_DESC', 'Ruta al directorio que contiene tus plantillas - Relativa a la \'ruta relativa\'');
+@define('INSTALL_RELUPLOADPATH', 'Ruta relativa para los ficheros transferidos');
+@define('INSTALL_RELUPLOADPATH_DESC', 'Ruta de los ficheros transferidos - Relativa a la \'ruta relativa\'');
+@define('INSTALL_URL', 'URL para el blog');
+@define('INSTALL_URL_DESC', 'URL base de tu instalaci&oacute;n de serendipity');
+@define('INSTALL_INDEXFILE', 'Fichero &iacute;ndice');
+@define('INSTALL_INDEXFILE_DESC', 'El nombre del fichero &iacute;ndice de serendipity');
+
+/* Generel settings */
+@define('INSTALL_CAT_SETTINGS', 'Opciones generales');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Configura el comportamiento de Serendipity');
+@define('INSTALL_USERNAME', 'Usuario administrador');
+@define('INSTALL_USERNAME_DESC', 'Nombre de usuario del administrador');
+@define('INSTALL_PASSWORD', 'Contrase&ntilde;a de administrador');
+@define('INSTALL_PASSWORD_DESC', 'Contrase&ntilde;a del administrador');
+@define('INSTALL_EMAIL', 'Correo electr&oacute;nico');
+@define('INSTALL_EMAIL_DESC', 'Correo electr&oacute;nico del administrador');
+@define('INSTALL_SENDMAIL', '¿Enviar correos al administrador?');
+@define('INSTALL_SENDMAIL_DESC', '¿Quieres recibir un correo electr&oacute;nico cuando env&iacute;an comentarios a tus entradas?');
+@define('INSTALL_SUBSCRIBE', '¿Permitir la subscripci&oacute;n de los usuarios a las entradas?');
+@define('INSTALL_SUBSCRIBE_DESC', 'Permite a los usuarios subscribirse a una entrada y de ese modo recibir un correo electr&oacute;nico cuando se hacen nuevos comentarios a esa entrada');
+@define('INSTALL_BLOGNAME', 'Nombre del blog');
+@define('INSTALL_BLOGNAME_DESC', 'El t&iacute;tulo de tu blog');
+@define('INSTALL_BLOGDESC', 'Descripci&oacute;n del blog');
+@define('INSTALL_BLOGDESC_DESC', 'Descripci&oacute;n de tu blog');
+@define('INSTALL_LANG', 'Idioma');
+@define('INSTALL_LANG_DESC', 'Selecciona el idioma del blog');
+
+/* Appearance and options */
+@define('INSTALL_CAT_DISPLAY', 'Apariencia');
+@define('INSTALL_CAT_DISPLAY_DESC', 'Configura el aspecto general de Serendipity');
+@define('INSTALL_WYSIWYG', 'Usar editor WYSIWYG');
+@define('INSTALL_WYSIWYG_DESC', '¿Quieres usar el editor WYSIWYG? (Funciona con IE5+, parcialmente con Mozilla 1.3+)');
+@define('INSTALL_XHTML11', 'Forzar compatibilidad XHTML 1.1');
+@define('INSTALL_XHTML11_DESC', '¿Quieres forzar la compatibilidad XHTML 1.1? (puede causar problemas con navegadores m&aacute;s antiguos que la 4ª generaci&oacute;n)');
+@define('INSTALL_POPUP', 'Activar el uso de ventanas emergentes');
+@define('INSTALL_POPUP_DESC', '¿Quieres que el blog use una ventana emergente para los comentarios, referencias, etc.?');
+@define('INSTALL_EMBED', '¿Est&aacute; Serendipity insertado en otra web?');
+@define('INSTALL_EMBED_DESC', 'Si quieres insertar Serendipity dentro de otra p&aacute;gina, ajusta a "true" para eliminar cualquier cabecera y s&oacute;lo mostrar los contenidos. Puedes hacer uso de la opci&oacute;n indexFile y usar una clase donde pongas las cabeceras normales de tu p&aacute;gina web. ¡Lee el fichero README para m&aacute;s informaci&oacute;n!');
+@define('INSTALL_TOP_AS_LINKS', '¿Mostrar Salidas/Sitios asociados como enlaces?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"no": Las Salidas y los Sitios asociados se muestran como texto sin formato para prevenir spam en google. "yes": Las Salidas y Sitios asociando se muestran como enlaces. "default": Usar el valor de la configuraci&oacute;n global (recomendado).');
+@define('INSTALL_BLOCKREF', 'Sitios asociados bloqueados');
+@define('INSTALL_BLOCKREF_DESC', '¿Hay alg&uacute;n servidor que no quieras que se muestre en la lista de Sitios asociados? Separa la lista de nombres de dominio con \';\' y advierte que se ¡bloquea por coincidencias en subcadenas!');
+@define('INSTALL_REWRITE', 'Reescritura de URL');
+@define('INSTALL_REWRITE_DESC', 'Selecciona la regla que quieres usar para generar URL. Activando estas reglas har&aacute; URL bonitas para tu blog y lo har&aacute; m&aacute;s indexable para los robots como google. El servidor web necesita tener o mod_rewrite o "AllowOverride All" para el directorio de serendipity. El valor predeterminado es autodetectado');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', 'Opciones para la conversi&oacute;n de im&aacute;genes');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'Informaci&oacute;n sobre c&oacute;mo deber&iacute;a serendipity manejar im&aacute;genes');
+@define('INSTALL_IMAGEMAGICK', 'Usar ImageMagick');
+@define('INSTALL_IMAGEMAGICK_DESC', '¿Tienes ImageMagick instalado y quieres usarlo para redimensionar im&aacute;genes?');
+@define('INSTALL_IMAGEMAGICKPATH', 'Ruta hasta el programa convert');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'Ruta completa y nombre del programa convert de ImageMagick');
+@define('INSTALL_THUMBSUFFIX', 'Sufijo de la miniatura');
+@define('INSTALL_THUMBSUFFIX_DESC', 'Las miniaturas se crear&aacute;n con el siguiente formato: original.[sufijo].ext');
+@define('INSTALL_THUMBWIDTH', 'Dimensiones de las miniaturas');
+@define('INSTALL_THUMBWIDTH_DESC', 'Anchura m&aacute;xima est&aacute;tica de las miniaturas auto-generadas');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', 'Datos personales');
+@define('USERCONF_CAT_PERSONAL_DESC', 'Cambia los datos personales');
+@define('USERCONF_USERNAME', 'Nombre de usuario');
+@define('USERCONF_USERNAME_DESC', 'El nombre de usuario que se usa para conectar al blog');
+@define('USERCONF_PASSWORD', 'Contrase&ntilde;a');
+@define('USERCONF_PASSWORD_DESC', 'La contrase&ntilde;a que se usar&aacute; para conectar al blog');
+@define('USERCONF_EMAIL', 'Correo electr&oacute;nico');
+@define('USERCONF_EMAIL_DESC', 'La direcci&oacute;n de correo electr&oacute;nico personal');
+@define('USERCONF_SENDCOMMENTS', '¿Enviar avisos de comentarios?');
+@define('USERCONF_SENDCOMMENTS_DESC', '¿Recibir correos electr&oacute;nicos cuando ponen comentarios en las entradas?');
+@define('USERCONF_SENDTRACKBACKS', '¿Enviar avisos de referencias?');
+@define('USERCONF_SENDTRACKBACKS_DESC', '¿Recibir correos electr&oacute;nicos cuando hacen referencias a las entradas?');
+@define('USERCONF_ALLOWPUBLISH', 'Derechos: ¿Publicar entradas?');
+@define('USERCONF_ALLOWPUBLISH_DESC', '¿El usuario puede publicar entradas?');
+@define('XML_IMAGE_TO_DISPLAY', 'Bot&oacute;n XML');
+@define('XML_IMAGE_TO_DISPLAY_DESC','Enlaces a feeds XML se mostrar&aacute;n con esta imagen. D&eacute;jalo vac&iacute;o para el valor predeterminado, introduce \'none\' para desactivar.');
+@define('ENTRY_SAVED', 'Tu entrada ha sido guardada');
+@define('SUCCESS', '&Eacute;xito');
+
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', ',');
+@define('NUMBER_FORMAT_THOUSANDS', '.');
+
+@define('POWERED_BY_SHOW_TEXT', 'Mostrar "Serendipity" como texto');
+@define('POWERED_BY_SHOW_TEXT_DESC', 'Mostrar&aacute; "Serendipity Weblog" como texto');
+@define('POWERED_BY_SHOW_IMAGE', 'Mostrar "Serendipity" con una imagen');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Mostrar&aacute; el logotipo de Serendipity');
+/* TRANSLATE */
+@define('SETTINGS_SAVED_AT', 'La nueva configuraci&oacute;n se ha guardado en la hora %s');
+@define('PLUGIN_ITEM_DISPLAY', '¿D&oacute;nde deber&iacute;a mostrarse el elemento?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'S&oacute;lo en la entrada extendida');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'S&oacute;lo en la entrada general');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'Siempre');
+@define('RSS_IMPORT_CATEGORY', 'Usa esta categor&iacute;a para las entradas importadas que no coincidan');
+@define('ERROR_UNKNOWN_NOUPLOAD', 'Ocurri&oacute; un error desconocido, fichero no importado. Quiz&aacute;s el tama&ntilde;o del fichero es mayor que el tama&ntilde;o m&aacute;ximo permitido por tu instalaci&oacute;n. Verifica con tu ISP o edita tu fichero php.ini para permitir transferir ficheros de tama&ntilde;o m&aacute;s grande.');
+@define('COMMENTS_WILL_BE_MODERATED', 'Los comentarios enviados ser&aacute;n sometidos a moderaci&oacute;n antes de ser mostrados.');
+@define('YOU_HAVE_THESE_OPTIONS', 'Tienes disponibles las siguientes opciones:');
+@define('THIS_COMMENT_NEEDS_REVIEW', 'Aviso: Este comentario necesita aprobaci&oacute;n antes de que se muestre');
+@define('DELETE_COMMENT', 'Borrar comentario');
+@define('APPROVE_COMMENT', 'Aprobar comentario');
+@define('REQUIRES_REVIEW', 'Requiere revisi&oacute;n');
+@define('COMMENT_APPROVED', 'El comentario #%s ha sido aprobado exitosamente');
+@define('COMMENT_DELETED', 'El comentario #%s ha sido borrado exitosamente');
+@define('VIEW', 'Ver');
+@define('COMMENT_ALREADY_APPROVED', 'El comentario #%s ya parece haber sido aprobado');
+@define('COMMENT_EDITED', 'El comentario seleccionado ha sido editado');
+@define('HIDE', 'Ocultar');
+@define('VIEW_EXTENDED_ENTRY', 'Continua leyendo "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'Este enlace no es para hacer click en &eacute;l. Contiene la URI de referencia para esta entrada. Puedes usar esta URI para enviar "ping-" y "trackbacks" desde tu propio blog a esta entrada. Para copiar el enlace, haz click con el bot&oacute;n derecho y selecciona "Copy Shortcut" en Internet Explorer o "Copy Link Location" en Mozilla.');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'Aviso: Esta referencia necesita aprobaci&oacute;n antes de que se muestre');
+@define('DELETE_TRACKBACK', 'Borrar referencia');
+@define('APPROVE_TRACKBACK', 'Aprobar referencia');
+@define('TRACKBACK_APPROVED', 'La referencia #%s ha sido aprobada exitosamente');
+@define('TRACKBACK_DELETED', 'La referencia #%s ha sido borrado exitosamente');
+@define('COMMENTS_MODERATE', 'Comentarios y referencias a esta entrada requieren moderaci&oacute;n');
+@define('PLUGIN_SUPERUSER_HTTPS', 'Usar https para conectar');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'Hacer que el enlace para conectar apunte a una conexi&oacute;n https. ¡Tu servidor web necesita soporte para esto!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', '¿Poder hacer click en los enlaces externos?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"no": Enlaces externos no verificados (Top Salidas, Top Sitios asociados, Comentarios de usuarios) no se muestran/se muestran como texto sin formato donde se pueda para prevenir spam de google (recomendado). "yes": Enlaces externos no verificados se muestran como enlaces. ¡Puede ser modificado en la configuraci&oacute;n del plugin de la barra lateral!');
+@define('PAGE_BROWSE_COMMENTS', 'P&aacute;gina %s de %s, total %s comentarios');
+@define('FILTERS', 'Filtros');
+@define('FIND_ENTRIES', 'Encontrar entradas');
+@define('FIND_COMMENTS', 'Encontrar comentarios');
+@define('FIND_MEDIA', 'Encontrar medios');
+@define('FILTER_DIRECTORY', 'Directorio');
+@define('SORT_BY', 'Ordenaci&oacute;n');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'No se ha enviado la referencia: No se pudo establecer conexi&oacute;n con %s en el puerto %d');
+@define('MEDIA', 'Medios');
+@define('MEDIA_LIBRARY', 'Biblioteca de medios');
+@define('ADD_MEDIA', 'A&ntilde;adir medio');
+@define('ENTER_MEDIA_URL', 'Introduce una URL para obtener el fichero:');
+@define('ENTER_MEDIA_UPLOAD', 'Selecciona el fichero que quieres transferir:');
+@define('SAVE_FILE_AS', 'Guardar el fichero como:');
+@define('STORE_IN_DIRECTORY', 'Almacenar dentro del siguiente directorio: ');
+@define('MEDIA_RENAME', 'Renombrar este fichero');
+@define('IMAGE_RESIZE', 'Redimensionar esta imagen');
+@define('MEDIA_DELETE', 'Borrar este fichero');
+@define('FILES_PER_PAGE', 'Ficheros por p&aacute;gina');
+@define('CLICK_FILE_TO_INSERT', 'Haz click en el fichero que quieres insertar:');
+@define('SELECT_FILE', 'Selecciona el fichero a insertar');
+@define('MEDIA_FULLSIZE', 'Tama&ntilde;o real');
+@define('CALENDAR_BOW_DESC', 'El d&iacute;a de la semana que debe considerarse como principio de semana. El predeterminado es el lunes');
+@define('SUPERUSER', 'Administraci&oacute;n del Blog');
+@define('ALLOWS_YOU_BLAHBLAH', 'Muestra un enlace en la barra lateral para acceder a la administraci&oacute;n de tu blog');
+@define('CALENDAR', 'Calendario');
+@define('SUPERUSER_OPEN_ADMIN', 'Abre administraci&oacute;n');
+@define('SUPERUSER_OPEN_LOGIN', 'Abre ventana de conexi&oacute;n');
+@define('INVERT_SELECTIONS', 'Invertir selecciones');
+@define('COMMENTS_DELETE_CONFIRM', '¿Est&aacute;s seguro que deseas eliminar los comentarios seleccionados?');
+@define('COMMENT_DELETE_CONFIRM', '¿Est&aacute;s seguro que deseas eliminar el comentario #%d, escrito por %s?');
+@define('DELETE_SELECTED_COMMENTS', 'Borrar comentarios seleccionados');
+@define('VIEW_COMMENT', 'Ver comentario');
+@define('VIEW_ENTRY', 'Ver entrada');
+@define('DELETE_FILE', 'Borrado el fichero llamado <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', 'Est&aacute;s a punto de borrar <b>%s</b><br />Si est&aacute;s usando este fichero en alguna de tus entradas, esto causar&aacute; enlaces o im&aacute;genes rotos<br />¿Est&aacute;s seguro de que quieres seguir?<br /><br />');
+@define('TRACKBACK_SENDING', 'Enviando referencia a la URI %s...');
+@define('TRACKBACK_SENT', 'Referencia exitosa');
+@define('TRACKBACK_FAILED', 'Referencia fallida: %s');
+@define('TRACKBACK_NOT_FOUND', 'No encontrada URI de referencia.');
+@define('TRACKBACK_URI_MISMATCH', 'La referencia autodetectada no coincide con nuestra URI destino.');
+@define('TRACKBACK_CHECKING', 'Comprobando <u>%s</u> para posibles referencias...');
+@define('TRACKBACK_NO_DATA', 'Destino no conten&iacute;a datos');
+@define('TRACKBACK_SIZE', 'La URI de destino excedi&oacute; el tama&ntilde;o de fichero m&aacute;ximo de %s bytes.');
+@define('VIEWMODE_THREADED', 'Cambiar a vista por hilos');
+@define('COMMENTS_VIEWMODE_THREADED', 'Hilos');
+@define('COMMENTS_VIEWMODE_LINEAR', 'Plano');
+@define('DISPLAY_COMMENTS_AS', 'Mostrar comentarios como');
+@define('LOGIN', 'Conectar');
+@define('AUTOMATIC_LOGIN', 'Guardar informaci&oacute;n');
+@define('DO_MARKUP', 'Realizar transformaciones marcas');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'Formato de fecha');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'El formato de fecha de la entrada actual, usa las variables strftime() de PHP. (Predeterminado: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'Incapaz de abrir el fichero plantilla, ¡por favor actualiza serendipity!');
+@define('ADVANCED_OPTIONS', 'Opciones avanzadas');
+@define('EDIT_ENTRY', 'Editar entrada');
+@define('ADD_MEDIA_BLAHBLAH', '<b>A&ntilde;ade un fichero a tu colecci&oacute;n de medios:</b><p>Desde aqu&iacute; puedes transferir un fichero de medios o puedes decirme que los coja de alg&uacute;n ¡lugar de la web! Si no tienes una imagen apropiada, <a href="http://images.google.com" target="_blank">busca im&aacute;genes en google</a> que vaya con tu forma de pensar, los resultados son &uacute;tiles y divertidos a veces :)<p><b>Selecciona el m&eacute;todo:</b><br>');
+@define('COMMENTS_FILTER_SHOW', 'Mostrar');
+@define('COMMENTS_FILTER_ALL', 'Todo');
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'S&oacute;lo lo aprobado');
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'Pendiente de aprobaci&oacute;n');
+@define('RSS_IMPORT_BODYONLY', 'Pon todo el texto importado en el "cuerpo" y no lo separes en la secci&oacute;n "entrada extendida".');
+@define('SYNDICATION_PLUGIN_FULLFEED', 'Mostrar los art&iacute;culos completos con la entrada extendida dentro del feed RSS');
+@define('MT_DATA_FILE', 'fichero de datos de Movable Type');
+@define('FORCE', 'Forzar');
+@define('CREATE_AUTHOR', 'Crear autor \'%s\'.');
+@define('CREATE_CATEGORY', 'Crear categor&iacute;a \'%s\'.');
+@define('MYSQL_REQUIRED', 'Debes tener la extensi&oacute;n MySQL para poder llevar a cabo esta acci&oacute;n.');
+@define('COULDNT_CONNECT', 'No se puede conectar al gestor de base de datos MySQL: %s.');
+@define('COULDNT_SELECT_DB', 'No se puede seleccionar la base de datos: %s.');
+@define('COULDNT_SELECT_USER_INFO', 'No se puede seleccionar la informaci&oacute;n del usuario: %s.');
+@define('COULDNT_SELECT_CATEGORY_INFO', 'No se puede seleccionar la informaci&oacute;n de la categor&iacute;a: %s.');
+@define('COULDNT_SELECT_ENTRY_INFO', 'No se puede seleccionar la informaci&oacute;n de la entrada: %s.');
+@define('COULDNT_SELECT_COMMENT_INFO', 'No se puede seleccionar la informaci&oacute;n del comentario: %s.');
+@define('WEEK', 'Semana');
+@define('WEEKS', 'Semanas');
+@define('MONTHS', 'Meses');
+@define('DAYS', 'D&iacute;as');
+@define('ARCHIVE_FREQUENCY', 'Frecuencia de los elementos del Calendario');
+@define('ARCHIVE_FREQUENCY_DESC', 'El intervalo temporal a usar entre cada elemento en la lista');
+@define('ARCHIVE_COUNT', 'N&uacute;mero de elementos en la lista');
+@define('ARCHIVE_COUNT_DESC', 'El n&uacute;mero total de meses, semanas o d&iacute;as que se visualizan');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'Abajo est&aacute; la lista de las extensiones instaladas');
+@define('SIDEBAR_PLUGIN', 'extensi&oacute;n de barra lateral');
+@define('EVENT_PLUGIN', 'extensi&oacute;n de evento');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'Click aqu&iacute; para instalar una nueva %s');
+@define('VERSION', 'versi&oacute;n');
+@define('INSTALL', 'Instalar');
+@define('ALREADY_INSTALLED', 'Ya est&aacute; instalado');
+@define('SELECT_A_PLUGIN_TO_ADD', 'Selecciona la extensi&oacute;n que quieras instalar');
+@define('INSTALL_OFFSET', 'Diferencia horaria del servidor');
+@define('STICKY_POSTINGS', 'Entradas permanentes');
+@define('INSTALL_FETCHLIMIT', 'Entradas a mostrar en la p&aacute;gina principal');
+@define('INSTALL_FETCHLIMIT_DESC', 'N&uacute;mero de entradas a mostrar en la p&aacute;gina principal');
+@define('IMPORT_ENTRIES', 'Importar entradas');
+@define('EXPORT_ENTRIES', 'Exportar entradas');
+@define('IMPORT_WELCOME', 'Bienvenido a la utilidad de importaci&oacute;n de Serendipity');
+@define('IMPORT_WHAT_CAN', 'Aqu&iacute; puedes importar entradas producidas en otros programas de weblog');
+@define('IMPORT_SELECT', 'Por favor selecciona el software desde el que quieres importar');
+@define('IMPORT_PLEASE_ENTER', 'Por favor introduce los datos como se requiere debajo');
+@define('IMPORT_NOW', '¡Importar ahora!');
+@define('IMPORT_STARTING', 'Iniciando procedimiento de importaci&oacute;n...');
+@define('IMPORT_FAILED', 'Importaci&oacute;n fallida');
+@define('IMPORT_DONE', 'Importaci&oacute;n completada con &eacute;xito');
+@define('IMPORT_WEBLOG_APP', 'Aplicaci&oacute;n weblog');
+@define('EXPORT_FEED', 'Exportar el feed RSS completo');
+@define('STATUS', 'Estatus despu&eacute;s de importar');
+@define('IMPORT_GENERIC_RSS', 'Importar RSS gen&eacute;rico');
+@define('ACTIVATE_AUTODISCOVERY', 'Enviar referencias a los enlaces encontrados en la entrada');
+@define('WELCOME_TO_ADMIN', 'Bienvenido a la Suite de Administraci&oacute;n de Serendipity.');
+@define('PLEASE_ENTER_CREDENTIALS', 'Por favor introduce tus credenciales abajo.');
+@define('ADMIN_FOOTER_POWERED_BY', 'Basado en Serendipity %s y PHP %s');
+@define('INSTALL_USEGZIP', 'Usar p&aacute;ginas comprimidas con gzip');
+@define('INSTALL_USEGZIP_DESC', 'Para acelerar el env&iacute;o de p&aacute;ginas, se pueden comprimir las p&aacute;ginas que se env&iacute;an al visitante, si su navegador lo admite. Esto es lo recomendado');
+@define('INSTALL_SHOWFUTURE', 'Mostrar entradas futuras');
+@define('INSTALL_SHOWFUTURE_DESC', 'Si se activa, mostrar&aacute; todas las entradas con fecha futura en tu blog. La acci&oacute;n predeterminada es no mostrar esas entradas y s&oacute;lo hacerlo cuando llegue la fecha de publicaci&oacute;n.');
+@define('INSTALL_DBPERSISTENT', 'Usar conexiones persistentes');
+@define('INSTALL_DBPERSISTENT_DESC', 'Activar el uso de conexiones persistentes a la base de datos, lee m&aacute;s en <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">here</a>. Normalmente no se recomienda esto');
+@define('NO_IMAGES_FOUND', 'No se encontraron im&aacute;genes');
+@define('PERSONAL_SETTINGS', 'Configuraci&oacute;n personal');
+@define('REFERER', 'Referer');
+@define('NOT_FOUND', 'No encontrado');
+@define('NOT_WRITABLE', 'No se puede escribir');
+@define('WRITABLE', 'Se puede escribir');
+@define('PROBLEM_DIAGNOSTIC', 'Debido a los problemas encontrados, no puedes continuar con la instalaci&oacute;n sin antes arreglar los errores se&ntilde;alados');
+@define('SELECT_INSTALLATION_TYPE', 'Selecciona qu&eacute; tipo de instalaci&oacute;n quieres usar');
+@define('WELCOME_TO_INSTALLATION', 'Bienvenido a la Instalaci&oacute;n de Serendipity');
+@define('FIRST_WE_TAKE_A_LOOK', 'Primero determinaremos tu configuraci&oacute;n actual e intentaremos diagnosticar cualquier problema de compatibilidad');
+@define('ERRORS_ARE_DISPLAYED_IN', 'Los errores se muestran en %s, las recomendaciones en %s y lo bien configurado en %s');
+@define('RED', 'rojo');
+@define('YELLOW', 'amarillo');
+@define('GREEN', 'verde');
+@define('PRE_INSTALLATION_REPORT', 'Informe de preinstalaci&oacute;n de Serendipity v%s');
+@define('RECOMMENDED', 'Recomendado');
+@define('ACTUAL', 'Actual');
+@define('PHPINI_CONFIGURATION', 'Configuraci&oacute;n de php.ini');
+@define('PHP_INSTALLATION', 'Instalaci&oacute;n de PHP');
+@define('THEY_DO', 'existen');
+@define('THEY_DONT', 'no existen');
+@define('SIMPLE_INSTALLATION', 'Instalaci&oacute;n simple');
+@define('EXPERT_INSTALLATION', 'Instalaci&oacute;n avanzada');
+@define('COMPLETE_INSTALLATION', 'Completar instalaci&oacute;n');
+@define('WONT_INSTALL_DB_AGAIN', 'no se instalar&aacute; de nuevo la base de datos');
+@define('CHECK_DATABASE_EXISTS', 'Comprobando si la base de datos y las tablas ya existen');
+@define('CREATING_PRIMARY_AUTHOR', 'Creando el autor principal \'%s\'');
+@define('SETTING_DEFAULT_TEMPLATE', 'Configurando la plantilla predeterminada');
+@define('INSTALLING_DEFAULT_PLUGINS', 'Instalando extensiones predeterminadas');
+@define('SERENDIPITY_INSTALLED', 'Serendipity se ha instalado exitosamente');
+@define('VISIT_BLOG_HERE', 'Visita tu nuevo blog aqu&iacute;');
+@define('THANK_YOU_FOR_CHOOSING', 'Gracias por elegir Serendipity');
+@define('ERROR_DETECTED_IN_INSTALL', 'Se detect&oacute; un error en la instalaci&oacute;n');
+@define('OPERATING_SYSTEM', 'Sistema operativo');
+@define('WEBSERVER_SAPI', 'Webserver SAPI');
+@define('TEMPLATE_SET', '\'%s\' ha sido configurada como tu plantilla activa');
+@define('SEARCH_ERROR', 'La funci&oacute;n de b&uacute;squeda no funcion&oacute; como se esperaba. Aviso para el administrador de este blog: esto ocurre porque faltan claves de &iacute;ndice en tu base de datos. En sistemas MySQL tu cuenta de usuario en la base de datos necesita tener privilegios para ejecutar esta consulta: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> El error espec&iacute;fico devuelto por la base de datos fue: <pre>%s</pre>');
+@define('EDIT_THIS_CAT', 'Editando "%s"');
+@define('CATEGORY_REMAINING', 'Borra esta categor&iacute;a y mueve sus entradas a esta categor&iacute;a');
+@define('CATEGORY_INDEX', 'Abajo se muestra una lista de las categor&iacute;as disponibles para tus entradas');
+@define('NO_CATEGORIES', 'No hay categor&iacute;as');
+@define('RESET_DATE', 'Volver a poner la fecha');
+@define('RESET_DATE_DESC', 'Click aqu&iacute; para poner la fecha actual');
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Los permisos se pueden modificar ejecutando: `<em>%s</em>` sobre el directorio que ha fallado, lo puedes hacer desde la l&iacute;nea de comandos o usando un programa FTP');
+@define('WARNING_TEMPLATE_DEPRECATED', 'Aviso: Tu plantilla actual est&aacute; usando un m&eacute;todo obsoleto de plantillas, actual&iacute;zala si es posible');
+@define('ENTRY_PUBLISHED_FUTURE', 'Esta entrada no se ha publicado todav&iacute;a.');
+@define('ENTRIES_BY', 'Entradas por %s');
+@define('PREVIOUS', 'Anterior');
+@define('NEXT', 'Siguiente');
+@define('APPROVE', 'Aprobar');
+@define('DO_MARKUP_DESCRIPTION', 'Aplicar transformaciones de marcas al texto (caras, marcas abreviadas como *. /, _, ...). Desactivando esto preservar&aacute; cualquier c&oacute;digo HTML en el texto.');
+@define('CATEGORY_ALREADY_EXIST', 'Una categor&iacute;a con el nombre "%s" ya existe');
+@define('IMPORT_NOTES', 'Nota:');
+@define('ERROR_FILE_FORBIDDEN', 'No te est&aacute; permitido transferir ficheros con contenido activo');
+@define('ADMIN', 'Administraci&oacute;n');
+@define('ADMIN_FRONTPAGE', 'P&aacute;gina principal');
+@define('QUOTE', 'Quote');
+@define('IFRAME_SAVE', 'Serendipity est&aacute; guardando tu entrada, creando referencias y llevando a cabo las posibles llamadas XML-RPC. Esto puede durar un tiempo..');
+@define('IFRAME_SAVE_DRAFT', 'Se ha guardado un borrador de esta entrada');
+@define('IFRAME_PREVIEW', 'Serendipity est&aacute; creando la vista previa de tu entrada...');
+@define('IFRAME_WARNING', 'Tu navegador no admite el concepto de "iframes". Por favor, edita tu fichero serendipity_config.inc.php y ajusta la variable $serendipity[\'use_iframe\'] a FALSE.');
+@define('NONE', 'ninguno');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Configuraci&oacute;n predeterminada para las nuevas entradas');
+@define('UPGRADE', 'Actualizar');
+@define('UPGRADE_TO_VERSION', 'Actualizar a la versi&oacute;n %s');
+@define('DELETE_DIRECTORY', 'Borrar directorio');
+@define('DELETE_DIRECTORY_DESC', 'Est&aacute;s a punto de borrar los contenidos de un directorio que contiene ficheros de medios, posiblemente ficheros utilizados en algunas de tus entradas.');
+@define('FORCE_DELETE', 'Borrar TODOS los ficheros de este directorio, incluyendo aquellos desconocidos para Serendipity');
+@define('CREATE_DIRECTORY', 'Crear directorio');
+@define('CREATE_NEW_DIRECTORY', 'Crear nuevo directorio');
+@define('CREATE_DIRECTORY_DESC', 'Aqu&iacute; puedes crear un nuevo directorio para almacenar ficheros de medios. Escoge el nombre del nuevo directorio y selecciona un directorio superior (opcional) donde ponerlo.');
+@define('BASE_DIRECTORY', 'Directorio base');
+@define('USERLEVEL_EDITOR_DESC', 'Editor est&aacute;ndar');
+@define('USERLEVEL_CHIEF_DESC', 'Editor jefe');
+@define('USERLEVEL_ADMIN_DESC', 'Administrador');
+@define('USERCONF_USERLEVEL', 'Nivel de acceso');
+@define('USERCONF_USERLEVEL_DESC', 'Este nivel se usa para determinar que clase de acceso al blog tiene el usuario');
+@define('USER_SELF_INFO', 'Conectado como %s (%s)');
+@define('ADMIN_ENTRIES', 'Entradas');
+@define('RECHECK_INSTALLATION', 'Volver a comprobar la instalaci&oacute;n');
+@define('IMAGICK_EXEC_ERROR', 'Incapaz de ejecutar: "%s", error: %s, variable devuelta: %d');
+@define('INSTALL_OFFSET_DESC', 'Introduce la diferencia de horas entre la fecha de tu servidor web (actual: %clock%) y la zona horaria deseada');
+@define('UNMET_REQUIREMENTS', 'Requisitos no alcanzados: %s');
+@define('CHARSET', 'Juego de caracteres');
+@define('AUTOLANG', 'Usar el lenguaje del navegador del visitante como predeterminado');
+@define('AUTOLANG_DESC', 'Si est&aacute; activado, se usar&aacute; la configuraci&oacute;n de lenguaje del navegador del visitante para determinar el lenguaje predeterminado de tu entrada as&iacute; como de la interfaz.');
+@define('INSTALL_AUTODETECT_URL', 'Autodetectar HTTP-Host usado');
+@define('INSTALL_AUTODETECT_URL_DESC', 'Si se configura como "S&iacute;", Serendipity asegurar&aacute; que el nombre de Host HTTP que us&oacute; por tu visitante para acceder al blog se usa como la URL base. Activando esto te permitir&aacute; usar varios nombres de dominio para tu blog, y usar ese dominio para todos los enlaces que siga el usuario.');
+@define('CONVERT_HTMLENTITIES', '¿Intentar autoconvertir las entidades HTML?');
+@define('EMPTY_SETTING', '¡No especificaste un valor v&aacute;lido para "%s"!');
+@define('USERCONF_REALNAME', 'Nombre real');
+@define('USERCONF_REALNAME_DESC', 'El nombre completo del autor. Este es el nombre que ver&aacute;n los lectores.');
+@define('HOTLINK_DONE', 'Fichero como recurso externo enlazado.<br />Hecho.');
+@define('ENTER_MEDIA_URL_METHOD', 'M&eacute;todo de obtenci&oacute;n:');
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Nota: Enlazar recursos externos te permite usar im&aacute;genes externas sin almacernalas localmente. Si escoges esto, aseg&uacute;rate de que tienes permiso para hacerlo en el servidor externo o bien el servidor es tuyo.');
+@define('MEDIA_HOTLINKED', 'enlazado externamente');
+@define('FETCH_METHOD_IMAGE', 'Descargar imagen a tu servidor');
+@define('FETCH_METHOD_HOTLINK', 'Enlazar externamente al servidor');
+@define('DELETE_HOTLINK_FILE', 'Borrado el recurso enlazado externamente con el nombre <b>%s</b>');
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Show E-Mail addresses?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_fa.inc.php b/lang/serendipity_lang_fa.inc.php
new file mode 100644 (file)
index 0000000..26790bc
--- /dev/null
@@ -0,0 +1,670 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved. See LICENSE file for licensing details
+# this translation, translated by Omid Mottaghi <http://oxygenws.com>
+# Please report me any bug with <webmaster@oxygenws.com>
+
+@define('LANG_CHARSET', 'UTF-8');
+@define('DATE_LOCALES', 'fa_IR, persian, fa');
+@define('DATE_FORMAT_ENTRY', '%A, %B %e. %Y');
+@define('DATE_FORMAT_SHORT', '%Y-%m-%d %H:%M');
+@define('WYSIWYG_LANG', 'fa');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', '.');
+@define('NUMBER_FORMAT_THOUSANDS', ',');
+@define('LANG_DIRECTION', 'rtl');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'بخش مدیریت Serendipity');
+@define('HAVE_TO_BE_LOGGED_ON', 'برای مشاهده این صفحه باید وارد سیستم شوید');
+@define('WRONG_USERNAME_OR_PASSWORD', 'نام کاربری یا رمز عبور شما اشتباه می باشد');
+@define('APPEARANCE', 'ظاهر');
+@define('MANAGE_STYLES', 'مدیریت پوسته ها');
+@define('CONFIGURE_PLUGINS', 'مدیریت افزونه ها');
+@define('CONFIGURATION', 'تنظیمات');
+@define('BACK_TO_BLOG', 'بازگشت به وبلاگ');
+@define('LOGIN', 'ورود');
+@define('LOGOUT', 'خروج');
+@define('LOGGEDOUT', 'خارج شدید.');
+@define('CREATE', 'ایجاد');
+@define('SAVE', 'ذخیره');
+@define('NAME', 'نام');
+@define('CREATE_NEW_CAT', 'ایجاد یک موضوع جدید');
+@define('I_WANT_THUMB', 'استفاده از کوچک شده عکس در ارسال.');
+@define('I_WANT_BIG_IMAGE', 'استفاده از عکس  اصلی در ارسال.');
+@define('I_WANT_NO_LINK', ' تمایل دارم به صورت عکس نمایش داده شود');
+@define('I_WANT_IT_TO_LINK', 'تمایل دارم به صورت لینکی به آدرس زیر نمایش داده شود:');
+@define('BACK', 'قبل');
+@define('FORWARD', 'بعد');
+@define('ANONYMOUS', 'ناشناس');
+@define('NEW_TRACKBACK_TO', 'یک ردپا جدید برای');
+@define('NEW_COMMENT_TO', 'یک نظر جدید برای');
+@define('RECENT', 'جدید...');
+@define('OLDER', 'قدیمی...');
+@define('DONE', 'انجام شد');
+@define('WELCOME_BACK', 'خوش آمدید،');
+@define('TITLE', 'تیتر');
+@define('DESCRIPTION', 'توضیحات');
+@define('PLACEMENT', 'گماشتن');
+@define('DELETE', 'حذف');
+@define('SAVE', 'ذخیره');
+@define('UP', 'بالا');
+@define('DOWN', 'پایین');
+@define('ENTRIES', 'ارسال ها');
+@define('NEW_ENTRY', 'ارسال جدید');
+@define('EDIT_ENTRIES', 'تغییر ارسال ها');
+@define('CATEGORIES', 'موضوعات');
+@define('WARNING_THIS_BLAHBLAH', "توجه:\\nدر صورتی که تعداد عکس هایی که نمونه عکس نداشته باشند زیاد باشد، ای عمل طول خواهد کشید.");
+@define('CREATE_THUMBS', 'دوباره سازی عکس های کوچک');
+@define('MANAGE_IMAGES', 'مدیریت عکس ها');
+@define('NAME', 'نام');
+@define('EMAIL', 'پست الکترونیکی');
+@define('HOMEPAGE', 'سایت');
+@define('COMMENT', 'نظر');
+@define('REMEMBER_INFO', 'آیا اطلاعات را به یاد داشته باشم؟ ');
+@define('SUBMIT_COMMENT', 'ارسال نظر');
+@define('NO_ENTRIES_TO_PRINT', 'هیچ ارسالی وجود ندارد');
+@define('COMMENTS', 'نظر ها');
+@define('ADD_COMMENT', 'ارسال نظر');
+@define('NO_COMMENTS', 'نظری وجود ندارد');
+@define('POSTED_BY', 'ارسال شده توسط');
+@define('ON', 'در');
+@define('A_NEW_COMMENT_BLAHBLAH', 'یک نظر جدید برای وبلاگ "%s"، در مورد "%s" ارسال شده است.');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'یک ردپا جدید در مورد "%s" ساخته شد.');
+@define('NO_CATEGORY', 'بدون موضوع');
+@define('ENTRY_BODY', 'بدنه ارسال');
+@define('EXTENDED_BODY', 'مطالب بیشتر');
+@define('CATEGORY', 'موضوع');
+@define('EDIT', 'ویرایش');
+@define('NO_ENTRIES_BLAHBLAH', 'هیچ مقداری برای گزارش %s پیدا نشد' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'جستجو برای عبارت %s، %s نتیجه برگردانید:');
+@define('SEARCH_TOO_SHORT', 'جستجوی شما باید بیشتر از 3 حرف باشد');
+@define('IMAGE', 'عکس');
+@define('ERROR_FILE_NOT_EXISTS', 'خطا: فایل های قدیمی وجود ندارند!');
+@define('ERROR_FILE_EXISTS', 'خطا: فایلی با این نام وجود دارد، نام دیگری انتخاب کنید!');
+@define('ERROR_SOMETHING', 'خطا: مشکلی وجود دارد.');
+@define('ADDING_IMAGE', 'افزودن عکس...');
+@define('THUMB_CREATED_DONE', 'عکس های کوچک ساخته شدند.<br>انجام شد.');
+@define('ERROR_FILE_EXISTS_ALREADY', 'خطا: این فایل قبلا در سیستم وجود داشته است!');
+@define('ERROR_UNKNOWN_NOUPLOAD', 'خطای ناشناخته، فایلی بالاگذاری نشد. ممکن است که حجم فایل شما بیشتر از ماکزیمم حجم اجازه داده شده باشد. لطفا ISP یا فایل php.ini خود را چک کنید.');
+@define('GO', 'برو!');
+@define('NEWSIZE', 'سایز جدید: ');
+@define('RESIZE_BLAHBLAH', '<b>تغییر سایز %s</b><p>');
+@define('ORIGINAL_SIZE', 'ابعاد اصلی: <i>%sx%s</i> پیکسل');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>در این مکان، شما می توانید ابعاد عکس را درست کنید. اگر تصمیم دارید ابعاد عکس را متناسب تغییر دهید، فقط یکی از اعداد را وارد کرده و سپس کلید TAB را فشار دهید --  من ضلع دیگر را به صورت متناسب تغییر خواهم داد</p>');
+@define('QUICKJUMP_CALENDAR', 'تقویم برای پرش سریع');
+@define('QUICKSEARCH', 'جستجوی سریع');
+@define('SEARCH_FOR_ENTRY', 'جستجو');
+@define('ARCHIVES', 'بایگانی');
+@define('BROWSE_ARCHIVES', 'پیمایش ماهیانه بایگانی');
+@define('TOP_REFERRER', 'بیشترین مراجعه کننده ها');
+@define('SHOWS_TOP_SITES', 'نمایش برترین هایی که به وبلاگ شما لینک داده اند');
+@define('TOP_EXITS', 'بیشترین خروج ها');
+@define('SHOWS_TOP_EXIT', 'نمایش بیشترین خروج ها از طریق لینک');
+@define('SYNDICATION', 'اتصال دهنده');
+@define('SHOWS_RSS_BLAHBLAH', 'نمایش لینک های RSS');
+@define('ADVERTISES_BLAHBLAH', 'تبلیغات سیستم این وبلاگ');
+@define('HTML_NUGGET', 'تکه کد HTML');
+@define('HOLDS_A_BLAHBLAH', 'تکه کدی از HTML را در نوار کناری داشته باشید');
+@define('TITLE_FOR_NUGGET', 'تیتر تکه کد HTML');
+@define('THE_NUGGET', 'تکه کد HTML!');
+@define('SYNDICATE_THIS_BLOG', 'متحد شدن با این وبلاگ');
+@define('YOU_CHOSE', 'شما %s را انتخاب کردید');
+@define('IMAGE_ROTATE_LEFT', 'عکس را 90 درجه بر خلاف حرکت عقربه های ساعت بچرخوان');
+@define('IMAGE_ROTATE_RIGHT', 'عکس را 90 درجه در جهت حرکت عقربه های ساعت بچرخوان');
+@define('IMAGE_SIZE', 'ابعاد عکس');
+@define('IMAGE_AS_A_LINK', 'وارد کردن عکس');
+@define('POWERED_BY', 'قدرتمند شده توسط');
+@define('TRACKBACKS', 'ردپا ها');
+@define('TRACKBACK', 'ردپا');
+@define('NO_TRACKBACKS', 'هیچ ردپای وجود ندارد');
+@define('TOPICS_OF', 'تاپیکی از');
+@define('VIEW_FULL', 'نمایش کامل');
+@define('VIEW_TOPICS', 'نمایش تاپیک ها');
+@define('AT', 'در');
+@define('SET_AS_TEMPLATE', 'به عنوان پوسته پیش فرض انتخاب کن');
+@define('IN', 'در');
+@define('EXCERPT', 'برگزیدن');
+@define('TRACKED', 'پیگیری شد');
+@define('LINK_TO_ENTRY', 'لینک به ارسال');
+@define('LINK_TO_REMOTE_ENTRY', 'لینک به ارسال خارجی');
+@define('IP_ADDRESS', 'آدرس IP');
+@define('USER', 'کاربر');
+@define('THUMBNAIL_USING_OWN', 'استفاده از %s به عنوان عکس کوچک (به دلیل ابعاد کوچک عکس).');
+@define('THUMBNAIL_FAILED_COPY', 'استفاده از %s به عنوان عکس کوچک به دلیل ایجاد اشکال در کپی مقدور نمی باشد!');
+@define('AUTHOR', 'نویسنده');
+@define('LAST_UPDATED', 'آخرین به روز رسانی');
+@define('TRACKBACK_SPECIFIC', 'یک آدرس ردپا برای ارسال');
+@define('DIRECT_LINK', 'لینک مستقیم به ارسال');
+@define('COMMENT_ADDED', 'توضیحات شما با موفقیت وارد شد. ');
+@define('COMMENT_ADDED_CLICK', 'برای بازگشت به نظر ها %sاینجا کلیک کنید%s و برای بستن این پنجره %sاینجا کلیک کنید%s.');
+@define('COMMENT_NOT_ADDED', 'ارسال نظر برای این مطلب ممکن نیست. ');
+@define('COMMENT_NOT_ADDED_CLICK', 'برای بازگشت به نظر ها %sاینجا%s، و برای بستن پنجره %sاینجا%s کلیک کنید.');
+@define('COMMENTS_DISABLE', 'اجازه ارسال نظر داده نشود');
+@define('COMMENTS_ENABLE', 'اجازه ارسال نظر داده شود');
+@define('COMMENTS_CLOSED', 'نویسنده اجازه ارسال نظر نداده است');
+@define('EMPTY_COMMENT', 'نظر شما خالی است، لطف %sبرگردید%s و دوباره سعی نمایید');
+@define('ENTRIES_FOR', 'ارسال ها از %s');
+@define('DOCUMENT_NOT_FOUND', 'مطلب %s یافت نشد.');
+@define('USERNAME', 'نام کاربری');
+@define('PASSWORD', 'رمز عبور');
+@define('AUTOMATIC_LOGIN', 'ذخیره اطلاعات');
+@define('SERENDIPITY_INSTALLATION', 'نصب Serendipity');
+@define('LEFT', 'چپ');
+@define('RIGHT', 'راست');
+@define('HIDDEN', 'مخفی');
+@define('REMOVE_TICKED_PLUGINS', 'حذف افزونه های تیک خورده');
+@define('SAVE_CHANGES_TO_LAYOUT', 'ثبت تغییرات در پوسته');
+@define('COMMENTS_FROM', 'نظر های ');
+@define('ERROR', 'خطا');
+@define('ENTRY_SAVED', 'ارسال شما ذخیره شد');
+@define('DELETE_SURE', 'آیا از حذف دائمی #%s اطمینان دارید؟');
+@define('NOT_REALLY', 'خیر');
+@define('DUMP_IT', 'بله');
+@define('RIP_ENTRY', 'مطلب #%s حذف شد.');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'موضوع #%s حذف شد. ارسال های قدیمی به موضوع #%s اضافه شد');
+@define('CATEGORY_DELETED', 'موضوع #%s حذف شد.');
+@define('INVALID_CATEGORY', 'موضوعی برای حذف انتخاب نشده است');
+@define('CATEGORY_SAVED', 'موضوع ذخیره شد');
+@define('SELECT_TEMPLATE', 'پوسته مورد علاقه خود را انتخاب کنید');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'اضافه کردن ارسال ها با مشکل مواجه شد!');
+@define('MT_DATA_FILE', 'فایل دادهء Movable Type');
+@define('FORCE', 'اجبار');
+@define('CREATE_AUTHOR', 'ایجاد نویسنده \'%s\'.');
+@define('CREATE_CATEGORY', 'ایجاد موضوع \'%s\'.');
+@define('MYSQL_REQUIRED', 'برای انجام این عمل، باید توسعه MySQL را نصب داشته باشید.');
+@define('COULDNT_CONNECT', 'اشکال در اتصال به بانک MySQL: %s.');
+@define('COULDNT_SELECT_DB', 'اشکال در انتخاب بانک: %s.');
+@define('COULDNT_SELECT_USER_INFO', 'اشکال در انتخاب نام کاربری: %s.');
+@define('COULDNT_SELECT_CATEGORY_INFO', 'اشکال در انتخاب موضوع: %s.');
+@define('COULDNT_SELECT_ENTRY_INFO', 'اشکال در کسب اطلاعات ارسال ها: %s.');
+@define('COULDNT_SELECT_COMMENT_INFO', 'اشکال در کسب ازلاعات نظر ها: %s.');
+@define('YES', 'بله');
+@define('NO', 'خیر');
+@define('USE_DEFAULT', 'پیش فرض');
+@define('CHECK_N_SAVE', 'چک و ثبت کن');
+@define('DIRECTORY_WRITE_ERROR', 'توانایی نوشتن در شاخه %s وجود ندارم. دسترسی ها را چک کنید.');
+@define('DIRECTORY_CREATE_ERROR', 'شاخه %s وجود ندارد یا قابلیت ایجاد کردن آن نیست. لطفا خودتان به صورت دستی، آن را بسازید');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; <i>%s %s</i> را اجرا کن');
+@define('CANT_EXECUTE_BINARY', 'توانایی اجرای %s نیست');
+@define('FILE_WRITE_ERROR', 'توانایی نوشتن در فایل %s نیست.');
+@define('FILE_CREATE_YOURSELF', 'لطفا یا خودتان فایل را ایجاد کنید، یا دسترسی ها را چک کنید');
+@define('COPY_CODE_BELOW', '<br />* کد زیر را کپی کرده و در %s در %s شاخه زیر بریزید:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'www را به کاربری که از آپاچی استفاده می کند تغییر دهید (مثلا nobody(.');
+@define('BROWSER_RELOAD', 'پس از تکمیل، صفحه مرورگر را refresh کنید.');
+@define('DIAGNOSTIC_ERROR', 'تعدادی خطا در اطلاعات ورودی شما یافت شد:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity هنوز نصب نشده است. لطفا هم اکنون آن را <a href="%s">نصب کنید</a>.');
+@define('INCLUDE_ERROR', 'خطای serendipity: توانایی وارد کردن فایل %s وجود ندارد - برنامه متوقف شد.');
+@define('DATABASE_ERROR', 'خطای serendipity: امکان اتصال به بانک نمی باشد - برنامه متوقف شد.');
+@define('CREATE_DATABASE', 'در حال نصب پیش فرضیات پایگاه داده...');
+@define('ATTEMPT_WRITE_FILE', 'تلاش برای نوشتن در فایل %s...');
+@define('WRITTEN_N_SAVED', 'تنظیمات نوشته و ذخیره شد');
+@define('IMAGE_ALIGNMENT', 'هم ترازی تصویر');
+@define('ENTER_NEW_NAME', 'نام جدیدی برای مقدار روبرو وارد کنید: ');
+@define('RESIZING', 'تغییر سایز');
+@define('RESIZE_DONE', 'انجام شد (تعداد %s تصویر تغییر کرد).');
+@define('SYNCING', 'هماهنگی پایگاه داده با شاخه تصاویر');
+@define('SYNC_DONE', 'انجام شد (تعداد %s تصویر هماهنگ شد).');
+@define('FILE_NOT_FOUND', 'توانایی تشخیص محل تصویر <b>%s</b> نیست، احتمالا قبلا حذف شده است؟');
+@define('ABORT_NOW', 'بازگشت');
+@define('REMOTE_FILE_NOT_FOUND', 'فایل بر روی سرور دور موجود نمی باشد، آیا از صحت آدرس: <b>%s</b> مطمئنید؟');
+@define('FILE_FETCHED', '%s با نام %s دریافت شد');
+@define('FILE_UPLOADED', 'فایل %s با موفقیت با نام %s بالاگذاری شد');
+@define('WORD_OR', 'یا');
+@define('SCALING_IMAGE', 'تغییر اندازه تصویر %s به %s x %s px');
+@define('KEEP_PROPORTIONS', 'حفظ تناسب');
+@define('REALLY_SCALE_IMAGE', 'آیا از تغییر اندازه تصاویر مطمئنید؟ این عمل قابل بازگشت نیست!');
+@define('TOGGLE_ALL', 'باز کردن همه');
+@define('TOGGLE_OPTION', 'انتخاب وضعیت گزینه ها');
+@define('SUBSCRIBE_TO_THIS_ENTRY', 'وقتی نظری ارسال شد، مرا خبر کن');
+@define('UNSUBSCRIBE_OK', "%s حذف شد");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'توضیح جدیدی برای مطلب "%s" ارسال شد');
+@define('SUBSCRIPTION_MAIL', "سلام %s,\n\nA نظر جدیدی برای مطلب \"%s\"، با تیتر \"%s\" ارسال شده است\nنام ارسال کننده: %s\n\nمی توانید مطلب را در لینک روبرو مشاهده کنید: %s\n\nمی توانید با کلیک روی لینک روبرو این نظر را قبول نکنید: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "سلام %s,\n\nA ردپای جدیدی برای مطلب \"%s\", با تیتر \"%s\" ارسال شده است\nنام ارسال کننده: %s\n\nمی توانید مطلب را در لینک روبرو مشاهده کنید: %s\n\nمی توانید با کلیک روی لینک روبرو این ردپا را قبول نکنید: %s\n");
+@define('SIGNATURE', "\n-- \n%s بر پایه Serendipity بنا شده است.\nبهترین سیستم وبلاگ موجود, شما هم می توانید از این سیستم استفاده کنید.\nسایت <http://s9y.org> را بری روش نصب و استفاده مرور کنید.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 نظرات');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'فیلد "نویسنده"');
+@define('SYNDICATION_PLUGIN_WEBMASTER', 'فیلد "مدیر"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'تصویر برای RSS');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', 'عرض تصویر');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'ارتفاع تصویر');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC', 'ایمیل مدیر سایت, البته در صورت موجود بودن. (خالی= مخفی) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', 'در صورت وجود، آدرس ایمیل نویسنده (خالی= مخفی) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'در صورت وجود، آدرس عکسی با توسعه GIF یا JPEG یا PNG. (خالی= لوگوی Serendipity)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'پیکسل، ماکزیمم. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'پیکسل، ماکزیزمم. 400');
+@define('SYNDICATION_PLUGIN_TTL', 'فیلد "ttl" (زمان زندگی)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'زمانی بر حسب دقیقه که سایت شما برای سایت ها و برنامه های خارجی cache خواهد شد (خالی= مخفی) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'فیلد زمان انتشار');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', 'آیا زمان انتشار ارسال ها در گزینه های RSS درج شود؟');
+@define('CONTENT', 'محتویات');
+@define('TYPE', 'نوع');
+@define('DRAFT', 'پیش نویس');
+@define('PUBLISH', 'انتشار');
+@define('PREVIEW', 'پیش نمایش');
+@define('DATE', 'تاریخ');
+@define('DATE_FORMAT_2', 'Y-m-d H:i');
+@define('DATE_INVALID', 'خطر: تاریخ وارد شده اشتباه می باشد. ساختار تاریخ باید شبیه YYYY-MM-DD HH:MM باشد.');
+@define('CATEGORY_PLUGIN_DESC', 'لیست موضوعات را نمایش می دهد.');
+@define('ALL_AUTHORS', 'تمامی نویسندگان');
+@define('CATEGORIES_TO_FETCH', 'موضوعات دریافتی');
+@define('CATEGORIES_TO_FETCH_DESC', 'موضوعات کدام نویسنده دریافت شود؟');
+@define('PAGE_BROWSE_ENTRIES', 'صفحه %s از %s، %s ارسال');
+@define('PREVIOUS_PAGE', 'صفحه قبل');
+@define('NEXT_PAGE', 'صفحه بعد');
+@define('ALL_CATEGORIES', 'تمامی موضوعات');
+@define('DO_MARKUP', 'ایجاد تغییرات Markup');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'تغییر تاریخ');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'طرز نمایش تاریخ در ارسال ها، از قوانین نگارش تابع strftime() در PHP پیروی کنید. (پیش فرض: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'توانایی باز کردن فایل پوسته وجود ندارد، لطفا serendipity را به روز کنید!');
+@define('ADVANCED_OPTIONS', 'گزینه های پیشرفته');
+@define('EDIT_ENTRY', 'تغییر ارسال');
+@define('HTACCESS_ERROR', 'برای چک کردن نصب وب سرور، serendipity احتیاج دارد که در فایل ".htaccess" مقادیری را بنویسد. این امر به دلیل محدودیت های دسترسی ممکن نمی باشد. لطفا سطح دسترسی را مشابه: <br />&nbsp;&nbsp;%s<br />تغییر داده و این صفحه را دوباره صدا بزنید.');
+@define('SIDEBAR_PLUGINS', 'افزونه های نوار کناری');
+@define('EVENT_PLUGINS', 'افزونه های رویداد');
+@define('SORT_ORDER', 'ترتیب مرتب سازی');
+@define('SORT_ORDER_NAME', 'نام فایل');
+@define('SORT_ORDER_EXTENSION', 'توسعه فایل');
+@define('SORT_ORDER_SIZE', 'سایز فایل');
+@define('SORT_ORDER_WIDTH', 'عرض عکس');
+@define('SORT_ORDER_HEIGHT', 'ارتفاع عکس');
+@define('SORT_ORDER_DATE', 'تاریخ بالاگذاری');
+@define('SORT_ORDER_ASC', 'صعودی');
+@define('SORT_ORDER_DESC', 'نزولی');
+@define('THUMBNAIL_SHORT', 'عکس کوچک');
+@define('ORIGINAL_SHORT', 'اصلی');
+@define('APPLY_MARKUP_TO', 'اعمال کردن markup به %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'ابتدای هفته');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity فهمید که نسخه فایل تنظیمات شما %s می باشد، در حالی که خود برنامه Serendipity نسخه %s است، شما احتیاج به به روز رسانی دارید! <a href="%s">اینجا کلیک کنید</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'سلام، به بخش به روز رسانی Serendipity خوش آمدید.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', 'من اینجا هستم تا به شما در به روز رسانی Serendipity %s کمک کنم.');
+@define('SERENDIPITY_UPGRADER_WHY', 'به خاطر نصب Serendipity %s این پیام را مشاهده می کنید، اما پایگاه داده خود را هنوز به روز نکرده اید');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'پایگاه داده (%s) به روز شد');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'من فایلی با توسعه .sql پیدا کردم که قبل از ادامه کار باید اجرا شود');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC', 'کارهای مخصوص این نسخه');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', 'هیچ کاری یافت نشد');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', 'آیا تمایل دارید که من کارهای فوق را انجام دهم؟');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'خیر، من خودم انجام می دهم');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'بله، ممنون میشم');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'در ظاهر احتیاجی به به روز رسانی نمی باشد');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', 'رسیدگی کردن به به روز رسانی Serendipity');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'شما توانایی به روز رسانی Serendipity را ندارید، لطفا از درست ایجاد شدن پایگاه داده اطمینان پیدا کنید');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'Serendipity به نسخه %s به روز رسانی شد');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', '%shere%s کلیک کنید تا به صفحه آغازین وبلاگتون برگردید');
+@define('MANAGE_USERS', 'مدیریت کاربران');
+@define('CREATE_NEW_USER', 'ایجاد یک کاربر جدید');
+@define('CREATE_NOT_AUTHORIZED', 'شما نمی توانید کاربری با سطح دسترسی مشابه خود را تغییر دهید');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'شما نمی توانید کاربری با سطح دسترسی بیشتر از خود ایجاد کنید');
+@define('CREATED_USER', 'کاربر %s ساخته شد');
+@define('MODIFIED_USER', 'مشخصات کاربر %s تغییر کرد');
+@define('USER_LEVEL', 'سطح دسترسی');
+@define('DELETE_USER', 'شما می خواهید کاربر #%d %s را حذف کنید. آیا مطمئن هستید؟ این عمل باعث می شود که تمامی پست های نوشته شده توسط ایشان در صفحه اصلی نمایش داده نشود.');
+@define('DELETED_USER', 'کاربر #%d %s حذف شد.');
+@define('LIMIT_TO_NUMBER', 'چه تعداد گزینه نمایش داده شود؟');
+@define('ENTRIES_PER_PAGE', 'ارسال ها در هر صفحه');
+@define('XML_IMAGE_TO_DISPLAY', 'دکمه XML');
+@define('XML_IMAGE_TO_DISPLAY_DESC', 'لینک XML ها با عکس طیر نمایش داده خواهد شد. مقدار خالی به عنوان مقدار پیش فرض در نظر گرفته می شود, عبارت \'none\' را برای غیر فعال کردن وارد کنید.');
+
+@define('DIRECTORIES_AVAILABLE', 'در لیست زیرشاخه های موجود می توانید روی نام شاخه کلیک کنید تا زیرشاخه ای جدید در آن شاخه درست کنید.');
+@define('ALL_DIRECTORIES', 'تمامی شاخه ها');
+@define('MANAGE_DIRECTORIES', 'مدیریت شاخه ها');
+@define('DIRECTORY_CREATED', 'شاخه <strong>%s</strong> ساخته شد.');
+@define('PARENT_DIRECTORY', 'شاخه پدر');
+@define('CONFIRM_DELETE_DIRECTORY', 'آیا مایلید تمام محتویات شاخه %s را حذف کنید؟');
+@define('ERROR_NO_DIRECTORY', 'خطا: شاخه %s وجود ندارد');
+@define('CHECKING_DIRECTORY', 'بررسی فایل های داخل شاخه %s');
+@define('DELETING_FILE', 'حذف فایل %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', 'توانایی حذف شاخه هایی که خالی نیستند وجود ندارد.اگر می خواهید فایل ها هم حذف شوند، گزینه "force deletion" را تیک بزنید، سپس فرم را دوباره ارسال کنید. فایل های موجود عبارتند از:');
+@define('DIRECTORY_DELETE_FAILED', 'حذف شاخه %s با مشکل مواجه شد. دسترسی ها یا پیام فوق را بررسی کنید.');
+@define('DIRECTORY_DELETE_SUCCESS', 'شاخه %s با موفقیت حذف شد.');
+@define('SKIPPING_FILE_EXTENSION', 'پرش از روی فایل: توسعه ناشناخته در %s.');
+@define('SKIPPING_FILE_UNREADABLE', 'پرش از روی فایل: %s قابل خواندن نمی باشد.');
+@define('FOUND_FILE', 'یافتن فایل جدید یا تغییر داده شده: %s.');
+@define('ALREADY_SUBCATEGORY', '%s قبلا زیر موضوعی از %s بوده.');
+@define('PARENT_CATEGORY', 'موضوع پدر');
+@define('IN_REPLY_TO', 'در پاسخ به');
+@define('TOP_LEVEL', 'بالاترین سطح');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s');
+@define('PERMISSIONS', 'دسترسی ها');
+@define('SETTINGS_SAVED_AT', 'تنظیمات جدید در %s ثبت شد');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', 'تنظیمات پایگاه داده');
+@define('INSTALL_CAT_DB_DESC', 'شما می توانید اطلاعات کامل پایگاه داده را در اینجا وارد کنید. Serendipity برای فعالیت به این اطلاعات نیاز دارد');
+@define('INSTALL_DBTYPE', 'نوع پایگاه داده');
+@define('INSTALL_DBTYPE_DESC', 'نوع پایگاه داده');
+@define('INSTALL_DBHOST', 'آدرس پایگاه داده');
+@define('INSTALL_DBHOST_DESC', 'آدرس هاستی که پایگاه داده روی آن قرار دارد');
+@define('INSTALL_DBUSER', 'کاربر پایگاه داده');
+@define('INSTALL_DBUSER_DESC', 'نام کاربری که توسط آن به پایگاه داده متصل می شوید');
+@define('INSTALL_DBPASS', 'رمز عبور پایگاه داده');
+@define('INSTALL_DBPASS_DESC', 'رمز عبور مربوط به نام کاربری که در فوق وارد کردید');
+@define('INSTALL_DBNAME', 'نام پایگاه داده');
+@define('INSTALL_DBNAME_DESC', 'نام پایگاه داده شما');
+@define('INSTALL_DBPREFIX', 'پیشوند جداول پایگاه داده');
+@define('INSTALL_DBPREFIX_DESC', 'پیشوند جدول های مربوط به Serendipity، به طور مثال. serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', 'مسیر ها');
+@define('INSTALL_CAT_PATHS_DESC', 'مسیر های متفاوت برای شاخه های مهم. فراموش نکنید که برای شاخه ها در آخر یک اسلش بگذارید!');
+@define('INSTALL_FULLPATH', 'مسیر کامل');
+@define('INSTALL_FULLPATH_DESC', 'آدرس مستقیم و کامل به مکان نصب Serendipity');
+@define('INSTALL_UPLOADPATH', 'مسیر بالاگذاری');
+@define('INSTALL_UPLOADPATH_DESC', 'تمامای بالاگذاری ها در این مسیر قرار خواهند گرفت، نسبت به مقدار  \'مسیر کامل\' - مثل \'uploads/\'');
+@define('INSTALL_RELPATH', 'مسیر دریافت');
+@define('INSTALL_RELPATH_DESC', 'مسیر Serendipity برای مرورگر شما، مثل \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', 'مسیر پوسته ها');
+@define('INSTALL_RELTEMPLPATH_DESC', 'مسیر شاخه ای که فایل های پوسته در آن قرار دارد - نسبت به مقدار \'مسیر دریافت\'');
+@define('INSTALL_RELUPLOADPATH', 'مسیر نسبی بالاگذاری');
+@define('INSTALL_RELUPLOADPATH_DESC', 'مسیر فایل های بالاگذاری شده برای مرورگر شما - نسبت به مقدار \'مسیر دریافت\'');
+@define('INSTALL_URL', 'آدرس وبلاگ');
+@define('INSTALL_URL_DESC', 'آدرس اصلی نصب Serendipity');
+@define('INSTALL_INDEXFILE', 'فایل ایندکس');
+@define('INSTALL_INDEXFILE_DESC', 'نام فایل ایندکس شما');
+
+/* GENERAL SETTINGS */
+@define('INSTALL_CAT_SETTINGS', 'تنظیمات عمومی');
+@define('INSTALL_CAT_SETTINGS_DESC', 'تنظیم کردن نوع رفتار Serendipity');
+@define('INSTALL_USERNAME', 'نام کاربری مدیر');
+@define('INSTALL_USERNAME_DESC', 'نام کاربری مدیر برای ورود');
+@define('INSTALL_PASSWORD', 'رمز عبور مدیر');
+@define('INSTALL_PASSWORD_DESC', 'رمز عبور مدیر برای ورود');
+@define('INSTALL_EMAIL', 'ایمیل مدیر');
+@define('INSTALL_EMAIL_DESC', 'ایمیل مدیر وبلاگ');
+@define('INSTALL_SENDMAIL', 'آیا ایمیل به مدیر؟ ارسال شود');
+@define('INSTALL_SENDMAIL_DESC', 'آیا علاقه دارید در هنگام ارسال نظر ایمیلی دریافت کنید؟');
+@define('INSTALL_SUBSCRIBE', 'اجازه ثبت نام کاربران داده شود؟');
+@define('INSTALL_SUBSCRIBE_DESC', 'اجازه ثبت نام کاربران داده شود تا در زمان ارسال نظری جدید، ایمیلی دریافت کنند');
+@define('INSTALL_BLOGNAME', 'نام وبلاگ');
+@define('INSTALL_BLOGNAME_DESC', 'تیتر وبلاگ شما');
+@define('INSTALL_BLOGDESC', 'توضیحات وبلاگ');
+@define('INSTALL_BLOGDESC_DESC', 'توضیحات وبلاگ شما');
+@define('INSTALL_LANG', 'زبان');
+@define('INSTALL_LANG_DESC', 'زبان وبلاگتان را انتخاب کنید');
+
+/* APPEARANCE AND OPTIONS */
+@define('INSTALL_CAT_DISPLAY', 'ظاهر و تنظیمات');
+@define('INSTALL_CAT_DISPLAY_DESC', 'تنظیم چگونگی نمایش Serendipity');
+@define('INSTALL_WYSIWYG', 'استفاده از ویرایشگر WYSIWYG');
+@define('INSTALL_WYSIWYG_DESC', 'آیا می خواهید از ویراشگر WYSIWYG استفاده کنید؟ (در IE5+، و مقداری در Mozilla 1.3+ قابل مشاهده می باشد)');
+@define('INSTALL_XHTML11', 'قبول کردن اجباری XHTML 1.1');
+@define('INSTALL_XHTML11_DESC', 'آیا تمایل دارید XHTML 1.1 به صورت اجباری امال کنید (احتمال وجود اشکل در برخی از مرورگر های قدیمی وجود دارد)');
+@define('INSTALL_POPUP', 'توانایی استفاده از پنجره های popup');
+@define('INSTALL_POPUP_DESC', 'آیا تمایل دارید که برای نظرات و ردپا ها از پنجره های popup استفاده شود؟');
+@define('INSTALL_EMBED', 'آیا Serendipity جاسازی شده است؟');
+@define('INSTALL_EMBED_DESC', 'اگر می خواهید Serendipity را در صفحه ای دیگر جاسازی کنید، مقدار این گزینه را "بله" وارد کنید تا فقط محتویات صفحه چاپ شوند.!');
+@define('INSTALL_TOP_AS_LINKS', 'نمایش بیشترین بینندگان و بیشترین خروج ها به صورت لینک؟');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"خیر": خروج ها و بازدید ها به صورت متن عادی نمایش داده خواهند شد. "بله": حروج ها و بازدید ها به صورت لینک نمایش داده خواهند شد. "پیش فرض": استفاده از تنظیمات جهانی (این گزینه توصیه می شود).');
+@define('INSTALL_BLOCKREF', 'بازدید کنندگان بلاک شده');
+@define('INSTALL_BLOCKREF_DESC', 'آیا آدرس خاصی وجود دارد که نمی خواهید در لیست بازدید کنندگان نمایش داده شود؟ آدرس ها را با یک علامت \';\' از هم جدا کنید و توجه کنید که آدرس ها توسط روش زیر رشته (substring) حذف خواهند شد!');
+@define('INSTALL_REWRITE', 'دوباره نویسی آدرس ها');
+@define('INSTALL_REWRITE_DESC', 'روش پردازش آدرس ها را مشخص کنید. دادن امکان دوباره نویسی آدرس ها توانایی موتور های جستجو را در ایندکس کردن وبلاگ شما بالا می برد. وب سرور شما باید اجازه دسترسی به mod_rewrite یا "AllowOverride All" را برای شاخه Serendipity داده باشد. مقدار پیش فرض "شناسایی خودکار" می باشد');
+
+/* IMAGECONVERSION SETTINGS */
+@define('INSTALL_CAT_IMAGECONV', 'تنظیمات تغییر عکس');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'اطلاعات کلی برای Serendipity برای چگونگی پردازش تصاویر');
+@define('INSTALL_IMAGEMAGICK', 'استفاده از Imagemagick');
+@define('INSTALL_IMAGEMAGICK_DESC', 'آیا شما image magick را نصب کرده اید و آیا می خواهید از آن به عنوان پردازنده تصاویر استفاده کنید؟');
+@define('INSTALL_IMAGEMAGICKPATH', 'مسیر تغییر فایل های باینری');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'آدرس کامل و نام فایل image magick برای تغییر فایل های باینری');
+@define('INSTALL_THUMBSUFFIX', 'پیشوند عکس های کوچک');
+@define('INSTALL_THUMBSUFFIX_DESC', 'عکس های کوچک با روش روبرو نامگذاری خواهند شد: نام اصلی.[پیشوند].توسعه');
+@define('INSTALL_THUMBWIDTH', 'ابعاد تصاویر کوچک');
+@define('INSTALL_THUMBWIDTH_DESC', 'بیشترین عرض عکس های کوچک ساخته شده');
+
+/* PERSONAL DETAILS */
+@define('USERCONF_CAT_PERSONAL', 'اطلاعات شخصی');
+@define('USERCONF_CAT_PERSONAL_DESC', 'ویرایش اطلاعات شخصی');
+@define('USERCONF_USERNAME', 'نام کاربری');
+@define('USERCONF_USERNAME_DESC', 'نام کاربری برای ورود شما به سیستم');
+@define('USERCONF_PASSWORD', 'رمز عبور');
+@define('USERCONF_PASSWORD_DESC', 'رمز عبور برای ورود شما به سیستم');
+@define('USERCONF_EMAIL', 'آدرس ایمیل');
+@define('USERCONF_EMAIL_DESC', 'آدرس ایمیل شخصی شما');
+@define('USERCONF_SENDCOMMENTS', 'آیا خبر ارسال نظر ارسال گردد؟');
+@define('USERCONF_SENDCOMMENTS_DESC', 'آیا می خواهید در زمان ارسال نظر ایمیلی برای با خبر شدن از آن دریافت کنید؟');
+@define('USERCONF_SENDTRACKBACKS', 'آیا خبر ردپا ارسال گردد؟');
+@define('USERCONF_SENDTRACKBACKS_DESC', 'آیا می خواهید در زمانی که ردپای ارسال می شود ایمیلی برای با خبر شدن از آن دریافت کنید؟');
+@define('USERCONF_ALLOWPUBLISH', 'قوانین: انتشار مطالب؟');
+@define('USERCONF_ALLOWPUBLISH_DESC', 'آیا این کاربر توانایی ارسال مطلب دارد؟');
+@define('SUCCESS', 'موفقیت');
+@define('POWERED_BY_SHOW_TEXT', 'نمایش متنی "Serendipity"');
+@define('POWERED_BY_SHOW_TEXT_DESC', 'عبارت "Serendipity Weblog" را به صورت متنی نمایش می دهد');
+@define('POWERED_BY_SHOW_IMAGE', 'نمایش "Serendipity" همراه با یک لوگو');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'لوگوی Serendipity را نمایش می دهد');
+@define('PLUGIN_ITEM_DISPLAY', 'این گزینه کجا نمایش داده شود؟');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'فقط ارسال های توسعه داده شده');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'فقط در صفحه خلاصه');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'همیشه');
+@define('RSS_IMPORT_CATEGORY', 'از این موضوع برای ارسال های وارد شده که موضوع خاصی ندارند استفاده کن');
+
+@define('COMMENTS_WILL_BE_MODERATED', 'نظرات ارسال شده قبل از نمایش داده شدن، باید مدیریت شوند.');
+@define('YOU_HAVE_THESE_OPTIONS', 'گزینه های زیر وجود دارند:');
+@define('THIS_COMMENT_NEEDS_REVIEW', 'توجه: نظر شما قبل از نمایش داده شدن، باید تایید شود');
+@define('DELETE_COMMENT', 'حذف نظر');
+@define('APPROVE_COMMENT', 'قبول نظر');
+@define('REQUIRES_REVIEW', 'مرور موارد مورد نیاز');
+@define('COMMENT_APPROVED', 'نظر #%s با موفقیت قبول شد');
+@define('COMMENT_DELETED', 'نظر #%s با موفقیت حذف شد');
+@define('COMMENTS_MODERATE', 'نظر ها و ردپا های این ارسال احتیاج به مدیریت دارند');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'توجه: این ردپا قبل از انتشار احتیاج به اعتبار سنجی دارد');
+@define('DELETE_TRACKBACK', 'حذف ردپا');
+@define('APPROVE_TRACKBACK', 'قبول ردپا');
+@define('TRACKBACK_APPROVED', 'ردپا #%s با موفقیت افزوده شد');
+@define('TRACKBACK_DELETED', 'ردپا #%s با موفقیت حذف شد');
+@define('VIEW', 'دیدگاه');
+@define('COMMENT_ALREADY_APPROVED', 'نظر #%s ظاهرا قبلا تایید شده است');
+@define('COMMENT_EDITED', 'نظر مشخص شده، ویرایش شد');
+@define('HIDE', 'مخفی');
+@define('VIEW_EXTENDED_ENTRY', 'ادامه مطلب "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'این لینک برای کلیک کردن نیست و فقط آدرس این مطلب را نگهداری می کند. شما باید از این لینک برای آدرس دادن یا ایجاد ردپا استفاده کنید. برای کپی کردن این لینک، روی لینک راست-کلیک کنید و مقدار "Copy Shortcut" در Internet Explorer یا "Copy Link Location" در Mozilla انتخاب کنید.');
+@define('PLUGIN_SUPERUSER_HTTPS', 'برای ورود از https استفاده کنید');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'اجازه بدید که لینک ورود به آدرسی با مقدار https اشاره کند. احتیاج است سایت شما SSL را پشتیبانی کند!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'لینک های خارجی را قابل کلیک شدن بکن؟');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"خیر": لینک های خارجی (مثل آخرین خروج ها و ...) برای جلوگیری از اسپم های گوگلی، به صورت متن ساده نمایش داده شوند (توصیه شده). "بله": لینک های خارجی به صورت پیوست نمایش داده شود.. توسط تنظیمات افزونه قابلیت تغییر وجود دارد!');
+@define('PAGE_BROWSE_COMMENTS', 'صفحه %s از %s، در کل %s نظر');
+@define('FILTERS', 'فیلترها');
+@define('FIND_ENTRIES', 'جستجوی ارسال ها');
+@define('FIND_COMMENTS', 'جستجوی نظر ها');
+@define('FIND_MEDIA', 'جستجوی رسانه ها');
+@define('FILTER_DIRECTORY', 'شاخه');
+@define('SORT_BY', 'مرتب بر حسب');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'هیچ ردپایی ارسال نشد: توانایی ایجاد اتصال به %s روی پورت %d نمی باشد');
+@define('MEDIA', 'رسانه');
+@define('MEDIA_LIBRARY', 'کتابخانه رسانه');
+@define('ADD_MEDIA', 'افزودن رسانه');
+@define('ENTER_MEDIA_URL', 'URL فایلی را برای دریافت وارد کنید:');
+@define('ENTER_MEDIA_UPLOAD', 'فایلی را برای بالاگذاری مشخص کنید:');
+@define('SAVE_FILE_AS', 'ذخیره فایل با نام:');
+@define('STORE_IN_DIRECTORY', 'ذخیره در شاخه: ');
+@define('ADD_MEDIA_BLAHBLAH', '<b>افزودن یک فایل به انبار:</b><p>در اینجا شما می توانید فایل های خود را بالاگذاری کنید، یا آدرس آنها را برای دریافت از اینترنت وارد کنید! اگر عکسی برای بالاگذاری ندارید جستجویی در <a href="http://images.google.com" target="_blank">اینجا</a> برای یافتن عکس مورد علاقه خود داشته باشید، نتیجه معمولا مفید و جالب خواهد بود :)<p><b>انتخاب روش:</b><br>');
+@define('MEDIA_RENAME', 'تغییر نام فایل');
+@define('IMAGE_RESIZE', 'تغییر اندازه تصویر');
+@define('MEDIA_DELETE', 'حذف فایل');
+@define('FILES_PER_PAGE', 'فایل در صفحه');
+@define('CLICK_FILE_TO_INSERT', 'برای الحاق کردن، روی تصویر کلیک کنید:');
+@define('SELECT_FILE', 'فایل را برای الحاق کردن مشخص کنید');
+@define('MEDIA_FULLSIZE', 'تمام سایز');
+@define('CALENDAR_BOW_DESC', 'روزی که به عنوان اولین روز هفته در نظر گرفته می شود. Monday مقدار پیش فرض می باشد');
+@define('SUPERUSER', 'مدیریت وبلاگ');
+@define('ALLOWS_YOU_BLAHBLAH', 'ایجاد لینکی در نوار کناری برای ورود به بخش مدیریت');
+@define('CALENDAR', 'تقویم');
+@define('SUPERUSER_OPEN_ADMIN', 'بخش مدیریت');
+@define('SUPERUSER_OPEN_LOGIN', 'باز کردن صفحه ورود');
+@define('INVERT_SELECTIONS', 'معکوس کردن انتخابات');
+@define('COMMENTS_DELETE_CONFIRM', 'آیا مطمئن هستید که نظرات انتخاب شده حذف شود؟');
+@define('COMMENT_DELETE_CONFIRM', 'آیا مطمئن هستید که نظر #%d، نوشته شده توسط %s حذف شود؟');
+@define('DELETE_SELECTED_COMMENTS', 'حذف نظرات انتخاب شده');
+@define('VIEW_COMMENT', 'نمایش نظر');
+@define('VIEW_ENTRY', 'نمایش ارسال');
+@define('DELETE_FILE_FAIL' , 'توانایی حذف فایل <b>%s</b> وجود ندارد');
+@define('DELETE_THUMBNAIL', 'عکس کوچک با نام <b>%s</b> حذف شد');
+@define('DELETE_FILE', 'فایل با تیتر <b>%s</b> حذف شد');
+@define('ABOUT_TO_DELETE_FILE', 'شما می خواهید <b>%s</b> را حذف کنید<br />اگر شما از این فایل در ارسال هاتون استفاده کردید، دیگر قابل مشاهده شدن یا لینک دادن نیست<br />آیا از انجام این عمل اطمینان دارید؟<br /><br />');
+@define('TRACKBACK_SENDING', 'ارسال ردپا به آدرس %s...');
+@define('TRACKBACK_SENT', 'موفقیت در ردپا');
+@define('TRACKBACK_FAILED', 'خطا در ردپا: %s');
+@define('TRACKBACK_NOT_FOUND', 'هیچ آدرسی برای ردپا یافت نشد.');
+@define('TRACKBACK_URI_MISMATCH', 'آدرس ردپا با آدرس موجود تناقض دارد.');
+@define('TRACKBACK_CHECKING', 'بررسی <u>%s</u> برای وجود ردپا...');
+@define('TRACKBACK_NO_DATA', 'هدف هیچ داده ای ندارد');
+@define('TRACKBACK_SIZE', 'آدرس هدف از محدودیت بیشترین حجم فایل به مقدار %s بایت تجاوز کرد.');
+@define('COMMENTS_VIEWMODE_THREADED', 'بند کشی شده');
+@define('COMMENTS_VIEWMODE_LINEAR', 'خطی');
+@define('DISPLAY_COMMENTS_AS', 'نمایش نظرات به صورت');
+@define('COMMENTS_FILTER_SHOW', 'نمایش');
+@define('COMMENTS_FILTER_ALL', 'تمام');
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'فقط تایید شده ها');
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'در انتظار تایید');
+@define('RSS_IMPORT_BODYONLY', 'تمام مقادیر وارد شده را در بخش "بدنه ارسال" قرار بده و در بخش "مطالب بیشتر" قرار نده.');
+@define('SYNDICATION_PLUGIN_FULLFEED', 'تمام ارسال ها با تمام متن  بدنه را در RSS قرار بده');
+@define('WEEK', 'هفته');
+@define('WEEKS', 'هفته ها');
+@define('MONTHS', 'ماه ها');
+@define('DAYS', 'روزها');
+@define('ARCHIVE_FREQUENCY', 'تناوب گزینه های تقویم');
+@define('ARCHIVE_FREQUENCY_DESC', 'فاصله بین تاریخ ارسال های موجود در لیست');
+@define('ARCHIVE_COUNT', 'تعداد گزنه های موجود در لیست');
+@define('ARCHIVE_COUNT_DESC', 'تعداد ماه ها، هفته ها و روز هایی که نمایش داده شود');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'لیستی از افزونه های نصب شده');
+@define('SIDEBAR_PLUGIN', 'افزونه نوار کناری');
+@define('EVENT_PLUGIN', 'افزونه رویداد');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'برای نصب یک %s جدید اینجا کلیک کنید');
+@define('VERSION', 'نگارش');
+@define('INSTALL', 'نصب');
+@define('ALREADY_INSTALLED', 'قبلا نصب شده');
+@define('SELECT_A_PLUGIN_TO_ADD', 'افزونه ای که می خواهید نصب کنید را انتخاب کنید');
+@define('INSTALL_OFFSET', 'مبدا زمان سرور');
+@define('STICKY_POSTINGS', 'پست های چسبناک');
+@define('INSTALL_FETCHLIMIT', 'ارسال هایی که در ابتدای صفحه نمایش داده شوند');
+@define('INSTALL_FETCHLIMIT_DESC', 'چه تعداد ارسال در صفحه اصلی نمایش داده شوند');
+@define('IMPORT_ENTRIES', 'وارد کردن داده ها');
+@define('EXPORT_ENTRIES', 'صادر کردن ارسال ها');
+@define('IMPORT_WELCOME', 'به ابزار واردات Serendipity خوش آمدید');
+@define('IMPORT_WHAT_CAN', 'در این مکان شما می توانید ارسال های سیستم های وبلاگ دیگر را وارد کنید');
+@define('IMPORT_SELECT', 'لطفا نام برنامه ای که می خواهید ارسال هایش را وارد کنید، انتخاب کنید');
+@define('IMPORT_PLEASE_ENTER', 'لطفا داده های خواسته شده را وارد کنید');
+@define('IMPORT_NOW', 'اکنون وارد کن!');
+@define('IMPORT_STARTING', 'شروع پروسه وارد کردن...');
+@define('IMPORT_FAILED', 'واردات با مشکل مواجه شد');
+@define('IMPORT_DONE', 'واردات با موفقیت انجام شد');
+@define('IMPORT_WEBLOG_APP', 'برنامه وبلاگ');
+@define('IMPORT_NOTES', 'توجه:');
+@define('EXPORT_FEED', 'صادر کردن RSS کامل');
+@define('STATUS', 'وضعیت بعد از واردات');
+@define('IMPORT_GENERIC_RSS', 'وارد کردن RSS های عمومی');
+@define('ACTIVATE_AUTODISCOVERY', 'ارسال ردپا به لینک های یافت شده در مطلب');
+@define('WELCOME_TO_ADMIN', 'به بخش مدیریت Serendipity خوش آمدید.');
+@define('PLEASE_ENTER_CREDENTIALS', 'لطفا نام کاربری و رمز عبورتان را در فیلد های زیر وارد کنید.');
+@define('ADMIN_FOOTER_POWERED_BY', 'ساخته شده توسط Serendipity %s و PHP %s');
+@define('INSTALL_USEGZIP', 'استفاده از صفحات فشرده gzip');
+@define('INSTALL_USEGZIP_DESC', 'برای افزایش سرعت باز شدن صفحات، ما می توانیم صفحات ارسالی به کاربران را فشرده کنیم، البته بستگی به پشتیبانی کردن مرورگر بیننده نیز دارد. این گزینه توصیه می شود');
+@define('INSTALL_SHOWFUTURE', 'نمایش پست های آینده');
+@define('INSTALL_SHOWFUTURE_DESC', 'در صورت فعال بودن، تمامی مقادیر آینده نیز در وبلاگ نمایش داده می شوند. پیش فرض نمایش داده نشدن مقادیر آینده می باشد و مقادیری که تاریخ انتشارشان رسیده باشد نمایش داده خواهند شد.');
+@define('INSTALL_DBPERSISTENT', 'استفاده از اتصال های پایدار');
+@define('INSTALL_DBPERSISTENT_DESC', 'برای استفاده از اتصال پایدار این گزینه را فعال کنید، برای اطلاعات بیشتر <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">اینجا</a> را مطالعه کنید. این گزینه در حالت عادی توصیه نمی شود');
+@define('NO_IMAGES_FOUND', 'هیچ تصویری یافت نشد');
+@define('PERSONAL_SETTINGS', 'تنظیمات شخصی');
+@define('REFERER', 'بازدید کننده');
+@define('NOT_FOUND', 'یافت نشد');
+@define('WRITABLE', 'نوشتنی');
+@define('NOT_WRITABLE', 'نوشتنی نیست');
+@define('PROBLEM_DIAGNOSTIC', 'به دلیل تشخیص یک مشکل، تا مشکلات فوق را برطرف نسازید نمی توانید به ادامه نصب بپردازید');
+@define('SELECT_INSTALLATION_TYPE', 'انتخاب کنید که چه نوع نصبی را می خواهید انجام دهید');
+@define('WELCOME_TO_INSTALLATION', 'به مراحل نصب Serendipity خوش آمدید');
+@define('FIRST_WE_TAKE_A_LOOK', 'در ابتدا ما گزینه های فعلی را بررسی می کنیم و سعی می کنیم نا همگونی ها را رفع کنیم');
+@define('ERRORS_ARE_DISPLAYED_IN', 'خطا ها در %s نمایش داده شدند، توصیه ها در %s و موفقیت ها در %s');
+@define('RED', 'قرمز');
+@define('YELLOW', 'زرد');
+@define('GREEN', 'سبز');
+@define('PRE_INSTALLATION_REPORT', 'گزارش قبل از نصب Serendipity نگارش %s');
+@define('RECOMMENDED', 'توصیه شده');
+@define('ACTUAL', 'واقعی');
+@define('PHPINI_CONFIGURATION', 'تنظیمات php.ini');
+@define('PHP_INSTALLATION', 'نصب PHP');
+@define('THEY_DO', 'انجام شده است');
+@define('THEY_DONT', 'انجام نشده است');
+@define('SIMPLE_INSTALLATION', 'نصب ساده');
+@define('EXPERT_INSTALLATION', 'نصب حرفه ای');
+@define('COMPLETE_INSTALLATION', 'نصب تکمیل شد');
+@define('WONT_INSTALL_DB_AGAIN', 'پایگاه داده دوباره نصب نخواهد شد');
+@define('CHECK_DATABASE_EXISTS', 'بررسی وجود پایگاه داده و جدول های آن');
+@define('CREATING_PRIMARY_AUTHOR', 'ایجاد نویسنده اصلی \'%s\'');
+@define('SETTING_DEFAULT_TEMPLATE', 'تنظیم پوسته پیش فرض');
+@define('INSTALLING_DEFAULT_PLUGINS', 'نصب افزونه های پیش فرض');
+@define('SERENDIPITY_INSTALLED', 'Serendipity با موفقیت نصب شد');
+@define('VISIT_BLOG_HERE', 'وبلاگ جدید خود را از اینجا ببینید');
+@define('THANK_YOU_FOR_CHOOSING', 'به خاطر نصب Serendipity سپاسگذاریم');
+@define('ERROR_DETECTED_IN_INSTALL', 'خطایی در زمان نصب تشخیص داده شد');
+@define('OPERATING_SYSTEM', 'سیستم عامل');
+@define('WEBSERVER_SAPI', 'SAPI وب سرور');
+@define('TEMPLATE_SET', '\'%s\' به عنوان پوسته پیش فرض ثبت شد');
+@define('SEARCH_ERROR', 'بخش جستجو به درستی کار نمی کند. این مورد را به مدیر سایت گزارش دهید: ممکن است این مشکل به دلیل از دست رفتن اندیس های جدول ها پیش آمده باشد. در MySQL شما باید دسترسی اجرای کوئری روبرو را داشته باشید: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title،body،extended)</pre> خطای برگشتی پایگاه داده: <pre>%s</pre>');
+@define('EDIT_THIS_CAT', 'در حال تغییر "%s"');
+@define('CATEGORY_REMAINING', 'حذف این موضوع و انتقال ارسال ها به این موضوع');
+@define('CATEGORY_INDEX', 'در زیر لیستی از موضوعات برای این ارسال وجود دارند');
+@define('NO_CATEGORIES', 'بدون موضوع');
+@define('RESET_DATE', 'تنظیم دوباره تاریخ');
+@define('RESET_DATE_DESC', 'برای تنظیم مجدد تاریخ به اکنون، اینجا کلیک کنید');
+@define('PROBLEM_PERMISSIONS_HOWTO', 'دسترسی ها می توانند از طریق دسترسی shell تغییر یابند: `<em>%s</em>` روی شاخه مشکل دار، یا تنظیم آن توسط برنامه های FTP');
+@define('WARNING_TEMPLATE_DEPRECATED', 'خطر: پوسته شما از نگارش قدیمی پوسته ها استفاده می کند، توصیه می شود اگر امکان دارد به روز رسانی کنید');
+@define('ENTRY_PUBLISHED_FUTURE', 'این ارسال هنوز منتشر نشده است.');
+@define('ENTRIES_BY', 'ارسال توسط %s');
+@define('PREVIOUS', 'قبل');
+@define('NEXT', 'بعد');
+@define('APPROVE', 'موافقت');
+@define('DO_MARKUP_DESCRIPTION', 'آیا تغییرات روی متن اعمال شود (شکلک ها، میانبر کردن متن های *، /، _، ...). غیر فعال کردن این گزینه، تمامی کد های HTML را حفظ خواهد کرد و تغییری اعمال نخواهد شد.');
+@define('CATEGORY_ALREADY_EXIST', 'یک موضوع با نام مشابه "%s" قبلا وجود دارد');
+@define('ERROR_FILE_FORBIDDEN', 'شما اجازه بالاگذاری فایل ندارید');
+@define('ADMIN', 'مدیر');
+@define('ADMIN_FRONTPAGE', 'صفحه آغازین');
+@define('QUOTE', 'نقل قول');
+@define('IFRAME_SAVE', 'اکنون Serendipity در حال ساخت پیش نمایش صفحات شما می باشد...');
+@define('IFRAME_SAVE_DRAFT', 'اکنون Serendipity در حال ساخت پیش نمایش صفحات شما می باشد...');
+@define('IFRAME_PREVIEW', 'اکنون Serendipity ارسال شما را ذخیره می کند، ساختن ردپا ها و. این عملیات ممکن است کمی به طول بیانجامد، لطفا صبر کنید.');
+@define('IFRAME_WARNING', 'مرورگر شما از iframe پشتیبانی نمی کند. لطفا فایل serendipity_config.inc.php را باز کرده و مقدار $serendipity[\'use_iframe\'] را برابر FALSE قرار دهید.');
+@define('NONE', 'هیچ کدام');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'تنظیمات پیش فرض برای ارسال های جدید');
+@define('UPGRADE', 'به روز رسانی');
+@define('UPGRADE_TO_VERSION', 'به روز رسانی به نسخه %s');
+@define('DELETE_DIRECTORY', 'حذف این شاخه');
+@define('DELETE_DIRECTORY_DESC', 'شما می خواهید شاخه ای را حذف کنید که دارای فایل می باشد, ممکن است این فایل ها در ارسال های شما استفاده شده باشند.');
+@define('FORCE_DELETE', 'فایل هایی که در پایگاه داده فایل ها وجود ندارند را هم حذف کن');
+@define('CREATE_DIRECTORY', 'ایجاد شاخه');
+@define('CREATE_NEW_DIRECTORY', 'ساخت شاخه جدید');
+@define('CREATE_DIRECTORY_DESC', 'در اینجا شما می توانید شاخه جدیدی برای ریختن رسانه ها بسازید. نام مناسبی برای شاخه انتخاب کنید و در صورتی که تمایل دارید شاخه پدر را نیز انتخاب کنید.');
+@define('BASE_DIRECTORY', 'شاخه اصلی');
+@define('USERLEVEL_EDITOR_DESC', 'ویرایشگر استاندارد');
+@define('USERLEVEL_CHIEF_DESC', 'ویرایشگر مدیر');
+@define('USERLEVEL_ADMIN_DESC', 'مدیر');
+@define('USERCONF_USERLEVEL', 'نوع دسترسی');
+@define('USERCONF_USERLEVEL_DESC', 'دسترسی باید یکی از گزینه های روبرو باشد: [USERLEVEL_ADMIN] - مدیر، [USERLEVEL_CHIEF] - رییس نویسندگان، [USERLEVEL_EDITOR] - نویسنده عادی.');
+@define('USER_SELF_INFO', 'کاربر %s با سطح دسترسی %s وارد شد');
+@define('ADMIN_ENTRIES', 'مقادیر');
+@define('RECHECK_INSTALLATION', 'چک کردن دوباره نصب برنامه');
+@define('IMAGICK_EXEC_ERROR', 'توانایی اجرای "%s" نمی باشد, خطا: %s, مقدار بازگشتی: %d');
+@define('INSTALL_OFFSET_DESC', 'اختلاف زمانی بین زمان وب سرور و زمان دلخواه خود را وارد کنید');
+@define('UNMET_REQUIREMENTS', 'اشکال در موارد مورد نیاز: %s');
+@define('CHARSET', 'نوع حروف');
+@define('AUTOLANG', 'از زبان پیش فرض مرورگر بیننده استفاده شود');
+@define('AUTOLANG_DESC', 'اگر فعال باشد، از زبان مرورگر بیننده برای زبان پیش فرض ورودی ها و زبان پوسته وبلاگ استفاده می شود.');
+@define('INSTALL_AUTODETECT_URL', 'تشخیص خودکار استفاده از HTTP-Host');
+@define('INSTALL_AUTODETECT_URL_DESC', 'اگر روی "بله" تنظیم شود, Serendipity قرار داشتن آدرس BaseURL که در بخش تنظیمات وارد کردید را در درخواست ارسالی بررسی می کند. فعال کردن این گزینه، باعث می شود که شما بتوانید از چندین دامنه برای دیدن وبلاگ Serendipity و تمامی لینک های وابسته به آن استفاده کنید.');
+@define('CONVERT_HTMLENTITIES', 'سعی در تغییر مقادیر HTML داشته باشم؟');
+@define('EMPTY_SETTING', 'شما مقدار معتبری برای "%s" انتخاب نکردید!');
+@define('USERCONF_REALNAME', 'نام واقعی');
+@define('USERCONF_REALNAME_DESC', 'نام کامل نویسنده. این نام توسط خواننده دیده خواهد شد');
+@define('HOTLINK_DONE', 'به فایل مربوطه، لینک داده شد.');
+@define('ENTER_MEDIA_URL_METHOD', 'روش دریافت:');
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'توجه: اگر شما گزینه "لینک دادن به سرور" را انتخاب کرده اید، توجه داشته باشید که باید به سرور دسترسی داشته باشید. لینک دادن به سایت های دیگر، به شما اجازه می دهد از فایل ها، بدون ذخیره در سایت خودتان، استفاده کنید.');
+@define('MEDIA_HOTLINKED', 'لینک داده شد');
+@define('FETCH_METHOD_IMAGE', 'عکس را روی سرور پایین گذاری کن');
+@define('FETCH_METHOD_HOTLINK', 'لینک دادن به سرور');
+@define('DELETE_HOTLINK_FILE', 'لینک فایل <b>%s</b> حذف شد');
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'آیا آدرس ایمیل ها دیده شود؟');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_fi.inc.php b/lang/serendipity_lang_fi.inc.php
new file mode 100644 (file)
index 0000000..9725dd5
--- /dev/null
@@ -0,0 +1,668 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+@define('LANG_CHARSET', 'UTF-8');
+@define('DATE_LOCALES', 'finnish, fi, fi_FI.UTF-8');
+@define('DATE_FORMAT_ENTRY', '%A, %B %e. %Y');
+@define('DATE_FORMAT_SHORT', '%Y-%m-%d %H:%M');
+@define('WYSIWYG_LANG', 'fi');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', ',');
+@define('NUMBER_FORMAT_THOUSANDS', '.');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Serendipity ylläpitovalikko');
+@define('HAVE_TO_BE_LOGGED_ON', 'Sinun täytyy kirjautua tätä toiminta varten');
+@define('WRONG_USERNAME_OR_PASSWORD', 'Väärä käyttäjätunnus tai salasana');
+@define('APPEARANCE', 'Ulkoasu');
+@define('MANAGE_STYLES', 'Tyylien ylläpito');
+@define('CONFIGURE_PLUGINS', 'Laajennosten asetukset');
+@define('CONFIGURATION', 'Asetukset');
+@define('BACK_TO_BLOG', 'Takaisin blogiin');
+@define('LOGIN', 'Kirjaudu');
+@define('LOGOUT', 'Poistu');
+@define('LOGGEDOUT', 'Poistuttu.');
+@define('CREATE', 'Luo');
+@define('SAVE', 'Talleta');
+@define('NAME', 'Nimi');
+@define('CREATE_NEW_CAT', 'Luo uusi luokka');
+@define('I_WANT_THUMB', 'Haluan käyttää pienoiskuvaa kirjauksessani.');
+@define('I_WANT_BIG_IMAGE', 'Haluan käyttää suurta kuvaa kirjauksessani.');
+@define('I_WANT_NO_LINK', ' Haluan sen kuvana');
+@define('I_WANT_IT_TO_LINK', 'Haluan sen linkkinä tähän kohteeseen:');
+@define('BACK', 'Takaisin');
+@define('FORWARD', 'Eteenpäin');
+@define('ANONYMOUS', 'Nimetön');
+@define('NEW_TRACKBACK_TO', 'Uusi paluuviite tehty');
+@define('NEW_COMMENT_TO', 'Uusi kommentti');
+@define('RECENT', 'Viimeisimmät...');
+@define('OLDER', 'Vanhemmat...');
+@define('DONE', 'Valmis');
+@define('WELCOME_BACK', 'Tervetuloa takaisin,');
+@define('TITLE', 'Otsikko');
+@define('DESCRIPTION', 'Kuvaus');
+@define('PLACEMENT', 'Sijainti');
+@define('DELETE', 'Poista');
+@define('SAVE', 'Talleta');
+@define('UP', 'YLÖS');
+@define('DOWN', 'ALAS');
+@define('ENTRIES', 'Kirjaukset');
+@define('NEW_ENTRY', 'Uusi kirjaus');
+@define('EDIT_ENTRIES', 'Muokkaa kirjauksia');
+@define('CATEGORIES', 'Luokat');
+@define('WARNING_THIS_BLAHBLAH', "HUOMAUTUS:\\nTämä saattaa kestää kauan jos pienoiskuvattomia kuvia on paljon..");
+@define('CREATE_THUMBS', 'Luo pienoiskuvat uudelleen');
+@define('MANAGE_IMAGES', 'Kuvien hallinta');
+@define('NAME', 'Nimi');
+@define('EMAIL', 'Sähköposti');
+@define('HOMEPAGE', 'Kotisivu');
+@define('COMMENT', 'Kommentti');
+@define('REMEMBER_INFO', 'Muista tiedot? ');
+@define('SUBMIT_COMMENT', 'Lähetä kommentti');
+@define('NO_ENTRIES_TO_PRINT', 'Ei kirjauksia');
+@define('COMMENTS', 'Kommentit');
+@define('ADD_COMMENT', 'Lisää kommentti');
+@define('NO_COMMENTS', 'Ei kommentteja');
+@define('POSTED_BY', 'Lähettänyt');
+@define('ON', '');
+@define('A_NEW_COMMENT_BLAHBLAH', 'Blogisi "%s", kirjaukseen "%s" on uusi kommentti.');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'Uusi paluuviittaus kirjaukseesi "%s".');
+@define('NO_CATEGORY', 'Ei luokkaa');
+@define('ENTRY_BODY', 'Kirjaus');
+@define('EXTENDED_BODY', 'Kirjauksen jatko');
+@define('CATEGORY', 'Luokka');
+@define('EDIT', 'Muokkaa');
+@define('NO_ENTRIES_BLAHBLAH', 'Kysely %s ei palauttanut yhtään kirjausta' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'Hakusi %s palautti %s osumaa:');
+@define('SEARCH_TOO_SHORT', 'Haun on oltava pidempi kuin 3 merkkiä');
+@define('IMAGE', 'Kuva');
+@define('ERROR_FILE_NOT_EXISTS', 'Virhe: Tiedostoa vanhalla nimellä ei ole!');
+@define('ERROR_FILE_EXISTS', 'Virhe: Tiedostonimi on jo käytössä, valitse uusi!');
+@define('ERROR_SOMETHING', 'Virhe: Jokin meni pieleen.');
+@define('ADDING_IMAGE', 'Lisätään kuvaa...');
+@define('THUMB_CREATED_DONE', 'Pienoiskuvaa luodaan.<br>Valmis.');
+@define('ERROR_FILE_EXISTS_ALREADY', 'Virhe: Tiedosto on jo olemassa!');
+@define('ERROR_UNKNOWN_NOUPLOAD', 'Pieleen meni, tiedostoa ei tuotu. Kenties tiedoston koko oli liian suuri. Kysy palveluntarjoajaltasi apua tai muokkaa php.ini tiedostoasi salliaksesi isompien tiedostojen tuonnin..');
+@define('GO', 'Tee!');
+@define('NEWSIZE', 'Uusi koko: ');
+@define('RESIZE_BLAHBLAH', '<b>Muokkaa kokoa %s</b><p>');
+@define('ORIGINAL_SIZE', 'Alkuperäinen koko: <i>%sx%s</i> pikseliä');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>Kuvan koon muokkaus. Voit muokata kuvan kokoa säilyttäen suhteet, lisää toiseen laatikkoon arvo ja paina tab-näppäintä, niin lasken sinulle suhteen mukaisen toisen arvon automaattisesti.</p>');
+@define('QUICKJUMP_CALENDAR', 'Pikasiirtymä kalenteriin');
+@define('QUICKSEARCH', 'Pikahaku');
+@define('SEARCH_FOR_ENTRY', 'Etsi kirjausta');
+@define('ARCHIVES', 'Arkisto');
+@define('BROWSE_ARCHIVES', 'Selaa arkistoa kuukausittain');
+@define('TOP_REFERRER', 'Huippuviittaajat');
+@define('SHOWS_TOP_SITES', 'Näyttää listan eniten viitanneista sivustoista.');
+@define('TOP_EXITS', 'Huippupoistumiset');
+@define('SHOWS_TOP_EXIT', 'Näyttää eniten viittaamasi sivustot, joille on poistuttu');
+@define('SYNDICATION', 'Ajantasaistus');
+@define('SHOWS_RSS_BLAHBLAH', 'Näyttää RSS linkit');
+@define('ADVERTISES_BLAHBLAH', 'Mainostaa Serendipityä');
+@define('HTML_NUGGET', 'HTML raapale');
+@define('HOLDS_A_BLAHBLAH', 'Lisää HTML raapaleen sivupalstaan');
+@define('TITLE_FOR_NUGGET', 'Raapaleen otsikko');
+@define('THE_NUGGET', 'HTML raaplae!');
+@define('SYNDICATE_THIS_BLOG', 'Ajantasaista tähän blogiin!');
+@define('YOU_CHOSE', 'Valitsit %s');
+@define('IMAGE_ROTATE_LEFT', 'Käännä kuvaa 90 astetta vastapäivään');
+@define('IMAGE_ROTATE_RIGHT', 'Käännä kuvaa 90 astetta myötäpäivään');
+@define('IMAGE_SIZE', 'Kuvan koko');
+@define('IMAGE_AS_A_LINK', 'Kuvan lisäys');
+@define('POWERED_BY', 'Moottorina');
+@define('TRACKBACKS', 'Paluuviitteet');
+@define('TRACKBACK', 'Paluuviite');
+@define('NO_TRACKBACKS', 'Ei paluuviitteitä');
+@define('TOPICS_OF', 'Aiheet');
+@define('VIEW_FULL', 'Näytä kaikki');
+@define('VIEW_TOPICS', 'Näytä aiheet');
+@define('AT', '');
+@define('SET_AS_TEMPLATE', 'Aseta malliksi');
+@define('IN', '');
+@define('EXCERPT', 'Ote');
+@define('TRACKED', 'Jäljitetty');
+@define('LINK_TO_ENTRY', 'Linkitä kirjaukseen');
+@define('LINK_TO_REMOTE_ENTRY', 'Linkitä toisen kirjaukseen');
+@define('IP_ADDRESS', 'IP-osoite');
+@define('USER', 'Käyttäjä');
+@define('THUMBNAIL_USING_OWN', 'Käytetään kuvaa %s sen omana pienoiskuvana, koska se on jo niin pieni.');
+@define('THUMBNAIL_FAILED_COPY', 'Halusttiin käyttää %s omana pienoiskuvanaan, mutta kopiointi epäonnistui.');
+@define('AUTHOR', 'Kirjoittaja');
+@define('LAST_UPDATED', 'Viimeisin päivitys');
+@define('TRACKBACK_SPECIFIC', 'Kirjauksen URI paluuviitteille');
+@define('DIRECT_LINK', 'Suora linkki tähän kirjaukseen');
+@define('COMMENT_ADDED', 'Kommentti lisätty. ');
+@define('COMMENT_ADDED_CLICK', 'Napasauta %spalataksesi%s kommentteihin, ja %s sulkeaksesi%s tämän ikkunan.');
+@define('COMMENT_NOT_ADDED', 'Tämän kirjauksen kommentointi ei ole sallittua. ');
+@define('COMMENT_NOT_ADDED_CLICK', 'Napsauta %spalataksesi%s kommentteihin, ja %ssulkeaksesi%s tämän ikkunan.');
+@define('COMMENTS_DISABLE', 'Kiellä kirjauksen kommentointi.');
+@define('COMMENTS_ENABLE', 'Salli kirjauksen kommentointi');
+@define('COMMENTS_CLOSED', 'Kirjoittaja ei salli tämän kirjauksen kommentointia');
+@define('EMPTY_COMMENT', 'Tyhjä kommentti, %spalaa%s ja yritä uudelleen');
+@define('ENTRIES_FOR', 'Kirjaukset alkaen %s');
+@define('DOCUMENT_NOT_FOUND', 'Kirjoitusta %s ei löytynyt.');
+@define('USERNAME', 'Käyttäjätunnus');
+@define('PASSWORD', 'Salasana');
+@define('AUTOMATIC_LOGIN', 'Talleta kirjautumistiedot');
+@define('SERENDIPITY_INSTALLATION', 'Serendipityn asennus');
+@define('LEFT', 'vasen');
+@define('RIGHT', 'oikea');
+@define('HIDDEN', 'piilotettu');
+@define('REMOVE_TICKED_PLUGINS', 'Poista valitut laajennokset');
+@define('SAVE_CHANGES_TO_LAYOUT', 'Talleta taiton muutokset');
+@define('COMMENTS_FROM', 'Kommentit alkaen');
+@define('ERROR', 'Virhe');
+@define('ENTRY_SAVED', 'Kirjauksesi on talletettu');
+@define('DELETE_SURE', 'Oletko varma, että haluat poistaa #%s lopullisesti?');
+@define('NOT_REALLY', 'En todellakaan...');
+@define('DUMP_IT', 'Anna mennä!');
+@define('RIP_ENTRY', 'Lepää rauhassa #%s');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Luokka #%s poistettu. Vanhat kirjoitukset siirretty luokkaan #%s');
+@define('CATEGORY_DELETED', 'Luokka #%s poistettu.');
+@define('INVALID_CATEGORY', 'Et valinnut luokkaa');
+@define('CATEGORY_SAVED', 'Luokka talletettu');
+@define('SELECT_TEMPLATE', 'Valitse pohja, jota haluat käyttää');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'Kirjausten lisäys meni pieleen!');
+@define('MT_DATA_FILE', 'Movable Type tiedosto');
+@define('FORCE', 'Pakota');
+@define('CREATE_AUTHOR', 'Luo kirjoittaja \'%s\'.');
+@define('CREATE_CATEGORY', 'Luo luokkka \'%s\'.');
+@define('MYSQL_REQUIRED', 'Tarvitset MySQL laajennoksen tehdäksesi tämän.');
+@define('COULDNT_CONNECT', 'Yhteyttä MySQL tietokantaan: %s ei saatu.');
+@define('COULDNT_SELECT_DB', 'Tietokantaa: %s ei voitu valita.');
+@define('COULDNT_SELECT_USER_INFO', 'Käyttäjätiedon: %s valinta epäonnistui.');
+@define('COULDNT_SELECT_CATEGORY_INFO', 'Luokan: %s valinta epäonnistui.');
+@define('COULDNT_SELECT_ENTRY_INFO', 'Kirjauksen: %s valinta epäonnistui.');
+@define('COULDNT_SELECT_COMMENT_INFO', 'Kommentin: %s valinta epäonnistui.');
+@define('YES', 'Kyllä');
+@define('NO', 'Ei');
+@define('USE_DEFAULT', 'Oletus');
+@define('CHECK_N_SAVE', 'Tarkista ja talleta');
+@define('DIRECTORY_WRITE_ERROR', 'Ei oikeutta hakemistoon %s.');
+@define('DIRECTORY_CREATE_ERROR', 'Hakemistoa %s ei ole, eikä voi luoda. Ole kiltti ja tee se itse.');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; komento <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', 'Ohjelman %s suoritus ei onnistu');
+@define('FILE_WRITE_ERROR', 'Tiedostoon %s kirjoittaminen ei onnistu.');
+@define('FILE_CREATE_YOURSELF', 'Ole kiltti ja tee tiedosto itse tai höllennä oikeuksia');
+@define('COPY_CODE_BELOW', '<br />* Kopioi alla oleva ja laita se tiedostoon %s kansiossa %s :<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Vaihda www apachen käyttäjätunnukseen (esim. nobody).');
+@define('BROWSER_RELOAD', 'Kun olet tehnyt tämän, lataa tämä sivu uudestaan.');
+@define('DIAGNOSTIC_ERROR', 'Antamasi tiedot aiheuttivat virheitä tarkistettaessa niitä:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity ei asennettu. Ole kiltti ja <a href="%s">asenna</a> se nyt.');
+@define('INCLUDE_ERROR', 'serendipity virhe: tiedostoa %s ei kyetty lukemaan - poistutaan.');
+@define('DATABASE_ERROR', 'serendipity virhe: tietokantayhteys virhe - poistutaan.');
+@define('CREATE_DATABASE', 'Luodaan oletuskanta...');
+@define('ATTEMPT_WRITE_FILE', 'Yritetään kirjoittaa tiedosto %s...');
+@define('WRITTEN_N_SAVED', 'Asetukset luotuja ja talletettu.');
+@define('IMAGE_ALIGNMENT', 'Kuvan tasaus');
+@define('ENTER_NEW_NAME', 'Anna uusi nimi: ');
+@define('RESIZING', 'Muokataan');
+@define('RESIZE_DONE', 'Valmis (muokattu %s kuvaa).');
+@define('SYNCING', 'Päivitetään tietokantaa vastaamaan kuvakansiota');
+@define('SYNC_DONE', 'Valmis (Päivitetty %s kuvaa).');
+@define('FILE_NOT_FOUND', 'Tiedostoa <b>%s</b> ei löydy, ehkäpä se on jo poistettu?');
+@define('ABORT_NOW', 'Luovuta nyt');
+@define('REMOTE_FILE_NOT_FOUND', 'Tiedostoa ei löytynyt kohdepalvelimelta, onhan  URL: <b>%s</b> oikein?');
+@define('FILE_FETCHED', '%s haettu nimelle %s');
+@define('FILE_UPLOADED', 'Tiedosto %s tuotu nimelle %s');
+@define('WORD_OR', 'Tai');
+@define('SCALING_IMAGE', 'Skaalataan %s %s x %s px');
+@define('KEEP_PROPORTIONS', 'Säilytä suhteet');
+@define('REALLY_SCALE_IMAGE', 'Skaalataanko kuva? Tätä operaatiota ei voi peruuttaa!');
+@define('TOGGLE_ALL', 'Näytä kaikki');
+@define('TOGGLE_OPTION', 'Näytä');
+@define('SUBSCRIBE_TO_THIS_ENTRY', 'Tilaa tämä kirjaus');
+@define('UNSUBSCRIBE_OK', "%s :n tilaus peruttu.");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'Uusi kommentti tilattuun kirjaukseen "%s"');
+@define('SUBSCRIPTION_MAIL', "Moi %s,\n\nKiinnostuksesi kohteeseen \"%s\" on uusi kommentti, otsikolla \"%s\"\nKommentoija on: %s\n\nKirjoitus on täällä: %s\n\nVoit peruuttaa tilauksesi linkistä: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "Moros %s,\n\nUusi paluuvittaus kiinnostuksesi kohteeseen \"%s\", otsikolla \"%s\"\nViittaaja on: %s\n\nLöydät kirjoituksen linkistä: %s\n\nVoit peruuttaa tilauksesi: %s\n");
+@define('SIGNATURE', "\n-- \n%s moottorina on Serendipity.\nParas blogisofta mailla halmeilla..\nTsekkaa <http://s9y.org> saadaksesi lisätietoja.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91 ');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0 ');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0 ');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 Kommentit');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3 ');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'Kenttä "päätoimittaja"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  'Kenttä "webMasterr"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'RSS linkin kuva');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', 'Kuvan leveys');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'Kuvan korkeus');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  'Webmasterin sähköpostiosoite tai tyhjää. (tyhjä: piilotettu) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', 'Päätoimittajan sähköpostiosoite tai tyhjää (tyhjä: piilotettu) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'GIF/JPEG/PNG kuvan urli tai tyhjää. (tyhjä: serendipityn logo)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'pikseleissä, max. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'pikseleissä, max. 400');
+@define('SYNDICATION_PLUGIN_TTL', 'Field "ttl" (elinikä)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'Aika minuuteissa, jonka ajantasaistajat saavat säilyttää kopiota tarkistamatta (tyhjä: piilotettu) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'Kenttä "julkaisuPäivä"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', 'Pitäisikö "julkaisuPäivä"-kenttä lisätä RSS-kanavalle näyttämään viimeisimmän kirjauksen päiväys?');
+@define('CONTENT', 'Sisältö');
+@define('TYPE', 'Tyyppi');
+@define('DRAFT', 'Luonnos');
+@define('PUBLISH', 'Julkaise');
+@define('PREVIEW', 'Esikatselu');
+@define('DATE', 'Päiväys');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', 'Päiväyksen muoto on virheellinen. Oikea muoto on VVVV-KK-PP TT:MM.');
+@define('CATEGORY_PLUGIN_DESC', 'Näyttää luokkalistan.');
+@define('ALL_AUTHORS', 'Kaikki kirjoittajat');
+@define('CATEGORIES_TO_FETCH', 'Haettavat luokat');
+@define('CATEGORIES_TO_FETCH_DESC', 'Kenen luokat haetaan?');
+@define('PAGE_BROWSE_ENTRIES', 'Sivu %s(%s), kaiken kaikkiaan %s kirjoitusta');
+@define('PREVIOUS_PAGE', 'edellinen sivu');
+@define('NEXT_PAGE', 'seuraava sivu');
+@define('ALL_CATEGORIES', 'Kaikki luokat');
+@define('DO_MARKUP', 'Tee notaatio muunnokset');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'Päiväyksen muotoilu');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'Kirjauksen todellinen päiväys, PHPn strftime() muuttujilla. (Oletus: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'Mallipohjan avaaminen epäonnistui, ole kiltti ja päivitä  serendipity!');
+@define('ADVANCED_OPTIONS', 'Edistyneen käyttäjän valinnat');
+@define('EDIT_ENTRY', 'Muokkaa kirjausta');
+@define('HTACCESS_ERROR', 'Serendipity tarvitsee oikeudet ".htaccess" tiedostoon tarkistaakseen asennuksen. Tarkistus epäonnistui, koska oikeudt ovat väärin. Ole kiltti ja korjaa: <br />&nbsp;&nbsp;%s<br />. Lataa tämä sivu uudestaan kun olet korjannut..');
+@define('SIDEBAR_PLUGINS', 'Sivupalstan laajennokset');
+@define('EVENT_PLUGINS', 'Tapahtumalaajennokset');
+@define('SORT_ORDER', 'Järjestyskenttä');
+@define('SORT_ORDER_NAME', 'Nimi');
+@define('SORT_ORDER_EXTENSION', 'Tiedostopääte');
+@define('SORT_ORDER_SIZE', 'Tiedostokoko');
+@define('SORT_ORDER_WIDTH', 'Kuvan leveys');
+@define('SORT_ORDER_HEIGHT', 'Kuvan korkeus');
+@define('SORT_ORDER_DATE', 'Tuontipäiväys');
+@define('SORT_ORDER_ASC', 'Nouseva');
+@define('SORT_ORDER_DESC', 'Laskeva');
+@define('THUMBNAIL_SHORT', 'Pienoiskuva');
+@define('ORIGINAL_SHORT', 'Alkup.');
+@define('APPLY_MARKUP_TO', 'Käytä notaatiota kohdassa %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'Viikon alusta');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipityn mielestä asetuksiesi versio on %s, mutta serendipityn versio on %s, tarvitaan päivitys! <a href="%s">Napsauta</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'Moro, ja teretulemas Serendipityn päivitykseen.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', 'Olen agenttisi ja autan sinua päivittämään Serendipity %s asennuksesi.');
+@define('SERENDIPITY_UPGRADER_WHY', 'Olet juuri asentanut Serendipity version %s, mutta kanta on jäänyt päivittämättä.');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'Tietokantapäivitykset (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'Seuraavat .sql-tiedostot pitäisi suorittaa ennen  Serendipityn käyttöä');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  'Versiokohtaiset tehtävät');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', 'Ei versiokohtaisia tehtäviä');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', 'Haluatko minun tekevän ne puolestasi?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'Ei, teen ne itse.');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'Juu, olehyvä vain');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'Näyttäisi siltä, ettet tarvitse päivityksiä.');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', 'Serendipity on päivitetty');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'Jätit automaattipäivitykset väliin. Varmista, että kanta on oikein asennettu ja oikeat skriptat on ajettu.');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'Serendipitysi on nyt versiota %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', 'Takaisin blogiin %stästä%s');
+@define('MANAGE_USERS', 'Käyttäjien ylläpito');
+@define('CREATE_NEW_USER', 'Luo uusi käyttäjä');
+@define('CREATE_NOT_AUTHORIZED', 'Et voi muokata samantasoisia käyttäjiä kuin itse olet');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'Et voi muokata ylempiarvoisiasi.');
+@define('CREATED_USER', 'Uusi käyttäjä %s on luotu');
+@define('MODIFIED_USER', 'Käyttäjä %s muokattu');
+@define('USER_LEVEL', 'Taso');
+@define('DELETE_USER', 'Olet aikeissa poistaa käyttäjän  #%d %s. Oletko tosissasi? Käyttäjän kirjoitukset sensuroidaan.');
+@define('DELETED_USER', 'Käyttäjä #%d %s tuhottu.');
+@define('LIMIT_TO_NUMBER', 'Montako näytetään?');
+@define('ENTRIES_PER_PAGE', 'kirjoitusta sivulla');
+@define('XML_IMAGE_TO_DISPLAY', 'XML Nappula');
+@define('XML_IMAGE_TO_DISPLAY_DESC','XML kanavat esitetään tällä kuvanappulalla.Tyhjä valitsee oletuksen kirjoittamalla:\'none\' ei käytetä kuvanappulaa.');
+
+@define('DIRECTORIES_AVAILABLE', 'Valitsemalla hakemistolistasta hakemiston valitset hakemiston johon uusi hakemisto luodaan.');
+@define('ALL_DIRECTORIES', 'kaikki hakemistot');
+@define('MANAGE_DIRECTORIES', 'Ylläpidä hakemistoja');
+@define('DIRECTORY_CREATED', 'Hakemisto <strong>%s</strong> on luotu.');
+@define('PARENT_DIRECTORY', 'Hakemistovanhempi');
+@define('CONFIRM_DELETE_DIRECTORY', 'Haluatko todella poistaa hakemiston %s sisältöineen?');
+@define('ERROR_NO_DIRECTORY', 'Virhe: Hakemistoa %s ei ole');
+@define('CHECKING_DIRECTORY', 'Tarkistetaan tiedostoja hakemistossa %s');
+@define('DELETING_FILE', 'Poistetaan tiedostoa %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', 'Hakemisto ei ole tyhjä. Valitse "pakota poiston", jos haluat poistaa tiedostotkin. Hakemiston tiedostot:');
+@define('DIRECTORY_DELETE_FAILED', 'Hakemiston %s poisto epäonnistui Tarkista oikeudet tai mahdollinen ylläoleva.');
+@define('DIRECTORY_DELETE_SUCCESS', 'Hakemisto %s poistettu.');
+@define('SKIPPING_FILE_EXTENSION', 'Ohitetaan tiedsto: Tiedostopääte %s puuttuu.');
+@define('SKIPPING_FILE_UNREADABLE', 'Ohitetaan tiedosto: %s, tiedostoa ei voi lukea.');
+@define('FOUND_FILE', 'Löytyi uusi/muokattu tiedosto: %s.');
+@define('ALREADY_SUBCATEGORY', '%s on jo %s alikategoria.');
+@define('PARENT_CATEGORY', 'Kategoriavanhempi');
+@define('IN_REPLY_TO', 'Vastauksena');
+@define('TOP_LEVEL', 'Ylin taso');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s');
+@define('PERMISSIONS', 'Oikeudet');
+@define('SETTINGS_SAVED_AT', 'Uudet asetukset on tallettetu %s');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', 'Tietokanta-asetukset');
+@define('INSTALL_CAT_DB_DESC', 'Serendipityn tarvitsemat tietokanta-asetukset.');
+@define('INSTALL_DBTYPE', 'Tietokantatyyppi');
+@define('INSTALL_DBTYPE_DESC', 'Tietokannan tyyppi');
+@define('INSTALL_DBHOST', 'Kantakone');
+@define('INSTALL_DBHOST_DESC', 'Kantapalvelimen nimi');
+@define('INSTALL_DBUSER', 'Kantakäyttäjä');
+@define('INSTALL_DBUSER_DESC', 'Kantakäyttäjän käyttäjätunnus');
+@define('INSTALL_DBPASS', 'Kantakäyttäjän salasana');
+@define('INSTALL_DBPASS_DESC', 'Kantakäyttäjän salasana');
+@define('INSTALL_DBNAME', 'Kannan nimi');
+@define('INSTALL_DBNAME_DESC', 'Tietokannan nimi');
+@define('INSTALL_DBPREFIX', 'Tauluetuliite');
+@define('INSTALL_DBPREFIX_DESC', 'Etuliite kantataulujen nimille.Esim serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', 'Polut');
+@define('INSTALL_CAT_PATHS_DESC', 'Tiedosto- ja hakemistopolut. Älä unohoda hakemistojen nimistä loppukauttaviivaa!');
+@define('INSTALL_FULLPATH', 'Asennuspolku');
+@define('INSTALL_FULLPATH_DESC', 'Serendipity-asennushakemiston täydellinen ja bsoluuttinen hakemistopolku');
+@define('INSTALL_UPLOADPATH', 'Tuontipolku');
+@define('INSTALL_UPLOADPATH_DESC', 'Kaikki tuodut tiedostot talletetaan tänne. Suhteessa aseunnuspolkkuun. - Yleensä \'uploads/\'');
+@define('INSTALL_RELPATH', 'Suhteellinen osoite');
+@define('INSTALL_RELPATH_DESC', 'Blogisi osoite, tyypillisesti \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', 'Malliosoite');
+@define('INSTALL_RELTEMPLPATH_DESC', 'Polku, josta mallipohjat löytyvät, suhteessa suhteelliseen polkuun.  \'relative path\'');
+@define('INSTALL_RELUPLOADPATH', 'Tuontiosoite');
+@define('INSTALL_RELUPLOADPATH_DESC', 'Tiedostotuontien osoite suhteessa suhteelliseen osoitteeseen');
+@define('INSTALL_URL', 'Blogin osoite');
+@define('INSTALL_URL_DESC', 'Serendipity asennuksen osoite');
+@define('INSTALL_INDEXFILE', 'Aloitustiedosto');
+@define('INSTALL_INDEXFILE_DESC', 'Serendipityn aloitustiedoston nimi');
+
+/* Generel settings */
+@define('INSTALL_CAT_SETTINGS', 'Yleiset asetukset');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Serendipity toimintojen muokkaus');
+@define('INSTALL_USERNAME', 'Ylläpitäjän tunnus');
+@define('INSTALL_USERNAME_DESC', 'Ylläpitäjän käyttäjätunnus');
+@define('INSTALL_PASSWORD', 'Ylläpitäjän salasana');
+@define('INSTALL_PASSWORD_DESC', 'Ylläpitäjän salasana');
+@define('INSTALL_EMAIL', 'Ylläpitäjän sähköpostiosoite');
+@define('INSTALL_EMAIL_DESC', 'Ylläpitäjän sähköpostiosoite.');
+@define('INSTALL_SENDMAIL', 'Postit ylläpitäjälle?');
+@define('INSTALL_SENDMAIL_DESC', 'Haluatko sähköpostia kun blogisasi kommentoidaan?');
+@define('INSTALL_SUBSCRIBE', 'Saavatko käyttäjät tilata kirjoituksia?');
+@define('INSTALL_SUBSCRIBE_DESC', 'Käyttäjät saavat sähköpostia kun tilattua kirjoitusta kommentoidaan.');
+@define('INSTALL_BLOGNAME', 'Blogin nimi');
+@define('INSTALL_BLOGNAME_DESC', 'Blogisi nimi');
+@define('INSTALL_BLOGDESC', 'Blogisi kuvaus');
+@define('INSTALL_BLOGDESC_DESC', 'Blogisi kuvaus');
+@define('INSTALL_LANG', 'Kieli');
+@define('INSTALL_LANG_DESC', 'Valitse blogisi käyttöliittymän kieli');
+
+/* Ulkoasu and options */
+@define('INSTALL_CAT_DISPLAY', 'Ulkoasuvalinnat');
+@define('INSTALL_CAT_DISPLAY_DESC', 'Ulkoasuun vaikuttavat valinnat');
+@define('INSTALL_WYSIWYG', 'Käytä WYSIWYG muokkainta');
+@define('INSTALL_WYSIWYG_DESC', 'Haluatko käyttää WYSIWYG muokkainta? (Väittä toimivansa IE5+, ja osittain  Mozilla 1.3+)');
+@define('INSTALL_XHTML11', 'Pakoita XHTML 1.1 yhteensopivaksi');
+@define('INSTALL_XHTML11_DESC', 'Serendipityn tuottama koodi on XHTML 1.1 yhteensopivaa (saattaa kyykyttää 4 sukupolvea vanhemmat palvelimet/selaimet)');
+@define('INSTALL_POPUP', 'Käytä ponnahdusikkunoita');
+@define('INSTALL_POPUP_DESC', 'Esitetäänkö paluuviitteet ja kommentit ponnahdusikkunoissa?');
+@define('INSTALL_EMBED', 'Käytätkö serendipityä osasena?');
+@define('INSTALL_EMBED_DESC', 'Serendipity osana olemassaolevaa sivua. Voit hyödyntää aloitussivu-valintaa sisällyttääksesi serendipity osaksi sivua. Katso README tiedostosta ohjeita!');
+@define('INSTALL_TOP_AS_LINKS', 'Näytä huippupoistumisosoitteet/viittausosoitteet linkkeinä?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"no": Ei, tekstinä google spämmin estämiseksi. "yes": Kyllä, linkkeinä.. "default": Oletus, käytä oletusasetusten valintaa (suositeltu vaihtoehto).');
+@define('INSTALL_BLOCKREF', 'Estä viittaukset');
+@define('INSTALL_BLOCKREF_DESC', 'Onko viittaajia, joiden osoitteita et halua nähdä? Erota palvelinosoitteet \';\':llä. Esto tehdään osamerkkijonoilla!');
+@define('INSTALL_REWRITE', 'URL uudelleenkirjoitus');
+@define('INSTALL_REWRITE_DESC', 'Valitse mitä sääntöjä käytetään blogisi sivuosoitteiden uudelleenkirjoitukseen. Siistityt osoitteet helpottava hakukoneiden indeksointia. Toimintaan tarvitaan webpalvelimella joko mod_rewrite tai "AllowOverride All" serendipity hakemistolle. Oletus on tutki automaattisesti');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', 'Kuvamuunnosten asetukset');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'Serendipityn kuvankäsittelyasetukset.');
+@define('INSTALL_IMAGEMAGICK', 'Käytä Imagemagick:ä');
+@define('INSTALL_IMAGEMAGICK_DESC', 'Onko image magick asennettuna ja haluatko käyttää sitä kuvien käsittelyyn?');
+@define('INSTALL_IMAGEMAGICKPATH', 'Convert-ohjelman sijainti');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'Imagemagick convert-ohjelman nimi ja täydellinen tiedostopolku');
+@define('INSTALL_THUMBSUFFIX', 'Pienoiskuvakkeen suffiksi');
+@define('INSTALL_THUMBSUFFIX_DESC', 'Pienoiskuvakkeet nimetään seuraavasti: originaali.[suffiksi].pääte');
+@define('INSTALL_THUMBWIDTH', 'Pienoiskuvakkeen mitat');
+@define('INSTALL_THUMBWIDTH_DESC', 'Pienoiskuvakkeen maksimileveys');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', 'Henkilötietosi');
+@define('USERCONF_CAT_PERSONAL_DESC', 'Henkilötietojen asettaminen');
+@define('USERCONF_USERNAME', 'Käyttäjänimesi');
+@define('USERCONF_USERNAME_DESC', 'Millä nimimerkillä kirjoitat tähän blogiin');
+@define('USERCONF_PASSWORD', 'Salasanasi');
+@define('USERCONF_PASSWORD_DESC', 'Nimimerkkisi salasana');
+@define('USERCONF_EMAIL', 'Sähköpostiosoitteesi');
+@define('USERCONF_EMAIL_DESC', 'Henkilökohtainen sähköpostiosoitteesi');
+@define('USERCONF_SENDCOMMENTS', 'Lähetänkö komentointi-ilmoitukset?');
+@define('USERCONF_SENDCOMMENTS_DESC', 'Haluatko postia kun joku kommentoi kirjoitustasi?');
+@define('USERCONF_SENDTRACKBACKS', 'Lähetä paluuviitteet?');
+@define('USERCONF_SENDTRACKBACKS_DESC', 'Haluatko paluupostia, kun joku tekee paluuviitteen kirjoitukseesi?');
+@define('USERCONF_ALLOWPUBLISH', 'Oikeudet: Sallitaanko kirjoitusten julkaisu?');
+@define('USERCONF_ALLOWPUBLISH_DESC', 'Saako tämä kirjoittaja julkistaa?');
+@define('SUCCESS', 'Onnistui');
+@define('POWERED_BY_SHOW_TEXT', 'Näytä "Serendipity" tekstinä');
+@define('POWERED_BY_SHOW_TEXT_DESC', 'Tulostaa "Serendipity Weblog" tekstinä');
+@define('POWERED_BY_SHOW_IMAGE', 'Näytä "Serendipity" logolla');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Näyttää serendipityn logon');
+@define('PLUGIN_ITEM_DISPLAY', 'Missä kohde näytetään?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'Vain jatko-osiosssa');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'Vain yleisnäkymässä');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'Kaikkialla');
+@define('RSS_IMPORT_CATEGORY', 'Käytä tätä luokkaa luokattomiin tuotuihin kirjauksiin');
+
+@define('COMMENTS_WILL_BE_MODERATED', 'Kommentit tarkistetaan ennen julkistusta.');
+@define('YOU_HAVE_THESE_OPTIONS', 'Voit:');
+@define('THIS_COMMENT_NEEDS_REVIEW', 'Varoitus: Kommentti hyväksytetään ennen julkistusta');
+@define('DELETE_COMMENT', 'Poista kommentti');
+@define('APPROVE_COMMENT', 'Hyväksy kommentti');
+@define('REQUIRES_REVIEW', 'Vaatii tarkistusta');
+@define('COMMENT_APPROVED', 'Kommentti #%s hyvksytty');
+@define('COMMENT_DELETED', 'Kommentti #%s poistettu');
+@define('COMMENTS_MODERATE', 'Kommentit & paluuviitteet on hyväksytettävä');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'Varoitus: Tätä paluuviitettä ei julkisteta ennen hyväksyntää');
+@define('DELETE_TRACKBACK', 'Poista paluuviite');
+@define('APPROVE_TRACKBACK', 'Hyväksy paluuviite');
+@define('TRACKBACK_APPROVED', 'Paluuviite #%s hyväksytty');
+@define('TRACKBACK_DELETED', 'Paluuviite #%s poistettu');
+@define('VIEW', 'Näytä');
+@define('COMMENT_ALREADY_APPROVED', 'Kommentti #%s on jo hyväksytty');
+@define('COMMENT_EDITED', 'Valittua kommenttia on muokattu');
+@define('HIDE', 'Piilota');
+@define('VIEW_EXTENDED_ENTRY', 'Jatka "%s":n lukemista');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'Tätä linkkiä ei ole tarkoitus napsauttaa. Voit käyttää tätä osoitetta paluuviitteisiin ja pingauksiin omasta blogistasi.Kopioi linkki ja käytä sitä omassa blogissasi.');
+@define('PLUGIN_SUPERUSER_HTTPS', 'Käytä https kirjautuaksesi');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'Login https:llä, web-palvelimesi tulee tukea tätä ominaisuutta!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'Tehdäänkö ulosviittauksista linkkejä?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"no": Ei kommentit, huippuviittaajat ja huippupoistumislinkkejä ei näytetä linkkeinä (suositellaan). "yes": Kyllä, näytetään linkkeinä!');
+@define('PAGE_BROWSE_COMMENTS', 'Sivu (%s/%s), yhteensä %s kommenttia');
+@define('FILTERS', 'Suotimet');
+@define('FIND_ENTRIES', 'Etsi kirjauksia');
+@define('FIND_COMMENTS', 'Etsi kommentteja');
+@define('FIND_MEDIA', 'Etsi media');
+@define('FILTER_DIRECTORY', 'Hakemisto');
+@define('SORT_BY', 'Järjestä');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'Ei paluuviitettä: Yhteyttä %s:n porttiin %d ei saatu');
+@define('MEDIA', 'Media');
+@define('MEDIA_LIBRARY', 'Mediakirjasto');
+@define('ADD_MEDIA', 'Lisää media');
+@define('ENTER_MEDIA_URL', 'Lisättävän tiedoston URL:');
+@define('ENTER_MEDIA_UPLOAD', 'Valitse tiedosto, jonka haluat tuoda:');
+@define('SAVE_FILE_AS', 'Talleta nimellä:');
+@define('STORE_IN_DIRECTORY', 'Talleta hakemistoon: ');
+@define('ADD_MEDIA_BLAHBLAH', '<b>Lisää tiedoston media kirjastoosi:</b><p>Voit tuoda tiedostoja tai käskeä minua hakemaan ne webistä. Jos et keksi sopivaa kuvaa, kokeile, <a href="http://images.google.com" target="_blank">googlea</a> mielikuvillasi, tulokset ovat yleensä käyttökelpoisia ja hauskoja :)<p><b>Valitse tapa:</b><br>');
+@define('MEDIA_RENAME', 'Uudelleennimeä tiedosto');
+@define('IMAGE_RESIZE', 'Muokkaa kuvan kokoa');
+@define('MEDIA_DELETE', 'Poista tiedosto');
+@define('FILES_PER_PAGE', 'Tiedostoja sivulla');
+@define('CLICK_FILE_TO_INSERT', 'Napsauta tiedostoa, jonka haluat lisätä:');
+@define('SELECT_FILE', 'Valitse lisättävä tiedosto');
+@define('MEDIA_FULLSIZE', 'Täysikokoinen');
+@define('CALENDAR_BOW_DESC', 'Viikon aloittava päivä. Oletus on maanantai');
+@define('SUPERUSER', 'Blogin ylläpito');
+@define('ALLOWS_YOU_BLAHBLAH', 'Linkki sivupalstaan, blogin ylläpitoon.');
+@define('CALENDAR', 'Kalenteri');
+@define('SUPERUSER_OPEN_ADMIN', 'Ylläpito');
+@define('SUPERUSER_OPEN_LOGIN', 'Sisäänkirjautuminen');
+@define('INVERT_SELECTIONS', 'Käännä valinnat');
+@define('COMMENTS_DELETE_CONFIRM', 'Haluatko todella poistaa valitut kommentit?');
+@define('COMMENT_DELETE_CONFIRM', 'Haluatko poistaa kommentin #%d, %s?');
+@define('DELETE_SELECTED_COMMENTS', 'Poista valitut kommentit');
+@define('VIEW_COMMENT', 'Näytä kommentti');
+@define('VIEW_ENTRY', 'Näytä kirjaus');
+@define('DELETE_FILE_FAIL' , 'Tiedoston <b>%s</b> poisto epäonnistui');
+@define('DELETE_THUMBNAIL', 'Poistettu pienoiskuva: <b>%s</b>');
+@define('DELETE_FILE', 'Tuhottu tiedosto <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', 'Olet aikeissa poistaa <b>%s</b>:n<br />Jos se on käytössä kirjauksissasi syntyy ongelmia<br />Oletko varma?<br /><br />');
+@define('TRACKBACK_SENDING', 'Lähetetään paluuviite URI %s...');
+@define('TRACKBACK_SENT', 'Paluuviite lähetetty');
+@define('TRACKBACK_FAILED', 'Paluuviite epäonnistui: %s');
+@define('TRACKBACK_NOT_FOUND', 'Ei paluuviitteen URI:a.');
+@define('TRACKBACK_URI_MISMATCH', 'Automaatin löytämä URI ei vastaa kohde URI:a.');
+@define('TRACKBACK_CHECKING', 'Tarkistetaan <u>%s</u> paluuviitteiden varalle...');
+@define('TRACKBACK_NO_DATA', 'Kohde on tyhjä');
+@define('TRACKBACK_SIZE', 'Kohteen URI ylittää tiedostokokorajan %s tavua.');
+@define('COMMENTS_VIEWMODE_THREADED', 'Vastausketjuina');
+@define('COMMENTS_VIEWMODE_LINEAR', 'Listana');
+@define('DISPLAY_COMMENTS_AS', 'Näytä kommentit');
+@define('COMMENTS_FILTER_SHOW', 'Näytä');
+@define('COMMENTS_FILTER_ALL', 'Kaikki');
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'Vain hyväksytyt');
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'Hyväksymättömät');
+@define('RSS_IMPORT_BODYONLY', 'Tuo kaikki teksti artikkelin runko-osaan ja jätä jatko-osio tyhjäksi..');
+@define('SYNDICATION_PLUGIN_FULLFEED', 'Näytä kirjaukset runko-osana RSS kanavilla');
+@define('WEEK', 'Viikko');
+@define('WEEKS', 'Viikkoja');
+@define('MONTHS', 'Kuukausia');
+@define('DAYS', 'Päiviä');
+@define('ARCHIVE_FREQUENCY', 'Kalenterimerkinnän frekvenssi');
+@define('ARCHIVE_FREQUENCY_DESC', 'Kalenterimerkintöjen välinen välimatka');
+@define('ARCHIVE_COUNT', 'Listakohtien lukumäärä');
+@define('ARCHIVE_COUNT_DESC', 'Näytettävien kuukausien ja viikkojen kokonaismäärä ');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'Asennetut laajennkoset');
+@define('SIDEBAR_PLUGIN', 'sivupalstan laajennos');
+@define('EVENT_PLUGIN', 'tapahtumalaajennos');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'Napsauta lisätäksesi uuden %s');
+@define('VERSION', 'versio');
+@define('INSTALL', 'Asenna');
+@define('ALREADY_INSTALLED', 'Asennettu jo');
+@define('SELECT_A_PLUGIN_TO_ADD', 'Valitse laajennos, jonka haluat asentaa');
+@define('INSTALL_OFFSET', 'Palvelimen aikasiirtymä');
+@define('STICKY_POSTINGS', 'Tahmeat kirjaukset');
+@define('INSTALL_FETCHLIMIT', 'Etusivulla esitettävät kirjaukset');
+@define('INSTALL_FETCHLIMIT_DESC', 'Selaimessa esitettävien kirjausten lukumäärä');
+@define('IMPORT_ENTRIES', 'Tuo kirjauksia');
+@define('EXPORT_ENTRIES', 'Vie kirjauksia');
+@define('IMPORT_WELCOME', 'Tervetula Serendipityn tuontiagentuuriin');
+@define('IMPORT_WHAT_CAN', 'Täällä voit tuoda kirjauksia muista blogi-softista.');
+@define('IMPORT_SELECT', 'Valitse ohjelma, josta haluat tuoda');
+@define('IMPORT_PLEASE_ENTER', 'Ole kiltti ja täytä allaoleva tieto.');
+@define('IMPORT_NOW', 'Tuo nyt!');
+@define('IMPORT_STARTING', 'Aloitan tuonnin...');
+@define('IMPORT_FAILED', 'Tuonti meni pieleen');
+@define('IMPORT_DONE', 'Tuonti onnistui');
+@define('IMPORT_WEBLOG_APP', 'Blogisofta');
+@define('EXPORT_FEED', 'Näytä koko RSS kanavan sisältö');
+@define('STATUS', 'Tuonnin jälkeinen tilanne');
+@define('IMPORT_GENERIC_RSS', 'Yleinen RSS tuonti');
+@define('ACTIVATE_AUTODISCOVERY', 'Lähetä paluuviitteet kirjauksen paluuviestiosoitteisiin.');
+@define('WELCOME_TO_ADMIN', 'Tervetuloa Serendipityn ylläpitoon.');
+@define('PLEASE_ENTER_CREDENTIALS', 'Kirjoita tunnistustietosi allaoleviin laatikoihin.');
+@define('ADMIN_FOOTER_POWERED_BY', 'Moottorina Serendipity %s and PHP %s');
+@define('INSTALL_USEGZIP', 'Käytä gzip pakattuja sivuja');
+@define('INSTALL_USEGZIP_DESC', 'Nopeuttaaksemme sivujen siirtoa selaimeen voimme pakata sivut, jos selain sitä tukee. Suositus: käytössä.');
+@define('INSTALL_SHOWFUTURE', 'Näytä tulevaisuus');
+@define('INSTALL_SHOWFUTURE_DESC', 'Näytä kirjaukset, joiden julkistuspäivä on tulevaisuudessa. Oletusarvoisesti näytetään vain nykyhetken kirjaukset.');
+@define('INSTALL_DBPERSISTENT', 'Käytä pysyviä kantayhteyksiä.');
+@define('INSTALL_DBPERSISTENT_DESC', 'Lue <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">here</a>. Ei suositella');
+@define('NO_IMAGES_FOUND', 'Ei kuvia');
+@define('PERSONAL_SETTINGS', 'Henkilökohtaiset astukset');
+@define('REFERER', 'Viittaaja');
+@define('NOT_FOUND', 'Ei löytynyt');
+@define('WRITABLE', 'Kirjoitettavissa');
+@define('NOT_WRITABLE', 'Ei kirjoitettavissa');
+@define('PROBLEM_DIAGNOSTIC', 'Diagnostiikkavirheiden takia et voi jatkaa asennusta, ennen kuin ylläolevat virheet on korjattu.');
+@define('SELECT_INSTALLATION_TYPE', 'Valitse asennustapa');
+@define('WELCOME_TO_INSTALLATION', 'Tervetuloa Serendipity asennukseen');
+@define('FIRST_WE_TAKE_A_LOOK', 'Ensiksi tarkistamme olemassaolevan asennuksen ja mahdolliset epäyhteensopimattomuudet.');
+@define('ERRORS_ARE_DISPLAYED_IN', 'Virheet esitetään %s, suositukset %s ja onnistumiset %s');
+@define('RED', 'punaisella');
+@define('YELLOW', 'keltaisella');
+@define('GREEN', 'vihreällä');
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s esiasennusraportti');
+@define('RECOMMENDED', 'Suositettu');
+@define('ACTUAL', 'Käytössä');
+@define('PHPINI_CONFIGURATION', 'php.ini muokkaus');
+@define('PHP_INSTALLATION', 'PHP asennus');
+@define('THEY_DO', 'tekevät');
+@define('THEY_DONT', 'eivät tee');
+@define('SIMPLE_INSTALLATION', 'Yksinkertainen asennus');
+@define('EXPERT_INSTALLATION', 'Mukautettu asennus');
+@define('COMPLETE_INSTALLATION', 'Täysi asennus');
+@define('WONT_INSTALL_DB_AGAIN', 'Tietokantaa ei uudelleenasenneta');
+@define('CHECK_DATABASE_EXISTS', 'Tarkistetaan onko kanta ja ovatko taulut jo olemassa');
+@define('CREATING_PRIMARY_AUTHOR', 'Luodaan päätoimittaja \'%s\'');
+@define('SETTING_DEFAULT_TEMPLATE', 'Asetetaan oletuspohja');
+@define('INSTALLING_DEFAULT_PLUGINS', 'Asennetaan oletuslaajennokset');
+@define('SERENDIPITY_INSTALLED', 'Serendipity on asennettu');
+@define('VISIT_BLOG_HERE', 'Uuteen blogiisi');
+@define('THANK_YOU_FOR_CHOOSING', 'Kiitos kun valitsit Serendipityn');
+@define('ERROR_DETECTED_IN_INSTALL', 'Asennuksessa tapahtui virhe');
+@define('OPERATING_SYSTEM', 'Käyttöjärjestelmä');
+@define('WEBSERVER_SAPI', 'Webserver SAPI');
+@define('TEMPLATE_SET', '\'%s\' on oletuspohjasi');
+@define('SEARCH_ERROR', 'Haku ei toiminut oletetusti. Huomautus blogin ylläpitäjlle:tämä saattaa johtua puuttuvista kantaindekseistä. MySQL:ssä kantakäyttäjällä on oltava oikeus ajaa kysely : <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> Kantavirhe oli: <pre>%s</pre>');
+@define('EDIT_THIS_CAT', 'Muokataan "%s"');
+@define('CATEGORY_REMAINING', 'Poista tämä luokka ja siirrä sen kirjaukset tähän luokkaan');
+@define('CATEGORY_INDEX', 'Luokkalista');
+@define('NO_CATEGORIES', 'Ei luokkia');
+@define('RESET_DATE', 'Nollaa päiväys');
+@define('RESET_DATE_DESC', 'Napsauta asettaaksesi päiväys kuluvaksi');
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Oikeuksia voi muuttaa komennolla: `<em>%s</em>` hakemistossa, tai FTP-ohjelmalla');
+@define('WARNING_TEMPLATE_DEPRECATED', 'Varoitus: Käyttämäsi oletuspohja on sisältää vanhentuneita määreitä, päivitä pohja jos se on mahdollista!');
+@define('ENTRY_PUBLISHED_FUTURE', 'Kirjausta ei ole julkistettu.');
+@define('ENTRIES_BY', '%s:n kirjaukset');
+@define('PREVIOUS', 'Edellinen');
+@define('NEXT', 'Seuraava');
+@define('APPROVE', 'Hyväksy');
+@define('DO_MARKUP_DESCRIPTION', 'Tee tekstille notaatiomuutokset (hymiöt, lyhennelmät käyttäen *, /, _, ...). Kieltämällä tämä säilyy  HTML-koodi tekstissä sellaisenaan.');
+@define('CATEGORY_ALREADY_EXIST', 'A category with the name "%s" already exist'); // Translate
+@define('IMPORT_NOTES', 'Note:'); // Translate
+@define('ERROR_FILE_FORBIDDEN', 'You are not allowed to upload files with active content'); // Translate
+@define('ADMIN', 'Administration'); // Re-Translate
+@define('ADMIN_FRONTPAGE', 'Frontpage'); // Translate
+@define('QUOTE', 'Quote'); // Translate
+@define('IFRAME_SAVE', 'Serendipity is now saving your entry, creating trackbacks and performing possible XML-RPC calls. This may take a while..'); // Translate
+@define('IFRAME_SAVE_DRAFT', 'A draft of this entry has been saved'); // Translate
+@define('IFRAME_PREVIEW', 'Serendipity is now creating the preview of your entry...'); // Translate
+@define('IFRAME_WARNING', 'Your browser does not support the concept of iframes. Please open your serendipity_config.inc.php file and set $serendipity[\'use_iframe\'] variable to FALSE.'); // Translate
+@define('NONE', 'none');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Default settings for new entries'); // Translate
+@define('UPGRADE', 'Upgrade'); // Translate
+@define('UPGRADE_TO_VERSION', 'Upgrade to version %s'); // Translate
+@define('DELETE_DIRECTORY', 'Delete directory'); // Translate
+@define('DELETE_DIRECTORY_DESC', 'You are about to delete the contents of a directory that contains media files, possibly files used in some of your entries.'); // Translate
+@define('FORCE_DELETE', 'Delete ALL files in this directory, including those not known by Serendipity'); // Translate
+@define('CREATE_DIRECTORY', 'Create directory'); // Translate
+@define('CREATE_NEW_DIRECTORY', 'Create new directory'); // Translate
+@define('CREATE_DIRECTORY_DESC', 'Here you can create a new directory to place media files in. Choose the name for your new directory and select an optional parent directory to place it in.'); // Translate
+@define('BASE_DIRECTORY', 'Base directory'); // Translate
+@define('USERLEVEL_EDITOR_DESC', 'Standard editor'); // Translate
+@define('USERLEVEL_CHIEF_DESC', 'Chief editor'); // Translate
+@define('USERLEVEL_ADMIN_DESC', 'Administrator'); // Translate
+@define('USERCONF_USERLEVEL', 'Access level'); // Translate
+@define('USERCONF_USERLEVEL_DESC', 'This level is used to determine what kind of access this user has to the blog'); // Translate
+@define('USER_SELF_INFO', 'Logged in as %s (%s)'); // Translate
+@define('ADMIN_ENTRIES', 'Entries'); // Translate
+@define('RECHECK_INSTALLATION', 'Recheck installation'); // Translate
+@define('IMAGICK_EXEC_ERROR', 'Unable to execute: "%s", error: %s, return var: %d'); // Translate
+@define('INSTALL_OFFSET_DESC', 'Enter the amount of hours between the date of your webserver (current: %clock%) and your desired time zone'); // Translate
+@define('UNMET_REQUIREMENTS', 'Requirements failed: %s'); // Translate
+@define('CHARSET', 'Charset');
+@define('AUTOLANG', 'Use visitor\'s browser language as default');
+@define('AUTOLANG_DESC', 'If enabled, this will use the visitor\'s browser language setting to determine the default language of your entry and interface language.');
+@define('INSTALL_AUTODETECT_URL', 'Autodetect used HTTP-Host'); // Translate
+@define('INSTALL_AUTODETECT_URL_DESC', 'If set to "true", Serendipity will ensure that the HTTP Host which was used by your visitor is used as your BaseURL setting. Enabling this will let you be able to use multiple domain names for your Serendipity Blog, and use the domain for all follow-up links which the user used to access your blog.'); // Translate
+@define('CONVERT_HTMLENTITIES', 'Try to auto-convert HTML entities?');
+@define('EMPTY_SETTING', 'You did not specify a valid value for "%s"!');
+@define('USERCONF_REALNAME', 'Real name'); // Translate
+@define('USERCONF_REALNAME_DESC', 'The full name of the author. This is the name seen by readers'); // Translate
+@define('HOTLINK_DONE', 'File hotlinked.<br />Done.'); // Translate
+@define('ENTER_MEDIA_URL_METHOD', 'Fetch method:'); // Translate
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Note: If you choose to hotlink to server, make sure you have permission to hotlink to the designated website, or the website is yours. Hotlink allows you to use off-site images without storing them locally.'); // Translate
+@define('MEDIA_HOTLINKED', 'hotlinked'); // Translate
+@define('FETCH_METHOD_IMAGE', 'Download image to your server'); // Translate
+@define('FETCH_METHOD_HOTLINK', 'Hotlink to server'); // Translate
+@define('DELETE_HOTLINK_FILE', 'Deleted the hotlinked file entitled <b>%s</b>'); // Translate
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Show E-Mail addresses?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_fr.inc.php b/lang/serendipity_lang_fr.inc.php
new file mode 100644 (file)
index 0000000..11d3611
--- /dev/null
@@ -0,0 +1,674 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Translation (c) by Sebastian Mordziol <argh@php-tools.net>
+# http://sebastian.mordziol.de
+
+@define('LANG_CHARSET', 'ISO-8859-1');
+@define('DATE_LOCALES', 'french, fr, fr_FR, en_US');
+@define('DATE_FORMAT_ENTRY', '%A, %e %B %Y');
+@define('DATE_FORMAT_SHORT', '%d.%m.%Y %H:%M');
+@define('WYSIWYG_LANG', 'fr');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', '.');
+@define('NUMBER_FORMAT_THOUSANDS', ',');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Administration de Serendipity');
+@define('HAVE_TO_BE_LOGGED_ON', 'Vous devez être authentifié pour accéder à cette page');
+@define('WRONG_USERNAME_OR_PASSWORD', 'Vous avez entré un nom d\'utilisateur ou un mot de passe erroné');
+@define('APPEARANCE', 'Apparence');
+@define('MANAGE_STYLES', 'Configurer les Styles');
+@define('CONFIGURE_PLUGINS', 'Configurer les Plugins');
+@define('CONFIGURATION', 'Configuration');
+@define('BACK_TO_BLOG', 'Revenir au Weblog');
+@define('LOGIN', 'Se connecter');
+@define('LOGOUT', 'Se déconnecter');
+@define('LOGGEDOUT', 'Déconnecté.');
+@define('CREATE', 'Créer');
+@define('SAVE', 'Enregistrer');
+@define('NAME', 'Nom');
+@define('CREATE_NEW_CAT', 'Créer une nouvelle catégorie');
+@define('I_WANT_THUMB', 'Je veux utiliser une miniature dans ma news.');
+@define('I_WANT_BIG_IMAGE', 'Je veux utiliser l\'image en taille rélle dans mon billet.');
+@define('I_WANT_NO_LINK', ' Je veux l\'afficher en tant qu\'image');
+@define('I_WANT_IT_TO_LINK', 'Je veux l\'afficher en tant que lien vers cette adresse:');
+@define('BACK', 'Précédent');
+@define('FORWARD', 'Suivant');
+@define('ANONYMOUS', 'Anonyme');
+@define('NEW_TRACKBACK_TO', 'Nouveau traçage fait sur');
+@define('NEW_COMMENT_TO', 'Nouveau commentaire posté sur');
+@define('RECENT', 'Récentes...');
+@define('OLDER', 'Plus anciennes...');
+@define('DONE', 'Effectué');
+@define('WELCOME_BACK', 'Bienvenue,');
+@define('TITLE', 'Titre');
+@define('DESCRIPTION', 'Description');
+@define('PLACEMENT', 'Emplacement');
+@define('DELETE', 'Supprimer');
+@define('SAVE', 'Enregistrer');
+@define('UP', '+HAUT');
+@define('DOWN', '+BAS');
+@define('ENTRIES', 'billets');
+@define('NEW_ENTRY', 'Poster un billet');
+@define('EDIT_ENTRIES', 'Éditer les billets');
+@define('CATEGORIES', 'Catégories');
+@define('WARNING_THIS_BLAHBLAH', "ATTENTION:\\nCeci peut prendre du temps si il y beaucoup d\'images sans miniatures.");
+@define('CREATE_THUMBS', 'Recréer les miniatures');
+@define('MANAGE_IMAGES', 'Configurer les images');
+@define('NAME', 'Nom');
+@define('EMAIL', 'Email');
+@define('HOMEPAGE', 'Site');
+@define('COMMENT', 'Commentaire');
+@define('REMEMBER_INFO', 'Enregistrer ces informations?');
+@define('SUBMIT_COMMENT', 'Poster le commentaire');
+@define('NO_ENTRIES_TO_PRINT', 'Aucun billet à afficher');
+@define('COMMENTS', 'Commentaires');
+@define('ADD_COMMENT', 'Ajouter un commentaire');
+@define('NO_COMMENTS', 'Pas de commentaires');
+@define('POSTED_BY', 'Posté par');
+@define('ON', 'sur');
+@define('A_NEW_COMMENT_BLAHBLAH', 'Un nouveau commentaire a été posté sur votre blog "%s", pour le billet intitulé "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'Un nouveau suivi a été fait sur votre blog au billet intitulée "%s".');
+@define('NO_CATEGORY', 'Pas de Catégorie');
+@define('ENTRY_BODY', 'Introduction');
+@define('EXTENDED_BODY', 'Corps du billet');
+@define('CATEGORY', 'Catégorie');
+@define('EDIT', 'Éditer');
+@define('NO_ENTRIES_BLAHBLAH', 'Aucun billet trouvé pour la requête %s' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'Votre recherche pour %s a donné %s résultats:');
+@define('SEARCH_TOO_SHORT', 'Vos critères de recherche doivent avoir un minimum de %s caractères');
+@define('IMAGE', 'Image');
+@define('ERROR_FILE_NOT_EXISTS', 'Erreur: Ce fichier n\'existe pas.');
+@define('ERROR_FILE_EXISTS', 'Erreur: Il existe déjà un fichier portant ce nom. Choisissez un nouveau nom.');
+@define('ERROR_SOMETHING', 'Erreur: Quelque chose ne va pas.');
+@define('ADDING_IMAGE', 'Ajout d\'une image...');
+@define('THUMB_CREATED_DONE', 'Miniature créee.<br>Terminé.');
+@define('ERROR_FILE_EXISTS_ALREADY', 'Erreur: Le fichier existe déjà sur votre machine.');
+@define('GO', 'Go!');
+@define('NEWSIZE', 'Nouvelle taille: ');
+@define('RESIZE_BLAHBLAH', '<b>Redimensionner %s</b><p>');
+@define('ORIGINAL_SIZE', 'Taille d\'origine: <i>%sx%s</i> pixel');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>Ici vous pouvez ajuster la taille de l\'image sélectionnée. Si vous voulez respecter les proportions de l\'image, entrez juste la hauteur ou la largeur, et pressez la touche TAB - la valeur correspondante sera insérée automatiquement:');
+@define('QUICKJUMP_CALENDAR', 'Saut rapide vers le Calendrier');
+@define('QUICKSEARCH', 'Recherche rapide');
+@define('SEARCH_FOR_ENTRY', 'Recherche d\'un billet');
+@define('ARCHIVES', 'Archives');
+@define('BROWSE_ARCHIVES', 'Afficher les archives par mois');
+@define('TOP_REFERRER', 'Top des liens entrants');
+@define('SHOWS_TOP_SITES', 'Montrer le top de sites qui affichent un lien vers votre blog');
+@define('TOP_EXITS', 'Top des liens sortants');
+@define('SHOWS_TOP_EXIT', 'Montrer le top des liens de sites qui sortent de votre blog');
+@define('SYNDICATION', 'Syndication');
+@define('SHOWS_RSS_BLAHBLAH', 'Montrer les liens de syndication RSS');
+@define('ADVERTISES_BLAHBLAH', 'Publicité sur l\'origine de votre blog');
+@define('HTML_NUGGET', 'Bloc HTML');
+@define('HOLDS_A_BLAHBLAH', 'Permet d\'afficher des contenus personnalisés au format HTML dans la barre latérale');
+@define('TITLE_FOR_NUGGET', 'Titre du bloc HTML');
+@define('THE_NUGGET', 'Contenu du bloc HTML');
+@define('SYNDICATE_THIS_BLOG', 'Syndiquer ce Blog');
+@define('YOU_CHOSE', 'Vous avez choisi %s');
+@define('IMAGE_SIZE', 'Taille de l\'image');
+@define('IMAGE_AS_A_LINK', 'Insérer l\'image');
+@define('POWERED_BY', 'propulsé par');
+@define('TRACKBACKS', 'Suivis');
+@define('TRACKBACK', 'Suivi');
+@define('NO_TRACKBACKS', 'Pas de suivis');
+@define('TOPICS_OF', 'Sujets de');
+@define('VIEW_FULL', 'Voir la totalité');
+@define('VIEW_TOPICS', 'Voir les sujets');
+@define('AT', 'à');
+@define('SET_AS_TEMPLATE', 'Choisir ce thème');
+@define('IN', 'dans');
+@define('EXCERPT', 'Excepté');
+@define('TRACKED', 'Suivi');
+@define('LINK_TO_ENTRY', 'Liens vers le billet');
+@define('LINK_TO_REMOTE_ENTRY', 'Lien vers le billet externe');
+@define('IP_ADDRESS', 'Adresse IP');
+@define('USER', 'Utilisateur');
+@define('THUMBNAIL_USING_OWN', 'L\'image %s est si petite qu\'elle va être utilisée comme sa propre miniature.');
+@define('THUMBNAIL_FAILED_COPY', 'La minitaure pour %s n\'a pas pu être copiée.');
+@define('AUTHOR', 'Auteur');
+@define('LAST_UPDATED', 'Dernière mise à jour');
+@define('TRACKBACK_SPECIFIC', 'Adresse de suivi spécifique pour ce billet');
+@define('DIRECT_LINK', 'Lien direct à ce billet');
+@define('COMMENT_ADDED', 'Votre commentaire a été ajouté.');
+@define('COMMENT_ADDED_CLICK', 'Cliquez %sici pour retourner%s aux commentaires, et %sici pour fermer%s cette fenêtre.');
+@define('COMMENT_NOT_ADDED', 'Votre commentaire n\'a pas pû être ajouté, car les commentaires pour ce billet ont été désactivés. ');
+@define('COMMENT_NOT_ADDED_CLICK', 'Cliquez %sici pour retourner%s aux commentaires, et %sici pour fermer%s cette fenêtre.');
+@define('COMMENTS_DISABLE', 'Ne pas autoriser de commentaires pour ce billet');
+@define('COMMENTS_ENABLE', 'Autoriser les commentaires pour ce billet');
+@define('COMMENTS_CLOSED', 'L\'auteur n\'a pas autorisé l\'ajout de commentaires pour ce billet.');
+@define('EMPTY_COMMENT', 'Votre commentaire est vide, %sretournez en arrière%s et réessayez');
+@define('ENTRIES_FOR', 'Billets pour %s');
+@define('DOCUMENT_NOT_FOUND', 'Le document %s n\'a pas été trouvé.');
+@define('USERNAME', 'Nom d\'utilisateur');
+@define('PASSWORD', 'Mot de passe');
+@define('AUTOMATIC_LOGIN', 'Garder en mémoire');
+@define('SERENDIPITY_INSTALLATION', 'Installation de Serendipity');
+@define('LEFT', 'gauche');
+@define('RIGHT', 'droite');
+@define('HIDDEN', 'caché');
+@define('REMOVE_TICKED_PLUGINS', 'Supprimer les plugins cochés');
+@define('SAVE_CHANGES_TO_LAYOUT', 'Enregistrer les changements');
+@define('COMMENTS_FROM', 'Commentaires de');
+@define('ERROR', 'Erreur');
+@define('DELETE_SURE', 'Etes vous sûr de vouloir supprimer #%s définitivement?');
+@define('NOT_REALLY', 'Pas vraiment...');
+@define('DUMP_IT', 'À la poubelle!');
+@define('RIP_ENTRY', 'Le billet #%s a rejoint l\'éternel.');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Catégorie #%s supprimée. Les billets ont été déplacés dans la catégorie #%s');
+@define('CATEGORY_DELETED', 'Catégorie #%s supprimée.');
+@define('INVALID_CATEGORY', 'Aucune catégorie sélectionnée pour la suppression');
+@define('CATEGORY_SAVED', 'Catégorie sauvegardée');
+@define('SELECT_TEMPLATE', 'Sélectionnez le thème que vous voulez utiliser pour votre blog');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'Les billets n\'ont pas pu être importés.');
+@define('YES', 'Oui');
+@define('NO', 'Non');
+@define('USE_DEFAULT', 'Default');
+@define('CHECK_N_SAVE', 'Vérifier &amp; sauvegarder');
+@define('DIRECTORY_WRITE_ERROR', 'Je ne peux pas écrire dans le répertoire %s. Il faudrait que vous me donniez les droits d\'accès nécessaires manuellement.');
+@define('DIRECTORY_CREATE_ERROR', 'Le répertoire %s n\'existe pas et ne peut pas être crée automatiquement. Veuillez le créer manuellement, ou me donner les droits d\'accès nécessaires.');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; exécute <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', 'Je ne peux pas exécuter le programme %s');
+@define('FILE_WRITE_ERROR', 'Je ne peux pas ouvrir le fichier %s pour écriture.');
+@define('FILE_CREATE_YOURSELF', 'Merci de créer le fichier vous-même ou de me donner les droits d\'accès nécessaires.');
+@define('COPY_CODE_BELOW', '<br />* Copiez le code ci-dessous et placez le %s dans votre %s répertoire:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Changez www dans le nom d\'utilisateur sous lequel fonctionne le serveur apache (nobody, par ex).');
+@define('BROWSER_RELOAD', 'Une fois ceci effectué, rechargez la page avec la touche "F5".');
+@define('DIAGNOSTIC_ERROR', 'J\'ai touvé quelques erreurs en vérifiant vos données:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity n\'est pas encore installé. Vous pouvez <a href="%s">l\'installer maintenant</a>.');
+@define('INCLUDE_ERROR', 'Erreur Serendipity: impossible d\'inclure le fichier %s.');
+@define('DATABASE_ERROR', 'Erreur Serendipity: impossible d\'ouvrir une connexion avec la base de données.');
+@define('CREATE_DATABASE', 'Création de la structure de la base de données...');
+@define('ATTEMPT_WRITE_FILE', 'Essai d\'écriture sur le fichier %s...');
+@define('WRITTEN_N_SAVED', 'Configuration écrite &amp; sauvegardée');
+@define('IMAGE_ALIGNMENT', 'Position de l\'image');
+@define('ENTER_NEW_NAME', 'Entrez le nouveau nom pour: ');
+@define('RESIZING', 'Redimensionnement');
+@define('RESIZE_DONE', 'Terminé (%s images redimensionnées).');
+@define('SYNCING', 'Synchronisation de la base de données avec votre collection d\'images');
+@define('SYNC_DONE', 'Terminé (%s images synchronisées).');
+@define('DELETE_IMAGE_FAIL' , 'Impossible de supprimer l\'image intitulée <b>%s</b>');
+@define('DELETE_THUMBNAIL', 'Suppression de la miniature de l\'image intitulée <b>%s</b>');
+@define('FILE_NOT_FOUND', 'Impossible de trouver le fichier intitulé <b>%s</b>, peut-être qu\'il a déjà été supprimé?');
+@define('ABORT_NOW', 'Annuler maintenant');
+@define('REMOTE_FILE_NOT_FOUND', 'Le fichier n\'a pas été trouvé sur le serveur distant, êtes vous sûr que l\'URL: <b>%s</b> est correcte?');
+@define('FILE_FETCHED', '%s téléchargé et savegardé sous %s');
+@define('FILE_UPLOADED', 'Le fichier %s a été uploadé avec succès sous %s');
+@define('WORD_OR', 'Ou');
+@define('SCALING_IMAGE', 'Redimensionnement %s en %s x %s px');
+@define('KEEP_PROPORTIONS', 'Conserver les proportions');
+@define('REALLY_SCALE_IMAGE', 'Réellement redimensionner l\'image? Attention: cette opération est irréversible!');
+@define('TOGGLE_ALL', 'Afficher/Ne pas afficher les détails');
+@define('TOGGLE_OPTION', 'Afficher les détails');
+@define('SUBSCRIBE_TO_THIS_ENTRY', 'Souscrire à ce billet');
+@define('UNSUBSCRIBE_OK', "%s est maintenant désinscrit de cette news");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'Nouveau commentaire posté à votre souscription du billet "%s"');
+@define('SUBSCRIPTION_MAIL', "Bonjour %s,\n\nUn nouveau commentaire a été posté au billet que vous surveillez \"%s\", intitulé \"%s\"\nLe pseudo de l\'auteur est: %s\n\nVous pouvez trouver le billet ici: %s\n\nVous pouvez vous désinscrire en cliquant sur ce lien: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "Bonjour %s,\n\nUn nouveau suivi a été ajouté au billet que vous surveillez \"%s\", intitulé \"%s\"\nLe pseudo de l\'auteur est: %s\n\nVous pouvez trouver le billet ici: %s\n\nVous pouvez vous désinscrire en cliquant sur ce lien: %s\n");
+@define('SIGNATURE', "\n-- \n%s est propulsé par Serendipity.\nLe blog des blogs que vous aussi pouvez utiliser!.\nAllez sur <http://s9y.org>, le site officiel.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0');
+@define('SYNDICATION_PLUGIN_20c', 'Commentaires RSS 2.0');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'Champs "managingEditor"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  'Champs "webMaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'Image pour le fil RSS');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', 'Largeur d\'image');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'Hauteur d\'image');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  'Adresse E-Mail du webmaster, si disponible. (aucun: invisible) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', 'Adresse E-Mail de l\'éditeur principal, si disponible. (aucun: invisible) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'Adresse d\'une image au format GIF/JPEG/PNG, si disponible. (aucune: logo serendipity)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'en pixels, maximum 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'en pixels, maximum 400');
+@define('SYNDICATION_PLUGIN_TTL', 'Champs "ttl" (time-to-live = temps à vivre)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'Laps de temps en minutes après lequel votre blog ne doit plus être pris du cache par des sites/programmes externes (aucun: invisible) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'Champs "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', 'Inclure le champs "pubDate" dans le fil RSS pour afficher la date de l\'entrée la plus récente?');
+@define('CONTENT', 'Contenu');
+@define('TYPE', 'Type');
+@define('DRAFT', 'Brouillon');
+@define('PUBLISH', 'Publication');
+@define('PREVIEW', 'Prévisualisation');
+@define('DATE', 'Date');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', 'Attention: La date entrée est invalide. Elle doit être au format YYYY-MM-DD HH:MM .');
+@define('CATEGORY_PLUGIN_DESC', 'Affiche la liste des catégories.');
+@define('ALL_AUTHORS', 'Tous les auteurs');
+@define('CATEGORIES_TO_FETCH', 'Catégories à afficher');
+@define('CATEGORIES_TO_FETCH_DESC', 'Afficher les catégories par auteur(s) spécifique(s)');
+@define('PREVIOUS_PAGE', 'Page précédente');
+@define('NEXT_PAGE', 'Page suivante');
+@define('ALL_CATEGORIES', 'Toutes les catégories');
+@define('DO_MARKUP', 'Transformation de balises dans le texte');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'Format de la date');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'Le format dans lequel la date des billets doit être affichée. Toute syntaxe permise par la fonction PHP <a href="http://www.php.net/strftime" target="blank">strftime()</a> est possible. (Défaut: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'Impossible d\'ouvrir le fichier du thème, merci de mettre à jour Serendipity!');
+@define('ADVANCED_OPTIONS', 'Options avancées');
+@define('EDIT_ENTRY', 'Éditer le billet');
+@define('HTACCESS_ERROR', 'Pour vérifier l\'installation de Serendipity sur votre serveur, Serendipity doit pouvoir créer le fichier ".htaccess". Ceci n\'a pas été possible car Serendipity n\'a pas les droits d\'accès suffisants dans ce répertoire. Vous pouvez ajuster les droits d\'accès avec la commande suivante: <br />&nbsp;&nbsp;%s<br />. Après, rechargez cette page avec la touche "F5".');
+@define('SIDEBAR_PLUGINS', 'Plugins pour la barre latérale');
+@define('EVENT_PLUGINS', 'Plugins d\'évènement');
+@define('SORT_ORDER', 'Trier par ordre');
+@define('SORT_ORDER_NAME', 'Nom du fichier');
+@define('SORT_ORDER_EXTENSION', 'Extension du fichier');
+@define('SORT_ORDER_SIZE', 'Taille du fichier');
+@define('SORT_ORDER_WIDTH', 'Largeur de l\'image');
+@define('SORT_ORDER_HEIGHT', 'Hauteur de l\'image');
+@define('SORT_ORDER_DATE', 'Date de l\'upload');
+@define('SORT_ORDER_ASC', 'Croissant');
+@define('SORT_ORDER_DESC', 'Décroissant' );
+@define('THUMBNAIL_SHORT', 'Miniature');
+@define('ORIGINAL_SHORT', 'Orig.');
+@define('APPLY_MARKUP_TO', 'Appliquer la transformation des balises à %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'Début de la semaine');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity a détecté que votre configuration (version %s) ne correspond pas à la version de votre installation de Serendipity (version %s). Pour continuer à utiliser Serendipity, l\'assistant de mise à jour va vous guider pour <a href="%s">mettre à jour</a> votre installation.');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'Bonjour, et bienvenue dans l\'assistant de mise à jour de Serendipity.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', 'Je vais vous guider pour la mise à jour de votre installation %s de Serendipity.');
+@define('SERENDIPITY_UPGRADER_WHY', 'Vous voyez ce message car vous avez installé Serendipity %s, mais la base de données doit être reconfigurée pour fonctionner correctement avec cette version.');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'Mises à jour de la base de données (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'Pour mettre à jour votre base de données, j\'ai trouvé les fichiers .sql suivants qui doivent être importés:');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  'Tâches spécifiques à la version');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', 'Aucune tâche spécifique à la nouvelle version n\'a été trouvée');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', 'Voulez-vous que j\'effectue les tâches suivantes?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'Non, je vais le faire manuellement');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'Oui, faites-le s\'il vous plait');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'Une mise à jour n\'est pas nécessaire pour votre installation de Serendipity, il n\'y a pas de tâches à effectuer.');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', 'Considérez Serendipity comme mis à jour.');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'Vous avez ignoré la mise à jour de Serendipity, assurez-vous que la base de données est installée correctement, et que les tâches nécessaires sont effectuées.');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'Votre installation de Serendipity a été mise à jour à la version %s.');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', 'Vous pouvez retourner à votre blog en %scliquant ici%s');
+@define('MANAGE_USERS', 'Administrer les utilisateurs');
+@define('CREATE_NEW_USER', 'Créer un nouvel utilisateur');
+@define('CREATE_NOT_AUTHORIZED', 'Vous ne pouvez pas éditer des utilisateurs qui ont le même niveau d\'autorisation que le vôtre.');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'Vous ne pouvez pas créer d\'utilisateur avec un niveau d\'autorisation plus élevé que le vôtre.');
+@define('CREATED_USER', 'Un nouvel utilisateur %s a été crée');
+@define('MODIFIED_USER', 'Les propriétés de l\'utilisateur %s ont été changées');
+@define('USER_LEVEL', 'Niveau d\'autorisation');
+@define('DELETE_USER', 'Vous êtes sur le point de supprimer l\'utilisateur #%d %s. Êtes-vous sûr de vouloir continuer? Les billets de cet utilisateur ne seront plus visibles dans votre blog.');
+@define('DELETED_USER', 'Utilisateur #%d %s supprimé.');
+@define('LIMIT_TO_NUMBER', 'Limiter le nombre de billets à?');
+@define('ENTRIES_PER_PAGE', 'billets par page');
+@define('XML_IMAGE_TO_DISPLAY', 'Bouton "XML"');
+@define('XML_IMAGE_TO_DISPLAY_DESC','Les liens vers les fils XML seront affichés avec cette image. Laisser vide pour l\'image par défaut, ou tapez \'none\' pour la désactiver.');
+
+@define('DIRECTORIES_AVAILABLE', 'Dans la liste des sous-dossiers disponibles, vous pouvez cliquer sur un nom de dossier pour en créer un nouveau à cet endroit.');
+@define('ALL_DIRECTORIES', 'tous les dossiers');
+@define('MANAGE_DIRECTORIES', 'Administrer les dossiers');
+@define('DIRECTORY_CREATED', 'Le dossier <strong>%s</strong> a été crée.');
+@define('PARENT_DIRECTORY', 'Dossier parent');
+@define('CONFIRM_DELETE_DIRECTORY', 'Êtes-vous sûr de vouloir supprimer tous les contenus du dossier %s?');
+@define('ERROR_NO_DIRECTORY', 'Erreur: Le dossier %s n\'existe pas');
+@define('CHECKING_DIRECTORY', 'Vérification des fichiers dans le dossier %s');
+@define('DELETING_FILE', 'Suppression du fichier %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', 'Impossible de supprimer un dossier non vide. Cochez la case "Forcer la suppression" si vous voulez supprimer les fichiers gênants, et puis effectuez l\'opération à nouveau. Les fichiers présents dans le dossier sont les suivants:');
+@define('DIRECTORY_DELETE_FAILED', 'La suppression du dossier %s a échoué. Vérifiez les droits d\'accès au répertoire et les messages ci-dessus.');
+@define('DIRECTORY_DELETE_SUCCESS', 'Suppression du dossier %s effectuée.');
+@define('SKIPPING_FILE_EXTENSION', 'Fichier ignoré: Pas d\'extension de fichier dans %s.');
+@define('SKIPPING_FILE_UNREADABLE', 'Fichier ignoré: impossible de lire à partir du fichier %s .');
+@define('FOUND_FILE', 'Fichier nouveau/modifié trouvé: %s.');
+@define('ALREADY_SUBCATEGORY', '%s est déjà une sous-catégorie de %s.');
+@define('PARENT_CATEGORY', 'Catégorie parent');
+@define('IN_REPLY_TO', 'En réponse à');
+@define('TOP_LEVEL', 'Racine');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', 'Configuration de la base de données');
+@define('INSTALL_CAT_DB_DESC', 'Vous permet d\'entrer toutes les données nécessaires pour la base données dont Serendipity a besoin pour fonctionner.');
+@define('INSTALL_DBTYPE', 'Type de base de données');
+@define('INSTALL_DBTYPE_DESC', 'Choisissez le type de votre base de données');
+@define('INSTALL_DBHOST', 'Serveur hôte');
+@define('INSTALL_DBHOST_DESC', 'Le nom du serveur hôte sur lequel réside la base de données (exemple: localhost)');
+@define('INSTALL_DBUSER', 'Nom d\'utilisateur');
+@define('INSTALL_DBUSER_DESC', 'Le nom d\'utilisateur à utiliser pour se connecter à la base de données');
+@define('INSTALL_DBPASS', 'Mot de passe');
+@define('INSTALL_DBPASS_DESC', 'Le mot de passe correspondant au nom d\'utilisateur');
+@define('INSTALL_DBNAME', 'Nom de la base de données');
+@define('INSTALL_DBNAME_DESC', 'Le nom de la base de données à laquelle Serendipity doit se connecter');
+@define('INSTALL_DBPREFIX', 'Préfixe des tables');
+@define('INSTALL_DBPREFIX_DESC', 'Le préfixe à utiliser pour les tables de Serendipity (exemple: serendipity_)');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', 'Chemins');
+@define('INSTALL_CAT_PATHS_DESC', 'Configuration des chemins aux dossiers et fichiers indispensables. N\'oubliez pas d\'ajouter les slashes ("/") finaux!');
+@define('INSTALL_FULLPATH', 'Chemin absolu');
+@define('INSTALL_FULLPATH_DESC', 'Le chemin complet et absolu du dossier d\'installation de Serendipity');
+@define('INSTALL_UPLOADPATH', 'Chemin pour les uploads');
+@define('INSTALL_UPLOADPATH_DESC', 'C\'est ici que Serendipity enregistre tous les fichiers uploadés. Chemin relatif au \'chemin absolu\' - normalement \'uploads/\'');
+@define('INSTALL_RELPATH', 'Chemin relatif');
+@define('INSTALL_RELPATH_DESC', 'Le chemin d\'accès à Serendipity pour votre navigateur, normalement \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', 'Chemin relatif des thèmes');
+@define('INSTALL_RELTEMPLPATH_DESC', 'Le chemin au dossier contenant vos thèmes - relatif au \'Chemin relatif\'');
+@define('INSTALL_RELUPLOADPATH', 'Chemin relatif des uploads');
+@define('INSTALL_RELUPLOADPATH_DESC', 'Le chemin d\'accès aux fichiers uploadés pour votre navigateur - relatif au \'Chemin relatif\'');
+@define('INSTALL_URL', 'Lien au blog');
+@define('INSTALL_URL_DESC', 'Le lien (URL) pour accéder à votre installation de Serendipity');
+@define('INSTALL_INDEXFILE', 'Script principal');
+@define('INSTALL_INDEXFILE_DESC', 'Le nom du script principal que vous voulez utiliser pour Serendipity (exemple: index.php)');
+
+/* General settings */
+@define('INSTALL_CAT_SETTINGS', 'Configuration générale');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Personnalisation et configuration générale de Serendipity');
+@define('INSTALL_USERNAME', 'Nom de l\'administrateur');
+@define('INSTALL_USERNAME_DESC', 'Le nom d\'utilisateur pour l\'accès de l\'administrateur');
+@define('INSTALL_PASSWORD', 'Mot de passe l\'administrateur');
+@define('INSTALL_PASSWORD_DESC', 'Le mot de passe pour l\'accès de l\'administrateur');
+@define('INSTALL_EMAIL', 'Email de l\'administrateur');
+@define('INSTALL_EMAIL_DESC', 'Adresse Email à utiliser pour l\'administrateur du blog');
+@define('INSTALL_SENDMAIL', 'Envoi d\'emails à l\'administrateur?');
+@define('INSTALL_SENDMAIL_DESC', 'Voulez-vous que l\'administrateur reçoive un email quand des commentaires sont postés dans les billets?');
+@define('INSTALL_SUBSCRIBE', 'Autoriser les utilisateurs de suivre des billets?');
+@define('INSTALL_SUBSCRIBE_DESC', 'Donner aux utilisateurs la possibilité de souscrire à un billet, et ainsi recevoir des emails quand des commentaires sont postés dans celui-ci?');
+@define('INSTALL_BLOGNAME', 'Titre du blog');
+@define('INSTALL_BLOGNAME_DESC', 'Le titre de votre blog');
+@define('INSTALL_BLOGDESC', 'Description de votre blog');
+@define('INSTALL_BLOGDESC_DESC', 'La description de votre blog');
+@define('INSTALL_LANG', 'Langue');
+@define('INSTALL_LANG_DESC', 'Choisissez la langue à utiliser pour votre blog. Celle-ci sera utilisée dans le blog et l\'interface d\'administration.');
+
+/* Appearance and options */
+@define('INSTALL_CAT_DISPLAY', 'Apparence et options');
+@define('INSTALL_CAT_DISPLAY_DESC', 'Personnalisation du \'look &amp; feel\' de l\'interface du blog.');
+@define('INSTALL_WYSIWYG', 'Utiliser l\'éditeur WYSIWYG');
+@define('INSTALL_WYSIWYG_DESC', 'Voulez-vous utiliser l\'éditeur WYSIWYG pour composer vos billets? (Fonctionne avec IE5+, et partiellement avec Mozilla 1.3+)');
+@define('INSTALL_XHTML11', 'Forcer la conformité XHTML 1.1');
+@define('INSTALL_XHTML11_DESC', 'Voulez-vous forcer la conformité au standard XHTML 1.1 (peut causer des problèmes au niveau de l\'administration et du blog dans les navigateurs plus anciens de la 4ème génération)');
+@define('INSTALL_POPUP', 'Activer les fenêtres pop-pup');
+@define('INSTALL_POPUP_DESC', 'Voulez-vous que le blog utilise des fenêtres pop-up pour les commentaires, traçages et autres?');
+@define('INSTALL_EMBED', 'Intégration dans une application externe');
+@define('INSTALL_EMBED_DESC', 'Si vous voulez intégrer Serendipity dans une page normale ou dans une application externe, choisissez \'Oui\'. Serendipity n\'affichera alors que les contenus du blog, vous permettant de les intégrer facilement dans n\'importe-quelle page. Vous pouvez aussi utiliser l\'option \'Script principal\' pour créer un encapsulateur (wrapper) qui vous permettra d\'ajouter vos propres contenus et visuel. Pour plus d\'informations sur l\'intégration de Serendipity, consultez le fichier README fourni dans l\'installation.');
+@define('INSTALL_BLOCKREF', 'Exclure des pages référantes');
+@define('INSTALL_BLOCKREF_DESC', 'Vous pouvez exclure des noms de domaine spécifiques de la liste des pages référantes: séparez chaque nom de domaine avec \';\', et notez que l\'exclusion du nom de domaine se fait par la fonction <a href="http://www.php.net/substring" target="_blank">substring()</a>.');
+@define('INSTALL_REWRITE', 'Réecritures URL');
+@define('INSTALL_REWRITE_DESC', 'Choisissez la méthode à utiliser pour la gestion des URL de votre blog. Si vous activez les réecritures URL, l\'accès à votre blog se fera par des URL simples, plus facilement indexables par les moteurs de recherche. Pour les activer, le module mod_rewrite doit être activé dans votre serveur, ou il doit autoriser l\'utilisation de la directive "AllowOverride All" pour le dossier d\'installation de Serendipity. Par défaut Serendipity choisit automatiquement l\'option à utiliser.');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', 'Options de gestion des images');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'Définissez comment Serendipity doit gérer les transformations/conversions d\'images dans votre médiathèque.');
+@define('INSTALL_IMAGEMAGICK', 'Utiliser Imagemagick');
+@define('INSTALL_IMAGEMAGICK_DESC', 'Est-ce que imageMagick est installé sur votre serveur, et voulez-vous l\'utiliser pour le redimensionnement de vos images?');
+@define('INSTALL_IMAGEMAGICKPATH', 'Chemin d\'accès au programme de conversion');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'Chemin absolu et nom de votre programme de conversion de imageMagick (normalement \'convert\')');
+@define('INSTALL_THUMBSUFFIX', 'Suffixe pour les miniatures');
+@define('INSTALL_THUMBSUFFIX_DESC', 'Les miniatures d\'images seront enregistrées de la manière suivante:: original.[suffixe].ext');
+@define('INSTALL_THUMBWIDTH', 'Dimensions des miniatures');
+@define('INSTALL_THUMBWIDTH_DESC', 'Largeur maximum (statique) des miniatures crées automatiquement');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', 'Détails personnels');
+@define('USERCONF_CAT_PERSONAL_DESC', 'Détails sur votre compte personnel');
+@define('USERCONF_USERNAME', 'Votre nom d\'utilisateur');
+@define('USERCONF_USERNAME_DESC', 'Votre nom d\'utilisateur');
+@define('USERCONF_PASSWORD', 'Votre mot de passe');
+@define('USERCONF_PASSWORD_DESC', 'Votre mot de passe');
+@define('USERCONF_EMAIL', 'Votre E-Mail');
+@define('USERCONF_EMAIL_DESC', 'Votre E-Mail');
+@define('USERCONF_SENDCOMMENTS', 'Notification de commentaire?');
+@define('USERCONF_SENDCOMMENTS_DESC', 'Voulez-vous recevoir un email lorsque quelqu\'un poste un commentaire dans votre billet?');
+@define('USERCONF_SENDTRACKBACKS', 'Notification de suivis?');
+@define('USERCONF_SENDTRACKBACKS_DESC', 'Voulez-vous recevoir un email lorsque quelqu\'un souscrit à l\'un de vos billets?');
+
+// TRANSLATE
+@define('PERMISSIONS', 'Permissions');
+@define('USERCONF_ALLOWPUBLISH', 'Publication de billets?');
+@define('USERCONF_ALLOWPUBLISH_DESC', 'Cet utilisateur est-il autorisé à poster des billets?');
+@define('ENTRY_SAVED', 'Votre billet a été enregistré');
+@define('SUCCESS', 'Succès');
+@define('POWERED_BY_SHOW_TEXT', 'Afficher \'Serendipity\' en tant que texte');
+@define('POWERED_BY_SHOW_TEXT_DESC', 'Affiche le slogan \'Serendipity Weblog\' en tant que texte');
+@define('POWERED_BY_SHOW_IMAGE', 'Afficher \'Serendipity\' avec un logo');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Affiche le logo Serendipity');
+@define('INSTALL_TOP_AS_LINKS', 'Afficher le top pages sortantes / référantes en tant que liens?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '\'Non\': affichage en tant que texte seulement pour prévenir le spam par Google. \'Oui\': affichage en tant que liens. Par défaut, l\'option de la configuration générale est utilisée.');
+
+/* TRANSLATE */
+@define('SETTINGS_SAVED_AT', 'La nouvelle configuration a été enregistrée à %s');
+@define('PLUGIN_ITEM_DISPLAY', 'Où le billet doit-il être affiché?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'Dans la vue détaillée seulement');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'Page d\'accueil seulement');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'Sur la page d\'accueil et la vue détaillée');
+@define('RSS_IMPORT_CATEGORY', 'Utiliser cette catégorie pour les billets à catégorie inconnue');
+@define('ERROR_UNKNOWN_NOUPLOAD', 'Erreur: impossible d\'uploader le fichier. Peut-être que la taille du fichier est plus grande que ce que votre serveur autorise. Vérifiez avec votre administrateur système ou éditez votre fichier php.ini pour autoriser le téléchargement de fichiers plus volumineux.');
+@define('COMMENTS_WILL_BE_MODERATED', 'Les commentaires postés doivent être approuvés avant d\'être affichés dans le blog.');
+@define('YOU_HAVE_THESE_OPTIONS', 'Vous avez les possibilités suivantes:');
+@define('THIS_COMMENT_NEEDS_REVIEW', 'Attention: ce commentaire doit être approuvé avant d\'être publié.');
+@define('DELETE_COMMENT', 'Supprimer le commentaire');
+@define('APPROVE_COMMENT', 'Approuver le commentaire');
+@define('REQUIRES_REVIEW', 'Doit être revu');
+@define('COMMENT_APPROVED', 'Le commentaire #%s a été approuvé');
+@define('COMMENT_DELETED', 'Le commentaire #%s a été supprimé');
+@define('VIEW', 'Afficher');
+@define('COMMENT_ALREADY_APPROVED', 'Le commentaire #%s semble déjà avoir été approuvé');
+@define('COMMENT_EDITED', 'Le commentaire sélectionné a été modifié');
+@define('HIDE', 'Cacher');
+@define('VIEW_EXTENDED_ENTRY', 'Continuer à lire "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'Ce lien n\\\'est pas fait pour être cliqué. Il contient le lien de traçage pour ce billet. Vous pouvez utiliser ce lien pour envoyer un ping ou faire un traçage sur ce billet à partir de votre blog. Pour copier le lien, faites un clic droit sur le lien, et sélectionnez \\\'Copier le lien\\\' dans Internet Explorer ou \\\'Copier le lien\\\' dans Mozilla.');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'Attention: Ce traçage doit être approuvé avant qu\'il puisse être affiché.');
+@define('DELETE_TRACKBACK', 'Supprimer le traçage');
+@define('APPROVE_TRACKBACK', 'Approuver le traçage');
+@define('TRACKBACK_APPROVED', 'Le taçage #%s a été approuvé');
+@define('TRACKBACK_DELETED', 'Le traçage #%s a été supprimé');
+@define('COMMENTS_MODERATE', 'Les commentaires ou traçages de ce billet doivent être approuvés.');
+@define('PLUGIN_SUPERUSER_HTTPS', 'Utiliser un accès sécurisé pour l\'authentification');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'Fait que le lien de l\'interface d\'administration montre vers un lien sécurisé (https). Attention: Votre serveur doit être configuré pour accepter ce genre de liens.');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'Rendre les liens sortants cliquables?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '\'Non\': Les liens sortants non vérifiés (Top liens sortants, Top pages référantes, Commentaires) ne sont pas affichés/affichés en tant que texte seulement quand possible pour prévenir le spam par Google (recommandé). \'Oui\': les liens non vérifiés sont affichés en tant que liens. Notez que vous pouvez remplacer cette option localement dans les plugins pour la barre latérale.');
+@define('PAGE_BROWSE_COMMENTS', 'Page %s de %s, %s commentaires au total');
+@define('FILTERS', 'Filtres');
+@define('FIND_ENTRIES', 'Trouver des billets');
+@define('FIND_COMMENTS', 'Trouver des commentaires');
+@define('FIND_MEDIA', 'Trouver des images');
+@define('FILTER_DIRECTORY', 'Dossier');
+@define('SORT_BY', 'Trier par');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'Pas de traçage envoyé: la connexion n\'a pas pu être établie à %s sur le port %d');
+@define('MEDIA', 'Document');
+@define('MEDIA_LIBRARY', 'Médiathèque');
+@define('ADD_MEDIA', 'Ajouter un document');
+@define('ENTER_MEDIA_URL', 'Entrez un lien d\'un fichier à télécharger:');
+@define('ENTER_MEDIA_UPLOAD', 'Sélectionnez un fichier à uploader:');
+@define('SAVE_FILE_AS', 'Enregistrer le fichier sous:');
+@define('STORE_IN_DIRECTORY', 'Enregistrer dans le dossier suivant: ');
+@define('MEDIA_RENAME', 'Renommer ce fichier');
+@define('IMAGE_RESIZE', 'Redimensionner cette image');
+@define('MEDIA_DELETE', 'Supprimer ce fichier');
+@define('FILES_PER_PAGE', 'Fichiers par page');
+@define('CLICK_FILE_TO_INSERT', 'Cliquez sur le fichier que vous voulez insérer:');
+@define('SELECT_FILE', 'Choisissez un fichier à insérer');
+@define('MEDIA_FULLSIZE', 'Taille réelle');
+@define('CALENDAR_BOW_DESC', 'Le jour qui doit être considéré comme début de la semaine. Lundi par défaut.');
+@define('SUPERUSER', 'Administration du blog');
+@define('ALLOWS_YOU_BLAHBLAH', 'Ajoute un lien à l\'administration de votre blog dans la barre latérale.');
+@define('CALENDAR', 'Calendrier');
+@define('SUPERUSER_OPEN_ADMIN', 'Aller à l\'administration');
+@define('SUPERUSER_OPEN_LOGIN', 'Aller à l\'écran d\'authentification');
+@define('INVERT_SELECTIONS', 'Inverser les sélections');
+@define('COMMENTS_DELETE_CONFIRM', 'Êtes-vous sûr de vouloir supprimer les commentaires sélectionnés?');
+@define('COMMENT_DELETE_CONFIRM', 'Êtes-vous sûr de vouloir supprimer le commentaire #%d, posté par %s?');
+@define('DELETE_SELECTED_COMMENTS', 'Supprimer les commentaires sélectionnés');
+@define('VIEW_COMMENT', 'Afficher le commentaire');
+@define('VIEW_ENTRY', 'Afficher le billet');
+@define('DELETE_FILE', 'Suppression du fichier intitulé <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', 'Vous êtes sur le point d\'effacer <b>%s</b>.<br />Si vous avez utilisé ce fichier dans un de vos billets, les liens vers celui-ci seront invalides<br />Êtes-vous sûr de vouloir continuer?<br /><br />');
+@define('TRACKBACK_SENDING', 'Envoie le traçage à l\'adresse %s...');
+@define('TRACKBACK_SENT', 'Traçage effectué');
+@define('TRACKBACK_FAILED', 'Traçage échoué: %s');
+@define('TRACKBACK_NOT_FOUND', 'Pas d\'adresse de traçage trouvée.');
+@define('TRACKBACK_URI_MISMATCH', 'L\'adresse de traçage déterminée automatiquement ne correspond pas l\'adresse cible.');
+@define('TRACKBACK_CHECKING', 'Vérifie <u>%s</u> pour des traçages éventuels...');
+@define('TRACKBACK_NO_DATA', 'L\'adresse cible ne contenait pas de données');
+@define('TRACKBACK_SIZE', 'L\'adresse cible dépasse la taille Target URI exceeded maximum filesize of %s bytes.');
+@define('VIEWMODE_THREADED', 'Passer en mode vue groupée');
+@define('COMMENTS_VIEWMODE_THREADED', 'Vue groupée');
+@define('COMMENTS_VIEWMODE_LINEAR', 'Vue non groupée');
+@define('DISPLAY_COMMENTS_AS', 'Afficher les commentaires en');
+@define('PAGE_BROWSE_ENTRIES', 'Page %s de %s sur %s billets au total');
+@define('ADD_MEDIA_BLAHBLAH', '<b>Ajouter un fichier à votre médiathèque:</b><p>Vous permet d\'uploader des fichiers, ou de me dire une adresse internet de laquelle je peux les télécharger. Si vous n\'avez pas d\'image appropriée, vous pouvez faire une <a href="http://images.google.com" target="_blank">recherche d\'images avec Google</a>, les résultats sont souvent intéressants et toujours très comiques :)<p><b>Choisissez une méthode:</b><br>');
+@define('COMMENTS_FILTER_SHOW', 'Afficher');
+@define('COMMENTS_FILTER_ALL', 'Tous');
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'Approuvés');
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'En attente d\'être approuvés');
+@define('RSS_IMPORT_BODYONLY', 'Mettre tout le texte importé dans l\'introduction du billet au lieu de le répartir sur l\'introduction et le corps du billet.');
+@define('SYNDICATION_PLUGIN_FULLFEED', 'Afficher les billets complets dans le fil RSS (include le corps du billet)');
+@define('MT_DATA_FILE', 'Fichier de données Movable Type');
+@define('FORCE', 'Forcer');
+@define('CREATE_AUTHOR', 'Créer l\'auteur \'%s\'.');
+@define('CREATE_CATEGORY', 'Créer la catégorie \'%s\'.');
+@define('MYSQL_REQUIRED', 'L\'extension MySQL doit être activée dans votre installation PHP pour pouvoir continuer.');
+@define('COULDNT_CONNECT', 'Impossible de se connecter à la base de données MySQL: %s.');
+@define('COULDNT_SELECT_DB', 'Impossible de sélectionner une base de données: %s.');
+@define('COULDNT_SELECT_USER_INFO', 'Impossible d\'accéder aux informations d\'utilisateurs: %s.');
+@define('COULDNT_SELECT_CATEGORY_INFO', 'Impossible d\'accéder aux informations de catégories: %s.');
+@define('COULDNT_SELECT_ENTRY_INFO', 'Impossible d\'accéder aux informations de billets: %s.');
+@define('COULDNT_SELECT_COMMENT_INFO', 'Impossible d\'accéder aux informations de commentaires: %s.');
+@define('WEEK', 'Semaine');
+@define('WEEKS', 'Semaines');
+@define('MONTHS', 'Mois');
+@define('DAYS', 'Jours');
+@define('ARCHIVE_FREQUENCY', 'Fréquence d\archivage des éléments dans le calendrier');
+@define('ARCHIVE_FREQUENCY_DESC', 'Intervalle dans le calendrier entre chaque élément de la liste');
+@define('ARCHIVE_COUNT', 'Nombre d\'éléments dans la liste');
+@define('ARCHIVE_COUNT_DESC', 'Le nombre total de mois, semaines ou jours à aficher');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'Ci-dessous: une liste des plugins installés');
+@define('SIDEBAR_PLUGIN', 'plugin de barre latérale');
+@define('EVENT_PLUGIN', 'plugin d\'évènement');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'Cliquez ici pour installer un nouveau %s');
+@define('VERSION', 'version');
+@define('INSTALL', 'Installer');
+@define('ALREADY_INSTALLED', 'Déjà installé');
+@define('SELECT_A_PLUGIN_TO_ADD', 'Sélectionnez le plugin que vous voulez installer');
+@define('INSTALL_OFFSET', 'Décalage de l\'heure serveur');
+@define('STICKY_POSTINGS', 'Billets indélébiles');
+@define('INSTALL_FETCHLIMIT', 'Billets à afficher sur la page d\'accueil');
+@define('INSTALL_FETCHLIMIT_DESC', 'Nombre de billets à afficher par page dans l\'interface principale du blog');
+@define('IMPORT_ENTRIES', 'Importer des billets');
+@define('EXPORT_ENTRIES', 'Exporter des billets');
+@define('IMPORT_WELCOME', 'Bienvenue dans l\'assistant d\'importation de Serendipity');
+@define('IMPORT_WHAT_CAN', 'Ici vous pouvez importer des billets d\'autres logiciels de Blog');
+@define('IMPORT_SELECT', 'Sélectionnez le logiciel dont vous voulez importer les billets');
+@define('IMPORT_PLEASE_ENTER', 'Complétez les informations requises ci-dessous');
+@define('IMPORT_NOW', 'Importer maintenant!');
+@define('IMPORT_STARTING', 'Importe les billets...');
+@define('IMPORT_FAILED', 'Importation échouée');
+@define('IMPORT_DONE', 'Importation terminée avec succès');
+@define('IMPORT_WEBLOG_APP', 'Logiciel de Blog');
+@define('EXPORT_FEED', 'Exporter le fil RSS complet');
+@define('STATUS', 'Statut après importation');
+@define('IMPORT_GENERIC_RSS', 'Importation générique de fils RSS');
+@define('ACTIVATE_AUTODISCOVERY', 'Envoyer des traçages aux liens trouvés dans le billet');
+@define('WELCOME_TO_ADMIN', 'Bienvenue dans l\'interface d\'administration de Serendipity');
+@define('PLEASE_ENTER_CREDENTIALS', 'Entrez vos données d\'authentification ci-dessous.');
+@define('ADMIN_FOOTER_POWERED_BY', 'Propulsé par Serendipity %s et PHP %s');
+@define('INSTALL_USEGZIP', 'Utiliser la compression gzip des pages');
+@define('INSTALL_USEGZIP_DESC', 'Pour augmenter la vitesse de transfert des pages, Serendipity peut comprimer les pages envoyées au navigateur du visiteur (si le navigateur peut interpréter cette compression). Recommandé.');
+@define('INSTALL_SHOWFUTURE', 'Afficher les billets futurs');
+@define('INSTALL_SHOWFUTURE_DESC', 'Si cette option est activée, les billets à paraître seront affichés dans votre blog. Par défaut, ces billets ne seront affichés qu\'à la date de publication définie.');
+@define('INSTALL_DBPERSISTENT', 'Utiliser les connexions permanentes');
+@define('INSTALL_DBPERSISTENT_DESC', 'Active l\'utilisation de connexions permanentes à la base de données. Pour plus d\'informations, consultez le <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">manuel de PHP</a>. Non recommandé en règle générale.');
+@define('NO_IMAGES_FOUND', 'Pas d\'images trouvées');
+@define('PERSONAL_SETTINGS', 'Réglages personnels');
+@define('REFERER', 'Page référante');
+@define('NOT_FOUND', 'Non trouvé');
+@define('NOT_WRITABLE', 'Protégé en écriture');
+@define('WRITABLE', 'Accessible en écriture');
+@define('PROBLEM_DIAGNOSTIC', 'À cause d\'erreurs survenues lors de l\'analyse préventive, vous ne pourrez continuer l\'installation qu\'après avoir corrigé les erreurs mentionnées ci-dessus.');
+@define('SELECT_INSTALLATION_TYPE', 'Choisissez le type d\'installation que vous voulez utiliser');
+@define('WELCOME_TO_INSTALLATION', 'Bienvenue dans l\'assistant d\'installation de Serendipity');
+@define('FIRST_WE_TAKE_A_LOOK', 'Tout d\'abord, nous allons faire une analyse préventive de votre installation et essayer de diagnostiquer d\'éventuels problèmes de compatibilité.');
+@define('ERRORS_ARE_DISPLAYED_IN', 'Les erreurs sont affichées en %s, les recommandations en %s et les succès en %s');
+@define('RED', 'rouge');
+@define('YELLOW', 'jaune');
+@define('GREEN', 'vert');
+@define('PRE_INSTALLATION_REPORT', 'Rapport pré-installation de Serendipity v%s');
+@define('RECOMMENDED', 'Recommandé');
+@define('ACTUAL', 'Actuel');
+@define('PHPINI_CONFIGURATION', 'configuration php.ini');
+@define('PHP_INSTALLATION', 'Installation PHP');
+@define('THEY_DO', 'ils font');
+@define('THEY_DONT', 'ils ne font pas');
+@define('SIMPLE_INSTALLATION', 'Installation rapide');
+@define('EXPERT_INSTALLATION', 'Installation expert');
+@define('COMPLETE_INSTALLATION', 'Installation complète');
+@define('WONT_INSTALL_DB_AGAIN', 'la base de données ne sera pas réinstallée');
+@define('CHECK_DATABASE_EXISTS', 'Vérifie si la base de données et les tableaux nécessaires sont déjà présents');
+@define('CREATING_PRIMARY_AUTHOR', 'Création de l\'auteur principal \'%s\'');
+@define('SETTING_DEFAULT_TEMPLATE', 'Définition du style par défaut');
+@define('INSTALLING_DEFAULT_PLUGINS', 'Installation des plugins par défaut');
+@define('SERENDIPITY_INSTALLED', 'Serendipity a été installé avec succès');
+@define('VISIT_BLOG_HERE', 'Accéder à votre nouveau blog');
+@define('THANK_YOU_FOR_CHOOSING', 'Merci d\'avoir choisi Serendipity');
+@define('ERROR_DETECTED_IN_INSTALL', 'Une erreur a été détectée pendant l\'installation');
+@define('OPERATING_SYSTEM', 'Système d\'exploitation');
+@define('WEBSERVER_SAPI', 'SAPI Serveur');
+@define('IMAGE_ROTATE_LEFT', 'Basculer l\'image de 90 degrés vers la droite');
+@define('IMAGE_ROTATE_RIGHT', 'Basculer l\'image de 90 degrés vers la gauche');
+@define('TEMPLATE_SET', '\'%s\' a été défini comme style actif');
+@define('SEARCH_ERROR', 'La fonction de recherche n\'a pas fonctionné comme prévu. Note à l\'administrateur de ce blog: cette erreur peut survenir si des clés d\'index manquent dans la base de données. Avec des systèmes MySQL, l\'utilisateur avec lequel Serendipity se connecte à la base de données doit avoir les privilèges nécessaires pour exécuter la commande suivante: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre>. Voici le message d\'erreur complet de la base de données: <pre>%s</pre>');
+@define('EDIT_THIS_CAT', 'Éditer "%s"');
+@define('CATEGORY_REMAINING', 'Effacer cette catégorie et déplacer tous les billets dans cette catégorie');
+@define('CATEGORY_INDEX', 'Voici une liste des catégories disponibles pour vos billets');
+@define('NO_CATEGORIES', 'Pas de catégories');
+@define('RESET_DATE', 'Réinitialiser la date');
+@define('RESET_DATE_DESC', 'Cliquez ici pour remettre la date à l\'heure actuelle');
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Les droits d\'accès peuvent être changés sur la ligne de commande par la commande: `<em>%s</em>` sur le répertoire qui fait défaut, ou en le faisant à l\'aide d\'un programme FTP.');
+@define('WARNING_TEMPLATE_DEPRECATED', 'Attention: les templates du style que vous avez choisi utilisent des fonctions périmées. Vous devriez les mettre à jour si possible.');
+@define('ENTRY_PUBLISHED_FUTURE', 'Cette entrée n\'est pas encore publiée.');
+@define('ENTRIES_BY', 'Entrées par %s');
+@define('PREVIOUS', 'Précédent');
+@define('NEXT', 'Suivant');
+@define('APPROVE', 'Valider');
+@define('DO_MARKUP_DESCRIPTION', 'Transforme les balises dans le texte (smileys, raccourcis via *, /, _, ...). La désactiver préserva tout le code HTML dans le texte.');
+@define('CATEGORY_ALREADY_EXIST', 'A category with the name "%s" already exist'); // Translate
+@define('IMPORT_NOTES', 'Note:'); // Translate
+@define('ERROR_FILE_FORBIDDEN', 'You are not allowed to upload files with active content'); // Translate
+@define('ADMIN', 'Administration'); // Re-Translate
+@define('ADMIN_FRONTPAGE', 'Frontpage'); // Translate
+@define('QUOTE', 'Quote'); // Translate
+@define('IFRAME_SAVE', 'Serendipity is now saving your entry, creating trackbacks and performing possible XML-RPC calls. This may take a while..'); // Translate
+@define('IFRAME_SAVE_DRAFT', 'A draft of this entry has been saved'); // Translate
+@define('IFRAME_PREVIEW', 'Serendipity is now creating the preview of your entry...'); // Translate
+@define('IFRAME_WARNING', 'Your browser does not support the concept of iframes. Please open your serendipity_config.inc.php file and set $serendipity[\'use_iframe\'] variable to FALSE.'); // Translate
+@define('NONE', 'none');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Default settings for new entries'); // Translate
+@define('UPGRADE', 'Upgrade'); // Translate
+@define('UPGRADE_TO_VERSION', 'Upgrade to version %s'); // Translate
+@define('DELETE_DIRECTORY', 'Delete directory'); // Translate
+@define('DELETE_DIRECTORY_DESC', 'You are about to delete the contents of a directory that contains media files, possibly files used in some of your entries.'); // Translate
+@define('FORCE_DELETE', 'Delete ALL files in this directory, including those not known by Serendipity'); // Translate
+@define('CREATE_DIRECTORY', 'Create directory'); // Translate
+@define('CREATE_NEW_DIRECTORY', 'Create new directory'); // Translate
+@define('CREATE_DIRECTORY_DESC', 'Here you can create a new directory to place media files in. Choose the name for your new directory and select an optional parent directory to place it in.'); // Translate
+@define('BASE_DIRECTORY', 'Base directory'); // Translate
+@define('USERLEVEL_EDITOR_DESC', 'Standard editor'); // Translate
+@define('USERLEVEL_CHIEF_DESC', 'Chief editor'); // Translate
+@define('USERLEVEL_ADMIN_DESC', 'Administrator'); // Translate
+@define('USERCONF_USERLEVEL', 'Access level'); // Translate
+@define('USERCONF_USERLEVEL_DESC', 'This level is used to determine what kind of access this user has to the blog'); // Translate
+@define('USER_SELF_INFO', 'Logged in as %s (%s)'); // Translate
+@define('ADMIN_ENTRIES', 'Entries'); // Translate
+@define('RECHECK_INSTALLATION', 'Recheck installation'); // Translate
+@define('IMAGICK_EXEC_ERROR', 'Unable to execute: "%s", error: %s, return var: %d'); // Translate
+@define('INSTALL_OFFSET_DESC', 'Enter the amount of hours between the date of your webserver (current: %clock%) and your desired time zone'); // Translate
+@define('UNMET_REQUIREMENTS', 'Requirements failed: %s'); // Translate
+@define('CHARSET', 'Charset');
+@define('AUTOLANG', 'Use visitor\'s browser language as default');
+@define('AUTOLANG_DESC', 'If enabled, this will use the visitor\'s browser language setting to determine the default language of your entry and interface language.');
+@define('INSTALL_AUTODETECT_URL', 'Autodetect used HTTP-Host'); // Translate
+@define('INSTALL_AUTODETECT_URL_DESC', 'If set to "true", Serendipity will ensure that the HTTP Host which was used by your visitor is used as your BaseURL setting. Enabling this will let you be able to use multiple domain names for your Serendipity Blog, and use the domain for all follow-up links which the user used to access your blog.'); // Translate
+@define('CONVERT_HTMLENTITIES', 'Try to auto-convert HTML entities?');
+@define('EMPTY_SETTING', 'You did not specify a valid value for "%s"!');
+@define('USERCONF_REALNAME', 'Real name'); // Translate
+@define('USERCONF_REALNAME_DESC', 'The full name of the author. This is the name seen by readers'); // Translate
+@define('HOTLINK_DONE', 'File hotlinked.<br />Done.'); // Translate
+@define('ENTER_MEDIA_URL_METHOD', 'Fetch method:'); // Translate
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Note: If you choose to hotlink to server, make sure you have permission to hotlink to the designated website, or the website is yours. Hotlink allows you to use off-site images without storing them locally.'); // Translate
+@define('MEDIA_HOTLINKED', 'hotlinked'); // Translate
+@define('FETCH_METHOD_IMAGE', 'Download image to your server'); // Translate
+@define('FETCH_METHOD_HOTLINK', 'Hotlink to server'); // Translate
+@define('DELETE_HOTLINK_FILE', 'Deleted the hotlinked file entitled <b>%s</b>'); // Translate
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Show E-Mail addresses?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_is.inc.php b/lang/serendipity_lang_is.inc.php
new file mode 100644 (file)
index 0000000..46ba192
--- /dev/null
@@ -0,0 +1,668 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+@define('LANG_CHARSET', 'ISO-8859-1');
+@define('DATE_LOCALES', 'icelandic, is, is_IS');
+@define('DATE_FORMAT_ENTRY', '%A, %e. %B %Y');
+@define('DATE_FORMAT_SHORT', '%d.%m.%y %H:%M');
+@define('WYSIWYG_LANG', 'is');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', ',');
+@define('NUMBER_FORMAT_THOUSANDS', '.');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Stjórnborð Serendipity');
+@define('HAVE_TO_BE_LOGGED_ON', 'Þú þarft að vera skráður inn til að skoða þessa síðu');
+@define('WRONG_USERNAME_OR_PASSWORD', 'Þú virðist hafa slegið inn rangt notandanafn eða lykilorð');
+@define('APPEARANCE', 'Útlit');
+@define('MANAGE_STYLES', 'Breyta útliti');
+@define('CONFIGURE_PLUGINS', 'Stilla viðbætur');
+@define('CONFIGURATION', 'Stillingar');
+@define('BACK_TO_BLOG', 'Aftur á bloggið');
+@define('LOGIN', 'Skrá inn');
+@define('LOGOUT', 'Skrá út');
+@define('LOGGEDOUT', 'Útskráður.');
+@define('CREATE', 'Búa til');
+@define('SAVE', 'Vista');
+@define('NAME', 'Nafn');
+@define('CREATE_NEW_CAT', 'Búa til nýjan flokk');
+@define('I_WANT_THUMB', 'Ég vil nota sýnishorn í færslunni.');
+@define('I_WANT_BIG_IMAGE', 'Ég vil nota stærri myndina í færslunni.');
+@define('I_WANT_NO_LINK', ' Ég vil birta þetta sem mynd');
+@define('I_WANT_IT_TO_LINK', 'Ég vil birta þetta sem hlekk á þessa slóð:');
+@define('BACK', 'Til baka');
+@define('FORWARD', 'Áfram');
+@define('ANONYMOUS', 'Nafnlaus');
+@define('NEW_TRACKBACK_TO', 'Ný tilvísun gerð á');
+@define('NEW_COMMENT_TO', 'Ný athugasemd send á');
+@define('RECENT', 'Nýlegt...');
+@define('OLDER', 'Eldra...');
+@define('DONE', 'Búin');
+@define('WELCOME_BACK', 'Velkomin(n) aftur,');
+@define('TITLE', 'Fyrirsögn');
+@define('DESCRIPTION', 'Lýsing');
+@define('PLACEMENT', 'Staðsetning');
+@define('DELETE', 'Eyða');
+@define('SAVE', 'Vista');
+@define('UP', 'Upp');
+@define('DOWN', 'Niður');
+@define('ENTRIES', 'færslur');
+@define('NEW_ENTRY', 'Nýja færslu');
+@define('EDIT_ENTRIES', 'Breyta færslum');
+@define('CATEGORIES', 'Flokkar');
+@define('WARNING_THIS_BLAHBLAH', "VARÚÐ:\\nÞetta gæti tekið langan tíma ef það eru margar myndir án sýnishorna.");
+@define('CREATE_THUMBS', 'Endurvinna sýnishorn');
+@define('MANAGE_IMAGES', 'Breyta myndum');
+@define('NAME', 'Nafn');
+@define('EMAIL', 'Netfang');
+@define('HOMEPAGE', 'Heimasíða');
+@define('COMMENT', 'Athugasemd');
+@define('REMEMBER_INFO', 'Muna þessar upplýsingar? ');
+@define('SUBMIT_COMMENT', 'Skrá athugasemd');
+@define('NO_ENTRIES_TO_PRINT', 'Engar færslur til að sýna.');
+@define('COMMENTS', 'Athugasemdir');
+@define('ADD_COMMENT', 'Bæta við athugasemd');
+@define('NO_COMMENTS', 'Engar athugasemdir.');
+@define('POSTED_BY', '');
+@define('ON', 'þann');
+@define('A_NEW_COMMENT_BLAHBLAH', 'Ný athugasemd hefur verið send á bloggið þitt, "%s", í færslunni "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'Ný tilvísun hefur verið gerð á bloggfærsluna þína, "%s".');
+@define('NO_CATEGORY', 'Enginn flokkur');
+@define('ENTRY_BODY', 'Innihald færslu');
+@define('EXTENDED_BODY', 'Aukainnihald');
+@define('CATEGORY', 'Flokkur');
+@define('EDIT', 'Breyta');
+@define('NO_ENTRIES_BLAHBLAH', 'Engar færslur fundnar fyrir fyrirspurn %s' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'Leit þín að %s skilaði %s niðurstöðum:');
+@define('SEARCH_TOO_SHORT', 'Leitarfyrirspurn þín verður að vera lengri en 3 stafir');
+@define('IMAGE', 'Mynd');
+@define('ERROR_FILE_NOT_EXISTS', 'Villa: Gamla skráarnafnið er ekki til!');
+@define('ERROR_FILE_EXISTS', 'Villa: Nýja skráarnafnið er þegar í notkun, veldu annað!');
+@define('ERROR_SOMETHING', 'Villa: Eitthvað er að.');
+@define('ADDING_IMAGE', 'Bæti við mynd...');
+@define('THUMB_CREATED_DONE', 'Sýnishorn búið til.<br>Búin.');
+@define('ERROR_FILE_EXISTS_ALREADY', 'Villa: Skráin er þegar til á vélinni!');
+@define('ERROR_UNKNOWN_NOUPLOAD', 'Óþekkt villa hefur komið upp, skrá ekki vistuð. Kannski var stærð skráarinnar meiri heldur en hámarksstærðin sem netjónninn skilgreinir. Hafðu samband við þjónustuaðilann þinn eða breytti php.ini skránni til að leyfa stærri skráarflutninga.');
+@define('GO', 'Go!');
+@define('NEWSIZE', 'Ný stærð: ');
+@define('RESIZE_BLAHBLAH', '<b>Breyta stærð %s</b><p>');
+@define('ORIGINAL_SIZE', 'Upprunaleg stærð: <i>%sx%s</i> pixel');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>Hér getur þú breytt stærð myndarinnar. Ef þú vilt breyta stærð hennar í réttum hlutföllum, sláðu þá inn eitthvað gildi í annan tveggja reitanna og ýttu á TAB takkann. -- Stærð þeirra verður reiknuð sjálfvirkt svo hlutföllin haldist rétt.</p>');
+@define('QUICKJUMP_CALENDAR', 'QuickJump dagatal');
+@define('QUICKSEARCH', 'Leita');
+@define('SEARCH_FOR_ENTRY', 'Leita að færslu');
+@define('ARCHIVES', 'Tímavélin');
+@define('BROWSE_ARCHIVES', 'Vafra gamlar færslur eftir mánuðum');
+@define('TOP_REFERRER', 'Topp ávísarar');
+@define('SHOWS_TOP_SITES', 'Sýna toppsíður sem vísuðu á bloggin þín');
+@define('TOP_EXITS', 'Topp útgönguleiðir');
+@define('SHOWS_TOP_EXIT', 'Sýnir helstu útgönguleiðir frá bloggunum þínum');
+@define('SYNDICATION', 'Sjálfvirkni');
+@define('SHOWS_RSS_BLAHBLAH', 'Sýnir RSS tengla');
+@define('ADVERTISES_BLAHBLAH', 'Auglýsir uppruna bloggsins');
+@define('HTML_NUGGET', 'HTML stubbur');
+@define('HOLDS_A_BLAHBLAH', 'Stubbur fyrir HTML í hliðarrammann þinn');
+@define('TITLE_FOR_NUGGET', 'Titill fyrir stubbinn');
+@define('THE_NUGGET', 'Stubbur HTML!');
+@define('SYNDICATE_THIS_BLOG', 'Skráðu RSS fyrir þetta blogg');
+@define('YOU_CHOSE', 'Þú valdir %s');
+@define('IMAGE_ROTATE_LEFT', 'Snúa mynd 90 gráður rangsælis');
+@define('IMAGE_ROTATE_RIGHT', 'Snúa mynd 90 gráður réttsælis');
+@define('IMAGE_SIZE', 'Stærð myndar');
+@define('IMAGE_AS_A_LINK', 'Innsetning myndar');
+@define('POWERED_BY', 'Knúið af');
+@define('TRACKBACKS', 'Tilvísanir');
+@define('TRACKBACK', 'Tilvísun');
+@define('NO_TRACKBACKS', 'Engar tilvísanir');
+@define('TOPICS_OF', 'Fyrirsagnir af');
+@define('VIEW_FULL', 'skoða allt');
+@define('VIEW_TOPICS', 'skoða fyrirsagnir');
+@define('AT', 'sendi klukkan');
+@define('SET_AS_TEMPLATE', 'Setja sem forsnið');
+@define('IN', 'í');
+@define('EXCERPT', 'Útdráttur');
+@define('TRACKED', 'Tracked');
+@define('LINK_TO_ENTRY', 'Vísa á færslu');
+@define('LINK_TO_REMOTE_ENTRY', 'Vísa á færslu á öðru kerfi');
+@define('IP_ADDRESS', 'IP-tala');
+@define('USER', 'Notandi');
+@define('THUMBNAIL_USING_OWN', 'Nota %s sem eigið sýnishorn, þar sem hún er þegar svo lítil.');
+@define('THUMBNAIL_FAILED_COPY', 'Vildi nota %s sem eigið sýnishorn, en gat ekki afritað!');
+@define('AUTHOR', 'Höfundur');
+@define('LAST_UPDATED', 'Síðast uppfært');
+@define('TRACKBACK_SPECIFIC', 'URI slóð fyrir tilvísun á þessa færslu');
+@define('DIRECT_LINK', 'Bein slóð á þessa færslu');
+@define('COMMENT_ADDED', 'Athugasemd þinni hefur verið bætt við. ');
+@define('COMMENT_ADDED_CLICK', 'Smelltu %shér til að fara%s á athugasemdir, og %shér til að loka%s þessum glugga.');
+@define('COMMENT_NOT_ADDED', 'Gat ekki bætt athugasemd þinni við, því athugasemdir hafa verið gerðar óvirkar fyrir þessa færslu. ');
+@define('COMMENT_NOT_ADDED_CLICK', 'Smelltu %shér til að fara%s á athugasemdir, og %shér til að loka%s þessum glugga.');
+@define('COMMENTS_DISABLE', 'Leyfa ekki athugasemdir á þessa færslu');
+@define('COMMENTS_ENABLE', 'Leyfa athugasemdir á þessu færslu');
+@define('COMMENTS_CLOSED', 'Höfundurinn leyfir ekki athugasemdir á þessa færslu');
+@define('EMPTY_COMMENT', 'Athugasemdin þín innihélt ekki neitt, svo vinsamlegast %sfarðu til baka%s og reyndu aftur');
+@define('ENTRIES_FOR', 'Færslur fyrir %s');
+@define('DOCUMENT_NOT_FOUND', 'Skjalið %s fannst ekki.');
+@define('USERNAME', 'Notandanafn');
+@define('PASSWORD', 'Lykilorð');
+@define('AUTOMATIC_LOGIN', 'Vista upplýsingar');
+@define('SERENDIPITY_INSTALLATION', 'Serendipity uppsetning');
+@define('LEFT', 'vinstri');
+@define('RIGHT', 'hægri');
+@define('HIDDEN', 'falinn');
+@define('REMOVE_TICKED_PLUGINS', 'Fjarlægja hakaðar viðbætur');
+@define('SAVE_CHANGES_TO_LAYOUT', 'Vista útlitsbreytingar');
+@define('COMMENTS_FROM', 'Athugasemdir frá');
+@define('ERROR', 'Villa');
+@define('ENTRY_SAVED', 'Færslan þín hefur verið vistuð');
+@define('DELETE_SURE', 'Ertu viss um að þú viljir eyða #%s endanlega?');
+@define('NOT_REALLY', 'Nei, eiginlega ekki...');
+@define('DUMP_IT', 'Fleygðu þessu!');
+@define('RIP_ENTRY', 'Hvíldu í friði, færsla #%s');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Flokki #%s eytt. Færslur færðar í flokk #%s');
+@define('CATEGORY_DELETED', 'Flokki #%s eytt.');
+@define('INVALID_CATEGORY', 'Enginn flokkur var valinn til eyðingar');
+@define('CATEGORY_SAVED', 'Flokkur vistaður');
+@define('SELECT_TEMPLATE', 'Veldu forsniðið sem þú vilt nota fyrir bloggið þitt');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'Viðbót færsla tókst ekki!');
+@define('MT_DATA_FILE', 'Movable Type gagnaskrá');
+@define('FORCE', 'Þvinga');
+@define('CREATE_AUTHOR', 'Búa til höfund \'%s\'.');
+@define('CREATE_CATEGORY', 'Búa til flokk \'%s\'.');
+@define('MYSQL_REQUIRED', 'Þú verður að hafa MySQL viðbótina til að gera þetta.');
+@define('COULDNT_CONNECT', 'Gat ekki tengst MySQL gagnagrunni: %s.');
+@define('COULDNT_SELECT_DB', 'Gat ekki valið gagnagrunn: %s.');
+@define('COULDNT_SELECT_USER_INFO', 'Gat ekki valið notandaupplýsingar: %s.');
+@define('COULDNT_SELECT_CATEGORY_INFO', 'Gat ekki valið flokksupplýsingar: %s.');
+@define('COULDNT_SELECT_ENTRY_INFO', 'Gat ekki valið færsluupplýsingar: %s.');
+@define('COULDNT_SELECT_COMMENT_INFO', 'Gat ekki valið athugasemdaupplýsingar: %s.');
+@define('YES', 'Já');
+@define('NO', 'Nei');
+@define('USE_DEFAULT', 'Sjálfgefið');
+@define('CHECK_N_SAVE', 'Prófa &amp; vista');
+@define('DIRECTORY_WRITE_ERROR', 'Get ekki skrifað í möppu %s. Athugaðu eiginleika hennar.');
+@define('DIRECTORY_CREATE_ERROR', 'Mappan %s er ekki til og gat ekki búið hana til. Vinsamlegast búðu hana til handvirkt');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; keyra <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', 'Get ekki keyrt %s skrána');
+@define('FILE_WRITE_ERROR', 'Gat ekki skrifað í skrá %s.');
+@define('FILE_CREATE_YOURSELF', 'Vinsamlegast búðu skrána til sjálfur eða athugaðu eiginleika');
+@define('COPY_CODE_BELOW', '<br />* Vistaðu bara kóðann fyrir neðan og settu hann í %s í %s möppunni:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Breyttu www í notandann sem að apache keyrir sem (t.d. nobody).');
+@define('BROWSER_RELOAD', 'Þegar þú ert búinn að því, uppfærðu þá síðunna með "reload/refresh" takkanum.');
+@define('DIAGNOSTIC_ERROR', 'Við urðum vör við einhverjar villur þegar við keyrðum greiningar á upplýsingunum sem þú gafst:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity er ekki uppsett. Vinsamlegast <a href="%s">settu það upp</a> núna.');
+@define('INCLUDE_ERROR', 'serendipity villa: gat ekki innlimað %s - hætti.');
+@define('DATABASE_ERROR', 'serendipity villa: gat ekki tengst gagnagrunni - hætti.');
+@define('CREATE_DATABASE', 'Geri sjálfgefnu uppsetninguna á gagnagrunninum...');
+@define('ATTEMPT_WRITE_FILE', 'Reyni að skrifa %s skrána...');
+@define('WRITTEN_N_SAVED', 'Stillingar skrifaðar &amp; vistaðar');
+@define('IMAGE_ALIGNMENT', 'Staðsetning myndar');
+@define('ENTER_NEW_NAME', 'Sláðu inn nýtt nafn fyrir: ');
+@define('RESIZING', 'Breyti stærð');
+@define('RESIZE_DONE', 'Búin (breytti stærð %s mynda).');
+@define('SYNCING', 'Samhæfi gagnagrunn við myndamöppu');
+@define('SYNC_DONE', 'Búin (Samhæfði %s myndir).');
+@define('FILE_NOT_FOUND', 'Fann ekki skrána <b>%s</b>, kannski er þegar búið að eyða henni?');
+@define('ABORT_NOW', 'Hætta við núna');
+@define('REMOTE_FILE_NOT_FOUND', 'Skráin fannst ekki á endaþjóninum. Ertu viss um að slóðin: <b>%s</b> sé rétt?');
+@define('FILE_FETCHED', '%s sótt sem %s');
+@define('FILE_UPLOADED', 'Skrá %s vistuð sem %s');
+@define('WORD_OR', 'Eða');
+@define('SCALING_IMAGE', 'Breyti stærð %s í %s x %s px');
+@define('KEEP_PROPORTIONS', 'Halda hlutföllum');
+@define('REALLY_SCALE_IMAGE', 'Ertu viss að þú viljir breyta stærð myndarinnar? Það er ekki hægt að breyta til baka!');
+@define('TOGGLE_ALL', 'Virkja stækka allt');
+@define('TOGGLE_OPTION', 'Virkja valmöguleika');
+@define('SUBSCRIBE_TO_THIS_ENTRY', 'Gerast áskrifandi að þessari færslu');
+@define('UNSUBSCRIBE_OK', "%s hefur nú verið afskráður frá þessari færslu");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'Ný athugasemd á færslu í áskrift "%s"');
+@define('SUBSCRIPTION_MAIL', "Halló %s,\n\nNý athugasemd hefur verið gerð á færslu sem þú ert að fylgjast með á \"%s\", kölluð \"%s\"\nNafn sendanda er: %s\n\nÞú getur fundið færsluna hér: %s\n\nÞú getur hætt við áskrift með því að smella á þennan hlekk: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "Halló %s,\n\nNýrri tilvísun var bætt við færsluna sem þú ert að fylgjast með á \"%s\", kölluð \"%s\"\nNafn sendanda er: %s\n\nÞú getur fundið færsluna hér: %s\n\nÞú getur hætt við áskrift með því að smella á þennan hlekk: %s\n");
+@define('SIGNATURE', "\n-- \n%s er knúið af Serendipity.\nBesta bloggkerfi sem til er, og þú getur notað það líka.\nKíktu á <http://s9y.org> til að komast að því hvernig.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91 straumur');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0 straumur');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0 straumur');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 athugasemdir');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3 straumur');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'Svæði "manageEditor"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  'Svæði "webMaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'Mynd fyrir RSS strauminn');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', 'Breidd myndar');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'Hæð myndar');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  'Netfang vefstjóra, ef það er fyrir hendi. (tómt: falið) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', 'Netfang umsjónaraðila, ef það er fyrir hendi. (tómt: falið) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'Slóð (URL) myndar í GIF/JPEG/PNG sniði, ef fyrir hendi. (tómt: serendipity-logo)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'í pixelum, hámark 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'í pixelum, hámark 400');
+@define('SYNDICATION_PLUGIN_TTL', 'Svæði "ttl" (time-to-live)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'Sá tími sem bloggið ætti ekki lengur að vera vistað af öðrum framandi síðum/forritum (tómt: falið) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'Svæði "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', 'Ætti "pubDate"-svæðið að vera innbyggt fyrir RSS-rás, til að sýna dagsetningu síðustu færslu?');
+@define('CONTENT', 'Innihald');
+@define('TYPE', 'Tegund');
+@define('DRAFT', 'Drög');
+@define('PUBLISH', 'Birta');
+@define('PREVIEW', 'Skoða');
+@define('DATE', 'Dagsetning');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', 'Varúð: Dagsetningin sem þú skilgreindir var ólögleg. Hún verður að vera gefin í ÁÁÁÁ-MM-DD KK:MM sniði.');
+@define('CATEGORY_PLUGIN_DESC', 'Sýnir listann af flokkum.');
+@define('ALL_AUTHORS', 'Allir höfundar');
+@define('CATEGORIES_TO_FETCH', 'Flokkar til að sækja');
+@define('CATEGORIES_TO_FETCH_DESC', 'Sækja flokka frá hvaða höfundi?');
+@define('PAGE_BROWSE_ENTRIES', 'Blaðsíða %s af %s, með samtals %s færslur');
+@define('PREVIOUS_PAGE', 'fyrri síða');
+@define('NEXT_PAGE', 'næsta síða');
+@define('ALL_CATEGORIES', 'Allir flokkar');
+@define('DO_MARKUP', 'Gera breytingar á texta');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'Dagsetningarsnið');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'Snið alvöru dagsetningar færslunnar, sem notar strftime() breytu PHP. (Sjálfgefið: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'Gat ekki opnað forsniðsskrá, vinsamlegast uppfærðu Serendipity!');
+@define('ADVANCED_OPTIONS', 'Þróaðir möguleikar');
+@define('EDIT_ENTRY', 'Breyta færslu');
+@define('HTACCESS_ERROR', 'Til að athuga uppsetninguna á staðbundna vefþjóninum þarf serendipity að geta skrifað í skrána ".htaccess". Þetta var ekki hægt vegna leyfisstillinga. Vinsamlegast breyttu leyfum skráarinnar svona:  <br />&nbsp;&nbsp;%s<br />og endurhladdu þessari síðu.');
+@define('SIDEBAR_PLUGINS', 'Viðbætur hliðarramma');
+@define('EVENT_PLUGINS', 'Viðbætur atburða');
+@define('SORT_ORDER', 'Röðunarregla');
+@define('SORT_ORDER_NAME', 'Skráarnafn');
+@define('SORT_ORDER_EXTENSION', 'Skráarending');
+@define('SORT_ORDER_SIZE', 'Skráarstærð');
+@define('SORT_ORDER_WIDTH', 'Breidd myndar');
+@define('SORT_ORDER_HEIGHT', 'Hæð myndar');
+@define('SORT_ORDER_DATE', 'Dagsetning vistunar');
+@define('SORT_ORDER_ASC', 'Upp á við');
+@define('SORT_ORDER_DESC', 'Niður á við');
+@define('THUMBNAIL_SHORT', 'Sýnishorni');
+@define('ORIGINAL_SHORT', 'Upphafl.');
+@define('APPLY_MARKUP_TO', 'Virkja textabreytingar á %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'Upphaf vikunnar');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity hefur tekið eftir að stillingarnar þínar eru uppsettar fyrir útgáfu %s, en þetta serindipity er af útgáfu %s. Serendipity á þó að vera af útgáfu %s, svo þú þarft að uppfæra! <a href="%s">Smelltu hér</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'Góðan dag, og velkomin í uppfærsluforrit Serendipity.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', 'Ég er hér til að hjálpa þér að uppfæra Serendipity %s uppsetninguna þína.');
+@define('SERENDIPITY_UPGRADER_WHY', 'Þú sérð þessi skilaboð vegna þess að þú hefur sett upp Serendipity %s, en þú hefur ekki uppfært gagnagrunnsuppsetninguna til að passa við þessa útgáfu');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'Uppfærslur gagnagrunns (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'Ég fann eftirfarandi .sql skrár sem þarf að keyra áður en þú getur haldið áfram með venjulega keyrslu á Serendipity');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  'Aðgerðir bundar við þessa útgáfu');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', 'Engar aðgerðir bundar við þessa útgáfu fundust');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', 'Viltu að ég framkvæmi ofangreindar aðgerðir?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'Nei, ég mun gera þær handvirkt');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'Já takk, gerðu það');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'Það virðist sem svo að þú þurfir ekki að keyra neinar uppfærslur');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', 'Uppfærslu lokið');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'Þú hefur hundsað uppfærslustig Serendipity. Vinsamlegast gakktu úr skugga um að gagnagrunnurinn sé rétt uppsettur, og fyrirætluð virkni sé í gangi');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'Serendipity uppsetningin þín hefur nú verið uppfærð í útgáfu %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', 'Þú getur farið aftur á bloggið þitt með því að smella %shér%s');
+@define('MANAGE_USERS', 'Sýsla með notendur');
+@define('CREATE_NEW_USER', 'Búa til nýjan notanda');
+@define('CREATE_NOT_AUTHORIZED', 'Þú getur ekki breytt notendum á með sama stjórnstig og þú');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'Þú getur ekki búið til notendur með hærra stjórnstig en þú');
+@define('CREATED_USER', 'Nýr notandi %s hefur verið búinn til');
+@define('MODIFIED_USER', 'Eiginleikum notanda %s hefur verið breytt');
+@define('USER_LEVEL', 'Stjórnstig');
+@define('DELETE_USER', 'Þú ert að fara að eyða notanda #%d %s. Ertu viss? Þá verður ekki hægt að sýna færslur eftir hann á síðunni.');
+@define('DELETED_USER', 'Notanda #%d %s eytt.');
+@define('LIMIT_TO_NUMBER', 'Hversu margar færslur skal sýna?');
+@define('ENTRIES_PER_PAGE', 'færslur á síðu');
+@define('XML_IMAGE_TO_DISPLAY', 'XML takki');
+@define('XML_IMAGE_TO_DISPLAY_DESC','Hlekkir á XML strauma verða sýnd með þessari mynd. Skildu eftir tómt fyrir sjálfgefið gildi, eða sláðu inn \'none\' til að óvirkja.');
+
+@define('DIRECTORIES_AVAILABLE', 'Í listanum af mögulegum undirmöppum geturðu smellt á hvaða möppu sem er til að búa til nýja möppu innan hennar.');
+@define('ALL_DIRECTORIES', 'allar möppur');
+@define('MANAGE_DIRECTORIES', 'Sýsla með möppur');
+@define('DIRECTORY_CREATED', 'Mappan <strong>%s</strong> hefur verið búin til.');
+@define('PARENT_DIRECTORY', 'Yfirmappa');
+@define('CONFIRM_DELETE_DIRECTORY', 'Ertu viss um að þú viljir fjarlægja allt innihald möppunnar %s?');
+@define('ERROR_NO_DIRECTORY', 'Villa: Mappan %s er ekki til');
+@define('CHECKING_DIRECTORY', 'Athuga skrár í möppu %s');
+@define('DELETING_FILE', 'Eyði skrá %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', 'Gat ekki fjarlægt möppuna sem var ekki tóm. Athugaðu "þvinga eyðslu" hakið ef þú vilt fjarlægja þessar skrár líka, og reyndi svo aftur. Skrár sem enn eru til:');
+@define('DIRECTORY_DELETE_FAILED', 'Eyðsla möppu %s gekk ekki. Athugaðu réttindi eða skilaboð að ofan.');
+@define('DIRECTORY_DELETE_SUCCESS', 'Mappa Directory %s successfully deleted.');
+@define('SKIPPING_FILE_EXTENSION', 'Sleppi skrá: Vantar ending á %s.');
+@define('SKIPPING_FILE_UNREADABLE', 'Sleppi skrá: %s ekki læsileg.');
+@define('FOUND_FILE', 'Fann nýja/breytta skrá: %s.');
+@define('ALREADY_SUBCATEGORY', '%s er þegar undirmappa %s.');
+@define('PARENT_CATEGORY', 'Yfirflokkur');
+@define('IN_REPLY_TO', 'Sem svar við');
+@define('TOP_LEVEL', 'Toppstig');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s straumur');
+@define('PERMISSIONS', 'Réttindi');
+@define('SETTINGS_SAVED_AT', 'Nýju stillingarnar voru vistaðar klukkan %s');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', 'Stillingar gagnagrunns');
+@define('INSTALL_CAT_DB_DESC', 'Hér getur þú slegið inn allar upplýsingar um gagnagrunninn. Serendipity þarf þetta til að geta virkað');
+@define('INSTALL_DBTYPE', 'Tegund gagnagrunns');
+@define('INSTALL_DBTYPE_DESC', 'Tegund gagnagrunns');
+@define('INSTALL_DBHOST', 'Vélarnafn (host) gagnagrunns');
+@define('INSTALL_DBHOST_DESC', 'Vélarnafnið á gagnagrunninum þínum');
+@define('INSTALL_DBUSER', 'Notandi gagnagrunns');
+@define('INSTALL_DBUSER_DESC', 'Notandanafnið sem notað verður til að tengjast gagnagrunninum');
+@define('INSTALL_DBPASS', 'Lykilorð gagnagrunns');
+@define('INSTALL_DBPASS_DESC', 'Lykilorðið sem nota á með notandanafninu að ofan');
+@define('INSTALL_DBNAME', 'Nafn gagnagrunns');
+@define('INSTALL_DBNAME_DESC', 'Nafnið á gagnagrunninum þínum');
+@define('INSTALL_DBPREFIX', 'Fasti á undan færslum í gagnagrunni');
+@define('INSTALL_DBPREFIX_DESC', 'Fasti fyrir nöfn í töflum, t.d. serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', 'Slóðir');
+@define('INSTALL_CAT_PATHS_DESC', 'Nokkrar slóðir á mikilvægar möppur og skrár. Ekki gleyma skástrikinu á eftir möppunöfnum (mappa/)!');
+@define('INSTALL_FULLPATH', 'Full slóð');
+@define('INSTALL_FULLPATH_DESC', 'Full og algjör slóð á serendipity uppsetninguna þína');
+@define('INSTALL_UPLOADPATH', 'Vistunarslóð');
+@define('INSTALL_UPLOADPATH_DESC', 'All sem er vistað mun fara hingað, m.t.t. fulla slóð - vanalega \'uploads\'');
+@define('INSTALL_RELPATH', 'Hlutfallsleg slóð');
+@define('INSTALL_RELPATH_DESC', 'Slóðin á serendipity fyrir vafrann þinn, vanalega \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', 'Hlutfallsleg slóð á forsnið');
+@define('INSTALL_RELTEMPLPATH_DESC', 'Slóðin á möppuna sem inniheldur forsniðin þín - m.t.t. til \'hlutfallslega slóð\'');
+@define('INSTALL_RELUPLOADPATH', 'Hlutfallsleg vistunarslóð');
+@define('INSTALL_RELUPLOADPATH_DESC', 'Slóðin á vistaðar skrár fyrir vafra - m.t.t. \'hlutfallslegar slóðar\'');
+@define('INSTALL_URL', 'Slóð (URL) á bloggið þitt');
+@define('INSTALL_URL_DESC', 'Grunnslóðin (Base URL) á serendipity uppsetninguna þína');
+@define('INSTALL_INDEXFILE', 'Index skrá');
+@define('INSTALL_INDEXFILE_DESC', 'Nafnið á serendipity index skránni þinni');
+
+/* GENERAL SETTINGS */
+@define('INSTALL_CAT_SETTINGS', 'Almennar stillingar');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Veldu hvernig Serendipity hagar sér');
+@define('INSTALL_USERNAME', 'Notandanafn umsjónarmanns');
+@define('INSTALL_USERNAME_DESC', 'Notandanafn fyrir innskráningu umsjónarmanns');
+@define('INSTALL_PASSWORD', 'Lykilorð umsjónarmanns');
+@define('INSTALL_PASSWORD_DESC', 'Lykilorð fyrir innskráningu umsjónarmanns');
+@define('INSTALL_EMAIL', 'Netfang umsjónarmanns');
+@define('INSTALL_EMAIL_DESC', 'Netfang umsjónarmanns bloggsins');
+@define('INSTALL_SENDMAIL', 'Senda póst á umsjónarmann?');
+@define('INSTALL_SENDMAIL_DESC', 'Viltu fá sendan póst þegar athugasemdir eru sendar á færslurnar þínar?');
+@define('INSTALL_SUBSCRIBE', 'Leyfa notendum að gerast áskrifendur að færslum?');
+@define('INSTALL_SUBSCRIBE_DESC', 'Leyfir notendum að gerast áskrifendur að færslu, og fá þar með póst þegar nýjar athugasemdir eru gerðar á þá færslu');
+@define('INSTALL_BLOGNAME', 'Nafn bloggs');
+@define('INSTALL_BLOGNAME_DESC', 'Fyrirsögnin á blogginu þínu');
+@define('INSTALL_BLOGDESC', 'Lýsing bloggs');
+@define('INSTALL_BLOGDESC_DESC', 'Lýsing á blogginu þínu');
+@define('INSTALL_LANG', 'Tungumál');
+@define('INSTALL_LANG_DESC', 'Veldu tungumálið sem vera skal á blogginu þínu');
+
+/* APPEARANCE AND OPTIONS */
+@define('INSTALL_CAT_DISPLAY', 'Útlit og valmöguleikar');
+@define('INSTALL_CAT_DISPLAY_DESC', 'Stilltu tilfinningu og útlit Serendipity út á við');
+@define('INSTALL_WYSIWYG', 'Nota WYSIWYG ritilinn');
+@define('INSTALL_WYSIWYG_DESC', 'Viltu nota WYSIWYG ritilinn? (Virkar á IE5+, og að hluta til í Mozilla 1.3+)');
+@define('INSTALL_XHTML11', 'Neyða XHTML 1.1 fylgni');
+@define('INSTALL_XHTML11_DESC', 'Viltu neyða XHTML 1.1 fylgni (getur valdið vandræðum fyrir bak- eða framvinnslu fyrir eldri fjórðukynslóðar vafra)');
+@define('INSTALL_POPUP', 'Virkja notkun innskotsglugga');
+@define('INSTALL_POPUP_DESC', 'Viltu nota innskotsglugga (popup) fyrir athugasemdir, tilvísanir, o.fl.?');
+@define('INSTALL_EMBED', 'Er Serendipity innifalin?');
+@define('INSTALL_EMBED_DESC', 'Ef þú vilt innifela serendipity á annarri síðu, stilltu þá á "true" að henda öllum hausum, og prenta bara innihaldið. Þú getur nýtt indexFile valmöguleikann til að nota "wrapper class" þar sem þú setur venjulega vefsíðuhausa. Sjá README skrá fyrir meiri upplýsingar.');
+@define('INSTALL_TOP_AS_LINKS', 'Sýna topp útgönguleiðir/ávísara sem tengla?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"nei": Útgönguleiðir og ávísarar eru sýnd sem venjulegur texti til að verjast google rusli. "já": Útgönguleiðir og ávísarar eru sýndir sem tenglar. "sjálfgefið": Nota stillingu úr almennum stillingum (ráðlagt).');
+@define('INSTALL_BLOCKREF', 'Óleyfðir ávísarar');
+@define('INSTALL_BLOCKREF_DESC', 'Eru einhverjar sérstakar vélar sem þú vilt ekki láta sjást í ávísaralistanum? Aðskildu lista vélanafna með \';\' og hafðu í huga að vélarnafninu er sleppt með "substring matches"!');
+@define('INSTALL_REWRITE', 'Endurskrifun slóða (URL)');
+@define('INSTALL_REWRITE_DESC', 'Veldu hvaða reglur þú vilt nota til að endurskrifa slóðir (URL). Að hafa þetta virkt mun gera slóðir á bloggið þitt fallegar og einfaldar, og gera auðveldara fyrir vefköngulær (s.s. google) að gera efnisyfirlit á síðuna). Vefþjónninn þarf að styðja annaðhvort mod_rewrite eða "AllowOverride All" fyrir serendipity möppuna þína. Sjjálfgefna stillingin er að skynja það sjálfkrafa.');
+
+/* IMAGECONVERSION SETTINGS */
+@define('INSTALL_CAT_IMAGECONV', 'Myndbreytingastillingar:');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'Skráðu inn almennar upplýsingar um hvernig serendipity ætti að sjá um myndir');
+@define('INSTALL_IMAGEMAGICK', 'Nota Imagemagick');
+@define('INSTALL_IMAGEMAGICK_DESC', 'Ertu með imagemagick uppsett og vilt nota það til að breyta stærð mynda?');
+@define('INSTALL_IMAGEMAGICKPATH', 'Slóð á forritið');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'Full slóð og nafnið á imagemagick myndvinnsuforritinu');
+@define('INSTALL_THUMBSUFFIX', 'Viðskeyti sýnishorna');
+@define('INSTALL_THUMBSUFFIX_DESC', 'Sýnishorn verða nefnd eftir eftirfarandi forsniði: upprunalegt.[viðskeyti].end');
+@define('INSTALL_THUMBWIDTH', 'Stærð sýnishorna');
+@define('INSTALL_THUMBWIDTH_DESC', 'Staðlað hágildi breiddar framkallaðra sýnishorna');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', 'Persónulegu upplýsingar þínar');
+@define('USERCONF_CAT_PERSONAL_DESC', 'Breyta persónulegu upplýsingum þínum');
+@define('USERCONF_USERNAME', 'Notandanafn þitt');
+@define('USERCONF_USERNAME_DESC', 'Notandanafnið sem þú notar til að skrá þig inn á bloggið');
+@define('USERCONF_PASSWORD', 'Lykilorðið þitt');
+@define('USERCONF_PASSWORD_DESC', 'Lykilorðið sem þú notar til að skrá þigg inn á bloggið');
+@define('USERCONF_EMAIL', 'Netfangið þitt');
+@define('USERCONF_EMAIL_DESC', 'Persónulega netfangið þitt');
+@define('USERCONF_SENDCOMMENTS', 'Senda tilkynningar v/athugasemda?');
+@define('USERCONF_SENDCOMMENTS_DESC', 'Viltu fá sendan póst þegar athugasemdir eru sendar á færslurnar þínar?');
+@define('USERCONF_SENDTRACKBACKS', 'Senda tilkynningar v/tilvísana?');
+@define('USERCONF_SENDTRACKBACKS_DESC', 'Viltu fá sendan póst þegar tilvísanir eru gerðar á færslurnar þínar?');
+@define('USERCONF_ALLOWPUBLISH', 'Réttindi: Birta færslur?');
+@define('USERCONF_ALLOWPUBLISH_DESC', 'Má þessi notandi birta færslur?');
+@define('SUCCESS', 'Árangur');
+@define('POWERED_BY_SHOW_TEXT', 'Sýna "Serendipity" sem texa');
+@define('POWERED_BY_SHOW_TEXT_DESC', 'Mun birta "Serendipity Weblog" sem texta');
+@define('POWERED_BY_SHOW_IMAGE', 'Sýna "Serendipity" með merki');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Sýnir merki Serendipity');
+@define('PLUGIN_ITEM_DISPLAY', 'Hvar ætti merkið að vera sýnt?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'Opna bara færslu');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'Yfirsýn yfir bara blaðsíðu');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'Öllum stundum');
+@define('RSS_IMPORT_CATEGORY', 'Nota þennan flokk fyrir færslur sem passa ekki í neinn flokk');
+
+@define('COMMENTS_WILL_BE_MODERATED', 'Innsendar athugasemdir þurfa að fá samþykki áður en þær verða birtar.');
+@define('YOU_HAVE_THESE_OPTIONS', 'Þú hefur eftirfarandi valmöguleika fyrir hendi:');
+@define('THIS_COMMENT_NEEDS_REVIEW', 'Athuga: Þessi athugasemd þarf samþykki áður en hún verður birt');
+@define('DELETE_COMMENT', 'Eyða athugasemd');
+@define('APPROVE_COMMENT', 'Samþykkja athugasemd');
+@define('REQUIRES_REVIEW', 'Þarf yfirlesningu');
+@define('COMMENT_APPROVED', 'Athugasemd #%s hefur verið samþykkt');
+@define('COMMENT_DELETED', 'Athugasemd #%s hefur verið eytt');
+@define('COMMENTS_MODERATE', 'Athugasemdir & tilvísanir á þessa færslu þurfa samþykki');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'Athuga: Þessi tilvísun þarf samþykki áður en hún verður birt');
+@define('DELETE_TRACKBACK', 'Eyða tilvísun');
+@define('APPROVE_TRACKBACK', 'Samþykkja tilvísun');
+@define('TRACKBACK_APPROVED', 'Tilvísun #%s hefur verið samþykkt');
+@define('TRACKBACK_DELETED', 'Tilvísun #%s hefur verið eytt');
+@define('VIEW', 'Skoða');
+@define('COMMENT_ALREADY_APPROVED', 'Athugasemd #%s virðist þegar hafa verið samþykkt');
+@define('COMMENT_EDITED', 'Athugasemdinni hefur verið breytt');
+@define('HIDE', 'Fela');
+@define('VIEW_EXTENDED_ENTRY', 'Halda áfram að lesa "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'Það er ekki ætlast til þess að smellt sé á þennan hlekk. Hann inniheldur tilvísunar URIs lóðina fyrir þessa færslu. Þú getur notað þetta URI til að senda ping- & tilvísanir frá eigin bloggi á þessa færslu. Til að afrita þennan hlekk, hægrismelltu þá á hlekkinn og veldu "Copy Shortcut" í Internet Explorer, og "Copy Link Location" í Mozilla.');
+@define('PLUGIN_SUPERUSER_HTTPS', 'Nota https fyrir innskráningu');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'Lætur innskráningarhlekkinn vísa á https slóð. Vefþjónninn þinn þarf að styðja þetta!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'Láta vera hægt að smellta á utanaðkomandi hlekki?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"nei": Óskoðaðir hlekkir út á við (Topp útgönguleiðir, ávísarar, athugasemdir notenda) eru sýndar/ekki sýndar sem venjulegur texti þegar á við til að koma í veg fyrir google ruslsendingar (ráðlagt). "já": Óskoðaðir hlekkir út á við eru sýndir sem hlekkir. Getur verið breytt með æðra valdi innan hliðarramma stillingum!');
+@define('PAGE_BROWSE_COMMENTS', 'Blaðsíða %s af %s, með %s athugasemdir');
+@define('FILTERS', 'Síur');
+@define('FIND_ENTRIES', 'Finna færslur');
+@define('FIND_COMMENTS', 'Finna athugasemdir');
+@define('FIND_MEDIA', 'Finna gögn');
+@define('FILTER_DIRECTORY', 'Möppum');
+@define('SORT_BY', 'Raða eftir');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'Engin tilvísun send: Náði ekki sambandi við %s á porti %d');
+@define('MEDIA', 'Gögn');
+@define('MEDIA_LIBRARY', 'Gagnasafni');
+@define('ADD_MEDIA', 'Bæta við gögnum');
+@define('ENTER_MEDIA_URL', 'Sláðu inn slóð skráarinnar til að sækja:');
+@define('ENTER_MEDIA_UPLOAD', 'Veldu skrána sem þú vilt vista:');
+@define('SAVE_FILE_AS', 'Vista skrá sem:');
+@define('STORE_IN_DIRECTORY', 'Vista innan eftirfarandi möppu: ');
+@define('ADD_MEDIA_BLAHBLAH', '<b>Bæta við skrá í gagnageymsluna þína:</b><p>Hér geturðu vistað gagnaskrár, eða sagt mér að sækja þær einhversstaðar annarsstaðar frá af vefnum! Ef þú ert ekki með mynd við hæfi, <a href="http://images.google.com" target="_blank">leitaðu að myndum á google</a> sem á við það sem þú ert að hugsa. Niðurstöðurnar eru oft nytsamlegar og fyndnar :)<p><b>Veldu leið:</b><br>');
+@define('MEDIA_RENAME', 'Endurnefna skrána');
+@define('IMAGE_RESIZE', 'Breyta stærð myndarinnar');
+@define('MEDIA_DELETE', 'Eyða þessari skrá');
+@define('FILES_PER_PAGE', 'Skrár á síðu');
+@define('CLICK_FILE_TO_INSERT', 'Smelltu á skrána sem þú vilt bæta við:');
+@define('SELECT_FILE', 'Veldu skrána til að bæta við');
+@define('MEDIA_FULLSIZE', 'Fylla skjáinn');
+@define('CALENDAR_BOW_DESC', 'Dagur vikunnar sem er tekinn sem byrjunardagur vikunnar. Sjálfgefið gildi er mánudagur');
+@define('SUPERUSER', 'Umsjón vefkerfis');
+@define('ALLOWS_YOU_BLAHBLAH', 'Gerir hlekk í hliðarramma bloggkerfisins sem vísar á umsjónarkerfið');
+@define('CALENDAR', 'Dagatal');
+@define('SUPERUSER_OPEN_ADMIN', 'Opna umsjónarkerfi');
+@define('SUPERUSER_OPEN_LOGIN', 'Opna innskráningarsíðu');
+@define('INVERT_SELECTIONS', 'Skipta út völdu fyrir óvalið');
+@define('COMMENTS_DELETE_CONFIRM', 'Ertu viss um að þú viljir eyða völdum athugasemdum?');
+@define('COMMENT_DELETE_CONFIRM', 'Ertu viss um að þú viljir eyða athugasemd #%d, skrifaðri af %s?');
+@define('DELETE_SELECTED_COMMENTS', 'Eyða völdum athugasemdum');
+@define('VIEW_COMMENT', 'Skoða athugasemd');
+@define('VIEW_ENTRY', 'Skoða færslu');
+@define('DELETE_FILE_FAIL' , 'Gat ekki eytt skrá <b>%s</b>');
+@define('DELETE_THUMBNAIL', 'Eyddi sýnishorni myndar nefnt <b>%s</b>');
+@define('DELETE_FILE', 'Eyddi skrá nenfdri <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', 'Þú ert að far aað eyða <b>%s</b><br />Ef þú ert að nota þessa skrá í einhverri af færslunum þínum, mun það valda dauðum hlekkjum eða óvirkum myndum<br />Ertu viss um að þú viljir halda áfram?<br /><br />');
+@define('TRACKBACK_SENDING', 'Sendi tilvísun á URI slóð %s...');
+@define('TRACKBACK_SENT', 'Tilvísun tókst');
+@define('TRACKBACK_FAILED', 'Tilvísun tókst ekki: %s');
+@define('TRACKBACK_NOT_FOUND', 'Engin URI-tilvísunarslóð fannst.');
+@define('TRACKBACK_URI_MISMATCH', 'URI slóðin sem ég fann út passar ekki við URI slóðina sem við ætluðum að nota.');
+@define('TRACKBACK_CHECKING', 'Athuga <u>%s</u> fyrir mögulegar tilvísanir...');
+@define('TRACKBACK_NO_DATA', 'Viðfang innihélt engin gögn');
+@define('TRACKBACK_SIZE', 'ViðfangsURI-slóð fór fram úr leyfðri stærð, %s bætum.');
+@define('COMMENTS_VIEWMODE_THREADED', 'Þræddan ham');
+@define('COMMENTS_VIEWMODE_LINEAR', 'Flatan ham');
+@define('DISPLAY_COMMENTS_AS', 'Sýna athugasemdir sem');
+@define('COMMENTS_FILTER_SHOW', 'Sýna');
+@define('COMMENTS_FILTER_ALL', 'Allt');
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'Einungis samþykktar');
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'Bíða eftir samþykki');
+@define('RSS_IMPORT_BODYONLY', 'Setja allan innfluttan texta í "body" hlutann og ekki skipta í "aukainnihald" hlutann.');
+@define('SYNDICATION_PLUGIN_FULLFEED', 'Show full articles with extended body inside RSS feed');
+@define('WEEK', 'Vika');
+@define('WEEKS', 'Vikur');
+@define('MONTHS', 'Mánuðir');
+@define('DAYS', 'Dagar');
+@define('ARCHIVE_FREQUENCY', 'Tíðni hlutar í dagatali');
+@define('ARCHIVE_FREQUENCY_DESC', 'Bilið á milli sem nota á í dagatali á milli tveggja hluta á listanum');
+@define('ARCHIVE_COUNT', 'Fjöldi hluta á listanum');
+@define('ARCHIVE_COUNT_DESC', 'Heildarfjöldi mánaða, vika eða daga til að birta');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'Að neðan er listi uppsettra viðbóta');
+@define('SIDEBAR_PLUGIN', 'hliðarrammaviðbót');
+@define('EVENT_PLUGIN', 'atburðaviðbót');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'Smelltu hér til að setja inn nýja %s %s');
+@define('VERSION', 'útgáfa');
+@define('INSTALL', 'Setja upp');
+@define('ALREADY_INSTALLED', 'Þegar uppsett');
+@define('SELECT_A_PLUGIN_TO_ADD', 'Veldu viðbót til að setja inn');
+@define('INSTALL_OFFSET', 'Frávik frá þjónstíma');
+@define('STICKY_POSTINGS', 'Þrautseigar innsetningar');
+@define('INSTALL_FETCHLIMIT', 'Færslur sem sýna skal á forsíðu');
+@define('INSTALL_FETCHLIMIT_DESC', 'Fjöldi færsla sem sýna skal á hverri síðu');
+@define('IMPORT_ENTRIES', 'Flytja inn gögn');
+@define('EXPORT_ENTRIES', 'Flytja út gögn');
+@define('IMPORT_WELCOME', 'Velkomin(n) í innflutningstól Serendipity');
+@define('IMPORT_WHAT_CAN', 'Hér getur þú flutt inn færslur frá öðrum bloggkerfum');
+@define('IMPORT_SELECT', 'Veldu hugbúnaðinn sem þú vilt flytja inn frá');
+@define('IMPORT_PLEASE_ENTER', 'Vinsamlegast sláðu inn gögnin eins og er farið fram á að neðan');
+@define('IMPORT_NOW', 'Flytja inn núna!');
+@define('IMPORT_STARTING', 'Hef innflutningsferlið...');
+@define('IMPORT_FAILED', 'Innflutningur mistókst');
+@define('IMPORT_DONE', 'Innflutningi lokið');
+@define('IMPORT_WEBLOG_APP', 'Bloggkerfi');
+@define('IMPORT_NOTES', 'Athuga:');
+@define('EXPORT_FEED', 'Flytja út allan RSS straum');
+@define('STATUS', 'Staða eftir innflutning');
+@define('IMPORT_GENERIC_RSS', 'Almennur RSS innflutningur');
+@define('ACTIVATE_AUTODISCOVERY', 'Senda tilvísanir á hlekki sem fyrirfinnast í færslunni');
+@define('WELCOME_TO_ADMIN', 'Velkomin(n) í stjórnborð Serendipity.');
+@define('PLEASE_ENTER_CREDENTIALS', 'Vinsamlegast auðkenndu þig.');
+@define('ADMIN_FOOTER_POWERED_BY', 'Knúið af Serendipity %s og PHP %s');
+@define('INSTALL_USEGZIP', 'Nota gzip til að þjappa síðum');
+@define('INSTALL_USEGZIP_DESC', 'Til að flýta afhendingu síða getum við þjappað gögnunum og sent gestunum, ef vafrinn hans styður það. Við mælum með þessu');
+@define('INSTALL_SHOWFUTURE', 'Sýna framtíðarfærslur');
+@define('INSTALL_SHOWFUTURE_DESC', 'Ef virkt, mun þetta sýna allar færslur sem þú sendir inn í framtíðinni á bloggið. Sjálfgefið er að fela þær þar til að birtingardagsetningin er komin.');
+@define('INSTALL_DBPERSISTENT', 'Viðhalda tengingum?');
+@define('INSTALL_DBPERSISTENT_DESC', 'Virkja notkun langlífra tenginga í gagnagrunn, lesa meira <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">hér</a>. Að jafnaði mælum við ekki með þessu');
+@define('NO_IMAGES_FOUND', 'Engar myndir fundust');
+@define('PERSONAL_SETTINGS', 'Persónulegar stillingar');
+@define('REFERER', 'Ávísari');
+@define('NOT_FOUND', 'Fannst ekki');
+@define('WRITABLE', 'Skrifanlegt');
+@define('NOT_WRITABLE', 'Ekki skrifanlegt');
+@define('PROBLEM_DIAGNOSTIC', 'Vegna vandkvæða í greiningu geturðu ekki haldið áfram fyrr en ofangreindar villur eru lagfærðar');
+@define('SELECT_INSTALLATION_TYPE', 'Veldu hvaða tegund uppsetningar þú vilt nota');
+@define('WELCOME_TO_INSTALLATION', 'Velkomin(n) í uppsetningu Serendipity');
+@define('FIRST_WE_TAKE_A_LOOK', 'Fyrst munum við líta á núverandi uppsetningu og finna út úr hvort einhver samhæfingarvandamál séu til staðar');
+@define('ERRORS_ARE_DISPLAYED_IN', 'Villur eru birtar í %s, meðmæli í %s og árangur í %s');
+@define('RED', 'rauðu');
+@define('YELLOW', 'gulu');
+@define('GREEN', 'grænu');
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s for-uppsetningarskýrsla');
+@define('RECOMMENDED', 'Mælt með');
+@define('ACTUAL', 'Raungildi');
+@define('PHPINI_CONFIGURATION', 'php.ini stillingar');
+@define('PHP_INSTALLATION', 'PHP uppsetning');
+@define('THEY_DO', 'þeir/þau gera það');
+@define('THEY_DONT', 'þeir/þau gera það ekki');
+@define('SIMPLE_INSTALLATION', 'Einföld uppsetning');
+@define('EXPERT_INSTALLATION', 'Flókin uppsetning');
+@define('COMPLETE_INSTALLATION', 'Ljúka uppsetningu');
+@define('WONT_INSTALL_DB_AGAIN', 'mun ekki setja upp gagnagrunnin aftur');
+@define('CHECK_DATABASE_EXISTS', 'Er að athuga hvort gagnagrunnur sé þegar til.  Ef þú sérð villu í uppflettingu á gagnagrunni, hundsaðu hana...');
+@define('CREATING_PRIMARY_AUTHOR', 'Bý til aðalhöfund \'%s\'');
+@define('SETTING_DEFAULT_TEMPLATE', 'Set upp sjálfgefið forsnið');
+@define('INSTALLING_DEFAULT_PLUGINS', 'Set upp sjálfgefnar viðbætur');
+@define('SERENDIPITY_INSTALLED', '%sUppsetning Serendipity tókst á kerfinu þínu.%s Vinsamlegast mundu lykilorðið þitt: "%s", og notandanafnið er "%s".%sÞú getur fundið nýja PHP bloggið þitt <a href="%s">hér</a>');
+@define('VISIT_BLOG_HERE', 'Heimsæktu nýja bloggið þitt hér');
+@define('THANK_YOU_FOR_CHOOSING', 'Takk fyrir að velja Serendipity');
+@define('ERROR_DETECTED_IN_INSTALL', 'Villa fannst í uppsetningunni');
+@define('OPERATING_SYSTEM', 'Stýrikerfi');
+@define('WEBSERVER_SAPI', 'SAPI vefþjóns');
+@define('TEMPLATE_SET', '\'%s\' hefur verið sett sem virka forsniðið þitt');
+@define('SEARCH_ERROR', 'Leitarfítusinn virkaði ekki eins og við mátti búast. Tilkynning sem berast skal umsjónarmanni bloggsins Þetta getur gerst vegna index lykla í gagnagrunninum sem vantar. Á MySQL kerfum verður gagnagrunnsnotandinn að geta gert eftirfarandi eftirspurn: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> Nákvæm villa sem gagnagrunnurinn skilaði var: <pre>%s</pre>');
+@define('EDIT_THIS_CAT', 'Breyti "%s - %s"');
+@define('CATEGORY_REMAINING', 'Eyða þessum flokki og færa færslur hans í þennan flokk: %s');
+@define('CATEGORY_INDEX', 'Fyrir neðan er listi af flokkum sem þú getur notað í færslurnar þínar');
+@define('NO_CATEGORIES', 'Engir flokkar');
+@define('RESET_DATE', 'Endurstilla dagsetningu');
+@define('RESET_DATE_DESC', 'Smelltu hér til að endurstilla dagsetningu í núverandi tíma');
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Réttindi er hægt að stilla með því að keyra skeljarskipunina `<em>%s</em>` á möppuna þar sem þetta mistókst, eða með því að breyta þessu í FTP forriti');
+@define('WARNING_TEMPLATE_DEPRECATED', 'Varúð: Forsniðið sem þú ert með valið er að nota úreldar forsniðsaðferðir. Þú ættir að uppfæra ef þú hefur tök á því');
+@define('ENTRY_PUBLISHED_FUTURE', 'Þessi færsla hefur ekki enn verið birt.');
+@define('ENTRIES_BY', 'Færslur eftir %s');
+@define('PREVIOUS', 'Fyrri');
+@define('NEXT', 'Næsta');
+@define('APPROVE', 'Samþykkja');
+@define('DO_MARKUP_DESCRIPTION', 'Virkja breytinga rá texta út frá ákveðnum táknum (broskarlar, styttri leiðir í gegnum *, /, _, ...). Óvirking á þessu mun varðveita allan HTML-kóða í textanum. Sjálfgefið gildi er "Já".');
+@define('CATEGORY_ALREADY_EXIST', 'Flokkur með nafninu "s" er þegar til');
+@define('ERROR_FILE_FORBIDDEN', 'Þú mátt ekki vista skrár með virkt innihald');
+@define('ADMIN', 'Stjórn:');
+@define('ADMIN_FRONTPAGE', 'Forsíða');
+@define('QUOTE', 'Tilvitnun');
+@define('IFRAME_SAVE', 'Serendipity er nú að vista færsluna þína, búa til tilvísanir og gera mögulegar XML-RPC aðgerðir. Þetta gæti tekið smá stund...');
+@define('IFRAME_SAVE_DRAFT', 'Drög að færslu hafa verið vistuð');
+@define('IFRAME_PREVIEW', 'Serendipity býr nú til sýnishorn af færslunni þinni...');
+@define('IFRAME_WARNING', 'Vafrinn þinn skilur ekki iframes hugtakið. Vinsamlegast opnaði serendipity_config.inc.php skrána þína og stilltu $serendipity[\'use_iframe\'] breytinu á FALSE.');
+@define('NONE', 'engin(n)');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Sjálfgefnar stillingar fyrir nýjar færslur');
+@define('UPGRADE', 'Uppfæra');
+@define('UPGRADE_TO_VERSION', 'Uppfæra í útgáfu %s');
+@define('DELETE_DIRECTORY', 'Eyða þessari möppu');
+@define('DELETE_DIRECTORY_DESC', 'Þú ert að fara að eyða innihaldi möppu sem er með margmiðlunargögn, sem eru mögulega í notkun í sumum færsla þinna.');
+@define('FORCE_DELETE', 'Neyða eyðslu skráa sem eru ekki inni í miðlunargagnagrunninum');
+@define('CREATE_DIRECTORY', 'Búa til möppu');
+@define('CREATE_NEW_DIRECTORY', 'Búa til nýja möppu');
+@define('CREATE_DIRECTORY_DESC', 'Hér geturðu búið til nýja möppu til að setja gögn. Veldu nafn á nýju möppuna þína og veldu möppu til að setja hana í ef við á.');
+@define('BASE_DIRECTORY', 'Grunnmappa');
+@define('USERLEVEL_EDITOR_DESC', 'Venjulegur notandi');
+@define('USERLEVEL_CHIEF_DESC', 'Stjórnandi');
+@define('USERLEVEL_ADMIN_DESC', 'Umsjónarmaður');
+@define('USERCONF_USERLEVEL', 'Réttindastig');
+@define('USERCONF_USERLEVEL_DESC', 'Réttindastig. Ætti að vera eitt af eftirfarandi: [USERLEVEL_ADMIN] - Umsjónarmaður, [USERLEVEL_CHIEF] - Stjórnandi, [USERLEVEL_EDITOR] - Venjulegur notandi.');
+@define('USER_SELF_INFO', 'skráð(ur) inn sem %s, með stjórnstig %s');
+@define('ADMIN_ENTRIES', 'Færslur');
+@define('RECHECK_INSTALLATION', 'Skoða uppsetningu aftur');
+@define('IMAGICK_EXEC_ERROR', 'Gat ekki framkvæmt: "%s", villa: %s, return var: %d');
+@define('INSTALL_OFFSET_DESC', 'Sláðu inn fjölda klukkustunda sem er á milli vefþjónsins þíns og tímasvæðisins sem þú vilt hafa (núverandi: %clock%)');
+@define('UNMET_REQUIREMENTS', 'Óuppfylltar þarfir: %s');
+@define('CHARSET', 'Stafasett (charset)');
+@define('AUTOLANG', 'Nota tungumálastillingar vafra gestsins sem sjálfgefið tungumál');
+@define('AUTOLANG_DESC', 'Ef þetta er virkt mun serendipity nota tungumálið sem stillt er á í vafra viðkomandi gests fyrir viðmótið (og færslur ef við á).');
+@define('INSTALL_AUTODETECT_URL', 'Skynja sjálfvirkt HTTP-Host');
+@define('INSTALL_AUTODETECT_URL_DESC', 'Ef þetta er stillt á "true" mun Serendipity sjá til þess að HTTP Host nafnið sem var notað sé notað sem BaseURL stilling. Að virkja þetta mun gera þér kleift að nota mörg mismunandi vélarnöfn fyrir Serendipity bloggið þitt, og nota það vélarnafn fyrir alla tengla fyrir alla tengla eftir það sem eru notaðir til að vafra um bloggið þitt.');
+@define('CONVERT_HTMLENTITIES', 'Reyna að Try to breyta HTML færslum sjálfkrafa?');
+@define('EMPTY_SETTING', 'Þú skilgreindir ekki löglegt gildi fyrir "%s"!');
+@define('USERCONF_REALNAME', 'Nafn');
+@define('USERCONF_REALNAME_DESC', 'Fullt nafn höfundar. Þetta er nafnið eins og lesendur sjá það');
+@define('HOTLINK_DONE', 'Skrá hotlinkuð.<br />Búin.');
+@define('ENTER_MEDIA_URL_METHOD', 'Sóknaraðferð:');
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Athuga: Ef þú vilt hotlinka á þjón, gakktu úr skuggu um að þú hafir réttindi á viðkomandi vefsíðu, eða að þú eigir vefsíðuna. Hotlink leyfir þér að nota myndir sem eru ekki á þínum vefþjóni án þess að vista þær á þjóninum.');
+@define('MEDIA_HOTLINKED', 'hotlinkað');
+@define('FETCH_METHOD_IMAGE', 'Sækja mynd á þjóninn þinn');
+@define('FETCH_METHOD_HOTLINK', 'Hotlinka á þjón');
+@define('DELETE_HOTLINK_FILE', 'Eyddi hotlinkaðri skrá, nefnd <b>%s</b>');
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Sýna netföng?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_it.inc.php b/lang/serendipity_lang_it.inc.php
new file mode 100644 (file)
index 0000000..1a1fc86
--- /dev/null
@@ -0,0 +1,670 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Translation (c) by Alessandro Pellizzari <alex@amiran.it>
+
+@define('LANG_CHARSET', 'ISO-8859-1');
+@define('DATE_LOCALES', 'italiano, it, it_IT');
+@define('DATE_FORMAT_ENTRY', '%A, %B %e. %Y');
+@define('DATE_FORMAT_SHORT', '%d-%m-%Y %H:%M');
+@define('WYSIWYG_LANG', 'it');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', ',');
+@define('NUMBER_FORMAT_THOUSANDS', '.');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Amministrazione di Serendipity');
+@define('HAVE_TO_BE_LOGGED_ON', 'Devi fare login per vedere questa pagina');
+@define('WRONG_USERNAME_OR_PASSWORD', 'Sembra che tu abbia inserito nome utente o password non validi');
+@define('APPEARANCE', 'Aspetto');
+@define('MANAGE_STYLES', 'Gestione stili');
+@define('CONFIGURE_PLUGINS', 'Configurazione Plugin');
+@define('CONFIGURATION', 'Configurazione');
+@define('BACK_TO_BLOG', 'Torna al Weblog');
+@define('LOGIN', 'Login');
+@define('LOGOUT', 'Logout');
+@define('LOGGEDOUT', 'Scollegato.');
+@define('CREATE', 'Crea');
+@define('SAVE', 'Salva');
+@define('NAME', 'Nome');
+@define('CREATE_NEW_CAT', 'Crea una Nuova Categoria');
+@define('I_WANT_THUMB', 'Voglio usare la miniatura nella mia notizia.');
+@define('I_WANT_BIG_IMAGE', 'Voglio usare l\'immagine grande nella mia notizia.');
+@define('I_WANT_NO_LINK', ' Voglio mostrarla come immagine');
+@define('I_WANT_IT_TO_LINK', 'Voglio mostrarla come link a questo URL:');
+@define('BACK', 'Indietro');
+@define('FORWARD', 'Avanti');
+@define('ANONYMOUS', 'Anonimo');
+@define('NEW_TRACKBACK_TO', 'Nuovo trackback verso');
+@define('NEW_COMMENT_TO', 'Nuovo commento mandato a');
+@define('RECENT', 'Recente...');
+@define('OLDER', 'Più vecchio...');
+@define('DONE', 'Fatto');
+@define('WELCOME_BACK', 'bentornato,');
+@define('TITLE', 'Titolo');
+@define('DESCRIPTION', 'Descrizione');
+@define('PLACEMENT', 'Posizionamento');
+@define('DELETE', 'Cancella');
+@define('SAVE', 'Salva');
+@define('SELECT_A_PLUGIN_TO_ADD', 'Scegli il plugin da aggiungere');
+@define('UP', 'SU');
+@define('DOWN', 'GIU`');
+@define('ENTRIES', 'notizie');
+@define('NEW_ENTRY', 'Nuova notizia');
+@define('EDIT_ENTRIES', 'Modifica notizie');
+@define('CATEGORIES', 'Categorie');
+@define('WARNING_THIS_BLAHBLAH', "ATTENZIONE:\\nPotrebbe essere necessario molto tempo se molte immagini non hanno le miniature.");
+@define('CREATE_THUMBS', 'Ricostruisci miniature');
+@define('MANAGE_IMAGES', 'Gestione immagini');
+@define('NAME', 'Nome');
+@define('EMAIL', 'E-mail');
+@define('HOMEPAGE', 'Homepage');
+@define('COMMENT', 'Commento');
+@define('REMEMBER_INFO', 'Memorizza le Informazioni? ');
+@define('SUBMIT_COMMENT', 'Manda Comment');
+@define('NO_ENTRIES_TO_PRINT', 'Nessuna notizia da stampare');
+@define('COMMENTS', 'Commenti');
+@define('ADD_COMMENT', 'Aggiungi Commento');
+@define('NO_COMMENTS', 'Nessun commento');
+@define('POSTED_BY', 'Scritto da');
+@define('ON', 'on');
+@define('A_NEW_COMMENT_BLAHBLAH', 'Un nuovo commento è stato mandato al tuo blog "%s", nella notizia intitolata "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'Un nuovo trackback è stato effettuato alla tua notizia intitolata "%s".');
+@define('NO_CATEGORY', 'Nessuna Categoria');
+@define('ENTRY_BODY', 'Corpo della Notizia');
+@define('EXTENDED_BODY', 'Corpo Esteso');
+@define('CATEGORY', 'Categoria');
+@define('EDIT', 'Modifica');
+@define('NO_ENTRIES_BLAHBLAH', 'Nessuna notizia trovata per la ricerca %s' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'La tua ricerca di %s ha fornito %s risultati:');
+@define('SEARCH_TOO_SHORT', 'La parola per la ricerca deve essere di almeno 3 caratteri');
+@define('IMAGE', 'Immagine');
+@define('ERROR_FILE_NOT_EXISTS', 'Errore: Il vecchio nome del file non esiste!');
+@define('ERROR_FILE_EXISTS', 'Errore: Nuovo nome file già usato, scegline un altro!');
+@define('ERROR_SOMETHING', 'Errore: Qualcosa non va.');
+@define('ADDING_IMAGE', 'Aggiunta image...');
+@define('THUMB_CREATED_DONE', 'Miniatura creata.<br>Fatto.');
+@define('ERROR_FILE_EXISTS_ALREADY', 'Errore: Il file esiste già sulla tua macchina!');
+@define('ERROR_UNKNOWN_NOUPLOAD', 'Errore sconosciuto, file non inviato. Forse le dimensioni sono superiori al massimo consentito dall\'installazione del server. Chiedi al tuo provider o modifica php.ini per consentire upload più corposi.');
+@define('GO', 'Vai!');
+@define('NEWSIZE', 'Nuove dimensioni: ');
+@define('RESIZE_BLAHBLAH', '<b>Ridimensiona %s</b><p>');
+@define('ORIGINAL_SIZE', 'Dimensione originale: <i>%sx%s</i> pixel');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>Qui puoi definire le nuove dimensioni dell\'immagine. Se vuoi mantenere le proporzioni inserisci un solo valore e premi TAB, calcolerò automaticamente le nuove dimensioni in modo da non modificare le proporzioni:');
+@define('QUICKJUMP_CALENDAR', 'Calendario di accesso veloce');
+@define('QUICKSEARCH', 'Ricerca veloce');
+@define('SEARCH_FOR_ENTRY', 'Cerca una notizia');
+@define('ARCHIVES', 'Archivi');
+@define('BROWSE_ARCHIVES', 'Sfoglia gli archivi per mese');
+@define('TOP_REFERRER', 'Top Referrers');
+@define('SHOWS_TOP_SITES', 'Mostra i maggiori siti che linkano il tuo blog');
+@define('TOP_EXITS', 'Top Exits');
+@define('SHOWS_TOP_EXIT', 'Mostra dove vanno i tuoi lettori quando escono dal blog');
+@define('SYNDICATION', 'Diffusione');
+@define('SHOWS_RSS_BLAHBLAH', 'Mostra i link di diffusione RSS');
+@define('ADVERTISES_BLAHBLAH', 'Pubblicizza le origini del tuo blog');
+@define('HTML_NUGGET', 'Pillola di HTML');
+@define('HOLDS_A_BLAHBLAH', 'Infila un pezzo di HTML nella tua barra laterale');
+@define('TITLE_FOR_NUGGET', 'Titolo della pillola');
+@define('THE_NUGGET', 'La pillola di HTML!');
+@define('SYNDICATE_THIS_BLOG', 'Diffondi Questo Blog');
+@define('YOU_CHOSE', 'Hai scelto %s');
+@define('IMAGE_SIZE', 'Dimensioni dell\'immagine');
+@define('IMAGE_AS_A_LINK', 'Inserimento immagine');
+@define('POWERED_BY', 'Powered by');
+@define('TRACKBACKS', 'Trackbacks');
+@define('TRACKBACK', 'Trackback');
+@define('NO_TRACKBACKS', 'Nessun Trackbacks');
+@define('TOPICS_OF', 'Argomenti di');
+@define('VIEW_FULL', 'vedi tutto');
+@define('VIEW_TOPICS', 'vedi argomenti');
+@define('AT', 'at');
+@define('SET_AS_TEMPLATE', 'Imposta come modello');
+@define('IN', 'in');
+@define('EXCERPT', 'Estratto');
+@define('TRACKED', 'Tracciato');
+@define('LINK_TO_ENTRY', 'Link alla notizia');
+@define('LINK_TO_REMOTE_ENTRY', 'Link alla notizia in remoto');
+@define('IP_ADDRESS', 'Indirizzo IP');
+@define('USER', 'Utente');
+@define('THUMBNAIL_USING_OWN', 'Uso %s come miniatura stessa perché è già abbastanza piccola.');
+@define('THUMBNAIL_FAILED_COPY', 'Volevo usare %s come miniatura di sé stessa ma non riesco a copiarla!');
+@define('AUTHOR', 'Autore');
+@define('LAST_UPDATED', 'Ultimo aggiornamento');
+@define('TRACKBACK_SPECIFIC', 'URI specifico di Trackback per questa notizia');
+@define('DIRECT_LINK', 'Link diretto a questa notizia');
+@define('COMMENT_ADDED', 'Il tuo commento è stato inviato con successo. ');
+@define('COMMENT_ADDED_CLICK', 'Clicka %squi per tornare%s ai commenti, e %squi per chiudere%s questa finestra.');
+@define('COMMENT_NOT_ADDED', 'Il tuo commento non può essere aggiunto, perché i commenti per questa notizia sono stati disattivati. ');
+@define('COMMENT_NOT_ADDED_CLICK', 'Clicka %squi per tornare%s ai commenti, e %squi per chiudere%s questa finestra.');
+@define('COMMENTS_DISABLE', 'Non consentire commenti a questa notizia');
+@define('COMMENTS_ENABLE', 'Consenti commenti a questa notizia');
+@define('COMMENTS_CLOSED', 'L\'autore non consente commenti a questa notizia');
+@define('EMPTY_COMMENT', 'Il tuo commento non conteneva nulla, per favore %storna indietro%s e riprova');
+@define('ENTRIES_FOR', 'Notizie per %s');
+@define('DOCUMENT_NOT_FOUND', 'Il documento %s non è stato trovato.');
+@define('USERNAME', 'Nome utente');
+@define('PASSWORD', 'Password');
+@define('AUTOMATIC_LOGIN', 'Salva informazioni');
+@define('SERENDIPITY_INSTALLATION', 'Installazione di Serendipity');
+@define('LEFT', 'sinistra');
+@define('RIGHT', 'destra');
+@define('HIDDEN', 'nascosto');
+@define('REMOVE_TICKED_PLUGINS', 'Rimuovi i plugin selezionati');
+@define('SAVE_CHANGES_TO_LAYOUT', 'Salva i cambiamenti al layout');
+@define('COMMENTS_FROM', 'Commenti da');
+@define('ERROR', 'Errore');
+@define('ENTRY_SAVED', 'La tua notizia è stata salvata');
+@define('DELETE_SURE', 'Sei sicuro di voler cancellare #%s in modo permanente?');
+@define('NOT_REALLY', 'Non proprio...');
+@define('DUMP_IT', 'Cestinalo!');
+@define('RIP_ENTRY', 'Addio notizia #%s');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Categoria #%s cancellata. Vecchi articoli spostati nella categoria #%s');
+@define('CATEGORY_DELETED', 'Categoria #%s cancellata.');
+@define('INVALID_CATEGORY', 'Nessuna categoria selezionata per la cancellazione');
+@define('CATEGORY_SAVED', 'Categoria salvata');
+@define('SELECT_TEMPLATE', 'Seleziona il modello che vuoi usare per il tuo blog');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'Notizie non inserite!');
+@define('YES', 'Sì');
+@define('NO', 'No');
+@define('USE_DEFAULT', 'Default');
+@define('CHECK_N_SAVE', 'Controlla &amp; salva');
+@define('DIRECTORY_WRITE_ERROR', 'Impossibile scrivere nella directory %s. Controllare i permessi.');
+@define('DIRECTORY_CREATE_ERROR', 'La directory %s non esiste e non può essere creata. Per favore crearla manualmente');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; esegui <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', 'Impossibile eseguire il binario %s');
+@define('FILE_WRITE_ERROR', 'Impossibile scrivere sul file %s.');
+@define('FILE_CREATE_YOURSELF', 'Per favore creare il file manualmente o controllare i permessi');
+@define('COPY_CODE_BELOW', '<br />* Copiare il codice qui sotto e metterlo in %s nella vostra cartella %s :<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Cambiare www con l\'utente con cui gira apache (es. nobody).');
+@define('BROWSER_RELOAD', 'Una volta eseguito, premete il bottone "Ricarica" del vostro browser.');
+@define('DIAGNOSTIC_ERROR', 'Sono stati rilevati degli errori durante il controllo dei dati inseriti:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity non è ancora installato. per favore <a href="%s">installatelo</a> ora.');
+@define('INCLUDE_ERROR', 'errore di serendipity: impossibile includere %s - terminato.');
+@define('DATABASE_ERROR', 'errore di serendipity: impossibile connettersi al database - terminato.');
+@define('CREATE_DATABASE', 'Creazione del database di default...');
+@define('ATTEMPT_WRITE_FILE', 'Tentativo di scrittura sul file %s...');
+@define('WRITTEN_N_SAVED', 'Configuratione scritta e salvata');
+@define('IMAGE_ALIGNMENT', 'Allineamento immagine');
+@define('ENTER_NEW_NAME', 'Inserisci il nuovo nome per: ');
+@define('RESIZING', 'Ridimensionamento');
+@define('RESIZE_DONE', 'Fatto (ridimensionate %s immagini).');
+@define('SYNCING', 'Sincronizzazione del database con la cartella delle immagini');
+@define('SYNC_DONE', 'Fatto (Sincronizzate %s immagini).');
+@define('FILE_NOT_FOUND', 'Impossibile trovare il file <b>%s</b>, forse è già stato cancellato?');
+@define('ABORT_NOW', 'Interrompi subito');
+@define('REMOTE_FILE_NOT_FOUND', 'File non trovato sul server remoto, sei sicuro che l\'URL: <b>%s</b> sia correttoi?');
+@define('FILE_FETCHED', '%s scaricato come %s');
+@define('FILE_UPLOADED', 'File %s inviato con successo come %s');
+@define('WORD_OR', 'O');
+@define('SCALING_IMAGE', 'Ridimensionamento di %s a %s x %s px');
+@define('KEEP_PROPORTIONS', 'Mantieni le proporzioni');
+@define('REALLY_SCALE_IMAGE', 'Vuoi veramente riscalare l\'immagine? Questa operazione non può essere annullata!');
+@define('TOGGLE_ALL', 'Espandi tutto');
+@define('TOGGLE_OPTION', 'Inverti l\'opzione');
+@define('SUBSCRIBE_TO_THIS_ENTRY', 'Iscriviti a questa notizia');
+@define('UNSUBSCRIBE_OK', "%s è stato disiscritto dalla notizia");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'Nuovo commento alla notizia "%s" a cui sei iscritto');
+@define('SUBSCRIPTION_MAIL', "Ciao %s,\n\nC'è un nuovo commento alla notizia che stai tenendo d'occhio su \"%s\", intitolata \"%s\"\nIl nome dell'autore è : %s\n\nPuoi trovare la notizia qui: %s\n\nPuoi disiscriverti clickando su questo link: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "Ciao %s,\n\nUn nuovo trackback è stato aggiunto alla notizia che stai tenendo d'occhio su \"%s\", intitolata \"%s\"\nIl nome dell'autore è: %s\n\nPuoi trovare la notizia qui: %s\n\nPuoi disiscriverti clickando su questo link: %s\n");
+@define('SIGNATURE', "\n-- \n%s powered by Serendipity.\nIl miglior blog del mondo, puoi usarlo anceh tu.\nGuarda <http://s9y.org> per sapere come.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91 feed');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0 feed');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0 feed');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 commenti');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3 feed');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'Campo "managingEditor"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  'Campo "webMaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'Immagine per il feed RSS');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', 'Larghezza Immagine');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'Altezza Immagine');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  'Indirizzo e-mail del webmaster, se disponibile. (vuoto: nascosto) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', 'Indirizzo e-mail dell\'editore, se disponibile. (vuoto: nascosto) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'URL di un\'immagine GIF/JPEG/PNG, se disponibile. (vuoto: serendipity-logo)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'in pixel, max. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'in pixel, max. 400');
+@define('SYNDICATION_PLUGIN_TTL', 'Campo "ttl" (time-to-live)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'Numero di minuti dopo i quali il tuo blog non dovrebbe essere tenuto in cache da altri siti/applicazioni (vuoto: nascosto) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'Campo "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', 'Il campo "pubDate" deve essere incluso in un canale RSS, per mostrare la data di inserimento dell\'ultima notizia?');
+@define('CONTENT', 'Contenuto');
+@define('TYPE', 'Tipo');
+@define('DRAFT', 'Bozza');
+@define('PUBLISH', 'Pubblica');
+@define('PREVIEW', 'Anteprima');
+@define('DATE', 'Data');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', 'Attenzione: La data specificata non è valida. Deve essere nel formato AAAA-MM-GG OO:MM .');
+@define('CATEGORY_PLUGIN_DESC', 'Mostra la lista delle categorie.');
+@define('ALL_AUTHORS', 'Tutti gli autori');
+@define('CATEGORIES_TO_FETCH', 'Categorie da scaricare');
+@define('CATEGORIES_TO_FETCH_DESC', 'Scarica le categorie di quale autore?');
+@define('PAGE_BROWSE_ENTRIES', 'Pagina %s di %s, in totale %s notizie');
+@define('PREVIOUS_PAGE', 'pagina precedente');
+@define('NEXT_PAGE', 'pagina seguente');
+@define('ALL_CATEGORIES', 'Tutte le categorie');
+@define('DO_MARKUP', 'Effettua trasformazioni del Markup');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'Formato data');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'Il formato della data della notizia, usando variabili di strftime() del PHP. (Default: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'Impossibile aprire il file di modello, per favore aggiornare serendipity!');
+@define('ADVANCED_OPTIONS', 'Opzioni avanzate');
+@define('EDIT_ENTRY', 'Modifica notizia');
+@define('HTACCESS_ERROR', 'Per controllare l\'installazione del tuo webserver, serendipity ha bisogno di scrivere nel file ".htaccess". Questo non è stato possibile a causa di permessi errati. Per favore sistema i permessi in questo modo: <br />&nbsp;&nbsp;%s<br />e ricarica questa pagina.');
+@define('SIDEBAR_PLUGINS', 'Plugin per le barre laterali');
+@define('EVENT_PLUGINS', 'Plugin di Evento');
+@define('SORT_ORDER', 'Ordinamento');
+@define('SORT_ORDER_NAME', 'Nome file');
+@define('SORT_ORDER_EXTENSION', 'Estensione del file');
+@define('SORT_ORDER_SIZE', 'Dimensioni del file');
+@define('SORT_ORDER_WIDTH', 'Larghezza immagine');
+@define('SORT_ORDER_HEIGHT', 'Altezza immagine');
+@define('SORT_ORDER_DATE', 'Data di upload');
+@define('SORT_ORDER_ASC', 'Crescente');
+@define('SORT_ORDER_DESC', 'Decrescente');
+@define('THUMBNAIL_SHORT', 'Mini');
+@define('ORIGINAL_SHORT', 'Orig.');
+@define('APPLY_MARKUP_TO', 'Applica markup a %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'Inizio settimana');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity ha rilevato che la configurazione si riferisce alla versione %s, mentre serendipity è installato nella versione %s, è necessario fare l\'upgrade! <a href="%s">Clicka qui</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'Salve, e benvenuto alla procedura di upgrade di Serendipity.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', 'Sono qui per aiutarti a fare l\'upgrade della tua installazione di Serendipity %s .');
+@define('SERENDIPITY_UPGRADER_WHY', 'Vedi questo messaggio perché hai appena installato Serendipity %s, ma non hai ancora aggiornato l\'installazione del database per questa versione');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'Database update (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'Ho trovato questi file .sql che hanno bisogno di essere caricati prima di continuare col funzionamento di Serendipity');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  'Procedure specifiche di versione');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', 'Nessuna procedura specifica della versione trovata');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', 'Vuoi eseguire le procedure indicate?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'No, le eseguirò manualmente');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'Sí, eseguile');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'Sembra che tu non abbia bisogno della procedura di upgrade');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', 'Considera Serendipity uggiornato');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'Hai ignorato la procedura di upgrade di  Serendipity, per favore controlla che il tuo database sia correttamente installato e che le funzioni periodiche vengano lanciate');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'La tua installazione di Serendipity è ora aggiornata alla versione %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', 'Puoi tornare al tuo blog clickando  %squi%s');
+@define('MANAGE_USERS', 'gestione Utenti');
+@define('CREATE_NEW_USER', 'Crea nuovo utente');
+@define('CREATE_NOT_AUTHORIZED', 'Non puoi modificare utenti con lo stesso tuo livello');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'Non puoi creare utenti di livello superiore al tuo');
+@define('CREATED_USER', 'Un nuovo utente %s è stato creato');
+@define('MODIFIED_USER', 'Le caratteristiche dell\'utente %s sono state modificate');
+@define('USER_LEVEL', 'Livello utente');
+@define('DELETE_USER', 'Stai per cancellare l\'utente #%d %s. Sei convinto? Questo impedirà la visualizzazione delle notizie scritte da lui sulla pagina principale.');
+@define('DELETED_USER', 'Utente #%d %s cancellato.');
+@define('LIMIT_TO_NUMBER', 'Quante notizie vuoi mostrare?');
+@define('ENTRIES_PER_PAGE', 'notizie per pagina');
+@define('XML_IMAGE_TO_DISPLAY', 'Pulsante XML');
+@define('XML_IMAGE_TO_DISPLAY_DESC','I link ai feed XML saranno indicati da questa immagine. Lasciare vuoto per l\'immagine di default, inserire \'none\' per disabilitarla.');
+
+@define('DIRECTORIES_AVAILABLE', 'Nella lista di sotto-directory disponibili puoi clickare sul nome di una directory per creare una nuova directory al suo interno.');
+@define('ALL_DIRECTORIES', 'tutte le directory');
+@define('MANAGE_DIRECTORIES', 'Gestione directory');
+@define('DIRECTORY_CREATED', 'La directory <strong>%s</strong> è stata creata.');
+@define('PARENT_DIRECTORY', 'Directory superiore');
+@define('CONFIRM_DELETE_DIRECTORY', 'Sei sicuro di voler cancellare tutto il contenuto della directory %s?');
+@define('ERROR_NO_DIRECTORY', 'Errore: La directory %s non esiste');
+@define('CHECKING_DIRECTORY', 'Controllo dei file nella directory %s');
+@define('DELETING_FILE', 'Cancellazione del file %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', 'Impossibile rimuovere directory non vuote. Attivare "Forzare la cancellazione" se volete rimuoverli e rimandare il form. I file esistenti sono:');
+@define('DIRECTORY_DELETE_FAILED', 'Cancellazione della directory %s fallita. Controllare i permessi o i messaggi soprastanti.');
+@define('DIRECTORY_DELETE_SUCCESS', 'Directory %s cancellata con successo.');
+@define('SKIPPING_FILE_EXTENSION', 'File evitato: Estensione mancante in %s.');
+@define('SKIPPING_FILE_UNREADABLE', 'File evitato: %s non è leggibile.');
+@define('FOUND_FILE', 'Trovato file nuovo/modificato: %s.');
+@define('ALREADY_SUBCATEGORY', '%s è già una sotto-categoria di %s.');
+@define('PARENT_CATEGORY', 'Categoria superiore');
+@define('IN_REPLY_TO', 'In risposta a');
+@define('TOP_LEVEL', 'Primo Livello');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', 'feed %s');
+@define('PERMISSIONS', 'Permessi');
+@define('SETTINGS_SAVED_AT', 'Le nuove impostazioni sono state salvate in %s');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', 'Impostazioni Database');
+@define('INSTALL_CAT_DB_DESC', 'Qui puoi inserire le informazioni sul database. Serendipity ne ha bisogno per funzionare');
+@define('INSTALL_DBTYPE', 'Tipo Database');
+@define('INSTALL_DBTYPE_DESC', 'Tipo di Database');
+@define('INSTALL_DBHOST', 'Host Database');
+@define('INSTALL_DBHOST_DESC', 'Il nome dell\'host del server database');
+@define('INSTALL_DBUSER', 'Utente Database');
+@define('INSTALL_DBUSER_DESC', 'Il nome utente con cui collegarsi al database');
+@define('INSTALL_DBPASS', 'Password Database');
+@define('INSTALL_DBPASS_DESC', 'La password dell\'utente indicato');
+@define('INSTALL_DBNAME', 'Nome Database');
+@define('INSTALL_DBNAME_DESC', 'Il nome del tuo database');
+@define('INSTALL_DBPREFIX', 'Prefisso Tabelle Database');
+@define('INSTALL_DBPREFIX_DESC', 'Prefisso per i nomi delle tabelle, per esempio serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', 'Percorsi');
+@define('INSTALL_CAT_PATHS_DESC', 'Percorsi a cartelle e file essenziali. Non dimenticare la barra alla fine del nome delle directory!');
+@define('INSTALL_FULLPATH', 'Percorso completo');
+@define('INSTALL_FULLPATH_DESC', 'Il percorso completo e assoluto all\'installazione di serendipity');
+@define('INSTALL_UPLOADPATH', 'Percorso Upload');
+@define('INSTALL_UPLOADPATH_DESC', 'Tutti gli upload andranno qui, relativo al \'Percorso completo\' - tipicamente \'uploads/\'');
+@define('INSTALL_RELPATH', 'Percorso relativo');
+@define('INSTALL_RELPATH_DESC', 'Percorso a serendipity nel browser, tipicamente \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', 'Percorso relativo dei modelli');
+@define('INSTALL_RELTEMPLPATH_DESC', 'Il percorso alla cartella contenente i modelli - relativa a \'percorso relativo\'');
+@define('INSTALL_RELUPLOADPATH', 'Percorso relativo degli upload');
+@define('INSTALL_RELUPLOADPATH_DESC', 'Percorso agli upload per il browser - relativo a \'percorso relativo\'');
+@define('INSTALL_URL', 'URL del blog');
+@define('INSTALL_URL_DESC', 'URL di base all\'installazione di serendipity');
+@define('INSTALL_INDEXFILE', 'File indice');
+@define('INSTALL_INDEXFILE_DESC', 'Il nome del file indice di serendipity');
+
+/* Generel settings */
+@define('INSTALL_CAT_SETTINGS', 'Impostazioni generali');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Personalizza il comportamento di Serendipity');
+@define('INSTALL_USERNAME', 'Nome utente di amministrazione');
+@define('INSTALL_USERNAME_DESC', 'Nome utente per l\'accesso come amministratore');
+@define('INSTALL_PASSWORD', 'Password di amministrazione');
+@define('INSTALL_PASSWORD_DESC', 'Password per l\'accesso come ammninistratore');
+@define('INSTALL_EMAIL', 'e-mail amministratore');
+@define('INSTALL_EMAIL_DESC', 'E-mail dell\'amministratore del blog');
+@define('INSTALL_SENDMAIL', 'Invia mail all\'amministratore?');
+@define('INSTALL_SENDMAIL_DESC', 'Vuoi che l\'amministratore riceva e-mail quando vengono scritti commenti alle notizie?');
+@define('INSTALL_SUBSCRIBE', 'Consenti iscrizione alle notizie?');
+@define('INSTALL_SUBSCRIBE_DESC', 'Consenti agli utenti di iscriversi alle notizie e quindi di ricevere un\'e-mail quando vengono scritti commenti a quelle notizie');
+@define('INSTALL_BLOGNAME', 'Nome del Blog');
+@define('INSTALL_BLOGNAME_DESC', 'Il titolo del tuo blog');
+@define('INSTALL_BLOGDESC', 'Descrizione del Blog');
+@define('INSTALL_BLOGDESC_DESC', 'La descrizione del tuo blog');
+@define('INSTALL_LANG', 'Lingua');
+@define('INSTALL_LANG_DESC', 'Seleziona la lingua del tuo blog');
+
+/* Appearance and options */
+@define('INSTALL_CAT_DISPLAY', 'Aspetto e opzioni');
+@define('INSTALL_CAT_DISPLAY_DESC', 'Personalizza l\'aspetto e il funzionamento di Serendipity');
+@define('INSTALL_WYSIWYG', 'Usa un editor WYSIWYG');
+@define('INSTALL_WYSIWYG_DESC', 'Vuoi usare l\'editor WYSIWYG? (Funziona con IE5+, parzialmente con Mozilla 1.3+)');
+@define('INSTALL_XHTML11', 'Forza l\'aderenza a XHTML 1.1');
+@define('INSTALL_XHTML11_DESC', 'Vuoi forzare l\'aderenza allo standard XHTML 1.1 (potrebbe causare problemi nel backend e nel frontend con i browser di vecchia generazione)');
+@define('INSTALL_POPUP', 'Abilita l\'uso di finestre popup');
+@define('INSTALL_POPUP_DESC', 'Vuoi usare dei popup per i commenti, i trackback, ecc.?');
+@define('INSTALL_EMBED', 'Hai inglobato serendipity?');
+@define('INSTALL_EMBED_DESC', 'Se vuoi inglobare serendipity in una normale pagina, imposta questa opzione a vero, in modo da scartare gli header e scrivere solo i contenuti. Puoi usare i normali header della tua pagina web. Leggi il file README per avere più informazioni!');
+@define('INSTALL_TOP_AS_LINKS', 'Mostra i Top Exit/Referrer come link?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"no": Exit e Referrer sono mostrati come puro testo per evitare spam su google. "sì": Exit e Referrer vengono mostrati come link. "default": Usa le impostazioni globali (raccomandato).');
+@define('INSTALL_BLOCKREF', 'Referers bloccati');
+@define('INSTALL_BLOCKREF_DESC', 'Ci sono particolari host che non vuoi mostrare nella lista dei referer? Separa la lista dei nomi di host con un \';\' e, nota bene, gli host vengono bloccati anche come sotto-stringhe!');
+@define('INSTALL_REWRITE', 'Riscrittura URL');
+@define('INSTALL_REWRITE_DESC', 'Seleziona quale regola vuoi per la generazione degli URL. Abilitare la riscrittura degli URL genera URL più belli e rende il blog meglio indicizzabile dai motori di ricerca come google. Il webserver deve supportare almeno mod_rewrite o "AllowOverride All" per la tua directory di serendipity. L\'impostazione di default è l\'auto-riconoscimento');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', 'Impostazione per la conversione di immagini');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'Inserisci informazioni generali su come serendipity deve trattare con le immagini');
+@define('INSTALL_IMAGEMAGICK', 'Usa Imagemagick');
+@define('INSTALL_IMAGEMAGICK_DESC', 'Hai image magick installato e vuoi usarlo per ridimensionare le immagini?');
+@define('INSTALL_IMAGEMAGICKPATH', 'Percorso al binario \'convert\'');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'Percorso completo e nome dell\'eseguibile \'convert\' di ImageMagick');
+@define('INSTALL_THUMBSUFFIX', 'Suffisso miniature');
+@define('INSTALL_THUMBSUFFIX_DESC', 'Le miniature avranno un nome nel formato: originale.[suffisso].est');
+@define('INSTALL_THUMBWIDTH', 'Dimensioni delle miniature');
+@define('INSTALL_THUMBWIDTH_DESC', 'Larghezza massima stabilita per le miniature auto-generate');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', 'I tuoi dettagli personali');
+@define('USERCONF_CAT_PERSONAL_DESC', 'Modifica i tuoi dettagli personali');
+@define('USERCONF_USERNAME', 'Il tuo nome utente');
+@define('USERCONF_USERNAME_DESC', 'Il nome utente che usi per collegarti al blog');
+@define('USERCONF_PASSWORD', 'La tua password');
+@define('USERCONF_PASSWORD_DESC', 'La password che usi per collegarti al blog');
+@define('USERCONF_EMAIL', 'Il tuo indirizzo e-mail');
+@define('USERCONF_EMAIL_DESC', 'Il tuo indirizzo e-mail personale');
+@define('USERCONF_SENDCOMMENTS', 'Manda avvisi di commenti?');
+@define('USERCONF_SENDCOMMENTS_DESC', 'Vuoi ricevere un\'e-mail quando vengono scritti commenti sui tuoi articoli?');
+@define('USERCONF_SENDTRACKBACKS', 'manda avvisi di trackback?');
+@define('USERCONF_SENDTRACKBACKS_DESC', 'Vuoi ricevere e-mail quando vengono aggiunti dei trackback ai tuoi articoli?');
+@define('USERCONF_ALLOWPUBLISH', 'Permessi: Pubblicazione notizie?');
+@define('USERCONF_ALLOWPUBLISH_DESC', 'A questo utente è consentito pubblicare notizie?');
+@define('SUCCESS', 'Successo');
+@define('POWERED_BY_SHOW_TEXT', 'Mostra "Serendipity" come testo');
+@define('POWERED_BY_SHOW_TEXT_DESC', 'Mostra "Serendipity Weblog" come testo');
+@define('POWERED_BY_SHOW_IMAGE', 'Mostra "Serendipity" con un logo');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Mostra il logo di Serendipity');
+@define('PLUGIN_ITEM_DISPLAY', 'Dove deve essere mostrato l\'oggetto?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'Solo notizia estesa');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'Solo pagina riassuntiva');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'Sempre');
+@define('RSS_IMPORT_CATEGORY', 'Usa questa categoria per le notizie importate non corrispondenti');
+
+@define('COMMENTS_WILL_BE_MODERATED', 'I commenti sottoposti sono soggetti a moderazione prima di essere mostrati.');
+@define('YOU_HAVE_THESE_OPTIONS', 'Sono disponibili le seguenti opzioni:');
+@define('THIS_COMMENT_NEEDS_REVIEW', 'Attenzione: Questo commento deve essere approvato prima di essere mostrato');
+@define('DELETE_COMMENT', 'Cancella commento');
+@define('APPROVE_COMMENT', 'Approva commento');
+@define('REQUIRES_REVIEW', 'Richiede revisione');
+@define('COMMENT_APPROVED', 'Il commento #%s è stato approvato con successo');
+@define('COMMENT_DELETED', 'Il commento #%s è stato cancellato con successo');
+@define('COMMENTS_MODERATE', 'Commenti e Traceback a questa notizia richiedono moderazione');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'Attenzione: Questo trackback richiede approvazione prima di essere mostrato');
+@define('DELETE_TRACKBACK', 'Cancella trackback');
+@define('APPROVE_TRACKBACK', 'Approva trackback');
+@define('TRACKBACK_APPROVED', 'Il trackback #%s è stato approvato con successo');
+@define('TRACKBACK_DELETED', 'Il trackback #%s è stato cancellato con successo');
+@define('VIEW', 'Vedi');
+@define('COMMENT_ALREADY_APPROVED', 'Il commento #%s sembra già essere stato approvato');
+@define('COMMENT_EDITED', 'Il commento selezionato è stato modificato');
+@define('HIDE', 'Nascondi');
+@define('VIEW_EXTENDED_ENTRY', 'Continua a leggere "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'Questo link non dovrebbe essere clickato. Contiene l\'URI di trackback per questa notizia. Puoi usare questo URI per mandare pingback e trackback dal tuo blog a questa notizia. Per copiare il link, clickaci col tasto destro e seleziona "Copia Collegamento".');
+@define('PLUGIN_SUPERUSER_HTTPS', 'Usa https per il  login');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'Imposta il link di login a una locazione https. Il webserver deve supportare questa configurazione!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'Rendi clickabili i link esterni?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"no": i link esterni non verificati (Top Exit, Top Referrer, Commenti degli utenti) non vengono mostrati/vengono mostrati come puro testo dove possibile, per evitare spam di google. (raccomandato). "Sì": I link esterni non verificati appaiono come link. Può essere reimpostato dalla configurazione dei plugin delle barre laterali!');
+@define('PAGE_BROWSE_COMMENTS', 'Pagina %s di %s, in totale %s commenti');
+@define('FILTERS', 'Filtri');
+@define('FIND_ENTRIES', 'Trova notizie');
+@define('FIND_COMMENTS', 'Trova commenti');
+@define('FIND_MEDIA', 'Trova media');
+@define('FILTER_DIRECTORY', 'Directory');
+@define('SORT_BY', 'Ordina per');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'Nessun Trackback inviato: Impossibile connettersi a %s sulla porta %d');
+@define('MEDIA', 'Media');
+@define('MEDIA_LIBRARY', 'Libreria Media');
+@define('ADD_MEDIA', 'Aggiungi media');
+@define('ENTER_MEDIA_URL', 'Inserisci l\'URL di un file da scaricare:');
+@define('ENTER_MEDIA_UPLOAD', 'Seleziona un file da inviare:');
+@define('SAVE_FILE_AS', 'Salva il file come:');
+@define('STORE_IN_DIRECTORY', 'Salva il file nella directory: ');
+@define('ADD_MEDIA_BLAHBLAH', '<b>Aggiungi un file al deposito di media:</b><p>Qui puoi inviare file media, o dirmi da dove prenderli in qualche parte del web! Se non hai l\'immagine giusta, <a href="http://images.google.com" target="_blank">cerca su google</a> quella che preferisci, i risultati spesso sono utili e divertenti :)<p><b>Seleziona il metodo:</b><br>');
+@define('MEDIA_RENAME', 'Rinomina questo file');
+@define('IMAGE_RESIZE', 'Ridimensiona questa immagine');
+@define('MEDIA_DELETE', 'Cancella questo file');
+@define('FILES_PER_PAGE', 'File per pagina');
+@define('CLICK_FILE_TO_INSERT', 'Clicka sul file che vuoi inserire:');
+@define('SELECT_FILE', 'Seleziona il file da inserire');
+@define('MEDIA_FULLSIZE', 'Dimensioni piene');
+@define('CALENDAR_BOW_DESC', 'Il giorno della settimana che dovrebbe essere considerato il primo. Il default è Lunedì');
+@define('SUPERUSER', 'Amministrazione del Blog');
+@define('ALLOWS_YOU_BLAHBLAH', 'Fornisce un link nella barra laterare per l\'amministrazione del blog');
+@define('CALENDAR', 'Calendario');
+@define('SUPERUSER_OPEN_ADMIN', 'Apri amministrazione');
+@define('SUPERUSER_OPEN_LOGIN', 'Apri schermo di login');
+@define('INVERT_SELECTIONS', 'Inverti la selezione');
+@define('COMMENTS_DELETE_CONFIRM', 'Sei sicuro di voler cancellare i commenti selezionati?');
+@define('COMMENT_DELETE_CONFIRM', 'Sei sicuro di voler cancellare il commento #%d, scritto da %s?');
+@define('DELETE_SELECTED_COMMENTS', 'Cancella i commenti selezionati');
+@define('VIEW_COMMENT', 'Vedi commento');
+@define('VIEW_ENTRY', 'Vedi notizia');
+@define('DELETE_FILE_FAIL' , 'Impossibile cancellare il file <b>%s</b>');
+@define('DELETE_THUMBNAIL', 'Cancellata miniatura dell\'immagine <b>%s</b>');
+@define('DELETE_FILE', 'Cancellato il file <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', 'Stai per cancellare <b>%s</b><br />Se stai usando questo file in altre notizie, questo causerà link o immagini "morti"<br />Sei sicuro di voler procedere?<br /><br />');
+@define('TRACKBACK_SENDING', 'Invio del trackback all\'URI %s...');
+@define('TRACKBACK_SENT', 'Trackback inviato con successo');
+@define('TRACKBACK_FAILED', 'Trackback fallito: %s');
+@define('TRACKBACK_NOT_FOUND', 'Nessun URI di trackback trovato.');
+@define('TRACKBACK_URI_MISMATCH', 'L\'URI di trackback auto-rilevato non corrisponde con il nostro URI di destinazione.');
+@define('TRACKBACK_CHECKING', 'Controllo di <u>%s</u> per possibili trackback...');
+@define('TRACKBACK_NO_DATA', 'La destinazione non contiene dati');
+@define('TRACKBACK_SIZE', 'L\'URI di destinazione eccede le dimensioni massime per i file di %s byte.');
+@define('COMMENTS_VIEWMODE_THREADED', 'Per argomento');
+@define('COMMENTS_VIEWMODE_LINEAR', 'Cronologicamente');
+@define('DISPLAY_COMMENTS_AS', 'Mostra commenti');
+@define('COMMENTS_FILTER_SHOW', 'Show'); // Translate
+@define('COMMENTS_FILTER_ALL', 'All'); // Translate
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'Only approved'); // Translate
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'Pending approval'); // Translate
+@define('RSS_IMPORT_BODYONLY', 'Put all imported text in the "body" section and do not split up into "extended entry" section.'); // Translate
+@define('SYNDICATION_PLUGIN_FULLFEED', 'Show full articles with extended body inside RSS feed'); // Translate
+@define('MT_DATA_FILE', 'Movable Type data file'); // Translate
+@define('FORCE', 'Force'); // Translate
+@define('CREATE_AUTHOR', 'Create author \'%s\'.'); // Translate
+@define('CREATE_CATEGORY', 'Create category \'%s\'.'); // Translate
+@define('MYSQL_REQUIRED', 'You must have the MySQL extension in order to perform this action.'); // Translate
+@define('COULDNT_CONNECT', 'Could not connect to MySQL database: %s.'); // Translate
+@define('COULDNT_SELECT_DB', 'Could not select database: %s.'); // Translate
+@define('COULDNT_SELECT_USER_INFO', 'Could not select user information: %s.'); // Translate
+@define('COULDNT_SELECT_CATEGORY_INFO', 'Could not select category information: %s.'); // Translate
+@define('COULDNT_SELECT_ENTRY_INFO', 'Could not select entry information: %s.'); // Translate
+@define('COULDNT_SELECT_COMMENT_INFO', 'Could not select comment information: %s.'); // Translate
+@define('WEEK', 'Week'); // Translate
+@define('WEEKS', 'Weeks'); // Translate
+@define('MONTHS', 'Months'); // Translate
+@define('DAYS', 'Days'); // Translate
+@define('ARCHIVE_FREQUENCY', 'Calendar item frequency'); // Translate
+@define('ARCHIVE_FREQUENCY_DESC', 'The calendar interval to use between each item in the list'); // Translate
+@define('ARCHIVE_COUNT', 'Number of items in the list'); // Translate
+@define('ARCHIVE_COUNT_DESC', 'The total number of months, weeks or days to display'); // Translate
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'Below is a list of installed plugins'); // Translate
+@define('SIDEBAR_PLUGIN', 'sidebar plugin'); // Translate
+@define('EVENT_PLUGIN', 'event plugin'); // Translate
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'Click here to install a new %s'); // Translate
+@define('VERSION', 'version'); // Translate
+@define('INSTALL', 'Install'); // Translate
+@define('ALREADY_INSTALLED', 'Already installed'); // Translate
+@define('SELECT_A_PLUGIN_TO_ADD', 'Select the plugin which you wish to install'); // Translate
+@define('INSTALL_OFFSET', 'Server time Offset'); // Translate
+@define('STICKY_POSTINGS', 'Sticky Postings'); // Translate
+@define('INSTALL_FETCHLIMIT', 'Entries to display on frontpage'); // Translate
+@define('INSTALL_FETCHLIMIT_DESC', 'Number of entries to display for each page on the frontend'); // Translate
+@define('IMPORT_ENTRIES', 'Import data'); // Translate
+@define('EXPORT_ENTRIES', 'Export entries'); // Translate
+@define('IMPORT_WELCOME', 'Welcome to the Serendipity import utility'); // Translate
+@define('IMPORT_WHAT_CAN', 'Here you can import entries from other weblog software applications'); // Translate
+@define('IMPORT_SELECT', 'Please select the software you wish to import from'); // Translate
+@define('IMPORT_PLEASE_ENTER', 'Please enter the data as requested below'); // Translate
+@define('IMPORT_NOW', 'Import now!'); // Translate
+@define('IMPORT_STARTING', 'Starting import procedure...'); // Translate
+@define('IMPORT_FAILED', 'Import failed'); // Translate
+@define('IMPORT_DONE', 'Import successfully completed'); // Translate
+@define('IMPORT_WEBLOG_APP', 'Weblog application'); // Translate
+@define('EXPORT_FEED', 'Export full RSS feed'); // Translate
+@define('STATUS', 'Status after import'); // Translate
+@define('IMPORT_GENERIC_RSS', 'Generic RSS import'); // Translate
+@define('ACTIVATE_AUTODISCOVERY', 'Send Trackbacks to links found in the entry'); // Translate
+@define('WELCOME_TO_ADMIN', 'Welcome to the Serendipity Administration Suite.'); // Translate
+@define('PLEASE_ENTER_CREDENTIALS', 'Please enter your credentials below.'); // Translate
+@define('ADMIN_FOOTER_POWERED_BY', 'Powered by Serendipity %s and PHP %s'); // Translate
+@define('INSTALL_USEGZIP', 'Use gzip compressed pages'); // Translate
+@define('INSTALL_USEGZIP_DESC', 'To speed up delivery of pages, we can compress the pages we send to the visitor, given that his browser supports this. This is recommended'); // Translate
+@define('INSTALL_SHOWFUTURE', 'Show future entries'); // Translate
+@define('INSTALL_SHOWFUTURE_DESC', 'If enabled, this will show all entries in the future on your blog. Default is to hide those entries and only show them if the publish date has arrived.'); // Translate
+@define('INSTALL_DBPERSISTENT', 'Use persistent connections'); // Translate
+@define('INSTALL_DBPERSISTENT_DESC', 'Enable the usage of persistent database connections, read more <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">here</a>. This is normally not recommended'); // Translate
+@define('NO_IMAGES_FOUND', 'No images found'); // Translate
+@define('PERSONAL_SETTINGS', 'Personal Settings'); // Translate
+@define('REFERER', 'Referer'); // Translate
+@define('NOT_FOUND', 'Not found'); // Translate
+@define('NOT_WRITABLE', 'Not writable'); // Translate
+@define('WRITABLE', 'Writable'); // Translate
+@define('PROBLEM_DIAGNOSTIC', 'Due to a problematic diagnostic, you cannot continue with the installation before the above errors are fixed'); // Translate
+@define('SELECT_INSTALLATION_TYPE', 'Select which installation type you wish to use'); // Translate
+@define('WELCOME_TO_INSTALLATION', 'Welcome to the Serendipity Installation'); // Translate
+@define('FIRST_WE_TAKE_A_LOOK', 'First we will take a look at your current setup and attempt to diagnose any compatibility problems'); // Translate
+@define('ERRORS_ARE_DISPLAYED_IN', 'Errors are displayed in %s, recommendations in %s and success in %s'); // Translate
+@define('RED', 'red'); // Translate
+@define('YELLOW', 'yellow'); // Translate
+@define('GREEN', 'green'); // Translate
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s pre-installation report'); // Translate
+@define('RECOMMENDED', 'Recommended'); // Translate
+@define('ACTUAL', 'Actual'); // Translate
+@define('PHPINI_CONFIGURATION', 'php.ini configuration'); // Translate
+@define('PHP_INSTALLATION', 'PHP installation'); // Translate
+@define('THEY_DO', 'they do'); // Translate
+@define('THEY_DONT', 'they don\'t'); // Translate
+@define('SIMPLE_INSTALLATION', 'Simple installation'); // Translate
+@define('EXPERT_INSTALLATION', 'Expert installation'); // Translate
+@define('COMPLETE_INSTALLATION', 'Complete installation'); // Translate
+@define('WONT_INSTALL_DB_AGAIN', 'won\'t install the database again'); // Translate
+@define('CHECK_DATABASE_EXISTS', 'Checking to see if the database and tables already exists'); // Translate
+@define('CREATING_PRIMARY_AUTHOR', 'Creating primary author \'%s\''); // Translate
+@define('SETTING_DEFAULT_TEMPLATE', 'Setting default template'); // Translate
+@define('INSTALLING_DEFAULT_PLUGINS', 'Installing default plugins'); // Translate
+@define('SERENDIPITY_INSTALLED', 'Serendipity has been successfully installed'); // Translate
+@define('VISIT_BLOG_HERE', 'Visit your new blog here'); // Translate
+@define('THANK_YOU_FOR_CHOOSING', 'Thank you for choosing Serendipity'); // Translate
+@define('ERROR_DETECTED_IN_INSTALL', 'An error was detected in the installation'); // Translate
+@define('OPERATING_SYSTEM', 'Operating system'); // Translate
+@define('WEBSERVER_SAPI', 'Webserver SAPI'); // Translate
+@define('IMAGE_ROTATE_LEFT', 'Rotate image 90 degrees counter-clockwise'); // Translate
+@define('IMAGE_ROTATE_RIGHT', 'Rotate image 90 degrees clockwise'); // Translate
+@define('TEMPLATE_SET', '\'%s\' has been set as your active template'); // Translate
+@define('SEARCH_ERROR', 'The search function did not work as expected. Notice for the administrator of this blog: This may happen because of missing index keys in your database. On MySQL systems your database user account needs to be privileged to execute this query: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> The specific error returned by the database was: <pre>%s</pre>'); // Translate
+@define('EDIT_THIS_CAT', 'Editing "%s"'); // Translate
+@define('CATEGORY_REMAINING', 'Delete this category and move its entries to this category'); // Translate
+@define('CATEGORY_INDEX', 'Below is a list of categories available to your entries'); // Translate
+@define('NO_CATEGORIES', 'No categories'); // Translate
+@define('RESET_DATE', 'Reset date'); // Translate
+@define('RESET_DATE_DESC', 'Click here to reset the date to the current time'); // Translate
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Permissions can be set by running shell command: `<em>%s</em>` on the failed directory, or by setting this using an FTP program'); // Translate
+@define('WARNING_TEMPLATE_DEPRECATED', 'Warning: Your current template is using a deprecated template method, you are advised to update if possible'); // Translate
+@define('ENTRY_PUBLISHED_FUTURE', 'This entry is not yet published.'); // Translate
+@define('ENTRIES_BY', 'Entries by %s'); // Translate
+@define('PREVIOUS', 'Previous'); // Translate
+@define('NEXT', 'Next'); // Translate
+@define('APPROVE', 'Approve'); // Translate
+@define('DO_MARKUP_DESCRIPTION', 'Applica le trasformazioni del markup al testo (smilies, abbreviazionicon *, /, _, ...). Disabilitare questa opzione significa mantenere il codice HTML nel testo.');
+@define('CATEGORY_ALREADY_EXIST', 'A category with the name "%s" already exist'); // Translate
+@define('IMPORT_NOTES', 'Note:'); // Translate
+@define('ERROR_FILE_FORBIDDEN', 'You are not allowed to upload files with active content'); // Translate
+@define('ADMIN', 'Administration'); // Re-Translate
+@define('ADMIN_FRONTPAGE', 'Frontpage'); // Translate
+@define('QUOTE', 'Quote'); // Translate
+@define('IFRAME_SAVE', 'Serendipity is now saving your entry, creating trackbacks and performing possible XML-RPC calls. This may take a while..'); // Translate
+@define('IFRAME_SAVE_DRAFT', 'A draft of this entry has been saved'); // Translate
+@define('IFRAME_PREVIEW', 'Serendipity is now creating the preview of your entry...'); // Translate
+@define('IFRAME_WARNING', 'Your browser does not support the concept of iframes. Please open your serendipity_config.inc.php file and set $serendipity[\'use_iframe\'] variable to FALSE.'); // Translate
+@define('NONE', 'none');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Default settings for new entries'); // Translate
+@define('UPGRADE', 'Upgrade'); // Translate
+@define('UPGRADE_TO_VERSION', 'Upgrade to version %s'); // Translate
+@define('DELETE_DIRECTORY', 'Delete directory'); // Translate
+@define('DELETE_DIRECTORY_DESC', 'You are about to delete the contents of a directory that contains media files, possibly files used in some of your entries.'); // Translate
+@define('FORCE_DELETE', 'Delete ALL files in this directory, including those not known by Serendipity'); // Translate
+@define('CREATE_DIRECTORY', 'Create directory'); // Translate
+@define('CREATE_NEW_DIRECTORY', 'Create new directory'); // Translate
+@define('CREATE_DIRECTORY_DESC', 'Here you can create a new directory to place media files in. Choose the name for your new directory and select an optional parent directory to place it in.'); // Translate
+@define('BASE_DIRECTORY', 'Base directory'); // Translate
+@define('USERLEVEL_EDITOR_DESC', 'Standard editor'); // Translate
+@define('USERLEVEL_CHIEF_DESC', 'Chief editor'); // Translate
+@define('USERLEVEL_ADMIN_DESC', 'Administrator'); // Translate
+@define('USERCONF_USERLEVEL', 'Access level'); // Translate
+@define('USERCONF_USERLEVEL_DESC', 'This level is used to determine what kind of access this user has to the blog'); // Translate
+@define('USER_SELF_INFO', 'Logged in as %s (%s)'); // Translate
+@define('ADMIN_ENTRIES', 'Entries'); // Translate
+@define('RECHECK_INSTALLATION', 'Recheck installation'); // Translate
+@define('IMAGICK_EXEC_ERROR', 'Unable to execute: "%s", error: %s, return var: %d'); // Translate
+@define('INSTALL_OFFSET_DESC', 'Enter the amount of hours between the date of your webserver (current: %clock%) and your desired time zone'); // Translate
+@define('UNMET_REQUIREMENTS', 'Requirements failed: %s'); // Translate
+@define('CHARSET', 'Charset');
+@define('AUTOLANG', 'Use visitor\'s browser language as default');
+@define('AUTOLANG_DESC', 'If enabled, this will use the visitor\'s browser language setting to determine the default language of your entry and interface language.');
+@define('INSTALL_AUTODETECT_URL', 'Autodetect used HTTP-Host'); // Translate
+@define('INSTALL_AUTODETECT_URL_DESC', 'If set to "true", Serendipity will ensure that the HTTP Host which was used by your visitor is used as your BaseURL setting. Enabling this will let you be able to use multiple domain names for your Serendipity Blog, and use the domain for all follow-up links which the user used to access your blog.'); // Translate
+@define('CONVERT_HTMLENTITIES', 'Try to auto-convert HTML entities?');
+@define('EMPTY_SETTING', 'You did not specify a valid value for "%s"!');
+@define('USERCONF_REALNAME', 'Real name'); // Translate
+@define('USERCONF_REALNAME_DESC', 'The full name of the author. This is the name seen by readers'); // Translate
+@define('HOTLINK_DONE', 'File hotlinked.<br />Done.'); // Translate
+@define('ENTER_MEDIA_URL_METHOD', 'Fetch method:'); // Translate
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Note: If you choose to hotlink to server, make sure you have permission to hotlink to the designated website, or the website is yours. Hotlink allows you to use off-site images without storing them locally.'); // Translate
+@define('MEDIA_HOTLINKED', 'hotlinked'); // Translate
+@define('FETCH_METHOD_IMAGE', 'Download image to your server'); // Translate
+@define('FETCH_METHOD_HOTLINK', 'Hotlink to server'); // Translate
+@define('DELETE_HOTLINK_FILE', 'Deleted the hotlinked file entitled <b>%s</b>'); // Translate
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Show E-Mail addresses?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_ja.inc.php b/lang/serendipity_lang_ja.inc.php
new file mode 100644 (file)
index 0000000..b803587
--- /dev/null
@@ -0,0 +1,670 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Translation (c) Tadashi Jokagi <elf2000@users.sourceforge.net>, 2004-2005.
+
+@define('LANG_CHARSET', 'UTF-8');
+@define('DATE_LOCALES', 'ja,jp,ja_JP.UTF-8');
+@define('DATE_FORMAT_ENTRY', '%Y年 %B %e(%A)');
+@define('DATE_FORMAT_SHORT', '%Y-%m-%d %H:%M');
+@define('WYSIWYG_LANG', 'ja-utf8');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', '.');
+@define('NUMBER_FORMAT_THOUSANDS', ',');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Serendipity 管理スイート');
+@define('HAVE_TO_BE_LOGGED_ON', 'このページを閲覧するにはログインしなければなりません。');
+@define('WRONG_USERNAME_OR_PASSWORD', '無効のユーザー名かパスワードを入力したように見えます。');
+@define('APPEARANCE', '外観');
+@define('MANAGE_STYLES', 'スタイル管理');
+@define('CONFIGURE_PLUGINS', 'プラグイン設定');
+@define('CONFIGURATION', '設定');
+@define('BACK_TO_BLOG', 'ウェブログに戻る');
+@define('LOGIN', 'ログイン');
+@define('LOGOUT', 'ログアウト');
+@define('LOGGEDOUT', 'ログアウトしました。');
+@define('CREATE', '作成');
+@define('SAVE', '保存');
+@define('NAME', '名前');
+@define('CREATE_NEW_CAT', '新規カテゴリを作成する');
+@define('I_WANT_THUMB', 'エントリ中でサムネイルを使用したい');
+@define('I_WANT_BIG_IMAGE', 'エントリの中で大きな画像を使用したい');
+@define('I_WANT_NO_LINK', ' 画像としてそれを表示したい');
+@define('I_WANT_IT_TO_LINK', 'それをこの URL へのリンクとして表示したい:');
+@define('BACK', '戻る');
+@define('FORWARD', '転送');
+@define('ANONYMOUS', '匿名');
+@define('NEW_TRACKBACK_TO', '新規トラックバックを作成する: ');
+@define('NEW_COMMENT_TO', '新規コメントを投稿する: ');
+@define('RECENT', '最近の記事...');
+@define('OLDER', '古い記事...');
+@define('DONE', '実行完了');
+@define('WELCOME_BACK', 'ようこそ!! ');
+@define('TITLE', '題名');
+@define('DESCRIPTION', '説明');
+@define('PLACEMENT', '配置');
+@define('DELETE', '削除');
+@define('SAVE', '保存');
+@define('UP', '上へ');
+@define('DOWN', '下へ');
+@define('ENTRIES', 'エントリ');
+@define('NEW_ENTRY', '新規エントリ追加');
+@define('EDIT_ENTRIES', 'エントリ編集');
+@define('CATEGORIES', 'カテゴリ一覧');
+@define('WARNING_THIS_BLAHBLAH', "警告:\\nサムネイルなしの画像が多い場合、長時間かかるかもしれません。");
+@define('CREATE_THUMBS', 'サムネイル再構築');
+@define('MANAGE_IMAGES', '画像管理');
+@define('NAME', '名前');
+@define('EMAIL', '電子メール');
+@define('HOMEPAGE', 'ホームページ');
+@define('COMMENT', 'コメント');
+@define('REMEMBER_INFO', '入力情報を記憶しますか?');
+@define('SUBMIT_COMMENT', 'コメント送信');
+@define('NO_ENTRIES_TO_PRINT', '表示するエントリはありません。');
+@define('COMMENTS', 'コメント');
+@define('ADD_COMMENT', 'コメント追加');
+@define('NO_COMMENTS', 'コメントがありません');
+@define('POSTED_BY', '投稿者');
+@define('ON', 'on');
+@define('A_NEW_COMMENT_BLAHBLAH', "エントリに新しいコメントが投稿されました。\n\nブログ名:%s\nエントリ名:\n%s");
+@define('A_NEW_TRACKBACK_BLAHBLAH', '題名 "%s" に新しいトラックバックが作成されました。');
+@define('NO_CATEGORY', 'カテゴリがありません');
+@define('ENTRY_BODY', 'エントリ本文');
+@define('EXTENDED_BODY', '拡張本文');
+@define('CATEGORY', 'カテゴリ');
+@define('EDIT', '編集');
+@define('NO_ENTRIES_BLAHBLAH', '照会 %s ではエントリは見つかりませんでした。' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', '%s の検索結果は %s 個あります:');
+@define('SEARCH_TOO_SHORT', '検索文字は 3 文字以上でなければなりません。');
+@define('IMAGE', '画像');
+@define('ERROR_FILE_NOT_EXISTS', 'エラー: 古いファイル名が存在しません!');
+@define('ERROR_FILE_EXISTS', 'エラー: 既に新しいファイル名が使用されています。別の名前を指定してください!');
+@define('ERROR_SOMETHING', 'エラー: 何かが間違っています。');
+@define('ADDING_IMAGE', '画像追加中...');
+@define('THUMB_CREATED_DONE', 'サムネイルを作成しました。<br>終了します。');
+@define('ERROR_FILE_EXISTS_ALREADY', 'エラー: ファイルはマシン上に既に存在します!');
+@define('ERROR_UNKNOWN_NOUPLOAD', '未知のエラーが生じました。ファイルはアップロードしませんでした。おそらくファイルサイズがサーバーのインストールで許可された最大サイズを超えたと思われます。ISP に確認するか、php.ini ファイルで許可されたアップロード可能な最大ファイルサイズを編集してください。');
+@define('GO', 'Go!');
+@define('NEWSIZE', '新規サイズ: ');
+@define('RESIZE_BLAHBLAH', '<b>リサイズ %s</b><p>');
+@define('ORIGINAL_SIZE', '元サイズ: <i>%sx%s</i> ピクセル');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>Here, you can adjust the image size. If you want to resize the image proportionally, just enter a value in one of the two boxes and press the TAB key --  I\'ll automatically calculate the new size so the image proportions don\'t get messed up</p>');
+@define('QUICKJUMP_CALENDAR', 'カレンダクイックジャンプ');
+@define('QUICKSEARCH', 'クイックサーチ');
+@define('SEARCH_FOR_ENTRY', 'エントリの検索');
+@define('ARCHIVES', '書庫一覧');
+@define('BROWSE_ARCHIVES', '月単位の書庫表示');
+@define('TOP_REFERRER', 'トップリファラ一覧');
+@define('SHOWS_TOP_SITES', 'あなたのブログにリンクしたサイトのトップを表示します。');
+@define('TOP_EXITS', 'Top Exits');
+@define('SHOWS_TOP_EXIT', 'あなたのブログから退出したリンクのトップを表示します。');
+@define('SYNDICATION', 'Syndication');
+@define('SHOWS_RSS_BLAHBLAH', 'RSS syndication リンクを表示します。');
+@define('ADVERTISES_BLAHBLAH', 'ブログの元を宣伝します。');
+@define('HTML_NUGGET', 'HTML ナゲット');
+@define('HOLDS_A_BLAHBLAH', 'サイドバーに HTML の情報(ナゲット)を保持します。');
+@define('TITLE_FOR_NUGGET', 'ナゲットの題名');
+@define('THE_NUGGET', 'HTML の塊です!');
+@define('SYNDICATE_THIS_BLOG', 'このブログと Syndicate');
+@define('YOU_CHOSE', 'あなたは %s を選択しました。');
+@define('IMAGE_ROTATE_LEFT', '左回り(時計と反対回り)に 90 度回転する');
+@define('IMAGE_ROTATE_RIGHT', '右回り(時計回り)に 90 度回転する');
+@define('IMAGE_SIZE', '画像サイズ');
+@define('IMAGE_AS_A_LINK', '画像の挿入');
+@define('POWERED_BY', 'Powered by');
+@define('TRACKBACKS', 'トラックバック');
+@define('TRACKBACK', 'トラックバック');
+@define('NO_TRACKBACKS', 'トラックバックがありません');
+@define('TOPICS_OF', 'Topics from');
+@define('VIEW_FULL', 'フル閲覧');
+@define('VIEW_TOPICS', 'トピック閲覧');
+@define('AT', 'at');
+@define('SET_AS_TEMPLATE', 'テンプレートとして設定');
+@define('IN', 'in');
+@define('EXCERPT', '抜粋');
+@define('TRACKED', 'Tracked');
+@define('LINK_TO_ENTRY', 'エントリにリンク');
+@define('LINK_TO_REMOTE_ENTRY', 'リモートエントリにリンク');
+@define('IP_ADDRESS', 'IP アドレス');
+@define('USER', 'ユーザー');
+@define('THUMBNAIL_USING_OWN', 'Using %s as it\'s own thumbnail because it is so small already.');
+@define('THUMBNAIL_FAILED_COPY', 'Wanted to use %s as it\'s own thumbnail, but failed to copy!');
+@define('AUTHOR', '執筆者');
+@define('LAST_UPDATED', '最終更新日');
+@define('TRACKBACK_SPECIFIC', 'このエントリのトラックバック URI を指定する');
+@define('DIRECT_LINK', 'このエントリへのダイレクトリンク');
+@define('COMMENT_ADDED', 'コメントの追加に成功しました。');
+@define('COMMENT_ADDED_CLICK', '%sここへ戻る%s をクリックするとコメントに戻ります。%sここで閉じる%s ウィンドウを閉じます。');
+@define('COMMENT_NOT_ADDED', 'このエントリへのコメントが無効になったのでコメントは追加できませんでした。');
+@define('COMMENT_NOT_ADDED_CLICK', '%s戻る%s でコメントに戻ります。%s閉じる%s でウィンドウを閉じます。');
+@define('COMMENTS_DISABLE', 'このエントリのコメントを許可しない');
+@define('COMMENTS_ENABLE', 'このエントリへのコメントを許可する');
+@define('COMMENTS_CLOSED', '執筆者はこのエントリへのコメントを許可していません');
+@define('EMPTY_COMMENT', 'コメントは何も含んでいません。%s戻る%s でもう一度試してください。');
+@define('ENTRIES_FOR', '%s のエントリ一覧');
+@define('DOCUMENT_NOT_FOUND', 'ドキュメント %s が見つかりません。');
+@define('USERNAME', 'ユーザー名');
+@define('PASSWORD', 'パスワード');
+@define('AUTOMATIC_LOGIN', '情報を保存する');
+@define('SERENDIPITY_INSTALLATION', 'Serendipity インストール作業');
+@define('LEFT', '左');
+@define('RIGHT', '右');
+@define('HIDDEN', '隠す');
+@define('REMOVE_TICKED_PLUGINS', '印のついたプラグインを削除');
+@define('SAVE_CHANGES_TO_LAYOUT', 'レイアウトへの変更を保存');
+@define('COMMENTS_FROM', 'Comments from');
+@define('ERROR', 'エラー');
+@define('ENTRY_SAVED', 'エントリは保存されました。');
+@define('DELETE_SURE', '#%s の削除を本当に実行しますか?');
+@define('NOT_REALLY', 'とりやめます...');
+@define('DUMP_IT', '実行します!');
+@define('RIP_ENTRY', 'R.I.P. エントリ #%s');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'カテゴリ #%s を削除しました。古い記事はカテゴリ #%s に移動しました。');
+@define('CATEGORY_DELETED', 'カテゴリ #%s を削除しました。');
+@define('INVALID_CATEGORY', 'カテゴリは破棄するために提供されませんでした。');
+@define('CATEGORY_SAVED', 'カテゴリを保存しました。');
+@define('SELECT_TEMPLATE', 'ウェブログに使用したいテンプレートを選択します。');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'エントリの挿入が成功しませんでした!');
+@define('MT_DATA_FILE', 'Movable Type データファイル');
+@define('FORCE', '強制');
+@define('CREATE_AUTHOR', '執筆者 \'%s\' を作成する');
+@define('CREATE_CATEGORY', 'カテゴリ \'%s\' を作成する');
+@define('MYSQL_REQUIRED', 'この操作を実行するには MySQL 拡張が古過ぎます。');
+@define('COULDNT_CONNECT', 'MySQL データベースへ接続できませんでした: %s.');
+@define('COULDNT_SELECT_DB', 'データベースを選択できませんでした: %s.');
+@define('COULDNT_SELECT_USER_INFO', 'ユーザー情報を選択できませんでした: %s.');
+@define('COULDNT_SELECT_CATEGORY_INFO', 'カテゴリ情報を選択できませんでした: %s.');
+@define('COULDNT_SELECT_ENTRY_INFO', 'エントリ情報を選択できませんでした: %s.');
+@define('COULDNT_SELECT_COMMENT_INFO', 'コメント情報を選択できませんでした: %s.');
+@define('YES', 'はい');
+@define('NO', 'いいえ');
+@define('USE_DEFAULT', 'デフォルト');
+@define('CHECK_N_SAVE', 'チェックと保存');
+@define('DIRECTORY_WRITE_ERROR', 'ディレクトリ %s の書き込みができませんでした。パーミッションを調べてください');
+@define('DIRECTORY_CREATE_ERROR', 'ディレクトリ %s が存在しないか作成することができませんでした。手動でディレクトリを作成してください。');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; 実行 <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', '%s バイナリを実行できませんでした。');
+@define('FILE_WRITE_ERROR', 'ファイル %s の書き込みができませんでした。');
+@define('FILE_CREATE_YOURSELF', '自分でファイルを作成するか、パーミッションを調べてください');
+@define('COPY_CODE_BELOW', '<br />* Just copy the code below and place it in %s in your %s folder:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Change www to the user apache runs as (i.e. nobody).');
+@define('BROWSER_RELOAD', '一度これを実行してにはブラウザーの「再読み込み」ボタンをクリックします。');
+@define('DIAGNOSTIC_ERROR', 'あなたの入力した情報の診断を実行する間にいくつかのエラーを検知しました:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity はまだインストールされていません。今から<a href="%s">インストール</a> してください。');
+@define('INCLUDE_ERROR', 'serendipity エラー: could not include %s - exiting.');
+@define('DATABASE_ERROR', 'serendipity エラー: データベースに接続できませんでした - 終了します。');
+@define('CREATE_DATABASE', 'デフォルトデータベースセットアップの作成中...');
+@define('ATTEMPT_WRITE_FILE', 'ファイル %s の書き込みを試みます...');
+@define('WRITTEN_N_SAVED', '設定の書き込みと保存');
+@define('IMAGE_ALIGNMENT', '画像位置あわせ');
+@define('ENTER_NEW_NAME', '新規名称の入力: ');
+@define('RESIZING', 'リサイズ中');
+@define('RESIZE_DONE', '終了しました (%s このイメージをリサイズしました)');
+@define('SYNCING', 'データベースと画像フォルダーの同期中');
+@define('SYNC_DONE', '終了しました (%s この画像を同期しました)');
+@define('FILE_NOT_FOUND', '<b>%s</b> とタイトルをつけられたファイルは既に削除されたため、恐らく見つけることができません。');
+@define('ABORT_NOW', '今中断する');
+@define('REMOTE_FILE_NOT_FOUND', 'ファイルはリモートサーバーにありませんでした。URL を確認しましたか: <b>%s</b> は正しいですか?');
+@define('FILE_FETCHED', '%s を %s として取得しました。');
+@define('FILE_UPLOADED', 'ファイル %s を %s としてアップロードすることに成功しました。');
+@define('WORD_OR', 'Or');
+@define('SCALING_IMAGE', '%s を %s×%s ピクセルに変換します。');
+@define('KEEP_PROPORTIONS', '比率を維持する');
+@define('REALLY_SCALE_IMAGE', '本当に画像を変換しますか? この操作は取り消すことができません!');
+@define('TOGGLE_ALL', 'すべて展開に切り替え');
+@define('TOGGLE_OPTION', 'オプションに切り替え');
+@define('SUBSCRIBE_TO_THIS_ENTRY', 'このエントリを購読する');
+@define('UNSUBSCRIBE_OK', "%s は今、このエントリの購読を取り消しました。");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', '購読済みエントリ "%s" に新規コメントです');
+@define('SUBSCRIPTION_MAIL', "こんにちは %s さん。\n監視中のエントリに新しいコメントが作成されました。\n\nブログ名:\n%s\nエントリ名:\n%s\n\n下記でエントリを見つけることができます:\n%s\n\n下記のリンクをクリックすると購読解除することができます:\n%s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "Hello %s,\n\nA new trackback was added to the entry you are monitoring on \"%s\", entitled \"%s\"\nThe name of the poster is: %s\n\nYou can find the entry here: %s\n\nYou can unsubscribe by clicking on this link: %s\n");
+@define('SIGNATURE', "\n-- \n%s は Serendipityを使っています。\n最良の blog を探しているなら <http://s9y.org> を見てください。");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91 フィード');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0 フォード');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0 フィード');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 コメント');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3 フィード');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', '"managingEditor" フィールド');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  '"webMaster" フィールド');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'RSS feed の画像');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', '画像の幅');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', '画像の高さ');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  'ウェブマスターの電子メールアドレスで、入力すると有効になります (空にすると隠します) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', '管理編集者の電子メールアドレスで、入力すると有効になります (空にすると隠します) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'GIF/JPEG/PNG 形式の画像の URL で、入力すると有効になります (空にすると serendipity ロゴ)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', '最大 144 ピクセルです。');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', '最大 400 ピクセルです。');
+@define('SYNDICATION_PLUGIN_TTL', '"ttl" フィールド(生存期間)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'Amount of minutes after which your blog should not be cached any more by foreign sites/applications (empty: hidden) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', '"pubDate" フィールド');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', 'Should the "pubDate"-field be embedded for a RSS-channel, to show the date of the latest entry?');
+@define('CONTENT', '内容');
+@define('TYPE', '種類');
+@define('DRAFT', '草稿');
+@define('PUBLISH', '公開');
+@define('PREVIEW', 'プレビュー');
+@define('DATE', '日付');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', '警告: 指定した日付は無効です。「YYYY-MM-DD HH:MM」の書式を与えなければなりません。');
+@define('CATEGORY_PLUGIN_DESC', 'カテゴリの一覧を表示します。');
+@define('ALL_AUTHORS', 'すべての執筆者');
+@define('CATEGORIES_TO_FETCH', 'カテゴリを取得');
+@define('CATEGORIES_TO_FETCH_DESC', 'どの執筆者のカテゴリを取得しますか?');
+@define('PAGE_BROWSE_ENTRIES', 'ページ %s/%s, 合計 %s エントリ');
+@define('PREVIOUS_PAGE', '前のページ');
+@define('NEXT_PAGE', '次のページ');
+@define('ALL_CATEGORIES', 'すべてのカテゴリ');
+@define('DO_MARKUP', 'マークアップ変換を行う');
+@define('GENERAL_PLUGIN_DATEFORMAT', '日付書式');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'エントリの実際の日付の書式です。PHP の strftime() 値を使用します (デフォルト: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'テンプレートファイルを開けません。serendipity をアップデートしてください!');
+@define('ADVANCED_OPTIONS', '高度なオプション');
+@define('EDIT_ENTRY', 'エントリ編集');
+@define('HTACCESS_ERROR', 'To check your local webserver installation, serendipity needs to be able to write the file ".htaccess". This was not possible because of permission errors. Please adjust the permissions like this: <br />&nbsp;&nbsp;%s<br />and reload this page.');
+@define('SIDEBAR_PLUGINS', 'サイドバープラグイン');
+@define('EVENT_PLUGINS', 'イベントプラグイン');
+@define('SORT_ORDER', 'ソート順');
+@define('SORT_ORDER_NAME', 'ファイル名');
+@define('SORT_ORDER_EXTENSION', 'ファイル拡張子');
+@define('SORT_ORDER_SIZE', 'ファイルサイズ');
+@define('SORT_ORDER_WIDTH', '画像の幅');
+@define('SORT_ORDER_HEIGHT', '画像の高さ');
+@define('SORT_ORDER_DATE', 'アップロード日付');
+@define('SORT_ORDER_ASC', '昇順');
+@define('SORT_ORDER_DESC', '降順');
+@define('THUMBNAIL_SHORT', 'サムネイル');
+@define('ORIGINAL_SHORT', 'オリジナル');
+@define('APPLY_MARKUP_TO', '%s へのマークアップを適用します。');
+@define('CALENDAR_BEGINNING_OF_WEEK', '週の開始曜日');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity は現在のインストール済みバージョン %s の設定を検出しました。しかし serendipity 自身はバージョン %s としてインストールされています。<a href="%s">ここをクリック</a>してアップグレードする必要があります!');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'やあ、Serendipity アップグレードエージェントにようこそ。');
+@define('SERENDIPITY_UPGRADER_PURPOSE', '私は Serendipity %s をアップグレードインストールするのを助けるためにここに居ます。');
+@define('SERENDIPITY_UPGRADER_WHY', '今 Serendipity %s をインストールしましたが、まだこのバージョンに適したデータベースをアップグレードインストールしていないのでこのメッセージを見ています。');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'データベースアップデート (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', '次の.sqlファイルを見つけました。Serendipity の通常動作を継続すること可能にするには、それを実行する必要があります');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  '特定バージョンのタスク');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', '特定バージョンのタスクバージョンが見つかりませんでした。');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', '上記タスクを行うことを望みますか?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'いいえ、手動で実行します。');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'はい、そうしてください');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'アップグレードの実行を必要としないように見えます。');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', '改良された Serendipity にアップグレードしました。');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', '
+Serendipity のアップグレードステージを無視しました。正しいデータベースが確実にインストールされ、スケジュール機能を実行します。');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'あなたの Serendipity は今バージョン %s にアップグレードしました。');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', '%sここ%s をクリックするとブログに戻ることができます。');
+@define('MANAGE_USERS', 'ユーザー管理');
+@define('CREATE_NEW_USER', '新規ユーザーを追加する');
+@define('CREATE_NOT_AUTHORIZED', 'あなたと同じユーザーレベルのユーザーを修正することは出来ません。');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'あなたより高いユーザーレベルを持ったユーザを作ることができません。');
+@define('CREATED_USER', '新規ユーザー %s を作成しました。');
+@define('MODIFIED_USER', 'ユーザー %s のプロパティを変更しました。');
+@define('USER_LEVEL', 'ユーザーレベル');
+@define('DELETE_USER', 'You are about to delete user #%d %s. Are you serious? This will disallow showing any entries written by him on the frontend.');
+@define('DELETED_USER', 'ユーザー ID #%d の %s を削除しました。');
+@define('LIMIT_TO_NUMBER', 'どれだけの項目を表示しますか?');
+@define('ENTRIES_PER_PAGE', 'ページ毎のエントリ');
+@define('XML_IMAGE_TO_DISPLAY', 'XML ボタン');
+@define('XML_IMAGE_TO_DISPLAY_DESC','Links to XML Feeds will be displayed by this image. Leave empty for default, enter \'none\' to disable.');
+
+@define('DIRECTORIES_AVAILABLE', 'In the list of available subdirectories you can click on any directory name to create a new directory within that structure.');
+@define('ALL_DIRECTORIES', 'すべてのディレクトリ');
+@define('MANAGE_DIRECTORIES', 'ディレクトリ管理');
+@define('DIRECTORY_CREATED', 'ディレクトリ <strong>%s</strong> を作成しました。');
+@define('PARENT_DIRECTORY', '親ディレクトリ');
+@define('CONFIRM_DELETE_DIRECTORY', '本当にディレクトリ %s の内容をすべて削除しますか?');
+@define('ERROR_NO_DIRECTORY', 'エラー: ディレクトリ %s がありません');
+@define('CHECKING_DIRECTORY', 'ディレクトリ %s 内のファイルを調べています');
+@define('DELETING_FILE', 'ファイル %s を削除中...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', '空でないディレクトリは削除できません。もし同様にファイルを削除したければチェックボックス「強制削除する」をチェックし、もう一度送信してください.存在するファイルは次の通りです:');
+@define('DIRECTORY_DELETE_FAILED', 'ディレクトリ %s の削除に失敗しました。パーミッションか上野メッセージを調べてください。');
+@define('DIRECTORY_DELETE_SUCCESS', 'ディレクトリ %s の削除に成功しました。');
+@define('SKIPPING_FILE_EXTENSION', 'ファイルを飛ばします: %s は拡張子がありません。');
+@define('SKIPPING_FILE_UNREADABLE', 'ファイルを飛ばします: %s は読み込めません。');
+@define('FOUND_FILE', '新規/修正されたファイルを見つけました: %s.');
+@define('ALREADY_SUBCATEGORY', '%s は %s のサブカテゴリに既に存在します。');
+@define('PARENT_CATEGORY', '親カテゴリ');
+@define('IN_REPLY_TO', '返信先指定');
+@define('TOP_LEVEL', 'トップレベル');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s フィード');
+@define('PERMISSIONS', '許可');
+@define('SETTINGS_SAVED_AT', '新しい設定は %s に保存されました。');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', 'データベース設定');
+@define('INSTALL_CAT_DB_DESC', 'ここですべてのデータベース情報を入力できます。Serendipity が機能するためにこれが必要です。');
+@define('INSTALL_DBTYPE', 'データベースタイプ');
+@define('INSTALL_DBTYPE_DESC', 'データベースの種類を指定します。');
+@define('INSTALL_DBHOST', 'データベースホスト');
+@define('INSTALL_DBHOST_DESC', 'データベースサーバーのホスト名を指定します。');
+@define('INSTALL_DBUSER', 'データベースユーザー');
+@define('INSTALL_DBUSER_DESC', 'データベースの接続に使用するユーザー名を指定します。');
+@define('INSTALL_DBPASS', 'データベースパスワード');
+@define('INSTALL_DBPASS_DESC', '上のユーザー名と一致するパスワードを指定します。');
+@define('INSTALL_DBNAME', 'データベース名');
+@define('INSTALL_DBNAME_DESC', '使用するデータベース名を指定します。');
+@define('INSTALL_DBPREFIX', 'データベーステーブル接頭語');
+@define('INSTALL_DBPREFIX_DESC', 'テーブル名の接頭語を指定します。例えば「serendipity_」です。');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', 'パス');
+@define('INSTALL_CAT_PATHS_DESC', '各種パスに必要なフォルダーとファイルを指定します。ディレクトリには末尾にスラッシュを忘れないでください!');
+@define('INSTALL_FULLPATH', 'フルパス');
+@define('INSTALL_FULLPATH_DESC', 'serendipity をインストールした絶対フルパスです。');
+@define('INSTALL_UPLOADPATH', 'アップロードパス');
+@define('INSTALL_UPLOADPATH_DESC', 'すべてのアップロードはここに来ます。「フルパス\」への相対パス - 通常「uploads/」です。');
+@define('INSTALL_RELPATH', '相対パス');
+@define('INSTALL_RELPATH_DESC', 'ブラウザーで使用する serendipity のパスです。通常「/serendipity/」 です。');
+@define('INSTALL_RELTEMPLPATH', '相対テンプレートパス');
+@define('INSTALL_RELTEMPLPATH_DESC', 'テンプレートが含まれるフォルダーへのパスです - 「相対パス」への相対です。');
+@define('INSTALL_RELUPLOADPATH', '相対アップロードパス path');
+@define('INSTALL_RELUPLOADPATH_DESC', 'ブラウザからのアップロードのパスです - 「相対パス」への相対です。');
+@define('INSTALL_URL', 'ブログの URL');
+@define('INSTALL_URL_DESC', 'serendipity をインストールしたベース URL');
+@define('INSTALL_INDEXFILE', 'インデックスファイル');
+@define('INSTALL_INDEXFILE_DESC', 'serendipity インデックスファイルの名前');
+
+/* Generel settings */
+@define('INSTALL_CAT_SETTINGS', '大域設定');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Serendipity がどのように振舞うかカスタマイズします。');
+@define('INSTALL_USERNAME', '管理者ユーザー名');
+@define('INSTALL_USERNAME_DESC', '管理者ログインのユーザー名を指定します。');
+@define('INSTALL_PASSWORD', '管理者パスワード');
+@define('INSTALL_PASSWORD_DESC', '管理者ログインのパスワードを指定します。');
+@define('INSTALL_EMAIL', '管理者電子メール');
+@define('INSTALL_EMAIL_DESC', 'ブログ管理者の電子メールを指定します。');
+@define('INSTALL_SENDMAIL', '管理者にメールを送信しますか?');
+@define('INSTALL_SENDMAIL_DESC', 'エントリにコメントが投稿されたとき、電子メールを受信しますか?');
+@define('INSTALL_SUBSCRIBE', 'ユーザーのエントリの購読を許可しますか?');
+@define('INSTALL_SUBSCRIBE_DESC', 'ユーザーがエントリを購読し、かつ新しいコメントがそのエントリへ作られた場合、そのメイルを受け取ることを許可します。');
+@define('INSTALL_BLOGNAME', 'ブログの名前');
+@define('INSTALL_BLOGNAME_DESC', 'ブログの題名を記述します。');
+@define('INSTALL_BLOGDESC', 'ブログの説明');
+@define('INSTALL_BLOGDESC_DESC', 'ブログについての紹介文を記述します。');
+@define('INSTALL_LANG', '言語');
+@define('INSTALL_LANG_DESC', 'ブログの言語を選択します。');
+
+/* Appearance and options */
+@define('INSTALL_CAT_DISPLAY', '外観とオプション');
+@define('INSTALL_CAT_DISPLAY_DESC', 'Serendipity のルックアンドフィールをカスタマイズ');
+@define('INSTALL_WYSIWYG', 'WYSIWYG エディタを使う');
+@define('INSTALL_WYSIWYG_DESC', 'WYSIWYG エディタを使用しますか? (実行には IE5 以上か+、Mozilla 1.3 以上が必要です)');
+@define('INSTALL_XHTML11', '強制的に XHTML 1.1 準拠');
+@define('INSTALL_XHTML11_DESC', '強制で XHTML 1.1 準拠にします (第 4 世代より古いブラウザーのフロントエンド・バックエンドの問題を起こすかもしれません。)');
+@define('INSTALL_POPUP', 'ポップアップウィンドウを有効');
+@define('INSTALL_POPUP_DESC', 'コメントやトラックバックにポップアップウィンドウを使用しますか?');
+@define('INSTALL_EMBED', 'serendipity を組み込みで使用しますか?');
+@define('INSTALL_EMBED_DESC', 'If you want to embed serendipity within a regular page, set to true to discard any headers and just print the contents. You can make use of the indexFile option to use a wrapper class where you put your normal webpage headers. より詳しい情報はファイル README を参照してください!');
+@define('INSTALL_TOP_AS_LINKS', 'トップの退出/リファラーのリンクを表示しますか?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"いいえ": Exits and Referrers are shown as plain text to prevent google spam. "yes": Exits and Referrers are shown as hyperlinks. "デフォルト": 大域設定をの設定を使用します(推奨)');
+@define('INSTALL_BLOCKREF', 'リファラーブロック');
+@define('INSTALL_BLOCKREF_DESC', 'Are there any special hosts you want not to show up in the referers list? ホスト名の一覧を「;」で列挙し、そのホスト名が部分一致でブロックされることに注意してください!');
+@define('INSTALL_REWRITE', 'URL 書き換え');
+@define('INSTALL_REWRITE_DESC', 'Select which rules you wish to use when generating URLs. Enabling rewrite rules will make pretty URLs for your blog and make it better indexable for spiders like google. The webserver needs to support either mod_rewrite or "AllowOverride All" for your serendipity dir. The default setting is auto-detected');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', '画像変換設定');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'serendipity がどのようにイメージを扱わなければならないかに関する一般的な情報を入力します。');
+@define('INSTALL_IMAGEMAGICK', 'Imagemagick を使う');
+@define('INSTALL_IMAGEMAGICK_DESC', 'image magick がインストール済みで、それを使って画像のリサイズをしたいですか?');
+@define('INSTALL_IMAGEMAGICKPATH', 'convert バイナリへのパス');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'image magic convert バイナリのフルパスと名前');
+@define('INSTALL_THUMBSUFFIX', 'サムネイル接尾辞');
+@define('INSTALL_THUMBSUFFIX_DESC', 'サムネイルは次の書式で指定されるでしょう: オリジナル.[接尾辞].拡張子');
+@define('INSTALL_THUMBWIDTH', 'サムネイルの大きさ');
+@define('INSTALL_THUMBWIDTH_DESC', '自動生成するサムネイルの不変の最大幅');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', '個人情報の詳細');
+@define('USERCONF_CAT_PERSONAL_DESC', '個人情報の詳細を変更します。');
+@define('USERCONF_USERNAME', 'ユーザー名');
+@define('USERCONF_USERNAME_DESC', 'ブログにログインするときに使うユーザー名を指定します。');
+@define('USERCONF_PASSWORD', 'パスワード');
+@define('USERCONF_PASSWORD_DESC', 'ブログにログインするときに使うパスワードを指定します。');
+@define('USERCONF_EMAIL', '電子メールアドレス');
+@define('USERCONF_EMAIL_DESC', '個人の電子メールアドレスをしていします。');
+@define('USERCONF_SENDCOMMENTS', 'コメント告知を送信しますか?');
+@define('USERCONF_SENDCOMMENTS_DESC', 'コメントをあなたのエントリが受けたとき、電子メールを受信しますか?');
+@define('USERCONF_SENDTRACKBACKS', 'トラックバック告知を送信しますか?');
+@define('USERCONF_SENDTRACKBACKS_DESC', 'トラックバックをあなたのエントリが受けたとき、電子メールを受信しますか?');
+@define('USERCONF_ALLOWPUBLISH', '権限: エントリを公開しますか?');
+@define('USERCONF_ALLOWPUBLISH_DESC', 'このユーザーがエントリを公開することを許可しますか?');
+@define('SUCCESS', 'Success');
+@define('POWERED_BY_SHOW_TEXT', 'テキストとして "Serendipity" を表示する');
+@define('POWERED_BY_SHOW_TEXT_DESC', 'テキストとして "Serendipity Weblog" を表示するでしょう。');
+@define('POWERED_BY_SHOW_IMAGE', '"Serendipity" とロゴを表示');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Serendipity ロゴを表示します。');
+@define('PLUGIN_ITEM_DISPLAY', 'どこで項目を表示するべきですか?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', '拡張エントリのみ表示');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', '概要ページのみ表示');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', '常に表示');
+@define('RSS_IMPORT_CATEGORY', '一致しなかったインポートしたエントリはこのカテゴリを使用する');
+
+@define('COMMENTS_WILL_BE_MODERATED', '送信されたコメントは表示する前にもでレーションされるでしょう。');
+@define('YOU_HAVE_THESE_OPTIONS', '次のオプションが利用可能です:');
+@define('THIS_COMMENT_NEEDS_REVIEW', '警告: このコメントは表示する前に認証が必要です');
+@define('DELETE_COMMENT', 'コメントを削除');
+@define('APPROVE_COMMENT', 'コメントを承認');
+@define('REQUIRES_REVIEW', 'レビューが必須');
+@define('COMMENT_APPROVED', 'コメント #%s の承認に成功しました。');
+@define('COMMENT_DELETED', 'コメント #%s の削除に成功しました。');
+@define('COMMENTS_MODERATE', 'このエントリのコメントとトラックバックにはモデレーションが必要');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', '警告: このトラックバックは表示する前に認証が必要です。');
+@define('DELETE_TRACKBACK', 'トラックバックを削除');
+@define('APPROVE_TRACKBACK', 'トラックバックを承認');
+@define('TRACKBACK_APPROVED', 'トラックバック #%s の承認に成功しました。');
+@define('TRACKBACK_DELETED', 'トラックバック #%s の削除に成功しました。');
+@define('VIEW', '閲覧');
+@define('COMMENT_ALREADY_APPROVED', 'コメント #%s は既に承認されたようです。');
+@define('COMMENT_EDITED', '選択されたコメントを編集しました。');
+@define('HIDE', '隠す');
+@define('VIEW_EXTENDED_ENTRY', '"%s" の続きを読む...');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'このリンクは、クリックされるのが目的ではありません。それは、このエントリ用のトラックバック URIを含んでいます。You can use this URI to send ping- & trackbacks from your own blog to this entry. このリンクをコピーするには、Internet Explorer の場合右クリックを、「ショートカットをコピー」を選択します。Mozilla の場合「リンクロケーションをコピー」を選択します。');
+@define('PLUGIN_SUPERUSER_HTTPS', 'ログインに https を使う');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'ログインの https ロケーションへのリンクポイントです。ウェブサーバーがこれをサポートしている必要があります!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', '外部リンクをクリック可能にしますか?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"いいえ": Unchecked external links (Top Exits, Top Referrers, User comments) are not shown/shown as plain text where applicable to prevent google spam (recommended). "はい": Unchecked external links are shown as hyperlinks. Can be overridden within sidebar plugin configuration!');
+@define('PAGE_BROWSE_COMMENTS', 'ページ %s/%s, 合計 %s コメント');
+@define('FILTERS', 'フィルター');
+@define('FIND_ENTRIES', 'エントリ検索');
+@define('FIND_COMMENTS', 'コメント検索');
+@define('FIND_MEDIA', 'メディア検索');
+@define('FILTER_DIRECTORY', 'ディレクトリ');
+@define('SORT_BY', 'ソート基準');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'トラックバックを送信しませんでした: %s のポート番号 %s に接続できませんでした。');
+@define('MEDIA', 'メディア');
+@define('MEDIA_LIBRARY', 'メディアライブラリ');
+@define('ADD_MEDIA', 'メディア追加');
+@define('ENTER_MEDIA_URL', '取得するファイルの URL を入力:');
+@define('ENTER_MEDIA_UPLOAD', 'あなたがアップロードしたいファイルを選択:');
+@define('SAVE_FILE_AS', '保存するファイル名:');
+@define('STORE_IN_DIRECTORY', '次のディレクトリの中に保管: ');
+@define('ADD_MEDIA_BLAHBLAH', '<b>メディアリポジトリにファイルを追加します:</b><p>ここでメディアファイルをアップロードするか、ウェブ中のどこかからそれらを取得するように私に命じることができます! If you don\'t have an appropriate image, <a href="http://images.google.com" target="_blank">search for images on google</a> matching your thoughts, the results are often useful and funny :)<p><b>選択方法:</b><br>');
+@define('MEDIA_RENAME', 'このファイルの名称を変更する');
+@define('IMAGE_RESIZE', 'この画像の大きさを変更する');
+@define('MEDIA_DELETE', 'このファイルを削除する');
+@define('FILES_PER_PAGE', 'ページ毎のファイル数');
+@define('CLICK_FILE_TO_INSERT', '追加したいファイルをクリック:');
+@define('SELECT_FILE', '追加するファイルを選択');
+@define('MEDIA_FULLSIZE', 'フルサイズ');
+@define('CALENDAR_BOW_DESC', 'その週の始めと考えるべき週の曜日です。デフォルトは「Monday(月曜日)」です。');
+@define('SUPERUSER', 'ブログ管理');
+@define('ALLOWS_YOU_BLAHBLAH', 'ブログ管理のサイドバーにリンクを提供します。');
+@define('CALENDAR', 'カレンダ');
+@define('SUPERUSER_OPEN_ADMIN', '管理画面を開く');
+@define('SUPERUSER_OPEN_LOGIN', 'ログイン画面を開く');
+@define('INVERT_SELECTIONS', '選択を反転');
+@define('COMMENTS_DELETE_CONFIRM', '本当に選択したコメントを削除しますか?');
+@define('COMMENT_DELETE_CONFIRM', 'コメント番号 #%d で %s が書いたコメントを本当に削除しますか?');
+@define('DELETE_SELECTED_COMMENTS', '選択したコメントの削除');
+@define('VIEW_COMMENT', 'コメント閲覧');
+@define('VIEW_ENTRY', 'エントリ閲覧');
+@define('DELETE_FILE_FAIL' , 'ファイル <b>%s</b> を削除できませんでした。');
+@define('DELETE_THUMBNAIL', '<b>%s</b> というタイトルの画像サムネイルを削除しました。');
+@define('DELETE_FILE', '<b>%s</b> というタイトルのファイルを削除しました。');
+@define('ABOUT_TO_DELETE_FILE', '<b>%s</b>を削除します。<br />もしこのファイルをエントリで使用していた場合、リンク切れや表示で気ない画像の原因になるでしょう。<br />本当に進みますか?<br /><br />');
+@define('TRACKBACK_SENDING', 'URI %s にトラックバックを送信中...');
+@define('TRACKBACK_SENT', 'トラックバック成功');
+@define('TRACKBACK_FAILED', 'トラックバック失敗: %s');
+@define('TRACKBACK_NOT_FOUND', 'トラックバック URI が見つかりません。');
+@define('TRACKBACK_URI_MISMATCH', '自動検出されたトラックバック URI はターゲット URI と一致しません。');
+@define('TRACKBACK_CHECKING', 'トラックバックが可能か <u>%s</u> を検査中...');
+@define('TRACKBACK_NO_DATA', '対象はデータが含まれませんでした。');
+@define('TRACKBACK_SIZE', 'ターゲット URI は最大ファイルサイズ %s を超過しました。');
+@define('COMMENTS_VIEWMODE_THREADED', 'スレッド');
+@define('COMMENTS_VIEWMODE_LINEAR', '一覧');
+@define('DISPLAY_COMMENTS_AS', 'コメント表示形式');
+@define('COMMENTS_FILTER_SHOW', '表示');
+@define('COMMENTS_FILTER_ALL', 'すべて');
+@define('COMMENTS_FILTER_APPROVED_ONLY', '承認済みのみ');
+@define('COMMENTS_FILTER_NEED_APPROVAL', '承認待ち');
+@define('RSS_IMPORT_BODYONLY', 'すべてのエントリは「本文」セクションに置き、拡張エントリセクションに分割しない');
+@define('SYNDICATION_PLUGIN_FULLFEED', 'RSS フィー土中で拡張本文とすべての記事を表示する');
+@define('WEEK', '週');
+@define('WEEKS', '週');
+@define('MONTHS', '月');
+@define('DAYS', '日');
+@define('ARCHIVE_FREQUENCY', 'カレンダ項目の周期');
+@define('ARCHIVE_FREQUENCY_DESC', 'リストの中で各項目間で使用するカレンダー間隔');
+@define('ARCHIVE_COUNT', '一覧中の項目の数');
+@define('ARCHIVE_COUNT_DESC', '表示する月・週または日の合計数');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', '以下にインストール済みのプラグインの一覧があります。');
+@define('SIDEBAR_PLUGIN', 'サイドバープラグイン');
+@define('EVENT_PLUGIN', 'イベントプラグイン');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', '新しい %s をインストールする');
+@define('VERSION', 'バージョン');
+@define('INSTALL', 'インストール');
+@define('ALREADY_INSTALLED', '既にインストール済みです。');
+@define('SELECT_A_PLUGIN_TO_ADD', 'インストールしたいプラグインを選択する');
+@define('INSTALL_OFFSET', 'サーバー時間差');
+@define('STICKY_POSTINGS', 'スティッキ投稿');
+@define('INSTALL_FETCHLIMIT', 'フロントページにエントリを表示する');
+@define('INSTALL_FETCHLIMIT_DESC', '各ページでフロントエンドに表示するエントリの数');
+@define('IMPORT_ENTRIES', 'インポートデータ');
+@define('EXPORT_ENTRIES', 'エクスポートエントリ');
+@define('IMPORT_WELCOME', 'ようこそ Serendipity のインポートユーティリティへ');
+@define('IMPORT_WHAT_CAN', 'ここで、他のウェブログソフトウェアアプリケーションからエントリをインポートすることができます。');
+@define('IMPORT_SELECT', 'あなたがインポートしたいソフトウェアを選択してください。');
+@define('IMPORT_PLEASE_ENTER', '下に要求されたデータを入力してください。');
+@define('IMPORT_NOW', '今すぐインポート!');
+@define('IMPORT_STARTING', 'インポート手続きをはじめました...');
+@define('IMPORT_FAILED', 'インポートに失敗しました。');
+@define('IMPORT_DONE', 'インポートに完了し成功しました。');
+@define('IMPORT_WEBLOG_APP', 'Weblog アプリケーション');
+@define('IMPORT_NOTES', '注:');
+@define('EXPORT_FEED', 'フル RSS フィードをエクスポートする');
+@define('STATUS', 'インポート後の状況');
+@define('IMPORT_GENERIC_RSS', '一般的な RSS をインポートする');
+@define('ACTIVATE_AUTODISCOVERY', 'エントリで見つたリンクにトラックバックを送る');
+@define('WELCOME_TO_ADMIN', 'ようこそ Serendipity の管理スイートへ');
+@define('PLEASE_ENTER_CREDENTIALS', 'ログイン情報を下記に入力してください。');
+@define('ADMIN_FOOTER_POWERED_BY', 'Powered by Serendipity %s and PHP %s');
+@define('INSTALL_USEGZIP', 'ページの gzip 圧縮を使う');
+@define('INSTALL_USEGZIP_DESC', 'ページの送信を高速化するために、ブラウザーがこれをサポートするなら、訪問者へ送るページを圧縮することができます。これが推奨です。');
+@define('INSTALL_SHOWFUTURE', '未来のエントリを表示する');
+@define('INSTALL_SHOWFUTURE_DESC', 'もし有効にしたならブログは未来を含むすべてのエントリを表示するでしょう。デフォルトはそれらのエントリを隠し、公開日が到来したらそれらを表示します。');
+@define('INSTALL_DBPERSISTENT', '継続的接続を使用する');
+@define('INSTALL_DBPERSISTENT_DESC', '継続的データベース接続の使用法を有効にします。詳しいことは <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">ここ</a> を参照してください。これは通常使用することを推奨しません。');
+@define('NO_IMAGES_FOUND', '画像が見つかりません。');
+@define('PERSONAL_SETTINGS', '個人設定');
+@define('REFERER', 'リファラー');
+@define('NOT_FOUND', '見つかりません');
+@define('WRITABLE', '書き込み可能');
+@define('NOT_WRITABLE', '書き込み不可能');
+@define('PROBLEM_DIAGNOSTIC', 'Due to a problematic diagnostic, you cannot continue with the installation before the above errors are fixed');
+@define('SELECT_INSTALLATION_TYPE', 'どのインストールタイプの使用を希望するか選択してください。');
+@define('WELCOME_TO_INSTALLATION', 'ようこそ Serendipity のインストール画面へ');
+@define('FIRST_WE_TAKE_A_LOOK', 'まず初めに、現在の設定を見てごんな互換性の問題があるか分析を試みます。');
+@define('ERRORS_ARE_DISPLAYED_IN', 'エラーは %s で、推奨は %s で、成功は %s で表示されます。');
+@define('RED', '赤');
+@define('YELLOW', '黄');
+@define('GREEN', '緑');
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s インストール作業前の報告');
+@define('RECOMMENDED', '推奨');
+@define('ACTUAL', '実際');
+@define('PHPINI_CONFIGURATION', 'php.ini 設定');
+@define('PHP_INSTALLATION', 'PHP インストール');
+@define('THEY_DO', 'それを行う');
+@define('THEY_DONT', 'それを行わない');
+@define('SIMPLE_INSTALLATION', '簡単なインストール作業を行う');
+@define('EXPERT_INSTALLATION', '上級者のインストール作業を行う');
+@define('COMPLETE_INSTALLATION', 'インストール作業を完了する');
+@define('WONT_INSTALL_DB_AGAIN', '再度データベースをインストールしないでしょう。');
+@define('CHECK_DATABASE_EXISTS', 'データベースとテーブルが既に存在するか確認します。');
+@define('CREATING_PRIMARY_AUTHOR', '主要な執筆者 \'%s\' を作成中');
+@define('SETTING_DEFAULT_TEMPLATE', 'デフォルトテンプレート設定');
+@define('INSTALLING_DEFAULT_PLUGINS', 'デフォルトプラグインのインストール');
+@define('SERENDIPITY_INSTALLED', 'Serendipity のインストールに成功しました。');
+@define('VISIT_BLOG_HERE', 'ここからあなたの新しいブログに訪問できます。');
+@define('THANK_YOU_FOR_CHOOSING', 'Serendipity を選んでくれてありがとうございます。');
+@define('ERROR_DETECTED_IN_INSTALL', 'インストール作業でエラーを検知しました。');
+@define('OPERATING_SYSTEM', 'オペレーションシステム');
+@define('WEBSERVER_SAPI', 'ウェブサーバー SAPI');
+@define('TEMPLATE_SET', '\'%s\' をアクティブテンプレートに設定しました。');
+@define('SEARCH_ERROR', 'サーチ機能は期待通りに働きませんでした。このブログの管理者に通知します: これはデータベースにインデックスキーがないから起きるのかもしれません。MySQLシステムにおいては、あなたのデータベース・ユーザアカウントがこの照会を実行する特権のある必要があります: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> データベースから返された特定のエラーはこの通りです: <pre>%s</pre>');
+@define('EDIT_THIS_CAT', '"%s" 編集中');
+@define('CATEGORY_REMAINING', 'このカテゴリーを削除し、このカテゴリーへのそのエントリーを移動させます。');
+@define('CATEGORY_INDEX', '下記にあなたのエントリに利用可能なカテゴリの一覧があります。');
+@define('NO_CATEGORIES', 'カテゴリがありません');
+@define('RESET_DATE', 'データリセット');
+@define('RESET_DATE_DESC', '現在の時刻への日付をリセットするにはここをクリックしてください。');
+@define('PROBLEM_PERMISSIONS_HOWTO', 'パーミッションはシェルコマンドの実行で設定することができます: `<em>%s</em>` on the failed directory, or by setting this using an FTP program');
+@define('WARNING_TEMPLATE_DEPRECATED', '警告: あなたの現在のテンプレートは非常に古いテンプレート方法を使用しています。可能なかぎり更新を提案します。');
+@define('ENTRY_PUBLISHED_FUTURE', 'このエントリはまだ公開されていません。');
+@define('ENTRIES_BY', '%s のエントリ一覧');
+@define('PREVIOUS', '前へ');
+@define('NEXT', '次へ');
+@define('APPROVE', '承認');
+@define('DO_MARKUP_DESCRIPTION', 'マークアップ変換をテキストに適用します (顔文字、「*」、「/」、「_」などのマークアップショートカット。無効にするとテキスト中のどんな HTML コードも保持します。デフォルトは「はい」です。');
+@define('CATEGORY_ALREADY_EXIST', '"%s" という名前のカテゴリは既に存在します。');
+@define('ERROR_FILE_FORBIDDEN', 'アクティブコンテンツのファイルをアップロードすることを認められていません。');
+@define('ADMIN', '管理');
+@define('ADMIN_FRONTPAGE', 'フロントページ');
+@define('QUOTE', '引用');
+@define('IFRAME_SAVE', 'Serendipity はをエントリ保存中で、トラックバックの作成と可能な限り XML-RPC 呼び出しを実行中です。これは時間がかかるかもしれません...');
+@define('IFRAME_SAVE_DRAFT', 'このエントリの草稿を保存しました。');
+@define('IFRAME_PREVIEW', 'Serendipity はエントリのプレビューを作成中です...');
+@define('IFRAME_WARNING', 'ブラウザーが iframe をサポートしていません。serendipity_config.inc.php ファイルを開いて、$serendipity[\'use_iframe\'] を FALSE に設定してください。');
+@define('NONE', 'なし');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', '新規エントリのデフォルト設定');
+@define('UPGRADE', 'アップグレード');
+@define('UPGRADE_TO_VERSION', 'バージョン %s へアップグレード');
+@define('DELETE_DIRECTORY', 'ディレクトリの削除');
+@define('DELETE_DIRECTORY_DESC', 'メディアファイル(恐らくあなたのエントリのうちのいくつかの中で使用されるファイル)を含むディレクトリの内容を削除をします。');
+@define('FORCE_DELETE', 'Serendipity でこのディレクトリ中の未知のものを含むファイルをすべて削除します。');
+@define('CREATE_DIRECTORY', 'ディレクトリの作成');
+@define('CREATE_NEW_DIRECTORY', '新規ディレクトリの作成');
+@define('CREATE_DIRECTORY_DESC', 'ここで、メディアファイルを中へ保存めに新しいディレクトリを作成することができます。新しいディレクトリの名前を選び、それを保存するオプションと親ディレクトリを選択します。');
+@define('BASE_DIRECTORY', 'ベースディレクトリ');
+@define('USERLEVEL_EDITOR_DESC', '標準の編集者');
+@define('USERLEVEL_CHIEF_DESC', 'チーフ編集者');
+@define('USERLEVEL_ADMIN_DESC', '管理者');
+@define('USERCONF_USERLEVEL', 'アクセスレベル');
+@define('USERCONF_USERLEVEL_DESC', 'このレベルはこのユーザがウェブログに対してどういう種類のアクセスを持つか決定するため使用されます。');
+@define('USER_SELF_INFO', '%s としてログイン中 (%s)');
+@define('ADMIN_ENTRIES', 'エントリ');
+@define('RECHECK_INSTALLATION', 'インストールの再検査');
+@define('IMAGICK_EXEC_ERROR', '実行できませんでした: "%s", エラー: %s, 返り値: %d');
+@define('INSTALL_OFFSET_DESC', 'ウェブサーバー(現在: %clock%)と希望の時間帯の時差を入力します。');
+@define('UNMET_REQUIREMENTS', '要求に失敗: %s');
+@define('CHARSET', '文字セット');
+@define('AUTOLANG', '訪問者が使用するブラウザーのデフォルト言語');
+@define('AUTOLANG_DESC', 'もし有効にしたならエントリとインターフェースの言語の決定は訪問者のブラウザーの言語設定を使用します。');
+@define('INSTALL_AUTODETECT_URL', '自動検知に HTTP-Host を使う');
+@define('INSTALL_AUTODETECT_URL_DESC', 'If set to "true", Serendipity will ensure that the HTTP Host which was used by your visitor is used as your BaseURL setting. Enabling this will let you be able to use multiple domain names for your Serendipity Blog, and use the domain for all follow-up links which the user used to access your blog.'); // Translate
+@define('CONVERT_HTMLENTITIES', 'HTML 実体への自動変換を試みますか?');
+@define('EMPTY_SETTING', '%s の値が正しく指定されていません!');
+@define('USERCONF_REALNAME', '本名');
+@define('USERCONF_REALNAME_DESC', '著作者のフルネームです。これは読者に見える名前です。');
+@define('HOTLINK_DONE', 'File hotlinked.<br />Done.'); // Translate
+@define('ENTER_MEDIA_URL_METHOD', '取得方法:');
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Note: If you choose to hotlink to server, make sure you have permission to hotlink to the designated website, or the website is yours. Hotlink allows you to use off-site images without storing them locally.'); // Translate
+@define('MEDIA_HOTLINKED', 'hotlinked'); // Translate
+@define('FETCH_METHOD_IMAGE', 'サーバーへ画像をダウンロード');
+@define('FETCH_METHOD_HOTLINK', 'Hotlink to server'); // Translate
+@define('DELETE_HOTLINK_FILE', 'Deleted the hotlinked file entitled <b>%s</b>'); // Translate
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', '電子メールアドレスを表示しますか?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/lang/serendipity_lang_ko.inc.php b/lang/serendipity_lang_ko.inc.php
new file mode 100644 (file)
index 0000000..76a41d6
--- /dev/null
@@ -0,0 +1,673 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Translation (c) by Park Dong-Suk and Erich Iseli <s9y@iseli.org>
+
+
+@define('LANG_CHARSET', 'UTF-8');
+@define('DATE_LOCALES', 'korean, ko, ko_KR');
+@define('DATE_FORMAT_ENTRY', '%Y-%m-%d %a');
+@define('DATE_FORMAT_SHORT', '%Y-%m-%d %H:%M');
+@define('WYSIWYG_LANG', 'en');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', '.');
+@define('NUMBER_FORMAT_THOUSANDS', ',');
+@define('LANG_DIRECTION', 'ltr');
+
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Serendipity Administration Suite');
+@define('HAVE_TO_BE_LOGGED_ON', 'You have to be logged in to view this page');
+@define('WRONG_USERNAME_OR_PASSWORD', 'You appear to have entered an invalid username or password');
+@define('APPEARANCE', 'Appearance');
+@define('MANAGE_STYLES', 'Manage styles');
+@define('CONFIGURE_PLUGINS', 'Configure Plugins');
+
+
+@define('CONFIGURATION', 'Configuration');
+@define('BACK_TO_BLOG', 'Back to Weblog');
+@define('LOGIN', 'Login');
+@define('LOGOUT', 'Logout');
+@define('LOGGEDOUT', 'Logged out.');
+@define('CREATE', 'Create');
+@define('SAVE', 'Save');
+@define('NAME', '이름');
+@define('CREATE_NEW_CAT', 'Create New Category');
+@define('I_WANT_THUMB', 'I want to use the thumbnail in my entry.');
+@define('I_WANT_BIG_IMAGE', 'I want to use the larger image in my entry.');
+@define('I_WANT_NO_LINK', ' I  want to display it as an image');
+@define('I_WANT_IT_TO_LINK', 'I want to display it as a link to this url:');
+@define('BACK', 'Back');
+@define('FORWARD', 'Forward');
+@define('ANONYMOUS', '익명');
+@define('NEW_TRACKBACK_TO', 'New trackback made to');
+@define('NEW_COMMENT_TO', 'New comment posted to');
+@define('RECENT', '최근…');
+@define('OLDER', '순서…');
+@define('DONE', 'Done');
+@define('WELCOME_BACK', 'Welcome back,');
+@define('TITLE', 'Title');
+@define('DESCRIPTION', 'Description');
+@define('PLACEMENT', 'Placement');
+@define('DELETE', 'Delete');
+@define('SAVE', 'Save');
+@define('UP', 'UP');
+@define('DOWN', 'DOWN');
+@define('ENTRIES', 'entries');
+@define('NEW_ENTRY', 'New entry');
+@define('EDIT_ENTRIES', 'Edit entries');
+@define('CATEGORIES', '목록');
+@define('WARNING_THIS_BLAHBLAH', "WARNING:\\nThis may take a long time if there are many images without thumbnails.");
+@define('CREATE_THUMBS', 'Rebuild Thumbs');
+@define('MANAGE_IMAGES', 'Manage images');
+@define('NAME', '이름');
+@define('EMAIL', '이메일');
+@define('HOMEPAGE', '홈페이지');
+@define('COMMENT', '꼬리말');
+@define('REMEMBER_INFO', '이름, 이메일, 홈페이지 기억하기');
+@define('SUBMIT_COMMENT', '등록');
+@define('NO_ENTRIES_TO_PRINT', '곧 새로운 글이 찾아옵니다. 화려한 컴백을 기대하세요');
+@define('COMMENTS', '꼬리말');
+@define('ADD_COMMENT', '꼬리말 쓰기');
+@define('NO_COMMENTS', '꼬리말 없습니다');
+@define('POSTED_BY', '글쓴 지구인:');
+@define('ON', 'on');
+@define('A_NEW_COMMENT_BLAHBLAH', 'A new comment has been posted on your blog "%s", in the entry entitled "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'A new trackback has been made to your blog-entry entitled "%s".');
+@define('NO_CATEGORY', 'No Category');
+@define('ENTRY_BODY', 'Entry Body');
+@define('EXTENDED_BODY', 'Extended Body');
+@define('CATEGORY', 'Category');
+@define('EDIT', 'Edit');
+@define('NO_ENTRIES_BLAHBLAH', 'No Entries Found for Query %s' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'Your search for %s returned %s results:');
+@define('SEARCH_TOO_SHORT', 'Your search-query must be longer than 3 characters');
+@define('IMAGE', 'Image');
+@define('ERROR_FILE_NOT_EXISTS', 'Error: Old filename doesn\'t exist!');
+@define('ERROR_FILE_EXISTS', 'Error: New filename already used, pick another!');
+@define('ERROR_SOMETHING', 'Error: Something\'s wrong.');
+@define('ADDING_IMAGE', 'Adding image...');
+@define('THUMB_CREATED_DONE', 'Thumbnail created.<br>Done.');
+@define('ERROR_FILE_EXISTS_ALREADY', 'Error: File already exists on your machine!');
+@define('ERROR_UNKNOWN_NOUPLOAD', 'Unknown error occured, file not uploaded. Maybe your filesize is larger than the maximum size allowed by your server installation. Check with your ISP or edit your php.ini file to allow larger file size uploads.');
+@define('GO', 'Go!');
+@define('NEWSIZE', 'New size: ');
+@define('RESIZE_BLAHBLAH', '<b>Resize %s</b><p>');
+@define('ORIGINAL_SIZE', 'Original size: <i>%sx%s</i> pixel');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>Here, you can adjust the image size. If you want to resize the image proportionally, just enter a value in one of the two boxes and press the TAB key --  I\'ll automatically calculate the new size so the image proportions don\'t get messed up</p>');
+@define('QUICKJUMP_CALENDAR', 'QuickJump Calendar');
+@define('QUICKSEARCH', '빨리찾기');
+@define('SEARCH_FOR_ENTRY', 'Search for an entry');
+@define('ARCHIVES', '문서 저장고');
+@define('BROWSE_ARCHIVES', 'Browse archives by month');
+@define('TOP_REFERRER', 'Top Referrers');
+@define('SHOWS_TOP_SITES', 'Shows top sites that linked to your blogs');
+@define('TOP_EXITS', 'Top Exits');
+@define('SHOWS_TOP_EXIT', 'Shows top exit links from your blogs');
+@define('SYNDICATION', 'Syndication');
+@define('SHOWS_RSS_BLAHBLAH', 'Shows RSS syndication links');
+@define('ADVERTISES_BLAHBLAH', 'Advertises the origins of your blog');
+@define('HTML_NUGGET', 'HTML Nugget');
+@define('HOLDS_A_BLAHBLAH', 'Holds a nugget of HTML in your sidebar');
+@define('TITLE_FOR_NUGGET', 'Title for the nugget');
+@define('THE_NUGGET', 'The Nugget of HTML!');
+@define('SYNDICATE_THIS_BLOG', 'Syndicate This Blog');
+@define('YOU_CHOSE', 'You chose %s');
+@define('IMAGE_ROTATE_LEFT', 'Rotate image 90 degrees counter-clockwise');
+@define('IMAGE_ROTATE_RIGHT', 'Rotate image 90 degrees clockwise');
+@define('IMAGE_SIZE', 'Image size');
+@define('IMAGE_AS_A_LINK', 'Image insertion');
+@define('POWERED_BY', '저작권');
+@define('TRACKBACKS', '전달하기');
+@define('TRACKBACK', '전달하기');
+@define('NO_TRACKBACKS', '아무도 이글을 전달을 안했군요!');
+@define('TOPICS_OF', 'Topics from');
+@define('VIEW_FULL', 'view full');
+@define('VIEW_TOPICS', 'view topics');
+@define('AT', 'at');
+@define('SET_AS_TEMPLATE', 'Set as template');
+@define('IN', 'in');
+@define('EXCERPT', 'Excerpt');
+@define('TRACKED', 'Tracked');
+@define('LINK_TO_ENTRY', 'Link to entry');
+@define('LINK_TO_REMOTE_ENTRY', 'Link to remote-entry');
+@define('IP_ADDRESS', 'IP-address');
+@define('USER', 'User');
+@define('THUMBNAIL_USING_OWN', 'Using %s as it\'s own thumbnail because it is so small already.');
+@define('THUMBNAIL_FAILED_COPY', 'Wanted to use %s as it\'s own thumbnail, but failed to copy!');
+@define('AUTHOR', 'Author');
+@define('LAST_UPDATED', 'Last Updated');
+@define('TRACKBACK_SPECIFIC', 'Trackback specific URI for this entry');
+@define('DIRECT_LINK', 'Direct link to this entry');
+@define('COMMENT_ADDED', '꼬리말이 성공적으로 등록되었습니다.');
+@define('COMMENT_ADDED_CLICK', 'Click %shere to return%s to the comments, and %shere to close%s this window.');
+@define('COMMENT_NOT_ADDED', '꼬리말을 달수 없습니다.');
+@define('COMMENT_NOT_ADDED_CLICK', 'Click %shere to return%s to the comments, and %shere to close%s this window.');
+@define('COMMENTS_DISABLE', 'Do not allow comments to this entry');
+@define('COMMENTS_ENABLE', 'Allow comments to this entry');
+@define('COMMENTS_CLOSED', 'The author does not allow comments to this entry');
+@define('EMPTY_COMMENT', 'Your comment did not contain anything, please %sgo back%s and try again');
+@define('ENTRIES_FOR', 'Entries from %s');
+@define('DOCUMENT_NOT_FOUND', 'The document %s was not found.');
+@define('USERNAME', 'Username');
+@define('PASSWORD', 'Password');
+@define('AUTOMATIC_LOGIN', 'Save information');
+@define('SERENDIPITY_INSTALLATION', 'Serendipity installation');
+@define('LEFT', 'left');
+@define('RIGHT', 'right');
+@define('HIDDEN', 'hidden');
+@define('REMOVE_TICKED_PLUGINS', 'Remove ticked plugins');
+@define('SAVE_CHANGES_TO_LAYOUT', 'Save changes to layout');
+@define('COMMENTS_FROM', 'Comments from');
+@define('ERROR', 'Error');
+@define('ENTRY_SAVED', 'Your entry has been saved');
+@define('DELETE_SURE', 'Are you sure you want to delete #%s permanently?');
+@define('NOT_REALLY', 'Not really...');
+@define('DUMP_IT', 'Dump it!');
+@define('RIP_ENTRY', 'R.I.P. entry #%s');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Category #%s deleted. Old articles moved to category #%s');
+@define('CATEGORY_DELETED', 'Category #%s deleted.');
+@define('INVALID_CATEGORY', 'No category was provided for deletion');
+@define('CATEGORY_SAVED', 'Category saved');
+@define('SELECT_TEMPLATE', 'Select the template you wish to use for your blog');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'Entries were not successfully inserted!');
+@define('MT_DATA_FILE', 'Movable Type data file');
+@define('FORCE', 'Force');
+@define('CREATE_AUTHOR', 'Create author \'%s\'.');
+@define('CREATE_CATEGORY', 'Create category \'%s\'.');
+@define('MYSQL_REQUIRED', 'You must have the MySQL extension in order to perform this action.');
+@define('COULDNT_CONNECT', 'Could not connect to MySQL database: %s.');
+@define('COULDNT_SELECT_DB', 'Could not select database: %s.');
+@define('COULDNT_SELECT_USER_INFO', 'Could not select user information: %s.');
+@define('COULDNT_SELECT_CATEGORY_INFO', 'Could not select category information: %s.');
+@define('COULDNT_SELECT_ENTRY_INFO', 'Could not select entry information: %s.');
+@define('COULDNT_SELECT_COMMENT_INFO', 'Could not select comment information: %s.');
+@define('YES', 'Yes');
+@define('NO', 'No');
+@define('USE_DEFAULT', 'Default');
+@define('CHECK_N_SAVE', 'Check &amp; save');
+@define('DIRECTORY_WRITE_ERROR', 'Can\'t write to directory %s. Check permissions.');
+@define('DIRECTORY_CREATE_ERROR', 'Directory %s does not exist and could not be created. Please manually create the directory');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; run <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', 'Can\'t execute the %s binary');
+@define('FILE_WRITE_ERROR', 'Can\'t write to file %s.');
+@define('FILE_CREATE_YOURSELF', 'Please create the file yourself or check permissions');
+@define('COPY_CODE_BELOW', '<br />* Just copy the code below and place it in %s in your %s folder:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Change www to the user apache runs as (i.e. nobody).');
+@define('BROWSER_RELOAD', 'Once you\'ve done this, hit your browser\'s "reload" button.');
+@define('DIAGNOSTIC_ERROR', 'We detected some errors while running some diagnostics on your entered information:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity is not yet installed. Please <a href="%s">install</a> it now.');
+@define('INCLUDE_ERROR', 'serendipity error: could not include %s - exiting.');
+@define('DATABASE_ERROR', 'serendipity error: unable to connect to database - exiting.');
+@define('CREATE_DATABASE', 'Creating default database setup...');
+@define('ATTEMPT_WRITE_FILE', 'Attemping to write %s file...');
+@define('WRITTEN_N_SAVED', 'Configuration written &amp; saved');
+@define('IMAGE_ALIGNMENT', 'Image alignment');
+@define('ENTER_NEW_NAME', 'Enter the new name for: ');
+@define('RESIZING', 'Resizing');
+@define('RESIZE_DONE', 'Done (resized %s images).');
+@define('SYNCING', 'Synchronizing the database with the image folder');
+@define('SYNC_DONE', 'Done (Synchronized %s images).');
+@define('FILE_NOT_FOUND', 'Unable to locate the file entitled <b>%s</b>, maybe it has already been deleted?');
+@define('ABORT_NOW', 'Abort now');
+@define('REMOTE_FILE_NOT_FOUND', 'File was not located on the remote server, are you sure the URL: <b>%s</b> is correct?');
+@define('FILE_FETCHED', '%s fetched as %s');
+@define('FILE_UPLOADED', 'File %s successfully uploaded as %s');
+@define('WORD_OR', 'Or');
+@define('SCALING_IMAGE', 'Scaling %s to %s x %s px');
+@define('KEEP_PROPORTIONS', 'Keep proportions');
+@define('REALLY_SCALE_IMAGE', 'Really scale the image? This operation cannot be undone!');
+@define('TOGGLE_ALL', 'Toggle expand all');
+@define('TOGGLE_OPTION', 'Toggle option');
+@define('SUBSCRIBE_TO_THIS_ENTRY', '꼬리말 이메일로 받기');
+@define('UNSUBSCRIBE_OK', "%s is now unsubscribed from this entry");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'New comment to subscribed entry "%s"');
+@define('SUBSCRIPTION_MAIL', "Hello %s,\n\nA new comment was made to the entry you are monitoring on \"%s\", entitled \"%s\"\nThe name of the poster is: %s\n\nYou can find the entry here: %s\n\nYou can unsubscribe by clicking on this link: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "Hello %s,\n\nA new trackback was added to the entry you are monitoring on \"%s\", entitled \"%s\"\nThe name of the poster is: %s\n\nYou can find the entry here: %s\n\nYou can unsubscribe by clicking on this link: %s\n");
+@define('SIGNATURE', "\n-- \n%s is powered by Serendipity.\nThe best blog around, you can use it too.\nCheck out <http://s9y.org> to find out how.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91 feed');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0 feed');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0 feed');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 comments');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3 feed');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'Field "managingEditor"');
+@define('SYNDICATION_PLUGIN_WEBMASTER', 'Field "webMaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'Image for the RSS feed');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', 'Image width');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'Image height');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC', 'E-Mail address of the webmaster, if available. (empty: hidden) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', 'E-Mail address of the managing editor, if available. (empty: hidden) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'URL of an image in GIF/JPEG/PNG format, if available. (empty: serendipity-logo)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'in pixels, max. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'in pixels, max. 400');
+@define('SYNDICATION_PLUGIN_TTL', 'Field "ttl" (time-to-live)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'Amount of minutes after which your blog should not be cached any more by foreign sites/applications (empty: hidden) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'Field "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', 'Should the "pubDate"-field be embedded for a RSS-channel, to show the date of the latest entry?');
+@define('CONTENT', 'Content');
+@define('TYPE', 'Type');
+@define('DRAFT', 'Draft');
+@define('PUBLISH', 'Publish');
+@define('PREVIEW', '미리보기');
+@define('DATE', 'Date');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', 'Warning: The date you specified was invalid. It has to be given in YYYY-MM-DD HH:MM format.');
+@define('CATEGORY_PLUGIN_DESC', 'Shows the list of categories.');
+@define('ALL_AUTHORS', 'All authors');
+@define('CATEGORIES_TO_FETCH', 'Categories to fetch');
+@define('CATEGORIES_TO_FETCH_DESC', 'Fetch categories from which author?');
+@define('PAGE_BROWSE_ENTRIES', '페이지 %s of %s, 총 %s 입력');
+@define('PREVIOUS_PAGE', '이전 제이지');
+@define('NEXT_PAGE', '다음 제이지');
+@define('ALL_CATEGORIES', '모든목록');
+@define('DO_MARKUP', 'Perform Markup Transformations');
+@define('DO_MARKUP_DESCRIPTION', 'Apply markup transformations to the text (smilies, shortcut markups via *, /, _, ...). Disabling this will preserve any HTML-code in the text.');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'Dateformatting');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'The format of the entry\'s actual date, using PHPs strftime() variables. (Default: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'Unable to open template file, please update serendipity!');
+@define('ADVANCED_OPTIONS', 'Advanced Options');
+@define('EDIT_ENTRY', 'Edit entry');
+@define('HTACCESS_ERROR', 'To check your local webserver installation, serendipity needs to be able to write the file ".htaccess". This was not possible because of permission errors. Please adjust the permissions like this: <br />&nbsp;&nbsp;%s<br />and reload this page.');
+@define('SIDEBAR_PLUGINS', 'Sidebar Plugins');
+@define('EVENT_PLUGINS', 'Event Plugins');
+@define('SORT_ORDER', 'Sort order');
+@define('SORT_ORDER_NAME', 'Filename');
+@define('SORT_ORDER_EXTENSION', 'File extension');
+@define('SORT_ORDER_SIZE', 'Filesize');
+@define('SORT_ORDER_WIDTH', 'Image width');
+@define('SORT_ORDER_HEIGHT', 'Image height');
+@define('SORT_ORDER_DATE', 'Upload date');
+@define('SORT_ORDER_ASC', 'Ascending');
+@define('SORT_ORDER_DESC', 'Descending');
+@define('THUMBNAIL_SHORT', 'Thumb');
+@define('ORIGINAL_SHORT', 'Orig.');
+@define('APPLY_MARKUP_TO', 'Apply markup to %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'Beginning of the week');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity has detected that your configuration is currently installed with version %s, however serendipity itself is installed as version %s, you need to upgrade! <a href="%s">Click here</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'Hi, and welcome to the Serendipity upgrade agent.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', 'I am here to help you upgrade your Serendipity %s installation.');
+@define('SERENDIPITY_UPGRADER_WHY', 'You are seeing this message because you have just installed Serendipity %s, but have not yet upgraded your database installation to fit this version');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'Database updates (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'I have found the following .sql files which needs to be run before you can continue normal operation of Serendipity');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC', 'Version specific tasks');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', 'No version specific tasks found');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', 'Do you wish me to perform the above tasks?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'No, I will run them manually');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'Yes, please do so');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'It appears you do not need any upgrades run');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', 'Consider Serendipity upgraded');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'You have ignored the upgrade stage of Serendipity, please make sure your database is correctly installed, and scheduled functions are run');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'Your Serendipity installation is now upgraded to version %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', 'You can return to your blog by clicking %shere%s');
+@define('MANAGE_USERS', 'Manage users');
+@define('CREATE_NEW_USER', 'Create new user');
+@define('CREATE_NOT_AUTHORIZED', 'You cannot modify users with the same userlevel as yourself');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'You cannot create users with a higher userlevel than yourself');
+@define('CREATED_USER', 'A new user %s has been created');
+@define('MODIFIED_USER', 'The properties of user %s have been changed');
+@define('USER_LEVEL', 'Userlevel');
+@define('DELETE_USER', 'You are about to delete user #%d %s. Are you serious? This will disallow showing any entries written by him on the frontend.');
+@define('DELETED_USER', 'User #%d %s deleted.');
+@define('LIMIT_TO_NUMBER', 'How many items should be displayed?');
+@define('ENTRIES_PER_PAGE', 'entries per page');
+@define('XML_IMAGE_TO_DISPLAY', 'XML Button');
+@define('XML_IMAGE_TO_DISPLAY_DESC','Links to XML Feeds will be displayed by this image. Leave empty for default, enter \'none\' to disable.');
+
+@define('DIRECTORIES_AVAILABLE', 'In the list of available subdirectories you can click on any directory name to create a new directory within that structure.');
+@define('ALL_DIRECTORIES', 'all directories');
+@define('MANAGE_DIRECTORIES', 'Manage directories');
+@define('DIRECTORY_CREATED', 'Directory <strong>%s</strong> has been created.');
+@define('PARENT_DIRECTORY', 'Parent directory');
+@define('CONFIRM_DELETE_DIRECTORY', 'Are you sure you want to remove all the contents of directory %s?');
+@define('ERROR_NO_DIRECTORY', 'Error: Directory %s does not exist');
+@define('CHECKING_DIRECTORY', 'Checking files in directory %s');
+@define('DELETING_FILE', 'Deleting file %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', 'Could not remove non-empty directory. Check the "force deletion" checkbox if you want to remove those files as well, and then submit again. Existing files are:');
+@define('DIRECTORY_DELETE_FAILED', 'Deletion of directory %s failed. Check permissions or messages above.');
+@define('DIRECTORY_DELETE_SUCCESS', 'Directory %s successfully deleted.');
+@define('SKIPPING_FILE_EXTENSION', 'Skipping file: Missing extension on %s.');
+@define('SKIPPING_FILE_UNREADABLE', 'Skipping file: %s not readable.');
+@define('FOUND_FILE', 'Found new/modified file: %s.');
+@define('ALREADY_SUBCATEGORY', '%s is a already a subcategory of %s.');
+@define('PARENT_CATEGORY', 'Parent category');
+@define('IN_REPLY_TO', '답글하기');
+@define('TOP_LEVEL', '첫째목록');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s feed');
+@define('PERMISSIONS', 'Permissions');
+@define('SETTINGS_SAVED_AT', 'The new settings have been saved at %s');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', 'Database settings');
+@define('INSTALL_CAT_DB_DESC', 'Here you can enter all your database information. Serendipity needs this to be able to function');
+@define('INSTALL_DBTYPE', 'Database type');
+@define('INSTALL_DBTYPE_DESC', 'Database type');
+@define('INSTALL_DBHOST', 'Database host');
+@define('INSTALL_DBHOST_DESC', 'The hostname for your database server');
+@define('INSTALL_DBUSER', 'Database user');
+@define('INSTALL_DBUSER_DESC', 'The username used to connect to your database');
+@define('INSTALL_DBPASS', 'Database password');
+@define('INSTALL_DBPASS_DESC', 'The password matching the above username');
+@define('INSTALL_DBNAME', 'Database name');
+@define('INSTALL_DBNAME_DESC', 'The name of your database');
+@define('INSTALL_DBPREFIX', 'Database table prefix');
+@define('INSTALL_DBPREFIX_DESC', 'Prefix for the table names, i.e. serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', 'Paths');
+@define('INSTALL_CAT_PATHS_DESC', 'Various paths to different essential folders and files. Don\'t forget trailing slashes for directories!');
+@define('INSTALL_FULLPATH', 'Full path');
+@define('INSTALL_FULLPATH_DESC', 'The full and absolute path to your serendipity installation');
+@define('INSTALL_UPLOADPATH', 'Upload path');
+@define('INSTALL_UPLOADPATH_DESC', 'All uploads will go here, relative to the \'Full path\' - typically \'uploads/\'');
+@define('INSTALL_RELPATH', 'Relative path');
+@define('INSTALL_RELPATH_DESC', 'Path to serendipity for your browser, typically \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', 'Relative template path');
+@define('INSTALL_RELTEMPLPATH_DESC', 'The path to the folder containing your templates - Relative to the \'relative path\'');
+@define('INSTALL_RELUPLOADPATH', 'Relative upload path');
+@define('INSTALL_RELUPLOADPATH_DESC', 'Path to your uploads for browsers - Relative to the \'relative path\'');
+@define('INSTALL_URL', 'URL to blog');
+@define('INSTALL_URL_DESC', 'Base URL to your serendipity installation');
+@define('INSTALL_INDEXFILE', 'Index file');
+@define('INSTALL_INDEXFILE_DESC', 'The name of your serendipity index file');
+
+/* Generel settings */
+@define('INSTALL_CAT_SETTINGS', 'General settings');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Customize how Serendipity behaves');
+@define('INSTALL_USERNAME', 'Admin username');
+@define('INSTALL_USERNAME_DESC', 'Username for admin login');
+@define('INSTALL_PASSWORD', 'Admin password');
+@define('INSTALL_PASSWORD_DESC', 'Password for admin login');
+@define('INSTALL_EMAIL', 'Admin email');
+@define('INSTALL_EMAIL_DESC', 'Email for the blog administrator');
+@define('INSTALL_SENDMAIL', 'Send mails to admin?');
+@define('INSTALL_SENDMAIL_DESC', 'Do you want to receive emails when comments are posted to your entries?');
+@define('INSTALL_SUBSCRIBE', 'Allow users to subscribe to entries?');
+@define('INSTALL_SUBSCRIBE_DESC', 'Allow users to subscribe to an entry and thereby receive a mail when new comments are made to that entry');
+@define('INSTALL_BLOGNAME', 'Blog name');
+@define('INSTALL_BLOGNAME_DESC', 'The title of your blog');
+@define('INSTALL_BLOGDESC', 'Blog description');
+@define('INSTALL_BLOGDESC_DESC', 'Description of your blog');
+@define('INSTALL_LANG', 'Language');
+@define('INSTALL_LANG_DESC', 'Select the language for your blog');
+
+/* Appearance and options */
+@define('INSTALL_CAT_DISPLAY', 'Appearance and options');
+@define('INSTALL_CAT_DISPLAY_DESC', 'Customize how Serendipity looks and feels');
+@define('INSTALL_WYSIWYG', 'Use WYSIWYG editor');
+@define('INSTALL_WYSIWYG_DESC', 'Do you want to use the WYSIWYG editor? (Works on IE5+, partially in Mozilla 1.3+)');
+@define('INSTALL_XHTML11', 'Force XHTML 1.1 compliance');
+@define('INSTALL_XHTML11_DESC', 'Do you want to force XHTML 1.1 compliance (may cause problems for back-/frontend on older 4th generation browsers)');
+@define('INSTALL_POPUP', 'Enable use of popup windows');
+@define('INSTALL_POPUP_DESC', 'Do you want to use popup windows for comments, trackbacks et al?');
+@define('INSTALL_EMBED', 'Is serendipity embedded?');
+@define('INSTALL_EMBED_DESC', 'If you want to embed serendipity within a regular page, set to true to discard any headers and just print the contents. You can make use of the indexFile option to use a wrapper class where you put your normal webpage headers. See the README file for more information!');
+@define('INSTALL_TOP_AS_LINKS', 'Show Top Exits/Referrers as links?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"no": Exits and Referrers are shown as plain text to prevent google spam. "yes": Exits and Referrers are shown as hyperlinks. "default": Use setting from global configuration (recommended).');
+@define('INSTALL_BLOCKREF', 'Blocked Referers');
+@define('INSTALL_BLOCKREF_DESC', 'Are there any special hosts you want not to show up in the referers list? Separate the list of hostnames with \';\' and note that the host is blocked by substring matches!');
+@define('INSTALL_REWRITE', 'URL Rewriting');
+@define('INSTALL_REWRITE_DESC', 'Select which rules you wish to use when generating URLs. Enabling rewrite rules will make pretty URLs for your blog and make it better indexable for spiders like google. The webserver needs to support either mod_rewrite or "AllowOverride All" for your serendipity dir. The default setting is auto-detected');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', 'Imageconversion Settings');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'Enter general information about how serendipity should handle Images');
+@define('INSTALL_IMAGEMAGICK', 'Use Imagemagick');
+@define('INSTALL_IMAGEMAGICK_DESC', 'Do you have image magick installed and want to use it to resize images?');
+@define('INSTALL_IMAGEMAGICKPATH', 'Path to convert binary');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'Full path & name of your image magick convert binary');
+@define('INSTALL_THUMBSUFFIX', 'Thumbnail suffix');
+@define('INSTALL_THUMBSUFFIX_DESC', 'Thumbnails will be named with the following format: original.[suffix].ext');
+@define('INSTALL_THUMBWIDTH', 'Thumbnail dimensions');
+@define('INSTALL_THUMBWIDTH_DESC', 'Static maximum width of auto-generated thumbnails');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', 'Your personal details');
+@define('USERCONF_CAT_PERSONAL_DESC', 'Change your personal details');
+@define('USERCONF_USERNAME', 'Your username');
+@define('USERCONF_USERNAME_DESC', 'The username you use to log in to the blog');
+@define('USERCONF_PASSWORD', 'Your password');
+@define('USERCONF_PASSWORD_DESC', 'The password you wish to use to log in to the blog');
+@define('USERCONF_EMAIL', 'Your e-mail address');
+@define('USERCONF_EMAIL_DESC', 'Your personal e-mail address');
+@define('USERCONF_SENDCOMMENTS', 'Send comment announcements?');
+@define('USERCONF_SENDCOMMENTS_DESC', 'Do you want to receive emails when comments are posted to your entries?');
+@define('USERCONF_SENDTRACKBACKS', 'Send trackback announcements?');
+@define('USERCONF_SENDTRACKBACKS_DESC', 'Do you want to receive emails when trackbacks are posted to your entries?');
+@define('USERCONF_ALLOWPUBLISH', 'Rights: Publishing entries?');
+@define('USERCONF_ALLOWPUBLISH_DESC', 'Is this user allowed to publish entries?');
+@define('SUCCESS', 'Success');
+@define('POWERED_BY_SHOW_TEXT', 'Show "Serendipity" as text');
+@define('POWERED_BY_SHOW_TEXT_DESC', 'Will display "Serendipity Weblog" as text');
+@define('POWERED_BY_SHOW_IMAGE', 'Show "Serendipity" with a logo');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Displays the Serendipity logo');
+@define('PLUGIN_ITEM_DISPLAY', 'Where should the item be displayed?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'Extended entry only');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'Overview page only');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'All times');
+@define('RSS_IMPORT_CATEGORY', 'Use this category for non-matching imported entries');
+
+@define('COMMENTS_WILL_BE_MODERATED', 'Submitted comments will be subject to moderation before being displayed.');
+@define('YOU_HAVE_THESE_OPTIONS', 'You have the following options available:');
+@define('THIS_COMMENT_NEEDS_REVIEW', 'Warning: This comment needs approval before it will be displayed');
+@define('DELETE_COMMENT', 'Delete comment');
+@define('APPROVE_COMMENT', 'Approve comment');
+@define('REQUIRES_REVIEW', 'Requires review');
+@define('COMMENT_APPROVED', 'Comment #%s has successfully been approved');
+@define('COMMENT_DELETED', 'Comment #%s has successfully been deleted');
+@define('COMMENTS_MODERATE', 'Comments & trackbacks to this entry requires moderation');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'Warning: This trackback needs approval before it will be displayed');
+@define('DELETE_TRACKBACK', 'Delete trackback');
+@define('APPROVE_TRACKBACK', 'Approve trackback');
+@define('TRACKBACK_APPROVED', 'Trackback #%s has successfully been approved');
+@define('TRACKBACK_DELETED', 'Trackback #%s has successfully been deleted');
+@define('VIEW', 'View');
+@define('COMMENT_ALREADY_APPROVED', 'Comment #%s appears to already have been approved');
+@define('COMMENT_EDITED', 'The selected comment has been edited');
+@define('HIDE', 'Hide');
+@define('VIEW_EXTENDED_ENTRY', 'Continue reading "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'This link is not meant to be clicked. It contains the trackback URI for this entry. You can use this URI to send ping- & trackbacks from your own blog to this entry. To copy the link, right click and select "Copy Shortcut" in Internet Explorer or "Copy Link Location" in Mozilla.');
+@define('PLUGIN_SUPERUSER_HTTPS', 'Use https for login');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'Lets the login-link point to a https-location. Your webserver needs to support this!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'Make external links clickable?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"no": Unchecked external links (Top Exits, Top Referrers, User comments) are not shown/shown as plain text where applicable to prevent google spam (recommended). "yes": Unchecked external links are shown as hyperlinks. Can be overridden within sidebar plugin configuration!');
+@define('PAGE_BROWSE_COMMENTS', 'Page %s of %s, totalling %s comments');
+@define('FILTERS', 'Filters');
+@define('FIND_ENTRIES', 'Find entries');
+@define('FIND_COMMENTS', 'Find comments');
+@define('FIND_MEDIA', 'Find media');
+@define('FILTER_DIRECTORY', 'Directory');
+@define('SORT_BY', 'Sort by');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'No Trackback sent: Could not open connection to %s on port %d');
+@define('MEDIA', 'Media');
+@define('MEDIA_LIBRARY', 'Media library');
+@define('ADD_MEDIA', 'Add media');
+@define('ENTER_MEDIA_URL', 'Enter an URL of a file to fetch:');
+@define('ENTER_MEDIA_UPLOAD', 'Select a file you wish to upload:');
+@define('SAVE_FILE_AS', 'Save the file as:');
+@define('STORE_IN_DIRECTORY', 'Store inside the following directory: ');
+@define('ADD_MEDIA_BLAHBLAH', '<b>Add a file to your media repository:</b><p>Here you can upload mediafiles, or tell me to fetch them from somewhere in the web! If you don\'t have an appropriate image, <a href="http://images.google.com" target="_blank">search for images on google</a> matching your thoughts, the results are often useful and funny :)<p><b>Select method:</b><br>');
+@define('MEDIA_RENAME', 'Rename this file');
+@define('IMAGE_RESIZE', 'Resize this image');
+@define('MEDIA_DELETE', 'Delete this file');
+@define('FILES_PER_PAGE', 'Files per page');
+@define('CLICK_FILE_TO_INSERT', 'Click the file you want to insert:');
+@define('SELECT_FILE', 'Select file to insert');
+@define('MEDIA_FULLSIZE', 'Fullsize');
+@define('CALENDAR_BOW_DESC', 'The day of the week that should be considered the beginning of the week. Default is Monday');
+@define('SUPERUSER', 'Blog Administration');
+@define('ALLOWS_YOU_BLAHBLAH', 'Provides a link in the sidebar to your blog administration');
+@define('CALENDAR', '달력');
+@define('SUPERUSER_OPEN_ADMIN', 'Open administration');
+@define('SUPERUSER_OPEN_LOGIN', 'Open login screen');
+@define('INVERT_SELECTIONS', 'Invert Selections');
+@define('COMMENTS_DELETE_CONFIRM', 'Are you sure you wish to delete the selected comments?');
+@define('COMMENT_DELETE_CONFIRM', 'Are you sure you wish to delete comment #%d, written by %s?');
+@define('DELETE_SELECTED_COMMENTS', 'Delete selected comments');
+@define('VIEW_COMMENT', 'View comment');
+@define('VIEW_ENTRY', 'View entry');
+@define('DELETE_FILE_FAIL', 'Unable to delete file <b>%s</b>');
+@define('DELETE_THUMBNAIL', 'Deleted the image thumbnail entitled <b>%s</b>');
+@define('DELETE_FILE', 'Deleted the file entitled <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', 'You are about to delete <b>%s</b><br />If you are using this file in some of your entries, it will cause dead links or images<br />Are you sure you wish to proceed?<br /><br />');
+@define('TRACKBACK_SENDING', 'Sending trackback to URI %s...');
+@define('TRACKBACK_SENT', 'Trackback successful');
+@define('TRACKBACK_FAILED', 'Trackback failed: %s');
+@define('TRACKBACK_NOT_FOUND', 'No trackback-URI found.');
+@define('TRACKBACK_URI_MISMATCH', 'The autodiscovered trackback URI does not match our target URI.');
+@define('TRACKBACK_CHECKING', 'Checking <u>%s</u> for possible trackbacks...');
+@define('TRACKBACK_NO_DATA', 'Target contained no data');
+@define('TRACKBACK_SIZE', 'Target URI exceeded maximum filesize of %s bytes.');
+@define('COMMENTS_VIEWMODE_THREADED', '답글');
+@define('COMMENTS_VIEWMODE_LINEAR', '연대순');
+@define('DISPLAY_COMMENTS_AS', '답글 형식');
+@define('COMMENTS_FILTER_SHOW', 'Show');
+@define('COMMENTS_FILTER_ALL', 'All');
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'Only approved');
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'Pending approval');
+@define('RSS_IMPORT_BODYONLY', 'Put all imported text in the "body" section and do not split up into "extended entry" section.');
+@define('SYNDICATION_PLUGIN_FULLFEED', 'Show full articles with extended body inside RSS feed');
+@define('WEEK', 'Week');
+@define('WEEKS', 'Weeks');
+@define('MONTHS', 'Months');
+@define('DAYS', 'Days');
+@define('ARCHIVE_FREQUENCY', 'Calendar item frequency');
+@define('ARCHIVE_FREQUENCY_DESC', 'The calendar interval to use between each item in the list');
+@define('ARCHIVE_COUNT', 'Number of items in the list');
+@define('ARCHIVE_COUNT_DESC', 'The total number of months, weeks or days to display');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'Below is a list of installed plugins');
+@define('SIDEBAR_PLUGIN', 'sidebar plugin');
+@define('EVENT_PLUGIN', 'event plugin');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'Click here to install a new %s');
+@define('VERSION', 'version');
+@define('INSTALL', 'Install');
+@define('ALREADY_INSTALLED', 'Already installed');
+@define('SELECT_A_PLUGIN_TO_ADD', 'Select the plugin which you wish to install');
+@define('INSTALL_OFFSET', 'Server time Offset');
+@define('STICKY_POSTINGS', 'Sticky Postings');
+@define('INSTALL_FETCHLIMIT', 'Entries to display on frontpage');
+@define('INSTALL_FETCHLIMIT_DESC', 'Number of entries to display for each page on the frontend');
+@define('IMPORT_ENTRIES', 'Import data');
+@define('EXPORT_ENTRIES', 'Export entries');
+@define('IMPORT_WELCOME', 'Welcome to the Serendipity import utility');
+@define('IMPORT_WHAT_CAN', 'Here you can import entries from other weblog software applications');
+@define('IMPORT_SELECT', 'Please select the software you wish to import from');
+@define('IMPORT_PLEASE_ENTER', 'Please enter the data as requested below');
+@define('IMPORT_NOW', 'Import now!');
+@define('IMPORT_STARTING', 'Starting import procedure...');
+@define('IMPORT_FAILED', 'Import failed');
+@define('IMPORT_DONE', 'Import successfully completed');
+@define('IMPORT_WEBLOG_APP', 'Weblog application');
+@define('EXPORT_FEED', 'Export full RSS feed');
+@define('STATUS', 'Status after import');
+@define('IMPORT_GENERIC_RSS', 'Generic RSS import');
+@define('ACTIVATE_AUTODISCOVERY', 'Send Trackbacks to links found in the entry');
+@define('WELCOME_TO_ADMIN', 'Welcome to the Serendipity Administration Suite.');
+@define('PLEASE_ENTER_CREDENTIALS', 'Please enter your credentials below.');
+@define('ADMIN_FOOTER_POWERED_BY', 'Powered by Serendipity %s and PHP %s');
+@define('INSTALL_USEGZIP', 'Use gzip compressed pages');
+@define('INSTALL_USEGZIP_DESC', 'To speed up delivery of pages, we can compress the pages we send to the visitor, given that his browser supports this. This is recommended');
+@define('INSTALL_SHOWFUTURE', 'Show future entries');
+@define('INSTALL_SHOWFUTURE_DESC', 'If enabled, this will show all entries in the future on your blog. Default is to hide those entries and only show them if the publish date has arrived.');
+@define('INSTALL_DBPERSISTENT', 'Use persistent connections');
+@define('INSTALL_DBPERSISTENT_DESC', 'Enable the usage of persistent database connections, read more <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">here</a>. This is normally not recommended');
+@define('NO_IMAGES_FOUND', 'No images found');
+@define('PERSONAL_SETTINGS', 'Personal Settings');
+@define('REFERER', 'Referer');
+@define('NOT_FOUND', 'Not found');
+@define('WRITABLE', 'Writable');
+@define('NOT_WRITABLE', 'Not writable');
+@define('PROBLEM_DIAGNOSTIC', 'Due to a problematic diagnostic, you cannot continue with the installation before the above errors are fixed');
+@define('SELECT_INSTALLATION_TYPE', 'Select which installation type you wish to use');
+@define('WELCOME_TO_INSTALLATION', 'Welcome to the Serendipity Installation');
+@define('FIRST_WE_TAKE_A_LOOK', 'First we will take a look at your current setup and attempt to diagnose any compatibility problems');
+@define('ERRORS_ARE_DISPLAYED_IN', 'Errors are displayed in %s, recommendations in %s and success in %s');
+@define('RED', 'red');
+@define('YELLOW', 'yellow');
+@define('GREEN', 'green');
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s pre-installation report');
+@define('RECOMMENDED', 'Recommended');
+@define('ACTUAL', 'Actual');
+@define('PHPINI_CONFIGURATION', 'php.ini configuration');
+@define('PHP_INSTALLATION', 'PHP installation');
+@define('THEY_DO', 'they do');
+@define('THEY_DONT', 'they don\'t');
+@define('SIMPLE_INSTALLATION', 'Simple installation');
+@define('EXPERT_INSTALLATION', 'Expert installation');
+@define('COMPLETE_INSTALLATION', 'Complete installation');
+@define('WONT_INSTALL_DB_AGAIN', 'won\'t install the database again');
+@define('CHECK_DATABASE_EXISTS', 'Checking to see if the database and tables already exists');
+@define('CREATING_PRIMARY_AUTHOR', 'Creating primary author \'%s\'');
+@define('SETTING_DEFAULT_TEMPLATE', 'Setting default template');
+@define('INSTALLING_DEFAULT_PLUGINS', 'Installing default plugins');
+@define('SERENDIPITY_INSTALLED', 'Serendipity has been successfully installed');
+@define('VISIT_BLOG_HERE', 'Visit your new blog here');
+@define('THANK_YOU_FOR_CHOOSING', 'Thank you for choosing Serendipity');
+@define('ERROR_DETECTED_IN_INSTALL', 'An error was detected in the installation');
+@define('OPERATING_SYSTEM', 'Operating system');
+@define('WEBSERVER_SAPI', 'Webserver SAPI');
+@define('TEMPLATE_SET', '\'%s\' has been set as your active template');
+@define('SEARCH_ERROR', 'The search function did not work as expected. Notice for the administrator of this blog: This may happen because of missing index keys in your database. On MySQL systems your database user account needs to be privileged to execute this query: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> The specific error returned by the database was: <pre>%s</pre>');
+@define('EDIT_THIS_CAT', 'Editing "%s"');
+@define('CATEGORY_REMAINING', 'Delete this category and move its entries to this category');
+@define('CATEGORY_INDEX', 'Below is a list of categories available to your entries');
+@define('NO_CATEGORIES', 'No categories');
+@define('RESET_DATE', 'Reset date');
+@define('RESET_DATE_DESC', 'Click here to reset the date to the current time');
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Permissions can be set by running shell command: `<em>%s</em>` on the failed directory, or by setting this using an FTP program');
+@define('WARNING_TEMPLATE_DEPRECATED', 'Warning: Your current template is using a deprecated template method, you are advised to update if possible');
+@define('ENTRY_PUBLISHED_FUTURE', 'This entry is not yet published.');
+@define('ENTRIES_BY', 'Entries by %s');
+@define('PREVIOUS', 'Previous');
+@define('NEXT', 'Next');
+@define('APPROVE', 'Approve');
+@define('CATEGORY_ALREADY_EXIST', 'A category with the name "%s" already exist');
+@define('IMPORT_NOTES', 'Note:'); // Translate
+@define('ERROR_FILE_FORBIDDEN', 'You are not allowed to upload files with active content'); // Translate
+@define('ADMIN', 'Administration'); // Re-Translate
+@define('ADMIN_FRONTPAGE', 'Frontpage'); // Translate
+@define('QUOTE', 'Quote'); // Translate
+@define('IFRAME_SAVE', 'Serendipity is now saving your entry, creating trackbacks and performing possible XML-RPC calls. This may take a while..'); // Translate
+@define('IFRAME_SAVE_DRAFT', 'A draft of this entry has been saved'); // Translate
+@define('IFRAME_PREVIEW', 'Serendipity is now creating the preview of your entry...'); // Translate
+@define('IFRAME_WARNING', 'Your browser does not support the concept of iframes. Please open your serendipity_config.inc.php file and set $serendipity[\'use_iframe\'] variable to FALSE.'); // Translate
+@define('NONE', 'none');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Default settings for new entries'); // Translate
+@define('UPGRADE', 'Upgrade'); // Translate
+@define('UPGRADE_TO_VERSION', 'Upgrade to version %s'); // Translate
+@define('DELETE_DIRECTORY', 'Delete directory'); // Translate
+@define('DELETE_DIRECTORY_DESC', 'You are about to delete the contents of a directory that contains media files, possibly files used in some of your entries.'); // Translate
+@define('FORCE_DELETE', 'Delete ALL files in this directory, including those not known by Serendipity'); // Translate
+@define('CREATE_DIRECTORY', 'Create directory'); // Translate
+@define('CREATE_NEW_DIRECTORY', 'Create new directory'); // Translate
+@define('CREATE_DIRECTORY_DESC', 'Here you can create a new directory to place media files in. Choose the name for your new directory and select an optional parent directory to place it in.'); // Translate
+@define('BASE_DIRECTORY', 'Base directory'); // Translate
+@define('USERLEVEL_EDITOR_DESC', 'Standard editor'); // Translate
+@define('USERLEVEL_CHIEF_DESC', 'Chief editor'); // Translate
+@define('USERLEVEL_ADMIN_DESC', 'Administrator'); // Translate
+@define('USERCONF_USERLEVEL', 'Access level'); // Translate
+@define('USERCONF_USERLEVEL_DESC', 'This level is used to determine what kind of access this user has to the blog'); // Translate
+@define('USER_SELF_INFO', 'Logged in as %s (%s)'); // Translate
+@define('ADMIN_ENTRIES', 'Entries'); // Translate
+@define('RECHECK_INSTALLATION', 'Recheck installation'); // Translate
+@define('IMAGICK_EXEC_ERROR', 'Unable to execute: "%s", error: %s, return var: %d'); // Translate
+@define('INSTALL_OFFSET_DESC', 'Enter the amount of hours between the date of your webserver (current: %clock%) and your desired time zone'); // Translate
+@define('UNMET_REQUIREMENTS', 'Requirements failed: %s'); // Translate
+@define('CHARSET', 'Charset');
+@define('AUTOLANG', 'Use visitor\'s browser language as default');
+@define('AUTOLANG_DESC', 'If enabled, this will use the visitor\'s browser language setting to determine the default language of your entry and interface language.');
+@define('INSTALL_AUTODETECT_URL', 'Autodetect used HTTP-Host'); // Translate
+@define('INSTALL_AUTODETECT_URL_DESC', 'If set to "true", Serendipity will ensure that the HTTP Host which was used by your visitor is used as your BaseURL setting. Enabling this will let you be able to use multiple domain names for your Serendipity Blog, and use the domain for all follow-up links which the user used to access your blog.'); // Translate
+@define('CONVERT_HTMLENTITIES', 'Try to auto-convert HTML entities?');
+@define('EMPTY_SETTING', 'You did not specify a valid value for "%s"!');
+@define('USERCONF_REALNAME', 'Real name'); // Translate
+@define('USERCONF_REALNAME_DESC', 'The full name of the author. This is the name seen by readers'); // Translate
+@define('HOTLINK_DONE', 'File hotlinked.<br />Done.'); // Translate
+@define('ENTER_MEDIA_URL_METHOD', 'Fetch method:'); // Translate
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Note: If you choose to hotlink to server, make sure you have permission to hotlink to the designated website, or the website is yours. Hotlink allows you to use off-site images without storing them locally.'); // Translate
+@define('MEDIA_HOTLINKED', 'hotlinked'); // Translate
+@define('FETCH_METHOD_IMAGE', 'Download image to your server'); // Translate
+@define('FETCH_METHOD_HOTLINK', 'Hotlink to server'); // Translate
+@define('DELETE_HOTLINK_FILE', 'Deleted the hotlinked file entitled <b>%s</b>'); // Translate
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Show E-Mail addresses?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_nl.inc.php b/lang/serendipity_lang_nl.inc.php
new file mode 100644 (file)
index 0000000..719542f
--- /dev/null
@@ -0,0 +1,672 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Translation (c) by Christiaan Heerze <webmaster@heimp.nl>
+# http://www.heimp.nl
+
+@define('LANG_CHARSET', 'ISO-8859-1');
+@define('DATE_LOCALES', 'dutch, nl_BE, nl, nl_BE.ISO8859-1');
+@define('DATE_FORMAT_ENTRY', '%A, %e %B %Y');
+@define('DATE_FORMAT_SHORT', '%d-m%-%Y %H:%M');
+@define('WYSIWYG_LANG', 'nl');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', ',');
+@define('NUMBER_FORMAT_THOUSANDS', '.');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Serendipity Beheer');
+@define('HAVE_TO_BE_LOGGED_ON', 'U moet zijn ingelogd om deze pagina te kunnen bekijken');
+@define('WRONG_USERNAME_OR_PASSWORD', 'Waarschijnlijk heeft u een ongeldige gebruikersnaam of wachtwoord ingevoerd.');
+@define('APPEARANCE', 'Uiterlijk');
+@define('MANAGE_STYLES', 'Beheer stijlen');
+@define('CONFIGURE_PLUGINS', 'Configureer Plugins');
+@define('CONFIGURATION', 'Configuratie');
+@define('BACK_TO_BLOG', 'Terug naar het Weblog');
+@define('LOGIN', 'Aanmelden');
+@define('LOGOUT', 'Afmelden');
+@define('LOGGEDOUT', 'Afgemeld.');
+@define('CREATE', 'Aanmaken');
+@define('EDIT_THIS_CAT', 'Bewerken "%s - %s"');
+@define('SAVE', 'Opslaan');
+@define('NAME', 'Naam');
+@define('CREATE_NEW_CAT', 'Maak een nieuwe categorie aan');
+@define('I_WANT_THUMB', 'Ik wil graag een indexplaatje in mijn artikel gebruiken.');
+@define('I_WANT_BIG_IMAGE', 'Ik wil graag de volledige afbeeldingen in mijn artikel gebruiken.');
+@define('I_WANT_NO_LINK', ' Ik wil het graag laten weergeven als een afbeelding');
+@define('I_WANT_IT_TO_LINK', 'Ik wil het graag als een verwijzing weergeven naar de volgende pagina:');
+@define('BACK', 'Terug');
+@define('FORWARD', 'Verder');
+@define('ANONYMOUS', 'Anoniem');
+@define('NEW_TRACKBACK_TO', 'Nieuwe trackback gemaakt voor');
+@define('NEW_COMMENT_TO', 'Nieuwe reactie op');
+@define('RECENT', 'Recentelijk...');
+@define('OLDER', 'Ouder...');
+@define('DONE', 'Gedaan');
+@define('WELCOME_BACK', 'Welkom terug,');
+@define('TITLE', 'Onderwerp');
+@define('DESCRIPTION', 'Beschrijving');
+@define('PLACEMENT', 'Placement');
+@define('DELETE', 'Verwijderen');
+@define('SAVE', 'Opslaan');
+@define('UP', 'OP');
+@define('DOWN', 'NEER');
+@define('ENTRIES', 'inzendingen');
+@define('NEW_ENTRY', 'Nieuwe inzending');
+@define('EDIT_ENTRIES', 'Bewerk inzendingen');
+@define('CATEGORIES', 'Categorieën');
+@define('WARNING_THIS_BLAHBLAH', "WAARSCHUWING:\\nDit kan veel tijd in beslag nemen als er veel grote afbeeldingen zijn, zonder index-afbeelding.");
+@define('CREATE_THUMBS', 'Creër nieuwe index-afbeeldingen');
+@define('MANAGE_IMAGES', 'Beheer afbeeldingen');
+@define('NAME', 'Naam');
+@define('EMAIL', 'E-mail');
+@define('HOMEPAGE', 'Webpagina');
+@define('COMMENT', 'Reactie');
+@define('REMEMBER_INFO', 'Onthoud Informatie? ');
+@define('SUBMIT_COMMENT', 'Reactie plaatsen');
+@define('NO_ENTRIES_TO_PRINT', 'Er zijn geen inzendingen af te drukken');
+@define('COMMENTS', 'Reacties');
+@define('ADD_COMMENT', 'Reactie toevoegen');
+@define('NO_COMMENTS', 'Geen reacties');
+@define('POSTED_BY', 'Geplaatst door');
+@define('ON', 'aan');
+@define('A_NEW_COMMENT_BLAHBLAH', 'Er is een nieuwe reactie geplaatst op uw Weblog "%s", op inzending met onderwerp "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'Een nieuwe trackback naar uw website is aangemaakt naar uw Weblog-inzending met onderwerp "%s".');
+@define('NO_CATEGORY', 'Geen categorie');
+@define('ENTRY_BODY', 'Verkorte inzending');
+@define('EXTENDED_BODY', 'Uitgebreide inzending');
+@define('CATEGORY', 'Categorie');
+@define('EDIT', 'Bewerk');
+@define('NO_ENTRIES_BLAHBLAH', 'Er zijn geen inzendingen gevonden voor zoekopdracht %s' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'Uw zoekopdracht naar %s heeft %s zoekresultaten opgeleverd:');
+@define('SEARCH_TOO_SHORT', 'Uw zoekopdracht moet uit meer dan 3 karakters bestaan');
+@define('IMAGE', 'Afbeelding');
+@define('ERROR_FILE_NOT_EXISTS', 'Fout: Oude bestandsnaam bestaat niet!');
+@define('ERROR_FILE_EXISTS', 'Fout: Nieuwe bestandsnaam is reeds in gebruik, kies een andere!');
+@define('ERROR_SOMETHING', 'Fout: Er gaat iets fout');
+@define('ADDING_IMAGE', 'Afbeelding toevoegen...');
+@define('THUMB_CREATED_DONE', 'Index-afbeelding gemaakt.<br>Succesvol.');
+@define('ERROR_FILE_EXISTS_ALREADY', 'Fout: Bestand bestaat al!');
+@define('ERROR_UNKNOWN_NOUPLOAD', 'Er is een onbekende fout opgetreden, het bestand is niet verzonden. Misschien is het bestand groter dan uw server toestaat. Controlleer dit bij uw provider of bewerk uw php.ini zodat deze grotere bestanden toe laat.');
+@define('GO', 'Uitvoeren!');
+@define('NEWSIZE', 'Nieuwe grootte: ');
+@define('RESIZE_BLAHBLAH', '<b>Vergroten/Verkleinen %s</b><p>');
+@define('ORIGINAL_SIZE', 'Originele grootte: <i>%sx%s</i> pixel');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>Hier kunt u de grootte van de afbeelding aanpassen. Als u de afbeeldingsverhoudingen wilt behouden, voer dan een waarde in een van de velden een grootte in en druk op de TAB-toets -- Het programma zal dan zelf de andere grootte berekenen zodat de verhoudingen hetzelfde blijven</p>');
+@define('QUICKJUMP_CALENDAR', 'Quickjump Kalender');
+@define('QUICKSEARCH', 'Zoeken');
+@define('SEARCH_FOR_ENTRY', 'Zoek naar een inzending');
+@define('ARCHIVES', 'Archief');
+@define('BROWSE_ARCHIVES', 'Doorzoek het archief, per maand');
+@define('TOP_REFERRER', 'Top Referrer');
+@define('SHOWS_TOP_SITES', 'Hier worden websites weergegeven die regelmatig naar uw website verwijzen of waar regelmatig lezers vandaan komen');
+@define('TOP_EXITS', 'Top Exits');
+@define('SHOWS_TOP_EXIT', 'Hier worden de, door u geplaatste, links getoond die regelmatig door uw lezers bekeken worden');
+@define('SYNDICATION', 'Syndication');
+@define('SHOWS_RSS_BLAHBLAH', 'Toont de RSS Syndication-Links');
+@define('ADVERTISES_BLAHBLAH', 'Toont een link waar anderen Serendipity software kunnen downloaden');
+@define('HTML_NUGGET', 'HTML Invoer');
+@define('HOLDS_A_BLAHBLAH', 'Een stukje waarin u uw eigen HTML-tekst kunt schrijven, deze verschijnt aan de zijkant');
+@define('TITLE_FOR_NUGGET', 'Naam van het stuk');
+@define('THE_NUGGET', 'The Nugget of HTML!');
+@define('SYNDICATE_THIS_BLOG', 'Abonneren op dit weblog');
+@define('YOU_CHOSE', 'U heeft zich voor %s opgegeven');
+@define('IMAGE_ROTATE_LEFT', 'Roteer de afbeelding 90 graden tegen de klok in');
+@define('IMAGE_ROTATE_RIGHT', 'Roteer de afbeelding 90 degrees met de klok mee');
+@define('IMAGE_SIZE', 'Grootte van de afbeelding');
+@define('IMAGE_AS_A_LINK', 'Image insertion');
+@define('POWERED_BY', 'Powered by');
+@define('TRACKBACKS', 'Trackbacks');
+@define('TRACKBACK', 'Trackback');
+@define('NO_TRACKBACKS', 'Geen Trackbacks');
+@define('TOPICS_OF', 'Onderwerpen bij');
+@define('VIEW_FULL', 'bekijk volledig');
+@define('VIEW_TOPICS', 'bekijk onderwerpen');
+@define('AT', 'op');
+@define('SET_AS_TEMPLATE', 'Gebruik als template');
+@define('IN', 'in');
+@define('EXCERPT', 'Uittreksel');
+@define('TRACKED', 'Gevolgd');
+@define('LINK_TO_ENTRY', 'Link naar inzending');
+@define('LINK_TO_REMOTE_ENTRY', 'Link naar externe inzending');
+@define('IP_ADDRESS', 'IP-adres');
+@define('USER', 'Gebruiker');
+@define('THUMBNAIL_USING_OWN', 'Behoud %s als zijn eigen index-afbeelding, verkleinen is niet nodig.');
+@define('THUMBNAIL_FAILED_COPY', '%s kon niet gekopieërd worden, kan dus niet als index-afbeelding gebruikt worden!');
+@define('AUTHOR', 'Auteur');
+@define('LAST_UPDATED', 'Laatst begewerkt');
+@define('TRACKBACK_SPECIFIC', 'Trackback is een specifieke link naar deze inzending');
+@define('DIRECT_LINK', 'Directe link naar deze inzending');
+@define('COMMENT_ADDED', 'Uw reactie is succesvol toegevoegd. ');
+@define('COMMENT_ADDED_CLICK', 'Klik %shier%s om terug te keren naar de reacties, of klik %shier%s om dit scherm af te sluiten.');
+@define('COMMENT_NOT_ADDED', 'Uw reactie kon niet worden toegevoegd omdat, deze functie voor deze inzending is uitgeschakeld. ');
+@define('COMMENT_NOT_ADDED_CLICK', 'Klik %shier%s om terug te keren naar de reacties, of klik %shier%s om dit scherm af te sluiten.');
+@define('COMMENTS_DISABLE', 'Sta geen reacties toe op deze inzending');
+@define('COMMENTS_ENABLE', 'Sta reacties toe op deze inzending');
+@define('COMMENTS_CLOSED', 'De auteur staat het niet toe te reageren op deze inzending');
+@define('EMPTY_COMMENT', 'Uw reactie bevatte geen tekst, gaat u alstublieft %sterug%s en probeer opnieuw');
+@define('ENTRIES_FOR', 'Inzendingen voor %s');
+@define('DOCUMENT_NOT_FOUND', 'Het document %s is helaas niet gevonden.');
+@define('USERNAME', 'Gebruikersnaam');
+@define('PASSWORD', 'Wachtwoord');
+@define('AUTOMATIC_LOGIN', 'Bewaar deze informatie');
+@define('SERENDIPITY_INSTALLATION', 'Serendipity installatie');
+@define('LEFT', 'links');
+@define('RIGHT', 'rechts');
+@define('HIDDEN', 'verborgen');
+@define('REMOVE_TICKED_PLUGINS', 'Verwijder geselecteerde plugins');
+@define('SAVE_CHANGES_TO_LAYOUT', 'Bewaar veranderingn in ontwerp');
+@define('COMMENTS_FROM', 'Reactie van');
+@define('ERROR', 'Fout');
+@define('ENTRY_SAVED', 'Uw inzending is bewaard');
+@define('DELETE_SURE', 'Weet u zeker dat u inzending #%s definitief wilt verwijderen?');
+@define('NOT_REALLY', 'Niet echt...');
+@define('DUMP_IT', 'Verwijder maar!');
+@define('RIP_ENTRY', 'Inzending #%s is verwijderd');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Categorie #%s is verwijderd. Aanwezige inzendingen zijn verplaatst naar categorie #%s');
+@define('CATEGORY_DELETED', 'Categorie #%s is verwijderd.');
+@define('CATEGORY_REMAINING', 'Verwijder deze categorie en verplaatst de inzendingen naar categorie: %s');
+@define('INVALID_CATEGORY', 'Er is geen categorie opgegeven om te verwijderen');
+@define('CATEGORY_SAVED', 'Categorie is opgeslagen');
+@define('SELECT_TEMPLATE', 'Selecteer een template dat u wenst te gebruiken voor uw weblog');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'Inzendingen zijn niet succesvol ingevoerd!');
+@define('MT_DATA_FILE', 'Movable Type databestand');
+@define('FORCE', 'Forceer');
+@define('CREATE_AUTHOR', 'Maak auteur \'%s\' aan.');
+@define('CREATE_CATEGORY', 'Maak categorie \'%s\' aan.');
+@define('MYSQL_REQUIRED', 'U moet een MySQL-verbinding hebben om deze actie te voltooien.');
+@define('COULDNT_CONNECT', 'Kan geen verbinding maken met de volgende MySQL database: %s.');
+@define('COULDNT_SELECT_DB', 'Kan de volgende database niet selecteren: %s.');
+@define('COULDNT_SELECT_USER_INFO', 'Kan de volgende gebruikers informatie niet selecteren: %s.');
+@define('COULDNT_SELECT_CATEGORY_INFO', 'Kan de volgende categorie niet selecteren: %s.');
+@define('COULDNT_SELECT_ENTRY_INFO', 'Kan de volgende inzendingen niet selecteren: %s.');
+@define('COULDNT_SELECT_COMMENT_INFO', 'Kan de volgende reactie niet selecteren: %s.');
+@define('YES', 'Ja');
+@define('NO', 'Nee');
+@define('USE_DEFAULT', 'Standaard');
+@define('CHECK_N_SAVE', 'Controlleer &amp; Bewaren');
+@define('DIRECTORY_WRITE_ERROR', 'Kan niet schrijven naar map %s. Controlleer de toegangsrechten.');
+@define('DIRECTORY_CREATE_ERROR', 'Map %s bestaat niet en kon niet worden aangemaakt. Maak deze alstublieft handmatig aan');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; voer <i>%s %s</i> uit');
+@define('CANT_EXECUTE_BINARY', 'Kan %s opdracht opdracht niet uitvoeren');
+@define('FILE_WRITE_ERROR', 'Kan niet schrijven naar bestand %s.');
+@define('FILE_CREATE_YOURSELF', 'Maakt u zelf het bestand aan of controlleer de toegangsrechten');
+@define('COPY_CODE_BELOW', '<br />* Kopieer de onderstaande code en voeg deze toe aan het bestand %s in uw %s map:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Verander gebruiker www in de gebruiker die de apache-server draait (bijvoorbeeld nobody).');
+@define('BROWSER_RELOAD', 'Als u diet heeft gedaan druk u op uw browser\'s "opnieuw openen" knop.');
+@define('DIAGNOSTIC_ERROR', 'Serendipity heeft enkele fouten gevonden, in de door u opgegeven informatie, tijden het uitvoeren van een diagnostische programma:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity is nog niet geinstalleerd. <a href="%s">Installeer</a> het nu alstublieft.');
+@define('INCLUDE_ERROR', 'serendipity fout: kan %s niet toevoegen - word afgesloten.');
+@define('DATABASE_ERROR', 'serendipity error: kan geen verbinding maken met de database - word afgesloten.');
+@define('CREATE_DATABASE', 'Maak standaar database aan...');
+@define('ATTEMPT_WRITE_FILE', 'Probeer bestand %s aan te maken...');
+@define('WRITTEN_N_SAVED', 'Configuratie geschreven &amp; opgeslagen');
+@define('IMAGE_ALIGNMENT', 'Afbeelding uitlijnen');
+@define('ENTER_NEW_NAME', 'Voer een nieuwe naam in voor: ');
+@define('RESIZING', 'Grootte aanpassen');
+@define('RESIZE_DONE', 'Gereed (%s afbeeldingen aangepast).');
+@define('SYNCING', 'Bezig met het synchroniseren van de database met de map waar de afbeeldingen in staan');
+@define('SYNC_DONE', 'Gereed (%s afbeeldingen gesynchroniseerd).');
+@define('FILE_NOT_FOUND', 'Kan bestand <b>%s</b> niet vinden, mogelijk is deze reeds verwijderd.');
+@define('ABORT_NOW', 'Annuleer nu');
+@define('REMOTE_FILE_NOT_FOUND', 'Het bestand is niet gevonden, weet u zeker dat de webpagina <b>%s</b> correct (geschreven) is?');
+@define('FILE_FETCHED', '%s opgehaald als %s');
+@define('FILE_UPLOADED', 'Het bestand %s is succesvol geupload als %s');
+@define('WORD_OR', 'Of');
+@define('SCALING_IMAGE', 'Aanpassen van de grootte van %s naar %s x %s px');
+@define('KEEP_PROPORTIONS', 'Behoud verhoudingen');
+@define('REALLY_SCALE_IMAGE', 'Wilt u de afbeelding echt aanpassen? Dit kan namelijk niet meer ongedaan gemaakt worden!');
+@define('TOGGLE_ALL', 'Alles uit- of inklappen');
+@define('TOGGLE_OPTION', 'Uit/Inklap opties');
+@define('SUBSCRIBE_TO_THIS_ENTRY', 'Abonneer op deze inzending');
+@define('UNSUBSCRIBE_OK', "%s is nu geabonneerd op deze inzending");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'Nieuwe reactie op geabonneerde inzending "%s"');
+@define('SUBSCRIPTION_MAIL', "Geachte %s,\n\nEen nieuwe reacties is geplaatst op \"%s\", op inzending \"%s\"\nDe persoon die gereageerd heeft is: %s\n\nU kunt de inzending hier vinden: %s\n\nU kunt zich uitschrijven door op deze link te drukken: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "Geachte %s,\n\nEen nieuwe trackback is toegevoegd op\"%s\", op inzending \"%s\"\nDe persoon die gereageerd heeft is: %s\n\nU kunt de inzending hier vinden: %s\n\nU kunt zich uitschrijven door op deze link te drukken: %s\n");
+@define('SIGNATURE', "\n-- \n%s is powered by Serendipity.\nEen van de beste weblogs. U kunt het ook gebruiken.\nGa naar <http://s9y.org> om uit te vinden hoe.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91 feed');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0 feed');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0 feed');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 reacties');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3 feed');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'Field "managingEditor"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  'Field "webMaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'Afbeelding voor de RSS feed');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', 'Breedte van de afbeelding');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'Hoogte van de afbeelding');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  'E-Mailadres van de webmaster, indien beschikbaar. (empty: hidden) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', 'E-Mailadres van de managing editor, indien beschikbaar. (empty: hidden) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'URL van een afbeelding in GIF/JPEG/PNG format, indien beschikbaar. (empty: serendipity-logo)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'in pixels, max. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'in pixels, max. 400');
+@define('SYNDICATION_PLUGIN_TTL', 'Field "ttl" (time-to-live)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'Aantal minuten nadat uw weblog niet meer gecached mag worden door buitenlandse sites/applicaties (empty: hidden) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'Field "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', 'Moet het "pubDate"-veld worden geintegreerd in uw RSS-channel, om zo de dag van de laatste inzending te tonen?');
+@define('CONTENT', 'Inhoud');
+@define('TYPE', 'Type');
+@define('DRAFT', 'Concept');
+@define('PUBLISH', 'Publiceren');
+@define('PREVIEW', 'Voorvertoning');
+@define('DATE', 'Datum');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', 'Opgelet: De door u ingevoerde datum is niet correct. Het moet opgegeven worden in het volgende formaat JJJJ-MM-DD UU:MM. Bijvoorbeeld 1970-12-31 14:39');
+@define('CATEGORY_PLUGIN_DESC', 'Toon de lijst met categoriëen.');
+@define('ALL_AUTHORS', 'Alle auteurs');
+@define('CATEGORIES_TO_FETCH', 'Op te halen categoriëen');
+@define('CATEGORIES_TO_FETCH_DESC', 'Catergoriëen op van welke auteur inzien?');
+@define('PAGE_BROWSE_ENTRIES', 'Pagina %s van %s, totaal %s inzendingen');
+@define('PREVIOUS_PAGE', 'vorige pagina');
+@define('NEXT_PAGE', 'volgende pagina');
+@define('ALL_CATEGORIES', 'Alle categoriëen');
+@define('DO_MARKUP', 'Voer tekstopmaak veranderingen uit');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'Datumopmaak');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'De echte datum van de inzending, gebruikmakend van de PHPs strftime() variabelen. (Standaard: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'Kan de template niet openen, update u alstublieft Serendipity!');
+@define('ADVANCED_OPTIONS', 'Geavanceerde Opties');
+@define('EDIT_ENTRY', 'Bewerk Inzending');
+@define('HTACCESS_ERROR', 'Controlleer uw webserver installatie, Serendipity moet kunnen schrijven naar het bestand ".htaccess". Dit was helaas niet mogelijk door fouten in toegangsrechten. Past u deze alstublieft als volgt aan: <br />&nbsp;&nbsp;%s<br />en laad deze pagina opnieuw.');
+@define('SIDEBAR_PLUGINS', 'Sidebar Plugins');
+@define('EVENT_PLUGINS', 'Evenementen Plugins');
+@define('SORT_ORDER', 'Sorteer volgorder');
+@define('SORT_ORDER_NAME', 'Bestandsnaam');
+@define('SORT_ORDER_EXTENSION', 'Bestandsextensies');
+@define('SORT_ORDER_SIZE', 'Bestandsgrootte');
+@define('SORT_ORDER_WIDTH', 'Afbeeldings breedte');
+@define('SORT_ORDER_HEIGHT', 'Afbeeldings hoogte');
+@define('SORT_ORDER_DATE', 'Upload datum');
+@define('SORT_ORDER_ASC', 'Oplopend');
+@define('SORT_ORDER_DESC', 'Aflopend');
+@define('THUMBNAIL_SHORT', 'Thumb');
+@define('ORIGINAL_SHORT', 'Orig.');
+@define('APPLY_MARKUP_TO', 'Tekstopmaak toepassen op %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'Begin van de vorige week');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity heeft ontdekt dat u configuratie momenteel versie %s is, terwijl Serendipity zelf geïnstalleerd is als versie %s, u moet opwaarderen! <a href="%s">Klik hier</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'Hallo en welkom bij de Serendipity upgrade agent.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', 'Ik zal u helpen Serendipity %s installatie te upgraden.');
+@define('SERENDIPITY_UPGRADER_WHY', 'U krijgt deze melding te zien omdat, u zojuist Serendipity %s geinstalleerd heeft, u heeft echter uw database nog niet geupgrade naar deze versie');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'Database updates (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'Zojuist zijn .sql-bestanden aangetroffen, welke eerst uitgevoerd moeten worden voordat Serendipity normaal kan functioneren');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  'Taken specifiek voor deze versie');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', 'Geen taken gevonden voor specifiek deze versie');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', 'Wilt u dat ik de bovenstaande taken uitvoer?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'Nee, ik voer ze zelf uit');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'Ja, alstublieft');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'U hoeft geen upgrades uit te voeren');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', 'Serendipity is geupgraded');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'U heeft ervoor gekozen geen upgrades uit te voeren, zorg ervoor dat uw database goed geïnstalleerd is en geplande taken uitgevoerd worden');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'Uw Serendipity installatie is nu geupgraded naar versie %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', 'U kunt terugkeren naar uw weblog door %shier%s te klikken');
+@define('MANAGE_USERS', 'Beheer gebruikers');
+@define('CREATE_NEW_USER', 'Maak nieuwe gebruiker aan');
+@define('CREATE_NOT_AUTHORIZED', 'U kunt geen gebruikers bewerken met hetzelfde gebruikersniveau als uzelf');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'U kunt geen gebruikers aanmaken met een hoger gebruikersniveau als uzelf');
+@define('CREATED_USER', '%s is aangemaakt als nieuwe gebruiker');
+@define('MODIFIED_USER', 'De eigenschappen van gebruiker, %s, zijn gewijzigd');
+@define('USER_LEVEL', 'Gebruikersniveau');
+@define('DELETE_USER', 'U staat op het punt de volgende gebruiker te verwijderen: #%d %s. Weet u zeker dat u deze gebruiker wilt verwijderen? Wanneer u dit doet zullen de inzendingen van deze gebruiker niet meer worden weergegeven.');
+@define('DELETED_USER', 'Gebruiker, #%d %s, is verwijderd.');
+@define('LIMIT_TO_NUMBER', 'Hoeveel items moeten er worden weergegeven?');
+@define('ENTRIES_PER_PAGE', 'inzendingen per pagina');
+@define('XML_IMAGE_TO_DISPLAY', 'XML Button');
+@define('XML_IMAGE_TO_DISPLAY_DESC','Deze afbeelding laat u uw XML Feeds weergeven. Laat het veld leeg voor de standaard instellingen, voer \'none\' in om het uit te schakellen.');
+
+@define('DIRECTORIES_AVAILABLE', 'In de lijst van beschikbare mappen kunt u een willekeurige map selecteren om een nieuwe map in aan te maken.');
+@define('ALL_DIRECTORIES', 'alle mappen');
+@define('MANAGE_DIRECTORIES', 'Beheer mappen');
+@define('DIRECTORY_CREATED', 'Map <strong>%s</strong> is aangemaakt.');
+@define('PARENT_DIRECTORY', 'Huidige map');
+@define('CONFIRM_DELETE_DIRECTORY', 'Weet u zeker dat u alle gevens uit map %s wilt verwijderen?');
+@define('ERROR_NO_DIRECTORY', 'Fout: Map %s bestaat niet');
+@define('CHECKING_DIRECTORY', 'Controleer de bestanden in map %s');
+@define('DELETING_FILE', 'Verwijder bestand %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', 'Kan een map die nog niet leeg is niet verwijderen. Vink "force deletion" aan als u ook deze bestanden wilt verwijderen, voer het daarna nogmaals uit. Aanwezige bestanden zijn:');
+@define('DIRECTORY_DELETE_FAILED', 'Het verwijderen van map %s is niet gelukt. Controleer de toegangsrechten of de bovenstaande meldingen.');
+@define('DIRECTORY_DELETE_SUCCESS', 'Map %s is succesvol verwijderd.');
+@define('SKIPPING_FILE_EXTENSION', 'Bestand overgeslagen: Er mist een extensie voor %s.');
+@define('SKIPPING_FILE_UNREADABLE', 'Bestand overgeslagen: %s het bestand is niet leesbaar.');
+@define('FOUND_FILE', 'Een nieuw of aangepast bestand is gevonden: %s.');
+@define('ALREADY_SUBCATEGORY', '%s is reeds een subcategorie van %s.');
+@define('PARENT_CATEGORY', 'Huidige catergorie');
+@define('IN_REPLY_TO', 'Reactie op');
+@define('TOP_LEVEL', 'Top level');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s feed');
+@define('PERMISSIONS', 'Toegangsrechten');
+@define('SETTINGS_SAVED_AT', 'De instellingen zijn opgeslagen in %s');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', 'Database instellingen');
+@define('INSTALL_CAT_DB_DESC', 'Hier kunt u de instellingen van uw database invoeren. Serendipity heeft deze nodig om te functioneren');
+@define('INSTALL_DBTYPE', 'Database type');
+@define('INSTALL_DBTYPE_DESC', 'Database type');
+@define('INSTALL_DBHOST', 'Database host');
+@define('INSTALL_DBHOST_DESC', 'De hostnaam van uw database');
+@define('INSTALL_DBUSER', 'Database gebruiker');
+@define('INSTALL_DBUSER_DESC', 'De gebruikersnaam die nodig is om verbinding te maken met uw database');
+@define('INSTALL_DBPASS', 'Database wachtwoord');
+@define('INSTALL_DBPASS_DESC', 'Het wachtwoord behorend bij de ingevoerde gebruikersnaam');
+@define('INSTALL_DBNAME', 'Database naam');
+@define('INSTALL_DBNAME_DESC', 'De naam van uw database');
+@define('INSTALL_DBPREFIX', 'Database kenmerk');
+@define('INSTALL_DBPREFIX_DESC', 'Het kenmerk waar dit weblog in de database te vinden is, bijvoorbeeld serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', 'Padden');
+@define('INSTALL_CAT_PATHS_DESC', 'Diverse padden naar essentiële mappen en bestanden. Let alstublieft op de aanduiding van mappen!');
+@define('INSTALL_FULLPATH', 'Volledig pad');
+@define('INSTALL_FULLPATH_DESC', 'Het volledige pad naar uw Serendipity installatie');
+@define('INSTALL_UPLOADPATH', 'Upload pad');
+@define('INSTALL_UPLOADPATH_DESC', 'Alle uploads worden in deze map geplaatst, bevind zich in \'Volledige pad\' - meestal is dit \'uploads/\'');
+@define('INSTALL_RELPATH', 'Browser pad');
+@define('INSTALL_RELPATH_DESC', 'Het pad naar Serendipity voor gebruik in uw browser, meestal is dit \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', 'Template browser-pad');
+@define('INSTALL_RELTEMPLPATH_DESC', 'Het pad naar waar de templates zich bevinden - gerelateerd aan het \'Browser pad\'');
+@define('INSTALL_RELUPLOADPATH', 'Upload browser-pad');
+@define('INSTALL_RELUPLOADPATH_DESC', 'Het pad naar uw uploadmap - gerelateerd aan het \'Browser pad\'');
+@define('INSTALL_URL', 'URL naar uw weblog');
+@define('INSTALL_URL_DESC', 'De URL naar uw Serendipity installatie');
+@define('INSTALL_INDEXFILE', 'Index bestand');
+@define('INSTALL_INDEXFILE_DESC', 'De naam van uw Serendipity index bestand');
+
+/* Generel settings */
+@define('INSTALL_CAT_SETTINGS', 'Algemene Instellingen');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Pas aan hoe Serendipity zich gedraagd');
+@define('INSTALL_USERNAME', 'Gebruikersnaam beheerder');
+@define('INSTALL_USERNAME_DESC', 'De gebruikersnaam van de beheerder');
+@define('INSTALL_PASSWORD', 'Wachtwoord beheerder');
+@define('INSTALL_PASSWORD_DESC', 'Het wachtwoord van de beheerder');
+@define('INSTALL_EMAIL', 'E-mailadres van beheerder');
+@define('INSTALL_EMAIL_DESC', 'E-mailadres van de beheerder van het weblog');
+@define('INSTALL_SENDMAIL', 'Verstuur e-mails naar beheerder?');
+@define('INSTALL_SENDMAIL_DESC', 'Wilt een e-mail ontvangen wanneer er een reactie geplaatst is op een van uw inzendingen?');
+@define('INSTALL_SUBSCRIBE', 'Abonneren op inzendingen?');
+@define('INSTALL_SUBSCRIBE_DESC', 'Maak het mogelijk voor gebruikers om zich te abonneren op uw inzendingen? Gebruikers zullen dan een e-mail ontvangen wanneer er een reactie geplaatst is op deze inzending');
+@define('INSTALL_BLOGNAME', 'Weblog naam');
+@define('INSTALL_BLOGNAME_DESC', 'De naam van uw weblog');
+@define('INSTALL_BLOGDESC', 'Omschrijving weblog');
+@define('INSTALL_BLOGDESC_DESC', 'De omschrijving van het weblog');
+@define('INSTALL_LANG', 'Taal');
+@define('INSTALL_LANG_DESC', 'Selecteer de taal die gebruikt word voor uw weblog');
+
+/* Appearance and options */
+@define('INSTALL_CAT_DISPLAY', 'Uiterlijk en opties');
+@define('INSTALL_CAT_DISPLAY_DESC', 'Pas aan hoe Serendipity zich gedraagd');
+@define('INSTALL_WYSIWYG', 'Gebruik de WYSIWYG editor');
+@define('INSTALL_WYSIWYG_DESC', 'Wilt u de WYSIWYG editor gebruiken? (Werkt met IE5+ en gedeeltelijk met Mozilla 1.3+)');
+@define('INSTALL_XHTML11', 'Forceer XHTML 1.1 compabiliteit');
+@define('INSTALL_XHTML11_DESC', 'Wilt u XHTML 1.1 compabiliteit forceren ? (Dit kan problemen veroorzaken met 4e generatie browsers)');
+@define('INSTALL_POPUP', 'Maak gebruik van popups');
+@define('INSTALL_POPUP_DESC', 'Wilt u gebruik maken van popups voor reacties, trackbacks e.d.?');
+@define('INSTALL_EMBED', 'Is Serendipity geïntegreerd in een ander pagina?');
+@define('INSTALL_EMBED_DESC', 'Als u Serendipity wilt integreren in een bestaande pagina, zet deze dan op ja om de headers te laten voor wat ze zijn en gewoon de inhoud weer te geven. Bekijk het README bestand voor meer informatie!');
+@define('INSTALL_TOP_AS_LINKS', 'Geef Top Exits/Referrers weer als links?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"Nee": Exits en Referrers worden als gewone tekst weergeven om het spammen door zoekmachines te voorkomen. "ja": Exits en Referrers worden getoond als hyperlinks. "standaard": Gebruik de instellingen vanuit uw algemene instellingen (aanbevolen).');
+@define('INSTALL_BLOCKREF', 'Geblokkeerde Referers');
+@define('INSTALL_BLOCKREF_DESC', 'Zijn er speciale hosts waarvan u niet wilt dat zij in uw Top Refferers lijst komen te staan? Scheid de hosts met \';\'');
+@define('INSTALL_REWRITE', 'URL Herschrijven');
+@define('INSTALL_REWRITE_DESC', 'Welke regels moeten er gehanteerd worden bij het genererem van URLs. Het inschakelen van deze optie zorgt voor aantrekkelijke URLs, het maakt het makkelijker voor zoekmachines om uw weblog te indexeren. De webserver moet wel mod_rewrite of "AllowOverride All" toestaan in uw Serendipity map. Standaard staat deze op automatisch');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', 'Afbeelding instellingen');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'Hier kunt u aangeven hoe Serendipity met afbeeldingen moet omgaan');
+@define('INSTALL_IMAGEMAGICK', 'Gebruik Imagemagick');
+@define('INSTALL_IMAGEMAGICK_DESC', 'Heeft u Imagemagick geïnstalleerd en wilt u deze gebruiken om het formaat van de afbeeldingen aan te passen?');
+@define('INSTALL_IMAGEMAGICKPATH', 'Pad naar de conversiebestanden');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'Volledig pad en naam uw Imagemagick convert binary');
+@define('INSTALL_THUMBSUFFIX', 'Index-afbeelding toevoeging');
+@define('INSTALL_THUMBSUFFIX_DESC', 'Index-afbeeldingen zullen als volgt worden weergeven: original.[suffix].ext');
+@define('INSTALL_THUMBWIDTH', 'Index-afbeelding formaat');
+@define('INSTALL_THUMBWIDTH_DESC', 'Maximale breedte van automatisch aangemaakte index-afbeeldingen');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', 'Uw persoonlijke gegevens');
+@define('USERCONF_CAT_PERSONAL_DESC', 'Pas uw persoonlijke gegevens aan');
+@define('USERCONF_USERNAME', 'Uw gebruikersnaam');
+@define('USERCONF_USERNAME_DESC', 'De gebruikersnaam waarmee in zich aanmeld op het weblog');
+@define('USERCONF_PASSWORD', 'Uw wachtwoord');
+@define('USERCONF_PASSWORD_DESC', 'Het wachtwoord dat u wilt gebruiken om zich aan te melden');
+@define('USERCONF_EMAIL', 'Uw e-mailadres');
+@define('USERCONF_EMAIL_DESC', 'Uw eigen e-mailadres');
+@define('USERCONF_SENDCOMMENTS', 'Bericht bij reacties?');
+@define('USERCONF_SENDCOMMENTS_DESC', 'Wilt u een e-mail ontvangen wanneer er reacties geplaatst worden op uw inzendingen?');
+@define('USERCONF_SENDTRACKBACKS', 'Verstuur trackback bericht?');
+@define('USERCONF_SENDTRACKBACKS_DESC', 'Wilt u een e-mail ontvangen wanneer er een trackback naar een van uw berichten is gemaakt?');
+@define('USERCONF_ALLOWPUBLISH', 'Toestaan berichten te plaatsen?');
+@define('USERCONF_ALLOWPUBLISH_DESC', 'Wilt u toestaan dat deze gebruiker berichten kan plaatsen?');
+@define('SUCCESS', 'Success');
+@define('POWERED_BY_SHOW_TEXT', 'Toon "Serendipity" als tekst');
+@define('POWERED_BY_SHOW_TEXT_DESC', 'Dit laat "Serendipity Weblog" als tekst zien');
+@define('POWERED_BY_SHOW_IMAGE', 'Toon "Serendipity" logo');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Toont het Serendipity logo');
+@define('PLUGIN_ITEM_DISPLAY', 'Waar moeten de items worden weergegeven?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'Alleen uitgebreide inzendingen');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'Alleen overzichtspagina');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'Altijd');
+@define('RSS_IMPORT_CATEGORY', 'Gebruik deze catergorie gebruiken om niet gelijke inzendingen in op te slaan');
+
+@define('COMMENTS_WILL_BE_MODERATED', 'Ingestuurde reacties zullen eerst worden gecontrolleerd voor deze geplaatst worden.');
+@define('YOU_HAVE_THESE_OPTIONS', 'U heeft de volgende opties tot uw beschikking:');
+@define('THIS_COMMENT_NEEDS_REVIEW', 'Waarschuwing: Deze reactie moet eerst worden goedgekeurd voor deze worden weergegeven');
+@define('DELETE_COMMENT', 'Verwijder reactie');
+@define('APPROVE_COMMENT', 'Keur reactie goed');
+@define('REQUIRES_REVIEW', 'Moet nagekeken worden');
+@define('COMMENT_APPROVED', 'Reactie #%s is goedgekeurd');
+@define('COMMENT_DELETED', 'Reactie #%s is succesvol verwijderd');
+@define('COMMENTS_MODERATE', 'Reacties & trackbacks moeten worden gecontrolleerd');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'Waarschuwing: Deze trackback moet worden goedgekeurd voor hij word weergegeven');
+@define('DELETE_TRACKBACK', 'Verwijder trackback');
+@define('APPROVE_TRACKBACK', 'Keur trackback goed');
+@define('TRACKBACK_APPROVED', 'Trackback #%s is goedgekeurd');
+@define('TRACKBACK_DELETED', 'Trackback #%s is verwijderd');
+@define('VIEW', 'Bekijk');
+@define('COMMENT_ALREADY_APPROVED', 'Reactie #%s is reeds goedgekeurd');
+@define('COMMENT_EDITED', 'De reactie is aangepast');
+@define('HIDE', 'Verbergen');
+@define('VIEW_EXTENDED_ENTRY', 'Ga door met lezen van "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'De link is niet bedoeld om aangekliked te worden. Het bevat een trackback URL voor deze inzending. U kunt deze URL gebruiken om ping- & trackbacks te versturen van uw weblog naar deze inzending. Om deze URL te kopiëeren klikt u op de rechter muisknop, "Copy Shortcut" voor Internet Explorer gebruikers of "Copy Link Location" voor Mozilla gebruikers.');
+@define('PLUGIN_SUPERUSER_HTTPS', 'Gebruik HTTPS om aan te melden');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'Laat de aanmelding via https verlopen. Uw webserver moet dit echter wel ondersteunen!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'Maak externe links aanklikbaar?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"nee": Niet gecontrolleerde externe links (Top Exits, Top Referrers, User comments) worden niet getoond of getoond als gewone tekst om spam vanuit zoekmachines te voorkomen. (aanbevolen). "ja": Niet gecontrolleerde externe links worden gewoon getoond als links. De Sidebar plugin configuratie kan dit beïnvloeden!');
+@define('PAGE_BROWSE_COMMENTS', 'Pagina %s van de %s, in totaal %s reactie(s)');
+@define('FILTERS', 'Filters');
+@define('FIND_ENTRIES', 'Zoek inzendingen');
+@define('FIND_COMMENTS', 'Zoek reacties');
+@define('FIND_MEDIA', 'Zoek media');
+@define('FILTER_DIRECTORY', 'Map');
+@define('SORT_BY', 'Sorteren op');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'Er is geen Trackback verzonden: Kan geen verbinding maken met %s via poort %d');
+@define('MEDIA', 'Media');
+@define('MEDIA_LIBRARY', 'Media bibliotheek');
+@define('ADD_MEDIA', 'Voeg media toe');
+@define('ENTER_MEDIA_URL', 'Voer een URL van een bestand toe om op te halen:');
+@define('ENTER_MEDIA_UPLOAD', 'Selecteer een bestand dat u wilt uploaden:');
+@define('SAVE_FILE_AS', 'Sla bestand op als:');
+@define('STORE_IN_DIRECTORY', 'Sla op in de volgende map: ');
+@define('ADD_MEDIA_BLAHBLAH', '<b>Voeg een bestand toe aan uw media verzameling:</b><p>Hier kunt u mediabestanden uploaden, of aangeven welke waar elders op het internet ze zich bevinden. Als u de juiste afbeelding niet kunt vinden, ga dan naar <a href="http://images.google.com" target="_blank">Zoek naar afbeeldingen op Google</a>.<p><b>Selectie methode:</b><br>');
+@define('MEDIA_RENAME', 'Hernoem dit bestand');
+@define('IMAGE_RESIZE', 'Wijzig formaat van de afbeelding');
+@define('MEDIA_DELETE', 'Verwijder dit bestand');
+@define('FILES_PER_PAGE', 'Bestanden per pagina');
+@define('CLICK_FILE_TO_INSERT', 'Selecteer het bestand dat u wilt invoeren:');
+@define('SELECT_FILE', 'Selecteer bestand om in te voeren');
+@define('MEDIA_FULLSIZE', 'Volledige grootte');
+@define('CALENDAR_BOW_DESC', 'De eerse dag van de week. Standaard is maandag');
+@define('SUPERUSER', 'Weblog Beheer');
+@define('ALLOWS_YOU_BLAHBLAH', 'Toont een link naar de beheersite van uw weblog');
+@define('CALENDAR', 'Kalender');
+@define('SUPERUSER_OPEN_ADMIN', 'Open beheerscherm');
+@define('SUPERUSER_OPEN_LOGIN', 'Open aanmeldscherm');
+@define('INVERT_SELECTIONS', 'Keer selectie om');
+@define('COMMENTS_DELETE_CONFIRM', 'Weet u zeker dat u de geselecteerde reacties wilt verwijderen?');
+@define('COMMENT_DELETE_CONFIRM', 'Weet u zeker dat u de reactie #%d, geschreven door %s wilt verwijderen?');
+@define('DELETE_SELECTED_COMMENTS', 'Verwijder geselecteerde reacties');
+@define('VIEW_COMMENT', 'Bekijk reactie');
+@define('VIEW_ENTRY', 'Bekijk inzending');
+@define('DELETE_FILE_FAIL' , 'Kan bestand <b>%s</b> niet verwijderen');
+@define('DELETE_THUMBNAIL', 'Verwijder index-afbeelding <b>%s</b>');
+@define('DELETE_FILE', 'Verwijder bestand genaamd <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', 'U staat op het punt om bestand <b>%s</b><br/> te verwijderen. Als u dit bestand in een van uw inzendingen gebruikt, zal dit leiden tot niet werkende links of afbeeldingen.<br />Weet u zeker dat u door wilt gaan?<br /><br />');
+@define('TRACKBACK_SENDING', 'Verstuur een trackback naar %s...');
+@define('TRACKBACK_SENT', 'Trackback succesvol');
+@define('TRACKBACK_FAILED', 'Trackback functioneerd niet: %s');
+@define('TRACKBACK_NOT_FOUND', 'Er is geen juiste trackback-URL gevonden.');
+@define('TRACKBACK_URI_MISMATCH', 'De gevonden trackback URL heeft geen overeenkomsten met de door u opgegeven uw.');
+@define('TRACKBACK_CHECKING', 'Controlleer <u>%s</u> op mogelijke trackbacks...');
+@define('TRACKBACK_NO_DATA', 'Doel bevatte geen gegevens');
+@define('TRACKBACK_SIZE', 'Doel URL heeft de maximale grootte overschreven van %s bytes.');
+@define('COMMENTS_VIEWMODE_THREADED', 'Samengevoegd');
+@define('COMMENTS_VIEWMODE_LINEAR', 'Lineair');
+@define('DISPLAY_COMMENTS_AS', 'Geeft reacties weer als');
+@define('COMMENTS_FILTER_SHOW', 'Tonen');
+@define('COMMENTS_FILTER_ALL', 'Alles');
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'Alleen geäuthoriseerden');
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'Wacht op authorisatie');
+@define('RSS_IMPORT_BODYONLY', 'Voeg alle geïmporteerde teksten in de "verkorte inzendingen"-sectie en splits deze niet op in de "uitgebreide inzendingen"-sectie.');
+@define('SYNDICATION_PLUGIN_FULLFEED', 'Geef volledige inzendingen weer in het RSS feed');
+@define('WEEK', 'Week');
+@define('WEEKS', 'Weken');
+@define('MONTHS', 'Maanden');
+@define('DAYS', 'Dagen');
+@define('ARCHIVE_FREQUENCY', 'Kalender item frequentie');
+@define('ARCHIVE_FREQUENCY_DESC', 'De interval die gebruikt moet worden voor ieder item in de lijst');
+@define('ARCHIVE_COUNT', 'Aantal items in de lijst');
+@define('ARCHIVE_COUNT_DESC', 'Het totaal aantal maanden, weken of dagen dat weergeven moet worden');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'Hieronder is een lijst met geïnstalleerde plugins');
+@define('SIDEBAR_PLUGIN', 'sidebar plugin');
+@define('EVENT_PLUGIN', 'evenementen plugin');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'Klik hier om een nieuwe %s te installeren');
+@define('VERSION', 'versie');
+@define('INSTALL', 'Installeren');
+@define('ALREADY_INSTALLED', 'Reed geïnstalleerd');
+@define('SELECT_A_PLUGIN_TO_ADD', 'Selecteerd welke plugin u wenst te installeren');
+@define('INSTALL_OFFSET', 'Aanpassing servertijd');
+@define('STICKY_POSTINGS', 'Post-its');
+@define('INSTALL_FETCHLIMIT', 'Inzendingen die weergegeven moeten woreden');
+@define('INSTALL_FETCHLIMIT_DESC', 'Aantal inzendingen die weergeven moeten worden voor elke pagina');
+@define('IMPORT_ENTRIES', 'Importeer inzendingen');
+@define('EXPORT_ENTRIES', 'Exporteer inzendingen');
+@define('IMPORT_WELCOME', 'Welkom bij de Serendipity import utility');
+@define('IMPORT_WHAT_CAN', 'Hier kunt u inzendingen uit andere weblog software importeren');
+@define('IMPORT_SELECT', 'Selecteer alstublieft uit welk type weblog u de gegevens wilt importeren');
+@define('IMPORT_PLEASE_ENTER', 'Voert u alstublieft de gegevens in die hieronder gevraagd worden');
+@define('IMPORT_NOW', 'Importeer nu!');
+@define('IMPORT_STARTING', 'Starten met importeren...');
+@define('IMPORT_FAILED', 'Importeren niet gelukt');
+@define('IMPORT_DONE', 'Importeren succesvol uitgevoerd');
+@define('IMPORT_WEBLOG_APP', 'Weblog applicatie');
+@define('EXPORT_FEED', 'Exporteer volledige RSS feed');
+@define('STATUS', 'Status na importeren');
+@define('IMPORT_GENERIC_RSS', 'Algemene RSS import');
+@define('ACTIVATE_AUTODISCOVERY', 'Verstuur trackbacks naar links gevonden in deze inzending');
+@define('WELCOME_TO_ADMIN', 'Welkom bij Serendipity Beheer.');
+@define('PLEASE_ENTER_CREDENTIALS', 'Voert u alstublieft, hieronder, uw gegevens in.');
+@define('ADMIN_FOOTER_POWERED_BY', 'Powered by Serendipity %s en PHP %s');
+@define('INSTALL_USEGZIP', 'Maak gebruik van gzip comprimeerde paginas');
+@define('INSTALL_USEGZIP_DESC', 'Om de verzending van paginas te versnellen, kunnen de paginas gecomprimeerd worden. Dit is alleen mogelijk als zijn/haar browser dit aan kan. Het word echter aangeraden');
+@define('INSTALL_SHOWFUTURE', 'Bekijk toekomstige inzendingen');
+@define('INSTALL_SHOWFUTURE_DESC', 'Wanneer dit is ingeschakeld zal het alle toekomstige inzendingen, reeds aanwezig in uw weblog, weergeven. Standaard staat deze ingesteld om de inzendingen pas te vertonen wanneer de publicatiedatum bereikt is.');
+@define('INSTALL_DBPERSISTENT', 'Gebruik altijd openstaande verbindingen');
+@define('INSTALL_DBPERSISTENT_DESC', 'Laat de verbinding met uw database openstaan, hierover kunt u meer lezen op <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">deze pagina</a>. Dit is normaliter niet aangeraden');
+@define('NO_IMAGES_FOUND', 'Geen afbeeldingen gevonden');
+@define('PERSONAL_SETTINGS', 'Personlijke instellingen');
+@define('REFERER', 'Referer');
+@define('NOT_FOUND', 'Niet gevonden');
+@define('WRITABLE', 'Beschrijfbaar');
+@define('NOT_WRITABLE', 'Niet beschrijfbaar');
+@define('PROBLEM_DIAGNOSTIC', 'Door een ernstig probleem, kun u niet door gaan met de installatie totdat u de hier bovenstaande fouten gecorrigeerd heeft');
+@define('SELECT_INSTALLATION_TYPE', 'Selecteer welk installatietype u wenst');
+@define('WELCOME_TO_INSTALLATION', 'Welkom bij de Serendipity Installatie');
+@define('FIRST_WE_TAKE_A_LOOK', 'Als eerste bekijken we uw huidige instellingen en zullen zo compabiliteitsproblemen opsporen');
+@define('ERRORS_ARE_DISPLAYED_IN', 'Alles fouten worden weergeven in %s, aanbevelingen in %s en voltooide taken in %s');
+@define('RED', 'rood');
+@define('YELLOW', 'geel');
+@define('GREEN', 'groen');
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s pre-installation bericht');
+@define('RECOMMENDED', 'Aanbevolen');
+@define('ACTUAL', 'Eigenlijke');
+@define('PHPINI_CONFIGURATION', 'php.ini configuratie');
+@define('PHP_INSTALLATION', 'PHP installatie');
+@define('THEY_DO', 'positief');
+@define('THEY_DONT', 'negatief');
+@define('SIMPLE_INSTALLATION', 'Eenvoudige installatie');
+@define('EXPERT_INSTALLATION', 'Geavanceerde installatie');
+@define('COMPLETE_INSTALLATION', 'Complete installatie');
+@define('WONT_INSTALL_DB_AGAIN', 'zal de database niet opnieuw installeren');
+@define('CHECK_DATABASE_EXISTS', 'Controlleer de database op aanwezigheid van de nodige tabellen');
+@define('CREATING_PRIMARY_AUTHOR', 'Maak hoofdauteur \'%s\' aan');
+@define('SETTING_DEFAULT_TEMPLATE', 'Stel standaard template in');
+@define('INSTALLING_DEFAULT_PLUGINS', 'Installeer standaard plugins');
+@define('SERENDIPITY_INSTALLED', 'Serendipity is met succes geïnstalleerd');
+@define('VISIT_BLOG_HERE', 'Bezoek uw weblog hier');
+@define('THANK_YOU_FOR_CHOOSING', 'Dank u voor het gebruiken van Serendipity');
+@define('ERROR_DETECTED_IN_INSTALL', 'Een fout is aangetroffen in de installatie');
+@define('OPERATING_SYSTEM', 'Besturingssysteem');
+@define('WEBSERVER_SAPI', 'Webserver SAPI');
+@define('TEMPLATE_SET', '\'%s\' is ingesteld als uw huidige template');
+@define('SEARCH_ERROR', 'De zoekfunctie werkte niet naar verwachting. Waarschuw de beheerder van dit weblog: dit komt mogelijk door het ontbreken van index keys in de database. Op MySQL systemen moet uw database useraccount deze bewerking kunnen uitvoeren: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> De foutmelding van de database is: <pre>%s</pre>');
+@define('EDIT_THIS_CAT', 'Editing "%s"'); // Translate
+@define('CATEGORY_REMAINING', 'Delete this category and move its entries to this category'); // Translate
+@define('CATEGORY_INDEX', 'Below is a list of categories available to your entries'); // Translate
+@define('NO_CATEGORIES', 'No categories'); // Translate
+@define('RESET_DATE', 'Reset date'); // Translate
+@define('RESET_DATE_DESC', 'Click here to reset the date to the current time'); // Translate
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Permissions can be set by running shell command: `<em>%s</em>` on the failed directory, or by setting this using an FTP program'); // Translate
+@define('WARNING_TEMPLATE_DEPRECATED', 'Warning: Your current template is using a deprecated template method, you are advised to update if possible'); // Translate
+@define('ENTRY_PUBLISHED_FUTURE', 'This entry is not yet published.'); // Translate
+@define('ENTRIES_BY', 'Entries by %s'); // Translate
+@define('PREVIOUS', 'Previous'); // Translate
+@define('NEXT', 'Next'); // Translate
+@define('APPROVE', 'Approve'); // Translate
+@define('DO_MARKUP_DESCRIPTION', 'Voer tekstopmaak uit (smilies, shortcut markups via *, /, _, ...). Met het uitschakelen van deze optie behoud u de HTML-code in the text.');
+@define('CATEGORY_ALREADY_EXIST', 'A category with the name "%s" already exist'); // Translate
+@define('IMPORT_NOTES', 'Note:'); // Translate
+@define('ERROR_FILE_FORBIDDEN', 'You are not allowed to upload files with active content'); // Translate
+@define('ADMIN', 'Administration'); // Re-Translate
+@define('ADMIN_FRONTPAGE', 'Frontpage'); // Translate
+@define('QUOTE', 'Quote'); // Translate
+@define('IFRAME_SAVE', 'Serendipity is now saving your entry, creating trackbacks and performing possible XML-RPC calls. This may take a while..'); // Translate
+@define('IFRAME_SAVE_DRAFT', 'A draft of this entry has been saved'); // Translate
+@define('IFRAME_PREVIEW', 'Serendipity is now creating the preview of your entry...'); // Translate
+@define('IFRAME_WARNING', 'Your browser does not support the concept of iframes. Please open your serendipity_config.inc.php file and set $serendipity[\'use_iframe\'] variable to FALSE.'); // Translate
+@define('NONE', 'none');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Default settings for new entries'); // Translate
+@define('UPGRADE', 'Upgrade'); // Translate
+@define('UPGRADE_TO_VERSION', 'Upgrade to version %s'); // Translate
+@define('DELETE_DIRECTORY', 'Delete directory'); // Translate
+@define('DELETE_DIRECTORY_DESC', 'You are about to delete the contents of a directory that contains media files, possibly files used in some of your entries.'); // Translate
+@define('FORCE_DELETE', 'Delete ALL files in this directory, including those not known by Serendipity'); // Translate
+@define('CREATE_DIRECTORY', 'Create directory'); // Translate
+@define('CREATE_NEW_DIRECTORY', 'Create new directory'); // Translate
+@define('CREATE_DIRECTORY_DESC', 'Here you can create a new directory to place media files in. Choose the name for your new directory and select an optional parent directory to place it in.'); // Translate
+@define('BASE_DIRECTORY', 'Base directory'); // Translate
+@define('USERLEVEL_EDITOR_DESC', 'Standard editor'); // Translate
+@define('USERLEVEL_CHIEF_DESC', 'Chief editor'); // Translate
+@define('USERLEVEL_ADMIN_DESC', 'Administrator'); // Translate
+@define('USERCONF_USERLEVEL', 'Access level'); // Translate
+@define('USERCONF_USERLEVEL_DESC', 'This level is used to determine what kind of access this user has to the blog'); // Translate
+@define('USER_SELF_INFO', 'Logged in as %s (%s)'); // Translate
+@define('ADMIN_ENTRIES', 'Entries'); // Translate
+@define('RECHECK_INSTALLATION', 'Recheck installation'); // Translate
+@define('IMAGICK_EXEC_ERROR', 'Unable to execute: "%s", error: %s, return var: %d'); // Translate
+@define('INSTALL_OFFSET_DESC', 'Enter the amount of hours between the date of your webserver (current: %clock%) and your desired time zone'); // Translate
+@define('UNMET_REQUIREMENTS', 'Requirements failed: %s'); // Translate
+@define('CHARSET', 'Charset');
+@define('AUTOLANG', 'Use visitor\'s browser language as default');
+@define('AUTOLANG_DESC', 'If enabled, this will use the visitor\'s browser language setting to determine the default language of your entry and interface language.');
+@define('INSTALL_AUTODETECT_URL', 'Autodetect used HTTP-Host'); // Translate
+@define('INSTALL_AUTODETECT_URL_DESC', 'If set to "true", Serendipity will ensure that the HTTP Host which was used by your visitor is used as your BaseURL setting. Enabling this will let you be able to use multiple domain names for your Serendipity Blog, and use the domain for all follow-up links which the user used to access your blog.'); // Translate
+@define('CONVERT_HTMLENTITIES', 'Try to auto-convert HTML entities?');
+@define('EMPTY_SETTING', 'You did not specify a valid value for "%s"!');
+@define('USERCONF_REALNAME', 'Real name'); // Translate
+@define('USERCONF_REALNAME_DESC', 'The full name of the author. This is the name seen by readers'); // Translate
+@define('HOTLINK_DONE', 'File hotlinked.<br />Done.'); // Translate
+@define('ENTER_MEDIA_URL_METHOD', 'Fetch method:'); // Translate
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Note: If you choose to hotlink to server, make sure you have permission to hotlink to the designated website, or the website is yours. Hotlink allows you to use off-site images without storing them locally.'); // Translate
+@define('MEDIA_HOTLINKED', 'hotlinked'); // Translate
+@define('FETCH_METHOD_IMAGE', 'Download image to your server'); // Translate
+@define('FETCH_METHOD_HOTLINK', 'Hotlink to server'); // Translate
+@define('DELETE_HOTLINK_FILE', 'Deleted the hotlinked file entitled <b>%s</b>'); // Translate
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Show E-Mail addresses?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_no.inc.php b/lang/serendipity_lang_no.inc.php
new file mode 100644 (file)
index 0000000..3b1e5c8
--- /dev/null
@@ -0,0 +1,670 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Translation (c) by Jo Christian Oterhals <oterhals@gmail.com>
+
+@define('LANG_CHARSET', 'ISO-8859-1');
+@define('DATE_LOCALES', 'norwegian, no, no_NO');
+@define('DATE_FORMAT_ENTRY', '%A d. %e. %B %Y');
+@define('DATE_FORMAT_SHORT', '%d.%m.%Y %H:%M');
+@define('WYSIWYG_LANG', 'no');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Serendipity Administrasjonssuite');
+@define('HAVE_TO_BE_LOGGED_ON', 'Du må være logget inn for å kunne se denne siden');
+@define('WRONG_USERNAME_OR_PASSWORD', 'Du har tastet inn feil brukernavn eller passord');
+@define('APPEARANCE', 'Utseende');
+@define('MANAGE_STYLES', 'Administrer temaer');
+@define('CONFIGURE_PLUGINS', 'Konfigurerer plugins');
+@define('CONFIGURATION', 'Konfigurasjon');
+@define('BACK_TO_BLOG', 'Tilbake til weblogg');
+@define('LOGIN', 'Logg inn');
+@define('LOGOUT', 'Logg ut');
+@define('LOGGEDOUT', 'Logget ut.');
+@define('CREATE', 'Opprett');
+@define('SAVE', 'Lagre');
+@define('NAME', 'Navn');
+@define('CREATE_NEW_CAT', 'Oppret ny kategori');
+@define('I_WANT_THUMB', 'Jeg vil bruke minibildet i min artikkel.');
+@define('I_WANT_BIG_IMAGE', 'Jeg vil bruke det originale bildet i min artikkel.');
+@define('I_WANT_NO_LINK', 'Vis bildet uten link');
+@define('I_WANT_IT_TO_LINK', 'Vis bildet med link');
+@define('BACK', 'Tilbake');
+@define('FORWARD', 'Frem');
+@define('ANONYMOUS', 'Anonym');
+@define('NEW_TRACKBACK_TO', 'Ny trackback opprettet til');
+@define('NEW_COMMENT_TO', 'Ny kommentar opprettet til');
+@define('RECENT', 'Nyere...');
+@define('OLDER', 'Eldre...');
+@define('DONE', 'Ferdig');
+@define('WELCOME_BACK', 'Velkommen tilbake,');
+@define('TITLE', 'Tittel');
+@define('DESCRIPTION', 'Beskrivelse');
+@define('PLACEMENT', 'Plassering');
+@define('DELETE', 'Slett');
+@define('UP', 'OPP');
+@define('DOWN', 'NED');
+@define('ENTRIES', 'artikler');
+@define('NEW_ENTRY', 'Ny artikkel');
+@define('EDIT_ENTRIES', 'Rediger artikler');
+@define('CATEGORIES', 'Kategorier');
+@define('WARNING_THIS_BLAHBLAH', "ADVARSEL:\\nDette kan ta lang tid hvis det er mange bilder uten minibilder.");
+@define('CREATE_THUMBS', 'Lag minibilder på nytt');
+@define('MANAGE_IMAGES', 'Administrer bilder');
+@define('NAME', 'Navn');
+@define('EMAIL', 'Email');
+@define('HOMEPAGE', 'Hjemmeside');
+@define('COMMENT', 'Kommentar');
+@define('REMEMBER_INFO', 'Husk opplysninger?');
+@define('SUBMIT_COMMENT', 'Legg til kommentar');
+@define('NO_ENTRIES_TO_PRINT', 'Der er ingen artikler å vise');
+@define('COMMENTS', 'Kommentarer');
+@define('ADD_COMMENT', 'Legg til kommentar');
+@define('NO_COMMENTS', 'Ingen kommentarr');
+@define('POSTED_BY', 'Skrevet av');
+@define('ON', 'aktiv');
+@define('A_NEW_COMMENT_BLAHBLAH', 'En ny kommentar har blitt opprettet på din blog "%s", til artiklen med navnet "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'En ny trackback har blitt laget til din artikel ved navn "%s".');
+@define('NO_CATEGORY', 'Ingen kategori');
+@define('ENTRY_BODY', 'Artikkelindhold');
+@define('EXTENDED_BODY', 'Utvidet indhold');
+@define('CATEGORY', 'Kategori');
+@define('EDIT', 'Rediger');
+@define('NO_ENTRIES_BLAHBLAH', 'Ingen artikler ble funnet som inneholdt %s' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'Ditt søk på %s retunerte %s resultater:');
+@define('SEARCH_TOO_SHORT', 'Ditt søk må være på mere enn 3 tegn');
+@define('IMAGE', 'Bilde');
+@define('ERROR_FILE_NOT_EXISTS', 'Feil: Det gamle filnavnet finnes ikke!');
+@define('ERROR_FILE_EXISTS', 'Feil: Det nye filnavnet brukes allerede, velg et andet!');
+@define('ERROR_SOMETHING', 'Fejl: Der gikk noe galt');
+@define('ADDING_IMAGE', 'Legg til et bilde...');
+@define('THUMB_CREATED_DONE', 'Minibilde er oprettet.<br>Utført.');
+@define('ERROR_FILE_EXISTS_ALREADY', 'Feil: Filen finnes allerede på din maskin!');
+@define('GO', 'Begynn!');
+@define('NEWSIZE', 'Ny størrelse: ');
+@define('RESIZE_BLAHBLAH', '<b>Endre størrelse på %s</b><p>');
+@define('ORIGINAL_SIZE', 'Original størrelse: <i>%sx%s</i> pixel');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>Her kan du justere bildets størrelse. Hvis du vil bevare proporsjonene, behøver du bare taste en av verdiene og trykke på TAB-tasten.  Jeg vil automatisk beregne den andre verdien:');
+@define('QUICKJUMP_CALENDAR', 'Hurtigkalender');
+@define('QUICKSEARCH', 'Søk');
+@define('SEARCH_FOR_ENTRY', 'Søk etter en artikel');
+@define('ARCHIVES', 'Arkiver');
+@define('BROWSE_ARCHIVES', 'Bla gjennom arkiv etter måneder');
+@define('TOP_REFERRER', 'Referanser');
+@define('SHOWS_TOP_SITES', 'Viser de sitene som oftest linker til din blog');
+@define('TOP_EXITS', 'Exit-sider');
+@define('SHOWS_TOP_EXIT', 'Viser de exit-sider det har blitt klikket flest ganger på');
+@define('SYNDICATION', 'Syndikering');
+@define('SHOWS_RSS_BLAHBLAH', 'Viser RSS syndikeringslinker');
+@define('ADVERTISES_BLAHBLAH', 'Reklamer for din blogs opprinnelse');
+@define('HTML_NUGGET', 'HTML Nugget');
+@define('HOLDS_A_BLAHBLAH', 'Indeholder en bit HTML i din sidebar');
+@define('TITLE_FOR_NUGGET', 'Tittel på din nugget');
+@define('THE_NUGGET', 'HTML-indholdet av din nugget');
+@define('SYNDICATE_THIS_BLOG', 'Syndiker denne bloggen');
+@define('YOU_CHOSE', 'Du valgte %s');
+@define('IMAGE_SIZE', 'Bildestørrelse');
+@define('IMAGE_AS_A_LINK', 'Sett inn bilde');
+@define('POWERED_BY', 'Drives av');
+@define('TRACKBACKS', 'Trackbacks');
+@define('TRACKBACK', 'Trackback');
+@define('NO_TRACKBACKS', 'Ingen Trackbacks');
+@define('TOPICS_OF', 'Emner av');
+@define('VIEW_FULL', 'Vis fullt');
+@define('VIEW_TOPICS', 'Vis temaer');
+@define('AT', 'kl');
+@define('SET_AS_TEMPLATE', 'Sett som mal');
+@define('IN', 'i');
+@define('EXCERPT', 'Utdrag');
+@define('TRACKED', 'Tracked');
+@define('LINK_TO_ENTRY', 'Link til artikel');
+@define('LINK_TO_REMOTE_ENTRY', 'Link til ekstern artikel');
+@define('IP_ADDRESS', 'IP-adresse');
+@define('USER', 'Bruker');
+@define('THUMBNAIL_USING_OWN', 'Bruker %s i seg selv som minibilde, fordi det allerede er så lite.');
+@define('THUMBNAIL_FAILED_COPY', 'Ville gjerne ha brukt %s som minibilde i seg selv, men kunne ikke kopiere!');
+@define('AUTHOR', 'Forfatter');
+@define('LAST_UPDATED', 'Sist opdatert');
+@define('TRACKBACK_SPECIFIC', 'Trackback URI til denne artikel');
+@define('DIRECT_LINK', 'Direktelink til denne artikel');
+@define('COMMENT_ADDED', 'Din kommentar ble lagt til. ');
+@define('COMMENT_ADDED_CLICK', 'Klik %her for å gå tilbake%s til kommentarene, og %sher for å lukke%s dette vinduet.');
+@define('COMMENT_NOT_ADDED', 'Din kommentar kunne ikke legges til fordi kommentarer til denne artikelen er blitt deaktivert.');
+@define('COMMENT_NOT_ADDED_CLICK', 'Klikk %sher for å gå tilbake%s til kommentarene, og %sher for å lukke%s dette vinduet. ');
+@define('COMMENTS_DISABLE', 'Tillat ikke kommentarer til denne artikelen');
+@define('COMMENTS_ENABLE', 'Tillat kommentarer til denne artikelen');
+@define('COMMENTS_CLOSED', 'Forfatteren har valgt ikke å tillate kommentarer til denne artikelen');
+@define('EMPTY_COMMENT', 'Din kommentar indeholdt ikke noe, vennligst gå %stilbage%s og prøv igjen');
+@define('ENTRIES_FOR', 'Artikler fra %s');
+@define('DOCUMENT_NOT_FOUND', 'Dokumentet %s kunne ikke finnes.');
+@define('USERNAME', 'Brukernavn');
+@define('PASSWORD', 'Passord');
+@define('AUTOMATIC_LOGIN', 'Lagre oplysningerne');
+@define('SERENDIPITY_INSTALLATION', 'Serendipity Installasjon');
+@define('LEFT', 'venstre');
+@define('RIGHT', 'høyre');
+@define('HIDDEN', 'skjult');
+@define('REMOVE_TICKED_PLUGINS', 'Fjern valgte plugins');
+@define('SAVE_CHANGES_TO_LAYOUT', 'Lagre layout-endringene');
+@define('COMMENTS_FROM', 'Kommentar fra');
+@define('ERROR', 'Feil');
+@define('ENTRY_SAVED', 'Din artikkel ble lagret');
+@define('DELETE_SURE', 'Er du sikker på du vil slette #%s permanent?');
+@define('NOT_REALLY', 'Egentlig ikke...');
+@define('DUMP_IT', 'Kast den!');
+@define('RIP_ENTRY', 'Farvel artikel #%s');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Kategori #%s ble slettet. Gamle artikler flyttet til kategori #%s');
+@define('CATEGORY_DELETED', 'Kategori #%s ble slettet.');
+@define('INVALID_CATEGORY', 'Ingen kategori ble valgt for sletting');
+@define('CATEGORY_SAVED', 'Kategori lagret');
+@define('SELECT_TEMPLATE', 'Velg den malen du ønsker å bruke til din blog');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'Det var problemer under indsettelsen av artiklene!');
+@define('YES', 'Ja');
+@define('NO', 'Nei');
+@define('USE_DEFAULT', 'Default');
+@define('CHECK_N_SAVE', 'Sjekk &amp; lagre');
+@define('DIRECTORY_WRITE_ERROR', 'Kan ikke skrive til biblioteket %s. Sjekk filrettighederne.');
+@define('DIRECTORY_CREATE_ERROR', 'Biblioteket %s eksisterer ikke og kunne ikke op1prettes. Vennligst opprett biblioteket manuelt');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; Kjør <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', 'Kan ikke eksekvere %s');
+@define('FILE_WRITE_ERROR', 'Kan ikke skrive til filen %s.');
+@define('FILE_CREATE_YOURSELF', 'Venligst opprett filen selv og sjekk dens rettigheter');
+@define('COPY_CODE_BELOW', '<br />* Kopier koden nedenunder og plasser den i %s i din %s mappe:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Endre www til den bruker som apache kører som (fx. nobody).');
+@define('BROWSER_RELOAD', 'Når du har gjort dette, så tryk på browserens "oppdater"-knapp');
+@define('DIAGNOSTIC_ERROR', 'Vi har opdaget noen feil mens vi kørte noen diagnostikker på dine oppgitte informasjoner:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity er ennå ikke installert. Klikk <a href="%s">her for å installere</a> nå.');
+@define('INCLUDE_ERROR', 'serendipityfejl: Kunne ikke inkludere %s - Avbryter.');
+@define('DATABASE_ERROR', 'serendipityfejl: Kunne ikke oprette forbindelse til databasen - Avbryter.');
+@define('CREATE_DATABASE', 'Oppretter standarddatabase-setup...');
+@define('ATTEMPT_WRITE_FILE', 'Forsøker å skrive til %s ...');
+@define('WRITTEN_N_SAVED', 'Konfigurasjon skrevet &amp; lagret');
+@define('IMAGE_ALIGNMENT', 'Bildejustering');
+@define('ENTER_NEW_NAME', 'Oppgi det nye navn for: ');
+@define('RESIZING', 'Endre dimensjoner');
+@define('RESIZE_DONE', 'Ferdig (Endret %s bilder).');
+@define('SYNCING', 'Synkronisere databasen med bildemappen');
+@define('SYNC_DONE', 'Ferdig (Synkroniserte %s bilder).');
+@define('DELETE_IMAGE_FAIL' , 'Kunne ikke slette bildet <b>%s</b>');
+@define('DELETE_THUMBNAIL', 'Slettet bildet med navn <b>%s</b>');
+@define('FILE_NOT_FOUND', 'Kunne ikke finne filen ved navn <b>%s</b>, den er kanskje allerede slettet?');
+@define('ABORT_NOW', 'Avbryt nå');
+@define('REMOTE_FILE_NOT_FOUND', 'Filen kunne ikke finnes på serveren, er du sikker på at URL-en: <b>%s</b> er korrekt?');
+@define('FILE_FETCHED', '%s hentet: %s');
+@define('FILE_UPLOADED', 'Filen %s er lastet opp: %s');
+@define('WORD_OR', 'eller');
+@define('SCALING_IMAGE', 'Endre størrelsen på %s til %s x %s px');
+@define('KEEP_PROPORTIONS', 'Bevar forholdet');
+@define('REALLY_SCALE_IMAGE', 'Er du sikker på at du vil endre størrelsen på dette bildet? Det er ingen vei tilbake!');
+@define('TOGGLE_ALL', 'Vis/Skjul alle');
+@define('TOGGLE_OPTION', 'Vis/Skjul denne opsjonen');
+@define('SUBSCRIBE_TO_THIS_ENTRY', 'Abonnér på denne artikkelen');
+@define('UNSUBSCRIBE_OK', "%s er ikke lenger abonnent på denne artikkelen");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'Ny kommentar til abonnert artikel "%s"');
+@define('SUBSCRIPTION_MAIL', "Hej %s,\n\nEn ny kommentar er blitt lagt til en artikkel du abonnerer på hos \"%s\", ved navn \"%s\"\nNavnet på skribenten er: %s\n\nDu kan finne artikkelen her: %s\n\nDu kan stoppe ditt abonnement ved å klikke på denne linken: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "Hei %s,\n\nEn ny trackback er laget til en artikkel du abonnerer på hos \"%s\", ved navn \"%s\"\nNavnet på skribenten er: %s\n\nDu kan finne artiklen her: %s\n\nDu kan stoppe ditt abonnement ved å klikke på denne linken: %s\n");
+@define('SIGNATURE', "\n-- \n%s bruker Serendipity.\nDen bedste blogg på dette, du kan også bruke det.\nKikk nærmere på <http://s9y.org> for å finne mere informasjon.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91-feed');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0-feed');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0-feed');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0-kommentarer');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3-feed');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s-feed');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'Feltet "Hovedredaktør"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  'Feltet "webmaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'Bilde til RSS-feed');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', 'Bildebredde');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'Bildehøjde');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  'Emailadressen til webmasteren, hvis tilgjengelig. (tom: skjult) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', 'E-mailadressen til redaktøren, hvis tilgjengelig. (tom: skjult) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'URL til et bilde i GIF/JPEG/PNG format, hvis tilgjengelig. (tom: serendipity-logo)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'i pixels, max. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'i pixels, max. 400');
+@define('SYNDICATION_PLUGIN_TTL', 'Feltet "ttl" (time-to-live)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'Antallet minutter din blog skal caches av eksterne sider/programmer (tom: skjult) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'Feltet "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', 'Skal "pubDate"-feltet være innkapslet til en RSS-kanal, for å vise datoen på den nyeste artikkelen?');
+@define('CONTENT', 'Innhold');
+@define('TYPE', 'Type');
+@define('DRAFT', 'Utkast');
+@define('PUBLISH', 'Publiser');
+@define('PREVIEW', 'Vis');
+@define('DATE', 'Dato');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', 'Advarsel: Den datoen du tastet inn var ugyldig. Den skal tastes inn i følgende format: ÅÅÅÅ-MM-DD TT:MM.');
+@define('CATEGORY_PLUGIN_DESC', 'Viser listen over kategorier.');
+@define('ALL_AUTHORS', 'Alle forfattere');
+@define('CATEGORIES_TO_FETCH', 'Kategorier som skal hentes');
+@define('CATEGORIES_TO_FETCH_DESC', 'Hent kategorier fra en bestemt forfatter?');
+@define('PAGE_BROWSE_ENTRIES', 'Side %s av %s, i alt %s artikler');
+@define('PREVIOUS_PAGE', 'forrige side');
+@define('NEXT_PAGE', 'neste side');
+@define('ALL_CATEGORIES', 'Alle kategorier');
+@define('DO_MARKUP', 'Utført Markup-transformasjon');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'Datoformat');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'Formatet på artiklens faktiske dato, brug PHPs strftime()-variabler. (Standard: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'Kunne ikke åpne malen, oppater Serendipity!');
+@define('ADVANCED_OPTIONS', 'Avanserte innstillinger');
+@define('EDIT_ENTRY', 'Rediger artikkel');
+@define('HTACCESS_ERROR', 'For å kunne sjekke din lokale webservers installasjon, må Serendipity være i stand til å skrive til filen ".htaccess". Dette var ikke mulig pga. feil rettigheter. Endre rettighetene slik: <br />&nbsp;&nbsp;%s<br />og oppdater denne siden.');
+@define('SORT_ORDER', 'Sorter etter');
+@define('SORT_ORDER_NAME', 'Filnavn');
+@define('SORT_ORDER_EXTENSION', 'Filtype');
+@define('SORT_ORDER_SIZE', 'Filstørrelse');
+@define('SORT_ORDER_WIDTH', 'Bildebredde');
+@define('SORT_ORDER_HEIGHT', 'Bildehøyde');
+@define('SORT_ORDER_DATE', 'Upload-dato');
+@define('SORT_ORDER_ASC', 'Stigende');
+@define('SORT_ORDER_DESC', 'Fallende');
+@define('THUMBNAIL_SHORT', 'Mini');
+@define('ORIGINAL_SHORT', 'Orig.');
+@define('APPLY_MARKUP_TO', 'Formater %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'Starten på uken');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity har opdaget at din nåværende konfigurasjon passer til versjon %s. Serendipity selv er installert som version %s, Det er nødvendig å oppgradere! <a href="%s">Klikk her!</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'Velkommen til Serendipitys oppgraderingsscript.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', 'Scriptet vil hjelpe deg med å oppgradere Serendipity %s.');
+@define('SERENDIPITY_UPGRADER_WHY', 'Denne meldingen vises fordi Serendipity versjon %s er installert, men databasen er ennå ikke opgradert til denne versjonen.');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'Databasen oppdateringer (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'Følgende .sql-filer må kjøres før Serendipity igjen kan fungere normalt.');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  'Versjonsspesifikke oppgaver');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', 'Ingen versjonsspesifikke oppgaver funnet');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', 'Ønsker du at ovenstående opgaver utføres?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'Nei, jeg utfører dem manuelt');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'Ja takk!');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'Det ser ut til at oppgradering ikke er nødvendig.');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', 'Serendipity er oppgradert');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'Du har ignorert en del av oppgraderingen. Vennligst undersøk hvorvidt databasen er korrekt opdatert, og planlagte opgaver utført');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'Din Serendipity-installation er nå oppgradert til version %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', 'Du kan vende tilbake til din blog ved å klikke %sher%s');
+@define('MANAGE_USERS', 'Håndter brukere');
+@define('CREATE_NEW_USER', 'Opprett ny bruker');
+@define('CREATE_NOT_AUTHORIZED', 'Du kan ikke redigere brukere med det samme brukernivå som deg selv');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'Du kan ikke opprette brukere med et høyere brukernivå enn deg selv');
+@define('CREATED_USER', 'En ny bruker %s er opprettet');
+@define('MODIFIED_USER', 'Egenskapene for brukeren %s er endret');
+@define('USER_LEVEL', 'brukernivå');
+@define('DELETE_USER', 'Du er i ferd med å slette bruker #%d %s. Er du sikker? Dette vil forhindre visning av alle artikler skrevet av brukeren.');
+@define('DELETED_USER', 'Bruker #%d %s er slettet.');
+@define('LIMIT_TO_NUMBER', 'Hvor mange punkter skal vises?');
+@define('ENTRIES_PER_PAGE', 'artikler per side');
+
+/* TRANSLATE */
+@define('PERMISSIONS', 'Rettigheter');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', 'Databaseinnstillinger');
+@define('INSTALL_CAT_DB_DESC', 'Her kan du taste inn all databaseinformasjon');
+@define('INSTALL_DBTYPE', 'Databasetype');
+@define('INSTALL_DBTYPE_DESC', 'Databasetype');
+@define('INSTALL_DBHOST', 'Databaseserver');
+@define('INSTALL_DBHOST_DESC', 'Hostname til din databaseserver');
+@define('INSTALL_DBUSER', 'Databasebrukernavn');
+@define('INSTALL_DBUSER_DESC', 'Brukernavnet som er brukt til å koble til databasen din');
+@define('INSTALL_DBPASS', 'Databasepassord');
+@define('INSTALL_DBPASS_DESC', 'Passordet som passer til brukernavnet over');
+@define('INSTALL_DBNAME', 'Databasenavn');
+@define('INSTALL_DBNAME_DESC', 'Navnet på din database');
+@define('INSTALL_DBPREFIX', 'Databasetabell-prefiks');
+@define('INSTALL_DBPREFIX_DESC', 'Prefiks på tabellnavn, f.eks. serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', 'Baner');
+@define('INSTALL_CAT_PATHS_DESC', 'Forskjellige baner til forskjellige essensielle mapper og filer. Glem ikke etterfølgende slasher på biblioteker!');
+@define('INSTALL_FULLPATH', 'Full bane');
+@define('INSTALL_FULLPATH_DESC', 'Den fulle og absolutte bane til din serendipity-installasjon');
+@define('INSTALL_UPLOADPATH', 'Upload-bane');
+@define('INSTALL_UPLOADPATH_DESC', 'Alle uploads blir plassert her, relativ til \'Full bane\' - typisk \'uploads/\'');
+@define('INSTALL_RELPATH', 'Relativ bane');
+@define('INSTALL_RELPATH_DESC', 'Bane til Serendipity i henhold til din browser, typisk \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', 'Relativ mal-bane');
+@define('INSTALL_RELTEMPLPATH_DESC', 'Bane til mappen som inneholder dine maler - Relativ til \'relative bane\'');
+@define('INSTALL_RELUPLOADPATH', 'Relativ upload-bane');
+@define('INSTALL_RELUPLOADPATH_DESC', 'Bane til dine uploads i henhold til din browser - Relativ til \'relative bane\'');
+@define('INSTALL_URL', 'URL til din blogg');
+@define('INSTALL_URL_DESC', 'Base-URL for din Serendipity-installasjon');
+@define('INSTALL_INDEXFILE', 'Index-fil');
+@define('INSTALL_INDEXFILE_DESC', 'Navnet på din Serendipity index-fil');
+
+/* Generel settings */
+@define('INSTALL_CAT_SETTINGS', 'Generelle innstillinger');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Tilpass måten Serendipity oppfører seg på');
+@define('INSTALL_USERNAME', 'Admin-brukernavn');
+@define('INSTALL_USERNAME_DESC', 'Brukernavn til admin-login');
+@define('INSTALL_PASSWORD', 'Admin-passord');
+@define('INSTALL_PASSWORD_DESC', 'Passord til admin-login');
+@define('INSTALL_EMAIL', 'Admin-email');
+@define('INSTALL_EMAIL_DESC', 'E-mailadresse til eieren av bloggen');
+@define('INSTALL_SENDMAIL', 'Send e-mailer til admin?');
+@define('INSTALL_SENDMAIL_DESC', 'Vil du motta email når kommentare blir gitt til dine artikler?');
+@define('INSTALL_SUBSCRIBE', 'Tillat brukere å abonnere på artikler?');
+@define('INSTALL_SUBSCRIBE_DESC', 'Tillat brukere å abonnere på en artikkel og dermed motte en mail når det oprettes nye kommentare på den artikkelen');
+@define('INSTALL_BLOGNAME', 'Navn på blogg');
+@define('INSTALL_BLOGNAME_DESC', 'Tittelen på din blogg');
+@define('INSTALL_BLOGDESC', 'Blogg-beskrivelse');
+@define('INSTALL_BLOGDESC_DESC', 'Beskrivelse av din blogg');
+@define('INSTALL_LANG', 'Språk');
+@define('INSTALL_LANG_DESC', 'Velg språket på din blogg');
+
+/* Appearance and options */
+@define('INSTALL_CAT_DISPLAY', 'Utseende og innstillinger');
+@define('INSTALL_CAT_DISPLAY_DESC', 'Tilpass hvordan Serendipity ser ut og føles');
+@define('INSTALL_WYSIWYG', 'Bruk WYSIWYG-editor');
+@define('INSTALL_WYSIWYG_DESC', 'Vil du benytte WYSIWYG-editoren? (Virker med IE5+, delvis i Mozilla 1.3+)');
+@define('INSTALL_XHTML11', 'Tving gjennom XHTML 1.1');
+@define('INSTALL_XHTML11_DESC', 'Ønsker du å kreve overholdelse av XHTML 1.1 (kan skape problemer i 4.-generasjonsbrowsere)');
+@define('INSTALL_POPUP', 'Aktiver bruk av popup-vinduer');
+@define('INSTALL_POPUP_DESC', 'Vil du åpne kommentarer og trackbacks i et popupvindu?');
+@define('INSTALL_EMBED', 'Er Serendipity embedded?');
+@define('INSTALL_EMBED_DESC', 'Hvis du ønsker å kapsle Serendipity inn i en normal side, aktiver da dette direktivet for å ignorere headere og kun skrive ut innholdet. Du kan benytte indexFile-direktivet til å lage en wrapper-fil hvor du plasserer din normale hjemmesides headere. Konsulter README filen for mer informasjon!');
+@define('INSTALL_TOP_AS_LINKS', 'Vis topp utgangssider/referanser som links?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"no": Utgangssider og referanser blir vist som ren tekst for å forhindre Google-spam.  "yes": Utgangssider og referanser blir vist som hyperlinker.  "default": Bruk innstillinger fra global konfigurasjon (anbefalt).');
+@define('INSTALL_BLOCKREF', 'Blokkér referanser');
+@define('INSTALL_BLOCKREF_DESC', 'Er det noen spesielle hosts du ikke ønsker skal vises i referanselisten?  Seprarer listen av hostnavn med \';\' og merk deg at disse er blokkert med substring-masker!');
+@define('INSTALL_REWRITE', 'URL-omskrivning');
+@define('INSTALL_REWRITE_DESC', 'Velg hvilken regel du ønsker å bruke når du genererer URL-er. Aktivering av omskrivningsregler vil gjøre URL-ene dine flotte og gjøre din side mer egnet for indeksering av roboter som google. Webserveren må enten støtte mod_rewrite eller "AllowOverride All" for ditt Serendipity-bibliotek. Standardindstillingen er automatisk beregnet');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', 'Bildekonverterings-innstillinger');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'Generell informasjon om hvordan Serendipity skal håndtere bilder');
+@define('INSTALL_IMAGEMAGICK', 'Bruk Imagemagick');
+@define('INSTALL_IMAGEMAGICK_DESC', 'Har du ImageMagick installert og ønsker å bruke det til å endre størrelse på bilder?');
+@define('INSTALL_IMAGEMAGICKPATH', 'Bane til convert binærfil');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'Full bane og navn på din ImageMagick convert binærfil');
+@define('INSTALL_THUMBSUFFIX', 'Thumbnail-suffiks');
+@define('INSTALL_THUMBSUFFIX_DESC', 'Thumbnails vil bli gitt navn etter følgende mønster: original.[suffix].ext');
+@define('INSTALL_THUMBWIDTH', 'Thumbnail-dimensjoner');
+@define('INSTALL_THUMBWIDTH_DESC', 'Statisk maksimalbredde på en auto-genereret thumbnail');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', 'Dine personlige detaljer');
+@define('USERCONF_CAT_PERSONAL_DESC', 'Endre dine personlige detaljer');
+@define('USERCONF_USERNAME', 'Ditt brukernavn');
+@define('USERCONF_USERNAME_DESC', 'Brukernavnet du vil bruke for å logge inn i bloggen');
+@define('USERCONF_PASSWORD', 'Ditt passord');
+@define('USERCONF_PASSWORD_DESC', 'Passordet du vil bruke for å logge inn i bloggen');
+@define('USERCONF_EMAIL', 'Din e-mailadresse');
+@define('USERCONF_EMAIL_DESC', 'Din personlige e-mailadresse');
+@define('USERCONF_SENDCOMMENTS', 'Send beskjeder om nye kommentarer?');
+@define('USERCONF_SENDCOMMENTS_DESC', 'Ønsker du å motta en mail når nye kommentarer blir lagt til dine artikler?');
+@define('USERCONF_SENDTRACKBACKS', 'Send bjeskeder om nye trackbacks?');
+@define('USERCONF_SENDTRACKBACKS_DESC', 'Ønsker du å motta en mail når nye trackbacks blir lagt til dine artikler?');
+@define('USERCONF_ALLOWPUBLISH', 'Tillatelse: Publisere artikler?');
+@define('USERCONF_ALLOWPUBLISH_DESC', 'Kan denne brukeren publisere artikler?');
+
+@define('DIRECTORIES_AVAILABLE', 'I listen over tilgjengelige undermapper, kan du klikke på en ny mappe for å oprette en ny mappe innenfor den stukturen.');
+@define('ALL_DIRECTORIES', 'alle mapper');
+@define('MANAGE_DIRECTORIES', 'Håndter mapper');
+@define('DIRECTORY_CREATED', 'Mappen <strong>%s</strong> er oprettet.');
+@define('PARENT_DIRECTORY', 'Hovedmappe');
+@define('CONFIRM_DELETE_DIRECTORY', 'Er du sikker på du vil slette alt indholdet i mappen %s?');
+@define('ERROR_NO_DIRECTORY', 'Feil: Mappen %s eksisterer ikke');
+@define('CHECKING_DIRECTORY', 'Sjekker filer i mappen %s');
+@define('DELETING_FILE', 'Sletter fil %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', 'Kunne ikke fjerne en ikke-tom mappe. Afkryss "tving gjennom sletting"-feltet hvis du vil slette disse og trykk deretter på Submit igjen. Eksisterende filer er:');
+@define('DIRECTORY_DELETE_FAILED', 'Sletting av mappe %s mislyktes. Sjekk rettigheter eller ovenstående beskjeder.');
+@define('DIRECTORY_DELETE_SUCCESS', 'Mappen %s er slettet.');
+@define('SKIPPING_FILE_EXTENSION', 'Ignorerte filen: Manglende filtype %s.');
+@define('SKIPPING_FILE_UNREADABLE', 'Ignorerte fil: %s er ikke lesbar.');
+@define('FOUND_FILE', 'Fant ny/endret fil: %s.');
+@define('ALREADY_SUBCATEGORY', '%s er allerede en underkategori av %s.');
+@define('PARENT_CATEGORY', 'Hovedkategori');
+@define('IN_REPLY_TO', 'Som svar på');
+@define('TOP_LEVEL', 'Topnivå');
+@define('XML_IMAGE_TO_DISPLAY', 'XML-knapp');
+@define('XML_IMAGE_TO_DISPLAY_DESC','Linker til XML-feeder vil bli vist med dette bildet.  Etterlat tomt for standard, tast inn \'none\' for å deaktivere.');
+@define('SUCCESS', 'Suksess');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', ',');
+@define('NUMBER_FORMAT_THOUSANDS', '.');
+@define('POWERED_BY_SHOW_TEXT', 'Vis "Serendipity" som tekst');
+@define('POWERED_BY_SHOW_TEXT_DESC', 'Vil vise "Serendipity Weblog" som tekst');
+@define('POWERED_BY_SHOW_IMAGE', 'Vis "Serendipity" med en logo');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Vis Serendipity-logoen');
+@define('SETTINGS_SAVED_AT', 'De nye innstillgene er lagret kl %s');
+@define('PLUGIN_ITEM_DISPLAY', 'Hvor skal enheten vises?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'Kun udvidet artikkel');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'Kun i oversikten');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'Hele tiden');
+@define('RSS_IMPORT_CATEGORY', 'Bruk denne kategorien for kategoriløse artikler');
+@define('ERROR_UNKNOWN_NOUPLOAD', 'Det oppstod en ukjent feil, filen ble ikke lastet opp. Kanskje er din filstørrelse større end den maksimale størrelse tillatt av ditt serveroppsett. Spør din webtilbyder eller rediger din php.ini fil for å tillate uploads av større filer.');
+@define('COMMENTS_WILL_BE_MODERATED', 'Kommentarer på denne artikkelen vil først bli vist når de er blitt godkjendt.');
+@define('YOU_HAVE_THESE_OPTIONS', 'Du har følgende muligheter:');
+@define('THIS_COMMENT_NEEDS_REVIEW', 'Advarsel: Denne kommentaren krever godkjennelse før den blir vist');
+@define('DELETE_COMMENT', 'Slett kommentar');
+@define('APPROVE_COMMENT', 'Godkjenn kommentar');
+@define('REQUIRES_REVIEW', 'Krever godkjennelse');
+@define('COMMENT_APPROVED', 'Kommentar #%s er godkjent');
+@define('COMMENT_DELETED', 'Kommentar #%s er slettet');
+@define('VIEW', 'Vis');
+@define('COMMENT_ALREADY_APPROVED', 'Kommentar #%s ser allerede ut til å være godkjent');
+@define('COMMENT_EDITED', 'Den valgte kommentar er redigert');
+@define('HIDE', 'Skjul');
+@define('VIEW_EXTENDED_ENTRY', 'Les resten av "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'Det er ikke meningen at denne linken skal klikkes.  Den innholder trackback-URI-en for denne postingen.  Du kan bruke denne URI-en til å sende ping- og trackbacks fra din egen blog til denne posten.  For å kopiere linken, høyreklikk og velg "Kopier snarvei" i Internet Explorer eller "Copy Link Location" i Mozilla.');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'Advarsel:  Denne trackbacken trenger godkjennelse før den blir vist.');
+@define('DELETE_TRACKBACK', 'Slett trackback');
+@define('APPROVE_TRACKBACK', 'Godkjenn trackback');
+@define('TRACKBACK_APPROVED', 'Trackback #%s har blitt godkjent');
+@define('TRACKBACK_DELETED', 'Trackback #%s har blitt slettet');
+@define('COMMENTS_MODERATE', 'Kommentarer og trackback til denne posten krever moderasjon.');
+@define('PLUGIN_SUPERUSER_HTTPS', 'Bruk https ved innlogging');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'Peker login-linken til en https-adresse. Webserveren din må støtte dette!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'Gjøre eksterne lenker klikkbare?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"no": Usjekkede eksterne lenker (topp utgangssider, referanser, brukerkommentarer) er ikke vist - vist som ren tekst hvor mulig, for å forhindre Google-spam (anbefalt).  "yes":  Usjekkede eksterne lenker blir vist som hyperlenker.  Kan bli overstyrt i sidebar plugin-konfigurasjon!');
+@define('PAGE_BROWSE_COMMENTS', 'Side %s av %s, totalt %s kommentarer');
+@define('FILTERS', 'Filtere');
+@define('FIND_ENTRIES', 'Finn poster');
+@define('FIND_COMMENTS', 'Finn kommentarer');
+@define('FIND_MEDIA', 'Finn media');
+@define('FILTER_DIRECTORY', 'Katalog');
+@define('SORT_BY', 'Sorter på');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'Ingen Trackback sendt:  Kunne ikke åpne tilkobling til %s på port %d');
+@define('MEDIA', 'Media');
+@define('MEDIA_LIBRARY', 'Media-bibliotek');
+@define('ADD_MEDIA', 'Legg til media');
+@define('ENTER_MEDIA_URL', 'Oppgi en URL til en fil som skal hentes:');
+@define('ENTER_MEDIA_UPLOAD', 'Velg en fil du ønsker å laste opp:');
+@define('SAVE_FILE_AS', 'Lagre filen som:');
+@define('STORE_IN_DIRECTORY', 'Lagre i følgende katalog: ');
+@define('MEDIA_RENAME', 'Gi denne filen nytt navn');
+@define('IMAGE_RESIZE', 'Endre størrelsen på dette bildet');
+@define('MEDIA_DELETE', 'Slett denne filen');
+@define('FILES_PER_PAGE', 'Antall filer per side');
+@define('CLICK_FILE_TO_INSERT', 'Klikk på filen du ønsker å sette inn:');
+@define('SELECT_FILE', 'Velg fil å sette inn');
+@define('MEDIA_FULLSIZE', 'Full størrelse');
+@define('CALENDAR_BOW_DESC', 'Ukedagen som skal være starten på uken.  Standard er mandag');
+@define('SUPERUSER', 'Blogg-administrasjon');
+@define('ALLOWS_YOU_BLAHBLAH', 'Legger en link til blogg-administrasjonen i sidebaren.');
+
+@define('CALENDAR', 'Kalender');
+@define('SUPERUSER_OPEN_ADMIN', 'Åpne administrasjon');
+@define('SUPERUSER_OPEN_LOGIN', 'Åpne login-skjerm');
+@define('INVERT_SELECTIONS', 'Inverter valgene');
+@define('COMMENTS_DELETE_CONFIRM', 'Er du sikker på at du ønsker å slette de valgte kommentarene?');
+@define('COMMENT_DELETE_CONFIRM', 'Er du sikker på at du ønsker å slette kommentar #%d, skrevet av %s?');
+@define('DELETE_SELECTED_COMMENTS', 'Slett valgte kommentarer');
+@define('VIEW_COMMENT', 'Se kommentar');
+@define('VIEW_ENTRY', 'Se posting');
+@define('DELETE_FILE', 'Slettet filen kalt <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', 'Du er i ferd med å slette <b>%s</b><br />Hvis du bruker denne filen i noen av postene dine vil dette forårsake døde lenker eller bilder<br />Er du sikker på at du vil gå videre?<br /><br />');
+@define('TRACKBACK_SENDING', 'Sender trackback til URI %s...');
+@define('TRACKBACK_SENT', 'Trackback suksess');
+@define('TRACKBACK_FAILED', 'Trackback slo feil: %s');
+@define('TRACKBACK_NOT_FOUND', 'Fant ingen trackback-URI.');
+@define('TRACKBACK_URI_MISMATCH', 'Den autofunnede trackback-URI-en stemmer ikke overens med vår mål-URI.');
+@define('TRACKBACK_CHECKING', 'Sjekker <u>%s</u> for mulige trackbacks...');
+@define('TRACKBACK_NO_DATA', 'Mål inneholdt ingen data');
+@define('TRACKBACK_SIZE', 'Mål-URI oversteg maksimum filstørrelse på %s bytes.');
+@define('VIEWMODE_THREADED', 'Bytt til trådet visning');
+@define('COMMENTS_VIEWMODE_THREADED', 'Trådet');
+@define('COMMENTS_VIEWMODE_LINEAR', 'Lineær');
+@define('DISPLAY_COMMENTS_AS', 'Vis kommentarer som');
+@define('SIDEBAR_PLUGINS', 'Sidebar-plugins');
+@define('EVENT_PLUGINS', 'Hendelses-lugins');
+@define('ADD_MEDIA_BLAHBLAH', '<b>Legg til en fil til ditt mediabibliotek:</b><p>Her kan du laste opp mediafiler, eller be meg om å hente dem fra en adresse på nettet!  Hvis du ikke har et passende bilde, <a href="http://images.google.com" target="_blank">søk etter bilder på Google</a> som passer til tankene dine.  Resultatene er ofte nyttige og morsomme :)<p><b>Velg metode:</b><br>');
+@define('COMMENTS_FILTER_SHOW', 'Show'); // Translate
+@define('COMMENTS_FILTER_ALL', 'All'); // Translate
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'Only approved'); // Translate
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'Pending approval'); // Translate
+@define('RSS_IMPORT_BODYONLY', 'Put all imported text in the "body" section and do not split up into "extended entry" section.'); // Translate
+@define('SYNDICATION_PLUGIN_FULLFEED', 'Show full articles with extended body inside RSS feed'); // Translate
+@define('MT_DATA_FILE', 'Movable Type data file'); // Translate
+@define('FORCE', 'Force'); // Translate
+@define('CREATE_AUTHOR', 'Create author \'%s\'.'); // Translate
+@define('CREATE_CATEGORY', 'Create category \'%s\'.'); // Translate
+@define('MYSQL_REQUIRED', 'You must have the MySQL extension in order to perform this action.'); // Translate
+@define('COULDNT_CONNECT', 'Could not connect to MySQL database: %s.'); // Translate
+@define('COULDNT_SELECT_DB', 'Could not select database: %s.'); // Translate
+@define('COULDNT_SELECT_USER_INFO', 'Could not select user information: %s.'); // Translate
+@define('COULDNT_SELECT_CATEGORY_INFO', 'Could not select category information: %s.'); // Translate
+@define('COULDNT_SELECT_ENTRY_INFO', 'Could not select entry information: %s.'); // Translate
+@define('COULDNT_SELECT_COMMENT_INFO', 'Could not select comment information: %s.'); // Translate
+@define('WEEK', 'Week'); // Translate
+@define('WEEKS', 'Weeks'); // Translate
+@define('MONTHS', 'Months'); // Translate
+@define('DAYS', 'Days'); // Translate
+@define('ARCHIVE_FREQUENCY', 'Calendar item frequency'); // Translate
+@define('ARCHIVE_FREQUENCY_DESC', 'The calendar interval to use between each item in the list'); // Translate
+@define('ARCHIVE_COUNT', 'Number of items in the list'); // Translate
+@define('ARCHIVE_COUNT_DESC', 'The total number of months, weeks or days to display'); // Translate
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'Below is a list of installed plugins'); // Translate
+@define('SIDEBAR_PLUGIN', 'sidebar plugin'); // Translate
+@define('EVENT_PLUGIN', 'event plugin'); // Translate
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'Click here to install a new %s'); // Translate
+@define('VERSION', 'version'); // Translate
+@define('INSTALL', 'Install'); // Translate
+@define('ALREADY_INSTALLED', 'Already installed'); // Translate
+@define('SELECT_A_PLUGIN_TO_ADD', 'Select the plugin which you wish to install'); // Translate
+@define('INSTALL_OFFSET', 'Server time Offset'); // Translate
+@define('STICKY_POSTINGS', 'Sticky Postings'); // Translate
+@define('INSTALL_FETCHLIMIT', 'Entries to display on frontpage'); // Translate
+@define('INSTALL_FETCHLIMIT_DESC', 'Number of entries to display for each page on the frontend'); // Translate
+@define('IMPORT_ENTRIES', 'Import data'); // Translate
+@define('EXPORT_ENTRIES', 'Export entries'); // Translate
+@define('IMPORT_WELCOME', 'Welcome to the Serendipity import utility'); // Translate
+@define('IMPORT_WHAT_CAN', 'Here you can import entries from other weblog software applications'); // Translate
+@define('IMPORT_SELECT', 'Please select the software you wish to import from'); // Translate
+@define('IMPORT_PLEASE_ENTER', 'Please enter the data as requested below'); // Translate
+@define('IMPORT_NOW', 'Import now!'); // Translate
+@define('IMPORT_STARTING', 'Starting import procedure...'); // Translate
+@define('IMPORT_FAILED', 'Import failed'); // Translate
+@define('IMPORT_DONE', 'Import successfully completed'); // Translate
+@define('IMPORT_WEBLOG_APP', 'Weblog application'); // Translate
+@define('EXPORT_FEED', 'Export full RSS feed'); // Translate
+@define('STATUS', 'Status after import'); // Translate
+@define('IMPORT_GENERIC_RSS', 'Generic RSS import'); // Translate
+@define('ACTIVATE_AUTODISCOVERY', 'Send Trackbacks to links found in the entry'); // Translate
+@define('WELCOME_TO_ADMIN', 'Welcome to the Serendipity Administration Suite.'); // Translate
+@define('PLEASE_ENTER_CREDENTIALS', 'Please enter your credentials below.'); // Translate
+@define('ADMIN_FOOTER_POWERED_BY', 'Powered by Serendipity %s and PHP %s'); // Translate
+@define('INSTALL_USEGZIP', 'Use gzip compressed pages'); // Translate
+@define('INSTALL_USEGZIP_DESC', 'To speed up delivery of pages, we can compress the pages we send to the visitor, given that his browser supports this. This is recommended'); // Translate
+@define('INSTALL_SHOWFUTURE', 'Show future entries'); // Translate
+@define('INSTALL_SHOWFUTURE_DESC', 'If enabled, this will show all entries in the future on your blog. Default is to hide those entries and only show them if the publish date has arrived.'); // Translate
+@define('INSTALL_DBPERSISTENT', 'Use persistent connections'); // Translate
+@define('INSTALL_DBPERSISTENT_DESC', 'Enable the usage of persistent database connections, read more <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">here</a>. This is normally not recommended'); // Translate
+@define('NO_IMAGES_FOUND', 'No images found'); // Translate
+@define('PERSONAL_SETTINGS', 'Personal Settings'); // Translate
+@define('REFERER', 'Referer'); // Translate
+@define('NOT_FOUND', 'Not found'); // Translate
+@define('NOT_WRITABLE', 'Not writable'); // Translate
+@define('WRITABLE', 'Writable'); // Translate
+@define('PROBLEM_DIAGNOSTIC', 'Due to a problematic diagnostic, you cannot continue with the installation before the above errors are fixed'); // Translate
+@define('SELECT_INSTALLATION_TYPE', 'Select which installation type you wish to use'); // Translate
+@define('WELCOME_TO_INSTALLATION', 'Welcome to the Serendipity Installation'); // Translate
+@define('FIRST_WE_TAKE_A_LOOK', 'First we will take a look at your current setup and attempt to diagnose any compatibility problems'); // Translate
+@define('ERRORS_ARE_DISPLAYED_IN', 'Errors are displayed in %s, recommendations in %s and success in %s'); // Translate
+@define('RED', 'red'); // Translate
+@define('YELLOW', 'yellow'); // Translate
+@define('GREEN', 'green'); // Translate
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s pre-installation report'); // Translate
+@define('RECOMMENDED', 'Recommended'); // Translate
+@define('ACTUAL', 'Actual'); // Translate
+@define('PHPINI_CONFIGURATION', 'php.ini configuration'); // Translate
+@define('PHP_INSTALLATION', 'PHP installation'); // Translate
+@define('THEY_DO', 'they do'); // Translate
+@define('THEY_DONT', 'they don\'t'); // Translate
+@define('SIMPLE_INSTALLATION', 'Simple installation'); // Translate
+@define('EXPERT_INSTALLATION', 'Expert installation'); // Translate
+@define('COMPLETE_INSTALLATION', 'Complete installation'); // Translate
+@define('WONT_INSTALL_DB_AGAIN', 'won\'t install the database again'); // Translate
+@define('CHECK_DATABASE_EXISTS', 'Checking to see if the database and tables already exists'); // Translate
+@define('CREATING_PRIMARY_AUTHOR', 'Creating primary author \'%s\''); // Translate
+@define('SETTING_DEFAULT_TEMPLATE', 'Setting default template'); // Translate
+@define('INSTALLING_DEFAULT_PLUGINS', 'Installing default plugins'); // Translate
+@define('SERENDIPITY_INSTALLED', 'Serendipity has been successfully installed'); // Translate
+@define('VISIT_BLOG_HERE', 'Visit your new blog here'); // Translate
+@define('THANK_YOU_FOR_CHOOSING', 'Thank you for choosing Serendipity'); // Translate
+@define('ERROR_DETECTED_IN_INSTALL', 'An error was detected in the installation'); // Translate
+@define('OPERATING_SYSTEM', 'Operating system'); // Translate
+@define('WEBSERVER_SAPI', 'Webserver SAPI'); // Translate
+@define('IMAGE_ROTATE_LEFT', 'Rotate image 90 degrees counter-clockwise'); // Translate
+@define('IMAGE_ROTATE_RIGHT', 'Rotate image 90 degrees clockwise'); // Translate
+@define('TEMPLATE_SET', '\'%s\' has been set as your active template'); // Translate
+@define('SEARCH_ERROR', 'The search function did not work as expected. Notice for the administrator of this blog: This may happen because of missing index keys in your database. On MySQL systems your database user account needs to be privileged to execute this query: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> The specific error returned by the database was: <pre>%s</pre>'); // Translate
+@define('EDIT_THIS_CAT', 'Editing "%s"'); // Translate
+@define('CATEGORY_REMAINING', 'Delete this category and move its entries to this category'); // Translate
+@define('CATEGORY_INDEX', 'Below is a list of categories available to your entries'); // Translate
+@define('NO_CATEGORIES', 'No categories'); // Translate
+@define('RESET_DATE', 'Reset date'); // Translate
+@define('RESET_DATE_DESC', 'Click here to reset the date to the current time'); // Translate
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Permissions can be set by running shell command: `<em>%s</em>` on the failed directory, or by setting this using an FTP program'); // Translate
+@define('WARNING_TEMPLATE_DEPRECATED', 'Warning: Your current template is using a deprecated template method, you are advised to update if possible'); // Translate
+@define('ENTRY_PUBLISHED_FUTURE', 'This entry is not yet published.'); // Translate
+@define('ENTRIES_BY', 'Entries by %s'); // Translate
+@define('PREVIOUS', 'Previous'); // Translate
+@define('NEXT', 'Next'); // Translate
+@define('APPROVE', 'Approve'); // Translate
+@define('DO_MARKUP_DESCRIPTION', 'Tilføy markup-transformasjoner på teksten (smilies, shortcut markups via *, /, _, ...). Hvis du slår dette av vil all HTML-kode i teksten bli beholdt.');
+@define('CATEGORY_ALREADY_EXIST', 'A category with the name "%s" already exist'); // Translate
+@define('IMPORT_NOTES', 'Note:'); // Translate
+@define('ERROR_FILE_FORBIDDEN', 'You are not allowed to upload files with active content'); // Translate
+@define('ADMIN', 'Administration'); // Re-Translate
+@define('ADMIN_FRONTPAGE', 'Frontpage'); // Translate
+@define('QUOTE', 'Quote'); // Translate
+@define('IFRAME_SAVE', 'Serendipity is now saving your entry, creating trackbacks and performing possible XML-RPC calls. This may take a while..'); // Translate
+@define('IFRAME_SAVE_DRAFT', 'A draft of this entry has been saved'); // Translate
+@define('IFRAME_PREVIEW', 'Serendipity is now creating the preview of your entry...'); // Translate
+@define('IFRAME_WARNING', 'Your browser does not support the concept of iframes. Please open your serendipity_config.inc.php file and set $serendipity[\'use_iframe\'] variable to FALSE.'); // Translate
+@define('NONE', 'none');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Default settings for new entries'); // Translate
+@define('UPGRADE', 'Upgrade'); // Translate
+@define('UPGRADE_TO_VERSION', 'Upgrade to version %s'); // Translate
+@define('DELETE_DIRECTORY', 'Delete directory'); // Translate
+@define('DELETE_DIRECTORY_DESC', 'You are about to delete the contents of a directory that contains media files, possibly files used in some of your entries.'); // Translate
+@define('FORCE_DELETE', 'Delete ALL files in this directory, including those not known by Serendipity'); // Translate
+@define('CREATE_DIRECTORY', 'Create directory'); // Translate
+@define('CREATE_NEW_DIRECTORY', 'Create new directory'); // Translate
+@define('CREATE_DIRECTORY_DESC', 'Here you can create a new directory to place media files in. Choose the name for your new directory and select an optional parent directory to place it in.'); // Translate
+@define('BASE_DIRECTORY', 'Base directory'); // Translate
+@define('USERLEVEL_EDITOR_DESC', 'Standard editor'); // Translate
+@define('USERLEVEL_CHIEF_DESC', 'Chief editor'); // Translate
+@define('USERLEVEL_ADMIN_DESC', 'Administrator'); // Translate
+@define('USERCONF_USERLEVEL', 'Access level'); // Translate
+@define('USERCONF_USERLEVEL_DESC', 'This level is used to determine what kind of access this user has to the blog'); // Translate
+@define('USER_SELF_INFO', 'Logged in as %s (%s)'); // Translate
+@define('ADMIN_ENTRIES', 'Entries'); // Translate
+@define('RECHECK_INSTALLATION', 'Recheck installation'); // Translate
+@define('IMAGICK_EXEC_ERROR', 'Unable to execute: "%s", error: %s, return var: %d'); // Translate
+@define('INSTALL_OFFSET_DESC', 'Enter the amount of hours between the date of your webserver (current: %clock%) and your desired time zone'); // Translate
+@define('UNMET_REQUIREMENTS', 'Requirements failed: %s'); // Translate
+@define('CHARSET', 'Charset');
+@define('AUTOLANG', 'Use visitor\'s browser language as default');
+@define('AUTOLANG_DESC', 'If enabled, this will use the visitor\'s browser language setting to determine the default language of your entry and interface language.');
+@define('INSTALL_AUTODETECT_URL', 'Autodetect used HTTP-Host'); // Translate
+@define('INSTALL_AUTODETECT_URL_DESC', 'If set to "true", Serendipity will ensure that the HTTP Host which was used by your visitor is used as your BaseURL setting. Enabling this will let you be able to use multiple domain names for your Serendipity Blog, and use the domain for all follow-up links which the user used to access your blog.'); // Translate
+@define('CONVERT_HTMLENTITIES', 'Try to auto-convert HTML entities?');
+@define('EMPTY_SETTING', 'You did not specify a valid value for "%s"!');
+@define('USERCONF_REALNAME', 'Real name'); // Translate
+@define('USERCONF_REALNAME_DESC', 'The full name of the author. This is the name seen by readers'); // Translate
+@define('HOTLINK_DONE', 'File hotlinked.<br />Done.'); // Translate
+@define('ENTER_MEDIA_URL_METHOD', 'Fetch method:'); // Translate
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Note: If you choose to hotlink to server, make sure you have permission to hotlink to the designated website, or the website is yours. Hotlink allows you to use off-site images without storing them locally.'); // Translate
+@define('MEDIA_HOTLINKED', 'hotlinked'); // Translate
+@define('FETCH_METHOD_IMAGE', 'Download image to your server'); // Translate
+@define('FETCH_METHOD_HOTLINK', 'Hotlink to server'); // Translate
+@define('DELETE_HOTLINK_FILE', 'Deleted the hotlinked file entitled <b>%s</b>'); // Translate
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Show E-Mail addresses?');
+
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_pt.inc.php b/lang/serendipity_lang_pt.inc.php
new file mode 100644 (file)
index 0000000..35b5819
--- /dev/null
@@ -0,0 +1,671 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+# Translation (c) by Ranulfo Netto <rcnetto@yahoo.com>
+
+@define('LANG_CHARSET', 'ISO-8859-1');
+@define('DATE_LOCALES', 'portuguese brazilian, pt, pt_BR');
+@define('DATE_FORMAT_ENTRY', '%A, %e de %B de %Y');
+@define('WYSIWYG_LANG', 'pt_br');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Painel de Administração do Serendipity');
+@define('HAVE_TO_BE_LOGGED_ON', 'Você deve entrar no sistema para ver esta página');
+@define('WRONG_USERNAME_OR_PASSWORD', 'Você deve ter fornecido nome de usuário ou senha inválidos');
+@define('APPEARANCE', 'Aparência');
+@define('MANAGE_STYLES', 'Gerenciar estilos');
+@define('CONFIGURE_PLUGINS', 'Configurar Plugins');
+@define('CONFIGURATION', 'Configuração');
+@define('BACK_TO_BLOG', 'De volta ao Weblog');
+@define('LOGIN', 'Login');
+@define('LOGOUT', 'Logout');
+@define('LOGGEDOUT', 'Logged out.');
+@define('CREATE', 'Criar');
+@define('SAVE', 'Salvar');
+@define('NAME', 'Nome');
+@define('CREATE_NEW_CAT', 'Criar nova categoria');
+@define('I_WANT_THUMB', 'Quero usar miniaturas em meu artigo.');
+@define('I_WANT_BIG_IMAGE', 'Quero usar a maior imagem em meu artigo.');
+@define('I_WANT_NO_LINK', ' Quero exibi-la como imagem');
+@define('I_WANT_IT_TO_LINK', 'Quero exibi-la como um link para esta URL:');
+@define('BACK', 'Volta');
+@define('FORWARD', 'Encaminha');
+@define('ANONYMOUS', 'Anônimo');
+@define('NEW_TRACKBACK_TO', 'Novo trackback feito para');
+@define('NEW_COMMENT_TO', 'Novo comentário enviado para');
+@define('RECENT', 'Recente...');
+@define('OLDER', 'Antigos...');
+@define('DONE', 'Pronto');
+@define('WELCOME_BACK', 'Bem-vindo de volta,');
+@define('TITLE', 'Título');
+@define('DESCRIPTION', 'Descrição');
+@define('PLACEMENT', 'Localização');
+@define('DELETE', 'Excluir');
+@define('SAVE', 'Salvar');
+@define('UP', 'Acima');
+@define('DOWN', 'Abaixo');
+@define('ENTRIES', 'Artigos:');
+@define('NEW_ENTRY', 'Novo artigo');
+@define('EDIT_ENTRIES', 'Editar artigos');
+@define('CATEGORIES', 'Categorias');
+@define('WARNING_THIS_BLAHBLAH', "ATENÇÃO:\\nIsso pode levar muito tempo se existirem muitas imagens sem miniaturas.");
+@define('CREATE_THUMBS', 'Reconstruir Miniaturas');
+@define('MANAGE_IMAGES', 'Gerenciar imagens');
+@define('NAME', 'Nome');
+@define('EMAIL', 'E-mail');
+@define('HOMEPAGE', 'Página pessoal');
+@define('COMMENT', 'Comentário');
+@define('REMEMBER_INFO', 'Relembrar Informações? ');
+@define('SUBMIT_COMMENT', 'Enviar Comentário');
+@define('NO_ENTRIES_TO_PRINT', 'Nenhum artigo para imprimir');
+@define('COMMENTS', 'Comentários');
+@define('ADD_COMMENT', 'Adicionar Comentários');
+@define('NO_COMMENTS', 'Nenhum cmentários');
+@define('POSTED_BY', 'Enviado por');
+@define('ON', 'em');
+@define('A_NEW_COMMENT_BLAHBLAH', 'Um novo comentário foi enviado para o seu Blog "%s", no artigo entitulada como "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'Um novo trackback foi feito para o seu Blog "%s", no artigo entitulada como "%s".');
+@define('NO_CATEGORY', 'Nenhuma categoria');
+@define('ENTRY_BODY', 'Corpo do artigo');
+@define('EXTENDED_BODY', 'Extensão do corpo do artigo');
+@define('CATEGORY', 'Categoria:');
+@define('EDIT', 'Editar');
+@define('NO_ENTRIES_BLAHBLAH', 'Nenhum artigo encontrada para a consulta %s' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'Sua busca para %s retornou %s resultados:');
+@define('SEARCH_TOO_SHORT', 'Sua consulta deve ter no mínimo 3 caracteres');
+@define('IMAGE', 'Imagem');
+@define('ERROR_FILE_NOT_EXISTS', 'Erro: O nome de arquivo antigo não existe!');
+@define('ERROR_FILE_EXISTS', 'Erro: O novo nome de arquivo já existe, escolha outro!');
+@define('ERROR_SOMETHING', 'Erro: Problema desconhecido.');
+@define('ADDING_IMAGE', 'Adicionando imagem...');
+@define('THUMB_CREATED_DONE', 'Miniatura criada.<br>Pronto.');
+@define('ERROR_FILE_EXISTS_ALREADY', 'Erro: Arquivo já existe em sua máquina!');
+@define('GO', 'Vai!');
+@define('NEWSIZE', 'Novo tamanho: ');
+@define('RESIZE_BLAHBLAH', '<b>Redimensionar %s</b><p>');
+@define('ORIGINAL_SIZE', 'Tamanho original: <i>%sx%s</i> pixel');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>Aqui você pode ajustar o novo tamanho das imagens. Se pretende manter as proporções, preencha apenas um valor e pressione a tecla TAB que automaticamente será calculado o novo tamanho de modo que as proporções não fiquem bagunçadas:');
+@define('QUICKJUMP_CALENDAR', 'Calendário de acesso rápido');
+@define('QUICKSEARCH', 'Pesquisa rápida');
+@define('SEARCH_FOR_ENTRY', 'Procure por um artigo');
+@define('ARCHIVES', 'Arquivos');
+@define('BROWSE_ARCHIVES', 'Navegar nos arquivos por mês');
+@define('TOP_REFERRER', 'Maiores Referências');
+@define('SHOWS_TOP_SITES', 'Exibe os links de entrada mais utilizados para entrar no seu blog');
+@define('TOP_EXITS', 'Maiores Saídas');
+@define('SHOWS_TOP_EXIT', 'Exibe os links de saída mais requisitados de seu blog');
+@define('SYNDICATION', 'Sindicalização');
+@define('SHOWS_RSS_BLAHBLAH', 'Shows RSS syndication links');
+@define('ADVERTISES_BLAHBLAH', 'Adverte da origem do seu blog');
+@define('HTML_NUGGET', 'Fragmento de HTML');
+@define('HOLDS_A_BLAHBLAH', 'Apresenta um fragmento de HTML à sua barra lateral');
+@define('TITLE_FOR_NUGGET', 'Título para o fragmento de HTML');
+@define('THE_NUGGET', 'Fragmento de HTML!');
+@define('SYNDICATE_THIS_BLOG', 'Sindicalizar esse Blog');
+@define('YOU_CHOSE', 'Sua escolha %s');
+@define('IMAGE_SIZE', 'Tamanho da imagem');
+@define('IMAGE_AS_A_LINK', 'Inserção de imagem');
+@define('POWERED_BY', 'Powered by');
+@define('TRACKBACKS', 'Trackbacks');
+@define('TRACKBACK', 'Trackback');
+@define('NO_TRACKBACKS', 'Nenhum Trackbacks');
+@define('TOPICS_OF', 'Tópicos de');
+@define('VIEW_FULL', 'ver tudo');
+@define('VIEW_TOPICS', 'ver tópicos');
+@define('AT', 'em');
+@define('SET_AS_TEMPLATE', 'Atribuir como template');
+@define('IN', 'no');
+@define('EXCERPT', 'Segmento');
+@define('TRACKED', 'Tracked');
+@define('LINK_TO_ENTRY', 'Link para o artigo');
+@define('LINK_TO_REMOTE_ENTRY', 'Link para artigo remoto');
+@define('IP_ADDRESS', 'Endereço IP');
+@define('USER', 'Usuário');
+@define('THUMBNAIL_USING_OWN', 'Usando %s como sua própria miniatura devido ao seu pequeno tamanho.');
+@define('THUMBNAIL_FAILED_COPY', 'A tentativa de usar %s como sua própria miniatura falhou devido à um erro na cópia!');
+@define('AUTHOR', 'Autor');
+@define('LAST_UPDATED', 'Última atualização');
+@define('TRACKBACK_SPECIFIC', 'URI específica do trackback para este artigo');
+@define('DIRECT_LINK', 'Link direto para este artigo');
+@define('COMMENT_ADDED', 'Seu comentário foi adicionado corretamente. ');
+@define('COMMENT_ADDED_CLICK', 'Clique %saqui para retornar%s aos comentários, ou %saqui para fechar%s esta janela.');
+@define('COMMENT_NOT_ADDED', 'Seus comentários não foram adicionados, porque comentários para este artigo foram desabilitadas. ');
+@define('COMMENT_NOT_ADDED_CLICK', 'Clique %saqui para retornar%s aos comentários, ou %saqui para fechar%s esta janela.');
+@define('COMMENTS_DISABLE', 'Não se permite comentários para este artigo');
+@define('COMMENTS_ENABLE', 'Comentários para este artigo são permitidos');
+@define('COMMENTS_CLOSED', 'O autor não autorizou comentários para este artigo');
+@define('EMPTY_COMMENT', 'Seu comentário está vazio, por favor, %svolte%s e tente novamente');
+@define('ENTRIES_FOR', 'Artigos para %s');
+@define('DOCUMENT_NOT_FOUND', 'O documento %s não foi encontrado.');
+@define('USERNAME', 'Usuário');
+@define('PASSWORD', 'Senha');
+@define('AUTOMATIC_LOGIN', 'Salvar informações');
+@define('SERENDIPITY_INSTALLATION', 'Instalação do Serendipity');
+@define('LEFT', 'esquerda');
+@define('RIGHT', 'direita');
+@define('HIDDEN', 'oculto');
+@define('REMOVE_TICKED_PLUGINS', 'Remover plugins marcados');
+@define('SAVE_CHANGES_TO_LAYOUT', 'Salvar modificações ao layout');
+@define('COMMENTS_FROM', 'Comentários de');
+@define('ERROR', 'Erro');
+@define('ENTRY_SAVED', 'Artigo salvo');
+@define('DELETE_SURE', 'Tem certeza que deseja excluir #%s definitivamente?');
+@define('NOT_REALLY', 'Não mesmo...');
+@define('DUMP_IT', 'Suma com ele!');
+@define('RIP_ENTRY', 'Até nunca mais artigo #%s');
+@define('CATEGORY_DELETED', 'Categoria #%s excluída. Os artigos antigos foram movidos para a categoria #%s');
+@define('INVALID_CATEGORY', 'Nenhuma categoria fornecida para exclusão');
+@define('CATEGORY_SAVED', 'Categoria salva');
+@define('SELECT_TEMPLATE', 'Selecione o template desejado para o seu Blog');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'Artigos não adicionados!');
+@define('YES', 'Sim');
+@define('NO', 'Não');
+@define('USE_DEFAULT', 'Default');
+@define('CHECK_N_SAVE', 'Verificar &amp; salvar');
+@define('DIRECTORY_WRITE_ERROR', 'Não foi possível escrever no diretório %s. Verifique as permissões.');
+@define('DIRECTORY_CREATE_ERROR', 'O Diretório %s não existe e não pode ser criado. Tente criá-lo manualmente');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; execute <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', 'Não pôde executar o binário %s');
+@define('FILE_WRITE_ERROR', 'Não foi possível editar o arquivo %s.');
+@define('FILE_CREATE_YOURSELF', 'Por favor, crie você mesmo o arquivo ou verifique suas permissões');
+@define('COPY_CODE_BELOW', '<br />* Copie o código abaixo e o coloque em %s no seu %s diretório:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Altere www para o usuário com o qual o apache é executado (ex.: nobody).');
+@define('BROWSER_RELOAD', 'Uma vez feito isso, pressione o botão "atualizar" ("reload") do seu navegador.');
+@define('DIAGNOSTIC_ERROR', 'Detectamos alguns erros quando verificamos as informações fornecidas por você:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity ainda não está instalado. Por favor <a href="%s">instale-o</a> agora.');
+@define('INCLUDE_ERROR', 'erro do serendipity: não foi possível incluir %s - abortando.');
+@define('DATABASE_ERROR', 'erro do serendipity: não foi possível conectar ao banco de dados - abortando.');
+@define('CREATE_DATABASE', 'Criando a instalação padrão do banco de dados...');
+@define('ATTEMPT_WRITE_FILE', 'Tentando editar o arquivo %s...');
+@define('WRITTEN_N_SAVED', 'Configuração escrita &amp; salva');
+@define('IMAGE_ALIGNMENT', 'Alinhamento de imagem');
+@define('ENTER_NEW_NAME', 'Informe o novo nome para: ');
+@define('RESIZING', 'Redimensionando');
+@define('RESIZE_DONE', 'Pronto (%s imagens redimensionadas).');
+@define('SYNCING', 'Sincronizando o banco de dados com o diretório de imagens');
+@define('SYNC_DONE', 'Pronto (%s imagens sincronizadas).');
+@define('DELETE_IMAGE_FAIL' , 'Não foi possível excluir a imagem <b>%s</b>');
+@define('DELETE_THUMBNAIL', 'Excluir a miniatura da imagem entitulada <b>%s</b>');
+@define('FILE_NOT_FOUND', 'Não foi possível localizar o arquivo entitulado <b>%s</b>, será que foi excluído?');
+@define('ABORT_NOW', 'Cancelar agora');
+@define('REMOTE_FILE_NOT_FOUND', 'O arquivo não foi localizado no servidor, tem certeza sobre a URL: <b>%s</b> está correta?');
+@define('FILE_FETCHED', '%s buscado como %s');
+@define('FILE_UPLOADED', 'O arquivo %s foi transferido corretamente: %s');
+@define('WORD_OR', 'Ou');
+@define('SCALING_IMAGE', 'Redimensionando %s para %s x %s px');
+@define('KEEP_PROPORTIONS', 'Manter proporções');
+@define('REALLY_SCALE_IMAGE', 'Quer mesmo redimensionar a imagem? Não haverá volta!!');
+@define('TOGGLE_ALL', 'Alternar para expandir tudo');
+@define('TOGGLE_OPTION', 'Opção para alternar');
+@define('SUBSCRIBE_TO_THIS_ENTRY', 'Inscrever-se para este artigo');
+@define('UNSUBSCRIBE_OK', "%s teve a inscrição cancelada para este artigo");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'Novo comentário para o artigo inscrita"%s"');
+@define('SUBSCRIPTION_MAIL', "Oi %s,\n\nUm novo comentário foi feito num artigo que você está monitorando em \"%s\", entitulada \"%s\"\nQuem enviou o comentário foi: %s\n\nO artigo à qual nos referimos pode ser encontrada em: %s\n\nVocê pode cancelar sua inscrição clicando neste link: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "Oi %s,\n\nUm novo trackback foi adicionado num artigo que você está monitorando em \"%s\", entitulada \"%s\"\nQuem enviou o comentário foi: %s\n\nO artigo à qual nos referimos pode ser encontrada em: %s\n\nVocê pode cancelar sua inscrição clicando neste link: %s\n");
+@define('SIGNATURE', "\n-- \n%s faz uso do Serendipity.\nO melhor Blog que tem por aí, e você também pode usá-lo.\nDê uma olhada em <http://s9y.org> para descobrir como.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91 feed');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0 feed');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0 feed');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 comments');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3 feed');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'Campo "managingEditor"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  'Campo "webMaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'Imagem para o RSS feed');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', 'Largura da imagem');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'Altura da imagem');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  'E-Mail do webmaster, se disponível. (vazio: oculto) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', 'E-Mail do editor, se disponível. (vazio: oculto) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'URL de uma imagem no formato GIF/JPEG/PNG, se disponível. (vazio: logotipo do serendipity)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'em pixels, max. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'em pixels, max. 400');
+@define('SYNDICATION_PLUGIN_TTL', 'Campo "ttl" (tempo de vida)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'Quantidade de minutos depois do qual seu blog não deverá ser mais "cacheados" por sites/aplicações (vazio: oculto) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'Campo "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', 'O campo "pubDate" deve ser empacotado para o canal RSS, para mostrar a data do último artigo?');
+@define('CONTENT', 'Conteúdo');
+@define('TYPE', 'Tipo');
+@define('DRAFT', 'Rascunho');
+@define('PUBLISH', 'Publicar');
+@define('PREVIEW', 'Pré-visualização');
+@define('DATE', 'Data');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', 'Atenção: A data que você especificou é inválida. Ela deve ser fornecida no formato DD/MM/AAAA HH:MM.');
+@define('CATEGORY_PLUGIN_DESC', 'Exibe a lista de categorias.');
+@define('ALL_AUTHORS', 'Todos autores');
+@define('CATEGORIES_TO_FETCH', 'Categorias para trazer');
+@define('CATEGORIES_TO_FETCH_DESC', 'Trazer categorias de qual autor?');
+@define('PAGE_BROWSE_ENTRIES', 'Página %s de %s, totalizando %s artigos');
+@define('PREVIOUS_PAGE', 'página anterior');
+@define('NEXT_PAGE', 'próxima página');
+@define('ALL_CATEGORIES', 'Todas as categorias');
+@define('DO_MARKUP', 'Executar trasnformações de marcação');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'Formatação de data');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'Formato da data atual do artigo, usando a mesma formatação da função strftime() do PHP. (Padrão: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'Não foi possível abrir o arquivo de template, por favor atualize o serendipity!');
+@define('ADVANCED_OPTIONS', 'Opções avançadas');
+@define('EDIT_ENTRY', 'Editar artigo');
+@define('HTACCESS_ERROR', 'Para checar a intalação do servidor web, serendipity precisa ter poder criar o arquivo ".htaccess". Isso não foi possível devido a erros de permissões. Por favor, ajuste as permissões para isso: <br />&nbsp;&nbsp;%s<br />e recarregue esta página.');
+@define('SIDEBAR_PLUGINS', 'Plugins da barra lateral');
+@define('EVENT_PLUGINS', 'Plugins de eventos');
+@define('SORT_ORDER', 'Ordenação');
+@define('SORT_ORDER_NAME', 'Nome do arquivo');
+@define('SORT_ORDER_EXTENSION', 'Extensão do arquivo');
+@define('SORT_ORDER_SIZE', 'Tamanho do arquivo');
+@define('SORT_ORDER_WIDTH', 'Largura da imagem');
+@define('SORT_ORDER_HEIGHT', 'Altura da imagem');
+@define('SORT_ORDER_DATE', 'Data de transferência');
+@define('SORT_ORDER_ASC', 'Ascendente');
+@define('SORT_ORDER_DESC', 'Descendente');
+@define('THUMBNAIL_SHORT', 'Miniatura');
+@define('ORIGINAL_SHORT', 'Orig.');
+@define('APPLY_MARKUP_TO', 'Aplicar marcação para %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'Começo da semana');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity detectou que sua configuração está instalada com a versão %s, entretanto serendipity está instalado na versão %s, você precisa atualizar o serendipity! <a href="%s">Clique aqui</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'Oi, e bem-vindo ao agente de atualização do Serendipity.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', 'Estou aqui para ajudá-lo a atualizar a instalação %s do seu Serendipity.');
+@define('SERENDIPITY_UPGRADER_WHY', 'Você enxerga esta mensagem porque acabou de instalar o Serendipity %s, mas ainda não atualizou a instalação do banco de dados para compatibilizar com esta versão');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'Atualização do banco de dados (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'Encontrei os seguintes arquivos .sql u]que precisam ser executados antes que você prossiga com a utilização normal do Serendipity');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  'Tarefas específicas da versão');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', 'Nenhuma tarefa específica da versão foi encontrada');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', 'Quer realizar as tarefas acima?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'Não, eu as executarei manualmente');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'Por favor, faça isso');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'Parece que que você não precisa executar nenhuma atualização');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', 'Considere a atualização do Serendipity');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'Você ignorou a fase de atualização do Serendipity, certifique-se de que o banco de dados está instalado corretamente e que as funções necessárias foram executadas');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'A sua instalação do Serendipity foi atualizada para a versão %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', 'Você pode retornar ao seu blog clicando %saqui%s');
+
+@define('MANAGE_USERS', 'Gerenciar usuários');
+@define('CREATE_NEW_USER', 'Criar novo usuário');
+@define('CREATE_NOT_AUTHORIZED', 'Você não pode modificar usuários que tenham o mesmo nível que o seu');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'Você não pode criar usuários com um nível maior que o seu');
+@define('CREATED_USER', 'Um novo usuário %s foi criado');
+@define('MODIFIED_USER', 'As propriedades do usuário %s foram alteradas');
+@define('USER_LEVEL', 'Nível do usuário');
+@define('DELETE_USER', 'Você está prestes a excluir o usuário #%d %s. Tem certeza disso? Isso fará com que os artigos escritos por ele não sejam mais exibidos.');
+@define('DELETED_USER', 'Usuário #%d %s excluído.');
+@define('LIMIT_TO_NUMBER', 'Quantos itens devem ser exibidos?');
+@define('ENTRIES_PER_PAGE', 'artigos por página');
+@define('XML_IMAGE_TO_DISPLAY', 'Botão XML');
+@define('XML_IMAGE_TO_DISPLAY_DESC','Links para XML Feeds serão exibidos por esta imagem. Deixe em branco para padrão, digite \'none\' para desabilitar.');
+
+@define('DIRECTORIES_AVAILABLE', 'Na lista de subdiretórios disponíveis você pode clicar em qualquer nome de diretório para criar um novo diretório dentro daquela estrutura.');
+@define('ALL_DIRECTORIES', 'todos os diretórios');
+@define('MANAGE_DIRECTORIES', 'Gerenciar diretórios');
+@define('DIRECTORY_CREATED', 'Diretório <strong>%s</strong> foi criado.');
+@define('PARENT_DIRECTORY', 'Diretório superior');
+@define('CONFIRM_DELETE_DIRECTORY', 'Tem certeza que quer excluir todo o conteúdo do diretório %s?');
+@define('ERROR_NO_DIRECTORY', 'Erro: Diretório %s não existe');
+@define('CHECKING_DIRECTORY', 'Verificando arquivos no diretório %s');
+@define('DELETING_FILE', 'Excluindo arquivo %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', 'Não foi possível remover um diretório que não esteja vazio. Marque a opção "forçar exclusão" se deseja remover seus arquivos também, e envie o comando novamente. Os arquivos existenntes são:');
+@define('DIRECTORY_DELETE_FAILED', 'A exclusão do diretório %s falhou. Verifique permissões ou as mensagem acima.');
+@define('DIRECTORY_DELETE_SUCCESS', 'Diretório %s excluído corretamente.');
+@define('SKIPPING_FILE_EXTENSION', 'Ignorando arquivo: Faltando extensão em %s.');
+@define('SKIPPING_FILE_UNREADABLE', 'Ignorando arquivo: %s ilegível.');
+@define('FOUND_FILE', 'Encontrado arquivo novo/modificado: %s.');
+@define('ALREADY_SUBCATEGORY', '%s já é uma subcategoria de %s.');
+@define('PARENT_CATEGORY', 'Categoria superior');
+@define('IN_REPLY_TO', 'Em reposta à');
+@define('TOP_LEVEL', 'Nível máximo');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s feed');
+@define('PERMISSIONS', 'Permissões');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', 'Configurações de banco de dados');
+@define('INSTALL_CAT_DB_DESC', 'Aqui você pode inserir todas as informações do seu banco de dados. O Serendipity precisa dessas informações para funcionar.');
+@define('INSTALL_DBTYPE', 'Tipo de banco de dados');
+@define('INSTALL_DBTYPE_DESC', 'Tipo de banco de dados');
+@define('INSTALL_DBHOST', 'Servidor de banco de dados');
+@define('INSTALL_DBHOST_DESC', 'Endereço/Nome do seu servidor de banco de dados');
+@define('INSTALL_DBUSER', 'Usuário de banco de dados');
+@define('INSTALL_DBUSER_DESC', 'O nome de usuário que conecta ao banco');
+@define('INSTALL_DBPASS', 'Senha do banco de dados');
+@define('INSTALL_DBPASS_DESC', 'A senha correspondente ao usuário acima');
+@define('INSTALL_DBNAME', 'Nome do banco de dados');
+@define('INSTALL_DBNAME_DESC', 'O nome do banco de dados');
+@define('INSTALL_DBPREFIX', 'Prefixo para as tabelas do banco de dados');
+@define('INSTALL_DBPREFIX_DESC', 'Prefixo utilizado para nomear as tabelas, ex.: serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', 'Caminhos');
+@define('INSTALL_CAT_PATHS_DESC', 'Os vários caminhos para pastas e arquivos essênciais. Não se esqueça de terminar com barras para os diretórios');
+@define('INSTALL_FULLPATH', 'Caminho completo');
+@define('INSTALL_FULLPATH_DESC', 'O caminho completo e absoluto para a sua instalação do serendipity');
+@define('INSTALL_UPLOADPATH', 'Caminho para o Upload');
+@define('INSTALL_UPLOADPATH_DESC', 'Todos os arquivos transferidos irão parar aí, relativo ao \'Caminho completo\' - geralmente \'uploads/\'');
+@define('INSTALL_RELPATH', 'Caminho relativo');
+@define('INSTALL_RELPATH_DESC', 'Caminho para o serendipity em seu navegador, geralmente \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', 'Caminho relativo do template');
+@define('INSTALL_RELTEMPLPATH_DESC', 'Caminho para o diretório onde estão os seus templates - Relativo ao \'caminho relativo\'');
+@define('INSTALL_RELUPLOADPATH', 'Caminho relativo do Upload');
+@define('INSTALL_RELUPLOADPATH_DESC', 'Caminho para o \'uploads\' em seu navegador - Relativo ao \'caminho relativo\'');
+@define('INSTALL_URL', 'URL do blog');
+@define('INSTALL_URL_DESC', 'URL base para a instalação do serendipity');
+@define('INSTALL_INDEXFILE', 'Arquivo inicial');
+@define('INSTALL_INDEXFILE_DESC', 'Nome do arquivo inicial do serendipity');
+
+/* Generel settings */
+@define('INSTALL_CAT_SETTINGS', 'Configurações gerais');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Padroniza como o Serendipity deve se comportar');
+@define('INSTALL_USERNAME', 'Usuário do administrador');
+@define('INSTALL_USERNAME_DESC', 'Nome de usuário para o login do administrador');
+@define('INSTALL_PASSWORD', 'Senha do administrador');
+@define('INSTALL_PASSWORD_DESC', 'Senha para o login do administrador');
+@define('INSTALL_EMAIL', 'E-mail do administrador');
+@define('INSTALL_EMAIL_DESC', 'E-mail do administrador do blog');
+@define('INSTALL_SENDMAIL', 'Enviar e-mails ao administrador?');
+@define('INSTALL_SENDMAIL_DESC', 'Você deseja receber notificações via e-mail quando novos comentários forem incluídos em seus artigos?');
+@define('INSTALL_SUBSCRIBE', 'Permitir que usuários se inscrevam nos artigos?');
+@define('INSTALL_SUBSCRIBE_DESC', 'Permitir que usuários se inscrevam nos artigos e com isso, recebam notificações via e-mail quando novos comentários forem adicionados?');
+@define('INSTALL_BLOGNAME', 'Nome do Blog');
+@define('INSTALL_BLOGNAME_DESC', 'Título do seu Blog');
+@define('INSTALL_BLOGDESC', 'Descrição do Blog');
+@define('INSTALL_BLOGDESC_DESC', 'Descrição');
+@define('INSTALL_LANG', 'Idioma');
+@define('INSTALL_LANG_DESC', 'Selecione o idioma para o seu blog');
+
+/* Appearance and options */
+@define('INSTALL_CAT_DISPLAY', 'Aparência e opções');
+@define('INSTALL_CAT_DISPLAY_DESC', 'Padroniza como o Serendipity é exibido');
+@define('INSTALL_WYSIWYG', 'Usar editor WYSIWYG');
+@define('INSTALL_WYSIWYG_DESC', 'Você quer usar o editor WYSIWYG? (Funciona no IE5+ e parcialmente no Mozilla 1.3+)');
+@define('INSTALL_XHTML11', 'Forçar adequação ao XHTML 1.1');
+@define('INSTALL_XHTML11_DESC', 'Quer forçar uma adequação ao padrão XHTML 1.1 (pode causar problemas de exibição nos navegadores de 4ª geração (4.x))');
+@define('INSTALL_POPUP', 'Habilitar o uso de janelas popups');
+@define('INSTALL_POPUP_DESC', 'Você quer que o weblog utilize janelas popups para comentários, trackbacks e etc?');
+@define('INSTALL_EMBED', 'O serendipity está integrado?');
+@define('INSTALL_EMBED_DESC', 'Se você quer empacotar o serendipity em um website, mude para verdadeiro para descartar quaisquer cabeçalhos e apenas imprimir o conteúdo. Você pode fazer uso da opção \'Arquivo inicial\' para usar uma classe mais abrangente onde você colocaria os cabeçalhos normais de sua página. Veja o arquivo README para mais informações!');
+@define('INSTALL_BLOCKREF', 'Referências bloqueadas');
+@define('INSTALL_BLOCKREF_DESC', 'Existem servidores especiais que você não gostaria de listar na sua lista de referências? Separe a lista dos servidores com \';\' e note que o servidor será bloqueado por uma busca parcial em sua string!');
+@define('INSTALL_REWRITE', 'Rescrita de URL');
+@define('INSTALL_REWRITE_DESC', 'Selecione as regras que você gostaria de usar na geração de URLs. A habilitação da rescrita de URL criará URLS bem formatadas para o seu blog e o deixará melhor indexável para bots como o do google. O servidor web precisa dar suporte ou ao mod_rewrite ou ao "AllowOverride All" para o diretório do seu serendipity. A configuração padrão é auto detectada');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', 'Configurações da conversão de imagens');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'Informações gerais sobre como o serendipity deve lidar com imagens');
+@define('INSTALL_IMAGEMAGICK', 'Usar Imagemagick');
+@define('INSTALL_IMAGEMAGICK_DESC', 'Você tem o \'image magick\' instalado e quer utilizá-lo para redimensionar imagens?');
+@define('INSTALL_IMAGEMAGICKPATH', 'Caminho para o executável do conversor');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'Caminho completo e nome do executável do image magick');
+@define('INSTALL_THUMBSUFFIX', 'Sufixo das miniaturas');
+@define('INSTALL_THUMBSUFFIX_DESC', 'As miniaturas serão nomeadas com o seguinte formato: original.[sufixo].ext');
+@define('INSTALL_THUMBWIDTH', 'Dimensão das miniaturas ');
+@define('INSTALL_THUMBWIDTH_DESC', 'Largura máxima estática das miniaturas geradas automaticamente');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', 'Detalhes pessoais');
+@define('USERCONF_CAT_PERSONAL_DESC', 'Altere os seus detalhes pessoais');
+@define('USERCONF_USERNAME', 'Seu nome de usuário');
+@define('USERCONF_USERNAME_DESC', 'O nome de usuário que você usa para se identificar no blog');
+@define('USERCONF_PASSWORD', 'Sua senha');
+@define('USERCONF_PASSWORD_DESC', 'A senha que você quer usar para se identificar no blog');
+@define('USERCONF_EMAIL', 'Seu endereço de e-mail');
+@define('USERCONF_EMAIL_DESC', 'Seu endereço de e-mail pessoal');
+@define('USERCONF_SENDCOMMENTS', 'Enviar notificação dos comentários?');
+@define('USERCONF_SENDCOMMENTS_DESC', 'Quer receber e-mails quando comentários forem enviados para os seus artigos?');
+@define('USERCONF_SENDTRACKBACKS', 'Enviar notificação de trackbacks?');
+@define('USERCONF_SENDTRACKBACKS_DESC', 'Quer receber e-mails quando trackbacks forem enviados para os seus artigos?');
+@define('USERCONF_ALLOWPUBLISH', 'Direitos: Publicação de artigos?');
+@define('USERCONF_ALLOWPUBLISH_DESC', 'Este usuário está autorizado a publicar artigos?');
+@define('SUCCESS', 'Sucesso');
+@define('POWERED_BY_SHOW_TEXT', 'Exibir "Serendipity" como texto');
+@define('POWERED_BY_SHOW_TEXT_DESC', 'Exibirá o "Serendipity Weblog" como texto');
+@define('POWERED_BY_SHOW_IMAGE', 'Exibir "Serendipity" como um logotipo');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Exibe o logotipo do Serendipity');
+
+@define('SETTINGS_SAVED_AT', 'As novas configurações foram salvas em %s');
+@define('PLUGIN_ITEM_DISPLAY', 'Onde o item deve ser exibido?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'Apenas artigo extendido');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'Página de visão geral apenas');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'Todas as vezes');
+@define('RSS_IMPORT_CATEGORY', 'Utilize essa categoria para artigos que não encontrem uma categoria no Serendipity');
+@define('ERROR_UNKNOWN_NOUPLOAD', 'Ocorreu um erro desconhecido, o arquivo não foi transferido. Talvez o tamanho do arquivo seja maior que o permitido pelo seu servidor. Verifique com o seu servidor de internet, ou edite o php.ini para permitir transferência de arquivos de maior tamanho.');
+@define('COMMENTS_WILL_BE_MODERATED', 'Comentários enviados estarão sujeitos a moderação antes de serem exibidos.');
+@define('YOU_HAVE_THESE_OPTIONS', 'Você possui as seguintes opções disponíveis');
+@define('THIS_COMMENT_NEEDS_REVIEW', 'Atenção: Esse comentário precisa de aprovação antes que seja exibido');
+@define('DELETE_COMMENT', 'Excluir comentário');
+@define('APPROVE_COMMENT', 'Aprovar comentário');
+@define('REQUIRES_REVIEW', 'Requer revisão');
+@define('COMMENT_APPROVED', 'Comentário #%s foi aprovado corretamente');
+@define('COMMENT_DELETED', 'Comentário #%s foi excluído corretamente');
+@define('VIEW', 'Exibir');
+@define('COMMENT_ALREADY_APPROVED', 'Comentário #%s parece já ter sido aprovado');
+@define('COMMENT_EDITED', 'O comentário selecionado foi editado');
+@define('HIDE', 'Ocultar');
+@define('VIEW_EXTENDED_ENTRY', 'Continuar lendo "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'Esse link não deve ser clicado. Ele contém a URI de trackback para este artigo. Você pode usar esse URI para enviar ping- & trackbacks do seu próprio weblog para esse artigo. Para copiar o link, clique com o botão direito e selecione "Copiar Atalho" no Internet Explorer ou "Copiar localização do link" no Mozilla.');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'Atenção: Esse trackback precisa de aprovação antes que seja exibido');
+@define('DELETE_TRACKBACK', 'Excluir trackback');
+@define('APPROVE_TRACKBACK', 'Aprovar trackback');
+@define('TRACKBACK_APPROVED', 'O trackback #%s foi aprovado corretamente');
+@define('TRACKBACK_DELETED', 'O trackback #%s foi excluído corretamente');
+@define('COMMENTS_MODERATE', 'Comentários & trackbacks para este artigo requerem moderação');
+@define('PLUGIN_SUPERUSER_HTTPS', 'Usar https para login');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'Permitir o link de login aponte para uma link https. seu servidor web precisa ter suporte a isso!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'Tornar clicáveis os links externos?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"não": Links externos não marcados (Maiores saídas, Maiores referências, Comentários de usuários) não são exibidos como puro texto para evitar spam do google (recomendado). "sim": Links externos não marcados são exibidos como links. Podem ser sobrescritos pela configuração da barra lateral!');
+@define('PAGE_BROWSE_COMMENTS', 'Página %s de %s, totlizando %s comentários');
+@define('FILTERS', 'Filtros');
+@define('FIND_ENTRIES', 'Encontrar artigos');
+@define('FIND_COMMENTS', 'Encontrar comentários');
+@define('FIND_MEDIA', 'Encontrar mídia');
+@define('FILTER_DIRECTORY', 'Diretório');
+@define('SORT_BY', 'Ordenar por');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'Nenhum trackback enviado: Não foi possível abrir conexão para %s na porta %d');
+@define('MEDIA', 'Mídia');
+@define('MEDIA_LIBRARY', 'Biblioteca de mídia');
+@define('ADD_MEDIA', 'Adicionar mídia');
+@define('ENTER_MEDIA_URL', 'Entre com a URL de um arquivo para buscá-lo:');
+@define('ENTER_MEDIA_UPLOAD', 'Selecione o arquivo que deseja transferir:');
+@define('SAVE_FILE_AS', 'Salvar arquivo como:');
+@define('STORE_IN_DIRECTORY', 'Guardar no seguinte diretório: ');
+@define('MEDIA_RENAME', 'Renomear esse arquivo');
+@define('IMAGE_RESIZE', 'Redimensionar essa imagem');
+@define('MEDIA_DELETE', 'Excluir esse arquivo');
+@define('FILES_PER_PAGE', 'Arquivos por página');
+@define('CLICK_FILE_TO_INSERT', 'Clique no arquivo que deseja inserir:');
+@define('SELECT_FILE', 'Selecione arquivo para inserir');
+@define('MEDIA_FULLSIZE', 'Tamanho total');
+@define('CALENDAR_BOW_DESC', 'Dia da semana que deve ser considerado o início da semana. Padrão é segunda-feira');
+@define('SUPERUSER', 'Administração do weblog');
+@define('ALLOWS_YOU_BLAHBLAH', 'Provê um link para a administração do weblog na barra lateral ');
+@define('CALENDAR', 'Calendário');
+@define('SUPERUSER_OPEN_ADMIN', 'Abrir administração');
+@define('SUPERUSER_OPEN_LOGIN', 'Abrir tela de login');
+@define('INVERT_SELECTIONS', 'Inverter Seleção');
+@define('COMMENTS_DELETE_CONFIRM', 'Tem certeza de que deseja excluir os comentários selecionados?');
+@define('COMMENT_DELETE_CONFIRM', 'Tem certeza de que deseja excluir o comentário #%d, escrito por %s?');
+@define('DELETE_SELECTED_COMMENTS', 'Excluir comentários selecionados');
+@define('VIEW_COMMENT', 'Exibir comentário');
+@define('VIEW_ENTRY', 'Exibir artigo');
+@define('DELETE_FILE', 'Excluir o campo entitulado <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', 'Você está prestes a excluir <b>%s</b><br />Se estiver utilizando esse arquivo em algum dos seus artigos, vai resultar em links ou imagens perdidas<br />Deseja realmente prosseguir com a exclusão?<br /><br />');
+@define('TRACKBACK_SENDING', 'Enviando trackback para a URI %s...');
+@define('TRACKBACK_SENT', 'Trackback enviada com sucesso');
+@define('TRACKBACK_FAILED', 'Trackback falhou: %s');
+@define('TRACKBACK_NOT_FOUND', 'Nenhum URI de trackback foi encontrado.');
+@define('TRACKBACK_URI_MISMATCH', 'A URI de trackback descoberta não com é semelhante à URI alvo.');
+@define('TRACKBACK_CHECKING', 'Checando <u>%s</u> por possíveis trackbacks...');
+@define('TRACKBACK_NO_DATA', 'O alvo não contém dados');
+@define('TRACKBACK_SIZE', 'URI alvo excedeu o tamanho máximo de %s bytes para um arquivo.');
+@define('VIEWMODE_THREADED', 'Alternar para exibição por discussão');
+@define('COMMENTS_VIEWMODE_THREADED', 'Discussão');
+@define('COMMENTS_VIEWMODE_LINEAR', 'Sequencial');
+@define('DISPLAY_COMMENTS_AS', 'Exibir comentários como');
+@define('DATE_FORMAT_SHORT', '%d/%m/%Y %H:%M');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', ',');
+@define('NUMBER_FORMAT_THOUSANDS', '.');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Categoria #%s excluída. Os artigos antigos foram movidos para a categoria #%s');
+@define('INSTALL_TOP_AS_LINKS', 'Exibir maiores saídas/referências como links?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"não": Saídas e Referências são exibidas como puro texto para prevenir spam do google. "sim": Saídas e Refrências são exibidas como links. "padrão": Usa o valor definido na configuração global (recomendado).');
+@define('ADD_MEDIA_BLAHBLAH', '<b>Adiciona um arquivo para o seu repositório de mídia:</b><p>Aqui você pode transferir arquivos de mídia, ou oriente-me para pegá-lo em algum lugar na web! Se não possuir uma imagem apropriada, <a href="http://images.google.com" target="_blank">procure no google</a> alguma imagem que tenha relação com o assunto, os resultados são geralmente úteis e divertidos :)<p><b>Selecione o método:</b><br>');
+@define('COMMENTS_FILTER_SHOW', 'Show'); // Translate
+@define('COMMENTS_FILTER_ALL', 'All'); // Translate
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'Only approved'); // Translate
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'Pending approval'); // Translate
+@define('RSS_IMPORT_BODYONLY', 'Put all imported text in the "body" section and do not split up into "extended entry" section.'); // Translate
+@define('SYNDICATION_PLUGIN_FULLFEED', 'Show full articles with extended body inside RSS feed'); // Translate
+@define('MT_DATA_FILE', 'Movable Type data file'); // Translate
+@define('FORCE', 'Force'); // Translate
+@define('CREATE_AUTHOR', 'Create author \'%s\'.'); // Translate
+@define('CREATE_CATEGORY', 'Create category \'%s\'.'); // Translate
+@define('MYSQL_REQUIRED', 'You must have the MySQL extension in order to perform this action.'); // Translate
+@define('COULDNT_CONNECT', 'Could not connect to MySQL database: %s.'); // Translate
+@define('COULDNT_SELECT_DB', 'Could not select database: %s.'); // Translate
+@define('COULDNT_SELECT_USER_INFO', 'Could not select user information: %s.'); // Translate
+@define('COULDNT_SELECT_CATEGORY_INFO', 'Could not select category information: %s.'); // Translate
+@define('COULDNT_SELECT_ENTRY_INFO', 'Could not select entry information: %s.'); // Translate
+@define('COULDNT_SELECT_COMMENT_INFO', 'Could not select comment information: %s.'); // Translate
+@define('WEEK', 'Week'); // Translate
+@define('WEEKS', 'Weeks'); // Translate
+@define('MONTHS', 'Months'); // Translate
+@define('DAYS', 'Days'); // Translate
+@define('ARCHIVE_FREQUENCY', 'Calendar item frequency'); // Translate
+@define('ARCHIVE_FREQUENCY_DESC', 'The calendar interval to use between each item in the list'); // Translate
+@define('ARCHIVE_COUNT', 'Number of items in the list'); // Translate
+@define('ARCHIVE_COUNT_DESC', 'The total number of months, weeks or days to display'); // Translate
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'Below is a list of installed plugins'); // Translate
+@define('SIDEBAR_PLUGIN', 'sidebar plugin'); // Translate
+@define('EVENT_PLUGIN', 'event plugin'); // Translate
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'Click here to install a new %s'); // Translate
+@define('VERSION', 'version'); // Translate
+@define('INSTALL', 'Install'); // Translate
+@define('ALREADY_INSTALLED', 'Already installed'); // Translate
+@define('SELECT_A_PLUGIN_TO_ADD', 'Select the plugin which you wish to install'); // Translate
+@define('INSTALL_OFFSET', 'Server time Offset'); // Translate
+@define('STICKY_POSTINGS', 'Sticky Postings'); // Translate
+@define('INSTALL_FETCHLIMIT', 'Entries to display on frontpage'); // Translate
+@define('INSTALL_FETCHLIMIT_DESC', 'Number of entries to display for each page on the frontend'); // Translate
+@define('IMPORT_ENTRIES', 'Import data'); // Translate
+@define('EXPORT_ENTRIES', 'Export entries'); // Translate
+@define('IMPORT_WELCOME', 'Welcome to the Serendipity import utility'); // Translate
+@define('IMPORT_WHAT_CAN', 'Here you can import entries from other weblog software applications'); // Translate
+@define('IMPORT_SELECT', 'Please select the software you wish to import from'); // Translate
+@define('IMPORT_PLEASE_ENTER', 'Please enter the data as requested below'); // Translate
+@define('IMPORT_NOW', 'Import now!'); // Translate
+@define('IMPORT_STARTING', 'Starting import procedure...'); // Translate
+@define('IMPORT_FAILED', 'Import failed'); // Translate
+@define('IMPORT_DONE', 'Import successfully completed'); // Translate
+@define('IMPORT_WEBLOG_APP', 'Weblog application'); // Translate
+@define('EXPORT_FEED', 'Export full RSS feed'); // Translate
+@define('STATUS', 'Status after import'); // Translate
+@define('IMPORT_GENERIC_RSS', 'Generic RSS import'); // Translate
+@define('ACTIVATE_AUTODISCOVERY', 'Send Trackbacks to links found in the entry'); // Translate
+@define('WELCOME_TO_ADMIN', 'Welcome to the Serendipity Administration Suite.'); // Translate
+@define('PLEASE_ENTER_CREDENTIALS', 'Please enter your credentials below.'); // Translate
+@define('ADMIN_FOOTER_POWERED_BY', 'Powered by Serendipity %s and PHP %s'); // Translate
+@define('INSTALL_USEGZIP', 'Use gzip compressed pages'); // Translate
+@define('INSTALL_USEGZIP_DESC', 'To speed up delivery of pages, we can compress the pages we send to the visitor, given that his browser supports this. This is recommended'); // Translate
+@define('INSTALL_SHOWFUTURE', 'Show future entries'); // Translate
+@define('INSTALL_SHOWFUTURE_DESC', 'If enabled, this will show all entries in the future on your blog. Default is to hide those entries and only show them if the publish date has arrived.'); // Translate
+@define('INSTALL_DBPERSISTENT', 'Use persistent connections'); // Translate
+@define('INSTALL_DBPERSISTENT_DESC', 'Enable the usage of persistent database connections, read more <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">here</a>. This is normally not recommended'); // Translate
+@define('NO_IMAGES_FOUND', 'No images found'); // Translate
+@define('PERSONAL_SETTINGS', 'Personal Settings'); // Translate
+@define('REFERER', 'Referer'); // Translate
+@define('NOT_FOUND', 'Not found'); // Translate
+@define('NOT_WRITABLE', 'Not writable'); // Translate
+@define('WRITABLE', 'Writable'); // Translate
+@define('PROBLEM_DIAGNOSTIC', 'Due to a problematic diagnostic, you cannot continue with the installation before the above errors are fixed'); // Translate
+@define('SELECT_INSTALLATION_TYPE', 'Select which installation type you wish to use'); // Translate
+@define('WELCOME_TO_INSTALLATION', 'Welcome to the Serendipity Installation'); // Translate
+@define('FIRST_WE_TAKE_A_LOOK', 'First we will take a look at your current setup and attempt to diagnose any compatibility problems'); // Translate
+@define('ERRORS_ARE_DISPLAYED_IN', 'Errors are displayed in %s, recommendations in %s and success in %s'); // Translate
+@define('RED', 'red'); // Translate
+@define('YELLOW', 'yellow'); // Translate
+@define('GREEN', 'green'); // Translate
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s pre-installation report'); // Translate
+@define('RECOMMENDED', 'Recommended'); // Translate
+@define('ACTUAL', 'Actual'); // Translate
+@define('PHPINI_CONFIGURATION', 'php.ini configuration'); // Translate
+@define('PHP_INSTALLATION', 'PHP installation'); // Translate
+@define('THEY_DO', 'they do'); // Translate
+@define('THEY_DONT', 'they don\'t'); // Translate
+@define('SIMPLE_INSTALLATION', 'Simple installation'); // Translate
+@define('EXPERT_INSTALLATION', 'Expert installation'); // Translate
+@define('COMPLETE_INSTALLATION', 'Complete installation'); // Translate
+@define('WONT_INSTALL_DB_AGAIN', 'won\'t install the database again'); // Translate
+@define('CHECK_DATABASE_EXISTS', 'Checking to see if the database and tables already exists'); // Translate
+@define('CREATING_PRIMARY_AUTHOR', 'Creating primary author \'%s\''); // Translate
+@define('SETTING_DEFAULT_TEMPLATE', 'Setting default template'); // Translate
+@define('INSTALLING_DEFAULT_PLUGINS', 'Installing default plugins'); // Translate
+@define('SERENDIPITY_INSTALLED', 'Serendipity has been successfully installed'); // Translate
+@define('VISIT_BLOG_HERE', 'Visit your new blog here'); // Translate
+@define('THANK_YOU_FOR_CHOOSING', 'Thank you for choosing Serendipity'); // Translate
+@define('ERROR_DETECTED_IN_INSTALL', 'An error was detected in the installation'); // Translate
+@define('OPERATING_SYSTEM', 'Operating system'); // Translate
+@define('WEBSERVER_SAPI', 'Webserver SAPI'); // Translate
+@define('IMAGE_ROTATE_LEFT', 'Rotate image 90 degrees counter-clockwise'); // Translate
+@define('IMAGE_ROTATE_RIGHT', 'Rotate image 90 degrees clockwise'); // Translate
+@define('TEMPLATE_SET', '\'%s\' has been set as your active template'); // Translate
+@define('SEARCH_ERROR', 'The search function did not work as expected. Notice for the administrator of this blog: This may happen because of missing index keys in your database. On MySQL systems your database user account needs to be privileged to execute this query: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> The specific error returned by the database was: <pre>%s</pre>'); // Translate
+@define('EDIT_THIS_CAT', 'Editing "%s"'); // Translate
+@define('CATEGORY_REMAINING', 'Delete this category and move its entries to this category'); // Translate
+@define('CATEGORY_INDEX', 'Below is a list of categories available to your entries'); // Translate
+@define('NO_CATEGORIES', 'No categories'); // Translate
+@define('RESET_DATE', 'Reset date'); // Translate
+@define('RESET_DATE_DESC', 'Click here to reset the date to the current time'); // Translate
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Permissions can be set by running shell command: `<em>%s</em>` on the failed directory, or by setting this using an FTP program'); // Translate
+@define('WARNING_TEMPLATE_DEPRECATED', 'Warning: Your current template is using a deprecated template method, you are advised to update if possible'); // Translate
+@define('ENTRY_PUBLISHED_FUTURE', 'This entry is not yet published.'); // Translate
+@define('ENTRIES_BY', 'Entries by %s'); // Translate
+@define('PREVIOUS', 'Previous'); // Translate
+@define('NEXT', 'Next'); // Translate
+@define('APPROVE', 'Approve'); // Translate
+@define('DO_MARKUP_DESCRIPTION', 'Apply markup transformations to the text (smilies, shortcut markups via *, /, _, ...). Disabling this will preserve any HTML-code in the text.'); // Translate
+@define('CATEGORY_ALREADY_EXIST', 'A category with the name "%s" already exist'); // Translate
+@define('IMPORT_NOTES', 'Note:'); // Translate
+@define('ERROR_FILE_FORBIDDEN', 'You are not allowed to upload files with active content'); // Translate
+@define('ADMIN', 'Administration'); // Re-Translate
+@define('ADMIN_FRONTPAGE', 'Frontpage'); // Translate
+@define('QUOTE', 'Quote'); // Translate
+@define('IFRAME_SAVE', 'Serendipity is now saving your entry, creating trackbacks and performing possible XML-RPC calls. This may take a while..'); // Translate
+@define('IFRAME_SAVE_DRAFT', 'A draft of this entry has been saved'); // Translate
+@define('IFRAME_PREVIEW', 'Serendipity is now creating the preview of your entry...'); // Translate
+@define('IFRAME_WARNING', 'Your browser does not support the concept of iframes. Please open your serendipity_config.inc.php file and set $serendipity[\'use_iframe\'] variable to FALSE.'); // Translate
+@define('NONE', 'none');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Default settings for new entries'); // Translate
+@define('UPGRADE', 'Upgrade'); // Translate
+@define('UPGRADE_TO_VERSION', 'Upgrade to version %s'); // Translate
+@define('DELETE_DIRECTORY', 'Delete directory'); // Translate
+@define('DELETE_DIRECTORY_DESC', 'You are about to delete the contents of a directory that contains media files, possibly files used in some of your entries.'); // Translate
+@define('FORCE_DELETE', 'Delete ALL files in this directory, including those not known by Serendipity'); // Translate
+@define('CREATE_DIRECTORY', 'Create directory'); // Translate
+@define('CREATE_NEW_DIRECTORY', 'Create new directory'); // Translate
+@define('CREATE_DIRECTORY_DESC', 'Here you can create a new directory to place media files in. Choose the name for your new directory and select an optional parent directory to place it in.'); // Translate
+@define('BASE_DIRECTORY', 'Base directory'); // Translate
+@define('USERLEVEL_EDITOR_DESC', 'Standard editor'); // Translate
+@define('USERLEVEL_CHIEF_DESC', 'Chief editor'); // Translate
+@define('USERLEVEL_ADMIN_DESC', 'Administrator'); // Translate
+@define('USERCONF_USERLEVEL', 'Access level'); // Translate
+@define('USERCONF_USERLEVEL_DESC', 'This level is used to determine what kind of access this user has to the blog'); // Translate
+@define('USER_SELF_INFO', 'Logged in as %s (%s)'); // Translate
+@define('ADMIN_ENTRIES', 'Entries'); // Translate
+@define('RECHECK_INSTALLATION', 'Recheck installation'); // Translate
+@define('IMAGICK_EXEC_ERROR', 'Unable to execute: "%s", error: %s, return var: %d'); // Translate
+@define('INSTALL_OFFSET_DESC', 'Enter the amount of hours between the date of your webserver (current: %clock%) and your desired time zone'); // Translate
+@define('UNMET_REQUIREMENTS', 'Requirements failed: %s'); // Translate
+@define('CHARSET', 'Charset');
+@define('AUTOLANG', 'Use visitor\'s browser language as default');
+@define('AUTOLANG_DESC', 'If enabled, this will use the visitor\'s browser language setting to determine the default language of your entry and interface language.');
+@define('INSTALL_AUTODETECT_URL', 'Autodetect used HTTP-Host'); // Translate
+@define('INSTALL_AUTODETECT_URL_DESC', 'If set to "true", Serendipity will ensure that the HTTP Host which was used by your visitor is used as your BaseURL setting. Enabling this will let you be able to use multiple domain names for your Serendipity Blog, and use the domain for all follow-up links which the user used to access your blog.'); // Translate
+@define('CONVERT_HTMLENTITIES', 'Try to auto-convert HTML entities?');
+@define('EMPTY_SETTING', 'You did not specify a valid value for "%s"!');
+@define('USERCONF_REALNAME', 'Real name'); // Translate
+@define('USERCONF_REALNAME_DESC', 'The full name of the author. This is the name seen by readers'); // Translate
+@define('HOTLINK_DONE', 'File hotlinked.<br />Done.'); // Translate
+@define('ENTER_MEDIA_URL_METHOD', 'Fetch method:'); // Translate
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Note: If you choose to hotlink to server, make sure you have permission to hotlink to the designated website, or the website is yours. Hotlink allows you to use off-site images without storing them locally.'); // Translate
+@define('MEDIA_HOTLINKED', 'hotlinked'); // Translate
+@define('FETCH_METHOD_IMAGE', 'Download image to your server'); // Translate
+@define('FETCH_METHOD_HOTLINK', 'Hotlink to server'); // Translate
+@define('DELETE_HOTLINK_FILE', 'Deleted the hotlinked file entitled <b>%s</b>'); // Translate
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Show E-Mail addresses?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_ru.inc.php b/lang/serendipity_lang_ru.inc.php
new file mode 100644 (file)
index 0000000..af8f265
--- /dev/null
@@ -0,0 +1,671 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+@define('LANG_CHARSET', 'utf-8');
+@define('DATE_LOCALES', 'ru_RU.utf-8');
+@define('DATE_FORMAT_ENTRY', '%A, %e %B. %Y');
+@define('DATE_FORMAT_SHORT', '%Y-%m-%d %H:%M');
+@define('WYSIWYG_LANG', 'en');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', '.');
+@define('NUMBER_FORMAT_THOUSANDS', ', ');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Администрирование Serendipity');
+@define('HAVE_TO_BE_LOGGED_ON', 'Вы должны войти под каким-нибудь пользователем, чтобы иметь доступ к этой странице');
+@define('WRONG_USERNAME_OR_PASSWORD', 'Похоже, что вы ввели неверное имя пользователя или пароль');
+@define('APPEARANCE', 'Внешний вид');
+@define('MANAGE_STYLES', 'Работа со стилями');
+@define('CONFIGURE_PLUGINS', 'Настройка плагинов');
+@define('CONFIGURATION', 'Конфигурация');
+@define('BACK_TO_BLOG', 'Назад к веблогу');
+@define('LOGIN', 'Войти');
+@define('LOGOUT', 'Выйти');
+@define('LOGGEDOUT', 'Сеанс завершён.');
+@define('CREATE', 'Создать');
+@define('EDIT_THIS_CAT', 'Редактирование "%s - %s"');
+@define('SAVE', 'Сохранить');
+@define('NAME', 'Имя');
+@define('CREATE_NEW_CAT', 'Создать новую категорию');
+@define('I_WANT_THUMB', 'В этой записи я хочу использовать тамбнэйл.');
+@define('I_WANT_BIG_IMAGE', 'В этой записи я хочу использовать изображение оригинальных размеров.');
+@define('I_WANT_NO_LINK', ' Я хочу, чтобы это было изображениe');
+@define('I_WANT_IT_TO_LINK', 'Я хочу, чтобы это была ссылка на вот этот url:');
+@define('BACK', 'Назад');
+@define('FORWARD', 'Вперёд');
+@define('ANONYMOUS', 'Аноним');
+@define('NEW_TRACKBACK_TO', 'Новая обратная ссылка была создана к');
+@define('NEW_COMMENT_TO', 'Новый комментарий было добавлен к');
+@define('RECENT', 'Недавнее...');
+@define('OLDER', 'Давнее...');
+@define('DONE', 'Done');
+@define('WELCOME_BACK', 'Добро пожаловать,');
+@define('TITLE', 'Заголовок');
+@define('DESCRIPTION', 'Описание');
+@define('PLACEMENT', 'Расположение');
+@define('DELETE', 'Удалить');
+@define('SAVE', 'Сохранить');
+@define('UP', 'ВВЕРХ');
+@define('DOWN', 'ВНИЗ');
+@define('ENTRIES', 'записи');
+@define('NEW_ENTRY', 'Новая запись');
+@define('EDIT_ENTRIES', 'Редактировать записи');
+@define('CATEGORIES', 'Категории');
+@define('WARNING_THIS_BLAHBLAH', "ВНИМАНИЕ:\\nЭта операция может занять длительное время, если имеется много изображений без тамбнэйлов.");
+@define('CREATE_THUMBS', 'Создать тамбнэйлы заново');
+@define('MANAGE_IMAGES', 'Работа с изображениями');
+@define('NAME', 'Имя');
+@define('EMAIL', 'Email');
+@define('HOMEPAGE', 'Домашняя страница');
+@define('COMMENT', 'Комментарий');
+@define('REMEMBER_INFO', 'Запомнить информацию? ');
+@define('SUBMIT_COMMENT', 'Отправить комментарий');
+@define('NO_ENTRIES_TO_PRINT', 'Нету здесь никаких заметок...');
+@define('COMMENTS', 'Комментарии');
+@define('ADD_COMMENT', 'Добавить комментарий');
+@define('NO_COMMENTS', 'Нет комментариев.');
+@define('POSTED_BY', 'Добавил ');
+@define('ON', 'on');
+@define('A_NEW_COMMENT_BLAHBLAH', 'Новый комментарий был добавлен в вашем блоге "%s", к записи "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'Новая обратная ссылка была создана к записи вашего блога под названием "%s".');
+@define('NO_CATEGORY', 'Без категории');
+@define('ENTRY_BODY', 'Текст записи');
+@define('EXTENDED_BODY', 'Допольнительный текст');
+@define('CATEGORY', 'Категория');
+@define('EDIT', 'Редактировать');
+@define('NO_ENTRIES_BLAHBLAH', 'Не было найдено записей по завпросу %s' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'По вашему поиску %s найдено результатов:');
+@define('SEARCH_TOO_SHORT', 'Ваш запрос на поиск должен быть длиннее 3 символов');
+@define('IMAGE', 'Изображение');
+@define('ERROR_FILE_NOT_EXISTS', 'Ошибка: Старое имя файла не существует!');
+@define('ERROR_FILE_EXISTS', 'Ошибка: Новое имя файла уже используется, пожалуйста выберите другое!');
+@define('ERROR_SOMETHING', 'Ошибка: Что-то не так...');
+@define('ADDING_IMAGE', 'Добавление изображения...');
+@define('THUMB_CREATED_DONE', 'Тамбнэйл успешно создан.');
+@define('ERROR_FILE_EXISTS_ALREADY', 'Ошибка: Файл уже существует на вашем компьютере!');
+@define('ERROR_UNKNOWN_NOUPLOAD', 'Произошла неизвестная ошибка, файл не был загружен. Возможно, размер вашего файл превысил допустивый максимальный размер, разрешённый на вашем сервере. Сверьтесь с вашим провайдером, или отредактируйте ваш файл php.ini чтобы позволить загрузку на сервер файлов большего размера.');
+@define('GO', 'Давай!');
+@define('NEWSIZE', 'Новый размер: ');
+@define('RESIZE_BLAHBLAH', '<b>Изменить размеры %s</b><p>');
+@define('ORIGINAL_SIZE', 'Оригинальный размер: <i>%sx%s</i> pixel');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>Здесь вы можете изменить размер изображения. Если вы хотите изменить размеры пропорционально, просто введите значение в одном из двух полей, и нажмите клавишу TAB - второе поле будет заполнено автоматически с учётом пропорций изображения.</p>');
+@define('QUICKJUMP_CALENDAR', 'Календарь');
+@define('QUICKSEARCH', 'Быстрый поиск');
+@define('SEARCH_FOR_ENTRY', 'Поиск по записям');
+@define('ARCHIVES', 'Архивы');
+@define('BROWSE_ARCHIVES', 'Просмотр архивов по месяцам');
+@define('TOP_REFERRER', 'Откуда пришли');
+@define('SHOWS_TOP_SITES', 'Показывает сайты, которые ссылались на ваш блог чаще всего');
+@define('TOP_EXITS', 'Куда ушли');
+@define('SHOWS_TOP_EXIT', 'Показывает сайты, куда читатели вашего блога уходили чаще всего');
+@define('SYNDICATION', 'Синхронизация');
+@define('SHOWS_RSS_BLAHBLAH', 'Показывает ссылки на RSS-ленты для аггрегации вашего блога');
+@define('ADVERTISES_BLAHBLAH', 'Рекламирует происхождение вашего блога (ссылка на сайт Serendipity)');
+@define('HTML_NUGGET', 'Фрагмент HTML');
+@define('HOLDS_A_BLAHBLAH', 'Добавляет фрагмент HTML кода в вашу боковую панель');
+@define('TITLE_FOR_NUGGET', 'Заголовок вашего фрагмента');
+@define('THE_NUGGET', 'Фрагмент HTML!');
+@define('SYNDICATE_THIS_BLOG', 'Новостные ленты');
+@define('YOU_CHOSE', 'Вы выбрали %s');
+@define('IMAGE_ROTATE_LEFT', 'Повернуть изображение на 90 градусов против часовой стрелки');
+@define('IMAGE_ROTATE_RIGHT', 'Повернуть изображение на 90 градусов по часовой стрелке');
+@define('IMAGE_SIZE', 'Размер изображения');
+@define('IMAGE_AS_A_LINK', 'Вставка изображения');
+@define('POWERED_BY', 'Сделано с помощью');
+@define('TRACKBACKS', 'Обратные ссылки');
+@define('TRACKBACK', 'Обратная ссылка');
+@define('NO_TRACKBACKS', 'Нет обратных ссылок');
+@define('TOPICS_OF', 'Заголовки');
+@define('VIEW_FULL', 'полный просмотр');
+@define('VIEW_TOPICS', 'посмотр заголовков');
+@define('AT', 'в');
+@define('SET_AS_TEMPLATE', 'Использовать этот стиль');
+@define('IN', 'в категории');
+@define('EXCERPT', 'Выборка');
+@define('TRACKED', 'Tracked');
+@define('LINK_TO_ENTRY', 'Ссылка на запись');
+@define('LINK_TO_REMOTE_ENTRY', 'Ссылка на удалённую (remote) запись');
+@define('IP_ADDRESS', 'IP-адрес');
+@define('USER', 'Пользователь');
+@define('THUMBNAIL_USING_OWN', '%s будет своим собственным тамбнэйлом, так как размеры изображения уже достаточно малы.');
+@define('THUMBNAIL_FAILED_COPY', 'Хотелось использовать %s как его собственный тамбнэйл, но не удалось скопировать файл!');
+@define('AUTHOR', 'Автор');
+@define('LAST_UPDATED', 'Последнее обновление');
+@define('TRACKBACK_SPECIFIC', 'URI этой записи для создания обратных ссылок (trackback)');
+@define('DIRECT_LINK', 'Прямая ссылка на эту запись');
+@define('COMMENT_ADDED', 'Ваш комментарий был успешно добавлен. ');
+@define('COMMENT_ADDED_CLICK', 'Кликните %sздесь, чтобы вернуться%s к комментариям, и %sздесь, чтобы закрыть%s это окно.');
+@define('COMMENT_NOT_ADDED', 'Ваш комментарий не смог быть добавлен, потому что эту запись запрещено комментировать. ');
+@define('COMMENT_NOT_ADDED_CLICK', 'Кликните %sздесь, чтобы вернуться%s к комментариям, и %sздесь, чтобы закрыть%s это окно.');
+@define('COMMENTS_DISABLE', 'Запретить добавление комментариев к этой записи');
+@define('COMMENTS_ENABLE', 'Разрешить добавление комментариев к этой записи');
+@define('COMMENTS_CLOSED', 'Автор не разрешил комментировать эту запись');
+@define('EMPTY_COMMENT', 'Ваш комментарий ничего не содержал? Пожалуйста %sвернитесь%s и попытайтесь снова');
+@define('ENTRIES_FOR', 'Записи для %s');
+@define('DOCUMENT_NOT_FOUND', 'Документ %s не найден.');
+@define('USERNAME', 'Имя пользователя');
+@define('PASSWORD', 'Пароль');
+@define('AUTOMATIC_LOGIN', 'Запомнить эту информацию');
+@define('SERENDIPITY_INSTALLATION', 'Установка Serendipity');
+@define('LEFT', 'слева');
+@define('RIGHT', 'справа');
+@define('HIDDEN', 'спрятан');
+@define('REMOVE_TICKED_PLUGINS', 'Убрать выделенные плагины');
+@define('SAVE_CHANGES_TO_LAYOUT', 'Сохранить изменения');
+@define('COMMENTS_FROM', 'Комментарии от');
+@define('ERROR', 'Ошибка');
+@define('ENTRY_SAVED', 'Ваша запись была сохранена');
+@define('DELETE_SURE', 'Вы уверены, что хотите удалить полностью #%s?');
+@define('NOT_REALLY', 'Не уверен...');
+@define('DUMP_IT', 'Уверен!');
+@define('RIP_ENTRY', 'Запись #%s удалена');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Категория #%s удалена. Старые записи перемещены в категорию #%s');
+@define('CATEGORY_DELETED', 'Категория #%s удалена.');
+@define('CATEGORY_REMAINING', 'Удалить эту категорию и переместить её записи в следующую категорию: %s');
+@define('INVALID_CATEGORY', 'Не было указано категории для удаления');
+@define('CATEGORY_SAVED', 'Данные о категории сохранены');
+@define('SELECT_TEMPLATE', 'Выберите стиль, который вы хотите использовать для вашего блога');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'Записи не были добавлены!');
+@define('MT_DATA_FILE', 'Файл данных Movable Type');
+@define('FORCE', 'Принудить');
+@define('CREATE_AUTHOR', 'Создать автора \'%s\'.');
+@define('CREATE_CATEGORY', 'Создать категорию \'%s\'.');
+@define('MYSQL_REQUIRED', 'Вы должны иметь поддержку MySQL чтобы выполнить это действие.');
+@define('COULDNT_CONNECT', 'Не удалось подключиться к базе данных MySQL : %s.');
+@define('COULDNT_SELECT_DB', 'Не удалось выбрать базу данных: %s.');
+@define('COULDNT_SELECT_USER_INFO', 'Не удалось выбрать информацию о пользователе: %s.');
+@define('COULDNT_SELECT_CATEGORY_INFO', 'Не удалось выбрать информацию о категории: %s.');
+@define('COULDNT_SELECT_ENTRY_INFO', 'Не удалось выбрать информацию о записи: %s.');
+@define('COULDNT_SELECT_COMMENT_INFO', 'Не удалось выбрать информацию о комментарии: %s.');
+@define('YES', 'Да');
+@define('NO', 'Нет');
+@define('USE_DEFAULT', 'По умолчанию');
+@define('CHECK_N_SAVE', 'Проверить &amp; сохранить');
+@define('DIRECTORY_WRITE_ERROR', 'Не могу записать в каталог %s. Проверьте права доступа к каталогу.');
+@define('DIRECTORY_CREATE_ERROR', 'Каталог %s не существует и не может быть создан. Пожалуйста, создайте его вручную.');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; run <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', 'Невозможно запустить файл %s');
+@define('FILE_WRITE_ERROR', 'Невозможна запись в файл %s.');
+@define('FILE_CREATE_YOURSELF', 'Пожалуйста создайте файл вручную или проверьте права доступа');
+@define('COPY_CODE_BELOW', '<br />* Просто скопируйте код ниже и поместите его в %s в вашей папке %s:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Изменить www на имя пользователя, под которым запущен apache (например, nobody).');
+@define('BROWSER_RELOAD', 'После того, как вы это сделаете, нажмите кнопку "reload" вашего браузера.');
+@define('DIAGNOSTIC_ERROR', 'Мы обнаружили несколько ошибок, пока проверяли введённую вами информацию:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity ещё не установлен. Пожалуйста <a href="%s">проведите установку</a> прямо сейчас.');
+@define('INCLUDE_ERROR', 'Ошибка serendipity: невозможно включить файл  %s - прекращение работы.');
+@define('DATABASE_ERROR', 'Ошибка serendipity: невозможно подключиться к базе данных - прекращение работы.');
+@define('CREATE_DATABASE', 'Создание настроек базы данных по умолчанию...');
+@define('ATTEMPT_WRITE_FILE', 'Попытка записать файл %s...');
+@define('WRITTEN_N_SAVED', 'Конфигурация записана &amp; сохранена');
+@define('IMAGE_ALIGNMENT', 'Выравнивание изображения');
+@define('ENTER_NEW_NAME', 'Введите новое имя для: ');
+@define('RESIZING', 'Изменение размеров');
+@define('RESIZE_DONE', 'Готово! (Изменено изображений: %s).');
+@define('SYNCING', 'Синхронизация базы данных с каталогом изображений');
+@define('SYNC_DONE', 'Готово! (Синхронизировано изображений: %s).');
+@define('FILE_NOT_FOUND', 'Невозможно найти файл <b>%s</b>, может быть он уже был удалён?');
+@define('ABORT_NOW', 'Отмена');
+@define('REMOTE_FILE_NOT_FOUND', 'Файл не был найден на удалённом сервере. Вы уверены, что эта ссылка верна? URL: <b>%s</b>');
+@define('FILE_FETCHED', '%s скачан и сохранён как %s');
+@define('FILE_UPLOADED', 'Файл %s успешно загружен на сервер как %s');
+@define('WORD_OR', 'Или');
+@define('SCALING_IMAGE', 'Изменение размеров %s на %s x %s точек');
+@define('KEEP_PROPORTIONS', 'Сохранить пропорции');
+@define('REALLY_SCALE_IMAGE', 'Вы уверены, что хотите изменить размеры изображения? Эта операция необратима!');
+@define('TOGGLE_ALL', 'Раскрыть все разделы');
+@define('TOGGLE_OPTION', 'Перключить опцию');
+@define('SUBSCRIBE_TO_THIS_ENTRY', 'Подписаться на эту запись');
+@define('UNSUBSCRIBE_OK', "%s теперь отписан от этой записи");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'Новый комментарий к записи, на которую вы подписаны - "%s"');
+@define('SUBSCRIPTION_MAIL', "Добрый день %s,\n\nНовый комментарий был добавлен к записи, за которой вы следите на \"%s\", запись под названием \"%s\"\nИмя автора: %s\n\nВы можете найти запись здесь: %s\n\nВы можете отписаться от записи, проследовав по этой ссылке: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "Добрый день %s,\n\nНовая обратная ссылка была добавлена к записи, за который вы следите на \"%s\", запись под названием \"%s\"\nИмя автора: %s\n\nВы можете найти запись здесь: %s\n\nВы можете отписаться от записи, проследовав по этой ссылке: %s\n");
+@define('SIGNATURE', "\n-- \n%s работает на движке Serendipity.\nЛучший блог, какой можно найти, и вы тоже можете им воспользоваться.\nЗагляните на <http://s9y.org> чтобы узнать больше.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 - комментарии');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'Поле "managingEditor"');
+@define('SYNDICATION_PLUGIN_WEBMASTER', 'Поле "webMaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'Изображение для RSS-ленты');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', 'Ширина изображения');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'Высота изображения');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC', 'E-Mail адрес веб-мастера, если таковой есть. (пустое поле будет скрыто) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', 'E-Mail адрес главного редактора, если таковой есть. (пустое поле будет скрыто) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'URL изображения в формате GIF/JPEG/PNG, если можно. (пустое поле означает serendipity-logo)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'в пикселях, макс. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'в пикселях, макс. 400');
+@define('SYNDICATION_PLUGIN_TTL', 'Поле "ttl" (time-to-live)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', 'Количество минут после которых ваш блог не должен оставаться в кэше внешних сайтов или приложений (пустое поле будет скрыто) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'Поле "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', 'Должно ли поле "pubDate" быть встроено в RSS-канал, чтобы показать дату последней записи?');
+@define('CONTENT', 'Содержимое');
+@define('TYPE', 'Тип');
+@define('DRAFT', 'Черновик');
+@define('PUBLISH', 'Опубликовать');
+@define('PREVIEW', 'Предварительный просмотр');
+@define('DATE', 'Дата');
+@define('DATE_FORMAT_2', 'Y-m-d H:i');
+@define('DATE_INVALID', 'Внимание: Дата, указанная вами, неверна. Она должна быть указана в формате YYYY-MM-DD HH:MM.');
+@define('CATEGORY_PLUGIN_DESC', 'Показывает список категорий.');
+@define('ALL_AUTHORS', 'Все авторы');
+@define('CATEGORIES_TO_FETCH', 'Категории для получения');
+@define('CATEGORIES_TO_FETCH_DESC', 'Получить категории какого автора?');
+@define('PAGE_BROWSE_ENTRIES', 'Страница %s из %s, всего записей: %s');
+@define('PREVIOUS_PAGE', 'предыдущая страница');
+@define('NEXT_PAGE', 'следующая страница');
+@define('ALL_CATEGORIES', 'Все категории');
+@define('DO_MARKUP', 'Произвести трансформации разметок');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'Формат даты');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'Формат даты записи, с использованием переменных PHP-функции strftime(). (По умолчанию: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'Невозможно открыть файл шаблона, пожалуйста обновите serendipity!');
+@define('ADVANCED_OPTIONS', 'Дополнительные опции');
+@define('EDIT_ENTRY', 'Редактировать запись');
+@define('HTACCESS_ERROR', 'Чтобы проверить настройки вашего веб-сервера, serendipity необходимо иметь права записи в файл ".htaccess". Эта операция не удалась из-за недостаточных прав доступа к файлу. Пожалуйста, измените эти права командой типа: <br />&nbsp;&nbsp;%s<br />и перегрузите эту страницу.');
+@define('SIDEBAR_PLUGINS', 'Плагины боковых панелей');
+@define('EVENT_PLUGINS', 'Event-плагины');
+@define('SORT_ORDER', 'Порядок сортировки');
+@define('SORT_ORDER_NAME', 'По имени файла');
+@define('SORT_ORDER_EXTENSION', 'По расширению файла');
+@define('SORT_ORDER_SIZE', 'По размеру файла');
+@define('SORT_ORDER_WIDTH', 'По ширине изображения');
+@define('SORT_ORDER_HEIGHT', 'По высоте изображения');
+@define('SORT_ORDER_DATE', 'По дате загрузки');
+@define('SORT_ORDER_ASC', 'По возрастанию');
+@define('SORT_ORDER_DESC', 'По убыванию');
+@define('THUMBNAIL_SHORT', 'Тамбнэйл');
+@define('ORIGINAL_SHORT', 'Оригинал');
+@define('APPLY_MARKUP_TO', 'Apply markup to %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'Начало недели');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity обнаружил, что ваша конфигурация установлена для версии %s, в то время как сами файлы движка serendipity соответствуют версии %s, вам нужен апгрейд! <a href="%s">Нажмите здесь чтобы продолжить</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'Привет, и добро пожаловать в агента обновления Serendipity.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', 'Я был создан чтобы помочь вам обновить ваш веблог Serendipity %s.');
+@define('SERENDIPITY_UPGRADER_WHY', 'Вы видите это сообщение потому что вы только что установили Serendipity %s, но не обновили вашу базу данных чтобы соответствовать этой версии');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', 'Обновления базы данных (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'Я нашёл следующие .sql файлы, которые должны быть выполнены перед тем, как вы сможете продолжить работу с Serendipity');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC', 'Специфичные для этой версии действия');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', 'Не было найдено действий, специфичных для этой версии');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', 'Вы хотите, чтобы я произвёл эти действия прямо сейчас?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'Нет, я произведу их самостоятельно и вручную');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'Да, пожалуйста');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'Похоже на то, что вам не нужно производить никаких обновлений');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', 'Считайте ваш движок Serendipity обновлённым');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'Вы проигнорировали этап автоматического обновления Serendipity, пожалуйста проследите чтбы ваша база данных была корректно обновлена и указанные действия произведены вручную');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'Ваш движок Serendipity теперь обновлён до версии %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', 'Вы можете вернуться к вашему блогу кликнув %sздесь%s');
+@define('MANAGE_USERS', 'Работа с пользователями');
+@define('CREATE_NEW_USER', 'Создать нового пользователя');
+@define('CREATE_NOT_AUTHORIZED', 'Вы не можете редактировать пользователей того же уровня доступа, что и ваш собственный');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'Вы не можете создать пользователей с уровнем доступа выше вашего собственного');
+@define('CREATED_USER', 'Новый пользователь %s был успешно создан');
+@define('MODIFIED_USER', 'Свойства пользователя %s были изменены');
+@define('USER_LEVEL', 'Userlevel');
+@define('DELETE_USER', 'Вы собираетесь удалить пользователя #%d %s. Вы уверены? Эта операция запретит отображение любых добавленных им записей.');
+@define('DELETED_USER', 'Пользователь #%d %s удалён.');
+@define('LIMIT_TO_NUMBER', 'Сколько заметок должно быть показано?');
+@define('ENTRIES_PER_PAGE', 'записей на странице');
+@define('XML_IMAGE_TO_DISPLAY', 'Кпонка XML');
+@define('XML_IMAGE_TO_DISPLAY_DESC', 'Ссылки на XML фиды будут отмечены этим изображением. Оставьте поле пустым для картинки по умолчанию, или введите \'none\' чтобы не показывать кнопки вообще.');
+
+@define('DIRECTORIES_AVAILABLE', 'В списке доступных каталогов вы можете кликнуть на любой каталог, чтобы создать в нём новый подкаталог.');
+@define('ALL_DIRECTORIES', 'все каталоги');
+@define('MANAGE_DIRECTORIES', 'Работа с каталогами');
+@define('DIRECTORY_CREATED', 'Каталог <strong>%s</strong> был успешно создан.');
+@define('PARENT_DIRECTORY', 'Главный каталог');
+@define('CONFIRM_DELETE_DIRECTORY', 'Вы уверены, что хотите удалить все содержимое каталога %s?');
+@define('ERROR_NO_DIRECTORY', 'Ошибка: Каталог %s не существует');
+@define('CHECKING_DIRECTORY', 'Проверка файлов в каталоге %s');
+@define('DELETING_FILE', 'Удаление файла %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', 'Не удалось удалить не пустой каталог. Поставьте галочку "Принудительное удаление", если вы хотиле удалить все файлы из этого каталога, и попробуйте удалить каталог снова. В каталоге найдены файлы:');
+@define('DIRECTORY_DELETE_FAILED', 'Не удалось удалить каталог %s. Проверьте права доступа или сообщения об ошибках выше.');
+@define('DIRECTORY_DELETE_SUCCESS', 'Каталог %s успешно удалён.');
+@define('SKIPPING_FILE_EXTENSION', 'Пропускаем файл: Нет расшерения у файла %s.');
+@define('SKIPPING_FILE_UNREADABLE', 'Пропускаем файл: %s - не читается.');
+@define('FOUND_FILE', 'Найден новый/изменённый файл: %s.');
+@define('ALREADY_SUBCATEGORY', '%s уже является подкатегорией %s.');
+@define('PARENT_CATEGORY', 'Главная категория');
+@define('IN_REPLY_TO', 'В ответ на');
+@define('TOP_LEVEL', 'Верхний уровень');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', 'лента %s');
+@define('PERMISSIONS', 'Права доступа');
+@define('SETTINGS_SAVED_AT', 'Новые настройки были сохранены в %s');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', 'Настройки базы данных');
+@define('INSTALL_CAT_DB_DESC', 'Здесь вы можете ввести всю информацию о вашей базе данных. Serendipity необходимы эти настройки чтобы нормально функционировать');
+@define('INSTALL_DBTYPE', 'Тип базы данных');
+@define('INSTALL_DBTYPE_DESC', 'Тип вашей базы данных');
+@define('INSTALL_DBHOST', 'Хост базы данных');
+@define('INSTALL_DBHOST_DESC', 'Имя сервера с вашей базой данных');
+@define('INSTALL_DBUSER', 'Пользователь базы данных');
+@define('INSTALL_DBUSER_DESC', 'Имя пользователя, используемое чтобы подключиться к вашей базе данных');
+@define('INSTALL_DBPASS', 'Пароль базы данных');
+@define('INSTALL_DBPASS_DESC', 'Пароль для указанного выше имени пользователя');
+@define('INSTALL_DBNAME', 'Имя базы данных');
+@define('INSTALL_DBNAME_DESC', 'Название вашей базы данных');
+@define('INSTALL_DBPREFIX', 'Префикс таблиц');
+@define('INSTALL_DBPREFIX_DESC', 'Префикс таблиц в вашей базе даынных, например serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', 'Пути');
+@define('INSTALL_CAT_PATHS_DESC', 'Различные пути к необходимым каталогам и файлам. Не забывайте слэши в конце путей к каталогам!');
+@define('INSTALL_FULLPATH', 'Полный путь');
+@define('INSTALL_FULLPATH_DESC', 'Полный и абсолютный путь к каталогу serendipity');
+@define('INSTALL_UPLOADPATH', 'Путь для аплоадов');
+@define('INSTALL_UPLOADPATH_DESC', 'Все загруженные на сервер файлы будут помещены в этто каталог, обычно он указывается относительно полного пути - чаще всего, \'uploads/\'');
+@define('INSTALL_RELPATH', 'Относительный путь');
+@define('INSTALL_RELPATH_DESC', 'Путь к serendipity для вашего браузера, обычно \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', 'Относительный путь к шаблонам');
+@define('INSTALL_RELTEMPLPATH_DESC', 'Пусть к каталогу с шаблонами - с учётом \'относительному пути\'');
+@define('INSTALL_RELUPLOADPATH', 'Относительный путь аплоадов');
+@define('INSTALL_RELUPLOADPATH_DESC', 'Путь к вашим загрузка для браузеров - с учётом \'относительного пути\'');
+@define('INSTALL_URL', 'URL вашего блога');
+@define('INSTALL_URL_DESC', 'Основной URL вашего блога');
+@define('INSTALL_INDEXFILE', 'Индекс-файл');
+@define('INSTALL_INDEXFILE_DESC', 'Имя индекс-файла вашего блога');
+
+/* Generel settings */
+@define('INSTALL_CAT_SETTINGS', 'Общие настройки');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Влияют на поведение вашего блога Serendipity');
+@define('INSTALL_USERNAME', 'Имя администратора');
+@define('INSTALL_USERNAME_DESC', 'Имя пользовтеля для администратора блога');
+@define('INSTALL_PASSWORD', 'Пароль администратора');
+@define('INSTALL_PASSWORD_DESC', 'Пароль для указанного выше имени администратора');
+@define('INSTALL_EMAIL', 'Email администратора');
+@define('INSTALL_EMAIL_DESC', 'Email для администратора блога');
+@define('INSTALL_SENDMAIL', 'Посылать почту администратору');
+@define('INSTALL_SENDMAIL_DESC', 'Хотите ли вы получать письма когда к вашим заметкам добавляются комментарии?');
+@define('INSTALL_SUBSCRIBE', 'Позволять пользователям подписываться на ваши записи?');
+@define('INSTALL_SUBSCRIBE_DESC', 'Могут ли пользователи подписываться на записи и таким образом получать уведомления по почте когда к этим записям добавляются комментарии');
+@define('INSTALL_BLOGNAME', 'Имя блога');
+@define('INSTALL_BLOGNAME_DESC', 'Название вашего блога');
+@define('INSTALL_BLOGDESC', 'Описание блога');
+@define('INSTALL_BLOGDESC_DESC', 'Краткое (в одну строку) описание вашего блога');
+@define('INSTALL_LANG', 'Язык');
+@define('INSTALL_LANG_DESC', 'Выберите язык интерфейса для вашего блога');
+
+/* Appearance and options */
+@define('INSTALL_CAT_DISPLAY', 'Внешний вид и опции');
+@define('INSTALL_CAT_DISPLAY_DESC', 'Изменить настройки интерфейса Serendipity');
+@define('INSTALL_WYSIWYG', 'Использовать WYSIWYG-редактор');
+@define('INSTALL_WYSIWYG_DESC', 'Желаете ли вы использовать WYSIWYG-редактор? (Работает в IE5+, частично в Mozilla 1.3+)');
+@define('INSTALL_XHTML11', 'Следить за соответствием XHTML 1.1');
+@define('INSTALL_XHTML11_DESC', 'Вы хотите включить принудительное соответствие стандарту XHTML 1.1? (может вызвать проблемы на старых браузерах 4го поколения)');
+@define('INSTALL_POPUP', 'Разрешить использование выскакивающих окон');
+@define('INSTALL_POPUP_DESC', 'Хотите ли вы использовать выскакивающие окна для комментариев, обратных ссылок, и т.д.?');
+@define('INSTALL_EMBED', 'Встроен ли ваш serendipity?');
+@define('INSTALL_EMBED_DESC', 'Если вы хотите встроить ваш блог serendipity в обычную страницу, установите этот параметр в true чтобы не выводить никаких заголовков, и лишь печатать содержимое блога. Вы можете использовать опцию индексного файла (indexFile) чтобы использовать другую страницу как главную и содержащую заголовки. Пожалуйста, прочитайте файл README чтобы узнать больше!');
+@define('INSTALL_TOP_AS_LINKS', 'Показывать адреса как ссылки?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"нет": Все адреса веб-сайтов показаны как обычный текст чтобы избежать google спама. "да": Все адреса веб-сайтов показаны как гипер-ссылки. "По умолчанию": Использовать настройки глобальной конфигурации (рекомендуется).');
+@define('INSTALL_BLOCKREF', 'Блокированные сайты');
+@define('INSTALL_BLOCKREF_DESC', 'Есть ли какие-то сайты, которые вы не хотите отображать в списке тех, откуда к вам пришли? Разделяйте элементы списка знаком \';\' и имейте в виду, что сайты блокируются по совпадению строк!');
+@define('INSTALL_REWRITE', 'Генерация URLов');
+@define('INSTALL_REWRITE_DESC', 'Выберите, какими правилами вы хотите пользоваться при генерации URLов. Включение этой опции позволит вам иметь красивые ссылки на вашем блоге и также сделает ваш блог более доступным для индексации поисковыми машинами вроде google. Ваш веб-сервер должен либо поддерживать mod_rewrite, либо содержать "AllowOverride All" для вашего каталога serendipity dir. Значение по умолчанию определяется автоматически');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', 'Настройки конвертации изображений');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'Общие настройки о том, как Serendipity должен работать с изображениями');
+@define('INSTALL_IMAGEMAGICK', 'Использование Imagemagick');
+@define('INSTALL_IMAGEMAGICK_DESC', 'Если у вас есть установленный пакет image magick, хотите ли вы его использовать для изменения размеров изображений?');
+@define('INSTALL_IMAGEMAGICKPATH', 'Путь к файлу convert');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'Полный путь и имя утилиты convert из пакета image magick');
+@define('INSTALL_THUMBSUFFIX', 'Суффикс тамбнэйлов');
+@define('INSTALL_THUMBSUFFIX_DESC', 'Тамбнэйлы будут создаваться в соответствии с форматом: original.[suffix].ext');
+@define('INSTALL_THUMBWIDTH', 'Размеры тамбнэйлов');
+@define('INSTALL_THUMBWIDTH_DESC', 'Максимальная ширина автоматически создаваемых тамбнэйлов');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', 'Личные настройки');
+@define('USERCONF_CAT_PERSONAL_DESC', 'Изменение ваших личных настроек');
+@define('USERCONF_USERNAME', 'Имя пользователя');
+@define('USERCONF_USERNAME_DESC', 'Имя пользователя, которое вы используете чтобы заходить на блог');
+@define('USERCONF_PASSWORD', 'Ваш пароль');
+@define('USERCONF_PASSWORD_DESC', 'Пароль, который вы хотите использовать при авторизации');
+@define('USERCONF_EMAIL', 'Ваш адрес e-mail');
+@define('USERCONF_EMAIL_DESC', 'Адрес вашей электронной почты');
+@define('USERCONF_SENDCOMMENTS', 'Посылать уведомления о комментария?');
+@define('USERCONF_SENDCOMMENTS_DESC', 'Желаете ли вы получать уведомления, когда к вашим записям добавляются новые комментарии?');
+@define('USERCONF_SENDTRACKBACKS', 'Посылать уведомления об обратных ссылках?');
+@define('USERCONF_SENDTRACKBACKS_DESC', 'Желаете ли вы получать уведомления об обратных ссылках на ваши записи?');
+@define('USERCONF_ALLOWPUBLISH', 'Права доступа: Добавление записей?');
+@define('USERCONF_ALLOWPUBLISH_DESC', 'Разрешено ли этому пользователю публиковать записи?');
+@define('SUCCESS', 'Успешно!');
+@define('POWERED_BY_SHOW_TEXT', 'Показывать "Serendipity" как текст');
+@define('POWERED_BY_SHOW_TEXT_DESC', 'Покажет слова "Веблог Serendipity" как текст');
+@define('POWERED_BY_SHOW_IMAGE', 'Показывать "Serendipity" и лого');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Показывает логотип Serendipity и ссылку');
+@define('PLUGIN_ITEM_DISPLAY', 'Где должен быть показан этот объект?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'Только в расширенном тексте записи');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'Только на странице обзора');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'В обоих случаях');
+@define('RSS_IMPORT_CATEGORY', 'Использовать эту категорию для импортированных записей  с несуществующими в вашей базе категориями');
+
+@define('COMMENTS_WILL_BE_MODERATED', 'Добавленные комментарии должны будут пройти модерацию прежде, чем будут показаны.');
+@define('YOU_HAVE_THESE_OPTIONS', 'У вас есть следующие варианты:');
+@define('THIS_COMMENT_NEEDS_REVIEW', 'Внимание: этот комментарий нуждается в подтверждении автором записи, прежде чем он может быть показан');
+@define('DELETE_COMMENT', 'Удалить комментарий');
+@define('APPROVE_COMMENT', 'Подтвердить комментарий');
+@define('REQUIRES_REVIEW', 'Требует обзора (review)');
+@define('COMMENT_APPROVED', 'Комментарий #%s был успешно подтверждён');
+@define('COMMENT_DELETED', 'Комментарий #%s был успешно удалён');
+@define('COMMENTS_MODERATE', 'Комментарии и обратные ссылки к этой записи требуют модерации');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'Внимание: эта обратная ссылка нуждается в подтверждении, прежде чем она сможет быть показана');
+@define('DELETE_TRACKBACK', 'Удалить обратную ссылку');
+@define('APPROVE_TRACKBACK', 'Подвердить обратную ссылку');
+@define('TRACKBACK_APPROVED', 'Обратная ссылка #%s была успешно подтверждена');
+@define('TRACKBACK_DELETED', 'Обратная ссылка #%s была успешно удалена');
+@define('VIEW', 'Просмотреть');
+@define('COMMENT_ALREADY_APPROVED', 'Похоже, что комментарий #%s уже был подтверждён автором записи');
+@define('COMMENT_EDITED', 'Выбранный комментарий был отредактирован');
+@define('HIDE', 'Спрятать');
+@define('VIEW_EXTENDED_ENTRY', 'Продолжить чтение "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'Эта ссылка не предназначена для того, чтобы её кликали. Она содержит специальный URI для обратных ссылок. Вы можете использовать этот URI для проверки и создания обратных ссылок на эту запись. Чтобы скопировать ссылку, нажмите на ней правую кнопку мышки и выберите "Copy Shortcut" в Internet Explorer или "Copy Link Location" в Mozilla.');
+@define('PLUGIN_SUPERUSER_HTTPS', 'Использовать https для входа в систему');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'Позволяет ссылке на страницу входа в систему указывать на https-ресурс. Ваш веб-сервер должен поддерживать https чтобы эта опция могла работать!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'Показывать внешние сайты как гиперссылки?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"no": Внешние сайты (Куда Ушли, Откуда Пришли, комментарии пользователей) не показываются, или показываются как обычный текст, где это возможно, чтобы предотвратить google-спам (рекомендуется). "yes": Внешние сайты показаны как гиперссылки. Эта опция может быть отменена конфигурацией плагина для боковых панелей!');
+@define('PAGE_BROWSE_COMMENTS', 'Страница %s из %s, всего комментариев:  %s');
+@define('FILTERS', 'Фильтры');
+@define('FIND_ENTRIES', 'Найти записи');
+@define('FIND_COMMENTS', 'Найти комментарии');
+@define('FIND_MEDIA', 'Найти файлы');
+@define('FILTER_DIRECTORY', 'Каталог');
+@define('SORT_BY', 'Упорядочить по');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'Не была послана обратная ссылка: невозможно создать соединение к %s через порт %d');
+@define('MEDIA', 'Медиа-файлы');
+@define('MEDIA_LIBRARY', 'Библиотека файлов');
+@define('ADD_MEDIA', 'Добавить медиа-файл');
+@define('ENTER_MEDIA_URL', 'Введите URL файла,<br>который нужно скачать:');
+@define('ENTER_MEDIA_UPLOAD', 'Выберите файл, который<br>вы хотите загрузить на сервер:');
+@define('SAVE_FILE_AS', 'Сохранить этот файл как:');
+@define('STORE_IN_DIRECTORY', 'Сохранить в следующем каталоге: ');
+@define('ADD_MEDIA_BLAHBLAH', '<b>Добавление файла в вашу медиа-коллекцию:</b><p>Здесь вы можете загрузить на сервер ваши медиа-файлы, или указать, откуда их можно скачать в сети! Если у вас нет подходящих изображений, <a href="http://images.google.com" target="_blank">поищите с помощью google</a>, что-нибудь да найдётся,очень часто результаты полезны и забавны :)<p><b>Выберите способ:</b><br>');
+@define('MEDIA_RENAME', 'Переименовать этот файл');
+@define('IMAGE_RESIZE', 'Изменить размер этого изображения');
+@define('MEDIA_DELETE', 'Удалить этот файл');
+@define('FILES_PER_PAGE', 'Файлов на странице');
+@define('CLICK_FILE_TO_INSERT', 'Кликните на файл, который вы хотите вставить:');
+@define('SELECT_FILE', 'Выберите файл для вставки');
+@define('MEDIA_FULLSIZE', 'Полный размер');
+@define('CALENDAR_BOW_DESC', 'День недели, который должен считаться началом недели. По умолчанию это понедельник.');
+@define('SUPERUSER', 'Администрирование');
+@define('ALLOWS_YOU_BLAHBLAH', 'Ссылка в вашей боковой панели на главную страницу администрирования вашего блога');
+@define('CALENDAR', 'Календарь');
+@define('SUPERUSER_OPEN_ADMIN', 'Перейти к администрированию');
+@define('SUPERUSER_OPEN_LOGIN', 'Войти в систему');
+@define('INVERT_SELECTIONS', 'Инвертировать отмеченное');
+@define('COMMENTS_DELETE_CONFIRM', 'Вы уверены, что хотите удалить отмеченные комментарии?');
+@define('COMMENT_DELETE_CONFIRM', 'Вы уверены, что хотите удалить комментарий #%d, созданный %s?');
+@define('DELETE_SELECTED_COMMENTS', 'Удалить отмеченные комментарии');
+@define('VIEW_COMMENT', 'Просмотреть комментарий');
+@define('VIEW_ENTRY', 'Просмотреть запись');
+@define('DELETE_FILE_FAIL', 'Не удалось удалить файл <b>%s</b>');
+@define('DELETE_THUMBNAIL', 'Удалён файл с тамбнэйлом <b>%s</b>');
+@define('DELETE_FILE', 'Удалён файл <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', 'Вы собираетесь удалить <b>%s</b><br />Если вы используете этот файл в каких-то ваших записях, это действие сделает ссылки или изображения в них недоступными.<br />Вы уверены, что хотите продолжить?<br /><br />');
+@define('TRACKBACK_SENDING', 'Отправка обратной ссылки на URI %s...');
+@define('TRACKBACK_SENT', 'Отправка обратной ссылки прошла успешно');
+@define('TRACKBACK_FAILED', 'Отправка обратной ссылки не удалась: %s');
+@define('TRACKBACK_NOT_FOUND', 'Не было найдено URI для обратной ссылки.');
+@define('TRACKBACK_URI_MISMATCH', 'Автоматически найденный URI обратной ссылки не совпадает с URI, на который вы ссылаетесь.');
+@define('TRACKBACK_CHECKING', 'Проверка <u>%s</u> на возможные обратные ссылки...');
+@define('TRACKBACK_NO_DATA', 'Указанная страница не содержит данных');
+@define('TRACKBACK_SIZE', 'Указанный URI превзошёл максимальный размер файла %s байт.');
+@define('COMMENTS_VIEWMODE_THREADED', 'Древовидной структурой');
+@define('COMMENTS_VIEWMODE_LINEAR', 'Как список');
+@define('DISPLAY_COMMENTS_AS', 'Показывать комментарии');
+@define('COMMENTS_FILTER_SHOW', 'Показывать');
+@define('COMMENTS_FILTER_ALL', 'Все');
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'Только подтверждённые');
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'Ожидающие подтверждения');
+@define('RSS_IMPORT_BODYONLY', 'Поместить весь импортированный текст в раздел "текст записи" и не создавать раздел "дополнительный текст записи".');
+@define('SYNDICATION_PLUGIN_FULLFEED', 'Показывать полные записи с дополнительным текстом записи в RSS-лентах');
+@define('WEEK', 'Неделя');
+@define('WEEKS', 'Недели');
+@define('MONTHS', 'Месяцы');
+@define('DAYS', 'Дни');
+@define('ARCHIVE_FREQUENCY', 'Частота разделов архива');
+@define('ARCHIVE_FREQUENCY_DESC', 'Календарный интервал для создания    списка архивных разделов');
+@define('ARCHIVE_COUNT', 'Количество архивных разделов в списке');
+@define('ARCHIVE_COUNT_DESC', 'Количество месяцев, недель или дней, архивы которых отображать');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'Ниже приведён список установленных плагинов');
+@define('SIDEBAR_PLUGIN', 'плагин боковых панелей');
+@define('EVENT_PLUGIN', 'event-плагин');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'Нажмите здесь чтобы установить новый %s');
+@define('VERSION', 'версия');
+@define('INSTALL', 'Установить');
+@define('ALREADY_INSTALLED', 'Уже установлен');
+@define('SELECT_A_PLUGIN_TO_ADD', 'Выберите плагин для добавления');
+@define('INSTALL_OFFSET', 'Смещение времени на сервере');
+@define('STICKY_POSTINGS', 'Закреплённые записи');
+@define('INSTALL_FETCHLIMIT', 'Записи, которые всегда следует отображать на главной странице');
+@define('INSTALL_FETCHLIMIT_DESC', 'Количество записей для показа на каждой странице frontend\'а');
+@define('IMPORT_ENTRIES', 'Импортировать записи');
+@define('EXPORT_ENTRIES', 'Экспортировать записи');
+@define('IMPORT_WELCOME', 'Добро пожаловать в утилиту импорта данных Serendipity');
+@define('IMPORT_WHAT_CAN', 'Здесь вы сможете импортировать в вашу базу данных записи из других блогов и приложений');
+@define('IMPORT_SELECT', 'Пожалуйста выберите программное обеспечение, из которого вы хотели бы импортировать данные');
+@define('IMPORT_PLEASE_ENTER', 'Пожалуйста введите запрашиваемые ниже данные');
+@define('IMPORT_NOW', 'Начать импорт!');
+@define('IMPORT_STARTING', 'Запуск процедуры импортирования...');
+@define('IMPORT_FAILED', 'Импорт данных не удался');
+@define('IMPORT_DONE', 'Импорт данных успешно завершён');
+@define('IMPORT_WEBLOG_APP', 'Приложение');
+@define('EXPORT_FEED', 'Экспортировать полную RSS-ленту');
+@define('STATUS', 'Статус после импорта');
+@define('IMPORT_GENERIC_RSS', 'Обычный импорт RSS');
+@define('ACTIVATE_AUTODISCOVERY', 'Посылать обратные ссылки на гиперссылки, найденные в записи');
+@define('WELCOME_TO_ADMIN', 'Добро пожаловать в раздел администрирования Serendipity.');
+@define('PLEASE_ENTER_CREDENTIALS', 'Пожалуйста введите ваши имя пользователя и пароль.');
+@define('ADMIN_FOOTER_POWERED_BY', 'Сделано с помощью Serendipity %s и PHP %s');
+@define('INSTALL_USEGZIP', 'Использовать страницы, сжатые с помощью gzip');
+@define('INSTALL_USEGZIP_DESC', 'Чтобы ускорить доставку страниц, мы можем сжимать страницы во время отправки их к посетителю, если его браузер поддерживает такое сжатие. Это рекомендуемая опция.');
+@define('INSTALL_SHOWFUTURE', 'Показывать записи с будущими датами');
+@define('INSTALL_SHOWFUTURE_DESC', 'Если включена, эта опция покажет все записи с будущими датами публикации. По умолчанию такие записи скрыты до тех пор, пока не наступит указанная дата публикации.');
+@define('INSTALL_DBPERSISTENT', 'Использовать persistent-соединения');
+@define('INSTALL_DBPERSISTENT_DESC', 'Разрешить использование persistent-соединений к базе данных, больше информации об этом можно получить <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">здесь</a>. Обычно, эта опция не рекомендуется');
+@define('NO_IMAGES_FOUND', 'Не было найдено изображений');
+@define('PERSONAL_SETTINGS', 'Личные настройки');
+@define('REFERER', 'Referer');
+@define('NOT_FOUND', 'Не найден');
+@define('WRITABLE', 'Есть доступ для записи');
+@define('NOT_WRITABLE', 'Нет доступа для записи');
+@define('PROBLEM_DIAGNOSTIC', 'Из-за проблем, найденных во время диагностики, вы не можете продолжать установку, пока указанные выше ошибки не будут исправлены');
+@define('SELECT_INSTALLATION_TYPE', 'Выберите, какой тип инсталляции вы хотите использовать');
+@define('WELCOME_TO_INSTALLATION', 'Добро пожаловать в установку Serendipity');
+@define('FIRST_WE_TAKE_A_LOOK', 'Сначала мы проведём анализ вашей текущей версии и попытаемся найти проблемы совместимости');
+@define('ERRORS_ARE_DISPLAYED_IN', 'Ошибки обозначены как %s, рекомендации как %s, а успешно пройденные проверки - как %s');
+@define('RED', 'красный');
+@define('YELLOW', 'жёлтый');
+@define('GREEN', 'зелёный');
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s - пред-установочный отчёт');
+@define('RECOMMENDED', 'Рекомендуется');
+@define('ACTUAL', 'На самом деле');
+@define('PHPINI_CONFIGURATION', 'конфигурация php.ini');
+@define('PHP_INSTALLATION', 'инсталляция PHP');
+@define('THEY_DO', 'they do');
+@define('THEY_DONT', 'they don\'t');
+@define('SIMPLE_INSTALLATION', 'Простая установка');
+@define('EXPERT_INSTALLATION', 'Продвинутая установка');
+@define('COMPLETE_INSTALLATION', 'Полная установка');
+@define('WONT_INSTALL_DB_AGAIN', 'не устанавливать базу данных снова');
+@define('CHECK_DATABASE_EXISTS', 'Проверка, существует ли уже база данных. Если вы увидите ошибку запроса к базе данных ниже, не обращайте внимания...');
+@define('CREATING_PRIMARY_AUTHOR', 'Создание основного автора \'%s\'');
+@define('SETTING_DEFAULT_TEMPLATE', 'Установка шаблона по умолчанию');
+@define('INSTALLING_DEFAULT_PLUGINS', 'Установка плагинов по умолчанию');
+@define('SERENDIPITY_INSTALLED', '%sSerendipity был успешно установлен на вашей системе.%s Пожалуйста запомните ваш пароль: "%s", ваше имя пользователя - "%s".%sВы можете найти ваш новый PHP блог <a href="%s">вот тут</a>');
+@define('VISIT_BLOG_HERE', 'Перейти на ваш новый блог');
+@define('THANK_YOU_FOR_CHOOSING', 'Спасибо за ваш выбор Serendipity');
+@define('ERROR_DETECTED_IN_INSTALL', 'Во время установки была обнаружена ошибка');
+@define('OPERATING_SYSTEM', 'Операционная система');
+@define('WEBSERVER_SAPI', 'SAPI веб-сервера');
+@define('TEMPLATE_SET', '\'%s\' был установлен вашим шаблоном по умолчанию');
+@define('SEARCH_ERROR', 'Функция поиска не работает как ожидается. Свяжитесь с администратором этого блога: это может происходить из-за отсутствующих индексов в вашей базе данных. На MySQL системах ваш аккаунт базы данных должен иметь привилегии, чтобы выполнить следующий запрос: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> Собственно ошибка, полученная от базы данных, была следующая: <pre>%s</pre>');
+
+@define('EDIT_THIS_CAT', 'Editing "%s"'); // Translate
+@define('CATEGORY_REMAINING', 'Delete this category and move its entries to this category'); // Translate
+@define('CATEGORY_INDEX', 'Below is a list of categories available to your entries'); // Translate
+@define('NO_CATEGORIES', 'No categories'); // Translate
+@define('RESET_DATE', 'Reset date'); // Translate
+@define('RESET_DATE_DESC', 'Click here to reset the date to the current time'); // Translate
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Permissions can be set by running shell command: `<em>%s</em>` on the failed directory, or by setting this using an FTP program'); // Translate
+@define('WARNING_TEMPLATE_DEPRECATED', 'Warning: Your current template is using a deprecated template method, you are advised to update if possible'); // Translate
+@define('ENTRY_PUBLISHED_FUTURE', 'This entry is not yet published.'); // Translate
+@define('ENTRIES_BY', 'Entries by %s'); // Translate
+@define('PREVIOUS', 'Previous'); // Translate
+@define('NEXT', 'Next'); // Translate
+@define('APPROVE', 'Approve'); // Translate
+@define('DO_MARKUP_DESCRIPTION', 'Apply markup transformations to the text (smilies, shortcut markups via *, /, _, ...). Disabling this will preserve any HTML-code in the text.'); // Translate
+@define('CATEGORY_ALREADY_EXIST', 'A category with the name "%s" already exist'); // Translate
+@define('IMPORT_NOTES', 'Note:'); // Translate
+@define('ERROR_FILE_FORBIDDEN', 'You are not allowed to upload files with active content'); // Translate
+@define('ADMIN', 'Administration'); // Re-Translate
+@define('ADMIN_FRONTPAGE', 'Frontpage'); // Translate
+@define('QUOTE', 'Quote'); // Translate
+@define('IFRAME_SAVE', 'Serendipity is now saving your entry, creating trackbacks and performing possible XML-RPC calls. This may take a while..'); // Translate
+@define('IFRAME_SAVE_DRAFT', 'A draft of this entry has been saved'); // Translate
+@define('IFRAME_PREVIEW', 'Serendipity is now creating the preview of your entry...'); // Translate
+@define('IFRAME_WARNING', 'Your browser does not support the concept of iframes. Please open your serendipity_config.inc.php file and set $serendipity[\'use_iframe\'] variable to FALSE.'); // Translate
+@define('NONE', 'none');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Default settings for new entries'); // Translate
+@define('UPGRADE', 'Upgrade'); // Translate
+@define('UPGRADE_TO_VERSION', 'Upgrade to version %s'); // Translate
+@define('DELETE_DIRECTORY', 'Delete directory'); // Translate
+@define('DELETE_DIRECTORY_DESC', 'You are about to delete the contents of a directory that contains media files, possibly files used in some of your entries.'); // Translate
+@define('FORCE_DELETE', 'Delete ALL files in this directory, including those not known by Serendipity'); // Translate
+@define('CREATE_DIRECTORY', 'Create directory'); // Translate
+@define('CREATE_NEW_DIRECTORY', 'Create new directory'); // Translate
+@define('CREATE_DIRECTORY_DESC', 'Here you can create a new directory to place media files in. Choose the name for your new directory and select an optional parent directory to place it in.'); // Translate
+@define('BASE_DIRECTORY', 'Base directory'); // Translate
+@define('USERLEVEL_EDITOR_DESC', 'Standard editor'); // Translate
+@define('USERLEVEL_CHIEF_DESC', 'Chief editor'); // Translate
+@define('USERLEVEL_ADMIN_DESC', 'Administrator'); // Translate
+@define('USERCONF_USERLEVEL', 'Access level'); // Translate
+@define('USERCONF_USERLEVEL_DESC', 'This level is used to determine what kind of access this user has to the blog'); // Translate
+@define('USER_SELF_INFO', 'Logged in as %s (%s)'); // Translate
+@define('ADMIN_ENTRIES', 'Entries'); // Translate
+@define('RECHECK_INSTALLATION', 'Recheck installation'); // Translate
+@define('IMAGICK_EXEC_ERROR', 'Unable to execute: "%s", error: %s, return var: %d'); // Translate
+@define('INSTALL_OFFSET_DESC', 'Enter the amount of hours between the date of your webserver (current: %clock%) and your desired time zone'); // Translate
+@define('UNMET_REQUIREMENTS', 'Requirements failed: %s'); // Translate
+@define('CHARSET', 'Charset');
+@define('AUTOLANG', 'Use visitor\'s browser language as default');
+@define('AUTOLANG_DESC', 'If enabled, this will use the visitor\'s browser language setting to determine the default language of your entry and interface language.');
+@define('INSTALL_AUTODETECT_URL', 'Autodetect used HTTP-Host'); // Translate
+@define('INSTALL_AUTODETECT_URL_DESC', 'If set to "true", Serendipity will ensure that the HTTP Host which was used by your visitor is used as your BaseURL setting. Enabling this will let you be able to use multiple domain names for your Serendipity Blog, and use the domain for all follow-up links which the user used to access your blog.'); // Translate
+@define('CONVERT_HTMLENTITIES', 'Try to auto-convert HTML entities?');
+@define('EMPTY_SETTING', 'You did not specify a valid value for "%s"!');
+@define('USERCONF_REALNAME', 'Real name'); // Translate
+@define('USERCONF_REALNAME_DESC', 'The full name of the author. This is the name seen by readers'); // Translate
+@define('HOTLINK_DONE', 'File hotlinked.<br />Done.'); // Translate
+@define('ENTER_MEDIA_URL_METHOD', 'Fetch method:'); // Translate
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Note: If you choose to hotlink to server, make sure you have permission to hotlink to the designated website, or the website is yours. Hotlink allows you to use off-site images without storing them locally.'); // Translate
+@define('MEDIA_HOTLINKED', 'hotlinked'); // Translate
+@define('FETCH_METHOD_IMAGE', 'Download image to your server'); // Translate
+@define('FETCH_METHOD_HOTLINK', 'Hotlink to server'); // Translate
+@define('DELETE_HOTLINK_FILE', 'Deleted the hotlinked file entitled <b>%s</b>'); // Translate
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Show E-Mail addresses?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_tn.inc.php b/lang/serendipity_lang_tn.inc.php
new file mode 100644 (file)
index 0000000..7ebe642
--- /dev/null
@@ -0,0 +1,669 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+@define('LANG_CHARSET', 'UTF-8');
+@define('DATE_LOCALES', 'tw, zh, zh-TW.UTF-8, zh_TW.UTF-8');
+@define('DATE_FORMAT_ENTRY', '%A, %B %e. %Y');
+@define('DATE_FORMAT_SHORT', '%Y-%m-%d %H:%M');
+@define('WYSIWYG_LANG', 'en');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', '.');
+@define('NUMBER_FORMAT_THOUSANDS', ',');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Serendipity 管理介面');
+@define('HAVE_TO_BE_LOGGED_ON', '請先登入');
+@define('WRONG_USERNAME_OR_PASSWORD', '您輸入了錯誤的帳號或密碼');
+@define('APPEARANCE', '外觀配置');
+@define('MANAGE_STYLES', '佈景管理');
+@define('CONFIGURE_PLUGINS', '設定外掛');
+@define('CONFIGURATION', '管理設定');
+@define('BACK_TO_BLOG', '回到網誌首頁');
+@define('LOGIN', '登入');
+@define('LOGOUT', '登出');
+@define('LOGGEDOUT', '登出.');
+@define('CREATE', '建立');
+@define('SAVE', '儲存');
+@define('NAME', '名稱');
+@define('CREATE_NEW_CAT', '新增類別');
+@define('I_WANT_THUMB', '我要在文章內使用縮圖.');
+@define('I_WANT_BIG_IMAGE', '我要在文章內使用大型圖片.');
+@define('I_WANT_NO_LINK', ' 我要它以圖片顯示');
+@define('I_WANT_IT_TO_LINK', '我要它以連結顯示這個 URL:');
+@define('BACK', '返回');
+@define('FORWARD', '前進');
+@define('ANONYMOUS', '匿名');
+@define('NEW_TRACKBACK_TO', '新的引用到');
+@define('NEW_COMMENT_TO', '新的迴響到');
+@define('RECENT', '新文庫...');
+@define('OLDER', '舊文庫...');
+@define('DONE', '完成');
+@define('WELCOME_BACK', '歡迎回來,');
+@define('TITLE', '標題');
+@define('DESCRIPTION', '簡介');
+@define('PLACEMENT', '位址');
+@define('DELETE', '刪除');
+@define('SAVE', '儲存');
+@define('UP', '上');
+@define('DOWN', '下');
+@define('ENTRIES', '文章');
+@define('NEW_ENTRY', '新增文章');
+@define('EDIT_ENTRIES', '編輯文章');
+@define('CATEGORIES', '類別');
+@define('WARNING_THIS_BLAHBLAH', "警告:\\n這個可能需要長時間如果有很多不是縮圖的圖片.");
+@define('CREATE_THUMBS', '重建縮圖');
+@define('MANAGE_IMAGES', '管理圖片');
+@define('NAME', '名稱');
+@define('EMAIL', 'Email');
+@define('HOMEPAGE', '網址');
+@define('COMMENT', '迴響');
+@define('REMEMBER_INFO', '記住資料? ');
+@define('SUBMIT_COMMENT', '傳送迴響');
+@define('NO_ENTRIES_TO_PRINT', '沒有文章可以顯示');
+@define('COMMENTS', '迴響');
+@define('ADD_COMMENT', '新增迴響');
+@define('NO_COMMENTS', '沒有迴響');
+@define('POSTED_BY', '作者');
+@define('ON', '在');
+@define('A_NEW_COMMENT_BLAHBLAH', '新迴響已發表到您的網誌 "%s", 在這個文章裡面 "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', '您的網誌文章 "%s" 已有了新的引用.');
+@define('NO_CATEGORY', '沒有類別');
+@define('ENTRY_BODY', '文章主內容');
+@define('EXTENDED_BODY', '文章副內容');
+@define('CATEGORY', '類別');
+@define('EDIT', '編輯');
+@define('NO_ENTRIES_BLAHBLAH', '找不到此查詢 %s 的文章' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', '您搜尋的 %s 顯示了 %s 結果:');
+@define('SEARCH_TOO_SHORT', '您搜尋的文字必須多於 3 個字詞');
+@define('IMAGE', '圖片');
+@define('ERROR_FILE_NOT_EXISTS', '錯誤: 檔案不存在!');
+@define('ERROR_FILE_EXISTS', '錯誤: 檔案名稱已被使用, 請重新輸入!');
+@define('ERROR_SOMETHING', '錯誤: 有錯誤.');
+@define('ADDING_IMAGE', '新增圖片...');
+@define('THUMB_CREATED_DONE', '縮圖建立.<br>完成.');
+@define('ERROR_FILE_EXISTS_ALREADY', '錯誤: 檔案已存在!');
+@define('ERROR_UNKNOWN_NOUPLOAD', '未知的錯誤發生, 檔案還沒上傳. 也許你的檔案大於限制的大小. 請詢問您的 ISP 或修改您的 php.ini 檔.');
+@define('GO', '繼續!');
+@define('NEWSIZE', '新大小: ');
+@define('RESIZE_BLAHBLAH', '<b>重設大小 %s</b><p>');
+@define('ORIGINAL_SIZE', '原有的大小: <i>%sx%s</i> 像素');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>在這裡您可以修改圖片大小. 如果您要修改成相同的圖片比例, 您只需要輸入一個數值然後按 TAB -- 系統會自動幫您計算比例以免出錯</p>');
+@define('QUICKJUMP_CALENDAR', '日曆快速跳躍');
+@define('QUICKSEARCH', '快速搜尋');
+@define('SEARCH_FOR_ENTRY', '搜尋文章');
+@define('ARCHIVES', '保存文庫');
+@define('BROWSE_ARCHIVES', '以月份瀏覽保存文庫');
+@define('TOP_REFERRER', '主要來源');
+@define('SHOWS_TOP_SITES', '顯示連結到您的網誌的網站');
+@define('TOP_EXITS', '主要出源');
+@define('SHOWS_TOP_EXIT', '顯示您的網誌的主要出源');
+@define('SYNDICATION', '文章同步');
+@define('SHOWS_RSS_BLAHBLAH', '顯示 RSS 同步連結');
+@define('ADVERTISES_BLAHBLAH', '宣傳您的網誌');
+@define('HTML_NUGGET', 'HTML 訊息');
+@define('HOLDS_A_BLAHBLAH', '顯示 HTML 訊息到側列');
+@define('TITLE_FOR_NUGGET', '訊息的標題');
+@define('THE_NUGGET', 'HTML 訊息!');
+@define('SYNDICATE_THIS_BLOG', '同步這個網誌');
+@define('YOU_CHOSE', '您選擇 %s');
+@define('IMAGE_SIZE', '圖片大小');
+@define('IMAGE_AS_A_LINK', '輸入圖片');
+@define('POWERED_BY', 'Powered by');
+@define('TRACKBACKS', '引用');
+@define('TRACKBACK', '引用');
+@define('NO_TRACKBACKS', '沒有引用');
+@define('TOPICS_OF', '主題');
+@define('VIEW_FULL', '瀏覽全部');
+@define('VIEW_TOPICS', '瀏覽主題');
+@define('AT', '在');
+@define('SET_AS_TEMPLATE', '使用佈景');
+@define('IN', '在');
+@define('EXCERPT', '摘要');
+@define('TRACKED', '引用');
+@define('LINK_TO_ENTRY', '連結到文章');
+@define('LINK_TO_REMOTE_ENTRY', '連結到遠端文章');
+@define('IP_ADDRESS', 'IP 位址');
+@define('USER', '作者');
+@define('THUMBNAIL_USING_OWN', '使用 %s 當它的縮圖尺寸因為圖片已經很小了.');
+@define('THUMBNAIL_FAILED_COPY', '使用 %s 當它的縮圖, 但是無法複製!');
+@define('AUTHOR', '發佈者');
+@define('LAST_UPDATED', '最後更新');
+@define('TRACKBACK_SPECIFIC', '引用此文章特定的 URI (網址)');
+@define('DIRECT_LINK', '直接的文章連結');
+@define('COMMENT_ADDED', '您的迴響已成功增入. ');
+@define('COMMENT_ADDED_CLICK', '點 %s這裡返回%s 到迴響, 和點 %s這裡關閉%s 這個視窗.');
+@define('COMMENT_NOT_ADDED', '您的迴響不能增入因為此篇文章不允許迴響. ');
+@define('COMMENT_NOT_ADDED_CLICK', '點 %s這裡返回%s 到迴響, 和點 %s這裡關閉%s 這個視窗.');
+@define('COMMENTS_DISABLE', '不允許迴響到這篇文章');
+@define('COMMENTS_ENABLE', '允許迴響到這篇文章');
+@define('COMMENTS_CLOSED', '作者不允許迴響到這篇文章');
+@define('EMPTY_COMMENT', '您的迴響沒有任何訊息, 請 %s返回%s 重試');
+@define('ENTRIES_FOR', '文章給 %s');
+@define('DOCUMENT_NOT_FOUND', '找不到此篇文件 %s.');
+@define('USERNAME', '帳號');
+@define('PASSWORD', '密碼');
+@define('AUTOMATIC_LOGIN', '自動登入');
+@define('SERENDIPITY_INSTALLATION', 'Serendipity 安裝程式');
+@define('LEFT', '左');
+@define('RIGHT', '右');
+@define('HIDDEN', '隱藏');
+@define('REMOVE_TICKED_PLUGINS', '移除勾選的外掛');
+@define('SAVE_CHANGES_TO_LAYOUT', '儲存外觀配置');
+@define('COMMENTS_FROM', '迴響來源');
+@define('ERROR', '錯誤');
+@define('ENTRY_SAVED', '您的文章已儲存');
+@define('DELETE_SURE', '確定要刪除 #%s 嗎?');
+@define('NOT_REALLY', '算了...');
+@define('DUMP_IT', '刪除吧!');
+@define('RIP_ENTRY', 'R.I.P. 文章 #%s');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', '類別 #%s 已刪除. 舊文章已被移動到類別 #%s');
+@define('CATEGORY_DELETED', '類別 #%s 已刪除.');
+@define('INVALID_CATEGORY', '沒有提供刪除的類別');
+@define('CATEGORY_SAVED', '類別已儲存');
+@define('SELECT_TEMPLATE', '請選擇網誌的佈景');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', '沒有完成增入文章!');
+@define('MT_DATA_FILE', 'Movable Type 資料檔');
+@define('FORCE', '強制');
+@define('CREATE_AUTHOR', '新增作者 \'%s\'.');
+@define('CREATE_CATEGORY', '新增類別 \'%s\'.');
+@define('MYSQL_REQUIRED', '您必須要有 MySQL 的擴充功能才能執行這個動作.');
+@define('COULDNT_CONNECT', '不能聯結到 MySQL 資料庫: %s.');
+@define('COULDNT_SELECT_DB', '不能選擇資料庫: %s.');
+@define('COULDNT_SELECT_USER_INFO', '不能選擇使用者的資料: %s.');
+@define('COULDNT_SELECT_CATEGORY_INFO', '不能選擇類別的資料: %s.');
+@define('COULDNT_SELECT_ENTRY_INFO', '不能選擇文章的資料: %s.');
+@define('COULDNT_SELECT_COMMENT_INFO', '不能選擇迴響的資料: %s.');
+@define('YES', '是');
+@define('NO', '否');
+@define('USE_DEFAULT', '預設');
+@define('CHECK_N_SAVE', '儲存');
+@define('DIRECTORY_WRITE_ERROR', '不能讀寫檔案夾 %s. 請檢查權限.');
+@define('DIRECTORY_CREATE_ERROR', '檔案夾 %s 不存在也無法建立. 請自己建立這個檔案夾');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; run <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', '無法執行 %s 資源檔案');
+@define('FILE_WRITE_ERROR', '無法讀寫檔案 %s.');
+@define('FILE_CREATE_YOURSELF', '請自己建立這個檔案或檢查權限');
+@define('COPY_CODE_BELOW', '<br />* 請複製下面的代碼然後放入 %s 到您的 %s 檔案夾:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', '請改變 www 到使用者的 Apache (i.e. nobody).');
+@define('BROWSER_RELOAD', '完成之後, 重新刷新您的瀏覽器.');
+@define('DIAGNOSTIC_ERROR', '系統偵測到一些錯誤:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity 還沒安裝完成. 請按 <a href="%s">安裝</a>.');
+@define('INCLUDE_ERROR', 'serendipity 錯誤: 無法包括 %s - 退出.');
+@define('DATABASE_ERROR', 'serendipity 錯誤: 無法連結到資料庫 - 退出.');
+@define('CHECK_DATABASE_EXISTS', '檢查資料庫是否存在. 如果您看到資料庫查詢錯誤, 請不用管它...');
+@define('CREATE_DATABASE', '建立預設資料庫設定...');
+@define('ATTEMPT_WRITE_FILE', '讀寫 %s 檔案...');
+@define('SERENDIPITY_INSTALLED', '%sSerendipity 已安裝完成.%s 請記得您的密碼: "%s", 您的帳號是 "%s".%s您現在可以到新建立的 <a href="%s">網誌</a>');
+@define('WRITTEN_N_SAVED', '儲存完畢');
+@define('IMAGE_ALIGNMENT', '圖片對齊');
+@define('ENTER_NEW_NAME', '輸入新名稱給: ');
+@define('RESIZING', '重設大小');
+@define('RESIZE_DONE', '完成 (重設 %s 個圖片).');
+@define('SYNCING', '進行資料庫和圖片檔案夾同步化');
+@define('SYNC_DONE', '完成 (同步了 %s 個圖片).');
+@define('FILE_NOT_FOUND', '找不到檔案名稱 <b>%s</b>, 也許已經被刪除了?');
+@define('ABORT_NOW', '放棄');
+@define('REMOTE_FILE_NOT_FOUND', '檔案不在遠端主機內, 您確定這個 URL: <b>%s</b> 是正確的嗎?');
+@define('FILE_FETCHED', '%s 取回為 %s');
+@define('FILE_UPLOADED', '檔案 %s 上傳為 %s');
+@define('WORD_OR', '或');
+@define('SCALING_IMAGE', '縮放 %s 到 %s x %s px');
+@define('KEEP_PROPORTIONS', '維持比例');
+@define('REALLY_SCALE_IMAGE', '確定要縮放圖片嗎? 這個動作不能復原!');
+@define('TOGGLE_ALL', '切換展開');
+@define('TOGGLE_OPTION', '切換選項');
+@define('SUBSCRIBE_TO_THIS_ENTRY', '訂閱這篇文章');
+@define('UNSUBSCRIBE_OK', "%s 已取消訂閱這篇文章");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', '新迴響到訂閱的文章 "%s"');
+@define('SUBSCRIPTION_MAIL', "您好 %s,\n\n您訂閱的文章有了新的迴響在 \"%s\", 標題是 \"%s\"\n迴響的發表者是: %s\n\n您可以在這找到此文章: %s\n\n您可以點這個連結取消訂閱: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "您好 %s,\n\n您訂閱的文章有了新的引用在 \"%s\", 標題是 \"%s\"\n引用的作者是: %s\n\n您可以在這找到此文章: %s\n\n您可以點這個連結取消訂閱: %s\n");
+@define('SIGNATURE', "\n-- \n%s is powered by Serendipity.\nThe best blog around, you can use it too.\nCheck out <http://s9y.org> to find out how.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91 feed');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0 feed');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0 feed');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 comments');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3 feed');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', '欄位 "managingEditor"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  '欄位 "webMaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'RSS feed 的圖片');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', '圖片寬度');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', '圖片高度');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  '管理員的電子郵件, 如果有. (空白: 隱藏) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', '作者的電子郵件, 如果有. (空白: 隱藏) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', '圖片的位址 URL, 以 GIF/JPEG/PNG 格式, 如果有. (空白: serendipity-logo)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', '像素, 最大. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', '像素, 最大. 400');
+@define('SYNDICATION_PLUGIN_TTL', '欄位 "ttl" (time-to-live)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', '過幾分鐘後您的文章不會被外來的網站或程式儲存到快取記憶裡 (空白: 隱藏) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', '欄位 "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', '"pubDate"-欄位需要內嵌到RSS-頻道, 以顯示最後文章的日期嗎?');
+@define('CONTENT', '內容');
+@define('TYPE', '類型');
+@define('DRAFT', '草稿');
+@define('PUBLISH', '公開');
+@define('PREVIEW', '預覽');
+@define('DATE', '日期');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', '警告: 您提供的日期不正確. 它必須是 YYYY-MM-DD HH:MM 格式.');
+@define('CATEGORY_PLUGIN_DESC', '顯示類別清單.');
+@define('ALL_AUTHORS', '全部作者');
+@define('CATEGORIES_TO_FETCH', '顯示類別');
+@define('CATEGORIES_TO_FETCH_DESC', '顯示哪位作者的類別?');
+@define('PAGE_BROWSE_ENTRIES', '頁數 %s 共 %s, 總共 %s 篇文章');
+@define('PREVIOUS_PAGE', '上一頁');
+@define('NEXT_PAGE', '下一頁');
+@define('ALL_CATEGORIES', '全部類別');
+@define('DO_MARKUP', '執行標記轉換');
+@define('GENERAL_PLUGIN_DATEFORMAT', '日期格式化');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', '文章的日期格式, 使用 PHP 的 strftime() 變數. (預設: "%s")');
+@define('ERROR_TEMPLATE_FILE', '無法開啟佈景檔案, 請更新 serendipity!');
+@define('ADVANCED_OPTIONS', '進階選項');
+@define('EDIT_ENTRY', '編輯文章');
+@define('HTACCESS_ERROR', '要檢查您的主機安裝設定, serendipity 需要讀寫檔案 ".htaccess". 但是因為權限錯誤, 沒有辦法為您檢查. 請改變檔案權限像這樣: <br />&nbsp;&nbsp;%s<br />然後重新刷新這個網頁.');
+@define('SIDEBAR_PLUGINS', '側列外掛');
+@define('EVENT_PLUGINS', '事件外掛');
+@define('SORT_ORDER', '排序');
+@define('SORT_ORDER_NAME', '檔案名稱');
+@define('SORT_ORDER_EXTENSION', '副檔名');
+@define('SORT_ORDER_SIZE', '檔案大小');
+@define('SORT_ORDER_WIDTH', '圖片寬度');
+@define('SORT_ORDER_HEIGHT', '圖片長度');
+@define('SORT_ORDER_DATE', '上傳日期');
+@define('SORT_ORDER_ASC', '遞增排序');
+@define('SORT_ORDER_DESC', '遞減排序');
+@define('THUMBNAIL_SHORT', '縮圖');
+@define('ORIGINAL_SHORT', '原始');
+@define('APPLY_MARKUP_TO', '套用標記到 %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', '一週的第一天');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity 偵測到您的配置版本是 %s, 但是 Serendipity 本身的安裝版本是 %s, 請更新您的程式版本! <a href="%s">更新</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', '您好, 歡迎來到 Serendipity 的更新系統.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', '更新系統會幫您更新到 Serendipity 版本 %s.');
+@define('SERENDIPITY_UPGRADER_WHY', '您看到這個訊息是因為您安裝了 Serendipity 版本 %s, 但是您沒有更新資料庫');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', '資料庫更新 (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', '系統找到以下的 .sql 檔, 那些檔案必須先執行才能繼續安裝 Serendipity');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  '特定的版本任務');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', '沒有特定的版本任務');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', '確定要執行上面的任務嗎?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', '我自己執行');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', '請幫我執行');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', '您不需要進行任何更新');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', '假裝 Serendipity 更新完成吧');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', '您略過了更新任務, 請確定資料庫已安裝完成, 和其他的任務安裝無誤');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', '您的 Serendipity 以更新至版本 %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', '您可以點 %s這裡%s 返回網誌首頁');
+@define('MANAGE_USERS', '管理作者');
+@define('CREATE_NEW_USER', '新增作者');
+@define('CREATE_NOT_AUTHORIZED', '您不能修改跟您相同權限的作者');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', '您不能新增比您高權限的作者');
+@define('CREATED_USER', '新作者 %s 已經新增');
+@define('MODIFIED_USER', '作者 %s 的資料已經更改');
+@define('USER_LEVEL', '作者權限');
+@define('DELETE_USER', '您要刪除這個作者 #%d %s. 確定嗎? 這會在主頁隱藏他所寫的任何文章.');
+@define('DELETED_USER', '作者 #%d %s 已被刪除.');
+@define('LIMIT_TO_NUMBER', '要顯示多少項目?');
+@define('ENTRIES_PER_PAGE', '每頁顯示的文章');
+@define('XML_IMAGE_TO_DISPLAY', 'XML 按鈕');
+@define('XML_IMAGE_TO_DISPLAY_DESC','連結到 XML Feeds 的都會用這個圖片表示. 不填寫將會使用預設的圖片, 或輸入 \'none\' 關閉這個功能.');
+
+@define('DIRECTORIES_AVAILABLE', '您可以在子目錄內點任何目錄來建立新的目錄.');
+@define('ALL_DIRECTORIES', '全部目綠');
+@define('MANAGE_DIRECTORIES', '管理目錄');
+@define('DIRECTORY_CREATED', '目錄 <strong>%s</strong> 已經新增.');
+@define('PARENT_DIRECTORY', '母目錄');
+@define('CONFIRM_DELETE_DIRECTORY', '確定要刪除這個目錄內的全部內容嗎 %s?');
+@define('ERROR_NO_DIRECTORY', '錯誤: 目錄 %s 不存在');
+@define('CHECKING_DIRECTORY', '檢查此目錄的檔案 %s');
+@define('DELETING_FILE', '刪除檔案 %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', '不能移除未清空的目錄. 勾選 "強制刪除" 核取方塊如果您要移除這些檔案, 然後在繼續. 存在的檔案是:');
+@define('DIRECTORY_DELETE_FAILED', '不能刪除目錄 %s. 請檢查權限或看上面的訊息.');
+@define('DIRECTORY_DELETE_SUCCESS', '目錄 %s 成功刪除.');
+@define('SKIPPING_FILE_EXTENSION', '略過檔案: 沒有 %s 的副檔名.');
+@define('SKIPPING_FILE_UNREADABLE', '略過檔案: %s 不能讀取.');
+@define('FOUND_FILE', '找到 新/修改 過的檔案: %s.');
+@define('ALREADY_SUBCATEGORY', '%s 已經是此類別的子類別 %s.');
+@define('PARENT_CATEGORY', '母類別');
+@define('IN_REPLY_TO', '回覆到');
+@define('TOP_LEVEL', '最高層');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s feed');
+@define('PERMISSIONS', '權限');
+@define('SETTINGS_SAVED_AT', '新設定已經被儲存到 %s');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', '資料庫設定');
+@define('INSTALL_CAT_DB_DESC', '您可以在這輸入全部的資料庫資料. Serendipity 需要這些資料才能正常運作');
+@define('INSTALL_DBTYPE', '資料庫類型');
+@define('INSTALL_DBTYPE_DESC', '資料庫類型');
+@define('INSTALL_DBHOST', '資料庫主機');
+@define('INSTALL_DBHOST_DESC', '資料庫主機名稱');
+@define('INSTALL_DBUSER', '資料庫帳號');
+@define('INSTALL_DBUSER_DESC', '登入資料庫的帳號');
+@define('INSTALL_DBPASS', '資料庫密碼');
+@define('INSTALL_DBPASS_DESC', '您的資料庫密碼');
+@define('INSTALL_DBNAME', '資料庫名稱');
+@define('INSTALL_DBNAME_DESC', '資料庫名稱');
+@define('INSTALL_DBPREFIX', '資料表前置名稱');
+@define('INSTALL_DBPREFIX_DESC', '資料表的前置名稱, 例如 serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', '路徑設定');
+@define('INSTALL_CAT_PATHS_DESC', '給檔案夾的路徑. 不要忘了最後的斜線!');
+@define('INSTALL_FULLPATH', '完全路徑');
+@define('INSTALL_FULLPATH_DESC', '您的 Serendipity 安裝的完全路徑和絕對路徑');
+@define('INSTALL_UPLOADPATH', '上傳路徑');
+@define('INSTALL_UPLOADPATH_DESC', '全部的上傳檔案會存到這裡, 以 \'完全路徑\' 表示的相對路徑 - 例如 \'uploads/\'');
+@define('INSTALL_RELPATH', '相對路徑');
+@define('INSTALL_RELPATH_DESC', '給瀏覽器的路徑, 例如 \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', '相對的佈景路徑');
+@define('INSTALL_RELTEMPLPATH_DESC', '您放佈景的路徑 - 以 \'相對路徑\' 表示的相對路徑');
+@define('INSTALL_RELUPLOADPATH', '相對的上傳路徑');
+@define('INSTALL_RELUPLOADPATH_DESC', '給瀏覽器上傳檔案的路徑 - 以 \'相對路徑\' 表示的相對路徑');
+@define('INSTALL_URL', '網誌 URL');
+@define('INSTALL_URL_DESC', '您的 Serendipity 安裝的基本 URL');
+@define('INSTALL_INDEXFILE', 'Index 檔案');
+@define('INSTALL_INDEXFILE_DESC', 'Serendipity 的 index 檔案');
+
+/* Generel settings */
+@define('INSTALL_CAT_SETTINGS', '一般設定');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Serendipity 的一般設定');
+@define('INSTALL_USERNAME', '管理員帳號');
+@define('INSTALL_USERNAME_DESC', '管理員的登入名稱');
+@define('INSTALL_PASSWORD', '管理員密碼');
+@define('INSTALL_PASSWORD_DESC', '管理員的登入密碼');
+@define('INSTALL_EMAIL', '電子郵件');
+@define('INSTALL_EMAIL_DESC', '管理員的電子郵件');
+@define('INSTALL_SENDMAIL', '寄送電子郵件給管理員?');
+@define('INSTALL_SENDMAIL_DESC', '當有人發佈迴響到您的文章時要收到電子郵件通知嗎?');
+@define('INSTALL_SUBSCRIBE', '允許使用者訂閱文章?');
+@define('INSTALL_SUBSCRIBE_DESC', '您可以允許使用者收到電子郵件通知, 當有迴響發佈時她們會收到通知.');
+@define('INSTALL_BLOGNAME', '網誌名稱');
+@define('INSTALL_BLOGNAME_DESC', '您的網誌標題');
+@define('INSTALL_BLOGDESC', '網誌簡介');
+@define('INSTALL_BLOGDESC_DESC', '介紹您的網誌');
+@define('INSTALL_LANG', '語系');
+@define('INSTALL_LANG_DESC', '網誌使用的語系');
+
+/* Appearance and options */
+@define('INSTALL_CAT_DISPLAY', '外觀及選項設定');
+@define('INSTALL_CAT_DISPLAY_DESC', '讓您設定 Serendipity 的外觀和其他設定');
+@define('INSTALL_WYSIWYG', '使用 WYSIWYG 編輯器');
+@define('INSTALL_WYSIWYG_DESC', '您要使用 WYSIWYG 編輯器嗎? (可在 IE5+ 使用, 某些部分可使用於 Mozilla 1.3+)');
+@define('INSTALL_XHTML11', '強制符合 XHTML 1.1 要求');
+@define('INSTALL_XHTML11_DESC', '您可以讓您的網誌強制符合 XHTML 1.1 的要求 (對舊的瀏覽器可能會有 後台/前台 的問題)');
+@define('INSTALL_POPUP', '使用彈出視窗');
+@define('INSTALL_POPUP_DESC', '您要在迴響, 引用等地方使用彈出視窗嗎?');
+@define('INSTALL_EMBED', '使用內嵌功能?');
+@define('INSTALL_EMBED_DESC', '如果你要將 Serendipity 以內嵌的方式放到網頁內, 選擇 是 會讓您捨棄任何標題然後只顯示網誌內容. 您可以用 indexFile 設定來使用包裝函式類別以便您放入網頁標題. 詳情請查詢 README 檔案!');
+@define('INSTALL_TOP_AS_LINKS', '以連結顯示 主要出源/主要來源?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"否": 出源和來源將用文字顯示以避免 google 的廣告. "是": 出源和來源將用連結顯示. "預設": 用全區裡面的設定 (建議).');
+@define('INSTALL_BLOCKREF', '阻擋來源');
+@define('INSTALL_BLOCKREF_DESC', '有任何特殊的主機您不想在來源裡顯示嗎? 用 \';\' 來分開主機名稱, 注意主機是以子字串方式阻擋!');
+@define('INSTALL_REWRITE', 'URL Rewriting');
+@define('INSTALL_REWRITE_DESC', '請選擇您想用的 URL Rewriting 方式. 開啟 rewrite 規則會以比較清楚的方式顯示 URL, 以便搜尋網站能正確的登入您的文章. 您的主機必須支援 mod_rewrite 或 "AllowOverride All" 到您的 Serendipity 檔案夾. 預設的設定是系統自動幫您偵測的');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', '圖片轉換設定');
+@define('INSTALL_CAT_IMAGECONV_DESC', '請設定 Serendipity 設定圖片轉換的方式');
+@define('INSTALL_IMAGEMAGICK', '使用 Imagemagick');
+@define('INSTALL_IMAGEMAGICK_DESC', '如果有安裝 image magick, 您要用它來改變圖片大小嗎?');
+@define('INSTALL_IMAGEMAGICKPATH', '轉換程式路徑');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'image magick 轉換程式的完全路徑和名稱');
+@define('INSTALL_THUMBSUFFIX', '縮圖後置字元');
+@define('INSTALL_THUMBSUFFIX_DESC', '縮圖會以下面的格式重新命名: original.[後置字元].ext');
+@define('INSTALL_THUMBWIDTH', '縮圖尺度');
+@define('INSTALL_THUMBWIDTH_DESC', '自動建立縮圖的最大寬度');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', '個人資料設定');
+@define('USERCONF_CAT_PERSONAL_DESC', '改變您的個人資料');
+@define('USERCONF_USERNAME', '您的帳號');
+@define('USERCONF_USERNAME_DESC', '您登入網誌的名稱');
+@define('USERCONF_PASSWORD', '您的密碼');
+@define('USERCONF_PASSWORD_DESC', '您登入網誌的密碼');
+@define('USERCONF_EMAIL', '您的電子郵件');
+@define('USERCONF_EMAIL_DESC', '您使用的電子郵件');
+@define('USERCONF_SENDCOMMENTS', '寄送迴響通知?');
+@define('USERCONF_SENDCOMMENTS_DESC', '當有新迴響到您的文章時要通知您嗎?');
+@define('USERCONF_SENDTRACKBACKS', '寄送引用通知?');
+@define('USERCONF_SENDTRACKBACKS_DESC', '當有新引用到您的文章時要通知您嗎?');
+@define('USERCONF_ALLOWPUBLISH', '權限: 可發佈文章?');
+@define('USERCONF_ALLOWPUBLISH_DESC', '允許這位作者發佈文章嗎?');
+@define('SUCCESS', '完成');
+@define('POWERED_BY_SHOW_TEXT', '以文字顯示 "Serendipity"');
+@define('POWERED_BY_SHOW_TEXT_DESC', '將用文字顯示 "Serendipity Weblog"');
+@define('POWERED_BY_SHOW_IMAGE', '以 logo 顯示 "Serendipity"');
+@define('POWERED_BY_SHOW_IMAGE_DESC', '顯示 Serendipity 的 logo');
+@define('PLUGIN_ITEM_DISPLAY', '該項目的顯示位址?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', '只在副內容顯示');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', '只在概觀內顯示');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', '永遠顯示');
+
+@define('COMMENTS_WILL_BE_MODERATED', '發佈的迴響將需要管理員的審核.');
+@define('YOU_HAVE_THESE_OPTIONS', '您有以下選擇:');
+@define('THIS_COMMENT_NEEDS_REVIEW', '警告: 這個迴響須審核才會顯示');
+@define('DELETE_COMMENT', '刪除迴響');
+@define('APPROVE_COMMENT', '認可迴響');
+@define('REQUIRES_REVIEW', '需要審核');
+@define('COMMENT_APPROVED', '迴響 #%s 已經通過審核');
+@define('COMMENT_DELETED', '迴響 #%s 已經成功刪除');
+@define('COMMENTS_MODERATE', '迴響和引用到這個文章需要管理員的審核');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', '警告: 這個引用需要管理員的審核才會顯示');
+@define('DELETE_TRACKBACK', '刪除引用');
+@define('APPROVE_TRACKBACK', '認可引用');
+@define('TRACKBACK_APPROVED', '引用 #%s 已經通過審核');
+@define('TRACKBACK_DELETED', '引用 #%s 已經成功刪除');
+@define('VIEW', '瀏覽');
+@define('COMMENT_ALREADY_APPROVED', '迴響 #%s 已經通過審核');
+@define('COMMENT_EDITED', '文章已被編輯');
+@define('HIDE', '隱藏');
+@define('VIEW_EXTENDED_ENTRY', '繼續閱讀 "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', '這個連結不是用來點的. 它包含了這個文章的引用 URI. 您可以從您的網誌內用這個 URI 來傳送 ping 和引用到這個文章. 如果要複製這個連結, 在連結上點右鍵然後選擇 "複製連結" (IE) 或 "複製連結位址" (Mozilla).');
+@define('PLUGIN_SUPERUSER_HTTPS', '用 https 登入');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', '讓登入連結連到 https 網址. 您的主機必須支援這項功能!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', '讓外來連結以連結顯示?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"否": 外來連結 (主要出源, 主要來源, 迴響) 都不會以文字顯示以避免 google 廣告 (建議使用). "是": 外來連結將以超連結的方式顯示. 可以在側列外掛蓋過此設定!');
+@define('PAGE_BROWSE_COMMENTS', '頁數 %s 共 %s, 總共 %s 個迴響');
+@define('FILTERS', '過濾');
+@define('FIND_ENTRIES', '搜尋文章');
+@define('FIND_COMMENTS', '搜尋迴響');
+@define('FIND_MEDIA', '搜尋媒體');
+@define('FILTER_DIRECTORY', '目錄');
+@define('SORT_BY', '排序');
+@define('TRACKBACK_COULD_NOT_CONNECT', '沒有送出引用: 無法開啟線路到 %s 用連接埠 %d');
+@define('MEDIA', '媒體');
+@define('MEDIA_LIBRARY', '媒體存庫');
+@define('ADD_MEDIA', '新增媒體');
+@define('ENTER_MEDIA_URL', '請輸入檔案的 URL:');
+@define('ENTER_MEDIA_UPLOAD', '請選擇要上傳的檔案:');
+@define('SAVE_FILE_AS', '儲存檔案:');
+@define('STORE_IN_DIRECTORY', '儲存到以下目錄: ');
+@define('ADD_MEDIA_BLAHBLAH', '<b>新增檔案到媒體存庫:</b><p>您可以在這上傳媒體檔, 或告訴系統到哪尋找! 如果您沒有想要的圖片, 您可以到 <a href="http://images.google.com" target="_blank">google尋找圖片</a>.<p><b>選擇方式:</b><br>');
+@define('MEDIA_RENAME', '更改檔案名稱');
+@define('IMAGE_RESIZE', '更改圖片尺寸');
+@define('MEDIA_DELETE', '刪除這個檔案');
+@define('FILES_PER_PAGE', '每頁顯示的檔案數');
+@define('CLICK_FILE_TO_INSERT', '點選您要輸入的檔案:');
+@define('SELECT_FILE', '選擇要輸入的檔案');
+@define('MEDIA_FULLSIZE', '完整尺寸');
+@define('CALENDAR_BOW_DESC', '一個禮拜的第一天. 預設是星期一');
+@define('SUPERUSER', '網誌管理');
+@define('ALLOWS_YOU_BLAHBLAH', '在側列提供連結到網誌管理');
+@define('CALENDAR', '日曆');
+@define('SUPERUSER_OPEN_ADMIN', '開啟管理頁面');
+@define('SUPERUSER_OPEN_LOGIN', '開啟登入頁面');
+@define('INVERT_SELECTIONS', '顛倒勾選');
+@define('COMMENTS_DELETE_CONFIRM', '確定要刪除勾選的迴響嗎?');
+@define('COMMENT_DELETE_CONFIRM', '確定要刪除迴響 #%d, 發佈者是 %s?');
+@define('DELETE_SELECTED_COMMENTS', '刪除勾選的迴響');
+@define('VIEW_COMMENT', '瀏覽迴響');
+@define('VIEW_ENTRY', '瀏覽文章');
+@define('DELETE_FILE_FAIL' , '無法刪除檔案 <b>%s</b>');
+@define('DELETE_THUMBNAIL', '刪除了圖片縮圖 <b>%s</b>');
+@define('DELETE_FILE', '刪除了檔案 <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', '您將刪除檔案 <b>%s</b><br />如果您有在其他的文章內使用這個檔案, 那個連結或圖片將會無效<br />確定要繼續嗎?<br /><br />');
+@define('TRACKBACK_SENDING', '傳送引用到 URI %s...');
+@define('TRACKBACK_SENT', '引用完成');
+@define('TRACKBACK_FAILED', '引用錯誤: %s');
+@define('TRACKBACK_NOT_FOUND', '找不到引用的URI.');
+@define('TRACKBACK_URI_MISMATCH', '自動搜尋的引用跟引用目標不相同.');
+@define('TRACKBACK_CHECKING', '搜尋 <u>%s</u> 的引用...');
+@define('TRACKBACK_NO_DATA', '目標沒有任何資料');
+@define('TRACKBACK_SIZE', '目標 URI 超出了允許的 %s bytes 檔案大小.');
+@define('COMMENTS_VIEWMODE_THREADED', '分線程');
+@define('COMMENTS_VIEWMODE_LINEAR', '直線程');
+@define('DISPLAY_COMMENTS_AS', '迴響顯示方式');
+@define('COMMENTS_FILTER_SHOW', '顯示');
+@define('COMMENTS_FILTER_ALL', '全部');
+@define('COMMENTS_FILTER_APPROVED_ONLY', '顯示審核迴響');
+@define('COMMENTS_FILTER_NEED_APPROVAL', '顯示等待審核');
+@define('RSS_IMPORT_BODYONLY', '將輸入的文字放到主內容, 將不拆開過長的文章到副內容地區.');
+@define('SYNDICATION_PLUGIN_FULLFEED', '在 RSS feed 裡顯示全部的文章');
+@define('WEEK', '週');
+@define('WEEKS', '週');
+@define('MONTHS', '月');
+@define('DAYS', '日');
+@define('ARCHIVE_FREQUENCY', '保存文庫的項目頻率');
+@define('ARCHIVE_FREQUENCY_DESC', '保存文庫使用的項目清單間隔');
+@define('ARCHIVE_COUNT', '保存文庫的項目數');
+@define('ARCHIVE_COUNT_DESC', '顯示的月, 週, 或日');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', '下面是安裝好的外掛');
+@define('SIDEBAR_PLUGIN', '側列外掛');
+@define('EVENT_PLUGIN', '事件外掛');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', '點這裡安裝新 %s');
+@define('VERSION', '版本');
+@define('INSTALL', '安裝');
+@define('ALREADY_INSTALLED', '已經安裝');
+@define('SELECT_A_PLUGIN_TO_ADD', '請選擇要安裝的外掛');
+@define('RSS_IMPORT_CATEGORY', '用這個類別給不相同的輸入文章');
+
+@define('INSTALL_OFFSET', '主機時區');
+@define('STICKY_POSTINGS', '頂置文章');
+@define('INSTALL_FETCHLIMIT', '在主頁顯示的文章');
+@define('INSTALL_FETCHLIMIT_DESC', '主頁顯示的文章數');
+@define('IMPORT_ENTRIES', '輸入資料');
+@define('EXPORT_ENTRIES', '輸出資料');
+@define('IMPORT_WELCOME', '歡迎來到 Serendipity 的輸入工具');
+@define('IMPORT_WHAT_CAN', '在這裡您可以輸入在其他網路網誌程式裡的文章');
+@define('IMPORT_SELECT', '請選擇輸入文章的網誌程式');
+@define('IMPORT_PLEASE_ENTER', '請輸入資料');
+@define('IMPORT_NOW', '開始輸入!');
+@define('IMPORT_STARTING', '開始輸入程序...');
+@define('IMPORT_FAILED', '輸入失敗');
+@define('IMPORT_DONE', '完成輸入');
+@define('IMPORT_WEBLOG_APP', '網誌程式');
+@define('EXPORT_FEED', '輸出完整的 RSS');
+@define('STATUS', '輸入後的狀態');
+@define('IMPORT_GENERIC_RSS', 'Generic RSS import');
+@define('ACTIVATE_AUTODISCOVERY', '傳送在文章內找到的引用連結');
+@define('WELCOME_TO_ADMIN', '歡迎到 Serendipity 管理介面.');
+@define('PLEASE_ENTER_CREDENTIALS', '請輸入您的資料.');
+@define('ADMIN_FOOTER_POWERED_BY', 'Powered by Serendipity %s and PHP %s');
+@define('INSTALL_USEGZIP', '使用 gzip 壓縮網頁');
+@define('INSTALL_USEGZIP_DESC', '為了能讓網頁更快速的顯示, 我們會將網頁壓縮然後顯示訪客, 如果訪客使用的瀏覽器支援壓縮網頁. 建議使用');
+@define('INSTALL_SHOWFUTURE', '顯示未來文章');
+@define('INSTALL_SHOWFUTURE_DESC', '如果開啟, 您的網誌將會顯示所有的未來文章. 預設的設定是將未來文章隱藏, 然後發佈日期到時自動顯示.');
+@define('INSTALL_DBPERSISTENT', '使用持續連線');
+@define('INSTALL_DBPERSISTENT_DESC', '對資料庫使用持續連線, 詳情請到 <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">這裡</a>. 通常並不建議使用');
+@define('NO_IMAGES_FOUND', '找不到圖片');
+@define('PERSONAL_SETTINGS', '個人設定');
+@define('REFERER', '來源');
+@define('NOT_FOUND', '找不到');
+@define('NOT_WRITABLE', '不可讀寫');
+@define('WRITABLE', '可讀寫');
+@define('PROBLEM_DIAGNOSTIC', '因為上面出現的問題, 您必須將錯誤解決才能繼續安裝');
+@define('SELECT_INSTALLATION_TYPE', '請選擇安裝類型');
+@define('WELCOME_TO_INSTALLATION', '歡迎到 Serendipity 安裝程式');
+@define('FIRST_WE_TAKE_A_LOOK', '首先安裝程式會檢查您的主機設定以避免出現錯誤');
+@define('ERRORS_ARE_DISPLAYED_IN', '錯誤顯示 %s, 建議 %s 完成無誤 %s');
+@define('RED', '紅');
+@define('YELLOW', '黃');
+@define('GREEN', '綠');
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s 安裝前報告');
+@define('RECOMMENDED', '建議');
+@define('ACTUAL', '實際');
+@define('PHPINI_CONFIGURATION', 'php.ini 設定');
+@define('PHP_INSTALLATION', 'PHP 安裝');
+@define('THEY_DO', 'they do'); // translate
+@define('THEY_DONT', 'they don\'t'); // Translate
+@define('SIMPLE_INSTALLATION', '簡單安裝');
+@define('EXPERT_INSTALLATION', '專門安裝');
+@define('COMPLETE_INSTALLATION', '完整安裝');
+@define('WONT_INSTALL_DB_AGAIN', '不會重新安裝資料庫');
+@define('CHECK_DATABASE_EXISTS', '檢查是否資料庫和資料表已經存在');
+@define('CREATING_PRIMARY_AUTHOR', '建立主要作者 \'%s\'');
+@define('SETTING_DEFAULT_TEMPLATE', '設定預設佈景');
+@define('INSTALLING_DEFAULT_PLUGINS', '安裝預設外掛');
+@define('SERENDIPITY_INSTALLED', 'Serendipity 已完成安裝');
+@define('VISIT_BLOG_HERE', '參觀您的網路日誌');
+@define('THANK_YOU_FOR_CHOOSING', '感謝您選擇 Serendipity');
+@define('ERROR_DETECTED_IN_INSTALL', '安裝時發生錯誤');
+@define('OPERATING_SYSTEM', '作業系統');
+@define('WEBSERVER_SAPI', '主機 SAPI');
+@define('TEMPLATE_SET', '\'%s\' 已被設定為您的主要佈景');
+@define('SEARCH_ERROR', '搜尋功能發生錯誤. 告知管理員: 發生這個錯誤可能因為資料庫沒有正確的 index keys. 如果使用 MySQL, 您的帳號必須有可執行: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> 的權限. 資料庫顯示的錯誤是: <pre>%s</pre>');
+@define('EDIT_THIS_CAT', '編輯 "%s"');
+@define('CATEGORY_REMAINING', '刪除這個類別然後將裡面的文章移到這個類別');
+@define('CATEGORY_INDEX', '下面是可移動到的類別');
+@define('NO_CATEGORIES', '沒有類別');
+@define('RESET_DATE', '重設日期');
+@define('RESET_DATE_DESC', '點這裡重設日期');
+@define('PROBLEM_PERMISSIONS_HOWTO', '權限可以用下面的 Shell 命令來執行: `<em>%s</em>` 然後執行在要改權限的檔案夾,或用 FTP 軟體');
+@define('WARNING_TEMPLATE_DEPRECATED', '警告: 您目前使用的佈景是用舊的方法製作,請盡快更新');
+@define('ENTRY_PUBLISHED_FUTURE', '這篇文章還未公開。');
+@define('ENTRIES_BY', '作者 %s');
+@define('PREVIOUS', '上一頁');
+@define('NEXT', '下一頁');
+@define('APPROVE', '認可');
+@define('DO_MARKUP_DESCRIPTION', '套用自動格式化到文章內 (表情圖案, 符號 *, /, _, ...)。關閉這項功能將會保存任何文章內出現的 HTML 碼。');
+@define('CATEGORY_ALREADY_EXIST', '類別 "%s" 已經存在');
+@define('IMPORT_NOTES', '注意:');
+@define('ERROR_FILE_FORBIDDEN', '您不能上傳此類檔案');
+@define('ADMIN', '管理介面');
+@define('ADMIN_FRONTPAGE', '管理首頁');
+@define('QUOTE', '引言');
+@define('IFRAME_SAVE', 'Serendipity 正在儲存您的文章,建立引用和執行 XML-RPC calls,請稍待..');
+@define('IFRAME_SAVE_DRAFT', '文章草稿已被儲存');
+@define('IFRAME_PREVIEW', 'Serendipity 正在建立您的預覽文章...');
+@define('IFRAME_WARNING', '您的瀏覽器不支援 iframes. 請打開 serendipity_config.inc.php 檔案然後設定 $serendipity[\'use_iframe\'] 變數至 FALSE.');
+@define('NONE', '沒有');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', '新文章將使用預設設定');
+@define('UPGRADE', '更新');
+@define('UPGRADE_TO_VERSION', '更新至版本 %s');
+@define('DELETE_DIRECTORY', '刪除目錄');
+@define('DELETE_DIRECTORY_DESC', '您將刪除目錄內的媒體檔案,注意檔案也許出現在其他文章內。');
+@define('FORCE_DELETE', '刪除此目錄內的檔案,包括 Serendipity 無法識別的檔案');
+@define('CREATE_DIRECTORY', '建立目錄');
+@define('CREATE_NEW_DIRECTORY', '建立新目錄');
+@define('CREATE_DIRECTORY_DESC', '在這裡您可以建立新的目錄來存放媒體檔案。輸入目錄名稱然後您可以選擇是否將它放到母目錄內。');
+@define('BASE_DIRECTORY', '基本目錄');
+@define('USERLEVEL_EDITOR_DESC', '一般作者');
+@define('USERLEVEL_CHIEF_DESC', '主編');
+@define('USERLEVEL_ADMIN_DESC', '管理員');
+@define('USERCONF_USERLEVEL', '權限');
+@define('USERCONF_USERLEVEL_DESC', '這個選項可以設定此作者在這個網誌內的權限');
+@define('USER_SELF_INFO', '登入作者是 %s (%s)');
+@define('ADMIN_ENTRIES', '文章');
+@define('RECHECK_INSTALLATION', '重新檢查安裝程序');
+@define('IMAGICK_EXEC_ERROR', '無法執行: "%s", 錯誤: %s, 傳回變數: %d');
+@define('INSTALL_OFFSET_DESC', '以小時計算,請輸入主機的時間 (current: %clock%) 跟您的時區的時差');
+@define('UNMET_REQUIREMENTS', '未達到需求: %s');
+@define('CHARSET', '編碼');
+@define('AUTOLANG', '使用讀者的瀏覽器內設定的語系');
+@define('AUTOLANG_DESC', '如果開啟,這個功能將使用讀者的瀏覽器內所設定的語系。');
+@define('INSTALL_AUTODETECT_URL', '自動偵測 HTTP-Host');
+@define('INSTALL_AUTODETECT_URL_DESC', '如果設定為 "true",Serendipity 會確定讀者的 HTTP Host 跟您的基本 URL 設定相同。開啟這項功能可以允許您使用多數的網域名稱給您的網誌,和使用這個網域給跟進的連結。');
+@define('CONVERT_HTMLENTITIES', '自動改變 HTML entities?');
+@define('EMPTY_SETTING', '您沒有提供 "%s" 的正確值!');
+@define('USERCONF_REALNAME', '全名');
+@define('USERCONF_REALNAME_DESC', '作者的全名,將顯示給全部讀者');
+@define('HOTLINK_DONE', '檔案盜連<br />結束。');
+@define('ENTER_MEDIA_URL_METHOD', '取得方法:');
+@define('ADD_MEDIA_BLAHBLAH_NOTE', '注意: 如果您選擇盜連方法,請先得到來源網站的允許。盜連允許您用其他網站的圖片而不需將圖片儲存在您的主機內。');
+@define('MEDIA_HOTLINKED', '盜連圖片');
+@define('FETCH_METHOD_IMAGE', '下載圖片到主機');
+@define('FETCH_METHOD_HOTLINK', '盜連到主機');
+@define('DELETE_HOTLINK_FILE', '刪除盜連的檔案 <b>%s</b>');
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', '顯示電子郵件嗎?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_tw.inc.php b/lang/serendipity_lang_tw.inc.php
new file mode 100644 (file)
index 0000000..1bbf9b5
--- /dev/null
@@ -0,0 +1,669 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+@define('LANG_CHARSET', 'big5');
+@define('DATE_LOCALES', 'tw, zh, zh-TW, zh_TW');
+@define('DATE_FORMAT_ENTRY', '%A, %B %e. %Y');
+@define('DATE_FORMAT_SHORT', '%Y-%m-%d %H:%M');
+@define('WYSIWYG_LANG', 'en');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', '.');
+@define('NUMBER_FORMAT_THOUSANDS', ',');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Serendipity ºÞ²z¤¶­±');
+@define('HAVE_TO_BE_LOGGED_ON', '½Ð¥ýµn¤J');
+@define('WRONG_USERNAME_OR_PASSWORD', '±z¿é¤J¤F¿ù»~ªº±b¸¹©Î±K½X');
+@define('APPEARANCE', '¥~Æ[°t¸m');
+@define('MANAGE_STYLES', '§G´ººÞ²z');
+@define('CONFIGURE_PLUGINS', '³]©w¥~±¾');
+@define('CONFIGURATION', 'ºÞ²z³]©w');
+@define('BACK_TO_BLOG', '¦^¨ì¤é°O­º­¶');
+@define('LOGIN', 'µn¤J');
+@define('LOGOUT', 'µn¥X');
+@define('LOGGEDOUT', 'µn¥X.');
+@define('CREATE', '«Ø¥ß');
+@define('SAVE', 'Àx¦s');
+@define('NAME', '¦WºÙ');
+@define('CREATE_NEW_CAT', '·s¼WÃþ§O');
+@define('I_WANT_THUMB', '§Ú­n¦b¤å³¹¤º¨Ï¥ÎÁY¹Ï.');
+@define('I_WANT_BIG_IMAGE', '§Ú­n¦b¤å³¹¤º¨Ï¥Î¤j«¬¹Ï¤ù.');
+@define('I_WANT_NO_LINK', ' §Ú­n¥¦¥H¹Ï¤ùÅã¥Ü');
+@define('I_WANT_IT_TO_LINK', '§Ú­n¥¦¥H³sµ²Åã¥Ü³o­Ó URL:');
+@define('BACK', 'ªð¦^');
+@define('FORWARD', '«e¶i');
+@define('ANONYMOUS', '°Î¦W');
+@define('NEW_TRACKBACK_TO', '·sªº¤Þ¥Î¨ì');
+@define('NEW_COMMENT_TO', '·sªº°jÅT¨ì');
+@define('RECENT', '·s¤å®w...');
+@define('OLDER', '¤å®w...');
+@define('DONE', '§¹¦¨');
+@define('WELCOME_BACK', 'Åwªï¦^¨Ó,');
+@define('TITLE', '¼ÐÃD');
+@define('DESCRIPTION', '²¤¶');
+@define('PLACEMENT', '¦ì§}');
+@define('DELETE', '§R°£');
+@define('SAVE', 'Àx¦s');
+@define('UP', '¤W');
+@define('DOWN', '¤U');
+@define('ENTRIES', '¤å³¹');
+@define('NEW_ENTRY', '·s¼W¤å³¹');
+@define('EDIT_ENTRIES', '½s¿è¤å³¹');
+@define('CATEGORIES', 'Ãþ§O');
+@define('WARNING_THIS_BLAHBLAH', "ĵ§i:\\n³o­Ó¥i¯à»Ý­nªø®É¶¡¦pªG¦³«Ü¦h¤£¬OÁY¹Ïªº¹Ï¤ù.");
+@define('CREATE_THUMBS', '­««ØÁY¹Ï');
+@define('MANAGE_IMAGES', 'ºÞ²z¹Ï¤ù');
+@define('NAME', '¦WºÙ');
+@define('EMAIL', 'Email');
+@define('HOMEPAGE', 'ºô§}');
+@define('COMMENT', '°jÅT');
+@define('REMEMBER_INFO', '°O¦í¸ê®Æ? ');
+@define('SUBMIT_COMMENT', '¶Ç°e°jÅT');
+@define('NO_ENTRIES_TO_PRINT', '¨S¦³¤å³¹¥i¥HÅã¥Ü');
+@define('COMMENTS', '°jÅT');
+@define('ADD_COMMENT', '·s¼W°jÅT');
+@define('NO_COMMENTS', '¨S¦³°jÅT');
+@define('POSTED_BY', '§@ªÌ');
+@define('ON', '¦b');
+@define('A_NEW_COMMENT_BLAHBLAH', '·s°jÅT¤wµoªí¨ì±zªº¤é°O "%s", ¦b³o­Ó¤å³¹¸Ì­± "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', '±zªº¤é°O¤å³¹ "%s" ¤w¦³¤F·sªº¤Þ¥Î.');
+@define('NO_CATEGORY', '¨S¦³Ãþ§O');
+@define('ENTRY_BODY', '¤å³¹¥D¤º®e');
+@define('EXTENDED_BODY', '¤å³¹°Æ¤º®e');
+@define('CATEGORY', 'Ãþ§O');
+@define('EDIT', '½s¿è');
+@define('NO_ENTRIES_BLAHBLAH', '§ä¤£¨ì¦¹¬d¸ß %s ªº¤å³¹' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', '±z·j´Mªº %s Åã¥Ü¤F %s µ²ªG:');
+@define('SEARCH_TOO_SHORT', '±z·j´Mªº¤å¦r¥²¶·¦h©ó 3 ­Ó¦rµü');
+@define('IMAGE', '¹Ï¤ù');
+@define('ERROR_FILE_NOT_EXISTS', '¿ù»~: Àɮפ£¦s¦b!');
+@define('ERROR_FILE_EXISTS', '¿ù»~: ÀɮצWºÙ¤w³Q¨Ï¥Î, ½Ð­«·s¿é¤J!');
+@define('ERROR_SOMETHING', '¿ù»~: ¦³¿ù»~.');
+@define('ADDING_IMAGE', '·s¼W¹Ï¤ù...');
+@define('THUMB_CREATED_DONE', 'ÁY¹Ï«Ø¥ß.<br>§¹¦¨.');
+@define('ERROR_FILE_EXISTS_ALREADY', '¿ù»~: Àɮפw¦s¦b!');
+@define('ERROR_UNKNOWN_NOUPLOAD', '¥¼ª¾ªº¿ù»~µo¥Í, ÀÉ®×ÁÙ¨S¤W¶Ç. ¤]³\§AªºÀɮפj©ó­­¨îªº¤j¤p. ½Ð¸ß°Ý±zªº ISP ©Î­×§ï±zªº php.ini ÀÉ.');
+@define('GO', 'Ä~Äò!');
+@define('NEWSIZE', '·s¤j¤p: ');
+@define('RESIZE_BLAHBLAH', '<b>­«³]¤j¤p %s</b><p>');
+@define('ORIGINAL_SIZE', '­ì¦³ªº¤j¤p: <i>%sx%s</i> ¹³¯À');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>¦b³o¸Ì±z¥i¥H­×§ï¹Ï¤ù¤j¤p. ¦pªG±z­n­×§ï¦¨¬Û¦Pªº¹Ï¤ù¤ñ¨Ò, ±z¥u»Ý­n¿é¤J¤@­Ó¼Æ­ÈµM«á«ö TAB -- ¨t²Î·|¦Û°ÊÀ°±z­pºâ¤ñ¨Ò¥H§K¥X¿ù</p>');
+@define('QUICKJUMP_CALENDAR', '¤é¾ä§Ö³t¸õÅD');
+@define('QUICKSEARCH', '§Ö³t·j´M');
+@define('SEARCH_FOR_ENTRY', '·j´M¤å³¹');
+@define('ARCHIVES', '«O¦s¤å®w');
+@define('BROWSE_ARCHIVES', '¥H¤ë¥÷ÂsÄý«O¦s¤å®w');
+@define('TOP_REFERRER', '¥D­n¨Ó·½');
+@define('SHOWS_TOP_SITES', 'Åã¥Ü³sµ²¨ì±zªº¤é°Oªººô¯¸');
+@define('TOP_EXITS', '¥D­n¥X·½');
+@define('SHOWS_TOP_EXIT', 'Åã¥Ü±zªº¤é°Oªº¥D­n¥X·½');
+@define('SYNDICATION', '¤å³¹¦P¨B');
+@define('SHOWS_RSS_BLAHBLAH', 'Åã¥Ü RSS ¦P¨B³sµ²');
+@define('ADVERTISES_BLAHBLAH', '«Å¶Ç±zªººô¸ô¤é°O');
+@define('HTML_NUGGET', 'HTML °T®§');
+@define('HOLDS_A_BLAHBLAH', 'Åã¥Ü HTML °T®§¨ì°¼¦C');
+@define('TITLE_FOR_NUGGET', '°T®§ªº¼ÐÃD');
+@define('THE_NUGGET', 'HTML °T®§!');
+@define('SYNDICATE_THIS_BLOG', '¦P¨B³o­Ó¤é°O');
+@define('YOU_CHOSE', '±z¿ï¾Ü %s');
+@define('IMAGE_SIZE', '¹Ï¤ù¤j¤p');
+@define('IMAGE_AS_A_LINK', '¿é¤J¹Ï¤ù');
+@define('POWERED_BY', 'Powered by');
+@define('TRACKBACKS', '¤Þ¥Î');
+@define('TRACKBACK', '¤Þ¥Î');
+@define('NO_TRACKBACKS', '¨S¦³¤Þ¥Î');
+@define('TOPICS_OF', '¥DÃD');
+@define('VIEW_FULL', 'ÂsÄý¥þ³¡');
+@define('VIEW_TOPICS', 'ÂsÄý¥DÃD');
+@define('AT', '¦b');
+@define('SET_AS_TEMPLATE', '¨Ï¥Î§G´º');
+@define('IN', '¦b');
+@define('EXCERPT', 'ºK­n');
+@define('TRACKED', '¤Þ¥Î');
+@define('LINK_TO_ENTRY', '³sµ²¨ì¤å³¹');
+@define('LINK_TO_REMOTE_ENTRY', '³sµ²¨ì»·ºÝ¤å³¹');
+@define('IP_ADDRESS', 'IP ¦ì§}');
+@define('USER', '§@ªÌ');
+@define('THUMBNAIL_USING_OWN', '¨Ï¥Î %s ·í¥¦ªºÁY¹Ï¤Ø¤o¦]¬°¹Ï¤ù¤w¸g«Ü¤p¤F.');
+@define('THUMBNAIL_FAILED_COPY', '¨Ï¥Î %s ·í¥¦ªºÁY¹Ï, ¦ý¬OµLªk½Æ»s!');
+@define('AUTHOR', 'µoªíªÌ');
+@define('LAST_UPDATED', '³Ì«á§ó·s');
+@define('TRACKBACK_SPECIFIC', '¤Þ¥Î¦¹¤å³¹¯S©wªº URI (ºô§})');
+@define('DIRECT_LINK', 'ª½±µªº¤å³¹³sµ²');
+@define('COMMENT_ADDED', '±zªº°jÅT¤w¦¨¥\¼W¤J. ');
+@define('COMMENT_ADDED_CLICK', 'ÂI %s³o¸Ìªð¦^%s ¨ì°jÅT, ©MÂI %s³o¸ÌÃö³¬%s ³o­Óµøµ¡.');
+@define('COMMENT_NOT_ADDED', '±zªº°jÅT¤£¯à¼W¤J¦]¬°¦¹½g¤å³¹¤£¤¹³\°jÅT. ');
+@define('COMMENT_NOT_ADDED_CLICK', 'ÂI %s³o¸Ìªð¦^%s ¨ì°jÅT, ©MÂI %s³o¸ÌÃö³¬%s ³o­Óµøµ¡.');
+@define('COMMENTS_DISABLE', '¤£¤¹³\°jÅT¨ì³o½g¤å³¹');
+@define('COMMENTS_ENABLE', '¤¹³\°jÅT¨ì³o½g¤å³¹');
+@define('COMMENTS_CLOSED', '§@ªÌ¤£¤¹³\°jÅT¨ì³o½g¤å³¹');
+@define('EMPTY_COMMENT', '±zªº°jÅT¨S¦³¥ô¦ó°T®§, ½Ð %sªð¦^%s ­«¸Õ');
+@define('ENTRIES_FOR', '¤å³¹µ¹ %s');
+@define('DOCUMENT_NOT_FOUND', '§ä¤£¨ì¦¹½g¤å¥ó %s.');
+@define('USERNAME', '±b¸¹');
+@define('PASSWORD', '±K½X');
+@define('AUTOMATIC_LOGIN', '¦Û°Êµn¤J');
+@define('SERENDIPITY_INSTALLATION', 'Serendipity ¦w¸Ëµ{¦¡');
+@define('LEFT', '¥ª');
+@define('RIGHT', '¥k');
+@define('HIDDEN', 'ÁôÂÃ');
+@define('REMOVE_TICKED_PLUGINS', '²¾°£¤Ä¿ïªº¥~±¾');
+@define('SAVE_CHANGES_TO_LAYOUT', 'Àx¦s¥~Æ[°t¸m');
+@define('COMMENTS_FROM', '°jÅT¨Ó·½');
+@define('ERROR', '¿ù»~');
+@define('ENTRY_SAVED', '±zªº¤å³¹¤wÀx¦s');
+@define('DELETE_SURE', '½T©w­n§R°£ #%s ¶Ü?');
+@define('NOT_REALLY', 'ºâ¤F...');
+@define('DUMP_IT', '§R°£§a!');
+@define('RIP_ENTRY', 'R.I.P. ¤å³¹ #%s');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Ãþ§O #%s ¤w§R°£. Â¤峹¤w³Q²¾°Ê¨ìÃþ§O #%s');
+@define('CATEGORY_DELETED', 'Ãþ§O #%s ¤w§R°£.');
+@define('INVALID_CATEGORY', '¨S¦³´£¨Ñ§R°£ªºÃþ§O');
+@define('CATEGORY_SAVED', 'Ãþ§O¤wÀx¦s');
+@define('SELECT_TEMPLATE', '½Ð¿ï¾Üºô¸ô¤é°Oªº§G´º');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', '¨S¦³§¹¦¨¼W¤J¤å³¹!');
+@define('MT_DATA_FILE', 'Movable Type ¸ê®ÆÀÉ');
+@define('FORCE', '±j¨î');
+@define('CREATE_AUTHOR', '·s¼W§@ªÌ \'%s\'.');
+@define('CREATE_CATEGORY', '·s¼WÃþ§O \'%s\'.');
+@define('MYSQL_REQUIRED', '±z¥²¶·­n¦³ MySQL ªºÂX¥R¥\¯à¤~¯à°õ¦æ³o­Ó°Ê§@.');
+@define('COULDNT_CONNECT', '¤£¯àÁpµ²¨ì MySQL ¸ê®Æ®w: %s.');
+@define('COULDNT_SELECT_DB', '¤£¯à¿ï¾Ü¸ê®Æ®w: %s.');
+@define('COULDNT_SELECT_USER_INFO', '¤£¯à¿ï¾Ü¨Ï¥ÎªÌªº¸ê®Æ: %s.');
+@define('COULDNT_SELECT_CATEGORY_INFO', '¤£¯à¿ï¾ÜÃþ§Oªº¸ê®Æ: %s.');
+@define('COULDNT_SELECT_ENTRY_INFO', '¤£¯à¿ï¾Ü¤å³¹ªº¸ê®Æ: %s.');
+@define('COULDNT_SELECT_COMMENT_INFO', '¤£¯à¿ï¾Ü°jÅTªº¸ê®Æ: %s.');
+@define('YES', '¬O');
+@define('NO', '§_');
+@define('USE_DEFAULT', '¹w³]');
+@define('CHECK_N_SAVE', 'Àx¦s');
+@define('DIRECTORY_WRITE_ERROR', '¤£¯àŪ¼gÀÉ®×§¨ %s. ½ÐÀˬdÅv­­.');
+@define('DIRECTORY_CREATE_ERROR', 'ÀÉ®×§¨ %s ¤£¦s¦b¤]µLªk«Ø¥ß. ½Ð¦Û¤v«Ø¥ß³o­ÓÀÉ®×§¨');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; run <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', 'µLªk°õ¦æ %s ¸ê·½ÀÉ®×');
+@define('FILE_WRITE_ERROR', 'µLªkŪ¼gÀÉ®× %s.');
+@define('FILE_CREATE_YOURSELF', '½Ð¦Û¤v«Ø¥ß³o­ÓÀɮשÎÀˬdÅv­­');
+@define('COPY_CODE_BELOW', '<br />* ½Ð½Æ»s¤U­±ªº¥N½XµM«á©ñ¤J %s ¨ì±zªº %s ÀÉ®×§¨:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', '½Ð§ïÅÜ www ¨ì¨Ï¥ÎªÌªº Apache (i.e. nobody).');
+@define('BROWSER_RELOAD', '§¹¦¨¤§«á, ­«·s¨ê·s±zªºÂsÄý¾¹.');
+@define('DIAGNOSTIC_ERROR', '¨t²Î°»´ú¨ì¤@¨Ç¿ù»~:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity ÁÙ¨S¦w¸Ë§¹¦¨. ½Ð«ö <a href="%s">¦w¸Ë</a>.');
+@define('INCLUDE_ERROR', 'serendipity ¿ù»~: µLªk¥]¬A %s - °h¥X.');
+@define('DATABASE_ERROR', 'serendipity ¿ù»~: µLªk³sµ²¨ì¸ê®Æ®w - °h¥X.');
+@define('CHECK_DATABASE_EXISTS', 'Àˬd¸ê®Æ®w¬O§_¦s¦b. ¦pªG±z¬Ý¨ì¸ê®Æ®w¬d¸ß¿ù»~, ½Ð¤£¥ÎºÞ¥¦...');
+@define('CREATE_DATABASE', '«Ø¥ß¹w³]¸ê®Æ®w³]©w...');
+@define('ATTEMPT_WRITE_FILE', 'Ū¼g %s ÀÉ®×...');
+@define('SERENDIPITY_INSTALLED', '%sSerendipity ¤w¦w¸Ë§¹¦¨.%s ½Ð°O±o±zªº±K½X: "%s", ±zªº±b¸¹¬O "%s".%s±z²{¦b¥i¥H¨ì·s«Ø¥ßªº <a href="%s">ºô¸ô¤é°O</a>');
+@define('WRITTEN_N_SAVED', 'Àx¦s§¹²¦');
+@define('IMAGE_ALIGNMENT', '¹Ï¤ù¹ï»ô');
+@define('ENTER_NEW_NAME', '¿é¤J·s¦WºÙµ¹: ');
+@define('RESIZING', '­«³]¤j¤p');
+@define('RESIZE_DONE', '§¹¦¨ (­«³] %s ­Ó¹Ï¤ù).');
+@define('SYNCING', '¶i¦æ¸ê®Æ®w©M¹Ï¤ùÀÉ®×§¨¦P¨B¤Æ');
+@define('SYNC_DONE', '§¹¦¨ (¦P¨B¤F %s ­Ó¹Ï¤ù).');
+@define('FILE_NOT_FOUND', '§ä¤£¨ìÀɮצWºÙ <b>%s</b>, ¤]³\¤w¸g³Q§R°£¤F?');
+@define('ABORT_NOW', '©ñ±ó');
+@define('REMOTE_FILE_NOT_FOUND', 'Àɮפ£¦b»·ºÝ¥D¾÷¤º, ±z½T©w³o­Ó URL: <b>%s</b> ¬O¥¿½Tªº¶Ü?');
+@define('FILE_FETCHED', '%s ¨ú¦^¬° %s');
+@define('FILE_UPLOADED', 'ÀÉ®× %s ¤W¶Ç¬° %s');
+@define('WORD_OR', '©Î');
+@define('SCALING_IMAGE', 'ÁY©ñ %s ¨ì %s x %s px');
+@define('KEEP_PROPORTIONS', 'ºû«ù¤ñ¨Ò');
+@define('REALLY_SCALE_IMAGE', '½T©w­nÁY©ñ¹Ï¤ù¶Ü? ³o­Ó°Ê§@¤£¯à´_­ì!');
+@define('TOGGLE_ALL', '¤Á´«®i¶}');
+@define('TOGGLE_OPTION', '¤Á´«¿ï¶µ');
+@define('SUBSCRIBE_TO_THIS_ENTRY', '­q¾\³o½g¤å³¹');
+@define('UNSUBSCRIBE_OK', "%s ¤w¨ú®ø­q¾\³o½g¤å³¹");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', '·s°jÅT¨ì­q¾\ªº¤å³¹ "%s"');
+@define('SUBSCRIPTION_MAIL', "±z¦n %s,\n\n±z­q¾\ªº¤å³¹¦³¤F·sªº°jÅT¦b \"%s\", ¼ÐÃD¬O \"%s\"\n°jÅTªºµoªíªÌ¬O: %s\n\n±z¥i¥H¦b³o§ä¨ì¦¹¤å³¹: %s\n\n±z¥i¥HÂI³o­Ó³sµ²¨ú®ø­q¾\: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "±z¦n %s,\n\n±z­q¾\ªº¤å³¹¦³¤F·sªº¤Þ¥Î¦b \"%s\", ¼ÐÃD¬O \"%s\"\n¤Þ¥Îªº§@ªÌ¬O: %s\n\n±z¥i¥H¦b³o§ä¨ì¦¹¤å³¹: %s\n\n±z¥i¥HÂI³o­Ó³sµ²¨ú®ø­q¾\: %s\n");
+@define('SIGNATURE', "\n-- \n%s is powered by Serendipity.\nThe best blog around, you can use it too.\nCheck out <http://s9y.org> to find out how.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91 feed');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0 feed');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0 feed');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 comments');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3 feed');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'Äæ¦ì "managingEditor"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  'Äæ¦ì "webMaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'RSS feed ªº¹Ï¤ù');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', '¹Ï¤ù¼e«×');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', '¹Ï¤ù°ª«×');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  'ºÞ²z­ûªº¹q¤l¶l¥ó, ¦pªG¦³. (ªÅ¥Õ: ÁôÂÃ) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', '§@ªÌªº¹q¤l¶l¥ó, ¦pªG¦³. (ªÅ¥Õ: ÁôÂÃ) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', '¹Ï¤ùªº¦ì§} URL, ¥H GIF/JPEG/PNG ®æ¦¡, ¦pªG¦³. (ªÅ¥Õ: serendipity-logo)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', '¹³¯À, ³Ì¤j. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', '¹³¯À, ³Ì¤j. 400');
+@define('SYNDICATION_PLUGIN_TTL', 'Äæ¦ì "ttl" (time-to-live)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', '¹L´X¤ÀÄÁ«á±zªº¤å³¹¤£·|³Q¥~¨Óªººô¯¸©Îµ{¦¡Àx¦s¨ì§Ö¨ú°O¾Ð¸Ì (ªÅ¥Õ: ÁôÂÃ) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'Äæ¦ì "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', '"pubDate"-Äæ¦ì»Ý­n¤º´O¨ìRSS-ÀW¹D, ¥HÅã¥Ü³Ì«á¤å³¹ªº¤é´Á¶Ü?');
+@define('CONTENT', '¤º®e');
+@define('TYPE', 'Ãþ«¬');
+@define('DRAFT', '¯ó½Z');
+@define('PUBLISH', '¤½¶}');
+@define('PREVIEW', '¹wÄý');
+@define('DATE', '¤é´Á');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', 'ĵ§i: ±z´£¨Ñªº¤é´Á¤£¥¿½T. ¥¦¥²¶·¬O YYYY-MM-DD HH:MM ®æ¦¡.');
+@define('CATEGORY_PLUGIN_DESC', 'Åã¥ÜÃþ§O²M³æ.');
+@define('ALL_AUTHORS', '¥þ³¡§@ªÌ');
+@define('CATEGORIES_TO_FETCH', 'Åã¥ÜÃþ§O');
+@define('CATEGORIES_TO_FETCH_DESC', 'Åã¥Ü­þ¦ì§@ªÌªºÃþ§O?');
+@define('PAGE_BROWSE_ENTRIES', '­¶¼Æ %s ¦@ %s, Á`¦@ %s ½g¤å³¹');
+@define('PREVIOUS_PAGE', '¤W¤@­¶');
+@define('NEXT_PAGE', '¤U¤@­¶');
+@define('ALL_CATEGORIES', '¥þ³¡Ãþ§O');
+@define('DO_MARKUP', '°õ¦æ¼Ð°OÂà´«');
+@define('GENERAL_PLUGIN_DATEFORMAT', '¤é´Á®æ¦¡¤Æ');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', '¤å³¹ªº¤é´Á®æ¦¡, ¨Ï¥Î PHP ªº strftime() ÅܼÆ. (¹w³]: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'µLªk¶}±Ò§G´ºÀÉ®×, ½Ð§ó·s serendipity!');
+@define('ADVANCED_OPTIONS', '¶i¶¥¿ï¶µ');
+@define('EDIT_ENTRY', '½s¿è¤å³¹');
+@define('HTACCESS_ERROR', '­nÀˬd±zªº¥D¾÷¦w¸Ë³]©w, serendipity »Ý­nŪ¼gÀÉ®× ".htaccess". ¦ý¬O¦]¬°Åv­­¿ù»~, ¨S¦³¿ìªk¬°±zÀˬd. ½Ð§ïÅÜÀÉ®×Åv­­¹³³o¼Ë: <br />&nbsp;&nbsp;%s<br />µM«á­«·s¨ê·s³o­Óºô­¶.');
+@define('SIDEBAR_PLUGINS', '°¼¦C¥~±¾');
+@define('EVENT_PLUGINS', '¨Æ¥ó¥~±¾');
+@define('SORT_ORDER', '±Æ§Ç');
+@define('SORT_ORDER_NAME', 'ÀɮצWºÙ');
+@define('SORT_ORDER_EXTENSION', '°ÆÀɦW');
+@define('SORT_ORDER_SIZE', 'Àɮפj¤p');
+@define('SORT_ORDER_WIDTH', '¹Ï¤ù¼e«×');
+@define('SORT_ORDER_HEIGHT', '¹Ï¤ùªø«×');
+@define('SORT_ORDER_DATE', '¤W¶Ç¤é´Á');
+@define('SORT_ORDER_ASC', '»¼¼W±Æ§Ç');
+@define('SORT_ORDER_DESC', '»¼´î±Æ§Ç');
+@define('THUMBNAIL_SHORT', 'ÁY¹Ï');
+@define('ORIGINAL_SHORT', '­ì©l');
+@define('APPLY_MARKUP_TO', '®M¥Î¼Ð°O¨ì %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', '¤@¶gªº²Ä¤@¤Ñ');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity °»´ú¨ì±zªº°t¸mª©¥»¬O %s, ¦ý¬O Serendipity ¥»¨­ªº¦w¸Ëª©¥»¬O %s, ½Ð§ó·s±zªºµ{¦¡ª©¥»! <a href="%s">§ó·s</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', '±z¦n, Åwªï¨Ó¨ì Serendipity ªº§ó·s¨t²Î.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', '§ó·s¨t²Î·|À°±z§ó·s¨ì Serendipity ª©¥» %s.');
+@define('SERENDIPITY_UPGRADER_WHY', '±z¬Ý¨ì³o­Ó°T®§¬O¦]¬°±z¦w¸Ë¤F Serendipity ª©¥» %s, ¦ý¬O±z¨S¦³§ó·s¸ê®Æ®w');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', '¸ê®Æ®w§ó·s (%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', '¨t²Î§ä¨ì¥H¤Uªº .sql ÀÉ, ¨º¨ÇÀÉ®×¥²¶·¥ý°õ¦æ¤~¯àÄ~Äò¦w¸Ë Serendipity');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  '¯S©wªºª©¥»¥ô°È');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', '¨S¦³¯S©wªºª©¥»¥ô°È');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', '½T©w­n°õ¦æ¤W­±ªº¥ô°È¶Ü?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', '§Ú¦Û¤v°õ¦æ');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', '½ÐÀ°§Ú°õ¦æ');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', '±z¤£»Ý­n¶i¦æ¥ô¦ó§ó·s');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', '°²¸Ë Serendipity §ó·s§¹¦¨§a');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', '±z²¤¹L¤F§ó·s¥ô°È, ½Ð½T©w¸ê®Æ®w¤w¦w¸Ë§¹¦¨, ©M¨ä¥Lªº¥ô°È¦w¸ËµL»~');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', '±zªº Serendipity ¥H§ó·s¦Üª©¥» %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', '±z¥i¥HÂI %s³o¸Ì%s ªð¦^¤é°O­º­¶');
+@define('MANAGE_USERS', 'ºÞ²z§@ªÌ');
+@define('CREATE_NEW_USER', '·s¼W§@ªÌ');
+@define('CREATE_NOT_AUTHORIZED', '±z¤£¯à­×§ï¸ò±z¬Û¦PÅv­­ªº§@ªÌ');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', '±z¤£¯à·s¼W¤ñ±z°ªÅv­­ªº§@ªÌ');
+@define('CREATED_USER', '·s§@ªÌ %s ¤w¸g·s¼W');
+@define('MODIFIED_USER', '§@ªÌ %s ªº¸ê®Æ¤w¸g§ó§ï');
+@define('USER_LEVEL', '§@ªÌÅv­­');
+@define('DELETE_USER', '±z­n§R°£³o­Ó§@ªÌ #%d %s. ½T©w¶Ü? ³o·|¦b¥D­¶ÁôÂÃ¥L©Ò¼gªº¥ô¦ó¤å³¹.');
+@define('DELETED_USER', '§@ªÌ #%d %s ¤w³Q§R°£.');
+@define('LIMIT_TO_NUMBER', '­nÅã¥Ü¦h¤Ö¶µ¥Ø?');
+@define('ENTRIES_PER_PAGE', '¨C­¶Åã¥Üªº¤å³¹');
+@define('XML_IMAGE_TO_DISPLAY', 'XML «ö¶s');
+@define('XML_IMAGE_TO_DISPLAY_DESC','³sµ²¨ì XML Feeds ªº³£·|¥Î³o­Ó¹Ï¤ùªí¥Ü. ¤£¶ñ¼g±N·|¨Ï¥Î¹w³]ªº¹Ï¤ù, ©Î¿é¤J \'none\' Ãö³¬³o­Ó¥\¯à.');
+
+@define('DIRECTORIES_AVAILABLE', '±z¥i¥H¦b¤l¥Ø¿ý¤ºÂI¥ô¦ó¥Ø¿ý¨Ó«Ø¥ß·sªº¥Ø¿ý.');
+@define('ALL_DIRECTORIES', '¥þ³¡¥Øºñ');
+@define('MANAGE_DIRECTORIES', 'ºÞ²z¥Ø¿ý');
+@define('DIRECTORY_CREATED', '¥Ø¿ý <strong>%s</strong> ¤w¸g·s¼W.');
+@define('PARENT_DIRECTORY', '¥À¥Ø¿ý');
+@define('CONFIRM_DELETE_DIRECTORY', '½T©w­n§R°£³o­Ó¥Ø¿ý¤ºªº¥þ³¡¤º®e¶Ü %s?');
+@define('ERROR_NO_DIRECTORY', '¿ù»~: ¥Ø¿ý %s ¤£¦s¦b');
+@define('CHECKING_DIRECTORY', 'Àˬd¦¹¥Ø¿ýªºÀÉ®× %s');
+@define('DELETING_FILE', '§R°£ÀÉ®× %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', '¤£¯à²¾°£¥¼²MªÅªº¥Ø¿ý. ¤Ä¿ï "±j¨î§R°£" ®Ö¨ú¤è¶ô¦pªG±z­n²¾°£³o¨ÇÀÉ®×, µM«á¦bÄ~Äò. ¦s¦bªºÀɮ׬O:');
+@define('DIRECTORY_DELETE_FAILED', '¤£¯à§R°£¥Ø¿ý %s. ½ÐÀˬdÅv­­©Î¬Ý¤W­±ªº°T®§.');
+@define('DIRECTORY_DELETE_SUCCESS', '¥Ø¿ý %s ¦¨¥\§R°£.');
+@define('SKIPPING_FILE_EXTENSION', '²¤¹LÀÉ®×: ¨S¦³ %s ªº°ÆÀɦW.');
+@define('SKIPPING_FILE_UNREADABLE', '²¤¹LÀÉ®×: %s ¤£¯àŪ¨ú.');
+@define('FOUND_FILE', '§ä¨ì ·s/­×§ï ¹LªºÀÉ®×: %s.');
+@define('ALREADY_SUBCATEGORY', '%s ¤w¸g¬O¦¹Ãþ§Oªº¤lÃþ§O %s.');
+@define('PARENT_CATEGORY', '¥ÀÃþ§O');
+@define('IN_REPLY_TO', '¦^ÂШì');
+@define('TOP_LEVEL', '³Ì°ª¼h');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s feed');
+@define('PERMISSIONS', 'Åv­­');
+@define('SETTINGS_SAVED_AT', '·s³]©w¤w¸g³QÀx¦s¨ì %s');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', '¸ê®Æ®w³]©w');
+@define('INSTALL_CAT_DB_DESC', '±z¥i¥H¦b³o¿é¤J¥þ³¡ªº¸ê®Æ®w¸ê®Æ. Serendipity »Ý­n³o¨Ç¸ê®Æ¤~¯à¥¿±`¹B§@');
+@define('INSTALL_DBTYPE', '¸ê®Æ®wÃþ«¬');
+@define('INSTALL_DBTYPE_DESC', '¸ê®Æ®wÃþ«¬');
+@define('INSTALL_DBHOST', '¸ê®Æ®w¥D¾÷');
+@define('INSTALL_DBHOST_DESC', '¸ê®Æ®w¥D¾÷¦WºÙ');
+@define('INSTALL_DBUSER', '¸ê®Æ®w±b¸¹');
+@define('INSTALL_DBUSER_DESC', 'µn¤J¸ê®Æ®wªº±b¸¹');
+@define('INSTALL_DBPASS', '¸ê®Æ®w±K½X');
+@define('INSTALL_DBPASS_DESC', '±zªº¸ê®Æ®w±K½X');
+@define('INSTALL_DBNAME', '¸ê®Æ®w¦WºÙ');
+@define('INSTALL_DBNAME_DESC', '¸ê®Æ®w¦WºÙ');
+@define('INSTALL_DBPREFIX', '¸ê®Æªí«e¸m¦WºÙ');
+@define('INSTALL_DBPREFIX_DESC', '¸ê®Æªíªº«e¸m¦WºÙ, ¨Ò¦p serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', '¸ô®|³]©w');
+@define('INSTALL_CAT_PATHS_DESC', 'µ¹ÀÉ®×§¨ªº¸ô®|. ¤£­n§Ñ¤F³Ì«áªº±×½u!');
+@define('INSTALL_FULLPATH', '§¹¥þ¸ô®|');
+@define('INSTALL_FULLPATH_DESC', '±zªº Serendipity ¦w¸Ëªº§¹¥þ¸ô®|©Mµ´¹ï¸ô®|');
+@define('INSTALL_UPLOADPATH', '¤W¶Ç¸ô®|');
+@define('INSTALL_UPLOADPATH_DESC', '¥þ³¡ªº¤W¶ÇÀÉ®×·|¦s¨ì³o¸Ì, ¥H \'§¹¥þ¸ô®|\' ªí¥Üªº¬Û¹ï¸ô®| - ¨Ò¦p \'uploads/\'');
+@define('INSTALL_RELPATH', '¬Û¹ï¸ô®|');
+@define('INSTALL_RELPATH_DESC', 'µ¹ÂsÄý¾¹ªº¸ô®|, ¨Ò¦p \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', '¬Û¹ïªº§G´º¸ô®|');
+@define('INSTALL_RELTEMPLPATH_DESC', '±z©ñ§G´ºªº¸ô®| - ¥H \'¬Û¹ï¸ô®|\' ªí¥Üªº¬Û¹ï¸ô®|');
+@define('INSTALL_RELUPLOADPATH', '¬Û¹ïªº¤W¶Ç¸ô®|');
+@define('INSTALL_RELUPLOADPATH_DESC', 'µ¹ÂsÄý¾¹¤W¶ÇÀɮתº¸ô®| - ¥H \'¬Û¹ï¸ô®|\' ªí¥Üªº¬Û¹ï¸ô®|');
+@define('INSTALL_URL', 'ºô¸ô¤é°O URL');
+@define('INSTALL_URL_DESC', '±zªº Serendipity ¦w¸Ëªº°ò¥» URL');
+@define('INSTALL_INDEXFILE', 'Index ÀÉ®×');
+@define('INSTALL_INDEXFILE_DESC', 'Serendipity ªº index ÀÉ®×');
+
+/* Generel settings */
+@define('INSTALL_CAT_SETTINGS', '¤@¯ë³]©w');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Serendipity ªº¤@¯ë³]©w');
+@define('INSTALL_USERNAME', 'ºÞ²z­û±b¸¹');
+@define('INSTALL_USERNAME_DESC', 'ºÞ²z­ûªºµn¤J¦WºÙ');
+@define('INSTALL_PASSWORD', 'ºÞ²z­û±K½X');
+@define('INSTALL_PASSWORD_DESC', 'ºÞ²z­ûªºµn¤J±K½X');
+@define('INSTALL_EMAIL', '¹q¤l¶l¥ó');
+@define('INSTALL_EMAIL_DESC', 'ºÞ²z­ûªº¹q¤l¶l¥ó');
+@define('INSTALL_SENDMAIL', '±H°e¹q¤l¶l¥óµ¹ºÞ²z­û?');
+@define('INSTALL_SENDMAIL_DESC', '·í¦³¤Hµo§G°jÅT¨ì±zªº¤å³¹®É­n¦¬¨ì¹q¤l¶l¥ó³qª¾¶Ü?');
+@define('INSTALL_SUBSCRIBE', '¤¹³\¨Ï¥ÎªÌ­q¾\¤å³¹?');
+@define('INSTALL_SUBSCRIBE_DESC', '±z¥i¥H¤¹³\¨Ï¥ÎªÌ¦¬¨ì¹q¤l¶l¥ó³qª¾, ·í¦³°jÅTµo§G®É¦o­Ì·|¦¬¨ì³qª¾.');
+@define('INSTALL_BLOGNAME', '¤é°O¦WºÙ');
+@define('INSTALL_BLOGNAME_DESC', '±zªº¤é°O¼ÐÃD');
+@define('INSTALL_BLOGDESC', '¤é°O²¤¶');
+@define('INSTALL_BLOGDESC_DESC', '¤¶²Ð±zªº¤é°O');
+@define('INSTALL_LANG', '»y¨t');
+@define('INSTALL_LANG_DESC', '±z¤é°O¨Ï¥Îªº»y¨t');
+
+/* Appearance and options */
+@define('INSTALL_CAT_DISPLAY', '¥~Æ[¤Î¿ï¶µ³]©w');
+@define('INSTALL_CAT_DISPLAY_DESC', 'Åý±z³]©w Serendipity ªº¥~Æ[©M¨ä¥L³]©w');
+@define('INSTALL_WYSIWYG', '¨Ï¥Î WYSIWYG ½s¿è¾¹');
+@define('INSTALL_WYSIWYG_DESC', '±z­n¨Ï¥Î WYSIWYG ½s¿è¾¹¶Ü? (¥i¦b IE5+ ¨Ï¥Î, ¬Y¨Ç³¡¤À¥i¨Ï¥Î©ó Mozilla 1.3+)');
+@define('INSTALL_XHTML11', '±j¨î²Å¦X XHTML 1.1 ­n¨D');
+@define('INSTALL_XHTML11_DESC', '±z¥i¥HÅý±zªº¤é°O±j¨î²Å¦X XHTML 1.1 ªº­n¨D (¹ïªºÂsÄý¾¹¥i¯à·|¦³ «á¥x/«e¥x ªº°ÝÃD)');
+@define('INSTALL_POPUP', '¨Ï¥Î¼u¥Xµøµ¡');
+@define('INSTALL_POPUP_DESC', '±z­n¦b°jÅT, ¤Þ¥Îµ¥¦a¤è¨Ï¥Î¼u¥Xµøµ¡¶Ü?');
+@define('INSTALL_EMBED', '¨Ï¥Î¤º´O¥\¯à?');
+@define('INSTALL_EMBED_DESC', '¦pªG§A­n±N Serendipity ¥H¤º´Oªº¤è¦¡©ñ¨ìºô­¶¤º, ¿ï¾Ü ¬O ·|Åý±z±Ë±ó¥ô¦ó¼ÐÃDµM«á¥uÅã¥Ü¤é°O¤º®e. ±z¥i¥H¥Î indexFile ³]©w¨Ó¨Ï¥Î¥]¸Ë¨ç¦¡Ãþ§O¥H«K±z©ñ¤Jºô­¶¼ÐÃD. ¸Ô±¡½Ð¬d¸ß README ÀÉ®×!');
+@define('INSTALL_TOP_AS_LINKS', '¥H³sµ²Åã¥Ü ¥D­n¥X·½/¥D­n¨Ó·½?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"§_": ¥X·½©M¨Ó·½±N¥Î¤å¦rÅã¥Ü¥HÁ×§K google ªº¼s§i. "¬O": ¥X·½©M¨Ó·½±N¥Î³sµ²Åã¥Ü. "¹w³]": ¥Î¥þ°Ï¸Ì­±ªº³]©w («ØÄ³).');
+@define('INSTALL_BLOCKREF', 'ªý¾×¨Ó·½');
+@define('INSTALL_BLOCKREF_DESC', '¦³¥ô¦ó¯S®íªº¥D¾÷±z¤£·Q¦b¨Ó·½¸ÌÅã¥Ü¶Ü? ¥Î \';\' ¨Ó¤À¶}¥D¾÷¦WºÙ, ª`·N¥D¾÷¬O¥H¤l¦r¦ê¤è¦¡ªý¾×!');
+@define('INSTALL_REWRITE', 'URL Rewriting');
+@define('INSTALL_REWRITE_DESC', '½Ð¿ï¾Ü±z·Q¥Îªº URL Rewriting ¤è¦¡. ¶}±Ò rewrite ³W«h·|¥H¤ñ¸û²M·¡ªº¤è¦¡Åã¥Ü URL, ¥H«K·j´Mºô¯¸¯à¥¿½Tªºµn¤J±zªº¤å³¹. ±zªº¥D¾÷¥²¶·¤ä´© mod_rewrite ©Î "AllowOverride All" ¨ì±zªº Serendipity ÀÉ®×§¨. ¹w³]ªº³]©w¬O¨t²Î¦Û°ÊÀ°±z°»´úªº');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', '¹Ï¤ùÂà´«³]©w');
+@define('INSTALL_CAT_IMAGECONV_DESC', '½Ð³]©w Serendipity ³]©w¹Ï¤ùÂà´«ªº¤è¦¡');
+@define('INSTALL_IMAGEMAGICK', '¨Ï¥Î Imagemagick');
+@define('INSTALL_IMAGEMAGICK_DESC', '¦pªG¦³¦w¸Ë image magick, ±z­n¥Î¥¦¨Ó§ïÅܹϤù¤j¤p¶Ü?');
+@define('INSTALL_IMAGEMAGICKPATH', 'Âà´«µ{¦¡¸ô®|');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'image magick Âà´«µ{¦¡ªº§¹¥þ¸ô®|©M¦WºÙ');
+@define('INSTALL_THUMBSUFFIX', 'ÁY¹Ï«á¸m¦r¤¸');
+@define('INSTALL_THUMBSUFFIX_DESC', 'ÁY¹Ï·|¥H¤U­±ªº®æ¦¡­«·s©R¦W: original.[«á¸m¦r¤¸].ext');
+@define('INSTALL_THUMBWIDTH', 'ÁY¹Ï¤Ø«×');
+@define('INSTALL_THUMBWIDTH_DESC', '¦Û°Ê«Ø¥ßÁY¹Ïªº³Ì¤j¼e«×');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', '­Ó¤H¸ê®Æ³]©w');
+@define('USERCONF_CAT_PERSONAL_DESC', '§ïÅܱzªº­Ó¤H¸ê®Æ');
+@define('USERCONF_USERNAME', '±zªº±b¸¹');
+@define('USERCONF_USERNAME_DESC', '±zµn¤Jºô¸ô¤é°Oªº¦WºÙ');
+@define('USERCONF_PASSWORD', '±zªº±K½X');
+@define('USERCONF_PASSWORD_DESC', '±zµn¤Jºô¸ô¤é°Oªº±K½X');
+@define('USERCONF_EMAIL', '±zªº¹q¤l¶l¥ó');
+@define('USERCONF_EMAIL_DESC', '±z¨Ï¥Îªº¹q¤l¶l¥ó');
+@define('USERCONF_SENDCOMMENTS', '±H°e°jÅT³qª¾?');
+@define('USERCONF_SENDCOMMENTS_DESC', '·í¦³·s°jÅT¨ì±zªº¤å³¹®É­n³qª¾±z¶Ü?');
+@define('USERCONF_SENDTRACKBACKS', '±H°e¤Þ¥Î³qª¾?');
+@define('USERCONF_SENDTRACKBACKS_DESC', '·í¦³·s¤Þ¥Î¨ì±zªº¤å³¹®É­n³qª¾±z¶Ü?');
+@define('USERCONF_ALLOWPUBLISH', 'Åv­­: ¥iµo§G¤å³¹?');
+@define('USERCONF_ALLOWPUBLISH_DESC', '¤¹³\³o¦ì§@ªÌµo§G¤å³¹¶Ü?');
+@define('SUCCESS', '§¹¦¨');
+@define('POWERED_BY_SHOW_TEXT', '¥H¤å¦rÅã¥Ü "Serendipity"');
+@define('POWERED_BY_SHOW_TEXT_DESC', '±N¥Î¤å¦rÅã¥Ü "Serendipity Weblog"');
+@define('POWERED_BY_SHOW_IMAGE', '¥H logo Åã¥Ü "Serendipity"');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'Åã¥Ü Serendipity ªº logo');
+@define('PLUGIN_ITEM_DISPLAY', '¸Ó¶µ¥ØªºÅã¥Ü¦ì§}?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', '¥u¦b°Æ¤º®eÅã¥Ü');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', '¥u¦b·§Æ[¤ºÅã¥Ü');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', '¥Ã»·Åã¥Ü');
+
+@define('COMMENTS_WILL_BE_MODERATED', 'µo§Gªº°jÅT±N»Ý­nºÞ²z­ûªº¼f®Ö.');
+@define('YOU_HAVE_THESE_OPTIONS', '±z¦³¥H¤U¿ï¾Ü:');
+@define('THIS_COMMENT_NEEDS_REVIEW', 'ĵ§i: ³o­Ó°jÅT¶·¼f®Ö¤~·|Åã¥Ü');
+@define('DELETE_COMMENT', '§R°£°jÅT');
+@define('APPROVE_COMMENT', '»{¥i°jÅT');
+@define('REQUIRES_REVIEW', '»Ý­n¼f®Ö');
+@define('COMMENT_APPROVED', '°jÅT #%s ¤w¸g³q¹L¼f®Ö');
+@define('COMMENT_DELETED', '°jÅT #%s ¤w¸g¦¨¥\§R°£');
+@define('COMMENTS_MODERATE', '°jÅT©M¤Þ¥Î¨ì³o­Ó¤å³¹»Ý­nºÞ²z­ûªº¼f®Ö');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', 'ĵ§i: ³o­Ó¤Þ¥Î»Ý­nºÞ²z­ûªº¼f®Ö¤~·|Åã¥Ü');
+@define('DELETE_TRACKBACK', '§R°£¤Þ¥Î');
+@define('APPROVE_TRACKBACK', '»{¥i¤Þ¥Î');
+@define('TRACKBACK_APPROVED', '¤Þ¥Î #%s ¤w¸g³q¹L¼f®Ö');
+@define('TRACKBACK_DELETED', '¤Þ¥Î #%s ¤w¸g¦¨¥\§R°£');
+@define('VIEW', 'ÂsÄý');
+@define('COMMENT_ALREADY_APPROVED', '°jÅT #%s ¤w¸g³q¹L¼f®Ö');
+@define('COMMENT_EDITED', '¤å³¹¤w³Q½s¿è');
+@define('HIDE', 'ÁôÂÃ');
+@define('VIEW_EXTENDED_ENTRY', 'Ä~Äò¾\Ū "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', '³o­Ó³sµ²¤£¬O¥Î¨ÓÂIªº. ¥¦¥]§t¤F³o­Ó¤å³¹ªº¤Þ¥Î URI. ±z¥i¥H±q±zªº¤é°O¤º¥Î³o­Ó URI ¨Ó¶Ç°e ping ©M¤Þ¥Î¨ì³o­Ó¤å³¹. ¦pªG­n½Æ»s³o­Ó³sµ², ¦b³sµ²¤WÂI¥kÁäµM«á¿ï¾Ü "½Æ»s³sµ²" (IE) ©Î "½Æ»s³sµ²¦ì§}" (Mozilla).');
+@define('PLUGIN_SUPERUSER_HTTPS', '¥Î https µn¤J');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'Åýµn¤J³sµ²³s¨ì https ºô§}. ±zªº¥D¾÷¥²¶·¤ä´©³o¶µ¥\¯à!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'Åý¥~¨Ó³sµ²¥H³sµ²Åã¥Ü?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"§_": ¥~¨Ó³sµ² (¥D­n¥X·½, ¥D­n¨Ó·½, °jÅT) ³£¤£·|¥H¤å¦rÅã¥Ü¥HÁ×§K google ¼s§i («ØÄ³¨Ï¥Î). "¬O": ¥~¨Ó³sµ²±N¥H¶W³sµ²ªº¤è¦¡Åã¥Ü. ¥i¥H¦b°¼¦C¥~±¾»\¹L¦¹³]©w!');
+@define('PAGE_BROWSE_COMMENTS', '­¶¼Æ %s ¦@ %s, Á`¦@ %s ­Ó°jÅT');
+@define('FILTERS', '¹LÂo');
+@define('FIND_ENTRIES', '·j´M¤å³¹');
+@define('FIND_COMMENTS', '·j´M°jÅT');
+@define('FIND_MEDIA', '·j´M´CÅé');
+@define('FILTER_DIRECTORY', '¥Ø¿ý');
+@define('SORT_BY', '±Æ§Ç');
+@define('TRACKBACK_COULD_NOT_CONNECT', '¨S¦³°e¥X¤Þ¥Î: µLªk¶}±Ò½u¸ô¨ì %s ¥Î³s±µ°ð %d');
+@define('MEDIA', '´CÅé');
+@define('MEDIA_LIBRARY', '´CÅé¦s®w');
+@define('ADD_MEDIA', '·s¼W´CÅé');
+@define('ENTER_MEDIA_URL', '½Ð¿é¤JÀɮתº URL:');
+@define('ENTER_MEDIA_UPLOAD', '½Ð¿ï¾Ü­n¤W¶ÇªºÀÉ®×:');
+@define('SAVE_FILE_AS', 'Àx¦sÀÉ®×:');
+@define('STORE_IN_DIRECTORY', 'Àx¦s¨ì¥H¤U¥Ø¿ý: ');
+@define('ADD_MEDIA_BLAHBLAH', '<b>·s¼WÀɮרì´CÅé¦s®w:</b><p>±z¥i¥H¦b³o¤W¶Ç´CÅéÀÉ, ©Î§i¶D¨t²Î¨ì­þ´M§ä! ¦pªG±z¨S¦³·Q­nªº¹Ï¤ù, ±z¥i¥H¨ì <a href="http://images.google.com" target="_blank">google´M§ä¹Ï¤ù</a>.<p><b>¿ï¾Ü¤è¦¡:</b><br>');
+@define('MEDIA_RENAME', '§ó§ïÀɮצWºÙ');
+@define('IMAGE_RESIZE', '§ó§ï¹Ï¤ù¤Ø¤o');
+@define('MEDIA_DELETE', '§R°£³o­ÓÀÉ®×');
+@define('FILES_PER_PAGE', '¨C­¶Åã¥ÜªºÀÉ®×¼Æ');
+@define('CLICK_FILE_TO_INSERT', 'ÂI¿ï±z­n¿é¤JªºÀÉ®×:');
+@define('SELECT_FILE', '¿ï¾Ü­n¿é¤JªºÀÉ®×');
+@define('MEDIA_FULLSIZE', '§¹¾ã¤Ø¤o');
+@define('CALENDAR_BOW_DESC', '¤@­Ó§«ôªº²Ä¤@¤Ñ. ¹w³]¬O¬P´Á¤@');
+@define('SUPERUSER', '¤é°OºÞ²z');
+@define('ALLOWS_YOU_BLAHBLAH', '¦b°¼¦C´£¨Ñ³sµ²¨ì¤é°OºÞ²z');
+@define('CALENDAR', '¤é¾ä');
+@define('SUPERUSER_OPEN_ADMIN', '¶}±ÒºÞ²z­¶­±');
+@define('SUPERUSER_OPEN_LOGIN', '¶}±Òµn¤J­¶­±');
+@define('INVERT_SELECTIONS', 'ÄA­Ë¤Ä¿ï');
+@define('COMMENTS_DELETE_CONFIRM', '½T©w­n§R°£¤Ä¿ïªº°jÅT¶Ü?');
+@define('COMMENT_DELETE_CONFIRM', '½T©w­n§R°£°jÅT #%d, µo§GªÌ¬O %s?');
+@define('DELETE_SELECTED_COMMENTS', '§R°£¤Ä¿ïªº°jÅT');
+@define('VIEW_COMMENT', 'ÂsÄý°jÅT');
+@define('VIEW_ENTRY', 'ÂsÄý¤å³¹');
+@define('DELETE_FILE_FAIL' , 'µLªk§R°£ÀÉ®× <b>%s</b>');
+@define('DELETE_THUMBNAIL', '§R°£¤F¹Ï¤ùÁY¹Ï <b>%s</b>');
+@define('DELETE_FILE', '§R°£¤FÀÉ®× <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', '±z±N§R°£ÀÉ®× <b>%s</b><br />¦pªG±z¦³¦b¨ä¥Lªº¤å³¹¤º¨Ï¥Î³o­ÓÀÉ®×, ¨º­Ó³sµ²©Î¹Ï¤ù±N·|µL®Ä<br />½T©w­nÄ~Äò¶Ü?<br /><br />');
+@define('TRACKBACK_SENDING', '¶Ç°e¤Þ¥Î¨ì URI %s...');
+@define('TRACKBACK_SENT', '¤Þ¥Î§¹¦¨');
+@define('TRACKBACK_FAILED', '¤Þ¥Î¿ù»~: %s');
+@define('TRACKBACK_NOT_FOUND', '§ä¤£¨ì¤Þ¥ÎªºURI.');
+@define('TRACKBACK_URI_MISMATCH', '¦Û°Ê·j´Mªº¤Þ¥Î¸ò¤Þ¥Î¥Ø¼Ð¤£¬Û¦P.');
+@define('TRACKBACK_CHECKING', '·j´M <u>%s</u> ªº¤Þ¥Î...');
+@define('TRACKBACK_NO_DATA', '¥Ø¼Ð¨S¦³¥ô¦ó¸ê®Æ');
+@define('TRACKBACK_SIZE', '¥Ø¼Ð URI ¶W¥X¤F¤¹³\ªº %s bytes Àɮפj¤p.');
+@define('COMMENTS_VIEWMODE_THREADED', '¤À½uµ{');
+@define('COMMENTS_VIEWMODE_LINEAR', 'ª½½uµ{');
+@define('DISPLAY_COMMENTS_AS', '°jÅTÅã¥Ü¤è¦¡');
+@define('COMMENTS_FILTER_SHOW', 'Åã¥Ü');
+@define('COMMENTS_FILTER_ALL', '¥þ³¡');
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'Åã¥Ü¼f®Ö°jÅT');
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'Åã¥Üµ¥«Ý¼f®Ö');
+@define('RSS_IMPORT_BODYONLY', '±N¿é¤Jªº¤å¦r©ñ¨ì¥D¤º®e, ±N¤£©î¶}¹Lªøªº¤å³¹¨ì°Æ¤º®e¦a°Ï.');
+@define('SYNDICATION_PLUGIN_FULLFEED', '¦b RSS feed ¸ÌÅã¥Ü¥þ³¡ªº¤å³¹');
+@define('WEEK', '¶g');
+@define('WEEKS', '¶g');
+@define('MONTHS', '¤ë');
+@define('DAYS', '¤é');
+@define('ARCHIVE_FREQUENCY', '«O¦s¤å®wªº¶µ¥ØÀW²v');
+@define('ARCHIVE_FREQUENCY_DESC', '«O¦s¤å®w¨Ï¥Îªº¶µ¥Ø²M³æ¶¡¹j');
+@define('ARCHIVE_COUNT', '«O¦s¤å®wªº¶µ¥Ø¼Æ');
+@define('ARCHIVE_COUNT_DESC', 'Åã¥Üªº¤ë, ¶g, ©Î¤é');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', '¤U­±¬O¦w¸Ë¦nªº¥~±¾');
+@define('SIDEBAR_PLUGIN', '°¼¦C¥~±¾');
+@define('EVENT_PLUGIN', '¨Æ¥ó¥~±¾');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'ÂI³o¸Ì¦w¸Ë·s %s');
+@define('VERSION', 'ª©¥»');
+@define('INSTALL', '¦w¸Ë');
+@define('ALREADY_INSTALLED', '¤w¸g¦w¸Ë');
+@define('SELECT_A_PLUGIN_TO_ADD', '½Ð¿ï¾Ü­n¦w¸Ëªº¥~±¾');
+@define('RSS_IMPORT_CATEGORY', '¥Î³o­ÓÃþ§Oµ¹¤£¬Û¦Pªº¿é¤J¤å³¹');
+
+@define('INSTALL_OFFSET', '¥D¾÷®É°Ï');
+@define('STICKY_POSTINGS', '³»¸m¤å³¹');
+@define('INSTALL_FETCHLIMIT', '¦b¥D­¶Åã¥Üªº¤å³¹');
+@define('INSTALL_FETCHLIMIT_DESC', '¥D­¶Åã¥Üªº¤å³¹¼Æ');
+@define('IMPORT_ENTRIES', '¿é¤J¸ê®Æ');
+@define('EXPORT_ENTRIES', '¿é¥X¸ê®Æ');
+@define('IMPORT_WELCOME', 'Åwªï¨Ó¨ì Serendipity ªº¿é¤J¤u¨ã');
+@define('IMPORT_WHAT_CAN', '¦b³o¸Ì±z¥i¥H¿é¤J¦b¨ä¥Lºô¸ô¤é°Oµ{¦¡¸Ìªº¤å³¹');
+@define('IMPORT_SELECT', '½Ð¿ï¾Ü¿é¤J¤å³¹ªº¤é°Oµ{¦¡');
+@define('IMPORT_PLEASE_ENTER', '½Ð¿é¤J¸ê®Æ');
+@define('IMPORT_NOW', '¶}©l¿é¤J!');
+@define('IMPORT_STARTING', '¶}©l¿é¤Jµ{§Ç...');
+@define('IMPORT_FAILED', '¿é¤J¥¢±Ñ');
+@define('IMPORT_DONE', '§¹¦¨¿é¤J');
+@define('IMPORT_WEBLOG_APP', '¤é°Oµ{¦¡');
+@define('EXPORT_FEED', '¿é¥X§¹¾ãªº RSS');
+@define('STATUS', '¿é¤J«áªºª¬ºA');
+@define('IMPORT_GENERIC_RSS', 'Generic RSS import');
+@define('ACTIVATE_AUTODISCOVERY', '¶Ç°e¦b¤å³¹¤º§ä¨ìªº¤Þ¥Î³sµ²');
+@define('WELCOME_TO_ADMIN', 'Åwªï¨ì Serendipity ºÞ²z¤¶­±.');
+@define('PLEASE_ENTER_CREDENTIALS', '½Ð¿é¤J±zªº¸ê®Æ.');
+@define('ADMIN_FOOTER_POWERED_BY', 'Powered by Serendipity %s and PHP %s');
+@define('INSTALL_USEGZIP', '¨Ï¥Î gzip À£ÁYºô­¶');
+@define('INSTALL_USEGZIP_DESC', '¬°¤F¯àÅýºô­¶§ó§Ö³tªºÅã¥Ü, §Ú­Ì·|±Nºô­¶À£ÁYµM«áÅã¥Ü³X«È, ¦pªG³X«È¨Ï¥ÎªºÂsÄý¾¹¤ä´©À£ÁYºô­¶. «ØÄ³¨Ï¥Î');
+@define('INSTALL_SHOWFUTURE', 'Åã¥Ü¥¼¨Ó¤å³¹');
+@define('INSTALL_SHOWFUTURE_DESC', '¦pªG¶}±Ò, ±zªº¤é°O±N·|Åã¥Ü©Ò¦³ªº¥¼¨Ó¤å³¹. ¹w³]ªº³]©w¬O±N¥¼¨Ó¤å³¹ÁôÂÃ, µM«áµo§G¤é´Á¨ì®É¦Û°ÊÅã¥Ü.');
+@define('INSTALL_DBPERSISTENT', '¨Ï¥Î«ùÄò³s½u');
+@define('INSTALL_DBPERSISTENT_DESC', '¹ï¸ê®Æ®w¨Ï¥Î«ùÄò³s½u, ¸Ô±¡½Ð¨ì <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">³o¸Ì</a>. ³q±`¨Ã¤£«ØÄ³¨Ï¥Î');
+@define('NO_IMAGES_FOUND', '§ä¤£¨ì¹Ï¤ù');
+@define('PERSONAL_SETTINGS', '­Ó¤H³]©w');
+@define('REFERER', '¨Ó·½');
+@define('NOT_FOUND', '§ä¤£¨ì');
+@define('NOT_WRITABLE', '¤£¥iŪ¼g');
+@define('WRITABLE', '¥iŪ¼g');
+@define('PROBLEM_DIAGNOSTIC', '¦]¬°¤W­±¥X²{ªº°ÝÃD, ±z¥²¶·±N¿ù»~¸Ñ¨M¤~¯àÄ~Äò¦w¸Ë');
+@define('SELECT_INSTALLATION_TYPE', '½Ð¿ï¾Ü¦w¸ËÃþ«¬');
+@define('WELCOME_TO_INSTALLATION', 'Åwªï¨ì Serendipity ¦w¸Ëµ{¦¡');
+@define('FIRST_WE_TAKE_A_LOOK', '­º¥ý¦w¸Ëµ{¦¡·|Àˬd±zªº¥D¾÷³]©w¥HÁ×§K¥X²{¿ù»~');
+@define('ERRORS_ARE_DISPLAYED_IN', '¿ù»~Åã¥Ü %s, «ØÄ³ %s §¹¦¨µL»~ %s');
+@define('RED', '¬õ');
+@define('YELLOW', '¶À');
+@define('GREEN', 'ºñ');
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s ¦w¸Ë«e³ø§i');
+@define('RECOMMENDED', '«ØÄ³');
+@define('ACTUAL', '¹ê»Ú');
+@define('PHPINI_CONFIGURATION', 'php.ini ³]©w');
+@define('PHP_INSTALLATION', 'PHP ¦w¸Ë');
+@define('THEY_DO', 'they do'); // translate
+@define('THEY_DONT', 'they don\'t'); // Translate
+@define('SIMPLE_INSTALLATION', '²³æ¦w¸Ë');
+@define('EXPERT_INSTALLATION', '±Mªù¦w¸Ë');
+@define('COMPLETE_INSTALLATION', '§¹¾ã¦w¸Ë');
+@define('WONT_INSTALL_DB_AGAIN', '¤£·|­«·s¦w¸Ë¸ê®Æ®w');
+@define('CHECK_DATABASE_EXISTS', 'Àˬd¬O§_¸ê®Æ®w©M¸ê®Æªí¤w¸g¦s¦b');
+@define('CREATING_PRIMARY_AUTHOR', '«Ø¥ß¥D­n§@ªÌ \'%s\'');
+@define('SETTING_DEFAULT_TEMPLATE', '³]©w¹w³]§G´º');
+@define('INSTALLING_DEFAULT_PLUGINS', '¦w¸Ë¹w³]¥~±¾');
+@define('SERENDIPITY_INSTALLED', 'Serendipity ¤w§¹¦¨¦w¸Ë');
+@define('VISIT_BLOG_HERE', '°ÑÆ[±zªººô¸ô¤é°O');
+@define('THANK_YOU_FOR_CHOOSING', '·PÁ±z¿ï¾Ü Serendipity');
+@define('ERROR_DETECTED_IN_INSTALL', '¦w¸Ë®Éµo¥Í¿ù»~');
+@define('OPERATING_SYSTEM', '§@·~¨t²Î');
+@define('WEBSERVER_SAPI', '¥D¾÷ SAPI');
+@define('TEMPLATE_SET', '\'%s\' ¤w³Q³]©w¬°±zªº¥D­n§G´º');
+@define('SEARCH_ERROR', '·j´M¥\¯àµo¥Í¿ù»~. §iª¾ºÞ²z­û: µo¥Í³o­Ó¿ù»~¥i¯à¦]¬°¸ê®Æ®w¨S¦³¥¿½Tªº index keys. ¦pªG¨Ï¥Î MySQL, ±zªº±b¸¹¥²¶·¦³¥i°õ¦æ: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> ªºÅv­­. ¸ê®Æ®wÅã¥Üªº¿ù»~¬O: <pre>%s</pre>');
+@define('EDIT_THIS_CAT', '½s¿è "%s"');
+@define('CATEGORY_REMAINING', '§R°£³o­ÓÃþ§OµM«á±N¸Ì­±ªº¤å³¹²¾¨ì³o­ÓÃþ§O');
+@define('CATEGORY_INDEX', '¤U­±¬O¥i²¾°Ê¨ìªºÃþ§O');
+@define('NO_CATEGORIES', '¨S¦³Ãþ§O');
+@define('RESET_DATE', '­«³]¤é´Á');
+@define('RESET_DATE_DESC', 'ÂI³o¸Ì­«³]¤é´Á');
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Åv­­¥i¥H¥Î¤U­±ªº Shell ©R¥O¨Ó°õ¦æ: `<em>%s</em>` µM«á°õ¦æ¦b­n§ïÅv­­ªºÀÉ®×§¨¡A©Î¥Î FTP ³nÅé');
+@define('WARNING_TEMPLATE_DEPRECATED', 'ĵ§i: ±z¥Ø«e¨Ï¥Îªº§G´º¬O¥Îªº¤èªk»s§@¡A½ÐºÉ§Ö§ó·s');
+@define('ENTRY_PUBLISHED_FUTURE', '³o½g¤å³¹ÁÙ¥¼¤½¶}¡C');
+@define('ENTRIES_BY', '§@ªÌ %s');
+@define('PREVIOUS', '¤W¤@­¶');
+@define('NEXT', '¤U¤@­¶');
+@define('APPROVE', '»{¥i');
+@define('DO_MARKUP_DESCRIPTION', '®M¥Î¦Û°Ê®æ¦¡¤Æ¨ì¤å³¹¤º (ªí±¡¹Ï®×, ²Å¸¹ *, /, _, ...)¡CÃö³¬³o¶µ¥\¯à±N·|«O¦s¥ô¦ó¤å³¹¤º¥X²{ªº HTML ½X¡C');
+@define('CATEGORY_ALREADY_EXIST', 'Ãþ§O "%s" ¤w¸g¦s¦b');
+@define('IMPORT_NOTES', 'ª`·N:');
+@define('ERROR_FILE_FORBIDDEN', '±z¤£¯à¤W¶Ç¦¹ÃþÀÉ®×');
+@define('ADMIN', 'ºÞ²z¤¶­±');
+@define('ADMIN_FRONTPAGE', 'ºÞ²z­º­¶');
+@define('QUOTE', '¤Þ¨¥');
+@define('IFRAME_SAVE', 'Serendipity ¥¿¦bÀx¦s±zªº¤å³¹¡A«Ø¥ß¤Þ¥Î©M°õ¦æ XML-RPC calls¡A½Ðµy«Ý..');
+@define('IFRAME_SAVE_DRAFT', '¤å³¹¯ó½Z¤w³QÀx¦s');
+@define('IFRAME_PREVIEW', 'Serendipity ¥¿¦b«Ø¥ß±zªº¹wÄý¤å³¹...');
+@define('IFRAME_WARNING', '±zªºÂsÄý¾¹¤£¤ä´© iframes. ½Ð¥´¶} serendipity_config.inc.php ÀÉ®×µM«á³]©w $serendipity[\'use_iframe\'] ÅܼƦܠFALSE.');
+@define('NONE', '¨S¦³');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', '·s¤å³¹±N¨Ï¥Î¹w³]³]©w');
+@define('UPGRADE', '§ó·s');
+@define('UPGRADE_TO_VERSION', '§ó·s¦Üª©¥» %s');
+@define('DELETE_DIRECTORY', '§R°£¥Ø¿ý');
+@define('DELETE_DIRECTORY_DESC', '±z±N§R°£¥Ø¿ý¤ºªº´CÅéÀɮסAª`·NÀɮפ]³\¥X²{¦b¨ä¥L¤å³¹¤º¡C');
+@define('FORCE_DELETE', '§R°£¦¹¥Ø¿ý¤ºªºÀɮסA¥]¬A Serendipity µLªkÃѧOªºÀÉ®×');
+@define('CREATE_DIRECTORY', '«Ø¥ß¥Ø¿ý');
+@define('CREATE_NEW_DIRECTORY', '«Ø¥ß·s¥Ø¿ý');
+@define('CREATE_DIRECTORY_DESC', '¦b³o¸Ì±z¥i¥H«Ø¥ß·sªº¥Ø¿ý¨Ó¦s©ñ´CÅéÀɮסC¿é¤J¥Ø¿ý¦WºÙµM«á±z¥i¥H¿ï¾Ü¬O§_±N¥¦©ñ¨ì¥À¥Ø¿ý¤º¡C');
+@define('BASE_DIRECTORY', '°ò¥»¥Ø¿ý');
+@define('USERLEVEL_EDITOR_DESC', '¤@¯ë§@ªÌ');
+@define('USERLEVEL_CHIEF_DESC', '¥D½s');
+@define('USERLEVEL_ADMIN_DESC', 'ºÞ²z­û');
+@define('USERCONF_USERLEVEL', 'Åv­­');
+@define('USERCONF_USERLEVEL_DESC', '³o­Ó¿ï¶µ¥i¥H³]©w¦¹§@ªÌ¦b³o­Óºô»x¤ºªºÅv­­');
+@define('USER_SELF_INFO', 'µn¤J§@ªÌ¬O %s (%s)');
+@define('ADMIN_ENTRIES', '¤å³¹');
+@define('RECHECK_INSTALLATION', '­«·sÀˬd¦w¸Ëµ{§Ç');
+@define('IMAGICK_EXEC_ERROR', 'µLªk°õ¦æ: "%s", ¿ù»~: %s, ¶Ç¦^ÅܼÆ: %d');
+@define('INSTALL_OFFSET_DESC', '¥H¤p®É­pºâ¡A½Ð¿é¤J¥D¾÷ªº®É¶¡ (current: %clock%) ¸ò±zªº®É°Ïªº®É®t');
+@define('UNMET_REQUIREMENTS', '¥¼¹F¨ì»Ý¨D: %s');
+@define('CHARSET', '½s½X');
+@define('AUTOLANG', '¨Ï¥ÎŪªÌªºÂsÄý¾¹¤º³]©wªº»y¨t');
+@define('AUTOLANG_DESC', '¦pªG¶}±Ò¡A³o­Ó¥\¯à±N¨Ï¥ÎŪªÌªºÂsÄý¾¹¤º©Ò³]©wªº»y¨t¡C');
+@define('INSTALL_AUTODETECT_URL', '¦Û°Ê°»´ú HTTP-Host');
+@define('INSTALL_AUTODETECT_URL_DESC', '¦pªG³]©w¬° "true"¡ASerendipity ·|½T©wŪªÌªº HTTP Host ¸ò±zªº°ò¥» URL ³]©w¬Û¦P¡C¶}±Ò³o¶µ¥\¯à¥i¥H¤¹³\±z¨Ï¥Î¦h¼Æªººô°ì¦WºÙµ¹±zªººô»x¡A©M¨Ï¥Î³o­Óºô°ìµ¹¸ò¶iªº³sµ²¡C');
+@define('CONVERT_HTMLENTITIES', '¦Û°Ê§ïÅÜ HTML entities?');
+@define('EMPTY_SETTING', '±z¨S¦³´£¨Ñ "%s" ªº¥¿½T­È!');
+@define('USERCONF_REALNAME', '¥þ¦W');
+@define('USERCONF_REALNAME_DESC', '§@ªÌªº¥þ¦W¡A±NÅã¥Üµ¹¥þ³¡ÅªªÌ');
+@define('HOTLINK_DONE', 'ÀÉ®×µs³s<br />µ²§ô¡C');
+@define('ENTER_MEDIA_URL_METHOD', '¨ú±o¤èªk:');
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'ª`·N: ¦pªG±z¿ï¾Üµs³s¤èªk¡A½Ð¥ý±o¨ì¨Ó·½ºô¯¸ªº¤¹³\¡Cµs³s¤¹³\±z¥Î¨ä¥Lºô¯¸ªº¹Ï¤ù¦Ó¤£»Ý±N¹Ï¤ùÀx¦s¦b±zªº¥D¾÷¤º¡C');
+@define('MEDIA_HOTLINKED', 'µs³s¹Ï¤ù');
+@define('FETCH_METHOD_IMAGE', '¤U¸ü¹Ï¤ù¨ì¥D¾÷');
+@define('FETCH_METHOD_HOTLINK', 'µs³s¨ì¥D¾÷');
+@define('DELETE_HOTLINK_FILE', '§R°£µs³sªºÀÉ®× <b>%s</b>');
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Åã¥Ü¹q¤l¶l¥ó¶Ü?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/lang/serendipity_lang_zh.inc.php b/lang/serendipity_lang_zh.inc.php
new file mode 100644 (file)
index 0000000..54b6fed
--- /dev/null
@@ -0,0 +1,669 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+@define('LANG_CHARSET', 'gb2312');
+@define('DATE_LOCALES', 'cn, zh, zh_CN.GB2312, zh_GB, zh_CN');
+@define('DATE_FORMAT_ENTRY', '%A, %B %e. %Y');
+@define('DATE_FORMAT_SHORT', '%Y-%m-%d %H:%M');
+@define('WYSIWYG_LANG', 'en');
+@define('NUMBER_FORMAT_DECIMALS', '2');
+@define('NUMBER_FORMAT_DECPOINT', '.');
+@define('NUMBER_FORMAT_THOUSANDS', ',');
+@define('LANG_DIRECTION', 'ltr');
+
+@define('SERENDIPITY_ADMIN_SUITE', 'Serendipity ¹ÜÀíÌ×¼þ');
+@define('HAVE_TO_BE_LOGGED_ON', 'ÇëÏȵÇÈë');
+@define('WRONG_USERNAME_OR_PASSWORD', 'ÄúÊäÈëÁË´íÎóµÄÕʺŻòÃÜÂë');
+@define('APPEARANCE', 'Íâ¹ÛÅäÖÃ');
+@define('MANAGE_STYLES', '²¼¾°¹ÜÀí');
+@define('CONFIGURE_PLUGINS', 'É趨Íâ¹Ò');
+@define('CONFIGURATION', '¹ÜÀíÉ趨');
+@define('BACK_TO_BLOG', '»Øµ½ÈÕ¼ÇÊ×Ò³');
+@define('LOGIN', 'µÇÈë');
+@define('LOGOUT', 'µÇ³ö');
+@define('LOGGEDOUT', 'µÇ³ö.');
+@define('CREATE', '½¨Á¢');
+@define('SAVE', '´¢´æ');
+@define('NAME', 'Ãû³Æ');
+@define('CREATE_NEW_CAT', 'ÐÂÔöÀà±ð');
+@define('I_WANT_THUMB', 'ÎÒÒªÔÚÎÄÕÂÄÚʹÓÃËõͼ.');
+@define('I_WANT_BIG_IMAGE', 'ÎÒÒªÔÚÎÄÕÂÄÚʹÓôóÐÍͼƬ.');
+@define('I_WANT_NO_LINK', ' ÎÒÒªËüÒÔͼƬÏÔʾ');
+@define('I_WANT_IT_TO_LINK', 'ÎÒÒªËüÒÔÁ¬½áÏÔʾÕâ¸ö URL:');
+@define('BACK', '·µ»Ø');
+@define('FORWARD', 'ǰ½ø');
+@define('ANONYMOUS', 'ÄäÃû');
+@define('NEW_TRACKBACK_TO', 'еÄÒýÓõ½');
+@define('NEW_COMMENT_TO', 'ÐµĻØÏìµ½');
+@define('RECENT', 'ÐÂÎÄ¿â...');
+@define('OLDER', '¾ÉÎÄ¿â...');
+@define('DONE', 'Íê³É');
+@define('WELCOME_BACK', '»¶Ó­»ØÀ´,');
+@define('TITLE', '±êÌâ');
+@define('DESCRIPTION', '¼ò½é');
+@define('PLACEMENT', 'λַ');
+@define('DELETE', 'ɾ³ý');
+@define('SAVE', '´¢´æ');
+@define('UP', 'ÉÏ');
+@define('DOWN', 'ÏÂ');
+@define('ENTRIES', 'ÎÄÕÂ');
+@define('NEW_ENTRY', 'ÐÂÔöÎÄÕÂ');
+@define('EDIT_ENTRIES', '±à¼­ÎÄÕÂ');
+@define('CATEGORIES', 'Àà±ð');
+@define('WARNING_THIS_BLAHBLAH', "¾¯¸æ:\\nÕâ¸ö¿ÉÄÜÐèÒª³¤Ê±¼äÈç¹ûÓкܶ಻ÊÇËõͼµÄͼƬ.");
+@define('CREATE_THUMBS', 'ÖØ½¨Ëõͼ');
+@define('MANAGE_IMAGES', '¹ÜÀíͼƬ');
+@define('NAME', 'Ãû³Æ');
+@define('EMAIL', 'Email');
+@define('HOMEPAGE', 'ÍøÖ·');
+@define('COMMENT', '»ØÏì');
+@define('REMEMBER_INFO', '¼Çס×ÊÁÏ? ');
+@define('SUBMIT_COMMENT', '´«ËÍ»ØÏì');
+@define('NO_ENTRIES_TO_PRINT', 'ûÓÐÎÄÕ¿ÉÒÔÏÔʾ');
+@define('COMMENTS', '»ØÏì');
+@define('ADD_COMMENT', 'ÐÂÔö»ØÏì');
+@define('NO_COMMENTS', 'ûÓлØÏì');
+@define('POSTED_BY', '×÷Õß');
+@define('ON', 'ÔÚ');
+@define('A_NEW_COMMENT_BLAHBLAH', 'лØÏìÒÑ·¢±íµ½ÄúµÄÈռǠ"%s", ÔÚÕâ¸öÎÄÕÂÀïÃæ "%s".');
+@define('A_NEW_TRACKBACK_BLAHBLAH', 'ÄúµÄÈÕ¼ÇÎÄÕ "%s" ÒÑÓÐÁËеÄÒýÓÃ.');
+@define('NO_CATEGORY', 'ûÓÐÀà±ð');
+@define('ENTRY_BODY', 'ÎÄÕÂÖ÷ÄÚÈÝ');
+@define('EXTENDED_BODY', 'ÎÄÕ¸±ÄÚÈÝ');
+@define('CATEGORY', 'Àà±ð');
+@define('EDIT', '±à¼­');
+@define('NO_ENTRIES_BLAHBLAH', 'ÕÒ²»µ½´Ë²éѯ %s µÄÎÄÕÂ' . "\n");
+@define('YOUR_SEARCH_RETURNED_BLAHBLAH', 'ÄúËÑѰµÄ %s ÏÔʾÁË %s ½á¹û:');
+@define('SEARCH_TOO_SHORT', 'ÄúËÑѰµÄÎÄ×Ö±ØÐë¶àì¶ 3 ¸ö×Ö´Ê');
+@define('IMAGE', 'ͼƬ');
+@define('ERROR_FILE_NOT_EXISTS', '´íÎó: µµ°¸²»´æÔÚ!');
+@define('ERROR_FILE_EXISTS', '´íÎó: µµ°¸Ãû³ÆÒѱ»Ê¹ÓÃ, ÇëÖØÐÂÊäÈë!');
+@define('ERROR_SOMETHING', '´íÎó: ÓдíÎó.');
+@define('ADDING_IMAGE', 'ÐÂÔöͼƬ...');
+@define('THUMB_CREATED_DONE', 'Ëõͼ½¨Á¢.<br>Íê³É.');
+@define('ERROR_FILE_EXISTS_ALREADY', '´íÎó: µµ°¸ÒÑ´æÔÚ!');
+@define('ERROR_UNKNOWN_NOUPLOAD', 'δ֪µÄ´íÎó·¢Éú, µµ°¸»¹Ã»ÉÏ´«. Ò²ÐíÄãµÄµµ°¸´óì¶ÏÞÖÆµÄ´óС. ÇëѯÎÊÄúµÄ ISP »òÐÞ¸ÄÄúµÄ php.ini µµ.');
+@define('GO', '¼ÌÐø!');
+@define('NEWSIZE', 'дóС: ');
+@define('RESIZE_BLAHBLAH', '<b>ÖØÉè´óС %s</b><p>');
+@define('ORIGINAL_SIZE', 'Ô­ÓеĴóС: <i>%sx%s</i> ÏñËØ');
+@define('HERE_YOU_CAN_ENTER_BLAHBLAH', '<p>ÔÚÕâÀïÄú¿ÉÒÔÐÞ¸ÄͼƬ´óС. Èç¹ûÄúÒªÐ޸ijÉÏàͬµÄͼƬ±ÈÀý, ÄúÖ»ÐèÒªÊäÈëÒ»¸öÊýֵȻºó°´ TAB -- ÏµÍ³»á×Ô¶¯°ïÄú¼ÆËã±ÈÀýÒÔÃâ³ö´í</p>');
+@define('QUICKJUMP_CALENDAR', 'ÈÕÀú¿ìËÙÌøÔ¾');
+@define('QUICKSEARCH', '¿ìËÙËÑѰ');
+@define('SEARCH_FOR_ENTRY', 'ËÑѰÎÄÕÂ');
+@define('ARCHIVES', '±£´æÎÄ¿â');
+@define('BROWSE_ARCHIVES', 'ÒÔÔ·Ýä¯ÀÀ±£´æÎÄ¿â');
+@define('TOP_REFERRER', 'Ö÷ÒªÀ´Ô´');
+@define('SHOWS_TOP_SITES', 'ÏÔʾÁ¬½áµ½ÄúµÄÈռǵÄÍøÕ¾');
+@define('TOP_EXITS', 'Ö÷Òª³öÔ´');
+@define('SHOWS_TOP_EXIT', 'ÏÔʾÄúµÄÈռǵÄÖ÷Òª³öÔ´');
+@define('SYNDICATION', 'ÎÄÕÂͬ²½');
+@define('SHOWS_RSS_BLAHBLAH', 'ÏÔʾ RSS Í¬²½Á¬½á');
+@define('ADVERTISES_BLAHBLAH', 'Ðû´«ÄúµÄÍøÂ·ÈÕ¼Ç');
+@define('HTML_NUGGET', 'HTML ѶϢ');
+@define('HOLDS_A_BLAHBLAH', 'ÏÔʾ HTML Ñ¶Ï¢µ½²àÁÐ');
+@define('TITLE_FOR_NUGGET', 'ѶϢµÄ±êÌâ');
+@define('THE_NUGGET', 'HTML ѶϢ!');
+@define('SYNDICATE_THIS_BLOG', 'ͬ²½Õâ¸öÈÕ¼Ç');
+@define('YOU_CHOSE', 'ÄúÑ¡Ôñ %s');
+@define('IMAGE_SIZE', 'ͼƬ´óС');
+@define('IMAGE_AS_A_LINK', 'ÊäÈëͼƬ');
+@define('POWERED_BY', 'Powered by');
+@define('TRACKBACKS', 'ÒýÓÃ');
+@define('TRACKBACK', 'ÒýÓÃ');
+@define('NO_TRACKBACKS', 'ûÓÐÒýÓÃ');
+@define('TOPICS_OF', 'Ö÷Ìâ');
+@define('VIEW_FULL', 'ä¯ÀÀÈ«²¿');
+@define('VIEW_TOPICS', 'ä¯ÀÀÖ÷Ìâ');
+@define('AT', 'ÔÚ');
+@define('SET_AS_TEMPLATE', 'ʹÓò¼¾°');
+@define('IN', 'ÔÚ');
+@define('EXCERPT', 'ժҪ');
+@define('TRACKED', 'ÒýÓÃ');
+@define('LINK_TO_ENTRY', 'Á¬½áµ½ÎÄÕÂ');
+@define('LINK_TO_REMOTE_ENTRY', 'Á¬½áµ½Ô¶¶ËÎÄÕÂ');
+@define('IP_ADDRESS', 'IP λַ');
+@define('USER', '×÷Õß');
+@define('THUMBNAIL_USING_OWN', 'ʹÓà%s µ±ËüµÄËõͼ³ß´çÒòΪͼƬÒѾ­ºÜСÁË.');
+@define('THUMBNAIL_FAILED_COPY', 'ʹÓà%s µ±ËüµÄËõͼ, µ«ÊÇÎÞ·¨¸´ÖÆ!');
+@define('AUTHOR', '·¢±íÕß');
+@define('LAST_UPDATED', '×îºó¸üÐÂ');
+@define('TRACKBACK_SPECIFIC', 'ÒýÓôËÎÄÕÂÌØ¶¨µÄ URI (ÍøÖ·)');
+@define('DIRECT_LINK', 'Ö±½ÓµÄÎÄÕÂÁ¬½á');
+@define('COMMENT_ADDED', 'ÄúµÄ»ØÏìÒѳɹ¦ÔöÈë. ');
+@define('COMMENT_ADDED_CLICK', 'µã %sÕâÀï·µ»Ø%s µ½»ØÏì, ºÍµã %sÕâÀï¹Ø±Õ%s Õâ¸öÊÓ´°.');
+@define('COMMENT_NOT_ADDED', 'ÄúµÄ»ØÏì²»ÄÜÔöÈëÒòΪ´ËƪÎÄÕ²»ÔÊÐí»ØÏì. ');
+@define('COMMENT_NOT_ADDED_CLICK', 'µã %sÕâÀï·µ»Ø%s µ½»ØÏì, ºÍµã %sÕâÀï¹Ø±Õ%s Õâ¸öÊÓ´°.');
+@define('COMMENTS_DISABLE', '²»ÔÊÐí»ØÏìµ½ÕâÆªÎÄÕÂ');
+@define('COMMENTS_ENABLE', 'ÔÊÐí»ØÏìµ½ÕâÆªÎÄÕÂ');
+@define('COMMENTS_CLOSED', '×÷Õß²»ÔÊÐí»ØÏìµ½ÕâÆªÎÄÕÂ');
+@define('EMPTY_COMMENT', 'ÄúµÄ»ØÏìûÓÐÈκÎѶϢ, Çë %s·µ»Ø%s ÖØÊÔ');
+@define('ENTRIES_FOR', 'ÎÄÕ¸ø %s');
+@define('DOCUMENT_NOT_FOUND', 'ÕÒ²»µ½´ËƪÎļþ %s.');
+@define('USERNAME', 'ÕʺÅ');
+@define('PASSWORD', 'ÃÜÂë');
+@define('AUTOMATIC_LOGIN', '×Ô¶¯µÇÈë');
+@define('SERENDIPITY_INSTALLATION', 'Serendipity °²×°³Ìʽ');
+@define('LEFT', '×ó');
+@define('RIGHT', 'ÓÒ');
+@define('HIDDEN', 'Òþ²Ø');
+@define('REMOVE_TICKED_PLUGINS', 'ÒÆ³ý¹´Ñ¡µÄÍâ¹Ò');
+@define('SAVE_CHANGES_TO_LAYOUT', '´¢´æÍâ¹ÛÅäÖÃ');
+@define('COMMENTS_FROM', '»ØÏìÀ´Ô´');
+@define('ERROR', '´íÎó');
+@define('ENTRY_SAVED', 'ÄúµÄÎÄÕÂÒÑ´¢´æ');
+@define('DELETE_SURE', 'È·¶¨ÒªÉ¾³ý #%s Âð?');
+@define('NOT_REALLY', 'ËãÁË...');
+@define('DUMP_IT', 'ɾ³ý°É!');
+@define('RIP_ENTRY', 'R.I.P. ÎÄÕ #%s');
+@define('CATEGORY_DELETED_ARTICLES_MOVED', 'Àà±ð #%s ÒÑɾ³ý. ¾ÉÎÄÕÂÒѱ»Òƶ¯µ½Àà±ð #%s');
+@define('CATEGORY_DELETED', 'Àà±ð #%s ÒÑɾ³ý.');
+@define('INVALID_CATEGORY', 'ûÓÐÌṩɾ³ýµÄÀà±ð');
+@define('CATEGORY_SAVED', 'Àà±ðÒÑ´¢´æ');
+@define('SELECT_TEMPLATE', 'ÇëÑ¡ÔñÍøÂ·ÈռǵIJ¼¾°');
+@define('ENTRIES_NOT_SUCCESSFULLY_INSERTED', 'ûÓÐÍê³ÉÔöÈëÎÄÕÂ!');
+@define('MT_DATA_FILE', 'Movable Type ×ÊÁϵµ');
+@define('FORCE', 'Ç¿ÖÆ');
+@define('CREATE_AUTHOR', 'ÐÂÔö×÷Õß \'%s\'.');
+@define('CREATE_CATEGORY', 'ÐÂÔöÀà±ð \'%s\'.');
+@define('MYSQL_REQUIRED', 'Äú±ØÐëÒªÓРMySQL µÄÀ©³ä¹¦ÄܲÅÄÜÖ´ÐÐÕâ¸ö¶¯×÷.');
+@define('COULDNT_CONNECT', '²»ÄÜÁª½áµ½ MySQL ×ÊÁÏ¿â: %s.');
+@define('COULDNT_SELECT_DB', '²»ÄÜÑ¡Ôñ×ÊÁÏ¿â: %s.');
+@define('COULDNT_SELECT_USER_INFO', '²»ÄÜÑ¡ÔñʹÓÃÕßµÄ×ÊÁÏ: %s.');
+@define('COULDNT_SELECT_CATEGORY_INFO', '²»ÄÜÑ¡ÔñÀà±ðµÄ×ÊÁÏ: %s.');
+@define('COULDNT_SELECT_ENTRY_INFO', '²»ÄÜÑ¡ÔñÎÄÕµÄ×ÊÁÏ: %s.');
+@define('COULDNT_SELECT_COMMENT_INFO', '²»ÄÜÑ¡Ôñ»ØÏìµÄ×ÊÁÏ: %s.');
+@define('YES', 'ÊÇ');
+@define('NO', '·ñ');
+@define('USE_DEFAULT', 'Ô¤Éè');
+@define('CHECK_N_SAVE', '´¢´æ');
+@define('DIRECTORY_WRITE_ERROR', '²»ÄܶÁдµµ°¸¼Ð %s. Çë¼ì²éȨÏÞ.');
+@define('DIRECTORY_CREATE_ERROR', 'µµ°¸¼Ð %s ²»´æÔÚÒ²ÎÞ·¨½¨Á¢. Çë×Ô¼º½¨Á¢Õâ¸öµµ°¸¼Ð');
+@define('DIRECTORY_RUN_CMD', '&nbsp;-&gt; run <i>%s %s</i>');
+@define('CANT_EXECUTE_BINARY', 'ÎÞ·¨Ö´ÐР%s ×ÊÔ´µµ°¸');
+@define('FILE_WRITE_ERROR', 'ÎÞ·¨¶Áдµµ°¸ %s.');
+@define('FILE_CREATE_YOURSELF', 'Çë×Ô¼º½¨Á¢Õâ¸öµµ°¸»ò¼ì²éȨÏÞ');
+@define('COPY_CODE_BELOW', '<br />* Çë¸´ÖÆÏÂÃæµÄ´úÂëÈ»ºó·ÅÈë %s µ½ÄúµÄ %s µµ°¸¼Ð:<b><pre>%s</pre></b>' . "\n");
+@define('WWW_USER', 'Çë¸Ä±ä www µ½Ê¹ÓÃÕߵĠApache (i.e. nobody).');
+@define('BROWSER_RELOAD', 'Íê³ÉÖ®ºó, ÖØÐÂË¢ÐÂÄúµÄä¯ÀÀÆ÷.');
+@define('DIAGNOSTIC_ERROR', 'ϵͳÕì²âµ½Ò»Ð©´íÎó:');
+@define('SERENDIPITY_NOT_INSTALLED', 'Serendipity »¹Ã»°²×°Íê³É. Çë°´ <a href="%s">°²×°</a>.');
+@define('INCLUDE_ERROR', 'serendipity ´íÎó: ÎÞ·¨°üÀ¨ %s - Í˳ö.');
+@define('DATABASE_ERROR', 'serendipity ´íÎó: ÎÞ·¨Á¬½áµ½×ÊÁÏ¿â - Í˳ö.');
+@define('CHECK_DATABASE_EXISTS', '¼ì²é×ÊÁÏ¿âÊÇ·ñ´æÔÚ. Èç¹ûÄú¿´µ½×ÊÁÏ¿â²éѯ´íÎó, Çë²»ÓùÜËü...');
+@define('CREATE_DATABASE', '½¨Á¢Ô¤Éè×ÊÁÏ¿âÉ趨...');
+@define('ATTEMPT_WRITE_FILE', '¶Áд %s µµ°¸...');
+@define('SERENDIPITY_INSTALLED', '%sSerendipity ÒѰ²×°Íê³É.%s Çë¼ÇµÃÄúµÄÃÜÂë: "%s", ÄúµÄÕʺÅÊÇ "%s".%sÄúÏÖÔÚ¿ÉÒÔµ½Ð½¨Á¢µÄ <a href="%s">ÍøÂ·ÈÕ¼Ç</a>');
+@define('WRITTEN_N_SAVED', '´¢´æÍê±Ï');
+@define('IMAGE_ALIGNMENT', 'ͼƬ¶ÔÆë');
+@define('ENTER_NEW_NAME', 'ÊäÈëÐÂÃû³Æ¸ø: ');
+@define('RESIZING', 'ÖØÉè´óС');
+@define('RESIZE_DONE', 'Íê³É (ÖØÉè %s ¸öͼƬ).');
+@define('SYNCING', '½øÐÐ×ÊÁÏ¿âºÍͼƬµµ°¸¼Ðͬ²½»¯');
+@define('SYNC_DONE', 'Íê³É (ͬ²½ÁË %s ¸öͼƬ).');
+@define('FILE_NOT_FOUND', 'ÕÒ²»µ½µµ°¸Ãû³Æ <b>%s</b>, Ò²ÐíÒѾ­±»É¾³ýÁË?');
+@define('ABORT_NOW', '·ÅÆú');
+@define('REMOTE_FILE_NOT_FOUND', 'µµ°¸²»ÔÚÔ¶¶ËÖ÷»úÄÚ, ÄúÈ·¶¨Õâ¸ö URL: <b>%s</b> ÊÇÕýÈ·µÄÂð?');
+@define('FILE_FETCHED', '%s È¡»ØÎª %s');
+@define('FILE_UPLOADED', 'µµ°¸ %s ÉÏ´«Îª %s');
+@define('WORD_OR', '»ò');
+@define('SCALING_IMAGE', 'Ëõ·Å %s µ½ %s x %s px');
+@define('KEEP_PROPORTIONS', 'ά³Ö±ÈÀý');
+@define('REALLY_SCALE_IMAGE', 'È·¶¨ÒªËõ·ÅͼƬÂð? Õâ¸ö¶¯×÷²»Äܸ´Ô­!');
+@define('TOGGLE_ALL', 'Çл»Õ¹¿ª');
+@define('TOGGLE_OPTION', 'Çл»Ñ¡Ïî');
+@define('SUBSCRIBE_TO_THIS_ENTRY', '¶©ÔÄÕâÆªÎÄÕÂ');
+@define('UNSUBSCRIBE_OK', "%s ÒÑÈ¡Ïû¶©ÔÄÕâÆªÎÄÕÂ");
+@define('NEW_COMMENT_TO_SUBSCRIBED_ENTRY', 'лØÏìµ½¶©ÔĵÄÎÄÕ "%s"');
+@define('SUBSCRIPTION_MAIL', "ÄúºÃ %s,\n\nÄú¶©ÔĵÄÎÄÕÂÓÐÁËÐµĻØÏìÔÚ \"%s\", ±êÌâÊÇ \"%s\"\n»ØÏìµÄ·¢±íÕßÊÇ: %s\n\nÄú¿ÉÒÔÔÚÕâÕÒµ½´ËÎÄÕÂ: %s\n\nÄú¿ÉÒÔµãÕâ¸öÁ¬½áÈ¡Ïû¶©ÔÄ: %s\n");
+@define('SUBSCRIPTION_TRACKBACK_MAIL', "ÄúºÃ %s,\n\nÄú¶©ÔĵÄÎÄÕÂÓÐÁËеÄÒýÓÃÔÚ \"%s\", ±êÌâÊÇ \"%s\"\nÒýÓõÄ×÷ÕßÊÇ: %s\n\nÄú¿ÉÒÔÔÚÕâÕÒµ½´ËÎÄÕÂ: %s\n\nÄú¿ÉÒÔµãÕâ¸öÁ¬½áÈ¡Ïû¶©ÔÄ: %s\n");
+@define('SIGNATURE', "\n-- \n%s is powered by Serendipity.\nThe best blog around, you can use it too.\nCheck out <http://s9y.org> to find out how.");
+@define('SYNDICATION_PLUGIN_091', 'RSS 0.91 feed');
+@define('SYNDICATION_PLUGIN_10', 'RSS 1.0 feed');
+@define('SYNDICATION_PLUGIN_20', 'RSS 2.0 feed');
+@define('SYNDICATION_PLUGIN_20c', 'RSS 2.0 comments');
+@define('SYNDICATION_PLUGIN_ATOM03', 'ATOM 0.3 feed');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR', 'À¸Î» "managingEditor"');
+@define('SYNDICATION_PLUGIN_WEBMASTER',  'À¸Î» "webMaster"');
+@define('SYNDICATION_PLUGIN_BANNERURL', 'RSS feed µÄͼƬ');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH', 'ͼƬ¿í¶È');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT', 'ͼƬ¸ß¶È');
+@define('SYNDICATION_PLUGIN_WEBMASTER_DESC',  '¹ÜÀíÔ±µÄµç×ÓÓʼþ, Èç¹ûÓÐ. (¿Õ°×: Òþ²Ø) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_MANAGINGEDITOR_DESC', '×÷Õߵĵç×ÓÓʼþ, Èç¹ûÓÐ. (¿Õ°×: Òþ²Ø) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_BANNERURL_DESC', 'ͼƬµÄλַ URL, ÒÔ GIF/JPEG/PNG ¸ñʽ, Èç¹ûÓÐ. (¿Õ°×: serendipity-logo)');
+@define('SYNDICATION_PLUGIN_BANNERWIDTH_DESC', 'ÏñËØ, ×î´ó. 144');
+@define('SYNDICATION_PLUGIN_BANNERHEIGHT_DESC', 'ÏñËØ, ×î´ó. 400');
+@define('SYNDICATION_PLUGIN_TTL', 'À¸Î» "ttl" (time-to-live)');
+@define('SYNDICATION_PLUGIN_TTL_DESC', '¹ý¼¸·ÖÖÓºóÄúµÄÎÄÕ²»»á±»ÍâÀ´µÄÍøÕ¾»ò³Ìʽ´¢´æµ½¿ìÈ¡¼ÇÒäÀï (¿Õ°×: Òþ²Ø) [RSS 2.0]');
+@define('SYNDICATION_PLUGIN_PUBDATE', 'À¸Î» "pubDate"');
+@define('SYNDICATION_PLUGIN_PUBDATE_DESC', '"pubDate"-À¸Î»ÐèÒªÄÚǶµ½RSS-ƵµÀ, ÒÔÏÔʾ×îºóÎÄÕµÄÈÕÆÚÂð?');
+@define('CONTENT', 'ÄÚÈÝ');
+@define('TYPE', 'ÀàÐÍ');
+@define('DRAFT', '²Ý¸å');
+@define('PUBLISH', '¹«¿ª');
+@define('PREVIEW', 'Ô¤ÀÀ');
+@define('DATE', 'ÈÕÆÚ');
+@define('DATE_FORMAT_2', 'Y-m-d H:i'); // Needs to be ISO 8601 compliant for date conversion!
+@define('DATE_INVALID', '¾¯¸æ: ÄúÌṩµÄÈÕÆÚ²»ÕýÈ·. Ëü±ØÐëÊÇ YYYY-MM-DD HH:MM ¸ñʽ.');
+@define('CATEGORY_PLUGIN_DESC', 'ÏÔʾÀà±ðÇåµ¥.');
+@define('ALL_AUTHORS', 'È«²¿×÷Õß');
+@define('CATEGORIES_TO_FETCH', 'ÏÔʾÀà±ð');
+@define('CATEGORIES_TO_FETCH_DESC', 'ÏÔʾÄÄλ×÷ÕßµÄÀà±ð?');
+@define('PAGE_BROWSE_ENTRIES', 'Ò³Êý %s ¹² %s, ×ܹ² %s ÆªÎÄÕÂ');
+@define('PREVIOUS_PAGE', 'ÉÏÒ»Ò³');
+@define('NEXT_PAGE', 'ÏÂÒ»Ò³');
+@define('ALL_CATEGORIES', 'È«²¿Àà±ð');
+@define('DO_MARKUP', 'Ö´Ðбê¼Çת»»');
+@define('GENERAL_PLUGIN_DATEFORMAT', 'ÈÕÆÚ¸ñʽ»¯');
+@define('GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH', 'ÎÄÕµÄÈÕÆÚ¸ñʽ, Ê¹ÓàPHP µÄ strftime() ±äÊý. (Ô¤Éè: "%s")');
+@define('ERROR_TEMPLATE_FILE', 'ÎÞ·¨¿ªÆô²¼¾°µµ°¸, Çë¸üРserendipity!');
+@define('ADVANCED_OPTIONS', '½ø½×Ñ¡Ïî');
+@define('EDIT_ENTRY', '±à¼­ÎÄÕÂ');
+@define('HTACCESS_ERROR', 'Òª¼ì²éÄúµÄÖ÷»ú°²×°É趨, serendipity ÐèÒª¶Áдµµ°¸ ".htaccess". µ«ÊÇÒòΪȨÏÞ´íÎó, Ã»Óа취ΪÄú¼ì²é. Çë¸Ä±äµµ°¸È¨ÏÞÏñÕâÑù: <br />&nbsp;&nbsp;%s<br />È»ºóÖØÐÂË¢ÐÂÕâ¸öÍøÒ³.');
+@define('SIDEBAR_PLUGINS', '²àÁÐÍâ¹Ò');
+@define('EVENT_PLUGINS', 'ʼþÍâ¹Ò');
+@define('SORT_ORDER', 'ÅÅÐò');
+@define('SORT_ORDER_NAME', 'µµ°¸Ãû³Æ');
+@define('SORT_ORDER_EXTENSION', '¸±µµÃû');
+@define('SORT_ORDER_SIZE', 'µµ°¸´óС');
+@define('SORT_ORDER_WIDTH', 'ͼƬ¿í¶È');
+@define('SORT_ORDER_HEIGHT', 'ͼƬ³¤¶È');
+@define('SORT_ORDER_DATE', 'ÉÏ´«ÈÕÆÚ');
+@define('SORT_ORDER_ASC', 'µÝÔöÅÅÐò');
+@define('SORT_ORDER_DESC', 'µÝ¼õÅÅÐò');
+@define('THUMBNAIL_SHORT', 'Ëõͼ');
+@define('ORIGINAL_SHORT', 'ԭʼ');
+@define('APPLY_MARKUP_TO', 'Ì×Óñê¼Çµ½ %s');
+@define('CALENDAR_BEGINNING_OF_WEEK', 'Ò»ÖܵĵÚÒ»Ìì');
+@define('SERENDIPITY_NEEDS_UPGRADE', 'Serendipity Õì²âµ½ÄúµÄÅäÖð汾ÊÇ %s, µ«ÊÇ Serendipity ±¾ÉíµÄ°²×°°æ±¾ÊÇ %s, Çë¸üÐÂÄúµÄ³Ìʽ°æ±¾! <a href="%s">¸üÐÂ</a>');
+@define('SERENDIPITY_UPGRADER_WELCOME', 'ÄúºÃ, »¶Ó­À´µ½ Serendipity µÄ¸üÐÂϵͳ.');
+@define('SERENDIPITY_UPGRADER_PURPOSE', '¸üÐÂϵͳ»á°ïÄú¸üе½ Serendipity °æ±¾ %s.');
+@define('SERENDIPITY_UPGRADER_WHY', 'Äú¿´µ½Õâ¸öѶϢÊÇÒòΪÄú°²×°ÁË Serendipity °æ±¾ %s, µ«ÊÇÄúûÓиüÐÂ×ÊÁÏ¿â');
+@define('SERENDIPITY_UPGRADER_DATABASE_UPDATES', '×ÊÁÏ¿â¸üР(%s)');
+@define('SERENDIPITY_UPGRADER_FOUND_SQL_FILES', 'ϵͳÕÒµ½ÒÔϵĠ.sql µµ, ÄÇЩµµ°¸±ØÐëÏÈÖ´ÐвÅÄܼÌÐø°²×° Serendipity');
+@define('SERENDIPITY_UPGRADER_VERSION_SPECIFIC',  'ÌØ¶¨µÄ°æ±¾ÈÎÎñ');
+@define('SERENDIPITY_UPGRADER_NO_VERSION_SPECIFIC', 'ûÓÐÌØ¶¨µÄ°æ±¾ÈÎÎñ');
+@define('SERENDIPITY_UPGRADER_PROCEED_QUESTION', 'È·¶¨ÒªÖ´ÐÐÉÏÃæµÄÈÎÎñÂð?');
+@define('SERENDIPITY_UPGRADER_PROCEED_ABORT', 'ÎÒ×Ô¼ºÖ´ÐÐ');
+@define('SERENDIPITY_UPGRADER_PROCEED_DOIT', 'Çë°ïÎÒÖ´ÐÐ');
+@define('SERENDIPITY_UPGRADER_NO_UPGRADES', 'Äú²»ÐèÒª½øÐÐÈκθüÐÂ');
+@define('SERENDIPITY_UPGRADER_CONSIDER_DONE', '¼Ù×° Serendipity ¸üÐÂÍê³É°É');
+@define('SERENDIPITY_UPGRADER_YOU_HAVE_IGNORED', 'ÄúÂÔ¹ýÁ˸üÐÂÈÎÎñ, ÇëÈ·¶¨×ÊÁÏ¿âÒѰ²×°Íê³É, ºÍÆäËûµÄÈÎÎñ°²×°ÎÞÎó');
+@define('SERENDIPITY_UPGRADER_NOW_UPGRADED', 'ÄúµÄ Serendipity ÒÔ¸üÐÂÖÁ°æ±¾ %s');
+@define('SERENDIPITY_UPGRADER_RETURN_HERE', 'Äú¿ÉÒÔµã %sÕâÀï%s ·µ»ØÈÕ¼ÇÊ×Ò³');
+@define('MANAGE_USERS', '¹ÜÀí×÷Õß');
+@define('CREATE_NEW_USER', 'ÐÂÔö×÷Õß');
+@define('CREATE_NOT_AUTHORIZED', 'Äú²»ÄÜÐ޸ĸúÄúÏàͬȨÏÞµÄ×÷Õß');
+@define('CREATE_NOT_AUTHORIZED_USERLEVEL', 'Äú²»ÄÜÐÂÔö±ÈÄú¸ßȨÏÞµÄ×÷Õß');
+@define('CREATED_USER', 'ÐÂ×÷Õß %s ÒѾ­ÐÂÔö');
+@define('MODIFIED_USER', '×÷Õß %s µÄ×ÊÁÏÒѾ­¸ü¸Ä');
+@define('USER_LEVEL', '×÷ÕßȨÏÞ');
+@define('DELETE_USER', 'ÄúҪɾ³ýÕâ¸ö×÷Õß #%d %s. È·¶¨Âð? Õâ»áÔÚÖ÷Ò³Òþ²ØËûËùдµÄÈκÎÎÄÕÂ.');
+@define('DELETED_USER', '×÷Õß #%d %s Òѱ»É¾³ý.');
+@define('LIMIT_TO_NUMBER', 'ÒªÏÔʾ¶àÉÙÏîÄ¿?');
+@define('ENTRIES_PER_PAGE', 'ÿҳÏÔʾµÄÎÄÕÂ');
+@define('XML_IMAGE_TO_DISPLAY', 'XML °´Å¥');
+@define('XML_IMAGE_TO_DISPLAY_DESC','Á¬½áµ½ XML Feeds µÄ¶¼»áÓÃÕâ¸öͼƬ±íʾ. ²»Ìîд½«»áʹÓÃÔ¤ÉèµÄͼƬ, »òÊäÈë \'none\' ¹Ø±ÕÕâ¸ö¹¦ÄÜ.');
+
+@define('DIRECTORIES_AVAILABLE', 'Äú¿ÉÒÔÔÚ×ÓĿ¼ÄÚµãÈκÎĿ¼À´½¨Á¢ÐµÄĿ¼.');
+@define('ALL_DIRECTORIES', 'È«²¿Ä¿ÂÌ');
+@define('MANAGE_DIRECTORIES', '¹ÜÀíĿ¼');
+@define('DIRECTORY_CREATED', 'Ŀ¼ <strong>%s</strong> ÒѾ­ÐÂÔö.');
+@define('PARENT_DIRECTORY', 'ĸĿ¼');
+@define('CONFIRM_DELETE_DIRECTORY', 'È·¶¨ÒªÉ¾³ýÕâ¸öĿ¼ÄÚµÄÈ«²¿ÄÚÈÝÂð %s?');
+@define('ERROR_NO_DIRECTORY', '´íÎó: Ä¿Â¼ %s ²»´æÔÚ');
+@define('CHECKING_DIRECTORY', '¼ì²é´ËĿ¼µÄµµ°¸ %s');
+@define('DELETING_FILE', 'ɾ³ýµµ°¸ %s...');
+@define('ERROR_DIRECTORY_NOT_EMPTY', '²»ÄÜÒÆ³ýδÇå¿ÕµÄĿ¼. ¹´Ñ¡ "Ç¿ÖÆÉ¾³ý" ºËÈ¡·½¿éÈç¹ûÄúÒªÒÆ³ýÕâЩµµ°¸, È»ºóÔÚ¼ÌÐø. ´æÔڵĵµ°¸ÊÇ:');
+@define('DIRECTORY_DELETE_FAILED', '²»ÄÜɾ³ýĿ¼ %s. Çë¼ì²éȨÏÞ»ò¿´ÉÏÃæµÄѶϢ.');
+@define('DIRECTORY_DELETE_SUCCESS', 'Ŀ¼ %s ³É¹¦É¾³ý.');
+@define('SKIPPING_FILE_EXTENSION', 'ÂÔ¹ýµµ°¸: Ã»ÓР%s µÄ¸±µµÃû.');
+@define('SKIPPING_FILE_UNREADABLE', 'ÂÔ¹ýµµ°¸: %s ²»ÄܶÁÈ¡.');
+@define('FOUND_FILE', 'ÕÒµ½ ÐÂ/Ð޸Ġ¹ýµÄµµ°¸: %s.');
+@define('ALREADY_SUBCATEGORY', '%s ÒѾ­ÊÇ´ËÀà±ðµÄ×ÓÀà±ð %s.');
+@define('PARENT_CATEGORY', 'ĸÀà±ð');
+@define('IN_REPLY_TO', '»Ø¸²µ½');
+@define('TOP_LEVEL', '×î¸ß²ã');
+@define('SYNDICATION_PLUGIN_GENERIC_FEED', '%s feed');
+@define('PERMISSIONS', 'ȨÏÞ');
+@define('SETTINGS_SAVED_AT', 'ÐÂÉ趨ÒѾ­±»´¢´æµ½ %s');
+
+/* DATABASE SETTINGS */
+@define('INSTALL_CAT_DB', '×ÊÁÏ¿âÉ趨');
+@define('INSTALL_CAT_DB_DESC', 'Äú¿ÉÒÔÔÚÕâÊäÈëÈ«²¿µÄ×ÊÁÏ¿â×ÊÁÏ. Serendipity ÐèÒªÕâЩ×ÊÁϲÅÄÜÕý³£ÔË×÷');
+@define('INSTALL_DBTYPE', '×ÊÁÏ¿âÀàÐÍ');
+@define('INSTALL_DBTYPE_DESC', '×ÊÁÏ¿âÀàÐÍ');
+@define('INSTALL_DBHOST', '×ÊÁÏ¿âÖ÷»ú');
+@define('INSTALL_DBHOST_DESC', '×ÊÁÏ¿âÖ÷»úÃû³Æ');
+@define('INSTALL_DBUSER', '×ÊÁÏ¿âÕʺÅ');
+@define('INSTALL_DBUSER_DESC', 'µÇÈë×ÊÁÏ¿âµÄÕʺÅ');
+@define('INSTALL_DBPASS', '×ÊÁÏ¿âÃÜÂë');
+@define('INSTALL_DBPASS_DESC', 'ÄúµÄ×ÊÁÏ¿âÃÜÂë');
+@define('INSTALL_DBNAME', '×ÊÁÏ¿âÃû³Æ');
+@define('INSTALL_DBNAME_DESC', '×ÊÁÏ¿âÃû³Æ');
+@define('INSTALL_DBPREFIX', '×ÊÁϱíǰÖÃÃû³Æ');
+@define('INSTALL_DBPREFIX_DESC', '×ÊÁϱíµÄǰÖÃÃû³Æ, ÀýÈç serendipity_');
+
+/* PATHS */
+@define('INSTALL_CAT_PATHS', '·¾¶É趨');
+@define('INSTALL_CAT_PATHS_DESC', '¸øµµ°¸¼ÐµÄ·¾¶. ²»ÒªÍüÁË×îºóµÄбÏß!');
+@define('INSTALL_FULLPATH', 'Íêȫ·¾¶');
+@define('INSTALL_FULLPATH_DESC', 'ÄúµÄ Serendipity °²×°µÄÍêȫ·¾¶ºÍ¾ø¶Ô·¾¶');
+@define('INSTALL_UPLOADPATH', 'ÉÏ´«Â·¾¶');
+@define('INSTALL_UPLOADPATH_DESC', 'È«²¿µÄÉÏ´«µµ°¸»á´æµ½ÕâÀï, ÒÔ \'Íêȫ·¾¶\' ±íʾµÄÏà¶Ô·¾¶ - ÀýÈç \'uploads/\'');
+@define('INSTALL_RELPATH', 'Ïà¶Ô·¾¶');
+@define('INSTALL_RELPATH_DESC', '¸øä¯ÀÀÆ÷µÄ·¾¶, ÀýÈç \'/serendipity/\'');
+@define('INSTALL_RELTEMPLPATH', 'Ïà¶ÔµÄ²¼¾°Â·¾¶');
+@define('INSTALL_RELTEMPLPATH_DESC', 'Äú·Å²¼¾°µÄ·¾¶ - ÒÔ \'Ïà¶Ô·¾¶\' ±íʾµÄÏà¶Ô·¾¶');
+@define('INSTALL_RELUPLOADPATH', 'Ïà¶ÔµÄÉÏ´«Â·¾¶');
+@define('INSTALL_RELUPLOADPATH_DESC', '¸øä¯ÀÀÆ÷ÉÏ´«µµ°¸µÄ·¾¶ - ÒÔ \'Ïà¶Ô·¾¶\' ±íʾµÄÏà¶Ô·¾¶');
+@define('INSTALL_URL', 'ÍøÂ·ÈռǠURL');
+@define('INSTALL_URL_DESC', 'ÄúµÄ Serendipity °²×°µÄ»ù±¾ URL');
+@define('INSTALL_INDEXFILE', 'Index µµ°¸');
+@define('INSTALL_INDEXFILE_DESC', 'Serendipity µÄ index µµ°¸');
+
+/* Generel settings */
+@define('INSTALL_CAT_SETTINGS', 'Ò»°ãÉ趨');
+@define('INSTALL_CAT_SETTINGS_DESC', 'Serendipity µÄÒ»°ãÉ趨');
+@define('INSTALL_USERNAME', '¹ÜÀíÔ±ÕʺÅ');
+@define('INSTALL_USERNAME_DESC', '¹ÜÀíÔ±µÄµÇÈëÃû³Æ');
+@define('INSTALL_PASSWORD', '¹ÜÀíÔ±ÃÜÂë');
+@define('INSTALL_PASSWORD_DESC', '¹ÜÀíÔ±µÄµÇÈëÃÜÂë');
+@define('INSTALL_EMAIL', 'µç×ÓÓʼþ');
+@define('INSTALL_EMAIL_DESC', '¹ÜÀíÔ±µÄµç×ÓÓʼþ');
+@define('INSTALL_SENDMAIL', '¼ÄË͵ç×ÓÓʼþ¸ø¹ÜÀíÔ±?');
+@define('INSTALL_SENDMAIL_DESC', 'µ±ÓÐÈË·¢²¼»ØÏìµ½ÄúµÄÎÄÕÂʱҪÊÕµ½µç×ÓÓʼþ֪ͨÂð?');
+@define('INSTALL_SUBSCRIBE', 'ÔÊÐíʹÓÃÕß¶©ÔÄÎÄÕÂ?');
+@define('INSTALL_SUBSCRIBE_DESC', 'Äú¿ÉÒÔÔÊÐíʹÓÃÕßÊÕµ½µç×ÓÓʼþ֪ͨ, µ±ÓлØÏì·¢²¼Ê±ËýÃÇ»áÊÕµ½Í¨Öª.');
+@define('INSTALL_BLOGNAME', 'ÈÕ¼ÇÃû³Æ');
+@define('INSTALL_BLOGNAME_DESC', 'ÄúµÄÈռDZêÌâ');
+@define('INSTALL_BLOGDESC', 'ÈռǼò½é');
+@define('INSTALL_BLOGDESC_DESC', '½éÉÜÄúµÄÈÕ¼Ç');
+@define('INSTALL_LANG', 'Óïϵ');
+@define('INSTALL_LANG_DESC', 'ÄúÈÕ¼ÇʹÓõÄÓïϵ');
+
+/* Appearance and options */
+@define('INSTALL_CAT_DISPLAY', 'Íâ¹Û¼°Ñ¡ÏîÉ趨');
+@define('INSTALL_CAT_DISPLAY_DESC', 'ÈÃÄúÉ趨 Serendipity µÄÍâ¹ÛºÍÆäËûÉ趨');
+@define('INSTALL_WYSIWYG', 'ʹÓàWYSIWYG ±à¼­Æ÷');
+@define('INSTALL_WYSIWYG_DESC', 'ÄúҪʹÓàWYSIWYG ±à¼­Æ÷Âð? (¿ÉÔÚ IE5+ Ê¹ÓÃ, Ä³Ð©²¿·Ö¿ÉʹÓÃì¶ Mozilla 1.3+)');
+@define('INSTALL_XHTML11', 'Ç¿ÖÆ·ûºÏ XHTML 1.1 ÒªÇó');
+@define('INSTALL_XHTML11_DESC', 'Äú¿ÉÒÔÈÃÄúµÄÈÕ¼ÇÇ¿ÖÆ·ûºÏ XHTML 1.1 µÄÒªÇó (¶Ô¾ÉµÄä¯ÀÀÆ÷¿ÉÄÜ»áÓРºǫ́/ǰ̨ µÄÎÊÌâ)');
+@define('INSTALL_POPUP', 'ʹÓõ¯³öÊÓ´°');
+@define('INSTALL_POPUP_DESC', 'ÄúÒªÔÚ»ØÏì, ÒýÓõȵط½Ê¹Óõ¯³öÊÓ´°Âð?');
+@define('INSTALL_EMBED', 'ʹÓÃÄÚǶ¹¦ÄÜ?');
+@define('INSTALL_EMBED_DESC', 'Èç¹ûÄãÒª½« Serendipity ÒÔÄÚǶµÄ·½Ê½·Åµ½ÍøÒ³ÄÚ, Ñ¡Ôñ ÊÇ »áÈÃÄúÉáÆúÈκαêÌâÈ»ºóÖ»ÏÔʾÈÕ¼ÇÄÚÈÝ. Äú¿ÉÒÔÓàindexFile É趨À´Ê¹Óðü×°º¯Ê½Àà±ðÒÔ±ãÄú·ÅÈëÍøÒ³±êÌâ. ÏêÇéÇë²éѯ README µµ°¸!');
+@define('INSTALL_TOP_AS_LINKS', 'ÒÔÁ¬½áÏÔʾ Ö÷Òª³öÔ´/Ö÷ÒªÀ´Ô´?');
+@define('INSTALL_TOP_AS_LINKS_DESC', '"·ñ": ³öÔ´ºÍÀ´Ô´½«ÓÃÎÄ×ÖÏÔʾÒÔ±ÜÃâ google µÄ¹ã¸æ. "ÊÇ": ³öÔ´ºÍÀ´Ô´½«ÓÃÁ¬½áÏÔʾ. "Ô¤Éè": ÓÃÈ«ÇøÀïÃæµÄÉ趨 (½¨Òé).');
+@define('INSTALL_BLOCKREF', '×èµ²À´Ô´');
+@define('INSTALL_BLOCKREF_DESC', 'ÓÐÈκÎÌØÊâµÄÖ÷»úÄú²»ÏëÔÚÀ´Ô´ÀïÏÔʾÂð? Óà\';\' À´·Ö¿ªÖ÷»úÃû³Æ, ×¢ÒâÖ÷»úÊÇÒÔ×Ó×Ö´®·½Ê½×èµ²!');
+@define('INSTALL_REWRITE', 'URL Rewriting');
+@define('INSTALL_REWRITE_DESC', 'ÇëÑ¡ÔñÄúÏëÓõĠURL Rewriting ·½Ê½. ¿ªÆô rewrite ¹æÔò»áÒԱȽÏÇå³þµÄ·½Ê½ÏÔʾ URL, ÒÔ±ãËÑÑ°ÍøÕ¾ÄÜÕýÈ·µÄµÇÈëÄúµÄÎÄÕÂ. ÄúµÄÖ÷»ú±ØÐëÖ§Ô® mod_rewrite »ò "AllowOverride All" µ½ÄúµÄ Serendipity µµ°¸¼Ð. Ô¤ÉèµÄÉ趨ÊÇϵͳ×Ô¶¯°ïÄúÕì²âµÄ');
+
+/* Imageconversion Settings */
+@define('INSTALL_CAT_IMAGECONV', 'ͼƬת»»É趨');
+@define('INSTALL_CAT_IMAGECONV_DESC', 'ÇëÉ趨 Serendipity É趨ͼƬת»»µÄ·½Ê½');
+@define('INSTALL_IMAGEMAGICK', 'ʹÓàImagemagick');
+@define('INSTALL_IMAGEMAGICK_DESC', 'Èç¹ûÓа²×° image magick, ÄúÒªÓÃËüÀ´¸Ä±äͼƬ´óСÂð?');
+@define('INSTALL_IMAGEMAGICKPATH', 'ת»»³Ìʽ·¾¶');
+@define('INSTALL_IMAGEMAGICKPATH_DESC', 'image magick ×ª»»³ÌʽµÄÍêȫ·¾¶ºÍÃû³Æ');
+@define('INSTALL_THUMBSUFFIX', 'ËõͼºóÖÃ×ÖÔª');
+@define('INSTALL_THUMBSUFFIX_DESC', 'Ëõͼ»áÒÔÏÂÃæµÄ¸ñÊ½ÖØÐÂÃüÃû: original.[ºóÖÃ×ÖÔª].ext');
+@define('INSTALL_THUMBWIDTH', 'Ëõͼ³ß¶È');
+@define('INSTALL_THUMBWIDTH_DESC', '×Ô¶¯½¨Á¢ËõͼµÄ×î´ó¿í¶È');
+
+/* Personal details */
+@define('USERCONF_CAT_PERSONAL', '¸öÈË×ÊÁÏÉ趨');
+@define('USERCONF_CAT_PERSONAL_DESC', '¸Ä±äÄúµÄ¸öÈË×ÊÁÏ');
+@define('USERCONF_USERNAME', 'ÄúµÄÕʺÅ');
+@define('USERCONF_USERNAME_DESC', 'ÄúµÇÈëÍøÂ·ÈռǵÄÃû³Æ');
+@define('USERCONF_PASSWORD', 'ÄúµÄÃÜÂë');
+@define('USERCONF_PASSWORD_DESC', 'ÄúµÇÈëÍøÂ·ÈռǵÄÃÜÂë');
+@define('USERCONF_EMAIL', 'ÄúµÄµç×ÓÓʼþ');
+@define('USERCONF_EMAIL_DESC', 'ÄúʹÓõĵç×ÓÓʼþ');
+@define('USERCONF_SENDCOMMENTS', '¼ÄËÍ»ØÏì֪ͨ?');
+@define('USERCONF_SENDCOMMENTS_DESC', 'µ±ÓÐлØÏìµ½ÄúµÄÎÄÕÂʱҪ֪ͨÄúÂð?');
+@define('USERCONF_SENDTRACKBACKS', '¼ÄËÍÒýÓÃ֪ͨ?');
+@define('USERCONF_SENDTRACKBACKS_DESC', 'µ±ÓÐÐÂÒýÓõ½ÄúµÄÎÄÕÂʱҪ֪ͨÄúÂð?');
+@define('USERCONF_ALLOWPUBLISH', 'ȨÏÞ: ¿É·¢²¼ÎÄÕÂ?');
+@define('USERCONF_ALLOWPUBLISH_DESC', 'ÔÊÐíÕâλ×÷Õß·¢²¼ÎÄÕÂÂð?');
+@define('SUCCESS', 'Íê³É');
+@define('POWERED_BY_SHOW_TEXT', 'ÒÔÎÄ×ÖÏÔʾ "Serendipity"');
+@define('POWERED_BY_SHOW_TEXT_DESC', '½«ÓÃÎÄ×ÖÏÔʾ "Serendipity Weblog"');
+@define('POWERED_BY_SHOW_IMAGE', 'ÒÔ logo ÏÔʾ "Serendipity"');
+@define('POWERED_BY_SHOW_IMAGE_DESC', 'ÏÔʾ Serendipity µÄ logo');
+@define('PLUGIN_ITEM_DISPLAY', '¸ÃÏîÄ¿µÄÏÔʾλַ?');
+@define('PLUGIN_ITEM_DISPLAY_EXTENDED', 'Ö»ÔÚ¸±ÄÚÈÝÏÔʾ');
+@define('PLUGIN_ITEM_DISPLAY_OVERVIEW', 'Ö»ÔڸŹÛÄÚÏÔʾ');
+@define('PLUGIN_ITEM_DISPLAY_BOTH', 'ÓÀÔ¶ÏÔʾ');
+
+@define('COMMENTS_WILL_BE_MODERATED', '·¢²¼µÄ»ØÏ콫ÐèÒª¹ÜÀíÔ±µÄÉóºË.');
+@define('YOU_HAVE_THESE_OPTIONS', 'ÄúÓÐÒÔÏÂÑ¡Ôñ:');
+@define('THIS_COMMENT_NEEDS_REVIEW', '¾¯¸æ: Õâ¸ö»ØÏìÐëÉóºË²Å»áÏÔʾ');
+@define('DELETE_COMMENT', 'ɾ³ý»ØÏì');
+@define('APPROVE_COMMENT', 'ÈϿɻØÏì');
+@define('REQUIRES_REVIEW', 'ÐèÒªÉóºË');
+@define('COMMENT_APPROVED', '»ØÏì #%s ÒѾ­Í¨¹ýÉóºË');
+@define('COMMENT_DELETED', '»ØÏì #%s ÒѾ­³É¹¦É¾³ý');
+@define('COMMENTS_MODERATE', '»ØÏìºÍÒýÓõ½Õâ¸öÎÄÕÂÐèÒª¹ÜÀíÔ±µÄÉóºË');
+@define('THIS_TRACKBACK_NEEDS_REVIEW', '¾¯¸æ: Õâ¸öÒýÓÃÐèÒª¹ÜÀíÔ±µÄÉóºË²Å»áÏÔʾ');
+@define('DELETE_TRACKBACK', 'ɾ³ýÒýÓÃ');
+@define('APPROVE_TRACKBACK', 'ÈÏ¿ÉÒýÓÃ');
+@define('TRACKBACK_APPROVED', 'ÒýÓà#%s ÒѾ­Í¨¹ýÉóºË');
+@define('TRACKBACK_DELETED', 'ÒýÓà#%s ÒѾ­³É¹¦É¾³ý');
+@define('VIEW', 'ä¯ÀÀ');
+@define('COMMENT_ALREADY_APPROVED', '»ØÏì #%s ÒѾ­Í¨¹ýÉóºË');
+@define('COMMENT_EDITED', 'ÎÄÕÂÒѱ»±à¼­');
+@define('HIDE', 'Òþ²Ø');
+@define('VIEW_EXTENDED_ENTRY', '¼ÌÐøÔĶÁ "%s"');
+@define('TRACKBACK_SPECIFIC_ON_CLICK', 'Õâ¸öÁ¬½á²»ÊÇÓÃÀ´µãµÄ. Ëü°üº¬ÁËÕâ¸öÎÄÕµÄÒýÓàURI. Äú¿ÉÒÔ´ÓÄúµÄÈÕ¼ÇÄÚÓÃÕâ¸ö URI À´´«ËÍ ping ºÍÒýÓõ½Õâ¸öÎÄÕÂ. Èç¹ûÒª¸´ÖÆÕâ¸öÁ¬½á, ÔÚÁ¬½áÉϵãÓÒ¼üÈ»ºóÑ¡Ôñ "¸´ÖÆÁ¬½á" (IE) »ò "¸´ÖÆÁ¬½áλַ" (Mozilla).');
+@define('PLUGIN_SUPERUSER_HTTPS', 'Óàhttps µÇÈë');
+@define('PLUGIN_SUPERUSER_HTTPS_DESC', 'ÈõÇÈëÁ¬½áÁ¬µ½ https ÍøÖ·. ÄúµÄÖ÷»ú±ØÐëÖ§Ô®ÕâÏÄÜ!');
+@define('INSTALL_SHOW_EXTERNAL_LINKS', 'ÈÃÍâÀ´Á¬½áÒÔÁ¬½áÏÔʾ?');
+@define('INSTALL_SHOW_EXTERNAL_LINKS_DESC', '"·ñ": ÍâÀ´Á¬½á (Ö÷Òª³öÔ´, Ö÷ÒªÀ´Ô´, »ØÏì) ¶¼²»»áÒÔÎÄ×ÖÏÔʾÒÔ±ÜÃâ google ¹ã¸æ (½¨ÒéʹÓÃ). "ÊÇ": ÍâÀ´Á¬½á½«ÒÔ³¬Á¬½áµÄ·½Ê½ÏÔʾ. ¿ÉÒÔÔÚ²àÁÐÍâ¹Ò¸Ç¹ý´ËÉ趨!');
+@define('PAGE_BROWSE_COMMENTS', 'Ò³Êý %s ¹² %s, ×ܹ² %s ¸ö»ØÏì');
+@define('FILTERS', '¹ýÂË');
+@define('FIND_ENTRIES', 'ËÑѰÎÄÕÂ');
+@define('FIND_COMMENTS', 'ËÑѰ»ØÏì');
+@define('FIND_MEDIA', 'ËÑѰýÌå');
+@define('FILTER_DIRECTORY', 'Ŀ¼');
+@define('SORT_BY', 'ÅÅÐò');
+@define('TRACKBACK_COULD_NOT_CONNECT', 'ûÓÐËͳöÒýÓÃ: ÎÞ·¨¿ªÆôÏß·µ½ %s ÓÃÁ¬½Ó²º %d');
+@define('MEDIA', 'ýÌå');
+@define('MEDIA_LIBRARY', 'ýÌå´æ¿â');
+@define('ADD_MEDIA', 'ÐÂÔöýÌå');
+@define('ENTER_MEDIA_URL', 'ÇëÊäÈëµµ°¸µÄ URL:');
+@define('ENTER_MEDIA_UPLOAD', 'ÇëÑ¡ÔñÒªÉÏ´«µÄµµ°¸:');
+@define('SAVE_FILE_AS', '´¢´æµµ°¸:');
+@define('STORE_IN_DIRECTORY', '´¢´æµ½ÒÔÏÂĿ¼: ');
+@define('ADD_MEDIA_BLAHBLAH', '<b>ÐÂÔöµµ°¸µ½Ã½Ìå´æ¿â:</b><p>Äú¿ÉÒÔÔÚÕâÉÏ´«Ã½Ìåµµ, »ò¸æËßϵͳµ½ÄÄѰÕÒ! Èç¹ûÄúûÓÐÏëÒªµÄͼƬ, Äú¿ÉÒÔµ½ <a href="http://images.google.com" target="_blank">googleѰÕÒͼƬ</a>.<p><b>Ñ¡Ôñ·½Ê½:</b><br>');
+@define('MEDIA_RENAME', '¸ü¸Äµµ°¸Ãû³Æ');
+@define('IMAGE_RESIZE', '¸ü¸ÄͼƬ³ß´ç');
+@define('MEDIA_DELETE', 'ɾ³ýÕâ¸öµµ°¸');
+@define('FILES_PER_PAGE', 'ÿҳÏÔʾµÄµµ°¸Êý');
+@define('CLICK_FILE_TO_INSERT', 'µãÑ¡ÄúÒªÊäÈëµÄµµ°¸:');
+@define('SELECT_FILE', 'Ñ¡ÔñÒªÊäÈëµÄµµ°¸');
+@define('MEDIA_FULLSIZE', 'ÍêÕû³ß´ç');
+@define('CALENDAR_BOW_DESC', 'Ò»¸öÀñ°ÝµÄµÚÒ»Ìì. Ô¤ÉèÊÇÐÇÆÚÒ»');
+@define('SUPERUSER', 'ÈռǹÜÀí');
+@define('ALLOWS_YOU_BLAHBLAH', 'ÔÚ²àÁÐÌṩÁ¬½áµ½ÈռǹÜÀí');
+@define('CALENDAR', 'ÈÕÀú');
+@define('SUPERUSER_OPEN_ADMIN', '¿ªÆô¹ÜÀíÒ³Ãæ');
+@define('SUPERUSER_OPEN_LOGIN', '¿ªÆôµÇÈëÒ³Ãæ');
+@define('INVERT_SELECTIONS', 'µßµ¹¹´Ñ¡');
+@define('COMMENTS_DELETE_CONFIRM', 'È·¶¨ÒªÉ¾³ý¹´Ñ¡µÄ»ØÏìÂð?');
+@define('COMMENT_DELETE_CONFIRM', 'È·¶¨ÒªÉ¾³ý»ØÏì #%d, ·¢²¼ÕßÊÇ %s?');
+@define('DELETE_SELECTED_COMMENTS', 'ɾ³ý¹´Ñ¡µÄ»ØÏì');
+@define('VIEW_COMMENT', 'ä¯ÀÀ»ØÏì');
+@define('VIEW_ENTRY', 'ä¯ÀÀÎÄÕÂ');
+@define('DELETE_FILE_FAIL' , 'ÎÞ·¨É¾³ýµµ°¸ <b>%s</b>');
+@define('DELETE_THUMBNAIL', 'ɾ³ýÁËͼƬËõͼ <b>%s</b>');
+@define('DELETE_FILE', 'ɾ³ýÁ˵µ°¸ <b>%s</b>');
+@define('ABOUT_TO_DELETE_FILE', 'Äú½«É¾³ýµµ°¸ <b>%s</b><br />Èç¹ûÄúÓÐÔÚÆäËûµÄÎÄÕÂÄÚʹÓÃÕâ¸öµµ°¸, ÄǸöÁ¬½á»òͼƬ½«»áÎÞЧ<br />È·¶¨Òª¼ÌÐøÂð?<br /><br />');
+@define('TRACKBACK_SENDING', '´«ËÍÒýÓõ½ URI %s...');
+@define('TRACKBACK_SENT', 'ÒýÓÃÍê³É');
+@define('TRACKBACK_FAILED', 'ÒýÓôíÎó: %s');
+@define('TRACKBACK_NOT_FOUND', 'ÕÒ²»µ½ÒýÓõÄURI.');
+@define('TRACKBACK_URI_MISMATCH', '×Ô¶¯ËÑѰµÄÒýÓøúÒýÓÃÄ¿±ê²»Ïàͬ.');
+@define('TRACKBACK_CHECKING', 'ËÑѰ <u>%s</u> µÄÒýÓÃ...');
+@define('TRACKBACK_NO_DATA', 'Ä¿±êûÓÐÈκÎ×ÊÁÏ');
+@define('TRACKBACK_SIZE', 'Ä¿±ê URI ³¬³öÁËÔÊÐíµÄ %s bytes µµ°¸´óС.');
+@define('COMMENTS_VIEWMODE_THREADED', '·ÖÏß³Ì');
+@define('COMMENTS_VIEWMODE_LINEAR', 'Ö±Ïß³Ì');
+@define('DISPLAY_COMMENTS_AS', '»ØÏìÏÔʾ·½Ê½');
+@define('COMMENTS_FILTER_SHOW', 'ÏÔʾ');
+@define('COMMENTS_FILTER_ALL', 'È«²¿');
+@define('COMMENTS_FILTER_APPROVED_ONLY', 'ÏÔʾÉóºË»ØÏì');
+@define('COMMENTS_FILTER_NEED_APPROVAL', 'ÏÔʾµÈ´ýÉóºË');
+@define('RSS_IMPORT_BODYONLY', '½«ÊäÈëµÄÎÄ×ַŵ½Ö÷ÄÚÈÝ, ½«²»²ð¿ª¹ý³¤µÄÎÄÕµ½¸±ÄÚÈݵØÇø.');
+@define('SYNDICATION_PLUGIN_FULLFEED', 'ÔÚ RSS feed ÀïÏÔʾȫ²¿µÄÎÄÕÂ');
+@define('WEEK', 'ÖÜ');
+@define('WEEKS', 'ÖÜ');
+@define('MONTHS', 'ÔÂ');
+@define('DAYS', 'ÈÕ');
+@define('ARCHIVE_FREQUENCY', '±£´æÎÄ¿âµÄÏîĿƵÂÊ');
+@define('ARCHIVE_FREQUENCY_DESC', '±£´æÎÄ¿âʹÓõÄÏîÄ¿Çåµ¥¼ä¸ô');
+@define('ARCHIVE_COUNT', '±£´æÎÄ¿âµÄÏîÄ¿Êý');
+@define('ARCHIVE_COUNT_DESC', 'ÏÔʾµÄÔÂ, ÖÜ, »òÈÕ');
+@define('BELOW_IS_A_LIST_OF_INSTALLED_PLUGINS', 'ÏÂÃæÊǰ²×°ºÃµÄÍâ¹Ò');
+@define('SIDEBAR_PLUGIN', '²àÁÐÍâ¹Ò');
+@define('EVENT_PLUGIN', 'ʼþÍâ¹Ò');
+@define('CLICK_HERE_TO_INSTALL_PLUGIN', 'µãÕâÀﰲװР%s');
+@define('VERSION', '°æ±¾');
+@define('INSTALL', '°²×°');
+@define('ALREADY_INSTALLED', 'ÒѾ­°²×°');
+@define('SELECT_A_PLUGIN_TO_ADD', 'ÇëÑ¡ÔñÒª°²×°µÄÍâ¹Ò');
+@define('RSS_IMPORT_CATEGORY', 'ÓÃÕâ¸öÀà±ð¸ø²»ÏàͬµÄÊäÈëÎÄÕÂ');
+
+@define('INSTALL_OFFSET', 'Server time Offset'); // Translate
+@define('STICKY_POSTINGS', 'Sticky Postings'); // Translate
+@define('INSTALL_FETCHLIMIT', 'Entries to display on frontpage'); // Translate
+@define('INSTALL_FETCHLIMIT_DESC', 'Number of entries to display for each page on the frontend'); // Translate
+@define('IMPORT_ENTRIES', 'Import data'); // Translate
+@define('EXPORT_ENTRIES', 'Export entries'); // Translate
+@define('IMPORT_WELCOME', 'Welcome to the Serendipity import utility'); // Translate
+@define('IMPORT_WHAT_CAN', 'Here you can import entries from other weblog software applications'); // Translate
+@define('IMPORT_SELECT', 'Please select the software you wish to import from'); // Translate
+@define('IMPORT_PLEASE_ENTER', 'Please enter the data as requested below'); // Translate
+@define('IMPORT_NOW', 'Import now!'); // Translate
+@define('IMPORT_STARTING', 'Starting import procedure...'); // Translate
+@define('IMPORT_FAILED', 'Import failed'); // Translate
+@define('IMPORT_DONE', 'Import successfully completed'); // Translate
+@define('IMPORT_WEBLOG_APP', 'Weblog application'); // Translate
+@define('EXPORT_FEED', 'Export full RSS feed'); // Translate
+@define('STATUS', 'Status after import'); // Translate
+@define('IMPORT_GENERIC_RSS', 'Generic RSS import'); // Translate
+@define('ACTIVATE_AUTODISCOVERY', 'Send Trackbacks to links found in the entry'); // Translate
+@define('WELCOME_TO_ADMIN', 'Welcome to the Serendipity Administration Suite.'); // Translate
+@define('PLEASE_ENTER_CREDENTIALS', 'Please enter your credentials below.'); // Translate
+@define('ADMIN_FOOTER_POWERED_BY', 'Powered by Serendipity %s and PHP %s'); // Translate
+@define('INSTALL_USEGZIP', 'Use gzip compressed pages'); // Translate
+@define('INSTALL_USEGZIP_DESC', 'To speed up delivery of pages, we can compress the pages we send to the visitor, given that his browser supports this. This is recommended'); // Translate
+@define('INSTALL_SHOWFUTURE', 'Show future entries'); // Translate
+@define('INSTALL_SHOWFUTURE_DESC', 'If enabled, this will show all entries in the future on your blog. Default is to hide those entries and only show them if the publish date has arrived.'); // Translate
+@define('INSTALL_DBPERSISTENT', 'Use persistent connections'); // Translate
+@define('INSTALL_DBPERSISTENT_DESC', 'Enable the usage of persistent database connections, read more <a href="http://php.net/manual/features.persistent-connections.php" target="_blank">here</a>. This is normally not recommended'); // Translate
+@define('NO_IMAGES_FOUND', 'No images found'); // Translate
+@define('PERSONAL_SETTINGS', 'Personal Settings'); // Translate
+@define('REFERER', 'Referer'); // Translate
+@define('NOT_FOUND', 'Not found'); // Translate
+@define('NOT_WRITABLE', 'Not writable'); // Translate
+@define('WRITABLE', 'Writable'); // Translate
+@define('PROBLEM_DIAGNOSTIC', 'Due to a problematic diagnostic, you cannot continue with the installation before the above errors are fixed'); // Translate
+@define('SELECT_INSTALLATION_TYPE', 'Select which installation type you wish to use'); // Translate
+@define('WELCOME_TO_INSTALLATION', 'Welcome to the Serendipity Installation'); // Translate
+@define('FIRST_WE_TAKE_A_LOOK', 'First we will take a look at your current setup and attempt to diagnose any compatibility problems'); // Translate
+@define('ERRORS_ARE_DISPLAYED_IN', 'Errors are displayed in %s, recommendations in %s and success in %s'); // Translate
+@define('RED', 'red'); // Translate
+@define('YELLOW', 'yellow'); // Translate
+@define('GREEN', 'green'); // Translate
+@define('PRE_INSTALLATION_REPORT', 'Serendipity v%s pre-installation report'); // Translate
+@define('RECOMMENDED', 'Recommended'); // Translate
+@define('ACTUAL', 'Actual'); // Translate
+@define('PHPINI_CONFIGURATION', 'php.ini configuration'); // Translate
+@define('PHP_INSTALLATION', 'PHP installation'); // Translate
+@define('THEY_DO', 'they do'); // Translate
+@define('THEY_DONT', 'they don\'t'); // Translate
+@define('SIMPLE_INSTALLATION', 'Simple installation'); // Translate
+@define('EXPERT_INSTALLATION', 'Expert installation'); // Translate
+@define('COMPLETE_INSTALLATION', 'Complete installation'); // Translate
+@define('WONT_INSTALL_DB_AGAIN', 'won\'t install the database again'); // Translate
+@define('CHECK_DATABASE_EXISTS', 'Checking to see if the database and tables already exists'); // Translate
+@define('CREATING_PRIMARY_AUTHOR', 'Creating primary author \'%s\''); // Translate
+@define('SETTING_DEFAULT_TEMPLATE', 'Setting default template'); // Translate
+@define('INSTALLING_DEFAULT_PLUGINS', 'Installing default plugins'); // Translate
+@define('SERENDIPITY_INSTALLED', 'Serendipity has been successfully installed'); // Translate
+@define('VISIT_BLOG_HERE', 'Visit your new blog here'); // Translate
+@define('THANK_YOU_FOR_CHOOSING', 'Thank you for choosing Serendipity'); // Translate
+@define('ERROR_DETECTED_IN_INSTALL', 'An error was detected in the installation'); // Translate
+@define('OPERATING_SYSTEM', 'Operating system'); // Translate
+@define('WEBSERVER_SAPI', 'Webserver SAPI'); // Translate
+@define('TEMPLATE_SET', '\'%s\' has been set as your active template'); // Translate
+@define('SEARCH_ERROR', 'The search function did not work as expected. Notice for the administrator of this blog: This may happen because of missing index keys in your database. On MySQL systems your database user account needs to be privileged to execute this query: <pre>CREATE FULLTEXT INDEX entry_idx on %sentries (title,body,extended)</pre> The specific error returned by the database was: <pre>%s</pre>'); // Translate
+@define('EDIT_THIS_CAT', 'Editing "%s"'); // Translate
+@define('CATEGORY_REMAINING', 'Delete this category and move its entries to this category'); // Translate
+@define('CATEGORY_INDEX', 'Below is a list of categories available to your entries'); // Translate
+@define('NO_CATEGORIES', 'No categories'); // Translate
+@define('RESET_DATE', 'Reset date'); // Translate
+@define('RESET_DATE_DESC', 'Click here to reset the date to the current time'); // Translate
+@define('PROBLEM_PERMISSIONS_HOWTO', 'Permissions can be set by running shell command: `<em>%s</em>` on the failed directory, or by setting this using an FTP program'); // Translate
+@define('WARNING_TEMPLATE_DEPRECATED', 'Warning: Your current template is using a deprecated template method, you are advised to update if possible'); // Translate
+@define('ENTRY_PUBLISHED_FUTURE', 'This entry is not yet published.'); // Translate
+@define('ENTRIES_BY', 'Entries by %s'); // Translate
+@define('PREVIOUS', 'Previous'); // Translate
+@define('NEXT', 'Next'); // Translate
+@define('APPROVE', 'Approve'); // Translate
+@define('DO_MARKUP_DESCRIPTION', 'Apply markup transformations to the text (smilies, shortcut markups via *, /, _, ...). Disabling this will preserve any HTML-code in the text.'); // Translate
+@define('CATEGORY_ALREADY_EXIST', 'A category with the name "%s" already exist'); // Translate
+@define('IMPORT_NOTES', 'Note:'); // Translate
+@define('ERROR_FILE_FORBIDDEN', 'You are not allowed to upload files with active content'); // Translate
+@define('ADMIN', 'Administration'); // Re-Translate
+@define('ADMIN_FRONTPAGE', 'Frontpage'); // Translate
+@define('QUOTE', 'Quote'); // Translate
+@define('IFRAME_SAVE', 'Serendipity is now saving your entry, creating trackbacks and performing possible XML-RPC calls. This may take a while..'); // Translate
+@define('IFRAME_SAVE_DRAFT', 'A draft of this entry has been saved'); // Translate
+@define('IFRAME_PREVIEW', 'Serendipity is now creating the preview of your entry...'); // Translate
+@define('IFRAME_WARNING', 'Your browser does not support the concept of iframes. Please open your serendipity_config.inc.php file and set $serendipity[\'use_iframe\'] variable to FALSE.'); // Translate
+@define('NONE', 'none');
+@define('USERCONF_CAT_DEFAULT_NEW_ENTRY', 'Default settings for new entries'); // Translate
+@define('UPGRADE', 'Upgrade'); // Translate
+@define('UPGRADE_TO_VERSION', 'Upgrade to version %s'); // Translate
+@define('DELETE_DIRECTORY', 'Delete directory'); // Translate
+@define('DELETE_DIRECTORY_DESC', 'You are about to delete the contents of a directory that contains media files, possibly files used in some of your entries.'); // Translate
+@define('FORCE_DELETE', 'Delete ALL files in this directory, including those not known by Serendipity'); // Translate
+@define('CREATE_DIRECTORY', 'Create directory'); // Translate
+@define('CREATE_NEW_DIRECTORY', 'Create new directory'); // Translate
+@define('CREATE_DIRECTORY_DESC', 'Here you can create a new directory to place media files in. Choose the name for your new directory and select an optional parent directory to place it in.'); // Translate
+@define('BASE_DIRECTORY', 'Base directory'); // Translate
+@define('USERLEVEL_EDITOR_DESC', 'Standard editor'); // Translate
+@define('USERLEVEL_CHIEF_DESC', 'Chief editor'); // Translate
+@define('USERLEVEL_ADMIN_DESC', 'Administrator'); // Translate
+@define('USERCONF_USERLEVEL', 'Access level'); // Translate
+@define('USERCONF_USERLEVEL_DESC', 'This level is used to determine what kind of access this user has to the blog'); // Translate
+@define('USER_SELF_INFO', 'Logged in as %s (%s)'); // Translate
+@define('ADMIN_ENTRIES', 'Entries'); // Translate
+@define('RECHECK_INSTALLATION', 'Recheck installation'); // Translate
+@define('IMAGICK_EXEC_ERROR', 'Unable to execute: "%s", error: %s, return var: %d'); // Translate
+@define('INSTALL_OFFSET_DESC', 'Enter the amount of hours between the date of your webserver (current: %clock%) and your desired time zone'); // Translate
+@define('UNMET_REQUIREMENTS', 'Requirements failed: %s'); // Translate
+@define('CHARSET', 'Charset');
+@define('AUTOLANG', 'Use visitor\'s browser language as default');
+@define('AUTOLANG_DESC', 'If enabled, this will use the visitor\'s browser language setting to determine the default language of your entry and interface language.');
+@define('INSTALL_AUTODETECT_URL', 'Autodetect used HTTP-Host'); // Translate
+@define('INSTALL_AUTODETECT_URL_DESC', 'If set to "true", Serendipity will ensure that the HTTP Host which was used by your visitor is used as your BaseURL setting. Enabling this will let you be able to use multiple domain names for your Serendipity Blog, and use the domain for all follow-up links which the user used to access your blog.'); // Translate
+@define('CONVERT_HTMLENTITIES', 'Try to auto-convert HTML entities?');
+@define('EMPTY_SETTING', 'You did not specify a valid value for "%s"!');
+@define('USERCONF_REALNAME', 'Real name'); // Translate
+@define('USERCONF_REALNAME_DESC', 'The full name of the author. This is the name seen by readers'); // Translate
+@define('HOTLINK_DONE', 'File hotlinked.<br />Done.'); // Translate
+@define('ENTER_MEDIA_URL_METHOD', 'Fetch method:'); // Translate
+@define('ADD_MEDIA_BLAHBLAH_NOTE', 'Note: If you choose to hotlink to server, make sure you have permission to hotlink to the designated website, or the website is yours. Hotlink allows you to use off-site images without storing them locally.'); // Translate
+@define('MEDIA_HOTLINKED', 'hotlinked'); // Translate
+@define('FETCH_METHOD_IMAGE', 'Download image to your server'); // Translate
+@define('FETCH_METHOD_HOTLINK', 'Hotlink to server'); // Translate
+@define('DELETE_HOTLINK_FILE', 'Deleted the hotlinked file entitled <b>%s</b>'); // Translate
+@define('SYNDICATION_PLUGIN_SHOW_MAIL', 'Show E-Mail addresses?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/plugins/serendipity_event_bbcode/lang_ja.inc.php b/plugins/serendipity_event_bbcode/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..4f60911
--- /dev/null
@@ -0,0 +1,20 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_EVENT_BBCODE_NAME',     'マークアップ: BB コード');
+        @define('PLUGIN_EVENT_BBCODE_DESC',     'BB コードを使用したテキストマークアップです。');
+        @define('PLUGIN_EVENT_BBCODE_TRANSFORM', '<a href="http://www.phpbb.com/phpBB/faq.php?mode=bbcode">BB コード</a> 書式を許可します。');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_bbcode/serendipity_event_bbcode.php b/plugins/serendipity_event_bbcode/serendipity_event_bbcode.php
new file mode 100644 (file)
index 0000000..b5ad639
--- /dev/null
@@ -0,0 +1,290 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_BBCODE_NAME',     'Textformatierung: BBCode');
+        @define('PLUGIN_EVENT_BBCODE_DESC',     'BBCode-Formatierung durchführen');
+        @define('PLUGIN_EVENT_BBCODE_TRANSFORM', '<a href="http://www.phpbb.com/phpBB/faq.php?mode=bbcode">BBCode</a>-Formatierung erlaubt');
+        break;
+
+    case 'en':
+    default:
+        @define('PLUGIN_EVENT_BBCODE_NAME',     'Markup: BBCode');
+        @define('PLUGIN_EVENT_BBCODE_DESC',     'Markup text using BBCode');
+        @define('PLUGIN_EVENT_BBCODE_TRANSFORM', '<a href="http://www.phpbb.com/phpBB/faq.php?mode=bbcode">BBCode</a> format allowed');
+        break;
+}
+
+class serendipity_event_bbcode extends serendipity_event
+{
+    var $title = PLUGIN_EVENT_BBCODE_NAME;
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_BBCODE_NAME);
+        $propbag->add('description',   PLUGIN_EVENT_BBCODE_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Jez Hancock, Garvin Hicking');
+        $propbag->add('version',       '2.0');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('cachable_events', array('frontend_display' => true));
+        $propbag->add('event_hooks',   array('frontend_display' => true, 'frontend_comment' => true, 'css' => true));
+
+        $this->markup_elements = array(
+            array(
+              'name'     => 'ENTRY_BODY',
+              'element'  => 'body',
+            ),
+            array(
+              'name'     => 'EXTENDED_BODY',
+              'element'  => 'extended',
+            ),
+            array(
+              'name'     => 'COMMENT',
+              'element'  => 'comment',
+            ),
+            array(
+              'name'     => 'HTML_NUGGET',
+              'element'  => 'html_nugget',
+            )
+        );
+
+        $conf_array = array();
+        $conf_array[] = 'info';
+        foreach($this->markup_elements as $element) {
+            $conf_array[] = $element['name'];
+        }
+        $propbag->add('configuration', $conf_array);
+
+        // Only allow numbers and characters for CSS: "red", "#FF0000", ...
+        $pattern_css   = '([ 0-9a-z#-]+?)';
+
+        // Only allow strings occuring in emails: .-_@, 0-9, a-z
+        $pattern_mail  = '([\.\-\+~@_0-9a-z]+?)';
+
+        // Only allow strings occuring in URLs: &;?:.-_@/, 0-9, a-z
+        $pattern_url   = '([@\?:&;0-9a-z#\.\-_\/]+?)';
+
+        // Disallow possibly evil HTML characters which may lead to Javascript XSS: '"();
+        $pattern_query = '([^"\'\(\);]+?)';
+        
+        // Note: 
+        //  * Anything between <xxx>...</xxx> tags will be caught by htmlspecialchars() and disallows custom HTML tags.
+        //  * (?::\w+)? means "non capturing" match on any word character.
+        //  * (?<!\\\\) means any bbcode which is not prefixed by \[...]        
+        $this->bbcodes = array(
+          '/(?<!\\\\)\[color(?::\w+)?=' . $pattern_css . '\](.*?)\[\/color(?::\w+)?\]/si'                 => "<span style=\"color:\\1\">\\2</span>",
+          '/(?<!\\\\)\[size(?::\w+)?='  . $pattern_css . '\](.*?)\[\/size(?::\w+)?\]/si'                  => "<span style=\"font-size:\\1\">\\2</span>",
+          '/(?<!\\\\)\[font(?::\w+)?='  . $pattern_css . '\](.*?)\[\/font(?::\w+)?\]/si'                  => "<span style=\"font-family:\\1\">\\2</span>",
+          '/(?<!\\\\)\[align(?::\w+)?=' . $pattern_css . '\](.*?)\[\/align(?::\w+)?\]/si'                 => "<div style=\"text-align:\\1\">\\2</div>",
+
+          '/(?<!\\\\)\[b(?::\w+)?\](.*?)\[\/b(?::\w+)?\]/si'                                              => "<span style=\"font-weight:bold\">\\1</span>",
+          '/(?<!\\\\)\[i(?::\w+)?\](.*?)\[\/i(?::\w+)?\]/si'                                              => "<span style=\"font-style:italic\">\\1</span>",
+          '/(?<!\\\\)\[u(?::\w+)?\](.*?)\[\/u(?::\w+)?\]/si'                                              => "<span style=\"text-decoration:underline\">\\1</span>",
+          '/(?<!\\\\)\[center(?::\w+)?\](.*?)\[\/center(?::\w+)?\]/si'                                    => "<div style=\"text-align:center\">\\1</div>",
+
+          // [email]
+          '/(?<!\\\\)\[email(?::\w+)?\]' . $pattern_mail . '\[\/email(?::\w+)?\]/si'                      => "<a href=\"mailto:\\1\" class=\"bb-email\">\\1</a>",
+          '/(?<!\\\\)\[email(?::\w+)?='  . $pattern_mail . '\](.*?)\[\/email(?::\w+)?\]/si'               => "<a href=\"mailto:\\1\" class=\"bb-email\">\\2</a>",
+
+          // [url]
+          '/(?<!\\\\)\[(google|search)\]'   . $pattern_query . '\[\/(google|search)\]/si'                 => "<a href=\"http://www.google.com/search?q=\\2\" target=\"_blank\" class=\"bb-url\">\\2</a>",
+          '/(?<!\\\\)\[url(?::\w+)?\]www\.' . $pattern_url   . '\[\/url(?::\w+)?\]/si'                    => "<a href=\"http://www.\\1\" target=\"_blank\" class=\"bb-url\">\\1</a>",
+          '/(?<!\\\\)\[url(?::\w+)?\]'      . $pattern_url   . '\[\/url(?::\w+)?\]/si'                    => "<a href=\"\\1\" target=\"_blank\" class=\"bb-url\">\\1</a>",
+          '/(?<!\\\\)\[url(?::\w+)?='       . $pattern_url   . '?\](.*?)\[\/url(?::\w+)?\]/si'            => "<a href=\"\\1\" target=\"_blank\" class=\"bb-url\">\\2</a>",
+
+          // [img]
+          '/(?<!\\\\)\[img(?::\w+)?\]' . $pattern_url . '\[\/img(?::\w+)?\]/si'                           => "<img src=\"\\1\" alt=\"\\1\" class=\"bb-image\" />",
+          '/(?<!\\\\)\[img(?::\w+)?=([0-9]*?)x([0-9]*?)\]' . $pattern_url . '\[\/img(?::\w+)?\]/si'       => "<img width=\"\\1\" height=\"\\2\" src=\"\\3\" alt=\"\\3\" class=\"bb-image\" />",
+
+          // [quote]
+          '/(?<!\\\\)\[quote(?::\w+)?\](.*?)\[\/quote(?::\w+)?\]/si'                                      => "<div class=\"bb-code-title\">QUOTE:<div class=\"bb-code\">\\1</div></div>",
+          '/(?<!\\\\)\[quote(?::\w+)?=(?:&quot;|"|\')?(.*?)["\']?(?:&quot;|"|\')?\](.*?)\[\/quote\]/si'   => "<div class=\"bb-code-title\">QUOTE \\1:<div class=\"bb-code\">\\2</div></div>",
+
+          // [list]
+          '/(?<!\\\\)(?:\s*<br\s*\/?>\s*)?\[\*(?::\w+)?\](.*?)(?=(?:\s*<br\s*\/?>\s*)?\[\*|(?:\s*<br\s*\/?>\s*)?\[\/?list)/si' => "\n<li class=\"bb-listitem\">\\1</li>",
+          '/(?<!\\\\)(?:\s*<br\s*\/?>\s*)?\[\/list(:(?!u|o)\w+)?\](?:<br\s*\/?>)?/si'    => "\n</ul>",
+          '/(?<!\\\\)(?:\s*<br\s*\/?>\s*)?\[\/list:u(:\w+)?\](?:<br\s*\/?>)?/si'         => "\n</ul>",
+          '/(?<!\\\\)(?:\s*<br\s*\/?>\s*)?\[\/list:o(:\w+)?\](?:<br\s*\/?>)?/si'         => "\n</ol>",
+          '/(?<!\\\\)(?:\s*<br\s*\/?>\s*)?\[list(:(?!u|o)\w+)?\]\s*(?:<br\s*\/?>)?/si'   => "\n<ul class=\"bb-list-unordered\">",
+          '/(?<!\\\\)(?:\s*<br\s*\/?>\s*)?\[list:u(:\w+)?\]\s*(?:<br\s*\/?>)?/si'        => "\n<ul class=\"bb-list-unordered\">",
+          '/(?<!\\\\)(?:\s*<br\s*\/?>\s*)?\[list:o(:\w+)?\]\s*(?:<br\s*\/?>)?/si'        => "\n<ol class=\"bb-list-ordered\">",
+          '/(?<!\\\\)(?:\s*<br\s*\/?>\s*)?\[list(?::o)?(:\w+)?=1\]\s*(?:<br\s*\/?>)?/si' => "\n<ol class=\"bb-list-ordered,bb-list-ordered-d\">",
+          '/(?<!\\\\)(?:\s*<br\s*\/?>\s*)?\[list(?::o)?(:\w+)?=i\]\s*(?:<br\s*\/?>)?/s'  => "\n<ol class=\"bb-list-ordered,bb-list-ordered-lr\">",
+          '/(?<!\\\\)(?:\s*<br\s*\/?>\s*)?\[list(?::o)?(:\w+)?=I\]\s*(?:<br\s*\/?>)?/s'  => "\n<ol class=\"bb-list-ordered,bb-list-ordered-ur\">",
+          '/(?<!\\\\)(?:\s*<br\s*\/?>\s*)?\[list(?::o)?(:\w+)?=a\]\s*(?:<br\s*\/?>)?/s'  => "\n<ol class=\"bb-list-ordered,bb-list-ordered-la\">",
+          '/(?<!\\\\)(?:\s*<br\s*\/?>\s*)?\[list(?::o)?(:\w+)?=A\]\s*(?:<br\s*\/?>)?/s'  => "\n<ol class=\"bb-list-ordered,bb-list-ordered-ua\">",
+
+          // escaped tags like \[b], \[color], \[url], ...
+          '/\\\\(\[\/?\w+(?::\w+)*\])/'                                      => "\\1"
+        );
+    }
+
+
+    function bbcode_callback($matches) {
+        $type  = $matches[1];
+        $input = trim($matches[2], "\r\n");
+
+        switch ($type) {
+            case 'code':
+                $search_replace = array(
+                    '&'         => '&amp;',
+                    ' '         => '&#160;',
+                    '&lt;'      => '&#60;',
+                    '<'         => '&#60;',
+                    '&gt;'      => '&#62;',
+                    '>'         => '&#62;',
+                    '&quot;'    => '&#34;',
+                    ':'         => '&#58;',
+                    '['         => '&#91;',
+                    ']'         => '&#93;',
+                    ')'         => '&#41;',
+                    '('         => '&#40;',
+                    '*'         => '&#42;',
+                    '\t'        => '&#160;&#160;&#160;&#160;',
+                    '\\"'       => '"',
+                    "\\'"       => "'"
+                );
+
+                $input = strtr($input, $search_replace);
+                break;
+
+            case 'php':
+                if (substr($input, 0, 2) != '<?') {
+                    $input = "<?php\n\n$input\n\n?>";
+                }
+
+                ob_start();
+                highlight_string($input);
+                $input = ob_get_contents();
+                ob_end_clean();
+
+                $input = str_replace('<br />', "\n", $input);
+                break;
+
+            default:
+                return false;
+        }
+
+        $input = "<div class=\"bb-$type-title\">" . strtoupper($type) . ":</div>"
+                . "<div class=\"bb-$type\">$input</div>";
+        return($input);
+    }
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'info':
+                $propbag->add('type',        'info');
+                $propbag->add('description',  PLUGIN_EVENT_BBCODE_TRANSFORM);
+                break;
+
+            default:
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        constant($name));
+                $propbag->add('description', sprintf(APPLY_MARKUP_TO, constant($name)));
+                $propbag->add('default', 'true');
+                break;
+        }
+        return true;
+    }
+
+    function install() {
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function uninstall() {
+        serendipity_plugin_api::hook_event('backend_cache_purge', $this->title);
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function bbcode($input) {
+        /* Regular expressions taken from http://smarty.incutio.com/?page=BBCodePlugin Wiki (Andre Rabold) */
+        $input = preg_replace(array_keys($this->bbcodes), array_values($this->bbcodes), $input);
+
+        // [code] & [php]
+        $input = preg_replace_callback('/(?<!\\\\)\[(code|php)(?::\w+)?\](.*?)\[\/\\1(?::\w+)?\]/si', array($this, 'bbcode_callback'), $input);
+        return $input;
+
+    }
+
+    function event_hook($event, &$bag, &$eventData) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+
+        if (isset($hooks[$event])) {
+            switch($event) {
+                case 'frontend_display':
+
+                    foreach ($this->markup_elements as $temp) {
+                        if (serendipity_db_bool($this->get_config($temp['name'], true)) && isset($eventData[$temp['element']])) {
+                            $element = $temp['element'];
+                            $eventData[$element] = $this->bbcode($eventData[$element]);
+                        }
+                    }
+                    return true;
+                    break;
+
+                case 'frontend_comment':
+                    if (serendipity_db_bool($this->get_config('COMMENT', true))) {
+                        echo '<div class="serendipity_commentDirection">' . PLUGIN_EVENT_BBCODE_TRANSFORM . '</div>';
+                    }
+                    return true;
+                    break;
+
+                case 'css':
+                    if (strpos($eventData, '.bb-code') !== false) {
+                        // class exists in CSS, so a user has customized it and we don't need default
+                        return true;
+                    }
+?>
+.bb-code, .bb-php, .bb-code-title, .bb-php-title {
+    margin-left: 20px;
+    margin-right: 20px;
+    color: black;
+}
+
+.bb-code-title, .bb-php-title {
+    margin-bottom: 2px;
+    background-color:#CCCCCC;
+    font-weight: bold;
+    padding-left: 5px;
+}
+
+.bb-code, .bb-php {
+    font-family: courier, "courier new";
+    background-color: #DDDDDD;
+    padding: 10px;
+}
+<?php
+                return true;
+                break;
+
+                default:
+                  return false;
+            }
+        } else {
+            return false;
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_blogpdf/font/courier.php b/plugins/serendipity_event_blogpdf/font/courier.php
new file mode 100644 (file)
index 0000000..4c009f3
--- /dev/null
@@ -0,0 +1,7 @@
+<?php
+for($i=0;$i<=255;$i++)
+       $fpdf_charwidths['courier'][chr($i)]=600;
+$fpdf_charwidths['courierB']=$fpdf_charwidths['courier'];
+$fpdf_charwidths['courierI']=$fpdf_charwidths['courier'];
+$fpdf_charwidths['courierBI']=$fpdf_charwidths['courier'];
+?>
diff --git a/plugins/serendipity_event_blogpdf/font/helvetica.php b/plugins/serendipity_event_blogpdf/font/helvetica.php
new file mode 100644 (file)
index 0000000..8fa7683
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+$fpdf_charwidths['helvetica']=array(
+       chr(0)=>278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278,
+       chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>278,'"'=>355,'#'=>556,'$'=>556,'%'=>889,'&'=>667,'\''=>191,'('=>333,')'=>333,'*'=>389,'+'=>584,
+       ','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>278,';'=>278,'<'=>584,'='=>584,'>'=>584,'?'=>556,'@'=>1015,'A'=>667,
+       'B'=>667,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>500,'K'=>667,'L'=>556,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944,
+       'X'=>667,'Y'=>667,'Z'=>611,'['=>278,'\\'=>278,']'=>278,'^'=>469,'_'=>556,'`'=>333,'a'=>556,'b'=>556,'c'=>500,'d'=>556,'e'=>556,'f'=>278,'g'=>556,'h'=>556,'i'=>222,'j'=>222,'k'=>500,'l'=>222,'m'=>833,
+       'n'=>556,'o'=>556,'p'=>556,'q'=>556,'r'=>333,'s'=>500,'t'=>278,'u'=>556,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>500,'{'=>334,'|'=>260,'}'=>334,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>222,chr(131)=>556,
+       chr(132)=>333,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>222,chr(146)=>222,chr(147)=>333,chr(148)=>333,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
+       chr(154)=>500,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>260,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333,
+       chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>556,chr(182)=>537,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>667,chr(193)=>667,chr(194)=>667,chr(195)=>667,chr(196)=>667,chr(197)=>667,
+       chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722,
+       chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>500,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>556,chr(241)=>556,
+       chr(242)=>556,chr(243)=>556,chr(244)=>556,chr(245)=>556,chr(246)=>556,chr(247)=>584,chr(248)=>611,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500);
+?>
diff --git a/plugins/serendipity_event_blogpdf/font/helveticab.php b/plugins/serendipity_event_blogpdf/font/helveticab.php
new file mode 100644 (file)
index 0000000..a8473c9
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+$fpdf_charwidths['helveticaB']=array(
+       chr(0)=>278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278,
+       chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>333,'"'=>474,'#'=>556,'$'=>556,'%'=>889,'&'=>722,'\''=>238,'('=>333,')'=>333,'*'=>389,'+'=>584,
+       ','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>333,';'=>333,'<'=>584,'='=>584,'>'=>584,'?'=>611,'@'=>975,'A'=>722,
+       'B'=>722,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>556,'K'=>722,'L'=>611,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944,
+       'X'=>667,'Y'=>667,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>584,'_'=>556,'`'=>333,'a'=>556,'b'=>611,'c'=>556,'d'=>611,'e'=>556,'f'=>333,'g'=>611,'h'=>611,'i'=>278,'j'=>278,'k'=>556,'l'=>278,'m'=>889,
+       'n'=>611,'o'=>611,'p'=>611,'q'=>611,'r'=>389,'s'=>556,'t'=>333,'u'=>611,'v'=>556,'w'=>778,'x'=>556,'y'=>556,'z'=>500,'{'=>389,'|'=>280,'}'=>389,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>278,chr(131)=>556,
+       chr(132)=>500,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>278,chr(146)=>278,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
+       chr(154)=>556,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>280,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333,
+       chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>611,chr(182)=>556,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722,
+       chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722,
+       chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>556,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>611,chr(241)=>611,
+       chr(242)=>611,chr(243)=>611,chr(244)=>611,chr(245)=>611,chr(246)=>611,chr(247)=>584,chr(248)=>611,chr(249)=>611,chr(250)=>611,chr(251)=>611,chr(252)=>611,chr(253)=>556,chr(254)=>611,chr(255)=>556);
+?>
diff --git a/plugins/serendipity_event_blogpdf/font/helveticabi.php b/plugins/serendipity_event_blogpdf/font/helveticabi.php
new file mode 100644 (file)
index 0000000..4137953
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+$fpdf_charwidths['helveticaBI']=array(
+       chr(0)=>278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278,
+       chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>333,'"'=>474,'#'=>556,'$'=>556,'%'=>889,'&'=>722,'\''=>238,'('=>333,')'=>333,'*'=>389,'+'=>584,
+       ','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>333,';'=>333,'<'=>584,'='=>584,'>'=>584,'?'=>611,'@'=>975,'A'=>722,
+       'B'=>722,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>556,'K'=>722,'L'=>611,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944,
+       'X'=>667,'Y'=>667,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>584,'_'=>556,'`'=>333,'a'=>556,'b'=>611,'c'=>556,'d'=>611,'e'=>556,'f'=>333,'g'=>611,'h'=>611,'i'=>278,'j'=>278,'k'=>556,'l'=>278,'m'=>889,
+       'n'=>611,'o'=>611,'p'=>611,'q'=>611,'r'=>389,'s'=>556,'t'=>333,'u'=>611,'v'=>556,'w'=>778,'x'=>556,'y'=>556,'z'=>500,'{'=>389,'|'=>280,'}'=>389,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>278,chr(131)=>556,
+       chr(132)=>500,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>278,chr(146)=>278,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
+       chr(154)=>556,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>280,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333,
+       chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>611,chr(182)=>556,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722,
+       chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722,
+       chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>556,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>611,chr(241)=>611,
+       chr(242)=>611,chr(243)=>611,chr(244)=>611,chr(245)=>611,chr(246)=>611,chr(247)=>584,chr(248)=>611,chr(249)=>611,chr(250)=>611,chr(251)=>611,chr(252)=>611,chr(253)=>556,chr(254)=>611,chr(255)=>556);
+?>
diff --git a/plugins/serendipity_event_blogpdf/font/helveticai.php b/plugins/serendipity_event_blogpdf/font/helveticai.php
new file mode 100644 (file)
index 0000000..d5bb6e0
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+$fpdf_charwidths['helveticaI']=array(
+       chr(0)=>278,chr(1)=>278,chr(2)=>278,chr(3)=>278,chr(4)=>278,chr(5)=>278,chr(6)=>278,chr(7)=>278,chr(8)=>278,chr(9)=>278,chr(10)=>278,chr(11)=>278,chr(12)=>278,chr(13)=>278,chr(14)=>278,chr(15)=>278,chr(16)=>278,chr(17)=>278,chr(18)=>278,chr(19)=>278,chr(20)=>278,chr(21)=>278,
+       chr(22)=>278,chr(23)=>278,chr(24)=>278,chr(25)=>278,chr(26)=>278,chr(27)=>278,chr(28)=>278,chr(29)=>278,chr(30)=>278,chr(31)=>278,' '=>278,'!'=>278,'"'=>355,'#'=>556,'$'=>556,'%'=>889,'&'=>667,'\''=>191,'('=>333,')'=>333,'*'=>389,'+'=>584,
+       ','=>278,'-'=>333,'.'=>278,'/'=>278,'0'=>556,'1'=>556,'2'=>556,'3'=>556,'4'=>556,'5'=>556,'6'=>556,'7'=>556,'8'=>556,'9'=>556,':'=>278,';'=>278,'<'=>584,'='=>584,'>'=>584,'?'=>556,'@'=>1015,'A'=>667,
+       'B'=>667,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>722,'I'=>278,'J'=>500,'K'=>667,'L'=>556,'M'=>833,'N'=>722,'O'=>778,'P'=>667,'Q'=>778,'R'=>722,'S'=>667,'T'=>611,'U'=>722,'V'=>667,'W'=>944,
+       'X'=>667,'Y'=>667,'Z'=>611,'['=>278,'\\'=>278,']'=>278,'^'=>469,'_'=>556,'`'=>333,'a'=>556,'b'=>556,'c'=>500,'d'=>556,'e'=>556,'f'=>278,'g'=>556,'h'=>556,'i'=>222,'j'=>222,'k'=>500,'l'=>222,'m'=>833,
+       'n'=>556,'o'=>556,'p'=>556,'q'=>556,'r'=>333,'s'=>500,'t'=>278,'u'=>556,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>500,'{'=>334,'|'=>260,'}'=>334,'~'=>584,chr(127)=>350,chr(128)=>556,chr(129)=>350,chr(130)=>222,chr(131)=>556,
+       chr(132)=>333,chr(133)=>1000,chr(134)=>556,chr(135)=>556,chr(136)=>333,chr(137)=>1000,chr(138)=>667,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>222,chr(146)=>222,chr(147)=>333,chr(148)=>333,chr(149)=>350,chr(150)=>556,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
+       chr(154)=>500,chr(155)=>333,chr(156)=>944,chr(157)=>350,chr(158)=>500,chr(159)=>667,chr(160)=>278,chr(161)=>333,chr(162)=>556,chr(163)=>556,chr(164)=>556,chr(165)=>556,chr(166)=>260,chr(167)=>556,chr(168)=>333,chr(169)=>737,chr(170)=>370,chr(171)=>556,chr(172)=>584,chr(173)=>333,chr(174)=>737,chr(175)=>333,
+       chr(176)=>400,chr(177)=>584,chr(178)=>333,chr(179)=>333,chr(180)=>333,chr(181)=>556,chr(182)=>537,chr(183)=>278,chr(184)=>333,chr(185)=>333,chr(186)=>365,chr(187)=>556,chr(188)=>834,chr(189)=>834,chr(190)=>834,chr(191)=>611,chr(192)=>667,chr(193)=>667,chr(194)=>667,chr(195)=>667,chr(196)=>667,chr(197)=>667,
+       chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>278,chr(205)=>278,chr(206)=>278,chr(207)=>278,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>584,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722,
+       chr(220)=>722,chr(221)=>667,chr(222)=>667,chr(223)=>611,chr(224)=>556,chr(225)=>556,chr(226)=>556,chr(227)=>556,chr(228)=>556,chr(229)=>556,chr(230)=>889,chr(231)=>500,chr(232)=>556,chr(233)=>556,chr(234)=>556,chr(235)=>556,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>556,chr(241)=>556,
+       chr(242)=>556,chr(243)=>556,chr(244)=>556,chr(245)=>556,chr(246)=>556,chr(247)=>584,chr(248)=>611,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500);
+?>
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/cp1250.map b/plugins/serendipity_event_blogpdf/font/makefont/cp1250.map
new file mode 100644 (file)
index 0000000..ec110af
--- /dev/null
@@ -0,0 +1,251 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+20AC Euro
+!82 U+201A quotesinglbase
+!84 U+201E quotedblbase
+!85 U+2026 ellipsis
+!86 U+2020 dagger
+!87 U+2021 daggerdbl
+!89 U+2030 perthousand
+!8A U+0160 Scaron
+!8B U+2039 guilsinglleft
+!8C U+015A Sacute
+!8D U+0164 Tcaron
+!8E U+017D Zcaron
+!8F U+0179 Zacute
+!91 U+2018 quoteleft
+!92 U+2019 quoteright
+!93 U+201C quotedblleft
+!94 U+201D quotedblright
+!95 U+2022 bullet
+!96 U+2013 endash
+!97 U+2014 emdash
+!99 U+2122 trademark
+!9A U+0161 scaron
+!9B U+203A guilsinglright
+!9C U+015B sacute
+!9D U+0165 tcaron
+!9E U+017E zcaron
+!9F U+017A zacute
+!A0 U+00A0 space
+!A1 U+02C7 caron
+!A2 U+02D8 breve
+!A3 U+0141 Lslash
+!A4 U+00A4 currency
+!A5 U+0104 Aogonek
+!A6 U+00A6 brokenbar
+!A7 U+00A7 section
+!A8 U+00A8 dieresis
+!A9 U+00A9 copyright
+!AA U+015E Scedilla
+!AB U+00AB guillemotleft
+!AC U+00AC logicalnot
+!AD U+00AD hyphen
+!AE U+00AE registered
+!AF U+017B Zdotaccent
+!B0 U+00B0 degree
+!B1 U+00B1 plusminus
+!B2 U+02DB ogonek
+!B3 U+0142 lslash
+!B4 U+00B4 acute
+!B5 U+00B5 mu
+!B6 U+00B6 paragraph
+!B7 U+00B7 periodcentered
+!B8 U+00B8 cedilla
+!B9 U+0105 aogonek
+!BA U+015F scedilla
+!BB U+00BB guillemotright
+!BC U+013D Lcaron
+!BD U+02DD hungarumlaut
+!BE U+013E lcaron
+!BF U+017C zdotaccent
+!C0 U+0154 Racute
+!C1 U+00C1 Aacute
+!C2 U+00C2 Acircumflex
+!C3 U+0102 Abreve
+!C4 U+00C4 Adieresis
+!C5 U+0139 Lacute
+!C6 U+0106 Cacute
+!C7 U+00C7 Ccedilla
+!C8 U+010C Ccaron
+!C9 U+00C9 Eacute
+!CA U+0118 Eogonek
+!CB U+00CB Edieresis
+!CC U+011A Ecaron
+!CD U+00CD Iacute
+!CE U+00CE Icircumflex
+!CF U+010E Dcaron
+!D0 U+0110 Dcroat
+!D1 U+0143 Nacute
+!D2 U+0147 Ncaron
+!D3 U+00D3 Oacute
+!D4 U+00D4 Ocircumflex
+!D5 U+0150 Ohungarumlaut
+!D6 U+00D6 Odieresis
+!D7 U+00D7 multiply
+!D8 U+0158 Rcaron
+!D9 U+016E Uring
+!DA U+00DA Uacute
+!DB U+0170 Uhungarumlaut
+!DC U+00DC Udieresis
+!DD U+00DD Yacute
+!DE U+0162 Tcommaaccent
+!DF U+00DF germandbls
+!E0 U+0155 racute
+!E1 U+00E1 aacute
+!E2 U+00E2 acircumflex
+!E3 U+0103 abreve
+!E4 U+00E4 adieresis
+!E5 U+013A lacute
+!E6 U+0107 cacute
+!E7 U+00E7 ccedilla
+!E8 U+010D ccaron
+!E9 U+00E9 eacute
+!EA U+0119 eogonek
+!EB U+00EB edieresis
+!EC U+011B ecaron
+!ED U+00ED iacute
+!EE U+00EE icircumflex
+!EF U+010F dcaron
+!F0 U+0111 dcroat
+!F1 U+0144 nacute
+!F2 U+0148 ncaron
+!F3 U+00F3 oacute
+!F4 U+00F4 ocircumflex
+!F5 U+0151 ohungarumlaut
+!F6 U+00F6 odieresis
+!F7 U+00F7 divide
+!F8 U+0159 rcaron
+!F9 U+016F uring
+!FA U+00FA uacute
+!FB U+0171 uhungarumlaut
+!FC U+00FC udieresis
+!FD U+00FD yacute
+!FE U+0163 tcommaaccent
+!FF U+02D9 dotaccent
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/cp1251.map b/plugins/serendipity_event_blogpdf/font/makefont/cp1251.map
new file mode 100644 (file)
index 0000000..de6a198
--- /dev/null
@@ -0,0 +1,255 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+0402 afii10051
+!81 U+0403 afii10052
+!82 U+201A quotesinglbase
+!83 U+0453 afii10100
+!84 U+201E quotedblbase
+!85 U+2026 ellipsis
+!86 U+2020 dagger
+!87 U+2021 daggerdbl
+!88 U+20AC Euro
+!89 U+2030 perthousand
+!8A U+0409 afii10058
+!8B U+2039 guilsinglleft
+!8C U+040A afii10059
+!8D U+040C afii10061
+!8E U+040B afii10060
+!8F U+040F afii10145
+!90 U+0452 afii10099
+!91 U+2018 quoteleft
+!92 U+2019 quoteright
+!93 U+201C quotedblleft
+!94 U+201D quotedblright
+!95 U+2022 bullet
+!96 U+2013 endash
+!97 U+2014 emdash
+!99 U+2122 trademark
+!9A U+0459 afii10106
+!9B U+203A guilsinglright
+!9C U+045A afii10107
+!9D U+045C afii10109
+!9E U+045B afii10108
+!9F U+045F afii10193
+!A0 U+00A0 space
+!A1 U+040E afii10062
+!A2 U+045E afii10110
+!A3 U+0408 afii10057
+!A4 U+00A4 currency
+!A5 U+0490 afii10050
+!A6 U+00A6 brokenbar
+!A7 U+00A7 section
+!A8 U+0401 afii10023
+!A9 U+00A9 copyright
+!AA U+0404 afii10053
+!AB U+00AB guillemotleft
+!AC U+00AC logicalnot
+!AD U+00AD hyphen
+!AE U+00AE registered
+!AF U+0407 afii10056
+!B0 U+00B0 degree
+!B1 U+00B1 plusminus
+!B2 U+0406 afii10055
+!B3 U+0456 afii10103
+!B4 U+0491 afii10098
+!B5 U+00B5 mu
+!B6 U+00B6 paragraph
+!B7 U+00B7 periodcentered
+!B8 U+0451 afii10071
+!B9 U+2116 afii61352
+!BA U+0454 afii10101
+!BB U+00BB guillemotright
+!BC U+0458 afii10105
+!BD U+0405 afii10054
+!BE U+0455 afii10102
+!BF U+0457 afii10104
+!C0 U+0410 afii10017
+!C1 U+0411 afii10018
+!C2 U+0412 afii10019
+!C3 U+0413 afii10020
+!C4 U+0414 afii10021
+!C5 U+0415 afii10022
+!C6 U+0416 afii10024
+!C7 U+0417 afii10025
+!C8 U+0418 afii10026
+!C9 U+0419 afii10027
+!CA U+041A afii10028
+!CB U+041B afii10029
+!CC U+041C afii10030
+!CD U+041D afii10031
+!CE U+041E afii10032
+!CF U+041F afii10033
+!D0 U+0420 afii10034
+!D1 U+0421 afii10035
+!D2 U+0422 afii10036
+!D3 U+0423 afii10037
+!D4 U+0424 afii10038
+!D5 U+0425 afii10039
+!D6 U+0426 afii10040
+!D7 U+0427 afii10041
+!D8 U+0428 afii10042
+!D9 U+0429 afii10043
+!DA U+042A afii10044
+!DB U+042B afii10045
+!DC U+042C afii10046
+!DD U+042D afii10047
+!DE U+042E afii10048
+!DF U+042F afii10049
+!E0 U+0430 afii10065
+!E1 U+0431 afii10066
+!E2 U+0432 afii10067
+!E3 U+0433 afii10068
+!E4 U+0434 afii10069
+!E5 U+0435 afii10070
+!E6 U+0436 afii10072
+!E7 U+0437 afii10073
+!E8 U+0438 afii10074
+!E9 U+0439 afii10075
+!EA U+043A afii10076
+!EB U+043B afii10077
+!EC U+043C afii10078
+!ED U+043D afii10079
+!EE U+043E afii10080
+!EF U+043F afii10081
+!F0 U+0440 afii10082
+!F1 U+0441 afii10083
+!F2 U+0442 afii10084
+!F3 U+0443 afii10085
+!F4 U+0444 afii10086
+!F5 U+0445 afii10087
+!F6 U+0446 afii10088
+!F7 U+0447 afii10089
+!F8 U+0448 afii10090
+!F9 U+0449 afii10091
+!FA U+044A afii10092
+!FB U+044B afii10093
+!FC U+044C afii10094
+!FD U+044D afii10095
+!FE U+044E afii10096
+!FF U+044F afii10097
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/cp1252.map b/plugins/serendipity_event_blogpdf/font/makefont/cp1252.map
new file mode 100644 (file)
index 0000000..dd490e5
--- /dev/null
@@ -0,0 +1,251 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+20AC Euro
+!82 U+201A quotesinglbase
+!83 U+0192 florin
+!84 U+201E quotedblbase
+!85 U+2026 ellipsis
+!86 U+2020 dagger
+!87 U+2021 daggerdbl
+!88 U+02C6 circumflex
+!89 U+2030 perthousand
+!8A U+0160 Scaron
+!8B U+2039 guilsinglleft
+!8C U+0152 OE
+!8E U+017D Zcaron
+!91 U+2018 quoteleft
+!92 U+2019 quoteright
+!93 U+201C quotedblleft
+!94 U+201D quotedblright
+!95 U+2022 bullet
+!96 U+2013 endash
+!97 U+2014 emdash
+!98 U+02DC tilde
+!99 U+2122 trademark
+!9A U+0161 scaron
+!9B U+203A guilsinglright
+!9C U+0153 oe
+!9E U+017E zcaron
+!9F U+0178 Ydieresis
+!A0 U+00A0 space
+!A1 U+00A1 exclamdown
+!A2 U+00A2 cent
+!A3 U+00A3 sterling
+!A4 U+00A4 currency
+!A5 U+00A5 yen
+!A6 U+00A6 brokenbar
+!A7 U+00A7 section
+!A8 U+00A8 dieresis
+!A9 U+00A9 copyright
+!AA U+00AA ordfeminine
+!AB U+00AB guillemotleft
+!AC U+00AC logicalnot
+!AD U+00AD hyphen
+!AE U+00AE registered
+!AF U+00AF macron
+!B0 U+00B0 degree
+!B1 U+00B1 plusminus
+!B2 U+00B2 twosuperior
+!B3 U+00B3 threesuperior
+!B4 U+00B4 acute
+!B5 U+00B5 mu
+!B6 U+00B6 paragraph
+!B7 U+00B7 periodcentered
+!B8 U+00B8 cedilla
+!B9 U+00B9 onesuperior
+!BA U+00BA ordmasculine
+!BB U+00BB guillemotright
+!BC U+00BC onequarter
+!BD U+00BD onehalf
+!BE U+00BE threequarters
+!BF U+00BF questiondown
+!C0 U+00C0 Agrave
+!C1 U+00C1 Aacute
+!C2 U+00C2 Acircumflex
+!C3 U+00C3 Atilde
+!C4 U+00C4 Adieresis
+!C5 U+00C5 Aring
+!C6 U+00C6 AE
+!C7 U+00C7 Ccedilla
+!C8 U+00C8 Egrave
+!C9 U+00C9 Eacute
+!CA U+00CA Ecircumflex
+!CB U+00CB Edieresis
+!CC U+00CC Igrave
+!CD U+00CD Iacute
+!CE U+00CE Icircumflex
+!CF U+00CF Idieresis
+!D0 U+00D0 Eth
+!D1 U+00D1 Ntilde
+!D2 U+00D2 Ograve
+!D3 U+00D3 Oacute
+!D4 U+00D4 Ocircumflex
+!D5 U+00D5 Otilde
+!D6 U+00D6 Odieresis
+!D7 U+00D7 multiply
+!D8 U+00D8 Oslash
+!D9 U+00D9 Ugrave
+!DA U+00DA Uacute
+!DB U+00DB Ucircumflex
+!DC U+00DC Udieresis
+!DD U+00DD Yacute
+!DE U+00DE Thorn
+!DF U+00DF germandbls
+!E0 U+00E0 agrave
+!E1 U+00E1 aacute
+!E2 U+00E2 acircumflex
+!E3 U+00E3 atilde
+!E4 U+00E4 adieresis
+!E5 U+00E5 aring
+!E6 U+00E6 ae
+!E7 U+00E7 ccedilla
+!E8 U+00E8 egrave
+!E9 U+00E9 eacute
+!EA U+00EA ecircumflex
+!EB U+00EB edieresis
+!EC U+00EC igrave
+!ED U+00ED iacute
+!EE U+00EE icircumflex
+!EF U+00EF idieresis
+!F0 U+00F0 eth
+!F1 U+00F1 ntilde
+!F2 U+00F2 ograve
+!F3 U+00F3 oacute
+!F4 U+00F4 ocircumflex
+!F5 U+00F5 otilde
+!F6 U+00F6 odieresis
+!F7 U+00F7 divide
+!F8 U+00F8 oslash
+!F9 U+00F9 ugrave
+!FA U+00FA uacute
+!FB U+00FB ucircumflex
+!FC U+00FC udieresis
+!FD U+00FD yacute
+!FE U+00FE thorn
+!FF U+00FF ydieresis
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/cp1253.map b/plugins/serendipity_event_blogpdf/font/makefont/cp1253.map
new file mode 100644 (file)
index 0000000..4bd826f
--- /dev/null
@@ -0,0 +1,239 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+20AC Euro
+!82 U+201A quotesinglbase
+!83 U+0192 florin
+!84 U+201E quotedblbase
+!85 U+2026 ellipsis
+!86 U+2020 dagger
+!87 U+2021 daggerdbl
+!89 U+2030 perthousand
+!8B U+2039 guilsinglleft
+!91 U+2018 quoteleft
+!92 U+2019 quoteright
+!93 U+201C quotedblleft
+!94 U+201D quotedblright
+!95 U+2022 bullet
+!96 U+2013 endash
+!97 U+2014 emdash
+!99 U+2122 trademark
+!9B U+203A guilsinglright
+!A0 U+00A0 space
+!A1 U+0385 dieresistonos
+!A2 U+0386 Alphatonos
+!A3 U+00A3 sterling
+!A4 U+00A4 currency
+!A5 U+00A5 yen
+!A6 U+00A6 brokenbar
+!A7 U+00A7 section
+!A8 U+00A8 dieresis
+!A9 U+00A9 copyright
+!AB U+00AB guillemotleft
+!AC U+00AC logicalnot
+!AD U+00AD hyphen
+!AE U+00AE registered
+!AF U+2015 afii00208
+!B0 U+00B0 degree
+!B1 U+00B1 plusminus
+!B2 U+00B2 twosuperior
+!B3 U+00B3 threesuperior
+!B4 U+0384 tonos
+!B5 U+00B5 mu
+!B6 U+00B6 paragraph
+!B7 U+00B7 periodcentered
+!B8 U+0388 Epsilontonos
+!B9 U+0389 Etatonos
+!BA U+038A Iotatonos
+!BB U+00BB guillemotright
+!BC U+038C Omicrontonos
+!BD U+00BD onehalf
+!BE U+038E Upsilontonos
+!BF U+038F Omegatonos
+!C0 U+0390 iotadieresistonos
+!C1 U+0391 Alpha
+!C2 U+0392 Beta
+!C3 U+0393 Gamma
+!C4 U+0394 Delta
+!C5 U+0395 Epsilon
+!C6 U+0396 Zeta
+!C7 U+0397 Eta
+!C8 U+0398 Theta
+!C9 U+0399 Iota
+!CA U+039A Kappa
+!CB U+039B Lambda
+!CC U+039C Mu
+!CD U+039D Nu
+!CE U+039E Xi
+!CF U+039F Omicron
+!D0 U+03A0 Pi
+!D1 U+03A1 Rho
+!D3 U+03A3 Sigma
+!D4 U+03A4 Tau
+!D5 U+03A5 Upsilon
+!D6 U+03A6 Phi
+!D7 U+03A7 Chi
+!D8 U+03A8 Psi
+!D9 U+03A9 Omega
+!DA U+03AA Iotadieresis
+!DB U+03AB Upsilondieresis
+!DC U+03AC alphatonos
+!DD U+03AD epsilontonos
+!DE U+03AE etatonos
+!DF U+03AF iotatonos
+!E0 U+03B0 upsilondieresistonos
+!E1 U+03B1 alpha
+!E2 U+03B2 beta
+!E3 U+03B3 gamma
+!E4 U+03B4 delta
+!E5 U+03B5 epsilon
+!E6 U+03B6 zeta
+!E7 U+03B7 eta
+!E8 U+03B8 theta
+!E9 U+03B9 iota
+!EA U+03BA kappa
+!EB U+03BB lambda
+!EC U+03BC mu
+!ED U+03BD nu
+!EE U+03BE xi
+!EF U+03BF omicron
+!F0 U+03C0 pi
+!F1 U+03C1 rho
+!F2 U+03C2 sigma1
+!F3 U+03C3 sigma
+!F4 U+03C4 tau
+!F5 U+03C5 upsilon
+!F6 U+03C6 phi
+!F7 U+03C7 chi
+!F8 U+03C8 psi
+!F9 U+03C9 omega
+!FA U+03CA iotadieresis
+!FB U+03CB upsilondieresis
+!FC U+03CC omicrontonos
+!FD U+03CD upsilontonos
+!FE U+03CE omegatonos
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/cp1254.map b/plugins/serendipity_event_blogpdf/font/makefont/cp1254.map
new file mode 100644 (file)
index 0000000..829473b
--- /dev/null
@@ -0,0 +1,249 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+20AC Euro
+!82 U+201A quotesinglbase
+!83 U+0192 florin
+!84 U+201E quotedblbase
+!85 U+2026 ellipsis
+!86 U+2020 dagger
+!87 U+2021 daggerdbl
+!88 U+02C6 circumflex
+!89 U+2030 perthousand
+!8A U+0160 Scaron
+!8B U+2039 guilsinglleft
+!8C U+0152 OE
+!91 U+2018 quoteleft
+!92 U+2019 quoteright
+!93 U+201C quotedblleft
+!94 U+201D quotedblright
+!95 U+2022 bullet
+!96 U+2013 endash
+!97 U+2014 emdash
+!98 U+02DC tilde
+!99 U+2122 trademark
+!9A U+0161 scaron
+!9B U+203A guilsinglright
+!9C U+0153 oe
+!9F U+0178 Ydieresis
+!A0 U+00A0 space
+!A1 U+00A1 exclamdown
+!A2 U+00A2 cent
+!A3 U+00A3 sterling
+!A4 U+00A4 currency
+!A5 U+00A5 yen
+!A6 U+00A6 brokenbar
+!A7 U+00A7 section
+!A8 U+00A8 dieresis
+!A9 U+00A9 copyright
+!AA U+00AA ordfeminine
+!AB U+00AB guillemotleft
+!AC U+00AC logicalnot
+!AD U+00AD hyphen
+!AE U+00AE registered
+!AF U+00AF macron
+!B0 U+00B0 degree
+!B1 U+00B1 plusminus
+!B2 U+00B2 twosuperior
+!B3 U+00B3 threesuperior
+!B4 U+00B4 acute
+!B5 U+00B5 mu
+!B6 U+00B6 paragraph
+!B7 U+00B7 periodcentered
+!B8 U+00B8 cedilla
+!B9 U+00B9 onesuperior
+!BA U+00BA ordmasculine
+!BB U+00BB guillemotright
+!BC U+00BC onequarter
+!BD U+00BD onehalf
+!BE U+00BE threequarters
+!BF U+00BF questiondown
+!C0 U+00C0 Agrave
+!C1 U+00C1 Aacute
+!C2 U+00C2 Acircumflex
+!C3 U+00C3 Atilde
+!C4 U+00C4 Adieresis
+!C5 U+00C5 Aring
+!C6 U+00C6 AE
+!C7 U+00C7 Ccedilla
+!C8 U+00C8 Egrave
+!C9 U+00C9 Eacute
+!CA U+00CA Ecircumflex
+!CB U+00CB Edieresis
+!CC U+00CC Igrave
+!CD U+00CD Iacute
+!CE U+00CE Icircumflex
+!CF U+00CF Idieresis
+!D0 U+011E Gbreve
+!D1 U+00D1 Ntilde
+!D2 U+00D2 Ograve
+!D3 U+00D3 Oacute
+!D4 U+00D4 Ocircumflex
+!D5 U+00D5 Otilde
+!D6 U+00D6 Odieresis
+!D7 U+00D7 multiply
+!D8 U+00D8 Oslash
+!D9 U+00D9 Ugrave
+!DA U+00DA Uacute
+!DB U+00DB Ucircumflex
+!DC U+00DC Udieresis
+!DD U+0130 Idotaccent
+!DE U+015E Scedilla
+!DF U+00DF germandbls
+!E0 U+00E0 agrave
+!E1 U+00E1 aacute
+!E2 U+00E2 acircumflex
+!E3 U+00E3 atilde
+!E4 U+00E4 adieresis
+!E5 U+00E5 aring
+!E6 U+00E6 ae
+!E7 U+00E7 ccedilla
+!E8 U+00E8 egrave
+!E9 U+00E9 eacute
+!EA U+00EA ecircumflex
+!EB U+00EB edieresis
+!EC U+00EC igrave
+!ED U+00ED iacute
+!EE U+00EE icircumflex
+!EF U+00EF idieresis
+!F0 U+011F gbreve
+!F1 U+00F1 ntilde
+!F2 U+00F2 ograve
+!F3 U+00F3 oacute
+!F4 U+00F4 ocircumflex
+!F5 U+00F5 otilde
+!F6 U+00F6 odieresis
+!F7 U+00F7 divide
+!F8 U+00F8 oslash
+!F9 U+00F9 ugrave
+!FA U+00FA uacute
+!FB U+00FB ucircumflex
+!FC U+00FC udieresis
+!FD U+0131 dotlessi
+!FE U+015F scedilla
+!FF U+00FF ydieresis
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/cp1255.map b/plugins/serendipity_event_blogpdf/font/makefont/cp1255.map
new file mode 100644 (file)
index 0000000..079e10c
--- /dev/null
@@ -0,0 +1,233 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+20AC Euro
+!82 U+201A quotesinglbase
+!83 U+0192 florin
+!84 U+201E quotedblbase
+!85 U+2026 ellipsis
+!86 U+2020 dagger
+!87 U+2021 daggerdbl
+!88 U+02C6 circumflex
+!89 U+2030 perthousand
+!8B U+2039 guilsinglleft
+!91 U+2018 quoteleft
+!92 U+2019 quoteright
+!93 U+201C quotedblleft
+!94 U+201D quotedblright
+!95 U+2022 bullet
+!96 U+2013 endash
+!97 U+2014 emdash
+!98 U+02DC tilde
+!99 U+2122 trademark
+!9B U+203A guilsinglright
+!A0 U+00A0 space
+!A1 U+00A1 exclamdown
+!A2 U+00A2 cent
+!A3 U+00A3 sterling
+!A4 U+20AA afii57636
+!A5 U+00A5 yen
+!A6 U+00A6 brokenbar
+!A7 U+00A7 section
+!A8 U+00A8 dieresis
+!A9 U+00A9 copyright
+!AA U+00D7 multiply
+!AB U+00AB guillemotleft
+!AC U+00AC logicalnot
+!AD U+00AD sfthyphen
+!AE U+00AE registered
+!AF U+00AF macron
+!B0 U+00B0 degree
+!B1 U+00B1 plusminus
+!B2 U+00B2 twosuperior
+!B3 U+00B3 threesuperior
+!B4 U+00B4 acute
+!B5 U+00B5 mu
+!B6 U+00B6 paragraph
+!B7 U+00B7 middot
+!B8 U+00B8 cedilla
+!B9 U+00B9 onesuperior
+!BA U+00F7 divide
+!BB U+00BB guillemotright
+!BC U+00BC onequarter
+!BD U+00BD onehalf
+!BE U+00BE threequarters
+!BF U+00BF questiondown
+!C0 U+05B0 afii57799
+!C1 U+05B1 afii57801
+!C2 U+05B2 afii57800
+!C3 U+05B3 afii57802
+!C4 U+05B4 afii57793
+!C5 U+05B5 afii57794
+!C6 U+05B6 afii57795
+!C7 U+05B7 afii57798
+!C8 U+05B8 afii57797
+!C9 U+05B9 afii57806
+!CB U+05BB afii57796
+!CC U+05BC afii57807
+!CD U+05BD afii57839
+!CE U+05BE afii57645
+!CF U+05BF afii57841
+!D0 U+05C0 afii57842
+!D1 U+05C1 afii57804
+!D2 U+05C2 afii57803
+!D3 U+05C3 afii57658
+!D4 U+05F0 afii57716
+!D5 U+05F1 afii57717
+!D6 U+05F2 afii57718
+!D7 U+05F3 gereshhebrew
+!D8 U+05F4 gershayimhebrew
+!E0 U+05D0 afii57664
+!E1 U+05D1 afii57665
+!E2 U+05D2 afii57666
+!E3 U+05D3 afii57667
+!E4 U+05D4 afii57668
+!E5 U+05D5 afii57669
+!E6 U+05D6 afii57670
+!E7 U+05D7 afii57671
+!E8 U+05D8 afii57672
+!E9 U+05D9 afii57673
+!EA U+05DA afii57674
+!EB U+05DB afii57675
+!EC U+05DC afii57676
+!ED U+05DD afii57677
+!EE U+05DE afii57678
+!EF U+05DF afii57679
+!F0 U+05E0 afii57680
+!F1 U+05E1 afii57681
+!F2 U+05E2 afii57682
+!F3 U+05E3 afii57683
+!F4 U+05E4 afii57684
+!F5 U+05E5 afii57685
+!F6 U+05E6 afii57686
+!F7 U+05E7 afii57687
+!F8 U+05E8 afii57688
+!F9 U+05E9 afii57689
+!FA U+05EA afii57690
+!FD U+200E afii299
+!FE U+200F afii300
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/cp1257.map b/plugins/serendipity_event_blogpdf/font/makefont/cp1257.map
new file mode 100644 (file)
index 0000000..2f2ecfa
--- /dev/null
@@ -0,0 +1,244 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+20AC Euro
+!82 U+201A quotesinglbase
+!84 U+201E quotedblbase
+!85 U+2026 ellipsis
+!86 U+2020 dagger
+!87 U+2021 daggerdbl
+!89 U+2030 perthousand
+!8B U+2039 guilsinglleft
+!8D U+00A8 dieresis
+!8E U+02C7 caron
+!8F U+00B8 cedilla
+!91 U+2018 quoteleft
+!92 U+2019 quoteright
+!93 U+201C quotedblleft
+!94 U+201D quotedblright
+!95 U+2022 bullet
+!96 U+2013 endash
+!97 U+2014 emdash
+!99 U+2122 trademark
+!9B U+203A guilsinglright
+!9D U+00AF macron
+!9E U+02DB ogonek
+!A0 U+00A0 space
+!A2 U+00A2 cent
+!A3 U+00A3 sterling
+!A4 U+00A4 currency
+!A6 U+00A6 brokenbar
+!A7 U+00A7 section
+!A8 U+00D8 Oslash
+!A9 U+00A9 copyright
+!AA U+0156 Rcommaaccent
+!AB U+00AB guillemotleft
+!AC U+00AC logicalnot
+!AD U+00AD hyphen
+!AE U+00AE registered
+!AF U+00C6 AE
+!B0 U+00B0 degree
+!B1 U+00B1 plusminus
+!B2 U+00B2 twosuperior
+!B3 U+00B3 threesuperior
+!B4 U+00B4 acute
+!B5 U+00B5 mu
+!B6 U+00B6 paragraph
+!B7 U+00B7 periodcentered
+!B8 U+00F8 oslash
+!B9 U+00B9 onesuperior
+!BA U+0157 rcommaaccent
+!BB U+00BB guillemotright
+!BC U+00BC onequarter
+!BD U+00BD onehalf
+!BE U+00BE threequarters
+!BF U+00E6 ae
+!C0 U+0104 Aogonek
+!C1 U+012E Iogonek
+!C2 U+0100 Amacron
+!C3 U+0106 Cacute
+!C4 U+00C4 Adieresis
+!C5 U+00C5 Aring
+!C6 U+0118 Eogonek
+!C7 U+0112 Emacron
+!C8 U+010C Ccaron
+!C9 U+00C9 Eacute
+!CA U+0179 Zacute
+!CB U+0116 Edotaccent
+!CC U+0122 Gcommaaccent
+!CD U+0136 Kcommaaccent
+!CE U+012A Imacron
+!CF U+013B Lcommaaccent
+!D0 U+0160 Scaron
+!D1 U+0143 Nacute
+!D2 U+0145 Ncommaaccent
+!D3 U+00D3 Oacute
+!D4 U+014C Omacron
+!D5 U+00D5 Otilde
+!D6 U+00D6 Odieresis
+!D7 U+00D7 multiply
+!D8 U+0172 Uogonek
+!D9 U+0141 Lslash
+!DA U+015A Sacute
+!DB U+016A Umacron
+!DC U+00DC Udieresis
+!DD U+017B Zdotaccent
+!DE U+017D Zcaron
+!DF U+00DF germandbls
+!E0 U+0105 aogonek
+!E1 U+012F iogonek
+!E2 U+0101 amacron
+!E3 U+0107 cacute
+!E4 U+00E4 adieresis
+!E5 U+00E5 aring
+!E6 U+0119 eogonek
+!E7 U+0113 emacron
+!E8 U+010D ccaron
+!E9 U+00E9 eacute
+!EA U+017A zacute
+!EB U+0117 edotaccent
+!EC U+0123 gcommaaccent
+!ED U+0137 kcommaaccent
+!EE U+012B imacron
+!EF U+013C lcommaaccent
+!F0 U+0161 scaron
+!F1 U+0144 nacute
+!F2 U+0146 ncommaaccent
+!F3 U+00F3 oacute
+!F4 U+014D omacron
+!F5 U+00F5 otilde
+!F6 U+00F6 odieresis
+!F7 U+00F7 divide
+!F8 U+0173 uogonek
+!F9 U+0142 lslash
+!FA U+015B sacute
+!FB U+016B umacron
+!FC U+00FC udieresis
+!FD U+017C zdotaccent
+!FE U+017E zcaron
+!FF U+02D9 dotaccent
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/cp1258.map b/plugins/serendipity_event_blogpdf/font/makefont/cp1258.map
new file mode 100644 (file)
index 0000000..fed915f
--- /dev/null
@@ -0,0 +1,247 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+20AC Euro
+!82 U+201A quotesinglbase
+!83 U+0192 florin
+!84 U+201E quotedblbase
+!85 U+2026 ellipsis
+!86 U+2020 dagger
+!87 U+2021 daggerdbl
+!88 U+02C6 circumflex
+!89 U+2030 perthousand
+!8B U+2039 guilsinglleft
+!8C U+0152 OE
+!91 U+2018 quoteleft
+!92 U+2019 quoteright
+!93 U+201C quotedblleft
+!94 U+201D quotedblright
+!95 U+2022 bullet
+!96 U+2013 endash
+!97 U+2014 emdash
+!98 U+02DC tilde
+!99 U+2122 trademark
+!9B U+203A guilsinglright
+!9C U+0153 oe
+!9F U+0178 Ydieresis
+!A0 U+00A0 space
+!A1 U+00A1 exclamdown
+!A2 U+00A2 cent
+!A3 U+00A3 sterling
+!A4 U+00A4 currency
+!A5 U+00A5 yen
+!A6 U+00A6 brokenbar
+!A7 U+00A7 section
+!A8 U+00A8 dieresis
+!A9 U+00A9 copyright
+!AA U+00AA ordfeminine
+!AB U+00AB guillemotleft
+!AC U+00AC logicalnot
+!AD U+00AD hyphen
+!AE U+00AE registered
+!AF U+00AF macron
+!B0 U+00B0 degree
+!B1 U+00B1 plusminus
+!B2 U+00B2 twosuperior
+!B3 U+00B3 threesuperior
+!B4 U+00B4 acute
+!B5 U+00B5 mu
+!B6 U+00B6 paragraph
+!B7 U+00B7 periodcentered
+!B8 U+00B8 cedilla
+!B9 U+00B9 onesuperior
+!BA U+00BA ordmasculine
+!BB U+00BB guillemotright
+!BC U+00BC onequarter
+!BD U+00BD onehalf
+!BE U+00BE threequarters
+!BF U+00BF questiondown
+!C0 U+00C0 Agrave
+!C1 U+00C1 Aacute
+!C2 U+00C2 Acircumflex
+!C3 U+0102 Abreve
+!C4 U+00C4 Adieresis
+!C5 U+00C5 Aring
+!C6 U+00C6 AE
+!C7 U+00C7 Ccedilla
+!C8 U+00C8 Egrave
+!C9 U+00C9 Eacute
+!CA U+00CA Ecircumflex
+!CB U+00CB Edieresis
+!CC U+0300 gravecomb
+!CD U+00CD Iacute
+!CE U+00CE Icircumflex
+!CF U+00CF Idieresis
+!D0 U+0110 Dcroat
+!D1 U+00D1 Ntilde
+!D2 U+0309 hookabovecomb
+!D3 U+00D3 Oacute
+!D4 U+00D4 Ocircumflex
+!D5 U+01A0 Ohorn
+!D6 U+00D6 Odieresis
+!D7 U+00D7 multiply
+!D8 U+00D8 Oslash
+!D9 U+00D9 Ugrave
+!DA U+00DA Uacute
+!DB U+00DB Ucircumflex
+!DC U+00DC Udieresis
+!DD U+01AF Uhorn
+!DE U+0303 tildecomb
+!DF U+00DF germandbls
+!E0 U+00E0 agrave
+!E1 U+00E1 aacute
+!E2 U+00E2 acircumflex
+!E3 U+0103 abreve
+!E4 U+00E4 adieresis
+!E5 U+00E5 aring
+!E6 U+00E6 ae
+!E7 U+00E7 ccedilla
+!E8 U+00E8 egrave
+!E9 U+00E9 eacute
+!EA U+00EA ecircumflex
+!EB U+00EB edieresis
+!EC U+0301 acutecomb
+!ED U+00ED iacute
+!EE U+00EE icircumflex
+!EF U+00EF idieresis
+!F0 U+0111 dcroat
+!F1 U+00F1 ntilde
+!F2 U+0323 dotbelowcomb
+!F3 U+00F3 oacute
+!F4 U+00F4 ocircumflex
+!F5 U+01A1 ohorn
+!F6 U+00F6 odieresis
+!F7 U+00F7 divide
+!F8 U+00F8 oslash
+!F9 U+00F9 ugrave
+!FA U+00FA uacute
+!FB U+00FB ucircumflex
+!FC U+00FC udieresis
+!FD U+01B0 uhorn
+!FE U+20AB dong
+!FF U+00FF ydieresis
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/cp874.map b/plugins/serendipity_event_blogpdf/font/makefont/cp874.map
new file mode 100644 (file)
index 0000000..1006e6b
--- /dev/null
@@ -0,0 +1,225 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+20AC Euro
+!85 U+2026 ellipsis
+!91 U+2018 quoteleft
+!92 U+2019 quoteright
+!93 U+201C quotedblleft
+!94 U+201D quotedblright
+!95 U+2022 bullet
+!96 U+2013 endash
+!97 U+2014 emdash
+!A0 U+00A0 space
+!A1 U+0E01 kokaithai
+!A2 U+0E02 khokhaithai
+!A3 U+0E03 khokhuatthai
+!A4 U+0E04 khokhwaithai
+!A5 U+0E05 khokhonthai
+!A6 U+0E06 khorakhangthai
+!A7 U+0E07 ngonguthai
+!A8 U+0E08 chochanthai
+!A9 U+0E09 chochingthai
+!AA U+0E0A chochangthai
+!AB U+0E0B sosothai
+!AC U+0E0C chochoethai
+!AD U+0E0D yoyingthai
+!AE U+0E0E dochadathai
+!AF U+0E0F topatakthai
+!B0 U+0E10 thothanthai
+!B1 U+0E11 thonangmonthothai
+!B2 U+0E12 thophuthaothai
+!B3 U+0E13 nonenthai
+!B4 U+0E14 dodekthai
+!B5 U+0E15 totaothai
+!B6 U+0E16 thothungthai
+!B7 U+0E17 thothahanthai
+!B8 U+0E18 thothongthai
+!B9 U+0E19 nonuthai
+!BA U+0E1A bobaimaithai
+!BB U+0E1B poplathai
+!BC U+0E1C phophungthai
+!BD U+0E1D fofathai
+!BE U+0E1E phophanthai
+!BF U+0E1F fofanthai
+!C0 U+0E20 phosamphaothai
+!C1 U+0E21 momathai
+!C2 U+0E22 yoyakthai
+!C3 U+0E23 roruathai
+!C4 U+0E24 ruthai
+!C5 U+0E25 lolingthai
+!C6 U+0E26 luthai
+!C7 U+0E27 wowaenthai
+!C8 U+0E28 sosalathai
+!C9 U+0E29 sorusithai
+!CA U+0E2A sosuathai
+!CB U+0E2B hohipthai
+!CC U+0E2C lochulathai
+!CD U+0E2D oangthai
+!CE U+0E2E honokhukthai
+!CF U+0E2F paiyannoithai
+!D0 U+0E30 saraathai
+!D1 U+0E31 maihanakatthai
+!D2 U+0E32 saraaathai
+!D3 U+0E33 saraamthai
+!D4 U+0E34 saraithai
+!D5 U+0E35 saraiithai
+!D6 U+0E36 sarauethai
+!D7 U+0E37 saraueethai
+!D8 U+0E38 sarauthai
+!D9 U+0E39 sarauuthai
+!DA U+0E3A phinthuthai
+!DF U+0E3F bahtthai
+!E0 U+0E40 saraethai
+!E1 U+0E41 saraaethai
+!E2 U+0E42 saraothai
+!E3 U+0E43 saraaimaimuanthai
+!E4 U+0E44 saraaimaimalaithai
+!E5 U+0E45 lakkhangyaothai
+!E6 U+0E46 maiyamokthai
+!E7 U+0E47 maitaikhuthai
+!E8 U+0E48 maiekthai
+!E9 U+0E49 maithothai
+!EA U+0E4A maitrithai
+!EB U+0E4B maichattawathai
+!EC U+0E4C thanthakhatthai
+!ED U+0E4D nikhahitthai
+!EE U+0E4E yamakkanthai
+!EF U+0E4F fongmanthai
+!F0 U+0E50 zerothai
+!F1 U+0E51 onethai
+!F2 U+0E52 twothai
+!F3 U+0E53 threethai
+!F4 U+0E54 fourthai
+!F5 U+0E55 fivethai
+!F6 U+0E56 sixthai
+!F7 U+0E57 seventhai
+!F8 U+0E58 eightthai
+!F9 U+0E59 ninethai
+!FA U+0E5A angkhankhuthai
+!FB U+0E5B khomutthai
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-1.map b/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-1.map
new file mode 100644 (file)
index 0000000..61740a3
--- /dev/null
@@ -0,0 +1,256 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+0080 .notdef
+!81 U+0081 .notdef
+!82 U+0082 .notdef
+!83 U+0083 .notdef
+!84 U+0084 .notdef
+!85 U+0085 .notdef
+!86 U+0086 .notdef
+!87 U+0087 .notdef
+!88 U+0088 .notdef
+!89 U+0089 .notdef
+!8A U+008A .notdef
+!8B U+008B .notdef
+!8C U+008C .notdef
+!8D U+008D .notdef
+!8E U+008E .notdef
+!8F U+008F .notdef
+!90 U+0090 .notdef
+!91 U+0091 .notdef
+!92 U+0092 .notdef
+!93 U+0093 .notdef
+!94 U+0094 .notdef
+!95 U+0095 .notdef
+!96 U+0096 .notdef
+!97 U+0097 .notdef
+!98 U+0098 .notdef
+!99 U+0099 .notdef
+!9A U+009A .notdef
+!9B U+009B .notdef
+!9C U+009C .notdef
+!9D U+009D .notdef
+!9E U+009E .notdef
+!9F U+009F .notdef
+!A0 U+00A0 space
+!A1 U+00A1 exclamdown
+!A2 U+00A2 cent
+!A3 U+00A3 sterling
+!A4 U+00A4 currency
+!A5 U+00A5 yen
+!A6 U+00A6 brokenbar
+!A7 U+00A7 section
+!A8 U+00A8 dieresis
+!A9 U+00A9 copyright
+!AA U+00AA ordfeminine
+!AB U+00AB guillemotleft
+!AC U+00AC logicalnot
+!AD U+00AD hyphen
+!AE U+00AE registered
+!AF U+00AF macron
+!B0 U+00B0 degree
+!B1 U+00B1 plusminus
+!B2 U+00B2 twosuperior
+!B3 U+00B3 threesuperior
+!B4 U+00B4 acute
+!B5 U+00B5 mu
+!B6 U+00B6 paragraph
+!B7 U+00B7 periodcentered
+!B8 U+00B8 cedilla
+!B9 U+00B9 onesuperior
+!BA U+00BA ordmasculine
+!BB U+00BB guillemotright
+!BC U+00BC onequarter
+!BD U+00BD onehalf
+!BE U+00BE threequarters
+!BF U+00BF questiondown
+!C0 U+00C0 Agrave
+!C1 U+00C1 Aacute
+!C2 U+00C2 Acircumflex
+!C3 U+00C3 Atilde
+!C4 U+00C4 Adieresis
+!C5 U+00C5 Aring
+!C6 U+00C6 AE
+!C7 U+00C7 Ccedilla
+!C8 U+00C8 Egrave
+!C9 U+00C9 Eacute
+!CA U+00CA Ecircumflex
+!CB U+00CB Edieresis
+!CC U+00CC Igrave
+!CD U+00CD Iacute
+!CE U+00CE Icircumflex
+!CF U+00CF Idieresis
+!D0 U+00D0 Eth
+!D1 U+00D1 Ntilde
+!D2 U+00D2 Ograve
+!D3 U+00D3 Oacute
+!D4 U+00D4 Ocircumflex
+!D5 U+00D5 Otilde
+!D6 U+00D6 Odieresis
+!D7 U+00D7 multiply
+!D8 U+00D8 Oslash
+!D9 U+00D9 Ugrave
+!DA U+00DA Uacute
+!DB U+00DB Ucircumflex
+!DC U+00DC Udieresis
+!DD U+00DD Yacute
+!DE U+00DE Thorn
+!DF U+00DF germandbls
+!E0 U+00E0 agrave
+!E1 U+00E1 aacute
+!E2 U+00E2 acircumflex
+!E3 U+00E3 atilde
+!E4 U+00E4 adieresis
+!E5 U+00E5 aring
+!E6 U+00E6 ae
+!E7 U+00E7 ccedilla
+!E8 U+00E8 egrave
+!E9 U+00E9 eacute
+!EA U+00EA ecircumflex
+!EB U+00EB edieresis
+!EC U+00EC igrave
+!ED U+00ED iacute
+!EE U+00EE icircumflex
+!EF U+00EF idieresis
+!F0 U+00F0 eth
+!F1 U+00F1 ntilde
+!F2 U+00F2 ograve
+!F3 U+00F3 oacute
+!F4 U+00F4 ocircumflex
+!F5 U+00F5 otilde
+!F6 U+00F6 odieresis
+!F7 U+00F7 divide
+!F8 U+00F8 oslash
+!F9 U+00F9 ugrave
+!FA U+00FA uacute
+!FB U+00FB ucircumflex
+!FC U+00FC udieresis
+!FD U+00FD yacute
+!FE U+00FE thorn
+!FF U+00FF ydieresis
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-11.map b/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-11.map
new file mode 100644 (file)
index 0000000..9168812
--- /dev/null
@@ -0,0 +1,248 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+0080 .notdef
+!81 U+0081 .notdef
+!82 U+0082 .notdef
+!83 U+0083 .notdef
+!84 U+0084 .notdef
+!85 U+0085 .notdef
+!86 U+0086 .notdef
+!87 U+0087 .notdef
+!88 U+0088 .notdef
+!89 U+0089 .notdef
+!8A U+008A .notdef
+!8B U+008B .notdef
+!8C U+008C .notdef
+!8D U+008D .notdef
+!8E U+008E .notdef
+!8F U+008F .notdef
+!90 U+0090 .notdef
+!91 U+0091 .notdef
+!92 U+0092 .notdef
+!93 U+0093 .notdef
+!94 U+0094 .notdef
+!95 U+0095 .notdef
+!96 U+0096 .notdef
+!97 U+0097 .notdef
+!98 U+0098 .notdef
+!99 U+0099 .notdef
+!9A U+009A .notdef
+!9B U+009B .notdef
+!9C U+009C .notdef
+!9D U+009D .notdef
+!9E U+009E .notdef
+!9F U+009F .notdef
+!A0 U+00A0 space
+!A1 U+0E01 kokaithai
+!A2 U+0E02 khokhaithai
+!A3 U+0E03 khokhuatthai
+!A4 U+0E04 khokhwaithai
+!A5 U+0E05 khokhonthai
+!A6 U+0E06 khorakhangthai
+!A7 U+0E07 ngonguthai
+!A8 U+0E08 chochanthai
+!A9 U+0E09 chochingthai
+!AA U+0E0A chochangthai
+!AB U+0E0B sosothai
+!AC U+0E0C chochoethai
+!AD U+0E0D yoyingthai
+!AE U+0E0E dochadathai
+!AF U+0E0F topatakthai
+!B0 U+0E10 thothanthai
+!B1 U+0E11 thonangmonthothai
+!B2 U+0E12 thophuthaothai
+!B3 U+0E13 nonenthai
+!B4 U+0E14 dodekthai
+!B5 U+0E15 totaothai
+!B6 U+0E16 thothungthai
+!B7 U+0E17 thothahanthai
+!B8 U+0E18 thothongthai
+!B9 U+0E19 nonuthai
+!BA U+0E1A bobaimaithai
+!BB U+0E1B poplathai
+!BC U+0E1C phophungthai
+!BD U+0E1D fofathai
+!BE U+0E1E phophanthai
+!BF U+0E1F fofanthai
+!C0 U+0E20 phosamphaothai
+!C1 U+0E21 momathai
+!C2 U+0E22 yoyakthai
+!C3 U+0E23 roruathai
+!C4 U+0E24 ruthai
+!C5 U+0E25 lolingthai
+!C6 U+0E26 luthai
+!C7 U+0E27 wowaenthai
+!C8 U+0E28 sosalathai
+!C9 U+0E29 sorusithai
+!CA U+0E2A sosuathai
+!CB U+0E2B hohipthai
+!CC U+0E2C lochulathai
+!CD U+0E2D oangthai
+!CE U+0E2E honokhukthai
+!CF U+0E2F paiyannoithai
+!D0 U+0E30 saraathai
+!D1 U+0E31 maihanakatthai
+!D2 U+0E32 saraaathai
+!D3 U+0E33 saraamthai
+!D4 U+0E34 saraithai
+!D5 U+0E35 saraiithai
+!D6 U+0E36 sarauethai
+!D7 U+0E37 saraueethai
+!D8 U+0E38 sarauthai
+!D9 U+0E39 sarauuthai
+!DA U+0E3A phinthuthai
+!DF U+0E3F bahtthai
+!E0 U+0E40 saraethai
+!E1 U+0E41 saraaethai
+!E2 U+0E42 saraothai
+!E3 U+0E43 saraaimaimuanthai
+!E4 U+0E44 saraaimaimalaithai
+!E5 U+0E45 lakkhangyaothai
+!E6 U+0E46 maiyamokthai
+!E7 U+0E47 maitaikhuthai
+!E8 U+0E48 maiekthai
+!E9 U+0E49 maithothai
+!EA U+0E4A maitrithai
+!EB U+0E4B maichattawathai
+!EC U+0E4C thanthakhatthai
+!ED U+0E4D nikhahitthai
+!EE U+0E4E yamakkanthai
+!EF U+0E4F fongmanthai
+!F0 U+0E50 zerothai
+!F1 U+0E51 onethai
+!F2 U+0E52 twothai
+!F3 U+0E53 threethai
+!F4 U+0E54 fourthai
+!F5 U+0E55 fivethai
+!F6 U+0E56 sixthai
+!F7 U+0E57 seventhai
+!F8 U+0E58 eightthai
+!F9 U+0E59 ninethai
+!FA U+0E5A angkhankhuthai
+!FB U+0E5B khomutthai
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-15.map b/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-15.map
new file mode 100644 (file)
index 0000000..6c2b571
--- /dev/null
@@ -0,0 +1,256 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+0080 .notdef
+!81 U+0081 .notdef
+!82 U+0082 .notdef
+!83 U+0083 .notdef
+!84 U+0084 .notdef
+!85 U+0085 .notdef
+!86 U+0086 .notdef
+!87 U+0087 .notdef
+!88 U+0088 .notdef
+!89 U+0089 .notdef
+!8A U+008A .notdef
+!8B U+008B .notdef
+!8C U+008C .notdef
+!8D U+008D .notdef
+!8E U+008E .notdef
+!8F U+008F .notdef
+!90 U+0090 .notdef
+!91 U+0091 .notdef
+!92 U+0092 .notdef
+!93 U+0093 .notdef
+!94 U+0094 .notdef
+!95 U+0095 .notdef
+!96 U+0096 .notdef
+!97 U+0097 .notdef
+!98 U+0098 .notdef
+!99 U+0099 .notdef
+!9A U+009A .notdef
+!9B U+009B .notdef
+!9C U+009C .notdef
+!9D U+009D .notdef
+!9E U+009E .notdef
+!9F U+009F .notdef
+!A0 U+00A0 space
+!A1 U+00A1 exclamdown
+!A2 U+00A2 cent
+!A3 U+00A3 sterling
+!A4 U+20AC Euro
+!A5 U+00A5 yen
+!A6 U+0160 Scaron
+!A7 U+00A7 section
+!A8 U+0161 scaron
+!A9 U+00A9 copyright
+!AA U+00AA ordfeminine
+!AB U+00AB guillemotleft
+!AC U+00AC logicalnot
+!AD U+00AD hyphen
+!AE U+00AE registered
+!AF U+00AF macron
+!B0 U+00B0 degree
+!B1 U+00B1 plusminus
+!B2 U+00B2 twosuperior
+!B3 U+00B3 threesuperior
+!B4 U+017D Zcaron
+!B5 U+00B5 mu
+!B6 U+00B6 paragraph
+!B7 U+00B7 periodcentered
+!B8 U+017E zcaron
+!B9 U+00B9 onesuperior
+!BA U+00BA ordmasculine
+!BB U+00BB guillemotright
+!BC U+0152 OE
+!BD U+0153 oe
+!BE U+0178 Ydieresis
+!BF U+00BF questiondown
+!C0 U+00C0 Agrave
+!C1 U+00C1 Aacute
+!C2 U+00C2 Acircumflex
+!C3 U+00C3 Atilde
+!C4 U+00C4 Adieresis
+!C5 U+00C5 Aring
+!C6 U+00C6 AE
+!C7 U+00C7 Ccedilla
+!C8 U+00C8 Egrave
+!C9 U+00C9 Eacute
+!CA U+00CA Ecircumflex
+!CB U+00CB Edieresis
+!CC U+00CC Igrave
+!CD U+00CD Iacute
+!CE U+00CE Icircumflex
+!CF U+00CF Idieresis
+!D0 U+00D0 Eth
+!D1 U+00D1 Ntilde
+!D2 U+00D2 Ograve
+!D3 U+00D3 Oacute
+!D4 U+00D4 Ocircumflex
+!D5 U+00D5 Otilde
+!D6 U+00D6 Odieresis
+!D7 U+00D7 multiply
+!D8 U+00D8 Oslash
+!D9 U+00D9 Ugrave
+!DA U+00DA Uacute
+!DB U+00DB Ucircumflex
+!DC U+00DC Udieresis
+!DD U+00DD Yacute
+!DE U+00DE Thorn
+!DF U+00DF germandbls
+!E0 U+00E0 agrave
+!E1 U+00E1 aacute
+!E2 U+00E2 acircumflex
+!E3 U+00E3 atilde
+!E4 U+00E4 adieresis
+!E5 U+00E5 aring
+!E6 U+00E6 ae
+!E7 U+00E7 ccedilla
+!E8 U+00E8 egrave
+!E9 U+00E9 eacute
+!EA U+00EA ecircumflex
+!EB U+00EB edieresis
+!EC U+00EC igrave
+!ED U+00ED iacute
+!EE U+00EE icircumflex
+!EF U+00EF idieresis
+!F0 U+00F0 eth
+!F1 U+00F1 ntilde
+!F2 U+00F2 ograve
+!F3 U+00F3 oacute
+!F4 U+00F4 ocircumflex
+!F5 U+00F5 otilde
+!F6 U+00F6 odieresis
+!F7 U+00F7 divide
+!F8 U+00F8 oslash
+!F9 U+00F9 ugrave
+!FA U+00FA uacute
+!FB U+00FB ucircumflex
+!FC U+00FC udieresis
+!FD U+00FD yacute
+!FE U+00FE thorn
+!FF U+00FF ydieresis
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-16.map b/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-16.map
new file mode 100644 (file)
index 0000000..202c8fe
--- /dev/null
@@ -0,0 +1,256 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+0080 .notdef
+!81 U+0081 .notdef
+!82 U+0082 .notdef
+!83 U+0083 .notdef
+!84 U+0084 .notdef
+!85 U+0085 .notdef
+!86 U+0086 .notdef
+!87 U+0087 .notdef
+!88 U+0088 .notdef
+!89 U+0089 .notdef
+!8A U+008A .notdef
+!8B U+008B .notdef
+!8C U+008C .notdef
+!8D U+008D .notdef
+!8E U+008E .notdef
+!8F U+008F .notdef
+!90 U+0090 .notdef
+!91 U+0091 .notdef
+!92 U+0092 .notdef
+!93 U+0093 .notdef
+!94 U+0094 .notdef
+!95 U+0095 .notdef
+!96 U+0096 .notdef
+!97 U+0097 .notdef
+!98 U+0098 .notdef
+!99 U+0099 .notdef
+!9A U+009A .notdef
+!9B U+009B .notdef
+!9C U+009C .notdef
+!9D U+009D .notdef
+!9E U+009E .notdef
+!9F U+009F .notdef
+!A0 U+00A0 space
+!A1 U+0104 Aogonek
+!A2 U+0105 aogonek
+!A3 U+0141 Lslash
+!A4 U+20AC Euro
+!A5 U+201E quotedblbase
+!A6 U+0160 Scaron
+!A7 U+00A7 section
+!A8 U+0161 scaron
+!A9 U+00A9 copyright
+!AA U+0218 Scommaaccent
+!AB U+00AB guillemotleft
+!AC U+0179 Zacute
+!AD U+00AD hyphen
+!AE U+017A zacute
+!AF U+017B Zdotaccent
+!B0 U+00B0 degree
+!B1 U+00B1 plusminus
+!B2 U+010C Ccaron
+!B3 U+0142 lslash
+!B4 U+017D Zcaron
+!B5 U+201D quotedblright
+!B6 U+00B6 paragraph
+!B7 U+00B7 periodcentered
+!B8 U+017E zcaron
+!B9 U+010D ccaron
+!BA U+0219 scommaaccent
+!BB U+00BB guillemotright
+!BC U+0152 OE
+!BD U+0153 oe
+!BE U+0178 Ydieresis
+!BF U+017C zdotaccent
+!C0 U+00C0 Agrave
+!C1 U+00C1 Aacute
+!C2 U+00C2 Acircumflex
+!C3 U+0102 Abreve
+!C4 U+00C4 Adieresis
+!C5 U+0106 Cacute
+!C6 U+00C6 AE
+!C7 U+00C7 Ccedilla
+!C8 U+00C8 Egrave
+!C9 U+00C9 Eacute
+!CA U+00CA Ecircumflex
+!CB U+00CB Edieresis
+!CC U+00CC Igrave
+!CD U+00CD Iacute
+!CE U+00CE Icircumflex
+!CF U+00CF Idieresis
+!D0 U+0110 Dcroat
+!D1 U+0143 Nacute
+!D2 U+00D2 Ograve
+!D3 U+00D3 Oacute
+!D4 U+00D4 Ocircumflex
+!D5 U+0150 Ohungarumlaut
+!D6 U+00D6 Odieresis
+!D7 U+015A Sacute
+!D8 U+0170 Uhungarumlaut
+!D9 U+00D9 Ugrave
+!DA U+00DA Uacute
+!DB U+00DB Ucircumflex
+!DC U+00DC Udieresis
+!DD U+0118 Eogonek
+!DE U+021A Tcommaaccent
+!DF U+00DF germandbls
+!E0 U+00E0 agrave
+!E1 U+00E1 aacute
+!E2 U+00E2 acircumflex
+!E3 U+0103 abreve
+!E4 U+00E4 adieresis
+!E5 U+0107 cacute
+!E6 U+00E6 ae
+!E7 U+00E7 ccedilla
+!E8 U+00E8 egrave
+!E9 U+00E9 eacute
+!EA U+00EA ecircumflex
+!EB U+00EB edieresis
+!EC U+00EC igrave
+!ED U+00ED iacute
+!EE U+00EE icircumflex
+!EF U+00EF idieresis
+!F0 U+0111 dcroat
+!F1 U+0144 nacute
+!F2 U+00F2 ograve
+!F3 U+00F3 oacute
+!F4 U+00F4 ocircumflex
+!F5 U+0151 ohungarumlaut
+!F6 U+00F6 odieresis
+!F7 U+015B sacute
+!F8 U+0171 uhungarumlaut
+!F9 U+00F9 ugrave
+!FA U+00FA uacute
+!FB U+00FB ucircumflex
+!FC U+00FC udieresis
+!FD U+0119 eogonek
+!FE U+021B tcommaaccent
+!FF U+00FF ydieresis
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-2.map b/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-2.map
new file mode 100644 (file)
index 0000000..65ae09f
--- /dev/null
@@ -0,0 +1,256 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+0080 .notdef
+!81 U+0081 .notdef
+!82 U+0082 .notdef
+!83 U+0083 .notdef
+!84 U+0084 .notdef
+!85 U+0085 .notdef
+!86 U+0086 .notdef
+!87 U+0087 .notdef
+!88 U+0088 .notdef
+!89 U+0089 .notdef
+!8A U+008A .notdef
+!8B U+008B .notdef
+!8C U+008C .notdef
+!8D U+008D .notdef
+!8E U+008E .notdef
+!8F U+008F .notdef
+!90 U+0090 .notdef
+!91 U+0091 .notdef
+!92 U+0092 .notdef
+!93 U+0093 .notdef
+!94 U+0094 .notdef
+!95 U+0095 .notdef
+!96 U+0096 .notdef
+!97 U+0097 .notdef
+!98 U+0098 .notdef
+!99 U+0099 .notdef
+!9A U+009A .notdef
+!9B U+009B .notdef
+!9C U+009C .notdef
+!9D U+009D .notdef
+!9E U+009E .notdef
+!9F U+009F .notdef
+!A0 U+00A0 space
+!A1 U+0104 Aogonek
+!A2 U+02D8 breve
+!A3 U+0141 Lslash
+!A4 U+00A4 currency
+!A5 U+013D Lcaron
+!A6 U+015A Sacute
+!A7 U+00A7 section
+!A8 U+00A8 dieresis
+!A9 U+0160 Scaron
+!AA U+015E Scedilla
+!AB U+0164 Tcaron
+!AC U+0179 Zacute
+!AD U+00AD hyphen
+!AE U+017D Zcaron
+!AF U+017B Zdotaccent
+!B0 U+00B0 degree
+!B1 U+0105 aogonek
+!B2 U+02DB ogonek
+!B3 U+0142 lslash
+!B4 U+00B4 acute
+!B5 U+013E lcaron
+!B6 U+015B sacute
+!B7 U+02C7 caron
+!B8 U+00B8 cedilla
+!B9 U+0161 scaron
+!BA U+015F scedilla
+!BB U+0165 tcaron
+!BC U+017A zacute
+!BD U+02DD hungarumlaut
+!BE U+017E zcaron
+!BF U+017C zdotaccent
+!C0 U+0154 Racute
+!C1 U+00C1 Aacute
+!C2 U+00C2 Acircumflex
+!C3 U+0102 Abreve
+!C4 U+00C4 Adieresis
+!C5 U+0139 Lacute
+!C6 U+0106 Cacute
+!C7 U+00C7 Ccedilla
+!C8 U+010C Ccaron
+!C9 U+00C9 Eacute
+!CA U+0118 Eogonek
+!CB U+00CB Edieresis
+!CC U+011A Ecaron
+!CD U+00CD Iacute
+!CE U+00CE Icircumflex
+!CF U+010E Dcaron
+!D0 U+0110 Dcroat
+!D1 U+0143 Nacute
+!D2 U+0147 Ncaron
+!D3 U+00D3 Oacute
+!D4 U+00D4 Ocircumflex
+!D5 U+0150 Ohungarumlaut
+!D6 U+00D6 Odieresis
+!D7 U+00D7 multiply
+!D8 U+0158 Rcaron
+!D9 U+016E Uring
+!DA U+00DA Uacute
+!DB U+0170 Uhungarumlaut
+!DC U+00DC Udieresis
+!DD U+00DD Yacute
+!DE U+0162 Tcommaaccent
+!DF U+00DF germandbls
+!E0 U+0155 racute
+!E1 U+00E1 aacute
+!E2 U+00E2 acircumflex
+!E3 U+0103 abreve
+!E4 U+00E4 adieresis
+!E5 U+013A lacute
+!E6 U+0107 cacute
+!E7 U+00E7 ccedilla
+!E8 U+010D ccaron
+!E9 U+00E9 eacute
+!EA U+0119 eogonek
+!EB U+00EB edieresis
+!EC U+011B ecaron
+!ED U+00ED iacute
+!EE U+00EE icircumflex
+!EF U+010F dcaron
+!F0 U+0111 dcroat
+!F1 U+0144 nacute
+!F2 U+0148 ncaron
+!F3 U+00F3 oacute
+!F4 U+00F4 ocircumflex
+!F5 U+0151 ohungarumlaut
+!F6 U+00F6 odieresis
+!F7 U+00F7 divide
+!F8 U+0159 rcaron
+!F9 U+016F uring
+!FA U+00FA uacute
+!FB U+0171 uhungarumlaut
+!FC U+00FC udieresis
+!FD U+00FD yacute
+!FE U+0163 tcommaaccent
+!FF U+02D9 dotaccent
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-4.map b/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-4.map
new file mode 100644 (file)
index 0000000..a7d87bf
--- /dev/null
@@ -0,0 +1,256 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+0080 .notdef
+!81 U+0081 .notdef
+!82 U+0082 .notdef
+!83 U+0083 .notdef
+!84 U+0084 .notdef
+!85 U+0085 .notdef
+!86 U+0086 .notdef
+!87 U+0087 .notdef
+!88 U+0088 .notdef
+!89 U+0089 .notdef
+!8A U+008A .notdef
+!8B U+008B .notdef
+!8C U+008C .notdef
+!8D U+008D .notdef
+!8E U+008E .notdef
+!8F U+008F .notdef
+!90 U+0090 .notdef
+!91 U+0091 .notdef
+!92 U+0092 .notdef
+!93 U+0093 .notdef
+!94 U+0094 .notdef
+!95 U+0095 .notdef
+!96 U+0096 .notdef
+!97 U+0097 .notdef
+!98 U+0098 .notdef
+!99 U+0099 .notdef
+!9A U+009A .notdef
+!9B U+009B .notdef
+!9C U+009C .notdef
+!9D U+009D .notdef
+!9E U+009E .notdef
+!9F U+009F .notdef
+!A0 U+00A0 space
+!A1 U+0104 Aogonek
+!A2 U+0138 kgreenlandic
+!A3 U+0156 Rcommaaccent
+!A4 U+00A4 currency
+!A5 U+0128 Itilde
+!A6 U+013B Lcommaaccent
+!A7 U+00A7 section
+!A8 U+00A8 dieresis
+!A9 U+0160 Scaron
+!AA U+0112 Emacron
+!AB U+0122 Gcommaaccent
+!AC U+0166 Tbar
+!AD U+00AD hyphen
+!AE U+017D Zcaron
+!AF U+00AF macron
+!B0 U+00B0 degree
+!B1 U+0105 aogonek
+!B2 U+02DB ogonek
+!B3 U+0157 rcommaaccent
+!B4 U+00B4 acute
+!B5 U+0129 itilde
+!B6 U+013C lcommaaccent
+!B7 U+02C7 caron
+!B8 U+00B8 cedilla
+!B9 U+0161 scaron
+!BA U+0113 emacron
+!BB U+0123 gcommaaccent
+!BC U+0167 tbar
+!BD U+014A Eng
+!BE U+017E zcaron
+!BF U+014B eng
+!C0 U+0100 Amacron
+!C1 U+00C1 Aacute
+!C2 U+00C2 Acircumflex
+!C3 U+00C3 Atilde
+!C4 U+00C4 Adieresis
+!C5 U+00C5 Aring
+!C6 U+00C6 AE
+!C7 U+012E Iogonek
+!C8 U+010C Ccaron
+!C9 U+00C9 Eacute
+!CA U+0118 Eogonek
+!CB U+00CB Edieresis
+!CC U+0116 Edotaccent
+!CD U+00CD Iacute
+!CE U+00CE Icircumflex
+!CF U+012A Imacron
+!D0 U+0110 Dcroat
+!D1 U+0145 Ncommaaccent
+!D2 U+014C Omacron
+!D3 U+0136 Kcommaaccent
+!D4 U+00D4 Ocircumflex
+!D5 U+00D5 Otilde
+!D6 U+00D6 Odieresis
+!D7 U+00D7 multiply
+!D8 U+00D8 Oslash
+!D9 U+0172 Uogonek
+!DA U+00DA Uacute
+!DB U+00DB Ucircumflex
+!DC U+00DC Udieresis
+!DD U+0168 Utilde
+!DE U+016A Umacron
+!DF U+00DF germandbls
+!E0 U+0101 amacron
+!E1 U+00E1 aacute
+!E2 U+00E2 acircumflex
+!E3 U+00E3 atilde
+!E4 U+00E4 adieresis
+!E5 U+00E5 aring
+!E6 U+00E6 ae
+!E7 U+012F iogonek
+!E8 U+010D ccaron
+!E9 U+00E9 eacute
+!EA U+0119 eogonek
+!EB U+00EB edieresis
+!EC U+0117 edotaccent
+!ED U+00ED iacute
+!EE U+00EE icircumflex
+!EF U+012B imacron
+!F0 U+0111 dcroat
+!F1 U+0146 ncommaaccent
+!F2 U+014D omacron
+!F3 U+0137 kcommaaccent
+!F4 U+00F4 ocircumflex
+!F5 U+00F5 otilde
+!F6 U+00F6 odieresis
+!F7 U+00F7 divide
+!F8 U+00F8 oslash
+!F9 U+0173 uogonek
+!FA U+00FA uacute
+!FB U+00FB ucircumflex
+!FC U+00FC udieresis
+!FD U+0169 utilde
+!FE U+016B umacron
+!FF U+02D9 dotaccent
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-5.map b/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-5.map
new file mode 100644 (file)
index 0000000..f9cd4ed
--- /dev/null
@@ -0,0 +1,256 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+0080 .notdef
+!81 U+0081 .notdef
+!82 U+0082 .notdef
+!83 U+0083 .notdef
+!84 U+0084 .notdef
+!85 U+0085 .notdef
+!86 U+0086 .notdef
+!87 U+0087 .notdef
+!88 U+0088 .notdef
+!89 U+0089 .notdef
+!8A U+008A .notdef
+!8B U+008B .notdef
+!8C U+008C .notdef
+!8D U+008D .notdef
+!8E U+008E .notdef
+!8F U+008F .notdef
+!90 U+0090 .notdef
+!91 U+0091 .notdef
+!92 U+0092 .notdef
+!93 U+0093 .notdef
+!94 U+0094 .notdef
+!95 U+0095 .notdef
+!96 U+0096 .notdef
+!97 U+0097 .notdef
+!98 U+0098 .notdef
+!99 U+0099 .notdef
+!9A U+009A .notdef
+!9B U+009B .notdef
+!9C U+009C .notdef
+!9D U+009D .notdef
+!9E U+009E .notdef
+!9F U+009F .notdef
+!A0 U+00A0 space
+!A1 U+0401 afii10023
+!A2 U+0402 afii10051
+!A3 U+0403 afii10052
+!A4 U+0404 afii10053
+!A5 U+0405 afii10054
+!A6 U+0406 afii10055
+!A7 U+0407 afii10056
+!A8 U+0408 afii10057
+!A9 U+0409 afii10058
+!AA U+040A afii10059
+!AB U+040B afii10060
+!AC U+040C afii10061
+!AD U+00AD hyphen
+!AE U+040E afii10062
+!AF U+040F afii10145
+!B0 U+0410 afii10017
+!B1 U+0411 afii10018
+!B2 U+0412 afii10019
+!B3 U+0413 afii10020
+!B4 U+0414 afii10021
+!B5 U+0415 afii10022
+!B6 U+0416 afii10024
+!B7 U+0417 afii10025
+!B8 U+0418 afii10026
+!B9 U+0419 afii10027
+!BA U+041A afii10028
+!BB U+041B afii10029
+!BC U+041C afii10030
+!BD U+041D afii10031
+!BE U+041E afii10032
+!BF U+041F afii10033
+!C0 U+0420 afii10034
+!C1 U+0421 afii10035
+!C2 U+0422 afii10036
+!C3 U+0423 afii10037
+!C4 U+0424 afii10038
+!C5 U+0425 afii10039
+!C6 U+0426 afii10040
+!C7 U+0427 afii10041
+!C8 U+0428 afii10042
+!C9 U+0429 afii10043
+!CA U+042A afii10044
+!CB U+042B afii10045
+!CC U+042C afii10046
+!CD U+042D afii10047
+!CE U+042E afii10048
+!CF U+042F afii10049
+!D0 U+0430 afii10065
+!D1 U+0431 afii10066
+!D2 U+0432 afii10067
+!D3 U+0433 afii10068
+!D4 U+0434 afii10069
+!D5 U+0435 afii10070
+!D6 U+0436 afii10072
+!D7 U+0437 afii10073
+!D8 U+0438 afii10074
+!D9 U+0439 afii10075
+!DA U+043A afii10076
+!DB U+043B afii10077
+!DC U+043C afii10078
+!DD U+043D afii10079
+!DE U+043E afii10080
+!DF U+043F afii10081
+!E0 U+0440 afii10082
+!E1 U+0441 afii10083
+!E2 U+0442 afii10084
+!E3 U+0443 afii10085
+!E4 U+0444 afii10086
+!E5 U+0445 afii10087
+!E6 U+0446 afii10088
+!E7 U+0447 afii10089
+!E8 U+0448 afii10090
+!E9 U+0449 afii10091
+!EA U+044A afii10092
+!EB U+044B afii10093
+!EC U+044C afii10094
+!ED U+044D afii10095
+!EE U+044E afii10096
+!EF U+044F afii10097
+!F0 U+2116 afii61352
+!F1 U+0451 afii10071
+!F2 U+0452 afii10099
+!F3 U+0453 afii10100
+!F4 U+0454 afii10101
+!F5 U+0455 afii10102
+!F6 U+0456 afii10103
+!F7 U+0457 afii10104
+!F8 U+0458 afii10105
+!F9 U+0459 afii10106
+!FA U+045A afii10107
+!FB U+045B afii10108
+!FC U+045C afii10109
+!FD U+00A7 section
+!FE U+045E afii10110
+!FF U+045F afii10193
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-7.map b/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-7.map
new file mode 100644 (file)
index 0000000..e163796
--- /dev/null
@@ -0,0 +1,250 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+0080 .notdef
+!81 U+0081 .notdef
+!82 U+0082 .notdef
+!83 U+0083 .notdef
+!84 U+0084 .notdef
+!85 U+0085 .notdef
+!86 U+0086 .notdef
+!87 U+0087 .notdef
+!88 U+0088 .notdef
+!89 U+0089 .notdef
+!8A U+008A .notdef
+!8B U+008B .notdef
+!8C U+008C .notdef
+!8D U+008D .notdef
+!8E U+008E .notdef
+!8F U+008F .notdef
+!90 U+0090 .notdef
+!91 U+0091 .notdef
+!92 U+0092 .notdef
+!93 U+0093 .notdef
+!94 U+0094 .notdef
+!95 U+0095 .notdef
+!96 U+0096 .notdef
+!97 U+0097 .notdef
+!98 U+0098 .notdef
+!99 U+0099 .notdef
+!9A U+009A .notdef
+!9B U+009B .notdef
+!9C U+009C .notdef
+!9D U+009D .notdef
+!9E U+009E .notdef
+!9F U+009F .notdef
+!A0 U+00A0 space
+!A1 U+2018 quoteleft
+!A2 U+2019 quoteright
+!A3 U+00A3 sterling
+!A6 U+00A6 brokenbar
+!A7 U+00A7 section
+!A8 U+00A8 dieresis
+!A9 U+00A9 copyright
+!AB U+00AB guillemotleft
+!AC U+00AC logicalnot
+!AD U+00AD hyphen
+!AF U+2015 afii00208
+!B0 U+00B0 degree
+!B1 U+00B1 plusminus
+!B2 U+00B2 twosuperior
+!B3 U+00B3 threesuperior
+!B4 U+0384 tonos
+!B5 U+0385 dieresistonos
+!B6 U+0386 Alphatonos
+!B7 U+00B7 periodcentered
+!B8 U+0388 Epsilontonos
+!B9 U+0389 Etatonos
+!BA U+038A Iotatonos
+!BB U+00BB guillemotright
+!BC U+038C Omicrontonos
+!BD U+00BD onehalf
+!BE U+038E Upsilontonos
+!BF U+038F Omegatonos
+!C0 U+0390 iotadieresistonos
+!C1 U+0391 Alpha
+!C2 U+0392 Beta
+!C3 U+0393 Gamma
+!C4 U+0394 Delta
+!C5 U+0395 Epsilon
+!C6 U+0396 Zeta
+!C7 U+0397 Eta
+!C8 U+0398 Theta
+!C9 U+0399 Iota
+!CA U+039A Kappa
+!CB U+039B Lambda
+!CC U+039C Mu
+!CD U+039D Nu
+!CE U+039E Xi
+!CF U+039F Omicron
+!D0 U+03A0 Pi
+!D1 U+03A1 Rho
+!D3 U+03A3 Sigma
+!D4 U+03A4 Tau
+!D5 U+03A5 Upsilon
+!D6 U+03A6 Phi
+!D7 U+03A7 Chi
+!D8 U+03A8 Psi
+!D9 U+03A9 Omega
+!DA U+03AA Iotadieresis
+!DB U+03AB Upsilondieresis
+!DC U+03AC alphatonos
+!DD U+03AD epsilontonos
+!DE U+03AE etatonos
+!DF U+03AF iotatonos
+!E0 U+03B0 upsilondieresistonos
+!E1 U+03B1 alpha
+!E2 U+03B2 beta
+!E3 U+03B3 gamma
+!E4 U+03B4 delta
+!E5 U+03B5 epsilon
+!E6 U+03B6 zeta
+!E7 U+03B7 eta
+!E8 U+03B8 theta
+!E9 U+03B9 iota
+!EA U+03BA kappa
+!EB U+03BB lambda
+!EC U+03BC mu
+!ED U+03BD nu
+!EE U+03BE xi
+!EF U+03BF omicron
+!F0 U+03C0 pi
+!F1 U+03C1 rho
+!F2 U+03C2 sigma1
+!F3 U+03C3 sigma
+!F4 U+03C4 tau
+!F5 U+03C5 upsilon
+!F6 U+03C6 phi
+!F7 U+03C7 chi
+!F8 U+03C8 psi
+!F9 U+03C9 omega
+!FA U+03CA iotadieresis
+!FB U+03CB upsilondieresis
+!FC U+03CC omicrontonos
+!FD U+03CD upsilontonos
+!FE U+03CE omegatonos
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-9.map b/plugins/serendipity_event_blogpdf/font/makefont/iso-8859-9.map
new file mode 100644 (file)
index 0000000..48c123a
--- /dev/null
@@ -0,0 +1,256 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+0080 .notdef
+!81 U+0081 .notdef
+!82 U+0082 .notdef
+!83 U+0083 .notdef
+!84 U+0084 .notdef
+!85 U+0085 .notdef
+!86 U+0086 .notdef
+!87 U+0087 .notdef
+!88 U+0088 .notdef
+!89 U+0089 .notdef
+!8A U+008A .notdef
+!8B U+008B .notdef
+!8C U+008C .notdef
+!8D U+008D .notdef
+!8E U+008E .notdef
+!8F U+008F .notdef
+!90 U+0090 .notdef
+!91 U+0091 .notdef
+!92 U+0092 .notdef
+!93 U+0093 .notdef
+!94 U+0094 .notdef
+!95 U+0095 .notdef
+!96 U+0096 .notdef
+!97 U+0097 .notdef
+!98 U+0098 .notdef
+!99 U+0099 .notdef
+!9A U+009A .notdef
+!9B U+009B .notdef
+!9C U+009C .notdef
+!9D U+009D .notdef
+!9E U+009E .notdef
+!9F U+009F .notdef
+!A0 U+00A0 space
+!A1 U+00A1 exclamdown
+!A2 U+00A2 cent
+!A3 U+00A3 sterling
+!A4 U+00A4 currency
+!A5 U+00A5 yen
+!A6 U+00A6 brokenbar
+!A7 U+00A7 section
+!A8 U+00A8 dieresis
+!A9 U+00A9 copyright
+!AA U+00AA ordfeminine
+!AB U+00AB guillemotleft
+!AC U+00AC logicalnot
+!AD U+00AD hyphen
+!AE U+00AE registered
+!AF U+00AF macron
+!B0 U+00B0 degree
+!B1 U+00B1 plusminus
+!B2 U+00B2 twosuperior
+!B3 U+00B3 threesuperior
+!B4 U+00B4 acute
+!B5 U+00B5 mu
+!B6 U+00B6 paragraph
+!B7 U+00B7 periodcentered
+!B8 U+00B8 cedilla
+!B9 U+00B9 onesuperior
+!BA U+00BA ordmasculine
+!BB U+00BB guillemotright
+!BC U+00BC onequarter
+!BD U+00BD onehalf
+!BE U+00BE threequarters
+!BF U+00BF questiondown
+!C0 U+00C0 Agrave
+!C1 U+00C1 Aacute
+!C2 U+00C2 Acircumflex
+!C3 U+00C3 Atilde
+!C4 U+00C4 Adieresis
+!C5 U+00C5 Aring
+!C6 U+00C6 AE
+!C7 U+00C7 Ccedilla
+!C8 U+00C8 Egrave
+!C9 U+00C9 Eacute
+!CA U+00CA Ecircumflex
+!CB U+00CB Edieresis
+!CC U+00CC Igrave
+!CD U+00CD Iacute
+!CE U+00CE Icircumflex
+!CF U+00CF Idieresis
+!D0 U+011E Gbreve
+!D1 U+00D1 Ntilde
+!D2 U+00D2 Ograve
+!D3 U+00D3 Oacute
+!D4 U+00D4 Ocircumflex
+!D5 U+00D5 Otilde
+!D6 U+00D6 Odieresis
+!D7 U+00D7 multiply
+!D8 U+00D8 Oslash
+!D9 U+00D9 Ugrave
+!DA U+00DA Uacute
+!DB U+00DB Ucircumflex
+!DC U+00DC Udieresis
+!DD U+0130 Idotaccent
+!DE U+015E Scedilla
+!DF U+00DF germandbls
+!E0 U+00E0 agrave
+!E1 U+00E1 aacute
+!E2 U+00E2 acircumflex
+!E3 U+00E3 atilde
+!E4 U+00E4 adieresis
+!E5 U+00E5 aring
+!E6 U+00E6 ae
+!E7 U+00E7 ccedilla
+!E8 U+00E8 egrave
+!E9 U+00E9 eacute
+!EA U+00EA ecircumflex
+!EB U+00EB edieresis
+!EC U+00EC igrave
+!ED U+00ED iacute
+!EE U+00EE icircumflex
+!EF U+00EF idieresis
+!F0 U+011F gbreve
+!F1 U+00F1 ntilde
+!F2 U+00F2 ograve
+!F3 U+00F3 oacute
+!F4 U+00F4 ocircumflex
+!F5 U+00F5 otilde
+!F6 U+00F6 odieresis
+!F7 U+00F7 divide
+!F8 U+00F8 oslash
+!F9 U+00F9 ugrave
+!FA U+00FA uacute
+!FB U+00FB ucircumflex
+!FC U+00FC udieresis
+!FD U+0131 dotlessi
+!FE U+015F scedilla
+!FF U+00FF ydieresis
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/koi8-r.map b/plugins/serendipity_event_blogpdf/font/makefont/koi8-r.map
new file mode 100644 (file)
index 0000000..6ad5d05
--- /dev/null
@@ -0,0 +1,256 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+2500 SF100000
+!81 U+2502 SF110000
+!82 U+250C SF010000
+!83 U+2510 SF030000
+!84 U+2514 SF020000
+!85 U+2518 SF040000
+!86 U+251C SF080000
+!87 U+2524 SF090000
+!88 U+252C SF060000
+!89 U+2534 SF070000
+!8A U+253C SF050000
+!8B U+2580 upblock
+!8C U+2584 dnblock
+!8D U+2588 block
+!8E U+258C lfblock
+!8F U+2590 rtblock
+!90 U+2591 ltshade
+!91 U+2592 shade
+!92 U+2593 dkshade
+!93 U+2320 integraltp
+!94 U+25A0 filledbox
+!95 U+2219 periodcentered
+!96 U+221A radical
+!97 U+2248 approxequal
+!98 U+2264 lessequal
+!99 U+2265 greaterequal
+!9A U+00A0 space
+!9B U+2321 integralbt
+!9C U+00B0 degree
+!9D U+00B2 twosuperior
+!9E U+00B7 periodcentered
+!9F U+00F7 divide
+!A0 U+2550 SF430000
+!A1 U+2551 SF240000
+!A2 U+2552 SF510000
+!A3 U+0451 afii10071
+!A4 U+2553 SF520000
+!A5 U+2554 SF390000
+!A6 U+2555 SF220000
+!A7 U+2556 SF210000
+!A8 U+2557 SF250000
+!A9 U+2558 SF500000
+!AA U+2559 SF490000
+!AB U+255A SF380000
+!AC U+255B SF280000
+!AD U+255C SF270000
+!AE U+255D SF260000
+!AF U+255E SF360000
+!B0 U+255F SF370000
+!B1 U+2560 SF420000
+!B2 U+2561 SF190000
+!B3 U+0401 afii10023
+!B4 U+2562 SF200000
+!B5 U+2563 SF230000
+!B6 U+2564 SF470000
+!B7 U+2565 SF480000
+!B8 U+2566 SF410000
+!B9 U+2567 SF450000
+!BA U+2568 SF460000
+!BB U+2569 SF400000
+!BC U+256A SF540000
+!BD U+256B SF530000
+!BE U+256C SF440000
+!BF U+00A9 copyright
+!C0 U+044E afii10096
+!C1 U+0430 afii10065
+!C2 U+0431 afii10066
+!C3 U+0446 afii10088
+!C4 U+0434 afii10069
+!C5 U+0435 afii10070
+!C6 U+0444 afii10086
+!C7 U+0433 afii10068
+!C8 U+0445 afii10087
+!C9 U+0438 afii10074
+!CA U+0439 afii10075
+!CB U+043A afii10076
+!CC U+043B afii10077
+!CD U+043C afii10078
+!CE U+043D afii10079
+!CF U+043E afii10080
+!D0 U+043F afii10081
+!D1 U+044F afii10097
+!D2 U+0440 afii10082
+!D3 U+0441 afii10083
+!D4 U+0442 afii10084
+!D5 U+0443 afii10085
+!D6 U+0436 afii10072
+!D7 U+0432 afii10067
+!D8 U+044C afii10094
+!D9 U+044B afii10093
+!DA U+0437 afii10073
+!DB U+0448 afii10090
+!DC U+044D afii10095
+!DD U+0449 afii10091
+!DE U+0447 afii10089
+!DF U+044A afii10092
+!E0 U+042E afii10048
+!E1 U+0410 afii10017
+!E2 U+0411 afii10018
+!E3 U+0426 afii10040
+!E4 U+0414 afii10021
+!E5 U+0415 afii10022
+!E6 U+0424 afii10038
+!E7 U+0413 afii10020
+!E8 U+0425 afii10039
+!E9 U+0418 afii10026
+!EA U+0419 afii10027
+!EB U+041A afii10028
+!EC U+041B afii10029
+!ED U+041C afii10030
+!EE U+041D afii10031
+!EF U+041E afii10032
+!F0 U+041F afii10033
+!F1 U+042F afii10049
+!F2 U+0420 afii10034
+!F3 U+0421 afii10035
+!F4 U+0422 afii10036
+!F5 U+0423 afii10037
+!F6 U+0416 afii10024
+!F7 U+0412 afii10019
+!F8 U+042C afii10046
+!F9 U+042B afii10045
+!FA U+0417 afii10025
+!FB U+0428 afii10042
+!FC U+042D afii10047
+!FD U+0429 afii10043
+!FE U+0427 afii10041
+!FF U+042A afii10044
diff --git a/plugins/serendipity_event_blogpdf/font/makefont/koi8-u.map b/plugins/serendipity_event_blogpdf/font/makefont/koi8-u.map
new file mode 100644 (file)
index 0000000..40a7e4f
--- /dev/null
@@ -0,0 +1,256 @@
+!00 U+0000 .notdef
+!01 U+0001 .notdef
+!02 U+0002 .notdef
+!03 U+0003 .notdef
+!04 U+0004 .notdef
+!05 U+0005 .notdef
+!06 U+0006 .notdef
+!07 U+0007 .notdef
+!08 U+0008 .notdef
+!09 U+0009 .notdef
+!0A U+000A .notdef
+!0B U+000B .notdef
+!0C U+000C .notdef
+!0D U+000D .notdef
+!0E U+000E .notdef
+!0F U+000F .notdef
+!10 U+0010 .notdef
+!11 U+0011 .notdef
+!12 U+0012 .notdef
+!13 U+0013 .notdef
+!14 U+0014 .notdef
+!15 U+0015 .notdef
+!16 U+0016 .notdef
+!17 U+0017 .notdef
+!18 U+0018 .notdef
+!19 U+0019 .notdef
+!1A U+001A .notdef
+!1B U+001B .notdef
+!1C U+001C .notdef
+!1D U+001D .notdef
+!1E U+001E .notdef
+!1F U+001F .notdef
+!20 U+0020 space
+!21 U+0021 exclam
+!22 U+0022 quotedbl
+!23 U+0023 numbersign
+!24 U+0024 dollar
+!25 U+0025 percent
+!26 U+0026 ampersand
+!27 U+0027 quotesingle
+!28 U+0028 parenleft
+!29 U+0029 parenright
+!2A U+002A asterisk
+!2B U+002B plus
+!2C U+002C comma
+!2D U+002D hyphen
+!2E U+002E period
+!2F U+002F slash
+!30 U+0030 zero
+!31 U+0031 one
+!32 U+0032 two
+!33 U+0033 three
+!34 U+0034 four
+!35 U+0035 five
+!36 U+0036 six
+!37 U+0037 seven
+!38 U+0038 eight
+!39 U+0039 nine
+!3A U+003A colon
+!3B U+003B semicolon
+!3C U+003C less
+!3D U+003D equal
+!3E U+003E greater
+!3F U+003F question
+!40 U+0040 at
+!41 U+0041 A
+!42 U+0042 B
+!43 U+0043 C
+!44 U+0044 D
+!45 U+0045 E
+!46 U+0046 F
+!47 U+0047 G
+!48 U+0048 H
+!49 U+0049 I
+!4A U+004A J
+!4B U+004B K
+!4C U+004C L
+!4D U+004D M
+!4E U+004E N
+!4F U+004F O
+!50 U+0050 P
+!51 U+0051 Q
+!52 U+0052 R
+!53 U+0053 S
+!54 U+0054 T
+!55 U+0055 U
+!56 U+0056 V
+!57 U+0057 W
+!58 U+0058 X
+!59 U+0059 Y
+!5A U+005A Z
+!5B U+005B bracketleft
+!5C U+005C backslash
+!5D U+005D bracketright
+!5E U+005E asciicircum
+!5F U+005F underscore
+!60 U+0060 grave
+!61 U+0061 a
+!62 U+0062 b
+!63 U+0063 c
+!64 U+0064 d
+!65 U+0065 e
+!66 U+0066 f
+!67 U+0067 g
+!68 U+0068 h
+!69 U+0069 i
+!6A U+006A j
+!6B U+006B k
+!6C U+006C l
+!6D U+006D m
+!6E U+006E n
+!6F U+006F o
+!70 U+0070 p
+!71 U+0071 q
+!72 U+0072 r
+!73 U+0073 s
+!74 U+0074 t
+!75 U+0075 u
+!76 U+0076 v
+!77 U+0077 w
+!78 U+0078 x
+!79 U+0079 y
+!7A U+007A z
+!7B U+007B braceleft
+!7C U+007C bar
+!7D U+007D braceright
+!7E U+007E asciitilde
+!7F U+007F .notdef
+!80 U+2500 SF100000
+!81 U+2502 SF110000
+!82 U+250C SF010000
+!83 U+2510 SF030000
+!84 U+2514 SF020000
+!85 U+2518 SF040000
+!86 U+251C SF080000
+!87 U+2524 SF090000
+!88 U+252C SF060000
+!89 U+2534 SF070000
+!8A U+253C SF050000
+!8B U+2580 upblock
+!8C U+2584 dnblock
+!8D U+2588 block
+!8E U+258C lfblock
+!8F U+2590 rtblock
+!90 U+2591 ltshade
+!91 U+2592 shade
+!92 U+2593 dkshade
+!93 U+2320 integraltp
+!94 U+25A0 filledbox
+!95 U+2022 bullet
+!96 U+221A radical
+!97 U+2248 approxequal
+!98 U+2264 lessequal
+!99 U+2265 greaterequal
+!9A U+00A0 space
+!9B U+2321 integralbt
+!9C U+00B0 degree
+!9D U+00B2 twosuperior
+!9E U+00B7 periodcentered
+!9F U+00F7 divide
+!A0 U+2550 SF430000
+!A1 U+2551 SF240000
+!A2 U+2552 SF510000
+!A3 U+0451 afii10071
+!A4 U+0454 afii10101
+!A5 U+2554 SF390000
+!A6 U+0456 afii10103
+!A7 U+0457 afii10104
+!A8 U+2557 SF250000
+!A9 U+2558 SF500000
+!AA U+2559 SF490000
+!AB U+255A SF380000
+!AC U+255B SF280000
+!AD U+0491 afii10098
+!AE U+255D SF260000
+!AF U+255E SF360000
+!B0 U+255F SF370000
+!B1 U+2560 SF420000
+!B2 U+2561 SF190000
+!B3 U+0401 afii10023
+!B4 U+0404 afii10053
+!B5 U+2563 SF230000
+!B6 U+0406 afii10055
+!B7 U+0407 afii10056
+!B8 U+2566 SF410000
+!B9 U+2567 SF450000
+!BA U+2568 SF460000
+!BB U+2569 SF400000
+!BC U+256A SF540000
+!BD U+0490 afii10050
+!BE U+256C SF440000
+!BF U+00A9 copyright
+!C0 U+044E afii10096
+!C1 U+0430 afii10065
+!C2 U+0431 afii10066
+!C3 U+0446 afii10088
+!C4 U+0434 afii10069
+!C5 U+0435 afii10070
+!C6 U+0444 afii10086
+!C7 U+0433 afii10068
+!C8 U+0445 afii10087
+!C9 U+0438 afii10074
+!CA U+0439 afii10075
+!CB U+043A afii10076
+!CC U+043B afii10077
+!CD U+043C afii10078
+!CE U+043D afii10079
+!CF U+043E afii10080
+!D0 U+043F afii10081
+!D1 U+044F afii10097
+!D2 U+0440 afii10082
+!D3 U+0441 afii10083
+!D4 U+0442 afii10084
+!D5 U+0443 afii10085
+!D6 U+0436 afii10072
+!D7 U+0432 afii10067
+!D8 U+044C afii10094
+!D9 U+044B afii10093
+!DA U+0437 afii10073
+!DB U+0448 afii10090
+!DC U+044D afii10095
+!DD U+0449 afii10091
+!DE U+0447 afii10089
+!DF U+044A afii10092
+!E0 U+042E afii10048
+!E1 U+0410 afii10017
+!E2 U+0411 afii10018
+!E3 U+0426 afii10040
+!E4 U+0414 afii10021
+!E5 U+0415 afii10022
+!E6 U+0424 afii10038
+!E7 U+0413 afii10020
+!E8 U+0425 afii10039
+!E9 U+0418 afii10026
+!EA U+0419 afii10027
+!EB U+041A afii10028
+!EC U+041B afii10029
+!ED U+041C afii10030
+!EE U+041D afii10031
+!EF U+041E afii10032
+!F0 U+041F afii10033
+!F1 U+042F afii10049
+!F2 U+0420 afii10034
+!F3 U+0421 afii10035
+!F4 U+0422 afii10036
+!F5 U+0423 afii10037
+!F6 U+0416 afii10024
+!F7 U+0412 afii10019
+!F8 U+042C afii10046
+!F9 U+042B afii10045
+!FA U+0417 afii10025
+!FB U+0428 afii10042
+!FC U+042D afii10047
+!FD U+0429 afii10043
+!FE U+0427 afii10041
+!FF U+042A afii10044
diff --git a/plugins/serendipity_event_blogpdf/font/symbol.php b/plugins/serendipity_event_blogpdf/font/symbol.php
new file mode 100644 (file)
index 0000000..b556ed8
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+$fpdf_charwidths['symbol']=array(
+       chr(0)=>250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250,
+       chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>713,'#'=>500,'$'=>549,'%'=>833,'&'=>778,'\''=>439,'('=>333,')'=>333,'*'=>500,'+'=>549,
+       ','=>250,'-'=>549,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>278,';'=>278,'<'=>549,'='=>549,'>'=>549,'?'=>444,'@'=>549,'A'=>722,
+       'B'=>667,'C'=>722,'D'=>612,'E'=>611,'F'=>763,'G'=>603,'H'=>722,'I'=>333,'J'=>631,'K'=>722,'L'=>686,'M'=>889,'N'=>722,'O'=>722,'P'=>768,'Q'=>741,'R'=>556,'S'=>592,'T'=>611,'U'=>690,'V'=>439,'W'=>768,
+       'X'=>645,'Y'=>795,'Z'=>611,'['=>333,'\\'=>863,']'=>333,'^'=>658,'_'=>500,'`'=>500,'a'=>631,'b'=>549,'c'=>549,'d'=>494,'e'=>439,'f'=>521,'g'=>411,'h'=>603,'i'=>329,'j'=>603,'k'=>549,'l'=>549,'m'=>576,
+       'n'=>521,'o'=>549,'p'=>549,'q'=>521,'r'=>549,'s'=>603,'t'=>439,'u'=>576,'v'=>713,'w'=>686,'x'=>493,'y'=>686,'z'=>494,'{'=>480,'|'=>200,'}'=>480,'~'=>549,chr(127)=>0,chr(128)=>0,chr(129)=>0,chr(130)=>0,chr(131)=>0,
+       chr(132)=>0,chr(133)=>0,chr(134)=>0,chr(135)=>0,chr(136)=>0,chr(137)=>0,chr(138)=>0,chr(139)=>0,chr(140)=>0,chr(141)=>0,chr(142)=>0,chr(143)=>0,chr(144)=>0,chr(145)=>0,chr(146)=>0,chr(147)=>0,chr(148)=>0,chr(149)=>0,chr(150)=>0,chr(151)=>0,chr(152)=>0,chr(153)=>0,
+       chr(154)=>0,chr(155)=>0,chr(156)=>0,chr(157)=>0,chr(158)=>0,chr(159)=>0,chr(160)=>750,chr(161)=>620,chr(162)=>247,chr(163)=>549,chr(164)=>167,chr(165)=>713,chr(166)=>500,chr(167)=>753,chr(168)=>753,chr(169)=>753,chr(170)=>753,chr(171)=>1042,chr(172)=>987,chr(173)=>603,chr(174)=>987,chr(175)=>603,
+       chr(176)=>400,chr(177)=>549,chr(178)=>411,chr(179)=>549,chr(180)=>549,chr(181)=>713,chr(182)=>494,chr(183)=>460,chr(184)=>549,chr(185)=>549,chr(186)=>549,chr(187)=>549,chr(188)=>1000,chr(189)=>603,chr(190)=>1000,chr(191)=>658,chr(192)=>823,chr(193)=>686,chr(194)=>795,chr(195)=>987,chr(196)=>768,chr(197)=>768,
+       chr(198)=>823,chr(199)=>768,chr(200)=>768,chr(201)=>713,chr(202)=>713,chr(203)=>713,chr(204)=>713,chr(205)=>713,chr(206)=>713,chr(207)=>713,chr(208)=>768,chr(209)=>713,chr(210)=>790,chr(211)=>790,chr(212)=>890,chr(213)=>823,chr(214)=>549,chr(215)=>250,chr(216)=>713,chr(217)=>603,chr(218)=>603,chr(219)=>1042,
+       chr(220)=>987,chr(221)=>603,chr(222)=>987,chr(223)=>603,chr(224)=>494,chr(225)=>329,chr(226)=>790,chr(227)=>790,chr(228)=>786,chr(229)=>713,chr(230)=>384,chr(231)=>384,chr(232)=>384,chr(233)=>384,chr(234)=>384,chr(235)=>384,chr(236)=>494,chr(237)=>494,chr(238)=>494,chr(239)=>494,chr(240)=>0,chr(241)=>329,
+       chr(242)=>274,chr(243)=>686,chr(244)=>686,chr(245)=>686,chr(246)=>384,chr(247)=>384,chr(248)=>384,chr(249)=>384,chr(250)=>384,chr(251)=>384,chr(252)=>494,chr(253)=>494,chr(254)=>494,chr(255)=>0);
+?>
diff --git a/plugins/serendipity_event_blogpdf/font/times.php b/plugins/serendipity_event_blogpdf/font/times.php
new file mode 100644 (file)
index 0000000..b9be1b2
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+$fpdf_charwidths['times']=array(
+       chr(0)=>250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250,
+       chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>408,'#'=>500,'$'=>500,'%'=>833,'&'=>778,'\''=>180,'('=>333,')'=>333,'*'=>500,'+'=>564,
+       ','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>278,';'=>278,'<'=>564,'='=>564,'>'=>564,'?'=>444,'@'=>921,'A'=>722,
+       'B'=>667,'C'=>667,'D'=>722,'E'=>611,'F'=>556,'G'=>722,'H'=>722,'I'=>333,'J'=>389,'K'=>722,'L'=>611,'M'=>889,'N'=>722,'O'=>722,'P'=>556,'Q'=>722,'R'=>667,'S'=>556,'T'=>611,'U'=>722,'V'=>722,'W'=>944,
+       'X'=>722,'Y'=>722,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>469,'_'=>500,'`'=>333,'a'=>444,'b'=>500,'c'=>444,'d'=>500,'e'=>444,'f'=>333,'g'=>500,'h'=>500,'i'=>278,'j'=>278,'k'=>500,'l'=>278,'m'=>778,
+       'n'=>500,'o'=>500,'p'=>500,'q'=>500,'r'=>333,'s'=>389,'t'=>278,'u'=>500,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>444,'{'=>480,'|'=>200,'}'=>480,'~'=>541,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500,
+       chr(132)=>444,chr(133)=>1000,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>556,chr(139)=>333,chr(140)=>889,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>444,chr(148)=>444,chr(149)=>350,chr(150)=>500,chr(151)=>1000,chr(152)=>333,chr(153)=>980,
+       chr(154)=>389,chr(155)=>333,chr(156)=>722,chr(157)=>350,chr(158)=>444,chr(159)=>722,chr(160)=>250,chr(161)=>333,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>200,chr(167)=>500,chr(168)=>333,chr(169)=>760,chr(170)=>276,chr(171)=>500,chr(172)=>564,chr(173)=>333,chr(174)=>760,chr(175)=>333,
+       chr(176)=>400,chr(177)=>564,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>500,chr(182)=>453,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>310,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>444,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722,
+       chr(198)=>889,chr(199)=>667,chr(200)=>611,chr(201)=>611,chr(202)=>611,chr(203)=>611,chr(204)=>333,chr(205)=>333,chr(206)=>333,chr(207)=>333,chr(208)=>722,chr(209)=>722,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>564,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722,
+       chr(220)=>722,chr(221)=>722,chr(222)=>556,chr(223)=>500,chr(224)=>444,chr(225)=>444,chr(226)=>444,chr(227)=>444,chr(228)=>444,chr(229)=>444,chr(230)=>667,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>500,
+       chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>564,chr(248)=>500,chr(249)=>500,chr(250)=>500,chr(251)=>500,chr(252)=>500,chr(253)=>500,chr(254)=>500,chr(255)=>500);
+?>
diff --git a/plugins/serendipity_event_blogpdf/font/timesb.php b/plugins/serendipity_event_blogpdf/font/timesb.php
new file mode 100644 (file)
index 0000000..c3eb9fa
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+$fpdf_charwidths['timesB']=array(
+       chr(0)=>250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250,
+       chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>555,'#'=>500,'$'=>500,'%'=>1000,'&'=>833,'\''=>278,'('=>333,')'=>333,'*'=>500,'+'=>570,
+       ','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>333,';'=>333,'<'=>570,'='=>570,'>'=>570,'?'=>500,'@'=>930,'A'=>722,
+       'B'=>667,'C'=>722,'D'=>722,'E'=>667,'F'=>611,'G'=>778,'H'=>778,'I'=>389,'J'=>500,'K'=>778,'L'=>667,'M'=>944,'N'=>722,'O'=>778,'P'=>611,'Q'=>778,'R'=>722,'S'=>556,'T'=>667,'U'=>722,'V'=>722,'W'=>1000,
+       'X'=>722,'Y'=>722,'Z'=>667,'['=>333,'\\'=>278,']'=>333,'^'=>581,'_'=>500,'`'=>333,'a'=>500,'b'=>556,'c'=>444,'d'=>556,'e'=>444,'f'=>333,'g'=>500,'h'=>556,'i'=>278,'j'=>333,'k'=>556,'l'=>278,'m'=>833,
+       'n'=>556,'o'=>500,'p'=>556,'q'=>556,'r'=>444,'s'=>389,'t'=>333,'u'=>556,'v'=>500,'w'=>722,'x'=>500,'y'=>500,'z'=>444,'{'=>394,'|'=>220,'}'=>394,'~'=>520,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500,
+       chr(132)=>500,chr(133)=>1000,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>556,chr(139)=>333,chr(140)=>1000,chr(141)=>350,chr(142)=>667,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>500,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
+       chr(154)=>389,chr(155)=>333,chr(156)=>722,chr(157)=>350,chr(158)=>444,chr(159)=>722,chr(160)=>250,chr(161)=>333,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>220,chr(167)=>500,chr(168)=>333,chr(169)=>747,chr(170)=>300,chr(171)=>500,chr(172)=>570,chr(173)=>333,chr(174)=>747,chr(175)=>333,
+       chr(176)=>400,chr(177)=>570,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>556,chr(182)=>540,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>330,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>500,chr(192)=>722,chr(193)=>722,chr(194)=>722,chr(195)=>722,chr(196)=>722,chr(197)=>722,
+       chr(198)=>1000,chr(199)=>722,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>389,chr(205)=>389,chr(206)=>389,chr(207)=>389,chr(208)=>722,chr(209)=>722,chr(210)=>778,chr(211)=>778,chr(212)=>778,chr(213)=>778,chr(214)=>778,chr(215)=>570,chr(216)=>778,chr(217)=>722,chr(218)=>722,chr(219)=>722,
+       chr(220)=>722,chr(221)=>722,chr(222)=>611,chr(223)=>556,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>722,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>556,
+       chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>570,chr(248)=>500,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>500,chr(254)=>556,chr(255)=>500);
+?>
diff --git a/plugins/serendipity_event_blogpdf/font/timesbi.php b/plugins/serendipity_event_blogpdf/font/timesbi.php
new file mode 100644 (file)
index 0000000..161f630
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+$fpdf_charwidths['timesBI']=array(
+       chr(0)=>250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250,
+       chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>389,'"'=>555,'#'=>500,'$'=>500,'%'=>833,'&'=>778,'\''=>278,'('=>333,')'=>333,'*'=>500,'+'=>570,
+       ','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>333,';'=>333,'<'=>570,'='=>570,'>'=>570,'?'=>500,'@'=>832,'A'=>667,
+       'B'=>667,'C'=>667,'D'=>722,'E'=>667,'F'=>667,'G'=>722,'H'=>778,'I'=>389,'J'=>500,'K'=>667,'L'=>611,'M'=>889,'N'=>722,'O'=>722,'P'=>611,'Q'=>722,'R'=>667,'S'=>556,'T'=>611,'U'=>722,'V'=>667,'W'=>889,
+       'X'=>667,'Y'=>611,'Z'=>611,'['=>333,'\\'=>278,']'=>333,'^'=>570,'_'=>500,'`'=>333,'a'=>500,'b'=>500,'c'=>444,'d'=>500,'e'=>444,'f'=>333,'g'=>500,'h'=>556,'i'=>278,'j'=>278,'k'=>500,'l'=>278,'m'=>778,
+       'n'=>556,'o'=>500,'p'=>500,'q'=>500,'r'=>389,'s'=>389,'t'=>278,'u'=>556,'v'=>444,'w'=>667,'x'=>500,'y'=>444,'z'=>389,'{'=>348,'|'=>220,'}'=>348,'~'=>570,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500,
+       chr(132)=>500,chr(133)=>1000,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>556,chr(139)=>333,chr(140)=>944,chr(141)=>350,chr(142)=>611,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>500,chr(148)=>500,chr(149)=>350,chr(150)=>500,chr(151)=>1000,chr(152)=>333,chr(153)=>1000,
+       chr(154)=>389,chr(155)=>333,chr(156)=>722,chr(157)=>350,chr(158)=>389,chr(159)=>611,chr(160)=>250,chr(161)=>389,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>220,chr(167)=>500,chr(168)=>333,chr(169)=>747,chr(170)=>266,chr(171)=>500,chr(172)=>606,chr(173)=>333,chr(174)=>747,chr(175)=>333,
+       chr(176)=>400,chr(177)=>570,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>576,chr(182)=>500,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>300,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>500,chr(192)=>667,chr(193)=>667,chr(194)=>667,chr(195)=>667,chr(196)=>667,chr(197)=>667,
+       chr(198)=>944,chr(199)=>667,chr(200)=>667,chr(201)=>667,chr(202)=>667,chr(203)=>667,chr(204)=>389,chr(205)=>389,chr(206)=>389,chr(207)=>389,chr(208)=>722,chr(209)=>722,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>570,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722,
+       chr(220)=>722,chr(221)=>611,chr(222)=>611,chr(223)=>500,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>722,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>556,
+       chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>570,chr(248)=>500,chr(249)=>556,chr(250)=>556,chr(251)=>556,chr(252)=>556,chr(253)=>444,chr(254)=>500,chr(255)=>444);
+?>
diff --git a/plugins/serendipity_event_blogpdf/font/timesi.php b/plugins/serendipity_event_blogpdf/font/timesi.php
new file mode 100644 (file)
index 0000000..de171fd
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+$fpdf_charwidths['timesI']=array(
+       chr(0)=>250,chr(1)=>250,chr(2)=>250,chr(3)=>250,chr(4)=>250,chr(5)=>250,chr(6)=>250,chr(7)=>250,chr(8)=>250,chr(9)=>250,chr(10)=>250,chr(11)=>250,chr(12)=>250,chr(13)=>250,chr(14)=>250,chr(15)=>250,chr(16)=>250,chr(17)=>250,chr(18)=>250,chr(19)=>250,chr(20)=>250,chr(21)=>250,
+       chr(22)=>250,chr(23)=>250,chr(24)=>250,chr(25)=>250,chr(26)=>250,chr(27)=>250,chr(28)=>250,chr(29)=>250,chr(30)=>250,chr(31)=>250,' '=>250,'!'=>333,'"'=>420,'#'=>500,'$'=>500,'%'=>833,'&'=>778,'\''=>214,'('=>333,')'=>333,'*'=>500,'+'=>675,
+       ','=>250,'-'=>333,'.'=>250,'/'=>278,'0'=>500,'1'=>500,'2'=>500,'3'=>500,'4'=>500,'5'=>500,'6'=>500,'7'=>500,'8'=>500,'9'=>500,':'=>333,';'=>333,'<'=>675,'='=>675,'>'=>675,'?'=>500,'@'=>920,'A'=>611,
+       'B'=>611,'C'=>667,'D'=>722,'E'=>611,'F'=>611,'G'=>722,'H'=>722,'I'=>333,'J'=>444,'K'=>667,'L'=>556,'M'=>833,'N'=>667,'O'=>722,'P'=>611,'Q'=>722,'R'=>611,'S'=>500,'T'=>556,'U'=>722,'V'=>611,'W'=>833,
+       'X'=>611,'Y'=>556,'Z'=>556,'['=>389,'\\'=>278,']'=>389,'^'=>422,'_'=>500,'`'=>333,'a'=>500,'b'=>500,'c'=>444,'d'=>500,'e'=>444,'f'=>278,'g'=>500,'h'=>500,'i'=>278,'j'=>278,'k'=>444,'l'=>278,'m'=>722,
+       'n'=>500,'o'=>500,'p'=>500,'q'=>500,'r'=>389,'s'=>389,'t'=>278,'u'=>500,'v'=>444,'w'=>667,'x'=>444,'y'=>444,'z'=>389,'{'=>400,'|'=>275,'}'=>400,'~'=>541,chr(127)=>350,chr(128)=>500,chr(129)=>350,chr(130)=>333,chr(131)=>500,
+       chr(132)=>556,chr(133)=>889,chr(134)=>500,chr(135)=>500,chr(136)=>333,chr(137)=>1000,chr(138)=>500,chr(139)=>333,chr(140)=>944,chr(141)=>350,chr(142)=>556,chr(143)=>350,chr(144)=>350,chr(145)=>333,chr(146)=>333,chr(147)=>556,chr(148)=>556,chr(149)=>350,chr(150)=>500,chr(151)=>889,chr(152)=>333,chr(153)=>980,
+       chr(154)=>389,chr(155)=>333,chr(156)=>667,chr(157)=>350,chr(158)=>389,chr(159)=>556,chr(160)=>250,chr(161)=>389,chr(162)=>500,chr(163)=>500,chr(164)=>500,chr(165)=>500,chr(166)=>275,chr(167)=>500,chr(168)=>333,chr(169)=>760,chr(170)=>276,chr(171)=>500,chr(172)=>675,chr(173)=>333,chr(174)=>760,chr(175)=>333,
+       chr(176)=>400,chr(177)=>675,chr(178)=>300,chr(179)=>300,chr(180)=>333,chr(181)=>500,chr(182)=>523,chr(183)=>250,chr(184)=>333,chr(185)=>300,chr(186)=>310,chr(187)=>500,chr(188)=>750,chr(189)=>750,chr(190)=>750,chr(191)=>500,chr(192)=>611,chr(193)=>611,chr(194)=>611,chr(195)=>611,chr(196)=>611,chr(197)=>611,
+       chr(198)=>889,chr(199)=>667,chr(200)=>611,chr(201)=>611,chr(202)=>611,chr(203)=>611,chr(204)=>333,chr(205)=>333,chr(206)=>333,chr(207)=>333,chr(208)=>722,chr(209)=>667,chr(210)=>722,chr(211)=>722,chr(212)=>722,chr(213)=>722,chr(214)=>722,chr(215)=>675,chr(216)=>722,chr(217)=>722,chr(218)=>722,chr(219)=>722,
+       chr(220)=>722,chr(221)=>556,chr(222)=>611,chr(223)=>500,chr(224)=>500,chr(225)=>500,chr(226)=>500,chr(227)=>500,chr(228)=>500,chr(229)=>500,chr(230)=>667,chr(231)=>444,chr(232)=>444,chr(233)=>444,chr(234)=>444,chr(235)=>444,chr(236)=>278,chr(237)=>278,chr(238)=>278,chr(239)=>278,chr(240)=>500,chr(241)=>500,
+       chr(242)=>500,chr(243)=>500,chr(244)=>500,chr(245)=>500,chr(246)=>500,chr(247)=>675,chr(248)=>500,chr(249)=>500,chr(250)=>500,chr(251)=>500,chr(252)=>500,chr(253)=>444,chr(254)=>500,chr(255)=>444);
+?>
diff --git a/plugins/serendipity_event_blogpdf/font/zapfdingbats.php b/plugins/serendipity_event_blogpdf/font/zapfdingbats.php
new file mode 100644 (file)
index 0000000..f2bdfd5
--- /dev/null
@@ -0,0 +1,15 @@
+<?php
+$fpdf_charwidths['zapfdingbats']=array(
+       chr(0)=>0,chr(1)=>0,chr(2)=>0,chr(3)=>0,chr(4)=>0,chr(5)=>0,chr(6)=>0,chr(7)=>0,chr(8)=>0,chr(9)=>0,chr(10)=>0,chr(11)=>0,chr(12)=>0,chr(13)=>0,chr(14)=>0,chr(15)=>0,chr(16)=>0,chr(17)=>0,chr(18)=>0,chr(19)=>0,chr(20)=>0,chr(21)=>0,
+       chr(22)=>0,chr(23)=>0,chr(24)=>0,chr(25)=>0,chr(26)=>0,chr(27)=>0,chr(28)=>0,chr(29)=>0,chr(30)=>0,chr(31)=>0,' '=>278,'!'=>974,'"'=>961,'#'=>974,'$'=>980,'%'=>719,'&'=>789,'\''=>790,'('=>791,')'=>690,'*'=>960,'+'=>939,
+       ','=>549,'-'=>855,'.'=>911,'/'=>933,'0'=>911,'1'=>945,'2'=>974,'3'=>755,'4'=>846,'5'=>762,'6'=>761,'7'=>571,'8'=>677,'9'=>763,':'=>760,';'=>759,'<'=>754,'='=>494,'>'=>552,'?'=>537,'@'=>577,'A'=>692,
+       'B'=>786,'C'=>788,'D'=>788,'E'=>790,'F'=>793,'G'=>794,'H'=>816,'I'=>823,'J'=>789,'K'=>841,'L'=>823,'M'=>833,'N'=>816,'O'=>831,'P'=>923,'Q'=>744,'R'=>723,'S'=>749,'T'=>790,'U'=>792,'V'=>695,'W'=>776,
+       'X'=>768,'Y'=>792,'Z'=>759,'['=>707,'\\'=>708,']'=>682,'^'=>701,'_'=>826,'`'=>815,'a'=>789,'b'=>789,'c'=>707,'d'=>687,'e'=>696,'f'=>689,'g'=>786,'h'=>787,'i'=>713,'j'=>791,'k'=>785,'l'=>791,'m'=>873,
+       'n'=>761,'o'=>762,'p'=>762,'q'=>759,'r'=>759,'s'=>892,'t'=>892,'u'=>788,'v'=>784,'w'=>438,'x'=>138,'y'=>277,'z'=>415,'{'=>392,'|'=>392,'}'=>668,'~'=>668,chr(127)=>0,chr(128)=>390,chr(129)=>390,chr(130)=>317,chr(131)=>317,
+       chr(132)=>276,chr(133)=>276,chr(134)=>509,chr(135)=>509,chr(136)=>410,chr(137)=>410,chr(138)=>234,chr(139)=>234,chr(140)=>334,chr(141)=>334,chr(142)=>0,chr(143)=>0,chr(144)=>0,chr(145)=>0,chr(146)=>0,chr(147)=>0,chr(148)=>0,chr(149)=>0,chr(150)=>0,chr(151)=>0,chr(152)=>0,chr(153)=>0,
+       chr(154)=>0,chr(155)=>0,chr(156)=>0,chr(157)=>0,chr(158)=>0,chr(159)=>0,chr(160)=>0,chr(161)=>732,chr(162)=>544,chr(163)=>544,chr(164)=>910,chr(165)=>667,chr(166)=>760,chr(167)=>760,chr(168)=>776,chr(169)=>595,chr(170)=>694,chr(171)=>626,chr(172)=>788,chr(173)=>788,chr(174)=>788,chr(175)=>788,
+       chr(176)=>788,chr(177)=>788,chr(178)=>788,chr(179)=>788,chr(180)=>788,chr(181)=>788,chr(182)=>788,chr(183)=>788,chr(184)=>788,chr(185)=>788,chr(186)=>788,chr(187)=>788,chr(188)=>788,chr(189)=>788,chr(190)=>788,chr(191)=>788,chr(192)=>788,chr(193)=>788,chr(194)=>788,chr(195)=>788,chr(196)=>788,chr(197)=>788,
+       chr(198)=>788,chr(199)=>788,chr(200)=>788,chr(201)=>788,chr(202)=>788,chr(203)=>788,chr(204)=>788,chr(205)=>788,chr(206)=>788,chr(207)=>788,chr(208)=>788,chr(209)=>788,chr(210)=>788,chr(211)=>788,chr(212)=>894,chr(213)=>838,chr(214)=>1016,chr(215)=>458,chr(216)=>748,chr(217)=>924,chr(218)=>748,chr(219)=>918,
+       chr(220)=>927,chr(221)=>928,chr(222)=>928,chr(223)=>834,chr(224)=>873,chr(225)=>828,chr(226)=>924,chr(227)=>924,chr(228)=>917,chr(229)=>930,chr(230)=>931,chr(231)=>463,chr(232)=>883,chr(233)=>836,chr(234)=>836,chr(235)=>867,chr(236)=>867,chr(237)=>696,chr(238)=>696,chr(239)=>874,chr(240)=>0,chr(241)=>874,
+       chr(242)=>760,chr(243)=>946,chr(244)=>771,chr(245)=>865,chr(246)=>771,chr(247)=>888,chr(248)=>967,chr(249)=>888,chr(250)=>831,chr(251)=>873,chr(252)=>927,chr(253)=>970,chr(254)=>918,chr(255)=>0);
+?>
diff --git a/plugins/serendipity_event_blogpdf/fpdf.php b/plugins/serendipity_event_blogpdf/fpdf.php
new file mode 100644 (file)
index 0000000..c307b7b
--- /dev/null
@@ -0,0 +1,1618 @@
+<?php
+/*******************************************************************************
+* Software: FPDF                                                               *
+* Version:  1.52                                                               *
+* Date:     2003-12-30                                                         *
+* Author:   Olivier PLATHEY                                                    *
+* License:  Freeware                                                           *
+*                                                                              *
+* You may use, modify and redistribute this software as you wish.              *
+*******************************************************************************/
+
+if(!class_exists('FPDF'))
+{
+define('FPDF_VERSION','1.52');
+
+class FPDF
+{
+//Private properties
+var $page;               //current page number
+var $n;                  //current object number
+var $offsets;            //array of object offsets
+var $buffer;             //buffer holding in-memory PDF
+var $pages;              //array containing pages
+var $state;              //current document state
+var $compress;           //compression flag
+var $DefOrientation;     //default orientation
+var $CurOrientation;     //current orientation
+var $OrientationChanges; //array indicating orientation changes
+var $k;                  //scale factor (number of points in user unit)
+var $fwPt,$fhPt;         //dimensions of page format in points
+var $fw,$fh;             //dimensions of page format in user unit
+var $wPt,$hPt;           //current dimensions of page in points
+var $w,$h;               //current dimensions of page in user unit
+var $lMargin;            //left margin
+var $tMargin;            //top margin
+var $rMargin;            //right margin
+var $bMargin;            //page break margin
+var $cMargin;            //cell margin
+var $x,$y;               //current position in user unit for cell positioning
+var $lasth;              //height of last cell printed
+var $LineWidth;          //line width in user unit
+var $CoreFonts;          //array of standard font names
+var $fonts;              //array of used fonts
+var $FontFiles;          //array of font files
+var $diffs;              //array of encoding differences
+var $images;             //array of used images
+var $PageLinks;          //array of links in pages
+var $links;              //array of internal links
+var $FontFamily;         //current font family
+var $FontStyle;          //current font style
+var $underline;          //underlining flag
+var $CurrentFont;        //current font info
+var $FontSizePt;         //current font size in points
+var $FontSize;           //current font size in user unit
+var $DrawColor;          //commands for drawing color
+var $FillColor;          //commands for filling color
+var $TextColor;          //commands for text color
+var $ColorFlag;          //indicates whether fill and text colors are different
+var $ws;                 //word spacing
+var $AutoPageBreak;      //automatic page breaking
+var $PageBreakTrigger;   //threshold used to trigger page breaks
+var $InFooter;           //flag set when processing footer
+var $ZoomMode;           //zoom display mode
+var $LayoutMode;         //layout display mode
+var $title;              //title
+var $subject;            //subject
+var $author;             //author
+var $keywords;           //keywords
+var $creator;            //creator
+var $AliasNbPages;       //alias for total number of pages
+
+/*******************************************************************************
+*                                                                              *
+*                               Public methods                                 *
+*                                                                              *
+*******************************************************************************/
+function FPDF($orientation='P',$unit='mm',$format='A4')
+{
+       //Some checks
+       $this->_dochecks();
+       //Initialization of properties
+       $this->page=0;
+       $this->n=2;
+       $this->buffer='';
+       $this->pages=array();
+       $this->OrientationChanges=array();
+       $this->state=0;
+       $this->fonts=array();
+       $this->FontFiles=array();
+       $this->diffs=array();
+       $this->images=array();
+       $this->links=array();
+       $this->InFooter=false;
+       $this->lasth=0;
+       $this->FontFamily='';
+       $this->FontStyle='';
+       $this->FontSizePt=12;
+       $this->underline=false;
+       $this->DrawColor='0 G';
+       $this->FillColor='0 g';
+       $this->TextColor='0 g';
+       $this->ColorFlag=false;
+       $this->ws=0;
+       //Standard fonts
+       $this->CoreFonts=array('courier'=>'Courier','courierB'=>'Courier-Bold','courierI'=>'Courier-Oblique','courierBI'=>'Courier-BoldOblique',
+               'helvetica'=>'Helvetica','helveticaB'=>'Helvetica-Bold','helveticaI'=>'Helvetica-Oblique','helveticaBI'=>'Helvetica-BoldOblique',
+               'times'=>'Times-Roman','timesB'=>'Times-Bold','timesI'=>'Times-Italic','timesBI'=>'Times-BoldItalic',
+               'symbol'=>'Symbol','zapfdingbats'=>'ZapfDingbats');
+       //Scale factor
+       if($unit=='pt')
+               $this->k=1;
+       elseif($unit=='mm')
+               $this->k=72/25.4;
+       elseif($unit=='cm')
+               $this->k=72/2.54;
+       elseif($unit=='in')
+               $this->k=72;
+       else
+               $this->Error('Incorrect unit: '.$unit);
+       //Page format
+       if(is_string($format))
+       {
+               $format=strtolower($format);
+               if($format=='a3')
+                       $format=array(841.89,1190.55);
+               elseif($format=='a4')
+                       $format=array(595.28,841.89);
+               elseif($format=='a5')
+                       $format=array(420.94,595.28);
+               elseif($format=='letter')
+                       $format=array(612,792);
+               elseif($format=='legal')
+                       $format=array(612,1008);
+               else
+                       $this->Error('Unknown page format: '.$format);
+               $this->fwPt=$format[0];
+               $this->fhPt=$format[1];
+       }
+       else
+       {
+               $this->fwPt=$format[0]*$this->k;
+               $this->fhPt=$format[1]*$this->k;
+       }
+       $this->fw=$this->fwPt/$this->k;
+       $this->fh=$this->fhPt/$this->k;
+       //Page orientation
+       $orientation=strtolower($orientation);
+       if($orientation=='p' or $orientation=='portrait')
+       {
+               $this->DefOrientation='P';
+               $this->wPt=$this->fwPt;
+               $this->hPt=$this->fhPt;
+       }
+       elseif($orientation=='l' or $orientation=='landscape')
+       {
+               $this->DefOrientation='L';
+               $this->wPt=$this->fhPt;
+               $this->hPt=$this->fwPt;
+       }
+       else
+               $this->Error('Incorrect orientation: '.$orientation);
+       $this->CurOrientation=$this->DefOrientation;
+       $this->w=$this->wPt/$this->k;
+       $this->h=$this->hPt/$this->k;
+       //Page margins (1 cm)
+       $margin=28.35/$this->k;
+       $this->SetMargins($margin,$margin);
+       //Interior cell margin (1 mm)
+       $this->cMargin=$margin/10;
+       //Line width (0.2 mm)
+       $this->LineWidth=.567/$this->k;
+       //Automatic page break
+       $this->SetAutoPageBreak(true,2*$margin);
+       //Full width display mode
+       $this->SetDisplayMode('fullwidth');
+       //Compression
+       $this->SetCompression(true);
+}
+
+function SetMargins($left,$top,$right=-1)
+{
+       //Set left, top and right margins
+       $this->lMargin=$left;
+       $this->tMargin=$top;
+       if($right==-1)
+               $right=$left;
+       $this->rMargin=$right;
+}
+
+function SetLeftMargin($margin)
+{
+       //Set left margin
+       $this->lMargin=$margin;
+       if($this->page>0 and $this->x<$margin)
+               $this->x=$margin;
+}
+
+function SetTopMargin($margin)
+{
+       //Set top margin
+       $this->tMargin=$margin;
+}
+
+function SetRightMargin($margin)
+{
+       //Set right margin
+       $this->rMargin=$margin;
+}
+
+function SetAutoPageBreak($auto,$margin=0)
+{
+       //Set auto page break mode and triggering margin
+       $this->AutoPageBreak=$auto;
+       $this->bMargin=$margin;
+       $this->PageBreakTrigger=$this->h-$margin;
+}
+
+function SetDisplayMode($zoom,$layout='continuous')
+{
+       //Set display mode in viewer
+       if($zoom=='fullpage' or $zoom=='fullwidth' or $zoom=='real' or $zoom=='default' or !is_string($zoom))
+               $this->ZoomMode=$zoom;
+       else
+               $this->Error('Incorrect zoom display mode: '.$zoom);
+       if($layout=='single' or $layout=='continuous' or $layout=='two' or $layout=='default')
+               $this->LayoutMode=$layout;
+       else
+               $this->Error('Incorrect layout display mode: '.$layout);
+}
+
+function SetCompression($compress)
+{
+       //Set page compression
+       if(function_exists('gzcompress'))
+               $this->compress=$compress;
+       else
+               $this->compress=false;
+}
+
+function SetTitle($title)
+{
+       //Title of document
+       $this->title=$title;
+}
+
+function SetSubject($subject)
+{
+       //Subject of document
+       $this->subject=$subject;
+}
+
+function SetAuthor($author)
+{
+       //Author of document
+       $this->author=$author;
+}
+
+function SetKeywords($keywords)
+{
+       //Keywords of document
+       $this->keywords=$keywords;
+}
+
+function SetCreator($creator)
+{
+       //Creator of document
+       $this->creator=$creator;
+}
+
+function AliasNbPages($alias='{nb}')
+{
+       //Define an alias for total number of pages
+       $this->AliasNbPages=$alias;
+}
+
+function Error($msg)
+{
+       //Fatal error
+       die('<B>FPDF error: </B>'.$msg);
+}
+
+function Open()
+{
+       //Begin document
+       if($this->state==0)
+               $this->_begindoc();
+}
+
+function Close()
+{
+       //Terminate document
+       if($this->state==3)
+               return;
+       if($this->page==0)
+               $this->AddPage();
+       //Page footer
+       $this->InFooter=true;
+       $this->Footer();
+       $this->InFooter=false;
+       //Close page
+       $this->_endpage();
+       //Close document
+       $this->_enddoc();
+}
+
+function AddPage($orientation='')
+{
+       //Start a new page
+       if($this->state==0)
+               $this->Open();
+       $family=$this->FontFamily;
+       $style=$this->FontStyle.($this->underline ? 'U' : '');
+       $size=$this->FontSizePt;
+       $lw=$this->LineWidth;
+       $dc=$this->DrawColor;
+       $fc=$this->FillColor;
+       $tc=$this->TextColor;
+       $cf=$this->ColorFlag;
+       if($this->page>0)
+       {
+               //Page footer
+               $this->InFooter=true;
+               $this->Footer();
+               $this->InFooter=false;
+               //Close page
+               $this->_endpage();
+       }
+       //Start new page
+       $this->_beginpage($orientation);
+       //Set line cap style to square
+       $this->_out('2 J');
+       //Set line width
+       $this->LineWidth=$lw;
+       $this->_out(sprintf('%.2f w',$lw*$this->k));
+       //Set font
+       if($family)
+               $this->SetFont($family,$style,$size);
+       //Set colors
+       $this->DrawColor=$dc;
+       if($dc!='0 G')
+               $this->_out($dc);
+       $this->FillColor=$fc;
+       if($fc!='0 g')
+               $this->_out($fc);
+       $this->TextColor=$tc;
+       $this->ColorFlag=$cf;
+       //Page header
+       $this->Header();
+       //Restore line width
+       if($this->LineWidth!=$lw)
+       {
+               $this->LineWidth=$lw;
+               $this->_out(sprintf('%.2f w',$lw*$this->k));
+       }
+       //Restore font
+       if($family)
+               $this->SetFont($family,$style,$size);
+       //Restore colors
+       if($this->DrawColor!=$dc)
+       {
+               $this->DrawColor=$dc;
+               $this->_out($dc);
+       }
+       if($this->FillColor!=$fc)
+       {
+               $this->FillColor=$fc;
+               $this->_out($fc);
+       }
+       $this->TextColor=$tc;
+       $this->ColorFlag=$cf;
+}
+
+function Header()
+{
+       //To be implemented in your own inherited class
+}
+
+function Footer()
+{
+       //To be implemented in your own inherited class
+}
+
+function PageNo()
+{
+       //Get current page number
+       return $this->page;
+}
+
+function SetDrawColor($r,$g=-1,$b=-1)
+{
+       //Set color for all stroking operations
+       if(($r==0 and $g==0 and $b==0) or $g==-1)
+               $this->DrawColor=sprintf('%.3f G',$r/255);
+       else
+               $this->DrawColor=sprintf('%.3f %.3f %.3f RG',$r/255,$g/255,$b/255);
+       if($this->page>0)
+               $this->_out($this->DrawColor);
+}
+
+function SetFillColor($r,$g=-1,$b=-1)
+{
+       //Set color for all filling operations
+       if(($r==0 and $g==0 and $b==0) or $g==-1)
+               $this->FillColor=sprintf('%.3f g',$r/255);
+       else
+               $this->FillColor=sprintf('%.3f %.3f %.3f rg',$r/255,$g/255,$b/255);
+       $this->ColorFlag=($this->FillColor!=$this->TextColor);
+       if($this->page>0)
+               $this->_out($this->FillColor);
+}
+
+function SetTextColor($r,$g=-1,$b=-1)
+{
+       //Set color for text
+       if(($r==0 and $g==0 and $b==0) or $g==-1)
+               $this->TextColor=sprintf('%.3f g',$r/255);
+       else
+               $this->TextColor=sprintf('%.3f %.3f %.3f rg',$r/255,$g/255,$b/255);
+       $this->ColorFlag=($this->FillColor!=$this->TextColor);
+}
+
+function GetStringWidth($s)
+{
+       //Get width of a string in the current font
+       $s=(string)$s;
+       $cw=&$this->CurrentFont['cw'];
+       $w=0;
+       $l=strlen($s);
+       for($i=0;$i<$l;$i++)
+               $w+=$cw[$s{$i}];
+       return $w*$this->FontSize/1000;
+}
+
+function SetLineWidth($width)
+{
+       //Set line width
+       $this->LineWidth=$width;
+       if($this->page>0)
+               $this->_out(sprintf('%.2f w',$width*$this->k));
+}
+
+function Line($x1,$y1,$x2,$y2)
+{
+       //Draw a line
+       $this->_out(sprintf('%.2f %.2f m %.2f %.2f l S',$x1*$this->k,($this->h-$y1)*$this->k,$x2*$this->k,($this->h-$y2)*$this->k));
+}
+
+function Rect($x,$y,$w,$h,$style='')
+{
+       //Draw a rectangle
+       if($style=='F')
+               $op='f';
+       elseif($style=='FD' or $style=='DF')
+               $op='B';
+       else
+               $op='S';
+       $this->_out(sprintf('%.2f %.2f %.2f %.2f re %s',$x*$this->k,($this->h-$y)*$this->k,$w*$this->k,-$h*$this->k,$op));
+}
+
+function AddFont($family,$style='',$file='')
+{
+       //Add a TrueType or Type1 font
+       $family=strtolower($family);
+       if($family=='arial')
+               $family='helvetica';
+       $style=strtoupper($style);
+       if($style=='IB')
+               $style='BI';
+       if(isset($this->fonts[$family.$style]))
+               $this->Error('Font already added: '.$family.' '.$style);
+       if($file=='')
+               $file=str_replace(' ','',$family).strtolower($style).'.php';
+       if(defined('FPDF_FONTPATH'))
+               $file=FPDF_FONTPATH.$file;
+       include($file);
+       if(!isset($name))
+               $this->Error('Could not include font definition file');
+       $i=count($this->fonts)+1;
+       $this->fonts[$family.$style]=array('i'=>$i,'type'=>$type,'name'=>$name,'desc'=>$desc,'up'=>$up,'ut'=>$ut,'cw'=>$cw,'enc'=>$enc,'file'=>$file);
+       if($diff)
+       {
+               //Search existing encodings
+               $d=0;
+               $nb=count($this->diffs);
+               for($i=1;$i<=$nb;$i++)
+                       if($this->diffs[$i]==$diff)
+                       {
+                               $d=$i;
+                               break;
+                       }
+               if($d==0)
+               {
+                       $d=$nb+1;
+                       $this->diffs[$d]=$diff;
+               }
+               $this->fonts[$family.$style]['diff']=$d;
+       }
+       if($file)
+       {
+               if($type=='TrueType')
+                       $this->FontFiles[$file]=array('length1'=>$originalsize);
+               else
+                       $this->FontFiles[$file]=array('length1'=>$size1,'length2'=>$size2);
+       }
+}
+
+function SetFont($family,$style='',$size=0)
+{
+       //Select a font; size given in points
+       global $fpdf_charwidths;
+
+       $family=strtolower($family);
+       if($family=='')
+               $family=$this->FontFamily;
+       if($family=='arial')
+               $family='helvetica';
+       elseif($family=='symbol' or $family=='zapfdingbats')
+               $style='';
+       $style=strtoupper($style);
+       if(is_int(strpos($style,'U')))
+       {
+               $this->underline=true;
+               $style=str_replace('U','',$style);
+       }
+       else
+               $this->underline=false;
+       if($style=='IB')
+               $style='BI';
+       if($size==0)
+               $size=$this->FontSizePt;
+       //Test if font is already selected
+       if($this->FontFamily==$family and $this->FontStyle==$style and $this->FontSizePt==$size)
+               return;
+       //Test if used for the first time
+       $fontkey=$family.$style;
+       if(!isset($this->fonts[$fontkey]))
+       {
+               //Check if one of the standard fonts
+               if(isset($this->CoreFonts[$fontkey]))
+               {
+                       if(!isset($fpdf_charwidths[$fontkey]))
+                       {
+                               //Load metric file
+                               $file=$family;
+                               if($family=='times' or $family=='helvetica')
+                                       $file.=strtolower($style);
+                               $file.='.php';
+                               if(defined('FPDF_FONTPATH'))
+                                       $file=FPDF_FONTPATH.$file;
+                               include($file);
+                               if(!isset($fpdf_charwidths[$fontkey]))
+                                       $this->Error('Could not include font metric file');
+                       }
+                       $i=count($this->fonts)+1;
+                       $this->fonts[$fontkey]=array('i'=>$i,'type'=>'core','name'=>$this->CoreFonts[$fontkey],'up'=>-100,'ut'=>50,'cw'=>$fpdf_charwidths[$fontkey]);
+               }
+               else
+                       $this->Error('Undefined font: '.$family.' '.$style);
+       }
+       //Select it
+       $this->FontFamily=$family;
+       $this->FontStyle=$style;
+       $this->FontSizePt=$size;
+       $this->FontSize=$size/$this->k;
+       $this->CurrentFont=&$this->fonts[$fontkey];
+       if($this->page>0)
+               $this->_out(sprintf('BT /F%d %.2f Tf ET',$this->CurrentFont['i'],$this->FontSizePt));
+}
+
+function SetFontSize($size)
+{
+       //Set font size in points
+       if($this->FontSizePt==$size)
+               return;
+       $this->FontSizePt=$size;
+       $this->FontSize=$size/$this->k;
+       if($this->page>0)
+               $this->_out(sprintf('BT /F%d %.2f Tf ET',$this->CurrentFont['i'],$this->FontSizePt));
+}
+
+function AddLink()
+{
+       //Create a new internal link
+       $n=count($this->links)+1;
+       $this->links[$n]=array(0,0);
+       return $n;
+}
+
+function SetLink($link,$y=0,$page=-1)
+{
+       //Set destination of internal link
+       if($y==-1)
+               $y=$this->y;
+       if($page==-1)
+               $page=$this->page;
+       $this->links[$link]=array($page,$y);
+}
+
+function Link($x,$y,$w,$h,$link)
+{
+       //Put a link on the page
+       $this->PageLinks[$this->page][]=array($x*$this->k,$this->hPt-$y*$this->k,$w*$this->k,$h*$this->k,$link);
+}
+
+function Text($x,$y,$txt)
+{
+       //Output a string
+       $s=sprintf('BT %.2f %.2f Td (%s) Tj ET',$x*$this->k,($this->h-$y)*$this->k,$this->_escape($txt));
+       if($this->underline and $txt!='')
+               $s.=' '.$this->_dounderline($x,$y,$txt);
+       if($this->ColorFlag)
+               $s='q '.$this->TextColor.' '.$s.' Q';
+       $this->_out($s);
+}
+
+function AcceptPageBreak()
+{
+       //Accept automatic page break or not
+       return $this->AutoPageBreak;
+}
+
+function Cell($w,$h=0,$txt='',$border=0,$ln=0,$align='',$fill=0,$link='')
+{
+       //Output a cell
+       $k=$this->k;
+       if($this->y+$h>$this->PageBreakTrigger and !$this->InFooter and $this->AcceptPageBreak())
+       {
+               //Automatic page break
+               $x=$this->x;
+               $ws=$this->ws;
+               if($ws>0)
+               {
+                       $this->ws=0;
+                       $this->_out('0 Tw');
+               }
+               $this->AddPage($this->CurOrientation);
+               $this->x=$x;
+               if($ws>0)
+               {
+                       $this->ws=$ws;
+                       $this->_out(sprintf('%.3f Tw',$ws*$k));
+               }
+       }
+       if($w==0)
+               $w=$this->w-$this->rMargin-$this->x;
+       $s='';
+       if($fill==1 or $border==1)
+       {
+               if($fill==1)
+                       $op=($border==1) ? 'B' : 'f';
+               else
+                       $op='S';
+               $s=sprintf('%.2f %.2f %.2f %.2f re %s ',$this->x*$k,($this->h-$this->y)*$k,$w*$k,-$h*$k,$op);
+       }
+       if(is_string($border))
+       {
+               $x=$this->x;
+               $y=$this->y;
+               if(is_int(strpos($border,'L')))
+                       $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-$y)*$k,$x*$k,($this->h-($y+$h))*$k);
+               if(is_int(strpos($border,'T')))
+                       $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-$y)*$k);
+               if(is_int(strpos($border,'R')))
+                       $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',($x+$w)*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-($y+$h))*$k);
+               if(is_int(strpos($border,'B')))
+                       $s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-($y+$h))*$k,($x+$w)*$k,($this->h-($y+$h))*$k);
+       }
+       if($txt!='')
+       {
+               if($align=='R')
+                       $dx=$w-$this->cMargin-$this->GetStringWidth($txt);
+               elseif($align=='C')
+                       $dx=($w-$this->GetStringWidth($txt))/2;
+               else
+                       $dx=$this->cMargin;
+               if($this->ColorFlag)
+                       $s.='q '.$this->TextColor.' ';
+               $txt2=str_replace(')','\\)',str_replace('(','\\(',str_replace('\\','\\\\',$txt)));
+               $s.=sprintf('BT %.2f %.2f Td (%s) Tj ET',($this->x+$dx)*$k,($this->h-($this->y+.5*$h+.3*$this->FontSize))*$k,$txt2);
+               if($this->underline)
+                       $s.=' '.$this->_dounderline($this->x+$dx,$this->y+.5*$h+.3*$this->FontSize,$txt);
+               if($this->ColorFlag)
+                       $s.=' Q';
+               if($link)
+                       $this->Link($this->x+$dx,$this->y+.5*$h-.5*$this->FontSize,$this->GetStringWidth($txt),$this->FontSize,$link);
+       }
+       if($s)
+               $this->_out($s);
+       $this->lasth=$h;
+       if($ln>0)
+       {
+               //Go to next line
+               $this->y+=$h;
+               if($ln==1)
+                       $this->x=$this->lMargin;
+       }
+       else
+               $this->x+=$w;
+}
+
+function MultiCell($w,$h,$txt,$border=0,$align='J',$fill=0)
+{
+       //Output text with automatic or explicit line breaks
+       $cw=&$this->CurrentFont['cw'];
+       if($w==0)
+               $w=$this->w-$this->rMargin-$this->x;
+       $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
+       $s=str_replace("\r",'',$txt);
+       $nb=strlen($s);
+       if($nb>0 and $s[$nb-1]=="\n")
+               $nb--;
+       $b=0;
+       if($border)
+       {
+               if($border==1)
+               {
+                       $border='LTRB';
+                       $b='LRT';
+                       $b2='LR';
+               }
+               else
+               {
+                       $b2='';
+                       if(is_int(strpos($border,'L')))
+                               $b2.='L';
+                       if(is_int(strpos($border,'R')))
+                               $b2.='R';
+                       $b=is_int(strpos($border,'T')) ? $b2.'T' : $b2;
+               }
+       }
+       $sep=-1;
+       $i=0;
+       $j=0;
+       $l=0;
+       $ns=0;
+       $nl=1;
+       while($i<$nb)
+       {
+               //Get next character
+               $c=$s{$i};
+               if($c=="\n")
+               {
+                       //Explicit line break
+                       if($this->ws>0)
+                       {
+                               $this->ws=0;
+                               $this->_out('0 Tw');
+                       }
+                       $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
+                       $i++;
+                       $sep=-1;
+                       $j=$i;
+                       $l=0;
+                       $ns=0;
+                       $nl++;
+                       if($border and $nl==2)
+                               $b=$b2;
+                       continue;
+               }
+               if($c==' ')
+               {
+                       $sep=$i;
+                       $ls=$l;
+                       $ns++;
+               }
+               $l+=$cw[$c];
+               if($l>$wmax)
+               {
+                       //Automatic line break
+                       if($sep==-1)
+                       {
+                               if($i==$j)
+                                       $i++;
+                               if($this->ws>0)
+                               {
+                                       $this->ws=0;
+                                       $this->_out('0 Tw');
+                               }
+                               $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
+                       }
+                       else
+                       {
+                               if($align=='J')
+                               {
+                                       $this->ws=($ns>1) ? ($wmax-$ls)/1000*$this->FontSize/($ns-1) : 0;
+                                       $this->_out(sprintf('%.3f Tw',$this->ws*$this->k));
+                               }
+                               $this->Cell($w,$h,substr($s,$j,$sep-$j),$b,2,$align,$fill);
+                               $i=$sep+1;
+                       }
+                       $sep=-1;
+                       $j=$i;
+                       $l=0;
+                       $ns=0;
+                       $nl++;
+                       if($border and $nl==2)
+                               $b=$b2;
+               }
+               else
+                       $i++;
+       }
+       //Last chunk
+       if($this->ws>0)
+       {
+               $this->ws=0;
+               $this->_out('0 Tw');
+       }
+       if($border and is_int(strpos($border,'B')))
+               $b.='B';
+       $this->Cell($w,$h,substr($s,$j,$i-$j),$b,2,$align,$fill);
+       $this->x=$this->lMargin;
+}
+
+function Write($h,$txt,$link='')
+{
+       //Output text in flowing mode
+       $cw=&$this->CurrentFont['cw'];
+       $w=$this->w-$this->rMargin-$this->x;
+       $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
+       $s=str_replace("\r",'',$txt);
+       $nb=strlen($s);
+       $sep=-1;
+       $i=0;
+       $j=0;
+       $l=0;
+       $nl=1;
+       while($i<$nb)
+       {
+               //Get next character
+               $c=$s{$i};
+               if($c=="\n")
+               {
+                       //Explicit line break
+                       $this->Cell($w,$h,substr($s,$j,$i-$j),0,2,'',0,$link);
+                       $i++;
+                       $sep=-1;
+                       $j=$i;
+                       $l=0;
+                       if($nl==1)
+                       {
+                               $this->x=$this->lMargin;
+                               $w=$this->w-$this->rMargin-$this->x;
+                               $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
+                       }
+                       $nl++;
+                       continue;
+               }
+               if($c==' ')
+                       $sep=$i;
+               $l+=$cw[$c];
+               if($l>$wmax)
+               {
+                       //Automatic line break
+                       if($sep==-1)
+                       {
+                               if($this->x>$this->lMargin)
+                               {
+                                       //Move to next line
+                                       $this->x=$this->lMargin;
+                                       $this->y+=$h;
+                                       $w=$this->w-$this->rMargin-$this->x;
+                                       $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
+                                       $i++;
+                                       $nl++;
+                                       continue;
+                               }
+                               if($i==$j)
+                                       $i++;
+                               $this->Cell($w,$h,substr($s,$j,$i-$j),0,2,'',0,$link);
+                       }
+                       else
+                       {
+                               $this->Cell($w,$h,substr($s,$j,$sep-$j),0,2,'',0,$link);
+                               $i=$sep+1;
+                       }
+                       $sep=-1;
+                       $j=$i;
+                       $l=0;
+                       if($nl==1)
+                       {
+                               $this->x=$this->lMargin;
+                               $w=$this->w-$this->rMargin-$this->x;
+                               $wmax=($w-2*$this->cMargin)*1000/$this->FontSize;
+                       }
+                       $nl++;
+               }
+               else
+                       $i++;
+       }
+       //Last chunk
+       if($i!=$j)
+               $this->Cell($l/1000*$this->FontSize,$h,substr($s,$j),0,0,'',0,$link);
+}
+
+function Image($file,$x,$y,$w=0,$h=0,$type='',$link='')
+{
+       //Put an image on the page
+       if(!isset($this->images[$file]))
+       {
+               //First use of image, get info
+               if($type=='')
+               {
+                       $pos=strrpos($file,'.');
+                       if(!$pos)
+                               $this->Error('Image file has no extension and no type was specified: '.$file);
+                       $type=substr($file,$pos+1);
+               }
+               $type=strtolower($type);
+               $mqr=get_magic_quotes_runtime();
+               set_magic_quotes_runtime(0);
+               if($type=='jpg' or $type=='jpeg')
+                       $info=$this->_parsejpg($file);
+               elseif($type=='png')
+                       $info=$this->_parsepng($file);
+               else
+               {
+                       //Allow for additional formats
+                       $mtd='_parse'.$type;
+                       if(!method_exists($this,$mtd))
+                               $this->Error('Unsupported image type: '.$type);
+                       $info=$this->$mtd($file);
+               }
+               set_magic_quotes_runtime($mqr);
+               $info['i']=count($this->images)+1;
+               $this->images[$file]=$info;
+       }
+       else
+               $info=$this->images[$file];
+       //Automatic width and height calculation if needed
+       if($w==0 and $h==0)
+       {
+               //Put image at 72 dpi
+               $w=$info['w']/$this->k;
+               $h=$info['h']/$this->k;
+       }
+       if($w==0)
+               $w=$h*$info['w']/$info['h'];
+       if($h==0)
+               $h=$w*$info['h']/$info['w'];
+       $this->_out(sprintf('q %.2f 0 0 %.2f %.2f %.2f cm /I%d Do Q',$w*$this->k,$h*$this->k,$x*$this->k,($this->h-($y+$h))*$this->k,$info['i']));
+       if($link)
+               $this->Link($x,$y,$w,$h,$link);
+}
+
+function Ln($h='')
+{
+       //Line feed; default value is last cell height
+       $this->x=$this->lMargin;
+       if(is_string($h))
+               $this->y+=$this->lasth;
+       else
+               $this->y+=$h;
+}
+
+function GetX()
+{
+       //Get x position
+       return $this->x;
+}
+
+function SetX($x)
+{
+       //Set x position
+       if($x>=0)
+               $this->x=$x;
+       else
+               $this->x=$this->w+$x;
+}
+
+function GetY()
+{
+       //Get y position
+       return $this->y;
+}
+
+function SetY($y)
+{
+       //Set y position and reset x
+       $this->x=$this->lMargin;
+       if($y>=0)
+               $this->y=$y;
+       else
+               $this->y=$this->h+$y;
+}
+
+function SetXY($x,$y)
+{
+       //Set x and y positions
+       $this->SetY($y);
+       $this->SetX($x);
+}
+
+function Output($name='',$dest='')
+{
+       //Output PDF to some destination
+       global $HTTP_SERVER_VARS;
+
+       //Finish document if necessary
+       if($this->state<3)
+               $this->Close();
+       //Normalize parameters
+       if(is_bool($dest))
+               $dest=$dest ? 'D' : 'F';
+       $dest=strtoupper($dest);
+       if($dest=='')
+       {
+               if($name=='')
+               {
+                       $name='doc.pdf';
+                       $dest='I';
+               }
+               else
+                       $dest='F';
+       }
+       switch($dest)
+       {
+               case 'I':
+                       //Send to standard output
+                       if(isset($HTTP_SERVER_VARS['SERVER_NAME']))
+                       {
+                               //We send to a browser
+                               Header('Content-Type: application/pdf');
+                               if(headers_sent())
+                                       $this->Error('Some data has already been output to browser, can\'t send PDF file');
+                               Header('Content-Length: '.strlen($this->buffer));
+                               Header('Content-disposition: inline; filename='.$name);
+                       }
+                       echo $this->buffer;
+                       break;
+               case 'D':
+                       //Download file
+                       if(isset($HTTP_SERVER_VARS['HTTP_USER_AGENT']) and strpos($HTTP_SERVER_VARS['HTTP_USER_AGENT'],'MSIE'))
+                               Header('Content-Type: application/force-download');
+                       else
+                               Header('Content-Type: application/octet-stream');
+                       if(headers_sent())
+                               $this->Error('Some data has already been output to browser, can\'t send PDF file');
+                       Header('Content-Length: '.strlen($this->buffer));
+                       Header('Content-disposition: attachment; filename='.$name);
+                       echo $this->buffer;
+                       break;
+               case 'F':
+                       //Save to local file
+                       $f=fopen($name,'wb');
+                       if(!$f)
+                               $this->Error('Unable to create output file: '.$name);
+                       fwrite($f,$this->buffer,strlen($this->buffer));
+                       fclose($f);
+                       break;
+               case 'S':
+                       //Return as a string
+                       return $this->buffer;
+               default:
+                       $this->Error('Incorrect output destination: '.$dest);
+       }
+       return '';
+}
+
+/*******************************************************************************
+*                                                                              *
+*                              Protected methods                               *
+*                                                                              *
+*******************************************************************************/
+function _dochecks()
+{
+       //Check for locale-related bug
+       if(1.1==1)
+               $this->Error('Don\'t alter the locale before including class file');
+       //Check for decimal separator
+       if(sprintf('%.1f',1.0)!='1.0')
+               setlocale(LC_NUMERIC,'C');
+}
+
+function _begindoc()
+{
+       //Start document
+       $this->state=1;
+       $this->_out('%PDF-1.3');
+}
+
+function _putpages()
+{
+       $nb=$this->page;
+       if(!empty($this->AliasNbPages))
+       {
+               //Replace number of pages
+               for($n=1;$n<=$nb;$n++)
+                       $this->pages[$n]=str_replace($this->AliasNbPages,$nb,$this->pages[$n]);
+       }
+       if($this->DefOrientation=='P')
+       {
+               $wPt=$this->fwPt;
+               $hPt=$this->fhPt;
+       }
+       else
+       {
+               $wPt=$this->fhPt;
+               $hPt=$this->fwPt;
+       }
+       $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
+       for($n=1;$n<=$nb;$n++)
+       {
+               //Page
+               $this->_newobj();
+               $this->_out('<</Type /Page');
+               $this->_out('/Parent 1 0 R');
+               if(isset($this->OrientationChanges[$n]))
+                       $this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]',$hPt,$wPt));
+               $this->_out('/Resources 2 0 R');
+               if(isset($this->PageLinks[$n]))
+               {
+                       //Links
+                       $annots='/Annots [';
+                       foreach($this->PageLinks[$n] as $pl)
+                       {
+                               $rect=sprintf('%.2f %.2f %.2f %.2f',$pl[0],$pl[1],$pl[0]+$pl[2],$pl[1]-$pl[3]);
+                               $annots.='<</Type /Annot /Subtype /Link /Rect ['.$rect.'] /Border [0 0 0] ';
+                               if(is_string($pl[4]))
+                                       $annots.='/A <</S /URI /URI '.$this->_textstring($pl[4]).'>>>>';
+                               else
+                               {
+                                       $l=$this->links[$pl[4]];
+                                       $h=isset($this->OrientationChanges[$l[0]]) ? $wPt : $hPt;
+                                       $annots.=sprintf('/Dest [%d 0 R /XYZ 0 %.2f null]>>',1+2*$l[0],$h-$l[1]*$this->k);
+                               }
+                       }
+                       $this->_out($annots.']');
+               }
+               $this->_out('/Contents '.($this->n+1).' 0 R>>');
+               $this->_out('endobj');
+               //Page content
+               $p=($this->compress) ? gzcompress($this->pages[$n]) : $this->pages[$n];
+               $this->_newobj();
+               $this->_out('<<'.$filter.'/Length '.strlen($p).'>>');
+               $this->_putstream($p);
+               $this->_out('endobj');
+       }
+       //Pages root
+       $this->offsets[1]=strlen($this->buffer);
+       $this->_out('1 0 obj');
+       $this->_out('<</Type /Pages');
+       $kids='/Kids [';
+       for($i=0;$i<$nb;$i++)
+               $kids.=(3+2*$i).' 0 R ';
+       $this->_out($kids.']');
+       $this->_out('/Count '.$nb);
+       $this->_out(sprintf('/MediaBox [0 0 %.2f %.2f]',$wPt,$hPt));
+       $this->_out('>>');
+       $this->_out('endobj');
+}
+
+function _putfonts()
+{
+       $nf=$this->n;
+       foreach($this->diffs as $diff)
+       {
+               //Encodings
+               $this->_newobj();
+               $this->_out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['.$diff.']>>');
+               $this->_out('endobj');
+       }
+       $mqr=get_magic_quotes_runtime();
+       set_magic_quotes_runtime(0);
+       foreach($this->FontFiles as $file=>$info)
+       {
+               //Font file embedding
+               $this->_newobj();
+               $this->FontFiles[$file]['n']=$this->n;
+               if(defined('FPDF_FONTPATH'))
+                       $file=FPDF_FONTPATH.$file;
+               $size=filesize($file);
+               if(!$size)
+                       $this->Error('Font file not found');
+               $this->_out('<</Length '.$size);
+               if(substr($file,-2)=='.z')
+                       $this->_out('/Filter /FlateDecode');
+               $this->_out('/Length1 '.$info['length1']);
+               if(isset($info['length2']))
+                       $this->_out('/Length2 '.$info['length2'].' /Length3 0');
+               $this->_out('>>');
+               $f=fopen($file,'rb');
+               $this->_putstream(fread($f,$size));
+               fclose($f);
+               $this->_out('endobj');
+       }
+       set_magic_quotes_runtime($mqr);
+       foreach($this->fonts as $k=>$font)
+       {
+               //Font objects
+               $this->fonts[$k]['n']=$this->n+1;
+               $type=$font['type'];
+               $name=$font['name'];
+               if($type=='core')
+               {
+                       //Standard font
+                       $this->_newobj();
+                       $this->_out('<</Type /Font');
+                       $this->_out('/BaseFont /'.$name);
+                       $this->_out('/Subtype /Type1');
+                       if($name!='Symbol' and $name!='ZapfDingbats')
+                               $this->_out('/Encoding /WinAnsiEncoding');
+                       $this->_out('>>');
+                       $this->_out('endobj');
+               }
+               elseif($type=='Type1' or $type=='TrueType')
+               {
+                       //Additional Type1 or TrueType font
+                       $this->_newobj();
+                       $this->_out('<</Type /Font');
+                       $this->_out('/BaseFont /'.$name);
+                       $this->_out('/Subtype /'.$type);
+                       $this->_out('/FirstChar 32 /LastChar 255');
+                       $this->_out('/Widths '.($this->n+1).' 0 R');
+                       $this->_out('/FontDescriptor '.($this->n+2).' 0 R');
+                       if($font['enc'])
+                       {
+                               if(isset($font['diff']))
+                                       $this->_out('/Encoding '.($nf+$font['diff']).' 0 R');
+                               else
+                                       $this->_out('/Encoding /WinAnsiEncoding');
+                       }
+                       $this->_out('>>');
+                       $this->_out('endobj');
+                       //Widths
+                       $this->_newobj();
+                       $cw=&$font['cw'];
+                       $s='[';
+                       for($i=32;$i<=255;$i++)
+                               $s.=$cw[chr($i)].' ';
+                       $this->_out($s.']');
+                       $this->_out('endobj');
+                       //Descriptor
+                       $this->_newobj();
+                       $s='<</Type /FontDescriptor /FontName /'.$name;
+                       foreach($font['desc'] as $k=>$v)
+                               $s.=' /'.$k.' '.$v;
+                       $file=$font['file'];
+                       if($file)
+                               $s.=' /FontFile'.($type=='Type1' ? '' : '2').' '.$this->FontFiles[$file]['n'].' 0 R';
+                       $this->_out($s.'>>');
+                       $this->_out('endobj');
+               }
+               else
+               {
+                       //Allow for additional types
+                       $mtd='_put'.strtolower($type);
+                       if(!method_exists($this,$mtd))
+                               $this->Error('Unsupported font type: '.$type);
+                       $this->$mtd($font);
+               }
+       }
+}
+
+function _putimages()
+{
+       $filter=($this->compress) ? '/Filter /FlateDecode ' : '';
+       reset($this->images);
+       while(list($file,$info)=each($this->images))
+       {
+               $this->_newobj();
+               $this->images[$file]['n']=$this->n;
+               $this->_out('<</Type /XObject');
+               $this->_out('/Subtype /Image');
+               $this->_out('/Width '.$info['w']);
+               $this->_out('/Height '.$info['h']);
+               if($info['cs']=='Indexed')
+                       $this->_out('/ColorSpace [/Indexed /DeviceRGB '.(strlen($info['pal'])/3-1).' '.($this->n+1).' 0 R]');
+               else
+               {
+                       $this->_out('/ColorSpace /'.$info['cs']);
+                       if($info['cs']=='DeviceCMYK')
+                               $this->_out('/Decode [1 0 1 0 1 0 1 0]');
+               }
+               $this->_out('/BitsPerComponent '.$info['bpc']);
+               $this->_out('/Filter /'.$info['f']);
+               if(isset($info['parms']))
+                       $this->_out($info['parms']);
+               if(isset($info['trns']) and is_array($info['trns']))
+               {
+                       $trns='';
+                       for($i=0;$i<count($info['trns']);$i++)
+                               $trns.=$info['trns'][$i].' '.$info['trns'][$i].' ';
+                       $this->_out('/Mask ['.$trns.']');
+               }
+               $this->_out('/Length '.strlen($info['data']).'>>');
+               $this->_putstream($info['data']);
+               unset($this->images[$file]['data']);
+               $this->_out('endobj');
+               //Palette
+               if($info['cs']=='Indexed')
+               {
+                       $this->_newobj();
+                       $pal=($this->compress) ? gzcompress($info['pal']) : $info['pal'];
+                       $this->_out('<<'.$filter.'/Length '.strlen($pal).'>>');
+                       $this->_putstream($pal);
+                       $this->_out('endobj');
+               }
+       }
+}
+
+function _putresources()
+{
+       $this->_putfonts();
+       $this->_putimages();
+       //Resource dictionary
+       $this->offsets[2]=strlen($this->buffer);
+       $this->_out('2 0 obj');
+       $this->_out('<</ProcSet [/PDF /Text /ImageB /ImageC /ImageI]');
+       $this->_out('/Font <<');
+       foreach($this->fonts as $font)
+               $this->_out('/F'.$font['i'].' '.$font['n'].' 0 R');
+       $this->_out('>>');
+       if(count($this->images))
+       {
+               $this->_out('/XObject <<');
+               foreach($this->images as $image)
+                       $this->_out('/I'.$image['i'].' '.$image['n'].' 0 R');
+               $this->_out('>>');
+       }
+       $this->_out('>>');
+       $this->_out('endobj');
+}
+
+function _putinfo()
+{
+       $this->_out('/Producer '.$this->_textstring('FPDF '.FPDF_VERSION));
+       if(!empty($this->title))
+               $this->_out('/Title '.$this->_textstring($this->title));
+       if(!empty($this->subject))
+               $this->_out('/Subject '.$this->_textstring($this->subject));
+       if(!empty($this->author))
+               $this->_out('/Author '.$this->_textstring($this->author));
+       if(!empty($this->keywords))
+               $this->_out('/Keywords '.$this->_textstring($this->keywords));
+       if(!empty($this->creator))
+               $this->_out('/Creator '.$this->_textstring($this->creator));
+       $this->_out('/CreationDate '.$this->_textstring('D:'.date('YmdHis')));
+}
+
+function _putcatalog()
+{
+       $this->_out('/Type /Catalog');
+       $this->_out('/Pages 1 0 R');
+       if($this->ZoomMode=='fullpage')
+               $this->_out('/OpenAction [3 0 R /Fit]');
+       elseif($this->ZoomMode=='fullwidth')
+               $this->_out('/OpenAction [3 0 R /FitH null]');
+       elseif($this->ZoomMode=='real')
+               $this->_out('/OpenAction [3 0 R /XYZ null null 1]');
+       elseif(!is_string($this->ZoomMode))
+               $this->_out('/OpenAction [3 0 R /XYZ null null '.($this->ZoomMode/100).']');
+       if($this->LayoutMode=='single')
+               $this->_out('/PageLayout /SinglePage');
+       elseif($this->LayoutMode=='continuous')
+               $this->_out('/PageLayout /OneColumn');
+       elseif($this->LayoutMode=='two')
+               $this->_out('/PageLayout /TwoColumnLeft');
+}
+
+function _puttrailer()
+{
+       $this->_out('/Size '.($this->n+1));
+       $this->_out('/Root '.$this->n.' 0 R');
+       $this->_out('/Info '.($this->n-1).' 0 R');
+}
+
+function _enddoc()
+{
+       $this->_putpages();
+       $this->_putresources();
+       //Info
+       $this->_newobj();
+       $this->_out('<<');
+       $this->_putinfo();
+       $this->_out('>>');
+       $this->_out('endobj');
+       //Catalog
+       $this->_newobj();
+       $this->_out('<<');
+       $this->_putcatalog();
+       $this->_out('>>');
+       $this->_out('endobj');
+       //Cross-ref
+       $o=strlen($this->buffer);
+       $this->_out('xref');
+       $this->_out('0 '.($this->n+1));
+       $this->_out('0000000000 65535 f ');
+       for($i=1;$i<=$this->n;$i++)
+               $this->_out(sprintf('%010d 00000 n ',$this->offsets[$i]));
+       //Trailer
+       $this->_out('trailer');
+       $this->_out('<<');
+       $this->_puttrailer();
+       $this->_out('>>');
+       $this->_out('startxref');
+       $this->_out($o);
+       $this->_out('%%EOF');
+       $this->state=3;
+}
+
+function _beginpage($orientation)
+{
+       $this->page++;
+       $this->pages[$this->page]='';
+       $this->state=2;
+       $this->x=$this->lMargin;
+       $this->y=$this->tMargin;
+       $this->FontFamily='';
+       //Page orientation
+       if(!$orientation)
+               $orientation=$this->DefOrientation;
+       else
+       {
+               $orientation=strtoupper($orientation{0});
+               if($orientation!=$this->DefOrientation)
+                       $this->OrientationChanges[$this->page]=true;
+       }
+       if($orientation!=$this->CurOrientation)
+       {
+               //Change orientation
+               if($orientation=='P')
+               {
+                       $this->wPt=$this->fwPt;
+                       $this->hPt=$this->fhPt;
+                       $this->w=$this->fw;
+                       $this->h=$this->fh;
+               }
+               else
+               {
+                       $this->wPt=$this->fhPt;
+                       $this->hPt=$this->fwPt;
+                       $this->w=$this->fh;
+                       $this->h=$this->fw;
+               }
+               $this->PageBreakTrigger=$this->h-$this->bMargin;
+               $this->CurOrientation=$orientation;
+       }
+}
+
+function _endpage()
+{
+       //End of page contents
+       $this->state=1;
+}
+
+function _newobj()
+{
+       //Begin a new object
+       $this->n++;
+       $this->offsets[$this->n]=strlen($this->buffer);
+       $this->_out($this->n.' 0 obj');
+}
+
+function _dounderline($x,$y,$txt)
+{
+       //Underline text
+       $up=$this->CurrentFont['up'];
+       $ut=$this->CurrentFont['ut'];
+       $w=$this->GetStringWidth($txt)+$this->ws*substr_count($txt,' ');
+       return sprintf('%.2f %.2f %.2f %.2f re f',$x*$this->k,($this->h-($y-$up/1000*$this->FontSize))*$this->k,$w*$this->k,-$ut/1000*$this->FontSizePt);
+}
+
+function _parsejpg($file)
+{
+       //Extract info from a JPEG file
+       $a=GetImageSize($file);
+       if(!$a)
+               $this->Error('Missing or incorrect image file: '.$file);
+       if($a[2]!=2)
+               $this->Error('Not a JPEG file: '.$file);
+       if(!isset($a['channels']) or $a['channels']==3)
+               $colspace='DeviceRGB';
+       elseif($a['channels']==4)
+               $colspace='DeviceCMYK';
+       else
+               $colspace='DeviceGray';
+       $bpc=isset($a['bits']) ? $a['bits'] : 8;
+       //Read whole file
+       $f=fopen($file,'rb');
+       $data='';
+       while(!feof($f))
+               $data.=fread($f,4096);
+       fclose($f);
+       return array('w'=>$a[0],'h'=>$a[1],'cs'=>$colspace,'bpc'=>$bpc,'f'=>'DCTDecode','data'=>$data);
+}
+
+function _parsepng($file)
+{
+       //Extract info from a PNG file
+       $f=fopen($file,'rb');
+       if(!$f)
+               $this->Error('Can\'t open image file: '.$file);
+       //Check signature
+       if(fread($f,8)!=chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10))
+               $this->Error('Not a PNG file: '.$file);
+       //Read header chunk
+       fread($f,4);
+       if(fread($f,4)!='IHDR')
+               $this->Error('Incorrect PNG file: '.$file);
+       $w=$this->_freadint($f);
+       $h=$this->_freadint($f);
+       $bpc=ord(fread($f,1));
+       if($bpc>8)
+               $this->Error('16-bit depth not supported: '.$file);
+       $ct=ord(fread($f,1));
+       if($ct==0)
+               $colspace='DeviceGray';
+       elseif($ct==2)
+               $colspace='DeviceRGB';
+       elseif($ct==3)
+               $colspace='Indexed';
+       else
+               $this->Error('Alpha channel not supported: '.$file);
+       if(ord(fread($f,1))!=0)
+               $this->Error('Unknown compression method: '.$file);
+       if(ord(fread($f,1))!=0)
+               $this->Error('Unknown filter method: '.$file);
+       if(ord(fread($f,1))!=0)
+               $this->Error('Interlacing not supported: '.$file);
+       fread($f,4);
+       $parms='/DecodeParms <</Predictor 15 /Colors '.($ct==2 ? 3 : 1).' /BitsPerComponent '.$bpc.' /Columns '.$w.'>>';
+       //Scan chunks looking for palette, transparency and image data
+       $pal='';
+       $trns='';
+       $data='';
+       do
+       {
+               $n=$this->_freadint($f);
+               $type=fread($f,4);
+               if($type=='PLTE')
+               {
+                       //Read palette
+                       $pal=fread($f,$n);
+                       fread($f,4);
+               }
+               elseif($type=='tRNS')
+               {
+                       //Read transparency info
+                       $t=fread($f,$n);
+                       if($ct==0)
+                               $trns=array(ord(substr($t,1,1)));
+                       elseif($ct==2)
+                               $trns=array(ord(substr($t,1,1)),ord(substr($t,3,1)),ord(substr($t,5,1)));
+                       else
+                       {
+                               $pos=strpos($t,chr(0));
+                               if(is_int($pos))
+                                       $trns=array($pos);
+                       }
+                       fread($f,4);
+               }
+               elseif($type=='IDAT')
+               {
+                       //Read image data block
+                       $data.=fread($f,$n);
+                       fread($f,4);
+               }
+               elseif($type=='IEND')
+                       break;
+               else
+                       fread($f,$n+4);
+       }
+       while($n);
+       if($colspace=='Indexed' and empty($pal))
+               $this->Error('Missing palette in '.$file);
+       fclose($f);
+       return array('w'=>$w,'h'=>$h,'cs'=>$colspace,'bpc'=>$bpc,'f'=>'FlateDecode','parms'=>$parms,'pal'=>$pal,'trns'=>$trns,'data'=>$data);
+}
+
+function _freadint($f)
+{
+       //Read a 4-byte integer from file
+       $i=ord(fread($f,1))<<24;
+       $i+=ord(fread($f,1))<<16;
+       $i+=ord(fread($f,1))<<8;
+       $i+=ord(fread($f,1));
+       return $i;
+}
+
+function _textstring($s)
+{
+       //Format a text string
+       return '('.$this->_escape($s).')';
+}
+
+function _escape($s)
+{
+       //Add \ before \, ( and )
+       return str_replace(')','\\)',str_replace('(','\\(',str_replace('\\','\\\\',$s)));
+}
+
+function _putstream($s)
+{
+       $this->_out('stream');
+       $this->_out($s);
+       $this->_out('endstream');
+}
+
+function _out($s)
+{
+       //Add a line to the document
+       if($this->state==2)
+               $this->pages[$this->page].=$s."\n";
+       else
+               $this->buffer.=$s."\n";
+}
+//End of class
+}
+
+//Handle special IE contype request
+if(isset($HTTP_SERVER_VARS['HTTP_USER_AGENT']) and $HTTP_SERVER_VARS['HTTP_USER_AGENT']=='contype')
+{
+       Header('Content-Type: application/pdf');
+       exit;
+}
+
+}
+?>
diff --git a/plugins/serendipity_event_blogpdf/lang_ja.inc.php b/plugins/serendipity_event_blogpdf/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..78ced59
--- /dev/null
@@ -0,0 +1,27 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_EVENT_BLOGPDF_NAME', 'PDF でブログをエクスポートする');
+        @define('PLUGIN_EVENT_BLOGPDF_DESC', '訪問者が PDF 形式でブログをダウンロードすることを許可します。');
+        @define('PLUGIN_EVENT_BLOGPDF_DOWNLOAD', 'このブログを PDF でダウンロードします!');
+        @define('PLUGIN_EVENT_BLOGPDF_PAGE', 'ページ');
+        @define('PLUGIN_EVENT_BLOGPDF_EXPORT', 'ブログをエクスポートする');
+
+        @define('PLUGIN_EVENT_BLOGPDF_VIEW', 'PDF で閲覧する: ');
+        @define('PLUGIN_EVENT_BLOGPDF_VIEW_FULL', '完全なブログ');
+        @define('PLUGIN_EVENT_BLOGPDF_VIEW_ENTRY', 'このエントリ');
+        @define('PLUGIN_EVENT_BLOGPDF_VIEW_CATEGORY', 'カテゴリ %s');
+        @define('PLUGIN_EVENT_BLOGPDF_VIEW_MONTH', '今月');
+        @define('PLUGIN_EVENT_BLOGPDF_MISSING', '無効なプラグイン操作 %s です。');
+?>
diff --git a/plugins/serendipity_event_blogpdf/serendipity_event_blogpdf.php b/plugins/serendipity_event_blogpdf/serendipity_event_blogpdf.php
new file mode 100644 (file)
index 0000000..0d431b3
--- /dev/null
@@ -0,0 +1,447 @@
+<?php # $Id$
+
+/* TODO:
+- Use Links inside entries
+- Put images
+- Build a nice TOC
+- Insert nice formatting, maybe user-defined? (Color, Font face)
+- Parse attributes like STRONG, BOLD, ...
+*/
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_BLOGPDF_NAME', 'Blog als PDF exportieren');
+        @define('PLUGIN_EVENT_BLOGPDF_DESC', 'Exportiert alle Einträge des Blogs in eine PDF-Datei');
+        @define('PLUGIN_EVENT_BLOGPDF_DOWNLOAD', 'Download des Blogs als PDF!');
+        @define('PLUGIN_EVENT_BLOGPDF_PAGE', 'Seite');
+        @define('PLUGIN_EVENT_BLOGPDF_EXPORT', 'Blog Export');
+
+        @define('PLUGIN_EVENT_BLOGPDF_VIEW', 'Als PDF ansehen: ');
+        @define('PLUGIN_EVENT_BLOGPDF_VIEW_FULL', 'Vollständiges Blog');
+        @define('PLUGIN_EVENT_BLOGPDF_VIEW_ENTRY', 'Dieser Artikel');
+        @define('PLUGIN_EVENT_BLOGPDF_VIEW_CATEGORY', 'Kategorie %s');
+        @define('PLUGIN_EVENT_BLOGPDF_VIEW_MONTH', 'Dieser Monat');
+        @define('PLUGIN_EVENT_BLOGPDF_MISSING', 'Ungültiger Plugin-Modus %s');
+        break;
+
+    case 'es':
+               @define('PLUGIN_EVENT_BLOGPDF_NAME', ' Exportar el blog como pdf ');  
+               @define('PLUGIN_EVENT_BLOGPDF_DESC', ' Exportar el blog completo como archivo pdf '); 
+               @define('PLUGIN_EVENT_BLOGPDF_DOWNLOAD', ' Descarga este blog como pdf!');  
+               @define('PLUGIN_EVENT_BLOGPDF_PAGE', ' página ');  
+               @define('PLUGIN_EVENT_BLOGPDF_EXPORT', ' Exportar Blog ');
+               
+               @define('PLUGIN_EVENT_BLOGPDF_VIEW', ' Ver como pdf:  ');  
+               @define('PLUGIN_EVENT_BLOGPDF_VIEW_FULL', ' Blog completo ');  
+               @define('PLUGIN_EVENT_BLOGPDF_VIEW_ENTRY', ' esta entrada ');  
+               @define('PLUGIN_EVENT_BLOGPDF_VIEW_CATEGORY', ' categor&iacute;a %s ');  
+               @define('PLUGIN_EVENT_BLOGPDF_VIEW_MONTH', ' este mes ');  
+               @define('PLUGIN_EVENT_BLOGPDF_MISSING', ' plugin de operaci&oacute;inv&aacute;lido %s ');
+        break;
+
+    case 'en':
+    default:
+        @define('PLUGIN_EVENT_BLOGPDF_NAME', 'Export blog as PDF');
+        @define('PLUGIN_EVENT_BLOGPDF_DESC', 'Allows visitors to download your blog in the PDF format');
+        @define('PLUGIN_EVENT_BLOGPDF_DOWNLOAD', 'Download this blog as PDF!');
+        @define('PLUGIN_EVENT_BLOGPDF_PAGE', 'Page');
+        @define('PLUGIN_EVENT_BLOGPDF_EXPORT', 'Blog Export');
+
+        @define('PLUGIN_EVENT_BLOGPDF_VIEW', 'View as PDF: ');
+        @define('PLUGIN_EVENT_BLOGPDF_VIEW_FULL', 'Full blog');
+        @define('PLUGIN_EVENT_BLOGPDF_VIEW_ENTRY', 'This entry');
+        @define('PLUGIN_EVENT_BLOGPDF_VIEW_CATEGORY', 'Category %s');
+        @define('PLUGIN_EVENT_BLOGPDF_VIEW_MONTH', 'This month');
+        @define('PLUGIN_EVENT_BLOGPDF_MISSING', 'Invalid plugin operator %s');
+        break;
+}
+
+define('FPDF_FONTPATH', S9Y_INCLUDE_PATH . 'plugins/serendipity_event_blogpdf/font/');
+include_once S9Y_INCLUDE_PATH . 'plugins/serendipity_event_blogpdf/fpdf.php';
+class PDF extends FPDF {
+    var $TOC = array();
+
+    function Header() {
+        global $serendipity;
+
+        $this->SetFont('Arial', 'B', 15);
+        $this->Cell(0, 10, PLUGIN_EVENT_BLOGPDF_EXPORT .': ' . $serendipity['blogTitle'] . ', ' . $serendipity['baseURL'], 1, 0, 'C');
+        $this->Ln(20);
+    }
+
+    function Footer() {
+        global $serendipity;
+
+        $this->SetY(-15);
+        $this->SetFont('Arial', 'I', 8);
+        $this->Cell(0, 10, PLUGIN_EVENT_BLOGPDF_PAGE . ' ' . $this->PageNo() . ' / {nb}', 0, 0, 'C');
+    }
+
+    function TOC_Add($header) {
+        $this->TOC[] = array(
+          'header' => $header,
+          'page'   => $this->PageNo(),
+          'pos'    => $this->GetY()
+        );
+    }
+
+    function TOC_Build() {
+        $cnt = count($this->TOC);
+        if ($cnt < 1) {
+            return;
+        }
+
+        $first = $this->n+1;
+        $last  = $first + $cnt;
+
+        foreach($this->TOC AS $ti => $toc) {
+            $this->_newobj();
+            $this->_out('<</Title ' . $this->_textstring($toc['header']));
+
+            // This ob has to be the obj reference to the last Outline-Type.
+            $this->_out('/Parent ' . ($first + $cnt) . ' 0 R');
+            if ($this->n > $first) {
+                $this->_out('/Prev ' . ($this->n - 1) . ' 0 R');
+            }
+
+            if ($this->n < $last && isset($TOC[$ti+1])) {
+                $this->_out('/Next ' . ($this->n + 1) . ' 0 R');
+            }
+
+            $this->_out(
+              sprintf(
+                '/Dest [%d 0 R /XYZ 0 %.2f null]',
+
+                1 + (2*$toc['page']),
+                ($this->h - $toc['pos']) * $this->k
+              )
+            );
+            $this->_out('/Count 0>>');
+            $this->_out('endobj');
+        }
+
+        $this->_newobj();
+        $this->OutlineRoot = $this->n;
+        $this->_out('<</Type /Outlines /First ' . $first . ' 0 R');
+        $this->_out('/Last ' . ($this->n - 1) . ' 0 R>>');
+        $this->_out('endobj');
+    }
+
+    function _putresources() {
+        parent::_putresources();
+        $this->TOC_Build();
+    }
+
+    function _putcatalog() {
+        parent::_putcatalog();
+        if(count($this->TOC) > 0) {
+            $this->_out('/Outlines '. $this->OutlineRoot . ' 0 R');
+            $this->_out('/PageMode /UseOutlines');
+        }
+    }
+}
+
+if (!function_exists('html_entity_decode')) {
+    function html_entity_decode($given_html, $quote_style = ENT_QUOTES) {
+        $trans_table = get_html_translation_table(HTML_SPECIALCHARS, $quote_style);
+        if ($trans_table["'"] != '&#039;') { # some versions of PHP match single quotes to &#39;
+          $trans_table["'"] = '&#039;';
+        }
+
+        return (strtr($given_html, array_flip($trans_table)));
+    }
+}
+
+class serendipity_event_blogpdf extends serendipity_event
+{
+    var $title = PLUGIN_EVENT_BLOGPDF_NAME;
+    var $pdf;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_BLOGPDF_NAME);
+        $propbag->add('description',   PLUGIN_EVENT_BLOGPDF_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Garvin Hicking');
+        $propbag->add('version',       '1.0');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('event_hooks',    array(
+            'external_plugin'  => true,
+            'entries_footer'   => true,
+            'frontend_display' => true
+        ));
+    }
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+    function event_hook($event, &$bag, &$eventData) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+        $links = array();
+        $article_show = false;
+
+        if (isset($hooks[$event])) {
+            switch($event) {
+                case 'frontend_display':
+                    if (isset($serendipity['GET']['id']) && is_numeric($serendipity['GET']['id'])) {
+                        $article_show = true;
+                        $year         = date('Y', serendipity_serverOffsetHour($eventData['timestamp']));
+                        $month        = date('m', serendipity_serverOffsetHour($eventData['timestamp']));
+                    } else {
+                        break;
+                    }
+
+                case 'entries_footer':
+                    if (isset($serendipity['GET']['id']) && is_numeric($serendipity['GET']['id'])) {
+                        $links[] = '<a href="' . $serendipity['baseURL'] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '') . 'plugin/articlepdf_' . $serendipity['GET']['id'] . '">' . PLUGIN_EVENT_BLOGPDF_VIEW_ENTRY . '</a>';
+                    }
+
+                    if (isset($serendipity['GET']['category'])) {
+                        $cid = explode('_', $serendipity['GET']['category']);
+                        if (is_numeric($cid[0])) {
+                            $cat = serendipity_fetchCategoryInfo($cid[0]);
+                            $links[] = '<a href="' . $serendipity['baseURL'] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '') . 'plugin/categorypdf_' . $cid[0] . '">' . sprintf(PLUGIN_EVENT_BLOGPDF_VIEW_CATEGORY, $cat['category_name']) . '</a>';
+                        }
+                    }
+
+                    if (empty($year) && empty($month) && isset($serendipity['GET']['range']) && is_numeric($serendipity['GET']['range'])) {
+                        $year  = substr($serendipity['GET']['range'], 0, 4);
+                        $month = substr($serendipity['GET']['range'], 4, 2);
+                    }
+
+                    if (empty($year)) {
+                        $year = date('Y', serendipity_serverOffsetHour());
+                    }
+
+                    if (empty($month)) {
+                        $month = date('m', serendipity_serverOffsetHour());
+                    }
+
+                    $links[] = '<a href="' . $serendipity['baseURL'] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '') . 'plugin/monthpdf_' . $year . $month . '">' . PLUGIN_EVENT_BLOGPDF_VIEW_MONTH . '</a>';
+                    $links[] = '<a href="' . $serendipity['baseURL'] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '') . 'plugin/blogpdf">' . PLUGIN_EVENT_BLOGPDF_VIEW_FULL . '</a>';
+
+                    if ($article_show) {
+                        $eventData['add_footer'] = '<br />' . PLUGIN_EVENT_BLOGPDF_VIEW . implode(' | ', $links);
+                    } else {
+                        echo '<br />' . PLUGIN_EVENT_BLOGPDF_VIEW . implode(' | ' , $links);
+                    }
+
+
+                    return true;
+                    break;
+
+                case 'external_plugin':
+                    $cachetime = 60*60*24; // one day
+
+                    $parts     = explode('_', $eventData);
+                    if (!empty($parts[1])) {
+                        $param     = (int) $parts[1];
+                    } else {
+                        $param     = null;
+                    }
+
+                    $methods = array('blogpdf', 'articlepdf', 'monthpdf', 'categorypdf');
+
+                    if (!in_array($parts[0], $methods)) {
+                        return;
+                    }
+
+                    $this->pdf       = new PDF();
+                    $this->pdf->AliasNbPages();
+
+                    switch($parts[0]) {
+                        case 'blogpdf':
+                            $feedcache = $serendipity['serendipityPath'] . 'archives/blog.pdf';
+                            $entries = serendipity_fetchEntries(); 
+                            $this->process(
+                              $feedcache,
+                              $entries
+                            );
+                            break;
+
+                        case 'articlepdf':
+                            $feedcache = $serendipity['serendipityPath'] . 'archives/article' . $param . '.pdf';
+                            $this->single = true;
+                            $entry = serendipity_fetchEntry('id', $param); 
+                            $this->process(
+                              $feedcache,
+                              $entry
+                            );
+                            break;
+
+                        case 'monthpdf':
+                            $feedcache = $serendipity['serendipityPath'] . 'archives/month' . $param . '.pdf';
+                            $entries = serendipity_fetchEntries($param);
+                            $this->process(
+                              $feedcache,
+                              $entries
+                            );
+                            break;
+
+                        case 'categorypdf':
+                            $feedcache = $serendipity['serendipityPath'] . 'archives/category' . $param . '.pdf';
+                            $serendipity['GET']['category'] = $param . '_category';
+                            $entries = serendipity_fetchEntries();
+                            $this->process(
+                              $feedcache,
+                              $entries
+                            );
+                            break;
+                    }
+
+                    $this->pdf->Output();
+
+                    return true;
+                    break;
+
+                default:
+                    return false;
+                    break;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    function process($feedcache, &$entries) {
+        if (!file_exists($feedcache) || filesize($feedcache) == 0 || filemtime($feedcache) < (time() - $cachetime)) {
+            if ($this->single) {
+                $this->print_entry(0, $entries, serendipity_formatTime(DATE_FORMAT_ENTRY, $entries['timestamp']));
+            } else {
+                $this->print_entries($entries);
+            }
+            $this->pdf->Close();
+            $fp = fopen($feedcache, 'wb');
+            fwrite($fp, $this->pdf->buffer);
+            fclose($fp);
+        } else {
+            $this->pdf->buffer = file_get_contents($feedcache);
+            $this->pdf->state = 3; // fake closed document to insert cached PDF
+        }
+
+        return true;
+    }
+
+    function print_entry($x, &$entry, $header = false) {
+        if ($header) {
+            $this->pdf->AddPage();
+            $this->pdf->SetFont('Courier','',12);
+            $this->pdf->TOC_Add($header);
+            $this->pdf->Cell(0, 10, $header, 1);
+            $this->pdf->Ln();
+            $this->pdf->Ln();
+        }
+
+        $entryLink = serendipity_archiveURL($entry['id'], $entry['title'], 'serendipityHTTPPath');
+        serendipity_plugin_api::hook_event('frontend_display', $entry, array('no_scramble' => true));
+
+        $posted_by = ' ' . POSTED_BY . ' ' . htmlspecialchars($entry['author']);
+        if (is_array($entry['categories']) && sizeof($entry['categories']) > 0) {
+            $posted_by .= ' ' . IN . ' ';
+            $cats = array();
+            foreach ($entry['categories'] as $cat) {
+                $cats[] = $cat['category_name'];
+            }
+            $posted_by .= implode(', ', $cats);
+        }
+
+        $posted_by .= ' ' . AT . ' ' . date('H:i', serendipity_serverOffsetHour($entry['timestamp']));
+
+        $this->pdf->SetFont('Arial', 'B', 11);
+        $this->pdf->Write(4, $this->prep_out($entry['title']) . "\n");
+        $this->pdf->Ln();
+
+        $this->pdf->SetFont('Arial', '', 10);
+        $this->pdf->Write(4, $this->prep_out($entry['body'] . $entry['extended']) . "\n");
+        $this->pdf->Ln();
+
+        $this->pdf->SetFont('Courier', '', 9);
+        $this->pdf->Write(4, $this->prep_out($posted_by) . "\n");
+        $this->pdf->Ln();
+
+        if ($this->single) {
+            $this->printComments(serendipity_fetchComments($entry['id']));
+        }
+
+    }
+
+    function printComments($comments) {
+        if (!is_array($comments) || count($comments) < 1) {
+            return;
+        }
+
+        foreach ($comments as $i => $comment) {
+            $comment['comment'] = htmlspecialchars(strip_tags($comment['body']));
+            if (!empty($comment['url']) && substr($comment['url'], 0, 7) != 'http://' && substr($comment['url'], 0, 8) != 'https://') {
+                $comment['url'] = 'http://' . $comment['url'];
+            }
+
+            serendipity_plugin_api::hook_event('frontend_display', $comment);
+
+            $name = empty($comment['username']) ? ANONYMOUS : $comment['username'];
+            $body = $comment['comment'];
+
+            $this->pdf->SetFont('Arial', '', 9);
+            $this->pdf->Write(
+              3,
+              $this->prep_out(
+                $body . "\n" .
+                '    ' . $name .
+                ' ' . ON . ' ' . serendipity_mb('ucfirst', serendipity_strftime('%b %e %Y, %H:%M', $comment['timestamp']))
+              ) . "\n"
+            );
+            $this->pdf->Ln();
+            $this->pdf->Ln();
+        }
+    }
+
+    function prep_out($string) {
+        return strip_tags(html_entity_decode($string));
+    }
+
+    function print_entries(&$entries) {
+        $extended = true;
+        $preview  = false;
+
+        $addData = array('extended' => $extended, 'preview' => $preview, 'no_scramble' => true);
+        serendipity_plugin_api::hook_event('entry_display', $entries, $addData);
+
+        /* pre-walk the array to collect them keyed by date */
+        $bydate = array();
+        if (!is_array($entries) || $entries[0] == false) {
+            return;
+        }
+
+        $lastDate = '';
+        for ($x = 0, $num_entries = count($entries); $x < $num_entries; $x++) {
+            $d = serendipity_formatTime(DATE_FORMAT_ENTRY, $entries[$x]['timestamp']);
+            $bydate[$d][] = $entries[$x];
+        }
+
+        foreach ($bydate as $date => $ents) {
+            $header = $date;
+            foreach ($ents as $x => $entry) {
+                $this->print_entry($x, $entry, $header);
+                $header = false;
+            } // end for-loop (entries)
+        } // end for-loop (dates)
+    } // end function serendipity_printEntries
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_browsercompatibility/lang_ja.inc.php b/plugins/serendipity_event_browsercompatibility/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..64ebef6
--- /dev/null
@@ -0,0 +1,18 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_EVENT_BROWSERCOMPATIBILITY_TITLE', 'ブラウザーの互換性');
+        @define('PLUGIN_EVENT_BROWSERCOMPATIBILITY_DESC', '異なる方法(CSS) を用いて最大限にブラウザーの互換性を強化します。');
+
+?>
diff --git a/plugins/serendipity_event_browsercompatibility/pngbehavior.htc b/plugins/serendipity_event_browsercompatibility/pngbehavior.htc
new file mode 100644 (file)
index 0000000..d4d7246
--- /dev/null
@@ -0,0 +1,89 @@
+<public:component lightWeight="true">
+<public:attach event="onpropertychange" onevent="propertyChanged()" />
+<public:attach event="onbeforeprint" onevent="beforePrint()" for="window"/>
+<public:attach event="onafterprint" onevent="afterPrint()" for="window"/>
+<script>
+
+/*
+ * PNG Behavior
+ *
+ * This script was created by Erik Arvidsson (http://webfx.eae.net/contact.html#erik)
+ * for WebFX (http://webfx.eae.net)
+ * Copyright 2002-2004
+ *
+ * For usage see license at http://webfx.eae.net/license.html
+ *
+ * Version: 1.02
+ * Created: 2001-??-?? First working version
+ * Updated: 2002-03-28 Fixed issue when starting with a non png image and
+ *                      switching between non png images
+ *          2003-01-06 Fixed RegExp to correctly work with IE 5.0x
+ *          2004-05-09  When printing revert to original
+ *
+ */
+
+var supported = /MSIE ((5\.5)|[6789])/.test(navigator.userAgent) &&
+                               navigator.platform == "Win32";
+
+var realSrc;
+var blankSrc = "{blanksrc}";
+var isPrinting = false;
+
+if (supported) fixImage();
+
+function propertyChanged() {
+       if (!supported || isPrinting) return;
+
+       var pName = event.propertyName;
+       if (pName != "src") return;
+       // if not set to blank
+       if (!new RegExp(blankSrc).test(src))
+               fixImage();
+};
+
+function fixImage() {
+       // get src
+       var src = element.src;
+
+       // check for real change
+       if (src == realSrc && /\.png$/i.test(src)) {
+               element.src = blankSrc;
+               return;
+       }
+
+       if ( ! new RegExp(blankSrc).test(src)) {
+               // backup old src
+               realSrc = src;
+       }
+
+       // test for png
+       if (/\.png$/i.test(realSrc)) {
+               // set blank image
+               width  = element.width;
+               height = element.height;
+               element.src = blankSrc;
+               // set filter
+               element.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "', sizingMethod='scale')";
+               element.runtimeStyle.width  = width;
+               element.runtimeStyle.height = height;
+       }
+       else {
+               // remove filter
+               element.runtimeStyle.filter = "";
+       }
+}
+
+function beforePrint() {
+       isPrinting = true;
+       element.src = realSrc;
+       element.runtimeStyle.filter = "";
+       realSrc = null;
+}
+
+function afterPrint() {
+       isPrinting = false;
+       fixImage();
+}
+
+</script>
+</public:component>
diff --git a/plugins/serendipity_event_browsercompatibility/serendipity_event_browsercompatibility.php b/plugins/serendipity_event_browsercompatibility/serendipity_event_browsercompatibility.php
new file mode 100644 (file)
index 0000000..a58ba6d
--- /dev/null
@@ -0,0 +1,89 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_BROWSERCOMPATIBILITY_TITLE', 'Browser-Kompatibilität');
+        @define('PLUGIN_EVENT_BROWSERCOMPATIBILITY_DESC', 'Wendet verschiedene (CSS) Methoden an, um maximale Browserkompatibilität zu erreichen');
+        break;
+
+    case 'en':
+    case 'es':
+    default:
+        @define('PLUGIN_EVENT_BROWSERCOMPATIBILITY_TITLE', 'Browser Compatibility');
+        @define('PLUGIN_EVENT_BROWSERCOMPATIBILITY_DESC', 'Uses different (CSS) methods to enforce maximum browser compatibility');
+        break;
+}
+
+class serendipity_event_browsercompatibility extends serendipity_event
+{
+    var $title = PLUGIN_EVENT_BROWSERCOMPATIBILITY_TITLE;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_BROWSERCOMPATIBILITY_TITLE);
+        $propbag->add('description',   PLUGIN_EVENT_BROWSERCOMPATIBILITY_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Garvin Hicking');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('version',       '1.0');
+        $propbag->add('event_hooks',    array(
+            'css' => true,
+            'css_backend' => true,
+            'external_plugin'  => true,
+        ));
+    }
+
+    function generate_content(&$title) {
+        $title = PLUGIN_EVENT_BROWSERCOMPATIBILITY_TITLE;
+    }
+
+    function event_hook($event, &$bag, &$eventData) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+        if (isset($hooks[$event])) {
+            switch($event) {
+                case 'css_backend':
+                case 'css':
+?>
+img {
+   behavior: url("<?php echo $serendipity['baseURL'] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : ''); ?>plugin/pngbehavior.htc");
+}
+<?php
+                    return true;
+                    break;
+
+                case 'external_plugin':
+                    switch($eventData) {
+                        case 'pngbehavior.htc':
+                            header('Content-Type: text/x-component');
+                            echo str_replace('{blanksrc}', serendipity_getTemplateFile('img/blank.gif'), file_get_contents(dirname(__FILE__) . '/pngbehavior.htc'));
+                            return true;
+                    }
+                    return true;
+                    break;
+
+                default:
+                    return false;
+                    break;
+            }
+        } else {
+            return false;
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/plugins/serendipity_event_contentrewrite/lang_ja.inc.php b/plugins/serendipity_event_contentrewrite/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..40610dd
--- /dev/null
@@ -0,0 +1,34 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_EVENT_CONTENTREWRITE_FROM', 'from');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_TO', 'to');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_NAME', 'コンテントリライター');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_DESCRIPTION', '単語を新しく選択された文字列に置換します (useful for acronyms)');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_NEWTITLE', '新規題名');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_NEWTDESCRIPTION', 'ここに新規項目の acronyms タイトルを入力します ({from})');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_OLDTITLE', 'Title #%d');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_OLDTDESCRIPTION', 'ここに acronyms を入力します ({from})');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_PTITLE', 'プラグインの題名');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_PDESCRIPTION', 'このプラグインの名前');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_NEWDESCRIPTION', '新規詳細');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_NEWDDESCRIPTION', 'ここに新規項目の詳細を入力します ({to})');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_OLDDESCRIPTION', 'Description #%s');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_OLDDDESCRIPTION', 'ここに詳細を入力します ({to})');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_REWRITESTRING', 'リライト文字列');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_REWRITESTRINGDESC', 'リライトに使用する文字列です。Place {from} and {to} anywhere you like to get a rewrite.' . "\n" . 'Example: <acronym title="{to}">{from}</acronym>');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_REWRITECHAR', 'リライト文字');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_REWRITECHARDESC', 'If there is any char you append to force rewriting, enter it here. If you want to only replace \'serendipity*\' with what you entered for that word but want the \'*\' removed, enter that char here.');
+
+?>
\ No newline at end of file
diff --git a/plugins/serendipity_event_contentrewrite/serendipity_event_contentrewrite.php b/plugins/serendipity_event_contentrewrite/serendipity_event_contentrewrite.php
new file mode 100644 (file)
index 0000000..71f34d6
--- /dev/null
@@ -0,0 +1,315 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_CONTENTREWRITE_FROM', 'quelle');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_TO', 'ziel');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_NAME', 'Wort-Ersetzer');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_DESCRIPTION', 'Ersetzt ein Wort mit einem neuen Inhalt, z.B. für Akronyme');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_NEWTITLE', 'Neuer Titel');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_NEWTDESCRIPTION', 'Der Akronym-Titel des neuen Eintrages ({quelle})');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_OLDTITLE', 'Titel #%d');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_OLDTDESCRIPTION', 'Das Akronym ({quelle})');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_PTITLE', 'Plugin Titel');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_PDESCRIPTION', 'Der Name dieses Pligins');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_NEWDESCRIPTION', 'Neue Beschreibung');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_NEWDDESCRIPTION', 'Die Beschreibung des neuen Eintrages ({ziel})');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_OLDDESCRIPTION', 'Beschreibung #%s');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_OLDDDESCRIPTION', 'Die Beschreibung des Eintrages ({ziel})');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_REWRITESTRING', 'Umformungsmaske');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_REWRITESTRINGDESC', 'Ein beliebiger Text der zur Ersetzung verwendet werden soll. Fügen Sie {quelle} und {ziel} irgendwo in diesem Text ein.' . "\n" . 'Beispiel: <acronym title="{quelle}">{ziel}</acronym>');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_REWRITECHAR', 'Rewrite Zeichen');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_REWRITECHARDESC', 'Falls es ein besonderes Zeichen geben soll, was die Wort-Ersetzung ausführt, geben Sie es hier an. Falls z.B. nur \'serendipity*\' damit ersetzt werden soll, was Sie als Akronym für \'serendipity\' definiert haben, und das \'*\' soll entfernt werden, dann geben Sie dieses Zeichen an.');
+        break;
+
+    case 'en':
+    case 'es':
+    default:
+        @define('PLUGIN_EVENT_CONTENTREWRITE_FROM', 'from');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_TO', 'to');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_NAME', 'Content Rewriter');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_DESCRIPTION', 'Replaces words with a new selected string (useful for acronyms)');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_NEWTITLE', 'New Title');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_NEWTDESCRIPTION', 'Enter the acronym-title for a new item here ({from})');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_OLDTITLE', 'Title #%d');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_OLDTDESCRIPTION', 'Enter the acronym here ({from})');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_PTITLE', 'Plugin-Title');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_PDESCRIPTION', 'The name of this plugin');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_NEWDESCRIPTION', 'New Description');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_NEWDDESCRIPTION', 'Enter the description for a new item here ({to})');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_OLDDESCRIPTION', 'Description #%s');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_OLDDDESCRIPTION', 'Enter the description here ({to})');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_REWRITESTRING', 'Rewrite string');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_REWRITESTRINGDESC', 'The string used to rewrite. Place {from} and {to} anywhere you like to get a rewrite.' . "\n" . 'Example: <acronym title="{to}">{from}</acronym>');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_REWRITECHAR', 'Rewrite char');
+        @define('PLUGIN_EVENT_CONTENTREWRITE_REWRITECHARDESC', 'If there is any char you append to force rewriting, enter it here. If you want to only replace \'serendipity*\' with what you entered for that word but want the \'*\' removed, enter that char here.');
+        break;
+}
+
+class serendipity_event_contentrewrite extends serendipity_event
+{
+    var $title = PLUGIN_EVENT_CONTENTREWRITE_NAME;
+    var $rewrite_from, $rewrite_to;
+
+    function cleanup() {
+        // Cleanup. Remove all empty configs on SAVECONF-Submit.
+        serendipity_plugin_api::remove_plugin_value($this->instance, array('title', 'description'));
+
+        return true;
+    }
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $this->title = $this->get_config('title', $this->title);
+        $propbag->add('name',          PLUGIN_EVENT_CONTENTREWRITE_NAME);
+        $propbag->add('description',   PLUGIN_EVENT_CONTENTREWRITE_DESCRIPTION);
+        $propbag->add('stackable',     true);
+        $propbag->add('author',        'Garvin Hicking');
+        $propbag->add('version',       '1.1');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('cachable_events', array('frontend_display' => true));
+        $propbag->add('event_hooks',    array(
+            'frontend_display' => true
+        ));
+
+        if (!empty($_POST['SAVECONF'])) $this->cleanup();
+        $rows = serendipity_db_query("SELECT name, value FROM {$serendipity['dbPrefix']}config WHERE name LIKE '" . $this->instance . "/%' ORDER BY name");
+
+        $counter = 0;
+        $values  = array();
+        $values[] = 'title';
+        $values[] = 'rewrite_string';
+        $values[] = 'rewrite_char';
+        $this->title_values = array();
+        $this->descr_values = array();
+        $this->rewrite_from = array();
+        $this->rewrite_to   = array();
+
+        if (is_array($rows)) {
+            foreach ($rows as $row) {
+                $plugin_value = str_replace($this->instance . '/', '', $row['name']);
+                preg_match('|^(.+)_([0-9]+)$|msU', $plugin_value, $reg_counter);
+
+                $found = false;
+                if ($reg_counter[1] == 'title') {
+                    $this->title_values[] = $plugin_value;
+                    $this->rewrite_from[] = $row['value'];
+                    $found = true;
+                } elseif ($reg_counter[1] == 'description') {
+                    $this->descr_values[] = $plugin_value;
+                    $this->rewrite_to[]   = $row['value'];
+                    $found = true;
+                }
+
+                if ($found) {
+                    $next_counter = $reg_counter[2] + 1;
+                    $counter      = ($next_counter > $counter ? $next_counter : $counter);
+                }
+            }
+        }
+
+        $counter        = ($counter > 0 ? $counter + 1 : $counter);
+
+        if (count($this->title_values) == count($this->descr_values)) {
+            foreach($this->title_values AS $key => $val) {
+                $values[] = $this->title_values[$key];
+                $values[] = $this->descr_values[$key];
+            }
+        }
+
+        $values[] = 'title'       . '_' . $counter;
+        $values[] = 'description' . '_' . $counter;
+
+        $this->markup_elements = array(
+            array(
+              'name'     => 'ENTRY_BODY',
+              'element'  => 'body',
+            ),
+            array(
+              'name'     => 'EXTENDED_BODY',
+              'element'  => 'extended',
+            ),
+            array(
+              'name'     => 'COMMENT',
+              'element'  => 'comment',
+            ),
+            array(
+              'name'     => 'HTML_NUGGET',
+              'element'  => 'html_nugget',
+            )
+        );
+
+        foreach($this->markup_elements as $element) {
+            $values[] = $element['name'];
+        }
+
+        $propbag->add('configuration', $values);
+        $this->counter = $counter;
+    }
+
+    function install() {
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function uninstall() {
+        serendipity_plugin_api::hook_event('backend_cache_purge', $this->title);
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        foreach($this->markup_elements as $element) {
+            if ($name==$element['name']) {
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        constant($name));
+                $propbag->add('description', sprintf(APPLY_MARKUP_TO, constant($name)));
+                return true;
+            }
+        }
+
+        preg_match('|^(.+)_([0-9]+)$|msU', $name, $switch);
+
+        if (!isset($switch[2])) {
+            $switch[1] = $name;
+            $switch[2] = 'empty';
+        }
+
+        switch($switch[1]) {
+            case 'title':
+
+                    if ($switch[2] != 'empty') {
+                        $propbag->add('type',        'string');
+
+                        if ($this->counter == $switch[2]) {
+                            $propbag->add('name',        PLUGIN_EVENT_CONTENTREWRITE_NEWTITLE);
+                            $propbag->add('description', PLUGIN_EVENT_CONTENTREWRITE_NEWTDESCRIPTION);
+                        } else {
+                            $propbag->add('name',        sprintf(PLUGIN_EVENT_CONTENTREWRITE_OLDTITLE, $switch[2]));
+                            $propbag->add('description', PLUGIN_EVENT_CONTENTREWRITE_OLDTDESCRIPTION);
+                        }
+                    } else {
+                        $propbag->add('type',        'string');
+                        $propbag->add('name',        PLUGIN_EVENT_CONTENTREWRITE_PTITLE);
+                        $propbag->add('description', PLUGIN_EVENT_CONTENTREWRITE_PDESCRIPTION);
+                    }
+                    break;
+
+            case 'description':
+                    $propbag->add('type',        'string');
+
+                    if ($this->counter == $switch[2]) {
+                        $propbag->add('name',        PLUGIN_EVENT_CONTENTREWRITE_NEWDESCRIPTION);
+                        $propbag->add('description', PLUGIN_EVENT_CONTENTREWRITE_NEWDDESCRIPTION);
+                    } else {
+                        $propbag->add('name',        sprintf(PLUGIN_EVENT_CONTENTREWRITE_OLDDESCRIPTION, $switch[2]));
+                        $propbag->add('description', PLUGIN_EVENT_CONTENTREWRITE_OLDDDESCRIPTION);
+                    }
+                    break;
+
+            case 'rewrite_string':
+                    $propbag->add('type',         'string');
+                    $propbag->add('name',         PLUGIN_EVENT_CONTENTREWRITE_REWRITESTRING);
+                    $propbag->add('description',  PLUGIN_EVENT_CONTENTREWRITE_REWRITESTRINGDESC);
+                    break;
+
+            case 'rewrite_char':
+                    $propbag->add('type',         'string');
+                    $propbag->add('name',         PLUGIN_EVENT_CONTENTREWRITE_REWRITECHAR);
+                    $propbag->add('description',  PLUGIN_EVENT_CONTENTREWRITE_REWRITECHARDESC);
+                    break;
+
+            default:
+                    return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title)
+    {
+        $title = $this->get_config('title', $this->title);
+?>
+<table>
+<?php
+    if (is_array($this->rewrite_from)) {
+            foreach($this->rewrite_from AS $key => $val) {
+?>
+    <tr>
+        <th style="font-size: 8pt; font-color: white;"><?php echo htmlspecialchars($val); ?></th>
+        <td><?php echo htmlspecialchars($this->rewrite_to[$key]); ?></td>
+    </tr>
+<?php
+            }
+        }
+?>
+</table>
+<?php
+    }
+
+    function event_hook($event, &$bag, &$eventData) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+        if (isset($hooks[$event])) {
+            switch($event) {
+                case 'frontend_display':
+                    $char   = &$this->get_config('rewrite_char');
+                    $string = &$this->get_config('rewrite_string');
+                    foreach($this->rewrite_from AS $nr => $v_from) {
+                        $v_to   = $this->rewrite_to[$nr];
+                        if ($v_from != '' && $v_to != '') {
+                            // Use the supplied rewrite string and replace the {from} and {to} values with the ones we got from the plugin
+                            $new =
+                              str_replace(
+                                array(
+                                  '{' . PLUGIN_EVENT_CONTENTREWRITE_FROM . '}',
+                                  '{' . PLUGIN_EVENT_CONTENTREWRITE_TO . '}'
+                                ),
+
+                                array(
+                                  str_replace(
+                                    $char,
+                                    '',
+                                    $v_from
+                                  ),
+
+                                  $v_to
+                                ),
+
+                                $string
+                            );
+
+                            // Build a regular expression (ungreedy, multiline) with our quoted value. $val here is the word needing the replacement
+                            $regex = '°([^\d\w])(' . preg_quote($v_from) . ')([^\d\w])°msU';
+
+                            // \1 and \3 are the prepend/append strings (usually whitespaces) and $new containing the new value
+                            foreach ($this->markup_elements as $temp) {
+                                if (serendipity_db_bool($this->get_config($temp['name'], true)) && isset($eventData[$temp['element']])) {
+                                    $element = $temp['element'];
+                                    $eventData[$element] = preg_replace($regex, '\1' . $new . '\3', $eventData[$element]);
+                                }
+                            }
+
+                        }
+                    }
+
+                    return true;
+                    break;
+            }
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/plugins/serendipity_event_creativecommons/lang_ja.inc.php b/plugins/serendipity_event_creativecommons/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..94f4b40
--- /dev/null
@@ -0,0 +1,29 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_CREATIVECOMMONS_NAME',        'クリエイティブコモンライセンス');
+        @define('PLUGIN_CREATIVECOMMONS_DESC',        'あなたのコンテンツのクリエイティブコモンズライセンスの選択と表示をします。');
+        @define('PLUGIN_CREATIVECOMMONS_TXT',         'テキストを表示しますか?');
+        @define('PLUGIN_CREATIVECOMMONS_TXT_DESC',    'For visible notifications of license status, show a brief explanation of your license choice.');
+        @define('PLUGIN_CREATIVECOMMONS_CAP',         'この作業のオリジナルコンテンツは <a href="#license_uri#">クリエイティブ・コモンズ・ライセンス</a> に帰属します。');
+        @define('PLUGIN_CREATIVECOMMONS_CAP_PD',      'この作業のオリジナルコンテンツは <a href="#license_url#}">パブリックドメイン</a> に捧げます。');
+        // @define('PLUGIN_CREATIVECOMMONS_BY',          'Require attribution?');
+        // @define('PLUGIN_CREATIVECOMMONS_BY_DESC',     'The licensor permits others to copy, distribute, display, and perform the work. In return, licensees must give the original author credit.');
+        @define('PLUGIN_CREATIVECOMMONS_NC',          'あなたの作品の商業用途を許可しますか?');
+        @define('PLUGIN_CREATIVECOMMONS_NC_DESC',     'The licensor permits others to copy, distribute, display, and perform the work. In return, licensees may not use the work for commercial purposes -- unless they get the licensor\'s permission.');
+        @define('PLUGIN_CREATIVECOMMONS_ND',          '作品の修正を許可しますか');
+        @define('PLUGIN_CREATIVECOMMONS_ND_DESC',     'The licensor permits others to copy, distribute, display and perform only unaltered copies of the work -- not derivative works based on it.');
+        @define('PLUGIN_CREATIVECOMMONS_SA_DESC',     'Yes, as long as others share alike');
+
+?>
diff --git a/plugins/serendipity_event_creativecommons/serendipity_event_creativecommons.php b/plugins/serendipity_event_creativecommons/serendipity_event_creativecommons.php
new file mode 100644 (file)
index 0000000..c7d9121
--- /dev/null
@@ -0,0 +1,377 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_CREATIVECOMMONS_NAME',        'Creative Commons Lizenz');
+        @define('PLUGIN_CREATIVECOMMONS_DESC',        'Wählen Sie eine Lizenz für den Inhalt');
+        @define('PLUGIN_CREATIVECOMMONS_TXT',         'Text anzeigen?');
+        @define('PLUGIN_CREATIVECOMMONS_TXT_DESC',    'Zeigt eine kurze Erklärung zu Ihrer individuellen Lizensierung an');
+        @define('PLUGIN_CREATIVECOMMONS_CAP',         'Der Inhalt dieses Werkes ist lizensiert unter der <a href="#license_uri#">Creative Commons Lizenz</a>');
+        @define('PLUGIN_CREATIVECOMMONS_CAP_PD',      'Der Inhalt dieses Werkes ist als <a href="#license_url#}">Public Domain</a> gewidmet');
+        // @define('PLUGIN_CREATIVECOMMONS_BY',          'Attribution (Nennung als Author) erforderlich?');
+        // @define('PLUGIN_CREATIVECOMMONS_BY_DESC',     'Der Lizenzgeber erlaubt anderen dieses Werk zu kopieren, zu verteilen, anzuwenden und darzustellen. Als Gegenleistung müssen Lizenznehmer den ursprünglichen Authoren nennen.');
+        @define('PLUGIN_CREATIVECOMMONS_NC',          'Kommerzielle Nutzung des Werkes erlauben?');
+        @define('PLUGIN_CREATIVECOMMONS_NC_DESC',     'Der Lizenzgeber erlaubt anderen dieses Werk zu kopieren, zu verteilen, anzuwenden und darzustellen. Als Gegenleistung dürfen die Lizenznehmer das Werk nicht in kommerziellem Kontext einsetzen - es sei denn, sie erhalten die ausdrückliche Genehmigung.');
+        @define('PLUGIN_CREATIVECOMMONS_ND',          'Veränderungen des Werkes erlauben?');
+        @define('PLUGIN_CREATIVECOMMONS_ND_DESC',     'Der Lizenzgeber erlaubt anderen dieses Werk in unveränderter Form zu kopieren, zu verteilen, anzuwenden und darzustellen. Daran anlehnende oder ableitende Werke sind nicht erlaubt.');
+        @define('PLUGIN_CREATIVECOMMONS_SA_DESC',     'Ja, solange dieses Recht weitergegeben wird');
+        break;
+
+    case 'en':
+    default:
+        @define('PLUGIN_CREATIVECOMMONS_NAME',        'Creative Commons License');
+        @define('PLUGIN_CREATIVECOMMONS_DESC',        'Choose and display a creative commons license for your content');
+        @define('PLUGIN_CREATIVECOMMONS_TXT',         'Show text?');
+        @define('PLUGIN_CREATIVECOMMONS_TXT_DESC',    'For visible notifications of license status, show a brief explanation of your license choice.');
+        @define('PLUGIN_CREATIVECOMMONS_CAP',         'Original content in this work is licensed under a <a href="#license_uri#">Creative Commons License</a>');
+        @define('PLUGIN_CREATIVECOMMONS_CAP_PD',      'Original content in this work is dedicated to the <a href="#license_url#}">Public Domain</a>');
+        // @define('PLUGIN_CREATIVECOMMONS_BY',          'Require attribution?');
+        // @define('PLUGIN_CREATIVECOMMONS_BY_DESC',     'The licensor permits others to copy, distribute, display, and perform the work. In return, licensees must give the original author credit.');
+        @define('PLUGIN_CREATIVECOMMONS_NC',          'Allow commercial uses of your work?');
+        @define('PLUGIN_CREATIVECOMMONS_NC_DESC',     'The licensor permits others to copy, distribute, display, and perform the work. In return, licensees may not use the work for commercial purposes -- unless they get the licensor\'s permission.');
+        @define('PLUGIN_CREATIVECOMMONS_ND',          'Allow modifications of your work?');
+        @define('PLUGIN_CREATIVECOMMONS_ND_DESC',     'The licensor permits others to copy, distribute, display and perform only unaltered copies of the work -- not derivative works based on it.');
+        @define('PLUGIN_CREATIVECOMMONS_SA_DESC',     'Yes, as long as others share alike');
+        break;
+}
+
+class serendipity_event_creativecommons extends serendipity_event {
+    var $title = PLUGIN_CREATIVECOMMONS_NAME;
+
+    function introspect(&$propbag)
+    {
+
+        $propbag->add('name',          PLUGIN_CREATIVECOMMONS_NAME);
+        $propbag->add('description',   PLUGIN_CREATIVECOMMONS_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Evan Nemerson');
+        $propbag->add('version',       '1.0');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('configuration', array('nc', 'nd', 'txt', 'cc_v2'));
+        $propbag->add('event_hooks',
+                      array('frontend_display:rss-1.0:per_entry' => true,
+                            'frontend_display:rss-1.0:once'      => true,
+                            'frontend_display:rss-1.0:namespace' => true,
+                            'frontend_display:rss-2.0:per_entry' => true,
+                            'frontend_display:rss-2.0:namespace' => true,
+                            'frontend_display:html:per_entry'    => true,
+                            'frontend_display:html_layout'       => true));
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            /*
+            case 'by':
+                $propbag->add('type',          'boolean');
+                $propbag->add('name',          PLUGIN_CREATIVECOMMONS_BY);
+                $propbag->add('description',   PLUGIN_CREATIVECOMMONS_BY_DESC);
+                break;
+            */
+
+            case 'cc_v2':
+                $propbag->add('type',          'hidden');
+                $propbag->add('value',         'true');
+                break;
+
+            case 'nc':
+                $propbag->add('type',          'boolean');
+                $propbag->add('name',          PLUGIN_CREATIVECOMMONS_NC);
+                $propbag->add('description',   PLUGIN_CREATIVECOMMONS_NC_DESC);
+                $propbag->add('default',       'true');
+                break;
+
+            case 'nd':
+                $propbag->add('type',          'radio');
+                $propbag->add('name',          PLUGIN_CREATIVECOMMONS_ND);
+                $propbag->add('description',   PLUGIN_CREATIVECOMMONS_ND_DESC);
+                $propbag->add('radio',         array(
+                    'value' => array('yes', 'sa', 'no'),
+                    'desc'  => array(YES, PLUGIN_CREATIVECOMMONS_SA_DESC, NO)
+                ));
+                $propbag->add('radio_per_row', '1');
+                $propbag->add('default', 'yes');
+
+                break;
+
+            case 'txt':
+                $propbag->add('type',          'boolean');
+                $propbag->add('name',          PLUGIN_CREATIVECOMMONS_TXT);
+                $propbag->add('description',   PLUGIN_CREATIVECOMMONS_TXT_DESC);
+                $propbag->add('default',       'true');
+                break;
+
+            default:
+                return false;
+                break;
+        }
+        return true;
+    }
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+    function event_hook($event, &$bag, &$eventData) {
+        global $serendipity;
+
+        $license_data    = $this->get_license_data();
+        $license_version = $this->get_config('cc_version', '1.0');
+        $license_type    = $license_data['type'];
+        $license_string  = $license_data['string'];
+        $rdf             = $license_data['rdf'];
+
+        if ($license_string == '') {
+            $license_uri = 'http://web.resource.org/cc/PublicDomain';
+        } else {
+            $license_uri = 'http://creativecommons.org/licenses/'.$license_string.'/'.$license_version.'/';
+            switch ($serendipity['lang']){
+                case 'ja':
+                    $license_uri .= 'jp/';
+                    break;
+                case 'de':
+                    $license_uri .= 'de/deed.de';
+                    break;
+            }
+        }
+
+        $cc_visibility = 'invisible';
+
+        switch ($event) {
+            case 'frontend_display:html_layout':
+                $cc_visibility = 'visible';
+            case 'frontend_display:html:per_entry':
+                $eventData['display_dat'] = '<div style="text-align: center;">';
+                if ($license_string == '') {
+                    if ($cc_visibility == 'visible') {
+                        $eventData['display_dat'] .= '<a href="http://creativecommons.org/licenses/publicdomain">';
+                        $eventData['display_dat'] .= '<img style="border: 0px" alt="No Rights Reserved" src="' . serendipity_getTemplateFile('img/norights.png') .'" />';
+                        $eventData['display_dat'] .= '</a>';
+                        if (serendipity_db_bool($this->get_config('txt', true))) {
+                            $eventData['display_dat'] .= '<br />' . str_replace('#license_uri#', $license_uri, PLUGIN_CREATIVECOMMONS_CAP_PD);
+                        }
+                    }
+                } elseif ($cc_visibility == 'visible') {
+                    $eventData['display_dat'] .= '<a href="'.$license_uri.'">';
+                    $eventData['display_dat'] .= '<img style="border: 0px" alt="Creative Commons License - Some Rights Reserved" src="' . serendipity_getTemplateFile('img/somerights20.gif') .'" />';
+                    $eventData['display_dat'] .= '</a>';
+                    if (serendipity_db_bool($this->get_config('txt', true))) {
+                        $eventData['display_dat'] .= '<br />' . str_replace('#license_uri#', $license_uri, PLUGIN_CREATIVECOMMONS_CAP);
+                    }
+                }
+
+                $eventData['display_dat'] .= '<!-- <rdf:RDF xmlns="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><Work rdf:about=""><license rdf:resource="'.$license_uri.'"/></Work><License rdf:about="'.$license_uri.'">';
+                if (is_array($rdf)) {
+                    foreach ($rdf as $rdf_t => $rdf_v) {
+                        $eventData['display_dat'] .= '  <'.$rdf_v.' rdf:resource="http://web.resource.org/cc/'.$rdf_t.'" />';
+                    }
+                }
+
+                $eventData['display_dat'] .= '</License></rdf:RDF> -->';
+                $eventData['display_dat'] .= '</div>';
+                return true;
+                break;
+
+            case 'frontend_display:rss-2.0:per_entry':
+                $eventData['display_dat'] = '<creativeCommons:license>'.$license_uri.'</creativeCommons:license>';
+                return true;
+                break;
+
+            case 'frontend_display:rss-1.0:per_entry':
+                $eventData['display_dat'] = '<cc:license rdf:resource="'.$license_uri.'" />';
+                return true;
+                break;
+
+            case 'frontend_display:rss-1.0:once':
+                $eventData['display_dat'] = '<cc:License rdf:about="'.$license_uri.'">';
+                foreach ($rdf as $rdf_t => $rdf_v) {
+                  $eventData['display_dat'] .= '<cc:'.$rdf_v.' rdf:resource="http://web.resource.org/cc/'.$rdf_t.'" />';
+                }
+                $eventData['display_dat'] .= '</cc:License>';
+                return true;
+                break;
+
+            case 'frontend_display:rss-2.0:namespace':
+                $eventData['display_dat'] = 'xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule"';
+                return true;
+                break;
+
+            case 'frontend_display:rss-1.0:namespace':
+                $eventData['display_dat'] = 'xmlns:cc="http://web.resource.org/cc/"';
+                return true;
+                break;
+
+            default:
+                return true;
+                break;
+        }
+    }
+
+    function get_license_data() {
+        $license_type = array();
+        $license_version = $this->get_config('cc_version', '1.0');
+
+        if ( ($license_version < 2.0) && ($this->get_config('cc_v2', 'false') == 'true') ) {
+          $this->set_config('cc_version', '2.0');
+          $license_version = '2.0';
+        }
+
+        if (($license_version >= 2.0) || serendipity_db_bool($this->get_config('by', true))) {
+            $license_type[] = 'by';
+        }
+
+        if ($this->get_config('nd') == 'no') {
+            $license_type[] = 'nd';
+        }
+
+        if (!serendipity_db_bool($this->get_config('nc', true))) {
+            $license_type[] = 'nc';
+        }
+
+        if ($this->get_config('nd') == 'sa') {
+            $license_type[] = 'sa';
+        }
+
+        $license_string = implode('-', $license_type);
+
+        switch ($license_string) {
+            case 'by':
+                $rdf = array(
+                    'Attribution'     => 'requires',
+                    'Reproduction'    => 'permits',
+                    'Distribution'    => 'permits',
+                    'DerivativeWorks' => 'permits',
+                    'Notice'          => 'requires'
+                );
+                break;
+
+            case 'by-nd':
+                $rdf = array(
+                    'Attribution'     => 'requires',
+                    'Reproduction'    => 'permits',
+                    'Distribution'    => 'permits',
+                    'Notice'          => 'requires'
+                );
+                break;
+
+            case 'by-nd-nc':
+                $rdf = array(
+                    'Attribution'     => 'requires',
+                    'Reproduction'    => 'permits',
+                    'Distribution'    => 'permits',
+                    'CommercialUse'   => 'prohibits',
+                    'Notice'          => 'requires'
+                );
+                break;
+
+            case 'by-nc':
+                $rdf = array(
+                    'Attribution'     => 'requires',
+                    'Reproduction'    => 'permits',
+                    'Distribution'    => 'permits',
+                    'DerivativeWorks' => 'permits',
+                    'CommercialUse'   => 'prohibits',
+                    'Notice'          => 'requires'
+                );
+                break;
+
+            case 'by-nc-sa':
+                $rdf = array(
+                    'Attribution'     => 'requires',
+                    'Reproduction'    => 'permits',
+                    'Distribution'    => 'permits',
+                    'DerivativeWorks' => 'permits',
+                    'ShareAlike'      => 'requires',
+                    'CommercialUse'   => 'prohibits',
+                    'Notice'          => 'requires'
+                );
+                break;
+
+            case 'by-sa':
+                $rdf = array(
+                    'Attribution'     => 'requires',
+                    'Reproduction'    => 'permits',
+                    'Distribution'    => 'permits',
+                    'DerivativeWorks' => 'permits',
+                    'ShareAlike'      => 'requires',
+                    'Notice'          => 'requires'
+                );
+                break;
+
+            case 'nd':
+                $rdf = array(
+                    'Reproduction'    => 'permits',
+                    'Distribution'    => 'permits',
+                    'Notice'          => 'requires'
+                );
+                break;
+
+            case 'nd-nc':
+                $rdf = array(
+                    'Reproduction'    => 'permits',
+                    'Distribution'    => 'permits',
+                    'CommercialUse'   => 'prohibits',
+                    'Notice'          => 'requires'
+                );
+                break;
+
+            case 'nc':
+                $rdf = array(
+                    'Reproduction'    => 'permits',
+                    'Distribution'    => 'permits',
+                    'DerivativeWorks' => 'permits',
+                    'CommercialUse'   => 'prohibits',
+                    'Notice'          => 'requires'
+                );
+                break;
+
+            case 'nc-sa':
+                $rdf = array(
+                    'Reproduction'    => 'permits',
+                    'Distribution'    => 'permits',
+                    'DerivativeWorks' => 'permits',
+                    'ShareAlike'      => 'requires',
+                    'CommercialUse'   => 'prohibits',
+                    'Notice'          => 'requires'
+                );
+                break;
+
+            case 'sa':
+                $rdf = array(
+                    'Reproduction'    => 'permits',
+                    'Distribution'    => 'permits',
+                    'DerivativeWorks' => 'permits',
+                    'ShareAlike'      => 'requires',
+                    'Notice'          => 'requires'
+                );
+                break;
+
+            case '':
+                $rdf = array(
+                    'Reproduction'    => 'permits',
+                    'Distribution'    => 'permits',
+                    'DerivativeWorks' => 'permits'
+                );
+            break;
+        }
+
+        return array(
+          'type'   => $license_type,
+          'string' => $license_string,
+          'rdf'    => $rdf
+        );
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_emoticate/lang_is.inc.php b/plugins/serendipity_event_emoticate/lang_is.inc.php
new file mode 100644 (file)
index 0000000..edcb274
--- /dev/null
@@ -0,0 +1,8 @@
+<?php # $Id$
+
+        @define('PLUGIN_EVENT_EMOTICATE_NAME', 'Textabreyting: Tilfinningavæða');
+        @define('PLUGIN_EVENT_EMOTICATE_DESC', 'Breyta venjulegum textabrosköllum í grafískar myndir');
+        @define('PLUGIN_EVENT_EMOTICATE_TRANSFORM', 'Venjulegum brosköllum, eins og :-) og ;-), verður breytt í myndir.');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/plugins/serendipity_event_emoticate/lang_ja.inc.php b/plugins/serendipity_event_emoticate/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..0e20030
--- /dev/null
@@ -0,0 +1,20 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_EVENT_EMOTICATE_NAME', 'マークアップ: 感情表現');
+        @define('PLUGIN_EVENT_EMOTICATE_DESC', '標準的な感情表現を画像に変換します。');
+        @define('PLUGIN_EVENT_EMOTICATE_TRANSFORM', '標準的な感情表現、 :-) や ;-) といったものは画像に変換します。');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_emoticate/serendipity_event_emoticate.php b/plugins/serendipity_event_emoticate/serendipity_event_emoticate.php
new file mode 100644 (file)
index 0000000..8c860af
--- /dev/null
@@ -0,0 +1,201 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_EMOTICATE_NAME', 'Textformatierung: Smilies');
+        @define('PLUGIN_EVENT_EMOTICATE_DESC', 'Standard Text-Smilies in Grafiken konvertieren');
+        @define('PLUGIN_EVENT_EMOTICATE_TRANSFORM', 'Standard-Text Smilies wie :-) und ;-) werden zu Bildern konvertiert.');
+        break;
+
+    case 'en':
+    default:
+        @define('PLUGIN_EVENT_EMOTICATE_NAME', 'Markup: Emoticate');
+        @define('PLUGIN_EVENT_EMOTICATE_DESC', 'Convert standard emoticons into graphic images');
+        @define('PLUGIN_EVENT_EMOTICATE_TRANSFORM', 'Standard emoticons like :-) and ;-) are converted to images.');
+        break;
+}
+
+class serendipity_event_emoticate extends serendipity_event
+{
+    var $title = PLUGIN_EVENT_EMOTICATE_NAME;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_EMOTICATE_NAME);
+        $propbag->add('description',   PLUGIN_EVENT_EMOTICATE_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Serendipity Team');
+        $propbag->add('version',       '1.1');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('cachable_events', array('frontend_display' => true));
+        $propbag->add('event_hooks',   array('frontend_display' => true, 'frontend_comment' => true));
+
+        $this->markup_elements = array(
+            array(
+              'name'     => 'ENTRY_BODY',
+              'element'  => 'body',
+            ),
+            array(
+              'name'     => 'EXTENDED_BODY',
+              'element'  => 'extended',
+            ),
+            array(
+              'name'     => 'COMMENT',
+              'element'  => 'comment',
+            ),
+            array(
+              'name'     => 'HTML_NUGGET',
+              'element'  => 'html_nugget',
+            )
+        );
+        $conf_array = array();
+        foreach($this->markup_elements as $element) {
+            $conf_array[] = $element['name'];
+        }
+        $propbag->add('configuration', $conf_array);
+
+    }
+
+    function install() {
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function uninstall() {
+        serendipity_plugin_api::hook_event('backend_cache_purge', $this->title);
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function getEmoticons() {
+        global $serendipity;
+
+        /* Avoid multiple runs of serendipity_getTemplateFile(),
+           in other words - if we already have a list of smilies, don't bother looking for another */
+        if (isset($this->smilies) && sizeof($this->smilies) != 0) {
+            return $this->smilies;
+        }
+
+        /* Hijack global variable $serendipity['custom_emoticons'] if it exists */
+        $hijack_file = serendipity_getTemplateFile('emoticons.inc.php', 'serendipityPath');
+        if (@file_exists($hijack_file)) {
+            @include $hijack_file; // This file contains $serendipity['custom_emoticons'] and maybe $serendipity['custom_emoticons_regexp']
+            if (isset($serendipity['custom_emoticons']) && is_array($serendipity['custom_emoticons'])) {
+                $this->smilies = $serendipity['custom_emoticons'];
+                if (is_array($this->smilies) && (!isset($serendipity['custom_emoticons_regexp']) || !$serendipity['custom_emoticons_regexp'])) {
+                    foreach($this->smilies AS $key => $val) {
+                        unset($this->smilies[$key]);
+                        $this->smilies[preg_quote($key, '/')] = $val;
+                    }
+                }
+            }
+        }
+
+        if (!isset($this->smilies)) {
+            $this->smilies = array(
+                "\:'\("    => serendipity_getTemplateFile('img/emoticons/cry.png'),
+
+                '\:\-?\)'  => serendipity_getTemplateFile('img/emoticons/smile.png'),
+
+                '\:\|'     => serendipity_getTemplateFile('img/emoticons/normal.png'),
+
+                '\:\-?O'  => serendipity_getTemplateFile('img/emoticons/eek.png'),
+
+                '\:\-?\('  => serendipity_getTemplateFile('img/emoticons/sad.png'),
+
+                '8\-?\)'  => serendipity_getTemplateFile('img/emoticons/cool.png'),
+
+                '\:\-?D'  => serendipity_getTemplateFile('img/emoticons/laugh.png'),
+
+                '\:\-?P'  => serendipity_getTemplateFile('img/emoticons/tongue.png'),
+
+                ';\-?\)'  => serendipity_getTemplateFile('img/emoticons/wink.png'),
+            );
+        }
+
+        return $this->smilies;
+    }
+
+    function humanReadableEmoticon($key) {
+        return str_replace(array('-?', '\\'), array('-', ''), $key);
+    }
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+    function example() {
+        $s  = '<table cellspacing="5" style="margin-left: auto; margin-right: auto">';
+        $s .= '<tr>';
+        $i = 1;
+        foreach($this->getEmoticons() as $key => $value) {
+            $s .= '<td style="text-align: center">' . $this->humanReadableEmoticon($key) . '</td><td><img src="'. $value .'"></td>' . "\n";
+            if ($i++ % 7 == 0) $s .= '</tr><tr>';
+        }
+        $s .= '</tr>';
+        $s .= '</table>';
+
+        return $s;
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        $propbag->add('type',        'boolean');
+        $propbag->add('name',        constant($name));
+        $propbag->add('description', sprintf(APPLY_MARKUP_TO, constant($name)));
+        $propbag->add('default', 'true');
+        return true;
+    }
+
+
+    function event_hook($event, &$bag, &$eventData) {
+        global $serendipity;
+        $hooks = &$bag->get('event_hooks');
+
+        if (isset($hooks[$event])) {
+            switch($event) {
+                case 'frontend_display':
+
+                    foreach ($this->markup_elements as $temp) {
+                        if (serendipity_db_bool($this->get_config($temp['name'], true)) && isset($eventData[$temp['element']])) {
+                            $element = &$eventData[$temp['element']];
+
+                            foreach ($this->getEmoticons() as $key => $value) {
+                                $element = preg_replace("/([\t\s\.\!>]+)" . $key . "([\t\s\!\.\)<]+|\$)/U",
+                                    "$1<img src=\"$value\" alt=\"" . $this->humanReadableEmoticon($key) . "\" style=\"display: inline; vertical-align: bottom;\" class=\"emoticon\" />$2",
+                                    $element);
+                            }
+                        }
+                    }
+                    return true;
+                    break;
+
+                case 'frontend_comment':
+                    if (serendipity_db_bool($this->get_config('COMMENT', true))) {
+                        echo '<div class="serendipity_commentDirection">' . PLUGIN_EVENT_EMOTICATE_TRANSFORM . '</div>';
+                    }
+                    return true;
+                    break;
+
+              default:
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/plugins/serendipity_event_entryproperties/lang_ja.inc.php b/plugins/serendipity_event_entryproperties/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..c3d00bd
--- /dev/null
@@ -0,0 +1,34 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_TITLE', 'エントリの拡張プロパティ');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_DESC', '(キャッシュ、非公開記事、スティッキ投稿)');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_STICKYPOSTS', 'スティッキ投稿としてこのエントリをマークする');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS', 'エントリを読むことが出来る人');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS_PRIVATE', '自分自身');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS_MEMBER', '共同執筆者');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS_PUBLIC', 'すべて');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE', 'エントリのキャッシュを許可しますか?');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_DESC', 'もし有効にすると、保存時にキャッシュされたバージョンを常に保存します。キャッシングはパフォーマンスを向上させるでしょうが、恐らく、他のプラグインのの柔軟性を減らすでしょう');
+        @define('PLUGIN_EVENT_ENTRYPROPERTY_BUILDCACHE', 'キャッシュされたエントリの構築');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_FETCHNEXT', 'エントリの次のバッチ取得中...');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_FETCHNO', '%d から %d のエントリを取得中');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_BUILDING', 'エントリ番号 #%d: 「<em>%s</em>」のキャッシュを構築中...');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHED', 'エントリをキャッシュしました。');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_DONE', 'エントリのキャッシュを完了しました。');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_ABORTED', 'エントリのキャッシュ作成を中断しました。');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_TOTAL', ' (合計 %d エントリ)...');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_NL2BR', 'nl2br を無効にする');
+
+?>
diff --git a/plugins/serendipity_event_entryproperties/serendipity_event_entryproperties.php b/plugins/serendipity_event_entryproperties/serendipity_event_entryproperties.php
new file mode 100644 (file)
index 0000000..670d9f2
--- /dev/null
@@ -0,0 +1,480 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_TITLE', 'Erweiterte Eigenschaften von Artikeln');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_DESC', '(Cache, nicht-öffentliche Artikel, dauerhafte Artikel)');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_STICKYPOSTS', 'Dauerhafte Artikel');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS', 'Artikel können gelesen werden von');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS_PRIVATE', 'mir selbst');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS_MEMBER', 'Co-Autoren');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS_PUBLIC', 'allen');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE', 'Artikel cachen?');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_DESC', 'Falls diese Option aktiviert ist, wird eine Cache-Version des Artikels gespeichert. Dieses Caching wird zwar die Performance erhöhen, aber Flexibilität anderer Plugins eventuell einschränken.');
+        @define('PLUGIN_EVENT_ENTRYPROPERTY_BUILDCACHE', 'Cachen aller Artikel');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_FETCHNEXT', 'Suche nach zu cachenden Artikeln...');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_FETCHNO', 'Bearbeite Artikel %d bis %d');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_BUILDING', 'Erzeuge cache für Artikel #%d, <em>%s</em>...');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHED', 'Artikel gecached.');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_DONE', 'Alle Artikel gecached.');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_ABORTED', 'Caching der Artikel ABGEBROCHEN.');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_TOTAL', ' (insgesamt %d Artikel vorhanden)...');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_NL2BR', 'Automatischen Zeilenumbruch deaktivieren');
+        break;
+
+    case 'en':
+    case 'es':
+    default:
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_TITLE', 'Extended properties for entries');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_DESC', '(cache, non-public articles, sticky posts)');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_STICKYPOSTS', 'Mark this entry as a Sticky Post');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS', 'Entries can be read by');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS_PRIVATE', 'Myself');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS_MEMBER', 'Co-authors');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS_PUBLIC', 'Everyone');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE', 'Allow to cache entries?');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_DESC', 'If enabled, a cached version will be generated on every saving. Caching will increase performance, but maybe decrease flexibility for other plugins.');
+        @define('PLUGIN_EVENT_ENTRYPROPERTY_BUILDCACHE', 'Build cached entries');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_FETCHNEXT', 'Fetching next batch of entries...');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_FETCHNO', 'Fetching entries %d to %d');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_BUILDING', 'Building cache for entry #%d, <em>%s</em>...');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHED', 'Entry cached.');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_DONE', 'Entry caching completed.');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_ABORTED', 'Entry caching ABORTED.');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_TOTAL', ' (totalling %d entries)...');
+        @define('PLUGIN_EVENT_ENTRYPROPERTIES_NL2BR', 'Disable nl2br');
+        break;
+}
+
+class serendipity_event_entryproperties extends serendipity_event
+{
+    var $services;
+    var $title = PLUGIN_EVENT_ENTRYPROPERTIES_TITLE;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_ENTRYPROPERTIES_TITLE);
+        $propbag->add('description',   PLUGIN_EVENT_ENTRYPROPERTIES_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Garvin Hicking');
+        $propbag->add('version',       '1.1');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('event_hooks',    array(
+            'frontend_fetchentries'                             => true,
+            'frontend_fetchentry'                               => true,
+            'backend_publish'                                   => true,
+            'backend_save'                                      => true,
+            'backend_display'                                   => true,
+            'backend_import_entry'                              => true,
+            'entry_display'                                     => true,
+            'frontend_entryproperties'                          => true,
+            'backend_sidebar_entries_event_display_buildcache'  => true,
+            'backend_sidebar_entries'                           => true,
+            'backend_cache_entries'                             => true,
+            'backend_cache_purge'                               => true,
+            'backend_plugins_new_instance'                      => true,
+            'frontend_entryproperties_query'                    => true
+        ));
+
+        $propbag->add('configuration', array('cache', 'default_read'));
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'default_read':
+                $propbag->add('type',        'radio');
+                $propbag->add('name',        USE_DEFAULT . ': ' . PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS);
+                $propbag->add('description', '');
+                $propbag->add('radio', array(
+                    'value' => array('private', 'member', 'public'),
+                    'desc'  => array(PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS_PRIVATE, PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS_MEMBER, PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS_PUBLIC)
+                ));
+                $propbag->add('default',     'public');
+                $propbag->add('radio_per_row', '1');
+
+                break;
+
+            case 'cache':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        PLUGIN_EVENT_ENTRYPROPERTIES_CACHE);
+                $propbag->add('description', PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_DESC);
+                $propbag->add('default',     'true');
+                break;
+        }
+        return true;
+    }
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+    function install() {
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function uninstall() {
+        serendipity_plugin_api::hook_event('backend_cache_purge', $this->title);
+    }
+
+    function updateCache(&$entry) {
+        global $serendipity;
+
+        serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}entryproperties WHERE entryid = " . (int)$entry['id'] . " AND property LIKE 'ep_cache_%'");
+        serendipity_plugin_api::hook_event('frontend_display', $entry);
+        serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}entryproperties (entryid, property, value) VALUES (" . (int)$entry['id'] . ", 'ep_cache_body', '" . serendipity_db_escape_string($entry['body']) . "')");
+        serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}entryproperties (entryid, property, value) VALUES (" . (int)$entry['id'] . ", 'ep_cache_extended', '" . serendipity_db_escape_string($entry['extended']) . "')");
+    }
+
+    function getSupportedProperties() {
+        static $supported_properties = array('is_sticky', 'access', 'cache_body', 'cache_extended', 'no_nl2br');
+
+        return $supported_properties;
+    }
+
+    function returnQueryCondition($is_cache) {
+        $and = '';
+        if (!$is_cache) {
+            $and = " AND property NOT LIKE 'ep_cache_%' ";
+        }
+        
+        return $and;
+    }
+
+    function addProperties(&$properties, &$eventData) {
+        global $serendipity;
+        // Get existing data
+        $property = serendipity_fetchEntryProperties($eventData['id']);
+        $supported_properties = serendipity_event_entryproperties::getSupportedProperties();
+
+        foreach($supported_properties AS $prop_key) {
+            $prop_val = (isset($properties[$prop_key]) ? $properties[$prop_key] : null);
+            $prop_key = 'ep_' . $prop_key;
+            if (!isset($property[$prop_key]) && !empty($prop_val)) {
+                $q = "INSERT INTO {$serendipity['dbPrefix']}entryproperties (entryid, property, value) VALUES (" . (int)$eventData['id'] . ", '" . serendipity_db_escape_string($prop_key) . "', '" . serendipity_db_escape_string($prop_val) . "')";
+            } elseif ($property[$propkey] != $prop_val && !empty($prop_val)) {
+                $q = "UPDATE {$serendipity['dbPrefix']}entryproperties SET value = '" . serendipity_db_escape_string($prop_val) . "' WHERE entryid = " . (int)$eventData['id'] . " AND property = '" . serendipity_db_escape_string($prop_key) . "'";
+            } else {
+                $q = "DELETE FROM {$serendipity['dbPrefix']}entryproperties WHERE entryid = " . (int)$eventData['id'] . " AND property = '" . serendipity_db_escape_string($prop_key) . "'";
+            }
+
+            serendipity_db_query($q);
+        }
+    }
+
+    function event_hook($event, &$bag, &$eventData, $addData = null) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+        $is_cache = serendipity_db_bool($this->get_config('cache', 'true'));
+        if (isset($hooks[$event])) {
+            switch($event) {
+                case 'frontend_entryproperties_query':
+                    $eventData['and'] = $this->returnQueryCondition($is_cache);
+                    return true;
+                    break;
+
+                case 'backend_display':
+                    $is_sticky =    (isset($eventData['properties']['ep_is_sticky']) && serendipity_db_bool($eventData['properties']['ep_is_sticky']))
+                                 || (isset($serendipity['POST']['properties']['is_sticky']) && serendipity_db_bool($serendipity['POST']['properties']['is_sticky']))
+                               ? 'checked="checked"'
+                               : '';
+                    $nl2br     =    (isset($eventData['properties']['ep_no_nl2br']) && serendipity_db_bool($eventData['properties']['ep_no_nl2br']))
+                                 || (isset($serendipity['POST']['properties']['no_nl2br']) && serendipity_db_bool($serendipity['POST']['properties']['no_nl2br']))
+                               ? 'checked="checked"'
+                               : '';
+
+                    $access_values = array(
+                        PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS_PRIVATE => 'private',
+                        PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS_MEMBER  => 'member',
+                        PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS_PUBLIC  => 'public',
+                    );
+
+                    if (isset($eventData['properties']['ep_access'])) {
+                        $access = $eventData['properties']['ep_access'];
+                    } elseif (isset($serendipity['POST']['properties']['access'])) {
+                        $access = $serendipity['POST']['properties']['access'];
+                    } else {
+                        $access = $this->get_config('default_read', 'public');
+                    }
+?>
+                    <fieldset style="margin: 5px">
+                        <legend><?php echo PLUGIN_EVENT_ENTRYPROPERTIES_TITLE; ?></legend>
+                            <input type="checkbox" name="serendipity[properties][is_sticky]" id="properties_is_sticky" value="true" <?php echo $is_sticky; ?> />
+                                <label title="<?php echo PLUGIN_EVENT_ENTRYPROPERTIES_STICKYPOSTS; ?>" for="properties_is_sticky">&nbsp;<?php echo PLUGIN_EVENT_ENTRYPROPERTIES_STICKYPOSTS; ?>&nbsp;&nbsp;</label><br />
+<?php if (class_exists('serendipity_event_nl2br')){ ?>
+                            <input type="checkbox" name="serendipity[properties][no_nl2br]" id="properties_no_nl2br" value="true" <?php echo $nl2br; ?> />
+                                <label title="<?php echo PLUGIN_EVENT_ENTRYPROPERTIES_NL2BR; ?>" for="properties_no_nl2br">&nbsp;<?php echo PLUGIN_EVENT_ENTRYPROPERTIES_NL2BR; ?>&nbsp;&nbsp;</label><br />
+
+<?php } ?>
+
+                            <?php echo PLUGIN_EVENT_ENTRYPROPERTIES_ACCESS; ?>:
+<?php
+                    foreach($access_values AS $radio_title => $radio_value) {
+?>
+                            <input type="radio" name="serendipity[properties][access]" id="properties_access_<?php echo $radio_value; ?>" value="<?php echo $radio_value; ?>" <?php echo $radio_value == $access ? 'checked="checked"' : ''; ?> />
+                                <label title="<?php echo $radio_title; ?>" for="properties_access_<?php echo $radio_value; ?>">&nbsp;<?php echo $radio_title; ?>&nbsp;&nbsp;</label>
+<?php
+                    }
+?>
+                            <br />
+                    </fieldset>
+<?php
+                    return true;
+                    break;
+
+                case 'backend_sidebar_entries':
+                    if ($is_cache) {
+?>
+                        <li><a href="?serendipity[adminModule]=event_display&amp;serendipity[adminAction]=buildcache"><?php echo PLUGIN_EVENT_ENTRYPROPERTY_BUILDCACHE; ?></a></li>
+<?php
+                    }
+                    return true;
+                    break;
+                case 'backend_import_entry':
+                    //TODO: (ph) Maybe handle caching?
+                    if (is_array($addData) && !$addData['nl2br']){
+                        $props = array();
+                        $props['no_nl2br'] = 'true';
+                        $this->addProperties($props, $eventData);
+                    }
+                break;
+                case 'backend_sidebar_entries_event_display_buildcache':
+                    if ($is_cache) {
+                        $per_fetch = 25;
+                        $page = (isset($serendipity['GET']['page']) ? $serendipity['GET']['page'] : 1);
+                        $from = ($page-1)*$per_fetch;
+                        $to   = ($page)*$per_fetch;
+                        printf(PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_FETCHNO, $from, $to);
+                        $entries = serendipity_fetchEntries(
+                            null,
+                            true,
+                            $per_fetch,
+                            false,
+                            false,
+                            'timestamp DESC',
+                            '',
+                            true
+                        );
+
+                        $total = serendipity_getTotalEntries();
+                        printf(PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_TOTAL . '<br />', $total);
+
+                        foreach($entries AS $idx => $entry) {
+                            printf(PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_BUILDING . '<br />', $entry['id'], htmlspecialchars($entry['title']));
+                            $this->updateCache($entry);
+                            echo PLUGIN_EVENT_ENTRYPROPERTIES_CACHED . '<br /><br />';
+                        }
+
+                        echo '<br />';
+
+                        if ($to < $total) {
+?>
+                        <script type="text/javascript">
+                            if (confirm("<?php echo htmlspecialchars(PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_FETCHNEXT); ?>")) {
+                                location.href = "?serendipity[adminModule]=event_display&serendipity[adminAction]=buildcache&serendipity[page]=<?php echo ($page+1); ?>";
+                            } else {
+                                alert("<?php echo htmlspecialchars(PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_ABORTED); ?>");
+                            }
+                        </script>
+<?php
+                        } else {
+                            echo '<div class="serendipity_msg_notice">' . PLUGIN_EVENT_ENTRYPROPERTIES_CACHE_DONE . '</div>';
+                        }
+                    }
+                    return true;
+                    break;
+
+                case 'backend_cache_entries':
+                    if (!$is_cache) {
+                        return true;
+                    }
+
+                    $entries = serendipity_fetchEntries(
+                        null,
+                        true,
+                        $serendipity['fetchLimit'],
+                        false,
+                        false,
+                        'timestamp DESC',
+                        '',
+                        true
+                    );
+
+                    foreach($entries AS $idx => $entry) {
+                        $this->updateCache($entry);
+                    }
+                    return true;
+                    break;
+
+                case 'backend_cache_purge':
+                    if (!$is_cache) {
+                        return true;
+                    }
+
+                    serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}entryproperties WHERE property LIKE 'ep_cache_%'");
+                    break;
+
+                case 'backend_publish':
+                case 'backend_save':
+                    if (!isset($serendipity['POST']['properties']) || !is_array($serendipity['POST']['properties']) || !isset($eventData['id'])) {
+                        return true;
+                    }
+
+                    if ($is_cache) {
+                        $serendipity['POST']['properties']['cache_body']     = $eventData['body'];
+                        $serendipity['POST']['properties']['cache_extended'] = $eventData['extended'];
+                    }
+
+                    $this->addProperties($serendipity['POST']['properties'], $eventData);
+
+                    return true;
+                    break;
+
+                case 'frontend_entryproperties':
+                    $and = $this->returnQueryCondition($is_cache);
+                    $q = "SELECT entryid, property, value FROM {$serendipity['dbPrefix']}entryproperties WHERE entryid IN (" . implode(', ', array_keys($addData)) . ") $and";
+
+                    $properties = serendipity_db_query($q);
+                    if (!is_array($properties)) {
+                        return true;
+                    }
+
+                    foreach($properties AS $idx => $row) {
+                        $eventData[$addData[$row['entryid']]]['properties'][$row['property']] = $row['value'];
+                    }
+                    return true;
+                    break;
+
+                case 'entry_display':
+                    // PH: This is done after Garvins suggestion to patchup $eventData in case an entry
+                    //     is in the process of being created. This must be done for the extended properties
+                    //     to be applied in the preview.
+                    if (is_array($serendipity['POST']['properties']) && count($serendipity['POST']['properties']) > 0){
+                        $parr = array();
+                        $supported_properties = serendipity_event_entryproperties::getSupportedProperties();
+                        foreach($supported_properties AS $prop_key) {
+                            if (isset($serendipity['POST']['properties'][$prop_key]))
+                                $parr['ep_' . $prop_key] = $serendipity['POST']['properties'][$prop_key];
+                        }
+                        $eventData[0]['properties'] = $parr;
+                    }
+                    break;
+
+                case 'frontend_fetchentries':
+                case 'frontend_fetchentry':
+                    $conds = array();
+                    if ($_SESSION['serendipityAuthedUser'] === true) {
+                        $conds[] = " (ep_access.property IS NULL OR ep_access.value = 'member' OR ep_access.value = 'public' OR (ep_access.value = 'private' AND e.authorid = " . (int)$serendipity['authorid'] . ")) ";
+                    } else {
+                        $conds[] = " (ep_access.property IS NULL OR ep_access.value = 'public') ";
+                    }
+
+                    if (count($conds) > 0) {
+                        $cond = implode(' AND ', $conds);
+                        if (empty($eventData['and'])) {
+                            $eventData['and'] = " WHERE $cond ";
+                        } else {
+                            $eventData['and'] .= " AND $cond ";
+                        }
+                    }
+
+                    $conds = array();
+                    if (!isset($addData['noSticky']) || $addData['noSticky'] !== true) {
+                        $conds[] = 'ep_sticky.value AS orderkey,';
+                    } else {
+                        $conds[] = 'e.isdraft AS orderkey,';
+                    }
+
+                    if ($is_cache && (!isset($addData['noCache']) || !$addData['noCache'])) {
+                        $conds[] = 'ep_cache_extended.value AS ep_cache_extended,';
+                        $conds[] = 'ep_cache_body.value     AS ep_cache_body,';
+                    }
+
+                    $cond = implode("\n", $conds);
+                    if (empty($eventData['addkey'])) {
+                        $eventData['addkey'] = $cond;
+                    } else {
+                        $eventData['addkey'] .= $cond;
+                    }
+
+                    $cond = 'orderkey DESC';
+                    if (empty($eventData['orderby'])) {
+                        $eventData['orderby'] = $cond;
+                    } else {
+                        $eventData['orderby'] = $cond . ', ' . $eventData['orderby'];
+                    }
+
+                    $joins = array();
+                    if ($is_cache && (!isset($addData['noCache']) || !$addData['noCache'])) {
+                        $joins[] = "LEFT OUTER JOIN {$serendipity['dbPrefix']}entryproperties ep_cache_extended
+                                                 ON (e.id = ep_cache_extended.entryid AND ep_cache_extended.property = 'ep_cache_extended')";
+                        $joins[] = "LEFT OUTER JOIN {$serendipity['dbPrefix']}entryproperties ep_cache_body
+                                                 ON (e.id = ep_cache_body.entryid AND ep_cache_body.property = 'ep_cache_body')";
+                    }
+                    $joins[] = "LEFT OUTER JOIN {$serendipity['dbPrefix']}entryproperties ep_access
+                                             ON (e.id = ep_access.entryid AND ep_access.property = 'ep_access')";
+
+                    if (!isset($addData['noSticky']) || $addData['noSticky'] !== true) {
+                        $joins[] = "LEFT JOIN {$serendipity['dbPrefix']}entryproperties ep_sticky
+                                                 ON (e.id = ep_sticky.entryid AND ep_sticky.property = 'ep_is_sticky')";
+                    }
+
+                    $cond = implode("\n", $joins);
+                    if (empty($eventData['joins'])) {
+                        $eventData['joins'] = $cond;
+                    } else {
+                        $eventData['joins'] .= $cond;
+                    }
+
+                    return true;
+                    break;
+
+                case 'backend_plugins_new_instance':
+                    // This hook will always push the entryproperties plugin as last in queue.
+                    // Happens always when a new plugin is added.
+                    // This is important because of its caching mechanism!
+
+                    // Fetch maximum sort_order value. This will be the new value of our current plugin.
+                    $q  = "SELECT MAX(sort_order) as sort_order_max FROM {$serendipity['dbPrefix']}plugins WHERE placement = '" . $addData['default_placement'] . "'";
+                    $rs  = serendipity_db_query($q, true, 'num');
+
+                    // Fetch current sort_order of current plugin.
+                    $q   = "SELECT sort_order FROM {$serendipity['dbPrefix']}plugins WHERE name = '" . $this->instance . "'";
+                    $cur = serendipity_db_query($q, true, 'num');
+                    
+                    // Decrease sort_order of all plugins after current plugin by one.
+                    $q = "UPDATE {$serendipity['dbPrefix']}plugins SET sort_order = sort_order - 1 WHERE placement = '" . $addData['default_placement'] . "' AND sort_order > " . intval($cur[0]);
+                    serendipity_db_query($q);
+
+                    // Set current plugin as last plugin in queue.
+                    $q = "UPDATE {$serendipity['dbPrefix']}plugins SET sort_order = " . intval($rs[0]) . " WHERE name = '" . $this->instance . "'";
+                    serendipity_db_query($q);
+
+                    return true;
+                    break;
+
+                default:
+                    return false;
+                    break;
+            }
+        } else {
+            return false;
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_htmlvalidator/lang_ja.inc.php b/plugins/serendipity_event_htmlvalidator/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..6ee1dde
--- /dev/null
@@ -0,0 +1,24 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_NAME', 'HTML 検証システム');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_DESC', 'XML 準拠のエントリを検証します。');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_CHARSET', '文字コード');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_CHARSETDESC', '通常の記事の文字コードを指定します。');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_DOCTYPE', 'ドキュメントタイプ');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_DOCTYPEDESC', '通常の記事のドキュメントタイプを指定します。');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_VALIDATE', '各プレビュー時に検証する');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_GOVALIDATE', 'プレビューで HTML 検証を表示');
+
+?>
diff --git a/plugins/serendipity_event_htmlvalidator/serendipity_event_htmlvalidator.php b/plugins/serendipity_event_htmlvalidator/serendipity_event_htmlvalidator.php
new file mode 100644 (file)
index 0000000..7dc5323
--- /dev/null
@@ -0,0 +1,272 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_NAME', 'HTML Validator');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_DESC', 'Überprüft, ob ein Artikel XML-konform ist');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_CHARSET', 'Zeichensatz');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_CHARSETDESC', 'Der übliche Zeichensatz Ihrer Einträge');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_DOCTYPE', 'Dokumenttyp');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_DOCTYPEDESC', 'Der übliche Dokumenttyp Ihrer Einträge');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_VALIDATE', 'Bei jeder Vorschau aktiviert');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_GOVALIDATE', 'HTML-Validator bei der Vorschau ausführen');
+        break;
+
+    case 'en':
+    case 'es':
+    default:
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_NAME', 'HTML Validator');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_DESC', 'Validates entries on their XML-conformity');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_CHARSET', 'Charset');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_CHARSETDESC', 'The usual charset of your articles');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_DOCTYPE', 'Doctype');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_DOCTYPEDESC', 'The usual document type of your articles');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_VALIDATE', 'Validate on each preview');
+        @define('PLUGIN_EVENT_HTMLVALIDATOR_GOVALIDATE', 'Show HTML-Validator on preview');
+        break;
+}
+
+class serendipity_event_htmlvalidator extends serendipity_event
+{
+    var $title = PLUGIN_EVENT_HTMLVALIDATOR_NAME;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_HTMLVALIDATOR_NAME);
+        $propbag->add('description',   PLUGIN_EVENT_HTMLVALIDATOR_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Garvin Hicking');
+        $propbag->add('version',       '1.0');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('event_hooks',    array(
+            'backend_preview' => true,
+            'backend_display' => true,
+        ));
+
+        $propbag->add('configuration', array('charset', 'doctype', 'default_validate'));
+
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'default_validate':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        PLUGIN_EVENT_HTMLVALIDATOR_VALIDATE);
+                $propbag->add('description', PLUGIN_EVENT_HTMLVALIDATOR_VALIDATE);
+                $propbag->add('default',     'false');
+                break;
+
+            case 'charset':
+                $propbag->add('type',        'select');
+                $propbag->add('name',        PLUGIN_EVENT_HTMLVALIDATOR_CHARSET);
+                $propbag->add('description', PLUGIN_EVENT_HTMLVALIDATOR_CHARSETDESC);
+                $propbag->add('default',     '(detect automatically)');
+                $propbag->add('select_values', array(
+                    '(detect automatically)' => '(detect automatically)',
+                    'utf-8 (Unicode, worldwide)' => 'utf-8 (Unicode, worldwide)',
+                    'utf-16 (Unicode, worldwide)' => 'utf-16 (Unicode, worldwide)',
+                    'iso-8859-1 (Western Europe)' => 'iso-8859-1 (Western Europe)',
+                    'iso-8859-2 (Central Europe)' => 'iso-8859-2 (Central Europe)',
+                    'iso-8859-3 (Southern Europe)' => 'iso-8859-3 (Southern Europe)',
+                    'iso-8859-4 (Baltic Rim)' => 'iso-8859-4 (Baltic Rim)',
+                    'iso-8859-5 (Cyrillic)' => 'iso-8859-5 (Cyrillic)',
+                    'iso-8859-6-i (Arabic)' => 'iso-8859-6-i (Arabic)',
+                    'iso-8859-7 (Greek)' => 'iso-8859-7 (Greek)',
+                    'iso-8859-8-i (Hebrew)' => 'so-8859-8-i (Hebrew)',
+                    'iso-8859-9 (Turkish)' => 'iso-8859-9 (Turkish)',
+                    'iso-8859-10 (Latin 6)' => 'iso-8859-10 (Latin 6)',
+                    'iso-8859-13 (Latin 7)' => 'iso-8859-13 (Latin 7)',
+                    'iso-8859-14 (Celtic)' => 'iso-8859-14 (Celtic)',
+                    'iso-8859-15 (Latin 9)' => 'iso-8859-15 (Latin 9)',
+                    'us-ascii (basic English)' => 'us-ascii (basic English)',
+                    'euc-jp (Japanese, Unix)' => 'euc-jp (Japanese, Unix)',
+                    'shift_jis (Japanese, Win/Mac)' => 'shift_jis (Japanese, Win/Mac)',
+                    'iso-2022-jp (Japanese, email)' => 'iso-2022-jp (Japanese, email)',
+                    'euc-kr (Korean)' => 'euc-kr (Korean)',
+                    'gb2312 (Chinese, simplified)' => 'gb2312 (Chinese, simplified)',
+                    'gb18030 (Chinese, simplified)' => 'gb18030 (Chinese, simplified)',
+                    'big5 (Chinese, traditional)' => 'big5 (Chinese, traditional)',
+                    'tis-620 (Thai)' => 'tis-620 (Thai)',
+                    'koi8-r (Russian)' => 'koi8-r (Russian)',
+                    'koi8-u (Ukrainian)' => 'koi8-u (Ukrainian)',
+                    'macintosh (MacRoman)' => 'macintosh (MacRoman)',
+                    'windows-1250 (Central Europe)' => 'windows-1250 (Central Europe)',
+                    'windows-1251 (Cyrillic)' => 'windows-1251 (Cyrillic)',
+                    'windows-1252 (Western Europe)' => 'windows-1252 (Western Europe)',
+                    'windows-1253 (Greek)' => 'windows-1253 (Greek)',
+                    'windows-1254 (Turkish)' => 'windows-1254 (Turkish)',
+                    'windows-1255 (Hebrew)' => 'windows-1255 (Hebrew)',
+                    'windows-1256 (Arabic)' => 'windows-1256 (Arabic)',
+                    'windows-1257 (Baltic Rim)' => 'windows-1257 (Baltic Rim)'
+                ));
+                break;
+
+            case 'doctype':
+                $propbag->add('type',        'select');
+                $propbag->add('name',        PLUGIN_EVENT_HTMLVALIDATOR_DOCTYPE);
+                $propbag->add('description', PLUGIN_EVENT_HTMLVALIDATOR_DOCTYPEDESC);
+                $propbag->add('default',     'Inline');
+                $propbag->add('select_values', array(
+                    'Inline'                 => '(detect automatically)',
+                    'XHTML 1.1'              => 'XHTML 1.1',
+                    'XHTML Basic 1.0'        => 'XHTML Basic 1.0',
+                    'XHTML 1.0 Strict'       => 'XHTML 1.0 Strict',
+                    'XHTML 1.0 Transitional' => 'XHTML 1.0 Transitional',
+                    'XHTML 1.0 Frameset'     => 'XHTML 1.0 Frameset',
+                    'HTML 4.01 Strict'       => 'HTML 4.01 Strict',
+                    'HTML 4.01 Transitional' => 'HTML 4.01 Transitional',
+                    'HTML 4.01 Frameset'     => 'HTML 4.01 Frameset',
+                    'HTML 3.2'               => 'HTML 3.2',
+                    'HTML 2.0'               => 'HTML 2.0'
+                ));
+                break;
+
+            default:
+                    return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+    function event_hook($event, &$bag, &$eventData) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+
+        if (isset($hooks[$event])) {
+            switch($event) {
+                case 'backend_display':
+?>
+                    <fieldset style="margin: 5px">
+                        <legend><?php echo PLUGIN_EVENT_HTMLVALIDATOR_NAME; ?></legend>
+<?php
+                        $selected = (($serendipity['POST']['chk_timestamp'] && $serendipity['POST']['default_validate']) || (!isset($serendipity['POST']['chk_timestamp']) && $this->get_config('default_validate') == 'true') ? 'checked="checked"' : '');
+?>
+                            <input style="margin: 0px; padding: 0px; vertical-align: bottom;" type="checkbox" name="serendipity[default_validate]" id="serendipity[default_validate]" value="true" <?php echo $selected; ?> />
+                                <label style="vertical-align: bottom; margin: 0px; padding: 0px;" for="serendipity[default_validate]">&nbsp;<?php echo PLUGIN_EVENT_HTMLVALIDATOR_GOVALIDATE; ?>&nbsp;&nbsp;</label>
+                    </fieldset>
+<?php
+                    break;
+
+                case 'backend_preview':
+                    if (!$serendipity['POST']['default_validate']) {
+                        return true;
+                    }
+
+                    $url = 'validator.w3.org';
+                    $path = '/check';
+                    $fp = fsockopen($url, 80, $errno, $errstr, 30);
+
+                    $doctype = $this->get_config('doctype');
+                    $charset = $this->get_config('charset');
+
+                    if (empty($doctype)) {
+                        $doctype = 'XHTML 1.1';
+                    }
+
+                    if (empty($charset)) {
+                        $charset = 'iso-8859-1 (Western Europe)';
+                    }
+
+                    $data = '<html><head><title>s9y</title></head><body><div>'
+                          . $eventData
+                          . '</div></body></html>';
+                    $request_data .= '-----------------------------24464570528145
+Content-Disposition: form-data; name="uploaded_file"; filename="s9y.htm"
+Content-Type: text/html
+
+' . $data . '
+-----------------------------24464570528145
+Content-Disposition: form-data; name="charset"
+
+' . $charset . '
+-----------------------------24464570528145
+Content-Disposition: form-data; name="doctype"
+
+' . $doctype . '
+-----------------------------24464570528145
+Content-Disposition: form-data; name="verbose"
+
+1
+-----------------------------24464570528145--';
+
+                    $request_length = strlen($request_data);
+                    $REQUEST = array();
+                    $REQUEST[] = 'POST ' . $path . ' HTTP/1.0';
+                    $REQUEST[] = 'Host: ' . $url;
+                    $REQUEST[] = 'User-Agent: serendipity/' . $serendipity['version'];
+                    $REQUEST[] = 'Referer: http://validator.w3.org/';
+                    $REQUEST[] = 'Content-Type: multipart/form-data; boundary=---------------------------24464570528145';
+                    $REQUEST[] = 'Content-Length: ' . $request_length;
+                    $REQUEST[] = 'Connection: close' . "\r\n";
+                    $REQUEST[] = $request_data;
+
+                    $REQUEST_STRING = implode("\r\n", $REQUEST);
+                    fputs($fp, $REQUEST_STRING);
+
+                    $line = fgets($fp, 1024);
+                    if (preg_match('@^HTTP/1\.. (2|3)0(2|0)@', $line)) {
+                        $out = '';
+                        $inheader = 1;
+                        while(!feof($fp) && strlen($out) < 200000) {
+                            $line = fgets($fp,1024);
+                            if ($inheader && ($line == "\n" || $line == "\r\n")) {
+                                $inheader = 0;
+                            } elseif (!$inheader) {
+                                $out .= $line;
+                            }
+                        }
+                    }
+                    fclose($fp);
+
+                    preg_match('@<table class="header">.+</table>.+</div>.+(<h2 .+)</body>@ms', $out, $html);
+
+                    // Cut the waste
+                    $html[1] = preg_replace(
+                                 array(
+                                   '@<address>.+</address>@ms',
+                                   '@<dl class="tip">.+</dl>@ms',
+                                   '@<div id="source".+>.+</div>@msU'
+                                 ),
+
+                                 array(
+                                   '',
+                                   '',
+                                   ''
+                                 ),
+
+                                 $html[1]
+                    );
+
+                    echo '<div style="border: 1px solid red; margin: 10px; padding: 5px; "><div>' . $html[1] . '</div>';
+                    return true;
+                    break;
+
+                default:
+                    return false;
+                    break;
+            }
+        } else {
+            return false;
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_karma/lang_ja.inc.php b/plugins/serendipity_event_karma/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..4ebab53
--- /dev/null
@@ -0,0 +1,56 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_KARMA_VERSION', '1.2');
+        @define('PLUGIN_KARMA_NAME', '評価');
+        @define('PLUGIN_KARMA_BLAHBLAH', 'ビジターにあなたのエントリの品質を評価させます。');
+        @define('PLUGIN_KARMA_VOTETEXT', 'この記事の評価: ');
+        @define('PLUGIN_KARMA_RATE', 'この記事の評価: %s');
+        @define('PLUGIN_KARMA_VOTEPOINT_1', 'とても素晴らしい!');
+        @define('PLUGIN_KARMA_VOTEPOINT_2', '素晴らしい');
+        @define('PLUGIN_KARMA_VOTEPOINT_3', '普通');
+        @define('PLUGIN_KARMA_VOTEPOINT_4', '面白くない');
+        @define('PLUGIN_KARMA_VOTEPOINT_5', 'よくない');
+        @define('PLUGIN_KARMA_VOTED', 'あなたの評価 "%s" は保管されました。');
+        @define('PLUGIN_KARMA_INVALID', 'あなたの投票は無効でした。');
+        @define('PLUGIN_KARMA_ALREADYVOTED', 'あなたは既に評価が保管されていました。');
+        @define('PLUGIN_KARMA_NOCOOKIE', 'Your browser must support cookies to be able to vote.');
+        @define('PLUGIN_KARMA_CLOSED', '%s 日以内の経過新しい記事での投票です!');
+        @define('PLUGIN_KARMA_ENTRYTIME', 'Voting time after publishing');
+        @define('PLUGIN_KARMA_VOTINGTIME', '投票時間');
+        @define('PLUGIN_KARMA_ENTRYTIME_BLAHBLAH', 'How long (in minutes) after your article has been published an unrestricted voting is allowed? Default: 1440 (one day)');
+        @define('PLUGIN_KARMA_VOTINGTIME_BLAHBLAH', 'Amount of time (in minutes) that needs to be passed from one vote to the other. Is only applied after the time above is expired. Default: 5');
+        @define('PLUGIN_KARMA_TIMEOUT', 'Flood protection: Another visitor has just recently voted. Please wait %s minutes.');
+        @define('PLUGIN_KARMA_CURRENT', '現在の評価: %2$s / %3$s 回の投票 /');
+        @define('PLUGIN_KARMA_EXTENDEDONLY', '拡張された記事のみ');
+        @define('PLUGIN_KARMA_EXTENDEDONLY_BLAHBLAH', 'Only show karmavoting on extended article view');
+        @define('PLUGIN_KARMA_MAXKARMA', 'Karmavoting period');
+        @define('PLUGIN_KARMA_MAXKARMA_BLAHBLAH', 'Only allow karmavoting until the article is X days old (Default: 7)');
+        @define('PLUGIN_KARMA_LOGGING', '投票をログ記録しますか?');
+        @define('PLUGIN_KARMA_LOGGING_BLAHBLAH', 'Should karma votes be logged?');
+        @define('PLUGIN_KARMA_ACTIVE', '評価の投票を有効にしますか?');
+        @define('PLUGIN_KARMA_ACTIVE_BLAHBLAH', '評価を投票する機能を有効にしますか?');
+        @define('PLUGIN_KARMA_VISITS', 'ビジター追跡を有効にしますか?');
+        @define('PLUGIN_KARMA_VISITS_BLAHBLAH', 'Should every click to an extended article be counted and displayed?');
+        @define('PLUGIN_KARMA_VISITSCOUNT', ' %4$s 回のヒット');
+        @define('PLUGIN_KARMA_STATISTICS_VISITS_TOP', 'トップビジターの記事');
+        @define('PLUGIN_KARMA_STATISTICS_VISITS_BOTTOM', 'Worst visited articles');
+        @define('PLUGIN_KARMA_STATISTICS_VOTES_TOP', 'Top karma-voted articles');
+        @define('PLUGIN_KARMA_STATISTICS_VOTES_BOTTOM', 'Least karma-voted articles');
+        @define('PLUGIN_KARMA_STATISTICS_POINTS_TOP', 'Best karma-voted articles');
+        @define('PLUGIN_KARMA_STATISTICS_POINTS_BOTTOM', 'Worst karma-voted articles');
+        @define('PLUGIN_KARMA_STATISTICS_VISITS_NO', 'ビジター');
+        @define('PLUGIN_KARMA_STATISTICS_VOTES_NO', '回の投票');
+        @define('PLUGIN_KARMA_STATISTICS_POINTS_NO', 'ポイント');
+?>
diff --git a/plugins/serendipity_event_karma/serendipity_event_karma.php b/plugins/serendipity_event_karma/serendipity_event_karma.php
new file mode 100644 (file)
index 0000000..f761f45
--- /dev/null
@@ -0,0 +1,633 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_KARMA_VERSION', '1.2');
+        @define('PLUGIN_KARMA_NAME', 'Karma');
+        @define('PLUGIN_KARMA_BLAHBLAH', 'Abstimmung über die Einträge');
+        @define('PLUGIN_KARMA_VOTETEXT', 'Karma dieses Eintrags: ');
+        @define('PLUGIN_KARMA_RATE', 'Eintrag bewerten: %s');
+        @define('PLUGIN_KARMA_VOTEPOINT_1', 'Sehr gut!');
+        @define('PLUGIN_KARMA_VOTEPOINT_2', 'Gut');
+        @define('PLUGIN_KARMA_VOTEPOINT_3', 'Neutral');
+        @define('PLUGIN_KARMA_VOTEPOINT_4', 'Uninteressant');
+        @define('PLUGIN_KARMA_VOTEPOINT_5', 'Übel');
+        @define('PLUGIN_KARMA_VOTED', 'Punktzahl "%s" gespeichert.');
+        @define('PLUGIN_KARMA_INVALID', 'Bewertung ungültig oder manipuliert!');
+        @define('PLUGIN_KARMA_ALREADYVOTED', 'Bewertung bereits gespeichert.');
+        @define('PLUGIN_KARMA_NOCOOKIE', 'Der Browser muss Cookies unterstützen um eine Abstimmung zu ermöglichen.');
+        @define('PLUGIN_KARMA_CLOSED', 'Stimm ab für Artikel, die jünger als %s Tage sind!');
+        @define('PLUGIN_KARMA_ENTRYTIME', 'Abstimmungszeitraum nach Veröffentlichung eines Artikels');
+        @define('PLUGIN_KARMA_VOTINGTIME', 'Abstimmungszeitraum');
+        @define('PLUGIN_KARMA_ENTRYTIME_BLAHBLAH', 'Wie lang (in Minuten) kann nach der Veröffentlichung eines Artikels ein uneingeschränkter Abstimmungszeitraum durchgeführt werden? Standard sind 1440 Minuten (ein Tag).');
+        @define('PLUGIN_KARMA_VOTINGTIME_BLAHBLAH', 'Wartezeit (in Minuten), die nach einer Stimmabgabe vergehen muss bevor eine nächste Stimme angenommen wird. Diese Einschränkung gilt erst nach Überschreitung des obigen uneingeschränkten Abstimmungszeitraumes. Standard: 5 Minuten.');
+        @define('PLUGIN_KARMA_TIMEOUT', 'Wahlschutz: Ein anderer Besucher hat gerade abgestimmt. Bitte %s Minuten warten.');
+        @define('PLUGIN_KARMA_CURRENT', 'Derzeitiges Karma: %2$s, %3$s Stimme(n)');
+        @define('PLUGIN_KARMA_EXTENDEDONLY', 'Nur erweiterte Artikel');
+        @define('PLUGIN_KARMA_EXTENDEDONLY_BLAHBLAH', 'Karmavoting nur im erweiterten Artikel einblenden');
+        @define('PLUGIN_KARMA_MAXKARMA', 'Maximaler Abstimmungszeitraum');
+        @define('PLUGIN_KARMA_MAXKARMA_BLAHBLAH', 'Abstimmungen nur erlauben bis der Artikel X Tage alt ist (Standard: 7)');
+        @define('PLUGIN_KARMA_LOGGING', 'Protokollieren');
+        @define('PLUGIN_KARMA_LOGGING_BLAHBLAH', 'Sollen Logfiles der Votes angelegt werden?');
+        @define('PLUGIN_KARMA_ACTIVE', 'Karmavoting aktivieren?');
+        @define('PLUGIN_KARMA_ACTIVE_BLAHBLAH', 'Soll das Karmavoting verfügbar sein?');
+        @define('PLUGIN_KARMA_VISITS', 'Aufrufstatisik aktivieren?');
+        @define('PLUGIN_KARMA_VISITS_BLAHBLAH', 'Soll jeder Klick auf einen Artikel gezählt und dargestellt werden?');
+        @define('PLUGIN_KARMA_VISITSCOUNT', ' %4$s Klicks');
+        @define('PLUGIN_KARMA_STATISTICS_VISITS_TOP', 'Meistbesuchte Artikel');
+        @define('PLUGIN_KARMA_STATISTICS_VISITS_BOTTOM', 'Wenigstbesuchte Artikel');
+        @define('PLUGIN_KARMA_STATISTICS_VOTES_TOP', 'Meistbewertete Artikel');
+        @define('PLUGIN_KARMA_STATISTICS_VOTES_BOTTOM', 'Wenigstbewertete Artikel');
+        @define('PLUGIN_KARMA_STATISTICS_POINTS_TOP', 'Bestbewertete Artikel');
+        @define('PLUGIN_KARMA_STATISTICS_POINTS_BOTTOM', 'Schlechtstbewerte Artikel');
+        @define('PLUGIN_KARMA_STATISTICS_VISITS_NO', 'Besuche');
+        @define('PLUGIN_KARMA_STATISTICS_VOTES_NO', 'Stimmen');
+        @define('PLUGIN_KARMA_STATISTICS_POINTS_NO', 'Punkte');
+
+        break;
+
+    case 'en':
+    default:
+        @define('PLUGIN_KARMA_VERSION', '1.2');
+        @define('PLUGIN_KARMA_NAME', 'Karma');
+        @define('PLUGIN_KARMA_BLAHBLAH', 'Let visitors rate the quality of your entries');
+        @define('PLUGIN_KARMA_VOTETEXT', 'Karma for this article: ');
+        @define('PLUGIN_KARMA_RATE', 'Rate this article: %s');
+        @define('PLUGIN_KARMA_VOTEPOINT_1', 'Very good!');
+        @define('PLUGIN_KARMA_VOTEPOINT_2', 'Good');
+        @define('PLUGIN_KARMA_VOTEPOINT_3', 'Neutral');
+        @define('PLUGIN_KARMA_VOTEPOINT_4', 'Not interesting');
+        @define('PLUGIN_KARMA_VOTEPOINT_5', 'Bad');
+        @define('PLUGIN_KARMA_VOTED', 'Your rating "%s" was stored.');
+        @define('PLUGIN_KARMA_INVALID', 'Your voting was invalid.');
+        @define('PLUGIN_KARMA_ALREADYVOTED', 'Your rating was already stored.');
+        @define('PLUGIN_KARMA_NOCOOKIE', 'Your browser must support cookies to be able to vote.');
+        @define('PLUGIN_KARMA_CLOSED', 'Vote for articles fresher than %s days!');
+        @define('PLUGIN_KARMA_ENTRYTIME', 'Voting time after publishing');
+        @define('PLUGIN_KARMA_VOTINGTIME', 'Voting time');
+        @define('PLUGIN_KARMA_ENTRYTIME_BLAHBLAH', 'How long (in minutes) after your article has been published an unrestricted voting is allowed? Default: 1440 (one day)');
+        @define('PLUGIN_KARMA_VOTINGTIME_BLAHBLAH', 'Amount of time (in minutes) that needs to be passed from one vote to the other. Is only applied after the time above is expired. Default: 5');
+        @define('PLUGIN_KARMA_TIMEOUT', 'Flood protection: Another visitor has just recently voted. Please wait %s minutes.');
+        @define('PLUGIN_KARMA_CURRENT', 'Current karma: %2$s, %3$s vote(s)');
+        @define('PLUGIN_KARMA_EXTENDEDONLY', 'Only extended article');
+        @define('PLUGIN_KARMA_EXTENDEDONLY_BLAHBLAH', 'Only show karmavoting on extended article view');
+        @define('PLUGIN_KARMA_MAXKARMA', 'Karmavoting period');
+        @define('PLUGIN_KARMA_MAXKARMA_BLAHBLAH', 'Only allow karmavoting until the article is X days old (Default: 7)');
+        @define('PLUGIN_KARMA_LOGGING', 'Log votes?');
+        @define('PLUGIN_KARMA_LOGGING_BLAHBLAH', 'Should karma votes be logged?');
+        @define('PLUGIN_KARMA_ACTIVE', 'Enable karma voting?');
+        @define('PLUGIN_KARMA_ACTIVE_BLAHBLAH', 'Is karma voting turned on?');
+        @define('PLUGIN_KARMA_VISITS', 'Enable visit tracking?');
+        @define('PLUGIN_KARMA_VISITS_BLAHBLAH', 'Should every click to an extended article be counted and displayed?');
+        @define('PLUGIN_KARMA_VISITSCOUNT', ' %4$s hits');
+        @define('PLUGIN_KARMA_STATISTICS_VISITS_TOP', 'Top visited articles');
+        @define('PLUGIN_KARMA_STATISTICS_VISITS_BOTTOM', 'Worst visited articles');
+        @define('PLUGIN_KARMA_STATISTICS_VOTES_TOP', 'Top karma-voted articles');
+        @define('PLUGIN_KARMA_STATISTICS_VOTES_BOTTOM', 'Least karma-voted articles');
+        @define('PLUGIN_KARMA_STATISTICS_POINTS_TOP', 'Best karma-voted articles');
+        @define('PLUGIN_KARMA_STATISTICS_POINTS_BOTTOM', 'Worst karma-voted articles');
+        @define('PLUGIN_KARMA_STATISTICS_VISITS_NO', 'visits');
+        @define('PLUGIN_KARMA_STATISTICS_VOTES_NO', 'votes');
+        @define('PLUGIN_KARMA_STATISTICS_POINTS_NO', 'points');
+
+        break;
+}
+
+class serendipity_event_karma extends serendipity_event
+{
+    var $karmaVote    = '';
+    var $karmaId      = '';
+    var $karmaTimeOut = '';
+    var $karmaVoting  = '';
+    var $title        = PLUGIN_KARMA_NAME;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_KARMA_NAME);
+        $propbag->add('description',   PLUGIN_KARMA_BLAHBLAH);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Garvin Hicking');
+        $propbag->add('version',       '1.01');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('event_hooks',   array('frontend_configure' => true, 'entry_display' => true, 'css' => true, 'event_additional_statistics' => true));
+        $propbag->add('scrambles_true_content', true);
+
+        $propbag->add('configuration', array('karma_active', 'visits_active', 'max_entrytime', 'max_votetime', 'extended_only', 'max_karmatime', 'logging'));
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'max_entrytime':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_ENTRYTIME);
+                $propbag->add('description', PLUGIN_KARMA_ENTRYTIME_BLAHBLAH);
+                $propbag->add('default', 1440);
+                break;
+
+            case 'max_votetime':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_VOTINGTIME);
+                $propbag->add('description', PLUGIN_KARMA_VOTINGTIME_BLAHBLAH);
+                $propbag->add('default', 5);
+                break;
+
+            case 'max_karmatime':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_KARMA_MAXKARMA);
+                $propbag->add('description', PLUGIN_KARMA_MAXKARMA_BLAHBLAH);
+                $propbag->add('default', 7);
+                break;
+
+            case 'karma_active':
+                $propbag->add('type', 'boolean');
+                $propbag->add('name', PLUGIN_KARMA_ACTIVE);
+                $propbag->add('description', PLUGIN_KARMA_ACTIVE_BLAHBLAH);
+                $propbag->add('default', 'true');
+                break;
+
+            case 'visits_active':
+                $propbag->add('type', 'boolean');
+                $propbag->add('name', PLUGIN_KARMA_VISITS);
+                $propbag->add('description', PLUGIN_KARMA_VISITS_BLAHBLAH);
+                $propbag->add('default', 'true');
+                break;
+
+            case 'extended_only':
+                $propbag->add('type', 'boolean');
+                $propbag->add('name', PLUGIN_KARMA_EXTENDEDONLY);
+                $propbag->add('description', PLUGIN_KARMA_EXTENDEDONLY_BLAHBLAH);
+                $propbag->add('default', 'false');
+                break;
+
+            case 'logging':
+                $propbag->add('type', 'boolean');
+                $propbag->add('name', PLUGIN_KARMA_LOGGING);
+                $propbag->add('description', PLUGIN_KARMA_LOGGING_BLAHBLAH);
+                $propbag->add('default', 'false');
+                break;
+
+            default:
+                    return false;
+        }
+        return true;
+    }
+
+    function checkScheme() {
+        global $serendipity;
+
+        $version = $this->get_config('version', '0.9');
+
+        if ($version == '1.1') {
+            $q   = "ALTER TABLE {$serendipity['dbPrefix']}karma ADD visits INT(11) default 0";
+            $sql = serendipity_db_schema_import($q);
+            $this->set_config('version', PLUGIN_KARMA_VERSION);
+        } elseif ($version == '1.0') {
+            $q   = "ALTER TABLE {$serendipity['dbPrefix']}karma ADD visits INT(11) default 0";
+            $sql = serendipity_db_schema_import($q);
+
+            $q   = "CREATE TABLE {$serendipity['dbPrefix']}karmalog (
+                        entryid int(11) default null,
+                        points int(4) default null,
+                        ip varchar(15),
+                        user_agent varchar(255),
+                        votetime int(11) default null
+                    )";
+            $sql = serendipity_db_schema_import($q);
+            $this->set_config('version', PLUGIN_KARMA_VERSION);
+        } elseif ($version != PLUGIN_KARMA_VERSION) {
+            $q   = "CREATE TABLE {$serendipity['dbPrefix']}karma (
+                        entryid int(11) default null,
+                        points int(4) default null,
+                        votes int(4) default null,
+                        lastvote int(10) {UNSIGNED} NULL,
+                        visits int(11) default null
+                    )";
+            $sql = serendipity_db_schema_import($q);
+
+            $q   = "CREATE TABLE {$serendipity['dbPrefix']}karmalog (
+                        entryid int(11) default null,
+                        points int(4) default null,
+                        ip varchar(15),
+                        user_agent varchar(255)
+                    )";
+            $sql = serendipity_db_schema_import($q);
+
+            $q   = "CREATE INDEX kfetch ON {$serendipity['dbPrefix']}karma (entryid, lastvote);";
+            $sql = serendipity_db_schema_import($q);
+
+            $q   = "CREATE INDEX kentryid ON {$serendipity['dbPrefix']}karma (entryid);";
+            $sql = serendipity_db_schema_import($q);
+            $this->set_config('version', PLUGIN_KARMA_VERSION);
+        }
+
+        return true;
+    }
+
+    function generate_content(&$title)
+    {
+        $title       = $this->title;
+    }
+
+    function event_hook($event, &$bag, &$eventData, $addData = null) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+
+        if (isset($hooks[$event])) {
+            switch($event) {
+                case 'frontend_configure':
+                    if (!isset($serendipity['COOKIE']['karmaVote'])) {
+                        serendipity_setCookie('karmaVote', serialize(array()));
+                    }
+
+                    if (!isset($serendipity['GET']['karmaId']) || !isset($serendipity['GET']['karmaVote'])) {
+                        return;
+                    }
+
+                    $this->karmaId     = (int)$serendipity['GET']['karmaId'];
+                    $this->karmaVoting = (int)$serendipity['GET']['karmaVote'];
+
+                    if (!isset($serendipity['COOKIE']['karmaVote'])) {
+                        $this->karmaVote = 'nocookie';
+                        return;
+                    }
+
+                    $karma   = unserialize($serendipity['COOKIE']['karmaVote']);
+
+                    if (!is_array($karma) || !is_numeric($this->karmaVoting) || !is_numeric($this->karmaId) || $this->karmaVoting > 2 || $this->karmaVoting < -2) {
+                        $this->karmaVote = 'invalid1';
+                        return;
+                    }
+
+                    if (!empty($karma[$this->karmaId])) {
+                        $this->karmaVote = 'alreadyvoted';
+                        return ;
+                    }
+
+                    if (stristr($_SERVER['HTTP_USER_AGENT'], 'google')) {
+                        // We don't want googlebots hitting the karma-voting
+                        $this->karmaVote = 'invalid1';
+                        return ;
+                    }
+
+                    // Voting takes place here.
+                    $q = 'SELECT *
+                            FROM ' . $serendipity['dbPrefix'] . 'entries AS e
+                 LEFT OUTER JOIN ' . $serendipity['dbPrefix'] . 'karma   AS k
+                              ON e.id = k.entryid
+                           WHERE e.id = ' . serendipity_db_escape_string($this->karmaId) . ' LIMIT 1';
+                    $row = serendipity_db_query($q, true);
+
+                    if (!isset($row) || !is_array($row)) {
+                        $this->karmaVote = 'invalid2';
+                        return;
+                    }
+
+                    $now = time();
+
+                    if ($row['votes'] > 0) {
+                        // Votes for this entry already exist. Do some checking.
+                        $max_entrytime = $this->get_config('max_entrytime', 1440) * 60;
+                        $max_votetime  = $this->get_config('max_votetime', 5)     * 60;
+                        $max_karmatime = $this->get_config('max_karmatime', 7)    * 24 * 60 * 60;
+
+                        if ($row['timestamp'] < ($now - $max_karmatime)) {
+                            $this->karmaVote = 'timeout2';
+                            return;
+                        }
+
+                        if (($row['timestamp'] > ($now - $max_entrytime)) || ($row['lastvote'] + $max_votetime < $now) || $row['lastvote'] == 0) {
+                            // Update votes
+                            $q = sprintf(
+                              "UPDATE {$serendipity['dbPrefix']}karma
+                                  SET points   = %s,
+                                      votes    = %s,
+                                      lastvote = %s
+                                WHERE entryid  = %s",
+                              $row['points'] + $this->karmaVoting,
+                              $row['votes']  + 1,
+                              $now,
+                              $this->karmaId
+                            );
+
+                            serendipity_db_query($q);
+                        } else {
+                            $this->karmaVote    = 'timeout';
+                            $this->karmaTimeOut = abs(round(($now - ($row['lastvote'] + $max_votetime)) / 60, 1));
+                            return;
+                        }
+                    } else {
+                        // No Votes. Just insert it.
+                        $q = sprintf(
+                          "INSERT INTO {$serendipity['dbPrefix']}karma
+                                       (entryid, points, votes, lastvote)
+                                VALUES (%s,      %s,     %s,    %s)",
+                          $this->karmaId,
+                          $this->karmaVoting,
+                          1,
+                          $now
+                        );
+
+                        $sql = serendipity_db_query($q);
+                    }
+
+                    if (serendipity_db_bool($this->get_config('logging', false))) {
+                        $q = sprintf(
+                          "INSERT INTO {$serendipity['dbPrefix']}karmalog
+                                       (entryid, points, ip, user_agent, votetime)
+                                VALUES (%s, %s, '%s', '%s', %s)",
+                          $this->karmaId,
+                          $this->karmaVoting,
+                          serendipity_db_escape_string($_SERVER['REMOTE_ADDR']),
+                          serendipity_db_escape_string($_SERVER['HTTP_USER_AGENT']),
+                          $now
+                        );
+                        $sql = serendipity_db_query($q);
+                        if (is_string($sql)) {
+                            mail($serendipity['serendipityEmail'] , 'KARMA ERROR', $q . '<br />' . $sql . '<br />');
+                        }
+                    }
+
+                    $karma[$this->karmaId] = $this->karmaVoting;
+                    $this->karmaVote       = 'voted';
+                    serendipity_setCookie('karmaVote', serialize($karma));
+
+                    return true;
+                    break;
+
+                case 'css':
+                    if (strpos($eventData, '.serendipity_karmaVoting')) {
+                        // class exists in CSS, so a user has customized it and we don't need default
+                        return true;
+                    }
+?>
+
+.serendipity_karmaVoting {
+    margin-left: auto;
+    margin-right: 0px;
+    text-align: right;
+    font-size: 7pt;
+    display: block;
+    margin-top: 5px;
+    margin-bottom: 0px;
+}
+
+.serendipity_karmaVoting a {
+    font-size: 7pt;
+    text-decoration: none;
+}
+
+.serendipity_karmaVoting a:hover {
+    color: green;
+}
+
+.serendipity_karmaError {
+    color: #FF8000;
+}
+
+.serendipity_karmaSuccess {
+    color: green;
+}
+<?php
+                    return true;
+                    break;
+
+                case 'event_additional_statistics':
+                    $sql = array();
+                    $sql['visits_top']    = array('visits', 'DESC');
+                    $sql['visits_bottom'] = array('visits', 'ASC');
+                    $sql['votes_top']     = array('votes', 'DESC');
+                    $sql['votes_bottom']  = array('votes', 'ASC');
+                    $sql['points_top']    = array('points', 'DESC');
+                    $sql['points_bottom'] = array('points', 'ASC');
+
+                    foreach($sql AS $key => $rows) {
+                        $q = "SELECT e.id,
+                                     e.title,
+                                     SUM(k.{$rows[0]}) AS no
+                                FROM {$serendipity['dbPrefix']}karma
+                                     AS k
+                                JOIN {$serendipity['dbPrefix']}entries
+                                     AS e
+                                  ON k.entryid = e.id
+                            WHERE k.{$rows[0]} IS NOT NULL AND k.{$rows[0]} != 0
+                            GROUP BY e.id, e.title ORDER BY no {$rows[1]} LIMIT {$addData['maxitems']}";
+                        $sql_rows = serendipity_db_query($q);
+?>
+    <dt><strong><?php echo constant('PLUGIN_KARMA_STATISTICS_' . strtoupper($key)); ?></strong></dt>
+    <dl>
+<?php
+                        if (is_array($sql_rows)) {
+                            foreach($sql_rows AS $id => $row) {
+    ?>
+        <dt><strong><a href="<?php echo serendipity_archiveURL($row['id'], $row['title'], 'serendipityHTTPPath'); ?>"><?php echo htmlspecialchars($row['title']); ?></a></strong></dt>
+        <dd><?php echo $row['no']; ?> <?php echo constant('PLUGIN_KARMA_STATISTICS_' . strtoupper($rows[0]) . '_NO'); ?></dd>
+    <?php
+                            }
+                        }
+?>
+    </dl>
+<?php
+                    }
+
+                    return true;
+                    break;
+
+                case 'entry_display':
+                    if ($bag->get('scrambles_true_content') && is_array($addData) && isset($addData['no_scramble'])) {
+                        return true;
+                    }
+
+                    if ($this->get_config('version') != PLUGIN_KARMA_VERSION) {
+                        $this->checkScheme();
+                    }
+
+                    // Check whether the cache plugin is used. If so, we need to append our karma-voting output
+                    // to the cached version, since that one is used instead of the 'extended' key later on.
+                    $extended_key = &$this->getFieldReference('extended', $eventData);
+
+                    switch($this->karmaVote) {
+                        case 'nocookie':
+                            // Users with no cookies won't be able to vote.
+                            $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . PLUGIN_KARMA_NOCOOKIE . '</div>';
+
+                        case 'timeout2':
+                            if (!isset($msg)) {
+                                $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . PLUGIN_KARMA_CLOSED . '</div>';
+                            }
+
+                        case 'timeout':
+                            if (!isset($msg)) {
+                                $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . sprintf(PLUGIN_KARMA_TIMEOUT, $this->karmaTimeOut) . '</div>';
+                            }
+
+                        case 'alreadyvoted':
+                            if (!isset($msg)) {
+                                $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . PLUGIN_KARMA_ALREADYVOTED . '</div>';
+                            }
+
+                        case 'invalid1':
+                        case 'invalid2':
+                        case 'invalid':
+                            if (!isset($msg)) {
+                                $msg = '<div class="serendipity_karmaVoting serendipity_karmaError"><a id="karma_vote' . $this->karmaId . '"></a>' . PLUGIN_KARMA_INVALID . '</div>';
+                            }
+
+                            /* OUTPUT MESSAGE */
+                            if ($addData['extended']) {
+                                $eventData[0]['exflag'] = 1;
+                                $extended_keys .= $msg;
+                            } else {
+                                $elements = count($eventData);
+                                // Find the right container to store our message in.
+                                for ($i = 0; $i < $elements; $i++) {
+                                    if ($eventData[$i]['id'] == $this->karmaId) {
+                                        $eventData[$i]['add_footer'] .= $msg;
+                                    }
+                                }
+                            }
+                            break;
+
+                        case 'voted':
+                        default:
+                            $track_clicks  = serendipity_db_bool($this->get_config('visits_active', true));
+                            $track_karma   = serendipity_db_bool($this->get_config('karma_active', true));
+                            $karma_active  = $track_karma;
+
+                            if (!is_array($eventData)) return;
+
+                            $karmatime     = $this->get_config('max_karmatime', 7);
+                            $max_karmatime = $karmatime    * 24 * 60 * 60;
+                            $now           = time();
+
+                            $url = serendipity_currentURL() . '&amp;';
+
+                            $karma = (isset($serendipity['COOKIE']['karmaVote']) ? unserialize($serendipity['COOKIE']['karmaVote']) : array());
+
+                            $link_1 = '<a class="serendipity_karmaVoting_link1" rel="nofollow" href="#" onclick="javascript:location.href=\'%5$sserendipity[karmaVote]=2&amp;serendipity[karmaId]=%1$s#karma_vote%1$s\';" title="' . sprintf(PLUGIN_KARMA_RATE, PLUGIN_KARMA_VOTEPOINT_1) . '">++</a>';
+                            $link_2 = '<a class="serendipity_karmaVoting_link2" rel="nofollow" href="#" onclick="javascript:location.href=\'%5$sserendipity[karmaVote]=1&amp;serendipity[karmaId]=%1$s#karma_vote%1$s\';" title="' . sprintf(PLUGIN_KARMA_RATE, PLUGIN_KARMA_VOTEPOINT_2) . '">+</a>';
+                            $link_3 = '<a class="serendipity_karmaVoting_link3" rel="nofollow" href="#" onclick="javascript:location.href=\'%5$sserendipity[karmaVote]=0&amp;serendipity[karmaId]=%1$s#karma_vote%1$s\';" title="' . sprintf(PLUGIN_KARMA_RATE, PLUGIN_KARMA_VOTEPOINT_3) . '">0</a>';
+                            $link_4 = '<a class="serendipity_karmaVoting_link4" rel="nofollow" href="#" onclick="javascript:location.href=\'%5$sserendipity[karmaVote]=-1&amp;serendipity[karmaId]=%1$s#karma_vote%1$s\';" title="' . sprintf(PLUGIN_KARMA_RATE, PLUGIN_KARMA_VOTEPOINT_4) . '">-</a>';
+                            $link_5 = '<a class="serendipity_karmaVoting_link5" rel="nofollow" href="#" onclick="javascript:location.href=\'%5$sserendipity[karmaVote]=-2&amp;serendipity[karmaId]=%1$s#karma_vote%1$s\';" title="' . sprintf(PLUGIN_KARMA_RATE, PLUGIN_KARMA_VOTEPOINT_5) . '">--</a>';
+
+                            if ($addData['extended'] && $eventData[0]['timestamp'] < ($now - $max_karmatime)) {
+                                $karma_active = false;
+                            }
+
+                            $karma_voting = '<br /><div class="serendipity_karmaVoting"><a id="karma_vote%1$s"></a>'
+                                  . ($karma_active ? PLUGIN_KARMA_VOTETEXT . ' ' . $link_1 . ' | ' . $link_2 . ' | ' . $link_3 . ' | ' . $link_4 . ' | ' . $link_5 . '<br />'
+                                  . PLUGIN_KARMA_CURRENT : '') . ($track_clicks ? PLUGIN_KARMA_VISITSCOUNT : '') . '</div>';
+
+                            $karma_current = '<br /><div class="serendipity_karmaVoting"><a id="karma_vote%1$s"></a>'
+                                . ($karma_active ? '<div class="serendipity_karmaSuccess">' . PLUGIN_KARMA_VOTED . '</div>'
+                                . PLUGIN_KARMA_CURRENT : '') . ($track_clicks ? PLUGIN_KARMA_VISITSCOUNT : '') . '</div>';
+
+                            $karma_timeout = '<br /><div class="serendipity_karmaVoting"><a id="karma_vote%1$s"></a>'
+                                . ($track_karma ? '<div>' . sprintf(PLUGIN_KARMA_CLOSED, $karmatime) . '</div>'
+                                . PLUGIN_KARMA_CURRENT : '') . ($track_clicks ? PLUGIN_KARMA_VISITSCOUNT : '') . '</div>';
+
+                            if ($addData['extended'] || $addData['preview']) {
+                                $entryid = (int)serendipity_db_escape_string($eventData[0]['id']);
+                                if ($track_clicks && !$addData['preview']) {
+                                    $sql = serendipity_db_query('UPDATE ' . $serendipity['dbPrefix'] . 'karma SET visits = visits + 1 WHERE entryid = ' . $entryid, true);
+                                    if (serendipity_db_affected_rows() < 1) {
+                                        serendipity_db_query("INSERT INTO {$serendipity['dbPrefix']}karma (entryid, points, votes, lastvote, visits) VALUES ('$entryid', 0, 0, 0, 1)");
+                                    }
+                                }
+
+                                $q = 'SELECT SUM(votes) AS votes, SUM(points) AS points, SUM(visits) AS visits
+                                        FROM ' . $serendipity['dbPrefix'] . 'karma   AS k
+                                       WHERE k.entryid = ' . $entryid . ' GROUP BY k.entryid LIMIT 1';
+                                $row = serendipity_db_query($q, true);
+
+                                if (empty($row['votes'])) {
+                                    $row['votes'] = 0;
+                                }
+
+                                if (empty($row['points'])) {
+                                    $row['points'] = 0;
+                                }
+
+                                if (empty($row['visits'])) {
+                                    $row['visits'] = 0;
+                                }
+
+                                $eventData[0]['exflag'] = 1;
+                                if (isset($karma[$entryid])) {
+                                    $extended_key .= sprintf($karma_current, $karma[$entryid], $row['points'], $row['votes'], $row['visits'], $url);
+                                } elseif ($eventData[0]['timestamp'] < ($now - $max_karmatime)) {
+                                    $extended_key .= sprintf($karma_timeout, $entryid, $row['points'], $row['votes'], $row['visits'], $url);
+                                } else {
+                                    $extended_key .= sprintf($karma_voting, $entryid, $row['points'], $row['votes'], $row['visits'], $url);
+                                }
+                            } elseif (!serendipity_db_bool($this->get_config('extended_only', false))) {
+                                $elements = count($eventData);
+
+                                // Get all existing entry IDs
+                                $entries  = array();
+                                for ($i = 0; $i < $elements; $i++) {
+                                    $entries[] = (int)$eventData[$i]['id'];
+                                }
+
+                                // Fetch votes for all entry IDs. Store them in an array for later usage.
+                                $q = 'SELECT k.entryid, SUM(votes) AS votes, SUM(points) AS points, SUM(visits) AS visits
+                                        FROM ' . $serendipity['dbPrefix'] . 'karma   AS k
+                                       WHERE k.entryid IN (' . implode(', ', $entries) . ') GROUP BY k.entryid';
+
+                                $sql = serendipity_db_query($q);
+
+                                $rows = array();
+                                if ($sql && is_array($sql)) {
+                                    foreach($sql AS $idx => $row) {
+                                        $rows[$row['entryid']] = array('votes' => $row['votes'], 'points' => $row['points'], 'visits' => $row['visits']);
+                                    }
+                                }
+
+                                // Walk entry array and insert karma voting line.
+                                for ($i = 0; $i < $elements; $i++) {
+                                    $entryid = $eventData[$i]['id'];
+                                    $votes   = (!empty($rows[$entryid]['votes']) ? $rows[$entryid]['votes'] : 0);
+                                    $points  = (!empty($rows[$entryid]['points']) ? $rows[$entryid]['points'] : 0);
+                                    $visits  = (!empty($rows[$entryid]['visits']) ? $rows[$entryid]['visits'] : 0);
+
+                                    if (!isset($eventData[$i]['add_footer'])) {
+                                        $eventData[$i]['add_footer'] = '';
+                                    }
+
+                                    if (isset($karma[$entryid])) {
+                                        $eventData[$i]['add_footer'] .= sprintf($karma_current, $karma[$entryid], $points, $votes, $visits, $url);
+                                    } elseif ($eventData[$i]['timestamp'] < ($now - $max_karmatime)) {
+                                        $eventData[$i]['add_footer'] .= sprintf($karma_timeout, $entryid, $points, $votes, $visits, $url);
+                                    } else {
+                                        $eventData[$i]['add_footer'] .= sprintf($karma_voting, $entryid, $points, $votes, $visits, $url);
+                                    }
+                                }
+                            }
+                    }
+                    return true;
+                    break;
+
+                default:
+                    return false;
+            }
+        } else {
+            return false;
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_livesearch/serendipity_event_livesearch.js b/plugins/serendipity_event_livesearch/serendipity_event_livesearch.js
new file mode 100644 (file)
index 0000000..b4672cc
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+// +----------------------------------------------------------------------+
+// | Copyright (c) 2004 Bitflux GmbH                                      |
+// +----------------------------------------------------------------------+
+// | Licensed under the Apache License, Version 2.0 (the "License");      |
+// | you may not use this file except in compliance with the License.     |
+// | You may obtain a copy of the License at                              |
+// | http://www.apache.org/licenses/LICENSE-2.0                           |
+// | Unless required by applicable law or agreed to in writing, software  |
+// | distributed under the License is distributed on an "AS IS" BASIS,    |
+// | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or      |
+// | implied. See the License for the specific language governing         |
+// | permissions and limitations under the License.                       |
+// +----------------------------------------------------------------------+
+// | Author: Bitflux GmbH <devel@bitflux.ch>                              |
+// +----------------------------------------------------------------------+
+
+*/
+var liveSearchReq = false;
+var t = null;
+var liveSearchLast = "";
+var isIE = false;
+
+// on !IE we only have to initialize it once
+if (window.XMLHttpRequest) {
+    liveSearchReq = new XMLHttpRequest();
+}
+
+function addLoadEvent(func) {
+  var oldonload = window.onload;
+  if (typeof window.onload != 'function') {
+    window.onload = func;
+  } else {
+    window.onload = function() {
+      oldonload();
+      func();
+    }
+  }
+}
+
+function liveSearchInit() {
+    if (navigator.userAgent.indexOf("Safari") > 0) {
+        document.getElementById('serendipityQuickSearchTermField').addEventListener("keydown", liveSearchKeyPress,false);
+        document.getElementById('searchform').addEventListener("submit", liveSearchSubmit,false);
+    } else if (navigator.product == "Gecko") {
+        document.getElementById('serendipityQuickSearchTermField').addEventListener("keypress", liveSearchKeyPress,false);
+        document.getElementById('searchform').addEventListener("submit", liveSearchSubmit,false);
+    } else {
+        document.getElementById('serendipityQuickSearchTermField').attachEvent("onkeydown", liveSearchKeyPress);
+        document.getElementById('searchform').attachEvent("onsubmit", liveSearchSubmit);
+        isIE = true;
+    }
+
+    if (document.getElementById('searchform').setAttribute) {
+        document.getElementById('searchform').setAttribute('autocomplete','off');
+        document.getElementById('serendipityQuickSearchTermField').setAttribute('autocomplete','off');
+    }
+    document.getElementById('serendipityQuickSearchTermField').style.border = '1px solid green';
+}
+
+function liveSearchKeyPress(event) {
+    if (event.keyCode == 40 ) { //KEY DOWN
+        highlight = document.getElementById("LSHighlight");
+        if (!highlight) {
+            highlight = document.getElementById("LSResult").firstChild.firstChild.firstChild;
+        } else {
+            highlight.removeAttribute("id");
+            highlight = highlight.nextSibling;
+        }
+        if (highlight) {
+            highlight.setAttribute("id","LSHighlight");
+        }
+        if (!isIE) { event.preventDefault(); }
+    }
+    //KEY UP
+    else if (event.keyCode == 38 ) {
+        highlight = document.getElementById("LSHighlight");
+        if (!highlight) {
+            highlight = document.getElementById("LSResult").firstChild.firstChild.lastChild;
+        }
+        else {
+            highlight.removeAttribute("id");
+            highlight = highlight.previousSibling;
+        }
+        if (highlight) {
+                highlight.setAttribute("id","LSHighlight");
+        }
+        if (!isIE) { event.preventDefault(); }
+    }
+    //ESC
+    else if (event.keyCode == 27) {
+        highlight = document.getElementById("LSHighlight");
+        if (highlight) {
+            highlight.removeAttribute("id");
+        }
+        document.getElementById("LSResult").style.display = "none";
+    } else {
+        liveSearchStart();
+    }
+}
+function liveSearchStart() {
+    if (t) {
+        window.clearTimeout(t);
+    }
+    t = window.setTimeout("liveSearchDoSearch()",200);
+}
+
+function liveSearchDoSearch() {
+    v = document.getElementById('serendipityQuickSearchTermField').value;
+    if (liveSearchLast != v && v.length > 3) {
+        if (liveSearchReq && liveSearchReq.readyState < 4) {
+            liveSearchReq.abort();
+        }
+
+        if (v == "") {
+            document.getElementById("LSResult").style.display = "none";
+            highlight = document.getElementById("LSHighlight");
+            if (highlight) {
+                highlight.removeAttribute("id");
+            }
+            return false;
+        }
+
+        if (window.XMLHttpRequest) {
+        // branch for IE/Windows ActiveX version
+        } else if (window.ActiveXObject) {
+            liveSearchReq = new ActiveXObject("Microsoft.XMLHTTP");
+        }
+
+        document.getElementById('LSResult').style.display = "block";
+        document.getElementById('LSResult').firstChild.innerHTML = '<div class="serendipity_livesearch_result">' + waittext + '</div>';
+
+        liveSearchReq.onreadystatechange= liveSearchProcessReqChange;
+        liveSearchReq.open("GET", lsbase + "s=" + v);
+        liveSearchLast = v;
+        liveSearchReq.send(null);
+    }
+}
+
+function liveSearchProcessReqChange() {
+
+    if (liveSearchReq.readyState == 4) {
+        var  res = document.getElementById("LSResult");
+        res.style.display = "block";
+        res.firstChild.innerHTML = liveSearchReq.responseText;
+    }
+}
+
+function liveSearchSubmit() {
+    var highlight = document.getElementById("LSHighlight");
+    if (highlight && highlight.firstChild) {
+        document.getElementById('searchform').action = highlight.firstChild.getAttribute("href");
+        return false;
+    } else {
+        return true;
+    }
+}
diff --git a/plugins/serendipity_event_livesearch/serendipity_event_livesearch.php b/plugins/serendipity_event_livesearch/serendipity_event_livesearch.php
new file mode 100644 (file)
index 0000000..a90233b
--- /dev/null
@@ -0,0 +1,174 @@
+<?php # $Id$
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_LIVESEARCH_NAME', 'LiveSearch');
+        @define('PLUGIN_EVENT_LIVESEARCH_DESC', 'Erweitert die Suchfunktion mit einer Live-aktualisierung (JavaScript)');
+        @define('PLUGIN_EVENT_LIVESEARCH_WAIT', 'Suche aktiviert, bitte warten...');
+
+        break;
+
+    case 'en':
+    case 'es':
+    default:
+        @define('PLUGIN_EVENT_LIVESEARCH_NAME', 'Livesearch');
+        @define('PLUGIN_EVENT_LIVESEARCH_DESC', 'Enhances the internal search function by adding live-updates on keypress (JavaScript)');
+        @define('PLUGIN_EVENT_LIVESEARCH_WAIT', 'Wait, sending request...');
+        break;
+}
+
+class serendipity_event_livesearch extends serendipity_event
+{
+    var $title = PLUGIN_EVENT_LIVESEARCH_NAME;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_LIVESEARCH_NAME);
+        $propbag->add('description',   PLUGIN_EVENT_LIVESEARCH_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Christian Stocker, Garvin Hicking');
+        $propbag->add('version',       '1.0');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('event_hooks',    array(
+            'external_plugin'    => true,
+            'frontend_header'    => true,
+            'css'                => true,
+            'quicksearch_plugin' => true
+        ));
+    }
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+    function event_hook($event, &$bag, &$eventData, $addData = null) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+
+        if (isset($hooks[$event])) {
+            switch($event) {
+                case 'css':
+                    if (strpos($eventData, '.serendipity_livesearch_row')) {
+                        // class exists in CSS, so a user has customized it and we don't need default
+                        return true;
+                    }
+?>
+#LSResult {
+    position: absolute;
+    margin-left: 4px;
+    margin-top: 4px;
+}
+
+#LSShadow {
+    position: relative;
+    bottom: 1px;
+    right: 1px;
+    color: inherit;
+    border-right: 2px solid #ccc;
+    border-bottom: 2px solid #ccc;
+}
+
+#LSHighlight {
+    background-color: #80FF80;
+    color: black;
+}
+
+.serendipity_livesearch_row {
+  margin: 0px;
+  line-height: 1.2em;
+  padding-top: 0.2em;
+  padding-bottom: 0.2em;
+  text-indent: -1em;
+  padding-left: 1em;
+  line-height: 1.2em;
+  padding-right: 1em;
+}
+
+.serendipity_livesearch_result {
+    position: relative;
+    bottom: 2px;
+    right: 2px;
+    border: 1px solid black;
+    padding: 2px;
+}
+<?php
+                    break;
+
+                case 'frontend_header':
+                    if (!$serendipity['embed'] || $serendipity['embed'] === 'false' || $serendipity['embed'] === false) {
+                        echo '<script type="text/javascript" src="' . $serendipity['baseURL'] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '') . 'plugin/ls-js"></script>';
+                    }
+                    break;
+
+                case 'quicksearch_plugin':
+                    echo '<script type="text/javascript">
+                    lsbase = "' . $serendipity['baseURL'] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '') . 'plugin/ls' . ($serendipity['rewrite'] == 'none' ? '&' : '?') . '";
+                    waittext = "' . PLUGIN_EVENT_LIVESEARCH_WAIT . '";
+                    addLoadEvent(liveSearchInit);
+                    </script>';
+                    break;
+
+                case 'external_plugin':
+                    $uri_parts = explode('?', str_replace('&amp;', '&', $eventData));
+
+                    // Try to get request parameters from eventData name
+                    if (!empty($uri_parts[1])) {
+                        $reqs = explode('&', $uri_parts[1]);
+                        foreach($reqs AS $id => $req) {
+                            $val = explode('=', $req);
+                            if (empty($_REQUEST[$val[0]])) {
+                                $_REQUEST[$val[0]] = $val[1];
+                            }
+                        }
+                    }
+
+                    $parts     = explode('_', $uri_parts[0]);
+                    if (!empty($parts[1])) {
+                        $param     = (int) $parts[1];
+                    } else {
+                        $param     = null;
+                    }
+
+                    switch($parts[0]) {
+                        case 'ls-js':
+                            header('Content-Type: text/javascript');
+                            echo file_get_contents(S9Y_INCLUDE_PATH . 'plugins/serendipity_event_livesearch/serendipity_event_livesearch.js');
+                            break;
+
+                        case 'ls':
+                            $res = serendipity_searchEntries($_REQUEST['s']);
+
+                            if (is_array($res) && count($res) > 0) {
+                                echo '<?xml version="1.0" encoding="utf-8" ?>';
+                                echo '<div class="serendipity_livesearch_result">';
+                                foreach($res AS $id => $entry) {
+                                    echo '<div class="serendipity_livesearch_row"><a href="' . serendipity_archiveURL($entry['id'], $entry['title'], 'baseURL') . '">' . htmlspecialchars($entry['title']) . '</a></div>';
+                                }
+                                echo '</div>';
+                            }
+
+                            break;
+                    }
+
+                    return true;
+                    break;
+
+                default:
+                    return false;
+                    break;
+            }
+        } else {
+            return false;
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_mailer/lang_ja.inc.php b/plugins/serendipity_event_mailer/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..58d0d4d
--- /dev/null
@@ -0,0 +1,25 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_EVENT_MAILER_NAME', '電子メールでエントリを送信する');
+        @define('PLUGIN_EVENT_MAILER_DESC', '指定のアドレスに電子メールで新しく作られたエントリを送ります。');
+        @define('PLUGIN_EVENT_MAILER_RECIPIENT', 'メール受信者');
+        @define('PLUGIN_EVENT_MAILER_RECIPIENTDESC', 'エントリを送信したい電子メールアドレス (提案: メーリングリスト)');
+        @define('PLUGIN_EVENT_MAILER_LINK', '記事へのリンクをメールしますか?');
+        @define('PLUGIN_EVENT_MAILER_LINKDESC', 'メールに記事へのリンクを含みます。');
+        @define('PLUGIN_EVENT_MAILER_STRIPTAGS', 'HTML を削除しますか?');
+        @define('PLUGIN_EVENT_MAILER_STRIPTAGSDESC', '電子メールから HTML タグを削除します。');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_mailer/serendipity_event_mailer.php b/plugins/serendipity_event_mailer/serendipity_event_mailer.php
new file mode 100644 (file)
index 0000000..45c0690
--- /dev/null
@@ -0,0 +1,134 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_MAILER_NAME', 'Artikel mailen');
+        @define('PLUGIN_EVENT_MAILER_DESC', 'Verschickt jeden neuen Artikel im Blog via E-Mail');
+        @define('PLUGIN_EVENT_MAILER_RECIPIENT', 'Mail-Empfänger');
+        @define('PLUGIN_EVENT_MAILER_RECIPIENTDESC', 'Die E-Mail Adresse an die die Artikel verschickt werden sollen (empfohlen: Eine Mailing-Liste)');
+        @define('PLUGIN_EVENT_MAILER_LINK', 'URL des Artikels mailen?');
+        @define('PLUGIN_EVENT_MAILER_LINKDESC', 'Verschickt die URL des Artikels.');
+        @define('PLUGIN_EVENT_MAILER_STRIPTAGS', 'HTML entfernen?');
+        @define('PLUGIN_EVENT_MAILER_STRIPTAGSDESC', 'Entfernt HTML-Anweisungen aus der Mail.');
+        break;
+
+    case 'en':
+    case 'es':
+    default:
+        @define('PLUGIN_EVENT_MAILER_NAME', 'Send entries via E-Mail');
+        @define('PLUGIN_EVENT_MAILER_DESC', 'Let you send a newly created entry via E-Mail to a specific address');
+        @define('PLUGIN_EVENT_MAILER_RECIPIENT', 'Mail recipient');
+        @define('PLUGIN_EVENT_MAILER_RECIPIENTDESC', 'E-Mail address you want to send the entries to (suggested: a mailing list)');
+        @define('PLUGIN_EVENT_MAILER_LINK', 'Mail link to article?');
+        @define('PLUGIN_EVENT_MAILER_LINKDESC', 'Include a link to the article in the mail.');
+        @define('PLUGIN_EVENT_MAILER_STRIPTAGS', 'Remove HTML?');
+        @define('PLUGIN_EVENT_MAILER_STRIPTAGSDESC', 'Remove HTML-Tags from the mail.');
+        break;
+}
+
+class serendipity_event_mailer extends serendipity_event
+{
+    var $title = PLUGIN_EVENT_MAILER_NAME;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_MAILER_NAME);
+        $propbag->add('description',   PLUGIN_EVENT_MAILER_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Sebastian Nohn, Kristian Köhntopp, Garvin Hicking');
+        $propbag->add('version',       '1.0');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('event_hooks',    array(
+            'backend_publish' => true
+        ));
+
+        $propbag->add('configuration', array('mailto', 'includelink', 'striptags'));
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'mailto':
+                $propbag->add('type',        'string');
+                $propbag->add('name',        PLUGIN_EVENT_MAILER_RECIPIENT);
+                $propbag->add('description', PLUGIN_EVENT_MAILER_RECIPIENTDESC);
+                $propbag->add('default', '');
+                break;
+
+            case 'includelink':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        PLUGIN_EVENT_MAILER_LINK);
+                $propbag->add('description', PLUGIN_EVENT_MAILER_LINKDESC);
+                $propbag->add('default',     'false');
+                break;
+
+            case 'striptags':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        PLUGIN_EVENT_MAILER_STRIPTAGS);
+                $propbag->add('description', PLUGIN_EVENT_MAILER_STRIPTAGSDESC);
+                $propbag->add('default',     'false');
+                break;
+
+            default:
+                break;
+        }
+
+        return true;
+    }
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+    function event_hook($event, &$bag, &$eventData) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+
+        if (isset($hooks[$event])) {
+            switch($event) {
+                case 'backend_publish':
+                    $mail = array(
+                      'to'      => $this->get_config('mailto'),
+                      'subject' => $eventData['title'],
+                      'body'    => $eventData['body'] . $eventData['extended'],
+//                      'from'    => $serendipity['blogTitle'] . ' - ' . $eventData['author'] . ' <' . $serendipity['serendipityEmail'] . '>'
+                      'from'    => $serendipity['serendipityEmail']
+                    );
+
+                    if (serendipity_db_bool($this->get_config('striptags', false)) == true) {
+                        $mail['body'] = strip_tags($mail['body']);
+                    }
+
+                    if (serendipity_db_bool($this->get_config('includelink', false)) == true) {
+                       $mail['body'] = serendipity_archiveURL($eventData['id'], $eventData['title']) . "\n\n" . $mail['body'];
+                    }
+
+                    serendipity_sendMail($mail['to'], $mail['subject'], $mail['body'], $mail['from']);
+                    return true;
+                    break;
+
+                default:
+                    return false;
+                    break;
+            }
+        } else {
+            return false;
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_nl2br/lang_ja.inc.php b/plugins/serendipity_event_nl2br/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..a099e78
--- /dev/null
@@ -0,0 +1,19 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_EVENT_NL2BR_NAME',     'マークアップ: NL2BR');
+        @define('PLUGIN_EVENT_NL2BR_DESC',     '改行を BR タグに変換します。');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_nl2br/serendipity_event_nl2br.php b/plugins/serendipity_event_nl2br/serendipity_event_nl2br.php
new file mode 100644 (file)
index 0000000..dd3fe27
--- /dev/null
@@ -0,0 +1,121 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_NL2BR_NAME',     'Textformatierung: NL2BR');
+        @define('PLUGIN_EVENT_NL2BR_DESC',     'Konvertiert Zeilenumbrüche zu HTML');
+        break;
+
+    case 'en':
+    default:
+        @define('PLUGIN_EVENT_NL2BR_NAME',     'Markup: NL2BR');
+        @define('PLUGIN_EVENT_NL2BR_DESC',     'Convert newlines to BR tags');
+        break;
+}
+
+class serendipity_event_nl2br extends serendipity_event
+{
+    var $title = PLUGIN_EVENT_NL2BR_NAME;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_NL2BR_NAME);
+        $propbag->add('description',   PLUGIN_EVENT_NL2BR_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Serendipity Team');
+        $propbag->add('version',       '1.2');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('cachable_events', array('frontend_display' => true));
+        $propbag->add('event_hooks',   array('frontend_display' => true));
+
+        $this->markup_elements = array(
+            array(
+              'name'     => 'ENTRY_BODY',
+              'element'  => 'body',
+            ),
+            array(
+              'name'     => 'EXTENDED_BODY',
+              'element'  => 'extended',
+            ),
+            array(
+              'name'     => 'COMMENT',
+              'element'  => 'comment',
+            ),
+            array(
+              'name'     => 'HTML_NUGGET',
+              'element'  => 'html_nugget',
+            )
+        );
+
+        $conf_array = array();
+        foreach($this->markup_elements as $element) {
+            $conf_array[] = $element['name'];
+        }
+        $propbag->add('configuration', $conf_array);
+    }
+
+    function install() {
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function uninstall() {
+        serendipity_plugin_api::hook_event('backend_cache_purge', $this->title);
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        $propbag->add('type',        'boolean');
+        $propbag->add('name',        constant($name));
+        $propbag->add('description', sprintf(APPLY_MARKUP_TO, constant($name)));
+        $propbag->add('default', 'true');
+        return true;
+    }
+
+    function event_hook($event, &$bag, &$eventData) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+
+        if (isset($hooks[$event])) {
+            switch($event) {
+              case 'frontend_display':
+
+                foreach ($this->markup_elements as $temp) {
+                    if (serendipity_db_bool($this->get_config($temp['name'], true)) && isset($eventData[$temp['element']]) &&
+                            !$eventData['properties']['ep_no_nl2br']) {
+                        $element = $temp['element'];
+                        $eventData[$element] = nl2br($eventData[$element]);
+                    }
+                }
+                return true;
+                break;
+
+              default:
+                return false;
+            }
+
+        } else {
+            return false;
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/plugins/serendipity_event_s9ymarkup/lang_is.inc.php b/plugins/serendipity_event_s9ymarkup/lang_is.inc.php
new file mode 100644 (file)
index 0000000..bfca5d3
--- /dev/null
@@ -0,0 +1,8 @@
+<?php # $Id$
+
+        @define('PLUGIN_EVENT_S9YMARKUP_NAME', 'Textabreyting: Serendipity');
+        @define('PLUGIN_EVENT_S9YMARKUP_DESC', 'Virkja grunntextabreytingar á texta í færslum');
+        @define('PLUGIN_EVENT_S9YMARKUP_TRANSFORM', 'Að setja texta innan stjarna gerir hann feitletraðan (*orð*), og til að undirstrika setur maður strik niðri á undan og eftir orði (_orð_).');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/plugins/serendipity_event_s9ymarkup/lang_ja.inc.php b/plugins/serendipity_event_s9ymarkup/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..0d045dd
--- /dev/null
@@ -0,0 +1,20 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_EVENT_S9YMARKUP_NAME', 'マークアップ: Serendipity');
+        @define('PLUGIN_EVENT_S9YMARKUP_DESC', 'エントリテキストに適用する基本的な serendipity マークアップ');
+        @define('PLUGIN_EVENT_S9YMARKUP_TRANSFORM', 'アスタリスクで囲んだマークテキストはボールド (*強調文字*)になり、下線は _下線_ になります。');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_s9ymarkup/serendipity_event_s9ymarkup.php b/plugins/serendipity_event_s9ymarkup/serendipity_event_s9ymarkup.php
new file mode 100644 (file)
index 0000000..3166981
--- /dev/null
@@ -0,0 +1,154 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_S9YMARKUP_NAME', 'Textformatierung: Serendipity');
+        @define('PLUGIN_EVENT_S9YMARKUP_DESC', 'Standard Serendipity Textformatierung durchführen');
+        @define('PLUGIN_EVENT_S9YMARKUP_TRANSFORM', 'Umschließende Sterne heben ein Wort hervor (*wort*), per _wort_ kann ein Wort unterstrichen werden.');
+        break;
+
+    case 'en':
+    default:
+        @define('PLUGIN_EVENT_S9YMARKUP_NAME', 'Markup: Serendipity');
+        @define('PLUGIN_EVENT_S9YMARKUP_DESC', 'Apply basic serendipity markup to entry text');
+        @define('PLUGIN_EVENT_S9YMARKUP_TRANSFORM', 'Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.');
+        break;
+}
+
+class serendipity_event_s9ymarkup extends serendipity_event
+{
+    var $title = PLUGIN_EVENT_S9YMARKUP_NAME;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_S9YMARKUP_NAME);
+        $propbag->add('description',   PLUGIN_EVENT_S9YMARKUP_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Serendipity Team');
+        $propbag->add('version',       '1.1');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('cachable_events', array('frontend_display' => true));
+        $propbag->add('event_hooks',   array('frontend_display' => true, 'frontend_comment' => true));
+
+        $this->markup_elements = array(
+            array(
+              'name'     => 'ENTRY_BODY',
+              'element'  => 'body',
+            ),
+            array(
+              'name'     => 'EXTENDED_BODY',
+              'element'  => 'extended',
+            ),
+            array(
+              'name'     => 'COMMENT',
+              'element'  => 'comment',
+            ),
+            array(
+              'name'     => 'HTML_NUGGET',
+              'element'  => 'html_nugget',
+            )
+        );
+
+        $conf_array = array();
+        foreach($this->markup_elements as $element) {
+            $conf_array[] = $element['name'];
+        }
+        $propbag->add('configuration', $conf_array);
+    }
+
+    function install() {
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function uninstall() {
+        serendipity_plugin_api::hook_event('backend_cache_purge', $this->title);
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+
+    function introspect_config_item($name, &$propbag)
+    {
+        $propbag->add('type',        'boolean');
+        $propbag->add('name',        constant($name));
+        $propbag->add('description', sprintf(APPLY_MARKUP_TO, constant($name)));
+        $propbag->add('default', 'true');
+        return true;
+    }
+
+
+    function event_hook($event, &$bag, &$eventData) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+
+        if (isset($hooks[$event])) {
+            switch($event) {
+                case 'frontend_display':
+
+                    foreach ($this->markup_elements as $temp) {
+                        if (serendipity_db_bool($this->get_config($temp['name'], true)) && isset($eventData[$temp['element']])) {
+                            $element = $temp['element'];
+                            $eventData[$element] = $this->_s9y_markup($eventData[$element]);
+                        }
+                    }
+                    return true;
+                    break;
+
+                case 'frontend_comment':
+                    if (serendipity_db_bool($this->get_config('COMMENT', true))) {
+                        echo '<div class="serendipity_commentDirection">' . PLUGIN_EVENT_S9YMARKUP_TRANSFORM . '</div>';
+                    }
+                    return true;
+                    break;
+
+                default:
+                    return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+
+    function _s9y_markup($text) {
+        $text = str_replace('\_', chr(1), $text);
+        $text = preg_replace('/#([[:alnum:]]+?)#/','&\1;',$text);
+        $text = preg_replace('/\b_([\S ]+?)_\b/','<u>\1</u>',$text);
+        $text = str_replace(chr(1), '\_', $text);
+
+        // bold
+        $text = str_replace('\*',chr(1),$text);
+        $text = str_replace('**',chr(2),$text);
+        $text = preg_replace('/(\S)\*(\S)/','\1' . chr(1) . '\2',$text);
+        $text = preg_replace('/\B\*([^*]+)\*\B/','<strong>\1</strong>',$text);
+        $text = str_replace(chr(2),'**',$text);
+        $text = str_replace(chr(1),'\*',$text);
+
+        // $text = preg_replace('/\|([0-9a-fA-F]+?)\|([\S ]+?)\|/','<font color="\1">\2</font>',$text);
+        $text = preg_replace('/\^([[:alnum:]]+?)\^/','<sup>\1</sup>',$text);
+        $text = preg_replace('/\@([[:alnum:]]+?)\@/','<sub>\1</sub>',$text);
+        $text = preg_replace('/([\\\])([*#_|^@%])/', '\2', $text);
+
+        return $text;
+
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/plugins/serendipity_event_searchhighlight/serendipity_event_searchhighlight.php b/plugins/serendipity_event_searchhighlight/serendipity_event_searchhighlight.php
new file mode 100644 (file)
index 0000000..e20a515
--- /dev/null
@@ -0,0 +1,230 @@
+<?php # $Id$
+
+/**********************************/
+/*  Authored by Tom Sommer, 2004  */
+/**********************************/
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_SEARCHHIGHLIGHT_NAME',     'Hebe Suchwörter hervor');
+        @define('PLUGIN_EVENT_SEARCHHIGHLIGHT_DESC',     'Hebt Suchwörter hervor, die ein User in einer Suchmaschine eingegeben hat');
+   break;
+    case 'en':
+    default:
+        @define('PLUGIN_EVENT_SEARCHHIGHLIGHT_NAME',     'Highlight search queries');
+        @define('PLUGIN_EVENT_SEARCHHIGHLIGHT_DESC',     'Highlights queries used in the referring search engine to locate your page');
+        break;
+}
+
+class serendipity_event_searchhighlight extends serendipity_event
+{
+    var $title = PLUGIN_EVENT_SEARCHHIGHLIGHT_NAME;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_SEARCHHIGHLIGHT_NAME);
+        $propbag->add('description',   PLUGIN_EVENT_SEARCHHIGHLIGHT_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Tom Sommer');
+        $propbag->add('version',       '1.1');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('event_hooks',   array('frontend_display' => true, 'css' => true));
+
+        $this->markup_elements = array(
+            array(
+              'name'     => 'ENTRY_BODY',
+              'element'  => 'body',
+            ),
+            array(
+              'name'     => 'EXTENDED_BODY',
+              'element'  => 'extended',
+            ),
+            array(
+              'name'     => 'COMMENT',
+              'element'  => 'comment',
+            ),
+            array(
+              'name'     => 'HTML_NUGGET',
+              'element'  => 'html_nugget',
+            )
+        );
+
+        $conf_array = array();
+        foreach($this->markup_elements as $element) {
+            $conf_array[] = $element['name'];
+        }
+        $propbag->add('configuration', $conf_array);
+    }
+
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+
+    function introspect_config_item($name, &$propbag)
+    {
+        $propbag->add('type',        'boolean');
+        $propbag->add('name',        constant($name));
+        $propbag->add('description', sprintf(APPLY_MARKUP_TO, constant($name)));
+        $propbag->add('default',     'true');
+        return true;
+    }
+
+    function loadConstants() {
+        define('PLUGIN_EVENT_SEARCHHIGHLIGHT_NONE', 0);
+        define('PLUGIN_EVENT_SEARCHHIGHLIGHT_GOOGLE', 1);
+        define('PLUGIN_EVENT_SEARCHHIGHLIGHT_YAHOO', 2);
+        define('PLUGIN_EVENT_SEARCHHIGHLIGHT_LYCOS', 3);
+        define('PLUGIN_EVENT_SEARCHHIGHLIGHT_MSN', 4);
+        define('PLUGIN_EVENT_SEARCHHIGHLIGHT_ALTAVISTA', 5);
+        define('PLUGIN_EVENT_SEARCHHIGHLIGHT_AOL_DE', 6);
+        define('PLUGIN_EVENT_SEARCHHIGHLIGHT_AOL_COM', 7);
+    }
+
+    function getSearchEngine() {
+        $url = parse_url($this->uri);
+
+        /* Patterns should be placed in the order in which they are most likely to occur */
+        if ( preg_match('@^(www\.)?google\.@i', $url['host']) ) {
+            return PLUGIN_EVENT_SEARCHHIGHLIGHT_GOOGLE;
+        }
+        if ( preg_match('@^search\.yahoo\.@i', $url['host']) ) {
+            return PLUGIN_EVENT_SEARCHHIGHLIGHT_YAHOO;
+        }
+        if ( preg_match('@^search\.lycos\.@i', $url['host']) ) {
+            return PLUGIN_EVENT_SEARCHHIGHLIGHT_LYCOS;
+        }
+        if ( preg_match('@^search\.msn\.@i', $url['host']) ) {
+            return PLUGIN_EVENT_SEARCHHIGHLIGHT_MSN;
+        }
+        if ( preg_match('@^(www\.)?altavista\.@i', $url['host']) ) {
+            return PLUGIN_EVENT_SEARCHHIGHLIGHT_ALTAVISTA;
+        }
+        if ( preg_match('@^suche\.aol\.de@i', $url['host']) ) {
+            return PLUGIN_EVENT_SEARCHHIGHLIGHT_AOL_DE;
+        }
+        if ( preg_match('@^search\.aol\.com@i', $url['host']) ) {
+            return PLUGIN_EVENT_SEARCHHIGHLIGHT_AOL_COM;
+        }
+
+
+
+        return false;
+    }
+
+    function getQuery() {
+        if ( empty($this->uri) ) {
+            return false;
+        }
+
+        $this->loadConstants();
+        $url = parse_url($this->uri);
+        parse_str($url['query'], $pStr);
+
+        switch ( $this->getSearchEngine() ) {
+            case PLUGIN_EVENT_SEARCHHIGHLIGHT_GOOGLE :
+                $query = $pStr['q'];
+                break;
+
+            case PLUGIN_EVENT_SEARCHHIGHLIGHT_YAHOO :
+                $query = $pStr['p'];
+                break;
+
+            case PLUGIN_EVENT_SEARCHHIGHLIGHT_LYCOS :
+                $query = $pStr['query'];
+                break;
+
+            case PLUGIN_EVENT_SEARCHHIGHLIGHT_MSN :
+                $query = $pStr['q'];
+                break;
+
+            case PLUGIN_EVENT_SEARCHHIGHLIGHT_ALTAVISTA :
+                $query = $pStr['q'];
+                break;
+
+            case PLUGIN_EVENT_SEARCHHIGHLIGHT_AOL_DE :
+                $query = $pStr['q'];
+                break;
+
+            case PLUGIN_EVENT_SEARCHHIGHLIGHT_AOL_COM :
+                $query = $pStr['query'];
+                break;
+
+            default:
+                return false;
+        }
+
+        /* Clean the query */
+        $query = trim($query);
+        $query = preg_replace('/(\"|\')/i', '', $query);
+
+        /* Split by search engine chars or spaces */
+        $words = preg_split('/[\s\,\+\.\-\/\=]+/', $query);
+
+        /* Strip search engine keywords or common words we don't bother to highlight */
+        $words = array_diff($words, array('AND', 'OR', 'FROM', 'IN'));
+
+        return $words;
+    }
+
+
+    function event_hook($event, &$bag, &$eventData) {
+        global $serendipity;
+
+        $this->uri = $_SERVER['HTTP_REFERER'];
+        $hooks = &$bag->get('event_hooks');
+
+        if (!isset($hooks[$event])) {
+            return false;
+        }
+
+        if ( $event == 'frontend_display' ) {
+            if ( ($queries = $this->getQuery()) === false ) {
+                return;
+            }
+
+            foreach ($this->markup_elements as $temp) {
+                if ( ! (serendipity_db_bool($this->get_config($temp['name'])) && isset($eventData[$temp['element']])) ) {
+                    continue;
+                }
+
+                $element = &$eventData[$temp['element']];
+
+                foreach ( $queries as $word ) {
+                    /* If the data contains HTML tags, we have to be careful not to break URIs and use a more complex preg */
+                    if ( preg_match('/\<.+\>/', $element) ) {
+                        $_pattern =  '/(?!<.*?)(\b'. preg_quote($word, '/') .'\b)(?![^<>]*?>)/im';
+                    } else {
+                        $_pattern = '/(\b'. preg_quote($word, '/') .'\b)/im';
+                    }
+                    $element = preg_replace($_pattern, '<span class="serendipity_searchQuery">$1</span>', $element);
+                } // end foreach
+            } // end foreach
+            return;
+        } // end if
+
+
+        if ( $event == 'css' ) {
+            /* If the user hasn't added a CSS Class called serendipity_searchQuery, we add a pretty one for him */
+            if ( strstr($eventData, '.serendipity_searchQuery') === false ) {
+                $eventData .= "\n";
+                $eventData .= '.serendipity_searchQuery {' . "\n";
+                $eventData .= '    background-color: #D81F2A;' . "\n";
+                $eventData .= '    color: #FFFFFF;' . "\n";
+                $eventData .= '}' . "\n";
+            }
+            return;
+        }
+
+    } // end function
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/plugins/serendipity_event_spamblock/36daysago.ttf b/plugins/serendipity_event_spamblock/36daysago.ttf
new file mode 100644 (file)
index 0000000..8a2baa2
Binary files /dev/null and b/plugins/serendipity_event_spamblock/36daysago.ttf differ
diff --git a/plugins/serendipity_event_spamblock/36daysago.txt b/plugins/serendipity_event_spamblock/36daysago.txt
new file mode 100644 (file)
index 0000000..01577ef
--- /dev/null
@@ -0,0 +1,85 @@
+__________________________________
+36 days ago  Created by Brian Kent
+¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
+Thanks for Downloading 36 days ago.
+
+-36 days ago
+-36 days ago Thick
+
+These fonts are best used/viewed with Kerning ON
+
+
+There are some alternative extra characters included in this font.
+
+[KEY]
+EXTRA CHARACTER = ACTUAL CHARACTER = ALT# CODE
+
+J = È = ALT+0200
+f = É = ALT+0201
+i = Ê = ALT+0202
+i = Ë = ALT+0203
+j = Ì = ALT+0204
+j = Í = ALT+0205
+l = Î = ALT+0206
+l = Ï = ALT+0207
+t = Ð = ALT+0208
+7 = Ñ = ALT+0209
+
+
+To type the extra characters, Press and Hold the ALT key, then
+on the Number Pad type in the 4 numbers.  When you release the
+ALT key the character will appear.
+
+
+
+If you have any questions or comments, you can e-mail me at
+kentpw@norwich.net
+
+You can visit my Homepage <ÆNIGMA GAMES & FONTS> at
+http://www.aenigmafonts.com/
+
+________________
+INSTALLING FONTS
+¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
+  There's a couple of ways to install Fonts. The 'easy' way to
+install fonts is to just Unzip/place the font file [.ttf] into your
+Windows\Fonts directory (I always use this method). If you're unable
+to do it the 'easy' way, then try to do it this way (for Windows
+95/98/NT):
+
+1] Unzip the Font(s) to a folder (or somewhere, just remember where
+you unzipped it) on your Computer.
+
+2] Next, click on the START button, then select SETTINGS then
+CONTROL PANEL.
+
+3] When the Control Panel Window pops up, Double Click on FONTS.
+
+4] When the FONTS window pops up, select File then Install New Font...
+
+5] A Add Fonts window will pop up, just go to the folder that you
+unzipped the Font(s) to, select the Font(s) and then click on OK.
+Now the Font(s) are installed.
+
+  Now you can use the Font(s) in programs that utilize Fonts.  Make
+sure that you install the font(s) first, then open up your apps
+(so the app will recognize the font).    Sometimes you'll have to
+wait until you computer 'auto-refreshes' for programs to recognize
+fonts (Windows is sometimes slow to do that).  You can refresh your
+computer quicker by going into Windows Explorer -or- My Computer and
+press F5 (or in the menubar select VIEW then REFRESH).
+
+
+__________
+DISCLAIMER
+¯¯¯¯¯¯¯¯¯¯
+-The font(s) in this zip file were created by me (Brian Kent).  All
+of my Fonts are Freeware, you can use them any way you want to
+(Personal use, Commercial use, or whatever).
+
+-If you have a Font related site and would like to offer my fonts on
+your site, go right ahead. All I ask is that you keep this text file
+intact with the Font.
+
+-You may not Sell or Distribute my Fonts for profit or alter them in
+any way without asking me first.  [e-mail -  kentpw@norwich.net]
diff --git a/plugins/serendipity_event_spamblock/Vera.ttf b/plugins/serendipity_event_spamblock/Vera.ttf
new file mode 100644 (file)
index 0000000..35b438e
Binary files /dev/null and b/plugins/serendipity_event_spamblock/Vera.ttf differ
diff --git a/plugins/serendipity_event_spamblock/VeraSe.ttf b/plugins/serendipity_event_spamblock/VeraSe.ttf
new file mode 100644 (file)
index 0000000..33a15b2
Binary files /dev/null and b/plugins/serendipity_event_spamblock/VeraSe.ttf differ
diff --git a/plugins/serendipity_event_spamblock/captcha_2.png b/plugins/serendipity_event_spamblock/captcha_2.png
new file mode 100644 (file)
index 0000000..98bd465
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_2.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_3.png b/plugins/serendipity_event_spamblock/captcha_3.png
new file mode 100644 (file)
index 0000000..4503e1e
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_3.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_4.png b/plugins/serendipity_event_spamblock/captcha_4.png
new file mode 100644 (file)
index 0000000..6e724bd
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_4.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_7.png b/plugins/serendipity_event_spamblock/captcha_7.png
new file mode 100644 (file)
index 0000000..dd19270
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_7.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_9.png b/plugins/serendipity_event_spamblock/captcha_9.png
new file mode 100644 (file)
index 0000000..f128417
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_9.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_a.png b/plugins/serendipity_event_spamblock/captcha_a.png
new file mode 100644 (file)
index 0000000..9e7d32d
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_a.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_b.png b/plugins/serendipity_event_spamblock/captcha_b.png
new file mode 100644 (file)
index 0000000..c60aff7
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_b.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_c.png b/plugins/serendipity_event_spamblock/captcha_c.png
new file mode 100644 (file)
index 0000000..ce33590
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_c.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_d.png b/plugins/serendipity_event_spamblock/captcha_d.png
new file mode 100644 (file)
index 0000000..dc755ef
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_d.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_e.png b/plugins/serendipity_event_spamblock/captcha_e.png
new file mode 100644 (file)
index 0000000..b98e2f3
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_e.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_f.png b/plugins/serendipity_event_spamblock/captcha_f.png
new file mode 100644 (file)
index 0000000..8facab4
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_f.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_h.png b/plugins/serendipity_event_spamblock/captcha_h.png
new file mode 100644 (file)
index 0000000..560d05e
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_h.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_j.png b/plugins/serendipity_event_spamblock/captcha_j.png
new file mode 100644 (file)
index 0000000..d6afa82
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_j.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_k.png b/plugins/serendipity_event_spamblock/captcha_k.png
new file mode 100644 (file)
index 0000000..b9d738a
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_k.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_l.png b/plugins/serendipity_event_spamblock/captcha_l.png
new file mode 100644 (file)
index 0000000..d83e19b
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_l.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_m.png b/plugins/serendipity_event_spamblock/captcha_m.png
new file mode 100644 (file)
index 0000000..f37a249
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_m.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_n.png b/plugins/serendipity_event_spamblock/captcha_n.png
new file mode 100644 (file)
index 0000000..d01be88
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_n.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_p.png b/plugins/serendipity_event_spamblock/captcha_p.png
new file mode 100644 (file)
index 0000000..bba7343
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_p.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_q.png b/plugins/serendipity_event_spamblock/captcha_q.png
new file mode 100644 (file)
index 0000000..2eb0822
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_q.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_r.png b/plugins/serendipity_event_spamblock/captcha_r.png
new file mode 100644 (file)
index 0000000..6d2ca62
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_r.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_t.png b/plugins/serendipity_event_spamblock/captcha_t.png
new file mode 100644 (file)
index 0000000..9817928
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_t.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_u.png b/plugins/serendipity_event_spamblock/captcha_u.png
new file mode 100644 (file)
index 0000000..c5d54ce
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_u.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_v.png b/plugins/serendipity_event_spamblock/captcha_v.png
new file mode 100644 (file)
index 0000000..6c4ab86
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_v.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_w.png b/plugins/serendipity_event_spamblock/captcha_w.png
new file mode 100644 (file)
index 0000000..07457b0
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_w.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_x.png b/plugins/serendipity_event_spamblock/captcha_x.png
new file mode 100644 (file)
index 0000000..5068200
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_x.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_y.png b/plugins/serendipity_event_spamblock/captcha_y.png
new file mode 100644 (file)
index 0000000..4909ed0
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_y.png differ
diff --git a/plugins/serendipity_event_spamblock/captcha_z.png b/plugins/serendipity_event_spamblock/captcha_z.png
new file mode 100644 (file)
index 0000000..adec225
Binary files /dev/null and b/plugins/serendipity_event_spamblock/captcha_z.png differ
diff --git a/plugins/serendipity_event_spamblock/chumbly.ttf b/plugins/serendipity_event_spamblock/chumbly.ttf
new file mode 100644 (file)
index 0000000..5774c55
Binary files /dev/null and b/plugins/serendipity_event_spamblock/chumbly.ttf differ
diff --git a/plugins/serendipity_event_spamblock/chumbly.txt b/plugins/serendipity_event_spamblock/chumbly.txt
new file mode 100644 (file)
index 0000000..a8bd1fc
--- /dev/null
@@ -0,0 +1,57 @@
+______________________________
+Chumbly  Created by Brian Kent
+¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
+Thanks for Downloading Chumbly.
+
+
+If you have any questions or comments, you can e-mail me at
+kentpw@norwich.net
+
+You can visit my Webpage <ÆNIGMA GAMES & FONTS> at
+http://www.aenigmafonts.com/
+
+________________
+INSTALLING FONTS
+¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
+  There's a couple of ways to install Fonts. The 'easy' way to
+install fonts is to just Unzip/place the font file [.ttf] into your
+Windows\Fonts directory (I always use this method). If you're unable
+to do it the 'easy' way, then try to do it this way (for Windows
+95/98/NT):
+
+1] Unzip the Font(s) to a folder (or somewhere, just remember where
+you unzipped it) on your Computer.
+
+2] Next, click on the START button, then select SETTINGS then
+CONTROL PANEL.
+
+3] When the Control Panel Window pops up, Double Click on FONTS.
+
+4] When the FONTS window pops up, select File then Install New Font...
+
+5] A Add Fonts window will pop up, just go to the folder that you
+unzipped the Font(s) to, select the Font(s) and then click on OK.
+Now the Font(s) are installed.
+
+  Now you can use the Font(s) in programs that utilize Fonts.  Make
+sure that you install the font(s) first, then open up your apps
+(so the app will recognize the font).    Sometimes you'll have to
+wait until your computer 'auto-refreshes' for programs to recognize
+fonts (Windows is sometimes slow to do that).  You can refresh your
+computer quicker by going into Windows Explorer -or- My Computer and
+press F5 (or in the menubar select VIEW then REFRESH).
+
+
+__________
+DISCLAIMER
+¯¯¯¯¯¯¯¯¯¯
+-The font(s) in this zip file were created by me (Brian Kent).  All
+of my Fonts are Freeware, you can use them any way you want to
+(Personal use, Commercial use, or whatever).
+
+-If you have a Font related site and would like to offer my fonts on
+your site, go right ahead. All I ask is that you keep this text file
+intact with the Font.
+
+-You may not Sell or Distribute my Fonts for profit or alter them in
+any way without asking me first.  [e-mail -  kentpw@norwich.net]
diff --git a/plugins/serendipity_event_spamblock/lang_ja.inc.php b/plugins/serendipity_event_spamblock/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..d34cc50
--- /dev/null
@@ -0,0 +1,93 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_TITLE', 'スパムプロテクター');
+        @define('PLUGIN_EVENT_SPAMBLOCK_DESC', 'コメントスパムを防止するさまざまな方法です。');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY', 'スパム防止: 無効なメッセージです。');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_IP', 'スパム防止: コメントした直後にコメントすることはできません。');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_RBL', 'スパム防止: あなたの投稿したコンピューターの IP アドレスはオープンリレーとして一覧化されています。');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_SURBL', 'スパム防止: コメントの URL はSURBL に URL 一覧化されています。');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_KILLSWITCH', 'このブログは「緊急コメント遮断モード」です。別の機会に来てください。');
+        @define('PLUGIN_EVENT_SPAMBLOCK_BODYCLONE', '複製コメントを許可しない');
+        @define('PLUGIN_EVENT_SPAMBLOCK_BODYCLONE_DESC', 'ユーザーが既に送信したコメントと同じ内容のコメントを送信することを許可しません。');
+        @define('PLUGIN_EVENT_SPAMBLOCK_KILLSWITCH', '緊急時のコメント遮断する');
+        @define('PLUGIN_EVENT_SPAMBLOCK_KILLSWITCH_DESC', 'Temporarily disable comments for all entries. Useful if your blog is under spam attack.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_IPFLOOD', 'IP ブロックの間隔');
+        @define('PLUGIN_EVENT_SPAMBLOCK_IPFLOOD_DESC', 'Only allow an IP to submit a comment every n minutes. Useful to prevent comment floods.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_RBL', 'RBL 一覧化されたホストからのコメントを拒否する');
+        @define('PLUGIN_EVENT_SPAMBLOCK_RBL_DESC', 'Enabling this setting will reject comments made from hosts which are listed in RBLs. Pay attention that this may affect proxy-users or dial-up users.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_SURBL', 'SURBL 一覧化ホストが含まれたコメントを拒否する');
+        @define('PLUGIN_EVENT_SPAMBLOCK_SURBL_DESC', 'Reject comments that containt SURBL-listed hosts');
+        @define('PLUGIN_EVENT_SPAMBLOCK_RBLLIST', 'どの RBL に連絡を受けるか');
+        @define('PLUGIN_EVENT_SPAMBLOCK_RBLLIST_DESC', '上に基づいたコメントブロックの RBL 一覧の提供を受けます。動的なホストのはリストを回避します。');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS', 'Captchas を有効にする');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_DESC', 'Will force the user to input a random string displayed in a specially crafted image. This will disallow automatted submits to your blog. Please remember that people with decreased vision may find it hard to read those captchas.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC', 'To prevent automatted Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Only if the strings match, your comment will be submitted. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC2', '入力ボックスにここに見える文字列を入力してください!');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC3', '上のスパム予防画像から文字列を入力してください: ');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_CAPTCHAS', 'You did not enter the correct string displayed in the spam-prevention image box. Please look at the image and enter the values displayed there.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_NOTTF', 'Captchas はサーバーで無効化されています。PHP 向けに GD ライブラリと freetype ライブラリがコンパイルされていることと、TTF ファイルがディレクトリに存在している必要があります。');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_TTL', '何日経過したら captcha を強制しますか');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_TTL_DESC', 'Captchas can be enforced depending on the age of your articles. Enter the amount of days after which entering a correct captcha is necessary. If set to 0, captchas will always be used.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FORCEMODERATION', '何日経過したらモデレートを強制しますか');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FORCEMODERATION_DESC', 'You can automatically set all comments for entries to be moderated. Enter the age of an entry in days, after which it should be auto-moderated. 0 means no auto-moderation.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LINKS_MODERATE', 'How many links before a comment gets moderated');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LINKS_MODERATE_DESC', 'When a comment reaches a certain amount of links, that comment can be set to be moderated. 0 means that no link-checking is done.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LINKS_REJECT', 'How many links before a comment gets rejected');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LINKS_REJECT_DESC', 'When a comment reaches a certain amount of links, that comment can be set to be moderated. 0 means that no link-checking is done.');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_NOTICE_MODERATION', 'Because of some conditions, your comment has been marked to require moderation by the owner of this blog.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHA_COLOR', 'captcha の背景色');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHA_COLOR_DESC', 'RGB 値を入力します: 0,255,255');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGFILE', 'ログファイルの位置');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGFILE_DESC', 'Information about rejected/moderated posts can be written to a logfile. Set this to an empty string if you want to disable logging.');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_KILLSWITCH', 'コメント緊急バリケード');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_BODYCLONE', '複製コメント');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_IPFLOOD', 'IP ブロック');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_RBL', 'RBL ブロック');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_SURBL', 'SURBL ブロック');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_CAPTCHAS', '無効な captcha (Entered: %s, Expected: %s)');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_FORCEMODERATION', 'X 日後は自動モデレートする');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_LINKS_REJECT', 'リンクが多すぎます。');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_LINKS_MODERATE', 'リンクが多すぎます。');
+        @define('PLUGIN_EVENT_SPAMBLOCK_HIDE_EMAIL', 'コメントしたユーザーの電子メールアドレスを隠す');
+        @define('PLUGIN_EVENT_SPAMBLOCK_HIDE_EMAIL_DESC', 'コメントユーザーの電子メールアドレスを表示しなくなるでしょう。');
+        @define('PLUGIN_EVENT_SPAMBLOCK_HIDE_EMAIL_NOTICE', 'E-Mail addresses will not be displayed and only used for E-Mail notifications');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGTYPE', 'ログ記録方法を選択する');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_DESC', 'Logging of rejected comments can be done in Database or to a plaintext file');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_FILE', 'ファイル (下の「ログファイル」オプションを参照)');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_DB', 'データベース');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_NONE', 'ログ記録しない');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_API_COMMENTS', 'API によってコメントを作成する方法');
+        @define('PLUGIN_EVENT_SPAMBLOCK_API_COMMENTS_DESC', 'This affects the moderation of comments made via API calls (Trackbacks, WFW:commentAPI comments). If set to "moderate", all those comments always need to be approved first. If set to "reject", the are completely disallowed. If set to "none", the comments will be treated as usual comments.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_API_MODERATE', 'モデレート');
+        @define('PLUGIN_EVENT_SPAMBLOCK_API_REJECT', '拒否');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_API', '(トラックバックに似た)API でのコメント作成を許可しません');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_ACTIVATE', '単語フィルターを有効にする');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_ACTIVATE_DESC', 'Searches comments for certain strings and marks them as spam.');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_URLS', 'URL の単語フィルター');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_URLS_DESC', '正規表現が許可されており、セミコロン(;)で文字列を区切ります。');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_AUTHORS', '著者名の単語フィルター');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_AUTHORS_DESC', '正規表現が許可されており、セミコロン(;)で文字列を区切ります。');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_spamblock/serendipity_event_spamblock.php b/plugins/serendipity_event_spamblock/serendipity_event_spamblock.php
new file mode 100644 (file)
index 0000000..b860055
--- /dev/null
@@ -0,0 +1,858 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+/* BC - TODO: Remove for 0.8 final */
+if (!function_exists('serendipity_serverOffsetHour')) {
+    function serendipity_serverOffsetHour() {
+        return time();
+    }
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_SPAMBLOCK_TITLE', 'Spamschutz');
+        @define('PLUGIN_EVENT_SPAMBLOCK_DESC', 'Mehrere Varianten um Kommentarspam einzudämmen');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY', 'Spamschutz: Ungültiger Kommentar');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_IP', 'Spamschutz: Ein weiterer Kommentar kann nicht so schnell übermittelt werden.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_RBL', 'Spamschutz: Ihre IP ist als Open Relay geführt, daher wird Ihr Kommentar abgewiesen.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_SURBL', 'Spamschutz: Ihre Nachricht enthält eine URL, die als SPAM geführt wird, daher wird Ihr Kommentar abgewiesen.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_KILLSWITCH', 'Dieses Blog ist im "Notfall Kommentar"-Modus. Bitte kommen Sie später wieder.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_BODYCLONE', 'Keine doppelten Kommentare erlauben');
+        @define('PLUGIN_EVENT_SPAMBLOCK_BODYCLONE_DESC', 'Verbietet Benutzern ein Kommentar zu übermitteln, was gleichlautend bereits besteht.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_KILLSWITCH', 'Notfall-Blockade von Kommentaren');
+        @define('PLUGIN_EVENT_SPAMBLOCK_KILLSWITCH_DESC', 'Übergangsweise Kommentare zu allen Einträgen verbieten. Nützlich, wenn das Blog unter andauerndem Spam-Beschuss leidet.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_IPFLOOD', 'IP-Block Intervall');
+        @define('PLUGIN_EVENT_SPAMBLOCK_IPFLOOD_DESC', 'Schränkt die Anzahl an Kommentare pro IP ein, indem nur alle X Minuten ein Kommentar erlaubt wird. Hilfreich um Spamfluten derselben IP abzuwehren.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_RBL', 'Kommentare abweisen, die von geblacklisteten IPs stammen');
+        @define('PLUGIN_EVENT_SPAMBLOCK_RBL_DESC', 'Wird diese Option aktiviert, werden Kommentare abgewiesen die von IPs stammen, die in einer RBL/Blacklist geführt werden. Die Aktivierung hiervon kann Dial-Up oder Proxy-User betreffen!');
+        @define('PLUGIN_EVENT_SPAMBLOCK_SURBL', 'Kommentare abweisen, die als SPAM gelistete URLs enthalten');
+        @define('PLUGIN_EVENT_SPAMBLOCK_SURBL_DESC', 'Wird diese Option aktiviert, werden Kommentare abgewiesen die als SPAM geblacklistet sind.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_RBLLIST', 'Welche RBLs sollen verwendet werden');
+        @define('PLUGIN_EVENT_SPAMBLOCK_RBLLIST_DESC', 'Eine Liste von zu verwendenden RBLs. Listen mit dynamischen Hosts sollten vermieden werden.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS', 'Captchas aktivieren');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_DESC', 'Erfordert die Eingabe eines zufälligen Buchstabenfolge vom Benutzer, damit ein Kommentar angenommen wird. Diese Eingabe kann von Spambots nicht getätigt werden und verhindert so automatische Kommentare. Jedoch können behinderte oder blinde Personen mit der Darstellung solcher Eingabegrafiken Probleme haben.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC', 'Um maschinelle und automatische Übertragung von Spamkommentaren zu verhinden, bitte die Zeichenfolge im dargestellten Bild in der Eingabemaske eintragen. Nur wenn die Zeichenfolge richtig eingegeben wurde, kann der Kommentar angenommen werden. Bitte beachten Sie, dass Ihr Browser Cookies unterstützen muss um dieses Verfahren anzuwenden. ');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC2', 'Bitte die dargestellte Zeichenfolge in die Eingabemaske eintragen!');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC3', 'Hier die Zeichenfolge der Spamschutz-Grafik eintragen: ');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_CAPTCHAS', 'Sie haben nicht die richtige Spamschutz-Zeichenfolge eingetragen, die in der Grafik dargestellt wurde. Bitte gucken Sie sich dieses Bild erneut an und tragen die korrekte Zeichenfolge ein.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_NOTTF', 'Captchas können auf Ihrem Server nicht dargestellt werden. Sie benötigen GDLib und die freetype Bibliotheken, sowie die richtigen .TTF Dateien.');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_TTL', 'Captchas nach wievielen Tagen erzwingen');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_TTL_DESC', 'Captchas können abhängig vom Alter des Artikels eingeblendet werden. Tragen Sie das Minimalalter eines Artikels in Tagen ein, ab dem Captchas erforderlich werden sollen. Falls auf 0 gesetzt, sind Captchas immer erforderlich.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FORCEMODERATION', 'Kommentarmoderation nach wievielen Tagen erzwingen');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FORCEMODERATION_DESC', 'Alle Kommentare zu einem Artikel können abhängig vom Alter des Artikels automatisch moderiert werden. Tragen Sie hier das Minimalalter eines Artikels in Tagen ein, ab dem jeder Kommentar erst nach Ihrer Moderation dargestellt wird.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LINKS_MODERATE', 'Erforderliche Anzahl an Links für Moderation');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LINKS_MODERATE_DESC', 'Wenn in einem Kommentar eine bestimmte Anzahl an Links vorhanden ist, kann der Kommentar automatisch moderiert werden. Falls auf 0 gesetzt, wird diese Linkprüfung nicht vorgenommen.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LINKS_REJECT', 'Erforderliche Anzahl an Links für Abweisung');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LINKS_REJECT_DESC', 'Wenn in einem Kommentar eine bestimmte Anzahl an Links vorhanden ist, kann der Kommentar automatisch abgelehnt werden. Falls auf 0 gesetzt, wird diese Linkprüfung nicht vorgenommen.');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_NOTICE_MODERATION', 'Aufgrund einiger Bedingungen wird der Kommentar moderiert und erst nach Bestätigung des Blog-Eigentümers dargestellt.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHA_COLOR', 'Hintergrundfarbe des Captchas');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHA_COLOR_DESC', 'RGB Werte eingeben: 0,255,255');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGFILE', 'Speicherplatz für das Logfile');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGFILE_DESC', 'Einige Informationen über die Abweisung/Moderation von Kommentaren kann in ein Logfile geschrieben werden. Wenn diese Option auf einen leeren Wert gesetzt wird, findet keine Protokollierung statt.');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_KILLSWITCH', 'Notfall-Blockade');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_BODYCLONE', 'Doppelter Kommentar');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_IPFLOOD', 'IP-Block');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_RBL', 'RBL-Block');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_CAPTCHAS', 'Captcha ungültig (Eingegeben: %s, Erwartet: %s)');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_FORCEMODERATION', 'Moderation nach X Tagen');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_LINKS_REJECT', 'Zu viele Links');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_LINKS_MODERATE', 'Zu viele Links');
+        @define('PLUGIN_EVENT_SPAMBLOCK_HIDE_EMAIL', 'E-Mail-Adressen bei Kommentatoren verstecken');
+        @define('PLUGIN_EVENT_SPAMBLOCK_HIDE_EMAIL_DESC', 'Zeigt in den Kommentaren keine E-Mail Adressen der jeweiligen Kommentatoren an');
+        @define('PLUGIN_EVENT_SPAMBLOCK_HIDE_EMAIL_NOTICE', 'Die angegebene E-Mail Adressse wird nicht dargestellt, sondern nur für evtl. Benachrichtigungen verwendet');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGTYPE', 'Protokollierung von fehlgeschlagenen Kommentaren');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_DESC', 'Die Protokollierung von fehlgeschlagenen Kommentaren und deren Gründen kann auf mehrere Arten durchgeführt werden.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_FILE', 'Einfache Datei (siehe Option "Logfile")');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_DB', 'Datenbank');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_NONE', 'Keine Protokollierung');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_API_COMMENTS', 'Behandlung von per API übermittelten Kommentaren');
+        @define('PLUGIN_EVENT_SPAMBLOCK_API_COMMENTS_DESC', 'Diese Einstellung bestimmt, wie per API abgegebene Kommentare (Trackbacks, wfw:commentApi) behandelt werden. Falls diese Einstellung auf "moderieren" gestellt ist, müssen alle solche Kommentare immer bestätigt werden. Falls auf "abweisen" gestellt, werden solche Kommentare global nicht erlaubt. Bei der Einstellung "keine" werden solche Kommentare wie andere behandelt.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_API_MODERATE', 'moderieren');
+        @define('PLUGIN_EVENT_SPAMBLOCK_API_REJECT', 'abweisen');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_API', 'Keine API-erstellten Kommentare (u.a. Trackbacks) erlaubt');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_ACTIVATE', 'Wortfilter aktivieren');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_ACTIVATE_DESC', 'Durchsucht Kommentare nach speziellen Zeichenketten und markiert diese als Spam.');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_URLS', 'Wortfilter für URLs');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_URLS_DESC', 'Reguläre Ausdrücke erlaubt, Zeichenkennten durch Semikolon (;) trennen.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_AUTHORS', 'Wortfilter für Autorennamen');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_AUTHORS_DESC', 'Reguläre Ausdrücke erlaubt, Zeichenkennten durch Semikolon (;) trennen.');
+        break;
+
+    default:
+        @define('PLUGIN_EVENT_SPAMBLOCK_TITLE', 'Spam Protector');
+        @define('PLUGIN_EVENT_SPAMBLOCK_DESC', 'A variety of methods to prevent comment spam');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY', 'Spam Prevention: Invalid message.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_IP', 'Spam Prevention: You cannot post a comment so soon after submitting another one.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_RBL', 'Spam Prevention: The IP of the computer you are posting from, is listed as an open relay.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_SURBL', 'Spam Prevention: Your comment contains an URL listed in SURBL.');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_KILLSWITCH', 'This blog is in "Emergency Comment Blockage Mode", please come back another time');
+        @define('PLUGIN_EVENT_SPAMBLOCK_BODYCLONE', 'Do not allow duplicate comments');
+        @define('PLUGIN_EVENT_SPAMBLOCK_BODYCLONE_DESC', 'Do not allow users to submit a comment which contains the same body as an already submitted comment');
+        @define('PLUGIN_EVENT_SPAMBLOCK_KILLSWITCH', 'Emergency comment shutdown');
+        @define('PLUGIN_EVENT_SPAMBLOCK_KILLSWITCH_DESC', 'Temporarily disable comments for all entries. Useful if your blog is under spam attack.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_IPFLOOD', 'IP block interval');
+        @define('PLUGIN_EVENT_SPAMBLOCK_IPFLOOD_DESC', 'Only allow an IP to submit a comment every n minutes. Useful to prevent comment floods.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_RBL', 'Reject comments from RBL-listed hosts');
+        @define('PLUGIN_EVENT_SPAMBLOCK_RBL_DESC', 'Enabling this setting will reject comments made from hosts which are listed in RBLs. Pay attention that this may affect proxy-users or dial-up users.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_SURBL', 'Reject comments that containt SURBL-listed hosts');
+        @define('PLUGIN_EVENT_SPAMBLOCK_SURBL_DESC', 'Reject comments that containt SURBL-listed hosts');
+        @define('PLUGIN_EVENT_SPAMBLOCK_RBLLIST', 'Which RBLs should be contacted');
+        @define('PLUGIN_EVENT_SPAMBLOCK_RBLLIST_DESC', 'Blocks comments based on provided RBL lists. Avoid lists with dynamic hosts.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS', 'Enable Captchas');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_DESC', 'Will force the user to input a random string displayed in a specially crafted image. This will disallow automated submits to your blog. Please remember that people with decreased vision may find it hard to read those captchas.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC', 'To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC2', 'Enter the string you see here in the input box!');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC3', 'Enter the string from the spam-prevention image above: ');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_CAPTCHAS', 'You did not enter the correct string displayed in the spam-prevention image box. Please look at the image and enter the values displayed there.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_ERROR_NOTTF', 'Captchas disabled on your server. You need GDLib and freetype libraries compiled to PHP, and need the .TTF files residing in your directory.');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_TTL', 'Force captchas after how many days');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_TTL_DESC', 'Captchas can be enforced depending on the age of your articles. Enter the amount of days after which entering a correct captcha is necessary. If set to 0, captchas will always be used.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FORCEMODERATION', 'Force comment moderation after how many days');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FORCEMODERATION_DESC', 'You can automatically set all comments for entries to be moderated. Enter the age of an entry in days, after which it should be auto-moderated. 0 means no auto-moderation.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LINKS_MODERATE', 'How many links before a comment gets moderated');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LINKS_MODERATE_DESC', 'When a comment reaches a certain amount of links, that comment can be set to be moderated. 0 means that no link-checking is done.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LINKS_REJECT', 'How many links before a comment gets rejected');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LINKS_REJECT_DESC', 'When a comment reaches a certain amount of links, that comment can be set to be moderated. 0 means that no link-checking is done.');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_NOTICE_MODERATION', 'Because of some conditions, your comment has been marked to require moderation by the owner of this blog.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHA_COLOR', 'Background color of the captcha');
+        @define('PLUGIN_EVENT_SPAMBLOCK_CAPTCHA_COLOR_DESC', 'Enter RGB values: 0,255,255');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGFILE', 'Logfile location');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGFILE_DESC', 'Information about rejected/moderated posts can be written to a logfile. Set this to an empty string if you want to disable logging.');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_KILLSWITCH', 'Emergency Comment Blockage');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_BODYCLONE', 'Duplicate comment');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_IPFLOOD', 'IP-block');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_RBL', 'RBL-block');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_SURBL', 'SURBL-block');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_CAPTCHAS', 'Invalid captcha (Entered: %s, Expected: %s)');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_FORCEMODERATION', 'Auto-moderation after X days');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_LINKS_REJECT', 'Too many hyperlinks');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_LINKS_MODERATE', 'Too many hyperlinks');
+        @define('PLUGIN_EVENT_SPAMBLOCK_HIDE_EMAIL', 'Hide E-Mail addresses of commenting users');
+        @define('PLUGIN_EVENT_SPAMBLOCK_HIDE_EMAIL_DESC', 'Will show no E-Mail addresses of commenting users');
+        @define('PLUGIN_EVENT_SPAMBLOCK_HIDE_EMAIL_NOTICE', 'E-Mail addresses will not be displayed and will only be used for E-Mail notifications');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGTYPE', 'Choose logging method');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_DESC', 'Logging of rejected comments can be done in Database or to a plaintext file');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_FILE', 'File (see "logfile" option below)');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_DB', 'Database');
+        @define('PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_NONE', 'No Logging');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_API_COMMENTS', 'How to treat comments made via APIs');
+        @define('PLUGIN_EVENT_SPAMBLOCK_API_COMMENTS_DESC', 'This affects the moderation of comments made via API calls (Trackbacks, WFW:commentAPI comments). If set to "moderate", all those comments always need to be approved first. If set to "reject", the are completely disallowed. If set to "none", the comments will be treated as usual comments.');
+        @define('PLUGIN_EVENT_SPAMBLOCK_API_MODERATE', 'moderate');
+        @define('PLUGIN_EVENT_SPAMBLOCK_API_REJECT', 'reject');
+        @define('PLUGIN_EVENT_SPAMBLOCK_REASON_API', 'No API-created comments (like trackbacks) allowed');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_ACTIVATE', 'Activate wordfilter');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_ACTIVATE_DESC', 'Searches comments for certain strings and marks them as spam.');
+
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_URLS', 'Wordfilter for URLs');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_URLS_DESC', 'Regular Expressions allowed, separate strings by semicolons (;).');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_AUTHORS', 'Wordfilter for author names');
+        @define('PLUGIN_EVENT_SPAMBLOCK_FILTER_AUTHORS_DESC', 'Regular Expressions allowed, separate strings by semicolons (;).');
+
+        break;
+}
+
+class serendipity_event_spamblock extends serendipity_event
+{
+var $filter_defaults;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $this->title = PLUGIN_EVENT_SPAMBLOCK_TITLE;
+
+        $propbag->add('name',          PLUGIN_EVENT_SPAMBLOCK_TITLE);
+        $propbag->add('description',   PLUGIN_EVENT_SPAMBLOCK_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Garvin Hicking, Sebastian Nohn');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('version',       '1.21');
+        $propbag->add('event_hooks',    array(
+            'frontend_saveComment' => true,
+            'external_plugin'      => true,
+            'frontend_comment'     => true,
+            'fetchcomments'        => true
+        ));
+        $propbag->add('configuration', array('killswitch', 'bodyclone', 'ipflood', 'surbl_enabled', 'rbl_enabled', 'rbllist', 'captchas', 'captchas_ttl', 'captcha_color', 'forcemoderation', 'disable_api_comments', 'links_moderate', 'links_reject', 'contentfilter_activate', 'contentfilter_urls', 'contentfilter_authors', 'hide_email', 'logtype', 'logfile'));
+
+        $this->filter_defaults = array(
+                                   'authors' => 'casino;phentermine;credit;loans;poker',
+                                   'urls'    => '8gold\.com;911easymoney\.com;canadianlabels\.net;condodream\.com;crepesuzette\.com;debt-help-bill-consolidation-elimination\.com;fidelityfunding\.net;flafeber\.com;gb\.com;houseofsevengables\.com;instant-quick-money-cash-advance-personal-loans-until-pay-day\.com;mediavisor\.com;newtruths\.com;oiline\.com;onlinegamingassociation\.com;online\-+poker\.com;popwow\.com;royalmailhotel\.com;spoodles\.com;sportsparent\.com;stmaryonline\.org;thatwhichis\.com;tmsathai\.org;uaeecommerce\.com;learnhowtoplay\.com'
+        );
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        global $serendipity;
+
+        switch($name) {
+            case 'disable_api_comments':
+                $propbag->add('type', 'radio');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_API_COMMENTS);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_API_COMMENTS_DESC);
+                $propbag->add('default', 'none');
+                $propbag->add('radio', array(
+                    'value' => array('moderate', 'reject', 'none'),
+                    'desc'  => array(PLUGIN_EVENT_SPAMBLOCK_API_MODERATE, PLUGIN_EVENT_SPAMBLOCK_API_REJECT, NONE)
+                ));
+                $propbag->add('radio_per_row', '1');
+
+                break;
+
+            case 'hide_email':
+                $propbag->add('type', 'boolean');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_HIDE_EMAIL);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_HIDE_EMAIL_DESC);
+                $propbag->add('default', false);
+                break;
+
+            case 'bodyclone':
+                $propbag->add('type', 'boolean');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_BODYCLONE);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_BODYCLONE_DESC);
+                $propbag->add('default', true);
+                break;
+
+            case 'captchas':
+                $propbag->add('type', 'boolean');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_DESC);
+                $propbag->add('default', true);
+                break;
+
+            case 'killswitch':
+                $propbag->add('type', 'boolean');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_KILLSWITCH);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_KILLSWITCH_DESC);
+                $propbag->add('default', false);
+                break;
+
+            case 'contentfilter_activate':
+                $propbag->add('type', 'radio');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_FILTER_ACTIVATE);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_FILTER_ACTIVATE_DESC);
+                $propbag->add('default', 'moderate');
+                $propbag->add('radio', array(
+                    'value' => array('moderate', 'reject', 'none'),
+                    'desc'  => array(PLUGIN_EVENT_SPAMBLOCK_API_MODERATE, PLUGIN_EVENT_SPAMBLOCK_API_REJECT, NONE)
+                ));
+                $propbag->add('radio_per_row', '1');
+
+                break;
+
+            case 'contentfilter_urls':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_FILTER_URLS);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_FILTER_URLS_DESC);
+                $propbag->add('default', $this->filter_defaults['urls']);
+                break;
+
+            case 'contentfilter_authors':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_FILTER_AUTHORS);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_FILTER_AUTHORS_DESC);
+                $propbag->add('default', $this->filter_defaults['authors']);
+                break;
+
+            case 'logfile':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_LOGFILE);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_LOGFILE_DESC);
+                $propbag->add('default', $serendipity['serendipityPath'] . 'spamblock.log');
+                break;
+
+            case 'logtype':
+                $propbag->add('type', 'radio');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_LOGTYPE);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_DESC);
+                $propbag->add('default', 'db');
+                $propbag->add('radio',         array(
+                    'value' => array('file', 'db', 'none'),
+                    'desc'  => array(PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_FILE, PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_DB, PLUGIN_EVENT_SPAMBLOCK_LOGTYPE_NONE)
+                ));
+                $propbag->add('radio_per_row', '1');
+
+                break;
+
+            case 'ipflood':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_IPFLOOD);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_IPFLOOD_DESC);
+                $propbag->add('default', 0);
+                break;
+
+            case 'surbl_enabled':
+                $propbag->add('type', 'boolean');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_SURBL);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_SURBL_DESC);
+                $propbag->add('default', false);
+                break;
+
+            case 'rbl_enabled':
+                $propbag->add('type', 'boolean');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_RBL);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_RBL_DESC);
+                $propbag->add('default', false);
+                break;
+
+            case 'rbllist':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_RBLLIST);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_RBLLIST_DESC);
+                $propbag->add('default', 'sbl-xbl.spamhaus.org, bl.spamcop.net');
+                break;
+
+            case 'captchas_ttl':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_TTL);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_TTL_DESC);
+                $propbag->add('default', '7');
+                break;
+
+            case 'captcha_color':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_CAPTCHA_COLOR);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_CAPTCHA_COLOR_DESC);
+                $propbag->add('default', '255,255,255');
+                break;
+
+            case 'forcemoderation':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_FORCEMODERATION);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_FORCEMODERATION_DESC);
+                $propbag->add('default', '30');
+                break;
+
+            case 'links_moderate':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_LINKS_MODERATE);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_LINKS_MODERATE_DESC);
+                $propbag->add('default', '7');
+                break;
+
+            case 'links_reject':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_LINKS_REJECT);
+                $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_LINKS_REJECT_DESC);
+                $propbag->add('default', '13');
+                break;
+
+            default:
+                    return false;
+        }
+
+        return true;
+    }
+
+    function checkScheme($maxVersion) {
+        global $serendipity;
+
+        $version = $this->get_config('version', '1.0');
+
+        if ($version != $maxVersion) {
+            $q   = "CREATE TABLE {$serendipity['dbPrefix']}spamblocklog (
+                          timestamp int(10) {UNSIGNED} default null,
+                          type varchar(255),
+                          reason text,
+                          entry_id int(10) {UNSIGNED} not null default '0',
+                          author varchar(80),
+                          email varchar(200),
+                          url varchar(200),
+                          useragent varchar(255),
+                          ip varchar(15),
+                          referer varchar(255),
+                          body text)";
+            $sql = serendipity_db_schema_import($q);
+
+            $q   = "CREATE INDEX kspamidx ON {$serendipity['dbPrefix']}spamblocklog (timestamp);";
+            $sql = serendipity_db_schema_import($q);
+
+            $q   = "CREATE INDEX kspamtypeidx ON {$serendipity['dbPrefix']}spamblocklog (type);";
+            $sql = serendipity_db_schema_import($q);
+
+            $q   = "CREATE INDEX kspamentryidx ON {$serendipity['dbPrefix']}spamblocklog (entry_id);";
+            $sql = serendipity_db_schema_import($q);
+
+            $this->set_config('version', $maxVersion);
+        }
+
+        return true;
+    }
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+    function event_hook($event, &$bag, &$eventData, $addData = null) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+
+        if (isset($hooks[$event])) {
+            $captchas_ttl = $this->get_config('captchas_ttl', 7);
+            $captchas     = (serendipity_db_bool($this->get_config('captchas', true)) ? true : false);
+            // Check if the entry is older than the allowed amount of time. Enforce kaptchas if that is true
+            // of if kaptchas are activated for every entry
+            $show_captcha = ($captchas && isset($eventData['timestamp']) && ($captchas_ttl < 1 || ($eventData['timestamp'] < (time() - ($captchas_ttl*60*60*24)))) ? true : false);
+
+            $forcemoderation = $this->get_config('forcemoderation', 60);
+            $links_moderate  = $this->get_config('links_moderate', 10);
+            $links_reject    = $this->get_config('links_reject', 20);
+
+            if (function_exists('imagettftext') && function_exists('imagejpeg')) {
+                $max_char = 5;
+                $min_char = 3;
+                $use_gd   = true;
+            } else {
+                $max_char = $min_char = 5;
+                $use_gd   = false;
+            }
+
+            switch($event) {
+                case 'fetchcomments':
+                    if (is_array($eventData) && !$_SESSION['serendipityAuthedUser'] && serendipity_db_bool($this->get_config('hide_email', false))) {
+                        // Will force emails to be not displayed in comments and RSS feed for comments. Will not apply to logged in admins (so not in the backend as well)
+                        @reset($eventData);
+                        while(list($idx, $comment) = each($eventData)) {
+                            $eventData[$idx]['no_email'] = true;
+                        }
+                    }
+                    break;
+
+                case 'frontend_saveComment':
+                    if (!is_array($eventData) || serendipity_db_bool($eventData['allow_comments'])) {
+                        if ($this->get_config('logtype', 'db') == 'db' && $this->get_config('version') != $bag->get('version')) {
+                            $this->checkScheme($bag->get('version'));
+                        }
+
+                        $serendipity['csuccess'] = 'true';
+                        $logfile = $this->get_config('logfile', $serendipity['serendipityPath'] . 'spamblock.log');
+
+                        // Check for global emergency moderation
+                        if ( $this->get_config('killswitch', false) === true ) {
+                            $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_KILLSWITCH, $addData);
+                            $eventData = array('allow_comments' => false);
+                            $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_KILLSWITCH;
+                            return false;
+                        }
+
+                        // Check for not allowing trackbacks/wfwcomments
+                        if ( ($addData['type'] != 'NORMAL' || $addData['source'] == 'API') &&
+                             $this->get_config('disable_api_comments', 'none') != 'none') {
+                            if ($this->get_config('disable_api_comments') == 'reject') {
+                                $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_API, $addData);
+                                $eventData = array('allow_comments' => false);
+                                $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_REASON_API;
+                            } elseif ($this->get_config('disable_api_comments') == 'moderate') {
+                                $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_REASON_API, $addData);
+                                $eventData['moderate_comments'] = true;
+                                $serendipity['csuccess']        = 'moderate';
+                                $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_REASON_API;
+                            }
+                            return false;
+                        }
+
+                        // Check for word filtering
+                        if ($filter_type = $this->get_config('contentfilter_activate', 'moderate')) {
+
+                            // Filter authors names
+                            $filter_authors = explode(';', $this->get_config('contentfilter_authors', $this->filter_defaults['authors']));
+                            if (is_array($filter_authors)) {
+                                foreach($filter_authors AS $filter_author) {
+                                    if (preg_match('@' . $filter_author . '@', $addData['name'])) {
+                                        if ($filter_type == 'moderate') {
+                                            $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_FILTER_AUTHORS, $addData);
+                                            $eventData['moderate_comments'] = true;
+                                            $serendipity['csuccess']        = 'moderate';
+                                            $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY;
+                                            return false;
+                                        } else {
+                                            $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_FILTER_AUTHORS, $addData);
+                                            $eventData = array('allow_comments' => false);
+                                            $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY;
+                                            return false;
+                                        }
+                                    }
+                                }
+                            }
+
+                            // Filter URL
+                            $filter_urls = explode(';', $this->get_config('contentfilter_urls', $this->filter_defaults['urls']));
+                            if (is_array($filter_urls)) {
+                                foreach($filter_urls AS $filter_url) {
+                                    if (preg_match('@' . $filter_url . '@', $addData['url'])) {
+                                        if ($filter_type == 'moderate') {
+                                            $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_FILTER_URLS, $addData);
+                                            $eventData['moderate_comments'] = true;
+                                            $serendipity['csuccess']        = 'moderate';
+                                            $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY;
+                                            return false;
+                                        } else {
+                                            $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_FILTER_URLS, $addData);
+                                            $eventData = array('allow_comments' => false);
+                                            $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY;
+                                            return false;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+
+                        // Check for maximum number of links before rejecting
+                        $link_count = substr_count(strtolower($addData['comment']), 'http://');
+                        if ($links_reject > 0 && $link_count > $links_reject) {
+                            $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_LINKS_REJECT, $addData);
+                            $eventData = array('allow_comments' => false);
+                            $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY;
+                            return false;
+                        }
+
+                        // Captcha checking
+                        if ($show_captcha && $addData['type'] == 'NORMAL') {
+                            if (!isset($_SESSION['spamblock']['captcha']) || !isset($serendipity['POST']['captcha']) || strtolower($serendipity['POST']['captcha']) != strtolower($_SESSION['spamblock']['captcha'])) {
+                                $this->log($logfile, $eventData['id'], 'REJECTED', sprintf(PLUGIN_EVENT_SPAMBLOCK_REASON_CAPTCHAS, $serendipity['POST']['captcha'], $_SESSION['spamblock']['captcha']), $addData);
+                                $eventData = array('allow_comments' => false);
+                                $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_CAPTCHAS;
+                                return false;
+                            } else {
+// DEBUG
+//                                $this->log($logfile, $eventData['id'], 'REJECTED', 'Captcha passed: ' . $serendipity['POST']['captcha'] . ' / ' . $_SESSION['spamblock']['captcha'] . ' // Source: ' . $_SERVER['REQUEST_URI'], $addData);
+                            }
+                        } else {
+// DEBUG
+//                            $this->log($logfile, $eventData['id'], 'REJECTED', 'Captcha not needed: ' . $serendipity['POST']['captcha'] . ' / ' . $_SESSION['spamblock']['captcha'] . ' // Source: ' . $_SERVER['REQUEST_URI'], $addData);
+                        }
+
+                        // Check for forced moderation
+                        if ($forcemoderation > 0 && $eventData['timestamp'] < (time() - ($forcemoderation * 60 * 60 * 24))) {
+                            $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_REASON_FORCEMODERATION, $addData);
+                            $eventData['moderate_comments'] = true;
+                            $serendipity['csuccess']        = 'moderate';
+                            $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_REASON_FORCEMODERATION;
+                            return false;
+                        }
+
+                        // Check for maximum number of links before forcing moderation
+                        if ($links_moderate > 0 && $link_count > $links_moderate) {
+                            $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_LINKS_MODERATE, $addData);
+                            $eventData['moderate_comments'] = true;
+                            $serendipity['csuccess']        = 'moderate';
+                            $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_REASON_LINKS_MODERATE;
+                            return false;
+                        }
+
+                        // Check for identical comments. We allow to bypass trackbacks from our server to our own blog.
+                        if ( $this->get_config('bodyclone', true) === true && $_SERVER['REMOTE_ADDR'] != $_SERVER['SERVER_ADDR']) {
+                            $query = "SELECT count(id) AS counter FROM {$serendipity['dbPrefix']}comments WHERE body = '" . serendipity_db_escape_string($addData['comment']) . "'";
+                            $row   = serendipity_db_query($query, true);
+                            if (is_array($row) && $row['counter'] > 0) {
+                                $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_BODYCLONE, $addData);
+                                $eventData = array('allow_comments' => false);
+                                $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY;
+                                return false;
+                            }
+                        }
+
+                        // Check last IP
+                        if ($addData['type'] == 'NORMAL' && $this->get_config('ipflood', 2) != 0 ) {
+                            $query = "SELECT max(timestamp) AS last_post FROM {$serendipity['dbPrefix']}comments WHERE ip = '" . serendipity_db_escape_string($_SERVER['REMOTE_ADDR']) . "'";
+                            $row   = serendipity_db_query($query, true);
+                            if (is_array($row) && $row['last_post'] > (time() - $this->get_config('ipflood', 2)*60)) {
+                                $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_IPFLOOD, $addData);
+                                $eventData = array('allow_comments' => false);
+                                $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_IP;
+                                return false;
+                            }
+                        }
+
+                        // Check for IP listed in RBL
+                        if (serendipity_db_bool($this->get_config('rbl_enabled', false))) {
+                            require_once 'bundled-libs/Net/DNSBL.php';
+                            $dnsbl = new Net_DNSBL();
+                            $remoteIP = $_SERVER['REMOTE_ADDR'];
+                            # $remoteIP = '81.70.69.193';
+
+                            $dnsbl->setBlacklists(explode(',', $this->get_config('rbllist')));
+                            if ($dnsbl->isListed($remoteIP)) {
+                                $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_RBL, $addData);
+                                $eventData = array('allow_comments' => false);
+                                $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_RBL;
+                                return false;
+                            }
+                        }
+
+                        // Check for IP listed in SURBL
+                        if (serendipity_db_bool($this->get_config('surbl_enabled', false))) {
+                            require_once 'bundled-libs/Net/DNSBL/SURBL.php';
+                            $surbl = new Net_DNSBL_SURBL();
+                            if ($surbl->isListed($addData['url'])) {
+                                $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_SURBL, $addData);
+                                $eventData = array('allow_comments' => false);
+                                $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_SURBL;
+                                return false;
+                            }
+                            // BEGIN Code copied from http://www.phpfreaks.com/quickcode/Extract_All_URLs_on_a_Page/15.php
+                            $urls = '(http|file|ftp)';
+                            $ltrs = '\w';
+                            $gunk = '/#~:.?+=&%@!\-';
+                            $punc = '.:?\-';
+                            $any = "$ltrs$gunk$punc";
+                            preg_match_all("{
+                                              \b
+                                              $urls   :
+                                              [$any] +?
+
+
+                                              (?=
+                                                [$punc] *
+                                                [^$any]
+                                              |
+                                                $
+                                              )
+                                          }x", $addData['comment'], $matches);
+                            // END Code copied from http://www.phpfreaks.com/quickcode/Extract_All_URLs_on_a_Page/15.php
+                            foreach ($matches[0] as $surbl_check_url) {
+                                if ($surbl->isListed($surbl_check_url)) {
+                                    $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_SURBL, $addData);
+                                    $eventData = array('allow_comments' => false);
+                                    $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_SURBL;
+                                    return false;
+                                }
+                            }
+                        }
+                    }
+                    return true;
+                    break;
+
+                case 'frontend_comment':
+                    if (serendipity_db_bool($this->get_config('hide_email', false))) {
+                        echo '<div class="serendipity_commentDirection">' . PLUGIN_EVENT_SPAMBLOCK_HIDE_EMAIL_NOTICE . '</div>';
+                    }
+
+                    if ($show_captcha) {
+                        echo '<div class="serendipity_commentDirection">';
+                        if (!isset($serendipity['POST']['preview']) || strtolower($serendipity['POST']['captcha'] != strtolower($_SESSION['spamblock']['captcha']))) {
+                            echo '<br />' . PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC . '<br />';
+                            if ($use_gd) {
+                                printf('<img src="%s" title="%s" alt="CAPTCHA" class="captcha" />',
+                                    $serendipity['baseURL'] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '') . 'plugin/captcha_' . md5(time()),
+                                    htmlspecialchars(PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC2)
+                                );
+                            } else {
+                                $bgcolors = explode(',', $this->get_config('captcha_color', '255,0,255'));
+                                $hexval   = '#' . dechex(trim($bgcolors[0])) . dechex(trim($bgcolors[1])) . dechex(trim($bgcolors[2]));
+                                $this->random_string($max_char, $min_char);
+                                echo '<div style="background-color: ' . $hexval . '">';
+                                for ($i = 1; $i <= $max_char; $i++) {
+                                    printf('<img src="%s" title="%s" alt="CAPTCHA ' . $i . '" class="captcha" />',
+                                        $serendipity['baseURL'] . ($serendipity['rewrite'] == 'none' ? $serendipity['indexFile'] . '?/' : '') . 'plugin/captcha_' . $i . '_' . md5(time()),
+                                        htmlspecialchars(PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC2)
+                                    );
+                                }
+                                echo '</div>';
+                            }
+                            echo '<br />';
+                            echo '<label for="captcha">'. PLUGIN_EVENT_SPAMBLOCK_CAPTCHAS_USERDESC3 . '</label><br /><input type="text" size="5" name="serendipity[captcha]" value="" id="captcha" />';
+                        } elseif (isset($serendipity['POST']['captcha'])) {
+                            echo '<input type="hidden" name="serendipity[captcha]" value="' . htmlspecialchars($serendipity['POST']['captcha']) . '" />';
+                        }
+                        echo '</div>';
+                    }
+
+                    return true;
+                    break;
+
+
+                case 'external_plugin':
+                    $parts     = explode('_', $eventData);
+                    if (!empty($parts[1])) {
+                        $param     = (int) $parts[1];
+                    } else {
+                        $param     = null;
+                    }
+
+                    $methods = array('captcha');
+
+                    if (!in_array($parts[0], $methods)) {
+                        return;
+                    }
+
+                    list($musec, $msec) = explode(' ', microtime());
+                    $srand = (float) $msec + ((float) $musec * 100000);
+                    srand($srand);
+                    mt_srand($srand);
+                    $width    = 120;
+                    $height   = 40;
+
+                    $bgcolors = explode(',', $this->get_config('captcha_color', '255,255,255'));
+                    $fontfiles = array('Vera.ttf', 'VeraSe.ttf', 'chumbly.ttf', '36daysago.ttf');
+
+                    if ($use_gd) {
+                        $strings  = $this->random_string($max_char, $min_char);
+                        $fontname = $fontfiles[array_rand($fontfiles)];
+                        $font     = $serendipity['serendipityPath'] . 'plugins/serendipity_event_spamblock/' . $fontname;
+
+                        if (!file_exists($font)) {
+                            // Search in shared plugin directory
+                            $font = S9Y_INCLUDE_PATH . 'plugins/serendipity_event_spamblock/' . $fontname;
+                        }
+
+                        if (!file_exists($font)) {
+                            die(PLUGIN_EVENT_SPAMBLOCK_ERROR_NOTTF);
+                        }
+
+                        header('Content-Type: image/jpeg');
+                        $image  = imagecreate($width, $height);
+                        imagecolorallocate($image, trim($bgcolors[0]), trim($bgcolors[1]), trim($bgcolors[2]));
+                        // imagettftext($image, 10, 1, 1, 15, imagecolorallocate($image, 255, 255, 255), $font, 'String: ' . $string);
+
+                        $pos_x  = 5;
+                        foreach($strings AS $idx => $charidx) {
+                            $color = imagecolorallocate($image, mt_rand(50, 235), mt_rand(50, 235), mt_rand(50,235));
+                            $size  = mt_rand(15, 21);
+                            $angle = mt_rand(-20, 20);
+                            $pos_y = ceil($height - (mt_rand($size/3, $size/2)));
+
+                            imagettftext(
+                              $image,
+                              $size,
+                              $angle,
+                              $pos_x,
+                              $pos_y,
+                              $color,
+                              $font,
+                              $this->chars[$charidx]
+                            );
+
+                            $pos_x = $pos_x + $size + 2;
+
+                        }
+                        imagejpeg($image, '', 90);
+                        imagedestroy($image);
+                    } else {
+                        header('Content-Type: image/png');
+                        $output_char = strtolower($_SESSION['spamblock']['captcha']{$parts[1] - 1});
+                        $cap = $serendipity['serendipityPath'] . 'plugins/serendipity_event_spamblock/captcha_' . $output_char . '.png';
+                        if (!file_exists($cap)) {
+                            $cap = S9Y_INCLUDE_PATH . 'plugins/serendipity_event_spamblock/captcha_' . $output_char . '.png';
+                        }
+
+                        if (file_exists($cap)) {
+                            echo file_get_contents($cap);
+                        }
+                    }
+                    return true;
+                    break;
+
+                default:
+                    return false;
+                    break;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    function random_string($max_char, $min_char) {
+        $this->chars = array(2, 3, 4, 7, 9); // 1, 5, 6 and 8 may look like characters.
+        $this->chars = array_merge($this->chars, array('A','B','C','D','E','F','H','J','K','L','M','N','P','Q','R','T','U','V','W','X','Y','Z')); // I, O, S may look like numbers
+
+        $strings   = array_rand($this->chars, mt_rand($max_char, $min_char));
+        $string    = '';
+        foreach($strings AS $idx => $charidx) {
+            $string .= $this->chars[$charidx];
+        }
+        $_SESSION['spamblock'] = array('captcha' => $string);
+
+        return $strings;
+    }
+
+    function log($logfile, $id, $switch, $reason, $comment) {
+        global $serendipity;
+
+        $method = $this->get_config('logtype');
+
+        switch($method) {
+            case 'file':
+                if (empty($logfile)) {
+                    return;
+                }
+
+                $fp = @fopen($logfile, 'a+');
+                if (!is_resource($fp)) {
+                    return;
+                }
+
+                fwrite($fp, sprintf(
+                    '[%s] - [%s: %s] - [#%s, Name "%s", E-Mail "%s", URL "%s", User-Agent "%s", IP %s] - [%s]' . "\n",
+                    date('Y-m-d H:i:s', serendipity_serverOffsetHour()),
+                    $switch,
+                    $reason,
+                    $id,
+                    str_replace("\n", ' ', $comment['name']),
+                    str_replace("\n", ' ', $comment['email']),
+                    str_replace("\n", ' ', $comment['url']),
+                    str_replace("\n", ' ', $_SERVER['HTTP_USER_AGENT']),
+                    $_SERVER['REMOTE_ADDR'],
+                    str_replace("\n", ' ', $comment['comment'])
+                ));
+
+                fclose($fp);
+                break;
+
+            case 'none':
+                return;
+                break;
+
+            case 'db':
+            default:
+                $q = sprintf("INSERT INTO {$serendipity['dbPrefix']}spamblocklog
+                                          (timestamp, type, reason, entry_id, author, email, url,  useragent, ip,   referer, body)
+                                   VALUES (%d,        '%s',  '%s',  '%s',     '%s',   '%s',  '%s', '%s',      '%s', '%s',    '%s')",
+
+                           serendipity_serverOffsetHour(),
+                           serendipity_db_escape_string($switch),
+                           serendipity_db_escape_string($reason),
+                           serendipity_db_escape_string($id),
+                           serendipity_db_escape_string($comment['name']),
+                           serendipity_db_escape_string($comment['email']),
+                           serendipity_db_escape_string($comment['url']),
+                           serendipity_db_escape_string($_SERVER['HTTP_USER_AGENT']),
+                           serendipity_db_escape_string($_SERVER['REMOTE_ADDR']),
+                           serendipity_db_escape_string(isset($_SESSION['HTTP_REFERER']) ? $_SESSION['HTTP_REFERER'] : $_SERVER['HTTP_REFERER']),
+                           serendipity_db_escape_string($comment['comment'])
+                );
+
+                serendipity_db_query($q);
+                break;
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_spartacus/lang_ja.inc.php b/plugins/serendipity_event_spartacus/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..f39c649
--- /dev/null
@@ -0,0 +1,21 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_EVENT_SPARTACUS_NAME', 'Spartacus');
+        @define('PLUGIN_EVENT_SPARTACUS_DESC', '[S]erendipity [P]lugin [A]ccess [R]epository [T]ool [A]nd [C]ustomization/[U]nification [S]ystem - オンラインリポジトリからプラグインのダウンロードを許可します。');
+        @define('PLUGIN_EVENT_SPARTACUS_FETCH', '新しい%sを Serendipity オンラインリポジトリから取得する');
+        @define('PLUGIN_EVENT_SPARTACUS_FETCHERROR', 'URL %s にアクセスできませんでした。おそらく Serendipity か SourceForge.net のサーバーがダウンしています - すみませんが、あとで再度試してください。');
+        @define('PLUGIN_EVENT_SPARTACUS_FETCHING', 'URL %s にアクセスを試みます...');
+
+?>
diff --git a/plugins/serendipity_event_spartacus/serendipity_event_spartacus.php b/plugins/serendipity_event_spartacus/serendipity_event_spartacus.php
new file mode 100644 (file)
index 0000000..9b2597a
--- /dev/null
@@ -0,0 +1,383 @@
+<?php # $Id$
+
+/************
+  TODO:
+
+  - Perform Serendipity version checks to only install plugins available for version
+  - Allow fetching files from mirrors / different locations - don't use ViewCVS hack (revision 1.999 dumbness)
+
+ ***********/
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_SPARTACUS_NAME', 'Spartacus');
+        @define('PLUGIN_EVENT_SPARTACUS_DESC', '[S]erendipity [P]lugin [A]ccess [R]epository [T]ool [A]nd [C]ustomization/[U]nification [S]ystem - Installiert Plugins direkt aus dem Netz.');
+        @define('PLUGIN_EVENT_SPARTACUS_FETCH', 'Hier klicken um ein neues %s aus dem Netz zu installieren.');
+        @define('PLUGIN_EVENT_SPARTACUS_FETCHERROR', 'Die URL %s konnte nicht geöffnet werden. Möglicherweise existieren Server- oder Netzwerkprobleme.');
+        @define('PLUGIN_EVENT_SPARTACUS_FETCHING', 'Versuche URL %s zu öffnen...');
+        break;
+    case 'en':
+    default:
+        @define('PLUGIN_EVENT_SPARTACUS_NAME', 'Spartacus');
+        @define('PLUGIN_EVENT_SPARTACUS_DESC', '[S]erendipity [P]lugin [A]ccess [R]epository [T]ool [A]nd [C]ustomization/[U]nification [S]ystem - Allows you to download plugins from our online repository');
+        @define('PLUGIN_EVENT_SPARTACUS_FETCH', 'Click here to fetch a new %s from the Serendipity Online Repository');
+        @define('PLUGIN_EVENT_SPARTACUS_FETCHERROR', 'The URL %s could not be opened. Maybe the Serendipity or SourceForge.net Server is down - we are sorry, you need to try again later.');
+        @define('PLUGIN_EVENT_SPARTACUS_FETCHING', 'Trying to open URL %s...');
+        break;
+}
+
+class serendipity_event_spartacus extends serendipity_event
+{
+    var $title = PLUGIN_EVENT_SPARTACUS_NAME;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_SPARTACUS_NAME);
+        $propbag->add('description',   PLUGIN_EVENT_SPARTACUS_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Garvin Hicking');
+        $propbag->add('version',       '1.01');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('event_hooks',    array(
+            'backend_plugins_sidebar_header' => true,
+            'backend_plugins_event_header'   => true,
+
+            'backend_plugins_fetchlist'      => true,
+            'backend_plugins_fetchplugin'    => true
+        ));
+    }
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+    function GetChildren(&$vals, &$i) {
+        $children = array();
+        $cnt = sizeof($vals);
+        while (++$i < $cnt) {
+            // compare type
+            switch ($vals[$i]['type']) {
+                case 'cdata':
+                    $children[] = $vals[$i]['value'];
+                    break;
+
+                case 'complete':
+                    $children[] = array(
+                        'tag'        => $vals[$i]['tag'],
+                        'attributes' => $vals[$i]['attributes'],
+                        'value'      => $vals[$i]['value']
+                    );
+                    break;
+
+                case 'open':
+                    $children[] = array(
+                        'tag'        => $vals[$i]['tag'],
+                        'attributes' => $vals[$i]['attributes'],
+                        'value'      => $vals[$i]['value'],
+                        'children'   => $this->GetChildren($vals, $i)
+                    );
+                    break;
+
+                case 'close':
+                    return $children;
+            }
+        }
+    }
+
+    // Create recursive directories; begins at serendipity plugin root folder level
+    function rmkdir($dir) {
+        global $serendipity;
+
+        $spaths = explode('/', $serendipity['serendipityPath'] . 'plugins/'); 
+        $paths  = explode('/', $dir);
+        
+        $stack  = ''; 
+        foreach($paths AS $pathid => $path) {
+            $stack .= $path . '/';
+
+            if ($spaths[$pathid] == $path) {
+                continue;
+            }
+            
+            if (!is_dir($stack) && !mkdir($stack)) {
+                return false;
+            }
+        }
+        
+        return true;
+    }
+
+    function &fetchfile($url, $target, $cacheTimeout = 0) {
+        printf(PLUGIN_EVENT_SPARTACUS_FETCHING, '<a href="' . $url . '">' . serendipity_truncateString($url, 68) . '</a>');
+        echo '<br />';
+
+        if (file_exists($target) && filesize($target) > 0 && filemtime($target) >= (time()-$cacheTimeout)) {
+            $data = file_get_contents($target);
+        } else {
+            require_once S9Y_INCLUDE_PATH . 'bundled-libs/HTTP/Request.php';
+            $req = &new HTTP_Request($url);
+
+            if (PEAR::isError($req->sendRequest()) || $req->getResponseCode() != '200') {
+                printf(PLUGIN_EVENT_SPARTACUS_FETCHERROR, $url);
+                if (file_exists($target) && filesize($target) > 0) {
+                    $data = file_get_contents($target);
+                }
+            } else {
+                // Fetch file
+                $data = $req->getResponseBody();
+                $tdir = dirname($target);
+                if (!is_dir($tdir) && !$this->rmkdir($tdir)) {
+                    printf(FILE_WRITE_ERROR, $tdir);
+                    echo '<br />';
+                    return false;
+                }
+
+                $fp = @fopen($target, 'w');
+
+                if (!$fp) {
+                    printf(FILE_WRITE_ERROR, $target);
+                    return false;
+                }
+
+                fwrite($fp, $data);
+                fclose($fp);
+            }
+        }
+
+        return $data;
+    }
+
+    function &fetchOnline($type) {
+        switch($type) {
+            // Sanitize to not fetch other URLs
+            default:
+            case 'event':
+                $url_type = 'event';
+                break;
+
+            case 'sidebar':
+                $url_type = 'sidebar';
+                break;
+        }
+
+        $url    = 'http://netmirror.org/mirror/serendipity/package_' . $url_type . '.xml';
+        $cacheTimeout = 60*60*12; // XML file is cached for half a day
+        $target = $serendipity['serendipityPath'] . 'templates_c/package_' . $url_type . '.xml';
+
+        $xml = $this->fetchfile($url, $target, $cacheTimeout);
+
+        echo '<br /><br />';
+
+        // XML functions
+        $p = xml_parser_create();
+        xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, 0);
+        xml_parse_into_struct($p, $xml, $vals, $index);
+        xml_parser_free($p);
+
+        $i = 0;
+        $tree = array();
+        $tree[] = array(
+            'tag'        => $vals[$i]['tag'],
+            'attributes' => $vals[$i]['attributes'],
+            'value'      => $vals[$i]['value'],
+            'children'   => $this->GetChildren($vals, $i)
+        );
+
+        return $tree;
+    }
+
+    function &buildList(&$tree, $type) {
+        $plugins = serendipity_plugin_api::get_installed_plugins();
+        $pluginstack = array();
+        $i = 0;
+
+        foreach($tree[0]['children'] AS $idx => $subtree) {
+            if ($subtree['tag'] == 'package') {
+                $i++;
+
+                foreach($subtree['children'] AS $child => $childtree) {
+                    switch($childtree['tag']) {
+                        case 'name':
+                            $pluginstack[$i]['plugin_class'] = $childtree['value'];
+                            $pluginstack[$i]['class_name']   = $childtree['value'];
+                            break;
+
+                        case 'summary':
+                            $pluginstack[$i]['name']         = $childtree['value'];
+                            break;
+
+                        case 'description':
+                            $pluginstack[$i]['desc']         = $childtree['value'];
+                            break;
+
+                        case 'release':
+                            $pluginstack[$i]['version']      = $childtree['children'][0]['value'];
+                            
+                            $pluginstack[$i]['requirements'] = array(
+                                'serendipity' => '',
+                                'php'         => '',
+                                'smarty'      => ''
+                            );
+
+                            foreach($childtree['children'] AS $relInfo) {
+                                if ($relInfo['tag'] == 'requirements:s9yVersion') {
+                                    $pluginstack[$i]['requirements']['serendipity'] = $relInfo['value'];
+                                }
+                            }
+                            break;
+
+                        case 'maintainers':
+                            $pluginstack[$i]['author']       = $childtree['children'][0]['children'][0]['value']; // I dig my PHP arrays ;-)
+                            break;
+                    }
+                }
+
+                $installable = true;
+                $upgradeLink = '';
+                if (in_array($pluginstack[$i]['class_name'], $plugins)) {
+                    $infoplugin =& serendipity_plugin_api::load_plugin($pluginstack[$i]['class_name']);
+                    if (is_object($infoplugin)) {
+                        $bag    = new serendipity_property_bag;
+                        $infoplugin->introspect($bag);
+                        if ($bag->get('version') == $pluginstack[$i]['version']) {
+                            $installable = false;
+                        } elseif (version_compare($bag->get('version'), $pluginstack[$i]['version'], '<')) {
+                            $pluginstack[$i]['upgradable']      = true;
+                            $pluginstack[$i]['upgrade_version'] = $pluginstack[$i]['version'];
+                            $pluginstack[$i]['version']         = $bag->get('version');
+                            $upgradeLink                        = '&amp;serendipity[spartacus_upgrade]=true';
+                        }
+                    }
+                }
+
+                $pluginstack[$i]['installable'] = $installable;
+                $pluginstack[$i]['pluginPath']  = 'online_repository';
+                $pluginstack[$i]['customURI']   = '&amp;serendipity[spartacus_fetch]=' . $type . $upgradeLink;
+            }
+        }
+
+        return $pluginstack;
+    }
+
+    function download(&$tree, $plugin_to_install) {
+        global $serendipity;
+
+        $pdir = $serendipity['serendipityPath'] . '/plugins/';
+        if (!is_writable($pdir)) {
+            printf(DIRECTORY_WRITE_ERROR, $pdir);
+            return false;
+        }
+
+        $files = array();
+        $found = false;
+        foreach($tree[0]['children'] AS $idx => $subtree) {
+            if ($subtree['tag'] != 'package') {
+                continue;
+            }
+
+            foreach($subtree['children'] AS $child => $childtree) {
+                if ($childtree['tag'] == 'name' && $childtree['value'] == $plugin_to_install) {
+                    $found = true;
+                }
+
+                if (!$found || $childtree['tag'] != 'release') {
+                    continue;
+                }
+
+                foreach($childtree['children'] AS $child2 => $childtree2) {
+                    if ($childtree2['tag'] != 'serendipityFilelist') {
+                        continue;
+                    }
+
+                    foreach($childtree2['children'] AS $idx => $_files) {
+                        if ($_files['tag'] == 'file' && !empty($_files['value'])) {
+                            $files[] = $_files['value'];
+                        }
+                    }
+                }
+
+                $found = false;
+            }
+        }
+
+        foreach($files AS $file) {
+            $url    = 'http://cvs.sourceforge.net/viewcvs.py/*checkout*/php-blog/additional_plugins/' . $file . '?rev=1.9999';
+            $target = $pdir . $file;
+            @mkdir($pdir . $plugin_to_install);
+            $this->fetchfile($url, $target);
+        }
+    }
+
+    function event_hook($event, &$bag, &$eventData) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+
+        if (isset($hooks[$event])) {
+            switch($event) {
+                case 'backend_plugins_sidebar_header':
+?>
+    <br /><a href="?serendipity[adminModule]=plugins&amp;serendipity[adminAction]=addnew&amp;serendipity[source]=spartacus" class="serendipityIconLink"><img src="<?php echo serendipity_getTemplateFile('admin/img/install.png') ?>" style="border: 0px none ; vertical-align: middle; display: inline;" alt=""><?php echo sprintf(PLUGIN_EVENT_SPARTACUS_FETCH, SIDEBAR_PLUGIN) ?></a>
+<?php
+                    return true;
+                    break;
+
+                case 'backend_plugins_event_header':
+?>
+    <br /><a href="?serendipity[adminModule]=plugins&amp;serendipity[adminAction]=addnew&amp;serendipity[type]=event&amp;serendipity[source]=spartacus" class="serendipityIconLink"><img src="<?php echo serendipity_getTemplateFile('admin/img/install.png') ?>" style="border: 0px none ; vertical-align: middle; display: inline;" alt=""><?php echo sprintf(PLUGIN_EVENT_SPARTACUS_FETCH, EVENT_PLUGIN) ?></a>
+<?php
+                    return true;
+                    break;
+
+                case 'backend_plugins_fetchlist':
+                    if ($serendipity['GET']['source'] != 'spartacus') {
+                        return false;
+                    }
+
+                    $type = (isset($serendipity['GET']['type']) ? $serendipity['GET']['type'] : 'sidebar');
+
+                    $eventData = array(
+                                   'pluginstack' => $this->buildList($this->fetchOnline($type), $type),
+                                   'errorstack'  => array()
+                    );
+
+                    return true;
+                    break;
+
+                case 'backend_plugins_fetchplugin':
+                    if (!empty($eventData['GET']['spartacus_fetch'])) {
+                        $this->download($this->fetchOnline($eventData['GET']['spartacus_fetch']), $eventData['GET']['install_plugin']);
+                        $eventData['GET']['pluginPath'] = $eventData['GET']['install_plugin'];
+                        
+                        if ($eventData['GET']['spartacus_upgrade']) {
+                            $eventData['install'] = false;
+                        }
+                    }
+
+                    return false;
+                    break;
+
+                default:
+                    return false;
+                    break;
+            }
+        } else {
+            return false;
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_statistics/lang_cz.php b/plugins/serendipity_event_statistics/lang_cz.php
new file mode 100644 (file)
index 0000000..4ff2a8a
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+@define('PLUGIN_EVENT_STATISTICS_NAME', 'Statistiky');
+@define('PLUGIN_EVENT_STATISTICS_DESC', 'Zobrazení statistik záznamù');
+@define('PLUGIN_EVENT_STATISTICS_OUT_STATISTICS', 'Statistiky');
+@define('PLUGIN_EVENT_STATISTICS_OUT_FIRST_ENTRY', 'První záznam');
+@define('PLUGIN_EVENT_STATISTICS_OUT_LAST_ENTRY', 'Poslední záznam');
+@define('PLUGIN_EVENT_STATISTICS_OUT_TOTAL_ENTRIES', 'Celkem záznamù');
+@define('PLUGIN_EVENT_STATISTICS_OUT_ENTRIES', 'záznamù');
+@define('PLUGIN_EVENT_STATISTICS_OUT_TOTAL_PUBLIC', ' ... publikovaných');
+@define('PLUGIN_EVENT_STATISTICS_OUT_TOTAL_DRAFTS', ' ... konceptù');
+@define('PLUGIN_EVENT_STATISTICS_OUT_CATEGORIES', 'Kategorie');
+@define('PLUGIN_EVENT_STATISTICS_OUT_CATEGORIES2', 'kategorií');
+@define('PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_CATEGORIES', 'Rozdìlení záznamù');
+@define('PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_CATEGORIES2', 'záznamù');
+@define('PLUGIN_EVENT_STATISTICS_OUT_UPLOADED_IMAGES', 'Nahraných obrázkù');
+@define('PLUGIN_EVENT_STATISTICS_OUT_UPLOADED_IMAGES2', 'obrázkù');
+@define('PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_IMAGES', 'Rozdìlení obrázkù podle typù');
+@define('PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_IMAGES2', 'souborù');
+@define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS', 'Pøijaté komentáøe');
+@define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS2', 'komentáøù');
+@define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS3', 'Nejèastìji komentované záznamy');
+@define('PLUGIN_EVENT_STATISTICS_OUT_TOPCOMMENTS', 'Nejèastìji komentující ètenáøi');
+@define('PLUGIN_EVENT_STATISTICS_OUT_LINK', 'linka');
+@define('PLUGIN_EVENT_STATISTICS_OUT_SUBSCRIBERS', 'Odbìratelé');
+@define('PLUGIN_EVENT_STATISTICS_OUT_SUBSCRIBERS2', 'odbìratelù');
+@define('PLUGIN_EVENT_STATISTICS_OUT_TOPSUBSCRIBERS', 'Nejèastìji odebírané záznamy');
+@define('PLUGIN_EVENT_STATISTICS_OUT_TOPSUBSCRIBERS2', 'odbìratelù');
+@define('PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS', 'Pøijaté odezvy');
+@define('PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS2', 'odezev');
+@define('PLUGIN_EVENT_STATISTICS_OUT_TOPTRACKBACK', 'Nejèastìji sledované záznamy');
+@define('PLUGIN_EVENT_STATISTICS_OUT_TOPTRACKBACK2', 'odezev)');
+@define('PLUGIN_EVENT_STATISTICS_OUT_TOPTRACKBACKS3', 'Nejèastìj\9aí odezvy ètenáøù');
+@define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS_PER_ARTICLE', 'poèet komentáøù na záznam');
+@define('PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS_PER_ARTICLE', 'poèet odezev na záznam');
+@define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_DAY', 'poèet záznamù za den');
+@define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_WEEK', 'poèet záznamù za týden');
+@define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_MONTH', 'poèet záznamù za mìsíc');
+@define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS_PER_ARTICLE2', 'komentáøù/záznamy');
+@define('PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS_PER_ARTICLE2', 'odezev/záznam');
+@define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_DAY2', 'záznamù/den');
+@define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_WEEK2', 'záznamù/týden');
+@define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_MONTH2', 'záznamù/mìsíc');
+@define('PLUGIN_EVENT_STATISTICS_OUT_CHARS', 'Celkový poèet znakù');
+@define('PLUGIN_EVENT_STATISTICS_OUT_CHARS2', 'znakù');
+@define('PLUGIN_EVENT_STATISTICS_OUT_CHARS_PER_ARTICLE', 'Znakù na záznam');
+@define('PLUGIN_EVENT_STATISTICS_OUT_CHARS_PER_ARTICLE2', 'znakù/záznam');
+@define('PLUGIN_EVENT_STATISTICS_OUT_LONGEST_ARTICLES', '%s nejdel\9aích záznamù');
+@define('PLUGIN_EVENT_STATISTICS_MAX_ITEMS', 'Poèet prvkù');
+@define('PLUGIN_EVENT_STATISTICS_MAX_ITEMS_DESC', 'Kolik prvkù vzít pro statistické vyhodnocení? (Default: 20)');
+?>
diff --git a/plugins/serendipity_event_statistics/lang_ja.inc.php b/plugins/serendipity_event_statistics/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..2bc9d2e
--- /dev/null
@@ -0,0 +1,64 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_EVENT_STATISTICS_NAME', '統計情報');
+        @define('PLUGIN_EVENT_STATISTICS_DESC', 'エントリパネルに興味のある統計へのリンクを加えます。');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_STATISTICS', '統計');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_FIRST_ENTRY', 'はじめのエントリ');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_LAST_ENTRY', '最後のエントリ');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOTAL_ENTRIES', '総エントリ数');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ENTRIES', 'エントリ');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOTAL_PUBLIC', ' ... 公開');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOTAL_DRAFTS', ' ... 草稿');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CATEGORIES', '総カテゴリ数');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CATEGORIES2', 'カテゴリ');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_CATEGORIES', 'エントリの配分');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_CATEGORIES2', 'エントリ');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_UPLOADED_IMAGES', 'アップロード済み総画像数');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_UPLOADED_IMAGES2', '画像');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_IMAGES', '種類別画像の配分');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_IMAGES2', 'ファイル');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS', '受信した総コメント数');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS2', 'コメント');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS3', '最も頻繁にコメントされたエントリ');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPCOMMENTS', '最も頻繁にコメントした人');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_LINK', 'リンク');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_SUBSCRIBERS', '総購読数');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_SUBSCRIBERS2', '購読');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPSUBSCRIBERS', '最も頻繁に購読されたエントリ');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPSUBSCRIBERS2', '購読');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS', '受信した総トラックバック数');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS2', 'トラックバック');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPTRACKBACK', '最も頻繁にトラックバックされたエントリ');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPTRACKBACK2', 'トラックバック');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPTRACKBACKS3', '最も頻繁にトラックバックした人');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS_PER_ARTICLE', 'エントリ毎の評価されたコメント数');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS_PER_ARTICLE', 'エントリ毎の評価されたトラックバック数');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_DAY', '一日当たりの評価されたエントリ数');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_WEEK', '一週間当たりの評価されたエントリ数');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_MONTH', '一ヶ月当たりの評価されたエントリ数');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS_PER_ARTICLE2', 'コメント/エントリ');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS_PER_ARTICLE2', 'トラックバック/エントリ');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_DAY2', 'エントリ/日');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_WEEK2', 'エントリ/週');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_MONTH2', 'エントリ/月');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CHARS', '文字の合計');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CHARS2', '文字');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CHARS_PER_ARTICLE', 'エントリ当たりの文字数');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CHARS_PER_ARTICLE2', '文字/エントリ');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_LONGEST_ARTICLES', '最長エントリトップ %s');
+        @define('PLUGIN_EVENT_STATISTICS_MAX_ITEMS', '最大項目数');
+        @define('PLUGIN_EVENT_STATISTICS_MAX_ITEMS_DESC', '統計値当たりに表示する項目数 (デフォルト: 20)');
+
+?>
diff --git a/plugins/serendipity_event_statistics/serendipity_event_statistics.php b/plugins/serendipity_event_statistics/serendipity_event_statistics.php
new file mode 100644 (file)
index 0000000..8f43c14
--- /dev/null
@@ -0,0 +1,502 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'cz':
+    case 'cs':
+        include_once S9Y_INCLUDE_PATH . 'plugins/serendipity_event_statistics/lang_cz.php';
+        break;
+
+    case 'de':
+        @define('PLUGIN_EVENT_STATISTICS_NAME', 'Statistiken');
+        @define('PLUGIN_EVENT_STATISTICS_DESC', 'Zeigt einen Link zu Statistiken in der Autorenoberfläche');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_STATISTICS', 'Statistik');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_FIRST_ENTRY', 'Erster Eintrag');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_LAST_ENTRY', 'Letzter Eintrag');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOTAL_ENTRIES', 'Insgesamt verfasste Artikel');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ENTRIES', 'Artikel');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOTAL_PUBLIC', ' ... davon öffentlich');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOTAL_DRAFTS', ' ... davon Entwürfe');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CATEGORIES', 'Vorhandene Kategorien');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CATEGORIES2', 'Kategorie(n)');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_CATEGORIES', 'Verteilung der Artikel auf Kategorien');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_CATEGORIES2', 'eingetragene(r) Artikel');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_UPLOADED_IMAGES', 'Hochgeladene Bilder');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_UPLOADED_IMAGES2', 'Bild(er)');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_IMAGES', 'Verteilung der Bild-Dateitypen');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_IMAGES2', 'vorhandene Datei(en)');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS', 'Erhaltene Kommentare');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS2', 'Kommentar(e)');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS3', 'Top kommentierte Artikel');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPCOMMENTS', 'Top Kommentatoren');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_LINK', 'Link');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_SUBSCRIBERS', 'Abonnenten');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_SUBSCRIBERS2', 'Abonnent(en)');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPSUBSCRIBERS', 'Top abonnierte Artikel');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPSUBSCRIBERS2', 'eingetragene(r) Abonnent(en)');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS', 'Erhaltene Trackbacks');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS2', 'Trackback(s)');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPTRACKBACK', 'Top Trackback-Artikel');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPTRACKBACK2', 'eingetragene(r) Trackback(s)');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPTRACKBACKS3', 'Top Trackbacker');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS_PER_ARTICLE', 'Durchschnittliche Kommentare pro Artikel');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS_PER_ARTICLE', 'Durchschnittliche Trackbacks pro Artikel');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_DAY', 'Durchschnittliche Artikel pro Tag');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_WEEK', 'Durchschnittliche Artikel pro Woche');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_MONTH', 'Durchschnittliche Artikel pro Monat');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS_PER_ARTICLE2', 'Kommentare/Artikel');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS_PER_ARTICLE2', 'Trackbacks/Artikel');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_DAY2', 'Artikel/Tag');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_WEEK2', 'Artikel/Woche');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_MONTH2', 'Artikel/Monat');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CHARS', 'Menge der verfassten Zeichen');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CHARS2', 'Zeichen');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CHARS_PER_ARTICLE', 'Zeichen pro Artikel');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CHARS_PER_ARTICLE2', 'Zeichen/Artikel');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_LONGEST_ARTICLES', 'Die %s längsten Artikel');
+        @define('PLUGIN_EVENT_STATISTICS_MAX_ITEMS', 'Anzahl Einträge');
+        @define('PLUGIN_EVENT_STATISTICS_MAX_ITEMS_DESC', 'Wieviele Einträge sollen pro Wert dargestellt werden? (Standard: 20)');
+        break;
+
+    case 'en':
+    case 'es':
+    default:
+        @define('PLUGIN_EVENT_STATISTICS_NAME', 'Statistics');
+        @define('PLUGIN_EVENT_STATISTICS_DESC', 'Adds a link to interesting statistics in your entries panel');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_STATISTICS', 'Statistics');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_FIRST_ENTRY', 'First entry');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_LAST_ENTRY', 'Last entry');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOTAL_ENTRIES', 'Total entries');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ENTRIES', 'entries');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOTAL_PUBLIC', ' ... public');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOTAL_DRAFTS', ' ... drafts');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CATEGORIES', 'Categories');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CATEGORIES2', 'categories');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_CATEGORIES', 'Distribution of entries');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_CATEGORIES2', 'entries');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_UPLOADED_IMAGES', 'Uploaded images');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_UPLOADED_IMAGES2', 'image(s)');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_IMAGES', 'Distribution of image types');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_IMAGES2', 'file(s)');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS', 'Received comments');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS2', 'comment(s)');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS3', 'Most frequently commented entries');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPCOMMENTS', 'Most frequently commenting people');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_LINK', 'link');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_SUBSCRIBERS', 'Subscribers');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_SUBSCRIBERS2', 'subscriber(s)');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPSUBSCRIBERS', 'Most frequently subscribed entries');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPSUBSCRIBERS2', 'subscriber(s)');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS', 'Received trackbacks');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS2', 'trackback(s)');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPTRACKBACK', 'Most frequently trackbacked entires');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPTRACKBACK2', 'trackback(s)');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TOPTRACKBACKS3', 'Most frequently trackbacking people');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS_PER_ARTICLE', 'estimated comments per entry');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS_PER_ARTICLE', 'estimated trackbacks per entry');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_DAY', 'estimated entries per day');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_WEEK', 'estimated entries per week');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_MONTH', 'estimated entries per month');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_COMMENTS_PER_ARTICLE2', 'comments/entries');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS_PER_ARTICLE2', 'trackbacks/entry');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_DAY2', 'entries/day');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_WEEK2', 'entries/week');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_MONTH2', 'entries/month');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CHARS', 'Total amount of characters');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CHARS2', 'characters');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CHARS_PER_ARTICLE', 'Characters per entry');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_CHARS_PER_ARTICLE2', 'chars/entry');
+        @define('PLUGIN_EVENT_STATISTICS_OUT_LONGEST_ARTICLES', 'The %s longest entries');
+        @define('PLUGIN_EVENT_STATISTICS_MAX_ITEMS', 'Maximum items');
+        @define('PLUGIN_EVENT_STATISTICS_MAX_ITEMS_DESC', 'How many items to display per statistical value? (Default: 20)');
+        break;
+}
+
+class serendipity_event_statistics extends serendipity_event
+{
+    var $title = PLUGIN_EVENT_STATISTICS_NAME;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_STATISTICS_NAME);
+        $propbag->add('description',   PLUGIN_EVENT_STATISTICS_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Garvin Hicking');
+        $propbag->add('version',       '1.0');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('event_hooks',    array(
+            'backend_sidebar_entries' => true,
+            'backend_sidebar_entries_event_display_statistics' => true
+        ));
+
+        $propbag->add('configuration', array('max_items'));
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'max_items':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_EVENT_STATISTICS_MAX_ITEMS);
+                $propbag->add('description', PLUGIN_EVENT_STATISTICS_MAX_ITEMS_DESC);
+                $propbag->add('default', 20);
+                break;
+        }
+
+        return true;
+    }
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+    function event_hook($event, &$bag, &$eventData) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+
+        if (isset($hooks[$event])) {
+            switch($event) {
+                case 'backend_sidebar_entries':
+                    // if ($serendipity['serendipityUserlevel'] >= USERLEVEL_EDITOR) {
+?>
+                        <li><a href="?serendipity[adminModule]=event_display&amp;serendipity[adminAction]=statistics"><?php echo PLUGIN_EVENT_STATISTICS_NAME; ?></a></li>
+<?php
+                    // }
+
+                    break;
+
+                case 'backend_sidebar_entries_event_display_statistics':
+                    $max_items = $this->get_config('max_items');
+
+                    if (!$max_items || !is_numeric($max_items) || $max_items < 1) {
+                        $max_items = 20;
+                    }
+
+                    $first_entry    = serendipity_db_query("SELECT timestamp FROM {$serendipity['dbPrefix']}entries ORDER BY timestamp ASC limit 1", true);
+                    $last_entry     = serendipity_db_query("SELECT timestamp FROM {$serendipity['dbPrefix']}entries ORDER BY timestamp DESC limit 1", true);
+                    $total_count    = serendipity_db_query("SELECT count(id) FROM {$serendipity['dbPrefix']}entries", true);
+                    $draft_count    = serendipity_db_query("SELECT count(id) FROM {$serendipity['dbPrefix']}entries WHERE isdraft = 'true'", true);
+                    $publish_count  = serendipity_db_query("SELECT count(id) FROM {$serendipity['dbPrefix']}entries WHERE isdraft = 'false'", true);
+                    $category_count = serendipity_db_query("SELECT count(categoryid) FROM {$serendipity['dbPrefix']}category", true);
+                    $cat_sql        = "SELECT c.category_name, count(e.id) as postings
+                                                    FROM {$serendipity['dbPrefix']}entrycat ec,
+                                                         {$serendipity['dbPrefix']}category c,
+                                                         {$serendipity['dbPrefix']}entries e
+                                                    WHERE ec.categoryid = c.categoryid AND ec.entryid = e.id
+                                                    GROUP BY ec.categoryid, c.category_name
+                                                    ORDER BY postings DESC";
+                    $category_rows  = serendipity_db_query($cat_sql);
+
+                    $image_count = serendipity_db_query("SELECT count(id) FROM {$serendipity['dbPrefix']}images", true);
+                    $image_rows = serendipity_db_query("SELECT extension, count(id) AS images FROM {$serendipity['dbPrefix']}images GROUP BY extension ORDER BY images DESC");
+
+                    $subscriber_count = count(serendipity_db_query("SELECT count(id) FROM {$serendipity['dbPrefix']}comments WHERE type = 'NORMAL' AND subscribed = 'true' GROUP BY email"));
+                    $subscriber_rows = serendipity_db_query("SELECT e.id, e.title, count(c.id) as postings
+                                                    FROM {$serendipity['dbPrefix']}comments c,
+                                                         {$serendipity['dbPrefix']}entries e
+                                                    WHERE e.id = c.entry_id AND type = 'NORMAL' AND subscribed = 'true'
+                                                    GROUP BY e.id, c.email, e.title
+                                                    ORDER BY postings DESC
+                                                    LIMIT $max_items");
+
+                    $comment_count = serendipity_db_query("SELECT count(id) FROM {$serendipity['dbPrefix']}comments WHERE type = 'NORMAL'", true);
+                    $comment_rows = serendipity_db_query("SELECT e.id, e.title, count(c.id) as postings
+                                                    FROM {$serendipity['dbPrefix']}comments c,
+                                                         {$serendipity['dbPrefix']}entries e
+                                                    WHERE e.id = c.entry_id AND type = 'NORMAL'
+                                                    GROUP BY e.id, e.title
+                                                    ORDER BY postings DESC
+                                                    LIMIT $max_items");
+
+                    $commentor_rows = serendipity_db_query("SELECT author, max(email) as email, max(url) as url, count(id) as postings
+                                                    FROM {$serendipity['dbPrefix']}comments c
+                                                    WHERE type = 'NORMAL'
+                                                    GROUP BY author
+                                                    ORDER BY postings DESC
+                                                    LIMIT $max_items");
+
+                    $tb_count = serendipity_db_query("SELECT count(id) FROM {$serendipity['dbPrefix']}comments WHERE type = 'TRACKBACK'", true);
+                    $tb_rows = serendipity_db_query("SELECT e.id, e.title, count(c.id) as postings
+                                                    FROM {$serendipity['dbPrefix']}comments c,
+                                                         {$serendipity['dbPrefix']}entries e
+                                                    WHERE e.id = c.entry_id AND type = 'TRACKBACK'
+                                                    GROUP BY e.id, e.title
+                                                    ORDER BY postings DESC
+                                                    LIMIT $max_items");
+
+                    $tbr_rows = serendipity_db_query("SELECT author, max(email) as email, max(url) as url, count(id) as postings
+                                                    FROM {$serendipity['dbPrefix']}comments c
+                                                    WHERE type = 'TRACKBACK'
+                                                    GROUP BY author
+                                                    ORDER BY postings DESC
+                                                    LIMIT $max_items");
+
+                    $length = serendipity_db_query("SELECT SUM(LENGTH(body) + LENGTH(extended)) FROM {$serendipity['dbPrefix']}entries", true);
+                    $length_rows = serendipity_db_query("SELECT id, title, (LENGTH(body) + LENGTH(extended)) as full_length FROM {$serendipity['dbPrefix']}entries ORDER BY full_length DESC LIMIT $max_items");
+
+?>
+    <h3><?php echo PLUGIN_EVENT_STATISTICS_OUT_STATISTICS; ?></h3>
+
+    <div style="margin: 5px; padding: 5px">
+    <dl>
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_FIRST_ENTRY; ?></strong></dt>
+        <dd><?php echo serendipity_formatTime(DATE_FORMAT_ENTRY . ' %H:%m', $first_entry[0]); ?></dd>
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_LAST_ENTRY; ?></strong></dt>
+        <dd><?php echo serendipity_formatTime(DATE_FORMAT_ENTRY . ' %H:%m', $last_entry[0]); ?></dd>
+        <br />
+        <hr />
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_TOTAL_ENTRIES; ?></strong></dt>
+        <dd><?php echo $total_count[0]; ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_ENTRIES; ?></dd>
+        <br />
+        <dl>
+            <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_TOTAL_PUBLIC; ?></strong></dt>
+            <dd><?php echo $publish_count[0]; ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_ENTRIES; ?></dd>
+            <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_TOTAL_DRAFTS; ?></strong></dt>
+            <dd><?php echo $draft_count[0]; ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_ENTRIES; ?></dd>
+        </dl>
+        <br />
+        <hr />
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_CATEGORIES; ?></strong></dt>
+        <dd><?php echo $category_count[0]; ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_CATEGORIES2; ?></dd>
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_CATEGORIES; ?></strong></dt>
+        <dl>
+<?php
+                    if (is_array($category_rows)) {
+                        foreach($category_rows AS $category => $cat_stat) {
+?>
+            <dt><strong><?php echo $cat_stat['category_name']; ?></strong></dt>
+            <dd><?php echo $cat_stat['postings']; ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_CATEGORIES2; ?></dd>
+<?php
+                        }
+                    }
+?>
+        </dl>
+        <br />
+        <hr />
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_UPLOADED_IMAGES; ?></strong></dt>
+        <dd><?php echo $image_count[0]; ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_UPLOADED_IMAGES2; ?></dd>
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_IMAGES; ?></strong></dt>
+        <dl>
+<?php
+                    if (is_array($image_rows)) {
+                        foreach($image_rows AS $image => $image_stat) {
+?>
+            <dt><strong><?php echo $image_stat['extension']; ?></strong></dt>
+            <dd><?php echo $image_stat['images']; ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_DISTRIBUTION_IMAGES2; ?></dd>
+<?php
+                        }
+                    }
+?>
+        </dl>
+        <br />
+        <hr />
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_COMMENTS; ?></strong></dt>
+        <dd><?php echo $comment_count[0]; ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_COMMENTS2; ?></dd>
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_COMMENTS3; ?></strong></dt>
+        <dl>
+<?php
+                    if (is_array($comment_rows)) {
+                        foreach($comment_rows AS $comment => $com_stat) {
+?>
+            <dt><strong><a href="<?php echo serendipity_archiveURL($com_stat['id'], $com_stat['title'], 'serendipityHTTPPath'); ?>"><?php echo $com_stat['title']; ?></a></strong></dt>
+            <dd><?php echo $com_stat['postings']; ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_COMMENTS2; ?></dd>
+<?php
+                        }
+                    }
+?>
+        </dl>
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_TOPCOMMENTS; ?></strong></dt>
+        <dl>
+<?php
+                    if (is_array($commentor_rows)) {
+                        foreach($commentor_rows AS $comment => $com_stat) {
+                            $link_start = '';
+                            $link_end   = '';
+                            $link_url   = '';
+
+                            if (!empty($com_stat['email'])) {
+                                $link_start = '<a href="mailto:' . htmlspecialchars($com_stat['email']) . '">';
+                                $link_end   = '</a>';
+                            }
+
+                            if (!empty($com_stat['url'])) {
+                                $link_url = ' (<a href="' . htmlspecialchars($com_stat['url']) . '">' . PLUGIN_EVENT_STATISTICS_OUT_LINK . '</a>)';
+                            }
+
+                            if (empty($com_stat['author'])) {
+                                $com_stat['author'] = ANONYMOUS;
+                            }
+?>
+            <dt><strong><?php echo $link_start . $com_stat['author'] . $link_end . $link_url; ?> </strong></dt>
+            <dd><?php echo $com_stat['postings']; ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_COMMENTS2; ?></dd>
+<?php
+                        }
+                    }
+?>
+        </dl>
+        <br />
+        <hr />
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_SUBSCRIBERS; ?></strong></dt>
+        <dd><?php echo $subscriber_count; ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_SUBSCRIBERS2; ?></dd>
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_TOPSUBSCRIBERS; ?></strong></dt>
+        <dl>
+<?php
+                    if (is_array($subscriber_rows)) {
+                        foreach($subscriber_rows AS $subscriber => $subscriber_stat) {
+?>
+            <dt><strong><a href="<?php echo serendipity_archiveURL($subscriber_stat['id'], $subscriber_stat['title'], 'serendipityHTTPPath'); ?>"><?php echo $subscriber_stat['title']; ?></a></strong></dt>
+            <dd><?php echo $subscriber_stat['postings']; ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_TOPSUBSCRIBERS2; ?></dd>
+<?php
+                        }
+                    }
+?>
+        </dl>
+        <br />
+        <hr />
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS; ?></strong></dt>
+        <dd><?php echo $tb_count[0]; ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS2; ?></dd>
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_TOPTRACKBACK; ?></strong></dt>
+        <dl>
+<?php
+                    if (is_array($tb_rows)) {
+                        foreach($tb_rows AS $tb => $tb_stat) {
+?>
+            <dt><strong><a href="<?php echo serendipity_archiveURL($tb_stat['id'], $tb_stat['title'], 'serendipityHTTPPath'); ?>"><?php echo $tb_stat['title']; ?></a></strong></dt>
+            <dd><?php echo $tb_stat['postings']; ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_TOPTRACKBACK2; ?></dd>
+<?php
+                        }
+                    }
+?>
+        </dl>
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_TOPTRACKBACKS3; ?></strong></dt>
+        <dl>
+<?php
+                    if (is_array($tbr_rows)) {
+                        foreach($tbr_rows AS $tb => $tb_stat) {
+                            if (empty($tb_stat['author'])) {
+                                $tb_stat['author'] = ANONYMOUS;
+                            }
+?>
+            <dt><strong><a href="<?php echo htmlspecialchars($tb_stat['url']); ?>"><?php echo htmlspecialchars($tb_stat['author']); ?></a></strong></dt>
+            <dd><?php echo $tb_stat['postings']; ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_TOPTRACKBACK2; ?></dd>
+<?php
+                        }
+                    }
+?>
+        </dl>
+        <br />
+        <hr />
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_COMMENTS_PER_ARTICLE; ?></strong></dt>
+        <dd><?php echo round($comment_count[0] / max($publish_count[0], 1), 2); ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_COMMENTS_PER_ARTICLE;2 ?></dd>
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS_PER_ARTICLE; ?></strong></dt>
+        <dd><?php echo round($tb_count[0] / max($publish_count[0], 1), 2); ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_TRACKBACKS_PER_ARTICLE2; ?></dd>
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_DAY; ?></strong></dt>
+        <dd><?php echo round($publish_count[0] / ((time() - $first_entry[0]) / (60*60*24)), 2);?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_DAY2; ?></dd>
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_WEEK; ?></strong></dt>
+        <dd><?php echo round($publish_count[0] / ((time() - $first_entry[0]) / (60*60*24*7)), 2);?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_WEEK2; ?></dd>
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_MONTH; ?></strong></dt>
+        <dd><?php echo round($publish_count[0] / ((time() - $first_entry[0]) / (60*60*24*31)), 2);?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_ARTICLES_PER_MONTH2; ?></dd>
+        <br />
+        <hr />
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_CHARS; ?></strong></dt>
+        <dd><?php echo $length[0]; ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_CHARS2; ?></dd>
+        <br />
+
+        <dt><strong><?php echo PLUGIN_EVENT_STATISTICS_OUT_CHARS_PER_ARTICLE; ?></strong></dt>
+        <dd><?php echo round($length[0] / max($publish_count[0], 1), 2); ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_CHARS_PER_ARTICLE2; ?></dd>
+        <br />
+
+        <dt><strong><?php printf(PLUGIN_EVENT_STATISTICS_OUT_LONGEST_ARTICLES, $max_items); ?></strong></dt>
+        <br />
+        <dl>
+<?php
+                    if (is_array($length_rows)) {
+                        foreach($length_rows AS $tb => $length_stat) {
+?>
+            <dt><strong><a href="<?php echo serendipity_archiveURL($length_stat['id'], $length_stat['title'], 'serendipityHTTPPath'); ?>"><?php echo $length_stat['title']; ?></a></strong></dt>
+            <dd><?php echo $length_stat['full_length']; ?> <?php echo PLUGIN_EVENT_STATISTICS_OUT_CHARS2; ?></dd>
+<?php
+                        }
+                    }
+?>
+        </dl>
+        <br />
+
+        <dt><strong><?php echo TOP_REFERRER; ?></strong></dt>
+        <dd><?php echo serendipity_displayTopReferrers($max_items, true); ?></dd>
+        <br />
+
+        <dt><strong><?php echo TOP_EXITS; ?></strong></dt>
+        <dd><?php echo serendipity_displayTopExits($max_items, true); ?></dd>
+    </dl>
+    <hr />
+    <?php serendipity_plugin_api::hook_event('event_additional_statistics', $eventData, array('maxitems' => $max_items)); ?>
+    </div>
+<?php
+                    return true;
+                    break;
+
+                default:
+                    return false;
+                    break;
+            }
+        } else {
+            return false;
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_templatechooser/lang_ja.inc.php b/plugins/serendipity_event_templatechooser/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..a0340a8
--- /dev/null
@@ -0,0 +1,18 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_EVENT_TEMPLATECHOOSER_NAME',     'テンプレート選択');
+        @define('PLUGIN_EVENT_TEMPLATECHOOSER_DESC',     '訪問者がすぐさまテンプレートを変更することを許可します。');
+
+?>
diff --git a/plugins/serendipity_event_templatechooser/serendipity_event_templatechooser.php b/plugins/serendipity_event_templatechooser/serendipity_event_templatechooser.php
new file mode 100644 (file)
index 0000000..15c96a2
--- /dev/null
@@ -0,0 +1,85 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_TEMPLATECHOOSER_NAME',     'Templateauswahl');
+        @define('PLUGIN_EVENT_TEMPLATECHOOSER_DESC',     'Ermöglicht Besuchern das Template zu ändern');
+        break;
+
+    case 'en':
+    default:
+        @define('PLUGIN_EVENT_TEMPLATECHOOSER_NAME',     'Template chooser');
+        @define('PLUGIN_EVENT_TEMPLATECHOOSER_DESC',     'Allows your visitors to change template on the fly');
+        break;
+}
+
+class serendipity_event_templatechooser extends serendipity_event
+{
+    var $title = PLUGIN_EVENT_TEMPLATECHOOSER_NAME;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',        PLUGIN_EVENT_TEMPLATECHOOSER_NAME);
+        $propbag->add('description', PLUGIN_EVENT_TEMPLATECHOOSER_DESC);
+        $propbag->add('stackable',   false);
+        $propbag->add('author',      'Evan Nemerson');
+        $propbag->add('version',     '1.1');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('event_hooks', array('frontend_configure' => true));
+
+        // Register (multiple) dependencies. KEY is the name of the depending plugin. VALUE is a mode of either 'remove' or 'keep'.
+        // If the mode 'remove' is set, removing the plugin results in a removal of the depending plugin. 'Keep' meens to
+        // not touch the depending plugin.
+        $this->dependencies = array('serendipity_plugin_templatedropdown' => 'remove');
+    }
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+    function event_hook($event, &$bag, &$eventData) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+
+        if (isset($hooks[$event])) {
+            switch($event) {
+              case 'frontend_configure':
+
+                if (isset($_REQUEST['user_template']) && (in_array($_REQUEST['user_template'], serendipity_fetchTemplates())) ) {
+                    $_SESSION['serendipityUseTemplate'] = $_REQUEST['user_template'];
+                }
+
+                if (isset($_SESSION['serendipityUseTemplate']) ) {
+                    $templateInfo = serendipity_fetchTemplateInfo($_SESSION['serendipityUseTemplate']);
+                    $eventData['template'] = $_SESSION['serendipityUseTemplate'];
+                    $eventData['template_engine'] = isset($templateInfo['engine']) ? $templateInfo['engine'] : $serendipity['defaultTemplate'];
+                }
+
+                return true;
+                break;
+
+              default:
+                return false;
+            }
+
+        } else {
+            return false;
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_textile/lang_ja.inc.php b/plugins/serendipity_event_textile/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..eb8ee29
--- /dev/null
@@ -0,0 +1,19 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_EVENT_TEXTILE_NAME', 'マークアップ: テクスタイル');
+        @define('PLUGIN_EVENT_TEXTILE_DESC', 'テクスタールコンバーターを通して出力をすべて解析します。');
+        @define('PLUGIN_EVENT_TEXTILE_TRANSFORM', '<a href="http://www.textism.com/tools/textile/">テクスタイル</a> 書式を許可します。');
+
+?>
diff --git a/plugins/serendipity_event_textile/serendipity_event_textile.php b/plugins/serendipity_event_textile/serendipity_event_textile.php
new file mode 100644 (file)
index 0000000..8cb88be
--- /dev/null
@@ -0,0 +1,239 @@
+<?php # $Id$
+
+require_once S9Y_INCLUDE_PATH . 'plugins/serendipity_event_textile/textile.php';
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_TEXTILE_NAME',     'Textformatierung: Textile');
+        @define('PLUGIN_EVENT_TEXTILE_DESC',     'Textile-Formatierung durchführen');
+        @define('PLUGIN_EVENT_TEXTILE_TRANSFORM', '<a href="http://www.textism.com/tools/textile/">Textile</a>-Formatierung erlaubt');
+        break;
+
+    case 'en':
+    default:
+        @define('PLUGIN_EVENT_TEXTILE_NAME', 'Markup: Textile');
+        @define('PLUGIN_EVENT_TEXTILE_DESC', 'Parse all output through the Textile converter');
+        @define('PLUGIN_EVENT_TEXTILE_TRANSFORM', '<a href="http://www.textism.com/tools/textile/">Textile</a>-formatting allowed');
+        break;
+}
+
+class serendipity_event_textile extends serendipity_event
+{
+    var $title = PLUGIN_EVENT_TEXTILE_NAME;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_TEXTILE_NAME);
+        $propbag->add('description',   PLUGIN_EVENT_TEXTILE_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Serendipity Team');
+        $propbag->add('version',       '1.1');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('cachable_events', array('frontend_display' => true));
+        $propbag->add('event_hooks',   array('frontend_display' => true, 'frontend_comment' => true));
+
+        $propbag->add('preserve_tags',
+          array(
+            'php',
+            'output',
+            'name'
+          )
+        );
+
+        $this->markup_elements = array(
+            array(
+              'name'     => 'ENTRY_BODY',
+              'element'  => 'body',
+            ),
+            array(
+              'name'     => 'EXTENDED_BODY',
+              'element'  => 'extended',
+            ),
+            array(
+              'name'     => 'COMMENT',
+              'element'  => 'comment',
+            ),
+            array(
+              'name'     => 'HTML_NUGGET',
+              'element'  => 'html_nugget',
+            )
+        );
+
+        $conf_array = array();
+        foreach($this->markup_elements as $element) {
+            $conf_array[] = $element['name'];
+        }
+        $propbag->add('configuration', $conf_array);
+    }
+
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+    function install() {
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function uninstall() {
+        serendipity_plugin_api::hook_event('backend_cache_purge', $this->title);
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        $propbag->add('type',        'boolean');
+        $propbag->add('name',        constant($name));
+        $propbag->add('description', sprintf(APPLY_MARKUP_TO, constant($name)));
+        $propbag->add('default', 'true');
+        return true;
+    }
+
+
+    function event_hook($event, &$bag, &$eventData) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+
+        if (isset($hooks[$event])) {
+            switch($event) {
+              case 'frontend_display':
+
+                $preserve_tags = &$bag->get('preserve_tags');
+
+                foreach ($this->markup_elements as $temp) {
+                    if (serendipity_db_bool($this->get_config($temp['name'], true))) {
+                        $element = $temp['element'];
+
+        /* find all the tags and store them in $blocks */
+
+                        $blocks = array();
+                        foreach($preserve_tags as $tag) {
+                            if (preg_match_all('/(<'.$tag.'[^>]?>.*<\/'.$tag.'>)/msU', $eventData[$element], $matches )) {
+                                foreach($matches[1] as $match) {
+                                    $blocks[] = $match;
+                                }
+                            }
+                        }
+
+        /* replace all the blocks with some code */
+
+                        foreach($blocks as $id=>$block) {
+                            $eventData[$element] = str_replace($block, '@BLOCK::'.$id.'@', $eventData[$element]);
+                        }
+
+        /* textile it */
+
+                        $eventData[$element] = textile($eventData[$element]);
+
+        /* each block will now be "<code>BLOCK::2</code>"
+         * so look for those place holders and replace
+         * them with the original blocks */
+
+                        if (preg_match_all('/<code>BLOCK::(\d+)<\/code>/', $eventData[$element], $matches )) {
+                            foreach($matches[1] as $key=>$match) {
+                                $eventData[$element] = str_replace($matches[0][$key], $blocks[$match], $eventData[$element]);
+                            }
+                        }
+
+        /* post-process each block */
+
+                        foreach($preserve_tags as $tag) {
+                            $method = '_process_tag_' . $tag;
+                            if (method_exists($this,$method)) {
+                                if (preg_match_all('/<'.$tag.'[^>]?>(.*)<\/'.$tag.'>/msU', $eventData[$element], $matches )) {
+                                    foreach($matches[1] as $key=>$match) {
+                                        $eventData[$element] = str_replace($matches[0][$key], $this->$method($match), $eventData[$element]);
+                                    }
+                                }
+                            }
+                        }
+
+        /* end textile processing */
+
+                    }
+                }
+                return true;
+
+                case 'frontend_comment':
+                    if (serendipity_db_bool($this->get_config('COMMENT', true))) {
+                        echo '<div class="serendipity_commentDirection">' . PLUGIN_EVENT_TEXTILE_TRANSFORM . '</div>';
+                    }
+                    return true;
+                    break;
+
+                default:
+                  return false;
+            }
+
+        } else {
+
+            return false;
+
+        }
+
+    }
+
+    function _process_tag_php($text) {
+
+        $code = "<?php\n" . trim($text) . "\n?>";
+
+        # Using OB, as highlight_string() only supports
+        # returning the result from 4.2.0
+
+        ob_start();
+        highlight_string($code);
+        $highlighted = ob_get_contents();
+        ob_end_clean();
+
+        # Fix output to use CSS classes and wrap well
+
+        $highlighted = '<p><div class="phpcode">' . str_replace(
+            array(
+                '&nbsp;',
+                '<br />',
+                '<font color="',
+                '</font>',
+                "\n ",
+                'Ê '
+            ),
+            array(
+                ' ',
+                "<br />\n",
+                '<span class="',
+                '</span>',
+                "\n&#160;",
+                '&#160; '
+            ),
+            $highlighted
+        ) . '</div></p>';
+
+        return $highlighted;
+
+    }
+
+
+    function _process_tag_output($text) {
+        return '<p><pre class="output">' . $text . '</pre></p>';
+    }
+
+    function _process_tag_name($text) {
+        return '<a name="'. $text . '"></a>';
+    }
+
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_textile/textile.php b/plugins/serendipity_event_textile/textile.php
new file mode 100644 (file)
index 0000000..4d528ed
--- /dev/null
@@ -0,0 +1,1096 @@
+<?php
+
+/*
+
+This is Textile
+A Humane Web Text Generator
+
+Version 2.0 beta
+8 July, 2003
+
+Copyright (c) 2003, Dean Allen, www.textism.com
+All rights reserved.
+
+_______
+LICENSE
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* Neither the name Textile nor the names of its contributors may be used to
+  endorse or promote products derived from this software without specific
+  prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+_____________
+USING TEXTILE
+
+Block modifier syntax:
+
+    Header: h(1-6).
+    Paragraphs beginning with 'hn. ' (where n is 1-6) are wrapped in header tags.
+    Example: h1. Header... -> <h1>Header...</h1>
+
+    Paragraph: p. (also applied by default)
+    Example: p. Text -> <p>Text</p>
+
+    Blockquote: bq.
+    Example: bq. Block quotation... -> <blockquote>Block quotation...</blockquote>
+
+    Blockquote with citation: bq.:http://citation.url
+    Example: bq.:http://textism.com/ Text...
+    ->    <blockquote cite="http://textism.com">Text...</blockquote>
+
+    Footnote: fn(1-100).
+    Example: fn1. Footnote... -> <p id="fn1">Footnote...</p>
+
+    Numeric list: #, ##
+    Consecutive paragraphs beginning with # are wrapped in ordered list tags.
+    Example: <ol><li>ordered list</li></ol>
+
+    Bulleted list: *, **
+    Consecutive paragraphs beginning with * are wrapped in unordered list tags.
+    Example: <ul><li>unordered list</li></ul>
+
+Phrase modifier syntax:
+
+            _emphasis_   ->   <em>emphasis</em>
+            __italic__   ->   <i>italic</i>
+              *strong*   ->   <strong>strong</strong>
+              **bold**   ->   <b>bold</b>
+          ??citation??   ->   <cite>citation</cite>
+        -deleted text-   ->   <del>deleted</del>
+       +inserted text+   ->   <ins>inserted</ins>
+         ^superscript^   ->   <sup>superscript</sup>
+           ~subscript~   ->   <sub>subscript</sub>
+                @code@   ->   <code>computer code</code>
+           %(bob)span%   ->   <span class="bob">span</span>
+
+         ==notextile==   ->   leave text alone (do not format)
+
+        "linktext":url   ->   <a href="url">linktext</a>
+ "linktext(title)":url   ->   <a href="url" title="title">linktext</a>
+
+            !imageurl!   ->   <img src="imageurl" />
+  !imageurl(alt text)!   ->   <img src="imageurl" alt="alt text" />
+    !imageurl!:linkurl   ->   <a href="linkurl"><img src="imageurl" /></a>
+
+ABC(Always Be Closing)   ->   <acronym title="Always Be Closing">ABC</acronym>
+
+
+Table syntax:
+
+    Simple tables:
+
+        |a|simple|table|row|
+        |And|Another|table|row|
+
+        |_. A|_. table|_. header|_.row|
+        |A|simple|table|row|
+
+    Tables with attributes:
+
+        table{border:1px solid black}.
+        {background:#ddd;color:red}. |{}| | | |
+
+
+Applying Attributes:
+
+    Most anywhere Textile code is used, attributes such as arbitrary css style,
+    css classes, and ids can be applied. The syntax is fairly consistent.
+
+    The following characters quickly alter the alignment of block elements:
+
+        <  ->  left align    ex. p<. left-aligned para
+        >  ->  right align       h3>. right-aligned header 3
+        =  ->  centred           h4=. centred header 4
+        <> ->  justified         p<>. justified paragraph
+
+    These will change vertical alignment in table cells:
+
+        ^  ->  top          ex. |^. top-aligned table cell|
+        -  ->  middle           |-. middle aligned|
+        ~  ->  bottom           |~. bottom aligned cell|
+
+    Plain (parentheses) inserted between block syntax and the closing dot-space
+    indicate classes and ids:
+
+        p(hector). paragraph -> <p class="hector">paragraph</p>
+
+        p(#fluid). paragraph -> <p id="fluid">paragraph</p>
+
+        (classes and ids can be combined)
+        p(hector#fluid). paragraph -> <p class="hector" id="fluid">paragraph</p>
+
+    Curly {brackets} insert arbitrary css style
+
+        p{line-height:18px}. paragraph -> <p style="line-height:18px">paragraph</p>
+
+        h3{color:red}. header 3 -> <h3 style="color:red">header 3</h3>
+
+    Square [brackets] insert language attributes
+
+        p[no]. paragraph -> <p lang="no">paragraph</p>
+
+        %[fr]phrase% -> <span lang="fr">phrase</span>
+
+    Usually Textile block element syntax requires a dot and space before the block
+    begins, but since lists don't, they can be styled just using braces
+
+        #{color:blue} one  ->  <ol style="color:blue">
+        # big                   <li>one</li>
+        # list                  <li>big</li>
+                                <li>list</li>
+                               </ol>
+
+    Using the span tag to style a phrase
+
+        It goes like this, %{color:red}the fourth the fifth%
+        -> It goes like this, <span style="color:red">the fourth the fifth</span>
+
+*/
+
+        $textile_hlgn = "(?:\<(?!>)|(?<!<)\>|\<\>|\=|[()]+)";
+        $textile_vlgn = "[\-^~]";
+        $textile_clas = "(?:\([^)]+\))";
+        $textile_lnge = "(?:\[[^]]+\])";
+        $textile_styl = "(?:\{[^}]+\})";
+        $textile_cspn = "(?:\\\\\d+)";
+        $textile_rspn = "(?:\/\d+)";
+        $textile_a = "(?:$textile_hlgn?$textile_vlgn?|$textile_vlgn?$textile_hlgn?)";
+        $textile_s = "(?:$textile_cspn?$textile_rspn?|$textile_rspn?$textile_cspn?)";
+        $textile_c = "(?:$textile_clas?$textile_styl?$textile_lnge?|$textile_styl?$textile_lnge?$textile_clas?|$textile_lnge?$textile_styl?$textile_clas?)";
+        $textile_pnct = '[\!"#\$%&\'()\*\+,\-\./:;<=>\?@\[\\\]\^_`{\|}\~]';
+
+    function textile($text,$lite='') {
+
+        if (get_magic_quotes_gpc()==1)
+            $text = stripslashes($text);
+
+        $text = textile_incomingEntities($text);
+        $text = textile_encodeEntities($text);
+        $text = textile_fixEntities($text);
+        $text = textile_cleanWhiteSpace($text);
+
+        $text = textile_getRefs($text);
+
+        $text = textile_noTextile($text);
+        $text = textile_image($text);
+        $text = textile_links($text);
+        $text = textile_code($text);
+        $text = textile_span($text);
+        $text = textile_superscript($text);
+        $text = textile_footnoteRef($text);
+        $text = textile_glyphs($text);
+        $text = textile_retrieve($text);
+
+        if ($lite=='') {
+            $text = textile_lists($text);
+            $text = textile_table($text);
+            $text = textile_block($text);
+        }
+
+            /* clean up <notextile> */
+        $text = preg_replace('/<\/?notextile>/', "",$text);
+
+            /* turn the temp char back to an ampersand entity */
+        $text = str_replace("x%x%","&#38;",$text);
+
+        $text = str_replace("<br />","<br />\n",$text);
+
+        return trim($text);
+    }
+
+// -------------------------------------------------------------
+    function textile_pba($in,$element="") // "parse block attributes"
+    {
+        global $textile_hlgn,$textile_vlgn,$textile_clas,$textile_styl,$textile_cspn,$textile_rspn,$textile_a,$textile_s,$textile_c;
+
+        $textile_style=''; $textile_class=''; $language=''; $textile_colspan=''; $rowspan=''; $id=''; $textile_atts='';
+
+        if (!empty($in)) {
+            $matched = $in;
+            if($element=='td'){
+                if(preg_match("/\\\\(\d+)/",$matched,$textile_csp)) $textile_colspan=$textile_csp[1];
+                if(preg_match("/\/(\d+)/",$matched,$rsp)) $rowspan=$rsp[1];
+
+                if (preg_match("/($textile_vlgn)/",$matched,$vert))
+                    $textile_style[] = "vertical-align:".textile_vAlign($vert[1]).";";
+            }
+
+            if(preg_match("/\{([^}]*)\}/",$matched,$textile_sty)) {
+                $textile_style[]=$textile_sty[1].';';
+                $matched = str_replace($textile_sty[0],'',$matched);
+            }
+
+            if(preg_match("/\[([^)]+)\]/U",$matched,$lng)) {
+                $language=$lng[1];
+                $matched = str_replace($lng[0],'',$matched);
+            }
+
+            if(preg_match("/\(([^()]+)\)/U",$matched,$textile_cls)) {
+                $textile_class=$textile_cls[1];
+                $matched = str_replace($textile_cls[0],'',$matched);
+            }
+
+            if(preg_match("/([(]+)/",$matched,$pl)) {
+                $textile_style[] = "padding-left:".strlen($pl[1])."em;";
+                $matched = str_replace($pl[0],'',$matched);
+            }
+            if(preg_match("/([)]+)/",$matched,$pr)) {
+                dump($pr);
+                $textile_style[] = "padding-right:".strlen($pr[1])."em;";
+                $matched = str_replace($pr[0],'',$matched);
+            }
+
+            if (preg_match("/($textile_hlgn)/",$matched,$horiz))
+                $textile_style[] = "text-align:".textile_hAlign($horiz[1]).";";
+
+            if (preg_match("/^(.*)#(.*)$/",$textile_class,$ids)) {
+                $id = $ids[2];
+                $textile_class = $ids[1];
+            }
+
+            if($textile_style) $textile_atts.=' style="'.join("",$textile_style).'"';
+            if($textile_class) $textile_atts.=' class="'.$textile_class.'"';
+            if($language) $textile_atts.=' lang="'.$language.'"';
+            if($id) $textile_atts.=' id="'.$id.'"';
+            if($textile_colspan) $textile_atts.=' colspan="'.$textile_colspan.'"';
+            if($rowspan) $textile_atts.=' rowspan="'.$rowspan.'"';
+
+            return $textile_atts;
+        } else {
+            return '';
+        }
+    }
+
+// -------------------------------------------------------------
+    function textile_table($text)
+    {
+        global $textile_a,$textile_c,$textile_s;
+        $text = $text."\n\n";
+        return preg_replace_callback("/^(?:table(_?$textile_s$textile_a$textile_c)\. ?\n)?^($textile_a$textile_c\.? ?\|.*\|)\n\n/smU",
+            "textile_fTable",$text);
+    }
+
+// -------------------------------------------------------------
+    function textile_fTable($matches)
+    {
+        global $textile_s,$textile_a,$textile_c;
+        $tatts = textile_pba($matches[1],'table');
+
+           foreach(preg_split("/\|$/m",$matches[2],-1,PREG_SPLIT_NO_EMPTY) as $row){
+            if (preg_match("/^($textile_a$textile_c\. )(.*)/m",$row,$rmtch)) {
+                $ratts = pba($rmtch[1],'tr');
+                $row = $rmtch[2];
+            } else $ratts = '';
+
+            foreach(explode("|",$row) as $textile_cell){
+                $textile_ctyp = "d";
+                if (preg_match("/^_/",$textile_cell)) $textile_ctyp = "h";
+                if (preg_match("/^(_?$textile_s$textile_a$textile_c\. )(.*)/",$textile_cell,$textile_cmtch)) {
+                    $textile_catts = pba($textile_cmtch[1],'td');
+                    $textile_cell = $textile_cmtch[2];
+                } else $textile_catts = '';
+
+                if(trim($textile_cell)!='')
+                    $textile_cells[] = "\t\t\t<t$textile_ctyp$textile_catts>$textile_cell</t$textile_ctyp>";
+            }
+            $rows[] = "\t\t<tr$ratts>\n".join("\n",$textile_cells)."\n\t\t</tr>";
+            unset($textile_cells,$textile_catts);
+        }
+        return "\t<table$tatts>\n".join("\n",$rows)."\n\t</table>\n\n";
+    }
+
+
+// -------------------------------------------------------------
+    function textile_lists($text)
+    {
+        global $textile_a,$textile_c;
+        return preg_replace_callback("/^([#*]+$textile_c .*)$(?![^#*])/smU","textile_fList",$text);
+    }
+
+// -------------------------------------------------------------
+    function textile_fList($m)
+    {
+        global $textile_a,$textile_c;
+        $text = explode("\n",$m[0]);
+        foreach($text as $line){
+            $nextline = next($text);
+            if(preg_match("/^([#*]+)($textile_a$textile_c) (.*)$/s",$line,$m)) {
+                list(,$tl,$textile_atts,$textile_content) = $m;
+                $nl = preg_replace("/^([#*]+)\s.*/","$1",$nextline);
+                if(!isset($lists[$tl])){
+                    $lists[$tl] = true;
+                    $textile_atts = textile_pba($textile_atts);
+                    $line = "\t<".textile_lT($tl)."l$textile_atts>\n\t<li>".$textile_content;
+                } else {
+                    $line = "\t\t<li>".$textile_content;
+                }
+
+                if ($nl===$tl){
+                    $line .= "</li>";
+                } elseif($nl=="*" or $nl=="#") {
+                    $line .= "</li>\n\t</".textile_lT($tl)."l>\n\t</li>";
+                    unset($lists[$tl]);
+                }
+                if (!$nl) {
+                    foreach($lists as $k=>$v){
+                        $line .= "</li>\n\t</".textile_lT($k)."l>";
+                        unset($lists[$k]);
+                    }
+                }
+            }
+            $out[] = $line;
+        }
+        return join("\n",$out);
+    }
+
+// -------------------------------------------------------------
+    function textile_lT($in)
+    {
+        return preg_match("/^#+/",$in) ? 'o' : 'u';
+    }
+
+// -------------------------------------------------------------
+    function textile_block($text)
+    {
+        global $textile_a,$textile_c;
+
+        $pre = false;
+        $find = array('bq','h[1-6]','fn\d+','p');
+
+        $text = preg_replace("/(.+)\n(?![#*\s|])/",
+            "$1<br />", $text);
+
+        $text = explode("\n",$text);
+        array_push($text," ");
+
+        foreach($text as $line) {
+            if (preg_match('/<pre>/i',$line)) { $pre = true; }
+            foreach($find as $tag){
+                $line = ($pre==false)
+                ?    preg_replace_callback("/^($tag)($textile_a$textile_c)\.(?::(\S+))? (.*)$/",
+                        "textile_fBlock",$line)
+                :    $line;
+            }
+
+            $line = preg_replace('/^(?!\t|<\/?pre|<\/?code|$| )(.*)/',"\t<p>$1</p>",$line);
+
+            $line=($pre==true) ? str_replace("<br />","\n",$line):$line;
+            if (preg_match('/<\/pre>/i',$line)) { $pre = false; }
+
+            $out[] = $line;
+        }
+        return join("\n",$out);
+    }
+
+// -------------------------------------------------------------
+    function textile_fBlock($m)
+    {
+#        dump($m);
+        list(,$tag,$textile_atts,$textile_cite,$textile_content) = $m;
+
+        $textile_atts = textile_pba($textile_atts);
+
+        if(preg_match("/fn(\d+)/",$tag,$fns)){
+            $tag = 'p';
+            $textile_atts.= ' id="fn'.$fns[1].'"';
+            $textile_content = '<sup>'.$fns[1].'</sup> '.$textile_content;
+        }
+
+        $textile_start = "\t<$tag";
+        $end = "</$tag>";
+
+        if ($tag=="bq") {
+            $textile_cite = textile_checkRefs($textile_cite);
+            $textile_cite = ($textile_cite!='') ? ' cite="'.$textile_cite.'"' : '';
+            $textile_start = "\t<blockquote$textile_cite>\n\t\t<p";
+            $end = "</p>\n\t</blockquote>";
+        }
+
+        return "$textile_start$textile_atts>$textile_content$end";
+    }
+
+
+// -------------------------------------------------------------
+    function textile_span($text)
+    {
+        global $textile_c,$textile_pnct;
+        $qtags = array('\*\*','\*','\?\?','-','__','_','%','\+','~');
+
+        foreach($qtags as $f) {
+            $text = preg_replace_callback(
+                "/(?<=^|\s|\>|[[:punct:]]|[{(\[])
+                ($f)
+                ($textile_c)
+                (?::(\S+))?
+                (\w.+\w)
+                ([[:punct:]]*)
+                $f
+                (?=[])}]|[[:punct:]]+|\s|$)
+            /xmU","textile_fSpan",$text);
+        }
+        return $text;
+    }
+
+// -------------------------------------------------------------
+    function textile_fSpan($m)
+    {
+#        dump($m);
+        global $textile_c;
+        $qtags = array(
+            '*'   => 'b',
+            '**'  => 'strong',
+            '??'  => 'cite',
+            '_'   => 'em',
+            '__'  => 'i',
+            '-'   => 'del',
+            '%'   => 'span',
+            '+'   => 'ins',
+            '~'   => 'sub');
+
+            list(,$tag,$textile_atts,$textile_cite,$textile_content,$end) = $m;
+            $tag = $qtags[$tag];
+            $textile_atts = textile_pba($textile_atts);
+            $textile_atts.= ($textile_cite!='') ? 'cite="'.$textile_cite.'"' : '';
+
+        return "<$tag$textile_atts>$textile_content$end</$tag>";
+    }
+
+// -------------------------------------------------------------
+    function textile_links($text)
+    {
+        global $textile_c;
+        return preg_replace_callback('/
+            ([\s[{(]|[[:punct:]])?     # $pre
+            "                          # start
+            ('.$textile_c.')                   # $textile_atts
+            ([^"]+)                  # $text
+            \s?
+            (?:\(([^)]+)\)(?="))?    # $title
+            ":
+            (\S+\b)                    # $url
+            (\/)?                      # $textile_slash
+            ([^\w\/;]*)                # $post
+            (?=\s|$)
+        /Ux',"textile_fLink",$text);
+    }
+
+// -------------------------------------------------------------
+    function textile_fLink($m)
+    {
+        list(,$pre,$textile_atts,$text,$title,$url,$textile_slash,$post) = $m;
+
+        $url = textile_checkRefs($url);
+
+        $textile_atts = textile_pba($textile_atts);
+        $textile_atts.= ($title!='') ? ' title="'.$title.'"' : '';
+
+        $textile_atts = ($textile_atts!='') ? textile_shelve($textile_atts) : '';
+
+        if ($text=='_') {
+            $text = $url;
+        }
+
+        if (preg_match('/^http(s?):\/\//i', $url)) {
+            $textile_atts.=' class="external"';
+        }
+
+        return $pre.'<a href="'.$url.$textile_slash.'"'.$textile_atts.'>'.$text.'</a>'.$post;
+
+    }
+
+// -------------------------------------------------------------
+    function textile_getRefs($text)
+    {
+        return preg_replace_callback("/(?<=^|\s)\[(.+)\]((?:http:\/\/|\/)\S+)(?=\s|$)/U",
+            "textile_refs",$text);
+    }
+
+// -------------------------------------------------------------
+    function textile_refs($m)
+    {
+        list(,$flag,$url) = $m;
+        $GLOBALS['urlrefs'][$flag] = $url;
+        return '';
+    }
+
+// -------------------------------------------------------------
+    function textile_checkRefs($text)
+    {
+        global $urlrefs;
+        return (isset($urlrefs[$text])) ? $urlrefs[$text] : $text;
+    }
+
+// -------------------------------------------------------------
+    function textile_image($text)
+    {
+        global $textile_c;
+        return preg_replace_callback("/
+            \!                   # opening
+            (\<|\=|\>)?          # optional alignment atts
+            ($textile_c)                 # optional style,class atts
+            (?:\. )?             # optional dot-space
+            ([^\s(!]+)           # presume this is the src
+            \s?                  # optional space
+            (?:\(([^\)]+)\))?    # optional title
+            \!                   # closing
+            (?::(\S+))?          # optional href
+            (?=\s|$)             # lookahead: space or end of string
+        /Ux","textile_fImage",$text);
+    }
+
+// -------------------------------------------------------------
+    function textile_fImage($m)
+    {
+        list(,$textile_algn,$textile_atts,$url) = $m;
+        $textile_atts = textile_pba($textile_atts);
+        $textile_atts.= ($textile_algn!='') ? ' align="'.textile_iAlign($textile_algn).'"' : '';
+        $textile_atts.= (isset($m[4])) ? ' title="'.$m[4].'"' : '';
+        $textile_size = @getimagesize($url);
+        if($textile_size) $textile_atts.= " $textile_size[3]";
+
+        $href = (isset($m[5])) ? textile_checkRefs($m[5]) : '';
+        $url = textile_checkRefs($url);
+
+        $out = '';
+        $out.= ($href!='') ? '<a href="'.$href.'">' : '';
+        $out.= '<img src="'.$url.'"'.$textile_atts.' />';
+        $out.= ($href!='') ? '</a>' : '';
+
+        return $out;
+    }
+
+// -------------------------------------------------------------
+    function textile_code($text)
+    {
+        global $textile_pnct;
+        return preg_replace_callback("/
+            (?:^|(?<=[\s\(])|([[{]))         # 1 open bracket?
+            @                                # opening
+            (?:\|(\w+)\|)?                   # 2 language
+            (.+)                             # 3 code
+            @                                # closing
+            (?:$|([\]}])|
+            (?=[[:punct:]]{1,2}|
+            \s))                             # 4 closing bracket?
+        /Ux","textile_fCode",$text);
+    }
+
+// -------------------------------------------------------------
+    function textile_fCode($m)
+    {
+        list(,$before,$lang,$textile_code,$textile_after) = $m;
+        $lang = ($lang!='') ? ' language="'.$lang.'"' : '';
+        return $before.'<code'.$lang.'>'.$textile_code.'</code>'.$textile_after;
+    }
+
+// -------------------------------------------------------------
+    function textile_shelve($val)
+    {
+        $GLOBALS['shelf'][] = $val;
+        return ' <'.count($GLOBALS['shelf']).'>';
+    }
+
+// -------------------------------------------------------------
+    function textile_retrieve($text)
+    {
+        global $textile_shelf;
+          $i = 0;
+        if(is_array($textile_shelf)) {
+        foreach($textile_shelf as $r){
+            $i++;
+            $text = str_replace("<$i>",$r,$text);
+        }
+        }
+            return $text;
+    }
+
+// -------------------------------------------------------------
+    function textile_incomingEntities($text)
+    {
+        /*  turn any incoming ampersands into a dummy character for now.
+            This uses a negative lookahead for alphanumerics followed by a semicolon,
+            implying an incoming html entity, to be skipped */
+
+        return preg_replace("/&(?![#a-z0-9]+;)/i","x%x%",$text);
+    }
+
+// -------------------------------------------------------------
+    function textile_encodeEntities($text)
+    {
+        /*  Convert high and low ascii to entities. If multibyte string functions are
+            available (on by default in php 4.3+), we convert using unicode mapping as
+            defined in the function encode_high(). If not, we use php's nasty
+            built-in htmlentities() */
+
+        return (function_exists('mb_encode_numericentity'))
+        ?    textile_encode_high($text)
+        :    htmlentities($text,ENT_NOQUOTES,"utf-8");
+    }
+
+// -------------------------------------------------------------
+    function textile_fixEntities($text)
+    {
+        /*  de-entify any remaining angle brackets or ampersands */
+        return str_replace(array("&gt;", "&lt;", "&amp;"),
+            array(">", "<", "&"), $text);
+    }
+
+// -------------------------------------------------------------
+    function textile_cleanWhiteSpace($text)
+    {
+        $out = str_replace(array("\r\n","\t"), array("\n",''), $text);
+        $out = preg_replace("/\n{3,}/","\n\n",$out);
+        $out = preg_replace("/\n *\n/","\n\n",$out);
+        $out = preg_replace('/"$/',"\" ", $out);
+        return $out;
+    }
+
+// -------------------------------------------------------------
+    function textile_noTextile($text)
+    {
+        return preg_replace('/(^|\s)==(.*)==(\s|$)?/msU',
+            '$1<notextile>$2</notextile>$3',$text);
+    }
+
+// -------------------------------------------------------------
+    function textile_superscript($text)
+    {
+        return preg_replace('/\^(.*)\^/mU','<sup>$1</sup>',$text);
+    }
+
+// -------------------------------------------------------------
+    function textile_footnoteRef($text)
+    {
+        return preg_replace('/\b\[([0-9]+)\](\s)?/U',
+            '<sup><a href="#fn$1">$1</a></sup>$2',$text);
+    }
+
+// -------------------------------------------------------------
+    function textile_glyphs($text)
+    {
+            // fix: hackish
+        $text = preg_replace('/"\z/',"\" ", $text);
+
+        $glyph_search = array(
+        '/([^\s[{(>])?\'(?(1)|(?=\s|s\b|[[:punct:]]))/',        //  single closing
+        '/\'/',                                                 //  single opening
+        '/([^\s[{(>])?"(?(1)|(?=\s|[[:punct:]]))/',             //  double closing
+        '/"/',                                                  //  double opening
+        '/\b( )?\.{3}/',                                        //  ellipsis
+        '/\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])/',           //  3+ uppercase acronym
+        '/(^|[^"][>\s])([A-Z][A-Z0-9 ]{2,})([^<a-z0-9]|$)/',    //  3+ uppercase caps
+        '/\s?--\s?/',                                           //  em dash
+        '/\s-\s/',                                              //  en dash
+        '/(\d+) ?x ?(\d+)/',                                    //  dimension sign
+        '/\b ?[([]TM[])]/i',                                    //  trademark
+        '/\b ?[([]R[])]/i',                                     //  registered
+        '/\b ?[([]C[])]/i');                                    //  copyright
+
+    $glyph_replace = array(
+        '$1&#8217;$2',                          //  single closing
+        '&#8216;',                              //  single opening
+        '$1&#8221;',                            //  double closing
+        '&#8220;',                              //  double opening
+        '$1&#8230;',                            //  ellipsis
+        '<acronym title="$2">$1</acronym>',     //  3+ uppercase acronym
+        '$1<span class="caps">$2</span>$3',     //  3+ uppercase caps
+        '&#8212;',                              //  em dash
+        ' &#8211; ',                            //  en dash
+        '$1&#215;$2',                           //  dimension sign
+        '&#8482;',                              //  trademark
+        '&#174;',                               //  registered
+        '&#169;');                              //  copyright
+
+
+    $textile_codepre = false;
+        /*  if no html, do a simple search and replace... */
+    if (!preg_match("/<.*>/",$text)) {
+        $text = preg_replace($glyph_search,$glyph_replace,$text);
+        return $text;
+    } else {
+        $text = preg_split("/(<.*>)/U",$text,-1,PREG_SPLIT_DELIM_CAPTURE);
+        foreach($text as $line) {
+                $offtags = ('code|pre|kbd|notextile');
+
+                    /*  matches are off if we're between <code>, <pre> etc. */
+                if (preg_match('/<('.$offtags.')>/i',$line)) $textile_codepre = true;
+                if (preg_match('/<\/('.$offtags.')>/i',$line)) $textile_codepre = false;
+
+                if (!preg_match("/<.*>/",$line) && $textile_codepre == false) {
+                    $line = preg_replace($glyph_search,$glyph_replace,$line);
+                }
+
+                    /* do htmlspecial if between <code> */
+                if ($textile_codepre == true) {
+                    $line = htmlspecialchars($line,ENT_NOQUOTES,"UTF-8");
+                    $line = preg_replace('/&lt;(\/?'.$offtags.')&gt;/',"<$1>",$line);
+                }
+
+            $glyph_out[] = $line;
+        }
+        return join('',$glyph_out);
+    }
+    }
+
+// -------------------------------------------------------------
+    function textile_iAlign($in)
+    {
+        $vals = array(
+            '<'=>'left',
+            '='=>'center',
+            '>'=>'right');
+        return (isset($vals[$in])) ? $vals[$in] : '';
+    }
+
+// -------------------------------------------------------------
+    function textile_hAlign($in)
+    {
+        $vals = array(
+            '<'=>'left',
+            '='=>'center',
+            '>'=>'right',
+            '<>'=>'justify');
+        return (isset($vals[$in])) ? $vals[$in] : '';
+    }
+
+// -------------------------------------------------------------
+    function textile_vAlign($in)
+    {
+        $vals = array(
+            '^'=>'top',
+            '-'=>'middle',
+            '~'=>'bottom');
+        return (isset($vals[$in])) ? $vals[$in] : '';
+    }
+
+// -------------------------------------------------------------
+    function textile_encode_high($text,$textile_charset="UTF-8")
+    {
+        $textile_cmap = textile_cmap();
+        return mb_encode_numericentity($text, $textile_cmap, $textile_charset);
+    }
+
+// -------------------------------------------------------------
+    function textile_decode_high($text,$textile_charset="UTF-8")
+    {
+        $textile_cmap = textile_cmap();
+        return mb_decode_numericentity($text, $textile_cmap, $textile_charset);
+    }
+
+// -------------------------------------------------------------
+    function textile_cmap()
+    {
+        $f = 0xffff;
+        $textile_cmap = array(
+         160,  255,  0, $f,
+         402,  402,  0, $f,
+         913,  929,  0, $f,
+         931,  937,  0, $f,
+         945,  969,  0, $f,
+         977,  978,  0, $f,
+         982,  982,  0, $f,
+         8226, 8226, 0, $f,
+         8230, 8230, 0, $f,
+         8242, 8243, 0, $f,
+         8254, 8254, 0, $f,
+         8260, 8260, 0, $f,
+         8465, 8465, 0, $f,
+         8472, 8472, 0, $f,
+         8476, 8476, 0, $f,
+         8482, 8482, 0, $f,
+         8501, 8501, 0, $f,
+         8592, 8596, 0, $f,
+         8629, 8629, 0, $f,
+         8656, 8660, 0, $f,
+         8704, 8704, 0, $f,
+         8706, 8707, 0, $f,
+         8709, 8709, 0, $f,
+         8711, 8713, 0, $f,
+         8715, 8715, 0, $f,
+         8719, 8719, 0, $f,
+         8721, 8722, 0, $f,
+         8727, 8727, 0, $f,
+         8730, 8730, 0, $f,
+         8733, 8734, 0, $f,
+         8736, 8736, 0, $f,
+         8743, 8747, 0, $f,
+         8756, 8756, 0, $f,
+         8764, 8764, 0, $f,
+         8773, 8773, 0, $f,
+         8776, 8776, 0, $f,
+         8800, 8801, 0, $f,
+         8804, 8805, 0, $f,
+         8834, 8836, 0, $f,
+         8838, 8839, 0, $f,
+         8853, 8853, 0, $f,
+         8855, 8855, 0, $f,
+         8869, 8869, 0, $f,
+         8901, 8901, 0, $f,
+         8968, 8971, 0, $f,
+         9001, 9002, 0, $f,
+         9674, 9674, 0, $f,
+         9824, 9824, 0, $f,
+         9827, 9827, 0, $f,
+         9829, 9830, 0, $f,
+         338,  339,  0, $f,
+         352,  353,  0, $f,
+         376,  376,  0, $f,
+         710,  710,  0, $f,
+         732,  732,  0, $f,
+         8194, 8195, 0, $f,
+         8201, 8201, 0, $f,
+         8204, 8207, 0, $f,
+         8211, 8212, 0, $f,
+         8216, 8218, 0, $f,
+         8218, 8218, 0, $f,
+         8220, 8222, 0, $f,
+         8224, 8225, 0, $f,
+         8240, 8240, 0, $f,
+         8249, 8250, 0, $f,
+         8364, 8364, 0, $f);
+        return $textile_cmap;
+    }
+
+
+// -------------------------------------------------------------
+    function textile_popup_help($name,$helpvar,$windowW,$windowH) {
+        return ' <a target="_blank" href="http://www.textpattern.com/help/?item='.$helpvar.'" onclick="window.open(this.href, \'popupwindow\', \'width='.$windowW.',height='.$windowH.',scrollbars,resizable\'); return false;">'.$name.'</a><br />';
+
+        return $out;
+    }
+
+// -------------------------------------------------------------
+    function textile_txtgps($thing)
+    {
+        if (isset($_POST[$thing])){
+            if (get_magic_quotes_gpc()==1){
+                return stripslashes($_POST[$thing]);
+            } else {
+                return $_POST[$thing];
+            }
+        } else {
+            return '';
+        }
+    }
+
+
+// -------------------------------------------------------------
+// The following functions are used to detextile html, a process
+// still in development.
+
+
+// -------------------------------------------------------------
+    function textile_detextile($text) {
+
+    $text = preg_replace("/<br \/>\s*/","\n",$text);
+
+    $oktags = array('p','ol','ul','li','i','b','em','strong','span','a','h[1-6]',
+        'table','tr','td','u','del','sup','sub','blockquote');
+
+    foreach($oktags as $tag){
+        $text = preg_replace_callback("/\t*<(".$tag.")\s*([^>]*)>(.*)<\/\\1>/Usi",
+        "textile_processTag",$text);
+    }
+
+        $glyphs = array(
+            '&#8217;'=>'\'',        # single closing
+            '&#8216;'=>'\'',        # single opening
+            '&#8221;'=>'"',         # double closing
+            '&#8220;'=>'"',         # double opening
+            '&#8212;'=>'--',        # em dash
+            '&#8211;'=>' - ',       # en dash
+            '&#215;' =>'x',         # dimension sign
+            '&#8482;'=>'(TM)',      # trademark
+            '&#174;' =>'(R)',       # registered
+            '&#169;' =>'(C)',       # copyright
+            '&#8230;'=>'...'        # ellipsis
+        );
+
+        foreach($glyphs as $f=>$r){
+            $text = str_replace($f,$r,$text);
+        }
+
+        $list = false;
+
+        $text = preg_split("/(<.*>)/U",$text,-1,PREG_SPLIT_DELIM_CAPTURE);
+            foreach($text as $line){
+
+            if ($list == false && preg_match('/<ol/',$line)){
+                $line = "";
+                $list = "o";
+            } else if (preg_match('/<\/ol/',$line)){
+                $line = "";
+                $list = false;
+            } else if ($list == false && preg_match('/<ul/',$line)){
+                $line = "";
+                $list = "u";
+            } else if (preg_match('/<\/ul/',$line)){
+                $line = "";
+                $list = false;
+            } else if ($list == 'o'){
+                $line = preg_replace('/<li.*>/U','# ', $line);
+            } else if ($list == 'u'){
+                $line = preg_replace('/<li.*>/U','* ', $line);
+            }
+            $glyph_out[] = $line;
+        }
+
+        $text = implode('',$glyph_out);
+
+        $text = preg_replace('/^\t* *p\. /m','',$text);
+
+        return textile_decode_high($text);
+    }
+
+
+// -------------------------------------------------------------
+    function textile_processTag($matches)
+    {
+        list($textile_all,$tag,$textile_atts,$textile_content) = $matches;
+        $textile_a = textile_splat($textile_atts);
+#        dump($tag); dump($textile_content); dump($textile_a);
+
+        $phr = array(
+        'em'=>'_',
+        'i'=>'__',
+        'b'=>'**',
+        'strong'=>'*',
+        'cite'=>'??',
+        'del'=>'-',
+        'ins'=>'+',
+        'sup'=>'^',
+        'sub'=>'~',
+        'span'=>'%');
+
+        $blk = array('p','h1','h2','h3','h4','h5','h6');
+
+        if(isset($phr[$tag])) {
+            return $phr[$tag].textile_sci($textile_a).$textile_content.$phr[$tag];
+        } elseif($tag=='blockquote') {
+            return 'bq.'.textile_sci($textile_a).' '.$textile_content;
+        } elseif(in_array($tag,$blk)) {
+            return $tag.textile_sci($textile_a).'. '.$textile_content;
+        } elseif ($tag=='a') {
+            $t = textile_filterAtts($textile_a,array('href','title'));
+            $out = '"'.$textile_content;
+            $out.= (isset($t['title'])) ? ' ('.$t['title'].')' : '';
+            $out.= '":'.$t['href'];
+            return $out;
+        } else {
+            return $textile_all;
+        }
+    }
+
+// -------------------------------------------------------------
+    function textile_filterAtts($textile_atts,$ok)
+    {
+        foreach($textile_atts as $textile_a) {
+            if(in_array($textile_a['name'],$ok)) {
+                if($textile_a['att']!='') {
+                $out[$textile_a['name']] = $textile_a['att'];
+                }
+            }
+        }
+#        dump($out);
+        return $out;
+    }
+
+// -------------------------------------------------------------
+    function textile_sci($textile_a)
+    {
+        $out = '';
+        foreach($textile_a as $t){
+            $out.= ($t['name']=='class') ? '(='.$t['att'].')' : '';
+            $out.= ($t['name']=='id') ? '[='.$t['att'].']' : '';
+            $out.= ($t['name']=='style') ? '{='.$t['att'].'}' : '';
+            $out.= ($t['name']=='cite') ? ':'.$t['att'] : '';
+        }
+        return $out;
+    }
+
+// -------------------------------------------------------------
+    function textile_splat($textile_attr)  // returns attributes as an array
+    {
+        $textile_arr = array();
+        $textile_atnm = '';
+        $mode = 0;
+
+        while (strlen($textile_attr) != 0){
+            $ok = 0;
+            switch ($mode) {
+                case 0: // name
+                    if (preg_match('/^([a-z]+)/i', $textile_attr, $match)) {
+                        $textile_atnm = $match[1]; $ok = $mode = 1;
+                        $textile_attr = preg_replace('/^[a-z]+/i', '', $textile_attr);
+                    }
+                break;
+
+                case 1: // =
+                    if (preg_match('/^\s*=\s*/', $textile_attr)) {
+                        $ok = 1; $mode = 2;
+                        $textile_attr = preg_replace('/^\s*=\s*/', '', $textile_attr);
+                    break;
+                    }
+                    if (preg_match('/^\s+/', $textile_attr)) {
+                        $ok = 1; $mode = 0;
+                        $textile_arr[] = array('name'=>$textile_atnm,'whole'=>$textile_atnm,'att'=>$textile_atnm);
+                        $textile_attr = preg_replace('/^\s+/', '', $textile_attr);
+                    }
+                break;
+
+                case 2: // value
+                    if (preg_match('/^("[^"]*")(\s+|$)/', $textile_attr, $match)) {
+                        $textile_arr[]=array('name' =>$textile_atnm,'whole'=>$textile_atnm.'='.$match[1],
+                                'att'=>str_replace('"','',$match[1]));
+                        $ok = 1; $mode = 0;
+                        $textile_attr = preg_replace('/^"[^"]*"(\s+|$)/', '', $textile_attr);
+                    break;
+                    }
+                    if (preg_match("/^('[^']*')(\s+|$)/", $textile_attr, $match)) {
+                        $textile_arr[]=array('name' =>$textile_atnm,'whole'=>$textile_atnm.'='.$match[1],
+                                'att'=>str_replace("'",'',$match[1]));
+                        $ok = 1; $mode = 0;
+                        $textile_attr = preg_replace("/^'[^']*'(\s+|$)/", '', $textile_attr);
+                    break;
+                    }
+                    if (preg_match("/^(\w+)(\s+|$)/", $textile_attr, $match)) {
+                        $textile_arr[]=
+                            array('name'=>$textile_atnm,'whole'=>$textile_atnm.'="'.$match[1].'"',
+                                'att'=>$match[1]);
+                        $ok = 1; $mode = 0;
+                        $textile_attr = preg_replace("/^\w+(\s+|$)/", '', $textile_attr);
+                    }
+                break;
+            }
+            if ($ok == 0){
+                $textile_attr = preg_replace('/^\S*\s*/', '', $textile_attr);
+                $mode = 0;
+            }
+        }
+        if ($mode == 1) $textile_arr[] =
+                array ('name'=>$textile_atnm,'whole'=>$textile_atnm.'="'.$textile_atnm.'"','att'=>$textile_atnm);
+
+        return $textile_arr;
+    }
+?>
diff --git a/plugins/serendipity_event_textwiki/lang_ja.inc.php b/plugins/serendipity_event_textwiki/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..3a40e9f
--- /dev/null
@@ -0,0 +1,19 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_EVENT_TEXTWIKI_NAME',     'マークアップ: Wiki');
+        @define('PLUGIN_EVENT_TEXTWIKI_DESC',     'Text_Wiki を使用してテキストをマークアップします。');
+        @define('PLUGIN_EVENT_TEXTWIKI_TRANSFORM', '<a href="http://c2.com/cgi/wiki">Wiki</a> 書式を許可します。');
+
+?>
diff --git a/plugins/serendipity_event_textwiki/serendipity_event_textwiki.php b/plugins/serendipity_event_textwiki/serendipity_event_textwiki.php
new file mode 100644 (file)
index 0000000..3ed700a
--- /dev/null
@@ -0,0 +1,678 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_TEXTWIKI_NAME',     'Textformatierung: Wiki');
+        @define('PLUGIN_EVENT_TEXTWIKI_DESC',     'Wiki-Formatierung durchführen');
+        @define('PLUGIN_EVENT_TEXTWIKI_TRANSFORM', '<a href="http://c2.com/cgi/wiki">Wiki</a>-Formatierung erlaubt');
+        break;
+
+    case 'en':
+    default:
+        @define('PLUGIN_EVENT_TEXTWIKI_NAME',     'Markup: Wiki');
+        @define('PLUGIN_EVENT_TEXTWIKI_DESC',     'Markup text using Text_Wiki');
+        @define('PLUGIN_EVENT_TEXTWIKI_TRANSFORM', '<a href="http://c2.com/cgi/wiki">Wiki</a> format allowed');
+
+        break;
+}
+
+// Currently only english available
+
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_PREFILETER', 'Converts different OS linebreaks (Unix/DOS) to unified format and concates lines ending with \. Default is on. Not recommended to switch off.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_DELIMITER', 'Converts the Text_Wiki internal delimiter "\xFF" (255) to avoid conflicts while parsing. Default is on. Not recommended to switch off.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_CODE', 'Marks text between <code> and </code> as code. Using <code type=".."> you can switch highlighting on (e.g. for PHP). Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_PHPCODE', 'Marks and highlights text between <php> and </php> as PHP code and adds PHP open tags. Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_HTML', 'Allows you to use real HTML between <html> and </html>. Beware JS is possible, too! If you use this, switch of markup for comments! Default is off. Not recommended to switch on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_RAW', 'Text between `` and `` is not touched by other markup rules. Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_INCLUDE', 'Allows you to include and run PHP code with the syntax [[include /path/to/script.php]]. Resulting output is parsed by markup rules. Beware, security risk! If you use this, switch of markup for comments! Default is off. Not recommended to switch on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_INCLUDE_DESC_BASE', 'The base directory to your scripts. Default this is set to "/path/to/scripts/". If you leave this blank and switch include on you can only use absolute pathes.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_HEADING', 'Lines starting with "+ " are marked as headlines (+ = <h1>, ++++++ = <h6>). Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_HORIZ', '---- is converted to a horizontal line (<hr>). Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_BREAK', 'Line endings marked with " _" define explicit linebreaks. Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_BLOCKQUOTE', 'Enables to use email style quoting ("> ", ">> ",...). Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_LIST', 'Allows creation of lists ("* " = undefined, "# " = numbered). Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_DEFLIST', 'Enables to create definition lists. Syntax: ": Topic : Definition". Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_TABLE', 'Allows you to create tables. Only used for complete lines. Syntax: "|| Cell 1 || Cell 2 || Cell 3 ||". Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_EMBED', 'Allows you to include and run PHP code with the syntax [[embed /path/to/script.php]]. Resulting output is not parsed by markup rules. Beware, security risk! If you use this, switch of markup for comments! Default is off. Not recommended to switch on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_EMBED_DESC_BASE', 'The base directory to your scripts. Default this is set to "/path/to/scripts/". If you leave this blank and switch embed on you can only use absolute pathes.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_IMAGE', 'Enables the inclusion of images. ([[image  /path/to/image.ext [HTML attributes] ]] or [[image  path/to/image.ext [link="PageName"] [HTML attributes] ]] for linkes images) Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_IMAGE_DESC_BASE', 'Base directory to your images. Default this is set to "/path/to/images". If you leave this blank you can only use absolute pathes or URLs.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_PHPLOOKUP', 'Creates lookup links to the PHP manual with [[php function-name]]. Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_TOC', 'Generates a table of contents over all used headlines with [[toc]]. Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_NEWLINE', 'Converts single newlines ("\n") to line breaks. Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_CENTER', 'Lines starting with "= " are centered. Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_PARAGRAPH', 'Double newlines are converted to paragraphs (<p></p>). Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_URL', 'Normal converts http://example.com to links, [http://example.com] to footnotes and [http://example.com Example] to descriptive links. Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_URL_DESC_TARGET', 'Defines the target for your URLs. This is default set to "_blank", what is mostly feasible.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_FREELINK', 'Enables definition of non-standard wiki links using "((Non-standard link format))" and "((Non-standard link|Describtion))". Default is off.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_FREELINK_DESC_PAGES', 'The freelink rule (as well as the wikilink rule) must know, which pages exist and which have to be marked as "new". This specifies a file (local or remote) which has to contain 1 pagename per line. If the file is remote, it will be cached for the specified time.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_FREELINK_DESC_VIEWURL', 'This URL is specified to view the freelinks. You have to specify a "%s" inside this URL which will be replaced with the name of the freelink page.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_FREELINK_DESC_NEWURL', 'This URL is specified to create new freelinks. You have to specify a "%s" inside this URL which will be replaced with the name of the freelink page.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_FREELINK_DESC_NEWTEXT', 'This text will be added to undefined freelinks to link to the create page. Initially this is set to "?".');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_FREELINK_DESC_CACHETIME', 'If you specify a remote file (URL) for your freelink pages, this file will be cached for as many seconds you specify here. Default is 1 hour.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_INTERWIKI', 'Allows inter wiki linking to MeatBal, Avagoto und Wiki using SiteName:PageName or [SiteName:PageName Show this text instead]. Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_INTERWIKI_DESC_TARGET', '');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_WIKILINK', 'Enables usage of standard WikiWords (2-X x uppercase) as wiki links. Default is off.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_WIKILINK_DESC_PAGES', 'The wikilink rule must know, which pages exist and which have to be marked as "new". This specifies a file (local or remote) which has to contain 1 pagename per line. If the file is remote, it will be cached for the specified time.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_WIKILINK_DESC_VIEWURL', 'This URL is specified to view the wikilinks. You have to specify a "%s" inside this URL which will be replaced with the name of the wikilink page.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_WIKILINK_DESC_NEWURL', 'This URL is specified to create new wikilinks. You have to specify a "%s" inside this URL which will be replaced with the name of the wikilink page.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_WIKILINK_DESC_NEWTEXT', 'This text will be added to undefined wikilinks to link to the create page. Initially this is set to "?".');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_WIKILINK_DESC_CACHETIME', 'If you specify a remote file (URL) for your wikilink pages, this file will be cached for as many seconds you specify here. Default is 1 hour.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_COLORTEXT', 'Colorize text using ##color|text##. Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_STRONG', '**Text** is marked strong. Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_BOLD', '\'\'\'Text\'\'\' is marked bold. Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_EMPHASIS', '//Text// is marked emphasised. Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_ITALIC', '\'\'Text\'\' is marked italic. Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_TT', '{{Text}} is writen in teletext (monotype). Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_SUPERSCRIPT', '^^Text^^ is written in superscript. Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_REVISE', 'Enables marking texts as revisions using "@@---delete this text+++insert this text@@". Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_TIGHTEN', 'Finds more than 3 newlines and reduces the to 2 newlines (paragraph). Default is on.');
+@define('PLUGIN_EVENT_TEXTWIKI_RULE_DESC_ENTITIES', 'Escapes HTML entities. Default is on.');
+
+class serendipity_event_textwiki extends serendipity_event
+{
+
+    var $wikiRules  = array(
+        'prefilter' => array(
+            'file' => 'Text/Wiki/Rule/prefilter.php',
+            'name' => 'Text_Wiki_Rule_prefilter',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_PREFILETER
+        ),
+
+        'delimiter' => array(
+            'file' => 'Text/Wiki/Rule/delimiter.php',
+            'name' => 'Text_Wiki_Rule_delimiter',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_DELIMITER
+        ),
+
+        'code' => array(
+            'file' => 'Text/Wiki/Rule/code.php',
+            'name' => 'Text_Wiki_Rule_code',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_CODE
+        ),
+
+        'phpcode' => array(
+            'file' => 'Text/Wiki/Rule/phpcode.php',
+            'name' => 'Text_Wiki_Rule_phpcode',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_PHPCODE
+        ),
+
+        'html' => array(
+            'file' => 'Text/Wiki/Rule/html.php',
+            'name' => 'Text_Wiki_Rule_html',
+            'flag' => false,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_HTML
+        ),
+
+        'raw' => array(
+            'file' => 'Text/Wiki/Rule/raw.php',
+            'name' => 'Text_Wiki_Rule_raw',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_RAW
+        ),
+
+        'include' => array(
+            'file' => 'Text/Wiki/Rule/include.php',
+            'name' => 'Text_Wiki_Rule_include',
+            'flag' => false,
+            'conf' => array(
+                'base' => '/path/to/scripts/'
+            ),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_INCLUDE,
+            's9yc' => array(
+                 'base' => array(
+                     'type' => 'string',
+                     'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_INCLUDE_DESC_BASE))
+        ),
+
+        'heading' => array(
+            'file' => 'Text/Wiki/Rule/heading.php',
+            'name' => 'Text_Wiki_Rule_heading',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_HEADING
+        ),
+
+        'horiz' => array(
+            'file' => 'Text/Wiki/Rule/horiz.php',
+            'name' => 'Text_Wiki_Rule_horiz',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_HORIZ
+        ),
+
+        'break' => array(
+            'file' => 'Text/Wiki/Rule/break.php',
+            'name' => 'Text_Wiki_Rule_break',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_BREAK
+        ),
+
+        'blockquote' => array(
+            'file' => 'Text/Wiki/Rule/blockquote.php',
+            'name' => 'Text_Wiki_Rule_blockquote',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_BLOCKQUOTE
+        ),
+
+        'list' => array(
+            'file' => 'Text/Wiki/Rule/list.php',
+            'name' => 'Text_Wiki_Rule_list',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_LIST
+        ),
+
+        'deflist' => array(
+            'file' => 'Text/Wiki/Rule/deflist.php',
+            'name' => 'Text_Wiki_Rule_deflist',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_DEFLIST
+        ),
+
+        'table' => array(
+            'file' => 'Text/Wiki/Rule/table.php',
+            'name' => 'Text_Wiki_Rule_table',
+            'flag' => true,
+            'conf' => array(
+                'border'  => 1,
+                'spacing' => 0,
+                'padding' => 4
+            ),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_TABLE
+        ),
+
+        'embed' => array(
+            'file' => 'Text/Wiki/Rule/embed.php',
+            'name' => 'Text_Wiki_Rule_embed',
+            'flag' => false,
+            'conf' => array(
+                'base' => '/path/to/scripts/'
+            ),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_EMBED,
+            's9yc' => array(
+                 'base' => array(
+                     'type' => 'string',
+                     'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_EMBED_DESC_BASE))
+        ),
+
+        'image' => array(
+            'file' => 'Text/Wiki/Rule/image.php',
+            'name' => 'Text_Wiki_Rule_image',
+            'flag' => true,
+            'conf' => array(
+                'base' => ''
+            ),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_IMAGE,
+            's9yc' => array(
+                 'base' => array(
+                     'type' => 'string',
+                     'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_IMAGE_DESC_BASE))
+        ),
+
+        'phplookup' => array(
+            'file' => 'Text/Wiki/Rule/phplookup.php',
+            'name' => 'Text_Wiki_Rule_phplookup',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_PHPLOOKUP
+        ),
+
+        'toc' => array(
+            'file' => 'Text/Wiki/Rule/toc.php',
+            'name' => 'Text_Wiki_Rule_toc',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_TOC
+        ),
+
+        'newline' => array(
+            'file' => 'Text/Wiki/Rule/newline.php',
+            'name' => 'Text_Wiki_Rule_newline',
+            'flag' => true,
+            'conf' => array(
+                'skip' => array(
+                    'code',
+                    'phpcode',
+                    'heading',
+                    'horiz',
+                    'deflist',
+                    'table',
+                    'list',
+                    'toc'
+                )
+            ),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_NEWLINE
+        ),
+
+        'center' => array(
+            'file' => 'Text/Wiki/Rule/center.php',
+            'name' => 'Text_Wiki_Rule_center',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_CENTER
+        ),
+
+        'paragraph' => array(
+            'file' => 'Text/Wiki/Rule/paragraph.php',
+            'name' => 'Text_Wiki_Rule_paragraph',
+            'flag' => true,
+            'conf' => array(
+                'skip' => array(
+                    'blockquote',
+                    'code',
+                    'phpcode',
+                    'heading',
+                    'horiz',
+                    'deflist',
+                    'table',
+                    'list',
+                    'toc'
+                )
+            ),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_PARAGRAPH
+        ),
+
+        'url' => array(
+            'file' => 'Text/Wiki/Rule/url.php',
+            'name' => 'Text_Wiki_Rule_url',
+            'flag' => true,
+            'conf' => array(
+                'target' => '_BLANK'
+            ),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_URL,
+            's9yc' => array(
+                 'target' => array(
+                     'type' => 'string',
+                     'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_URL_DESC_TARGET)),
+        ),
+
+        'freelink' => array(
+            'file' => 'Text/Wiki/Rule/freelink.php',
+            'name' => 'Text_Wiki_Rule_freelink',
+            'flag' => false,
+            'conf' => array(
+                'pages'       => array(),
+                'view_url' => 'http://example.com/index.php?page=%s',
+                'new_url'  => 'http://example.com/new.php?page=%s',
+                'new_text' => '?'
+            ),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_FREELINK,
+            's9yc' => array(
+                 'pages' => array(
+                     'type' => 'string',
+                     'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_FREELINK_DESC_PAGES),
+                 'view_url' => array(
+                     'type' => 'string',
+                     'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_FREELINK_DESC_VIEWURL),
+                 'new_url' => array(
+                     'type' => 'string',
+                     'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_FREELINK_DESC_NEWURL),
+                 'new_text' => array(
+                     'type' => 'string',
+                     'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_FREELINK_DESC_NEWTEXT),
+                 'cachetime' => array(
+                     'type' => 'string',
+                     'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_WIKILINK_DESC_CACHETIME))
+        ),
+
+        'interwiki' => array(
+            'file' => 'Text/Wiki/Rule/interwiki.php',
+            'name' => 'Text_Wiki_Rule_interwiki',
+            'flag' => true,
+            'conf' => array(
+                'sites' => array(
+                    'MeatBall' => 'http://www.usemod.com/cgi-bin/mb.pl?%s',
+                    'Advogato' => 'http://advogato.org/%s',
+                    'Wiki'     => 'http://c2.com/cgi/wiki?%s'
+                ),
+                'target' => '_BLANK'
+            ),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_INTERWIKI,
+            's9yc' => array(
+                 'pages' => array(
+                     'target' => 'string',
+                     'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_INTERWIKI_DESC_TARGET))
+        ),
+
+        'wikilink' => array(
+            'file' => 'Text/Wiki/Rule/wikilink.php',
+            'name' => 'Text_Wiki_Rule_wikilink',
+            'flag' => false,
+            'conf' => array(
+                'pages'       => array(),
+                'view_url' => 'http://example.com/index.php?page=%s',
+                'new_url'  => 'http://example.com/new.php?page=%s',
+                'new_text' => '?'
+            ),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_WIKILINK,
+            's9yc' => array(
+                 'pages' => array(
+                     'type' => 'string',
+                     'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_WIKILINK_DESC_PAGES),
+                 'view_url' => array(
+                     'type' => 'string',
+                     'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_WIKILINK_DESC_VIEWURL),
+                 'new_url' => array(
+                     'type' => 'string',
+                     'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_WIKILINK_DESC_NEWURL),
+                 'new_text' => array(
+                     'type' => 'string',
+                     'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_WIKILINK_DESC_NEWTEXT),
+                 'cachetime' => array(
+                     'type' => 'string',
+                     'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_WIKILINK_DESC_CACHETIME))
+        ),
+
+        'colortext' => array(
+            'file' => 'Text/Wiki/Rule/colortext.php',
+            'name' => 'Text_Wiki_Rule_colortext',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_COLORTEXT
+        ),
+
+        'strong' => array(
+            'file' => 'Text/Wiki/Rule/strong.php',
+            'name' => 'Text_Wiki_Rule_strong',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_STRONG
+        ),
+
+        'bold' => array(
+            'file' => 'Text/Wiki/Rule/bold.php',
+            'name' => 'Text_Wiki_Rule_bold',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_BOLD
+        ),
+
+        'emphasis' => array(
+            'file' => 'Text/Wiki/Rule/emphasis.php',
+            'name' => 'Text_Wiki_Rule_emphasis',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_EMPHASIS
+        ),
+
+        'italic' => array(
+            'file' => 'Text/Wiki/Rule/italic.php',
+            'name' => 'Text_Wiki_Rule_italic',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_ITALIC
+        ),
+
+        'tt' => array(
+            'file' => 'Text/Wiki/Rule/tt.php',
+            'name' => 'Text_Wiki_Rule_tt',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_TT
+        ),
+
+        'superscript' => array(
+            'file' => 'Text/Wiki/Rule/superscript.php',
+            'name' => 'Text_Wiki_Rule_superscript',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_SUPERSCRIPT
+        ),
+
+        'revise' => array(
+            'file' => 'Text/Wiki/Rule/revise.php',
+            'name' => 'Text_Wiki_Rule_revise',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_REVISE
+        ),
+
+        'tighten' => array(
+            'file' => 'Text/Wiki/Rule/tighten.php',
+            'name' => 'Text_Wiki_Rule_tighten',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_TIGHTEN
+        ),
+
+        'entities' => array(
+            'file' => 'Text/Wiki/Rule/entities.php',
+            'name' => 'Text_Wiki_Rule_entities',
+            'flag' => true,
+            'conf' => array(),
+            'desc' => PLUGIN_EVENT_TEXTWIKI_RULE_DESC_ENTITIES
+        )
+    );
+
+    var $nonWikiRules = array();
+    var $title = PLUGIN_EVENT_TEXTWIKI_NAME;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_TEXTWIKI_NAME);
+        $propbag->add('description',   PLUGIN_EVENT_TEXTWIKI_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Tobias Schlitt');
+        $propbag->add('version',       '1.1');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('cachable_events', array('frontend_display' => true));
+        $propbag->add('event_hooks',   array('frontend_display' => true, 'frontend_comment' => true));
+
+        $this->markup_elements = array(
+            array(
+              'name'     => 'ENTRY_BODY',
+              'element'  => 'body',
+            ),
+            array(
+              'name'     => 'EXTENDED_BODY',
+              'element'  => 'extended',
+            ),
+            array(
+              'name'     => 'COMMENT',
+              'element'  => 'comment',
+            ),
+            array(
+              'name'     => 'HTML_NUGGET',
+              'element'  => 'html_nugget',
+            )
+        );
+
+        $conf_array = array();
+        // Add markup elements config
+        foreach($this->markup_elements as $element) {
+            $conf_array[] = $element['name'];
+        }
+        // Save non wiki-rule configuration
+        $this->nonWikiRules = $conf_array;
+        // Seperate markup elements from wiki-rule config
+        $conf_array[] = "internal_seperator";
+        // Add wiki-rule config
+        $this->_introspect_rule_config($conf_array);
+        $propbag->add('configuration', $conf_array);
+    }
+
+    function _introspect_rule_config(&$conf_array) {
+        foreach($this->wikiRules as $name => $rule) {
+            // If sub configurations exist
+            if (isset($rule['s9yc']) && is_array($rule['s9yc'])) {
+                if ($conf_array[(count($conf_array) - 1)] != 'internal_seperator') {
+                    $conf_array[] = 'internal_seperator';
+                }
+                // Add wiki-rule config itself
+                $conf_array[] = $name;
+                foreach ($rule['s9yc'] as $confname => $conf) {
+                    $conf_array[] = $name . '_' . $confname;
+                }
+                $conf_array[] = "internal_seperator";
+            } else {
+                // Add only wiki-rule config itself
+                $conf_array[] = $name;
+            }
+        }
+    }
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+    function install() {
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function uninstall() {
+        serendipity_plugin_api::hook_event('backend_cache_purge', $this->title);
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        if (in_array($name, $this->nonWikiRules)) {
+            $propbag->add('type',        'boolean');
+            $propbag->add('name',        defined($name) ? constant($name) : $name);
+            $propbag->add('description', sprintf(APPLY_MARKUP_TO, defined($name) ? constant($name) : $name));
+        } else if ($name == 'internal_seperator') {
+            $propbag->add('type',        'seperator');
+            $propbag->add('name',        'Seperator');
+            $propbag->add('description', 'Seperator');
+        } else {
+            $this->_introspect_rule_config_item($name, $propbag);
+        }
+        return true;
+    }
+
+    function _introspect_rule_config_item($name, &$propbag) {
+        if (strpos($name, '_') === false) {
+            $propbag->add('type',        'boolean');
+            $propbag->add('name',        ucfirst($name));
+            $propbag->add('description', $this->wikiRules[$name]['desc']);
+            return true;
+        } else {
+            $parts = explode('_', $name, 2);
+            $conf = $this->wikiRules[$parts[0]]['s9yc'][$parts[1]];
+            $propbag->add('type',        $conf['type']);
+            $propbag->add('name',        ucfirst($parts[0]).' '.ucwords((str_replace('_', ' ',$parts[1]))));
+            $propbag->add('description', $conf['desc']);
+            return true;
+        }
+    }
+
+    function event_hook($event, &$bag, &$eventData) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+
+        if (!isset($this->wiki) || !is_a($this->wiki, 'text_wiki')) {
+            $this->_init_wiki($bag);
+        }
+
+        if (isset($hooks[$event])) {
+            switch($event) {
+                case 'frontend_display':
+                    foreach ($this->markup_elements as $temp) {
+                        if (serendipity_db_bool($this->get_config($temp['name'], true)) && isset($eventData[$temp['element']])) {
+                            $element = $temp['element'];
+                            $eventData[$element] = $this->wiki->transform($eventData[$element]);
+                        }
+                    }
+                    return true;
+                    break;
+
+                case 'frontend_comment':
+                    if (serendipity_db_bool($this->get_config('COMMENT', true))) {
+                        echo '<div class="serendipity_commentDirection">' . PLUGIN_EVENT_TEXTWIKI_TRANSFORM . '</div>';
+                    }
+                    return true;
+                    break;
+
+                default:
+                  return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    function _init_wiki(&$bag) {
+        @include_once 'Text/Wiki.php';
+
+        if (class_exists('Text_Wiki')) {
+            $this->wiki =& new Text_Wiki;
+        } else {
+            return false;
+        }
+        foreach ($this->wikiRules as $name => $rule) {
+            if ($this->get_config($name, $rule['flag'])) {
+                $this->_add_wiki_rule($bag, $name, $rule);
+            }
+        }
+        return true;
+    }
+
+    function _add_wiki_rule(&$bag, $name, $rule) {
+        $rule_info = $rule;
+        $rule_info['flag'] = true;
+        if (isset($rule['s9yc']) && is_array($rule['s9yc'])) {
+            foreach ($rule['s9yc'] as $confName => $confVals) {
+                if ($confName === 'pages') {
+                    $rule_info['conf']['pages'] = $this->_get_link_pages($bag, $name);
+                } else {
+                    $rule_info['conf'][$confName] = $this->get_config($name.'_'.$confName, $rule_info['conf'][$confName]);
+                }
+            }
+        }
+        $this->wiki->insertRule($name, $rule_info);
+        return true;
+    }
+
+    function _get_link_pages(&$bag, $ruleName) {
+        global $serendipity;
+        if ($this->get_config($ruleName.'_pages') === null) {
+            return array();
+        }
+        $pagesFile = $this->get_config($ruleName.'_pages');
+        if (!is_file($pagesFile)) {
+            $cacheFile = $serendipity['uploadPath']."serendipity_plugin_event_wiki_".$ruleName.".cache";
+            $cacheTime = (int)$this->get_config($ruleName.'_cachetime', 3600);
+            if (!is_file($cacheFile) || (filemtime($cacheFile) + $cacheTime) < time()) {
+                $pagesArray = @file($pagesFile);
+                if (!$pagesArray) { return array(); }
+                $putCache = @fopen($cacheFile, 'w');
+                if (!$putCache) { return array(); }
+                fputs($putCache, implode("", $pagesArray));
+                fclose($putCache);
+            }
+            $pagesFile = $cacheFile;
+        }
+        $pagesArray = array_map(trim, file($pagesFile));
+        return (is_array($pagesArray)) ? $pagesArray : array();
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_trackexits/serendipity_event_trackexits.php b/plugins/serendipity_event_trackexits/serendipity_event_trackexits.php
new file mode 100644 (file)
index 0000000..5b4dda4
--- /dev/null
@@ -0,0 +1,225 @@
+<?php # $Id$
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_TRACKBACK_NAME', 'Textformatierung: Externe Links zählen');
+        @define('PLUGIN_EVENT_TRACKBACK_DESC', 'Click auf Externe Links verfolgen');
+        @define('PLUGIN_EVENT_TRACKBACK_COMMENTREDIRECTION', 'URL von Kommentatoren maskieren?');
+        @define('PLUGIN_EVENT_TRACKBACK_COMMENTREDIRECTION_BLAHBLA', 'Verhindert Spam-Missbrauch aber auch positiven Nutzen von Verlinkungen innerhalb Blogs. Wenn der Wert auf "s9y" gesetzt wird, werden interne Routinen zur Weiterleitung verwendet. Bei dem Wert "google" wird Google verwendet. Ein leerer Wert schaltet die Weiterleitung aus(Standard).');
+        @define('PLUGIN_EVENT_TRACKBACK_COMMENTREDIRECTION_NONE', 'Keine');
+        @define('PLUGIN_EVENT_TRACKBACK_COMMENTREDIRECTION_S9Y', 'Serendipity Exit-Tracking Routine');
+        @define('PLUGIN_EVENT_TRACKBACK_COMMENTREDIRECTION_GOOGLE', 'Google PageRank Deflector');
+        break;
+
+    case 'en':
+    default:
+        @define('PLUGIN_EVENT_TRACKBACK_NAME', 'Markup: Track exits');
+        @define('PLUGIN_EVENT_TRACKBACK_DESC', 'Track clicks on external URLs');
+        @define('PLUGIN_EVENT_TRACKBACK_COMMENTREDIRECTION', 'Use URL-redirection on URL to commenting user?');
+        @define('PLUGIN_EVENT_TRACKBACK_COMMENTREDIRECTION_BLAHBLA', 'Reduces Comment-Abuse but also disables positive effects of linking to the URL of a commenting user. Serendipity\'s internal routines will redirect to the target page and log the exit. The Google PageRank Deflector will prevent the link from gaining rack on Google. An empty value disables this feature entriely (default).');
+        @define('PLUGIN_EVENT_TRACKBACK_COMMENTREDIRECTION_NONE', 'None');
+        @define('PLUGIN_EVENT_TRACKBACK_COMMENTREDIRECTION_S9Y', 'Serendipity Exit-Tracking Routine');
+        @define('PLUGIN_EVENT_TRACKBACK_COMMENTREDIRECTION_GOOGLE', 'Google PageRank Deflector');
+        break;
+}
+
+class serendipity_event_trackexits extends serendipity_event
+{
+    var $title = PLUGIN_EVENT_TRACKBACK_NAME;
+    var $links;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_TRACKBACK_NAME);
+        $propbag->add('description',   PLUGIN_EVENT_TRACKBACK_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Serendipity Team');
+        $propbag->add('version',       '1.1');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('cachable_events', array('frontend_display' => true));
+        $propbag->add('event_hooks',   array('frontend_display' => true));
+        $propbag->add('scrambles_true_content', true);
+
+        $this->markup_elements = array(
+            array(
+              'name'     => 'ENTRY_BODY',
+              'element'  => 'body',
+            ),
+            array(
+              'name'     => 'EXTENDED_BODY',
+              'element'  => 'extended',
+            ),
+            array(
+              'name'     => 'COMMENT',
+              'element'  => 'comment',
+            ),
+            array(
+              'name'     => 'HTML_NUGGET',
+              'element'  => 'html_nugget',
+            )
+        );
+
+        $conf_array = array();
+        foreach($this->markup_elements as $element) {
+            $conf_array[] = $element['name'];
+        }
+        $conf_array[] = 'commentredirection';
+        $propbag->add('configuration', $conf_array);
+    }
+
+    function install() {
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function uninstall() {
+        serendipity_plugin_api::hook_event('backend_cache_purge', $this->title);
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'commentredirection':
+                $propbag->add('type',        'select');
+                $propbag->add('select_values', array('none'     => PLUGIN_EVENT_TRACKBACK_COMMENTREDIRECTION_NONE,
+                                                     's9y'      => PLUGIN_EVENT_TRACKBACK_COMMENTREDIRECTION_S9Y,
+                                                     'google'   => PLUGIN_EVENT_TRACKBACK_COMMENTREDIRECTION_GOOGLE));
+                $propbag->add('name',        PLUGIN_EVENT_TRACKBACK_COMMENTREDIRECTION);
+                $propbag->add('description', PLUGIN_EVENT_TRACKBACK_COMMENTREDIRECTION_BLAHBLA);
+                $propbag->add('default', 'none');
+                break;
+
+            default:
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        constant($name));
+                $propbag->add('description', sprintf(APPLY_MARKUP_TO, constant($name)));
+                $propbag->add('default', 'true');
+        }
+        return true;
+    }
+
+    function event_hook($event, &$bag, &$eventData, $addData = null) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+
+        if (isset($hooks[$event])) {
+            switch($event) {
+                case 'frontend_display':
+                    if ($bag->get('scrambles_true_content') && is_array($addData) && isset($addData['no_scramble'])) {
+                        return true;
+                    }
+
+                    $serendipity['encodeExitsCallback_entry_id'] = (int)(isset($eventData['entry_id']) ? $eventData['entry_id'] : $eventData['id']);
+
+                    // Fetch all existing links from the database. They have been inserted there by our trackback-discovery.
+                    if (empty($serendipity['encodeExitsCallback_entry_id'])) {
+                        $this->links = array();
+                    } else {
+                        $this->links = serendipity_db_query("SELECT id, link FROM {$serendipity['dbPrefix']}references WHERE entry_id = {$serendipity['encodeExitsCallback_entry_id']}", false, 'both', false, 'link', 'id');
+                    }
+
+                    foreach ($this->markup_elements as $temp) {
+                        if (serendipity_db_bool($this->get_config($temp['name'], true)) && isset($eventData[$temp['element']])) {
+                            $element = $temp['element'];
+
+                            $eventData[$element] = preg_replace_callback(
+                                "#<a(.*)href=(\"|')http(s?)://([^\"']+)(\"|')#isUm",
+                                array($this, '_encodeExitsCallback'),
+                                $eventData[$element]
+                            );
+
+                            if ($temp['element'] == 'comment' && !empty($eventData['url'])) {
+                                switch(trim($this->get_config('commentredirection'))) {
+                                    case 's9y':
+                                        $eventData['url'] = $this->_encodeExitsCallback(
+                                                              array(
+                                                                1 => ' ',
+                                                                2 => '"',
+                                                                3 => '',
+                                                                4 => $eventData['url'],
+                                                                5 => '"'
+                                                              ),
+                                                              true
+                                                            );
+                                        break;
+
+                                    case 'google':
+                                        $eventData['url'] = 'http://www.google.com/url?sa=D&q=' . $eventData['url'];
+                                        break;
+
+                                    default:
+                                        break;
+                                }
+                            }
+                        }
+                    }
+
+                    return true;
+                    break;
+
+                default:
+                    return false;
+            }
+
+        } else {
+            return false;
+        }
+    }
+
+
+    /**
+    * Transforms '<a href="http://url/">' into
+    * '<a href="exit.php?url=encurl" ...>'.
+    */
+    function _encodeExitsCallback($buffer, $url_only = false) {
+        global $serendipity;
+
+        $entry_id = $serendipity['encodeExitsCallback_entry_id'];
+        $url      = 'http' . $buffer[3] . '://' . $buffer[4];
+
+        if ($url_only) {
+            return sprintf(
+                '%sexit.php?url=%s%s',
+                $serendipity['baseURL'],
+                base64_encode($buffer[4]),
+                ($entry_id != 0) ? '&amp;entry_id=' . $entry_id : ''
+            );
+        }
+
+        if (is_array($this->links) && isset($this->links[$url])) {
+            return sprintf(
+                '<a%shref="%sexit.php?url_id=%s%s" title="%s" onmouseover="window.status=\'%s\';return true;" onmouseout="window.status=\'\';return true;"',
+                $buffer[1],
+                $serendipity['baseURL'],
+                $this->links[$url],
+                ($entry_id != 0) ? '&amp;entry_id=' . $entry_id : '',
+                $url,
+                $url
+            );
+        } else {
+            return sprintf(
+                '<a%shref="%sexit.php?url=%s%s" title="%s" onmouseover="window.status=\'%s\';return true;" onmouseout="window.status=\'\';return true;"',
+                $buffer[1],
+                $serendipity['baseURL'],
+                base64_encode($url),
+                ($entry_id != 0) ? '&amp;entry_id=' . $entry_id : '',
+                $url,
+                $url
+            );
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_weblogping/lang_ja.inc.php b/plugins/serendipity_event_weblogping/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..9d737c7
--- /dev/null
@@ -0,0 +1,23 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_EVENT_WEBLOGPING_PING', 'XML-RPC ping のアナウンス先エントリ:');
+        @define('PLUGIN_EVENT_WEBLOGPING_SENDINGPING', 'XML-RPC ping をホスト %s に送信中');
+        @define('PLUGIN_EVENT_WEBLOGPING_TITLE', 'アナウンスエントリ一覧');
+        @define('PLUGIN_EVENT_WEBLOGPING_DESC', '新規エントリの通知をオンラインサービスに送信します。');
+        @define('PLUGIN_EVENT_WEBLOGPING_SUPERSEDES', '(supersedes %s)');
+        @define('PLUGIN_EVENT_WEBLOGPING_CUSTOM', 'カスタム ping サービス');
+        @define('PLUGIN_EVENT_WEBLOGPING_CUSTOM_BLAHBLA', '「,」で区切られた、一つ以上の特別な ping サービスです。「host.domain/path」のような書式で入力する必要があります。"*"がホスト名の初めに入力されれば、拡張 XML-RPC オプションは、そのホスト(ただもしホストに支援されれば)のもとへ送られるでしょう。"*"がホスト名の初めに入力されれば、拡張 XML-RPC オプションは、そのホスト(ただもしホストがサポートしていれば)のもとへ送られるでしょう。');
+
+?>
diff --git a/plugins/serendipity_event_weblogping/serendipity_event_weblogping.php b/plugins/serendipity_event_weblogping/serendipity_event_weblogping.php
new file mode 100644 (file)
index 0000000..dcf9d9c
--- /dev/null
@@ -0,0 +1,237 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_WEBLOGPING_PING', 'Einträge ankündigen (via XML-RPC ping) bei:');
+        @define('PLUGIN_EVENT_WEBLOGPING_SENDINGPING', 'Sende XML-RPC ping zu %s');
+        @define('PLUGIN_EVENT_WEBLOGPING_TITLE', 'Einträge ankündigen');
+        @define('PLUGIN_EVENT_WEBLOGPING_DESC', 'Benachrichtigt diverse Internetseiten, das ein neuer Eintrag erstellt wurde.');
+        @define('PLUGIN_EVENT_WEBLOGPING_SUPERSEDES', '(ersetzt %s)');
+        @define('PLUGIN_EVENT_WEBLOGPING_CUSTOM', 'Selbstdefinierte Ping-Services');
+        @define('PLUGIN_EVENT_WEBLOGPING_CUSTOM_BLAHBLA', 'Mehrere durch "," getrennte Ping-Services im Format: "host.domain/pfad". Falls am Anfang eines Hosts ein "*" eingefügt wird, werden an den Host die erweiterten XML-RPC Optionen gesendet; der Host muss diese Optionen unterstützen.');
+        break;
+
+    case 'en':
+    case 'es':
+    default:
+        @define('PLUGIN_EVENT_WEBLOGPING_PING', 'Announce entries (via XML-RPC ping) to:');
+        @define('PLUGIN_EVENT_WEBLOGPING_SENDINGPING', 'Sending XML-RPC ping to host %s');
+        @define('PLUGIN_EVENT_WEBLOGPING_TITLE', 'Announce entries');
+        @define('PLUGIN_EVENT_WEBLOGPING_DESC', 'Send notification of new entries to online services');
+        @define('PLUGIN_EVENT_WEBLOGPING_SUPERSEDES', '(supersedes %s)');
+        @define('PLUGIN_EVENT_WEBLOGPING_CUSTOM', 'Custom ping-services');
+        @define('PLUGIN_EVENT_WEBLOGPING_CUSTOM_BLAHBLA', 'One or more special ping services, seperated by ",". The entries need to be formatted like: "host.domain/path". If a "*" is entered at the beginning of the hostname, the extended XML-RPC options will be sent to that host (only if supported by the host).');
+        break;
+}
+
+class serendipity_event_weblogping extends serendipity_event
+{
+    var $services;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_WEBLOGPING_TITLE);
+        $propbag->add('description',   PLUGIN_EVENT_WEBLOGPING_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Serendipity Team');
+        $propbag->add('version',       '1.01');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('event_hooks',    array(
+            'backend_display' => true,
+            'frontend_display' => true,
+            'backend_insert' => true,
+            'backend_update' => true,
+            'backend_publish' => true,
+            'backend_draft' => true
+        ));
+
+        $servicesdb = array();
+        $servicesdb_file = dirname(__FILE__) . '/servicesdb_' . $serendipity['lang'] . '.inc.php';
+        if (!file_exists($servicesdb_file)) {
+            $servicesdb_file = dirname(__FILE__) . '/servicesdb_en.inc.php';
+        }
+        include $servicesdb_file;
+        $this->services =& $servicesdb;
+
+
+        $manual_services = explode(',', $this->get_config('manual_services'));
+        if (is_array($manual_services)) {
+            foreach($manual_services as $ms_index => $ms_name) {
+                if (!empty($ms_name)) {
+                    $is_extended = ($ms_name{0} == '*' ? true : false);
+                    $ms_name = trim($ms_name, '*');
+                    $ms_parts = explode('/', $ms_name);
+                    $ms_host = $ms_parts[0];
+                    unset($ms_party[0]);
+
+                    $this->services[] = array(
+                                          'name'     => $ms_name,
+                                          'host'     => $ms_host,
+                                          'path'     => implode('/', $ms_parts),
+                                          'extended' => $is_extended
+                    );
+                }
+            }
+        }
+
+        $conf_array = array();
+        foreach($this->services AS $key => $service) {
+            $conf_array[] = $service['name'];
+        }
+
+        $conf_array[] = 'manual_services';
+
+        $propbag->add('configuration', $conf_array);
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'manual_services':
+                $propbag->add('type',        'string');
+                $propbag->add('name',        PLUGIN_EVENT_WEBLOGPING_CUSTOM);
+                $propbag->add('description', PLUGIN_EVENT_WEBLOGPING_CUSTOM_BLAHBLA);
+                $propbag->add('default', '');
+                break;
+
+            default:
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        $name);
+                $propbag->add('description', sprintf(PLUGIN_EVENT_WEBLOGPING_PING, $name));
+                $propbag->add('default', 'false');
+        }
+        return true;
+    }
+
+    function generate_content(&$title) {
+        $title = PLUGIN_EVENT_WEBLOGPING_TITLE;
+    }
+
+    function event_hook($event, &$bag, &$eventData) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+        if (isset($hooks[$event])) {
+            switch($event) {
+                case 'backend_display':
+?>
+                    <fieldset style="margin: 5px">
+                        <legend><?php echo PLUGIN_EVENT_WEBLOGPING_PING; ?></legend>
+<?php
+                    foreach($this->services AS $index => $service) {
+                        // Detect if the current checkbox needs to be saved. We use the field chk_timestamp to see,
+                        // if the form has already been submitted and individual changes shall be preserved
+                        $selected = (($serendipity['POST']['chk_timestamp'] && $serendipity['POST']['announce_entries_' . $service['name']]) || (!isset($serendipity['POST']['chk_timestamp']) && $this->get_config($service['name']) == 'true') ? 'checked="checked"' : '');
+
+                        $onclick = '';
+                        if (!empty($service['supersedes'])) {
+                            $onclick    = 'onclick="';
+                            $supersedes = explode(', ', $service['supersedes']);
+                            foreach($supersedes AS $sid => $servicename) {
+                                $onclick .= 'document.getElementById(\'serendipity[announce_entries_' . $servicename . ']\').checked = false; ';
+                            }
+                            $onclick    .= '"';
+                        }
+
+                        $title    = sprintf(PLUGIN_EVENT_WEBLOGPING_SENDINGPING, $service['name'])
+                                  . (!empty($service['supersedes']) ?  ' ' . sprintf(PLUGIN_EVENT_WEBLOGPING_SUPERSEDES, $service['supersedes']) : '');
+?>
+                            <input <?php echo $onclick; ?> style="margin: 0px; padding: 0px; vertical-align: bottom;" type="checkbox" name="serendipity[announce_entries_<?php echo $service['name']; ?>]" id="serendipity[announce_entries_<?php echo $service['name']; ?>]" value="true" <?php echo $selected; ?> />
+                                <label title="<?php echo $title; ?>" style="vertical-align: bottom; margin: 0px; padding: 0px;" for="serendipity[announce_entries_<?php echo $service['name']; ?>]">&nbsp;<?php echo $service['name']; ?>&nbsp;&nbsp;</label><br />
+<?php
+    }
+?>
+                    </fieldset>
+<?php
+                    return true;
+                    break;
+
+                case 'backend_publish':
+                    // First cycle through list of services to remove superseding services which may have been checked
+                    foreach ($this->services as $index => $service) {
+                        if (!empty($service['supersedes']) && isset($serendipity['POST']['announce_entries_' . $service['name']])) {
+                            $supersedes = explode(', ', $service['supersedes']);
+                            foreach($supersedes AS $sid => $servicename) {
+                                // A service has been checked that is superseded by another checked meta-service. Remove that service from the list of services to be ping'd
+                                unset($serendipity['POST']['announce_entries_' . $servicename]);
+                            }
+                        }
+                    }
+
+                    foreach ($this->services as $index => $service) {
+                        if (isset($serendipity['POST']['announce_entries_' . $service['name']])) {
+                            printf(PLUGIN_EVENT_WEBLOGPING_SENDINGPING . '...<br />', $service['host']);
+                            flush();
+
+                            # XXX append $serendipity['indexFile'] to baseURL?
+                            $args = array(
+                              new XML_RPC_Value(
+                                $serendipity['blogTitle'],
+                                'string'
+                              ),
+                              new XML_RPC_Value(
+                                $serendipity['baseURL'],
+                                'string'
+                              )
+                            );
+
+                            if ($service['extended']) {
+                                # the checkUrl: for when the main page is not really the main page
+                                $args[] = new XML_RPC_Value(
+                                  '',
+                                  'string'
+                                );
+
+                                # the rssUrl
+                                $args[] = new XML_RPC_Value(
+                                  $serendipity['baseURL'] . 'rss.php?version=2.0',
+                                  'string'
+                                );
+                            }
+
+                            $message = new XML_RPC_Message(
+                              $service['extended'] ? 'weblogUpdates.extendedPing' : 'weblogUpdates.ping',
+                              $args
+                            );
+
+                            $client = new XML_RPC_Client(
+                              trim($service['path']),
+                              trim($service['host'])
+                            );
+
+                            # 15 second timeout may not be long enough for weblogs.com
+                            $result = $client->send($message, 15);
+                        }
+                    }
+
+                    return true;
+                    break;
+
+                case 'frontend_display':
+                case 'backend_insert':
+                case 'backend_update':
+                case 'backend_draft':
+                default:
+                    return false;
+                    break;
+            }
+        } else {
+            return false;
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_event_weblogping/servicesdb_en.inc.php b/plugins/serendipity_event_weblogping/servicesdb_en.inc.php
new file mode 100644 (file)
index 0000000..bb14187
--- /dev/null
@@ -0,0 +1,62 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+##########################################################################
+
+        $servicesdb = array(
+            array(
+              'name'       => 'Ping-o-Matic',
+              'host'       => 'rpc.pingomatic.com',
+              'path'       => '/',
+              'extended'   => true,
+              'supersedes' => array('blo.gs', 'blogrolling.com', 'technorati.com', 'weblogs.com', 'Yahoo!')
+            ),
+
+            array(
+              'name'     => 'blo.gs',
+              'host'     => 'ping.blo.gs',
+              'path'     => '/',
+              'extended' => true
+            ),
+
+            array(
+              'name' => 'blogrolling.com',
+              'host' => 'rpc.blogrolling.com',
+              'path' => '/pinger/'
+            ),
+
+            array(
+              'name' => 'technorati.com',
+              'host' => 'rpc.technorati.com',
+              'path' => '/rpc/ping'
+            ),
+
+            array(
+              'name' => 'weblogs.com',
+              'host' => 'rpc.weblogs.com',
+              'path' => '/RPC2'
+            ),
+
+            array(
+              'name' => 'blogg.de',
+              'host' => 'xmlrpc.blogg.de',
+              'path' => '/'
+            ),
+
+            array(
+              'name' => 'Yahoo!',
+              'host' => 'api.my.yahoo.com',
+              'path' => '/RPC2'
+            ),
+            array(
+              'name' => 'Blogbot.dk',
+              'host' => 'blogbot.dk',
+              'path' => '/io/xml-rpc.php')
+        );
+?>
diff --git a/plugins/serendipity_event_weblogping/servicesdb_ja.inc.php b/plugins/serendipity_event_weblogping/servicesdb_ja.inc.php
new file mode 100644 (file)
index 0000000..89f8dac
--- /dev/null
@@ -0,0 +1,97 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+##########################################################################
+
+        $servicesdb = array(
+            array(
+              'name'       => 'Myblog japan',
+              'host'       => 'ping.myblog.jp',
+              'path'       => '/',
+              'extended' => true
+            ),
+
+            array(
+              'name'        => 'BLOGGERS.JP',
+              'host'        => 'ping.bloggers.jp',
+              'path'        => '/rpc/',
+              'extended' => true
+            ),
+
+            array(
+              'name'        => 'blogpeople.net',
+              'host'        => 'www.blogpeople.net',
+              'path'        => '/weblogUpdates',
+              'extended' => true
+            ),
+
+            array(
+              'name'        => 'ココログ',
+              'host'        => 'ping.cocolog-nifty.com',
+              'path'        => '/xmlrpc',
+              'extended' => true
+            ),
+
+            array(
+              'name'        => 'goo',
+              'host'        => 'blog.goo.ne.jp',
+              'path'        => '/XMLRPC',
+              'extended' => true
+            ),
+
+            array(
+              'name'        => 'coreblog',
+              'host'        => 'coreblog.org',
+              'path'        => '/ping/',
+              'extended' => true
+            ),
+
+            array(
+              'name'        => 'bulkfeeds',
+              'host'        => 'bulkfeeds.net',
+              'path'        => '/rpc',
+              'extended' => true
+            ),
+
+            array(
+              'name'        => 'blogrolling',
+              'host'        => 'rpc.blogrolling.com',
+              'path'        => '/pinger/',
+              'extended' => true
+            ),
+
+            array(
+              'name'        => 'dontpushme.com',
+              'host'        => 'www.dontpushme.com',
+              'path'        => '/ft/XmlRpc/Daily.do',
+              'extended' => true
+            ),
+
+            array(
+              'name'        => 'Excite エキサイト : ブログ(blog)',
+              'host'        => 'ping.exblog.jp',
+              'path'        => '/xmlrpc',
+              'extended' => true
+            ),
+
+            array(
+              'name'        => 'blogdb.jp',
+              'host'        => 'blogdb.jp',
+              'path'        => '/xmlrpc',
+              'extended' => true
+            ),
+
+            array(
+              'name'        => 'BLOGOOGLE(ブログール) Pingサーバ',
+              'host'        => 'www.blogoole.com',
+              'path'        => '/ping/',
+              'extended' => true
+            )
+        );
+?>
diff --git a/plugins/serendipity_event_xhtmlcleanup/serendipity_event_xhtmlcleanup.php b/plugins/serendipity_event_xhtmlcleanup/serendipity_event_xhtmlcleanup.php
new file mode 100644 (file)
index 0000000..d65ffa6
--- /dev/null
@@ -0,0 +1,171 @@
+<?php # $Id$
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_XHTMLCLEANUP_NAME', 'Übliche XHTML-Fehler beseitigen');
+        @define('PLUGIN_EVENT_XHTMLCLEANUP_DESC', 'Korrigiert übliche Fehler, die beim XHTML-Markup der Einträge gemacht werden können');
+        break;
+
+    case 'en':
+    default:
+        @define('PLUGIN_EVENT_XHTMLCLEANUP_NAME', 'Fix common XHTML errors');
+        @define('PLUGIN_EVENT_XHTMLCLEANUP_DESC', 'This plugin corrects common issues with XHTML markup in entries. It assists in keeping your blog XHTML compliant.');
+        break;
+}
+
+if (!function_exists('html_entity_decode')) {
+    function html_entity_decode($given_html, $quote_style = ENT_QUOTES) {
+        $trans_table = get_html_translation_table(HTML_SPECIALCHARS, $quote_style);
+        if ($trans_table["'"] != '&#039;') { # some versions of PHP match single quotes to &#39;
+          $trans_table["'"] = '&#039;';
+        }
+
+        return (strtr($given_html, array_flip($trans_table)));
+    }
+}
+
+class serendipity_event_xhtmlcleanup extends serendipity_event
+{
+    var $title = PLUGIN_EVENT_XHTMLCLEANUP_NAME;
+    var $cleanup_tag, $cleanup_checkfor, $cleanup_val;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_XHTMLCLEANUP_NAME);
+        $propbag->add('description',   PLUGIN_EVENT_XHTMLCLEANUP_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Garvin Hicking');
+        $propbag->add('version',       '1.1');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('cachable_events', array('frontend_display' => true));
+        $propbag->add('event_hooks',   array('frontend_display' => true));
+
+        $this->markup_elements = array(
+            array(
+              'name'     => 'ENTRY_BODY',
+              'element'  => 'body',
+            ),
+            array(
+              'name'     => 'EXTENDED_BODY',
+              'element'  => 'extended',
+            ),
+            array(
+              'name'     => 'COMMENT',
+              'element'  => 'comment',
+            ),
+            array(
+              'name'     => 'HTML_NUGGET',
+              'element'  => 'html_nugget',
+            )
+        );
+
+        $conf_array = array();
+        foreach($this->markup_elements as $element) {
+            $conf_array[] = $element['name'];
+        }
+        $propbag->add('configuration', $conf_array);
+    }
+
+    function install() {
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function uninstall() {
+        serendipity_plugin_api::hook_event('backend_cache_purge', $this->title);
+        serendipity_plugin_api::hook_event('backend_cache_entries', $this->title);
+    }
+
+    function generate_content(&$title) {
+        $title = $this->title;
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        $propbag->add('type',        'boolean');
+        $propbag->add('name',        constant($name));
+        $propbag->add('description', sprintf(APPLY_MARKUP_TO, constant($name)));
+        $propbag->add('default',     'true');
+        return true;
+    }
+
+    function event_hook($event, &$bag, &$eventData, $addData = null) {
+        global $serendipity;
+
+        $hooks = &$bag->get('event_hooks');
+
+        if (isset($hooks[$event])) {
+            switch($event) {
+                case 'frontend_display':
+                    foreach ($this->markup_elements as $temp) {
+                        if (serendipity_db_bool($this->get_config($temp['name'], true)) && isset($eventData[$temp['element']])) {
+                            $element = $temp['element'];
+                            $this->cleanup_tag      = 'IMG';
+                            $this->cleanup_checkfor = 'ALT';
+                            $this->cleanup_val      = '';
+                            // Basic cleanup (core s9y functionality)
+                            $eventData[$element]    = xhtml_cleanup($eventData[$element]);
+                            $eventData[$element]    = preg_replace_callback('@(<img.+/?>)@imsU', array($this, 'clean_tag'), $eventData[$element]);
+                            $eventData[$element]    = preg_replace_callback("@<a(.*)href=(\"|')([^\"']+)(\"|')@isUm", array($this, 'clean_htmlspecialchars'), $eventData[$element]);
+                        }
+                    }
+
+                    return true;
+                    break;
+
+                default:
+                    return false;
+            }
+
+        } else {
+            return false;
+        }
+    }
+
+    // Takes an input tag and search for ommitted attributes. Expects a single tag (array, index 0)
+    function clean_tag($data) {
+        // Restore tags from preg_replace_callback buffer, as those can't be passed in the function header
+        $tag      = &$this->cleanup_tag;
+        $checkfor = &$this->cleanup_checkfor;
+        $val      = &$this->cleanup_val;
+
+        // Instead of nasty regex-mangling we use the XML parser to get the attribute list of our input tag
+        $p = xml_parser_create();
+        @xml_parse_into_struct($p, $data[0], $vals, $index);
+        xml_parser_free($p);
+
+        // Check if the xml parser returned anything useful
+        if (is_array($vals) && isset($vals[0]) && $vals[0]['tag'] == $tag) {
+
+            if (!empty($vals[0]['attributes'][$checkfor])) {
+                // The attribute we search for already exists. Return original string.
+                return $data[0];
+            }
+
+            // Assign the value we submitted for the attribute to insert
+            $vals[0]['attributes'][$checkfor] = $val;
+
+            // Reconstruct XHTML tag.
+            $atts = ' ';
+            foreach($vals[0]['attributes'] AS $att => $att_con) {
+                $atts .= strtolower($att) . '="' . $att_con . '" ';
+            }
+
+            return '<' . strtolower($tag) . $atts . ' />';
+        }
+
+        return $data[0];
+    }
+
+    function clean_htmlspecialchars($given, $quote_style = ENT_QUOTES) {
+        return '<a' . $given[1] . 'href=' . $given[2] . htmlspecialchars(html_entity_decode($given[3], $quote_style), $quote_style) . $given[4];
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_plugin_comments/lang_is.inc.php b/plugins/serendipity_plugin_comments/lang_is.inc.php
new file mode 100644 (file)
index 0000000..ae1f97e
--- /dev/null
@@ -0,0 +1,12 @@
+<?php # $Id$
+
+        @define('PLUGIN_COMMENTS_BLAHBLAH', 'Sýnir síðustu athugasemdir á færslurnar þínar');
+        @define('PLUGIN_COMMENTS_WORDWRAP', 'Línuskil');
+        @define('PLUGIN_COMMENTS_WORDWRAP_BLAHBLAH', 'Hversu mörg orð þar til línuskil eiga sér stað? (Sjálfgefið gildi: 30)');
+        @define('PLUGIN_COMMENTS_MAXCHARS', 'Hámarksstafafjöldi á athugasemd');
+        @define('PLUGIN_COMMENTS_MAXCHARS_BLAHBLAH', 'Hversu margir stafir eiga að vera birtir fyrir hverja athugasemd? (Sjálfgefið gildi: 120)');
+        @define('PLUGIN_COMMENTS_MAXENTRIES', 'Hámarksfjöldi athugasemda');
+        @define('PLUGIN_COMMENTS_MAXENTRIES_BLAHBLAH', 'Hversu margar athugasemdir skal sýna? (Sjálfgefið gildi: 15)');
+        @define('PLUGIN_COMMENTS_ABOUT', '%s um%s');
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/plugins/serendipity_plugin_comments/lang_ja.inc.php b/plugins/serendipity_plugin_comments/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..d1a9219
--- /dev/null
@@ -0,0 +1,12 @@
+<?php
+
+        @define('PLUGIN_COMMENTS_BLAHBLAH', 'あなたのエントリへの最後のコメントを表示します。');
+        @define('PLUGIN_COMMENTS_WORDWRAP', 'ワードラップ');
+        @define('PLUGIN_COMMENTS_WORDWRAP_BLAHBLAH', 'ワードラップするまでそれくらいの単語が現れますか? (デフォルト: 30)');
+        @define('PLUGIN_COMMENTS_MAXCHARS', 'コメントの最大文字数');
+        @define('PLUGIN_COMMENTS_MAXCHARS_BLAHBLAH', '各コメントで何文字位表示しますか? (デフォルト: 120)');
+        @define('PLUGIN_COMMENTS_MAXENTRIES', 'コメントの最大数');
+        @define('PLUGIN_COMMENTS_MAXENTRIES_BLAHBLAH', 'どれくらいのコメントを表示しますか? (デフォルト: 15)');
+        @define('PLUGIN_COMMENTS_ABOUT', '%s エントリ:%s');
+
+?>
diff --git a/plugins/serendipity_plugin_comments/serendipity_plugin_comments.php b/plugins/serendipity_plugin_comments/serendipity_plugin_comments.php
new file mode 100644 (file)
index 0000000..06c7cda
--- /dev/null
@@ -0,0 +1,181 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_COMMENTS_BLAHBLAH', 'Zeigt die letzten Kommentare');
+        @define('PLUGIN_COMMENTS_WORDWRAP', 'Zeilenumbruch');
+        @define('PLUGIN_COMMENTS_WORDWRAP_BLAHBLAH', 'Nach wievielen Wörtern soll ein Zeilenumbruch eingefügt werden? (Standard: 30)');
+        @define('PLUGIN_COMMENTS_MAXCHARS', 'Zeichen pro Kommentar');
+        @define('PLUGIN_COMMENTS_MAXCHARS_BLAHBLAH', 'Wieviele Zeichen sollen pro Kommentar gezeigt werden? (Standard: 120)');
+        @define('PLUGIN_COMMENTS_MAXENTRIES', 'Anzahl an Kommentaren');
+        @define('PLUGIN_COMMENTS_MAXENTRIES_BLAHBLAH', 'Wieviele Kommentare sollen gezeigt werden? (Standard: 15)');
+        @define('PLUGIN_COMMENTS_ABOUT', '%s zu%s');
+        break;
+
+    case 'en':
+    case 'es':
+    default:
+        @define('PLUGIN_COMMENTS_BLAHBLAH', 'Displays the last comments to your entries');
+        @define('PLUGIN_COMMENTS_WORDWRAP', 'Wordwrap');
+        @define('PLUGIN_COMMENTS_WORDWRAP_BLAHBLAH', 'How many words until a wordwrap will occur? (Default: 30)');
+        @define('PLUGIN_COMMENTS_MAXCHARS', 'Maximum chars per comment');
+        @define('PLUGIN_COMMENTS_MAXCHARS_BLAHBLAH', 'How many chars will be displayed for each comment? (Default: 120)');
+        @define('PLUGIN_COMMENTS_MAXENTRIES', 'Maximum number of comments');
+        @define('PLUGIN_COMMENTS_MAXENTRIES_BLAHBLAH', 'How many comments will be shown? (Default: 15)');
+        @define('PLUGIN_COMMENTS_ABOUT', '%s about%s');
+        break;
+}
+
+class serendipity_plugin_comments extends serendipity_plugin
+{
+    var $title = COMMENTS;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          COMMENTS);
+        $propbag->add('description',   PLUGIN_COMMENTS_BLAHBLAH);
+        $propbag->add('stackable',     true);
+        $propbag->add('author',        'Garvin Hicking');
+        $propbag->add('version',       '1.0');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('configuration', array(
+                                             'wordwrap',
+                                             'max_chars',
+                                             'max_entries',
+                                             'dateformat'));
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'wordwrap':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_COMMENTS_WORDWRAP);
+                $propbag->add('description', PLUGIN_COMMENTS_WORDWRAP_BLAHBLAH);
+                $propbag->add('default', 30);
+
+                break;
+
+            case 'max_chars':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_COMMENTS_MAXCHARS);
+                $propbag->add('description', PLUGIN_COMMENTS_MAXCHARS_BLAHBLAH);
+                $propbag->add('default', 120);
+                break;
+
+            case 'max_entries':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_COMMENTS_MAXENTRIES);
+                $propbag->add('description', PLUGIN_COMMENTS_MAXENTRIES_BLAHBLAH);
+                $propbag->add('default', 15);
+                break;
+
+            case 'dateformat':
+                $propbag->add('type', 'string');
+                $propbag->add('name', GENERAL_PLUGIN_DATEFORMAT);
+                $propbag->add('description', sprintf(GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH, '%a, %d.%m.%Y %H:%M'));
+                $propbag->add('default', '%a, %d.%m.%Y %H:%M');
+                break;
+
+            default:
+                    return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title)
+    {
+        global $serendipity;
+        $title       = $this->title;
+        $max_entries = $this->get_config('max_entries');
+        $max_chars   = $this->get_config('max_chars');
+        $wordwrap    = $this->get_config('wordwrap');
+        $dateformat  = $this->get_config('dateformat');
+
+        if (!$max_entries || !is_numeric($max_entries) || $max_entries < 1) {
+            $max_entries = 15;
+        }
+
+        if (!$max_chars || !is_numeric($max_chars) || $max_chars < 1) {
+            $max_chars = 120;
+        }
+
+        if (!$wordwrap || !is_numeric($wordwrap) || $wordwrap < 1) {
+            $wordwrap = 30;
+        }
+
+        if (!$dateformat || strlen($dateformat) < 1) {
+            $dateformat = '%a, %d.%m.%Y %H:%M';
+        }
+
+        $q = 'SELECT    c.body              AS comment,
+                        c.timestamp         AS stamp,
+                        c.author            AS user,
+                        e.title             AS subject,
+                        e.id                AS entry_id,
+                        c.id                AS comment_id,
+                        c.type              AS comment_type,
+                        c.url               AS comment_url,
+                        c.title             AS comment_title
+                FROM    '.$serendipity['dbPrefix'].'comments AS c,
+                        '.$serendipity['dbPrefix'].'entries  AS e
+               WHERE    e.id = c.entry_id
+                 AND    NOT (c.type = \'TRACKBACK\' AND c.author = \'' . serendipity_db_escape_string($serendipity['blogTitle']) . '\' AND c.title != \'\')
+                 AND    c.status = \'approved\'
+            ORDER BY    c.timestamp DESC
+            LIMIT ' . $max_entries;
+?>
+<div style="margin: 0px; padding: 0px; text-align: left;">
+<?php
+        $sql = serendipity_db_query($q);
+
+        if ($sql && is_array($sql)) {
+            foreach($sql AS $key => $row) {
+                $comments = wordwrap(strip_tags($row['comment']), $max_chars, '@@@', 1);
+                $aComment = explode('@@@', $comments);
+                $comment  = $aComment[0];
+                if (count($aComment) > 1) {
+                    $comment .= ' [...]';
+                }
+
+                if ($row['comment_type'] == 'TRACKBACK' && $row['comment_url'] != '') {
+                    $user = '<a class="highlight" href="' . strip_tags($row['comment_url']) . '" title="' . htmlspecialchars(strip_tags($row['comment_title'])) . '">' . htmlspecialchars(strip_tags($row['user'])) . '</a>';
+                } else {
+                    $user = htmlspecialchars(strip_tags($row['user']));
+                }
+
+                $entry = array('comment' => wordwrap($comment, $wordwrap, "\n", 1));
+                serendipity_plugin_api::hook_event('frontend_display', $entry);
+                printf(
+                  PLUGIN_COMMENTS_ABOUT,
+
+                  $user,
+                  ' <a class="highlight" href="' . serendipity_archiveURL($row['entry_id'], $row['subject'], 'baseURL') .'#c' . $row['comment_id'] . '" title="' . htmlspecialchars($row['subject']) . '">'
+                      . htmlspecialchars($row['subject'])
+                      . '</a><br />' . "\n"
+                      . htmlspecialchars(serendipity_strftime($dateformat, $row['stamp'])) . '<br />' . "\n"
+                      . strip_tags($entry['comment'], '<br><img>')
+                      . '<br /><br /><br />' . "\n\n"
+                );
+            }
+        }
+?>
+</div>
+<?php
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_plugin_creativecommons/lang_ja.inc.php b/plugins/serendipity_plugin_creativecommons/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..0f452cb
--- /dev/null
@@ -0,0 +1,18 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_SIDEBAR_CREATIVECOMMONS_NAME', 'クリエイティブコモンズ');
+        @define('PLUGIN_SIDEBAR_CREATIVECOMMONS_DESC', 'サイドバーにクリエイティブコモンズを告示します。');
+
+?>
diff --git a/plugins/serendipity_plugin_creativecommons/serendipity_plugin_creativecommons.php b/plugins/serendipity_plugin_creativecommons/serendipity_plugin_creativecommons.php
new file mode 100644 (file)
index 0000000..e94cfae
--- /dev/null
@@ -0,0 +1,71 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de': {
+        @define('PLUGIN_SIDEBAR_CREATIVECOMMONS_NAME', 'Creative Commons');
+        @define('PLUGIN_SIDEBAR_CREATIVECOMMONS_DESC', 'Zeigt einen Creative Commons Hinweis an');
+    }
+    break;
+
+    case 'en':
+    default: {
+        @define('PLUGIN_SIDEBAR_CREATIVECOMMONS_NAME', 'Creative Commons');
+        @define('PLUGIN_SIDEBAR_CREATIVECOMMONS_DESC', 'Display a creative commons notification in the sidebar.');
+    }
+    break;
+}
+
+class serendipity_plugin_creativecommons extends serendipity_plugin {
+    var $title = PLUGIN_SIDEBAR_CREATIVECOMMONS_NAME;
+
+    function introspect(&$propbag)
+    {
+        $this->title = $this->get_config('title', $this->title);
+
+        $propbag->add('name',          PLUGIN_SIDEBAR_CREATIVECOMMONS_NAME);
+        $propbag->add('description',   PLUGIN_SIDEBAR_CREATIVECOMMONS_DESC);
+        $propbag->add('stackable',     true);
+        $propbag->add('author',        'Evan Nemerson');
+        $propbag->add('version',       '1.0');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('configuration', array('title'));
+
+        $this->dependencies = array('serendipity_event_creativecommons' => 'remove');
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'title':
+                $propbag->add('type',          'string');
+                $propbag->add('name',          TITLE);
+                $propbag->add('description',   TITLE);
+                $propbag->add('default', '');
+                break;
+        }
+        return true;
+    }
+
+    function generate_content(&$title) {
+      global $serendipity;
+
+      $title = $this->get_config('title', $this->title);
+
+      $eventData = array('display_dat' => '');
+      serendipity_plugin_api::hook_event('frontend_display:html_layout', $eventData);
+      echo $eventData['display_dat'];
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_plugin_entrylinks/serendipity_plugin_entrylinks.php b/plugins/serendipity_plugin_entrylinks/serendipity_plugin_entrylinks.php
new file mode 100644 (file)
index 0000000..e8ffe21
--- /dev/null
@@ -0,0 +1,214 @@
+<?php # $Id$
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_ENTRYLINKS_NAME', 'Links des Artikels');
+        @define('PLUGIN_ENTRYLINKS_BLAHBLAH', 'Zeigt alle referenzierten Links eines Artikels');
+        @define('PLUGIN_ENTRYLINKS_NEWWIN', 'Links in neuem Fenster öffnen?');
+        @define('PLUGIN_ENTRYLINKS_NEWWIN_BLAHBLAH', 'Sollen die Links in einem neuen Fenster geöffnet werden? (Standard: Nein)');
+        @define('PLUGIN_ENTRYLINKS_REFERERS', 'Eingehende Links');
+        @define('PLUGIN_ENTRYLINKS_WORDWRAP', 'Zeilenumbruch');
+        @define('PLUGIN_ENTRYLINKS_WORDWRAP_BLAHBLAH', 'Nach wievielen Wörtern soll ein Zeilenumbruch eingefügt werden? (Standard: 30)');
+        @define('PLUGIN_ENTRYLINKS_MAXREF', 'Anzahl eingehender Links');
+        @define('PLUGIN_ENTRYLINKS_MAXREF_BLAHBLAH', 'Wieviele eingehende Links sollen höchstens dargestellt werden? (Standard: 15)');
+        @define('PLUGIN_ENTRYLINKS_ORDERBY', 'Reihenfolge eingehender Links');
+        @define('PLUGIN_ENTRYLINKS_ORDERBY_BLAHBLAH', 'Wonach sollen die eingehenden Links geordnet werden? (Standard: Häufigkeit)');
+        @define('PLUGIN_ENTRYLINKS_ORDERBY_DAY', 'Datum');
+        @define('PLUGIN_ENTRYLINKS_ORDERBY_FULLCOUNT', 'Häufigkeit');
+        break;
+
+    case 'en':
+    default:
+        @define('PLUGIN_ENTRYLINKS_NAME', 'Entry\'s Links');
+        @define('PLUGIN_ENTRYLINKS_BLAHBLAH', 'Shows all links referrenced in an article');
+        @define('PLUGIN_ENTRYLINKS_NEWWIN', 'Open links in new window?');
+        @define('PLUGIN_ENTRYLINKS_NEWWIN_BLAHBLAH', 'Should the links be opened in a new window? (Default: Current window)');
+        @define('PLUGIN_ENTRYLINKS_REFERERS', 'Referring links');
+        @define('PLUGIN_ENTRYLINKS_WORDWRAP', 'Wordwrap');
+        @define('PLUGIN_ENTRYLINKS_WORDWRAP_BLAHBLAH', 'How many words until a wordwrap will occur? (Default: 30)');
+        @define('PLUGIN_ENTRYLINKS_MAXREF', 'Maximum referring links');
+        @define('PLUGIN_ENTRYLINKS_MAXREF_BLAHBLAH', 'How many referring links should be displayed? (Default: 15)');
+        @define('PLUGIN_ENTRYLINKS_ORDERBY', 'Order of referring links');
+        @define('PLUGIN_ENTRYLINKS_ORDERBY_BLAHBLAH', 'By which key should the referring links be ordered? (Default: number of links)');
+        @define('PLUGIN_ENTRYLINKS_ORDERBY_DAY', 'Date');
+        @define('PLUGIN_ENTRYLINKS_ORDERBY_FULLCOUNT', 'Number of links');
+
+        break;
+}
+
+class serendipity_plugin_entrylinks extends serendipity_plugin
+{
+    var $title = PLUGIN_ENTRYLINKS_NAME;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $this->title = $this->get_config('title', $this->title);
+
+        $propbag->add('name',          PLUGIN_ENTRYLINKS_NAME);
+        $propbag->add('description',   PLUGIN_ENTRYLINKS_BLAHBLAH);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Garvin Hicking');
+        $propbag->add('version',       '1.0');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('configuration', array('title', 'newwin', 'markup', 'wordwrap', 'show_exits', 'show_referers', 'maxref', 'orderby'));
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'title':
+                $propbag->add('type', 'string');
+                $propbag->add('name', TITLE);
+                $propbag->add('description', TITLE);
+                $propbag->add('default', '');
+                break;
+
+            case 'newwin':
+                $propbag->add('type', 'boolean');
+                $propbag->add('name', PLUGIN_ENTRYLINKS_NEWWIN);
+                $propbag->add('description', PLUGIN_ENTRYLINKS_NEWWIN_BLAHBLAH);
+                $propbag->add('default', 'false');
+                break;
+
+            case 'markup':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        DO_MARKUP);
+                $propbag->add('description', DO_MARKUP_DESCRIPTION);
+                $propbag->add('default', 'true');
+                break;
+
+            case 'show_exits':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        TOP_EXITS);
+                $propbag->add('description', SHOWS_TOP_EXIT);
+                $propbag->add('default', 'true');
+                break;
+
+            case 'show_referers':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        TOP_REFERRER);
+                $propbag->add('description', SHOWS_TOP_SITES);
+                $propbag->add('default', '');
+                break;
+
+            case 'maxref':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_ENTRYLINKS_MAXREF);
+                $propbag->add('description', PLUGIN_ENTRYLINKS_MAXREF_BLAHBLAH);
+                $propbag->add('default', 15);
+                break;
+
+            case 'wordwrap':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_ENTRYLINKS_WORDWRAP);
+                $propbag->add('description', PLUGIN_ENTRYLINKS_WORDWRAP_BLAHBLAH);
+                $propbag->add('default', 30);
+                break;
+
+            case 'orderby':
+                $select = array('day' => PLUGIN_ENTRYLINKS_ORDERBY_DAY, 'fullcount' => PLUGIN_ENTRYLINKS_ORDERBY_FULLCOUNT);
+                $propbag->add('type', 'select');
+                $propbag->add('name', PLUGIN_ENTRYLINKS_ORDERBY);
+                $propbag->add('description', PLUGIN_ENTRYLINKS_ORDERBY_BLAHBLAH);
+                $propbag->add('select_values', $select);
+                $propbag->add('default', 'fullcount');
+                break;
+
+            default:
+                    return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title)
+    {
+        global $serendipity;
+
+        $title = $this->get_config('title', $this->title);
+
+        if (!isset($serendipity['GET']['id']) || !is_numeric($serendipity['GET']['id'])) {
+            return false;
+        } else {
+            $id = serendipity_db_escape_string($serendipity['GET']['id']);
+        }
+
+        $target   = '';
+        $newwin   = $this->get_config('newwin', 'false');
+        $wordwrap = $this->get_config('wordwrap', 30);
+        $maxref   = $this->get_config('maxref', 15);
+        $orderby  = $this->get_config('orderby', 'fullcount');
+
+        if ($newwin == 'true') {
+            $target = ' target="_blank" ';
+        }
+
+
+        $counter    = array();
+
+        if ($this->get_config('show_exits', 'true') == 'true') {
+            $exits      = serendipity_db_query("SELECT SUM(count) as fullcount, scheme, host, port, path, query, " . serendipity_db_concat("scheme, '://', host, ':', port, path, '?', query") . " AS fulllink FROM {$serendipity['dbPrefix']}exits WHERE entry_id = " . $id . " GROUP BY scheme,host,port,path,query");
+            if (is_array($exits)) {
+                foreach($exits AS $key => $row) {
+                    $url = sprintf('%s://%s%s%s%s',
+                      $row['scheme'],
+                      $row['host'],
+                      (!empty($row['port']) ? ':' . $row['port'] : ''),
+                      $row['path'],
+                      (!empty($row['query']) ? '?' . $row['query'] : '')
+                    );
+
+                    $counter[$url] = $row['fullcount'];
+                }
+            }
+        }
+
+        $references = serendipity_db_query("SELECT link, max(name) as name FROM {$serendipity['dbPrefix']}references WHERE entry_id = " . $id . " GROUP BY link");
+        if (is_array($references)) {
+            $links = '<ul style="margin: 5px; padding: 10px; text-align: left">';
+            foreach($references AS $key => $row) {
+                $count = '';
+                if (isset($counter[$row['link']])) {
+                    $count = '<br /><div style="text-align: right; margin: 0px">[' . $counter[$row['link']] . ']</div>';
+                }
+                $links .= '<li><a href="' . $row['link'] . '" ' . $target . '>' . wordwrap($row['name'], $wordwrap, "<br />", 1) . "</a>$count</li>";
+            }
+            $links .= '</ul>';
+
+            if ($this->get_config('markup', 'true') == 'true') {
+                $entry = array('html_nugget' => $links, 'entry_id' => $id);
+                serendipity_plugin_api::hook_event('frontend_display', $entry);
+                echo $entry['html_nugget'];
+            } else {
+                echo $links;
+            }
+        }
+
+        if ($this->get_config('show_referers', 'true') == 'true') {
+            $ref      = serendipity_db_query("SELECT SUM(count) as fullcount, scheme, host, port, path, query, " . serendipity_db_concat("scheme, '://', host, ':', port, path, '?', query") . " AS fulllink FROM {$serendipity['dbPrefix']}referrers WHERE entry_id = " . $id . " GROUP BY scheme,host,port,path,query ORDER BY $orderby DESC LIMIT $maxref");
+            if (is_array($ref)) {
+                echo PLUGIN_ENTRYLINKS_REFERERS . '<ul style="margin: 5px; padding: 10px; text-align: left">';
+                foreach($ref AS $key => $row) {
+                    $url = sprintf('%s://%s%s%s%s',
+                      $row['scheme'],
+                      $row['host'],
+                      (!empty($row['port']) ? ':' . $row['port'] : ''),
+                      $row['path'],
+                      (!empty($row['query']) ? '?' . $row['query'] : '')
+                    );
+
+                    echo '<li><a href="' . $url . '" ' . $target . '>' . wordwrap($row['host'], $wordwrap, "<br />", 1) . '</a><br /><div style="text-align: right; margin: 0px;">[' . $row['fullcount'] . "]</div></li>";
+                }
+                echo '</ul>';
+            }
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_plugin_eventwrapper/serendipity_plugin_eventwrapper.php b/plugins/serendipity_plugin_eventwrapper/serendipity_plugin_eventwrapper.php
new file mode 100644 (file)
index 0000000..30a7c1e
--- /dev/null
@@ -0,0 +1,103 @@
+<?php # $Id$
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_EVENT_WRAPPER_NAME', 'Event-Ausgabe Wrapper');
+        @define('PLUGIN_EVENT_WRAPPER_DESC', 'Zeigt die Ausgabedaten eines Event-Plugins an');
+        @define('PLUGIN_EVENT_WRAPPER_PLUGIN', 'Quell Event-Plugin');
+        @define('PLUGIN_EVENT_WRAPPER_PLUGINDESC', 'Wählen Sie das Event-Plugin aus, für das die Ausgabe dargestellt werden soll');
+        @define('PLUGIN_EVENT_WRAPPER_TITLEDESC', 'Geben Sie den Titel für die Sidebar an. Die Eingabe eines leeren Titels zeigt den des Event-Plugins an.');
+        break;
+
+    case 'en':
+    case 'es':
+    default:
+        @define('PLUGIN_EVENT_WRAPPER_NAME', 'Event-Output wrapper');
+        @define('PLUGIN_EVENT_WRAPPER_DESC', 'Displays gathered data by a certain event plugin');
+        @define('PLUGIN_EVENT_WRAPPER_PLUGIN', 'Source event plugin');
+        @define('PLUGIN_EVENT_WRAPPER_PLUGINDESC', 'Select the event plugin for which the output should be displayed');
+        @define('PLUGIN_EVENT_WRAPPER_TITLEDESC', 'Enter the title for this sidebar item (leave empty for inheritance by event plugin)');
+
+        break;
+}
+
+class serendipity_plugin_eventwrapper extends serendipity_plugin
+{
+var $rewrite_from, $rewrite_to;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_EVENT_WRAPPER_NAME);
+        $propbag->add('description',   PLUGIN_EVENT_WRAPPER_DESC);
+        $propbag->add('stackable',     true);
+        $propbag->add('author',        'Garvin Hicking');
+        $propbag->add('version',       '1.0');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('configuration', array('event_plugin', 'title'));
+
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        global $serendipity;
+
+        switch($name) {
+            case 'event_plugin':
+                $plugins = serendipity_plugin_api::get_event_plugins();
+                $select = array();
+
+                if (is_array($plugins)) {
+                    foreach($plugins AS $plugname => $plugarray) {
+                        $select[$plugname] = $plugarray['t'];
+                    }
+                }
+
+                $propbag->add('type',        'select');
+                $propbag->add('name',        PLUGIN_EVENT_WRAPPER_PLUGIN);
+                $propbag->add('description', PLUGIN_EVENT_WRAPPER_PLUGINDESC);
+                $propbag->add('select_values', $select);
+                $propbag->add('default', 'false');
+                break;
+
+            case 'title':
+                $propbag->add('type',        'string');
+                $propbag->add('name',        TITLE);
+                $propbag->add('description', PLUGIN_EVENT_WRAPPER_TITLEDESC);
+                $propbag->add('default', '');
+                break;
+
+            default:
+                    return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title)
+    {
+        $plug = $this->get_config('event_plugin', 'false');
+        if ($plug == 'false') {
+            return;
+        }
+
+        $wrap = &serendipity_plugin_api::get_event_plugins($plug);
+        $faketitle = '';
+        if (is_object($wrap)) {
+            $wrap->generate_content($faketitle);
+        }
+
+        if ($this->get_config('title') != '') {
+            $title = $this->get_config('title');
+        } else {
+            $title = $faketitle;
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_plugin_history/lang_ja.inc.php b/plugins/serendipity_plugin_history/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..eccbfa0
--- /dev/null
@@ -0,0 +1,41 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_HISTORY_NAME', '履歴');
+        @define('PLUGIN_HISTORY_DESC', 'Displays ancient entries of an adjustable age.');
+        @define('PLUGIN_HISTORY_MIN_AGE', '最小期');
+        @define('PLUGIN_HISTORY_MIN_AGE_DESC', 'Minimum age of entries (単位は日).');
+        @define('PLUGIN_HISTORY_MAX_AGE', '最大期');
+        @define('PLUGIN_HISTORY_MAX_AGE_DESC','Maximum age of entries (単位は日).');
+        @define('PLUGIN_HISTORY_MAX_ENTRIES', '最大エントリ');
+        @define('PLUGIN_HISTORY_MAX_ENTRIES_DESC', '表示するエントリの数');
+        @define('PLUGIN_HISTORY_SHOWFULL', '完全なエントリ');
+        @define('PLUGIN_HISTORY_SHOWFULL_DESC', 'Display full entries instead of linked headlines.');
+        @define('PLUGIN_HISTORY_INTRO', 'イントロ');
+        @define('PLUGIN_HISTORY_INTRO_DESC', 'A short intro like \'One year ago I said:\'.');
+        @define('PLUGIN_HISTORY_OUTRO', 'アウトロ');
+        @define('PLUGIN_HISTORY_OUTRO_DESC', 'A short Outro like \'Nice, eh?\'.');
+        @define('PLUGIN_HISTORY_DISPLAYDATE', '日付表示をする');
+        @define('PLUGIN_HISTORY_DISPLAYDATE_DESC', 'Display the date of each entry?');
+        @define('PLUGIN_HISTORY_MAXLENGTH', '題名の長さ');
+        @define('PLUGIN_HISTORY_MAXLENGTH_DESC', 'After how many characters to cut the titles (0 for full titles)?');
+        @define('PLUGIN_HISTORY_SPECIALAGE', 'Ready-made age?');
+        @define('PLUGIN_HISTORY_SPECIALAGE_DESC', 'If you want to define your own timerange instead of a ready-made, select \'I\'ll define one\' here and adjust the two settings below.');
+        @define('PLUGIN_HISTORY_SPECIALAGE_YEAR', 'Display items of exactly one year ago');
+        @define('PLUGIN_HISTORY_CUSTOMAGE', 'Let me define the age');
+        @define('PLUGIN_HISTORY_OYA', '1 年前');
+        @define('PLUGIN_HISTORY_MYSELF', 'I\'ll define one');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_plugin_history/serendipity_plugin_history.php b/plugins/serendipity_plugin_history/serendipity_plugin_history.php
new file mode 100644 (file)
index 0000000..18a3f57
--- /dev/null
@@ -0,0 +1,242 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_HISTORY_NAME', 'Geschichte');
+        @define('PLUGIN_HISTORY_DESC', 'Zeigt Einträge eines einstellbaren Alters an.');
+        @define('PLUGIN_HISTORY_MIN_AGE', 'Mindestalter');
+        @define('PLUGIN_HISTORY_MIN_AGE_DESC', 'Mindestalter der Einträge (in Tagen).');
+        @define('PLUGIN_HISTORY_MAX_AGE', 'Höchstalter');
+        @define('PLUGIN_HISTORY_MAX_AGE_DESC','Höchstalter der Einträge (in Tagen).');
+        @define('PLUGIN_HISTORY_MAX_ENTRIES', 'Anzahl');
+        @define('PLUGIN_HISTORY_MAX_ENTRIES_DESC', 'Wieviele Einträge sollen maximal angezeigt werden?');
+        @define('PLUGIN_HISTORY_SHOWFULL', 'Ganze Einträge');
+        @define('PLUGIN_HISTORY_SHOWFULL_DESC', 'Nicht nur Überschriften, sondern ganze Einträge anzeigen.');
+        @define('PLUGIN_HISTORY_INTRO', 'Intro');
+        @define('PLUGIN_HISTORY_INTRO_DESC', 'Text, der vor den Einträgen angezeigt werden soll');
+        @define('PLUGIN_HISTORY_OUTRO', 'Outro');
+        @define('PLUGIN_HISTORY_OUTRO_DESC', 'Text, der hinter den Einträgen angezeigt werden soll');
+        @define('PLUGIN_HISTORY_DISPLAYDATE', 'Datum anzeigen');
+        @define('PLUGIN_HISTORY_DISPLAYDATE_DESC', 'Vor jedem Eintrag das Datum anzeigen?');
+        @define('PLUGIN_HISTORY_MAXLENGTH', 'Überschriftenlänge');
+        @define('PLUGIN_HISTORY_MAXLENGTH_DESC', 'Nach wievielen Zeichen sollen die Überschriften abgeschnitten werden (0 für garnicht)?');
+        @define('PLUGIN_HISTORY_SPECIALAGE', 'Vorgefertigter Zeitrahmen');
+        @define('PLUGIN_HISTORY_SPECIALAGE_DESC', 'Wenn Sie statt einem vorgefertigten lieber einen eigenen Zeitraum einstellen möchten, wählen Sie \'Anderer\' aus und füllen die unteren beiden Felder.');
+        @define('PLUGIN_HISTORY_SPECIALAGE_YEAR', 'Zeigt Einträge vom selben Datum des letzten Jahres an.');
+        @define('PLUGIN_HISTORY_CUSTOMAGE', 'Zeitrahmen selbst einstellen');
+        @define('PLUGIN_HISTORY_OYA', 'Heute vor einem Jahr');
+        @define('PLUGIN_HISTORY_MYSELF', 'Anderer');
+    break;
+    default:
+        @define('PLUGIN_HISTORY_NAME', 'History');
+        @define('PLUGIN_HISTORY_DESC', 'Displays ancient entries of an adjustable age.');
+        @define('PLUGIN_HISTORY_MIN_AGE', 'Min age');
+        @define('PLUGIN_HISTORY_MIN_AGE_DESC', 'Minimum age of entries (in days).');
+        @define('PLUGIN_HISTORY_MAX_AGE', 'Max age');
+        @define('PLUGIN_HISTORY_MAX_AGE_DESC','Maximum age of entries (in days).');
+        @define('PLUGIN_HISTORY_MAX_ENTRIES', 'Maximum entries');
+        @define('PLUGIN_HISTORY_MAX_ENTRIES_DESC', 'Number of entries to display');
+        @define('PLUGIN_HISTORY_SHOWFULL', 'Full entries');
+        @define('PLUGIN_HISTORY_SHOWFULL_DESC', 'Display full entries instead of linked headlines.');
+        @define('PLUGIN_HISTORY_INTRO', 'Intro');
+        @define('PLUGIN_HISTORY_INTRO_DESC', 'A short intro like \'One year ago I said:\'.');
+        @define('PLUGIN_HISTORY_OUTRO', 'Outro');
+        @define('PLUGIN_HISTORY_OUTRO_DESC', 'A short Outro like \'Nice, eh?\'.');
+        @define('PLUGIN_HISTORY_DISPLAYDATE', 'Display date');
+        @define('PLUGIN_HISTORY_DISPLAYDATE_DESC', 'Display the date of each entry?');
+        @define('PLUGIN_HISTORY_MAXLENGTH', 'Title-Length');
+        @define('PLUGIN_HISTORY_MAXLENGTH_DESC', 'After how many characters to cut the titles (0 for full titles)?');
+        @define('PLUGIN_HISTORY_SPECIALAGE', 'Ready-made age?');
+        @define('PLUGIN_HISTORY_SPECIALAGE_DESC', 'If you want to define your own timerange instead of a ready-made, select \'I\'ll define one\' here and adjust the two settings below.');
+        @define('PLUGIN_HISTORY_SPECIALAGE_YEAR', 'Display items of exactly one year ago');
+        @define('PLUGIN_HISTORY_CUSTOMAGE', 'Let me define the age');
+        @define('PLUGIN_HISTORY_OYA', 'One year ago');
+        @define('PLUGIN_HISTORY_MYSELF', 'I\'ll define one');
+    break;
+}
+
+class serendipity_plugin_history extends serendipity_plugin
+{
+    var $title = PLUGIN_HISTORY_NAME;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $this->title = $this->get_config('title', $this->title);
+
+        $propbag->add('name',          PLUGIN_HISTORY_NAME);
+        $propbag->add('description',   PLUGIN_HISTORY_DESC);
+        $propbag->add('stackable',     true);
+        $propbag->add('author',        'Jannis Hermanns');
+        $propbag->add('version',       '1.0');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('configuration', array('title',
+                                             'intro',
+                                             'outro',
+                                             'maxlength',
+                                             'specialage',
+                                             'min_age',
+                                             'max_age',
+                                             'max_entries',
+                                             'full',
+                                             'amount',
+                                             'displaydate',
+                                             'dateformat'));
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'title':
+                $propbag->add('type', 'string');
+                $propbag->add('name', TITLE);
+                $propbag->add('description', '');
+                $propbag->add('default', PLUGIN_HISTORY_NAME);
+            break;
+            case 'intro':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_HISTORY_INTRO);
+                $propbag->add('description', PLUGIN_HISTORY_INTRO_DESC);
+                $propbag->add('default', '');
+            break;
+            case 'outro':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_HISTORY_OUTRO);
+                $propbag->add('description', PLUGIN_HISTORY_OUTRO_DESC);
+                $propbag->add('default', '');
+            break;
+            case 'maxlength':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_HISTORY_MAXLENGTH);
+                $propbag->add('description', PLUGIN_HISTORY_MAXLENGTH_DESC);
+                $propbag->add('default', 30);
+            break;
+            case 'specialage':
+                $propbag->add('type', 'select');
+                $propbag->add('name', PLUGIN_HISTORY_SPECIALAGE);
+                $propbag->add('description', PLUGIN_HISTORY_SPECIALAGE_DESC);
+                $propbag->add('default', 'year');
+                $propbag->add('select_values', array('year'=>PLUGIN_HISTORY_OYA,'custom'=>PLUGIN_HISTORY_MYSELF));
+            break;
+            case 'min_age':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_HISTORY_MIN_AGE);
+                $propbag->add('description', PLUGIN_HISTORY_MIN_AGE_DESC);
+                $propbag->add('default', 365);
+            break;
+            case 'max_age':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_HISTORY_MAX_AGE);
+                $propbag->add('description', PLUGIN_HISTORY_MAX_AGE_DESC);
+                $propbag->add('default', 365);
+            break;
+            case 'max_entries':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_HISTORY_MAX_ENTRIES);
+                $propbag->add('description', PLUGIN_HISTORY_MAX_ENTRIES_DESC);
+                $propbag->add('default', 5);
+            break;
+            case 'full':
+                $propbag->add('type',         'select');
+                $propbag->add('name',         PLUGIN_HISTORY_SHOWFULL);
+                $propbag->add('description',  PLUGIN_HISTORY_SHOWFULL_DESC);
+                $propbag->add('select_values', array('false','true'));
+                $propbag->add('default',     'false');
+            break;
+            case 'displaydate':
+                $propbag->add('type',         'select');
+                $propbag->add('name',         PLUGIN_HISTORY_DISPLAYDATE);
+                $propbag->add('description',  PLUGIN_HISTORY_DISPLAYDATE_DESC);
+                $propbag->add('select_values', array('false','true'));
+                $propbag->add('default',     'true');
+            break;
+            case 'dateformat':
+                $propbag->add('type', 'string');
+                $propbag->add('name', GENERAL_PLUGIN_DATEFORMAT);
+                $propbag->add('description', sprintf(GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH, '%a, %d.%m.%Y %H:%M'));
+                $propbag->add('default', '%a, %d.%m.%Y %H:%M');
+            break;
+            default:
+                    return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title)
+    {
+     global $serendipity;
+        $title       = $this->get_config('title', $this->title);
+        $intro       = $this->get_config('intro');
+        $outro       = $this->get_config('outro');
+        $maxlength   = $this->get_config('maxlength');
+        $max_entries = $this->get_config('max_entries');
+        $min_age     = $this->get_config('min_age');
+        $max_age     = $this->get_config('max_age');
+        $specialage  = $this->get_config('specialage');
+        $displaydate = $this->get_config('displaydate', 'true');
+        $dateformat  = $this->get_config('dateformat');
+        $full        = ($this->get_config('full', 'false') != 'true') ? false : true;
+
+        if (!is_numeric($min_age) || $min_age < 0 || $specialage == 'year') {
+            $min_age = 365 + date('L', serendipity_serverOffsetHour());
+        }
+
+        if (!is_numeric($max_age) || $max_age < 1 || $specialage == 'year') {
+            $max_age = 365 + date('L', serendipity_serverOffsetHour());
+        }
+
+        if (!is_numeric($max_entries) || $max_entries < 1) {
+            $max_entries = 5;
+        }
+
+        if (!is_numeric($maxlength) ||$maxlength <0)
+            $maxlength = 30;
+
+        if (strlen($dateformat) < 1) {
+            $dateformat = '%a, %d.%m.%Y %H:%M';
+        }
+
+        $nowts = serendipity_serverOffsetHour();
+        $maxts = mktime(23, 59, 59,  date('m', $nowts), date('d', $nowts), date('Y', $nowts));
+        $mints = mktime(0, 0, 0, date('m', $nowts), date('d', $nowts), date('Y', $nowts));
+        $e     = serendipity_fetchEntries(array(($mints-$max_age*86400),
+                                            ($maxts-$min_age*86400)), $full, $max_entries);
+        echo (empty($intro)) ? '' : "$intro<br />";
+
+        if (!is_array($e)) {
+            return false;
+        }
+
+        if ( ($e_c = count($e)) == 0 ) {
+            return false;
+        }
+
+        for($x=0; $x < $e_c; $x++) {
+            $url = serendipity_archiveURL($e[$x]['id'],
+                                          $e[$x]['title'],
+                                          'serendipityHTTPPath'
+            );
+            $date = ($displaydate=='0') ? '' : strftime($dateformat,$e[$x]['timestamp']);
+            $t = ($maxlength==0 || strlen($e[$x]['title'])<=$maxlength) ?
+                    $e[$x]['title'] :
+                    (trim(serendipity_mb('substr', $e[$x]['title'], 0, $maxlength-3)).' [...]');
+            echo $date . "<a href='$url' title='".str_replace("'", '`', $e[$x][title])."'>".$t."</a> " .
+                 strip_tags($e[$x]['body']) . '<br />';
+        }
+        echo $outro;
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_plugin_recententries/lang_is.inc.php b/plugins/serendipity_plugin_recententries/lang_is.inc.php
new file mode 100644 (file)
index 0000000..57c8b5e
--- /dev/null
@@ -0,0 +1,9 @@
+<?php # $Id$
+
+        @define('PLUGIN_RECENTENTRIES_TITLE', 'Nýlegar færslur');
+        @define('PLUGIN_RECENTENTRIES_BLAHBLAH', 'Sýnir titla og dagsetningar nýlegustu færslanna');
+        @define('PLUGIN_RECENTENTRIES_NUMBER', 'Fjöldi færsla');
+        @define('PLUGIN_RECENTENTRIES_NUMBER_BLAHBLAH', 'Hversu margar færslur ættu að vera sýndar? (Sjálfgefið gildi: 10)');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/plugins/serendipity_plugin_recententries/lang_ja.inc.php b/plugins/serendipity_plugin_recententries/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..9e80b4b
--- /dev/null
@@ -0,0 +1,25 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_RECENTENTRIES_TITLE', '最近のエントリ');
+        @define('PLUGIN_RECENTENTRIES_BLAHBLAH', 'もっとも最近のエントリの題名と日付を表示します');
+        @define('PLUGIN_RECENTENTRIES_NUMBER', 'エントリの数');
+        @define('PLUGIN_RECENTENTRIES_NUMBER_BLAHBLAH', 'どれくらいのエントリを表示しますか? (デフォルト: 10)');
+        @define('PLUGIN_RECENTENTRIES_NUMBER_FROM', 'フロントページエントリで省略する');
+        @define('PLUGIN_RECENTENTRIES_NUMBER_FROM_DESC', 'Only recent entries that are not on the front page will be shown. (Default: latest ' . $serendipity['fetchLimit'] . ' will be skipped)');
+        @define('PLUGIN_RECENTENTRIES_NUMBER_FROM_RADIO_ALL', 'すべて表示');
+        @define('PLUGIN_RECENTENTRIES_NUMBER_FROM_RADIO_RECENT', 'フロントページ項目は省略する');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_plugin_recententries/serendipity_plugin_recententries.php b/plugins/serendipity_plugin_recententries/serendipity_plugin_recententries.php
new file mode 100644 (file)
index 0000000..aa729b9
--- /dev/null
@@ -0,0 +1,187 @@
+<?php # $Id$
+
+// Contributed by Christian Machmeier <cm@redsplash.de>
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_RECENTENTRIES_TITLE', 'Aktuelle Einträge');
+        @define('PLUGIN_RECENTENTRIES_BLAHBLAH', 'Zeigt die Titel der aktuellsten Einträge mit Datum');
+        @define('PLUGIN_RECENTENTRIES_NUMBER', 'Anzahl der Einträge');
+        @define('PLUGIN_RECENTENTRIES_NUMBER_BLAHBLAH', 'Wieviele Einträge sollen angezeigt werden? (Standard: 10)');
+        @define('PLUGIN_RECENTENTRIES_NUMBER_FROM', 'Angezeigte Einträge überspringen');
+        @define('PLUGIN_RECENTENTRIES_NUMBER_FROM_DESC', 'Nur die neuesten Einträge, die nicht schon auf der Hauptseite zu sehen sind, werden angezeigt. (Default: die neuesten ' . $serendipity['fetchLimit'] . ' werden übersprungen)');
+        @define('PLUGIN_RECENTENTRIES_NUMBER_FROM_RADIO_ALL', 'Alle anzeigen');
+        @define('PLUGIN_RECENTENTRIES_NUMBER_FROM_RADIO_RECENT', 'Einträge auf der Hauptseite überspringen');
+        break;
+
+    case 'en':
+    case 'es':
+    default:
+        @define('PLUGIN_RECENTENTRIES_TITLE', 'Recent Entries');
+        @define('PLUGIN_RECENTENTRIES_BLAHBLAH', 'Shows the titles and dates of the most recent entries');
+        @define('PLUGIN_RECENTENTRIES_NUMBER', 'Number of entries');
+        @define('PLUGIN_RECENTENTRIES_NUMBER_BLAHBLAH', 'How many entries should be displayed? (Default: 10)');
+        @define('PLUGIN_RECENTENTRIES_NUMBER_FROM', 'Skip front page entries');
+        @define('PLUGIN_RECENTENTRIES_NUMBER_FROM_DESC', 'Only recent entries that are not on the front page will be shown. (Default: latest ' . $serendipity['fetchLimit'] . ' will be skipped)');
+        @define('PLUGIN_RECENTENTRIES_NUMBER_FROM_RADIO_ALL', 'Show all');
+        @define('PLUGIN_RECENTENTRIES_NUMBER_FROM_RADIO_RECENT', 'Skip front page items');
+        break;
+}
+
+class serendipity_plugin_recententries extends serendipity_plugin {
+    var $title = PLUGIN_RECENTENTRIES_TITLE;
+
+    function introspect(&$propbag) {
+        $this->title = $this->get_config('title', $this->title);
+
+        $propbag->add('name',          PLUGIN_RECENTENTRIES_TITLE);
+        $propbag->add('description',   PLUGIN_RECENTENTRIES_BLAHBLAH);
+        $propbag->add('stackable',     true);
+        $propbag->add('author',        'Christian Machmeier');
+        $propbag->add('version',       '1.2');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('configuration', array('title', 'number', 'number_from', 'dateformat', 'category'));
+    }
+
+    function introspect_config_item($name, &$propbag) {
+        switch($name) {
+            case 'title':
+                $propbag->add('type',        'string');
+                $propbag->add('name',        TITLE);
+                $propbag->add('description', TITLE_FOR_NUGGET);
+                $propbag->add('default',     PLUGIN_RECENTENTRIES_TITLE);
+                break;
+
+            case 'number':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_RECENTENTRIES_NUMBER);
+                $propbag->add('description', PLUGIN_RECENTENTRIES_NUMBER_BLAHBLAH);
+                $propbag->add('default', 10);
+                break;
+
+                case 'number_from':
+                    $propbag->add('type', 'radio');
+                    $propbag->add('name', PLUGIN_RECENTENTRIES_NUMBER_FROM);
+                    $propbag->add('description', PLUGIN_RECENTENTRIES_NUMBER_FROM_DESC);
+                    $propbag->add('radio',  array(
+                        'value' => array('all', 'skip'),
+                        'desc'  => array(PLUGIN_RECENTENTRIES_NUMBER_FROM_RADIO_ALL, PLUGIN_RECENTENTRIES_NUMBER_FROM_RADIO_RECENT)
+                        ));
+                    $propbag->add('default', 'all');
+                break;
+
+            case 'dateformat':
+                $propbag->add('type', 'string');
+                $propbag->add('name', GENERAL_PLUGIN_DATEFORMAT);
+                $propbag->add('description', sprintf(GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH, '%A, %B %e %Y'));
+                $propbag->add('default', '%A, %B %e %Y');
+                break;
+
+            case 'category':
+                $cats    = serendipity_fetchCategories($serendipity['authorid']);
+                if (!is_array($cats)) {
+                    return false;
+                }
+
+                $catlist = serendipity_generateCategoryList($cats, array(0), 4);
+                $tmp_select_cats = explode('@@@', $catlist);
+
+                if (!is_array($tmp_select_cats)) {
+                    return false;
+                }
+
+                $select_cats = array();
+                $select_cats['none'] = ALL_CATEGORIES;
+                foreach($tmp_select_cats as $cidx => $tmp_select_cat) {
+                    $select_cat = explode('|||', $tmp_select_cat);
+                    if (!empty($select_cat[0]) && !empty($select_cat[1])) {
+                        $select_cats[$select_cat[0]] = $select_cat[1];
+                    }
+                }
+
+                $propbag->add('type',          'select');
+                $propbag->add('select_values', $select_cats);
+                $propbag->add('name',          CATEGORY);
+                $propbag->add('description',   CATEGORIES_TO_FETCH);
+                $propbag->add('default',       'none');
+                break;
+
+            default:
+                return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title) {
+        global $serendipity;
+
+        $number         = $this->get_config('number');
+        $dateformat     = $this->get_config('dateformat');
+        $category       = $this->get_config('category', 'none');
+        $title          = $this->get_config('title', $this->title);
+        $number_from_sw = $this->get_config('number_from');
+
+        $sql_join   = '';
+        $sql_where  = '';
+        if ($category != 'none' && is_numeric($category)) {
+            $sql_join = 'LEFT OUTER JOIN ' . $serendipity['dbPrefix'] . 'entrycat AS ec ON id = ec.entryid
+                         LEFT OUTER JOIN ' . $serendipity['dbPrefix'] . 'category AS c  ON ec.categoryid = c.categoryid';
+            $sql_where = ' AND (c.category_left BETWEEN ' . implode(' AND ', serendipity_fetchCategoryRange($category)) . ')';
+        }
+
+        if (!$number || !is_numeric($number) || $number < 1) {
+            $number = 10;
+        }
+
+        $sql_number = serendipity_db_limit_sql($number);
+
+        switch($number_from_sw) {
+            case 'skip':
+                $sql_number = serendipity_db_limit_sql(serendipity_db_limit($serendipity['fetchLimit'], $number));
+                break;
+        }
+
+        if (!$dateformat || strlen($dateformat) < 1) {
+            $dateformat = '%A, %B %e %Y';
+        }
+
+        $entries_query = "SELECT id,
+                                                title,
+                                                timestamp
+                                           FROM {$serendipity['dbPrefix']}entries
+                                                $sql_join
+                                          WHERE isdraft = 'false' AND timestamp <= " . time() . "
+                                                $sql_where
+                                       ORDER BY timestamp DESC
+                                                $sql_number";
+        $entries = serendipity_db_query($entries_query);
+
+        if (isset($entries) && is_array($entries)) {
+            foreach ($entries as $k => $entry) {
+                $entryLink = serendipity_archiveURL(
+                               $entry['id'],
+                               $entry['title'],
+                               'serendipityHTTPPath'
+                            );
+
+                echo '<a href="' . $entryLink . '" title="' . htmlspecialchars($entry['title']) . '">' . $entry['title'] . '</a><br />'
+                     . '<div class="serendipitySideBarDate">'
+                     . htmlspecialchars(serendipity_strftime($dateformat, $entry['timestamp']))
+                     . '</div><br />';
+            }
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_plugin_remoterss/lang_ja.inc.php b/plugins/serendipity_plugin_remoterss/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..b6fe3f7
--- /dev/null
@@ -0,0 +1,35 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_REMOTERSS_TITLE', 'リモート RSS/OPML-Blogroll フィード');
+        @define('PLUGIN_REMOTERSS_BLAHBLAH', 'リモート RSS/OPML フィードの項目を表示します (例えば Blogroll)');
+        @define('PLUGIN_REMOTERSS_NUMBER', 'エントリの数');
+        @define('PLUGIN_REMOTERSS_NUMBER_BLAHBLAH', 'どれくらいのエントリを表示しますか (デフォルト: 入力のすべてのエントリ)');
+        @define('PLUGIN_REMOTERSS_SIDEBARTITLE', 'フィードタイトル');
+        @define('PLUGIN_REMOTERSS_SIDEBARTITLE_BLAHBLAH', 'ブログサイドバーでのフィードタイトル');
+        @define('PLUGIN_REMOTERSS_RSSURI', 'RSS/OPML URI');
+        @define('PLUGIN_REMOTERSS_RSSURI_BLAHBLAH', '表示したい RSS/OPML フィードの URI を選びます。');
+        @define('PLUGIN_REMOTERSS_NOURI', 'RSS/OPML が選択されていません。');
+        @define('PLUGIN_REMOTERSS_RSSTARGET', 'RSS/OPML リンクターゲット');
+        @define('PLUGIN_REMOTERSS_RSSTARGET_BLAHBLAH', 'Target of the link to one of the displayed RSS items (デフォルト: _blank)');
+        @define('PLUGIN_REMOTERSS_CACHETIME', '入力を更新する時間?');
+        @define('PLUGIN_REMOTERSS_CACHETIME_BLAHBLAH', 'The contents of a feed are stored in a cache which will be updated as soon as its older than X minutes (デフォルト: 3 時間)');
+        @define('PLUGIN_REMOTERSS_FEEDTYPE', 'フィードタイプ');
+        @define('PLUGIN_REMOTERSS_FEEDTYPE_BLAHBLAH', 'リモートフィードの形式を選択します。');
+        @define('PLUGIN_REMOTERSS_BULLETIMG', 'バレットイメージ');
+        @define('PLUGIN_REMOTERSS_BULLETIMG_BLAHBLAH', '各ヘッドラインの前に表示する画像');
+        @define('PLUGIN_REMOTERSS_DISPLAYDATE', '日付の表示');
+        @define('PLUGIN_REMOTERSS_DISPLAYDATE_BLAHBLAH', 'ヘッドラインの下に日付を表示しますか?');
+
+?>
diff --git a/plugins/serendipity_plugin_remoterss/serendipity_plugin_remoterss.php b/plugins/serendipity_plugin_remoterss/serendipity_plugin_remoterss.php
new file mode 100644 (file)
index 0000000..e43805e
--- /dev/null
@@ -0,0 +1,579 @@
+<?php
+
+// Contributed by Udo Gerhards <udo@babyblaue-seiten.de>
+// OPML Contributed by Richard Thomas Harrison <rich@mibnet.plus.com>
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_REMOTERSS_TITLE', 'Fremder RSS/OPML-Blogroll Feed');
+        @define('PLUGIN_REMOTERSS_BLAHBLAH', 'Zeigt Einträge eines externen RSS/OPML-Feeds an (z.B. Blogroll)');
+        @define('PLUGIN_REMOTERSS_NUMBER', 'Anzahl der Einträge');
+        @define('PLUGIN_REMOTERSS_NUMBER_BLAHBLAH', 'Wieviele Einträge sollen angezeigt werden? (Standard: alle im Feed)');
+        @define('PLUGIN_REMOTERSS_SIDEBARTITLE', 'Feed-Titel');
+        @define('PLUGIN_REMOTERSS_SIDEBARTITLE_BLAHBLAH', 'Titel der Feed-Anzeige in der Sidebar des Blogs');
+        @define('PLUGIN_REMOTERSS_RSSURI', 'RSS/OPML-URI');
+        @define('PLUGIN_REMOTERSS_RSSURI_BLAHBLAH', 'URI des RSS/OPML-Feeds, der angezeigt werden soll');
+        @define('PLUGIN_REMOTERSS_RSSTARGET', 'Link-Target');
+        @define('PLUGIN_REMOTERSS_RSSTARGET_BLAHBLAH', 'Target des Links zu einem der angezeigten RSS-Einträge (Standard: _blank)');
+        @define('PLUGIN_REMOTERSS_NOURI', 'Kein RSS/OPML-Feed gewählt');
+        @define('PLUGIN_REMOTERSS_CACHETIME', 'Wann wird der Feed aktualisiert?');
+        @define('PLUGIN_REMOTERSS_CACHETIME_BLAHBLAH', 'Die Inhalte des fremden Feeds werden gecached. Sobald der Cache älter ist als X Minuten wird er aktualisiert (Standard: 3 Stunden)');
+        @define('PLUGIN_REMOTERSS_FEEDTYPE', 'Typ des Feeds');
+        @define('PLUGIN_REMOTERSS_FEEDTYPE_BLAHBLAH', 'Wählen Sie das Format des einzubindenden Feeds');
+        @define('PLUGIN_REMOTERSS_BULLETIMG', 'Bullet Image');
+        @define('PLUGIN_REMOTERSS_BULLETIMG_BLAHBLAH', 'Image to display before each headline.');
+        @define('PLUGIN_REMOTERSS_DISPLAYDATE', 'Display Date');
+        @define('PLUGIN_REMOTERSS_DISPLAYDATE_BLAHBLAH', 'Display the date below the headline?');
+
+        break;
+
+    case 'en':
+    case 'es':
+    default:
+        @define('PLUGIN_REMOTERSS_TITLE', 'Remote RSS/OPML-Blogroll Feed');
+        @define('PLUGIN_REMOTERSS_BLAHBLAH', 'Show items of a remote RSS/OPML feed (e.g. Blogroll)');
+        @define('PLUGIN_REMOTERSS_NUMBER', 'Number of entries');
+        @define('PLUGIN_REMOTERSS_NUMBER_BLAHBLAH', 'How many entries should be displayed? (Default: every entry of the feed)');
+        @define('PLUGIN_REMOTERSS_SIDEBARTITLE', 'Feed-Title');
+        @define('PLUGIN_REMOTERSS_SIDEBARTITLE_BLAHBLAH', 'Title of the feed in the blog sidebar');
+        @define('PLUGIN_REMOTERSS_RSSURI', 'RSS/OPML URI');
+        @define('PLUGIN_REMOTERSS_RSSURI_BLAHBLAH', 'URI of the RSS/OPML feed which you want to display');
+        @define('PLUGIN_REMOTERSS_NOURI', 'No RSS/OPML feed selected');
+        @define('PLUGIN_REMOTERSS_RSSTARGET', 'RSS/OPML linktarget');
+        @define('PLUGIN_REMOTERSS_RSSTARGET_BLAHBLAH', 'Target of the link to one of the displayed RSS items (Default: _blank)');
+        @define('PLUGIN_REMOTERSS_CACHETIME', 'When to update the feed?');
+        @define('PLUGIN_REMOTERSS_CACHETIME_BLAHBLAH', 'The contents of a feed are stored in a cache which will be updated as soon as its older than X minutes (Default: 3 hours)');
+        @define('PLUGIN_REMOTERSS_FEEDTYPE', 'Feedtype');
+        @define('PLUGIN_REMOTERSS_FEEDTYPE_BLAHBLAH', 'Choose the format of the remote Feed');
+        @define('PLUGIN_REMOTERSS_BULLETIMG', 'Bullet Image');
+        @define('PLUGIN_REMOTERSS_BULLETIMG_BLAHBLAH', 'Image to display before each headline.');
+        @define('PLUGIN_REMOTERSS_DISPLAYDATE', 'Display Date');
+        @define('PLUGIN_REMOTERSS_DISPLAYDATE_BLAHBLAH', 'Display the date below the headline?');
+
+        break;
+}
+
+class s9y_remoterss_XMLTree {
+    function GetChildren($vals, &$i) {
+        $children = array();
+        $cnt = sizeof($vals);
+        while (++$i < $cnt) {
+            // compare type
+            switch ($vals[$i]['type']) {
+                case 'cdata':
+                    $children[] = $vals[$i]['value'];
+                    break;
+
+                case 'complete':
+                    $children[] = array(
+                        'tag'        => $vals[$i]['tag'],
+                        'attributes' => $vals[$i]['attributes'],
+                        'value'      => $vals[$i]['value']
+                    );
+                    break;
+
+                case 'open':
+                    $children[] = array(
+                        'tag'        => $vals[$i]['tag'],
+                        'attributes' => $vals[$i]['attributes'],
+                        'value'      => $vals[$i]['value'],
+                        'children'   => $this->GetChildren($vals, $i)
+                    );
+                    break;
+
+                case 'close':
+                    return $children;
+            }
+        }
+    }
+
+    function GetXMLTree($file) {
+        require_once S9Y_INCLUDE_PATH . 'bundled-libs/HTTP/Request.php';
+        $req = &new HTTP_Request($file);
+
+        if (PEAR::isError($req->sendRequest()) || $req->getResponseCode() != '200') {
+            $data = file_get_contents($file);
+        } else {
+            // Fetch file
+            $data = $req->getResponseBody();
+        }
+
+        // Global replacements
+        // by: waldo@wh-e.com - trim space around tags not within
+        $data = eregi_replace('>[[:space:]]+<', '><', $data);
+
+        // Flatten the input opml file to not have nested categories
+        $data = preg_replace('@<outline[^>]+[^/]>@imsU', '', $data);
+        $data = str_replace('</outline>', '', $data);
+
+        // XML functions
+        $p = xml_parser_create();
+        // by: anony@mous.com - meets XML 1.0 specification
+        xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, 0);
+        xml_parser_set_option($p, XML_OPTION_TARGET_ENCODING, LANG_CHARSET);
+        xml_parse_into_struct($p, $data, $vals, $index);
+        xml_parser_free($p);
+
+        $i = 0;
+        $tree = array();
+        $tree[] = array(
+            'tag'        => $vals[$i]['tag'],
+            'attributes' => $vals[$i]['attributes'],
+            'value'      => $vals[$i]['value'],
+            'children'   => $this->GetChildren($vals, $i)
+        );
+
+        return $tree;
+    }
+}
+
+define('OPMLDEBUG', '0');
+
+class s9y_remoterss_OPML {
+    var $cacheOPMLHead;
+    var $cacheOPMLBody;
+    var $cacheOPMLOutline;
+
+    function s9y_remoterss_OPML() {
+        $this->cacheOPMLHead    = array();
+        $this->cacheOPMLBody    = array();
+        $this->cacheOPMLOutline = array();
+    }
+
+    function parseOPML($file) {
+        $xmltree  = new s9y_remoterss_XMLTree();
+        $opmltree = $xmltree->GetXMLTree($file);
+
+        return $opmltree[0];
+    }
+
+    function findOPMLTag($arr, $tag) {
+        $i = 0;
+        $tagindex = false;
+        $children = $arr['children'];
+        $cnt = count($children);
+
+        while ($i < $cnt) {
+
+            if ($children[$i]['tag'] == $tag) {
+                $tagindex = $i;
+                break;
+            }
+
+            ++$i;
+        }
+
+        return $tagindex !== false ? $tagindex : false;
+    }
+
+    function getOPMLTag($tree, $tag) {
+        $tagindex = $this->findOPMLTag($tree, $tag);
+
+        if (OPMLDEBUG == 1) {
+            echo "\ngetOPMLTag('" . $tag . "') = " . $tagindex . "<pre>\n";
+            print_r($tree['children'][$tagindex]);
+            echo "\n</pre>\n";
+        }
+
+        return $tagindex !== false ? $tree['children'][$tagindex] : false;
+    }
+
+    function getOPMLHead($tree) {
+        $head = array();
+
+        if (isset($this->cacheOPMLHead) && count($this->cacheOPMLHead) != 0) {
+            $head = $this->cacheOPMLHead;
+        } else {
+
+            if (OPMLDEBUG == 1) {
+                echo "\ngetOPMLHead<br />\n";
+            }
+
+            $head = $this->getOPMLTag($tree, 'head');
+
+            if ($head !== false) {
+                $this->cacheOPMLHead = $head;
+
+                if (OPMLDEBUG == 1) {
+                    echo "\nCaching head<pre>\n";
+                    print_r($this->cacheOPMLHead);
+                    echo "\n</pre>\n";
+                }
+            } elseif (OPMLDEBUG == 1) {
+                echo "\nfalse<br />\n";
+            }
+
+        }
+
+        return $head['tag'] == 'head' ? $head : false;
+    }
+
+    function getOPMLBody($tree) {
+        $body = array();
+
+        if (isset($this->cacheOPMLBody) && count($this->cacheOPMLBody) != 0) {
+                $body = $this->cacheOPMLBody;
+        } else {
+
+            if (OPMLDEBUG == 1) {
+                echo "\ngetOPMLBody<br />\n";
+            }
+
+            $body = $this->getOPMLTag($tree, 'body');
+
+            if ($body !== false) {
+                $this->cacheOPMLBody = $body;
+
+                if (OPMLDEBUG == 1) {
+                    echo "\nCaching body<pre>\n";
+                    print_r($this->cacheOPMLBody);
+                    echo "\n</pre>\n";
+                }
+
+            } elseif (OPMLDEBUG == 1) {
+                echo "\nfalse<br />\n";
+            }
+        }
+
+        return $body['tag'] == 'body' ? $body : false;
+    }
+
+    function getOPMLOutline($tree, $index) {
+
+        if (isset($this->cacheOPMLOutline[$index])) {
+            return $this->cacheOPMLOutline[$index];
+        }
+
+        $body = $this->getOPMLBody($tree);
+
+        if (!$body) {
+            return false;
+        }
+
+        $outline = $body['children'][$index];
+
+        if ($outline['tag'] == 'outline') {
+            $this->cacheOPMLOutline[$index] = $outline;
+
+            if (OPMLDEBUG == 1) {
+                echo "\ngetOPMLOutline[" . $index . "]<br />\n";
+                echo "\nCaching outline[" . $index . "]<pre>\n";
+                print_r($this->cacheOPMLOutline[$index]);
+                echo "\n</pre>\n";
+            }
+
+            return $outline;
+        } else {
+            return false;
+        }
+    }
+
+    function getOPMLOutlineAttr($tree, $index) {
+        $outline = $this->getOPMLOutline($tree, $index);
+
+        return $outline != false ? $outline['attributes'] : false;
+    }
+
+}
+
+class serendipity_plugin_remoterss extends serendipity_plugin {
+    var $title = PLUGIN_REMOTERSS_TITLE;
+
+    function introspect(&$propbag) {
+        $this->title = $this->get_config('sidebartitle', $this->title);
+
+        $propbag->add('name',          PLUGIN_REMOTERSS_TITLE);
+        $propbag->add('description',   PLUGIN_REMOTERSS_BLAHBLAH);
+        $propbag->add('stackable',     true);
+        $propbag->add('author',        'Udo Gerhards, Richard Thomas Harrison');
+        $propbag->add('version',       '1.1');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('configuration', array('number', 'displaydate', 'dateformat', 'sidebartitle', 'rssuri', 'charset', 'target', 'cachetime', 'feedtype', 'bulletimg', 'markup'));
+    }
+
+    function introspect_config_item($name, &$propbag) {
+        switch($name) {
+            case 'markup':
+                $propbag->add('type', 'boolean');
+                $propbag->add('name', DO_MARKUP);
+                $propbag->add('description', DO_MARKUP_DESCRIPTION);
+                $propbag->add('default', 'false');
+                break;
+
+            case 'charset':
+                $propbag->add('type', 'radio');
+                $propbag->add('name', CHARSET);
+                $propbag->add('description', CHARSET);
+                $propbag->add('default', 'native');
+
+                $charsets = array();
+                if (LANG_CHARSET != 'UTF-8') {
+                    $charsets['value'][] = $charsets['desc'][] = 'UTF-8';
+                }
+                if (LANG_CHARSET != 'ISO-8859-1') {
+                    $charsets['value'][] = $charsets['desc'][] = 'ISO-8859-1';
+                }
+
+                $charsets['value'][] = 'native';
+                $charsets['desc'][]  = LANG_CHARSET;
+                $propbag->add('radio', $charsets);
+                break;
+
+            case 'feedtype':
+                $select = array('rss' => 'RSS', 'opml' => 'OPML');
+                $propbag->add('type', 'select');
+                $propbag->add('name', PLUGIN_REMOTERSS_FEEDTYPE);
+                $propbag->add('description', PLUGIN_REMOTERSS_FEEDTYPE_BLAHBLAH);
+                $propbag->add('select_values', $select);
+                $propbag->add('default', 'rss');
+                break;
+
+            case 'number':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_REMOTERSS_NUMBER);
+                $propbag->add('description', PLUGIN_REMOTERSS_NUMBER_BLAHBLAH);
+                $propbag->add('default', '0');
+                break;
+
+            case 'dateformat':
+                $propbag->add('type', 'string');
+                $propbag->add('name', GENERAL_PLUGIN_DATEFORMAT);
+                $propbag->add('description', sprintf(GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH, '%A, %B %e. %Y'));
+                $propbag->add('default', '%A, %B %e. %Y');
+                break;
+
+            case 'sidebartitle':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_REMOTERSS_SIDEBARTITLE);
+                $propbag->add('description', PLUGIN_REMOTERSS_SIDEBARTITLE_BLAHBLAH);
+                $propbag->add('default', '');
+                break;
+
+            case 'rssuri':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_REMOTERSS_RSSURI);
+                $propbag->add('description', PLUGIN_REMOTERSS_RSSURI_BLAHBLAH);
+                $propbag->add('default', '');
+                break;
+
+            case 'target':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_REMOTERSS_RSSTARGET);
+                $propbag->add('description', PLUGIN_REMOTERSS_RSSTARGET_BLAHBLAH);
+                $propbag->add('default', '_blank');
+                break;
+
+            case 'cachetime':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_REMOTERSS_CACHETIME);
+                $propbag->add('description', PLUGIN_REMOTERSS_CACHETIME_BLAHBLAH);
+                $propbag->add('default', 10800);
+                break;
+
+            case 'bulletimg':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_REMOTERSS_BULLETIMG);
+                $propbag->add('description', PLUGIN_REMOTERSS_BULLETIMG_BLAHBLAH);
+                $propbag->add('default', '');
+                break;
+
+
+            case 'displaydate':
+                $propbag->add('type', 'boolean');
+                $propbag->add('name', PLUGIN_REMOTERSS_DISPLAYDATE);
+                $propbag->add('description', PLUGIN_REMOTERSS_BLAHBLAH);
+                $propbag->add('default', 'true');
+                break;
+
+            default:
+                return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title) {
+        global $serendipity;
+
+        $number       = $this->get_config('number');
+        $displaydate  = $this->get_config('displaydate','true');
+        $dateformat   = $this->get_config('dateformat');
+        $sidebartitle = $title = $this->get_config('sidebartitle', $this->title);
+        $rssuri       = $this->get_config('rssuri');
+        $target       = $this->get_config('target');
+        $cachetime    = $this->get_config('cachetime');
+        $feedtype     = $this->get_config('feedtype', 'rss');
+        $markup       = $this->get_config('markup', 'false');
+        $bulletimg    = $this->get_config('bulletimg');
+
+        if (!$number || !is_numeric($number) || $number < 1) {
+            $showAll = true;
+        } else {
+            $showAll = false;
+        }
+
+        if (!$dateformat || strlen($dateformat) < 1) {
+            $dateformat = '%A, %B %e. %Y';
+        }
+
+        if (!$target || strlen($target) < 1) {
+            $target = '_blank';
+        }
+
+        if (!$cachetime || !is_numeric($cachetime)) {
+            $cachetime = 10800; // 3 hours in seconds
+        }
+
+        if (trim($rssuri)) {
+            $feedcache = $serendipity['serendipityPath'] . 'archives/remoterss_cache_' . preg_replace('@[^a-z0-9]*@i', '', $rssuri) . '.dat';
+            if (!file_exists($feedcache) || filesize($feedcache) == 0 || filemtime($feedcache) < (time() - $cachetime)) {
+
+                if ($feedtype == 'rss') {
+                    require_once 'bundled-libs/Onyx/RSS.php';
+                    $c = &new Onyx_RSS();
+                    $c->parse($rssuri);
+
+                    $i = 0;
+                    $content = '';
+                    while (($showAll || ($i < $number)) && ($item = $c->getNextItem())) {
+                        if (empty($item['title'])) {
+                            continue;
+                        }
+                        $content .= '<a href="' . $this->decode($item['link']) . '" target="'.$target.'">';
+                        if (!empty($bulletimg)) {
+                            $content .= '<img src="' . $bulletimg . '" border="0" alt="*" /> ';
+                        }
+                        $content .= $this->decode($item['title']) . "</a><br />\n";
+                        $item['timestamp'] = @strtotime(isset($item['pubdate']) ? $item['pubdate'] : $item['dc:date']);
+                        if (!($item['timestamp'] == -1) AND ($displaydate == 'true')) {
+                            $content .= '<div class="serendipitySideBarDate">'
+                                      . htmlspecialchars(serendipity_formatTime($dateformat, $item['timestamp'], false))
+                                      . '</div><br />';
+
+                        }
+                        ++$i;
+                    }
+
+                    $fp = @fopen($feedcache, 'w');
+                    if ($fp) {
+                        fwrite($fp, $content);
+                        fclose($fp);
+                    } else {
+                        echo '<!-- Cache failed to ' . $feedcache . ' in ' . getcwd() . ' --><br />';
+                    }
+                } elseif ($feedtype == 'opml') {
+                    $opml = new s9y_remoterss_OPML();
+                    $opmltree = $opml->parseOPML($rssuri);
+
+                    if (OPMLDEBUG == 1) {
+                        echo "\n<pre>\n";
+                        print_r($opmltree);
+                        echo "\n</pre>\n";
+                    }
+
+                    if ($opmltree['tag'] === 'opml') {
+                        $head        = $opml->getOPMLHead($opmltree);
+                        $ownerName   = $opml->getOPMLTag($head, 'ownerName');
+                        $blogrolling = $ownerName != false ? ($ownerName['value'] == 'Blogroll Owner' ? true : false) : false;
+
+                        $i = 0;
+                        $content = '';
+                        while (($showAll || ($i < $number)) && ($item = $opml->getOPMLOutlineAttr($opmltree, $i))) {
+                            if (!empty($item['url'])) {
+                                $url = $this->decode($item['url']);
+                            } elseif (!empty($item['htmlUrl'])) {
+                                $url = $this->decode($item['htmlUrl']);
+                            } elseif (!empty($item['xmlUrl'])) {
+                                $url = $this->decode($item['xmlUrl']);
+                            } elseif (!empty($item['urlHTTP'])) {
+                                $url = $this->decode($item['urlHTTP']);
+                            } else {
+                                $url = '';
+                            }
+
+                            if (!empty($item['text'])) {
+                                $text = htmlspecialchars($this->decode($item['text']));
+                            } elseif (!empty($item['title'])) {
+                                $text = htmlspecialchars($this->decode($item['title']));
+                            } elseif (!empty($item['description'])) {
+                                $text = htmlspecialchars($this->decode($item['description']));
+                            } else {
+                                $text = '';
+                            }
+
+                            if ($blogrolling === true && (!empty($text) || !empty($url))) {
+                                $content .= '&bull; <a href="' . $url . '" target="' . $target . '" title="' . $text . '">' . htmlspecialchars($text) . "</a>";
+                                if (isset($item['isRecent'])) {
+                                    $content .= ' <span style="color: Red; ">*</span>';
+                                }
+                                $content .= "<br />";
+                            } elseif ((isset($item['type']) && $item['type'] == 'url') || !empty($url)) {
+                                $content .= '&bull; <a href="' .$url . '" target="' . $target . '" title="' . $text . '">' . $text . "</a>";
+                                $content .= "<br />";
+                            }
+                            ++$i;
+                        }
+
+                        /* Pretend to be a html_nugget so we can apply markup events. */
+                        if ($markup == 'true') {
+                            $entry = array('html_nugget' => $content);
+                            serendipity_plugin_api::hook_event('frontend_display', $entry);
+                            $content = $entry['html_nugget'];
+                        }
+
+                        $fp = @fopen($feedcache, 'w');
+                        if ($fp) {
+                            fwrite($fp, $content);
+                            fclose($fp);
+                        } else {
+                            echo '<!-- Cache failed to ' . $feedcache . ' in ' . getcwd() . ' --><br />';
+                        }
+
+                    } else {
+                        echo '<!-- Not a valid OPML feed -->';
+                    }
+                } else {
+                    echo '<!-- no valid feedtype -->';
+                }
+            } else {
+                $content = file_get_contents($feedcache);
+            }
+
+            echo $content;
+        } else {
+           echo PLUGIN_REMOTERSS_NOURI;
+        }
+    }
+
+    function decode($string) {
+        switch($this->get_config('charset', 'native')) {
+            case 'native':
+                return $string;
+
+            case 'ISO-8859-1':
+                if (function_exists('iconv')) {
+                    return iconv('ISO-8859-1', LANG_CHARSET, $string);
+                } elseif (function_exists('recode')) {
+                    return recode('iso-8859-1..' . LANG_CHARSET, $string);
+                } else {
+                    return $string;
+                }
+            
+            case 'UTF-8':
+            default:
+                return utf8_decode($string);
+        }
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
\ No newline at end of file
diff --git a/plugins/serendipity_plugin_shoutbox/lang_ja.inc.php b/plugins/serendipity_plugin_shoutbox/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..f21ad0e
--- /dev/null
@@ -0,0 +1,27 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_SHOUTBOX_NAME', '一言箱');
+        @define('PLUGIN_SHOUTBOX_DELETE', '削除');
+        @define('PLUGIN_SHOUTBOX_SUBMIT', '一言どうぞ');
+        @define('PLUGIN_SHOUTBOX_BLAHBLAH', 'コメントに関係ない一言箱を表示します。');
+        @define('PLUGIN_SHOUTBOX_WORDWRAP', 'ワードラップ');
+        @define('PLUGIN_SHOUTBOX_WORDWRAP_BLAHBLAH', '何文字でワードラップを行いますか? (デフォルト: 30)');
+        @define('PLUGIN_SHOUTBOX_MAXCHARS', 'コメント毎の最大文字数');
+        @define('PLUGIN_SHOUTBOX_MAXCHARS_BLAHBLAH', 'どれだけの文字を各コメントに表示しますか? (デフォルト: 120)');
+        @define('PLUGIN_SHOUTBOX_MAXENTRIES', '最大コメント数');
+        @define('PLUGIN_SHOUTBOX_MAXENTRIES_BLAHBLAH', 'どれだけのコメントを表示しますか? (デフォルト: 15)');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_plugin_shoutbox/serendipity_plugin_shoutbox.php b/plugins/serendipity_plugin_shoutbox/serendipity_plugin_shoutbox.php
new file mode 100644 (file)
index 0000000..d5d0d33
--- /dev/null
@@ -0,0 +1,220 @@
+<?php # $Id$
+
+/* Contributed by Matthias Lange (http://blog.dinnri.de/ml/) */
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_SHOUTBOX_NAME', 'Shoutbox');
+        @define('PLUGIN_SHOUTBOX_BLAHBLAH', 'Zeigt eine Shoutbox für beliebige Kommentare');
+        @define('PLUGIN_SHOUTBOX_DELETE', 'Löschen');
+        @define('PLUGIN_SHOUTBOX_SUBMIT', 'Abschicken');
+        @define('PLUGIN_SHOUTBOX_WORDWRAP', 'Zeilenumbruch');
+        @define('PLUGIN_SHOUTBOX_WORDWRAP_BLAHBLAH', 'Nach wievielen Zeichen soll ein Zeilenumbruch eingefügt werden?');
+        @define('PLUGIN_SHOUTBOX_MAXCHARS', 'Zeichen pro Kommentar');
+        @define('PLUGIN_SHOUTBOX_MAXCHARS_BLAHBLAH', 'Wieviele Zeichen sollen pro Kommentar gezeigt werden? (Standard: 120)');
+        @define('PLUGIN_SHOUTBOX_MAXENTRIES', 'Anzahl an Kommentaren');
+        @define('PLUGIN_SHOUTBOX_MAXENTRIES_BLAHBLAH', 'Wieviele Kommentare sollen gezeigt werden? (Standard: 15)');
+        break;
+
+    case 'en':
+    case 'es':
+    default:
+        @define('PLUGIN_SHOUTBOX_NAME', 'Shoutbox');
+        @define('PLUGIN_SHOUTBOX_DELETE', 'Delete');
+        @define('PLUGIN_SHOUTBOX_SUBMIT', 'Shout it out');
+        @define('PLUGIN_SHOUTBOX_BLAHBLAH', 'Displays a shoutbox for unrelated comments');
+        @define('PLUGIN_SHOUTBOX_WORDWRAP', 'Wordwrap');
+        @define('PLUGIN_SHOUTBOX_WORDWRAP_BLAHBLAH', 'How many chars until a wordwrap will occur? (Default: 30)');
+        @define('PLUGIN_SHOUTBOX_MAXCHARS', 'Maximum chars per comment');
+        @define('PLUGIN_SHOUTBOX_MAXCHARS_BLAHBLAH', 'How many chars will be displayed for each comment? (Default: 120)');
+        @define('PLUGIN_SHOUTBOX_MAXENTRIES', 'Maximum number of comments');
+        @define('PLUGIN_SHOUTBOX_MAXENTRIES_BLAHBLAH', 'How many comments will be shown? (Default: 15)');
+        break;
+}
+
+class serendipity_plugin_shoutbox extends serendipity_plugin
+{
+    var $title = PLUGIN_SHOUTBOX_NAME;
+
+    function introspect(&$propbag)
+    {
+        global $serendipity;
+
+        $propbag->add('name',          PLUGIN_SHOUTBOX_NAME);
+        $propbag->add('description',   PLUGIN_SHOUTBOX_BLAHBLAH);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Matthias Lange');
+        $propbag->add('version',       '1.0');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+
+        $propbag->add('configuration', array(
+                                             'wordwrap',
+                                             'max_chars',
+                                             'max_entries',
+                                             'dateformat'));
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'wordwrap':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_SHOUTBOX_WORDWRAP);
+                $propbag->add('description', PLUGIN_SHOUTBOX_WORDWRAP_BLAHBLAH);
+                $propbag->add('default',     30);
+                break;
+
+            case 'max_chars':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_SHOUTBOX_MAXCHARS);
+                $propbag->add('description', PLUGIN_SHOUTBOX_MAXCHARS_BLAHBLAH);
+                $propbag->add('default',     120);
+                break;
+
+            case 'max_entries':
+                $propbag->add('type', 'string');
+                $propbag->add('name', PLUGIN_SHOUTBOX_MAXENTRIES);
+                $propbag->add('description', PLUGIN_SHOUTBOX_MAXENTRIES_BLAHBLAH);
+                $propbag->add('default',     15);
+                break;
+
+            case 'dateformat':
+                $propbag->add('type', 'string');
+                $propbag->add('name', GENERAL_PLUGIN_DATEFORMAT);
+                $propbag->add('description', sprintf(GENERAL_PLUGIN_DATEFORMAT_BLAHBLAH, '%a, %m.%m.%Y %H:%M'));
+                $propbag->add('default',     '%a, %d.%m.%Y %H:%M');
+                break;
+
+            default:
+                    return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title)
+    {
+        global $serendipity;
+
+        $title       = $this->title;
+        $max_entries = $this->get_config('max_entries');
+        $max_chars   = $this->get_config('max_chars');
+        $wordwrap    = $this->get_config('wordwrap');
+        $dateformat  = $this->get_config('dateformat');
+
+        // Create table, if not yet existant
+        if ($this->get_config('version') != '1.0') {
+            $q   = "CREATE TABLE {$serendipity['dbPrefix']}shoutbox (
+                        id {AUTOINCREMENT} {PRIMARY},
+                        timestamp int(10) {UNSIGNED} NULL,
+                        ip varchar(15) default NULL,
+                        body text
+                    )";
+            $sql = serendipity_db_schema_import($q);
+            $this->set_config('version', '1.0');
+        }
+
+        //Put new shout into the database if necessary
+        if (!empty($_REQUEST['action']) && $_REQUEST['action'] == 'fillshoutbox' && $_REQUEST['serendipity']['shouttext'] != '') {
+
+            $sql =  sprintf(
+                      "INSERT INTO %sshoutbox (
+                            timestamp,
+                            ip,
+                            body
+                       ) VALUES (
+                            %s,
+                            '%s',
+                            '%s'
+                       )",
+
+                    $serendipity['dbPrefix'],
+                    time(),
+                    serendipity_db_escape_string($_SERVER['REMOTE_ADDR']),
+                    serendipity_db_escape_string($_REQUEST['serendipity']['shouttext']));
+            serendipity_db_query($sql);
+        }
+        if (!empty($serendipity['GET']['action']) && $serendipity['GET']['action'] == 'shoutboxdelete'
+          && $_SESSION['serendipityAuthedUser'] === true) {
+            $sql  = sprintf("DELETE from %sshoutbox
+                              WHERE id = %d",
+                                    $serendipity['dbPrefix'],
+                                    (int)$serendipity['GET']['comment_id']);
+            serendipity_db_query($sql);
+         }
+
+        if (!$max_entries || !is_numeric($max_entries) || $max_entries < 1) {
+            $max_entries = 15;
+        }
+
+        if (!$max_chars || !is_numeric($max_chars) || $max_chars < 1) {
+            $max_chars = 120;
+        }
+
+        if (!$wordwrap || !is_numeric($wordwrap) || $wordwrap < 1) {
+            $wordwrap = 30;
+        }
+
+        if (!$dateformat || strlen($dateformat) < 1) {
+            $dateformat = '%a, %d.%m.%Y %H:%M';
+        }
+       ?>
+       <form action="<?php echo serendipity_currentURL(); ?>" method="post">
+            <div>
+                <input type="hidden" name="action" value="fillshoutbox" />
+                <textarea name="serendipity[shouttext]" rows="4" cols="15" style="width: 90%"></textarea>
+                <input name='submit' type='submit' value='<?php echo PLUGIN_SHOUTBOX_SUBMIT; ?>' />
+            </div>
+        </form><br />
+<?php
+        $q = 'SELECT    s.body              AS comment,
+                        s.timestamp         AS stamp,
+                        s.id                AS comment_id
+                FROM    '.$serendipity['dbPrefix'].'shoutbox AS s
+            ORDER BY    s.timestamp DESC
+               LIMIT ' . $max_entries;
+?>
+<div style="margin: 0px; padding: 0px; text-align: left;">
+<?php
+        $sql = serendipity_db_query($q);
+        if ($sql && is_array($sql)) {
+            foreach($sql AS $key => $row) {
+                $comments = wordwrap(strip_tags($row['comment']), $max_chars, '@@@', 1);
+                $aComment = explode('@@@', $comments);
+                $comment  = $aComment[0];
+                if (count($aComment) > 1) {
+                    $comment .= ' [...]';
+                }
+
+                $deleteLink = "";
+                if ($_SESSION['serendipityAuthedUser'] === true) {
+                    $deleteLink =  ' | <a href="' . $serendipity['baseURL']
+                                  . '?serendipity[action]=shoutboxdelete&amp;serendipity[comment_id]='
+                                  . $row['comment_id'] . '">' . PLUGIN_SHOUTBOX_DELETE . '</a>';
+                }
+                $entry = array('comment' => wordwrap($comment, $wordwrap, "\n",1));
+                serendipity_plugin_api::hook_event('frontend_display', $entry);
+
+                echo "<b>" . htmlspecialchars(serendipity_strftime($dateformat, $row['stamp'])) . '</b> <br />' . "\n"
+                     . $entry['comment']
+                     . $deleteLink
+                     . '<br /><br /><br />' . "\n\n";
+            }
+        }
+?>
+</div>
+<?php
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_plugin_templatedropdown/lang_ja.inc.php b/plugins/serendipity_plugin_templatedropdown/lang_ja.inc.php
new file mode 100644 (file)
index 0000000..b1ea930
--- /dev/null
@@ -0,0 +1,21 @@
+<?php # $Id$
+
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+# Translated by                                                          #
+# (c) 2004-2005 Tadashi Jokagi <elf2000@users.sourceforge.net>           #
+#                                                                        #
+##########################################################################
+
+        @define('PLUGIN_TEMPLATEDROPDOWN_NAME',     'テンプレートドロップダウン');
+        @define('PLUGIN_TEMPLATEDROPDOWN_DESC',     'テンプレート変更のボックスを表示します。');
+        @define('PLUGIN_TEMPLATEDROPDOWN_SUBMIT',   '送信ボタンの表示は?');
+        @define('PLUGIN_TEMPLATEDROPDOWN_SUBMIT_DESC',   '送信ボタンの表示をしますか?');
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/plugins/serendipity_plugin_templatedropdown/serendipity_plugin_templatedropdown.php b/plugins/serendipity_plugin_templatedropdown/serendipity_plugin_templatedropdown.php
new file mode 100644 (file)
index 0000000..aff77a6
--- /dev/null
@@ -0,0 +1,97 @@
+<?php # $Id$
+
+// Probe for a language include with constants. Still include defines later on, if some constants were missing
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+}
+
+switch ($serendipity['lang']) {
+    case 'de':
+        @define('PLUGIN_TEMPLATEDROPDOWN_NAME',     'Template dropdown');
+        @define('PLUGIN_TEMPLATEDROPDOWN_DESC',     'Zeigt eine Box um Templates zu ändern');
+        @define('PLUGIN_TEMPLATEDROPDOWN_SUBMIT',   'Submit-Button?');
+        @define('PLUGIN_TEMPLATEDROPDOWN_SUBMIT_DESC',   'Einen Submit-Button anzeigen?');
+        break;
+
+    case 'en':
+    default:
+        @define('PLUGIN_TEMPLATEDROPDOWN_NAME',     'Template dropdown');
+        @define('PLUGIN_TEMPLATEDROPDOWN_DESC',     'Show a box to change templates');
+        @define('PLUGIN_TEMPLATEDROPDOWN_SUBMIT',   'Submit button?');
+        @define('PLUGIN_TEMPLATEDROPDOWN_SUBMIT_DESC',   'Show a submit button?');
+        break;
+}
+
+class serendipity_plugin_templatedropdown extends serendipity_plugin {
+    var $title = PLUGIN_TEMPLATEDROPDOWN_NAME;
+
+    function introspect(&$propbag)
+    {
+        $this->title = $this->get_config('title', $this->title);
+
+        $propbag->add('name',          PLUGIN_TEMPLATEDROPDOWN_NAME);
+        $propbag->add('description',   PLUGIN_TEMPLATEDROPDOWN_DESC);
+        $propbag->add('stackable',     false);
+        $propbag->add('author',        'Evan Nemerson');
+        $propbag->add('version',       '1.0');
+        $propbag->add('requirements',  array(
+            'serendipity' => '0.8',
+            'smarty'      => '2.6.7',
+            'php'         => '4.1.0'
+        ));
+        $propbag->add('configuration', array('title', 'show_submit'));
+
+        // Register (multiple) dependencies. KEY is the name of the depending plugin. VALUE is a mode of either 'remove' or 'keep'.
+        // If the mode 'remove' is set, removing the plugin results in a removal of the depending plugin. 'Keep' meens to
+        // not touch the depending plugin.
+        $this->dependencies = array('serendipity_event_templatechooser' => 'remove');
+    }
+
+    function introspect_config_item($name, &$propbag)
+    {
+        switch($name) {
+            case 'title':
+                $propbag->add('type',        'string');
+                $propbag->add('name',        TITLE);
+                $propbag->add('description', TITLE);
+                $propbag->add('default',     '');
+                break;
+
+            case 'show_submit':
+                $propbag->add('type',        'boolean');
+                $propbag->add('name',        PLUGIN_TEMPLATEDROPDOWN_SUBMIT);
+                $propbag->add('description', PLUGIN_TEMPLATEDROPDOWN_SUBMIT_DESC);
+                $propbag->add('default',     'false');
+                break;
+
+            default:
+                    return false;
+        }
+        return true;
+    }
+
+    function generate_content(&$title) {
+        global $serendipity;
+
+        $title = $this->get_config('title', $this->title);
+
+        $url = serendipity_currentURL();
+
+        echo '<form id="theme_chooser" action="' . $url . '" method="post">';
+        echo '<select name="user_template" onchange="document.getElementById(\'theme_chooser\').submit();">';
+        foreach (serendipity_fetchTemplates() as $template) {
+            $templateInfo = serendipity_fetchTemplateInfo($template);
+            echo '<option value="' . $template . '" ' . (serendipity_get_config_var('template', 'default') == $template ? 'selected="selected"' : '') . '>' . $templateInfo['name'] . '</option>';
+        }
+        echo '</select>';
+
+        if ($this->get_config('show_submit', 'false') == 'true') {
+            echo '<input type="submit" name="submit" value="' . GO . '" size="4" />';
+        }
+        echo '</form>';
+    }
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/rss.php b/rss.php
new file mode 100644 (file)
index 0000000..fcd9042
--- /dev/null
+++ b/rss.php
@@ -0,0 +1,298 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+header('Content-Type: text/xml; charset=utf-8');
+
+include_once('serendipity_config.inc.php');
+$version         = $_GET['version'];
+$description     = $serendipity['blogDescription'];
+$title           = $serendipity['blogTitle'];
+$comments        = FALSE;
+
+if ( empty($version) ) {
+    list($version) = serendipity_discover_rss($_GET['file'], $_GET['ext']);
+}
+
+if (isset($_GET['category'])) {
+    $serendipity['GET']['category'] = $_GET['category'];
+}
+
+if (!isset($_GET['type'])) {
+    $_GET['type'] = 'content';
+}
+
+if (!isset($_GET['nocache'])) {
+    switch ($_GET['type']) {
+    case 'comments':
+            $latest_entry = serendipity_fetchComments(isset($_GET['cid']) ? $_GET['cid'] : null, 1, 'desc');
+        break;
+    case 'content':
+    default:
+            $latest_entry = serendipity_fetchEntries(null, false, 1, false, false, 'last_modified DESC', '', false, true);
+        break;
+    }
+
+    /*
+     * Caching logic - Do not send feed if nothing has changed
+     * Implementation inspired by Simon Willison [http://simon.incutio.com/archive/2003/04/23/conditionalGet], Thiemo Maettig
+     */
+
+    // See if the client has provided the required headers.
+    // Always convert the provided header into GMT timezone to allow comparing to the server-side last-modified header
+    $modified_since = !empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])
+                    ? gmdate('D, d M Y H:i:s \G\M\T', serendipity_serverOffsetHour(strtotime(stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE'])), true))
+                    : false;
+    $none_match     = !empty($_SERVER['HTTP_IF_NONE_MATCH'])
+                    ? str_replace('"', '', stripslashes($_SERVER['HTTP_IF_NONE_MATCH']))
+                    : false;
+
+    if (is_array($latest_entry) && isset($latest_entry[0]['last_modified'])) {
+        $last_modified = gmdate('D, d M Y H:i:s \G\M\T', serendipity_serverOffsetHour($latest_entry[0]['last_modified'], true));
+        $etag          = '"' . $last_modified . '"';
+
+        header('Last-Modified: ' . $last_modified);
+        header('ETag: '          . $etag);
+
+        if (($none_match == $last_modified && $modified_since == $last_modified) ||
+            (!$none_match && $modified_since == $last_modified) ||
+            (!$modified_since && $none_match == $last_modified)) {
+            header('HTTP/1.0 304 Not Modified');
+            return;
+        }
+    }
+}
+
+switch ($_GET['type']) {
+case 'comments':
+    $entries     = serendipity_fetchComments(isset($_GET['cid']) ? $_GET['cid'] : null, 15, 'desc');
+    $title       = $title . ' ' . COMMENTS;
+    $description = COMMENTS_FROM . ' ' . $description;
+    $comments    = TRUE;
+    break;
+case 'content':
+default:
+    if (isset($_GET['all']) && $_GET['all']) {
+        // Fetch all entries in reverse order for later importing. Fetch sticky entries as normal entries.
+        $entries = serendipity_fetchEntries(null, true, '', false, false, 'id ASC', '', false, true);
+    } else {
+        $entries = serendipity_fetchEntries(null, true, 15, false, (isset($modified_since) ? $modified_since : false), 'timestamp DESC', '', false, true);
+    }
+    break;
+}
+
+if (!empty($serendipity['GET']['category'])) {
+    $cInfo       = serendipity_fetchCategoryInfo((int)$serendipity['GET']['category']);
+    $title       = serendipity_utf8_encode(htmlspecialchars($title . ' - '. $cInfo['category_name']));
+} else {
+    $title       = serendipity_utf8_encode(htmlspecialchars($title));
+}
+
+$description = serendipity_utf8_encode(htmlspecialchars($description));
+$fullFeed    = false;
+$showMail    = true;
+
+include_once(S9Y_INCLUDE_PATH . 'include/plugin_api.inc.php');
+$plugins = serendipity_plugin_api::enum_plugins();
+
+if (is_array($plugins)) {
+    // load each plugin to make some introspection
+    foreach ($plugins as $plugin_data) {
+        if (preg_match('|@serendipity_syndication_plugin|', $plugin_data['name'])) {
+            $plugin =& serendipity_plugin_api::load_plugin($plugin_data['name'], $plugin_data['authorid']);
+            $additional_fields = $plugin->generate_rss_fields($title, $description, $entries);
+            $fullFeed = $plugin->get_config('fullfeed', false);
+            $showMail = serendipity_db_bool($plugin->get_config('show_mail', $showMail));
+            break;
+        }
+    }
+}
+
+echo '<?xml version="1.0" encoding="utf-8" ?>';
+
+if (strstr($version, 'atom')) {
+    echo "\n" . '<?xml-stylesheet href="' . serendipity_getTemplateFile('atom.css') . '" type="text/css" ?>';
+}
+
+echo "\n";
+switch ($version) {
+case '0.91':
+    print <<<HEAD
+<rss version="0.91">
+<channel>
+<title>$title</title>
+<link>{$serendipity['baseURL']}</link>
+<description>$description</description>
+<language>{$serendipity['lang']}</language>
+{$additional_fields['image']}
+
+HEAD;
+break;
+
+case '1.0':
+    $rdf_seq_li = "\n";
+    if (is_array($entries)) {
+        foreach($entries AS $entry) {
+            $rdf_seq_li .= '        <rdf:li resource="' . serendipity_rss_getguid($entry, $comments) . '" />' . "\n";
+        }
+
+        $entries['display_dat'] = '';
+        serendipity_plugin_api::hook_event('frontend_display:rss-1.0:namespace', $entries);
+    } else {
+        $entries = array();
+    }
+    
+    if ($showMail) {
+        $head_mail = "<admin:errorReportsTo rdf:resource=\"mailto:{$serendipity['email']}\" />";
+    } else {
+        $head_mail = '';
+    }
+
+    print <<<HEAD
+<rdf:RDF {$entries['display_dat']}
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:admin="http://webns.net/mvcb/"
+   xmlns:content="http://purl.org/rss/1.0/modules/content/"
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
+   xmlns:wfw="http://wellformedweb.org/CommentAPI/">
+<channel rdf:about="{$serendipity['baseURL']}rss.php?version=1.0">
+    <title>$title</title>
+    <link>{$serendipity['baseURL']}</link>
+    <description>$description</description>
+    <dc:language>{$serendipity['lang']}</dc:language>
+    $head_mail
+
+    {$additional_fields['image_rss1.0_channel']}
+
+    <items>
+      <rdf:Seq>{$rdf_seq_li}</rdf:Seq>
+    </items>
+</channel>
+
+{$additional_fields['image_rss1.0_rdf']}
+
+HEAD;
+break;
+
+case '2.0':
+    if (is_array($entries)) {
+        $entries['display_dat'] = '';
+        serendipity_plugin_api::hook_event('frontend_display:rss-2.0:namespace', $entries);
+    } else {
+        $entries = array();
+    }
+
+    if ($showMail) {
+        $head_mail = "<admin:errorReportsTo rdf:resource=\"mailto:{$serendipity['email']}\" />";
+    } else {
+        $head_mail = '';
+    }
+
+    print <<<HEAD
+<rss version="2.0"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:admin="http://webns.net/mvcb/"
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
+   xmlns:wfw="http://wellformedweb.org/CommentAPI/"
+   xmlns:content="http://purl.org/rss/1.0/modules/content/"
+   {$entries['display_dat']}>
+<channel>
+    <title>$title</title>
+    <link>{$serendipity['baseURL']}</link>
+    <description>$description</description>
+    <dc:language>{$serendipity['lang']}</dc:language>
+    $head_mail
+    <generator>Serendipity {$serendipity['version']} - http://www.s9y.org/</generator>
+    {$additional_fields['channel']}
+    {$additional_fields['image']}
+
+HEAD;
+break;
+
+case 'atom0.3':
+    if (is_array($entries)) {
+        $modified = gmdate('Y-m-d\TH:i:s\Z', serendipity_serverOffsetHour($entries[0]['last_modified']));
+    } else {
+        $modified = gmdate('Y-m-d\TH:i:s\Z', serendipity_serverOffsetHour());
+    }
+
+    if ($showMail) {
+        $head_mail = "<admin:errorReportsTo rdf:resource=\"mailto:{$serendipity['email']}\" />";
+    } else {
+        $head_mail = '';
+    }
+
+    print <<<HEAD
+<feed version="0.3"
+   xmlns="http://purl.org/atom/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:admin="http://webns.net/mvcb/"
+   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
+   xmlns:wfw="http://wellformedweb.org/CommentAPI/">
+    <link href="{$serendipity['baseURL']}rss.php?version=atom0.3" rel="service.feed" title="$title" type="application/x.atom+xml" />
+    <link href="{$serendipity['baseURL']}"                        rel="alternate"    title="$title" type="text/html" />
+    <link href="{$serendipity['baseURL']}rss.php?version=2.0"     rel="alternate"    title="$title" type="application/rss+xml" />
+    <title mode="escaped" type="text/html">$title</title>
+    <tagline mode="escaped" type="text/html">$description</tagline>
+    <id>{$serendipity['baseURL']}</id>
+    <modified>$modified</modified>
+    <generator url="http://www.s9y.org/" version="{$serendipity['version']}">Serendipity {$serendipity['version']} - http://www.s9y.org/</generator>
+    <dc:language>{$serendipity['lang']}</dc:language>
+    $head_mail
+    <info mode="xml" type="text/html">
+        <div xmlns="http://www.w3.org/1999/xhtml">You are viewing an ATOM formatted XML site feed. Usually this file is inteded to be viewed in an aggregator or syndication software. If you want to know more about ATOM, please visist <a href="http://atomenabled.org/">Atomenabled.org</a></div>
+    </info>
+
+HEAD;
+break;
+
+case 'opml1.0':
+    if (is_array($entries)) {
+        $modified = gmdate('Y-m-d\TH:i:s\Z', serendipity_serverOffsetHour($entries[0]['last_modified']));
+    } else {
+        $modified = gmdate('Y-m-d\TH:i:s\Z', serendipity_serverOffsetHour());
+    }
+    print <<<HEAD
+<opml version="{$version}">
+<head>
+    <title>$title</title>
+    <dateModified>$modified</dateModified>
+    <ownerName>Serendipity {$serendipity['version']} - http://www.s9y.org/</ownerName>
+</head>
+<body>
+HEAD;
+break;
+
+default:
+    die("Invalid RSS version specified\n");
+}
+
+unset($entries['display_dat']); // Only needed for headers.
+serendipity_printEntries_rss($entries, $version, $comments, $fullFeed, $showMail);
+
+switch ($version) {
+case '0.91':
+case '2.0':
+    print "</channel>\n";
+    print "</rss>\n";
+    break;
+case '1.0':
+    if (is_array($entries)) {
+        $entries['display_dat'] = '';
+        serendipity_plugin_api::hook_event('frontend_display:rss-1.0:once', $entries);
+        echo $entries['display_dat'];
+    }
+    print '</rdf:RDF>';
+    break;
+case 'atom0.3':
+    print '</feed>';
+    break;
+case 'opml1.0':
+    print "</body>\n</opml>";
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/serendipity.css.php b/serendipity.css.php
new file mode 100644 (file)
index 0000000..736ecd4
--- /dev/null
@@ -0,0 +1,69 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+/* This is a small hack to allow CSS display during installations and upgrades */
+define('IN_installer', true);
+define('IN_upgrader', true);
+
+include_once('serendipity_config.inc.php');
+
+if (!isset($css_mode)) {
+    if (!empty($serendipity['GET']['css_mode'])) {
+        $css_mode = $serendipity['GET']['css_mode'];
+    } else {
+        $css_mode = 'serendipity.css';
+    }
+}
+
+switch($css_mode) {
+    case 'serendipity.css':
+    default:
+        $css_hook = 'css';
+        $css_file = 'style.css';
+        break;
+
+    case 'serendipity_admin.css':
+        $css_hook = 'css_backend';
+        $css_file = 'admin/style.css';
+        break;
+}
+
+function serendipity_printStylesheet($file) {
+    global $serendipity;
+    return str_replace(
+             array(
+               '{TEMPLATE_PATH}',
+               '{LANG_DIRECTION}'
+             ),
+
+             array(
+               dirname($file) . '/',
+               LANG_DIRECTION
+             ),
+
+             @file_get_contents($file, 1));
+}
+
+
+if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false) {
+    header('Cache-Control: no-cache');
+}
+header('Content-type: text/css');
+
+if (IS_installed === false) {
+    if (file_exists('templates/' . $serendipity['defaultTemplate'] . '/' . $css_file)) {
+        echo serendipity_printStylesheet('templates/' . $serendipity['defaultTemplate'] . '/' . $css_file);
+    }
+    die();
+}
+
+
+$out = serendipity_printStylesheet(serendipity_getTemplateFile($css_file, ''));
+
+serendipity_plugin_api::hook_event($css_hook, $out);
+
+echo $out;
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/serendipity_admin.php b/serendipity_admin.php
new file mode 100644 (file)
index 0000000..e54f5a5
--- /dev/null
@@ -0,0 +1,265 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+define('IN_installer', true);
+define('IN_upgrader', true);
+define('IN_serendipity', true);
+include('serendipity_config.inc.php');
+header('Content-Type: text/html; charset=' . LANG_CHARSET);
+
+if (IS_installed === false) {
+    require_once(S9Y_INCLUDE_PATH . 'include/functions_installer.inc.php');
+    require_once S9Y_INCLUDE_PATH . 'include/functions_config.inc.php';
+    $css_file = 'serendipity.css.php?serendipity[css_mode]=serendipity_admin.css';
+} else {
+    $css_file = serendipity_rewriteURL('serendipity_admin.css');
+}
+
+if (isset($serendipity['GET']['adminModule']) && $serendipity['GET']['adminModule'] == 'logout') {
+    serendipity_logout();
+} else {
+    if (IS_installed === true && !serendipity_userLoggedIn()) {
+        // Try again to log in, this time with enabled external authentication event hook
+        serendipity_login(true);
+    }
+}
+
+// If we are inside an iframe, halt the script
+if (serendipity_is_iframe()) {
+    return true;
+}
+
+?>
+<html>
+    <head>
+        <title><?php echo SERENDIPITY_ADMIN_SUITE; ?></title>
+        <meta http-equiv="Content-Type" content="text/html; charset=<?php echo LANG_CHARSET; ?>" />
+        <link rel="stylesheet" type="text/css" href="<?php echo $css_file; ?>" />
+        <script type="text/javascript">
+        function spawn() {
+            if (self.Spawnextended) {
+                Spawnextended();
+            }
+
+            if (self.Spawnbody) {
+                Spawnbody();
+            }
+
+            if (self.Spawnnugget) {
+                Spawnnugget();
+            }
+        }
+        
+        function SetCookie(name, value) {
+            var today  = new Date();
+            var expire = new Date();
+            expire.setTime(today.getTime() + (60*60*24*30));
+            document.cookie = 'serendipity[' + name + ']='+escape(value) + ';expires=' + expire.toGMTString();
+        }
+        </script>
+    </head>
+    <body id="serendipity_admin_page" onload="spawn()">
+        <table cellspacing="0" cellpadding="0" border="0" id="serendipityAdminFrame">
+            <tr>
+                <td colspan="2" id="serendipityAdminBanner">
+                <?php if ( IS_installed === true && IS_up2date === true ) { ?>
+                    <h1><?php echo SERENDIPITY_ADMIN_SUITE ?></h1>
+                    <h2><?php echo $serendipity['blogTitle'] ?></h2>
+                <?php } elseif ( IS_installed === false || IS_up2date === false ) { ?>
+                    <h1><?php echo SERENDIPITY_INSTALLATION ?></h1>
+                <?php } ?>
+                </td>
+            </tr>
+            <tr>
+                <td colspan="2" id="serendipityAdminInfopane">
+                    <?php if (serendipity_userLoggedIn()) { ?>
+                        <?php echo sprintf(USER_SELF_INFO, $serendipity['serendipityUser'], $serendipity['permissionLevels'][$serendipity['serendipityUserlevel']]) ?>
+                    <?php } ?>
+                </td>
+            </tr>
+            <tr valign="top">
+<?php
+if (!isset($serendipity['serendipityPath']) || IS_installed === false || IS_up2date === false ) {
+    if (IS_installed === false) {
+        $file = 'include/admin/installer.inc.php';
+    } elseif ( IS_up2date === false ) {
+        $file = 'include/admin/upgrader.inc.php';
+    } else {
+        $file = ''; // For register_global, safety
+    }
+?>
+                <td class="serendipityAdminContent" colspan="2">
+                    <?php require_once(S9Y_INCLUDE_PATH . $file); ?>
+<?php
+
+
+} elseif ( serendipity_userLoggedIn() == false ) {
+?>
+                <td colspan="2" class="serendipityAdminContent">
+                    <div align="center"><?php echo WELCOME_TO_ADMIN ?><br /><?php echo PLEASE_ENTER_CREDENTIALS ?></div>
+                    <br />
+                    <?php if ( isset($serendipity['POST']['action']) && !serendipity_userLoggedIn() ) { ?>
+                    <div class="serendipityAdminMsgError"><?php echo WRONG_USERNAME_OR_PASSWORD; ?></div>
+                    <?php } ?>
+                    <form action="?" method="post">
+                        <input type="hidden" name="serendipity[action]" value="admin" />
+                        <table cellspacing="10" cellpadding="0" border="0" align="center">
+                            <tr>
+                                <td><?php echo USERNAME ?></td>
+                                <td><input type="text" name="serendipity[user]" /></td>
+                            </tr>
+                            <tr>
+                                <td><?php echo PASSWORD ?></td>
+                                <td><input type="password" name="serendipity[pass]" /></td>
+                            </tr>
+                            <tr>
+                                <td colspan="2"><input id="autologin" type="checkbox" name="serendipity[auto]" /><label for="autologin"> <?php echo AUTOMATIC_LOGIN ?>
+                            </tr>
+                            <tr>
+                                <td colspan="2" align="right"><input type="submit" name="submit" value="<?php echo LOGIN ?> &gt;" class="serendipityPrettyButton" /></td>
+                            </tr>
+                        </table>
+                    </form>
+                    <a href="<?php echo $serendipity['serendipityHTTPPath']; ?>"><?php echo BACK_TO_BLOG;?></a>
+<?php
+
+
+
+} else {
+?>
+                <td id="serendipitySideBar">
+                    <ul class="serendipitySideBarMenu">
+                        <li><a href="serendipity_admin.php"><?php echo ADMIN_FRONTPAGE; ?></a></li>
+                        <li><a href="serendipity_admin.php?serendipity[adminModule]=personal"><?php echo PERSONAL_SETTINGS; ?></a></li>
+                    </ul>
+                    <br />
+                    <ul class="serendipitySideBarMenu">
+                        <li class="serendipitySideBarMenuHead"><?php echo ADMIN_ENTRIES ?></li>
+                        <li><a href="serendipity_admin.php?serendipity[adminModule]=entries&amp;serendipity[adminAction]=new"><?php echo NEW_ENTRY; ?></a></li>
+                        <li><a href="serendipity_admin.php?serendipity[adminModule]=entries&amp;serendipity[adminAction]=editSelect"><?php echo EDIT_ENTRIES; ?></a></li>
+                        <li><a href="serendipity_admin.php?serendipity[adminModule]=comments"><?php echo COMMENTS; ?></a></li>
+                        <li><a href="serendipity_admin.php?serendipity[adminModule]=category&amp;serendipity[adminAction]=view"><?php echo CATEGORIES; ?></a></li>
+                        <?php serendipity_plugin_api::hook_event('backend_sidebar_entries', $serendipity); ?>
+                    </ul>
+
+                    <ul class="serendipitySideBarMenu">
+                        <li class="serendipitySideBarMenuHead"><?php echo MEDIA; ?></li>
+                        <li><a href="serendipity_admin.php?serendipity[adminModule]=media&amp;serendipity[adminAction]=addSelect"><?php echo ADD_MEDIA; ?></a></li>
+                        <li><a href="serendipity_admin.php?serendipity[adminModule]=media"><?php echo MEDIA_LIBRARY; ?></a></li>
+                        <?php if ($serendipity['serendipityUserlevel'] >= USERLEVEL_CHIEF) { ?>
+                        <li><a href="serendipity_admin.php?serendipity[adminModule]=media&amp;serendipity[adminAction]=directorySelect"><?php echo MANAGE_DIRECTORIES; ?></a></li>
+                        <?php } ?>
+                        <li><a href="serendipity_admin.php?serendipity[adminModule]=media&amp;serendipity[adminAction]=sync" onclick="return confirm('<?php echo WARNING_THIS_BLAHBLAH; ?>');"><?php echo CREATE_THUMBS; ?></a></li>
+                        <?php serendipity_plugin_api::hook_event('backend_sidebar_entries_images', $serendipity); ?>
+                    </ul>
+
+<?php if ($serendipity['serendipityUserlevel'] >= USERLEVEL_CHIEF) { ?>
+                    <ul class="serendipitySideBarMenu">
+                        <li class="serendipitySideBarMenuHead"><?php echo APPEARANCE; ?></li>
+                        <li><a href="serendipity_admin.php?serendipity[adminModule]=templates"><?php echo MANAGE_STYLES; ?></a></li>
+                        <li><a href="serendipity_admin.php?serendipity[adminModule]=plugins"><?php echo CONFIGURE_PLUGINS; ?></a></li>
+                        <?php serendipity_plugin_api::hook_event('backend_sidebar_admin_appearance', $serendipity); ?>
+                    </ul>
+<?php } ?>
+                    <ul class="serendipitySideBarMenu">
+                        <li class="serendipitySideBarMenuHead"><?php echo ADMIN; ?></li>
+                        <?php if ($serendipity['serendipityUserlevel'] >= USERLEVEL_CHIEF) { ?>
+                        <li><a href="serendipity_admin.php?serendipity[adminModule]=configuration"><?php echo CONFIGURATION; ?></a></li>
+                        <?php } ?>
+                        <?php if ($serendipity['serendipityUserlevel'] >= USERLEVEL_CHIEF) { ?>
+                        <li><a href="serendipity_admin.php?serendipity[adminModule]=users"><?php echo MANAGE_USERS; ?></a></li>
+                        <?php } ?>
+                        <li><a href="serendipity_admin.php?serendipity[adminModule]=import"><?php echo IMPORT_ENTRIES; ?></a></li>
+                        <li><a href="serendipity_admin.php?serendipity[adminModule]=export"><?php echo EXPORT_ENTRIES; ?></a></li>
+                        <?php serendipity_plugin_api::hook_event('backend_sidebar_admin', $serendipity); ?>
+                    </ul>
+                    <br />
+                    <ul class="serendipitySideBarMenu">
+                        <li><a href="<?php echo $serendipity['baseURL']; ?>"><?php echo BACK_TO_BLOG; ?></a></li>
+                        <li><a href="serendipity_admin.php?serendipity[adminModule]=logout"><?php echo LOGOUT; ?></a></li>
+                    </ul>
+
+                </td>
+                <td class="serendipityAdminContent">
+<?php
+    if (!isset($serendipity['GET']['adminModule'])) {
+        $serendipity['GET']['adminModule'] = (isset($serendipity['POST']['adminModule']) ? $serendipity['POST']['adminModule'] : '');
+    }
+
+    switch($serendipity['GET']['adminModule']) {
+        case 'installer':
+        case 'configuration':
+            include S9Y_INCLUDE_PATH . 'include/admin/configuration.inc.php';
+            break;
+
+        case 'media':
+        case 'images':
+            include S9Y_INCLUDE_PATH . 'include/admin/images.inc.php';
+            break;
+
+        case 'templates':
+            include S9Y_INCLUDE_PATH . 'include/admin/templates.inc.php';
+            break;
+
+        case 'plugins':
+            include S9Y_INCLUDE_PATH . 'include/admin/plugins.inc.php';
+            break;
+
+        case 'users':
+            include S9Y_INCLUDE_PATH . 'include/admin/users.inc.php';
+            break;
+
+        case 'personal':
+            include S9Y_INCLUDE_PATH . 'include/admin/personal.inc.php';
+            break;
+
+        case 'export':
+            include S9Y_INCLUDE_PATH . 'include/admin/export.inc.php';
+            break;
+
+        case 'import':
+            include S9Y_INCLUDE_PATH . 'include/admin/import.inc.php';
+            break;
+
+        case 'entries':
+            include S9Y_INCLUDE_PATH . 'include/admin/entries.inc.php';
+            break;
+
+        case 'comments':
+            include S9Y_INCLUDE_PATH . 'include/admin/comments.inc.php';
+            break;
+
+        case 'category':
+        case 'categories':
+            include S9Y_INCLUDE_PATH . 'include/admin/category.inc.php';
+            break;
+
+        case 'logout':
+            echo LOGGEDOUT;
+            break;
+
+        case 'event_display':
+            serendipity_plugin_api::hook_event('backend_sidebar_entries_event_display_' . $serendipity['GET']['adminAction'], $serendipity);
+            break;
+
+        case 'logout':
+            echo LOGGEDOUT;
+            break;
+
+        default:
+            include S9Y_INCLUDE_PATH . 'include/admin/overview.inc.php';
+            break;
+    }
+}
+?>
+                </td>
+            </tr>
+        </table>
+        <br />
+        <div id="serendipityAdminFooter"><?php echo sprintf(ADMIN_FOOTER_POWERED_BY, $serendipity['versionInstalled'], phpversion()); ?></div>
+    </body>
+</html>
+<?php
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/serendipity_admin_image_selector.php b/serendipity_admin_image_selector.php
new file mode 100644 (file)
index 0000000..318c003
--- /dev/null
@@ -0,0 +1,235 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+include('serendipity_config.inc.php');
+
+if (IN_serendipity !== true) {
+    die ("Don't hack!");
+}
+
+header('Content-Type: text/html; charset=' . LANG_CHARSET);
+
+if ($_SESSION['serendipityAuthedUser'] !== true)  {
+    die(HAVE_TO_BE_LOGGED_ON);
+}
+
+if (!isset($serendipity['GET']['adminModule'])) {
+    $serendipity['GET']['adminModule'] = (isset($serendipity['POST']['adminModule']) ? $serendipity['POST']['adminModule'] : '');
+}
+
+if (!isset($serendipity['GET']['step'])) {
+    $serendipity['GET']['step']        = (isset($serendipity['POST']['step'])        ? $serendipity['POST']['step']        : '');
+}
+
+?>
+<html>
+    <head>
+        <title><?php echo SELECT_FILE; ?></title>
+        <meta http-equiv="Content-Type" content="text/html; charset=<?php echo LANG_CHARSET; ?>" />
+        <link rel="stylesheet" type="text/css" href="<?php echo serendipity_getTemplateFile('admin/style.css') ?>" />
+    </head>
+
+    <script type="text/javascript">
+        function SetCookie(name, value) {
+            var today  = new Date();
+            var expire = new Date();
+            expire.setTime(today.getTime() + (60*60*24*30));
+            document.cookie = 'serendipity[' + name + ']='+escape(value) + ';expires=' + expire.toGMTString();
+        }
+    </script>
+<body id="serendipityAdminBodyImageSelector">
+
+<div class="serendipityAdminContent">
+<?php
+switch ($serendipity['GET']['step']) {
+    case '1':
+        if (isset($serendipity['GET']['adminAction'])) { // Embedded upload form
+            switch ($serendipity['GET']['adminAction']) {
+                case 'addSelect':
+                    $image_selector_addvars = array(
+                        'step'          => 1,
+                        'textarea'      => (!empty($serendipity['GET']['textarea'])      ? $serendipity['GET']['textarea']      : ''),
+                        'htmltarget'    => (!empty($serendipity['GET']['htmltarget'])    ? $serendipity['GET']['htmltarget']    : ''),
+                        'filename_only' => (!empty($serendipity['GET']['filename_only']) ? $serendipity['GET']['filename_only'] : '')
+                    );
+                    include S9Y_INCLUDE_PATH . 'include/admin/images.inc.php';
+                    break 2;
+
+                case 'add':
+                    include S9Y_INCLUDE_PATH . 'include/admin/images.inc.php';
+                    if (isset($created_thumbnail) && is_array($created_thumbnail)) {
+                        $serendipity['GET']['image'] = (int)$image_id; // $image_id is passed from images.inc.php
+
+                        if (!empty($serendipity['POST']['htmltarget'])) {
+                            $serendipity['GET']['htmltarget'] = $serendipity['POST']['htmltarget'];
+                        }
+
+                        if (!empty($serendipity['POST']['filename_only'])) {
+                            $serendipity['GET']['filename_only'] = $serendipity['POST']['filename_only'];
+                        }
+
+                        if (!empty($serendipity['POST']['textarea'])) {
+                            $serendipity['GET']['textarea'] = $serendipity['POST']['textarea'];
+                        }
+                        break;
+                    } else {
+                        break 2;
+                    }
+            }
+        }
+
+        $file           = serendipity_fetchImageFromDatabase($serendipity['GET']['image']);
+        $file['imgsrc'] = $serendipity['serendipityHTTPPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] . '.' . $file['thumbnail_name'] . '.' . $file['extension'];
+        if ($file['hotlink']) {
+            $imgName    = $file['path'];
+        } else {
+            $imgName    = $serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $file['path'] . $file['name'] .'.'. $file['extension'];
+        }
+
+        $thumbbasename  = $file['path'] . $file['name'] . '.' . $file['thumbnail_name'] . '.' . $file['extension'];
+
+        if ($file['hotlink']) {
+            $thumbName  = $file['path'];
+        } else {
+            $thumbName  = $serendipity['serendipityHTTPPath'] . $serendipity['uploadHTTPPath'] . $thumbbasename;
+        }
+        $thumbsize     = @getimagesize($serendipity['serendipityPath'] . $serendipity['uploadPath'] . $thumbbasename);
+        $is_image      = serendipity_isImage($file);
+?>
+<script type="text/javascript" language="JavaScript" src="<?php echo $serendipity['serendipityHTTPPath']; ?>serendipity_define.js.php"></script>
+<script type="text/javascript" language="Javascript" src="<?php echo $serendipity['serendipityHTTPPath']; ?>serendipity_editor.js"></script>
+
+<div>
+<?php
+        if (!file_exists($file['imgsrc']) && $is_image) {
+
+            $dimWidth  = $file['dimensions_width'];
+            $dimHeight = $file['dimensions_height'];
+
+            if ($file['hotlink']) {
+                $thumbDim    = @serendipity_calculate_aspect_size($dimWidth, $dimHeight, $serendipity['thumbSize']);
+                $thumbWidth  = $thumbDim[0];
+                $thumbHeight = $thumbDim[1];
+                $imgsrc      = $file['path'];
+            } else {
+                $thumbWidth  = $thumbsize[0];
+                $thumbHeight = $thumbsize[1];
+                $imgsrc      = $file['imgsrc'];
+            }
+?>
+    <img align="right" src="<?php echo $imgsrc; ?>">
+    <h1><?php printf(YOU_CHOSE, $file['name']); ?></h1>
+    <p>
+        <form action="#" method="GET" name="serendipity[selForm]" onSubmit="serendipity_imageSelector_done()">
+            <div>
+                <input type="hidden" name="imgThumbWidth"  value="<?php echo $thumbWidth; ?>" />
+                <input type="hidden" name="imgThumbHeight" value="<?php echo $thumbHeight; ?>" />
+                <input type="hidden" name="imgWidth"  value="<?php echo $dimWidth; ?>" />
+                <input type="hidden" name="imgHeight" value="<?php echo $dimHeight; ?>" />
+                <input type="hidden" name="imgName"   value="<?php echo $imgName; ?>" />
+                <input type="hidden" name="thumbName" value="<?php echo $thumbName; ?>" />
+                <input type="hidden" name="hotlink" value="<?php echo $file['hotlink']; ?>" />
+                <?php if (!empty($serendipity['GET']['htmltarget'])) { ?>
+                <input type="hidden" name="serendipity[htmltarget]" value="<?php echo htmlspecialchars($serendipity['GET']['htmltarget']); ?>" />
+                <?php } ?>
+                <?php if (!empty($serendipity['GET']['filename_only'])) { ?>
+                <input type="hidden" name="serendipity[filename_only]" value="<?php echo htmlspecialchars($serendipity['GET']['filename_only']); ?>" />
+                <?php } ?>
+
+                <b><?php echo IMAGE_SIZE; ?>:</b>
+                <br />
+                <input id="radio_link_no" type="radio" name="serendipity[linkThumbnail]" value="no" checked="checked" /><label for="radio_link_no"><?php echo I_WANT_THUMB; ?></label><br />
+                <input id="radio_link_yes" type="radio" name="serendipity[linkThumbnail]" value="yes" /><label for="radio_link_yes"><?php echo I_WANT_BIG_IMAGE; ?></label><br />
+                <br />
+
+                <?php if (empty($serendipity['GET']['filename_only']) || $serendipity['GET']['filename_only'] != 'true') { ?>
+                <b><?php echo IMAGE_ALIGNMENT; ?>:</b>
+                <br />
+                <input type="radio" name="serendipity[align]" value="" />                       <img src="<?php echo serendipity_getTemplateFile('img/img_align_top.png') ?>"   vspace="5" /><br />
+                <input type="radio" name="serendipity[align]" value="left" checked="checked" /> <img src="<?php echo serendipity_getTemplateFile('img/img_align_left.png') ?>"  vspace="5" /><br />
+                <input type="radio" name="serendipity[align]" value="right" />                  <img src="<?php echo serendipity_getTemplateFile('img/img_align_right.png') ?>" vspace="5" /><br />
+                <br />
+
+                <b><?php echo IMAGE_AS_A_LINK; ?>:</b>
+                <br />
+                <input id="radio_islink_yes" type="radio" name="serendipity[isLink]" checked="checked" /><label for="radio_islink_yes"> <?php echo I_WANT_NO_LINK; ?></label><br />
+                <input id="radio_islink_no"  type="radio" name="serendipity[isLink]" /><label for="radio_islink_no"> <?php echo I_WANT_IT_TO_LINK; ?></label>
+                <?php if ($file['hotlink']) { ?>
+                <input type="text"  name="serendipity[url]" size="30" value="<?php echo $file['path']; ?>" onfocus="value='';" /><br />
+                <?php } else { ?>
+                <input type="text"  name="serendipity[url]" size="30" value="<?php echo $serendipity['serendipityHTTPPath'] . $serendipity['uploadPath'] . $file['path'] . $file['name'] .'.'. $file['extension']; ?>" onfocus="value='';" /><br />
+                <?php } ?>
+                <br />
+
+                <b><?php echo COMMENT; ?>:</b>
+                <br />
+                <textarea id="serendipity_imagecomment" name="serendipity[imagecomment]" rows="5" cols="40"></textarea>
+                <br />
+                <?php } ?>
+
+                <input type="button" value="<?php echo BACK; ?>" onclick="history.go(-1);" />
+                <input type="button" value="<?php echo DONE; ?>" onclick="serendipity_imageSelector_done('<?php echo $serendipity['GET']['textarea'] ?>')" />
+            </div>
+        </form>
+    </p>
+<?php
+    } else {
+        // What to do if file is no image.
+        // For the future, maybe allow the user to add title/link description and target window
+
+        if (!empty($serendipity['GET']['filename_only'])) {
+?>
+    <script type="text/javascript">
+        self.opener.serendipity_imageSelector_addToElement('<?php echo htmlspecialchars($imgName); ?>', '<?php echo htmlspecialchars($serendipity['GET']['htmltarget']); ?>');
+        self.close();
+    </script>
+<?php
+        } else {
+?>
+    <script type="text/javascript">
+    block = '<a href="<?php echo htmlspecialchars($imgName); ?>" title="<?php echo htmlspecialchars($file['name'] . '.' . $file['extension']); ?>" target="_blank"><?php echo htmlspecialchars($file['name'] . '.' . $file['extension']); ?></a>';
+    if (self.opener.editorref) {
+        self.opener.editorref.surroundHTML(block, '');
+    } else {
+        self.opener.serendipity_imageSelector_addToBody(block, '<?php echo $serendipity['GET']['textarea']; ?>');
+    }
+    self.close();
+    </script>
+<?php
+        }
+    }
+    break;
+
+    default:
+        $add_url = '';
+        if (!empty($serendipity['GET']['htmltarget'])) {
+            $add_url .= '&amp;serendipity[htmltarget]=' . $serendipity['GET']['htmltarget'];
+        }
+
+        if (!empty($serendipity['GET']['filename_only'])) {
+            $add_url .= '&amp;serendipity[filename_only]=' . $serendipity['GET']['filename_only'];
+        }
+?>
+    <h1><?php echo SELECT_FILE; ?></h1>
+    <h2><?php echo CLICK_FILE_TO_INSERT; ?></h2>
+    <br />
+
+    <?php
+        serendipity_displayImageList(
+          isset($serendipity['GET']['page'])   ? $serendipity['GET']['page']   : 1,
+          3,
+          false,
+          '?serendipity[step]=1' . $add_url . '&amp;serendipity[textarea]='. $serendipity['GET']['textarea'],
+          true
+        );
+}
+?>
+
+</div>
+</body>
+</html>
+
+<?php
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/serendipity_config.inc.php b/serendipity_config.inc.php
new file mode 100644 (file)
index 0000000..8490bd1
--- /dev/null
@@ -0,0 +1,301 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+if (!headers_sent()) {
+    session_start();
+}
+
+if (!defined('S9Y_INCLUDE_PATH')) {
+    define('S9Y_INCLUDE_PATH', dirname(__FILE__) . '/');
+}
+define('S9Y_CONFIG_TEMPLATE',     S9Y_INCLUDE_PATH . 'include/tpl/config_local.inc.php');
+define('S9Y_CONFIG_USERTEMPLATE', S9Y_INCLUDE_PATH . 'include/tpl/config_personal.inc.php');
+
+define('IS_installed', file_exists('serendipity_config_local.inc.php'));
+
+if (IS_installed === true && !defined('IN_serendipity')) {
+    define('IN_serendipity', true);
+}
+
+include_once(S9Y_INCLUDE_PATH . 'include/compat.inc.php');
+
+// The version string
+$serendipity['version']         = '0.8';
+
+// Name of folder for the default theme
+$serendipity['defaultTemplate'] = 'default';
+
+// Setting this to 'false' will enable debugging output. All alpa/beta/cvs snapshot versions will emit debug information by default. To increase the debug level (to enable Smarty debugging), set this flag to 'debug'.
+$serendipity['production']      = (preg_match('@\-(alpha|beta|cvs)@', $serendipity['version']) ? false : true);
+
+// Set error reporting
+error_reporting(E_ALL & ~E_NOTICE);
+
+if ($serendipity['production'] !== true) {
+    if ($serendipity['production'] === 'debug') {
+        error_reporting(E_ALL);
+    }
+    @ini_set('display_errors', 'on');
+}
+
+// Default rewrite method
+$serendipity['rewrite']         = 'none';
+
+// Message container
+$serendipity['messagestack']    = array();
+
+// Can the user change the date of publishing for an entry?
+$serendipity['allowDateManipulation'] = true;
+
+// How much time is allowed to pass since the publising of an entry, so that a comment to that entry
+// will update it's LastModified stamp? If the time is passed, a comment to an old entry will no longer
+// push an article as being updated.
+$serendipity['max_last_modified']    = 60 * 60 * 24 * 7;
+
+// Clients can send a If-Modified Header to the RSS Feed (Conditional Get) and receive all articles beyond
+// that date. However it is still limited by the number below of maximum entries
+$serendipity['max_fetch_limit']      = 50;
+
+// How many bytes are allowed for fetching trackbacks, so that no binary files get accidently trackbacked?
+$serendipity['trackback_filelimit']  = 150 * 1024;
+
+if (!isset($serendipity['fetchLimit'])) {
+    $serendipity['fetchLimit'] = 15;
+}
+
+// Should IFRAMEs be used for previewing entries and sending trackbacks?
+$serendipity['use_iframe'] = true;
+
+/* Default language for autodetection */
+$serendipity['autolang'] = 'en';
+
+/* Availiable languages */
+$serendipity['languages'] = array('en' => 'English',
+                                  'de' => 'German',
+                                  'da' => 'Danish',
+                                  'es' => 'Spanish',
+                                  'fr' => 'French',
+                                  'fi' => 'Finnish',
+                                  'cs' => 'Czech (Win-1250)',
+                                  'cz' => 'Czech (ISO-8859-2)',
+                                  'nl' => 'Dutch',
+                                  'is' => 'Icelandic',
+                                  'pt' => 'Portuguese Brazilian',
+                                  'bg' => 'Bulgarian',
+                                  'no' => 'Norwegian',
+                                  'it' => 'Italian',
+                                  'ru' => 'Russian',
+                                  'fa' => 'Persian',
+                                  'tw' => 'Traditional Chinese (Big5)',
+                                  'tn' => 'Traditional Chinese (UTF-8)',
+                                  'zh' => 'Simplified Chinese (GB2312)',
+                                  'cn' => 'Simplified Chinese (UTF-8)',
+                                  'ja' => 'Japanese',
+                                  'ko' => 'Korean');
+
+/*
+ *   Load main language file
+ */
+include($serendipity['serendipityPath'] . 'include/lang.inc.php');
+
+/* URI paths
+ * These could be defined in the language headers, except that would break
+ * backwards URL compatibility
+ */
+@define('PATH_ARCHIVES', 'archives');
+@define('PATH_ARCHIVE', 'archive');
+@define('PATH_AUTHORS', 'authors');
+@define('PATH_UNSUBSCRIBE', 'unsubscribe');
+@define('PATH_DELETE', 'delete');
+@define('PATH_APPROVE', 'approve');
+@define('PATH_FEEDS', 'feeds');
+@define('PATH_CATEGORIES', 'categories');
+@define('PATH_PLUGIN', 'plugin');
+@define('PATH_ADMIN', 'admin');
+@define('PATH_ENTRIES', 'entries');
+@define('PATH_SEARCH', 'search');
+@define('PATH_SMARTY_COMPILE', 'templates_c'); // will be placed inside the template directory
+
+/* Changing this is NOT recommended, rewrite rules does not take them into account - yet */
+@define('PERM_ARCHIVES', '%id%-%title%.html');
+@define('PERM_CATEGORIES', '%id%-%title%');
+@define('PERM_AUTHORS', '%id%-%title%');
+@define('PERM_FEEDS_CATEGORIES', '%id%-%title%.rss');
+
+/* URI patterns
+ * Note that it's important to use @ as the pattern delimiter. DO NOT use shortcuts
+ * like \d or \s, since mod_rewrite will use the regexps as well and chokes on them.
+ * If you add new patterns, remember to add the new rules to the *.tpl files and
+ * function serendipity_installFiles().
+ */
+@define('PAT_FILENAME', '0-9a-z\.\_!;,\+\-');
+@define('PAT_UNSUBSCRIBE', '@/'.PATH_UNSUBSCRIBE.'/(.*)/([0-9]+)@');
+@define('PAT_APPROVE', '@/'.PATH_APPROVE.'/(.*)/(.*)/([0-9]+)@');
+@define('PAT_DELETE', '@/'.PATH_DELETE.'/(.*)/(.*)/([0-9]+)@');
+@define('PAT_ARCHIVES', '@/'.PATH_ARCHIVES.'([/A-Za-z0-9]+)\.html@');
+@define('PAT_AUTHORS', '@/'.PATH_AUTHORS.'/([0-9]+)@');
+@define('PAT_COMMENTSUB', '@/([0-9]+)[_\-][' . PAT_FILENAME . ']*\.html@i');
+@define('PAT_FEEDS', '@/'.PATH_FEEDS.'/@');
+@define('PAT_FEEDS_CATEGORIES', '@/'.PATH_FEEDS.'\/'. PATH_CATEGORIES .'/([0-9]+)@');
+@define('PAT_FEED', '@/(index|atom|rss|b2rss|b2rdf).(rss|rdf|rss2|xml)$@');
+@define('PAT_ADMIN', '@/(' . PATH_ADMIN . '|'. PATH_ENTRIES .')(/.+)?@');
+@define('PAT_ARCHIVE', '@/'.PATH_ARCHIVE.'$@');
+@define('PAT_CATEGORIES', '@/'.PATH_CATEGORIES.'/([0-9]+)@');
+@define('PAT_PLUGIN', '@/' . PATH_PLUGIN . '/(.*)@');
+@define('PAT_SEARCH', '@/' . PATH_SEARCH . '/(.*)@');
+@define('PAT_CSS', '@/(serendipity\.css|serendipity_admin\.css)@');
+
+@define('USERLEVEL_ADMIN', 255);
+@define('USERLEVEL_CHIEF', 1);
+@define('USERLEVEL_EDITOR', 0);
+
+@define('VIEWMODE_THREADED', 'threaded');
+@define('VIEWMODE_LINEAR', 'linear');
+
+
+/*
+ *   Kill the script if we are not installed, and not inside the installer
+ */
+if ( !defined('IN_installer') && IS_installed === false ) {
+    header('Location: ' . ($_SERVER['HTTPS'] == 'on' ? 'https://' : 'http://') . $_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']) . '/serendipity_admin.php');
+    serendipity_die(sprintf(SERENDIPITY_NOT_INSTALLED, 'serendipity_admin.php'));
+}
+
+if (defined('IN_installer') && IS_installed === false) {
+    $serendipity['lang'] = $serendipity['autolang'];
+    $css_mode            = 'serendipity_admin.css';
+    return 1;
+}
+
+/*
+ *   Load DB configuration information
+ *   Load Functions
+ *   Make sure that the file included is in the current directory and not any possible
+ *   include path
+ */
+if (file_exists($_SERVER['DOCUMENT_ROOT'] . dirname($_SERVER['PHP_SELF']) . '/serendipity_config_local.inc.php')) {
+    include_once($_SERVER['DOCUMENT_ROOT'] . dirname($_SERVER['PHP_SELF']) . '/serendipity_config_local.inc.php');
+} elseif (file_exists($serendipity['serendipityPath'] . '/serendipity_config_local.inc.php')) {
+    include_once($serendipity['serendipityPath'] . '/serendipity_config_local.inc.php');
+} else {
+    include_once(S9Y_INCLUDE_PATH . '/serendipity_config_local.inc.php');
+}
+
+define('IS_up2date', version_compare($serendipity['version'], $serendipity['versionInstalled'], '<='));
+
+/*
+ *  Include main functions
+ */
+include_once(S9Y_INCLUDE_PATH . 'include/functions.inc.php');
+
+if (serendipity_FUNCTIONS_LOADED!== true) {
+    serendipity_die(sprintf(INCLUDE_ERROR, 'include/functions.inc.php'));
+}
+
+/*
+ *   Attempt to connect to the database
+ */
+if (!serendipity_db_connect()) {
+    serendipity_die(DATABASE_ERROR);
+}
+
+/*
+ *   Load Configuration options from the database
+ */
+
+serendipity_load_configuration();
+
+/*
+ * If a user is logged in, fetch his preferences. He possibly wants to have a different language
+ */
+
+if (IS_installed === true) {
+    serendipity_login(false);
+}
+
+$serendipity['lang'] = serendipity_getSessionLanguage(); // @see function declaration for todo
+
+if (isset($_SESSION['serendipityAuthorid'])) {
+    serendipity_load_configuration($_SESSION['serendipityAuthorid']);
+}
+
+/*
+ *   Load main language file again, because now we have the preferred language
+ */
+
+include(S9Y_INCLUDE_PATH . 'include/lang.inc.php');
+
+/*
+ *   Set current locale, if any has been defined
+ */
+if (defined('DATE_LOCALES')) {
+    $locales = explode(',', DATE_LOCALES);
+    foreach ($locales as $locale) {
+        $locale = trim($locale);
+        if (setlocale(LC_TIME, $locale) == $locale) {
+            break;
+        }
+    }
+}
+
+/*
+ *   Fallback charset, if none is defined in the language files
+ */
+@define('LANG_CHARSET', 'ISO-8859-1');
+
+/*
+ *  Create array of permission levels, with descriptions
+ */
+$serendipity['permissionLevels'] = array(USERLEVEL_EDITOR => USERLEVEL_EDITOR_DESC,
+                                         USERLEVEL_CHIEF => USERLEVEL_CHIEF_DESC,
+                                         USERLEVEL_ADMIN => USERLEVEL_ADMIN_DESC);
+
+
+if ( (isset($serendipity['autodetect_baseURL']) && serendipity_db_bool($serendipity['autodetect_baseURL'])) ||
+     (isset($serendipity['embed']) && serendipity_db_bool($serendipity['embed'])) ) {
+    $serendipity['baseURL'] = 'http' . (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 's' : '') . '://' . $_SERVER['HTTP_HOST'] . $serendipity['serendipityHTTPPath'];
+}
+
+/*
+ *  Check if the installed version is higher than the version of the config
+ */
+
+if (IS_up2date === false && !defined('IN_upgrader')) {
+    if (preg_match(PAT_CSS, $_SERVER['REQUEST_URI'], $matches)) {
+        $css_mode = 'serendipity_admin.css';
+        return 1;
+    }
+
+    serendipity_die(sprintf(SERENDIPITY_NEEDS_UPGRADE, $serendipity['versionInstalled'], $serendipity['version'], $serendipity['serendipityHTTPPath'] . 'serendipity_admin.php'));
+}
+
+// We don't care who tells us what to do
+if (!isset($serendipity['GET']['action'])) {
+    $serendipity['GET']['action'] = (isset($serendipity['POST']['action']) ? $serendipity['POST']['action'] : '');
+}
+
+if (!isset($serendipity['GET']['adminAction'])) {
+    $serendipity['GET']['adminAction'] = (isset($serendipity['POST']['adminAction']) ? $serendipity['POST']['adminAction'] : '');
+}
+
+// Some stuff...
+if (!isset($_SESSION['serendipityAuthedUser'])) {
+    $_SESSION['serendipityAuthedUser'] = false;
+}
+
+$old_include = @ini_get('include_path');
+@ini_set('include_path', $serendipity['serendipityPath'] . PATH_SEPARATOR . $serendipity['serendipityPath'] . 'bundled-libs/' . PATH_SEPARATOR . $old_include);
+
+if (isset($_SESSION['serendipityUser'])) {
+    $serendipity['user']  = $_SESSION['serendipityUser'];
+}
+
+if (isset($_SESSION['serendipityEmail'])) {
+    $serendipity['email'] = $_SESSION['serendipityEmail'];
+}
+
+serendipity_plugin_api::hook_event('frontend_configure', $serendipity);
+
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/serendipity_define.js.php b/serendipity_define.js.php
new file mode 100644 (file)
index 0000000..61f5bd2
--- /dev/null
@@ -0,0 +1,16 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+header('Content-type: application/x-javascript');
+include_once('serendipity_config.inc.php');
+?>
+<!-- // Hide from older browsers
+// This page serves to carry through any variables without having to parse a complete .js file as .php
+
+var XHTML11 = <?php echo ($serendipity['XHTML11'] ? 'true' : 'false'); ?>;
+
+// -->
+<?php
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/serendipity_editor.js b/serendipity_editor.js
new file mode 100644 (file)
index 0000000..4918d30
--- /dev/null
@@ -0,0 +1,228 @@
+<!-- // Hide from older browsers
+/* $Id$ */
+/*
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+*/
+
+/*
+    Written by chris wetherell
+    http://www.massless.org
+    chris [THE AT SIGN] massless.org
+
+    warning: it only works for IE4+/Win and Moz1.1+
+    feel free to take it for your site
+    if there are any problems, let chris know.
+*/
+
+var thisForm;
+
+function getMozSelection(txtarea) {
+    var selLength = txtarea.textLength;
+    var selStart = txtarea.selectionStart;
+    var selEnd = txtarea.selectionEnd;
+
+    if (selEnd==1 || selEnd==2) {
+        selEnd=selLength;
+    }
+    return (txtarea.value).substring(selStart, selEnd);
+}
+
+function getIESelection(txtarea) {
+    return document.selection.createRange().text;
+}
+
+function mozWrap(txtarea, lft, rgt) {
+    var selLength = txtarea.textLength;
+    var selStart = txtarea.selectionStart;
+    var selEnd = txtarea.selectionEnd;
+
+    if (selEnd==1 || selEnd==2) selEnd=selLength;
+    var s1 = (txtarea.value).substring(0,selStart);
+    var s2 = (txtarea.value).substring(selStart, selEnd)
+    var s3 = (txtarea.value).substring(selEnd, selLength);
+    txtarea.value = s1 + lft + s2 + rgt + s3;
+}
+
+function IEWrap(txtarea, lft, rgt) {
+    strSelection = document.selection.createRange().text;
+    if (strSelection != "") {
+        document.selection.createRange().text = lft + strSelection + rgt;
+    } else {
+        txtarea.value = txtarea.value + lft + rgt;
+    }
+}
+
+function wrapSelection(txtarea, lft, rgt) {
+    if (document.all) {
+        IEWrap(txtarea, lft, rgt);
+    } else if (document.getElementById) {
+        mozWrap(txtarea, lft, rgt);
+    }
+}
+
+function wrapSelectionWithLink(txtarea) {
+    var my_link = prompt("Enter URL:","http://");
+
+    if (document.all && getIESelection(txtarea) == "" ||
+         document.getElementById && getMozSelection(txtarea) == "") {
+        var my_desc = prompt("Enter Description", '');
+    }
+
+    if (my_link != null) {
+        lft = "<a href=\"" + my_link + "\">";
+        if (my_desc != null && my_desc != "") {
+            rgt = my_desc + "</a>";
+        } else {
+            rgt = "</a>";
+        }
+        wrapSelection(txtarea, lft, rgt);
+    }
+
+    return;
+}
+/* end chris w. script */
+
+function mozInsert(txtarea, str) {
+    var selLength = txtarea.textLength;
+    var selStart = txtarea.selectionStart;
+    var selEnd = txtarea.selectionEnd;
+    if (selEnd==1 || selEnd==2) {
+        selEnd=selLength;
+    }
+    var s1 = (txtarea.value).substring(0,selStart);
+    var s2 = (txtarea.value).substring(selStart, selEnd)
+    var s3 = (txtarea.value).substring(selEnd, selLength);
+    txtarea.value = s1 + str + s2 + s3;
+}
+
+function wrapInsImage(area) {
+    var loc = prompt('Enter the Image Location: ');
+    if (!loc) {
+        return;
+    }
+    mozInsert(area,'<img src="'+ loc + '" alt="" />');
+}
+
+/* end Better-Editor functions */
+
+function serendipity_insImage (area) {
+    var loc = prompt('Enter the Image Location: ');
+    if (!loc) {
+        area.focus();
+        return;
+    }
+
+    area.value = area.value + '<img src="' + loc + '" alt="" />';
+    area.focus();
+}
+
+function serendipity_insBasic (area, tag) {
+    area.value = area.value + "<" + tag + "></" + tag + ">";
+    area.focus();
+}
+
+function serendipity_insLink (area) {
+    var loc  = prompt('Enter URL Location: ');
+    var text = prompt('Enter Description: ');
+
+    if (!loc) {
+        area.focus();
+        return;
+    }
+
+    area.value = area.value + '<a href="' + loc + '">' + (text ? text : loc) + '</a>';
+    area.focus();
+}
+
+function serendipity_imageSelector_addToElement (str, el)
+{
+    document.getElementById(el).value = str;
+    document.getElementById(el).focus();
+    document.getElementById(el).onchange();
+}
+
+function serendipity_imageSelector_addToBody (str, textarea)
+{
+    document.forms['serendipityEntry']['serendipity['+ textarea +']'].value += str;
+    document.forms['serendipityEntry']['serendipity['+ textarea +']'].focus();
+}
+
+function serendipity_imageSelector_done(textarea)
+{
+    var insert = '';
+    var img = '';
+    var src = '';
+    var f = document.forms['serendipity[selForm]'].elements;
+
+    if (f['serendipity[linkThumbnail]'][0].checked == true) {
+        img       = f['thumbName'].value;
+        imgWidth  = f['imgThumbWidth'].value;
+        imgHeight = f['imgThumbHeight'].value;
+    } else {
+        img       = f['imgName'].value;
+        imgWidth  = f['imgWidth'].value;
+        imgHeight = f['imgHeight'].value;
+    }
+
+    if (f['serendipity[filename_only]'] && f['serendipity[filename_only]'].value == 'true') {
+        self.opener.serendipity_imageSelector_addToElement(img, f['serendipity[htmltarget]'].value);
+        self.close();
+        return true;
+    }
+
+    if (document.getElementById('serendipity_imagecomment').value != '') {
+        styled = false;
+    } else {
+        styled = true;
+    }
+
+    floating = 'center';
+    if (XHTML11) {
+        if (f['serendipity[align]'][0].checked == true) {
+            img = "<img width='" + imgWidth + "' height='" + imgHeight + "' " + (styled ? 'style="border: 0px; padding-left: 5px; padding-right: 5px;"' : '') + ' src="' + img + "\" alt=\"\" />";
+        } else if (f['serendipity[align]'][1].checked == true) {
+            img = "<img width='" + imgWidth + "' height='" + imgHeight + "' " + (styled ? 'style="float: left; border: 0px; padding-left: 5px; padding-right: 5px;"' : '') + ' src="' + img + "\" alt=\"\" />";
+            floating = 'left';
+        } else if (f['serendipity[align]'][2].checked == true) {
+            img = "<img width='" + imgWidth + "' height='" + imgHeight + "' " + (styled ? 'style="float: right; border: 0px; padding-left: 5px; padding-right: 5px;"' : '') + ' src="' + img + "\" alt=\"\" />";
+            floating = 'right';
+        }
+    } else {
+        if (f['serendipity[align]'][0].checked == true) {
+            img = "<img width='" + imgWidth + "' height='" + imgHeight + "' border='0' hspace='5' src='" + img + "' alt='' />";
+        } else if (f['serendipity[align]'][1].checked == true) {
+            img = "<img width='" + imgWidth + "' height='" + imgHeight + "' border='0' hspace='5' align='left' src='" + img + "' alt='' />";
+            floating = 'left';
+        } else if (f['serendipity[align]'][2].checked == true) {
+            img = "<img width='" + imgWidth + "' height='" + imgHeight + "' border='0' hspace='5' align='right' src='" + img + "' alt='' />";
+            floating = 'right';
+        }
+    }
+
+    if (f['serendipity[isLink]'][1].checked == true) {
+        insert = "<a href='" + f['serendipity[url]'].value + "'>" + img + "</a>";
+    } else {
+        insert = img;
+    }
+
+    if (document.getElementById('serendipity_imagecomment').value != '') {
+        comment = f['serendipity[imagecomment]'].value;
+        block = '<div class="serendipity_imageComment_' + floating + '" style="width: ' + imgWidth + 'px">'
+              +     '<div class="serendipity_imageComment_img">' + insert + '</div>'
+              +     '<div class="serendipity_imageComment_txt">' + comment + '</div>'
+              + '</div>';
+    } else {
+        block = insert;
+    }
+
+    if (self.opener.editorref) {
+        self.opener.editorref.surroundHTML(block, '');
+    } else {
+        self.opener.serendipity_imageSelector_addToBody(block, textarea);
+    }
+
+    self.close();
+}
+
+// -->
diff --git a/serendipity_xmlrpc.php b/serendipity_xmlrpc.php
new file mode 100644 (file)
index 0000000..d82df22
--- /dev/null
@@ -0,0 +1,509 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+$debug_xmlrpc = false;
+if ($debug_xmlrpc) {
+    $fp = fopen('rpc.log', 'a');
+    fwrite($fp, '[' . date('d.m.Y H:i') . ']' . print_r($HTTP_RAW_POST_DATA, true));
+    fclose($fp);
+    ob_start();
+}
+
+require_once 'serendipity_config.inc.php';
+require_once 'bundled-libs/XML/RPC/Server.php';
+
+$dispatches = array(
+                    /* BLOGGER API */
+                    'blogger.getUsersBlogs' =>
+                        array('function' => 'blogger_getUsersBlogs'),
+                    'blogger.getUserInfo' =>
+                        array('function' => 'blogger_getUserInfo'),
+                    'blogger.newPost' =>
+                        array('function' => 'blogger_newPost'),
+                    'blogger.editPost' =>
+                        array('function' => 'blogger_editPost'),
+                    'blogger.deletePost' =>
+                        array('function' => 'blogger_deletePost'),
+                    'blogger.getRecentPosts' =>
+                        array('function' => 'blogger_getRecentPosts'),
+                    'blogger.getPost' =>
+                        array('function' => 'blogger_getPost'),
+
+                    /* MT/metaWeblog API */
+                    'metaWeblog.newPost' =>
+                        array('function' => 'metaWeblog_newPost'),
+                    'metaWeblog.editPost' =>
+                        array('function' => 'metaWeblog_editPost'),
+                    'metaWeblog.getPost' =>
+                        array('function' => 'metaWeblog_getPost'),
+                    'metaWeblog.deletePost' =>
+                        array('function' => 'metaWeblog_deletePost'),
+                    'metaWeblog.setPostCategories' =>
+                        array('function' => 'metaWeblog_setPostCategories'),
+                    'metaWeblog.getPostCategories' =>
+                        array('function' => 'metaWeblog_getPostCategories'),
+                    'metaWeblog.newMediaObject' =>
+                        array('function' => 'metaWeblog_newMediaObject'),
+                    'metaWeblog.getRecentPosts' =>
+                        array('function' => 'mt_getRecentPostTitles'),
+                    'mt.getRecentPostTitles' =>
+                        array('function' => 'mt_getRecentPostTitles'),
+                    'mt.getCategoryList' =>
+                        array('function' => 'mt_getCategoryList'),
+                    'mt.getPostCategories' =>
+                        array('function' => 'metaWeblog_getPostCategories'),
+                    'mt.setPostCategories' =>
+                        array('function' => 'metaWeblog_setPostCategories'),
+                    'mt.supportedTextFilters' =>
+                        array('function' => 'mt_supportedTextFilters'),
+                    'mt.publishPost' =>
+                        array('function' => 'metaWeblog_publishPost'));
+
+function blogger_getUsersBlogs($message) {
+    global $serendipity;
+
+    $val = $message->params[1];
+    $username = $val->getval();
+    $val = $message->params[2];
+    $password = $val->getval();
+    if (!serendipity_authenticate_author($username, $password)) {
+        return new XML_RPC_Response('', 4, 'Authentication Failed');
+    }
+    $blog1 = new XML_RPC_Value(
+        array('url'      => new XML_RPC_Value($serendipity['baseURL']),
+              'blogid'   => new XML_RPC_Value('1'),
+              'blogName' => new XML_RPC_Value($serendipity['blogTitle'])),
+        'struct');
+    $blogs = new XML_RPC_Value( array($blog1), 'array');
+    $r = new XML_RPC_Response($blogs);
+    return($r);
+}
+
+function blogger_getUserInfo($message) {
+    global $serendipity;
+    $val = $message->params[1];
+    $username = $val->getval();
+    $val = $message->params[2];
+    $password = $val->getval();
+    if (!serendipity_authenticate_author($username, $password)) {
+        return new XML_RPC_Response('', 4, 'Authentication Failed');
+    }
+    $userdata = new XML_RPC_Value(
+        array('nickname'  => new XML_RPC_Value($serendipity['serendipityUser']),
+              'userid'    => new XML_RPC_Value($serendipity['authorid'], 'string'),
+              'url'       => new XML_RPC_Value($serendipity['baseURL']),
+              'email'     => new XML_RPC_Value($serendipity['serendipityEmail']),
+              'lastname'  => new XML_RPC_Value(''),
+              'firstname' => new XML_RPC_Value('')),
+        'struct');
+    $r = new XML_RPC_Response($userdata);
+    return($r);
+}
+
+function blogger_getRecentPosts($message) {
+    $val = $message->params[2];
+    $username = $val->getval();
+    $val = $message->params[3];
+    $password = $val->getval();
+    $val = $message->params[4];
+    $numposts = $val->getval();
+    if (!serendipity_authenticate_author($username, $password)) {
+        return new XML_RPC_Response('', 4, 'Authentication Failed');
+    }
+    $entries = serendipity_fetchEntries('', false, $numposts);
+    $xml_entries_vals = array();
+    foreach ( $entries as $entry ) {
+        $xml_entries_vals[] = new XML_RPC_Value(
+            array(
+                  'postid'      => new XML_RPC_Value($entry['id'], 'string'),
+                  'title'       => new XML_RPC_Value($entry['title'], 'string'),
+                  'userid'      => new XML_RPC_Value($entry['authorid'], 'string'),
+                  'dateCreated' => new XML_RPC_Value(XML_RPC_iso8601_encode($entry['timestamp']), 'dateTime.iso8601'),
+                  'postid'      => new XML_RPC_Value($entry['id'], 'string')), 'struct');
+    }
+    $xml_entries = new XML_RPC_Value($xml_entries_vals, 'array');
+    return new XML_RPC_Response($xml_entries);
+}
+
+function blogger_getPost($message) {
+    global $serendipity;
+    $val = $message->params[1];
+    $postid = $val->getval();
+    $val = $message->params[2];
+    $username = $val->getval();
+    $val = $message->params[3];
+    $password = $val->getval();
+    if (!serendipity_authenticate_author($username, $password)) {
+        return new XML_RPC_Response('', 4, 'Authentication Failed');
+    }
+
+    $entry = serendipity_fetchEntry('id', $postid);
+    $entry = new XML_RPC_Value(blogger_setEntry($entry), 'struct');
+    return new XML_RPC_Response($entry);
+}
+
+function mt_getCategoryList($message) {
+    global $serendipity;
+
+    $val = $message->params[1];
+    $username = $val->getval();
+    $val = $message->params[2];
+    $password = $val->getval();
+    if (!serendipity_authenticate_author($username, $password)) {
+        return new XML_RPC_Response('', 4, 'Authentication Failed');
+    }
+    $cats = serendipity_fetchCategories($serendipity['authorid']);
+    $xml_entries_vals = array();
+    foreach ( $cats as $cat ) {
+        $xml_entries_vals[] = new XML_RPC_Value(
+            array(
+              'categoryId'   => new XML_RPC_Value($cat['categoryid'], 'string'),
+              'categoryName' => new XML_RPC_Value($cat['category_name'], 'string')
+            ),
+            'struct'
+        );
+    }
+    $xml_entries = new XML_RPC_Value($xml_entries_vals, 'array');
+    return new XML_RPC_Response($xml_entries);
+}
+
+function mt_getRecentPostTitles($message) {
+    $val = $message->params[1];
+    $username = $val->getval();
+    $val = $message->params[2];
+    $password = $val->getval();
+    $val = $message->params[3];
+    $numposts = $val->getval();
+    if (!serendipity_authenticate_author($username, $password)) {
+        return new XML_RPC_Response('', 4, 'Authentication Failed');
+    }
+    $entries = serendipity_fetchEntries('', false, $numposts);
+    $xml_entries_vals = array();
+    foreach ($entries as $entry) {
+        $xml_entries_vals[] = new XML_RPC_Value(
+            array(
+                'postid'      => new XML_RPC_Value($entry['id'], 'string'),
+                'title'       => new XML_RPC_Value($entry['title'], 'string'),
+                'userid'      => new XML_RPC_Value($entry['authorid'], 'string'),
+                'dateCreated' => new XML_RPC_Value(XML_RPC_iso8601_encode($entry['timestamp']), 'dateTime.iso8601'),
+                'postid'      => new XML_RPC_Value($entry['id'], 'string')
+            ),
+            'struct');
+    }
+    $xml_entries = new XML_RPC_Value($xml_entries_vals, 'array');
+    return new XML_RPC_Response($xml_entries);
+}
+
+function mt_supportedTextFilters($message) {
+    # we support no text filters currently
+    return new XML_RPC_Response(new XML_RPC_Value(array(), 'array'));
+}
+
+function blogger_newPost($message) {
+    global $serendipity;
+    $val = $message->params[2];
+    $username = $val->getval();
+    $val = $message->params[3];
+    $password = $val->getval();
+    if (!serendipity_authenticate_author($username, $password)) {
+        return new XML_RPC_Response('', 4, 'Authentication Failed');
+    }
+    $val = $message->params[4];
+    $entry['body']  = $val->getval();
+    $entry['allow_comments'] = $serendipity['allowCommentsDefault'];
+    $entry['moderate_comments'] = $serendipity['moderateCommentsDefault'];
+    $id = serendipity_updertEntry($entry);
+    return new XML_RPC_Response(new XML_RPC_Value($id, 'string'));
+}
+
+function blogger_editPost($message) {
+    $val = $message->params[1];
+    $entry['id'] = $val->getval();
+    $val = $message->params[2];
+    $username = $val->getval();
+    $val = $message->params[3];
+    $password = $val->getval();
+    if (!serendipity_authenticate_author($username, $password)) {
+        return new XML_RPC_Response('', 4, 'Authentication Failed');
+    }
+    $val = $message->params[4];
+    $entry['body']  = $val->getval();
+    $entry['author'] = $username;
+    $id = serendipity_updertEntry($entry);
+    return new XML_RPC_Response(new XML_RPC_Value($id, 'string'));
+}
+
+function blogger_deletePost($message) {
+    $val = $message->params[1];
+    $entry['id'] = $val->getval();
+    $val = $message->params[2];
+    $username = $val->getval();
+    $val = $message->params[3];
+    $password = $val->getval();
+    if (!serendipity_authenticate_author($username, $password)) {
+        return new XML_RPC_Response('', 4, 'Authentication Failed');
+    }
+    $val = $message->params[4];
+    $entry['body']  = $val->getval();
+    $entry['author'] = $username;
+    $id = serendipity_deleteEntry($entry['id']);
+    return new XML_RPC_Response(new XML_RPC_Value(1, 'boolean'));
+}
+
+function universal_fetchCategories($post_categories) {
+    global $serendipity;
+
+    $categories = array();
+    if (is_array($post_categories)) {
+        foreach($post_categories AS $cat_id => $cat_obj) {
+            if (is_object($cat_obj)) {
+                $cat_name = $cat_obj->getval();
+                $cat = serendipity_fetchCategories(null, $cat_name);
+                if (isset($cat[0]['categoryid'])) {
+                    $categories[$cat[0]['categoryid']] = $cat[0]['categoryid'];
+                }
+            } elseif (is_array($cat_obj) && isset($cat_obj['categoryId'])) {
+                $cat_id = $cat_obj['categoryId']->getval();
+                $categories[$cat_id] = $cat_id;
+            }
+        }
+    }
+
+    return $categories;
+}
+
+function metaWeblog_newPost($message) {
+    global $serendipity;
+    $val = $message->params[1];
+    $username = $val->getval();
+    $val = $message->params[2];
+    $password = $val->getval();
+
+    if (!serendipity_authenticate_author($username, $password)) {
+        return new XML_RPC_Response('', 4, 'Authentication Failed');
+    }
+
+    $val = $message->params[3];
+    $post_array = $val->getval();
+    $val = $message->params[4];
+    $publish = $val->getval();
+
+    $entry['categories']        = universal_fetchCategories($post_array['categories']);
+    $entry['title']             = $post_array['title'];
+    $entry['body']              = $post_array['description'];
+    $entry['extended']          = $post_array['mt_text_more'];
+    $entry['isdraft']           = ($publish == 0) ? 'true' : 'false';
+    $entry['allow_comments']    = $serendipity['allowCommentsDefault'];
+    $entry['moderate_comments'] = $serendipity['moderateCommentsDefault'];
+
+    $id = serendipity_updertEntry($entry);
+
+    return new XML_RPC_Response(new XML_RPC_Value($id, 'string'));
+}
+
+function metaWeblog_publishPost($message) {
+    global $serendipity;
+
+    $val = $message->params[0];
+    $postid = $val->getval();
+    $val = $message->params[1];
+    $username = $val->getval();
+    $val = $message->params[2];
+    $password = $val->getval();
+
+    if (!serendipity_authenticate_author($username, $password)) {
+        return new XML_RPC_Response('', 4, 'Authentication Failed');
+    }
+
+    $entry['isdraft']    = 'false';
+    $entry['id']         = $postid;
+
+    $id = serendipity_updertEntry($entry);
+    return new XML_RPC_Response(new XML_RPC_Value($id ? true : false, 'boolean'));
+}
+
+function metaWeblog_editPost($message) {
+    global $serendipity;
+
+    $val = $message->params[0];
+    $postid = $val->getval();
+    $val = $message->params[1];
+    $username = $val->getval();
+    $val = $message->params[2];
+    $password = $val->getval();
+
+    if (!serendipity_authenticate_author($username, $password)) {
+        return new XML_RPC_Response('', 4, 'Authentication Failed');
+    }
+
+    $val = $message->params[3];
+    $post_array = $val->getval();
+    $val = $message->params[4];
+    $publish = $val->getval();
+
+    $entry['categories']    = universal_fetchCategories($post_array['categories']);
+    $entry['title']         = $post_array['title'];
+    $entry['body']          = $post_array['description'];
+    $entry['extended']      = $post_array['mt_text_more'];
+    $entry['isdraft']       = ($publish == 0) ? 'true' : 'false';
+    $entry['author']        = $username;
+    $entry['authorid']      = $serendipity['authorid'];
+    $entry['id']            = $postid;
+
+    $id = serendipity_updertEntry($entry);
+    return new XML_RPC_Response(new XML_RPC_Value($id ? true : false, 'boolean'));
+}
+
+function metaWeblog_getPost($message) {
+    global $serendipity;
+    $val = $message->params[0];
+    $postid = $val->getval();
+    $val = $message->params[1];
+    $username = $val->getval();
+    $val = $message->params[2];
+    $password = $val->getval();
+    if (!serendipity_authenticate_author($username, $password)) {
+        return new XML_RPC_Response('', 4, 'Authentication Failed');
+    }
+
+    $entry = serendipity_fetchEntry('id', $postid);
+    $entry = new XML_RPC_Value(metaWeblog_setEntry($entry), 'struct');
+
+    return new XML_RPC_Response($entry);
+}
+
+function metaWeblog_deletePost($message) {
+    $val = $message->params[1];
+    $entry['id'] = $val->getval();
+    $val = $message->params[2];
+    $username = $val->getval();
+    $val = $message->params[3];
+    $password = $val->getval();
+    if (!serendipity_authenticate_author($username, $password)) {
+        return new XML_RPC_Response('', 4, 'Authentication Failed');
+    }
+    $val = $message->params[4];
+    $entry['body'] = $val->getval();
+    $entry['author'] = $username;
+    $id = serendipity_deleteEntry($entry['id']);
+    return new XML_RPC_Response(new XML_RPC_Value(1, 'boolean'));
+}
+
+function metaWeblog_setPostCategories($message) {
+    global $serendipity;
+    $val = $message->params[0];
+    $postid = $val->getval();
+    $val = $message->params[1];
+    $username = $val->getval();
+    $val = $message->params[2];
+    $password = $val->getval();
+    $categories = $message->params[3];
+
+    if (!serendipity_authenticate_author($username, $password)) {
+        return new XML_RPC_Response('', 4, 'Authentication Failed');
+    }
+
+    $category_ids = universal_fetchCategories($categories->getval(), true);
+    serendipity_updateEntryCategories($postid, $category_ids);
+    return new XML_RPC_Response(new XML_RPC_Value(1, 'boolean'));
+}
+
+function metaWeblog_getPostCategories($message) {
+    $val = $message->params[0];
+    $postid = $val->getval();
+    $val = $message->params[1];
+    $username = $val->getval();
+    $val = $message->params[2];
+    $password = $val->getval();
+    if (!serendipity_authenticate_author($username, $password)) {
+        return new XML_RPC_Response('', 4, 'Authentication Failed');
+    }
+
+    $entry = serendipity_fetchEntry('id', (int)$postid);
+
+    $categories = array();
+    if (is_array($entry['categories'])) {
+        foreach($entry['categories'] AS $i => $cat) {
+            $categories[] = new XML_RPC_Value(
+                array(
+                  'categoryId'   => new XML_RPC_Value($cat['categoryid'], 'string'),
+                  'categoryName' => new XML_RPC_Value($cat['category_name'], 'string')
+                ),
+                'struct'
+            );
+        }
+    }
+
+    return new XML_RPC_Response(new XML_RPC_Value($categories, 'array'));
+}
+
+function metaWeblog_newMediaObject($message) {
+    global $serendipity;
+    $val = $message->params[0];
+    $postid = $val->getval();
+    $val = $message->params[1];
+    $username = $val->getval();
+    $val = $message->params[2];
+    $password = $val->getval();
+    $val = $message->params[3];
+    $struct = $val->getval();
+    if (!serendipity_authenticate_author($username, $password)) {
+        return new XML_RPC_Response('', 4, 'Authentication Failed');
+    }
+
+    $full = $serendipity['serendipityPath'] . $serendipity['uploadPath'] . $struct['name'];
+
+    if (!is_dir(dirname($full))) {
+        @mkdir(dirname($full));
+    }
+
+    $fp = fopen($full, 'w');
+    fwrite($fp, base64_decode($struct['bits']));
+    fclose($fp);
+    $path = $serendipity['baseURL'] . $serendipity['uploadPath'] . $struct['name'];
+    return new XML_RPC_Response(new XML_RPC_Value(array('url' => new XML_RPC_Value($path, 'string')), 'struct'));
+}
+
+function blogger_setEntry(&$entry) {
+    $tmp = array(
+          'content'           => new XML_RPC_Value($entry['extended'], 'string'),
+    );
+    return universal_setEntry($entry, $tmp);
+}
+
+function metaWeblog_setEntry(&$entry) {
+    $tmp = array(
+          'mt_text_more'      => new XML_RPC_Value($entry['extended'], 'string'),
+    );
+    return universal_setEntry($entry, $tmp);
+}
+
+function universal_setEntry(&$entry, &$tmp) {
+    $tmp = array(
+        'dateCreated'       => new XML_RPC_Value(XML_RPC_iso8601_encode($entry['timestamp']), 'dateTime.iso8601'),
+        'postid'            => new XML_RPC_Value($entry['id'], 'string'),
+        'userid'            => new XML_RPC_Value($entry['authorid'], 'string'),
+        'description'       => new XML_RPC_Value($entry['body'], 'string'),
+        'mt_excerpt'        => new XML_RPC_Value('', 'string'),
+        'mt_allow_comments' => new XML_RPC_Value(1, 'int'),
+        'mt_allow_pings'    => new XML_RPC_Value(1, 'int'),
+        'mt_convert_breaks' => new XML_RPC_Value('', 'string'),
+        'mt_keywords'       => new XML_RPC_Value('', 'string'),
+        'title'             => new XML_RPC_Value($entry['title'],'string'),
+        'permalink'         => new XML_RPC_Value(serendipity_rewriteURL(PATH_ARCHIVES.'/' . $postid . '_.html', 'baseURL'), 'string'),
+        'link'              => new XML_RPC_Value(serendipity_rewriteURL(PATH_ARCHIVES.'/' . $postid . '_.html', 'baseURL'), 'string'),
+    );
+
+    return array_merge($entry, $tmp);
+}
+
+$server = new XML_RPC_Server($dispatches,1);
+if ($debug_xmlrpc) {
+    $fp = fopen('rpc.log', 'a');
+    fwrite($fp, ob_get_contents() . "\n---------------------------------------\n");
+    fclose($fp);
+    ob_end_flush();
+}
+/* vim: set sts=4 ts=4 expandtab : */
+?>
diff --git a/sql/db.sql b/sql/db.sql
new file mode 100644 (file)
index 0000000..f294162
--- /dev/null
@@ -0,0 +1,194 @@
+####
+#### Important notes:
+#### If you make modifications (additions, subtractions), please
+#### make the appropriate change in the db_update files.  If you don't
+#### know the syntax for a different database, e-mail the list for
+#### help.
+####
+####
+
+#
+# Table structure for table '{PREFIX}authors'
+#
+
+create table {PREFIX}authors (
+  realname varchar(255) NOT NULL default '',
+  username varchar(20) default null,
+  password varchar(32) default null,
+  authorid {AUTOINCREMENT} {PRIMARY},
+  mail_comments int(1) default '1',
+  mail_trackbacks int(1) default '1',
+  email varchar(128) not null default '',
+  userlevel int(4) {UNSIGNED} not null default '0',
+  right_publish int(1) default '1'
+);
+
+#
+# table structure for table '{PREFIX}comments'
+#
+
+create table {PREFIX}comments (
+  id {AUTOINCREMENT} {PRIMARY},
+  entry_id int(10) {UNSIGNED} not null default '0',
+  parent_id int(10) {UNSIGNED} not null default '0',
+  timestamp int(10) {UNSIGNED} default null,
+  title varchar(150) default null,
+  author varchar(80) default null,
+  email varchar(200) default null,
+  url varchar(200) default null,
+  ip varchar(15) default null,
+  body text,
+  type varchar(100) default 'regular',
+  subscribed {BOOLEAN},
+  status varchar(50) not null,
+  referer varchar(200) default null
+);
+
+#
+# table structure for table '{PREFIX}entries'
+#
+
+create table {PREFIX}entries (
+  id {AUTOINCREMENT} {PRIMARY},
+  title varchar(200) default null,
+  timestamp int(10) {UNSIGNED} default null,
+  body text,
+  comments int(4) {UNSIGNED} default '0',
+  trackbacks int(4) {UNSIGNED} default '0',
+  extended text,
+  exflag int(1) default null,
+  author varchar(20) default null,
+  authorid int(11) default null,
+  isdraft {BOOLEAN},
+  allow_comments {BOOLEAN},
+  last_modified int(10) {UNSIGNED} default null,
+  moderate_comments {BOOLEAN}
+);
+
+# FULLTEXT_MYSQL is ignored on all Non-MySQL setups (SQLite, PostgreSQL)
+CREATE {FULLTEXT_MYSQL} INDEX entry_idx on {PREFIX}entries (title,body,extended);
+CREATE INDEX date_idx ON {PREFIX}entries (timestamp);
+CREATE INDEX mod_idx ON {PREFIX}entries (last_modified);
+
+#
+# table structure for table '{PREFIX}references'
+#
+
+create table {PREFIX}references (
+  id {AUTOINCREMENT} {PRIMARY},
+  entry_id int(10) {UNSIGNED} not null default '0',
+  link text,
+  name text
+);
+
+#
+# Table structure for table '{PREFIX}exits'
+#
+
+CREATE TABLE {PREFIX}exits (
+  entry_id int(11) NOT NULL default '0',
+  day date NOT NULL,
+  count int(11) NOT NULL default '0',
+  scheme varchar(5),
+  host varchar(128) NOT NULL,
+  port varchar(5),
+  path varchar(255),
+  query varchar(255),
+  PRIMARY KEY  (host,day,entry_id)
+);
+
+#
+# Table structure for table '{PREFIX}referrers'
+#
+
+CREATE TABLE {PREFIX}referrers (
+  entry_id int(11) NOT NULL default '0',
+  day date NOT NULL,
+  count int(11) NOT NULL default '0',
+  scheme varchar(5),
+  host varchar(128) NOT NULL,
+  port varchar(5),
+  path varchar(255),
+  query varchar(255),
+  PRIMARY KEY  (host,day,entry_id)
+);
+
+#
+# Table structure for table 'serendipity_config'
+#
+
+create table {PREFIX}config (
+  name varchar(255) not null,
+  value text not null,
+  authorid int(11) default '0'
+);
+
+CREATE INDEX configauthorid_idx ON {PREFIX}config (authorid);
+
+CREATE TABLE {PREFIX}suppress (
+  ip varchar(15) default NULL,
+  scheme varchar(5),
+  host varchar(128),
+  port varchar(5),
+  path varchar(255),
+  query varchar(255),
+  last timestamp NOT NULL
+);
+
+CREATE INDEX url_idx on {PREFIX}suppress (host, ip);
+
+CREATE TABLE {PREFIX}plugins (
+  name varchar(128) not null,
+  placement varchar(6) not null default 'right',
+  sort_order int(4) not null default '0',
+  authorid int(11) default '0',
+  path varchar(255) default null,
+  PRIMARY KEY(name)
+);
+
+CREATE INDEX pluginauthorid_idx ON {PREFIX}plugins (authorid);
+
+CREATE TABLE {PREFIX}category (
+  categoryid {AUTOINCREMENT} {PRIMARY},
+  category_name varchar(255) default NULL,
+  category_icon varchar(255) default NULL,
+  category_description text,
+  authorid int(11) default NULL,
+  category_left int(11) default '0',
+  category_right int(11) default '0',
+  parentid int(11) DEFAULT '0' NOT NULL
+);
+
+CREATE TABLE {PREFIX}images (
+  id {AUTOINCREMENT} {PRIMARY},
+  name varchar(255) not null default '',
+  extension varchar(5) not null default '',
+  mime varchar(255) not null default '',
+  size int(11) not null default '0',
+  dimensions_width int(11) not null default '0',
+  dimensions_height int(11) not null default '0',
+  date int(11) not null default '0',
+  thumbnail_name varchar(255) not null default '',
+  authorid int(11) default '0',
+  path text,
+  hotlink int(1)
+);
+
+CREATE INDEX imagesauthorid_idx ON {PREFIX}images (authorid);
+CREATE {FULLTEXT} INDEX pathkey_idx on {PREFIX}images (path);
+
+CREATE TABLE {PREFIX}entrycat (
+  entryid int(11) not null,
+  categoryid int(11) not null
+);
+
+CREATE UNIQUE INDEX entryid_idx ON {PREFIX}entrycat (entryid, categoryid);
+
+create table {PREFIX}entryproperties (
+  entryid int(11) not null,
+  property varchar(255) not null,
+  value text
+);
+
+CREATE INDEX entrypropid_idx ON {PREFIX}entryproperties (entryid);
+CREATE UNIQUE INDEX prop_idx ON {PREFIX}entryproperties (entryid, property);
diff --git a/sql/db_update_0.2_0.3_mysql.sql b/sql/db_update_0.2_0.3_mysql.sql
new file mode 100644 (file)
index 0000000..db3a20a
--- /dev/null
@@ -0,0 +1,17 @@
+ALTER TABLE {PREFIX}entries ADD COLUMN trackbacks INT(4) DEFAULT 0 AFTER `comments`;
+
+ALTER TABLE {PREFIX}entries ADD COLUMN isdraft ENUM('true', 'false') NOT NULL DEFAULT 'false' AFTER `categoryid`;
+
+ALTER TABLE {PREFIX}comments ADD COLUMN subscribed ENUM('true', 'false') NOT NULL DEFAULT 'false' AFTER `type`;
+
+INSERT INTO {PREFIX}config (name, value) VALUES ('allowSubscriptions', 'false');
+
+INSERT INTO {PREFIX}config (name, value) VALUES ('template', 'default');
+
+INSERT INTO {PREFIX}config (name, value) VALUES ('embed', 'false');
+
+INSERT INTO {PREFIX}config (name, value) VALUES ('indexFile', 'index.php');
+
+INSERT INTO {PREFIX}config (name, value) VALUES ('blockReferer', ';');
+
+INSERT INTO {PREFIX}config (name, value) VALUES ('XHTML11', 'false'); 
diff --git a/sql/db_update_0.2_0.3_postgres.sql b/sql/db_update_0.2_0.3_postgres.sql
new file mode 100644 (file)
index 0000000..941fea8
--- /dev/null
@@ -0,0 +1,17 @@
+ALTER TABLE {PREFIX}entries ADD COLUMN trackbacks INT(4) DEFAULT 0 AFTER `comments`;
+
+ALTER TABLE {PREFIX}entries ADD COLUMN isdraft BOOLEAN NOT NULL FALSE AFTER `categoryid`;
+
+ALTER TABLE {PREFIX}comments ADD COLUMN subscribed BOOLEAN NOT NULL AFTER `type`;
+
+INSERT INTO {PREFIX}config (name, value) VALUES ('allowSubscriptions', 'false');
+
+INSERT INTO {PREFIX}config (name, value) VALUES ('template', 'default');
+
+INSERT INTO {PREFIX}config (name, value) VALUES ('embed', 'false');
+
+INSERT INTO {PREFIX}config (name, value) VALUES ('indexFile', 'index.php');
+
+INSERT INTO {PREFIX}config (name, value) VALUES ('blockReferer', ';');
+
+INSERT INTO {PREFIX}config (name, value) VALUES ('XHTML11', 'false'); 
diff --git a/sql/db_update_0.3_0.4_mysql.sql b/sql/db_update_0.3_0.4_mysql.sql
new file mode 100644 (file)
index 0000000..02b6adc
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE {PREFIX}entries ADD COLUMN allow_comments ENUM('true', 'false') NOT NULL DEFAULT 'true' AFTER isdraft;
diff --git a/sql/db_update_0.3_0.4_postgres.sql b/sql/db_update_0.3_0.4_postgres.sql
new file mode 100644 (file)
index 0000000..9c351a7
--- /dev/null
@@ -0,0 +1,4 @@
+ALTER TABLE {PREFIX}entries ADD COLUMN allow_comments BOOLEAN;
+UPDATE {PREFIX}entries SET allow_comments=TRUE;
+ALTER TABLE {PREFIX}entries ALTER COLUMN allow_comments SET NOT NULL;
+ALTER TABLE {PREFIX}entries ALTER COLUMN allow_comments SET DEFAULT TRUE;
diff --git a/sql/db_update_0.5.1_0.6_mysql.sql b/sql/db_update_0.5.1_0.6_mysql.sql
new file mode 100644 (file)
index 0000000..3aa5569
--- /dev/null
@@ -0,0 +1,3 @@
+CREATE INDEX date_idx ON {PREFIX}entries (timestamp);
+
+CREATE INDEX mod_idx ON {PREFIX}entries (last_modified);
diff --git a/sql/db_update_0.5.1_0.6_postgres.sql b/sql/db_update_0.5.1_0.6_postgres.sql
new file mode 100644 (file)
index 0000000..3aa5569
--- /dev/null
@@ -0,0 +1,3 @@
+CREATE INDEX date_idx ON {PREFIX}entries (timestamp);
+
+CREATE INDEX mod_idx ON {PREFIX}entries (last_modified);
diff --git a/sql/db_update_0.5_0.5.1_mysql.sql b/sql/db_update_0.5_0.5.1_mysql.sql
new file mode 100644 (file)
index 0000000..60e0ee6
--- /dev/null
@@ -0,0 +1,34 @@
+CREATE TABLE `{PREFIX}images` (
+  `id` int(11) NOT NULL auto_increment,
+  `name` varchar(255) NOT NULL default '',
+  `extension` varchar(5) NOT NULL default '',
+  `mime` varchar(15) NOT NULL default '',
+  `size` int(11) NOT NULL default '0',
+  `dimensions_width` int(11) NOT NULL default '0',
+  `dimensions_height` int(11) NOT NULL default '0',
+  `thumbnail_name` varchar(255) NOT NULL default '',
+  `date` int(11) NOT NULL default '0',
+  PRIMARY KEY  (`id`)
+) TYPE=MyISAM;
+
+UPDATE {PREFIX}plugins
+   SET name = REPLACE(name, 'serendipity_plugin_content_rewrite', 'serendipity_event_contentrewrite')
+ WHERE name LIKE '%serendipity_plugin_content_rewrite%';
+
+UPDATE {PREFIX}config
+   SET name = REPLACE(name, 'serendipity_plugin_content_rewrite', 'serendipity_event_contentrewrite')
+ WHERE name LIKE '%serendipity_plugin_content_rewrite%';
+
+UPDATE {PREFIX}plugins
+   SET placement = 'event'
+ WHERE name LIKE '%serendipity_event_contentrewrite%';
+
+ALTER TABLE {PREFIX}entries ADD last_modified INT(10) UNSIGNED default null;
+CREATE INDEX date_idx ON {PREFIX}entries (timestamp);
+CREATE INDEX mod_idx ON {PREFIX}entries (last_modified);
+UPDATE {PREFIX}entries SET last_modified = timestamp;
+
+INSERT INTO {PREFIX}plugins(name, placement, sort_order) VALUES ('serendipity_event_nl2br:39979424fea674e78399659e67edaf12', 'event', 10);
+INSERT INTO {PREFIX}plugins(name, placement, sort_order) VALUES ('serendipity_event_s9ymarkup:fdd8bf23ff500827cf76d7d31957d3c8', 'event', 11);
+INSERT INTO {PREFIX}plugins(name, placement, sort_order) VALUES ('serendipity_event_emoticate:e30b433546aa10a632b0d703ebe1aa29', 'event', 12);
+INSERT INTO {PREFIX}plugins(name, placement, sort_order) VALUES ('serendipity_event_trackexits:25e6d8eb7d662936abb6454956aaa8ab', 'event', 13);
diff --git a/sql/db_update_0.5_0.5.1_postgres.sql b/sql/db_update_0.5_0.5.1_postgres.sql
new file mode 100644 (file)
index 0000000..67e8398
--- /dev/null
@@ -0,0 +1,34 @@
+CREATE TABLE {PREFIX}images (
+  id SERIAL primary key,
+  name varchar(255) NOT NULL default '',
+  extension varchar(5) NOT NULL default '',
+  mime varchar(15) NOT NULL default '',
+  size int NOT NULL default '0',
+  dimensions_width int NOT NULL default '0',
+  dimensions_height int NOT NULL default '0',
+  thumbnail_name varchar(255) NOT NULL default '',
+  date int NOT NULL default '0'
+);
+
+UPDATE {PREFIX}plugins
+   SET name = REPLACE(name, 'serendipity_plugin_content_rewrite', 'serendipity_event_contentrewrite')
+ WHERE name LIKE '%serendipity_plugin_content_rewrite%';
+
+UPDATE {PREFIX}config
+   SET name = REPLACE(name, 'serendipity_plugin_content_rewrite', 'serendipity_event_contentrewrite')
+ WHERE name LIKE '%serendipity_plugin_content_rewrite%';
+
+UPDATE {PREFIX}plugins
+   SET placement = 'event'
+ WHERE name LIKE '%serendipity_event_contentrewrite%';
+
+ALTER TABLE {PREFIX}entries ADD COLUMN last_modified INT;
+
+CREATE INDEX date_idx ON {PREFIX}entries (timestamp);
+CREATE INDEX mod_idx ON {PREFIX}entries (last_modified);
+UPDATE {PREFIX}entries SET last_modified = timestamp;
+
+INSERT INTO {PREFIX}plugins(name, placement, sort_order) VALUES ('serendipity_event_nl2br:39979424fea674e78399659e67edaf12', 'event', 10);
+INSERT INTO {PREFIX}plugins(name, placement, sort_order) VALUES ('serendipity_event_s9ymarkup:fdd8bf23ff500827cf76d7d31957d3c8', 'event', 11);
+INSERT INTO {PREFIX}plugins(name, placement, sort_order) VALUES ('serendipity_event_emoticate:e30b433546aa10a632b0d703ebe1aa29', 'event', 12);
+INSERT INTO {PREFIX}plugins(name, placement, sort_order) VALUES ('serendipity_event_trackexits:25e6d8eb7d662936abb6454956aaa8ab', 'event', 13);
diff --git a/sql/db_update_0.6.10_0.6.11_mysql.sql b/sql/db_update_0.6.10_0.6.11_mysql.sql
new file mode 100644 (file)
index 0000000..b4d32ba
--- /dev/null
@@ -0,0 +1 @@
+DROP TABLE {PREFIX}css
diff --git a/sql/db_update_0.6.10_0.6.11_postgres.sql b/sql/db_update_0.6.10_0.6.11_postgres.sql
new file mode 100644 (file)
index 0000000..b4d32ba
--- /dev/null
@@ -0,0 +1 @@
+DROP TABLE {PREFIX}css
diff --git a/sql/db_update_0.6.1_0.6.2_mysql.sql b/sql/db_update_0.6.1_0.6.2_mysql.sql
new file mode 100644 (file)
index 0000000..8a8b5a3
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE {PREFIX}category ADD COLUMN category_icon varchar(255) DEFAULT NULL after `category_name`;
diff --git a/sql/db_update_0.6.1_0.6.2_postgres.sql b/sql/db_update_0.6.1_0.6.2_postgres.sql
new file mode 100644 (file)
index 0000000..66586ae
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE {PREFIX}category ADD COLUMN category_icon varchar(255);
diff --git a/sql/db_update_0.6.2_0.6.3_mysql.sql b/sql/db_update_0.6.2_0.6.3_mysql.sql
new file mode 100644 (file)
index 0000000..84de077
--- /dev/null
@@ -0,0 +1,2 @@
+ALTER TABLE {PREFIX}images ADD COLUMN path text;
+CREATE {FULLTEXT} INDEX pathkey_idx on {PREFIX}images (path);
diff --git a/sql/db_update_0.6.2_0.6.3_postgres.sql b/sql/db_update_0.6.2_0.6.3_postgres.sql
new file mode 100644 (file)
index 0000000..95ad1a7
--- /dev/null
@@ -0,0 +1,4 @@
+ALTER TABLE {PREFIX}images ADD COLUMN path text;
+ALTER TABLE {PREFIX}images ALTER COLUMN path SET DEFAULT '/';
+UPDATE {PREFIX}images SET path = '/';
+CREATE {FULLTEXT} INDEX pathkey_idx on {PREFIX}images (path);
diff --git a/sql/db_update_0.6.3_0.6.4_mysql.sql b/sql/db_update_0.6.3_0.6.4_mysql.sql
new file mode 100644 (file)
index 0000000..9e71c5e
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE {PREFIX}authors ADD right_publish INT(1) DEFAULT '1';
diff --git a/sql/db_update_0.6.3_0.6.4_postgres.sql b/sql/db_update_0.6.3_0.6.4_postgres.sql
new file mode 100644 (file)
index 0000000..dc5ad12
--- /dev/null
@@ -0,0 +1,3 @@
+ALTER TABLE {PREFIX}authors ADD COLUMN right_publish int2;
+ALTER TABLE {PREFIX}authors ALTER COLUMN right_publish SET DEFAULT '1';
+UPDATE {PREFIX}authors SET right_publish=1;
diff --git a/sql/db_update_0.6.4_0.6.5_mysql.sql b/sql/db_update_0.6.4_0.6.5_mysql.sql
new file mode 100644 (file)
index 0000000..638f7d1
--- /dev/null
@@ -0,0 +1,15 @@
+ALTER TABLE {PREFIX}category
+  ADD parentid INT(11) DEFAULT '0' NOT NULL,
+  ADD category_left INT(11) DEFAULT '0' NOT NULL,
+  ADD category_right INT(11) DEFAULT '0' NOT NULL;
+
+create table {PREFIX}entrycat (
+  entryid int(11) not null,
+  categoryid int(11) not null
+);
+
+INSERT INTO {PREFIX}entrycat (entryid, categoryid) SELECT id, categoryid FROM {PREFIX}entries;
+
+ALTER TABLE {PREFIX}entries DROP categoryid;
+
+ALTER TABLE {PREFIX}comments ADD parent_id int(10) {UNSIGNED} default '0' not null;
diff --git a/sql/db_update_0.6.4_0.6.5_postgres.sql b/sql/db_update_0.6.4_0.6.5_postgres.sql
new file mode 100644 (file)
index 0000000..eb94f2e
--- /dev/null
@@ -0,0 +1,21 @@
+ALTER TABLE {PREFIX}category ADD COLUMN parentid INT4;
+ALTER TABLE {PREFIX}category ADD COLUMN category_left INT4;
+ALTER TABLE {PREFIX}category ADD COLUMN category_right INT4;
+UPDATE {PREFIX}category SET parentid=0, category_left=0, category_right=0;
+
+ALTER TABLE {PREFIX}category ALTER COLUMN parentid SET NOT NULL;
+ALTER TABLE {PREFIX}category ALTER COLUMN category_left SET NOT NULL;
+ALTER TABLE {PREFIX}category ALTER COLUMN category_right SET NOT NULL;
+
+CREATE TABLE {PREFIX}entrycat (
+  entryid int4 not null,
+  categoryid int4 not null
+);
+
+INSERT INTO {PREFIX}entrycat (entryid, categoryid)  (SELECT id, categoryid FROM {PREFIX}entries);
+
+ALTER TABLE {PREFIX}entries DROP COLUMN categoryid;
+
+ALTER TABLE {PREFIX}comments ADD COLUMN parent_id int4;
+UPDATE {PREFIX}comments SET parent_id=0;
+ALTER TABLE {PREFIX}comments ALTER COLUMN parent_id SET NOT NULL;
diff --git a/sql/db_update_0.6.5_0.6.6_mysql.sql b/sql/db_update_0.6.5_0.6.6_mysql.sql
new file mode 100644 (file)
index 0000000..b1562c6
--- /dev/null
@@ -0,0 +1 @@
+CREATE UNIQUE INDEX entryid_idx ON {PREFIX}entrycat (entryid, categoryid);
diff --git a/sql/db_update_0.6.5_0.6.6_postgres.sql b/sql/db_update_0.6.5_0.6.6_postgres.sql
new file mode 100644 (file)
index 0000000..b1562c6
--- /dev/null
@@ -0,0 +1 @@
+CREATE UNIQUE INDEX entryid_idx ON {PREFIX}entrycat (entryid, categoryid);
diff --git a/sql/db_update_0.6.6_0.6.7_mysql.sql b/sql/db_update_0.6.6_0.6.7_mysql.sql
new file mode 100644 (file)
index 0000000..7fbee92
--- /dev/null
@@ -0,0 +1,3 @@
+ALTER TABLE `{PREFIX}entries` ADD `moderate_comments` ENUM('true','false') DEFAULT 'false' NOT NULL AFTER `allow_comments`;
+ALTER TABLE `{PREFIX}comments` ADD `status` VARCHAR( 50 ) NOT NULL AFTER `subscribed` ;
+UPDATE {PREFIX}comments SET status = 'approved';
diff --git a/sql/db_update_0.6.6_0.6.7_postgres.sql b/sql/db_update_0.6.6_0.6.7_postgres.sql
new file mode 100644 (file)
index 0000000..2548044
--- /dev/null
@@ -0,0 +1,7 @@
+ALTER TABLE {PREFIX}entries ADD COLUMN moderate_comments BOOLEAN;
+ALTER TABLE {PREFIX}comments ADD COLUMN status varchar(50);
+UPDATE {PREFIX}comments SET status = 'approved';
+UPDATE {PREFIX}entries SET moderate_comments = false;
+ALTER TABLE {PREFIX}entries ALTER COLUMN moderate_comments SET NOT NULL;
+ALTER TABLE {PREFIX}comments ALTER COLUMN status SET NOT NULL;
+
diff --git a/sql/db_update_0.6.8_0.6.9_mysql.sql b/sql/db_update_0.6.8_0.6.9_mysql.sql
new file mode 100644 (file)
index 0000000..e990f50
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE {PREFIX}images CHANGE mime mime VARCHAR(255) NOT NULL default '';
diff --git a/sql/db_update_0.6.8_0.6.9_postgres.sql b/sql/db_update_0.6.8_0.6.9_postgres.sql
new file mode 100644 (file)
index 0000000..e2118ad
--- /dev/null
@@ -0,0 +1,9 @@
+ALTER TABLE {PREFIX}images ADD COLUMN oldmime varchar(15);
+UPDATE {PREFIX}images SET oldmime = mime;
+ALTER TABLE {PREFIX}images DROP mime;
+
+ALTER TABLE {PREFIX}images ADD COLUMN mime varchar(255);
+UPDATE {PREFIX}images SET mime = oldmime;
+ALTER TABLE {PREFIX}images DROP COLUMN oldmime;
+ALTER TABLE {PREFIX}images ALTER COLUMN mime SET NOT NULL;
+
diff --git a/sql/db_update_0.6.9_0.7.0_mysql.sql b/sql/db_update_0.6.9_0.7.0_mysql.sql
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/sql/db_update_0.6.9_0.7.0_postgresql.sql b/sql/db_update_0.6.9_0.7.0_postgresql.sql
new file mode 100644 (file)
index 0000000..b8ad361
--- /dev/null
@@ -0,0 +1,2 @@
+DROP INDEX entry_idx;
+CREATE INDEX entry_idx ON {PREFIX}_entries(title);
diff --git a/sql/db_update_0.6_0.6.1_mysql.sql b/sql/db_update_0.6_0.6.1_mysql.sql
new file mode 100644 (file)
index 0000000..7fc9073
--- /dev/null
@@ -0,0 +1,15 @@
+ALTER TABLE {PREFIX}authors ADD userlevel INT(4) UNSIGNED DEFAULT '0';
+UPDATE {PREFIX}authors SET userlevel = 255 WHERE authorid = 1;
+UPDATE {PREFIX}authors SET userlevel = 1 WHERE authorid > 1;
+
+ALTER TABLE {PREFIX}config  ADD authorid  INT UNSIGNED NOT NULL DEFAULT '0';
+CREATE INDEX configauthorid_idx ON {PREFIX}config (authorid);
+
+ALTER TABLE {PREFIX}config  DROP PRIMARY KEY;
+ALTER TABLE {PREFIX}config  ADD PRIMARY KEY (name, authorid);
+
+ALTER TABLE {PREFIX}plugins  ADD authorid  INT UNSIGNED DEFAULT '0';
+CREATE INDEX pluginauthorid_idx ON {PREFIX}plugins (authorid);
+
+ALTER TABLE {PREFIX}images  ADD authorid  INT UNSIGNED DEFAULT '0';
+CREATE INDEX imagesauthorid_idx ON {PREFIX}images (authorid);
diff --git a/sql/db_update_0.6_0.6.1_postgres.sql b/sql/db_update_0.6_0.6.1_postgres.sql
new file mode 100644 (file)
index 0000000..63be745
--- /dev/null
@@ -0,0 +1,22 @@
+
+ALTER TABLE {PREFIX}authors ADD COLUMN userlevel SMALLINT;
+ALTER TABLE {PREFIX}authors ALTER COLUMN userlevel SET DEFAULT '0';
+UPDATE {PREFIX}authors SET userlevel = 255 WHERE authorid = 1;
+UPDATE {PREFIX}authors SET userlevel = 1 WHERE authorid > 1;
+
+ALTER TABLE {PREFIX}config  ADD COLUMN authorid  INT;
+UPDATE {PREFIX}config SET authorid=0;
+ALTER TABLE {PREFIX}config  ALTER COLUMN authorid SET NOT NULL;
+ALTER TABLE {PREFIX}config  ALTER COLUMN authorid SET DEFAULT '0';
+CREATE INDEX configauthorid_idx ON {PREFIX}config (authorid);
+
+ALTER TABLE {PREFIX}config  DROP CONSTRAINT {PREFIX}config_pkey;
+ALTER TABLE {PREFIX}config  ADD PRIMARY KEY (name, authorid);
+
+ALTER TABLE {PREFIX}plugins  ADD COLUMN authorid  INT;
+ALTER TABLE {PREFIX}plugins  ALTER COLUMN authorid SET DEFAULT '0';
+CREATE INDEX pluginsauthorid_idx ON {PREFIX}plugins (authorid);
+
+ALTER TABLE {PREFIX}images  ADD COLUMN authorid  INT;
+ALTER TABLE {PREFIX}images  ALTER COLUMN authorid SET DEFAULT '0';
+CREATE INDEX imagesauthorid_idx ON {PREFIX}images (authorid);
diff --git a/sql/db_update_0.8-alpha10_0.8-alpha11_mysql.sql b/sql/db_update_0.8-alpha10_0.8-alpha11_mysql.sql
new file mode 100644 (file)
index 0000000..b6898d6
--- /dev/null
@@ -0,0 +1,7 @@
+@CREATE {FULLTEXT_MYSQL} INDEX entry_idx ON {PREFIX}entries (title,body,extended);
+@CREATE INDEX date_idx ON {PREFIX}entries (timestamp);
+@CREATE INDEX mod_idx ON {PREFIX}entries (last_modified);
+@CREATE INDEX configauthorid_idx ON {PREFIX}config (authorid);
+@CREATE INDEX pluginauthorid_idx ON {PREFIX}plugins (authorid);
+@CREATE INDEX imagesauthorid_idx ON {PREFIX}images (authorid);
+@CREATE INDEX entrypropid_idx ON {PREFIX}entryproperties (entryid);
diff --git a/sql/db_update_0.8-alpha11_0.8-alpha12_mysql.sql b/sql/db_update_0.8-alpha11_0.8-alpha12_mysql.sql
new file mode 100644 (file)
index 0000000..fffdfe9
--- /dev/null
@@ -0,0 +1,2 @@
+ALTER TABLE {PREFIX}authors ADD realname VARCHAR( 255 ) NOT NULL FIRST;
+UPDATE {PREFIX}authors SET realname = username;
diff --git a/sql/db_update_0.8-alpha11_0.8-alpha12_postgres.sql b/sql/db_update_0.8-alpha11_0.8-alpha12_postgres.sql
new file mode 100644 (file)
index 0000000..232ec34
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE {PREFIX}authors ADD COLUMN realname varchar(255);
diff --git a/sql/db_update_0.8-alpha11_0.8-alpha12_sqlite.sql b/sql/db_update_0.8-alpha11_0.8-alpha12_sqlite.sql
new file mode 100644 (file)
index 0000000..525f8d4
--- /dev/null
@@ -0,0 +1,31 @@
+create table {PREFIX}tempauthors (
+  realname varchar(255) NOT NULL default '',
+  username varchar(20) default null,
+  password varchar(32) default null,
+  authorid {AUTOINCREMENT} {PRIMARY},
+  mail_comments int(1) default '1',
+  mail_trackbacks int(1) default '1',
+  email varchar(128) not null default '',
+  userlevel int(4) {UNSIGNED} not null default '0',
+  right_publish int(1) default '1'
+);
+
+INSERT INTO {PREFIX}tempauthors (username, password, authorid, mail_comments, mail_trackbacks, email, userlevel, right_publish) SELECT username, password, authorid, mail_comments, mail_trackbacks, email, userlevel, right_publish FROM {PREFIX}authors;
+DROP TABLE {PREFIX}authors;
+
+create table {PREFIX}authors (
+  realname varchar(255) NOT NULL default '',
+  username varchar(20) default null,
+  password varchar(32) default null,
+  authorid {AUTOINCREMENT} {PRIMARY},
+  mail_comments int(1) default '1',
+  mail_trackbacks int(1) default '1',
+  email varchar(128) not null default '',
+  userlevel int(4) {UNSIGNED} not null default '0',
+  right_publish int(1) default '1'
+);
+
+INSERT INTO {PREFIX}authors (username, password, authorid, mail_comments, mail_trackbacks, email, userlevel, right_publish) SELECT username, password, authorid, mail_comments, mail_trackbacks, email, userlevel, right_publish FROM {PREFIX}tempauthors;
+DROP TABLE {PREFIX}tempauthors;
+
+UPDATE {PREFIX}authors SET realname = username;
\ No newline at end of file
diff --git a/sql/db_update_0.8-alpha12_0.8-alpha13_mysql.sql b/sql/db_update_0.8-alpha12_0.8-alpha13_mysql.sql
new file mode 100644 (file)
index 0000000..89294c9
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE {PREFIX}images ADD hotlink INT(1);
diff --git a/sql/db_update_0.8-alpha12_0.8-alpha13_postgres.sql b/sql/db_update_0.8-alpha12_0.8-alpha13_postgres.sql
new file mode 100644 (file)
index 0000000..47d95f5
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE {PREFIX}images ADD COLUMN hotlink INT2;
diff --git a/sql/db_update_0.8-alpha12_0.8-alpha13_sqlite.sql b/sql/db_update_0.8-alpha12_0.8-alpha13_sqlite.sql
new file mode 100644 (file)
index 0000000..6ea1809
--- /dev/null
@@ -0,0 +1,35 @@
+CREATE TABLE {PREFIX}tempimages (
+  id {AUTOINCREMENT} {PRIMARY},
+  name varchar(255) not null default '',
+  extension varchar(5) not null default '',
+  mime varchar(255) not null default '',
+  size int(11) not null default '0',
+  dimensions_width int(11) not null default '0',
+  dimensions_height int(11) not null default '0',
+  date int(11) not null default '0',
+  thumbnail_name varchar(255) not null default '',
+  authorid int(11) default '0',
+  path text,
+  hotlink int(1)
+);
+
+INSERT INTO {PREFIX}tempimages (id, name, extension, mime, size, dimensions_width, dimensions_height, date, thumbnail_name, authorid, path) SELECT id, name, extension, mime, size, dimensions_width, dimensions_height, date, thumbnail_name, authorid, path FROM {PREFIX}images;
+DROP TABLE {PREFIX}images;
+
+CREATE TABLE {PREFIX}images (
+  id {AUTOINCREMENT} {PRIMARY},
+  name varchar(255) not null default '',
+  extension varchar(5) not null default '',
+  mime varchar(255) not null default '',
+  size int(11) not null default '0',
+  dimensions_width int(11) not null default '0',
+  dimensions_height int(11) not null default '0',
+  date int(11) not null default '0',
+  thumbnail_name varchar(255) not null default '',
+  authorid int(11) default '0',
+  path text,
+  hotlink int(1)
+);
+
+INSERT INTO {PREFIX}images (id, name, extension, mime, size, dimensions_width, dimensions_height, date, thumbnail_name, authorid, path) SELECT id, name, extension, mime, size, dimensions_width, dimensions_height, date, thumbnail_name, authorid, path FROM {PREFIX}tempimages;
+DROP TABLE {PREFIX}tempimages;
diff --git a/sql/db_update_0.8-alpha1_0.8-alpha2_mysql.sql b/sql/db_update_0.8-alpha1_0.8-alpha2_mysql.sql
new file mode 100644 (file)
index 0000000..da4a342
--- /dev/null
@@ -0,0 +1,8 @@
+create table {PREFIX}entryproperties (
+  entryid int(11) not null,
+  property varchar(255) not null,
+  value text
+);
+
+CREATE UNIQUE INDEX prop_idx ON {PREFIX}entryproperties (entryid, property);
+CREATE INDEX entrypropid_idx ON {PREFIX}entryproperties (entryid);
diff --git a/sql/db_update_0.8-alpha4_0.8-alpha5_mysql.sql b/sql/db_update_0.8-alpha4_0.8-alpha5_mysql.sql
new file mode 100644 (file)
index 0000000..60f49fb
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE {PREFIX}comments ADD referer varchar(200) default null;
diff --git a/sql/db_update_0.8-alpha4_0.8-alpha5_postgres.sql b/sql/db_update_0.8-alpha4_0.8-alpha5_postgres.sql
new file mode 100644 (file)
index 0000000..b029119
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE {PREFIX}comments ADD COLUMN referer varchar(200);
\ No newline at end of file
diff --git a/sql/db_update_0.8-alpha4_0.8-alpha5_sqlite.sql b/sql/db_update_0.8-alpha4_0.8-alpha5_sqlite.sql
new file mode 100644 (file)
index 0000000..022a00a
--- /dev/null
@@ -0,0 +1,38 @@
+create table {PREFIX}tempcomments (
+  id {AUTOINCREMENT} {PRIMARY},
+  entry_id int(10) {UNSIGNED} not null default '0',
+  parent_id int(10) {UNSIGNED} not null default '0',
+  timestamp int(10) {UNSIGNED} default null,
+  title varchar(150) default null,
+  author varchar(80) default null,
+  email varchar(200) default null,
+  url varchar(200) default null,
+  ip varchar(15) default null,
+  body text,
+  type varchar(100) default 'regular',
+  subscribed {BOOLEAN},
+  status varchar(50) not null
+);
+
+INSERT INTO {PREFIX}tempcomments (id, entry_id, parent_id, timestamp, title, author, email, url, ip, body, type, subscribed, status) SELECT id, entry_id, parent_id, timestamp, title, author, email, url, ip, body, type, subscribed, status FROM {PREFIX}comments;
+DROP TABLE {PREFIX}comments;
+
+create table {PREFIX}comments (
+  id {AUTOINCREMENT} {PRIMARY},
+  entry_id int(10) {UNSIGNED} not null default '0',
+  parent_id int(10) {UNSIGNED} not null default '0',
+  timestamp int(10) {UNSIGNED} default null,
+  title varchar(150) default null,
+  author varchar(80) default null,
+  email varchar(200) default null,
+  url varchar(200) default null,
+  ip varchar(15) default null,
+  body text,
+  type varchar(100) default 'regular',
+  subscribed {BOOLEAN},
+  status varchar(50) not null,
+  referer varchar(200) default null
+);
+
+INSERT INTO {PREFIX}comments (id, entry_id, parent_id, timestamp, title, author, email, url, ip, body, type, subscribed, status) SELECT id, entry_id, parent_id, timestamp, title, author, email, url, ip, body, type, subscribed, status FROM {PREFIX}tempcomments;
+DROP TABLE {PREFIX}tempcomments;
diff --git a/sql/db_update_0.8-alpha5_0.8-alpha6_mysql.sql b/sql/db_update_0.8-alpha5_0.8-alpha6_mysql.sql
new file mode 100644 (file)
index 0000000..96a48a0
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE {PREFIX}plugins ADD path varchar(255) default null;
diff --git a/sql/db_update_0.8-alpha5_0.8-alpha6_postgres.sql b/sql/db_update_0.8-alpha5_0.8-alpha6_postgres.sql
new file mode 100644 (file)
index 0000000..72767c5
--- /dev/null
@@ -0,0 +1 @@
+ALTER TABLE {PREFIX}plugins ADD COLUMN path varchar(255);
diff --git a/sql/db_update_0.8-alpha5_0.8-alpha6_sqlite.sql b/sql/db_update_0.8-alpha5_0.8-alpha6_sqlite.sql
new file mode 100644 (file)
index 0000000..b22f3aa
--- /dev/null
@@ -0,0 +1,22 @@
+create table {PREFIX}tempplugins (
+  name varchar(128) not null,
+  placement varchar(6) not null default 'right',
+  sort_order int(4) not null default '0',
+  authorid int(11) default '0',
+  PRIMARY KEY(name)
+);
+
+INSERT INTO {PREFIX}tempplugins (name, placement, sort_order, authorid) SELECT name, placement, sort_order, authorid FROM {PREFIX}plugins;
+DROP TABLE {PREFIX}plugins;
+
+create table {PREFIX}plugins (
+  name varchar(128) not null,
+  placement varchar(6) not null default 'right',
+  sort_order int(4) not null default '0',
+  authorid int(11) default '0',
+  path varchar(255) default null,
+  PRIMARY KEY(name)
+);
+
+INSERT INTO {PREFIX}plugins (name, placement, sort_order, authorid) SELECT name, placement, sort_order, authorid FROM {PREFIX}tempplugins;
+DROP TABLE {PREFIX}tempplugins;
diff --git a/sql/db_update_0.8-beta3_0.8-beta4_mysql.sql b/sql/db_update_0.8-beta3_0.8-beta4_mysql.sql
new file mode 100644 (file)
index 0000000..4f755d8
--- /dev/null
@@ -0,0 +1 @@
+@ALTER TABLE {PREFIX}comments DROP INDEX body_idx;
diff --git a/sql/db_update_0.8-beta3_0.8-beta4_postgres.sql b/sql/db_update_0.8-beta3_0.8-beta4_postgres.sql
new file mode 100644 (file)
index 0000000..36a01e5
--- /dev/null
@@ -0,0 +1 @@
+@DROP INDEX body_idx;
diff --git a/sql/db_update_0.8-beta3_0.8-beta4_sqlite.sql b/sql/db_update_0.8-beta3_0.8-beta4_sqlite.sql
new file mode 100644 (file)
index 0000000..36a01e5
--- /dev/null
@@ -0,0 +1 @@
+@DROP INDEX body_idx;
diff --git a/sql/db_update_0.8-beta5_0.8-beta6_mysql.sql b/sql/db_update_0.8-beta5_0.8-beta6_mysql.sql
new file mode 100644 (file)
index 0000000..7411113
--- /dev/null
@@ -0,0 +1,2 @@
+@ALTER TABLE {PREFIX}suppress DROP INDEX url_idx;
+CREATE INDEX url_idx on {PREFIX}suppress (host, ip);
diff --git a/sql/db_update_0.8-beta5_0.8-beta6_postgres.sql b/sql/db_update_0.8-beta5_0.8-beta6_postgres.sql
new file mode 100644 (file)
index 0000000..f5fbc5d
--- /dev/null
@@ -0,0 +1,2 @@
+@DROP INDEX url_idx;
+CREATE INDEX url_idx on {PREFIX}suppress (host, ip);
diff --git a/sql/db_update_0.8-beta5_0.8-beta6_sqlite.sql b/sql/db_update_0.8-beta5_0.8-beta6_sqlite.sql
new file mode 100644 (file)
index 0000000..f5fbc5d
--- /dev/null
@@ -0,0 +1,2 @@
+@DROP INDEX url_idx;
+CREATE INDEX url_idx on {PREFIX}suppress (host, ip);
diff --git a/templates/HOWTO b/templates/HOWTO
new file mode 100644 (file)
index 0000000..7e9bfb5
--- /dev/null
@@ -0,0 +1 @@
+Please read our detailed information on http://www.s9y.org/44.html
\ No newline at end of file
diff --git a/templates/blue/htmlarea.css b/templates/blue/htmlarea.css
new file mode 100644 (file)
index 0000000..0e0507b
--- /dev/null
@@ -0,0 +1,44 @@
+body {
+  background-color: #e6eaee;
+  padding-left: 20px;
+  padding-right: 20px;
+  padding-bottom: 10px;
+  color: #000000;
+  font-family: sans-serif;
+  line-height: 20px;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 9pt;
+}
+
diff --git a/templates/blue/info.txt b/templates/blue/info.txt
new file mode 100644 (file)
index 0000000..fe794c3
--- /dev/null
@@ -0,0 +1,3 @@
+Name: blue
+Author: Sebastian Bergmann
+Date: 16/02/2004
diff --git a/templates/blue/preview.png b/templates/blue/preview.png
new file mode 100644 (file)
index 0000000..fa4c475
Binary files /dev/null and b/templates/blue/preview.png differ
diff --git a/templates/blue/style.css b/templates/blue/style.css
new file mode 100644 (file)
index 0000000..10305a2
--- /dev/null
@@ -0,0 +1,341 @@
+a, a:visited {
+  color: #993300;
+  text-decoration: none;
+}
+
+a:hover {
+  color: #cc3300;
+  text-decoration: underline;
+}
+
+body {
+  background-color: #f0f0f0;
+  color: #000000;
+  font-family: sans-serif;
+  line-height: 20px;
+  margin-left: 0px;
+  margin-right: 0px;
+  margin-top: 0px;
+  margin-bottom: 0px;
+}
+
+p, td, th, div, span {
+  vertical-align: top;
+}
+
+#content {
+  width: auto;
+}
+
+#mainpane {
+  width: 100%;
+}
+
+#serendipity_banner {
+  background-color: #dddddd;
+  border-bottom: dashed 1px #000080;
+  width: 100%;
+}
+
+a.homelink1,
+a.homelink1:hover,
+a.homelink1:link,
+a.homelink1:visited,
+#serendipity_banner h1 {
+  color: #666666;
+  font-size: x-large;
+  font-weight: bold;
+  margin-top: 0px;
+  padding-left: 20px;
+  padding-top: 5px;
+  text-decoration: none;
+}
+
+a.homelink2,
+a.homelink2:hover,
+a.homelink2:link,
+a.homelink2:visited,
+#serendipity_banner h2 {
+  color: #aaaaaa;
+  font-size: large;
+  font-weight: bold;
+  padding-left: 20px;
+  text-decoration: none;
+}
+
+#serendipityRightSideBar {
+  background-color: #f0f0f0;
+  border-left: 1px dashed #4068ab;
+  border-bottom: 1px dashed #4068ab;
+  padding: 20px;
+  vertical-align: top;
+}
+
+#serendipityLeftSideBar {
+  background-color: #f0f0f0;
+  border-right: 1px dashed #4068ab;
+  border-bottom: 1px dashed #4068ab;
+  padding: 20px;
+  vertical-align: top;
+}
+
+div.serendipitySideBarTitle {
+  font-size: small;
+  font-weight: bold;
+  margin-bottom: 8px;
+}
+
+div.serendipitySideBarItem {
+  background-color: #e6eaee;
+  border: 1px dashed #d0d0d0;
+  font-size: x-small;
+  margin-bottom: 12px;
+  padding-left: 10px;
+  padding-right: 10px;
+  padding-bottom: 10px;
+}
+
+.serendipity_entry {
+  background-color: #e6eaee;
+  display: block;
+  padding-left: 20px;
+  padding-right: 20px;
+  padding-bottom: 10px;
+}
+
+div.serendipity_Entry_Date {
+  background-color: #e6eaee;
+  border: 1px dashed #d0d0d0;
+  margin: 10px;
+  padding: 10px;
+  width: auto;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+.serendipity_title {
+  border: 1px;
+  color: #1a3c5a;
+  font-weight: bold;
+  margin-bottom: 8px;
+  margin-top: 8px;
+  padding-left: 20px;
+}
+
+.serendipity_title a:link,
+.serendipity_title a:visited {
+  border: 0;
+  color: #000000;
+  text-decoration: none;
+}
+
+.serendipity_title a:hover {
+  color: #cc3300;
+}
+
+.serendipity_date {
+  color: #000080;
+  display: block;
+  font-weight: bold;
+  text-align: right;
+  width: 100%;
+}
+
+.serendipity_commentsTitle {
+  background-color: #f2f4f6;
+  border: 0px;
+  color: #404040;
+  display: block;
+  font-size: small;
+  padding-left:8px;
+  width: 100%;
+}
+
+.serendipity_time {
+  display: block;
+  font-size: large;
+  font-weight: bold;
+  margin-top: 8px;
+}
+
+td.serendipity_commentsLabel {
+  font-size: small;
+  font-weight: bold;
+  vertical-align: top;
+  width: 10%;
+}
+
+td.serendipity_comment {
+  color: #404040;
+  font-size: small;
+  margin-bottom: 12px;
+  padding-left:8px;
+}
+
+.serendipity_comment_source {
+  margin-top: 5px;
+}
+
+.serendipity_comment {
+  padding-top: 1em;
+  overflow: auto;
+}
+
+td.serendipityEntriesBox {
+  background-color: #ffffff;
+  padding: 10px;
+  margin: 10px;
+}
+
+td.serendipity_admin {
+  padding: 10px;
+}
+
+table.serendipity_calendar td {
+  font-size: small;
+  padding: 3px;
+}
+
+table.serendipity_calendar a {
+  font-weight: bold;
+  text-decoration:none;
+}
+
+table.serendipity_calendar a:hover {
+  text-decoration:underline;
+}
+
+td.serendipity_weekDayName {
+  background-color: #dddddd;
+  font-size: small;
+  font-weight: bold;
+}
+
+div.serendipityPlug, div.serendipityPlug a {
+  font-size: small;
+}
+
+img.serendipityImageButton {
+  cursor: hand;
+}
+
+div.serendipity_admin_title {
+  font-size: large;
+  font-weight: bold;
+  margin-bottom: 12px;
+}
+
+div.serendipity_admin_list_title {
+  font-weight: bold;
+  margin-bottom: 8px;
+}
+
+td.serendipity_admin_list_item {
+  border: dotted 1px #d0d0d0;
+}
+
+div.serendipity_entryFooter {
+  clear: both;
+  color: #000000;
+  font-size: x-small;
+  padding-top: 5px;
+  padding-bottom: 4px;
+}
+
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+    margin: 0px;
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+    text-align: center;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 9pt;
+    text-align: center;
+}
+
+.serendipity_admin_list_item_even {
+    background-color: #ffffff;
+}
+
+.serendipity_admin_list_item_uneven {
+    background-color: #E0E0E0;
+}
+
+.serendipity_admin_filters {
+    border: 1px dashed;
+    background-color: #FFFFFF;
+    font-size: 10px;
+    margin-bottom: 10px;
+    padding: 2px;
+}
+
+.serendipity_admin_filters_headline {
+    border-bottom: 1px solid;
+    font-weight: bold;
+}
+
+.serendipity_admin_sortorder {
+    font-size: 10px;
+    text-align: center;
+}
+
+.serendipity_admin_sortorder input,
+.serendipity_admin_sortorder select,
+.serendipity_admin_filters input,
+.serendipity_admin_filters select {
+    font-size: 10px;
+}
+
+.serendipity_comments {
+}
+
+.serendipity_center {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center;
+}
+
+.serendipity_msg_important {
+    color: red;
+}
+
+.serendipity_msg_notice {
+    color: green;
+}
+
+.serendipity_entry_author_self {
+}
+
+.serendipity_comment_author_self {
+    background-color: #f2f4f6;
+}
diff --git a/templates/default-rtl/admin/img/background.jpg b/templates/default-rtl/admin/img/background.jpg
new file mode 100644 (file)
index 0000000..7635ca9
Binary files /dev/null and b/templates/default-rtl/admin/img/background.jpg differ
diff --git a/templates/default-rtl/admin/img/banner_background.png b/templates/default-rtl/admin/img/banner_background.png
new file mode 100644 (file)
index 0000000..ae06c20
Binary files /dev/null and b/templates/default-rtl/admin/img/banner_background.png differ
diff --git a/templates/default-rtl/admin/img/button_background.png b/templates/default-rtl/admin/img/button_background.png
new file mode 100644 (file)
index 0000000..d48532b
Binary files /dev/null and b/templates/default-rtl/admin/img/button_background.png differ
diff --git a/templates/default-rtl/admin/img/infobar_background.png b/templates/default-rtl/admin/img/infobar_background.png
new file mode 100644 (file)
index 0000000..09c9077
Binary files /dev/null and b/templates/default-rtl/admin/img/infobar_background.png differ
diff --git a/templates/default-rtl/admin/img/menu_background.png b/templates/default-rtl/admin/img/menu_background.png
new file mode 100644 (file)
index 0000000..1569837
Binary files /dev/null and b/templates/default-rtl/admin/img/menu_background.png differ
diff --git a/templates/default-rtl/admin/img/menuheader_background.png b/templates/default-rtl/admin/img/menuheader_background.png
new file mode 100644 (file)
index 0000000..998597b
Binary files /dev/null and b/templates/default-rtl/admin/img/menuheader_background.png differ
diff --git a/templates/default-rtl/admin/style.css b/templates/default-rtl/admin/style.css
new file mode 100644 (file)
index 0000000..14073f9
--- /dev/null
@@ -0,0 +1,252 @@
+body {
+    font-family: Tahoma, Verdana;
+    margin: 0 0 0 0;
+    background: #7F9BC2 url({TEMPLATE_PATH}img/background.jpg) repeat-x;
+    direction: {LANG_DIRECTION};
+}
+
+#serendipity_admin_page {
+    text-align: center;
+}
+
+#serendipityAdminBodyImageSelector {
+    background: #FFF;
+}
+
+#serendipityAdminFrame {
+    text-align: right;
+    width: 80%;
+    min-width: 777px;
+    margin: auto;
+    background: #FFF;
+    border: 2px solid #0F3353;
+    border-top: 0;
+    padding:2px;
+}
+
+#serendipityAdminBanner {
+    background-color: #FFF;
+    height: 80px;
+    background: url({TEMPLATE_PATH}img/banner_background.png);
+}
+
+#serendipityAdminInfopane {
+    background: #F8F9FA url({TEMPLATE_PATH}img/infobar_background.png);
+    font-size: 10px;
+    padding: 5px;
+    vertical-align: middle;
+    text-align: left;
+    color: #5E5E5E;
+    height: 27px;
+}
+
+#serendipityAdminMainpane {
+    background: #FFF;
+    border: 2px solid #0F3353;
+    border-top: inherit;
+    padding: 5px;
+}
+
+.serendipityAdminContent {
+    font-size: 0.8em;
+    padding: 10px 5px 20px 5px;
+    width: 80%;
+}
+
+#serendipityAdminBanner h1 {
+    padding-right: 20px;
+    font-size: 1.5em;
+    margin: 0;
+}
+
+#serendipityAdminBanner h2 {
+    padding-right: 30px;
+    font-size: 1em;
+    color: #AAA;
+    margin: 0;
+}
+
+#serendipitySideBar {
+    width: 20%;
+    padding-top: 10px;
+}
+
+#serendipityAdminFooter {
+    font-size: 0.7em;
+    text-align: center;
+    color: #FFF;
+}
+
+.serendipitySideBarTitle {
+    padding-right: 2px;
+    font-weight: bold;
+    font-size: 0.9em;
+}
+
+.serendipitySideBarContent {
+    padding-right: 10px;
+    font-size: 0.8em;
+}
+
+.serendipitySideBarItem {
+    margin-bottom: 10px;
+}
+
+.serendipity_admin_title {
+    font-size: 1.5em;
+    margin-bottom: 5px;
+}
+
+.serendipity_admin_list_item.serendipity_admin_list_item_uneven {
+    border: 1px solid #294366;
+    background: #F8F9FA;
+    margin-bottom: 5px;
+}
+
+.serendipity_admin_list_item.serendipity_admin_list_item_even {
+    border: 1px solid #294366;
+    background: #F2F3F2;
+    margin: 0 0 5px 0;
+}
+
+.serendipityAdminMsgError {
+    color: #F00;
+    text-align: center;
+    font-weight: bold;
+    margin: 10px;
+}
+
+.serendipityAdminMsgSuccess {
+    color: #0B0;
+    text-align: center;
+    font-weight: bold;
+    margin: 10px;
+}
+
+.serendipityAdminMsgNote {
+    background: #FFFF9D;
+    border: 1px solid #F70;
+    padding: 3px;
+    text-align: center;
+    margin: 10px;
+}
+
+
+
+td, th {
+    font-size: 0.8em;
+}
+
+a:visited,
+a:link {
+    color: #294366;
+    text-decoration: underline;
+}
+
+a:hover {
+    color: #D40041;
+}
+
+input, select, textarea {
+    background: #F8F9FA;
+    font-family: Tahoma, Verdana;
+    font-size: 0.9em;
+    border: 1px solid #294366;
+}
+
+#serendipity_iframe {
+    border: 1px solid #294366;
+    text-align: center;
+    margin: auto;
+}
+
+ul.serendipitySideBarMenu {
+    padding: 0;
+    margin: 0;
+}
+
+ul.serendipitySideBarMenu li {
+    font-weight: bold;
+    font-size: 0.8em;
+    line-height: 1.6em;
+    background:url({TEMPLATE_PATH}img/menu_background.png) right no-repeat;
+    padding: 4px 5px inherit inherit ;
+    list-style: none;
+    display: block;
+    margin: 0;
+}
+
+ul.serendipitySideBarMenu li.serendipitySideBarMenuHead {
+    background: url({TEMPLATE_PATH}img/menuheader_background.png) right no-repeat;
+    padding-right: 3px;
+}
+
+ul.serendipitySideBarMenu a:link,
+ul.serendipitySideBarMenu a:visited {
+    text-decoration: none;
+    font-weight: bold;
+}
+
+.serendipityImageButton {
+    cursor: pointer;
+}
+
+a:link.serendipityIconLink,
+a:visited.serendipityIconLink {
+    border: 0;
+    font-weight: bold;
+    text-decoration: none;
+    margin-right: 4px;
+}
+
+.serendipityIconLink img {
+    margin-left: 2px;
+    vertical-align: bottom;
+    border: 0;
+}
+
+a:link.serendipityIconLinkRight,
+a:visited.serendipityIconLinkRight {
+    border: 0;
+    font-weight: bold;
+    text-decoration: none;
+    margin-right: 4px;
+}
+.serendipityIconLinkRight img {
+    margin-right: 2px;
+    vertical-align: bottom;
+    border: 0;
+}
+
+
+a:link.serendipityPrettyButton,
+a:visited.serendipityPrettyButton,
+a:hover.serendipityPrettyButton {
+    text-decoration: none;
+    color: #1D2E3F;
+}
+
+.serendipityPrettyButton {
+    padding: 1px;
+    background: url({TEMPLATE_PATH}img/button_background.png) repeat-x top;
+    color: #1D2E3F;
+    font-weight: bold;
+    font-size: 0.9em;
+    border: 1px outset #000;
+    margin: 2px;
+}
+
+/* Special class if the button is a <a> tag */
+a.serendipityPrettyButton {
+    padding: 2px 4px 2px 4px;
+    cursor: default;
+}
+
+
+.direction_ltr {
+    direction: ltr;
+}
+
+.direction_rtl {
+    direction: rtl;
+}
diff --git a/templates/default-rtl/htmlarea.css b/templates/default-rtl/htmlarea.css
new file mode 100644 (file)
index 0000000..c040c8c
--- /dev/null
@@ -0,0 +1,45 @@
+body {
+    font-size: 10pt;
+    padding: 10px;
+    color: #333333;
+    background-color: #FAFFFF;
+    font-size: 9.5pt;
+    font-weight: normal;
+    font-family: Tahoma, verdana, arial, geneva, helvetica, sans-serif;
+    direction: rtl;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+}
+
+.serendipity_imageComment_left {
+    float: right;
+}
+
+.serendipity_imageComment_right {
+    float: left;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 9pt;
+}
+
diff --git a/templates/default-rtl/img/background.png b/templates/default-rtl/img/background.png
new file mode 100644 (file)
index 0000000..a318d7c
Binary files /dev/null and b/templates/default-rtl/img/background.png differ
diff --git a/templates/default-rtl/info.txt b/templates/default-rtl/info.txt
new file mode 100644 (file)
index 0000000..df2e3cb
--- /dev/null
@@ -0,0 +1,4 @@
+Name: RTL-Languages v0.1
+Author: Tom Sommer, Omid Mottaghi
+Date: 28/2/2005
+Require Serendipity: 0.8
diff --git a/templates/default-rtl/preview.png b/templates/default-rtl/preview.png
new file mode 100644 (file)
index 0000000..4bad5ac
Binary files /dev/null and b/templates/default-rtl/preview.png differ
diff --git a/templates/default-rtl/style.css b/templates/default-rtl/style.css
new file mode 100644 (file)
index 0000000..9f05e31
--- /dev/null
@@ -0,0 +1,353 @@
+h4,h3 {
+    margin: 0;
+}
+
+.serendipitySideBarContent input {
+    width: 150px;
+}
+
+#mainpane {
+    border-bottom: 1px solid #000000;
+    margin: auto;
+    width: 100%;
+    border-top: 0px;
+    background-color: #FFFFFF;
+    border-top: 1px solid #000000;
+}
+
+#content {
+    padding: 10px;
+    margin: 10px;
+    width: auto;
+}
+
+#serendipityRightSideBar {
+    width: 170px;
+    border-right: 1px dashed #000000;
+    padding: 10px;
+    vertical-align: top;
+}
+
+#serendipityLeftSideBar {
+    width: 170px;
+    border-left: 1px dashed #000000;
+    padding: 10px;
+    vertical-align: top;
+}
+
+body {
+    font-size: 10pt;
+    margin: 0;
+    background-color: #D2DFF2;
+    font-size: 10px;
+    font-family: Tahoma, verdana, arial, helvetica, sans-serif;
+    margin-bottom: 30px;
+    direction:rtl;
+}
+
+input, textarea {
+    font-size: 10pt;
+    font-family: Tahoma, verdana, arial, helvetica, sans-serif;
+}
+
+th, td {
+    font-size: 10pt;
+}
+
+p, td, th, div, span {
+    font-family: Tahoma, verdana, arial, helvetica, sans-serif;
+}
+
+#serendipity_banner {
+    margin: auto;
+    width: 100%;
+    height: 72px;
+    background-image: url({TEMPLATE_PATH}img/background.png);
+}
+
+a.homelink1,
+a.homelink1:hover,
+a.homelink1:link,
+a.homelink1:visited,
+#serendipity_banner h1 {
+    color: #FFFFFF;
+    font-family: Tahoma, Verdana, Arial, Geneva, Helvetica, sans-serif;
+    font-size : 20px;
+    padding-right:15px;
+    padding-top: 10px;
+    margin: 0px;
+    text-decoration: none;
+}
+
+a.homelink2,
+a.homelink2:hover,
+a.homelink2:link,
+a.homelink2:visited,
+#serendipity_banner h2 {
+    color: #FFFFFF;
+    padding-right: 15px;
+    font-size: 14px;
+    margin: 0px;
+    text-decoration: none;
+}
+
+.serendipity_title {
+    font-family: Tahoma, Verdana, Arial, Geneva, Helvetica, sans-serif;
+    font-size: medium;
+    font-weight: bold;
+    margin-top: 10px;
+    color: #333333;
+    padding-right: 5px;
+    border-bottom: 2px solid #36558C;
+}
+
+.serendipity_title a:link,
+.serendipity_title a:visited {
+   text-decoration: none;
+   border: 0;
+   color: #000000;
+}
+
+.serendipity_title a:hover {
+   color: #FF0000;
+}
+
+.serendipity_entry {
+    font-family: Tahoma, Verdana, Arial, Geneva, Helvetica, sans-serif;
+    color: #333333;
+    font-size: 9.5pt;
+    font-weight: normal;
+    padding-left: 10px;
+    width: 95%;
+    margin: auto;
+    margin-top: 10px;
+}
+
+.serendipity_entry_body_folded,
+.serendipity_entry_body_unfolded,
+.serendipity_entry_extended {
+    /* Inner blocks of .serendipity_entry, can be used for further customization */
+}
+
+.serendipity_entry_date {
+    margin: auto;
+}
+
+.serendipity_date {
+    font-family: Tahoma, Verdana, Arial, Geneva, Helvetica, sans-serif;
+    font-size: large;
+    color: #333333;
+    margin: 0;
+    margin-top: 20px;
+    text-align: left;
+}
+
+.serendipity_commentsTitle {
+    font-family: Tahoma, Verdana, Arial, Geneva, Helvetica, sans-serif;
+    font-size: small;
+    font-weight: bold;
+    margin-top: 10px;
+    color: #333333;
+    padding-right: 5px;
+    border-bottom: 2px solid #36558C;
+}
+
+div.serendipity_entryFooter {
+    font-family: Tahoma, Verdana, Arial, Geneva, Helvetica, sans-serif;
+    font-size: x-small;
+    color: #000000;
+    padding-top: 10px;
+    padding-bottom: 4px;
+    clear: both;
+}
+
+img.serendipity_entryIcon {
+    float: left;
+    border: 0px;
+}
+
+img.serendipity_entryIcon {
+    float: left;
+    border: 0px;
+}
+
+td.serendipity_commentsLabel {
+    font-size: 12px;
+    font-weight: bold;
+    vertical-align: top;
+}
+
+td.serendipity_commentsValue input,
+td.serendipity_commentsValue select,
+td.serendipity_commentsValue textarea {
+    font-size: 12px;
+    padding: 2px;
+    width: 400px;
+}
+
+
+.serendipity_commentForm {
+    font-size: 13px;
+    color: #404040;
+    margin-bottom: 13px;
+    margin-right: 10px;
+    margin-left: 10px;
+    background-color: #FFFFFF;
+}
+.serendipity_comment {
+    font-size: 13px;
+    margin-top: 10px;
+    margin-right: 10px;
+    margin-left: 10px;
+    color: #404040;
+    padding: 3px;
+    background-color: #FFFFFF;
+    overflow: auto;
+}
+
+.serendipity_comment_source {
+    margin-top: 5px;
+    padding-right: 5px;
+    margin-bottom: 5px;
+    padding-bottom: 3px;
+    border-bottom: 2px solid #36558C;
+}
+
+a:link,
+a:visited,
+a:active {
+    color: #003366;
+    text-decoration: underline;
+}
+a:hover {
+    color: #000000;
+    text-decoration: underline;
+}
+
+table.serendipity_calendar td {
+    font-size:11px;
+    padding: 3px;
+}
+table.serendipity_calendar a {
+    color: #FF0000;
+    font-weight: bold;
+    text-decoration:none;
+}
+
+table.serendipity_calendar a:hover {
+    text-decoration: none;
+}
+
+td.serendipity_weekDayName {
+    font-size:11px;
+    font-weight:bold;
+}
+td.serendipity_calendarHeader a:link,
+td.serendipity_calendarHeader a:visited,
+td.serendipity_calendarHeader a:hover {
+    border: 0;
+    text-decoration: none;
+}
+
+div.serendipityPlug {
+    padding-right: 10px;
+}
+
+div.serendipityPlug a {
+    text-decoration: none;
+    border: 0px;
+}
+
+/* Container for each item on the side bar */
+div.serendipitySideBarItem {
+    padding-bottom: 12px;
+    margin-bottom: 12px;
+    font-size: 12px;
+    font-weight:normal;
+    border-bottom: solid 2px #36558C;
+}
+
+/* title of an individual item */
+.serendipitySideBarTitle {
+    margin: 0;
+    font-family: Tahoma, Verdana, Arial, Geneva, Helvetica, sans-serif;
+    color: #000000;
+    font-size: 12px;
+    font-weight:bold;
+    padding-right:2px;
+    padding-bottom:2px;
+}
+
+.serendipityImageButton {
+    cursor: pointer;
+}
+.serendipity_entry p {
+    margin: 0px;
+    padding-bottom: 0px;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid #DDDDDD;
+    background-color: #EFEFEF;
+    margin: 3px;
+    padding: 3px;
+    text-align: center;
+}
+
+.serendipity_imageComment_center {
+    margin: auto;
+}
+
+.serendipity_imageComment_left {
+    float: right;
+}
+
+.serendipity_imageComment_right {
+    float: left;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    text-align: center;
+}
+
+.serendipity_imageComment_txt {
+    border-top: 1px solid #DDDDDD;
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 8pt;
+    text-align: center;
+}
+
+.serendipity_comments {
+}
+
+.serendipity_center {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center;
+}
+
+.serendipity_msg_important {
+    color: red;
+}
+
+.serendipity_msg_notice {
+    color: green;
+}
+
+.serendipity_entry_author_self {
+}
+
+.serendipity_comment_author_self .serendipity_comment_source {
+    background-color: #EEEEFF;
+}
+#serendipity_commentsURL #serendipity_commentsEmail {
+    direction: ltr;
+}
\ No newline at end of file
diff --git a/templates/default/admin/img/accept.png b/templates/default/admin/img/accept.png
new file mode 100644 (file)
index 0000000..5b0f6a6
Binary files /dev/null and b/templates/default/admin/img/accept.png differ
diff --git a/templates/default/admin/img/background.jpg b/templates/default/admin/img/background.jpg
new file mode 100644 (file)
index 0000000..7635ca9
Binary files /dev/null and b/templates/default/admin/img/background.jpg differ
diff --git a/templates/default/admin/img/banner_background.png b/templates/default/admin/img/banner_background.png
new file mode 100644 (file)
index 0000000..ae06c20
Binary files /dev/null and b/templates/default/admin/img/banner_background.png differ
diff --git a/templates/default/admin/img/big_delete.png b/templates/default/admin/img/big_delete.png
new file mode 100644 (file)
index 0000000..816e06a
Binary files /dev/null and b/templates/default/admin/img/big_delete.png differ
diff --git a/templates/default/admin/img/big_rename.png b/templates/default/admin/img/big_rename.png
new file mode 100644 (file)
index 0000000..4126975
Binary files /dev/null and b/templates/default/admin/img/big_rename.png differ
diff --git a/templates/default/admin/img/big_resize.png b/templates/default/admin/img/big_resize.png
new file mode 100644 (file)
index 0000000..7d8ff85
Binary files /dev/null and b/templates/default/admin/img/big_resize.png differ
diff --git a/templates/default/admin/img/big_rotate_ccw.png b/templates/default/admin/img/big_rotate_ccw.png
new file mode 100644 (file)
index 0000000..c381bad
Binary files /dev/null and b/templates/default/admin/img/big_rotate_ccw.png differ
diff --git a/templates/default/admin/img/big_rotate_cw.png b/templates/default/admin/img/big_rotate_cw.png
new file mode 100644 (file)
index 0000000..61b0495
Binary files /dev/null and b/templates/default/admin/img/big_rotate_cw.png differ
diff --git a/templates/default/admin/img/big_zoom.png b/templates/default/admin/img/big_zoom.png
new file mode 100644 (file)
index 0000000..e845f6d
Binary files /dev/null and b/templates/default/admin/img/big_zoom.png differ
diff --git a/templates/default/admin/img/button_background.png b/templates/default/admin/img/button_background.png
new file mode 100644 (file)
index 0000000..d48532b
Binary files /dev/null and b/templates/default/admin/img/button_background.png differ
diff --git a/templates/default/admin/img/clock.png b/templates/default/admin/img/clock.png
new file mode 100644 (file)
index 0000000..7c622a0
Binary files /dev/null and b/templates/default/admin/img/clock.png differ
diff --git a/templates/default/admin/img/clock_future.png b/templates/default/admin/img/clock_future.png
new file mode 100644 (file)
index 0000000..2517b4f
Binary files /dev/null and b/templates/default/admin/img/clock_future.png differ
diff --git a/templates/default/admin/img/configure.png b/templates/default/admin/img/configure.png
new file mode 100644 (file)
index 0000000..a4a3834
Binary files /dev/null and b/templates/default/admin/img/configure.png differ
diff --git a/templates/default/admin/img/delete.png b/templates/default/admin/img/delete.png
new file mode 100644 (file)
index 0000000..dfb80b2
Binary files /dev/null and b/templates/default/admin/img/delete.png differ
diff --git a/templates/default/admin/img/downarrow.png b/templates/default/admin/img/downarrow.png
new file mode 100644 (file)
index 0000000..a4f8e50
Binary files /dev/null and b/templates/default/admin/img/downarrow.png differ
diff --git a/templates/default/admin/img/edit.png b/templates/default/admin/img/edit.png
new file mode 100644 (file)
index 0000000..33de951
Binary files /dev/null and b/templates/default/admin/img/edit.png differ
diff --git a/templates/default/admin/img/folder.png b/templates/default/admin/img/folder.png
new file mode 100644 (file)
index 0000000..2d8e3ba
Binary files /dev/null and b/templates/default/admin/img/folder.png differ
diff --git a/templates/default/admin/img/infobar_background.png b/templates/default/admin/img/infobar_background.png
new file mode 100644 (file)
index 0000000..09c9077
Binary files /dev/null and b/templates/default/admin/img/infobar_background.png differ
diff --git a/templates/default/admin/img/install.png b/templates/default/admin/img/install.png
new file mode 100644 (file)
index 0000000..0fcda3b
Binary files /dev/null and b/templates/default/admin/img/install.png differ
diff --git a/templates/default/admin/img/install_now.png b/templates/default/admin/img/install_now.png
new file mode 100644 (file)
index 0000000..4a450a7
Binary files /dev/null and b/templates/default/admin/img/install_now.png differ
diff --git a/templates/default/admin/img/install_template.png b/templates/default/admin/img/install_template.png
new file mode 100644 (file)
index 0000000..ffbce22
Binary files /dev/null and b/templates/default/admin/img/install_template.png differ
diff --git a/templates/default/admin/img/menu_background.png b/templates/default/admin/img/menu_background.png
new file mode 100644 (file)
index 0000000..4c5497f
Binary files /dev/null and b/templates/default/admin/img/menu_background.png differ
diff --git a/templates/default/admin/img/menuheader_background.png b/templates/default/admin/img/menuheader_background.png
new file mode 100644 (file)
index 0000000..7f76961
Binary files /dev/null and b/templates/default/admin/img/menuheader_background.png differ
diff --git a/templates/default/admin/img/menuitem.png b/templates/default/admin/img/menuitem.png
new file mode 100644 (file)
index 0000000..2253ae8
Binary files /dev/null and b/templates/default/admin/img/menuitem.png differ
diff --git a/templates/default/admin/img/mime_unknown.png b/templates/default/admin/img/mime_unknown.png
new file mode 100644 (file)
index 0000000..35c93d2
Binary files /dev/null and b/templates/default/admin/img/mime_unknown.png differ
diff --git a/templates/default/admin/img/next.png b/templates/default/admin/img/next.png
new file mode 100644 (file)
index 0000000..24a89b5
Binary files /dev/null and b/templates/default/admin/img/next.png differ
diff --git a/templates/default/admin/img/previous.png b/templates/default/admin/img/previous.png
new file mode 100644 (file)
index 0000000..6992aa7
Binary files /dev/null and b/templates/default/admin/img/previous.png differ
diff --git a/templates/default/admin/img/rotate.png b/templates/default/admin/img/rotate.png
new file mode 100644 (file)
index 0000000..c381bad
Binary files /dev/null and b/templates/default/admin/img/rotate.png differ
diff --git a/templates/default/admin/img/thumbnail.png b/templates/default/admin/img/thumbnail.png
new file mode 100644 (file)
index 0000000..91adff8
Binary files /dev/null and b/templates/default/admin/img/thumbnail.png differ
diff --git a/templates/default/admin/img/uparrow.png b/templates/default/admin/img/uparrow.png
new file mode 100644 (file)
index 0000000..dfad497
Binary files /dev/null and b/templates/default/admin/img/uparrow.png differ
diff --git a/templates/default/admin/img/upgrade_now.png b/templates/default/admin/img/upgrade_now.png
new file mode 100644 (file)
index 0000000..b622ed3
Binary files /dev/null and b/templates/default/admin/img/upgrade_now.png differ
diff --git a/templates/default/admin/img/user_admin.png b/templates/default/admin/img/user_admin.png
new file mode 100644 (file)
index 0000000..a6ed9b4
Binary files /dev/null and b/templates/default/admin/img/user_admin.png differ
diff --git a/templates/default/admin/img/user_chief.png b/templates/default/admin/img/user_chief.png
new file mode 100644 (file)
index 0000000..4aeaa1d
Binary files /dev/null and b/templates/default/admin/img/user_chief.png differ
diff --git a/templates/default/admin/img/user_editor.png b/templates/default/admin/img/user_editor.png
new file mode 100644 (file)
index 0000000..8aa2004
Binary files /dev/null and b/templates/default/admin/img/user_editor.png differ
diff --git a/templates/default/admin/img/zoom.png b/templates/default/admin/img/zoom.png
new file mode 100644 (file)
index 0000000..6dd1931
Binary files /dev/null and b/templates/default/admin/img/zoom.png differ
diff --git a/templates/default/admin/style.css b/templates/default/admin/style.css
new file mode 100644 (file)
index 0000000..cb8a4c4
--- /dev/null
@@ -0,0 +1,257 @@
+body {
+    font-family: Verdana;
+    margin: 0 0 0 0;
+    background: #7F9BC2 url({TEMPLATE_PATH}img/background.jpg) repeat-x;
+    direction: {LANG_DIRECTION};
+}
+
+#serendipity_admin_page {
+    text-align: center;
+}
+
+#serendipityAdminBodyImageSelector {
+    background: #FFF;
+}
+
+#serendipityAdminFrame {
+    text-align: left;
+    width: 80%;
+    min-width: 777px;
+    margin: auto;
+    background: #FFF;
+    border: 2px solid #0F3353;
+    border-top: 0;
+}
+
+#serendipityAdminBanner {
+    background-color: #FFF;
+    height: 80px;
+    background: url({TEMPLATE_PATH}img/banner_background.png);
+}
+
+#serendipityAdminInfopane {
+    background: #F8F9FA url({TEMPLATE_PATH}img/infobar_background.png);
+    font-size: 10px;
+    padding: 5px;
+    vertical-align: middle;
+    text-align: right;
+    color: #5E5E5E;
+    height: 27px;
+}
+
+#serendipityAdminMainpane {
+    background: #FFF;
+    border: 2px solid #0F3353;
+    border-top: inherit;
+    padding: 5px;
+}
+
+.serendipityAdminContent {
+    font-size: 0.8em;
+    padding: 10px 5px 20px 5px;
+    width: 80%;
+}
+
+#serendipityAdminBanner h1 {
+    padding-left: 20px;
+    font-size: 1.8em;
+    margin: 0;
+}
+
+#serendipityAdminBanner h2 {
+    padding-left: 30px;
+    font-size: 1em;
+    color: #AAA;
+    margin: 0;
+}
+
+#serendipitySideBar {
+    width: 20%;
+    padding-top: 10px;
+}
+
+#serendipityAdminFooter {
+    font-size: 0.7em;
+    text-align: center;
+    color: #FFF;
+}
+
+.serendipitySideBarTitle {
+    padding-left: 2px;
+    font-weight: bold;
+    font-size: 0.9em;
+}
+
+.serendipitySideBarContent {
+    padding-left: 10px;
+    font-size: 0.8em;
+}
+
+.serendipitySideBarItem {
+    margin-bottom: 10px;
+}
+
+.serendipity_admin_title {
+    font-size: 2em;
+    margin-bottom: 5px;
+}
+
+.serendipity_admin_list_item.serendipity_admin_list_item_uneven {
+    border: 1px solid #294366;
+    background: #F8F9FA;
+    margin-bottom: 5px;
+}
+
+.serendipity_admin_list_item.serendipity_admin_list_item_even {
+    border: 1px solid #294366;
+    background: #F2F3F2;
+    margin: 0 0 5px 0;
+}
+
+.serendipityAdminMsgError {
+    color: #F00;
+    text-align: center;
+    font-weight: bold;
+    margin: 10px;
+}
+
+.serendipityAdminMsgSuccess {
+    color: #0B0;
+    text-align: center;
+    font-weight: bold;
+    margin: 10px;
+}
+
+.serendipityAdminMsgNote {
+    background: #FFFF9D;
+    border: 1px solid #F70;
+    padding: 3px;
+    text-align: center;
+    margin: 10px;
+}
+
+
+
+td, th {
+    font-size: 0.8em;
+}
+
+a:visited,
+a:link {
+    color: #294366;
+    text-decoration: underline;
+}
+
+a:hover {
+    color: #D40041;
+}
+
+input, select, textarea {
+    background: #F8F9FA;
+    font-family: Verdana;
+    font-size: 0.9em;
+    border: 1px solid #294366;
+}
+
+#serendipity_iframe {
+    border: 1px solid #294366;
+    text-align: center;
+    margin: auto;
+}
+
+ul.serendipitySideBarMenu {
+    padding: 0;
+    margin: 0;
+}
+
+ul.serendipitySideBarMenu li.serendipitySideBarMenuHead {
+    font-size: 0.85em;
+    list-style: none;
+    display: block;
+    font-weight: bold;
+    background: url({TEMPLATE_PATH}img/menuheader_background.png) no-repeat;
+    height: 1.6em;
+    padding-left: 3px;
+}
+
+ul.serendipitySideBarMenu li {
+    font-size: 0.8em;
+    font-weight: normal;
+    background:url({TEMPLATE_PATH}img/menu_background.png) no-repeat;
+    padding-top: 4px;
+    padding-left: 5px;
+    height: 1.6em;
+    list-style:none;
+    display:block;
+    margin:0;
+}
+
+ul.serendipitySideBarMenu a:link,
+ul.serendipitySideBarMenu a:visited {
+    text-decoration: none;
+    font-weight: bold;
+}
+
+.serendipityImageButton {
+    cursor: pointer;
+}
+
+a:link.serendipityIconLink,
+a:visited.serendipityIconLink {
+    border: 0;
+    font-weight: bold;
+    text-decoration: none;
+    margin-right: 4px;
+}
+
+.serendipityIconLink img {
+    margin-right: 2px;
+    vertical-align: bottom;
+    border: 0;
+}
+
+a:link.serendipityIconLinkRight,
+a:visited.serendipityIconLinkRight {
+    border: 0;
+    font-weight: bold;
+    text-decoration: none;
+    margin-left: 4px;
+}
+.serendipityIconLinkRight img {
+    margin-left: 2px;
+    vertical-align: bottom;
+    border: 0;
+}
+
+
+a:link.serendipityPrettyButton,
+a:visited.serendipityPrettyButton,
+a:hover.serendipityPrettyButton {
+    text-decoration: none;
+    color: #1D2E3F;
+}
+
+.serendipityPrettyButton {
+    padding: 1px;
+    background: url({TEMPLATE_PATH}img/button_background.png) repeat-x top;
+    color: #1D2E3F;
+    font-weight: bold;
+    font-size: 0.9em;
+    border: 1px outset #000;
+    margin: 2px;
+}
+
+/* Special class if the button is a <a> tag */
+a.serendipityPrettyButton {
+    padding: 2px 4px 2px 4px;
+    cursor: default;
+}
+
+
+.direction_ltr {
+    direction: ltr;
+}
+
+.direction_rtl {
+    direction: rtl;
+}
diff --git a/templates/default/atom.css b/templates/default/atom.css
new file mode 100644 (file)
index 0000000..449ff44
--- /dev/null
@@ -0,0 +1,89 @@
+/* Basic CSS taken from http://www.blogger.com/styles/atom.css */
+
+feed {
+  display:block;
+  font-family:verdana, sans-serif;
+  margin:2%;
+  font-size:90%;
+  color:#000000;
+  background:#ffffff;
+}
+
+title {
+  display:block;
+  font-size:1.3em;
+  color:inherit;
+  background:inherit;
+  font-weight:bold;
+}
+
+tagline, link {
+  display:block;
+  font-size:0.9em;
+}
+
+id, modified {
+  display:none;
+}
+
+generator {
+  display:block;
+  font-size:0.9em;
+}
+
+info {
+  display:block;
+  margin:3em 4em 3em 4em;
+  color:#CC3333;
+  background:#FFFF66;
+  border:solid #CCCC66 2px;
+  text-align:center;
+  padding:1.5em;
+  font-family:mono;
+  font-size:0.8em;
+}
+
+entry {
+  display:block;
+  color:inherit;
+  background:inherit;
+  padding:0;
+  margin:1em 1em 4em 1em;
+  
+}
+
+entry modified, entry name {
+  display:inline;
+  color:#999999;
+  background:inherit;
+  font-size:0.8em;
+}
+
+entry created, entry issued, entry id {
+  display:none;
+}
+
+/* Using a single 'commentRSS' and 'comments' is used for compatibility to Opera */
+slash\:comments, wfw\:commentRss, commentRss, comments, wfw\:comment, comment {
+  display:none;
+}
+
+entry title {
+  display:block;
+  font-size:1em;
+  font-weight:bold;
+  color:inherit;
+  background:inherit;
+  padding:1em 1em 0em 1em;
+  margin:0;
+  border-top:solid 1px #dddddd;
+}
+
+content {
+  display:block;
+  font-size:0.9em;
+  color:inherit;
+  background:inherit;
+  padding:1em;
+  line-height:1.5em;
+}
diff --git a/templates/default/commentform.tpl b/templates/default/commentform.tpl
new file mode 100644 (file)
index 0000000..b00dd89
--- /dev/null
@@ -0,0 +1,59 @@
+<div class="serendipityCommentForm">
+    <a id="serendipity_CommentForm"></a>
+    <form id="serendipity_comment" action="{$commentform_action}#feedback" method="post">
+    <div><input type="hidden" name="serendipity[entry_id]" value="{$commentform_id}" /></div>
+    <table border="0" width="100%" cellpadding="3">
+        <tr>
+            <td class="serendipity_commentsLabel"><label for="serendipity_commentform_name">{$CONST.NAME}</label></td>
+            <td class="serendipity_commentsValue"><input type="text" id="serendipity_commentform_name" name="serendipity[name]" value="{$commentform_name}" size="30" /></td>
+        </tr>
+
+        <tr>
+            <td class="serendipity_commentsLabel"><label for="serendipity_commentform_email">{$CONST.EMAIL}</label></td>
+            <td class="serendipity_commentsValue"><input type="text" id="serendipity_commentform_email" name="serendipity[email]" value="{$commentform_email}" /></td>
+        </tr>
+
+        <tr>
+            <td class="serendipity_commentsLabel"><label for="serendipity_commentform_url">{$CONST.HOMEPAGE}</label></td>
+            <td class="serendipity_commentsValue"><input type="text" id="serendipity_commentform_url" name="serendipity[url]" value="{$commentform_url}" /></td>
+        </tr>
+
+        <tr>
+            <td class="serendipity_commentsLabel"><label for="serendipity_replyTo">{$CONST.IN_REPLY_TO}</label></td>
+            <td class="serendipity_commentsValue">{$commentform_replyTo}</td>
+        </tr>
+
+        <tr>
+            <td class="serendipity_commentsLabel"><label for="serendipity_commentform_comment">{$CONST.COMMENT}</label></td>
+            <td class="serendipity_commentsValue">
+                <textarea rows="10" cols="40" id="serendipity_commentform_comment" name="serendipity[comment]">{$commentform_data}</textarea><br />
+                {serendipity_hookPlugin hook="frontend_comment" data=$commentform_entry}
+            </td>
+        </tr>
+
+{if $is_commentform_showToolbar}
+        <tr>
+            <td>&#160;</td>
+            <td class="serendipity_commentsLabel">
+                <input id="checkbox_remember" type="checkbox" name="serendipity[remember]" {$commentform_remember} /><label for="checkbox_remember">{$CONST.REMEMBER_INFO}</label>
+    {if $is_allowSubscriptions}
+                <br />
+                <input id="checkbox_subscribe" type="checkbox" name="serendipity[subscribe]" {$commentform_subscribe} /><label for="checkbox_subscribe">{$CONST.SUBSCRIBE_TO_THIS_ENTRY}</label>
+    {/if}
+            </td>
+       </tr>
+{/if}
+
+{if $is_moderate_comments}
+       <tr>
+            <td class="serendipity_commentsValue serendipity_msg_important" colspan="2">{$CONST.COMMENTS_WILL_BE_MODERATED}</td>
+       </tr>
+{/if}
+
+       <tr>
+            <td>&#160;</td>
+            <td><input type="submit" name="serendipity[submit]" value="{$CONST.SUBMIT_COMMENT}" /> <input type="submit" name="serendipity[preview]" value="{$CONST.PREVIEW}" /></td>
+        </tr>
+    </table>
+    </form>
+</div>
diff --git a/templates/default/commentpopup.tpl b/templates/default/commentpopup.tpl
new file mode 100644 (file)
index 0000000..3808377
--- /dev/null
@@ -0,0 +1,61 @@
+{if $is_xhtml}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+           "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+{else}
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+           "http://www.w3.org/TR/html4/loose.dtd">
+{/if}
+
+<html>
+<head>
+    <title>{$head_title|@default:$blogTitle} {if $head_subtitle} - {$head_subtitle}{/if}</title>
+    <meta http-equiv="Content-Type" content="text/html; charset={$head_charset}" />
+    <meta name="Powered-By" content="Serendipity v.{$head_version}" />
+    <link rel="stylesheet" type="text/css" href="{$serendipityHTTPPath}serendipity.css.php" />
+    <link rel="alternate"  type="application/rss+xml" title="{$blogTitle} RSS feed" href="{$serendipityBaseURL}{$serendipityRewritePrefix}feeds/index.rss2" />
+    <link rel="alternate"  type="application/x.atom+xml"  title="{$blogTitle} Atom feed"  href="{$serendipityBaseURL}{$serendipityRewritePrefix}feeds/atom.xml" />
+</head>
+
+<body class="s9y_wrap" id="serendipity_comment_page">
+
+{if $is_comment_added}
+
+    {$CONST.COMMENT_ADDED}{$comment_string.0}<a href="{$comment_url}">{$comment_string.1}</a>{$comment_string.2}<a href="#" onclick="self.close()">{$comment_string.3}</a>{$comment_string.4}
+
+{elseif $is_comment_notadded}
+
+    {$CONST.COMMENT_NOT_ADDED}{$comment_string.0}<a href="{$comment_url}">{$comment_string.1}</a>{$comment_string.2}<a href="#" onclick="self.close()">{$comment_string.3}</a>{$comment_string.4}
+
+{elseif $is_comment_empty}
+
+    {$comment_string.0}<a href="#" onclick="history.go(-1)">{$comment_string.1}</a>
+
+{elseif $is_showtrackbacks}
+
+    <div class="serendipity_commentsTitle">{$CONST.TRACKBACKS}</div><br />
+    <dl>
+        <dt><b>{$CONST.TRACKBACK_SPECIFIC}:</b><br /></dt>
+        <dd><a rel="nofollow" href="{$comment_url}">{$comment_url}</a><br /></dd>
+
+        <dt><b>{$CONST.DIRECT_LINK}:</b><br /></dt>
+        <dd><a href="{$comment_entryurl}">{$comment_entryurl}</a></dd>
+    </dl>
+
+    {serendipity_printTrackbacks entry=$entry_id}
+
+{elseif $is_showcomments}
+
+    <div class="serendipity_commentsTitle">{$CONST.COMMENTS}</div>
+
+    {serendipity_printComments entry=$entry_id}
+    {if $is_comment_allowed}
+        <div class="serendipity_commentsTitle">{$CONST.ADD_COMMENT}</div>
+        {$COMMENTFORM}
+    {else}
+        <div class="serendipity_center serendipity_msg_important">{$CONST.COMMENTS_CLOSED}</div>
+    {/if}
+
+{/if}
+
+</body>
+</html>
diff --git a/templates/default/comments.tpl b/templates/default/comments.tpl
new file mode 100644 (file)
index 0000000..e95bfb6
--- /dev/null
@@ -0,0 +1,27 @@
+{foreach from=$comments item=comment}
+    <a id="c{$comment.id}"></a>
+    <div class="serendipity_comment serendipity_comment_author_{$comment.author|@makeFilename} {if $entry.author == $comment.author}serendipity_comment_author_self{/if}" style="padding-left: {$comment.depth*20}px">
+        <div class="serendipity_commentBody">{$comment.body}</div>
+        <div class="serendipity_comment_source">
+            <a href="#c{$comment.id}" title="Link to comment #{$comment.trace}">#{$comment.trace}</a>
+            {if $comment.email}
+                <a href="mailto:{$comment.email}">{$comment.author|@default:$CONST.ANONYMOUS}</a>
+            {else}
+                {$comment.author|@default:$CONST.ANONYMOUS}
+            {/if}
+            {if $comment.url}
+                (<a href="{$comment.url}" title="{$comment.url|@escape}">Link</a>)
+            {/if}
+            {$CONST.ON}
+            {$comment.timestamp|@formatTime:$CONST.DATE_FORMAT_SHORT}
+            {if $entry.is_entry_owner}
+                (<a href="{$comment.link_delete}" onclick="return confirm('{$CONST.COMMENT_DELETE_CONFIRM|@sprintf:$comment.id:$comment.author}');">delete</a>)
+            {/if}
+            {if $entry.allow_comments}
+                (<a href="#serendipity_CommentForm" onclick="document.getElementById('serendipity_replyTo').value='{$comment.id}';">Reply</a>)
+            {/if}
+        </div>
+    </div>
+{foreachelse}
+    <div class="serendipity_center">{$CONST.NO_COMMENTS}</div>
+{/foreach}
diff --git a/templates/default/content.tpl b/templates/default/content.tpl
new file mode 100644 (file)
index 0000000..9f88267
--- /dev/null
@@ -0,0 +1,7 @@
+<!-- CONTENT START -->
+
+{$content_message}
+{$ENTRIES}
+{$ARCHIVES}
+
+<!-- CONTENT END -->
diff --git a/templates/default/entries.tpl b/templates/default/entries.tpl
new file mode 100644 (file)
index 0000000..4ec6a0f
--- /dev/null
@@ -0,0 +1,196 @@
+<!-- ENTRIES START -->
+    {serendipity_hookPlugin hook="entries_header" addData="$entry_id"}
+
+    {foreach from=$entries item="dategroup"}
+    <div class="serendipity_Entry_Date">
+        {if $dategroup.is_sticky}
+        <h3 class="serendipity_date">{$CONST.STICKY_POSTINGS}</h3>
+        {else}
+        <h3 class="serendipity_date">{$dategroup.date|@formatTime:DATE_FORMAT_ENTRY}</h3>
+        {/if}
+
+        {foreach from=$dategroup.entries item="entry"}
+        <h4 class="serendipity_title"><a href="{$entry.link}">{$entry.title}</a></h4>
+
+        <div class="serendipity_entry serendipity_entry_author_{$entry.author|@makeFilename} {if $entry.is_entry_owner}serendipity_entry_author_self{/if}">
+            {if $entry.categories}
+            <span class="serendipity_entryIcon">
+            {foreach from=$entry.categories item="category"}
+                {if $category.category_icon}
+                    <a href="{$category.category_link}"><img class="serendipity_entryIcon" title="{$category.category_name|@escape}{$category.category_description|@emptyPrefix}" alt="{$category.category_name|@escape}" src="{$category.category_icon}" /></a>
+                {/if}
+            {/foreach}
+            </span>
+            {/if}
+
+            <div class="serendipity_entry_body">
+                {$entry.body}
+            </div>
+
+            {if $entry.is_extended}
+            <div class="serendipity_entry_extended"><a id="extended"></a>{$entry.extended}</div>
+            {/if}
+
+            {if $entry.has_extended and not $is_single_entry and not $entry.is_extended}
+            <br /><a href="{$entry.link}#extended">{$CONST.VIEW_EXTENDED_ENTRY|@sprintf:$entry.title}</a><br /><br />
+            {/if}
+
+            <div class='serendipity_entryFooter'>
+                {$CONST.POSTED_BY} <a href="{$entry.link_author}">{$entry.author}</a>
+                {if $entry.categories}
+                   {$CONST.IN} {foreach from=$entry.categories item="category" name="categories"}<a href="{$category.category_link}">{$category.category_name|@escape}</a>{if not $smarty.foreach.categories.last}, {/if}{/foreach}
+                {/if}
+
+                {if $dategroup.is_sticky}
+                    {$CONST.ON}
+                {else}
+                    {$CONST.AT}
+                {/if} <a href="{$entry.link}">{if $dategroup.is_sticky}{$entry.timestamp|@formatTime:DATE_FORMAT_ENTRY} {/if}{$entry.timestamp|@formatTime:'%H:%M'}</a>
+
+                {if $entry.has_comments}
+                    {if $use_popups}
+                        | <a href="{$entry.link_popup_comments}" onclick="window.open(this.href, 'comments', 'width=480,height=480,scrollbars=yes'); return false;">{$entry.label_comments} ({$entry.comments})</a>
+                    {else}
+                        | <a href="{$entry.link}#comments">{$entry.label_comments} ({$entry.comments})</a>
+                    {/if}
+                {/if}
+
+                {if $entry.has_trackbacks}
+                    {if $use_popups}
+                        | <a href="{$entry.link_popup_trackbacks}" onclick="window.open(this.href, 'comments', 'width=480,height=480,scrollbars=yes'); return false;">{$entry.label_trackbacks} ({$entry.trackbacks})</a>
+                    {else}
+                        | <a href="{$entry.link}#trackbacks">{$entry.label_trackbacks} ({$entry.trackbacks})</a>
+                    {/if}
+                {/if}
+
+                {if $entry.is_entry_owner and not $is_preview}
+                        | <a href="{$entry.link_edit}">{$CONST.EDIT_ENTRY}</a>
+                {/if}
+
+                {$entry.add_footer}
+            </div>
+        </div>
+        <!--
+        <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+                 xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"
+                 xmlns:dc="http://purl.org/dc/elements/1.1/">
+        <rdf:Description
+                 rdf:about="{$entry.link_rdf}"
+                 trackback:ping="{$entry.link_trackback}"
+                 dc:title="{$entry.title}"
+                 dc:identifier="{$entry.rdf_ident}" />
+        </rdf:RDF>
+        -->
+        {$entry.plugin_display_dat}
+
+        {if $is_single_entry and not $use_popups and not $is_preview}
+            {if $CONST.DATA_UNSUBSCRIBED}
+                <br /><div class="serendipity_center serendipity_msg_notice">{$CONST.DATA_UNSUBSCRIBED|@sprintf:$CONST.UNSUBSCRIBE_OK}</div><br />
+            {/if}
+
+            {if $CONST.DATA_TRACKBACK_DELETED}
+                <br /><div class="serendipity_center serendipity_msg_notice">{$CONST.DATA_TRACKBACK_DELETED|@sprintf:$CONST.TRACKBACK_DELETED}</div><br />
+            {/if}
+
+            {if $CONST.DATA_TRACKBACK_APPROVED}
+                <br /><div class="serendipity_center serendipity_msg_notice">{$CONST.DATA_TRACKBACK_APPROVED|@sprintf:$CONST.TRACKBACK_APPROVED}</div><br />
+            {/if}
+
+            {if $CONST.DATA_COMMENT_DELETED}
+                <br /><div class="serendipity_center serendipity_msg_notice">{$CONST.DATA_COMMENT_DELETED|@sprintf:$CONST.COMMENT_DELETED}</div><br />
+            {/if}
+
+            {if $CONST.DATA_COMMENT_APPROVED}
+                <br /><div class="serendipity_center serendipity_msg_notice">{$CONST.DATA_COMMENT_APPROVED|@sprintf:$CONST.COMMENT_APPROVED}</div><br />
+            {/if}
+
+            <div class="serendipity_comments">
+                <br />
+                <a id="trackbacks"></a>
+                <div class="serendipity_commentsTitle">{$CONST.TRACKBACKS}</div>
+                    <div class="serendipity_center">
+                        <a rel="nofollow" style="font-weight: normal" href="{$entry.link_trackback}" onclick="alert('{$CONST.TRACKBACK_SPECIFIC_ON_CLICK|@escape:htmlall}'); return false;" title="{$CONST.TRACKBACK_SPECIFIC_ON_CLICK|@escape}">{$CONST.TRACKBACK_SPECIFIC}</a>
+                    </div>
+                    <br />
+                        {serendipity_printTrackbacks entry=$entry.id}
+            </div>
+        {/if}
+
+        {if $is_single_entry and not $is_preview}
+            <div class="serendipity_comments">
+                <br />
+                <a id="comments"></a>
+                <div class="serendipity_commentsTitle">{$CONST.COMMENTS}</div>
+                <div class="serendipity_center">{$CONST.DISPLAY_COMMENTS_AS}
+                {if $entry.viewmode eq $CONST.VIEWMODE_LINEAR}
+                    ({$CONST.COMMENTS_VIEWMODE_LINEAR} | <a href="{$entry.link_viewmode_threaded}#comments">{$CONST.COMMENTS_VIEWMODE_THREADED}</a>)
+                {else}
+                    (<a href="{$entry.link_viewmode_linear}#comments">{$CONST.COMMENTS_VIEWMODE_LINEAR}</a> | {$CONST.COMMENTS_VIEWMODE_THREADED})
+                {/if}
+                </div>
+                <br />
+                    {serendipity_printComments entry=$entry.id mode=$entry.viewmode}
+
+                {if $entry.is_entry_owner}
+                    {if $entry.allow_comments}
+                    <div class="serendipity_center">(<a href="{$entry.link_deny_comments}">{$CONST.COMMENTS_DISABLE}</a>)</div>
+                    {else}
+                    <div class="serendipity_center">(<a href="{$entry.link_allow_comments}">{$CONST.COMMENTS_ENABLE}</a>)</div>
+                    {/if}
+                {/if}
+                <a id="feedback"></a>
+
+                {foreach from=$comments_messagestack item="message"}
+                <div class="serendipity_center serendipity_msg_important">{$message}</div>
+                {/foreach}
+
+                {if $is_comment_added}
+
+                <br />
+                <div class="serendipity_center serendipity_msg_notice">{$CONST.COMMENT_ADDED}</div>
+
+                {elseif $is_comment_moderate}
+
+                <br />
+                <div class="serendipity_center serendipity_msg_notice">{$CONST.COMMENT_ADDED}<br />{$CONST.THIS_COMMENT_NEEDS_REVIEW}</div>
+
+                {elseif not $entry.allow_comments}
+
+                <br />
+                <div class="serendipity_center serendipity_msg_important">{$CONST.COMMENTS_CLOSED}</div>
+
+                {else}
+
+                <br />
+                <div class="serendipity_commentsTitle">{$CONST.ADD_COMMENT}</div>
+                {$COMMENTFORM}
+
+                {/if}
+            </div>
+        {/if}
+
+        {$entry.backend_preview}
+        {/foreach}
+    </div>
+    {foreachelse}
+    {if not $plugin_clean_page}
+        {$CONST.NO_ENTRIES_TO_PRINT}
+    {/if}
+    {/foreach}
+
+    <div class='serendipity_entryFooter' style="text-align: center">
+    {if $footer_prev_page}
+        <a href="{$footer_prev_page}">&laquo; {$CONST.PREVIOUS_PAGE}</a>&#160;&#160;
+    {/if}
+
+    {if $footer_info}
+        ({$footer_info})
+    {/if}
+
+    {if $footer_next_page}
+        <a href="{$footer_next_page}">&raquo; {$CONST.NEXT_PAGE}</a>
+    {/if}
+
+    {serendipity_hookPlugin hook="entries_footer"}
+    </div>
+<!-- ENTRIES END -->
diff --git a/templates/default/entries_archives.tpl b/templates/default/entries_archives.tpl
new file mode 100644 (file)
index 0000000..c92905f
--- /dev/null
@@ -0,0 +1,16 @@
+{foreach from=$archives item="archive"}
+<table cellspacing="4" cellpadding="4" border="0">
+    <tr>
+        <td colspan="4"><h2>{$archive.year}</h2></td>
+    </tr>
+    {foreach from=$archive.months item="month"}
+    <tr>
+        <td width="100"><img src="{serendipity_getFile file="img/graph_bar_horisontal.png"}" height="10" width="{math width=100 equation="count * width / max" count=$month.entry_count max=$max_entries format="%d"}" style="border: 1px solid #000000"></td>
+        <td>{$month.date|@formatTime:"%B"}</td>
+        <td>{$month.entry_count} {$CONST.ENTRIES}</td>
+        <td>({if $month.entry_count}<a href="{$month.link}">{/if}{$CONST.VIEW_FULL}{if $month.entry_count}</a>{/if})</td>
+        <td>({if $month.entry_count}<a href="{$month.link_summary}">{/if}{$CONST.VIEW_TOPICS}{if $month.entry_count}</a>{/if})</td>
+    </tr>
+    {/foreach}
+</table>
+{/foreach}
diff --git a/templates/default/entries_summary.tpl b/templates/default/entries_summary.tpl
new file mode 100644 (file)
index 0000000..62c6d62
--- /dev/null
@@ -0,0 +1,12 @@
+<div class='serendipity_date'>{$CONST.TOPICS_OF} {$dateRange.0|@formatTime:"%B, %Y"}</div>
+
+<div class="serendipity_entry">
+    <ul>
+    {foreach from=$entries item="entries"}
+        {foreach from=$entries.entries item="entry"}
+            <li><a href="{$entry.link}">{$entry.title}</a>
+                <br />{$CONST.POSTED_BY} {$entry.author} {$CONST.ON} {$entry.timestamp|@formatTime:DATE_FORMAT_ENTRY}</li>
+        {/foreach}
+    {/foreach}
+    </ul>
+</div>
diff --git a/templates/default/htmlarea.css b/templates/default/htmlarea.css
new file mode 100644 (file)
index 0000000..9db65fb
--- /dev/null
@@ -0,0 +1,44 @@
+body {
+    font-size: 10pt;
+    padding: 10px;
+    color: #333333;
+    background-color: #FAFFFF;
+    font-size: 9.5pt;
+    font-weight: normal;
+    font-family: verdana, arial, geneva, helvetica, sans-serif;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 9pt;
+}
+
diff --git a/templates/default/img/back.png b/templates/default/img/back.png
new file mode 100644 (file)
index 0000000..0fc771a
Binary files /dev/null and b/templates/default/img/back.png differ
diff --git a/templates/default/img/background.png b/templates/default/img/background.png
new file mode 100644 (file)
index 0000000..a318d7c
Binary files /dev/null and b/templates/default/img/background.png differ
diff --git a/templates/default/img/blank.gif b/templates/default/img/blank.gif
new file mode 100644 (file)
index 0000000..35d42e8
Binary files /dev/null and b/templates/default/img/blank.gif differ
diff --git a/templates/default/img/blank.png b/templates/default/img/blank.png
new file mode 100644 (file)
index 0000000..42ce15e
Binary files /dev/null and b/templates/default/img/blank.png differ
diff --git a/templates/default/img/delete.png b/templates/default/img/delete.png
new file mode 100644 (file)
index 0000000..fb4dfaa
Binary files /dev/null and b/templates/default/img/delete.png differ
diff --git a/templates/default/img/down.png b/templates/default/img/down.png
new file mode 100644 (file)
index 0000000..2789bce
Binary files /dev/null and b/templates/default/img/down.png differ
diff --git a/templates/default/img/emoticons/cool.png b/templates/default/img/emoticons/cool.png
new file mode 100644 (file)
index 0000000..87856f9
Binary files /dev/null and b/templates/default/img/emoticons/cool.png differ
diff --git a/templates/default/img/emoticons/cry.png b/templates/default/img/emoticons/cry.png
new file mode 100644 (file)
index 0000000..7119993
Binary files /dev/null and b/templates/default/img/emoticons/cry.png differ
diff --git a/templates/default/img/emoticons/eek.png b/templates/default/img/emoticons/eek.png
new file mode 100644 (file)
index 0000000..cada94a
Binary files /dev/null and b/templates/default/img/emoticons/eek.png differ
diff --git a/templates/default/img/emoticons/laugh.png b/templates/default/img/emoticons/laugh.png
new file mode 100644 (file)
index 0000000..97124bf
Binary files /dev/null and b/templates/default/img/emoticons/laugh.png differ
diff --git a/templates/default/img/emoticons/normal.png b/templates/default/img/emoticons/normal.png
new file mode 100644 (file)
index 0000000..4e3aed2
Binary files /dev/null and b/templates/default/img/emoticons/normal.png differ
diff --git a/templates/default/img/emoticons/sad.png b/templates/default/img/emoticons/sad.png
new file mode 100644 (file)
index 0000000..a1605e6
Binary files /dev/null and b/templates/default/img/emoticons/sad.png differ
diff --git a/templates/default/img/emoticons/smile.png b/templates/default/img/emoticons/smile.png
new file mode 100644 (file)
index 0000000..1a78732
Binary files /dev/null and b/templates/default/img/emoticons/smile.png differ
diff --git a/templates/default/img/emoticons/tongue.png b/templates/default/img/emoticons/tongue.png
new file mode 100644 (file)
index 0000000..6daa3c4
Binary files /dev/null and b/templates/default/img/emoticons/tongue.png differ
diff --git a/templates/default/img/emoticons/wink.png b/templates/default/img/emoticons/wink.png
new file mode 100644 (file)
index 0000000..e660744
Binary files /dev/null and b/templates/default/img/emoticons/wink.png differ
diff --git a/templates/default/img/forward.png b/templates/default/img/forward.png
new file mode 100644 (file)
index 0000000..5c8fe96
Binary files /dev/null and b/templates/default/img/forward.png differ
diff --git a/templates/default/img/graph_bar_horisontal.png b/templates/default/img/graph_bar_horisontal.png
new file mode 100644 (file)
index 0000000..6351577
Binary files /dev/null and b/templates/default/img/graph_bar_horisontal.png differ
diff --git a/templates/default/img/img_align_left.png b/templates/default/img/img_align_left.png
new file mode 100644 (file)
index 0000000..6ec5a7c
Binary files /dev/null and b/templates/default/img/img_align_left.png differ
diff --git a/templates/default/img/img_align_right.png b/templates/default/img/img_align_right.png
new file mode 100644 (file)
index 0000000..4830f23
Binary files /dev/null and b/templates/default/img/img_align_right.png differ
diff --git a/templates/default/img/img_align_top.png b/templates/default/img/img_align_top.png
new file mode 100644 (file)
index 0000000..93f9a00
Binary files /dev/null and b/templates/default/img/img_align_top.png differ
diff --git a/templates/default/img/minus.png b/templates/default/img/minus.png
new file mode 100644 (file)
index 0000000..fd3b8f2
Binary files /dev/null and b/templates/default/img/minus.png differ
diff --git a/templates/default/img/norights.png b/templates/default/img/norights.png
new file mode 100644 (file)
index 0000000..f2b27a5
Binary files /dev/null and b/templates/default/img/norights.png differ
diff --git a/templates/default/img/plus.png b/templates/default/img/plus.png
new file mode 100644 (file)
index 0000000..7cc031c
Binary files /dev/null and b/templates/default/img/plus.png differ
diff --git a/templates/default/img/rename.png b/templates/default/img/rename.png
new file mode 100644 (file)
index 0000000..252cb13
Binary files /dev/null and b/templates/default/img/rename.png differ
diff --git a/templates/default/img/s9y_banner_small.png b/templates/default/img/s9y_banner_small.png
new file mode 100644 (file)
index 0000000..b22087a
Binary files /dev/null and b/templates/default/img/s9y_banner_small.png differ
diff --git a/templates/default/img/scale.png b/templates/default/img/scale.png
new file mode 100644 (file)
index 0000000..066fb19
Binary files /dev/null and b/templates/default/img/scale.png differ
diff --git a/templates/default/img/somerights20.gif b/templates/default/img/somerights20.gif
new file mode 100644 (file)
index 0000000..656c579
Binary files /dev/null and b/templates/default/img/somerights20.gif differ
diff --git a/templates/default/img/up.png b/templates/default/img/up.png
new file mode 100644 (file)
index 0000000..9f09fff
Binary files /dev/null and b/templates/default/img/up.png differ
diff --git a/templates/default/img/xml.gif b/templates/default/img/xml.gif
new file mode 100644 (file)
index 0000000..3cefc36
Binary files /dev/null and b/templates/default/img/xml.gif differ
diff --git a/templates/default/img/zoom.png b/templates/default/img/zoom.png
new file mode 100644 (file)
index 0000000..e5b1e24
Binary files /dev/null and b/templates/default/img/zoom.png differ
diff --git a/templates/default/index.tpl b/templates/default/index.tpl
new file mode 100644 (file)
index 0000000..9763ef8
--- /dev/null
@@ -0,0 +1,54 @@
+{if $is_embedded != true}
+{if $is_xhtml}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+           "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+{else}
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+           "http://www.w3.org/TR/html4/loose.dtd">
+{/if}
+
+<html>
+<head>
+    <title>{$head_title|@default:$blogTitle} {if $head_subtitle} - {$head_subtitle}{/if}</title>
+    <meta http-equiv="Content-Type" content="text/html; charset={$head_charset}" />
+    <meta name="Powered-By" content="Serendipity v.{$head_version}" />
+    <link rel="stylesheet" type="text/css" href="{$head_link_stylesheet}" />
+    <link rel="alternate"  type="application/rss+xml" title="{$blogTitle} RSS feed" href="{$serendipityBaseURL}{$serendipityRewritePrefix}feeds/index.rss2" />
+    <link rel="alternate"  type="application/x.atom+xml"  title="{$blogTitle} Atom feed"  href="{$serendipityBaseURL}{$serendipityRewritePrefix}feeds/atom.xml" />
+{if $entry_id}
+    <link rel="pingback" href="{$serendipityBaseURL}comment.php?type=pingback&amp;entry_id={$entry_id}" />
+{/if}
+
+{serendipity_hookPlugin hook="frontend_header"}
+</head>
+
+<body>
+{else}
+{serendipity_hookPlugin hook="frontend_header"}
+{/if}
+
+{if $is_raw_mode != true}
+<div id="serendipity_banner">
+    <h1><a class="homelink1" href="{$serendipityBaseURL}">{$head_title|@default:$blogTitle}</a></h1>
+    <h2><a class="homelink2" href="{$serendipityBaseURL}">{$head_subtitle|@default:$blogDescription}</a></h2>
+</div>
+
+<table id="mainpane">
+    <tr>
+{if $leftSidebarElements > 0}
+        <td id="serendipityLeftSideBar" valign="top">{serendipity_printSidebar side="left"}</td>
+{/if}
+        <td id="content" valign="top">{$CONTENT}</td>
+{if $rightSidebarElements > 0}
+        <td id="serendipityRightSideBar" valign="top">{serendipity_printSidebar side="right"}</td>
+{/if}
+    </tr>
+</table>
+{/if}
+
+{$raw_data}
+
+{if $is_embedded != true}
+</body>
+</html>
+{/if}
diff --git a/templates/default/info.txt b/templates/default/info.txt
new file mode 100644 (file)
index 0000000..d336bd4
--- /dev/null
@@ -0,0 +1,4 @@
+Name: Serendipity v2.3
+Author: Tom Sommer
+Date: 12/8-2004
+Require Serendipity: 0.8
diff --git a/templates/default/plugin_calendar.tpl b/templates/default/plugin_calendar.tpl
new file mode 100644 (file)
index 0000000..996001a
--- /dev/null
@@ -0,0 +1,33 @@
+<table style="width: 100%" cellspacing="0" cellpadding="0" class="serendipity_calendar">
+    <tr>
+        <td class="serendipity_calendarHeader">
+{if $plugin_calendar_head.minScroll le $plugin_calendar_head.month_date}
+            <a title="{$CONST.BACK}" href="{$plugin_calendar_head.uri_previous}"><img alt="{$CONST.BACK}" src="{serendipity_getFile file="img/back.png"}" style="border: 0px" /></a>
+{/if}
+        </td>
+
+        <td colspan="5" class="serendipity_calendarHeader" style="text-align: center; vertical-align: bottom">
+            <b><a style="white-space: nowrap" href="{$plugin_calendar_head.uri_month}">{$plugin_calendar_head.month_date|formatTime:"%B '%y":false}</a></b>
+        </td>
+
+        <td class="serendipity_calendarHeader" style="text-align: right">
+{if $plugin_calendar_head.maxScroll ge $plugin_calendar_head.month_date}
+            <a title="{$CONST.FORWARD}" href="{$plugin_calendar_head.uri_next}"><img alt="{$CONST.FORWARD}" src="{serendipity_getFile file="img/forward.png"}" style="border: 0px" /></a>
+{/if}
+        </td>
+    </tr>
+
+    <tr>
+    {foreach from=$plugin_calendar_dow item="dow"}
+        <td scope="col" abbr="{$dow.date|@formatTime:"%A":false}" title="{$dow.date|@formatTime:"%A":false}" class="serendipity_weekDayName" align="center">{$dow.date|@formatTime:"%a":false}</td>
+    {/foreach}
+    </tr>
+
+    {foreach from=$plugin_calendar_weeks item="week"}
+        <tr class="serendipity_calendar">
+        {foreach from=$week.days item="day"}
+            <td class="serendipity_calendarDay {$day.classes}">{if isset($day.properties.Active) and $day.properties.Active}<a href="{$day.properties.Link}">{/if}{$day.name|@default:"&#160;"}{if isset($day.properties.Active) and $day.properties.Active}</a>{/if}</td>
+        {/foreach}
+        </tr>
+    {/foreach}
+</table>
diff --git a/templates/default/preview.png b/templates/default/preview.png
new file mode 100644 (file)
index 0000000..4bad5ac
Binary files /dev/null and b/templates/default/preview.png differ
diff --git a/templates/default/sidebar.tpl b/templates/default/sidebar.tpl
new file mode 100644 (file)
index 0000000..a0cd196
--- /dev/null
@@ -0,0 +1,12 @@
+{if $is_raw_mode}
+<div id="serendipity{$pluginside}SideBar">
+{/if}
+{foreach from=$plugindata item=item}
+    <div class="serendipitySideBarItem container_{$item.class}">
+        <h3 class="serendipitySideBarTitle {$item.class}">{$item.title}</h3>
+        <div class="serendipitySideBarContent">{$item.content}</div>
+    </div>
+{/foreach}
+{if $is_raw_mode}
+</div>
+{/if}
diff --git a/templates/default/style.css b/templates/default/style.css
new file mode 100644 (file)
index 0000000..faab58d
--- /dev/null
@@ -0,0 +1,349 @@
+h4,h3 {
+    margin: 0;
+}
+
+.serendipitySideBarContent input {
+    width: 150px;
+}
+
+#mainpane {
+    border-bottom: 1px solid #000000;
+    margin: auto;
+    width: 100%;
+    border-top: 0px;
+    background-color: #FFFFFF;
+    border-top: 1px solid #000000;
+}
+
+#content {
+    padding: 10px;
+    margin: 10px;
+    width: auto;
+}
+
+#serendipityRightSideBar {
+    width: 170px;
+    border-left: 1px dashed #000000;
+    padding: 10px;
+    vertical-align: top;
+}
+
+#serendipityLeftSideBar {
+    width: 170px;
+    border-right: 1px dashed #000000;
+    padding: 10px;
+    vertical-align: top;
+}
+
+body {
+    font-size: 10pt;
+    margin: 0;
+    background-color: #D2DFF2;
+    font-size: 10px;
+    font-family: verdana, arial, helvetica, sans-serif;
+    margin-bottom: 30px;
+}
+
+input, textarea {
+    font-size: 10pt;
+    font-family: verdana, arial, helvetica, sans-serif;
+}
+
+th, td {
+    font-size: 10pt;
+}
+
+p, td, th, div, span {
+    font-family: verdana, arial, helvetica, sans-serif;
+}
+
+#serendipity_banner {
+    margin: auto;
+    width: 100%;
+    height: 72px;
+    background-image: url({TEMPLATE_PATH}img/background.png);
+}
+
+a.homelink1,
+a.homelink1:hover,
+a.homelink1:link,
+a.homelink1:visited,
+#serendipity_banner h1 {
+    color: #FFFFFF;
+    font-family: Verdana, Arial, Geneva, Helvetica, sans-serif;
+    font-size : 20px;
+    padding-left:15px;
+    padding-top: 10px;
+    margin: 0px;
+    text-decoration: none;
+}
+
+a.homelink2,
+a.homelink2:hover,
+a.homelink2:link,
+a.homelink2:visited,
+#serendipity_banner h2 {
+    color: #FFFFFF;
+    padding-left: 15px;
+    font-size: 14px;
+    margin: 0px;
+    text-decoration: none;
+}
+
+.serendipity_title {
+    font-family: Verdana, Arial, Geneva, Helvetica, sans-serif;
+    font-size: medium;
+    font-weight: bold;
+    margin-top: 10px;
+    color: #333333;
+    padding-left: 5px;
+    border-bottom: 2px solid #36558C;
+}
+
+.serendipity_title a:link,
+.serendipity_title a:visited {
+   text-decoration: none;
+   border: 0;
+   color: #000000;
+}
+
+.serendipity_title a:hover {
+   color: #FF0000;
+}
+
+.serendipity_entry {
+    font-family:Verdana, Arial, Geneva, Helvetica, sans-serif;
+    color: #333333;
+    font-size: 9.5pt;
+    font-weight: normal;
+    padding-right: 10px;
+    width: 95%;
+    margin: auto;
+    margin-top: 10px;
+}
+
+.serendipity_entry_body_folded,
+.serendipity_entry_body_unfolded,
+.serendipity_entry_extended {
+    /* Inner blocks of .serendipity_entry, can be used for further customization */
+}
+
+.serendipity_entry_date {
+    margin: auto;
+}
+
+.serendipity_date {
+    font-family: Verdana, Arial, Geneva, Helvetica, sans-serif;
+    font-size: large;
+    color: #333333;
+    margin: 0;
+    margin-top: 20px;
+    text-align: right;
+}
+
+.serendipity_commentsTitle {
+    font-family: Verdana, Arial, Geneva, Helvetica, sans-serif;
+    font-size: small;
+    font-weight: bold;
+    margin-top: 10px;
+    color: #333333;
+    padding-left: 5px;
+    border-bottom: 2px solid #36558C;
+}
+
+div.serendipity_entryFooter {
+    font-family:Verdana, Arial, Geneva, Helvetica, sans-serif;
+    font-size: x-small;
+    color: #000000;
+    padding-top: 10px;
+    padding-bottom: 4px;
+    clear: both;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+td.serendipity_commentsLabel {
+    font-size: 12px;
+    font-weight: bold;
+    vertical-align: top;
+}
+
+td.serendipity_commentsValue input,
+td.serendipity_commentsValue select,
+td.serendipity_commentsValue textarea {
+    font-size: 12px;
+    padding: 2px;
+    width: 400px;
+}
+
+
+.serendipity_commentForm {
+    font-size: 13px;
+    color: #404040;
+    margin-bottom: 13px;
+    margin-right: 10px;
+    margin-left: 10px;
+    background-color: #FFFFFF;
+}
+.serendipity_comment {
+    font-size: 13px;
+    margin-top: 10px;
+    margin-right: 10px;
+    margin-left: 10px;
+    color: #404040;
+    padding: 3px;
+    background-color: #FFFFFF;
+    overflow: auto;
+}
+
+.serendipity_comment_source {
+    margin-top: 5px;
+    padding-left: 5px;
+    margin-bottom: 5px;
+    padding-bottom: 3px;
+    border-bottom: 2px solid #36558C;
+}
+
+a:link,
+a:visited,
+a:active {
+    color: #003366;
+    text-decoration: underline;
+}
+a:hover {
+    color: #000000;
+    text-decoration: underline;
+}
+
+table.serendipity_calendar td {
+    font-size:11px;
+    padding: 3px;
+}
+table.serendipity_calendar a {
+    color: #FF0000;
+    font-weight: bold;
+    text-decoration:none;
+}
+
+table.serendipity_calendar a:hover {
+    text-decoration: none;
+}
+
+td.serendipity_weekDayName {
+    font-size:11px;
+    font-weight:bold;
+}
+td.serendipity_calendarHeader a:link,
+td.serendipity_calendarHeader a:visited,
+td.serendipity_calendarHeader a:hover {
+    border: 0;
+    text-decoration: none;
+}
+
+div.serendipityPlug {
+    padding-left: 10px;
+}
+
+div.serendipityPlug a {
+    text-decoration: none;
+    border: 0px;
+}
+
+/* Container for each item on the side bar */
+div.serendipitySideBarItem {
+    padding-bottom: 12px;
+    margin-bottom: 12px;
+    font-size: 12px;
+    font-weight:normal;
+    border-bottom: solid 2px #36558C;
+}
+
+/* title of an individual item */
+.serendipitySideBarTitle {
+    margin: 0;
+    font-family:Verdana, Arial, Geneva, Helvetica, sans-serif;
+    color: #000000;
+    font-size: 12px;
+    font-weight:bold;
+    padding-left:2px;
+    padding-bottom:2px;
+}
+
+.serendipityImageButton {
+    cursor: pointer;
+}
+.serendipity_entry p {
+    margin: 0px;
+    padding-bottom: 0px;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid #DDDDDD;
+    background-color: #EFEFEF;
+    margin: 3px;
+    padding: 3px;
+    text-align: center;
+}
+
+.serendipity_imageComment_center {
+    margin: auto;
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    text-align: center;
+}
+
+.serendipity_imageComment_txt {
+    border-top: 1px solid #DDDDDD;
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 8pt;
+    text-align: center;
+}
+
+.serendipity_comments {
+}
+
+.serendipity_center {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center;
+}
+
+.serendipity_msg_important {
+    color: red;
+}
+
+.serendipity_msg_notice {
+    color: green;
+}
+
+.serendipity_entry_author_self {
+}
+
+.serendipity_comment_author_self .serendipity_comment_source {
+    background-color: #EEEEFF;
+}
diff --git a/templates/default/trackbacks.tpl b/templates/default/trackbacks.tpl
new file mode 100644 (file)
index 0000000..e8a9cae
--- /dev/null
@@ -0,0 +1,17 @@
+{foreach from=$trackbacks item=trackback}
+    <div class="serendipity_comment">
+        <div class="serendipity_commentBody">
+            <a href="{$trackback.url|@strip_tags}" {'blank'|@xhtml_target}>{$trackback.title}</a><br />
+            {$trackback.body|@strip_tags|@escape:all}
+        </div>
+        <div class="serendipity_comment_source">
+            <b>Weblog:</b> {$trackback.author|@default:$CONST.ANONYMOUS}<br />
+            <b>{$CONST.TRACKED}:</b> {$trackback.timestamp|@formatTime:'%b %d, %H:%M'}
+        {if $entry.is_entry_owner}
+            (<a href="{$serendipityBaseURL}comment.php?serendipity[delete]={$trackback.id}&amp;serendipity[entry]={$trackback.entry_id}&amp;serendipity[type]=trackbacks">{$CONST.DELETE}</a>)
+        {/if}
+        </div>
+    </div>
+{foreachelse}
+    <div class="serendipity_center">{$CONST.NO_TRACKBACKS}</div>
+{/foreach}
diff --git a/templates/idea/img/I_had_an_idea.jpg b/templates/idea/img/I_had_an_idea.jpg
new file mode 100644 (file)
index 0000000..cb61258
Binary files /dev/null and b/templates/idea/img/I_had_an_idea.jpg differ
diff --git a/templates/idea/img/bullet.gif b/templates/idea/img/bullet.gif
new file mode 100644 (file)
index 0000000..ac4ae17
Binary files /dev/null and b/templates/idea/img/bullet.gif differ
diff --git a/templates/idea/img/clock_face_messy_paint_runs.jpg b/templates/idea/img/clock_face_messy_paint_runs.jpg
new file mode 100644 (file)
index 0000000..ddcd9e3
Binary files /dev/null and b/templates/idea/img/clock_face_messy_paint_runs.jpg differ
diff --git a/templates/idea/img/quote.gif b/templates/idea/img/quote.gif
new file mode 100644 (file)
index 0000000..0003004
Binary files /dev/null and b/templates/idea/img/quote.gif differ
diff --git a/templates/idea/info.txt b/templates/idea/info.txt
new file mode 100644 (file)
index 0000000..00f34a2
--- /dev/null
@@ -0,0 +1,3 @@
+Name: Idea
+Author: Evan Nemerson
+Date: 01/07/2004
diff --git a/templates/idea/preview.png b/templates/idea/preview.png
new file mode 100644 (file)
index 0000000..41f29e2
Binary files /dev/null and b/templates/idea/preview.png differ
diff --git a/templates/idea/style.css b/templates/idea/style.css
new file mode 100644 (file)
index 0000000..f9ada90
--- /dev/null
@@ -0,0 +1,391 @@
+/* HTML Elements */
+
+body {
+  color: #999;
+  background: white;
+  font-family: verdana, arial, sans-serif;
+}
+
+a,
+a:link,
+a:visited {
+  color: #336666;
+  text-decoration: none;
+}
+
+a:active,
+a:hover {
+  color: #669999;
+  text-decoration: none;
+}
+
+img {
+  border: 0;
+}
+
+h3, h4 {
+  margin: 0;
+  padding: 0;
+}
+
+input[type="text"],
+input[type="password"],
+input[type="button"],
+input[type="submit"],
+select,
+textarea {
+  border: 1px #999 solid;
+  background-color: white;
+  color: #333;
+}
+
+input:focus,    input:hover,
+button:focus,   button:hover,
+submit:focus,   submit:hover,
+select:focus,   select:hover,
+textarea:focus, textarea:hover {
+  background-color: #eee;
+}
+
+input.radio,
+input[type="radio"],
+input[type="checkbox"] {
+  border: none;
+}
+
+blockquote {
+  border: 1px #999 dashed;
+  background-image: url(templates/idea/img/quote.gif);
+  background-repeat: no-repeat;
+  background-position: 0.5em 0.5em;
+  padding: 1em;
+  margin: 1em;
+  margin-right: 0;
+}
+
+ul {
+  list-style-image: url(templates/idea/img/bullet.gif);
+  list-style-type: circle;
+  padding-left: 1em;
+}
+
+::-moz-selection {
+  background: #eee;
+}
+
+::selection {
+  background: #eee;
+}
+
+/* Banner */
+
+#serendipity_banner {
+  background-image: url(templates/idea/img/I_had_an_idea.jpg);
+  background-repeat: no-repeat;
+  height: 150px;
+}
+
+#serendipity_banner h1 {
+  margin-left: 140px;
+  font-size: x-large;
+  font-variant: small-caps;
+  padding-top: 1em;
+}
+
+#serendipity_banner h2 {
+  margin-left: 140px;
+  font-size: small;
+  border-bottom: 1px #999 dashed;
+}
+
+a.homelink1,
+a.homelink1:hover,
+a.homelink1:link,
+a.homelink1:visited {
+  color: #999;
+  text-decoration: none;
+}
+
+a.homelink2,
+a.homelink2:hover,
+a.homelink2:link,
+a.homelink2:visited {
+  color: #999;
+  text-decoration: none;
+}
+
+/* Calendar */
+
+table.serendipity_calendar a,
+table.serendipity_calendar a:link,
+table.serendipity_calendar a:visited {
+  font-weight: bold;
+  font-style: italic;
+}
+
+table.serendipity_calendar a:hover {
+  background: #ccc;
+  color: #003366;
+}
+
+table.serendipity_calendar td {
+  font-size: x-small;
+  padding: 0.2em;
+  text-align: center;
+}
+
+td.serendipity_calendarHeader a,
+td.serendipity_calendarHeader a:link,
+td.serendipity_calendarHeader a:visited,
+td.serendipity_calendarHeader a:hover {
+  color: #003366;
+  font-weight: bold;
+  border: 0;
+  background: white;
+}
+
+/* Sidebars */
+
+#serendipityLeftSideBar,
+#serendipityRightSideBar {
+  display: block;
+  padding: 10px;
+  width: 11em;
+  vertical-align: top;
+}
+
+.serendipitySideBarTitle {
+  font-size: x-small;
+  color: #666;
+  font-weight: bolder;
+  line-height: 140%;
+  padding: 0.2em;
+  padding-left: 1em;
+  letter-spacing: 0.2em;
+  padding-bottom: 0;
+}
+
+#serendipityRightSideBar * .serendipitySideBarTitle {
+  border-left: 1px #666 dashed;
+}
+
+#serendipityLeftSideBar * .serendipitySideBarTitle {
+  border-right: 1px #666 dashed;
+}
+
+div.serendipitySideBarItem {
+  margin-bottom: 1em;
+  padding-bottom: 1em;
+}
+
+.serendipitySideBarContent {
+  color: #333;
+  border-top: 1px #666 dashed;
+  font-size: x-small;
+  padding-top: 0.5em;
+  padding-left: 1em;
+  padding-right: 1em;
+}
+
+#serendipityRightSideBar * .serendipitySideBarContent {
+  border-right: 1px #666 dashed;
+}
+
+#serendipityLeftSideBar * .serendipitySideBarContent {
+  border-left: 1px #666 dashed;
+}
+
+/* Entries */
+
+div.serendipity_Entry_Date {
+  padding-left: 1em;
+}
+
+.serendipity_date {
+  color: #999;
+  font-size: small;
+  font-weight: bold;
+  text-transform: lowercase;
+  margin-bottom: 0.7em;
+  border-bottom: 1px #999 dashed;
+  text-align: right;
+
+  background-image: url(templates/idea/img/clock_face_messy_paint_runs.jpg);
+  background-repeat: no-repeat;
+  background-position: bottom right;
+  height: 21px;
+  padding-right: 60px;
+  vertical-align: bottom;
+}
+
+.serendipity_title,
+.serendipity_Admin_title {
+  padding-bottom: 0.7em;
+  font-size: medium;
+  font-weight: bold;
+  text-transform: uppercase;
+}
+
+.serendipity_title a,
+.serendipity_title a:hover,
+.serendipity_title a:link,
+.serendipity_title a:visited,
+.serendipity_Admin_title a,
+.serendipity_Admin_title a:hover,
+.serendipity_Admin_title a:link,
+.serendipity_Admin_title a:visited {
+  color: #999;
+  text-decoration: none;
+}
+
+.serendipity_entry,
+.serendipity_admin {
+  font-size: small;
+  font-weight: normal;
+  line-height: 140%;
+  padding-left: 1em;
+}
+
+div.serendipity_entryFooter {
+  padding-top: 1em;
+  margin-bottom: 1em;
+  clear: both;
+  font-size: x-small;
+}
+
+/* Comments */
+
+.serendipity_comment {
+  border-left: double #999 thick;
+  font-size: small;
+  margin-left: 10px;
+  margin-right: 10px;
+  margin-top: 1em;
+  padding: 3px;
+  padding-bottom: 0;
+  overflow: auto;
+}
+
+.serendipity_commentBody {
+  padding-bottom: 1em;
+}
+
+.serendipity_commentsLabel {
+  font-size: small;
+}
+
+.serendipity_commentsTitle {
+  font-size: medium;
+  font-weight: bold;
+  text-transform: uppercase;
+}
+
+/* Admin */
+
+.serendipity_admin td {
+}
+
+/* Misc */
+
+#content {
+  width: 100%;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+    margin: 0px;
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+    text-align: center;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 9pt;
+    text-align: center;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+    padding: 0.3em;
+}
+
+.serendipity_admin_list_item_even {
+}
+
+.serendipity_admin_list_item_uneven {
+    background-color: #eee;
+}
+
+.serendipity_admin_filters {
+    border: 1px dashed;
+    background-color: #FFFFFF;
+    font-size: 10px;
+    margin-bottom: 10px;
+    padding: 2px;
+}
+
+.serendipity_admin_filters_headline {
+    border-bottom: 1px solid;
+}
+
+.serendipity_admin_sortorder {
+    font-size: 10px;
+    text-align: center;
+}
+
+.serendipity_admin_sortorder input,
+.serendipity_admin_sortorder select,
+.serendipity_admin_filters input,
+.serendipity_admin_filters select {
+    font-size: 10px;
+}
+
+.serendipity_comments {
+}
+
+.serendipity_center {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center;
+}
+
+.serendipity_msg_important {
+    color: red;
+}
+
+.serendipity_msg_notice {
+    color: green;
+}
+
+.serendipity_entry_author_self {
+}
+
+.serendipity_comment_author_self {
+  border-left: double #669999 thick;
+  color: #669999;
+}
diff --git a/templates/kubrick/comments.tpl b/templates/kubrick/comments.tpl
new file mode 100644 (file)
index 0000000..b82bc5f
--- /dev/null
@@ -0,0 +1,23 @@
+{foreach from=$comments item=comment name="comments"}
+    <a id="c{$comment.id}"></a>
+    <li class="{if $smarty.foreach.comments.iteration is odd}graybox{/if}" style="margin-left: {$comment.depth*20}px">
+        <cite>{if $comment.url}
+                <a href="{$comment.url}" target="_blank">{$comment.author|@default:$CONST.ANONYMOUS}</a>
+            {else}
+                {$comment.author|@default:$CONST.ANONYMOUS}
+            {/if}</cite> {$CONST.SAYS}:<br />
+        <small class="commentmetadata">
+            <a href="#c{$comment.id}" title="{$CONST.LINK_TO_COMMENT|sprintf:$comment.trace}">#{$comment.trace}</a>
+            {$comment.timestamp|@formatTime:$CONST.DATE_FORMAT_SHORT}
+            {if $entry.is_entry_owner}
+                (<a href="{$comment.link_delete}" onclick="return confirm('{$CONST.COMMENT_DELETE_CONFIRM|@sprintf:$comment.id:$comment.author}');">{$CONST.DELETE}</a>)
+            {/if}
+            {if $entry.allow_comments}
+                (<a href="#serendipity_CommentForm" onclick="document.getElementById('serendipity_replyTo').value='{$comment.id}';">{$CONST.REPLY}</a>)
+            {/if}
+        </small>
+        <p>{$comment.body}</p>
+    </li>
+{foreachelse}
+    <p class="nocomments">{$CONST.NO_COMMENTS}</p>
+{/foreach}
diff --git a/templates/kubrick/config.inc.php b/templates/kubrick/config.inc.php
new file mode 100644 (file)
index 0000000..9bd5030
--- /dev/null
@@ -0,0 +1,11 @@
+<?php # $Id$
+
+$probelang = dirname(__FILE__) . '/lang_' . $serendipity['lang'] . '.inc.php';
+if (file_exists($probelang)) {
+    include $probelang;
+} else {
+    include dirname(__FILE__) . '/lang_en.inc.php';
+}
+
+$serendipity['smarty']->assign('CONST', get_defined_constants());
+?>
\ No newline at end of file
diff --git a/templates/kubrick/entries.tpl b/templates/kubrick/entries.tpl
new file mode 100644 (file)
index 0000000..f6bd84d
--- /dev/null
@@ -0,0 +1,197 @@
+<!-- ENTRIES START -->
+    {serendipity_hookPlugin hook="entries_header" addData="$entry_id"}
+
+    {foreach from=$entries item="dategroup"}
+        {foreach from=$dategroup.entries item="entry"}
+        <div class="post">
+            <h2 id="post-{$entry.id}"><a href="{$entry.link}">{$entry.title}</a></h2>
+            {if !$is_single_entry}<small>{$entry.timestamp|@formatTime:DATE_FORMAT_ENTRY}</small>{/if}
+
+            {if $entry.categories}
+            <span class="categoryIcon">
+            {foreach from=$entry.categories item="category"}
+                {if $category.category_icon}
+                    <a href="{$category.category_link}"><img class="categoryIcon" title="{$category.category_name|@escape}{$category.category_description|@emptyPrefix}" alt="{$category.category_name|@escape}" src="{$category.category_icon}" /></a>
+                {/if}
+            {/foreach}
+            </span>
+            {/if}
+
+            <div class="entrytext">
+                <p>
+                {$entry.body}
+                {if $is_single_entry}
+                <a id="extended"></a>{$entry.extended}
+                {/if}
+                </p>
+
+                {if $entry.has_extended and not $is_single_entry and not $entry.is_extended}
+                <br /><a href="{$entry.link}#extended">{$CONST.VIEW_EXTENDED_ENTRY|@sprintf:$entry.title}</a><br /><br />
+                {/if}
+
+            <p class="postmetadata{if $is_single_entry} graybox{/if}">
+                <small>
+                {if $is_single_entry}
+
+                               {$CONST.ENTRY_POSTED_BY} <a href="{$entry.link_author}">{$entry.author}</a> {$CONST.ON} {$entry.timestamp|@formatTime:DATE_FORMAT_ENTRY} {$CONST.AT} {$entry.timestamp|@formatTime:"%H:%M"}.
+                {if $entry.categories}
+                   {$CONST.FILED_UNDER} {foreach from=$entry.categories item="category" name="categories"}<a href="{$category.category_link}">{$category.category_name|@escape}</a>{if not $smarty.foreach.categories.last}, {/if}{/foreach}.
+                {/if}
+                {if $entry.allow_comments}
+                    {$CONST.LEAVE_RESPONSE|sprintf:'<a href="#serendipity_CommentForm">':'</a>':"<a href=\"$entry[link]\">":'</a>'}
+                    {if $entry.moderate_comments}
+                        {$CONST.SUBJECT_TO_MODERATION}
+                    {/if}
+                {else}
+                    {$CONST.COMMENTS_CLOSED}
+                {/if}
+
+                {else}
+                {$CONST.POSTED_BY} <a href="{$entry.link_author}">{$entry.author}</a>
+                {if $entry.categories}
+                   {$CONST.IN} {foreach from=$entry.categories item="category" name="categories"}<a href="{$category.category_link}">{$category.category_name|@escape}</a>{if not $smarty.foreach.categories.last}, {/if}{/foreach}
+                {/if}
+
+                {if $dategroup.is_sticky}
+                    {$CONST.ON}
+                {else}
+                    {$CONST.AT}
+                {/if} <a href="{$entry.link}">{if $dategroup.is_sticky}{$entry.timestamp|@formatTime:DATE_FORMAT_ENTRY} {/if}{$entry.timestamp|@formatTime:'%H:%M'}</a>
+
+                {if $entry.has_comments}
+                    {if $use_popups}
+                        | <a href="{$entry.link_popup_comments}" onclick="window.open(this.href, 'comments', 'width=480,height=480,scrollbars=yes'); return false;">{$entry.label_comments} ({$entry.comments})</a>
+                    {else}
+                        | <a href="{$entry.link}#comments">{$entry.label_comments} ({$entry.comments})</a>
+                    {/if}
+                {/if}
+
+                {if $entry.has_trackbacks}
+                    {if $use_popups}
+                        | <a href="{$entry.link_popup_trackbacks}" onclick="window.open(this.href, 'comments', 'width=480,height=480,scrollbars=yes'); return false;">{$entry.label_trackbacks} ({$entry.trackbacks})</a>
+                    {else}
+                        | <a href="{$entry.link}#trackbacks">{$entry.label_trackbacks} ({$entry.trackbacks})</a>
+                    {/if}
+                {/if}
+
+                {if $entry.is_entry_owner and not $is_preview}
+                        | <a href="{$entry.link_edit}">{$CONST.EDIT_ENTRY}</a>
+                {/if}
+                {/if}
+                {$entry.add_footer}
+                </small>
+            </p>
+            </div>
+        </div>
+        <!--
+        <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+                 xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"
+                 xmlns:dc="http://purl.org/dc/elements/1.1/">
+        <rdf:Description
+                 rdf:about="{$entry.link_rdf}"
+                 trackback:ping="{$entry.link_trackback}"
+                 dc:title="{$entry.title}"
+                 dc:identifier="{$entry.rdf_ident}" />
+        </rdf:RDF>
+        -->
+        {$entry.plugin_display_dat}
+
+        {if $is_single_entry and not $use_popups and not $is_preview}
+            {if $CONST.DATA_UNSUBSCRIBED}
+                <br /><div class="serendipity_center serendipity_msg_notice">{$CONST.DATA_UNSUBSCRIBED|@sprintf:$CONST.UNSUBSCRIBE_OK}</div><br />
+            {/if}
+
+            {if $CONST.DATA_TRACKBACK_DELETED}
+                <br /><div class="serendipity_center serendipity_msg_notice">{$CONST.DATA_TRACKBACK_DELETED|@sprintf:$CONST.TRACKBACK_DELETED}</div><br />
+            {/if}
+
+            {if $CONST.DATA_TRACKBACK_APPROVED}
+                <br /><div class="serendipity_center serendipity_msg_notice">{$CONST.DATA_TRACKBACK_APPROVED|@sprintf:$CONST.TRACKBACK_APPROVED}</div><br />
+            {/if}
+
+            {if $CONST.DATA_COMMENT_DELETED}
+                <br /><div class="serendipity_center serendipity_msg_notice">{$CONST.DATA_COMMENT_DELETED|@sprintf:$CONST.COMMENT_DELETED}</div><br />
+            {/if}
+
+            {if $CONST.DATA_COMMENT_APPROVED}
+                <br /><div class="serendipity_center serendipity_msg_notice">{$CONST.DATA_COMMENT_APPROVED|@sprintf:$CONST.COMMENT_APPROVED}</div><br />
+            {/if}
+                <a id="trackbacks"></a><h3>{$CONST.TRACKBACKS}</h3>
+                    <div class="serendipity_center">
+                        <a style="font-weight: normal" href="{$entry.link_trackback}" onclick="alert('{$CONST.TRACKBACK_SPECIFIC_ON_CLICK|@escape:htmlall}'); return false;" title="{$CONST.TRACKBACK_SPECIFIC_ON_CLICK|@escape}">{$CONST.TRACKBACK_SPECIFIC}</a>
+                    </div>
+                    <ol class="commentlist">
+                        {serendipity_printTrackbacks entry=$entry.id}
+                    </ol>
+        {/if}
+
+        {if $is_single_entry and not $is_preview}
+                <a id="comments"></a><h3>{$CONST.COMMENTS}</h3>
+                <div class="serendipity_center">{$CONST.DISPLAY_COMMENTS_AS}
+                {if $entry.viewmode eq $CONST.VIEWMODE_LINEAR}
+                    ({$CONST.COMMENTS_VIEWMODE_LINEAR} | <a href="{$entry.link_viewmode_threaded}#comments">{$CONST.COMMENTS_VIEWMODE_THREADED}</a>)
+                {else}
+                    (<a href="{$entry.link_viewmode_linear}#comments">{$CONST.COMMENTS_VIEWMODE_LINEAR}</a> | {$CONST.COMMENTS_VIEWMODE_THREADED})
+                {/if}
+                </div>
+                <br />
+                <ol class="commentlist">
+                    {serendipity_printComments entry=$entry.id mode=$entry.viewmode}
+                </ol>
+
+                {if $entry.is_entry_owner}
+                    {if $entry.allow_comments}
+                    <div class="serendipity_center">(<a href="{$entry.link_deny_comments}">{$CONST.COMMENTS_DISABLE}</a>)</div>
+                    {else}
+                    <div class="serendipity_center">(<a href="{$entry.link_allow_comments}">{$CONST.COMMENTS_ENABLE}</a>)</div>
+                    {/if}
+                {/if}
+                <a id="feedback"></a>
+
+                {foreach from=$comments_messagestack item="message"}
+                <div class="serendipity_center serendipity_msg_important">{$message}</div>
+                {/foreach}
+
+                {if $is_comment_added}
+
+                <br />
+                <div class="serendipity_center serendipity_msg_notice">{$CONST.COMMENT_ADDED}</div>
+
+                {elseif $is_comment_moderate}
+
+                <br />
+                <div class="serendipity_center serendipity_msg_notice">{$CONST.COMMENT_ADDED}<br />{$CONST.THIS_COMMENT_NEEDS_REVIEW}</div>
+
+                {else}
+
+                <br />
+                <h3>{$CONST.ADD_COMMENT}</h3>
+                {$COMMENTFORM}
+
+                {/if}
+        {/if}
+
+        {$entry.backend_preview}
+        {/foreach}
+    {foreachelse}
+    {if not $plugin_clean_page}
+        {$CONST.NO_ENTRIES_TO_PRINT}
+    {/if}
+    {/foreach}
+
+    <div class="navigation" style="text-align: center">
+    {if $footer_prev_page}
+        <a href="{$footer_prev_page}">&laquo; {$CONST.PREVIOUS_PAGE}</a>&#160;&#160;
+    {/if}
+
+    {if $footer_info}
+        ({$footer_info})
+    {/if}
+
+    {if $footer_next_page}
+        <a href="{$footer_next_page}">&raquo; {$CONST.NEXT_PAGE}</a>
+    {/if}
+
+    {serendipity_hookPlugin hook="entries_footer"}
+    </div>
+<!-- ENTRIES END -->
diff --git a/templates/kubrick/images/kubrickbg.jpg b/templates/kubrick/images/kubrickbg.jpg
new file mode 100644 (file)
index 0000000..ca66cdc
Binary files /dev/null and b/templates/kubrick/images/kubrickbg.jpg differ
diff --git a/templates/kubrick/images/kubrickbgcolor.jpg b/templates/kubrick/images/kubrickbgcolor.jpg
new file mode 100644 (file)
index 0000000..b6875ba
Binary files /dev/null and b/templates/kubrick/images/kubrickbgcolor.jpg differ
diff --git a/templates/kubrick/images/kubrickbgwide.jpg b/templates/kubrick/images/kubrickbgwide.jpg
new file mode 100644 (file)
index 0000000..62d1864
Binary files /dev/null and b/templates/kubrick/images/kubrickbgwide.jpg differ
diff --git a/templates/kubrick/images/kubrickfooter.jpg b/templates/kubrick/images/kubrickfooter.jpg
new file mode 100644 (file)
index 0000000..d47c7a6
Binary files /dev/null and b/templates/kubrick/images/kubrickfooter.jpg differ
diff --git a/templates/kubrick/images/kubrickheader.jpg b/templates/kubrick/images/kubrickheader.jpg
new file mode 100644 (file)
index 0000000..806b363
Binary files /dev/null and b/templates/kubrick/images/kubrickheader.jpg differ
diff --git a/templates/kubrick/images/kubricklogo.jpg b/templates/kubrick/images/kubricklogo.jpg
new file mode 100644 (file)
index 0000000..b183e43
Binary files /dev/null and b/templates/kubrick/images/kubricklogo.jpg differ
diff --git a/templates/kubrick/images/kubrickportrait.png b/templates/kubrick/images/kubrickportrait.png
new file mode 100644 (file)
index 0000000..02ce70b
Binary files /dev/null and b/templates/kubrick/images/kubrickportrait.png differ
diff --git a/templates/kubrick/index.tpl b/templates/kubrick/index.tpl
new file mode 100644 (file)
index 0000000..8c96d5d
--- /dev/null
@@ -0,0 +1,59 @@
+{if $is_embedded != true}
+{if $is_xhtml}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+           "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+{else}
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+           "http://www.w3.org/TR/html4/loose.dtd">
+{/if}
+
+<html>
+<head>
+    <title>{$head_title|@default:$blogTitle} {if $head_subtitle} - {$head_subtitle}{/if}</title>
+    <meta http-equiv="Content-Type" content="text/html; charset={$head_charset}" />
+    <meta name="Powered-By" content="Serendipity v.{$head_version}" />
+    <link rel="stylesheet" type="text/css" href="{$serendipityHTTPPath}serendipity.css.php" />
+    <link rel="alternate"  type="application/rss+xml" title="{$blogTitle} RSS feed" href="{$serendipityBaseURL}{$serendipityRewritePrefix}feeds/index.rss2" />
+    <link rel="alternate"  type="application/x.atom+xml"  title="{$blogTitle} Atom feed"  href="{$serendipityBaseURL}{$serendipityRewritePrefix}feeds/atom.xml" />
+{if $entry_id}
+    <link rel="pingback" href="{$serendipityBaseURL}comment.php?type=pingback&amp;entry_id={$entry_id}" />
+{/if}
+
+{serendipity_hookPlugin hook="frontend_header"}
+</head>
+
+<body>
+{else}
+{serendipity_hookPlugin hook="frontend_header"}
+{/if}
+<div id="page">
+<div id="header" onclick="location.href='{$serendipityBaseURL}';" style="cursor: pointer;">
+    <div id="headerimg">
+        <h1>{$head_title|@default:$blogTitle}</h1>
+        <div class="description">{$head_subtitle|@default:$blogDescription}</div>
+    </div>
+</div>
+<hr />
+
+<div id="content" class="narrowcolumn">
+    {$CONTENT}
+</div>
+
+{if $rightSidebarElements > 0}
+    <div id="sidebar" valign="top">{serendipity_printSidebar side="right"}</div>
+{/if}
+
+<hr />
+<div id="footer">
+    <p>
+    {$CONST.PROUDLY_POWERED_BY} <a href="http://www.s9y.org">Serendipity {$serendipityVersion}</a>.<br />
+    Design is <a href="http://binarybonsai.com/kubrick/">Kubrick</a>, by Michael Heilemann, ported by <a href="http://blog.dreamcoder.dk">Tom Sommer</a>.
+    </p>
+</div>
+
+</div>
+
+{if $is_embedded != true}
+</body>
+</html>
+{/if}
diff --git a/templates/kubrick/info.txt b/templates/kubrick/info.txt
new file mode 100644 (file)
index 0000000..7c0e2ed
--- /dev/null
@@ -0,0 +1,3 @@
+Name: Kubrick 1.2.6 port
+Author: Tom Sommer
+Date: 12/8-2004
diff --git a/templates/kubrick/lang_de.inc.php b/templates/kubrick/lang_de.inc.php
new file mode 100644 (file)
index 0000000..f89c37c
--- /dev/null
@@ -0,0 +1,11 @@
+<?php # $Id$
+@define('REPLY', 'Antworten');
+@define('SAYS', 'schreibt');
+@define('LINK_TO_COMMENT', 'Link zu Kommentar #%d');
+@define('ENTRY_POSTED_BY', 'Dieser Eintrag wurde geschrieben von ');
+@define('FILED_UNDER', 'und ist abgelegt in');
+@define('LEAVE_RESPONSE', 'Sie können einen %sKommentar hinterlassen%s, oder ein %sTrackback%s von Ihrem eigenen Blog senden.');
+@define('SUBJECT_TO_MODERATION', 'Alle neuen Kommentare werden moderiert, bevor sie auf dieser Seite erscheinen.');
+@define('COMMENTS_CLOSED', 'Sowohl Kommentare als auch Trackbacks sind derzeit deaktiviert.');
+@define('PROUDLY_POWERED_BY', 'Dieses Weblog wird betrieben mit ');
+?>
\ No newline at end of file
diff --git a/templates/kubrick/lang_en.inc.php b/templates/kubrick/lang_en.inc.php
new file mode 100644 (file)
index 0000000..78061d2
--- /dev/null
@@ -0,0 +1,11 @@
+<?php # $Id$
+@define('REPLY', 'Reply');
+@define('SAYS', 'says');
+@define('LINK_TO_COMMENT', 'Link to comment #%d');
+@define('ENTRY_POSTED_BY', 'This entry was posted by');
+@define('FILED_UNDER', 'and is filed under');
+@define('LEAVE_RESPONSE', 'You can %sleave a response%s, or %strackback%s from your own blog.');
+@define('SUBJECT_TO_MODERATION', 'All new comments are subject to moderation before being displayed.');
+@define('COMMENTS_CLOSED', 'Both comments and trackbacks are currently closed.');
+@define('PROUDLY_POWERED_BY', 'My weblog is proudly powered by');
+?>
\ No newline at end of file
diff --git a/templates/kubrick/preview.png b/templates/kubrick/preview.png
new file mode 100644 (file)
index 0000000..8ba3a7e
Binary files /dev/null and b/templates/kubrick/preview.png differ
diff --git a/templates/kubrick/sidebar.tpl b/templates/kubrick/sidebar.tpl
new file mode 100644 (file)
index 0000000..967aa23
--- /dev/null
@@ -0,0 +1,8 @@
+<ul>
+{foreach from=$plugindata item=item}
+        <li>
+            <h2>{$item.title}</h2>
+            <p>{$item.content}</p>
+    </li>
+{/foreach}
+</ul>
diff --git a/templates/kubrick/style.css b/templates/kubrick/style.css
new file mode 100644 (file)
index 0000000..f0a8b2a
--- /dev/null
@@ -0,0 +1,625 @@
+/*   
+       Kubrick v1.2.5  for  WordPress 1.2
+        http://binarybonsai.com/kubrick/
+
+       This theme was designed and built by Michael Heilemann,
+       whose blog you will find at http://binarybonsai.com/
+
+       The CSS, XHTML and design is released under GPL:
+       http://www.opensource.org/licenses/gpl-license.php
+       
+
+       *** REGARDING IMAGES ***
+       All CSS that involves the use of images, can be found in the 'index.php' file.
+       This is to ease installation inside subdirectories of a server.
+
+       Have fun, and don't be afraid to contact me if you have questions.
+*/
+
+
+
+/* Begin Typography & Colors */
+body {
+       font-size: 62.5%; /* Resets 1em to 10px */
+       font-family: 'Lucida Grande', Verdana, Arial, Sans-Serif;
+       background-color: #d5d6d7;
+       color: #333;
+       text-align: center;
+    background: url("{TEMPLATE_PATH}images/kubrickbgcolor.jpg");
+    }
+
+#page {
+       background-color: white;
+       border: 1px solid #959596;
+       text-align: left;
+    background: url("{TEMPLATE_PATH}images/kubrickbg.jpg") repeat-y top; border: none;
+       }
+
+#header {
+       background-color: #73a0c5;
+    background: url("{TEMPLATE_PATH}images/kubrickheader.jpg") no-repeat bottom center;
+    margin: 0 !important; margin: 0 0 0 1px; padding: 1px; height: 198px; width: 758px;
+       }
+
+#content {
+       font-size: 1.2em
+       }
+
+img.categoryIcon {
+    float: right;
+    border: 0px;
+    margin: 5px;
+}
+
+#serendipityQuickSearchTermField {
+    width: 90%;
+}
+
+.widecolumn .entry p {
+       font-size: 1.05em;
+       }
+
+.narrowcolumn .entry, .widecolumn .entry {
+       line-height: 1.4em;
+       }
+
+.widecolumn {
+       line-height: 1.6em;
+       }
+       
+.narrowcolumn .postmetadata {
+       text-align: center;
+       }
+
+.graybox {
+       background-color: #f8f8f8;
+       border-top: 1px solid #ddd;
+       border-bottom: 1px solid #ddd;
+       }
+
+#footer {
+       background-color: #eee;
+    background: url("{TEMPLATE_PATH}/images/kubrickfooter.jpg") no-repeat bottom; border: none;
+       }
+
+small {
+       font-family: Arial, Helvetica, Sans-Serif;
+       font-size: 0.9em;
+       line-height: 1.5em;
+       }
+
+h1, h2, h3 {
+       font-family: 'Trebuchet MS', 'Lucida Grande', Verdana, Arial, Sans-Serif;
+       font-weight: bold;
+       }
+
+h1 {
+       font-size: 4em;
+       text-align: center;
+       }
+
+.description {
+       font-size: 1.2em;
+       text-align: center;
+       }
+
+h2 {
+       font-size: 1.6em;
+       }
+
+h2.pagetitle {
+       font-size: 1.6em;
+       }
+
+#sidebar h2 {
+       font-family: 'Lucida Grande', Verdana, Sans-Serif;
+       font-size: 1.2em;
+       }
+
+h3 {
+       font-size: 1.3em;
+       }
+
+h1, h1 a, h1 a:hover, h1 a:visited, .description {
+       text-decoration: none;
+       color: white;
+       }
+
+h2, h2 a, h2 a:visited, h3, h3 a, h3 a:visited {
+       color: #333;
+       }
+
+h2, h2 a, h2 a:hover, h2 a:visited, h3, h3 a, h3 a:hover, h3 a:visited, #sidebar h2, #wp-calendar caption, cite {
+       text-decoration: none;
+       }
+
+.entry p a:visited {
+       color: #b85b5a;
+       }
+
+.commentlist li, .serendipity_commentForm input, .serendipity_commentForm textarea {
+       font: 0.9em 'Lucida Grande', Verdana, Arial, Sans-Serif;
+       }
+       
+.commentlist li {
+       font-weight: bold;
+       }
+
+.commentlist cite, .commentlist cite a {
+       font-weight: bold;
+       font-style: normal;
+       font-size: 1.1em;
+       }
+
+.commentlist p {
+       font-weight: normal;
+       line-height: 1.5em;
+       text-transform: none;
+       }
+
+.serendipity_commentForm {
+       font-family: 'Lucida Grande', Verdana, Arial, Sans-Serif;
+       }
+
+.commentmetadata {
+       font-weight: normal;
+       }
+
+#sidebar {
+       font: 1em 'Lucida Grande', Verdana, Arial, Sans-Serif;
+       }
+
+small, #sidebar ul ul li, #sidebar ul ol li, .nocomments, .postmetadata, blockquote, strike {
+       color: #777;
+       }
+       
+code {
+       font: 1.1em 'Courier New', Courier, Fixed;
+       }
+
+acronym, abbr, span.caps
+{
+       font-size: 0.9em;
+       letter-spacing: .07em;
+       }
+
+a, h2 a:hover, h3 a:hover {
+       color: #06c;
+       text-decoration: none;
+       }
+
+a:hover {
+       color: #147;
+       text-decoration: underline;
+       }
+       
+#wp-calendar #prev a {
+       font-size: 9pt;
+       }
+
+#wp-calendar a {
+       text-decoration: none;
+       }
+
+#wp-calendar caption {
+       font: bold 1.3em 'Lucida Grande', Verdana, Arial, Sans-Serif;
+       text-align: center;
+       }
+
+#wp-calendar th {
+       font-style: normal;
+       text-transform: capitalize;
+       }
+/* End Typography & Colors */
+
+
+
+/* Begin Structure */
+body {
+       margin: 0;
+       padding: 0; 
+       }
+
+#page {
+       background-color: white;
+       margin: 20px auto;
+       padding: 0;
+       width: 760px;
+       }
+       
+#header {
+       padding: 0;
+       margin: 0 auto;
+       height: 200px;
+       width: 100%;
+       background-color: #73a0c5;
+       }
+
+#headerimg {
+       margin: 0;
+       height: 200px;
+       width: 100%;
+       }
+
+.narrowcolumn {
+       float: left;
+       padding: 0 0 20px 45px;
+       margin: 0px 0 0;
+       width: 450px;
+       }
+
+.widecolumn {
+       padding: 10px 0 20px 0;
+       margin: 5px 0 0 150px;
+       width: 450px;
+       }
+       
+.post {
+       margin: 0 0 40px;
+       text-align: justify;
+       }
+
+.widecolumn .post {
+       margin: 0;
+       }
+
+.narrowcolumn .postmetadata {
+       padding-top: 5px;
+       }
+
+.widecolumn .postmetadata {
+       margin: 30px 0;
+       }
+       
+#footer {
+       padding: 0;
+       margin: 0 auto;
+       width: 760px;
+       clear: both;
+       }
+
+#footer p {
+       margin: 0;
+       padding: 20px 0;
+       text-align: center;
+       }
+/* End Structure */
+
+
+
+/*     Begin Headers */
+h1 {
+       padding-top: 70px;
+       margin: 0;
+       }
+
+.description {
+       text-align: center;
+       }
+
+h2 {
+       margin: 30px 0 0;
+       }
+
+h2.pagetitle {
+       margin-top: 30px;
+       text-align: center;
+}
+
+#sidebar h2 {
+       margin: 5px 0 0;
+       padding: 0;
+       }
+
+h3 {
+       padding: 0;
+       margin: 30px 0 0;
+       }
+
+h3.comments {
+       padding: 0;
+       margin: 40px auto 20px ;
+       }
+/* End Headers */
+
+
+
+/* Begin Images */
+p img {
+       padding: 0;
+       max-width: 100%;
+       }
+
+/*     Using 'class="alignright"' on an image will (who would've
+       thought?!) align the image to the right. And using 'class="centered',
+       will of course center the image. This is much better than using
+       align="center", being much more futureproof (and valid) */
+       
+img.centered {
+       display: block;
+       margin-left: auto;
+       margin-right: auto;
+       }
+       
+img.alignright {
+       padding: 4px;
+       margin: 0 0 2px 7px;
+       display: inline;
+       }
+
+img.alignleft {
+       padding: 4px;
+       margin: 0 7px 2px 0;
+       display: inline;
+       }
+
+.alignright {
+       float: right;
+       }
+       
+.alignleft {
+       float: left
+       }
+/* End Images */
+
+
+
+/* Begin Lists
+
+       Special stylized non-IE bullets
+       Do not work in Internet Explorer, which merely default to normal bullets. */
+
+html>body .entry ul {
+       margin-left: 0px;
+       padding: 0 0 0 30px;
+       list-style: none;
+       padding-left: 10px;
+       text-indent: -10px;
+       } 
+
+html>body .entry li {
+       margin: 7px 0 8px 10px;
+       }
+
+.entry ul li:before, #sidebar ul ul li:before {
+       content: "\00BB \0020";
+       }
+
+.entry ol {
+       padding: 0 0 0 35px;
+       margin: 0;
+       }
+
+.entry ol li {
+       margin: 0;
+       padding: 0;
+       }
+
+.postmetadata ul, .postmetadata li {
+       display: inline;
+       list-style-type: none;
+       list-style-image: none;
+       }
+       
+#sidebar ul, #sidebar ul ol {
+       margin: 0;
+       padding: 0;
+       }
+
+#sidebar ul li {
+       list-style-type: none;
+       list-style-image: none;
+       margin-bottom: 15px;
+       }
+
+#sidebar ul p, #sidebar ul select {
+       margin: 5px 0 8px;
+       }
+
+#sidebar ul ul, #sidebar ul ol {
+       margin: 5px 0 0 10px;
+       }
+
+#sidebar ul ul ul, #sidebar ul ol {
+       margin: 0 0 0 10px;
+       }
+
+ol li, #sidebar ul ol li {
+       list-style: decimal outside;
+       }
+
+#sidebar ul ul li, #sidebar ul ol li {
+       margin: 3px 0 0;
+       padding: 0;
+       }
+/* End Entry Lists */
+
+
+
+/* Begin Form Elements */
+#searchform {
+       margin: 10px auto;
+       padding: 5px 3px; 
+       text-align: center;
+       }
+
+#sidebar #searchform #s {
+       width: 130px;
+       padding: 2px;
+       }
+
+#sidebar #searchsubmit {
+       padding: 1px;
+       }
+
+.entry form { /* This is mainly for password protected posts, makes them look better. */
+       text-align:center;
+       }
+
+select {
+       width: 130px;
+       }
+
+.serendipity_calendarDay {
+    text-align: center;
+}
+
+.serendipity_commentsValue input, 
+.serendipity_commentsValue select {
+       width: 100%;
+       padding: 2px;
+       }
+
+.serendipity_commentsValue textarea {
+       width: 100%;
+       padding: 2px;
+       }
+
+.serendipity_commentForm submit {
+       margin: 0;
+       float: right;
+       }
+/* End Form Elements */
+
+
+
+/* Begin Comments*/
+.graybox {
+       margin: 0;
+       padding: 10px;
+       }
+
+.commentlist {
+       padding: 0;
+       text-align: justify;
+       }
+
+.commentlist li {
+       margin: 15px 0 3px;
+       padding: 5px 10px 3px;
+       list-style: none;
+       }
+
+.commentlist p {
+       margin: 10px 5px 10px 0;
+       }
+
+.serendipity_commentForm {
+       margin: 5px 0;
+       }
+
+.serendipity_commentsLabel {
+    vertical-align:top;
+    }
+
+.nocomments {
+       text-align: center;
+       margin: 0;
+       padding: 0;
+       }
+
+.commentmetadata {
+       margin: 0;
+       display: block;
+       }
+/* End Comments */
+
+
+
+/* Begin Sidebar */
+#sidebar
+{
+       padding: 20px 0 10px 0;
+       margin-left: 545px;
+       width: 190px;
+       }
+
+#sidebar form {
+       margin: 0;
+       }
+/* End Sidebar */
+
+
+
+/* Begin Calendar */
+#wp-calendar {
+       empty-cells: show;
+       margin: 10px auto 0;
+       width: 155px;
+       }
+
+#wp-calendar #next a {
+       padding-right: 10px;
+       text-align: right;
+       }
+
+#wp-calendar #prev a {
+       padding-left: 10px;
+       text-align: left;
+       }
+
+#wp-calendar a {
+       display: block;
+       }
+
+#wp-calendar caption {
+       text-align: center;
+       width: 100%;
+       }
+
+#wp-calendar td {
+       padding: 3px 0;
+       text-align: center;
+       }
+
+#wp-calendar td.pad:hover { /* Doesn't work in IE */
+       background-color: #fff; }
+/* End Calendar */
+
+
+
+/* Begin Various Tags & Classes */
+acronym, abbr, span.caps {
+       cursor: help;
+       }
+
+acronym, abbr {
+       border-bottom: 1px dashed #999;
+       }
+
+blockquote {
+       margin: 15px 30px 0 10px;
+       padding-left: 20px;
+       border-left: 5px solid #ddd;
+       }
+
+blockquote cite {
+       margin: 5px 0 0;
+       display: block;
+       }
+
+.center {
+       text-align: center;
+       }
+
+hr {
+       display: none;
+       }
+
+a img {
+       border: none;
+       }
+
+.navigation {
+       display: block;
+       text-align: center;
+       margin-top: 10px;
+       margin-bottom: 60px;
+       }
+/* End Various Tags & Classes*/
+
+
+
+/* "Daisy, Daisy, give me your answer do. I'm half crazy all for the love of you.
+       It won't be a stylish marriage, I can't afford a carriage.
+       But you'll look sweet upon the seat of a bicycle built for two." */
diff --git a/templates/kubrick/trackbacks.tpl b/templates/kubrick/trackbacks.tpl
new file mode 100644 (file)
index 0000000..065ce11
--- /dev/null
@@ -0,0 +1,15 @@
+{foreach from=$trackbacks item=trackback name="trackbacks"}
+    <li class="{if $smarty.foreach.comments.iteration is odd}graybox{/if}">
+        <cite><a href="{$trackback.url|@strip_tags}" {'blank'|@xhtml_target}>{$trackback.title}</a></cite>
+        <p>{$trackback.body|@strip_tags|@escape:all}</p>
+        <small class="commentmetadata">
+            <b>Weblog:</b> {$trackback.author|@default:$CONST.ANONYMOUS}<br />
+            <b>{$CONST.TRACKED}:</b> {$trackback.timestamp|@formatTime:'%b %d, %H:%M'}
+        {if $entry.is_entry_owner}
+            (<a href="{$serendipityBaseURL}comment.php?serendipity[delete]={$trackback.id}&amp;serendipity[entry]={$trackback.entry_id}&amp;serendipity[type]=trackbacks">{$CONST.DELETE}</a>)
+        {/if}
+        </small>
+    </li>
+{foreachelse}
+    <p class="nocomments">{$CONST.NO_TRACKBACKS}</p>
+{/foreach}
diff --git a/templates/moz-modern/htmlarea.css b/templates/moz-modern/htmlarea.css
new file mode 100644 (file)
index 0000000..93ced34
--- /dev/null
@@ -0,0 +1,43 @@
+body {
+  font-family: Trebuchet MS, Tahoma, Verdana;
+  background-color: #BAC6D1;
+  color: #494F5D;
+  font-size: small;
+  font-weight: normal;
+  padding: 10px;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 9pt;
+}
+
diff --git a/templates/moz-modern/img/back.png b/templates/moz-modern/img/back.png
new file mode 100644 (file)
index 0000000..abd33b4
Binary files /dev/null and b/templates/moz-modern/img/back.png differ
diff --git a/templates/moz-modern/img/background.png b/templates/moz-modern/img/background.png
new file mode 100644 (file)
index 0000000..3a6dd1b
Binary files /dev/null and b/templates/moz-modern/img/background.png differ
diff --git a/templates/moz-modern/img/background2.png b/templates/moz-modern/img/background2.png
new file mode 100644 (file)
index 0000000..8d23a8a
Binary files /dev/null and b/templates/moz-modern/img/background2.png differ
diff --git a/templates/moz-modern/img/forward.png b/templates/moz-modern/img/forward.png
new file mode 100644 (file)
index 0000000..8292e79
Binary files /dev/null and b/templates/moz-modern/img/forward.png differ
diff --git a/templates/moz-modern/index.tpl b/templates/moz-modern/index.tpl
new file mode 100644 (file)
index 0000000..c2d5c87
--- /dev/null
@@ -0,0 +1,61 @@
+{if $is_embedded != true}
+{if $is_xhtml}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+           "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+{else}
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+           "http://www.w3.org/TR/html4/loose.dtd">
+{/if}
+
+<html>
+<head>
+    <title>{$head_title|@default:$blogTitle} {if $head_subtitle} - {$head_subtitle}{/if}</title>
+    <meta http-equiv="Content-Type" content="text/html; charset={$head_charset}" />
+    <meta name="Powered-By" content="Serendipity v.{$head_version}" />
+    <link rel="stylesheet" type="text/css" href="{$head_link_stylesheet}" />
+    <link rel="alternate"  type="application/rss+xml" title="{$blogTitle} RSS feed" href="{$serendipityBaseURL}{$serendipityRewritePrefix}feeds/index.rss2" />
+    <link rel="alternate"  type="application/x.atom+xml"  title="{$blogTitle} Atom feed"  href="{$serendipityBaseURL}{$serendipityRewritePrefix}feeds/atom.xml" />
+{if $entry_id}
+    <link rel="pingback" href="{$serendipityBaseURL}comment.php?type=pingback&amp;entry_id={$entry_id}" />
+{/if}
+
+{serendipity_hookPlugin hook="frontend_header"}
+</head>
+
+<body>
+{else}
+{serendipity_hookPlugin hook="frontend_header"}
+{/if}
+
+<div id="serendipity_banner">
+    <h1><a class="homelink1" href="{$serendipityBaseURL}">{$head_title|@default:$blogTitle}</a></h1>
+    <h2><a class="homelink2" href="{$serendipityBaseURL}">{$head_subtitle|@default:$blogDescription}</a></h2>
+</div>
+
+<div id="mainpane">
+{if $leftSidebarElements > 0}
+    <div id="serendipityLeftSideBar">{serendipity_printSidebar side="left"}</div>
+{/if}
+
+{if $rightSidebarElements < 1}
+    <div id="content_left">
+{elseif $leftSidebarElements < 1}
+    <div id="content_right">
+{else}
+    <div id="content">
+{/if}
+               {$CONTENT}
+               {$raw_data}
+       </div>
+
+{if $rightSidebarElements > 0}
+    <div id="serendipityRightSideBar">{serendipity_printSidebar side="right"}</div>
+{/if}
+
+    <div id="copyright">Powered by <a href="http://www.s9y.org/">serendipity</a>, Design by <a href="http://supergarv.de/">Garvin Hicking</a>. Smile, you're on the candid credit line!</div>
+</div>
+
+{if $is_embedded != true}
+</body>
+</html>
+{/if}
diff --git a/templates/moz-modern/info.txt b/templates/moz-modern/info.txt
new file mode 100644 (file)
index 0000000..6de4f43
--- /dev/null
@@ -0,0 +1,4 @@
+Name: Mozilla Modern Tribute
+Author: Garvin Hicking
+Date: 2004-03-02
+Require Serendipity: 0.8
diff --git a/templates/moz-modern/preview.png b/templates/moz-modern/preview.png
new file mode 100644 (file)
index 0000000..ddb2e13
Binary files /dev/null and b/templates/moz-modern/preview.png differ
diff --git a/templates/moz-modern/style.css b/templates/moz-modern/style.css
new file mode 100644 (file)
index 0000000..d40f9ff
--- /dev/null
@@ -0,0 +1,477 @@
+/*
+ *
+ * "Mozilla Modern Tribute" for serendipity (http://www.s9y.org/), by Garvin Hicking (http://supergarv.de/)
+ *
+ */
+
+/* HTML Elements */
+
+body {
+  background-color: #C7D0D9;
+  color: #FFFFFF;
+  font-family: Trebuchet MS, Tahoma, Verdana;
+  margin: 0px;
+  padding: 0px;
+  top: 0px;
+  left: 0px;
+}
+
+a,
+a:link,
+a:visited {
+  color: #5D616E;
+  text-decoration: underline;
+  font-weight: bold;
+  font-size: smaller;
+  padding-left: 3px;
+  padding-right: 3px;
+}
+
+a:active,
+a:hover {
+  color: #C7D0D9;
+  text-decoration: none;
+  background-color: #5D616E;
+}
+
+h3, h4 {
+  margin: 0px;
+}
+
+/* Banner */
+
+#serendipity_banner {
+  font-weight: bold;
+  padding-left: 15px;
+  border-bottom: 1px solid #8F9FB1;
+  border-top: 1px solid #8F9FB1;
+  background-image: url({TEMPLATE_PATH}img/background.png);
+  margin-top: 10px;
+  padding-top: 5px;
+}
+
+a.homelink1,
+a.homelink1:hover,
+a.homelink1:link,
+a.homelink1:visited,
+#serendipity_banner h1 {
+  color: #F8FAFE;
+  font-size: x-large;
+  margin-top: 5px;
+  margin-bottom: 1px;
+  border-bottom: 1px solid;
+  display: inline;
+  padding-right: 15px;
+  padding-left: 5px;
+  text-decoration: none;
+}
+
+a.homelink2,
+a.homelink2:hover,
+a.homelink2:link,
+a.homelink2:visited,
+#serendipity_banner h2 {
+  color: #494F5D;
+  font-size: small;
+  margin-top: 2px;
+  margin-bottom: 6px;
+  padding-left: 5px;
+  text-decoration: none;
+}
+
+#serendipity_banner h2 a:hover {
+  color: #FFFFFF;
+}
+
+/* Calendar */
+
+table.serendipity_calendar {
+  width: 130px;
+  margin-left: auto;
+  margin-right: auto;
+  margin-top: 5px;
+  margin-bottom: 5px;
+}
+
+table.serendipity_calendar a,
+table.serendipity_calendar a:link,
+table.serendipity_calendar a:visited,
+table.serendipity_calendar a:hover {
+  color: #999999;
+  font-size: x-small;
+}
+
+table.serendipity_calendar td {
+  font-size: x-small;
+  text-align: center;
+}
+
+td.serendipity_weekDayName {
+  font-size: x-small;
+  font-weight: bold;
+}
+
+td.serendipity_calendarHeader a:link,
+td.serendipity_calendarHeader a:visited,
+td.serendipity_calendarHeader a:hover {
+  border: 0;
+  text-decoration: none;
+}
+
+/* Sidebars */
+
+#mainpane {
+  position: absolute;
+  margin-top: 3px;
+  width: 99%;
+}
+
+#content {
+  margin-left: 210px;
+  margin-right: 210px;
+}
+
+#content_left {
+  margin-left: 210px;
+}
+
+#content_right {
+  margin-right: 210px;
+}
+
+#serendipityLeftSideBar {
+  width: 200px;
+  top: 0px;
+  position: absolute;
+  padding: 5px;
+  margin: 3px;
+  margin-top: 20px;
+  left: 2px;
+}
+
+#serendipityRightSideBar {
+  width: 200px;
+  position: absolute;
+  top: 0px;
+  right: 2px;
+  padding: 5px;
+  margin: 3px;
+  margin-top: 20px;
+}
+
+div.serendipitySideBarItem {
+  color: #666666;
+  font-size: small;
+  font-weight: normal;
+  margin-bottom: 12px;
+  padding-bottom: 12px;
+}
+
+.serendipity_commentsTitle,
+#serendipityLeftSideBar .serendipitySideBarTitle {
+  border-left: 10px solid #8F9FB1;
+  margin: 0;
+  font-size: smaller;
+  font-weight: bold;
+  padding-left: 4px;
+  text-transform: uppercase;
+  border-top: 1px solid white;
+  border-bottom: 1px solid white;
+  border-right: 1px solid white;
+  background-color: #BAC6D1;
+  color: white;
+  margin-bottom: 10px;
+  letter-spacing: 2px;
+  -moz-border-radius-topright: 8px;
+  -moz-border-radius-bottomright: 8px;
+}
+
+#serendipityLeftSideBar div.serendipitySideBarContent {
+  padding: 2px;
+  border-right: 5px solid #BAC6D1;
+  padding-bottom: 5px;
+  border-bottom: 1px solid #BAC6D1;
+  margin-right: 5px;
+  -moz-border-radius-bottomright: 15px;
+}
+
+#serendipityRightSideBar .serendipitySideBarTitle {
+  border-right: 10px solid #8F9FB1;
+  margin: 0px;
+  font-size: smaller;
+  font-weight: bold;
+  padding-right: 4px;
+  text-transform: uppercase;
+  text-align: right;
+  border-left: 1px solid white;
+  border-top: 1px solid white;
+  border-bottom: 1px solid white;
+  color: white;
+  margin-bottom: 10px;
+  background-color: #BAC6D1;
+  letter-spacing: 2px;
+  -moz-border-radius-topleft: 8px;
+  -moz-border-radius-bottomleft: 8px;
+}
+
+#serendipityRightSideBar div.serendipitySideBarContent {
+  padding: 2px;
+  border-left: 5px solid #BAC6D1;
+  padding-bottom: 5px;
+  border-bottom: 1px solid #BAC6D1;
+  margin-right: 5px;
+  margin-left: 5px;
+  padding-left: 10px;
+  -moz-border-radius-bottomleft: 15px;
+}
+
+/* Entries */
+
+div.serendipity_Entry_Date {
+  margin: 10px;
+  margin-bottom: 0px;
+  padding: 10px;
+  width: auto;
+}
+
+.serendipity_date {
+  color: #ffffff;
+  font-size: smaller;
+  font-weight: bold;
+  margin-top: 15px;
+  border-left: 5px solid #8F9FB1;
+  padding-left: 15px;
+  background-color: #BAC6D1;
+}
+
+.serendipity_title,
+.serendipity_Admin_title {
+  border-top: 1px solid #8F9FB1;
+  border-left: 5px solid #8F9FB1;
+  font-size: large;
+  font-weight: bold;
+  padding: 10px;
+  margin-top: 20px;
+  -moz-border-radius-topleft: 16px;
+}
+
+.serendipity_entry,
+.serendipity_admin {
+  background-color: #BAC6D1;
+  margin-top: 10px;
+  color: #494F5D;
+  font-size: small;
+  font-weight: normal;
+  padding: 10px;
+}
+
+div.serendipity_entryFooter {
+  clear: both;
+  font-size: x-small;
+  margin-top: 15px;
+  border-top: 1px solid #8F9FB1;
+  border-bottom: 2px solid #8F9FB1;
+  background-color: #C7D0D9;
+  padding-left: 2px;
+  color: #494F5D;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+/* Comments */
+
+.serendipityCommentForm input,
+.serendipityCommentForm textarea {
+  background-color: #C7D0D9;
+  border: 1px solid #8F9FB1;
+  padding: 2px;
+  font-family: Trebuchet MS, Tahoma, Verdana;
+  -moz-border-radius: 5px;
+}
+
+.serendipity_comment {
+  background-color: #C7D0D9;
+  color: #494F5D;
+  font-size: small;
+  margin-left: 2px;
+  margin-right: 2px;
+  padding: 6px;
+  overflow: auto;
+}
+
+.serendipity_comment a {
+  margin: 0px;
+  padding: 0px;
+}
+
+.serendipity_commentsLabel {
+  font-size: small;
+  vertical-align: top;
+  padding-top: 5px;
+}
+
+.serendipity_commentsValue textarea,
+.serendipity_commentsValue input {
+  width: 99%;
+}
+
+.serendipity_commentsTitle {
+  margin-top: 20px;
+  margin-bottom: 15px;
+}
+
+.serendipity_comment_source {
+  border-top: 1px solid #8F9FB1;
+  border-bottom: 2px solid #8F9FB1;
+  background-color: #BAC6D1;
+  padding-left: 5px;
+  font-size: smaller;
+  margin-top: 10px;
+}
+
+/* Misc */
+
+#serendipity_comment_page {
+}
+
+/* Admin */
+
+.serendipity_admin td {
+  color: #494F5D;
+}
+
+.serendipity_admin input,
+.serendipity_admin select,
+.serendipity_admin textarea,
+.serendipity_admin fieldset{
+  background-color: #C7D0D9;
+  border: 1px solid #8F9FB1;
+  padding: 2px;
+  font-family: Trebuchet MS, Tahoma, Verdana;
+  -moz-border-radius: 5px;
+}
+
+#serendipity_admin_entries_page #content,
+#serendipity_admin_image_page #content,
+#serendipity_admin_page #content {
+  padding-left: 35px;
+}
+
+#serendipity_admin_page, #serendipity_admin_image_page, #serendipity_admin_entries_page {
+}
+
+#serendipity_admin_entries_page #serendipityLeftSideBar,
+#serendipity_admin_page #serendipityLeftSideBar,
+#serendipity_admin_image_page #serendipityLeftSideBar
+ {
+ position: relative;
+}
+
+/* Copyright stuff */
+
+#copyright {
+  color: #C7D0D8;
+  text-align: center;
+  margin: 10px;
+}
+
+#copyright a {
+  color: #C7D0D8;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+    margin: 0px;
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+    text-align: center;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 9pt;
+    text-align: center;
+}
+
+.serendipity_admin_list_item_even {
+    background-color: #ffffff;
+}
+
+.serendipity_admin_list_item_uneven {
+    background-color: #E0E0E0;
+}
+
+.serendipity_admin_filters {
+    border: 1px dashed;
+    font-size: 12px;
+    margin-bottom: 10px;
+    padding: 2px;
+}
+
+.serendipity_admin_filters_headline {
+    border-bottom: 1px solid;
+}
+
+.serendipity_admin_sortorder {
+    text-align: center;
+}
+
+.serendipity_admin_sortorder input,
+.serendipity_admin_sortorder select,
+.serendipity_admin_filters input,
+.serendipity_admin_filters select {
+}
+
+.serendipity_comments {
+}
+
+.serendipity_center {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center;
+}
+
+div.serendipityPlug {
+    text-align: center;
+}
+
+.serendipity_msg_important {
+    color: red;
+}
+
+.serendipity_msg_notice {
+    color: green;
+}
+
+.serendipity_entry_author_self {
+}
+
+.serendipity_comment_author_self .serendipity_comment_source {
+    background-color: #FFFFFF;
+}
diff --git a/templates/mt-clean/info.txt b/templates/mt-clean/info.txt
new file mode 100644 (file)
index 0000000..fa410ef
--- /dev/null
@@ -0,0 +1,3 @@
+Name: MT - Clean
+Author: Evan Nemerson
+Date: 29/06/2004
diff --git a/templates/mt-clean/preview.png b/templates/mt-clean/preview.png
new file mode 100644 (file)
index 0000000..c57e9ad
Binary files /dev/null and b/templates/mt-clean/preview.png differ
diff --git a/templates/mt-clean/style.css b/templates/mt-clean/style.css
new file mode 100644 (file)
index 0000000..613ecd8
--- /dev/null
@@ -0,0 +1,291 @@
+/* HTML Elements */
+
+body {
+  color: #333;
+  background: white;
+}
+
+a,
+a:link,
+a:visited {
+  text-decoration: underline;
+  color: #003366;
+}
+
+a:active,
+a:hover {
+  color: #999999;
+}
+
+h3, h4 {
+  margin: 0;
+  padding: 0;
+}
+
+/* Banner */
+
+#serendipity_banner {
+  font-family: palatino, georgia, verdana, arial, sans-serif;
+  color: #333;
+  font-weight: normal;
+  padding: 15px;
+  border-top: 4px double #666;
+}
+
+a.homelink1,
+a.homelink1:hover,
+a.homelink1:link,
+a.homelink1:visited,
+#serendipity_banner h1 {
+  text-decoration: none;
+  color: #333;
+  font-size: xx-large;
+}
+
+a.homelink2,
+a.homelink2:hover,
+a.homelink2:link,
+a.homelink2:visited,
+#serendipity_banner h2 {
+  font-size: x-large;
+  text-decoration: none;
+  color: #333;
+  font-size: small;
+}
+
+/* Calendar */
+
+table.serendipity_calendar a,
+table.serendipity_calendar a:link,
+table.serendipity_calendar a:visited,
+table.serendipity_calendar a:hover {
+  color: #666;
+  font-size: x-small;
+}
+
+table.serendipity_calendar td {
+  line-height: 140%;
+  font-size: x-small;
+}
+
+td.serendipity_weekDayName {
+  font-size: x-small;
+  font-weight: bold;
+  line-height: 140%;
+}
+
+td.serendipity_calendarHeader a:link,
+td.serendipity_calendarHeader a:visited,
+td.serendipity_calendarHeader a:hover {
+  font-family: palatino, georgia, times new roman, serif;
+  color: #666600;
+  font-size: small;
+  letter-spacing: 0.3em;
+  text-transform: uppercase;
+  text-decoration: none;
+}
+
+/* Sidebars */
+
+#serendipityLeftSideBar,
+#serendipityRightSideBar {
+  display: block;
+  padding: 10px;
+  vertical-align: top;
+}
+
+.serendipitySideBarTitle {
+  font-family: palatino, georgia, times new roman, serif;
+  color: #666600;
+  font-size: small;
+  letter-spacing: 0.3em;
+  text-transform: uppercase;
+}
+
+div.serendipitySideBarItem {
+  font-family: palatino, georgia, times new roman, serif;
+  color: #333;
+  font-size: x-small;
+  font-weight: normal;
+  margin-bottom: 1em;
+  padding-bottom: 1em;
+}
+
+/* Entries */
+
+div.serendipity_Entry_Date {
+  margin: 10px;
+  padding: 10px;
+  width: auto;
+}
+
+.serendipity_date {
+  font-family: palatino, georgia, times new roman, serif;
+  font-size: large;
+  color: #333;
+  border-bottom: 1px solid #999;
+  margin-top: 10px;
+  font-weight: bold;
+}
+
+.serendipity_title,
+.serendipity_title a,
+.serendipity_title a:hover,
+.serendipity_title a:link,
+.serendipity_title a:visited,
+.serendipity_Admin_title,
+.serendipity_Admin_title a,
+.serendipity_Admin_title a:hover,
+.serendipity_Admin_title a:link,
+.serendipity_Admin_title a:visited {
+  font-family: palatino, georgia, times new roman, serif;
+  color: #666;
+  font-size: medium;
+  text-decoration: none;
+}
+
+.serendipity_entry,
+.serendipity_admin {
+  font-size: small;
+  font-weight: normal;
+  line-height: 140%;
+  padding: 10px;
+}
+
+div.serendipity_entryFooter {
+  clear: both;
+  font-size: x-small;
+}
+
+/* Comments */
+
+.serendipity_comment {
+  font-size: small;
+  margin-left: 10px;
+  margin-right: 10px;
+  padding: 3px;
+  overflow: auto;
+}
+
+.serendipity_comment_source {
+  border-bottom: 1px dotted #999;
+}
+
+.serendipity_commentsLabel {
+  font-size: small;
+}
+
+.serendipity_commentsTitle {
+  font-size: normal;
+  font-weight: bold;
+  text-transform: uppercase;
+}
+
+/* Admin */
+
+.serendipity_admin td {
+}
+
+/* Misc */
+
+#content {
+  width: 100%;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+    margin: 0px;
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+    text-align: center;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 9pt;
+    text-align: center;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+.serendipity_admin_list_item_even {
+    background-color: #ffffff;
+}
+
+.serendipity_admin_list_item_uneven {
+    background-color: #E0E0E0;
+}
+
+.serendipity_admin_filters {
+    border: 1px dashed;
+    background-color: #FFFFFF;
+    font-size: 10px;
+    margin-bottom: 10px;
+    padding: 2px;
+}
+
+.serendipity_admin_filters_headline {
+    border-bottom: 1px solid;
+}
+
+.serendipity_admin_sortorder {
+    font-size: 10px;
+    text-align: center;
+}
+
+.serendipity_admin_sortorder input,
+.serendipity_admin_sortorder select,
+.serendipity_admin_filters input,
+.serendipity_admin_filters select {
+    font-size: 10px;
+}
+
+.serendipity_comments {
+}
+
+.serendipity_center {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center;
+}
+
+.serendipity_msg_important {
+    color: red;
+}
+
+.serendipity_msg_notice {
+    color: green;
+}
+
+.serendipity_entry_author_self {
+}
+
+.serendipity_comment_author_self {
+    background-color: #f5f5f5;
+}
diff --git a/templates/mt-georgiablue/info.txt b/templates/mt-georgiablue/info.txt
new file mode 100644 (file)
index 0000000..1b940f7
--- /dev/null
@@ -0,0 +1,3 @@
+Name: MT - GeorgiaBlue
+Author: Evan Nemerson
+Date: 29/06/2004
diff --git a/templates/mt-georgiablue/preview.png b/templates/mt-georgiablue/preview.png
new file mode 100644 (file)
index 0000000..1ae6f12
Binary files /dev/null and b/templates/mt-georgiablue/preview.png differ
diff --git a/templates/mt-georgiablue/style.css b/templates/mt-georgiablue/style.css
new file mode 100644 (file)
index 0000000..d124515
--- /dev/null
@@ -0,0 +1,304 @@
+/* HTML Elements */
+
+body {
+  color: #333;
+  background: white;
+}
+
+a,
+a:link,
+a:visited {
+  color: #999966;
+  text-decoration: none;
+}
+
+a:active,
+a:hover {
+  color: #99CC66;
+}
+
+h3, h4 {
+  margin: 0;
+  padding: 0;
+}
+
+/* Banner */
+
+#serendipity_banner {
+  font-family: verdana, arial, sans-serif;
+  border-bottom: thin dotted white;
+  border-top: medium solid #99CCFF;
+  background: #336699;
+  padding: 15px;
+  letter-spacing: 0.2em;
+}
+
+a.homelink1,
+a.homelink1:hover,
+a.homelink1:link,
+a.homelink1:visited,
+#serendipity_banner h1 {
+  color: white;
+  text-decoration: none;
+  font-size: x-large;
+}
+
+a.homelink2,
+a.homelink2:hover,
+a.homelink2:link,
+a.homelink2:visited,
+#serendipity_banner h2 {
+  font-size: x-large;
+  text-decoration: none;
+  color: #99CCFF;
+  font-size: small;
+}
+
+/* Calendar */
+
+table.serendipity_calendar a,
+table.serendipity_calendar a:link,
+table.serendipity_calendar a:visited,
+table.serendipity_calendar a:hover {
+  color: #666;
+  font-size: x-small;
+}
+
+table.serendipity_calendar td {
+  line-height: 140%;
+  font-size: x-small;
+}
+
+td.serendipity_weekDayName {
+  font-size: x-small;
+}
+
+td.serendipity_calendarHeader a:link,
+td.serendipity_calendarHeader a:visited,
+td.serendipity_calendarHeader a:hover {
+  font-family: verdana, arial, sans-serif;
+  color: #003366;
+  font-size: x-small;
+  text-decoration: none;
+  font-weight: bold;
+}
+
+/* Sidebars */
+
+#serendipityLeftSideBar,
+#serendipityRightSideBar {
+  display: block;
+  padding: 10px;
+  vertical-align: top;
+}
+
+.serendipitySideBarTitle {
+  font-family: verdana, arial, sans-serif;
+  color: #666;
+  font-size: x-small;
+  font-weight: bold;
+  background-color: #eee;
+  line-height: 140%;
+  padding: 0.2em;
+  letter-spacing: 0.2em;
+  text-transform: uppercase;
+  text-align: center;
+}
+
+div.serendipitySideBarItem {
+  font-family: verdana, arial, sans-serif;
+  color: #333;
+  font-size: x-small;
+  font-weight: normal;
+  margin-bottom: 1em;
+  padding-bottom: 1em;
+}
+
+.serendipitySideBarContent {
+  padding-top: 0.5em;
+  padding-left: 0.7em;
+  padding-right: 0.7em;
+}
+
+/* Entries */
+
+div.serendipity_Entry_Date {
+}
+
+.serendipity_date {
+  font-family: georgia, verdana, arial, sans-serif;
+  font-size: small;
+  color: #666;
+  border: thin #999 solid;
+  padding: 0.5em;
+  margin-bottom: 1em;
+  padding-left: 1em;
+}
+
+.serendipity_title,
+.serendipity_title a,
+.serendipity_title a:hover,
+.serendipity_title a:link,
+.serendipity_title a:visited,
+.serendipity_Admin_title,
+.serendipity_Admin_title a,
+.serendipity_Admin_title a:hover,
+.serendipity_Admin_title a:link,
+.serendipity_Admin_title a:visited {
+  font-family: verdana, arial;
+  color: #003366;
+  font-weight: bold;
+  font-size: small;
+  text-transform: uppercase;
+  text-decoration: none;
+  padding-left: 0.7em;
+}
+
+.serendipity_entry,
+.serendipity_admin {
+  font-size: small;
+  font-weight: normal;
+  line-height: 140%;
+  padding: 1em;
+  padding-left: 1.5em;
+}
+
+div.serendipity_entryFooter {
+  padding-top: 1em;
+  color: #003366;
+  clear: both;
+  font-size: x-small;
+}
+
+/* Comments */
+
+.serendipity_comment {
+  font-size: small;
+  margin-left: 10px;
+  margin-right: 10px;
+  padding: 3px;
+  overflow: auto;
+}
+
+.serendipity_comment_source {
+  border-bottom: 1px dotted #999;
+}
+
+.serendipity_commentsLabel {
+  font-size: small;
+}
+
+.serendipity_commentsTitle {
+  font-size: normal;
+  font-weight: bold;
+  text-transform: uppercase;
+}
+
+/* Admin */
+
+.serendipity_admin td {
+}
+
+/* Misc */
+
+#content {
+  width: 100%;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+    margin: 0px;
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+    text-align: center;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 9pt;
+    text-align: center;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+.serendipity_admin_list_item_even {
+    background-color: #ffffff;
+}
+
+.serendipity_admin_list_item_uneven {
+    background-color: #eee;
+}
+
+.serendipity_admin_filters {
+    border: 1px dashed;
+    background-color: #FFFFFF;
+    font-size: 10px;
+    margin-bottom: 10px;
+    padding: 2px;
+}
+
+.serendipity_admin_filters_headline {
+    border-bottom: 1px solid;
+}
+
+.serendipity_admin_sortorder {
+    font-size: 10px;
+    text-align: center;
+}
+
+.serendipity_admin_sortorder input,
+.serendipity_admin_sortorder select,
+.serendipity_admin_filters input,
+.serendipity_admin_filters select {
+    font-size: 10px;
+}
+
+.serendipity_comments {
+}
+
+.serendipity_center {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center;
+}
+
+.serendipity_msg_important {
+    color: red;
+}
+
+.serendipity_msg_notice {
+    color: green;
+}
+
+.serendipity_entry_author_self {
+}
+
+.serendipity_comment_author_self {
+    background-color: #f5f5f5;
+}
diff --git a/templates/mt-gettysburg/info.txt b/templates/mt-gettysburg/info.txt
new file mode 100644 (file)
index 0000000..5562785
--- /dev/null
@@ -0,0 +1,3 @@
+Name: MT - GettysBurg
+Author: Evan Nemerson
+Date: 29/06/2004
diff --git a/templates/mt-gettysburg/preview.png b/templates/mt-gettysburg/preview.png
new file mode 100644 (file)
index 0000000..a8ce45f
Binary files /dev/null and b/templates/mt-gettysburg/preview.png differ
diff --git a/templates/mt-gettysburg/style.css b/templates/mt-gettysburg/style.css
new file mode 100644 (file)
index 0000000..f9d5527
--- /dev/null
@@ -0,0 +1,312 @@
+/* HTML Elements */
+
+body {
+  color: #333;
+  background: #eee;
+}
+
+#mainpane {
+  margin-left: 1em;
+  margin-bottom: 1em;
+  margin-right: 1em;
+  background: white;
+}
+
+a,
+a:link,
+a:visited {
+  text-decoration: none;
+  color: #003366;
+}
+
+a:active,
+a:hover {
+  color: #FFCC66;
+}
+
+h3, h4 {
+  margin: 0;
+  padding: 0;
+}
+
+/* Banner */
+
+#serendipity_banner {
+  margin-left: 1em;
+  margin-top: 1em;
+  margin-right: 1em;
+  font-family: georgia, verdana, arial, sans-serif;
+  border-left: thin white solid;
+  border-top: thin white solid;
+  border-right: thin white solid;
+  background: #003366;
+  padding: 15px;
+}
+
+a.homelink1,
+a.homelink1:hover,
+a.homelink1:link,
+a.homelink1:visited,
+#serendipity_banner h1 {
+  text-decoration: none;
+  color: white;
+  font-size: xx-large;
+}
+
+a.homelink2,
+a.homelink2:hover,
+a.homelink2:link,
+a.homelink2:visited,
+#serendipity_banner h2 {
+  font-size: x-large;
+  text-decoration: none;
+  color: white;
+  font-size: small;
+}
+
+/* Calendar */
+
+table.serendipity_calendar a,
+table.serendipity_calendar a:link,
+table.serendipity_calendar a:visited,
+table.serendipity_calendar a:hover {
+  color: #003366;
+  font-size: x-small;
+}
+
+table.serendipity_calendar td {
+  color: white;
+  line-height: 140%;
+  font-size: x-small;
+}
+
+td.serendipity_weekDayName {
+  color: white;
+  font-size: x-small;
+  font-weight: bold;
+  line-height: 140%;
+}
+
+td.serendipity_calendarHeader a:link,
+td.serendipity_calendarHeader a:visited,
+td.serendipity_calendarHeader a:hover {
+  color: white;
+  font-family: verdana, arial, sans-serif;
+  font-size: x-small;
+  font-weight: bold;
+  line-height: 140%;
+}
+
+/* Sidebars */
+
+#serendipityLeftSideBar,
+#serendipityRightSideBar {
+  vertical-align: top;
+  background: #999;
+  font-family: verdana, arial, sans-serif;
+  color: #333;
+}
+
+.serendipitySideBarTitle {
+  color: white;
+  font-size: small;
+  font-family: georgia, verdana, arial, sans-serif;
+  border-bottom: thin white dotted;
+  text-align: center;
+}
+
+div.serendipitySideBarItem {
+  font-family: palatino, georgia, times new roman, serif;
+  color: #333;
+  font-size: x-small;
+  font-weight: normal;
+  margin-bottom: 1em;
+  padding-bottom: 1em;
+}
+
+.serendipitySideBarContent {
+  padding: 0.7em;
+}
+
+/* Entries */
+
+div.serendipity_Entry_Date {
+  margin: 10px;
+  padding: 10px;
+  width: auto;
+}
+
+.serendipity_date {
+  font-family: georgia, verdana, arial, sans-serif;
+  font-size: small;
+  color: #666;
+  border-bottom: 1px solid #999;
+  margin-top: 10px;
+  font-weight: bold;
+}
+
+.serendipity_title,
+.serendipity_title a,
+.serendipity_title a:hover,
+.serendipity_title a:link,
+.serendipity_title a:visited,
+.serendipity_Admin_title,
+.serendipity_Admin_title a,
+.serendipity_Admin_title a:hover,
+.serendipity_Admin_title a:link,
+.serendipity_Admin_title a:visited {
+  padding-top: 1em;
+  padding-bottom: 1em;
+  font-family: verdana, arial, sans-serif;
+  color: black;
+  font-size: small;
+  text-decoration: none;
+  text-transform: uppercase;
+}
+
+.serendipity_entry,
+.serendipity_admin {
+  font-size: small;
+  font-weight: normal;
+  line-height: 140%;
+}
+
+div.serendipity_entryFooter {
+  clear: both;
+  color: black;
+  padding-top: 1em;
+  font-size: x-small;
+}
+
+/* Comments */
+
+.serendipity_comment {
+  font-size: small;
+  margin-left: 10px;
+  margin-right: 10px;
+  padding: 3px;
+  overflow: auto;
+}
+
+.serendipity_comment_source {
+  border-bottom: 1px dotted #999;
+}
+
+.serendipity_commentsLabel {
+  font-size: small;
+}
+
+.serendipity_commentsTitle {
+  font-size: normal;
+  font-weight: bold;
+  text-transform: uppercase;
+}
+
+/* Admin */
+
+.serendipity_admin td {
+}
+
+/* Misc */
+
+#content {
+  width: 100%;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+    margin: 0px;
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+    text-align: center;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 9pt;
+    text-align: center;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+.serendipity_admin_list_item_even {
+    background-color: #ffffff;
+}
+
+.serendipity_admin_list_item_uneven {
+    background-color: #E0E0E0;
+}
+
+.serendipity_admin_filters {
+    border: 1px dashed;
+    background-color: #FFFFFF;
+    font-size: 10px;
+    margin-bottom: 10px;
+    padding: 2px;
+}
+
+.serendipity_admin_filters_headline {
+    border-bottom: 1px solid;
+}
+
+.serendipity_admin_sortorder {
+    font-size: 10px;
+    text-align: center;
+}
+
+.serendipity_admin_sortorder input,
+.serendipity_admin_sortorder select,
+.serendipity_admin_filters input,
+.serendipity_admin_filters select {
+    font-size: 10px;
+}
+
+.serendipity_comments {
+}
+
+.serendipity_center {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center;
+}
+
+.serendipity_msg_important {
+    color: red;
+}
+
+.serendipity_msg_notice {
+    color: green;
+}
+
+.serendipity_entry_author_self {
+}
+
+.serendipity_comment_author_self {
+    background-color: #f5f5f5;
+}
diff --git a/templates/mt-plainjane/info.txt b/templates/mt-plainjane/info.txt
new file mode 100644 (file)
index 0000000..24ee536
--- /dev/null
@@ -0,0 +1,3 @@
+Name: MT - Plainjane
+Author: Evan Nemerson
+Date: 29/06/2004
diff --git a/templates/mt-plainjane/preview.png b/templates/mt-plainjane/preview.png
new file mode 100644 (file)
index 0000000..774b163
Binary files /dev/null and b/templates/mt-plainjane/preview.png differ
diff --git a/templates/mt-plainjane/style.css b/templates/mt-plainjane/style.css
new file mode 100644 (file)
index 0000000..3bc1480
--- /dev/null
@@ -0,0 +1,303 @@
+/* HTML Elements */
+
+body {
+  color: #666;
+  background: white;
+}
+
+a,
+a:link,
+a:visited {
+  color: #336666;
+  text-decoration: none;
+}
+
+a:active,
+a:hover {
+  color: #669999;
+}
+
+h3, h4 {
+  margin: 0;
+  padding: 0;
+}
+
+/* Banner */
+
+#serendipity_banner {
+  padding: 1em;
+}
+
+a.homelink1,
+a.homelink1:hover,
+a.homelink1:link,
+a.homelink1:visited,
+#serendipity_banner h1 {
+  font-family: verdana, arial, sans-serif;
+  font-size: x-large;
+  color: #cc9933;
+  text-decoration: none;
+}
+
+a.homelink2,
+a.homelink2:hover,
+a.homelink2:link,
+a.homelink2:visited,
+#serendipity_banner h2 {
+  font-family: verdana, arial, sans-serif;
+  color: #ccc;
+  font-size: x-small;
+  font-weight: bold;
+}
+
+/* Calendar */
+
+table.serendipity_calendar a,
+table.serendipity_calendar a:link,
+table.serendipity_calendar a:visited,
+table.serendipity_calendar a:hover {
+  color: #666;
+  font-size: x-small;
+}
+
+table.serendipity_calendar td {
+  line-height: 140%;
+  font-size: x-small;
+}
+
+td.serendipity_weekDayName {
+  font-size: x-small;
+}
+
+td.serendipity_calendarHeader a:link,
+td.serendipity_calendarHeader a:visited,
+td.serendipity_calendarHeader a:hover {
+  font-family: verdana, arial, sans-serif;
+  color: #003366;
+  font-size: x-small;
+  text-decoration: none;
+  font-weight: bold;
+}
+
+/* Sidebars */
+
+#serendipityLeftSideBar,
+#serendipityRightSideBar {
+  display: block;
+  padding: 10px;
+  vertical-align: top;
+}
+
+.serendipitySideBarTitle {
+  font-family: verdana, arial, sans-serif;
+  color: #999;
+  font-size: x-small;
+  font-weight: bold;
+  line-height: 140%;
+  padding: 0.2em;
+  letter-spacing: 0.2em;
+  text-transform: uppercase;
+  border-bottom: thin #666 dotted;
+  padding-left: 1em;
+}
+
+div.serendipitySideBarItem {
+  font-family: verdana, arial, sans-serif;
+  color: #333;
+  font-size: x-small;
+  font-weight: normal;
+  margin-bottom: 1em;
+  padding-bottom: 1em;
+}
+
+.serendipitySideBarContent {
+  padding-top: 0.5em;
+  padding-left: 1em;
+  padding-right: 1em;
+}
+
+/* Entries */
+
+div.serendipity_Entry_Date {
+  padding-left: 1em;
+}
+
+.serendipity_date {
+  font-family: verdana, arial, sans-serif;
+  font-size: normal;
+  color: #999;
+  font-weight: bold;
+  text-transform: uppercase;
+  padding-top: 1em;
+  border-bottom: thin #666 dotted;
+}
+
+.serendipity_title {
+  border-left: thin #666 dotted;
+  border-right: thin #666 dotted;
+}
+
+.serendipity_title a,
+.serendipity_title a:hover,
+.serendipity_title a:link,
+.serendipity_title a:visited,
+.serendipity_Admin_title,
+.serendipity_Admin_title a,
+.serendipity_Admin_title a:hover,
+.serendipity_Admin_title a:link,
+.serendipity_Admin_title a:visited {
+  font-family: verdana, arial;
+  font-size: small;
+  font-weight: bold;
+  color: #ccc;
+  text-transform: uppercase;
+  text-decoration: none;
+  padding-left: 0.7em;
+}
+
+.serendipity_entry,
+.serendipity_admin {
+  font-size: small;
+  font-weight: normal;
+  line-height: 140%;
+  padding: 1em;
+  padding-left: 0.7em;
+  border-left: thin #666 dotted;
+  border-right: thin #666 dotted;
+  border-bottom: thin #666 dotted;
+}
+
+div.serendipity_entryFooter {
+  padding-top: 1em;
+  clear: both;
+  font-size: x-small;
+}
+
+div.serendipity_entryFooter a {
+  text-decoration: underline;
+}
+
+/* Comments */
+
+.serendipity_comment {
+  font-size: small;
+  margin-left: 10px;
+  margin-right: 10px;
+  padding: 3px;
+  overflow: auto;
+}
+
+.serendipity_comment_source {
+  border-bottom: 1px dotted #999;
+}
+
+.serendipity_commentsLabel {
+  font-size: small;
+}
+
+.serendipity_commentsTitle {
+  font-size: normal;
+  font-weight: bold;
+  text-transform: uppercase;
+}
+
+/* Admin */
+
+.serendipity_admin td {
+}
+
+/* Misc */
+
+#content {
+  width: 100%;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+    margin: 0px;
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+    text-align: center;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 9pt;
+    text-align: center;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+.serendipity_admin_list_item_even {
+    background-color: #ffffff;
+}
+
+.serendipity_admin_list_item_uneven {
+    background-color: #eee;
+}
+
+.serendipity_admin_filters {
+    border: 1px dashed;
+    background-color: #FFFFFF;
+    margin-bottom: 10px;
+    padding: 2px;
+}
+
+.serendipity_admin_filters_headline {
+    border-bottom: 1px solid;
+}
+
+.serendipity_admin_sortorder {
+    text-align: center;
+}
+
+
+.serendipity_comments {
+}
+
+.serendipity_center {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center;
+}
+
+.serendipity_msg_important {
+    color: red;
+}
+
+.serendipity_msg_notice {
+    color: green;
+}
+
+.serendipity_entry_author_self {
+}
+
+.serendipity_comment_author_self .serendipity_comment_source {
+    border-bottom: 2px solid #cc9933;
+}
diff --git a/templates/mt-rusty/info.txt b/templates/mt-rusty/info.txt
new file mode 100644 (file)
index 0000000..b074fb5
--- /dev/null
@@ -0,0 +1,3 @@
+Name: MT - Rusty
+Author: Evan Nemerson
+Date: 29/06/2004
diff --git a/templates/mt-rusty/preview.png b/templates/mt-rusty/preview.png
new file mode 100644 (file)
index 0000000..64095de
Binary files /dev/null and b/templates/mt-rusty/preview.png differ
diff --git a/templates/mt-rusty/style.css b/templates/mt-rusty/style.css
new file mode 100644 (file)
index 0000000..f16c676
--- /dev/null
@@ -0,0 +1,323 @@
+/* HTML Elements */
+
+body {
+  background: #6c6457;
+}
+
+#mainpane {
+  margin-left: 1em;
+  margin-bottom: 1em;
+  margin-right: 1em;
+  background: white;
+  padding: 0px;
+  border-spacing: 0px;
+}
+
+a,
+a:link,
+a:visited {
+  color: #993300;
+}
+
+a:active,
+a:hover {
+  color: #FFCC66;
+}
+
+h3, h4 {
+  margin: 0;
+  padding: 0;
+}
+
+/* Banner */
+
+#serendipity_banner {
+  margin-left: 1em;
+  margin-top: 1em;
+  margin-right: 1em;
+  font-family: georgia, verdana, arial, sans-serif;
+  border-left: thin white dotted;
+  border-top: thin white dotted;
+  border-right: thin white dotted;
+  background: #993300;
+  padding: 15px;
+}
+
+a.homelink1,
+a.homelink1:hover,
+a.homelink1:link,
+a.homelink1:visited,
+#serendipity_banner h1 {
+  text-decoration: none;
+  color: white;
+  font-size: x-large;
+  font-weight: bold;
+}
+
+a.homelink2,
+a.homelink2:hover,
+a.homelink2:link,
+a.homelink2:visited,
+#serendipity_banner h2 {
+  font-family: verdana, arial, sans-serif;
+  color: white;
+  font-size: x-small;
+  font-weight: bold;
+  text-decoration: none;
+}
+
+/* Calendar */
+
+table.serendipity_calendar td {
+  color: white;
+  line-height: 140%;
+  font-size: x-small;
+}
+
+td.serendipity_weekDayName {
+  color: white;
+  font-size: x-small;
+  font-weight: bold;
+  line-height: 140%;
+}
+
+td.serendipity_calendarHeader a,
+td.serendipity_calendarHeader a:link,
+td.serendipity_calendarHeader a:active,
+td.serendipity_calendarHeader a:visited,
+td.serendipity_calendarHeader a:hover {
+  color: white;
+  font-family: verdana, arial, sans-serif;
+  font-size: x-small;
+  font-weight: bold;
+  line-height: 140%;
+}
+
+/* Sidebars */
+
+#serendipityLeftSideBar,
+#serendipityRightSideBar {
+  border: thin white dotted;
+  border-left: 0;
+  vertical-align: top;
+  background: #FF9933;
+  font-family: verdana, arial, sans-serif;
+  color: #333;
+  font-size: x-small;
+  padding: 0;
+  margin: 0;
+}
+
+.serendipitySideBarTitle {
+  color: white;
+  font-size: small;
+  font-family: verdana, arial, sans-serif;
+  border-bottom: thin white dotted;
+  text-align: center;
+  line-height: 140%;
+  margin-right: 0.5em;
+  font-weight: normal;
+  width: 11em;
+}
+
+div.serendipitySideBarItem {
+  font-family: palatino, georgia, times new roman, serif;
+  color: #333;
+  font-size: x-small;
+  font-weight: normal;
+  margin-bottom: 1em;
+  padding-bottom: 1em;
+}
+
+.serendipitySideBarContent {
+  padding: 0.7em;
+}
+
+.serendipitySideBarContent a,
+.serendipitySideBarContent a:link,
+.serendipitySideBarContent a:active,
+.serendipitySideBarContent a:visited,
+.serendipitySideBarContent a:hover
+{
+  text-decoration: none;
+}
+
+#content {
+  border: thin #333 dotted;
+}
+
+/* Entries */
+
+div.serendipity_Entry_Date {
+  margin: 10px;
+  padding: 10px;
+  width: auto;
+}
+
+.serendipity_date {
+  font-family: georgia, verdana, arial, sans-serif;
+  font-size: small;
+  color: #666;
+  border-bottom: 1px solid #999;
+  margin-top: 10px;
+  font-weight: bold;
+}
+
+.serendipity_title,
+.serendipity_title a,
+.serendipity_title a:hover,
+.serendipity_title a:link,
+.serendipity_title a:visited,
+.serendipity_Admin_title,
+.serendipity_Admin_title a,
+.serendipity_Admin_title a:hover,
+.serendipity_Admin_title a:link,
+.serendipity_Admin_title a:visited {
+  padding-top: 0.5em;
+  padding-bottom: 1em;
+  font-family: verdana, arial, sans-serif;
+  color: #003366;
+  font-size: small;
+  text-decoration: none;
+  text-transform: uppercase;
+}
+
+.serendipity_entry,
+.serendipity_admin {
+  color: #666;
+  font-size: small;
+  font-weight: normal;
+  line-height: 140%;
+}
+
+div.serendipity_entryFooter {
+  font-family: verdana, arial, sans-serif;
+  font-size: x-small;
+  color: #003366;
+  padding-top: 1em;
+}
+
+/* Comments */
+
+.serendipity_comment {
+  font-size: small;
+  margin-left: 10px;
+  margin-right: 10px;
+  padding: 3px;
+  overflow: auto;
+}
+
+.serendipity_comment_source {
+  border-bottom: 1px dotted #999;
+}
+
+.serendipity_commentsLabel {
+  font-size: small;
+}
+
+.serendipity_commentsTitle {
+  font-size: normal;
+  font-weight: bold;
+  text-transform: uppercase;
+}
+
+/* Admin */
+
+.serendipity_admin td {
+}
+
+/* Misc */
+
+#content {
+  width: 100%;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+    margin: 0px;
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+    text-align: center;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 9pt;
+    text-align: center;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+.serendipity_admin_list_item_even {
+    background-color: white;
+}
+
+.serendipity_admin_list_item_uneven {
+    background-color: #E0E0E0;
+}
+
+.serendipity_admin_filters {
+    border: 1px dashed;
+    background-color: #FFFFFF;
+    margin-bottom: 10px;
+    padding: 2px;
+}
+
+.serendipity_admin_filters_headline {
+    border-bottom: 1px solid;
+}
+
+.serendipity_admin_sortorder {
+    text-align: center;
+}
+
+
+.serendipity_comments {
+}
+
+.serendipity_center {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center;
+}
+
+.serendipity_msg_important {
+    color: red;
+}
+
+.serendipity_msg_notice {
+    color: green;
+}
+
+.serendipity_entry_author_self {
+}
+
+.serendipity_comment_author_self {
+    background-color: #f7f7f7;
+}
diff --git a/templates/mt-stormy/inactive.txt b/templates/mt-stormy/inactive.txt
new file mode 100644 (file)
index 0000000..27ed525
--- /dev/null
@@ -0,0 +1,2 @@
+This template is under maintainance. If you want to use it, delete this
+file.
diff --git a/templates/mt-stormy/info.txt b/templates/mt-stormy/info.txt
new file mode 100644 (file)
index 0000000..48ec378
--- /dev/null
@@ -0,0 +1,3 @@
+Name: mt-stormy
+Author: Sebastian Bergmann
+Date: 17/02/2004
diff --git a/templates/mt-stormy/style.css b/templates/mt-stormy/style.css
new file mode 100644 (file)
index 0000000..01aa5ae
--- /dev/null
@@ -0,0 +1,163 @@
+/* HTML Elements */
+
+body {
+  background: #333333;
+  margin: 0px 0px 10px 0px;
+}
+
+a,
+a:link,
+a:visited {
+  color: #99ccff;
+  text-decoration: none;
+}
+
+a:active,
+a:hover {
+  color: #99cc66;
+}
+
+h3, h4 {
+  margin: 0px;
+  padding: 0px;
+}
+
+/* Banner */
+
+#serendipity_banner {
+  background: #000000;
+  border-bottom: 1px dotted #999999;
+  border-top: 3px dotted #999999;
+  color: #ffffff;
+  font-family: Verdana, Arial, sans-serif;
+  font-weight: normal;
+  padding: 15px;
+  letter-spacing: .2em;
+}
+
+#serendipity_banner h1 {
+  font-size: x-large;
+  text-transform: uppercase;
+  text-decoration: none;
+}
+
+#serendipity_banner h2 {
+  font-size: x-small;
+  font-weight: bold;
+  letter-spacing: normal;
+  text-transform: none;
+}
+
+/* Calendar */
+
+table.serendipity_calendar a,
+table.serendipity_calendar a:link,
+table.serendipity_calendar a:visited,
+table.serendipity_calendar a:hover {
+}
+
+table.serendipity_calendar td {
+}
+
+td.serendipity_weekDayName {
+}
+
+td.serendipity_calendarHeader a:link,
+td.serendipity_calendarHeader a:visited,
+td.serendipity_calendarHeader a:hover {
+}
+
+/* Sidebars */
+
+#serendipityLeftSideBar,
+#serendipityRightSideBar {
+  display: block;
+  padding: 15px;
+  vertical-align: top;
+}
+
+.serendipitySideBarTitle {
+  color: #999999;
+  font-family: Verdana, Arial, sans-serif;
+  font-size: x-small;
+  font-weight: bold;
+  letter-spacing: .2em;
+  line-height: 140%;
+  margin-top: 10px;
+  padding: 2px;
+  text-align: left;
+  text-transform: uppercase;
+}
+
+div.serendipitySideBarItem {
+  background: #333333;
+  color: #003366;
+  font-family: Verdana, Arial, sans-serif;
+  font-size: x-small;
+  font-weight: normal;
+  line-height: 140%;
+  padding: 2px;
+}
+
+/* Entries */
+
+div.serendipity_Entry_Date {
+}
+
+.serendipity_date {
+}
+
+.serendipity_title,
+.serendipity_Admin_title {
+}
+
+.serendipity_entry,
+.serendipity_admin {
+}
+
+div.serendipity_entryFooter {
+  clear: both;
+}
+
+/* Comments */
+
+.serendipity_comment {
+  overflow: auto;
+}
+
+.serendipity_commentsLabel {
+}
+
+.serendipity_commentsTitle {
+}
+
+/* Admin */
+
+.serendipity_admin td {
+}
+
+/* Misc */
+
+#content {
+  width: 100%;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+.serendipity_msg_important {
+    color: red;
+}
+
+.serendipity_msg_notice {
+    color: green;
+}
+
+.serendipity_entry_author_self {
+}
+
+.serendipity_comment_author_self {
+    background-color: #efefef;
+}
diff --git a/templates/mt-trendy/htmlarea.css b/templates/mt-trendy/htmlarea.css
new file mode 100644 (file)
index 0000000..c3a7b6f
--- /dev/null
@@ -0,0 +1,44 @@
+body {
+  font-family: Verdana, Arial, sans-serif;
+  background-color: #333333;
+  color: #cccccc;
+  font-size: small;
+  font-weight: normal;
+  line-height: 140%;
+  padding: 10px;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 9pt;
+}
+
diff --git a/templates/mt-trendy/img/back.png b/templates/mt-trendy/img/back.png
new file mode 100644 (file)
index 0000000..e2c8a14
Binary files /dev/null and b/templates/mt-trendy/img/back.png differ
diff --git a/templates/mt-trendy/img/forward.png b/templates/mt-trendy/img/forward.png
new file mode 100644 (file)
index 0000000..03bc469
Binary files /dev/null and b/templates/mt-trendy/img/forward.png differ
diff --git a/templates/mt-trendy/info.txt b/templates/mt-trendy/info.txt
new file mode 100644 (file)
index 0000000..ea71f50
--- /dev/null
@@ -0,0 +1,3 @@
+Name: MT - Trendy
+Author: Sebastian Bergmann
+Date: 16/02/2004
diff --git a/templates/mt-trendy/preview.png b/templates/mt-trendy/preview.png
new file mode 100644 (file)
index 0000000..4c6585f
Binary files /dev/null and b/templates/mt-trendy/preview.png differ
diff --git a/templates/mt-trendy/style.css b/templates/mt-trendy/style.css
new file mode 100644 (file)
index 0000000..1ad590b
--- /dev/null
@@ -0,0 +1,287 @@
+/* HTML Elements */
+
+body {
+  background-color: #333333;
+  color: black;
+  font-family: Verdana, Arial, sans-serif;
+  margin: 0px;
+}
+
+a,
+a:link,
+a:visited {
+  color: #cccc66;
+  text-decoration: none;
+}
+
+a:active,
+a:hover {
+  color: #ffff99;
+}
+
+h3, h4 {
+  margin: 0;
+}
+
+/* Banner */
+
+#serendipity_banner {
+  font-weight: bold;
+  padding-left: 15px;
+}
+
+a.homelink1,
+a.homelink1:hover,
+a.homelink1:link,
+a.homelink1:visited,
+#serendipity_banner h1 {
+  color: #cc9933;
+  font-size: x-large;
+}
+
+a.homelink2,
+a.homelink2:hover,
+a.homelink2:link,
+a.homelink2:visited,
+#serendipity_banner h2 {
+  color: #cccccc;
+  font-size: small;
+  text-transform: none;
+  letter-spacing: none;
+}
+
+/* Calendar */
+
+table.serendipity_calendar a,
+table.serendipity_calendar a:link,
+table.serendipity_calendar a:visited,
+table.serendipity_calendar a:hover {
+  color: #999999;
+  font-size: x-small;
+}
+
+table.serendipity_calendar td {
+  font-size: x-small;
+}
+
+td.serendipity_weekDayName {
+  font-size: x-small;
+  font-weight: bold;
+  line-height: 140%;
+}
+
+td.serendipity_calendarHeader a:link,
+td.serendipity_calendarHeader a:visited,
+td.serendipity_calendarHeader a:hover {
+  border: 0;
+  text-decoration: none;
+}
+
+/* Sidebars */
+
+#serendipityLeftSideBar,
+#serendipityRightSideBar {
+  background-color: #333333;
+  color: #cccccc;
+  display: block;
+  margin-top: 35px;
+  padding: 10px;
+  vertical-align: top;
+}
+
+.serendipitySideBarTitle {
+  border-bottom: 1px solid #666666;
+  color: #cccccc;
+  margin: 0;
+  font-size: x-small;
+  font-weight: bold;
+  padding-left: 2px;
+  text-transform: uppercase;
+}
+
+div.serendipitySideBarItem {
+  color: #666666;
+  font-size: small;
+  font-weight: normal;
+  margin-bottom: 12px;
+  padding-bottom: 12px;
+}
+
+/* Entries */
+
+div.serendipity_Entry_Date {
+  margin: 10px;
+  padding: 10px;
+  width: auto;
+}
+
+.serendipity_date {
+  border-bottom: 1px solid #666666;
+  color: #999999;
+  font-size: normal;
+  font-weight: bold;
+  margin-top: 10px;
+  text-transform: uppercase;
+}
+
+.serendipity_title,
+.serendipity_Admin_title {
+  border: 1px solid #666666;
+  border-bottom: 0;
+  color: #cccccc;
+  font-size: small;
+  font-weight: bold;
+  padding: 10px;
+}
+
+.serendipity_entry,
+.serendipity_admin {
+  background-color: #333333;
+  border: 1px solid #666666;
+  border-top: 0;
+  color: #cccccc;
+  font-size: small;
+  font-weight: normal;
+  line-height: 140%;
+  padding: 10px;
+}
+
+div.serendipity_entryFooter {
+  clear: both;
+  color: #999999;
+  font-size: x-small;
+}
+
+/* Comments */
+
+.serendipity_comment {
+  border: 1px solid #666666;
+  color: #cccccc;
+  font-size: small;
+  margin-left: 10px;
+  margin-right: 10px;
+  padding: 3px;
+  overflow: auto;
+}
+
+.serendipity_commentsLabel {
+  color: #cccccc;
+  font-size: small;
+}
+
+.serendipity_commentsTitle {
+  color: #999999;
+  font-size: normal;
+  font-weight: bold;
+  text-transform: uppercase;
+}
+
+/* Admin */
+
+.serendipity_admin td {
+  color: #cccccc;
+}
+
+/* Misc */
+
+#content {
+  width: 100%;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+    margin: 0px;
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+    text-align: center;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 9pt;
+    text-align: center;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+.serendipity_admin_list_item_even {
+    background-color: #ffffff;
+}
+
+.serendipity_admin_list_item_uneven {
+    background-color: #E0E0E0;
+}
+
+.serendipity_admin_filters {
+    border: 1px dashed #FFF;
+    font-size: 10px;
+    margin-bottom: 10px;
+    padding: 2px;
+}
+
+.serendipity_admin_filters_headline {
+    border-bottom: 1px solid;
+}
+
+.serendipity_admin_sortorder {
+    font-size: 10px;
+    text-align: center;
+}
+
+.serendipity_admin_sortorder input,
+.serendipity_admin_sortorder select,
+.serendipity_admin_filters input,
+.serendipity_admin_filters select {
+    font-size: 10px;
+}
+
+
+.serendipity_comments {
+}
+
+.serendipity_center {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center;
+}
+
+.serendipity_msg_important {
+    color: red;
+}
+
+.serendipity_msg_notice {
+    color: green;
+}
+
+.serendipity_entry_author_self {
+}
+
+.serendipity_comment_author_self {
+    background-color: #000000;
+}
diff --git a/templates/mt3-chalkboard/info.txt b/templates/mt3-chalkboard/info.txt
new file mode 100644 (file)
index 0000000..03cae20
--- /dev/null
@@ -0,0 +1,3 @@
+Name: MT3 - Chalkboard
+Author: Kaustubh Srikanth
+Date: 31-06-2004
diff --git a/templates/mt3-chalkboard/preview.png b/templates/mt3-chalkboard/preview.png
new file mode 100644 (file)
index 0000000..a490c62
Binary files /dev/null and b/templates/mt3-chalkboard/preview.png differ
diff --git a/templates/mt3-chalkboard/style.css b/templates/mt3-chalkboard/style.css
new file mode 100644 (file)
index 0000000..337c48f
--- /dev/null
@@ -0,0 +1,433 @@
+body {
+    color: #FFFFFF;
+}
+
+h4,h3 {
+    margin: 0;
+}
+
+.serendipitySideBarContent input {
+    width: 175px;
+}
+
+#mainpane {
+    line-height: 140%;
+    text-align: left;
+    padding: 0px;
+    width: 700px;
+    background-color: #222;
+    border-left: 1px solid #FFFFFF;
+    border-right: 1px solid #FFFFFF;
+    border-bottom: 1px solid #FFFFFF;
+    margin: auto;
+}
+
+#serendipity_comment_page {
+    line-height: 140%;
+    text-align: left;
+    padding: 0px;
+    background-color: #222;
+    border: 1px solid #FFFFFF;
+    margin: auto;
+
+}
+
+#content {
+    width: 500px;
+    color: #ffffff;
+}
+
+#serendipityRightSideBar {
+    width: 150px;
+    padding: 10px;
+    background-color: #222;
+    vertical-align: top;
+}
+
+#serendipityLeftSideBar {
+    width: 150px;
+    padding: 10px;
+    vertical-align: top;
+    background-color: #222;
+}
+
+body {
+       margin: 0px 0px 20px 0px;
+       background-color: #6699CC;
+}
+
+input, textarea {
+    font-size: x-small;
+    font-family: verdana, arial, helvetica, sans-serif;
+}
+
+th, td {
+    font-size: x-small;
+}
+
+p, td, th, div, span {
+    font-family: verdana, arial, helvetica, sans-serif;
+}
+
+#serendipity_banner {
+    font-family: Georgia, 'Times New Roman', serif;
+    color: #FFFFFF;
+    background-color: #000000;
+    text-align: left;
+    border-bottom: 1px solid #FFFFFF;
+    border-left: 1px solid #FFFFFF;
+    border-right: 1px solid #FFFFFF;
+    width: 698px;
+    height: 76px;
+    margin: auto;
+}
+
+a.homelink1,
+a.homelink1:hover,
+a.homelink1:link,
+a.homelink1:visited,
+#serendipity_banner h1 {
+    color: #ffffff;
+    font-size: xx-large;
+    font-weight: normal;
+    padding-left:10px;
+    padding-top: 5px;
+    margin: 0px;
+    text-decoration: none;
+}
+
+a.homelink2,
+a.homelink2:hover,
+a.homelink2:link,
+a.homelink2:visited,
+#serendipity_banner h2 {
+    color: #FFFFFF;
+    padding-left: 10px;
+    font-size: small;
+    font-weight: normal;
+    margin: 0px;
+    text-decoration: none;
+}
+
+.serendipity_title {
+    color: #FFFFFF;
+    font-family: Georgia, 'Times New Roman', serif;
+    font-size: medium;
+    text-align: left;
+    font-weight: bold;
+    padding-left: 7px;
+}
+
+.serendipity_title a:link {
+    color: #ffffff;
+    text-decoration: none;
+}
+
+.serendipity_title a:visited {
+    color: #ffffff;
+    text-decoration: none;
+}
+
+.serendipity_title a:hover {
+    color: #ffffff;
+    text-decoration: none;
+}
+
+.serendipity_entry {
+    padding: 10px 15px 5px 7px;
+    background-color: #222;
+    color: #ffffff;
+    font-family: Helvetica, Arial, sans-serif;
+    font-size: small;
+    clear: both;
+}
+
+.serendipity_entry_body_folded,
+.serendipity_entry_body_unfolded,
+.serendipity_entry_extended {
+    /* Inner blocks of .serendipity_entry, can be used for further customization */
+}
+
+div.serendipity_Entry_Date {
+    padding-left: 5px;
+    width: auto;
+}
+
+.serendipity_date {
+    color: #FFFFFF;
+    font-family: Helvetica, Arial, sans-serif;
+    font-size: small;
+    text-align: left;
+    font-weight: bold;
+    margin-bottom: 10px;
+}
+
+.serendipity_commentsTitle {
+    display: block;
+    width: 100%;
+    color: #ffffff;
+    font-size: x-small;
+    font-weight: bold;
+    padding-left:8px;
+}
+
+div.serendipity_entryFooter {
+    color: #FFFFFF;
+    font-family: Helvetica, Arial, sans-serif;
+    font-size: x-small;
+    border-top: 1px solid #666666;
+    text-align: left;
+    margin-bottom: 25px;
+    line-height: normal;
+    padding: 3px;
+
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+TD.serendipity_commentsLabel {
+    font-weight: bold;
+    width: 10%;
+    vertical-align: top;
+}
+
+.serendipity_commentForm {
+    font-size:x-small;
+    color: #000000;
+    margin-bottom: 13px;
+    margin-right: 10px;
+    margin-left: 10px;
+}
+.serendipity_comment {
+    font-family: Helvetica, Arial, sans-serif;
+    margin-right: 10px;
+    margin-left: 10px;
+    color: #ffffff;
+    padding: 3px;
+    padding-bottom: 0;
+    font-size: small;
+    border-right: 1px dotted #BBB;
+    overflow: auto;
+}
+
+.serendipity_comment_source {
+    font-family: Helvetica, Arial, sans-serif;
+    margin-top: 5px;
+    padding-left: 5px;
+    margin-bottom: 5px;
+    font-weight: bold;
+    font-size: small;
+}
+
+td.serendipity_admin {
+    padding: 10px;
+}
+
+a {
+       text-decoration: underline;
+
+
+       }
+
+a:link {
+       color: #6699CC;
+       }
+
+a:visited {
+       color: #6699CC;
+       }
+
+a:active {
+       color: #6699CC;
+       }
+
+a:hover {
+       color: #99CC66;
+       }
+
+table.serendipity_calendar td {
+    font-size: x-small;
+    padding: 3px;
+}
+table.serendipity_calendar a {
+    font-weight: bold;
+    text-decoration:none;
+}
+
+table.serendipity_calendar a:hover {
+    text-decoration: none;
+}
+
+td.serendipity_weekDayName {
+    font-size: x-small;
+    font-weight:bold;
+}
+td.serendipity_calendarHeader a:link,
+td.serendipity_calendarHeader a:visited,
+td.serendipity_calendarHeader a:hover {
+    border: 0;
+    text-decoration: none;
+}
+div.serendipityPlug, div.serendipityPlug a {
+    font-size: 11px;
+    text-decoration: none;
+    border: 0px;
+    text-align: center;
+}
+
+/* Container for each item on the side bar */
+div.serendipitySideBarItem {
+       color: #ffffff;
+       font-family: Helvetica, Arial, sans-serif;
+       font-size: x-small;
+       text-align: left;
+       margin-bottom: 25px;
+       line-height: normal;
+       padding: 3px;}
+
+/* title of an individual item */
+.serendipitySideBarTitle {
+    color: #ffffff;
+    font-family: Helvetica, Arial, sans-serif;
+    font-size: x-small;
+    text-align: left;
+    font-weight: bold;
+    text-transform: uppercase;
+    letter-spacing: .3em;
+    padding-bottom: 5px;
+}
+
+.serendipityImageButton {
+    cursor: pointer;
+}
+
+td.serendipitySideBar {
+    font-size: x-small;
+    width: 200px;
+    padding: 10px;
+}
+
+div.serendipity_admin_title {
+    font-size: 22px;
+    font-weight: bold;
+    margin-bottom: 12px;
+    color: #ffffff;
+}
+div.serendipity_admin,
+.serendipityEntryEdit {
+    color: #ffffff;
+}
+
+div.serendipity_admin_list_title {
+    font-size: 12px;
+    font-weight: bold;
+    margin-bottom: 8px;
+}
+
+td.serendipity_admin_list_item {
+    border: dashed 1px #000000;
+}
+
+.serendipity_entry p {
+    margin: 0px;
+    padding-bottom: 10px;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+    margin: 0px;
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+    text-align: center;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: xx-small;
+    text-align: center;
+}
+
+.serendipity_admin_list_item_even {
+    background-color: #000000;
+}
+
+.serendipity_admin_list_item_uneven {
+    background-color: #222;
+}
+.serendipity_admin_filters {
+    border: 1px dashed;
+    font-size: 10px;
+    margin-bottom: 10px;
+    padding: 2px;
+}
+
+.serendipity_admin_filters_headline {
+    border-bottom: 1px solid;
+}
+
+.serendipity_admin_sortorder {
+    font-size: 10px;
+    text-align: center;
+}
+
+.serendipity_admin_sortorder input,
+.serendipity_admin_sortorder select,
+.serendipity_admin_filters input,
+.serendipity_admin_filters select {
+    font-size: 10px;
+}
+
+.serendipity_comments {
+}
+
+.serendipity_center {
+    text-align: center;
+    font-family: Helvetica, Arial, sans-serif;
+    font-size: small;
+}
+
+.serendipity_msg_important {
+    color: red;
+}
+
+.serendipity_msg_notice {
+    color: green;
+}
+
+.serendipity_entry_author_self {
+}
+
+.serendipity_comment_author_self {
+    border-right: 1px solid #6699CC;
+}
diff --git a/templates/mt3-gettysburg/info.txt b/templates/mt3-gettysburg/info.txt
new file mode 100644 (file)
index 0000000..636f25f
--- /dev/null
@@ -0,0 +1,3 @@
+Name: MT3 - Gettysburg
+Author: Kaustubh Srikanth & Tom Sommer
+Date: 31-06-2004
diff --git a/templates/mt3-gettysburg/preview.png b/templates/mt3-gettysburg/preview.png
new file mode 100644 (file)
index 0000000..883d3b8
Binary files /dev/null and b/templates/mt3-gettysburg/preview.png differ
diff --git a/templates/mt3-gettysburg/style.css b/templates/mt3-gettysburg/style.css
new file mode 100644 (file)
index 0000000..2a2b0ae
--- /dev/null
@@ -0,0 +1,405 @@
+h4,h3 {
+    margin: 0;
+}
+
+.serendipitySideBarContent input {
+    width: 175px;
+}
+
+#mainpane {
+    line-height: 140%;
+    text-align: left;
+    padding: 0px;
+    width: 700px;
+    background-color: #FFFFFF;
+    border: 1px solid #FFFFFF;
+    margin: auto;
+}
+
+#content {
+    width: 500px;
+}
+
+#serendipityRightSideBar {
+    width: 150px;
+    padding: 10px;
+    background-color: #FAFFFF;
+    vertical-align: top;
+}
+
+#serendipityLeftSideBar {
+    width: 150px;
+    padding: 10px;
+    vertical-align: top;
+    background-color: #FAFFFF;
+}
+
+body {
+       margin: 0px 0px 20px 0px;
+       background-color: #8FABBE;
+}
+
+input, textarea {
+    font-size: x-small;
+    font-family: verdana, arial, helvetica, sans-serif;
+}
+
+th, td {
+    font-size: x-small;
+}
+
+p, td, th, div, span {
+    font-family: verdana, arial, helvetica, sans-serif;
+}
+
+#serendipity_banner {
+    font-family: Verdana, Arial, sans-serif;
+    color: #FFFFFF;
+    background-color: #999999;
+    text-align: left;
+    border-bottom: 1px solid #FFFFFF;
+    width: 700px;
+    height: 72px;
+    margin: auto;
+}
+
+a.homelink1,
+a.homelink1:hover,
+a.homelink1:link,
+a.homelink1:visited,
+#serendipity_banner h1 {
+    color: #FFFFFF;
+    font-family: Verdana, Arial, Geneva, Helvetica, sans-serif;
+    font-size: xx-large;
+    font-weight: normal;
+    padding-left:10px;
+    padding-top: 5px;
+    margin: 0px;
+    text-decoration: none;
+}
+
+a.homelink2,
+a.homelink2:hover,
+a.homelink2:link,
+a.homelink2:visited,
+#serendipity_banner h2 {
+    color: #FFFFFF;
+    padding-left: 10px;
+    font-size: small;
+    font-weight: normal;
+    margin: 0px;
+    text-decoration: none;
+}
+
+.serendipity_title {
+    color: #666666;
+    font-family: Verdana, Arial, sans-serif;
+    font-size: small;
+    text-align: left;
+    font-weight: bold;
+}
+
+.serendipity_title a:link {
+    color: #666666;
+    text-decoration: none;
+}
+
+.serendipity_title a:visited {
+    color: #666666;
+    text-decoration: none;
+}
+
+.serendipity_title a:hover {
+    color: #666666;
+    text-decoration: none;
+}
+
+.serendipity_entry {
+       padding: 0px 15px 5px 0px;
+       background-color: #FFFFFF;
+       color: #666666;
+       font-family: Verdana, Arial, sans-serif;
+       font-size: x-small;
+       clear: both;
+}
+
+.serendipity_entry_body_folded,
+.serendipity_entry_body_unfolded,
+.serendipity_entry_extended {
+    /* Inner blocks of .serendipity_entry, can be used for further customization */
+}
+
+div.serendipity_Entry_Date {
+    padding-left: 15px;
+    width: auto;
+}
+
+.serendipity_date {
+    color: #666666;
+    font-family: Verdana, Arial, sans-serif;
+    font-size: x-small;
+    text-align: left;
+    font-weight: bold;
+    margin-bottom: 10px;
+}
+
+.serendipity_commentsTitle {
+    display: block;
+    width: 100%;
+    color: #404040;
+    font-size: small;
+    font-weight: bold;
+}
+
+div.serendipity_entryFooter {
+    color: #999999;
+    font-family: Verdana, Arial, sans-serif;
+    font-size: x-small;
+    border-top: 1px solid #999999;
+    text-align: left;
+    margin-bottom: 25px;
+    line-height: normal;
+    padding: 3px;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+td.serendipity_commentsLabel {
+    font-size: x-small;
+    font-weight: bold;
+    vertical-align: top;
+}
+
+td.serendipity_commentsValue input,
+td.serendipity_commentsValue select,
+td.serendipity_commentsValue textarea {
+    width: 99%;
+    border: 1px solid #333;
+    padding: 2px;
+}
+
+.serendipity_commentForm {
+    font-size:x-small;
+    color: #404040;
+    margin-bottom: 13px;
+    margin-right: 10px;
+    margin-left: 10px;
+    background-color: #FFFFFF;
+}
+.serendipity_comment {
+    font-size: x-small;
+    margin-right: 10px;
+    margin-left: 10px;
+    color: #404040;
+    padding: 3px;
+    background-color: #FFFFFF;
+    overflow: auto;
+}
+
+.serendipity_comment_source {
+    margin-top: 5px;
+    padding-left: 5px;
+    margin-bottom: 5px;
+}
+
+td.serendipity_admin {
+    padding: 10px;
+}
+
+a {
+       text-decoration: underline;
+
+
+       }
+
+a:link {
+       color: #8FABBE;
+       }
+
+a:visited {
+       color: #8FABBE;
+       }
+
+a:active {
+       color: #8FABBE;
+       }
+
+a:hover {
+       color: #006699;
+       }
+
+table.serendipity_calendar td {
+    font-size: x-small;
+    text-align: center;
+    padding: 3px;
+}
+table.serendipity_calendar a {
+    font-weight: bold;
+    text-decoration:underline;
+}
+
+table.serendipity_calendar a:hover {
+    text-decoration: none;
+}
+
+td.serendipity_weekDayName {
+    font-size: x-small;
+    font-weight:bold;
+}
+td.serendipity_calendarHeader a:link,
+td.serendipity_calendarHeader a:visited,
+td.serendipity_calendarHeader a:hover {
+    border: 0;
+    text-decoration: none;
+}
+div.serendipityPlug, div.serendipityPlug a {
+    font-size: 11px;
+    text-decoration: none;
+    border: 0px;
+}
+
+/* Container for each item on the side bar */
+div.serendipitySideBarItem {
+       color: #999999;
+       font-family: Verdana, Arial, sans-serif;
+       font-size: x-small;
+       text-align: left;
+       margin-bottom: 25px;
+       line-height: normal;
+       padding: 3px;}
+
+/* title of an individual item */
+.serendipitySideBarTitle {
+    color: #666666;
+    font-family: Verdana, Arial, sans-serif;
+    font-size: x-small;
+    text-align: center;
+    font-weight: bold;
+    text-transform: uppercase;
+    letter-spacing: .2em;
+    padding-bottom: 5px;
+}
+
+.serendipityImageButton {
+    cursor: pointer;
+}
+
+td.serendipitySideBar {
+    font-size: x-small;
+    width: 200px;
+    padding: 10px;
+}
+
+div.serendipity_admin_title {
+    font-size: 22px;
+    font-weight: bold;
+    margin-bottom: 12px;
+}
+
+div.serendipity_admin_list_title {
+    font-size: 12px;
+    font-weight: bold;
+    margin-bottom: 8px;
+}
+
+td.serendipity_admin_list_item {
+    padding: 15px;
+    border: dashed 1px #000000;
+}
+
+.serendipity_entry p {
+    margin: 0px;
+    padding-bottom: 10px;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+    margin: 0px;
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+    text-align: center;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: xx-small;
+    text-align: center;
+}
+
+.serendipity_admin_list_item_even {
+    background-color: #ffffff;
+}
+
+.serendipity_admin_list_item_uneven {
+    background-color: #E0E0E0;
+}
+.serendipity_admin_filters {
+    border: 1px dashed;
+    background-color: #FFFFFF;
+    font-size: 10px;
+    margin-bottom: 10px;
+    padding: 2px;
+}
+
+.serendipity_admin_filters_headline {
+    border-bottom: 1px solid;
+}
+
+.serendipity_admin_sortorder {
+    font-size: 10px;
+    text-align: center;
+}
+
+.serendipity_admin_sortorder input,
+.serendipity_admin_sortorder select,
+.serendipity_admin_filters input,
+.serendipity_admin_filters select {
+    font-size: 10px;
+}
+
+.serendipity_comments {
+}
+
+.serendipity_center {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center;
+}
+
+.serendipity_entry_author_self {
+}
+
+.serendipity_comment_author_self {
+    background-color: #f5f5f5;
+}
diff --git a/templates/mt3-independence/info.txt b/templates/mt3-independence/info.txt
new file mode 100644 (file)
index 0000000..d04b078
--- /dev/null
@@ -0,0 +1,3 @@
+Name: MT3 - Independence
+Author: Kaustubh Srikanth & Tom Sommer
+Date: 31-06-2004
diff --git a/templates/mt3-independence/preview.png b/templates/mt3-independence/preview.png
new file mode 100644 (file)
index 0000000..fe0e3b9
Binary files /dev/null and b/templates/mt3-independence/preview.png differ
diff --git a/templates/mt3-independence/style.css b/templates/mt3-independence/style.css
new file mode 100644 (file)
index 0000000..1f0e057
--- /dev/null
@@ -0,0 +1,428 @@
+h4,h3 {
+    margin: 0;
+}
+
+.serendipitySideBarContent input {
+    width: 175px;
+}
+
+#mainpane {
+    line-height: 140%;
+    text-align: left;
+    padding: 0px;
+    width: 700px;
+    background-color: #ffffff;
+    border: 1px solid #FFFFFF;
+    margin: auto;
+}
+
+#content {
+    width: 500px;
+}
+
+#serendipityRightSideBar {
+    width: 170px;
+    padding: 10px;
+    background-color: #ffffff;
+    vertical-align: top;
+}
+
+#serendipityLeftSideBar {
+    width: 130px;
+    padding: 10px;
+    vertical-align: top;
+    background-color: #ffffff;
+}
+
+body {
+    margin: 0px 0px 20px 0px;
+    background-color: #0F314E;
+}
+
+input, textarea {
+    font-size: x-small;
+    font-family: verdana, arial, helvetica, sans-serif;
+}
+
+td, td {
+    font-size: x-small;
+}
+
+p, td, th, div, span {
+    font-family: verdana, arial, helvetica, sans-serif;
+}
+
+#serendipity_banner {
+    font-family: Georgia, 'Times New Roman', serif;
+    color: #FFFFFF;
+    background-color: #B22222;
+    text-align: left;
+    border-bottom: 1px solid #FFFFFF;
+    width: 700px;
+    height: 72px;
+    margin: auto;
+}
+
+a.homelink1,
+a.homelink1:hover,
+a.homelink1:link,
+a.homelink1:visited,
+#serendipity_banner h1 {
+    color: #ffffff;
+    font-size: xx-large;
+    font-weight: normal;
+    padding-left: 10px;
+    padding-top: 2px;
+    margin: 0px;
+    text-decoration: none;
+}
+
+a.homelink2,
+a.homelink2:hover,
+a.homelink2:link,
+a.homelink2:visited,
+#serendipity_banner h2 {
+    color: #FFFFFF;
+    padding-left: 10px;
+    font-size: small;
+    font-weight: normal;
+    margin: 0px;
+    text-decoration: none;
+}
+
+.serendipity_title {
+    color: #333;
+    font-family: 'Trebuchet MS', Verdana, sans-serif;
+    font-size: small;
+    text-align: left;
+    font-weight: bold;
+    margin-bottom: 0px;
+}
+
+.serendipity_title a:link,
+.serendipity_title a:visited,
+.serendipity_title a:hover {
+    color: #333;
+    text-decoration: none;
+}
+
+.serendipity_entry {
+    background-color: #ffffff;
+    color: #666666;
+    font-family: 'Trebuchet MS', Verdana, sans-serif;
+    font-size: small;
+    clear:both;
+}
+
+.serendipity_entry_body_folded,
+.serendipity_entry_body_unfolded,
+.serendipity_entry_extended {
+    /* Inner blocks of .serendipity_entry, can be used for further customization */
+}
+
+div.serendipity_Entry_Date {
+    width: auto;
+    padding-left: 15px;
+}
+
+.serendipity_date {
+    color: #B22222;
+    font-family: 'Trebuchet MS', Verdana, sans-serif;
+    font-size: small;
+    text-align: left;
+    font-weight: bold;
+    padding-top: 5px;
+    margin-bottom: 10px;
+}
+
+.serendipity_commentTitle {
+    display: block;
+    color: #333;
+    font-family: 'Trebuchet MS', Verdana, sans-serif;
+    border-bottom: 1px solid #999999;
+    font-size: small;
+    text-align: left;
+    font-weight: bold;
+    margin-bottom: 10px;
+}
+
+div.serendipity_entryFooter {
+    color: #999999;
+    font-family: 'Trebuchet MS', Verdana, sans-serif;
+    font-size: x-small;
+    border-top: 1px solid #999999;
+    text-align: left;
+    margin-bottom: 25px;
+    line-height: normal;
+    padding: 3px;
+
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+td.serendipity_commentsLabel {
+    font-size: x-small;
+    font-weight: bold;
+    vertical-align: top;
+}
+
+td.serendipity_commentsValue input,
+td.serendipity_commentsValue select,
+td.serendipity_commentsValue textarea {
+    width: 99%;
+    border: 1px solid #333;
+    padding: 2px;
+}
+
+.serendipity_commentForm {
+    font-size:x-small;
+    color: #ffffff;
+    margin-bottom: 13px;
+    margin-right: 10px;
+    margin-left: 10px;
+    background-color: #FFFFFF;
+}
+.serendipity_comment {
+    font-size: x-small;
+    margin-right: 15px;
+    margin-left: 15px;
+    padding: 3px;
+    padding-bottom: 0;
+    background-color: #FFFFFF;
+    border-right: 1px dotted #BBB;
+    overflow: auto;
+}
+
+.serendipity_comment_source {
+    margin-top: 5px;
+    padding-left: 5px;
+}
+
+td.serendipity_admin {
+    padding: 10px;
+}
+
+a {
+    text-decoration: underline;
+
+
+    }
+
+a:link {
+    color: #0F314E;
+    }
+
+a:visited {
+    color: #0F314E;
+    }
+
+a:active {
+    color: #0F314E;
+    }
+
+a:hover {
+    color: #B22222;
+    }
+
+table.serendipity_calendar td {
+    text-align: center;
+}
+table.serendipity_calendar a {
+    text-decoration:underline;
+}
+
+table.serendipity_calendar a:hover {
+    text-decoration: none;
+}
+
+td.serendipity_weekDayName {
+    text-align: center;
+    font-weight: normal;
+}
+td.serendipity_calendarHeader a:link,
+td.serendipity_calendarHeader a:visited,
+td.serendipity_calendarHeader a:hover {
+    color: #B22222;
+    font-family: Verdana, Arial, sans-serif;
+    font-size: x-small;
+    text-align: left;
+    font-weight: bold;
+
+    text-transform: uppercase;
+    padding: 3px;
+    letter-spacing: .25em;
+    text-decoration: none;
+}
+div.serendipityPlug {
+    text-align: center;
+}
+
+div.serendipityPlug a {
+    text-decoration: none;
+    border: 0px;
+}
+
+.serendipitySideBarContent {
+    padding: 3px;
+}
+
+/* Container for each item on the side bar */
+div.serendipitySideBarItem {
+    color: #666666;
+    font-family: 'Trebuchet MS', Verdana, sans-serif;
+    font-size: x-small;
+    text-align: left;
+    margin-bottom: 15px;
+    line-height: normal;
+    padding: 3px;
+}
+
+/* title of an individual item */
+.serendipitySideBarTitle {
+    color: #B22222;
+    font-family: Verdana, Arial, sans-serif;
+    font-size: x-small;
+    border-bottom: 1px solid #B22222;
+    font-weight: bold;
+    text-transform: uppercase;
+    letter-spacing: .2em;
+    padding: 3px;
+}
+
+.serendipityImageButton {
+    cursor: pointer;
+}
+
+td.serendipitySideBar {
+    font-size: x-small;
+    width: 200px;
+    padding: 10px;
+}
+
+div.serendipity_admin_title {
+    font-size: 22px;
+    font-weight: bold;
+    margin-bottom: 12px;
+}
+
+div.serendipity_admin_list_title {
+    font-size: 12px;
+    font-weight: bold;
+    margin-bottom: 8px;
+}
+
+td.serendipity_admin_list_item {
+    border: dashed 1px #000000;
+}
+
+.serendipity_entry p {
+    margin: 0px;
+    padding-bottom: 10px;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+    margin: 0px;
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+    text-align: center;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: xx-small;
+    text-align: center;
+}
+
+.serendipity_admin_list_item_even {
+    background-color: #fefefe;
+}
+
+.serendipity_admin_list_item_uneven {
+    background-color: #eee;
+}
+
+.serendipity_admin_filters {
+    border: 1px dashed;
+    background-color: #FFFFFF;
+    font-size: 10px;
+    margin-bottom: 10px;
+    padding: 2px;
+}
+
+.serendipity_admin_filters_headline {
+    border-bottom: 1px solid;
+}
+
+.serendipity_admin_sortorder {
+    font-size: 10px;
+    text-align: center;
+}
+
+.serendipity_admin_sortorder input,
+.serendipity_admin_sortorder select,
+.serendipity_admin_filters input,
+.serendipity_admin_filters select {
+    font-size: 10px;
+}
+
+.serendipity_comments {
+}
+
+.serendipity_center {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center;
+}
+
+.serendipity_msg_important {
+    color: red;
+    font-weight: bold;
+    font-size: small;
+}
+
+.serendipity_msg_notice {
+    color: green;
+    font-weight: bold;
+    font-size: small;
+}
+
+.serendipity_entry_author_self {
+}
+
+.serendipity_comment_author_self {
+    border-right: 1px dashed #B22222;
+}
+
+/* vim: set sts=4 ts=4 expandtab : */
diff --git a/templates/mt3-squash/info.txt b/templates/mt3-squash/info.txt
new file mode 100644 (file)
index 0000000..636e45b
--- /dev/null
@@ -0,0 +1,3 @@
+Name: MT3 - Squash
+Author: Kaustubh Srikanth
+Date: 31-06-2004
diff --git a/templates/mt3-squash/preview.png b/templates/mt3-squash/preview.png
new file mode 100644 (file)
index 0000000..d8cae35
Binary files /dev/null and b/templates/mt3-squash/preview.png differ
diff --git a/templates/mt3-squash/style.css b/templates/mt3-squash/style.css
new file mode 100644 (file)
index 0000000..439c8e8
--- /dev/null
@@ -0,0 +1,414 @@
+h4,h3 {
+    margin: 0;
+}
+
+.serendipitySideBarContent input {
+    width: 175px;
+}
+
+#mainpane {
+    line-height: 140%;
+    text-align: left;
+    padding: 0px;
+    width: 700px;
+    background-color: #ffffff;
+    border: 1px solid #FFFFFF;
+    margin: auto;
+}
+
+#content {
+    width: 500px;
+}
+
+#serendipityRightSideBar {
+    width: 180px;
+    padding: 10px;
+    background-color: #ffffff;
+    vertical-align: top;
+}
+
+#serendipityLeftSideBar {
+    width: 150px;
+    padding: 10px;
+    vertical-align: top;
+    background-color: #ffffff;
+}
+
+body {
+       margin: 0px 0px 20px 0px;
+       background-color: #DBDAD6;
+}
+
+input, textarea {
+    font-size: x-small;
+    font-family: verdana, arial, helvetica, sans-serif;
+}
+
+th, td {
+    font-size: x-small;
+}
+
+p, td, th, div, span {
+    font-family: verdana, arial, helvetica, sans-serif;
+}
+
+#serendipity_banner {
+    font-family: Verdana, Arial, sans-serif;
+    color: #FFFFFF;
+    background-color: #E7AA5C;
+    text-align: left;
+    border-bottom: 1px solid #FFFFFF;
+    width: 700px;
+    height: 72px;
+    margin: auto;
+}
+
+a.homelink1,
+a.homelink1:hover,
+a.homelink1:link,
+a.homelink1:visited,
+#serendipity_banner h1 {
+    color: #ffffff;
+    font-size: xx-large;
+    font-weight: normal;
+    padding-left: 5px;
+    padding-top: 5px;
+    margin: 0px;
+    text-decoration: none;
+}
+
+a.homelink2,
+a.homelink2:hover,
+a.homelink2:link,
+a.homelink2:visited,
+#serendipity_banner h2 {
+    color: #FFFFFF;
+    padding-left: 5px;
+    font-size: small;
+    font-weight: normal;
+    margin: 0px;
+    text-decoration: none;
+}
+
+.serendipity_title {
+    color: #333;
+    font-family: 'Trebuchet MS', Verdana, sans-serif;
+    font-size: small;
+    text-align: left;
+    font-weight: bold;
+}
+
+.serendipity_title a:link {
+    color: #333;
+    text-decoration: none;
+}
+
+.serendipity_title a:visited {
+    color: #333;
+    text-decoration: none;
+}
+
+.serendipity_title a:hover {
+    color: #333;
+    text-decoration: none;
+}
+
+.serendipity_entry {
+    padding: 15px 15px 5px 0px;
+    background-color: #FFFFFF;
+    color: #666666;
+    font-family: 'Trebuchet MS', Verdana, sans-serif;
+    font-size: small;
+    clear:both;
+}
+
+.serendipity_entry_body_folded,
+.serendipity_entry_body_unfolded,
+.serendipity_entry_extended {
+    /* Inner blocks of .serendipity_entry, can be used for further customization */
+}
+
+div.serendipity_Entry_Date {
+    padding-left: 15px;
+    width: auto;
+}
+
+.serendipity_date {
+    color: #666666;
+    font-family: 'Trebuchet MS', Verdana, sans-serif;
+    font-size: small;
+    text-align: left;
+    font-weight: bold;
+    margin-bottom: 10px;
+}
+
+.serendipity_commentsTitle {
+    font-family: 'Trebuchet MS', Verdana, sans-serif;
+    display: block;
+    width: 100%;
+    color: #666666;
+    font-size: small;
+    font-weight: bold;
+}
+
+div.serendipity_entryFooter {
+    color: #999999;
+    font-family: 'Trebuchet MS', Verdana, sans-serif;
+    font-size: x-small;
+    border-top: 1px solid #999999;
+    text-align: left;
+    margin-bottom: 25px;
+    line-height: normal;
+    padding: 3px;
+
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+td.serendipity_commentsValue input,
+td.serendipity_commentsValue select,
+td.serendipity_commentsValue textarea {
+    width: 95%;
+    border: 1px solid #999999;
+    padding: 2px;
+}
+
+
+td.serendipity_commentsLabel {
+    font-size: x-small;
+    font-weight: bold;
+    vertical-align: top;
+}
+
+.serendipity_commentForm {
+    font-size:x-small;
+    color: #666666;
+    margin-bottom: 13px;
+    margin-right: 10px;
+    margin-left: 10px;
+    background-color: #FFFFFF;
+}
+.serendipity_comment {
+    font-size: x-small;
+    margin-right: 10px;
+    margin-left: 10px;
+    color: #666666;
+    padding: 3px;
+    background-color: #FFFFFF;
+    border-right: 1px dotted #BBB;
+    border-left: 1px dotted #BBB;
+    margin-bottom: 10px;
+    overflow: auto;
+}
+
+.serendipity_comment_source {
+    margin-top: 5px;
+    padding-left: 5px;
+    margin-bottom: 5px;
+}
+
+td.serendipity_admin {
+    padding: 10px;
+}
+
+a {
+       text-decoration: underline;
+
+
+       }
+
+a {
+       text-decoration: underline;
+
+
+       }
+
+a:link {
+       color: #CC6600;
+       }
+
+a:visited {
+       color: #CC6600;
+       }
+
+a:active {
+       color: #CC6600;
+       }
+
+a:hover {
+       color: #FFCC33;
+       }
+
+table.serendipity_calendar td {
+    font-size: x-small;
+    padding: 3px;
+    text-align: center;
+}
+table.serendipity_calendar a {
+    font-weight: bold;
+    text-decoration: underline;
+}
+
+table.serendipity_calendar a:hover {
+    text-decoration: none;
+}
+
+td.serendipity_weekDayName {
+    font-size: x-small;
+    font-weight:bold;
+}
+td.serendipity_calendarHeader a:link,
+td.serendipity_calendarHeader a:visited,
+td.serendipity_calendarHeader a:hover {
+    border: 0;
+    text-decoration: none;
+}
+div.serendipityPlug, div.serendipityPlug a {
+    font-size: 11px;
+    text-decoration: none;
+    border: 0px;
+    text-align: center;
+}
+
+/* Container for each item on the side bar */
+div.serendipitySideBarItem {
+    color: #666666;
+    font-family: 'Trebuchet MS', Verdana, sans-serif;
+    font-size: x-small;
+    text-align: left;
+    margin-bottom: 25px;
+    line-height: normal;
+    padding: 3px;}
+
+/* title of an individual item */
+.serendipitySideBarTitle {
+    color: #666666;
+    font-family: Verdana, Arial, sans-serif;
+    font-size: x-small;
+    text-align: center;
+    font-weight: bold;
+    text-transform: uppercase;
+    letter-spacing: .2em;
+    padding: 3px;
+}
+
+.serendipityImageButton {
+    cursor: pointer;
+}
+
+td.serendipitySideBar {
+    font-size: x-small;
+    width: 200px;
+    padding: 10px;
+}
+
+div.serendipity_admin_title {
+    font-size: 22px;
+    font-weight: bold;
+    margin-bottom: 12px;
+}
+
+div.serendipity_admin_list_title {
+    font-size: 12px;
+    font-weight: bold;
+    margin-bottom: 8px;
+}
+
+td.serendipity_admin_list_item {
+    padding: 15px;
+    border: dashed 1px #000000;
+}
+
+.serendipity_entry p {
+    margin: 0px;
+    padding-bottom: 10px;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+    margin: 0px;
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+    text-align: center;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: xx-small;
+    text-align: center;
+}
+
+.serendipity_admin_list_item_even {
+    background-color: #ffffff;
+}
+
+.serendipity_admin_list_item_uneven {
+    background-color: #E0E0E0;
+}
+.serendipity_admin_filters {
+    border: 1px dashed;
+    background-color: #FFFFFF;
+    font-size: 10px;
+    margin-bottom: 10px;
+    padding: 2px;
+}
+
+.serendipity_admin_filters_headline {
+    border-bottom: 1px solid;
+}
+
+.serendipity_admin_sortorder {
+    font-size: 10px;
+    text-align: center;
+}
+
+.serendipity_admin_sortorder input,
+.serendipity_admin_sortorder select,
+.serendipity_admin_filters input,
+.serendipity_admin_filters select {
+    font-size: 10px;
+}
+
+.serendipity_center {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center;
+}
+
+.serendipity_entry_author_self {
+}
+
+.serendipity_comment_author_self {
+    background-color: #f5f5f5;
+}
diff --git a/templates/newspaper/htmlarea.css b/templates/newspaper/htmlarea.css
new file mode 100644 (file)
index 0000000..e045a98
--- /dev/null
@@ -0,0 +1,43 @@
+body {
+    color: #061C37;
+    font-family: Georgia, Tahoma, Verdana, Arial;
+    background-color: #ffffff;
+    padding-left: 16px;
+    font-size: 9pt;
+    text-align:justify;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 9pt;
+}
+
diff --git a/templates/newspaper/img/shadowb.png b/templates/newspaper/img/shadowb.png
new file mode 100644 (file)
index 0000000..41aa321
Binary files /dev/null and b/templates/newspaper/img/shadowb.png differ
diff --git a/templates/newspaper/img/shadowbl.png b/templates/newspaper/img/shadowbl.png
new file mode 100644 (file)
index 0000000..70804b1
Binary files /dev/null and b/templates/newspaper/img/shadowbl.png differ
diff --git a/templates/newspaper/img/shadowbr.png b/templates/newspaper/img/shadowbr.png
new file mode 100644 (file)
index 0000000..4aeba4d
Binary files /dev/null and b/templates/newspaper/img/shadowbr.png differ
diff --git a/templates/newspaper/img/shadowr.png b/templates/newspaper/img/shadowr.png
new file mode 100644 (file)
index 0000000..673ee17
Binary files /dev/null and b/templates/newspaper/img/shadowr.png differ
diff --git a/templates/newspaper/img/shadowt.png b/templates/newspaper/img/shadowt.png
new file mode 100644 (file)
index 0000000..b29001c
Binary files /dev/null and b/templates/newspaper/img/shadowt.png differ
diff --git a/templates/newspaper/info.txt b/templates/newspaper/info.txt
new file mode 100644 (file)
index 0000000..c8f41ef
--- /dev/null
@@ -0,0 +1,3 @@
+Name: Newspaper Blog 
+Author: Jannis Hermanns 
+Date: 26/6-2003
diff --git a/templates/newspaper/layout.php b/templates/newspaper/layout.php
new file mode 100644 (file)
index 0000000..fa59eec
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+##########################################################################
+# serendipity - another blogger...                                       #
+##########################################################################
+#                                                                        #
+# (c) 2003 Jannis Hermanns <J@hacked.it>                                 #
+#          Kristian Köhntopp fucked it up                                #
+# http://www.jannis.to/programming/serendipity.html                      #
+#                                                                        #
+##########################################################################
+
+$OPENSHADOW = '<table  cellspacing="0" width="100%" cellpadding="0" style="padding:0px">
+                 <tr>
+                   <td valign="top" align="left" style="padding:10px;border-top:1px solid #cdcdcd; border-left: 1px solid #cdcdcd;">
+';
+
+$CLOSESHADOW = '</td>
+                <td style="width:8px; background-image:url('.$serendipity['baseURL'].'/templates/newspaper/img/shadowr.png);" valign="top"><img src="'.$serendipity['baseURL'].'/templates/newspaper/img/shadowt.png" border="0" hspace="0" vspace="0" alt="neu" /></td>
+              </tr>
+              <tr>
+                <td style="height:10px; background-image:url('.$serendipity['baseURL'].'/templates/newspaper/img/shadowb.png);"><img src="'.$serendipity['baseURL'].'/templates/newspaper/img/shadowbl.png" border="0" hspace="0" vspace="0" alt="new" /></td>
+                <td style="height:10px; width:8px;"><img src="'.$serendipity['baseURL'].'/templates/newspaper/img/shadowbr.png" border="0" hspace="0" vspace="0" alt="neu" /></td>
+              </tr>
+            </table>
+';
+?>
+
+<table width="100%" cellspacing="4" border="0">
+    <tr>
+        <td colspan="3" width="100%" class="serendipityBanner">
+            <div id="serendipity_banner">
+                <h1><a class="homelink1" href="<?php echo $serendipity['baseURL']; ?>"><?php echo htmlspecialchars($serendipity['blogTitle']); ?></a></h1>
+            <h2>
+<?php
+$sub = isset($serendipity['blogSubTitle']) ? $serendipity['blogSubTitle'] : $serendipity['blogDescription'];
+if (strlen($sub)) {
+?>
+    <h2><a class="homelink2" href="<?php echo $serendipity['baseURL']; ?>"><?php echo $sub ?></a></h2>
+<?php
+}
+?>
+
+</h2>
+            </div>
+        </td>
+    </tr>
+    <tr>
+        <td width="150" valign="top" align="left" class="serendipitySideBar">
+            <?php
+                serendipity_plugin_api::generate_plugins('left', 'span');
+//              serendipity_plugin_api::generate_plugins('right', 'span');
+            ?>
+
+        </td>
+        <td width="100%" valign="top" align="left" class="serendipityContent">
+            <?php echo $OPENSHADOW; ?>
+            <?php
+                // The main area
+                switch ($serendipity["GET"]["action"]) {
+
+                    // User wants to read the diary
+                    case "read":
+                        if (isset($serendipity['GET']['id'])) {
+                            serendipity_printEntries(array(serendipity_fetchEntry("id", $serendipity['GET']['id'])), 1);
+                        } else {
+                            serendipity_printEntries(serendipity_fetchEntries($serendipity['range'], true, $serendipity['fetchLimit']));
+                        }
+                    break;
+
+                    // User searches
+                    case "search":
+                        $r = serendipity_searchEntries($serendipity["GET"]["searchTerm"]);
+                        if ( strlen($serendipity["GET"]["searchTerm"]) <= 3 ) {
+                                echo SEARCH_TOO_SHORT;
+                                break;
+                        }
+
+                        if ($r === true) {
+                            echo sprintf(NO_ENTRIES_BLAHBLAH, $serendipity['GET']['searchTerm']);
+                            break;
+                        }
+                        echo sprintf(YOUR_SEARCH_RETURNED_BLAHBLAH, $serendipity["GET"]["searchTerm"], count($r));
+                        serendipity_printEntries($r);
+                    break;
+
+                    // Show the archive
+                    case "archives":
+                       serendipity_printArchives();
+                    break;
+
+
+                    // Welcome screen or whatever
+                    default:
+                        serendipity_printEntries(serendipity_fetchEntries(null, true, $serendipity['fetchLimit']));
+                }
+            ?>
+            <?php echo $CLOSESHADOW; ?>
+        </td>
+        <td valign="top" align="left" class="serendipitySideBar">
+            <?php
+//              serendipity_plugin_api::generate_plugins('left', 'span');
+                serendipity_plugin_api::generate_plugins('right', 'span');
+            ?>
+
+        </td>
+    </tr>
+</table>
diff --git a/templates/newspaper/preview.png b/templates/newspaper/preview.png
new file mode 100644 (file)
index 0000000..2136dec
Binary files /dev/null and b/templates/newspaper/preview.png differ
diff --git a/templates/newspaper/style.css b/templates/newspaper/style.css
new file mode 100644 (file)
index 0000000..d917cab
--- /dev/null
@@ -0,0 +1,352 @@
+A {
+    border-bottom:0px dotted #1a3c5a;
+
+    color: #32557A;
+    font-weight: bold;
+    text-decoration: none;
+}
+
+A IMG {
+       border-bottom:0px solid #ffffff;
+}
+
+A:hover {
+    color: #EE7F09;
+}
+
+SPAN.serendipityReferer, SPAN.serendipityReferer A {
+    font-weight: normal;
+    text-decoration: none;
+    font-size:10px;
+}
+
+H3 {
+       margin: 4px;
+}
+
+h4 {
+       margin:4px;
+}
+
+PRE {
+    font-size: 7pt;
+}
+
+INPUT,SELECT {
+    font-size: 7pt;
+       border: 1px solid #ababab;
+       background-color: #FCFFF9;
+}
+
+#mainpane {
+
+}
+
+#content {
+
+}
+
+#serendipityRightSideBar {
+       padding: 10px;
+}
+
+#serendipityLeftSideBar A {
+       font-weight: normal;
+}
+
+.serendipity_entryFooter {
+       margin-top:10px;
+       border-bottom:1px dashed #cdcdcd;
+}
+
+.serendipityPlug A {
+
+}
+
+BODY,P, TD, TH, DIV, SPAN {
+        color: #061C37;
+       font-size: 8pt;
+       font-family: Georgia, Tahoma, Verdana, Arial;
+}
+
+BODY {
+       background-color: #ffffff;
+}
+
+.serendipity_banner {
+       background-color: #FFFDEC;
+}
+
+
+a.homelink1,
+a.homelink1:hover,
+a.homelink1:link,
+a.homelink1:visited,
+#serendipity_banner h1 {
+       font-size: 25px;
+       font-family: Georgia;
+        color:#082447;
+}
+
+a.homelink2,
+a.homelink2:hover,
+a.homelink2:link,
+a.homelink2:visited,
+#serendipity_banner h2 {
+       padding-left:38px;
+       font-size: 14px;
+       font-family: Georgia;
+        color:#082447;
+}
+
+
+.serendipity_title {
+       font-variant:small-caps;
+       font-size:11pt;
+       letter-spacing:2pt;
+       font-style: italic;
+       font-weight:bold;
+       padding-top: 16px;
+       padding-bottom:8px;
+       border-top:1px dashed #cdcdcd;
+}
+
+.serendipity_entry {
+       padding-left: 16px;
+       font-size: 9pt;
+       text-align:justify;
+}
+
+.serendipity_entry a {
+
+}
+
+div.serendipity_Entry_Date {
+
+}
+
+.serendipity_date {
+       text-align: right;
+       font-size: 12pt;
+       font-weight: bolder;
+       text-decoration:italic;
+       padding-top: 24px;
+}
+
+.serendipity_commentsTitle {
+        font-size: 24pt;
+}
+
+.serendipity_time {
+}
+
+TD.serendipity_commentsLabel {
+
+}
+
+TD.serendipity_comment {
+    border-bottom:1px dotted #cdcdcd;
+    padding-top:16px;
+}
+
+.serendipity_comment {
+    padding-top: 1em;
+    overflow: auto;
+}
+
+.serendipity_comment_source {
+
+}
+
+TD.serendipityEntriesBox {
+
+}
+
+TD.serendipity_admin {
+
+}
+
+TABLE.serendipity_calendar {
+
+}
+
+TD.serendipity_calendarDay, TD.serendipity_calendarBlankDay, TD.serendipity_calendarDayFirstInRow, TD.serendipity_calendarBlankDayFirstInRow{
+       padding: 2px;
+       border-top:1px solid #F0EEDE;
+       border-left:1px solid #F0EEDE;
+}
+
+TD.serendipity_calendarDayLastInRow, TD.serendipity_calendarBlankDayLastInRow {
+       padding: 2px;
+       border-top:1px solid #F0EEDE;
+       border-left:1px solid #F0EEDE;
+       border-right:1px solid #F0EEDE;
+}
+
+TD.serendipity_calendarDayLastRow, TD.serendipity_calendarBlankDayLastRow {
+       padding: 2px;
+       border-top:1px solid #F0EEDE;
+       border-left:1px solid #F0EEDE;
+       border-bottom: 1px solid #F0EEDE;
+}
+
+TD.serendipity_calendarDayLastInLastRow, TD.serendipity_calendarBlankDayLastInLastRow {
+       padding: 2px;
+       border-top:1px solid #F0EEDE;
+       border-left:1px solid #F0EEDE;
+       border-right:1px solid #F0EEDE;
+       border-bottom:1px solid #F0EEDE;
+}
+
+
+
+TABLE.serendipity_calendar A {
+
+}
+
+TABLE.serendipity_calendar A:hover {
+
+}
+
+TD.serendipity_calendarHeader {
+       border-bottom: 0px solid #cdcdcd;
+       border-left: 0px;
+       border right: 0px
+}
+
+TD.serendipity_weekDayName {
+
+}
+
+div.serendipityPlug, div.jBlogPlug A {
+
+}
+
+/* Container for each item on the side bar */
+div.serendipitySideBarItem {
+
+       padding-bottom: 20px;
+}
+
+
+TD.serendipityBanner {
+
+       padding-top:0px;
+}
+
+TD.serendipityContent {
+       padding-left: 16px;
+       padding-right: 16px;
+       padding-top: 0px;
+       border-bottom: 1px dotted #ABABAB;
+
+}
+
+#serendipityRightSideBar #serendipitySideBarContent A {
+        font-size: 8px;
+}
+
+#serendipitySidebarContent {
+    text-indent: 15px;
+}
+
+/* title of an individual item */
+div.serendipitySideBarTitle {
+       font-weight: bold;
+}
+
+img.serendipityImageButton {
+
+}
+
+
+div.serendipity_admin_title {
+
+}
+
+div.serendipity_admin_list_title {
+
+}
+
+td.serendipity_admin_list_item {
+
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+    margin: 0px;
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+    text-align: center;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 9pt;
+    text-align: center;
+}
+
+img.serendipity_entryIcon {
+    float: right;
+    border: 0px;
+}
+
+.serendipity_admin_list_item_even {
+    background-color: #ffffff;
+}
+
+.serendipity_admin_list_item_uneven {
+    background-color: #E0E0E0;
+}
+
+.serendipity_admin_filters,
+.serendipity_admin_filters input,
+.serendipity_admin_filters select {
+}
+
+.serendipity_comments {
+}
+
+.serendipity_center {
+    margin-left: auto;
+    margin-right: auto;
+    text-align: center;
+}
+
+.serendipity_msg_important {
+    color: red;
+}
+
+.serendipity_msg_notice {
+    color: green;
+}
+
+.serendipity_entry_author_self {
+}
+
+.serendipity_comment_author_self {
+    background-color: #efefef;
+}
diff --git a/templates/wp/atom.css b/templates/wp/atom.css
new file mode 100644 (file)
index 0000000..c7313ed
--- /dev/null
@@ -0,0 +1,89 @@
+/* Basic CSS taken from http://www.blogger.com/styles/atom.css */
+
+feed {
+  display:block;
+  font-family:verdana, sans-serif;
+  margin:2%;
+  font-size:90%;
+  color:#000000;
+  background:#ffffff;
+}
+
+title {
+  display:block;
+  font-size:1.3em;
+  color:inherit;
+  background:inherit;
+  font-weight:bold;
+}
+
+tagline, link {
+  display:block;
+  font-size:0.9em;
+}
+
+id, modified {
+  display:none;
+}
+
+generator {
+  display:block;
+  font-size:0.9em;
+}
+
+info {
+  display:block;
+  margin:3em 4em 3em 4em;
+  color:#CC3333;
+  background:#FFFF66;
+  border:solid #CCCC66 2px;
+  text-align:center;
+  padding:1.5em;
+  font-family:mono;
+  font-size:0.8em;
+}
+
+entry {
+  display:block;
+  color:inherit;
+  background:inherit;
+  padding:0;
+  margin:1em 1em 4em 1em;
+  
+}
+
+entry modified, entry name {
+  display:inline;
+  color:#999999;
+  background:inherit;
+  font-size:0.8em;
+}
+
+entry created, entry issued, entry id {
+  display:none;
+}
+
+/* Using a single 'commentRSS' and 'comments' is used for compatibility to Opera */
+slash\:comments, wfw\:commentRss, commentRss, comments, wfw\:comment, comment {
+  display:none;
+}
+
+entry title {
+  display:block;
+  font-size:1em;
+  font-weight:bold;
+  color:inherit;
+  background:inherit;
+  padding:1em 1em 0em 1em;
+  margin:0;
+  border-top:solid 1px #dddddd;
+}
+
+content {
+  display:block;
+  font-size:0.9em;
+  color:inherit;
+  background:inherit;
+  padding:1em;
+  line-height:1.5em;
+}
\ No newline at end of file
diff --git a/templates/wp/commentform.tpl b/templates/wp/commentform.tpl
new file mode 100644 (file)
index 0000000..33bd41a
--- /dev/null
@@ -0,0 +1,52 @@
+<p>
+  <p><a href='{$serendipityBaseURL}/rss.php?version=2.0&amp;type=comments&amp;cid={$commentform_id}'><abbr title="Really Simple Syndication">RSS</abbr> feed for comments on this post.</a></p>
+  <h2 id="postcomment">Leave a comment</h2>
+
+  <form action="{$commentform_action}#feedback" method="post" id="commentform">
+    <p>
+      {serendipity_hookPlugin hook="frontend_comment" data=$commentform_entry}
+    </p>
+    <p>
+      <input id="name" type="text" name="serendipity[name]" value="{$commentform_name}" size="28" tabindex="1" />
+      <label for="author">{$CONST.NAME}</label>
+    </p>
+
+    <p>
+      <input type="text" id="email" name="serendipity[email]" value="{$commentform_email}" size="28" tabindex="2" />
+      <label for="email">{$CONST.EMAIL}</label>
+    </p>
+
+    <p>
+      <input id="url" type="text" name="serendipity[url]" value="{$commentform_url}" size="28" tabindex="3" />
+      <label for="url">{$CONST.HOMEPAGE}</label>
+    </p>
+
+    <p>
+      <label for="comment">{$CONST.COMMENT}</label><br />
+      <textarea id="comment" rows="4" cols="40" name="serendipity[comment]">{$commentform_data}</textarea>
+    </p>
+
+    {if $is_commentform_showToolbar}
+      <p>
+        <input id="checkbox_remember" type="checkbox" name="serendipity[remember]" {$commentform_remember} />
+        <label for="checkbox_remember">{$CONST.REMEMBER_INFO}</label>
+      </p>
+      {if $is_allowSubscriptions}
+        <p>
+          <input id="checkbox_subscribe" type="checkbox" name="serendipity[subscribe]" {$commentform_subscribe} />
+          <label for="checkbox_subscribe">{$CONST.SUBSCRIBE_TO_THIS_ENTRY}</label>
+        </p>
+      {/if}
+    {/if}
+
+    {if $is_moderate_comments}
+      <p>{$CONST.COMMENTS_WILL_BE_MODERATED}</p>
+    {/if}
+
+    <p>
+      <input type="hidden" name="serendipity[entry_id]" value="{$commentform_id}" />
+      <input type="submit" name="serendipity[submit]" value="{$CONST.SUBMIT_COMMENT}" />
+      <input type="submit" name="serendipity[preview]" value="{$CONST.PREVIEW}" />
+    </p>
+  </form>
+</p>
diff --git a/templates/wp/comments.tpl b/templates/wp/comments.tpl
new file mode 100644 (file)
index 0000000..00ced17
--- /dev/null
@@ -0,0 +1,6 @@
+{foreach from=$comments item=comment}
+  <li id="comment-{$comment.id}">
+    <p><strong></strong>{$comment.body}</p>
+    <p><cite>Comment by {if $comment.url}<a href="{$comment.url}" rel='external'>{$comment.username|@default:$CONST.ANONYMOUS}</a>{else}{$comment.username|@default:$CONST.ANONYMOUS}{/if} &#8212; {$comment.timestamp|@formatTime:'%m/%d/%Y'} @ <a href="#comment-{$comment.id}">{$comment.timestamp|@formatTime:'%I:%M %p'}</a></cite></p>
+  </li>
+{/foreach}
diff --git a/templates/wp/content.tpl b/templates/wp/content.tpl
new file mode 100644 (file)
index 0000000..9f88267
--- /dev/null
@@ -0,0 +1,7 @@
+<!-- CONTENT START -->
+
+{$content_message}
+{$ENTRIES}
+{$ARCHIVES}
+
+<!-- CONTENT END -->
diff --git a/templates/wp/entries.tpl b/templates/wp/entries.tpl
new file mode 100644 (file)
index 0000000..cec28cc
--- /dev/null
@@ -0,0 +1,66 @@
+    {serendipity_hookPlugin hook="entries_header" addData="$entry_id"}
+
+    {foreach from=$entries item="dategroup"}
+      {if $dategroup.is_sticky}
+        <h2>{$CONST.STICKY_POSTINGS}</h2>
+      {else}
+        <h2>{$dategroup.date|@formatTime:DATE_FORMAT_ENTRY}</h2>
+      {/if}
+
+      {foreach from=$dategroup.entries item="entry"}
+        <div class="post">
+        <h3 class="storytitle" id="post-{$entry.id}"><a href="{$entry.link}" rel="bookmark" title="Permanent Link: {$entry.title}">{$entry.title}</a></h3>
+
+        <div class="meta">Filed under:
+          <ul class="post-categories">{foreach from=$entry.categories item="category"}
+            <li><a title="View all posts in {$category.category_name}" href="{$serendipityHTTPPath}{$serendipityRewritePrefix}{$CONST.PATH_CATEGORIES}/{$category.category_id}-{$category.category_name|@makeFilename}">{$category.category_name}</a></li>
+          {/foreach}</ul>
+          &#8212; {$entry.author} @ {$entry.timestamp|@formatTime:'%I:%M %p'}
+        </div>
+       
+       <div class="storycontent">
+          <p>
+            {$entry.body}
+            {if $entry.is_extended}
+              {$entry.extended}
+            {/if}
+          </p>
+          {if $entry.has_extended and not $is_single_entry and not $entry.is_extended}
+            <p><a href="{$entry.link}#extended">{$CONST.VIEW_EXTENDED_ENTRY|@sprintf:$entry.title}</a></p>
+          {/if}
+       </div>
+
+       <div class="feedback"> 
+          <a href="{$entry.link}#comments">Comments ({$entry.comments+$entry.trackbacks})</a>
+          {$entry.add_footer}
+       </div>
+
+        <!--
+        <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+                 xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"
+                 xmlns:dc="http://purl.org/dc/elements/1.1/">
+        <rdf:Description
+                 rdf:about="{$serendipityBaseURL}{$serendipityRewritePrefix}feeds/ei_{$entry.id}.rdf"
+                 trackback:ping="{$serendipityBaseURL}comment.php?type=trackback&amp;entry_id={$entry.id}"
+                 dc:title="{$entry.title}"
+                 dc:identifier="{$entry.rdf_ident}" />
+        </rdf:RDF>
+        -->
+        {$entry.plugin_display_dat}
+
+        {if $is_single_entry and not $is_preview}
+          <h2 id="comments">Comments <a href="#postcomment" title="Leave a comment">&raquo;</a></h2>
+          <p>The <acronym title="Uniform Resource Identifier">URI</acronym> to TrackBack this entry is: <em>{$serendipityBaseURL}comment.php?type=trackback&amp;entry_id={$entry.id}</em></p>
+          <ol id="commentlist">
+            {serendipity_printTrackbacks entry=$entry.id}
+            {serendipity_printComments entry=$entry.id mode=$CONST.VIEWMODE_LINEAR}
+          </ol>
+          {$COMMENTFORM}
+        {/if}
+        </div>
+      {/foreach}
+    {foreachelse}
+      {if not $plugin_clean_page}
+        {$CONST.NO_ENTRIES_TO_PRINT}
+      {/if}
+    {/foreach}
diff --git a/templates/wp/entries_archives.tpl b/templates/wp/entries_archives.tpl
new file mode 100644 (file)
index 0000000..c92905f
--- /dev/null
@@ -0,0 +1,16 @@
+{foreach from=$archives item="archive"}
+<table cellspacing="4" cellpadding="4" border="0">
+    <tr>
+        <td colspan="4"><h2>{$archive.year}</h2></td>
+    </tr>
+    {foreach from=$archive.months item="month"}
+    <tr>
+        <td width="100"><img src="{serendipity_getFile file="img/graph_bar_horisontal.png"}" height="10" width="{math width=100 equation="count * width / max" count=$month.entry_count max=$max_entries format="%d"}" style="border: 1px solid #000000"></td>
+        <td>{$month.date|@formatTime:"%B"}</td>
+        <td>{$month.entry_count} {$CONST.ENTRIES}</td>
+        <td>({if $month.entry_count}<a href="{$month.link}">{/if}{$CONST.VIEW_FULL}{if $month.entry_count}</a>{/if})</td>
+        <td>({if $month.entry_count}<a href="{$month.link_summary}">{/if}{$CONST.VIEW_TOPICS}{if $month.entry_count}</a>{/if})</td>
+    </tr>
+    {/foreach}
+</table>
+{/foreach}
diff --git a/templates/wp/entries_summary.tpl b/templates/wp/entries_summary.tpl
new file mode 100644 (file)
index 0000000..b456bb4
--- /dev/null
@@ -0,0 +1,12 @@
+<div class='serendipity_date'>{$CONST.TOPICS_OF} {$dateRange.0|@formatTime:"%B, %Y"}</div>
+
+<div class="serendipity_entry">
+    {foreach from=$entries item="entries"}
+        <ul>
+        {foreach from=$entries.entries item="entry"}
+            <li><a href="{$entry.link}">{$entry.title}</a>
+                <br />{$CONST.POSTED_BY} {$entry.username} {$CONST.ON} {$entry.timestamp|@formatTime:DATE_FORMAT_ENTRY}</li>
+        {/foreach}
+        </ul>
+    {/foreach}
+</div>
diff --git a/templates/wp/htmlarea.css b/templates/wp/htmlarea.css
new file mode 100644 (file)
index 0000000..9db65fb
--- /dev/null
@@ -0,0 +1,44 @@
+body {
+    font-size: 10pt;
+    padding: 10px;
+    color: #333333;
+    background-color: #FAFFFF;
+    font-size: 9.5pt;
+    font-weight: normal;
+    font-family: verdana, arial, geneva, helvetica, sans-serif;
+}
+
+/** Embedded images with the s9y image manager **/
+.serendipity_imageComment_center,
+.serendipity_imageComment_left,
+.serendipity_imageComment_right {
+    border: 1px solid black;
+    background-color: #EFEFEF;
+    margin: 3px;
+}
+
+.serendipity_imageComment_center {
+}
+
+.serendipity_imageComment_left {
+    float: left;
+}
+
+.serendipity_imageComment_right {
+    float: right;
+}
+
+.serendipity_imageComment_img,
+.serendipity_imageComment_img img {
+    margin: 0px;
+    padding: 0px;
+    border: 0px;
+}
+
+.serendipity_imageComment_txt {
+    margin: 0px;
+    padding: 3px;
+    clear: both;
+    font-size: 9pt;
+}
+
diff --git a/templates/wp/index.tpl b/templates/wp/index.tpl
new file mode 100644 (file)
index 0000000..0659155
--- /dev/null
@@ -0,0 +1,48 @@
+{if $is_embedded != true}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+       <title>{$head_title|@default:$blogTitle} {if $head_subtitle} - {$head_subtitle}{/if}</title>
+       
+       <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+       <meta name="generator" content="Serendipity v.{$head_version}" />
+
+       <style type="text/css" media="screen">
+               @import url( {serendipity_getFile file="wp-layout.css"} );
+       </style>
+       {serendipity_hookPlugin hook="frontend_header"}
+</head>
+
+<body>
+{/if}
+
+{if $is_raw_mode != true}
+<div id="rap">
+<h1 id="header"><a href="{$serendipityBaseURL}" title="{$head_title|@default:$blogTitle}: {$head_subtitle|@default:$blogDescription}">{$head_title|@default:$blogTitle}</a></h1>
+
+<div id="content">
+
+{$CONTENT}
+
+</div>
+{/if}
+
+{$raw_data}
+
+{if $leftSidebarElements or $rightSidebarElements}
+  <div id="menu">
+    <ul>
+      {if $leftSidebarElements}{serendipity_printSidebar side="left"}{/if}
+      {if $rightSidebarElements}{serendipity_printSidebar side="right"}{/if}
+    </ul>
+  </div>
+{/if}
+
+</div>
+
+<p class="credit"><cite>Powered by <a href="http://www.s9y.org/" title="Powered by Serendipity PHP Weblog"><strong>Serendipity</strong></a></cite></p>
+{if $is_embedded != true}
+</body>
+</html>
+{/if}
diff --git a/templates/wp/info.txt b/templates/wp/info.txt
new file mode 100644 (file)
index 0000000..6ef6ed6
--- /dev/null
@@ -0,0 +1,4 @@
+Name: WP-compat
+Author: Evan Nemerson
+Date: 20/11-2004
+Engine: yes
diff --git a/templates/wp/plugin_calendar.tpl b/templates/wp/plugin_calendar.tpl
new file mode 100644 (file)
index 0000000..c638a00
--- /dev/null
@@ -0,0 +1,32 @@
+<table id="wp-calendar">
+  <caption>{$plugin_calendar_head.month_date|formatTime:"%B '%y":false}</caption>
+  <thead>
+    <tr>
+      <th abbr="Sunday" scope="col" title="Sunday">S</th>
+      <th abbr="Monday" scope="col" title="Monday">M</th>
+      <th abbr="Tuesday" scope="col" title="Tuesday">T</th>
+      <th abbr="Wednesday" scope="col" title="Wednesday">W</th>
+      <th abbr="Thursday" scope="col" title="Thursday">T</th>
+      <th abbr="Friday" scope="col" title="Friday">F</th>
+      <th abbr="Saturday" scope="col" title="Saturday">S</th>
+    </tr>
+  </thead>
+
+  <tfoot>
+    <tr>
+      <td colspan="3" id="prev">{if $plugin_calendar_head.minScroll le $plugin_calendar_head.month_date}<a href="{$plugin_calendar_head.uri_previous}" title="View posts for previous month">&laquo;</a>{/if}</td>
+      <td class="pad">&nbsp;</td>
+      <td colspan="3" id="next">{if $plugin_calendar_head.maxScroll ge $plugin_calendar_head.month_date}<a href="{$plugin_calendar_head.uri_next}" title="View posts for previous month">&raquo;</a>{/if}</td>
+    </tr>
+  </tfoot>
+
+  <tbody>
+    {foreach from=$plugin_calendar_weeks item="week"}
+      <tr>
+        {foreach from=$week.days item="day"}
+          <td>{if isset($day.properties.Active) and $day.properties.Active}<a href="{$day.properties.Link}">{/if}{$day.name|@default:"&nbsp;"}{if isset($day.properties.Active) and $day.properties.Active}</a>{/if}</td>
+        {/foreach}
+      </tr>
+    {/foreach}
+  </tbody>
+</table>
diff --git a/templates/wp/sidebar.tpl b/templates/wp/sidebar.tpl
new file mode 100644 (file)
index 0000000..6376fc3
--- /dev/null
@@ -0,0 +1,5 @@
+{foreach from=$plugindata item=item}
+  <li id="{$item.class}">{$item.title}
+    {$item.content}
+  </li>
+{/foreach}
diff --git a/templates/wp/trackbacks.tpl b/templates/wp/trackbacks.tpl
new file mode 100644 (file)
index 0000000..2a8ce99
--- /dev/null
@@ -0,0 +1,6 @@
+{foreach from=$trackbacks item=trackback}
+  <li id="trackback-{$trackback.id}">
+    <p><strong>{$trackback.title}</strong><br />{$trackback.body|@strip_tags|@escape:all}</p>
+    <p><cite>Trackback by <a href='{$trackback.url|@strip_tags}' rel='external'>{$trackback.author|@default:$CONST.ANONYMOUS}</a> &#8212; {$trackback.timestamp|@formatTime:$CONST.DATE_FORMAT_SHORT} @ <a href="#trackback-{$trackback.id}">{$trackback.timestamp|@formatTime:'%g:%M %a'}</a></cite> </p>
+  </li>
+{/foreach}
\ No newline at end of file
diff --git a/templates/wp/wp-layout.css b/templates/wp/wp-layout.css
new file mode 100644 (file)
index 0000000..2ba54b1
--- /dev/null
@@ -0,0 +1,145 @@
+/* Serendipity WP default
+   By Evan Nemerson
+   December 11, 2004
+
+   This is just a simple template modeled after the default one. It is
+   meant mostly as something to collect dust while you use a custom WP
+   theme, but it can also be used to guide you in creating your own.
+   It is licensed under the BSD license, like the rest of Serendipity,
+   and unlike most WP themes (which are GPL). */
+
+#content {
+    border-right: 1px dashed #000000;
+    border-bottom: 1px solid #000000;
+    border-top: 0px;
+    background-color: #FFFFFF;
+    position: absolute;
+    margin-right: 16em;
+}
+
+#menu {
+    vertical-align: top;
+    background: white;
+    width: 16em;
+    position: absolute;
+    right: 0;
+}
+
+#content > * {
+    padding: 10px;
+    margin: 10px;
+    width: auto;
+}
+
+#menu > ul {
+    display: block;
+    list-style: none;
+    padding-left: 0;
+    margin: 1em;
+}
+
+#menu > ul > li {
+  font-size: 1.2em;
+  font-weight: bold;
+  margin-bottom: 1em;
+  padding-bottom: 1em;
+  border-bottom: solid 2px #36558C;
+}
+
+#menu > ul > li > * {
+  font-size: 0.83em;
+  font-weight: normal;
+}
+
+body {
+    font-size: 10pt;
+    margin: 0;
+    font-size: 10px;
+    font-family: verdana, arial, helvetica, sans-serif;
+    margin-bottom: 30px;
+}
+
+input, textarea {
+    font-size: 10pt;
+    font-family: verdana, arial, helvetica, sans-serif;
+}
+
+th, td {
+    font-size: 10pt;
+}
+
+p, td, th, div, span {
+    font-family: verdana, arial, helvetica, sans-serif;
+}
+
+#header {
+    margin: auto;
+    width: 100%;
+    padding: 1em;
+    background-image: url(../default/img/background.png);
+    border-bottom: 1px solid #000000;
+}
+
+#header a,
+#header a:hover,
+#header a:link,
+#header a:visited {
+    color: #FFFFFF;
+    font-family: Verdana, Arial, Geneva, Helvetica, sans-serif;
+    text-decoration: none;
+}
+
+h2 {
+    font-family: Verdana, Arial, Geneva, Helvetica, sans-serif;
+    font-size: large;
+    color: #333333;
+    margin: 0;
+    margin-top: 20px;
+    text-align: right;
+}
+
+.storytitle {
+    font-family: Verdana, Arial, Geneva, Helvetica, sans-serif;
+    font-size: medium;
+    font-weight: bold;
+    margin-top: 1em;
+    color: #333333;
+    border-bottom: 2px solid #36558C;
+}
+
+.storytitle a:link,
+.storytitle a:visited {
+   text-decoration: none;
+   border: 0;
+   color: #000000;
+}
+
+.meta > ul > li, ul.post-meta li {
+    display: inline;
+}
+
+.meta > ul {
+    display: inline;
+    list-style: none;
+    margin: 0;
+    padding: 0;
+}
+
+.storytitle {
+    margin: auto;
+}
+
+.storytitle a:hover {
+   color: #FF0000;
+}
+
+.storycontent {
+    font-family:Verdana, Arial, Geneva, Helvetica, sans-serif;
+    color: #333333;
+    font-size: 1.3em;
+    font-weight: normal;
+    padding-right: 10px;
+    width: 95%;
+    margin: auto;
+    margin-top: 1em;
+}
\ No newline at end of file
diff --git a/wfwcomment.php b/wfwcomment.php
new file mode 100644 (file)
index 0000000..9835685
--- /dev/null
@@ -0,0 +1,40 @@
+<?php # $Id$
+# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
+# All rights reserved.  See LICENSE file for licensing details
+
+include_once('serendipity_config.inc.php');
+
+if ($_REQUEST['cid'] != '' && $HTTP_RAW_POST_DATA != '') {
+    $comment = array();
+
+    if (!preg_match('@<author[^>]*>(.*)</author[^>]*>@i', $HTTP_RAW_POST_DATA, $name)) {
+        preg_match('@<dc:creator[^>]*>(.*)</dc:creator[^>]*>@i', $HTTP_RAW_POST_DATA, $name);
+    }
+
+    if (isset($name[1]) && !empty($name[1])) {
+        if (preg_match('@^(.*)\((.*)\)@i', $name[1], $names)) {
+            $comment['name'] = utf8_decode($names[2]);
+            $comment['email'] = utf8_decode($names[1]);
+        } else {
+            $comment['name'] = utf8_decode($name[1]);
+        }
+    }
+
+    if (preg_match('@<link[^>]*>(.*)</link[^>]*>@i', $HTTP_RAW_POST_DATA, $link)) {
+        $comment['url'] = utf8_decode($link[1]);
+    }
+
+    if (preg_match('@<description[^>]*>(.*)</description[^>]*>@ims', $HTTP_RAW_POST_DATA, $description)) {
+        if (preg_match('@^<!\[CDATA\[(.*)\]\]>@ims', $description[1], $cdata)) {
+            $comment['comment'] = utf8_decode($cdata[1]);
+        } else {
+            $comment['comment'] = utf8_decode($description[1]);
+        }
+
+        if (!empty($comment['comment'])) {
+            serendipity_saveComment($_REQUEST['cid'], $comment, 'NORMAL', 'API');
+        }
+    }
+}
+
+?>